廣告牌在實(shí)際游戲開發(fā)中使用非常廣泛,可以用于草叢,云朵等,其實(shí)現(xiàn)的具體效果就是讓攝像機(jī)在任意角度時(shí),使用廣告牌的物體都會(huì)面向攝像機(jī),廣告牌屬于經(jīng)典的頂點(diǎn)變換。
1. 創(chuàng)建相關(guān)場景,shader,材質(zhì)球,和一個(gè)Quad,為了方便觀察,我們將Quad沿x軸翻轉(zhuǎn)50度并設(shè)置后位置,完成后效果如下:

2. 我們都知道如果想讓一個(gè)物體面向攝像機(jī)的時(shí)候,需要表面法線和向上方向的垂直,但往往因物體角度的旋轉(zhuǎn)導(dǎo)致兩者并不垂直,此時(shí)我們需要固定一個(gè)方向來更正另一個(gè)方向

3. 打開shader文件,首先簡單定義一下shder內(nèi)屬性和方法,其中_VerticalBillboarding字段用來固定一個(gè)視角
Shader "Youcai/test/BillBoard" {
Properties{
_MainTex("Main Tex", 2D) = "white"{}
_Color("Main Color", Color) = (1,1,1,1)
_VerticalBillboarding("Vertical Restraints", Range(0,1)) = 1
}
SubShader{
Tags {"Queue" = "Transparent" "IgnoreProjector" = "True" "RenderType" = "Transparent" "DisableBatching" = "True"}
Pass
{
Tags {"LightMode" = "ForwardBase"}
ZWrite off
Blend SrcAlpha OneMinusSrcAlpha
Cull off
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#include "UnityCG.cginc"
sampler2D _MainTex;
float4 _MainTex_ST;
fixed4 _Color;
float _VerticalBillboarding;
struct a2v
{
float4 vertex: POSITION;
float4 texcoord : TEXCOORD0;
};
struct v2f
{
float4 pos: SV_POSITION;
float2 uv: TEXCOORD0;
};
void vert(in a2v v, out v2f f)
{
}
fixed4 frag(v2f f) : SV_Target
{
}
ENDCG
}
}
FallBack "Transparent/VertexLit"
}
4. 定義頂點(diǎn)著色器和片元著色器內(nèi)容,其中頂點(diǎn)著色器內(nèi)為核心部分
void vert(in a2v v, out v2f f)
{
//計(jì)算以模型空間下原點(diǎn)為錨點(diǎn),根據(jù)頂點(diǎn)位置最后做偏移
float3 center = float3(0, 0, 0);
//將攝像機(jī)位置轉(zhuǎn)為模型空間位置
float3 object_viewer = mul(unity_WorldToObject, float4(_WorldSpaceCameraPos, 1));
/*
1. 我們首先假定攝像機(jī)到錨點(diǎn)位置為表面法線(不理解可以看步驟2)
2. 通過控制法線的y軸值來確定固定的視角為法線還是向上方向
3. _VerticalBillboarding越接近1,normalDir值y值不偏移,則越強(qiáng)制偏向攝像機(jī)
*/
float3 normalDir = object_viewer - center;
normalDir.y = (normalDir.y * _VerticalBillboarding);
normalDir = normalize(normalDir);
//法線應(yīng)與向上方向垂直,我們通過三元表達(dá)式獲取一個(gè)向上方向的大致方向
float3 upDir = abs(normalDir.y) > 0.999 ? float3(0, 0, 1) : float3(0, 1, 0);
//通過向上方向和法線的叉乘獲得向右方向
float3 rightDir = normalize(cross(normalDir, upDir));
//通過向右方向在求取正確的向上方向
upDir = normalize(cross(normalDir, rightDir));
//獲取當(dāng)前頂點(diǎn)距錨點(diǎn)偏移值
float3 centerOffs = v.vertex.xyz - center;
//求取正確頂點(diǎn)位置 向右對(duì)應(yīng)x軸,向上對(duì)應(yīng)y軸,法線對(duì)應(yīng)z軸進(jìn)行偏移
float3 localPos = center + rightDir * centerOffs.x + upDir * centerOffs.y + normalDir * centerOffs.z;
//片元傳遞正確uv和坐標(biāo)
f.pos = UnityObjectToClipPos(float4(localPos, v.vertex.w));
f.uv = TRANSFORM_TEX(v.texcoord, _MainTex);
}
fixed4 frag(v2f f) : SV_Target
{
fixed4 c = tex2D(_MainTex, f.uv);
c.rgb *= _Color.rgb;
return c;
}
5. 賦予Quad材質(zhì)球,通過更改Vertical Restraints屬性來查看效果吧!
