广告牌

作者:追风剑情 发布于:2017-12-9 13:30 分类:Shader

一、创建Shader

// Upgrade NOTE: replaced '_World2Object' with 'unity_WorldToObject'

Shader "Custom/BillboardingShader"
{
	Properties
	{
		_MainTex ("Texture", 2D) = "white" {}
		//调整整体颜色
		_Color ("Color Tint", Color) = (1,1,1,1)
		//约束垂直方向的程度
		_VerticalBillboarding ("Vertical Restraints", Range(0, 1)) = 1
	}
	SubShader
	{
		//广告牌技术需要使用物体的模型空间下的位置来作为锚点进行计算。所以需要关闭批处理,避免模型空间丢失。
		Tags { "Queue"="Transparent" "IgnoreProjector"="True" "RenderType"="Opaque" "DisableBatching"="True" }
		LOD 100

		Pass
		{
			Tags { "LightMode"="ForwardBase" }
			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
			{
				float4 pos : SV_POSITION;
				float2 uv : TEXCOORD0;
			};

			sampler2D _MainTex;
			float4 _MainTex_ST;
			float4 _Color;
			float _VerticalBillboarding;
			
			v2f vert (appdata v)
			{
				v2f o;
				//选择模型空间的原点作为广告牌的锚点
				float3 center = float3(0, 0, 0);
				//获取模型空间下的视角位置
				float3 viewer = mul(unity_WorldToObject, float4(_WorldSpaceCameraPos, 1));

				//根据观察位置和锚点计算目标法线方向
				float3 normalDir = viewer - center;

				//根据_VerticalBillboarding属性来控制垂直方向上的约束度
				//当_VerticalBillboarding为1时,意味着法线方向固定为视角方向;
				//当_VerticalBillboarding为1时,意味着向上方向固定为(0,1,0)
				normalDir.y = normalDir.y * _VerticalBillboarding;
				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个正交基矢量normalDir、upDir、rightDir
				//我们根据原始位置相对于锚点的偏移量以及3个正交基矢量,以计算得到新的顶点位置:
				float3 centerOffs = v.vertex.xyz - center;
				float3 localPos = center + rightDir * centerOffs.x + upDir * centerOffs.y + normalDir * centerOffs.z;

				o.pos = mul(UNITY_MATRIX_MVP, float4(localPos, 1));
				o.uv = TRANSFORM_TEX(v.uv, _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"
}

二、创建工程

2222.png

场景效果

1111.png

标签: Shader

Powered by emlog  蜀ICP备18021003号-1   sitemap

川公网安备 51019002001593号