-
-
Save kaiware007/8ebad2d28638ff83b6b74970a4f70c9a to your computer and use it in GitHub Desktop.
Shader "Unlit/Billboard" | |
{ | |
Properties | |
{ | |
_MainTex ("Texture", 2D) = "white" {} | |
} | |
SubShader | |
{ | |
Tags{ "Queue" = "Transparent" "IgnoreProjector" = "True" "RenderType" = "Transparent" "DisableBatching" = "True" } | |
ZWrite 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 pos : SV_POSITION; | |
}; | |
sampler2D _MainTex; | |
float4 _MainTex_ST; | |
v2f vert (appdata v) | |
{ | |
v2f o; | |
o.pos = UnityObjectToClipPos(v.vertex); | |
o.uv = v.uv.xy; | |
// billboard mesh towards camera | |
float3 vpos = mul((float3x3)unity_ObjectToWorld, v.vertex.xyz); | |
float4 worldCoord = float4(unity_ObjectToWorld._m03, unity_ObjectToWorld._m13, unity_ObjectToWorld._m23, 1); | |
float4 viewPos = mul(UNITY_MATRIX_V, worldCoord) + float4(vpos, 0); | |
float4 outPos = mul(UNITY_MATRIX_P, viewPos); | |
o.pos = outPos; | |
UNITY_TRANSFER_FOG(o,o.vertex); | |
return o; | |
} | |
fixed4 frag (v2f i) : SV_Target | |
{ | |
// sample the texture | |
fixed4 col = tex2D(_MainTex, i.uv); | |
// apply fog | |
UNITY_APPLY_FOG(i.fogCoord, col); | |
return col; | |
} | |
ENDCG | |
} | |
} | |
} |
The direction is not towards the camera further it is only billboard the mesh not its collider
How could a shader program (which executes on the GPU as part of the graphics pipeline) possibly access and manipulate the physics collider data??? Short answer: it can't
Shader "Custom/Billboard"
{
Properties
{
_MainTex("Texture Image", 2D) = "white" {}
_ScaleX("Scale X", Float) = 1.0
_ScaleY("Scale Y", Float) = 1.0
}
SubShader
{
Tags {"Queue" = "Transparent" "IgnoreProjector" = "True" "RenderType" = "Transparent"}
ZWrite Off
Blend SrcAlpha OneMinusSrcAlpha
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
}
}
}
I don't know why but Unity said there was an error on one line in your code. Might be because I'm using unity 2017.
Instead of UNITY_TRANSFER_FOG(o,o.vertex);
I believe it should be: UNITY_TRANSFER_FOG(o,o.pos);
Shader "Unlit/Billboard"
{
Properties
{
_MainTex ("Texture", 2D) = "white" {}
}
SubShader
{
Tags{ "Queue" = "Transparent" "IgnoreProjector" = "True" "RenderType" = "Transparent" "DisableBatching" = "True" }
ZWrite 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 pos : SV_POSITION;
};
sampler2D _MainTex;
float4 _MainTex_ST;
v2f vert (appdata v)
{
v2f o;
o.pos = UnityObjectToClipPos(v.vertex);
o.uv = v.uv.xy;
// billboard mesh towards camera
float3 vpos = mul((float3x3)unity_ObjectToWorld, v.vertex.xyz);
float4 worldCoord = float4(unity_ObjectToWorld._m03, unity_ObjectToWorld._m13, unity_ObjectToWorld._m23, 1);
float4 viewPos = mul(UNITY_MATRIX_V, worldCoord) + float4(vpos, 0);
float4 outPos = mul(UNITY_MATRIX_P, viewPos);
o.pos = outPos;
UNITY_TRANSFER_FOG(o,o.pos);
return o;
}
fixed4 frag (v2f i) : SV_Target
{
// sample the texture
fixed4 col = tex2D(_MainTex, i.uv);
// apply fog
UNITY_APPLY_FOG(i.fogCoord, col);
return col;
}
ENDCG
}
}
}
Hi!
If its no trouble, could you help explain these two calculations you perform here?
float4 viewPos = mul(UNITY_MATRIX_V, worldCoord) + float4(vpos, 0);
float4 outPos = mul(UNITY_MATRIX_P, viewPos);
I'm having a bit of trouble understanding what exactly is going on with it.
Hi !
Thanks, this shader was exactly what I was looking for, but does anyone know why it doesn't work with flipped sprites ? (either with flipX or scale.x = -1)
Same code, but rewritten to match URP shader style.
float3 vpos = TransformObjectToWorldDir(IN.vertex, false);
float3 worldCoord = GetObjectToWorldMatrix()._m03_m13_m23;
float3 viewPos = TransformWorldToView(worldCoord) + vpos;
OUT.vertex = TransformWViewToHClip(viewPos);
Third line should be:
float3 viewPos = TransformWorldToView(worldCoord) + float3(-vpos.x, vpos.y, vpos.z);
otherwise what we see is the back of plane (set to "cull back" then you will see)
Shader "Unit/Fx_BillBoard"
{
Properties
{
[Enum(UnityEngine.Rendering.BlendMode)]_Src("Src", Float) = 1
[Enum(UnityEngine.Rendering.BlendMode)]_Dst("Dst", Float) = 1
_MainTex("MainTex", 2D) = "white" {}
}
SubShader
{
Tags { "RenderType"="Opaque" "Queue"="Transparent" "PreviewType"="Plane" }
LOD 100
CGINCLUDE
#pragma target 3.0
ENDCG
Blend [_Src] [_Dst], SrcAlpha OneMinusSrcAlpha
AlphaToMask Off
Cull Off
ColorMask RGBA
ZWrite Off
ZTest LEqual
Stencil
{
Ref 255
CompFront Always
PassFront Keep
FailFront Keep
ZFailFront Keep
CompBack Always
PassBack Keep
FailBack Keep
ZFailBack Keep
}
Pass
{
Name "Unlit"
Tags { "LightMode"="ForwardBase" }
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#pragma multi_compile_instancing
#include "UnityCG.cginc"
#include "UnityShaderVariables.cginc"
struct appdata
{
float4 vertex : POSITION;
float4 color : COLOR;
float3 ase_normal : NORMAL;
float4 ase_tangent : TANGENT;
float4 ase_texcoord : TEXCOORD0;
};
struct v2f
{
float4 vertex : SV_POSITION;
#ifdef ASE_NEEDS_FRAG_WORLD_POSITION
float3 worldPos : TEXCOORD0;
#endif
float4 ase_texcoord1 : TEXCOORD1;
float4 ase_color : COLOR;
};
uniform float _Src;
uniform float _Dst;
uniform sampler2D _MainTex;
uniform float4 _MainTex_ST;
v2f vert ( appdata v )
{
v2f o;
//Calculate new billboard vertex position and normal;
float3 upCamVec = normalize ( UNITY_MATRIX_V._m10_m11_m12 );
float3 forwardCamVec = -normalize ( UNITY_MATRIX_V._m20_m21_m22 );
float3 rightCamVec = normalize( UNITY_MATRIX_V._m00_m01_m02 );
float4x4 rotationCamMatrix = float4x4( rightCamVec, 0, upCamVec, 0, forwardCamVec, 0, 0, 0, 0, 1 );
v.ase_normal = normalize( mul( float4( v.ase_normal , 0 ), rotationCamMatrix )).xyz;
v.ase_tangent.xyz = normalize( mul( float4( v.ase_tangent.xyz , 0 ), rotationCamMatrix )).xyz;
//This unfortunately must be made to take non-uniform scaling into account;
//Transform to world coords, apply rotation and transform back to local;
v.vertex = mul( v.vertex , unity_ObjectToWorld );
v.vertex = mul( v.vertex , rotationCamMatrix );
v.vertex = mul( v.vertex , unity_WorldToObject );
o.ase_texcoord1.xy = v.ase_texcoord.xy;
o.ase_color = v.color;
//setting value to unused interpolator channels and avoid initialization warnings
o.ase_texcoord1.zw = 0;
o.vertex = UnityObjectToClipPos(v.vertex);
#ifdef ASE_NEEDS_FRAG_WORLD_POSITION
o.worldPos = mul(unity_ObjectToWorld, v.vertex).xyz;
#endif
return o;
}
fixed4 frag (v2f i ) : SV_Target
{
float2 uv_MainTex = i.ase_texcoord1.xy * _MainTex_ST.xy + _MainTex_ST.zw;
float4 finalColor = tex2D( _MainTex, uv_MainTex);
return finalColor;
}
ENDCG
}
}
}
The direction is not towards the camera further it is only billboard the mesh not its collider