Shader实现Unity中物体轮廓外发光效果,效果如图
上述效果分两个pass实现,就是每一个pass会绘制一次,至于为什么更改Shader以及相关GPU绘制物体基本流程可以自行搜索,这里只做代码实现以及实现原理,这里更改顶点Shader以及片元着色Shader,这也是我们自己可以代码干预的。
在Assets目录下创建Shader:Create->Shader->Unlit Shader
再创建材质球:Create->Material,将材质球拖入你需要外发光的物体上
创建好后单机材质球在Inspector中找到Shader,更换为Shader->Unlit->你创建好的Shader然后双击打开shader
一、物体边缘黑色光
Pass
{
cull front
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#pragma multi_compile_fog
#include "UnityCG.cginc"
struct appdata
{
float4 vertex : POSITION;
float2 uv : TEXCOORD0;
float3 normal:NORMAL;
};
struct v2f
{
float2 uv : TEXCOORD0;
UNITY_FOG_COORDS(1)
float4 vertex : SV_POSITION;
float4 w_vertex:TEXTURE2;
float3 w_normal:TEXTURE1;
};
sampler2D _MainTex;
float4 _MainTex_ST;
v2f vert (appdata v)
{
v2f o;
float4 new_vert=v.vertex+float4(v.normal,1)*float4(0.1,0.1,0.1,1);
o.vertex = UnityObjectToClipPos(new_vert);
o.uv = TRANSFORM_TEX(v.uv, _MainTex);
o.w_normal=UnityObjectToWorldNormal(v.normal);
o.w_vertex=mul(unity_ObjectToWorld,v.vertex);
UNITY_TRANSFER_FOG(o,o.vertex);
return o;
}
fixed4 frag (v2f i) : SV_Target
{
fixed4 col = fixed4(0,0,0,1);
UNITY_APPLY_FOG(i.fogCoord, col);
return col;
}
ENDCG
}
在第一个pass后直接添加第二个pass,下面讲解上述代码原理:
1.原理
网格包含有顶点坐标,发现,纹理坐标等信息,我们利用法线扩大物体顶点后计算相机与物体顶点法线的之间,法线与相机的角度cos,作为每个顶点都不同的值,并将他作为混合模式的值进行光照计算
2.实现
2.1CGPROGRAM
CGPROGRAM表示Cg program,cg代码开始,最后会有ENDCG表示cg结束
2.2顶点、片元着色器
#pragma vertex vert
#pragma fragment frag
顶点着色器函数名为vert
片元着色器函数名为frag
#include "UnityCG.cginc"
shader的库函数
v2f vert (appdata v)
这里开始顶点绘制,在上面struct v2f中拿到需要的参数
v2f vert (appdata v)
{
v2f o;
float4 new_vert=v.vertex+float4(v.normal,1)*float4(0.1,0.1,0.1,1);
o.vertex = UnityObjectToClipPos(new_vert);
o.uv = TRANSFORM_TEX(v.uv, _MainTex);
o.w_normal=UnityObjectToWorldNormal(v.normal);
o.w_vertex=mul(unity_ObjectToWorld,v.vertex);
UNITY_TRANSFER_FOG(o,o.vertex);
return o;
}
将顶点沿着法线方向放大0.1,
并将新顶点模型坐标转为世界坐标再转为相对相机为原点的坐标。法线向量从对象空间转换到世界空间,返回数据给渲染管道。
fixed4 frag (v2f i) : SV_Target
{
fixed4 col = fixed4(0,0,0,1);
UNITY_APPLY_FOG(i.fogCoord, col);
return col;
}
这里我只需要黑色外轮廓所以直接返回黑色
注意cull front剔除前面
上面把效果图中黑色外轮廓实现,注意unity写shader并没有提示,小心错误
二、物体边缘轮廓发亮
Pass
{
cull front
blend SrcAlpha One
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#include "UnityCG.cginc"
struct appdata
{
float4 vertex : POSITION;
float2 uv : TEXCOORD0;
float3 normal:NORMAL;
};
struct v2f
{
float2 uv : TEXCOORD0;
UNITY_FOG_COORDS(1)
float4 vertex : SV_POSITION;
float4 w_vertex:TEXTURE2;
float3 w_normal:TEXTURE1;
};
sampler2D _MainTex;
float4 _MainTex_ST;
v2f vert (appdata v)
{
v2f o;
float4 new_vert=v.vertex+float4(v.normal,1)*float4(0.5,0.5,0.5,1);
o.vertex = UnityObjectToClipPos(new_vert);
o.w_normal=UnityObjectToWorldNormal(v.normal);
o.w_vertex=mul(unity_ObjectToWorld,v.vertex);
UNITY_TRANSFER_FOG(o,o.vertex);
return o;
}
fixed4 frag (v2f i) : SV_Target
{
float3 view_dir=i.w_vertex-_WorldSpaceCameraPos;
float3 w_normal=i.w_normal;
view_dir=normalize(view_dir);
w_normal=normalize(w_normal);
float value=dot(view_dir,w_normal);
value=(value<0)?0:value;
value=pow(value,2);
fixed4 col =fixed4(0,1,0,value);
UNITY_APPLY_FOG(i.fogCoord, col);
return col;
}
ENDCG
}
blend SrcAlpha One 这种混合模式通常用于实现一些半透明的效果,其他混合模式可以去unity官方手册查看,下面提供跳转链接
Unity 用户手册 2020.3 (LTS) - Unity 手册
frag中的参数用于计算value值
这样写完之后会导致边缘可能发黑,因为剔除前面但可能网格包含前面,文章来源:https://www.toymoban.com/news/detail-857257.html
所以value=(value<0)?0:value;将前面的删除。其他原理与上述差不多文章来源地址https://www.toymoban.com/news/detail-857257.html
注意:
本篇参考博易创为老师的内容,可以去搜索看看。
只想实现的可以直接复制上述两个pass的代码。
结尾:实现的方式有好多种,我的只是参考。如果frag中点乘不懂的话可以联系我。有任何错误请指出,补充请评论,看到会第一时间回复,谢谢。
到了这里,关于Unity_物体轮廓外发光的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!