原文链接
版权声明:本文为CSDN博主「Unity小林」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
正文
游戏中,有时我们需要让某些物体 一直面向我们,比如天上的云和星星之类的,或者广告牌,如果用模型的话,比较耗性能,所以我们采用 quad 面片来节省性能,然后 quad 面片要一直看向摄像机。
效果如下:
无论我们怎么移动摄像机,
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
}
}
}