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
