Unity Shader 广告牌技术

广告牌技术,简单地说就是让一个平面始终朝向摄像机,感觉用的地方很多。最近在在玩全战三国,渣电脑开最低画质里面的树都是用了广告牌技术,一直都在随镜头旋转,不知道开了最高画质是不是也是这样子。

在这里我实现了一个一直朝向镜头的“滑稽”,代码其实就是《Unity Shader入门精要》里面的一个例子。
以下是效果图:
在这里插入图片描述
以下是代码
运算全在顶点着色器里面。其本质是构建旋转矩阵,我们需要三个基向量以及一个锚点,这个锚点是固定不变的。广告牌技术使用的基向量通常就是表面法线,指向上的方向,以及指向右的方向。

Shader "Summer/BillboardMat"
{
	Properties
	{
		_MainTex ("Texture", 2D) = "white" {}
		_Color("Color",Color)=(1,1,1,1)
		_VerticalBillboarding("Vertical Restraints", Range(0,1))=1
	}
	SubShader
	{
		Tags { "RenderType"="Transparent" "Queue"="Transparent" 
				"IgnoreProjection"="True" "DisableBatching"="True"}
		LOD 100

		Pass
		{
			Tags{"LightMode"="ForwardBase"}

			ZWrite Off
			Blend SrcAlpha OneMinusSrcAlpha
			Cull off 

			CGPROGRAM
			#pragma vertex vert
			#pragma fragment frag
			
			#include "UnityCG.cginc"

			struct v2f
			{
				float2 uv : TEXCOORD0;
				float4 vertex : SV_POSITION;
			};

			sampler2D _MainTex;
			float4 _MainTex_ST;
			fixed4 _Color;
			fixed _VerticalBillboarding;
			
			v2f vert (appdata_base v)
			{
				v2f o;
				o.uv = TRANSFORM_TEX(v.texcoord, _MainTex);
				float3 center=float3(0,0,0);
				float3 viewer=mul(unity_WorldToObject,float4(_WorldSpaceCameraPos,1));

				float3 normalDir=viewer-center;
				normalDir.y*=_VerticalBillboarding;
				normalDir=normalize(normalDir);

				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));

				float3 centerOffs=v.vertex-center;
				float3 localPos=center+rightDir*centerOffs.x
								+upDir*centerOffs.y+normalDir*centerOffs.z;
				o.vertex=UnityObjectToClipPos(float4(localPos,1));
				return o;
			}
			
			fixed4 frag (v2f i) : SV_Target
			{
				fixed4 col = tex2D(_MainTex, i.uv);
				col.rgb*=_Color.rgb;
				
				return col;
			}
			ENDCG
		}
	}
}
			float3 center=float3(0,0,0);
			float3 viewer=mul(unity_WorldToObject,float4(_WorldSpaceCameraPos,1));
			这里设定一个锚点(模型空间的原点),以及求视角位置。
			所有的计算都是在模型空间下进行的。
			float3 normalDir=viewer-center;
			normalDir.y*=_VerticalBillboarding;
			normalDir=normalize(normalDir);
			这里根据观察位置以及锚点计算目标法线方向,而且根据_VerticalBillboarding属性控制垂直方向上的约束度
			_VerticalBillboarding为1,法线固定为视角方向;为0,向上方向固定为(0,1,0)
			float3 upDir=abs(normalDir.y)>0.999?float3(0,0,1):float3(0,1,0);
			//abs 计算输入值的绝对值。
			float3 rightDir=normalize(cross(upDir,normalDir));
			upDir=normalize(cross(normalDir,rightDir));
			然后是计算三个基向量,因为上方向还不是准确的,所以反过来上方向
			float3 centerOffs=v.vertex-center;
			float3 localPos=center+rightDir*centerOffs.x
								+upDir*centerOffs.y+normalDir*centerOffs.z;
			o.vertex=UnityObjectToClipPos(float4(localPos,1));
			最后是根据原始位置相对于锚点的偏移量以及三个正交基矢量计算新的顶点位置
			最后将顶点位置转换的裁剪空间

关于书上说用的是Quad而不能用Plane,因为这个代码是建立在一个竖直摆放的多边形的多边形的基础上的,我不太理解,便试了试,果然是不行,具体什么原因我也不知道。

  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值