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.