Unity_物体轮廓外发光

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值

这样写完之后会导致边缘可能发黑,因为剔除前面但可能网格包含前面,

所以value=(value<0)?0:value;将前面的删除。其他原理与上述差不多

注意:
本篇参考博易创为老师的内容,可以去搜索看看。
只想实现的可以直接复制上述两个pass的代码。

结尾:实现的方式有好多种,我的只是参考。如果frag中点乘不懂的话可以联系我。有任何错误请指出,补充请评论,看到会第一时间回复,谢谢。

  • 7
    点赞
  • 22
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值