Unity3D-Shader-實現X光效果


【舊博客轉移 - 2016年1月3日 16:40 

最近學習了一些Shader效果,打算把學到的知識總結一下,這篇講一下這種輪廓發光的效果(如下圖所示),也有一些地方管這個叫X光

 
 

 

 

1.原理

可以看到圖上的藍色人物,邊緣顏色比較深,而中間的比較淺,這是利用法線跟視線向量的點乘值計算出顏色濃度來實現的
 

2.代碼

Shader "lijia/Xray"
{
    Properties
    {
        _RimColor("RimColor", Color) = (0, 0, 1, 1)
        _RimIntensity("Intensity", Range(0, 2)) = 1
    }
    SubShader
    {
        Tags {"Queue"="Transparent" "RenderType"="Opaque" }

        LOD 200
        Pass
        {
            Blend SrcAlpha One//打開混合模式
            ZWrite off
            Lighting off

            CGPROGRAM
            #pragma vertex vert
            #pragma fragment frag

            #include "UnityCG.cginc"

            struct appdata
            {
                float4 vertex : POSITION;
                float3 normal:Normal;
            };

            struct v2f
            {
                float4 pos : SV_POSITION;
                fixed4 color:COLOR;
            };

            fixed4 _RimColor;
            float _RimIntensity;

            v2f vert (appdata v)
            {
                v2f o;
                o.pos = mul(UNITY_MATRIX_MVP, v.vertex);
                float3 viewDir = normalize(ObjSpaceViewDir(v.vertex));//計算出頂點到相機的向量
                float val = 1 - saturate(dot(v.normal, viewDir));//計算點乘值
                o.color = _RimColor * val * (1 + _RimIntensity);//計算強度
                return o;
            }

            fixed4 frag (v2f i) : COLOR
            {
                return i.color;
            }
            ENDCG
        }
    }
}

 

float3 viewDir = normalize(ObjSpaceViewDir(v.vertex));//計算出頂點到相機的向量
這一句是調用了UnityCG.cginc庫中的ObjSpaceViewDir方法,獲得viewDir

inline float3 ObjSpaceViewDir( in float4 v )
{
    float3 objSpaceCameraPos = mul(_World2Object, float4(_WorldSpaceCameraPos.xyz, 1)).xyz;
    return objSpaceCameraPos - v.xyz;
}

 

翻看UnityCG中ObjSpaceViewDir方法的源碼,發現它是拿到_WorldSpaceCameraPos(世界坐標相機的位置),左乘World2Object矩陣,轉成模型坐標系
最后objSpaceCameraPos - v.xyz (向量相減),得到viewDir向量

viewDir跟normal的點乘值,就表示兩個向量的夾角大小

  1. 夾角 < 90°時,點乘>0
  2. 夾角 = 90°時,點乘=0
  3. 夾角 > 90°時,點乘<0

邊緣的頂點,點乘值接近90度,也就是值接近0,所以這里用1減去點乘值( saturate函數:返回0-1之間的數 )

float val = 1 - saturate(dot(v.normal, viewDir));

計算出顏色強度后,把顏色傳給fragment着色器去輸出渲染,就可以看到效果了

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM