注释加代码
Shader "Custome/Chapter11/BillBoard" {
Properties {
_MainTex("Image Sequence",2D) = "white" { }
_Color("Color Tint",Color) = (1, 1, 1, 1)
_VerticalBillboarding("Vertical Restraints",Range(0,1)) = 1
}
SubShader{
Tags {"Queue"="Transparent" "IgnoreProjector"="True" "RenderType"="Transparent"
//批处理会合并相关的模型,
//会使模型丢失自己的模型空间
//为了利用模型空间我们关闭它
"DisableBatching"="True"}
Pass {
// Pass for ambient light & first pixel light (directional light)
Tags { "LightMode"="ForwardBase" }
ZWrite Off
Blend SrcAlpha OneMinusSrcAlpha
//这里我们绘制了两面,所以即使视线方向和unity
//的Z轴Normal方向相反也没有关系,但是一些情况下
//可能会有所不同
Cull Off
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#include "UnityCG.cginc"
#include "Lighting.cginc"
sampler2D _MainTex;
float4 _MainTex_ST;
fixed4 _Color;
fixed _VerticalBillboarding;
struct v2f {
float4 pos : POSITION;
float2 uv : TEXCOORD0;
};
v2f vert(appdata_base v) {
v2f o;
//假设中心在模型空间是固定的
float3 center = float3(0,0,0);
float3 viewer = mul(unity_WorldToObject,float4(_WorldSpaceCameraPos,1));
float3 normalDir = viewer - center;
//计算3个正交矢量。首先,我们根据观察位置和锚点计算目标法线方向,
//并根据_VerticalBillboarding 属性来控制垂直方向上的约束度。
//如果 _VerticalBillboarding 等于 1, 意味着法线方向固定为视角方向
//如果 _VerticalBillboarding 等于 0, 意味着向上方向固定为(0,1,0)
normalDir.y = normalDir.y * _VerticalBillboarding;//这个值类似模拟视角方向
normalDir = normalize(normalDir);
//获得近似的up dir
//当我们移动摄像机在上方时会导致nor dir 和 front dir平行,
//此时我们要让up dir 指向前面
float3 upDir = abs(normalDir.y) > 0.75 ? float3(0, 0, 1) : float3(0, 1, 0);
float3 rightDir = normalize(cross(upDir,normalDir));
//得到准确的upDir
upDir = normalize(cross(normalDir,rightDir));
//将quad的每个顶点沿着矩阵旋转
float3 centerOffs = v.vertex.xyz - center;
float3 localPos = center + rightDir*centerOffs.x + upDir*centerOffs.y + normalDir*centerOffs.z;
o.pos = UnityObjectToClipPos(float4(localPos, 1));
o.uv = TRANSFORM_TEX(v.texcoord,_MainTex);
return o;
}
fixed4 frag(v2f i) : SV_Target {
fixed4 c = tex2D(_MainTex, i.uv);
c.rgb *= _Color.rgb;
return c;
}
ENDCG
}
}
Fallback "Transparent/VertexLit"
}