【转载】Unity Shader 广告牌效果

576 阅读2分钟

原文链接

版权声明:本文为CSDN博主「Unity小林」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。

原文链接:blog.csdn.net/weixin_4383…

正文

游戏中,有时我们需要让某些物体 一直面向我们,比如天上的云和星星之类的,或者广告牌,如果用模型的话,比较耗性能,所以我们采用 quad 面片来节省性能,然后 quad 面片要一直看向摄像机。

效果如下:

20200211232350499.gif 无论我们怎么移动摄像机,quad 面片都是面对我们的。

代码如下:

Shader "MyShader/015"
{
    Properties
    {
        _MainTex ("Texture", 2D) = "white" {}
	[MaterialToggle]_Vertical("Vertical",Range(0,1)) = 1//约束垂直方向的程度
    }
    SubShader
    {
		//通常是透明背景,所以需要设置pass的相关状态,以渲染透明效果
		//为了不影响顶点计算,关闭合批,防止部分顶点被合并
        Tags { "RenderType"="Transparent" "Queue"="Transparent" "IgnoreProjection"="True" "DisableBacthing"="True" }
        LOD 100

        Pass
        {
            ZWrite Off
            Blend SrcAlpha OneMinusSrcAlpha
            Cull Off

            CGPROGRAM
            #pragma vertex vert
            #pragma fragment frag
            // make fog work
            #pragma multi_compile_fog

            #include "UnityCG.cginc"

            struct appdata
            {
                float4 vertex : POSITION;
                float2 uv : TEXCOORD0;
            };

            struct v2f
            {
                float2 uv : TEXCOORD0;
                UNITY_FOG_COORDS(1)
                float4 vertex : SV_POSITION;
            };

            sampler2D _MainTex;
            float4 _MainTex_ST;
	     fixed _Vertical;

            v2f vert (appdata v)
            {
                v2f o;
                float3 center = float3(0, 0, 0);//模型中心点
                float3 view = mul(unity_WorldToObject, float4(_WorldSpaceCameraPos, 1));//世界空间视角方向转为模型空间视角方向

                float3 normalDir = view - center;//表面法线,从模型的中心点到模型空间视角的方向向量
                //_Vertical为0时,法线方向为水平方向,所以quad面片只能在水平方向旋转
                //_Vertical为1时,法线方向可以是任意方向,所以无论摄像机在什么方向,quad面片都面向摄像机
                normalDir.y = normalDir.y*_Vertical;
                normalDir = normalize(normalDir);//归一化

                //获得粗略的向上方向,为了防止法线方向和向上方向平行(如果平行,叉积会得到错误的结果),对法线方向的y分量进行判断
                float3 upDir = abs(normalDir.y) > 0.999 ? float3(0, 0, 1) : float3(0, 1, 0);
                //根据法线方向和粗略的向上方向得到向右方向,并归一化
                float3 rightDir = normalize(cross(upDir, normalDir));
                //根据法线方向和向右方向获得准确的向上方向
                upDir = normalize(cross(normalDir, rightDir));
                //根据原始的位置相对于锚点的偏移量以及3个正交基矢量,以计算得到新的顶点位置
                float3 centerOffset = v.vertex.xyz - center;
                float3 localPos = center + rightDir * centerOffset.x + upDir * centerOffset.y + normalDir * centerOffset.z;
                //把模型空间的顶点位置变换到裁剪空间
                o.vertex = UnityObjectToClipPos(float4(localPos,1));
                o.uv = TRANSFORM_TEX(v.uv, _MainTex);
                UNITY_TRANSFER_FOG(o,o.vertex);
                return o;
            }

            fixed4 frag (v2f i) : SV_Target
            {
                // sample the texture
                fixed4 col = tex2D(_MainTex, i.uv);
                // apply fog
                UNITY_APPLY_FOG(i.fogCoord, col);
                return col;
            }
            ENDCG
        }
    }
}