Shader "CM/Billboard1"{ Properties { _MainTex ("Texture", 2D) = "white" {} } SubShader { Pass { CGPROGRAM #pragma vertex vert #pragma fragment frag #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 Billboard(float4 vertex) { float4 ori=mul(UNITY_MATRIX_MV, float4(0,0,0,1)); float4 vt = vertex; float2 r1=float2(_Object2World[0][0],_Object2World[0][2]); float2 r2=float2(_Object2World[2][0],_Object2World[2][2]); vt.xy = vt.x*r1 + vt.z*r2; vt.z = 0; vt.xyz += ori.xyz; return mul(UNITY_MATRIX_P, vt); } v2f vert (appdata_base v) { v2f o; o.pos = Billboard(v.vertex); return o; } fixed4 frag(v2f i) : COLOR { return tex2D(_MainTex, i.uv); } ENDCG } }}
跟着相机转的plane:
广告板技术之二: 来自wiki ----------- https://en.wikibooks.org/wiki/Cg_Programming/Unity/Billboards 不过这种技术不能缩放广告板
Shader "Cg shader for billboards" { Properties { _MainTex ("Texture Image", 2D) = "white" {} } SubShader { Pass { CGPROGRAM #pragma vertex vert #pragma fragment frag // User-specified uniforms uniform sampler2D _MainTex; struct vertexInput { float4 vertex : POSITION; float4 tex : TEXCOORD0; }; struct vertexOutput { float4 pos : SV_POSITION; float4 tex : TEXCOORD0; }; vertexOutput vert(vertexInput input) { vertexOutput output; output.pos = mul(UNITY_MATRIX_P, mul(UNITY_MATRIX_MV, float4(0.0, 0.0, 0.0, 1.0)) - float4(input.vertex.x, input.vertex.y, 0.0, 0.0)); output.tex = input.tex; return output; } float4 frag(vertexOutput input) : COLOR { return tex2D(_MainTex, float2(input.tex.xy)); } ENDCG } }}
广告板技术之三: 来自wiki -----------https://en.wikibooks.org/wiki/Cg_Programming/Unity/Billboards 这种技术可缩放广告板
Shader "Cg shader for billboards" { Properties { _MainTex ("Texture Image", 2D) = "white" {} _ScaleX ("Scale X", Float) = 1.0 _ScaleY ("Scale Y", Float) = 1.0 } SubShader { Pass { CGPROGRAM #pragma vertex vert #pragma fragment frag // User-specified uniforms uniform sampler2D _MainTex; uniform float _ScaleX; uniform float _ScaleY; struct vertexInput { float4 vertex : POSITION; float4 tex : TEXCOORD0; }; struct vertexOutput { float4 pos : SV_POSITION; float4 tex : TEXCOORD0; }; vertexOutput vert(vertexInput input) { vertexOutput output; output.pos = mul(UNITY_MATRIX_P, mul(UNITY_MATRIX_MV, float4(0.0, 0.0, 0.0, 1.0)) - float4(input.vertex.x, input.vertex.y, 0.0, 0.0) * float4(_ScaleX, _ScaleY, 1.0, 1.0)); output.tex = input.tex; return output; } float4 frag(vertexOutput input) : COLOR { return tex2D(_MainTex, float2(input.tex.xy)); } ENDCG } }}
广告板技术4:Y轴锁定的广告板 ------------------------------------------------------------------- 只能一个片使用该shader,两个片以上就会出问题(因为Unity会动态合并或静态合并)
Shader "CM/Billboard"{ Properties { _MainTex ("Base texture", 2D) = "white" {} _VerticalBillboarding("Vertical Restraints", Range(0,1)) = 1 } SubShader { Tags { "Queue"="Transparent" "IgnoreProjector"="True" "RenderType"="Transparent" } Blend one one cull off zwrite off Pass { CGPROGRAM #pragma vertex vert #pragma fragment frag #pragma fragmentoption ARB_precision_hint_fastest #include "UnityCG.cginc" sampler2D _MainTex; float4 _MainTex_ST; float _VerticalBillboarding; struct v2f { float4 pos : SV_POSITION; float2 uv : TEXCOORD0; }; void CalcOrthonormalBasis(float3 dir,out float3 right,out float3 up) { up = abs(dir.y) > 0.999f ? float3(0,0,1) : float3(0,1,0); right = normalize(cross(up,dir)); up = cross(dir,right); } v2f vert (appdata_full v) { v2f o; o.uv = TRANSFORM_TEX(v.texcoord.xy, _MainTex); float3 centerLocal = 0; float3 centerOffs = v.vertex; float3 viewerLocal = mul(_World2Object,float4(_WorldSpaceCameraPos,1)); float3 localDir = viewerLocal - centerLocal; localDir.y =localDir.y * _VerticalBillboarding; float3 rightLocal; float3 upLocal; CalcOrthonormalBasis(normalize(localDir) ,rightLocal,upLocal); float3 BBNormal = rightLocal * v.normal.x + upLocal * v.normal.y; float3 BBLocalPos = centerLocal - (rightLocal * centerOffs.x + upLocal * centerOffs.y); o.pos = mul(UNITY_MATRIX_MVP, float4(BBLocalPos, 1)); return o; } fixed4 frag (v2f i) : COLOR { fixed4 col = tex2D(_MainTex, i.uv); return col; } ENDCG } }}
广告板技术5:与4表现一样,计算方式不一样
Shader "CM/Billboard"{ Properties { _MainTex ("Texture", 2D) = "white" {} } SubShader { Tags { "Queue" = "Transparent" "RenderType"="Transparent" } Blend srcalpha one cull off zwrite off LOD 100 Pass { CGPROGRAM #pragma vertex vert #pragma fragment frag #include "UnityCG.cginc" struct appdata { float4 vertex : POSITION; float3 normal : NORMAL; float2 uv : TEXCOORD0; }; struct v2f { float4 vertex : SV_POSITION; float2 uv : TEXCOORD0; float randAlpha: TEXCOORD1; }; sampler2D _MainTex; float4 _MainTex_ST; inline float4 Billboard(float4 localVertex) { float2 billboardDirection_local_xy = normalize ( _WorldSpaceCameraPos.xz -float2(_World2Object[1].w, _World2Object[2].w) ); float2x2 billboardRotation = float2x2( billboardDirection_local_xy.y, billboardDirection_local_xy.x, -billboardDirection_local_xy.x, billboardDirection_local_xy.y ); float4 billboardLocalVertex; billboardLocalVertex.xz = mul(billboardRotation, localVertex.xz); billboardLocalVertex.yw = localVertex.yw; return billboardLocalVertex; } float4x4 inverse(float4x4 input) { #define minor(a,b,c) determinant(float3x3(input.a, input.b, input.c)) //determinant(float3x3(input._22_23_23, input._32_33_34, input._42_43_44)) float4x4 cofactors = float4x4( minor(_22_23_24, _32_33_34, _42_43_44), -minor(_21_23_24, _31_33_34, _41_43_44), minor(_21_22_24, _31_32_34, _41_42_44), -minor(_21_22_23, _31_32_33, _41_42_43), -minor(_12_13_14, _32_33_34, _42_43_44), minor(_11_13_14, _31_33_34, _41_43_44), -minor(_11_12_14, _31_32_34, _41_42_44), minor(_11_12_13, _31_32_33, _41_42_43), minor(_12_13_14, _22_23_24, _42_43_44), -minor(_11_13_14, _21_23_24, _41_43_44), minor(_11_12_14, _21_22_24, _41_42_44), -minor(_11_12_13, _21_22_23, _41_42_43), -minor(_12_13_14, _22_23_24, _32_33_34), minor(_11_13_14, _21_23_24, _31_33_34), -minor(_11_12_14, _21_22_24, _31_32_34), minor(_11_12_13, _21_22_23, _31_32_33) ); #undef minor return transpose(cofactors) / determinant(input); } v2f vert (appdata v) { v2f o; float4 bbLocalVertx = Billboard(v.vertex); o.vertex = mul(UNITY_MATRIX_MVP, bbLocalVertx); o.uv = TRANSFORM_TEX(v.uv, _MainTex); return o; } fixed4 frag (v2f i) : SV_Target { fixed4 col = tex2D(_MainTex, i.uv); return col; } ENDCG } }}
广告板技术6: 草 ---------------------- 类似4、5,不过要提防unity的动静态合并,可以先选择在3dsmax中做一个草坪的4边形集合,这样就可以确定各四边形的localCenter.