广告牌技术会根据视角方向来旋转一个被纹理着色的多边形(一般是一个简单的四边形,相当于广告牌),使得多边形看起来好像总是面对摄像机。本质是构建旋转矩阵,需要三个基向量。一般使用的基向量就是表面法线(normal)、指向上的方向(up)以及指向右的方向(right)。还需要一个锚点,这个锚点在旋转过程中是固定不变的,以此确定多边形在空间的位置。
Shader "Unlit/Bollboarding" { Properties { _MainTex ("Texture", 2D) = "white" {} } SubShader { Tags { "RenderType"="Transparent" "Queue"="Transparent" "DisableBatching"="True" } LOD 100 Cull Off Blend SrcAlpha OneMinusSrcAlpha Pass { CGPROGRAM #pragma vertex vert #pragma fragment frag #include "UnityCG.cginc" struct appdata { float4 vertex : POSITION; float2 uv : TEXCOORD0; }; struct v2f { float2 uv : TEXCOORD0; float4 vertex : SV_POSITION; }; sampler2D _MainTex; float4 _MainTex_ST; v2f vert (appdata v) { v2f o; fixed3 center = fixed3(0, 0, 0); //固定是原点 fixed3 upDir = fixed3(0, 1, 0); //固定向上 //中心指向摄像机,作为法线,就是被看见的面朝向摄像机 fixed3 normalDir = normalize(mul(unity_WorldToObject, _WorldSpaceCameraPos)) - center; //算出新的右边的坐标轴 fixed3 rightDir = normalize(cross(upDir, normalDir)); //再算出真实上的坐标轴 upDir = normalize(cross(normalDir, rightDir)); //此时,center,normalDir,rightDir,upDir构建出了一个朝向摄像机的新模型空间在原模型空间的表示方式 float3 offsetPos = v.vertex.xyz - center; float3 localPos = center + rightDir * offsetPos.x + upDir * offsetPos.y + normalDir * offsetPos.z;//变换到新的模型空间 o.vertex = UnityObjectToClipPos(float4(localPos,1)); o.uv = TRANSFORM_TEX(v.uv, _MainTex); return o; } fixed4 frag (v2f i) : SV_Target { fixed4 col = tex2D(_MainTex, i.uv); return col; } ENDCG } } }
这里固定了一个向上的up,normal是根据相机视野来改变的,然后用这两个计算right,因为up和normal不一定是垂直的,所以up需要再使用right和normal叉乘计算。构建出坐标轴后对模型空间点进行变换方法可以查看 坐标空间变换过程坐标空间变换过程
效果