ShaderForge-轮廓内发光
发表于2018-07-12
本篇使用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