ShaderForge-轮廓内发光

发表于2018-07-12
评论0 3.9k浏览
本篇使用Unity ShaderForge插件和编写Unity Shader Code两种方式来实现轮廓内发光。

发光效果

内发光:发光效果不能超出模型的范围,模型中心最暗向着边缘方向逐渐变亮

内发光效果的实现原理:

我们要塑造物体边缘反射光比较亮,物体中央反射光比较暗的效果,这里给出两种实现方法:
1)将物体法线(Normal Dir)和视角(View Dir)点积,得到从视角看过去从中心最亮逐渐衰减的效果,再做一个1减的操作,最终得到中间最暗逐渐变亮的效果
2)使用菲涅尔法线

边缘颜色:
乘以颜色值
边缘光强度:
乘以强度值
垂直于表面时,反射较弱,而当视线非垂直表面时,夹角越小,反射越明显。如果你看向一个圆球,那圆球中心的反射较弱,靠近边缘较强,这就是“菲涅尔效应”。

shaderforge实现内发光:

设定灯光模式(使用自定义灯光,不接受环境光)
设定方式有两种:
1)直接创建customlighting shader 
2)创建shader,在Lighting属性栏中将Light Mode设定为Unlit/Custom绘制节点树,自定义灯光

方案1 使用视角法线和物体表面法线实现轮廓光

Geometry Data->fresnel从物体上获取fresnel反射
Fresnel乘以color,乘以强度
乘法结果+texture2d->输出到custom lighting

方案2 菲涅尔边缘发光

Geometry Data->Normal Dir.和Geometry Data->View Dir.做点积操作
One Minus点积值
乘以color乘以发光强度
乘法结果+tecture2d->输出到custom lighting

然后将shaderforge生成的shader加载到物体的material上,模型就会有内发光效果了!!!



手写Unity Shader实现内发光

对着shaderforge生成的shader练习自己写unity shader
// Upgrade NOTE: replaced '_World2Object' with 'unity_WorldToObject'
// Upgrade NOTE: replaced 'mul(UNITY_MATRIX_MVP,*)' with 'UnityObjectToClipPos(*)'
Shader "Shader Learn/InneGlow" { //Shader文件索引路径
    //属性
    Properties
    {
        _MainTex("main tex", 2D) = "gray"{} //表面贴图
        [HDR]_RimColor("rim color", Color) = (0.7426471, 0.07644895, 0.07644895, 1)//边缘颜色
        _RimPower("rim power", range(1, 10)) = 2//边缘强度
    }
    SubShader
        {
            // Pass通道主要是解决一些顶点和片段着色器功能
            Pass
            {
                //CG程序开始
                CGPROGRAM
//声明顶点着色器函数为vert
#pragma vertex vert
//声明片段着色器函数为frag
#pragma fragment frag
#include"UnityCG.cginc"
                //顶点着色器的输入
                struct VertexInput
                {
                    float4 vertex:POSITION;
                    float3 normal:NORMAL;
                    float4 texcoord:TEXCOORD0;
                };
                //顶点着色器的输出
                struct VertexOutput
                {
                    float4 vertex:POSITION;
                    float4 uv:TEXCOORD0;
                    float4 NdotV:COLOR;
                };
                sampler2D _MainTex;
                float4 _RimColor;
                float _RimPower;
                //顶点着色器函数
                VertexOutput vert(VertexInput v)
                {
                    VertexOutput o;
                    o.vertex = UnityObjectToClipPos(v.vertex);
                    o.uv = v.texcoord;
                    float3 V = WorldSpaceViewDir(v.vertex);
                        V = mul(unity_WorldToObject, V);//视方向从世界到模型坐标系的转换
                    o.NdotV.x = dot(v.normal, normalize(V));//必须在同一坐标系才能正确做点乘运算
                    return o;
                }
                //片段着色器函数
                float4 frag(VertexOutput IN) :COLOR
                {
                    float4 c = tex2D(_MainTex, IN.uv);
                    //用视方向和法线方向做点乘,越边缘的地方,法线和视方向越接近90度,点乘越接近0.
                    //用(1- 上面点乘的结果)*颜色,来反映边缘颜色情况
                    c.rgb += (1 - IN.NdotV.x)* _RimPower * _RimColor.rgb;
                    return c;
                }
                    //CG程序结束
                    ENDCG
            }
        }
        FallBack "Diffuse"
}

可以实现同样的效果!
我们可以使用shaderforge快速直观的调出我们想要的效果,但是如果遇到效率问题还是需要自己去优化shader代码!

参考

角色内发光
shaderforge发光
Shader实例:边缘发光和描边

以上,我们已经实现了轮廓内发光shader,接下来我们再进一步,在轮廓内发光的基础上加上从中心向四周衰减的色彩光。

效果

节点树

在轮廓内发光的基础上加上(1减fresnel)*color
来自:https://blog.csdn.net/v_xchen_v/article/details/78262756

如社区发表内容存在侵权行为,您可以点击这里查看侵权投诉指引