AR场景中有时会需要使用billboard(公告牌)的效果,但目前部分AR引擎不像Unity和UE那类游戏引擎一样对billboard有很好的支持。
并且AR的billboard在y方向与常规游戏相机的y方向是不同的。
故这里提供一种仅通过shader实现的billboard。

直接上shader代码:
(因为借用了Unity做为编辑器,故这里一些变量是从Unity中取的)

 



Shader "Will/Billboard"
{
	Properties
	{
		_MainTex ("Texture", 2D) = "white" {}
		_ScaleOffset("Scale(XY) and Offset(ZW)", Vector) = (1, 1, 0, 0)
		_BrightStrength("Bright Strength", Range(0, 10)) = 1.0
	}
	SubShader
	{
		Tags { "RenderType"="Transparent" "Queue"="Transparent"}
		LOD 100

		ZWrite Off
		Cull Off
		Blend SrcAlpha OneMinusSrcAlpha

		Pass
		{
			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;
			float4 _ScaleOffset;
			fixed _BrightStrength;
			
			v2f vert (appdata v)
			{
				v2f o;

				// get camera world position from Unity directly 。如果使用的引擎不能得到这个,可以通过脚本来传入。
				float3 camPos = _WorldSpaceCameraPos;

				float4 objCenter = mul(UNITY_MATRIX_M, float4(0.0f, 0.0f, 0.0f, 1.0f));
				// float3 z1 = -normalize(camPos - objCenter.xyz/objCenter.w); // 这里可以不用除以w项,因为w项为1
				float3 z1 = -normalize(camPos - objCenter.xyz );

				float3 x1 = normalize(cross(float3(0.0f, 1.0f, 0.0f), z1)); // AR中 Camera的y始终是铅锤朝上的,但是普通游戏中就不是了。这种方式,如果绕x轴旋转Camera,会在普通游戏的视图中看到朝向的错误。

				float3 y1 = cross(z1, x1);

				// 构建新的 model 矩阵,先缩放。
				// scale 
				x1 *= _ScaleOffset.x;
				y1 *= _ScaleOffset.y;
				
				// 再构建旋转和位移的矩阵来乘以上一步缩放后的点. 新的model矩阵的坐标轴即是由面朝相机应该有的方向组成的,x1,y1,z1分别是面朝相机的面片在世界坐标中应该的方向,偏移量使用旧的model矩阵中的值即可。
				float4x4 modelNew = float4x4(
					x1.x, y1.x, z1.x, UNITY_MATRIX_M._14 + _ScaleOffset.z,
					x1.y, y1.y, z1.y, UNITY_MATRIX_M._24 + _ScaleOffset.w,
					x1.z, y1.z, z1.z, UNITY_MATRIX_M._34,
					0.0f, 0.0f, 0.0f, 1.0f
				);

				o.vertex = mul(UNITY_MATRIX_P, mul(UNITY_MATRIX_V, mul(modelNew, v.vertex)));

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

				col.xyz = col.xyz + fixed3( col.xyz * col.w  ) * _BrightStrength;
				//col.a = fixed4( 1.0, 1.0, 1.0, col.a );

				// apply fog
				UNITY_APPLY_FOG(i.fogCoord, col);
				return col;
			}
			ENDCG
		}
	}
}


可用于简单AR引擎的Billboard(公告牌)

发表评论

电子邮件地址不会被公开。 必填项已用*标注

浙公网安备 33010602005964号