Hi!
I’m drawing point clouds as a huge bunch of cubes using a fancy geometry shader and kind of can’t figure out how to properly use the generated cubes as shadow casters.
I already found out I have to define shadow passes myself but I’m not sure whether I have to do all the geometry generation again in the following passes or whether I can somehow transfer the whole ordeal.
I’d really appreciate any hints as I’m really no expert at shader programming and don’t quite get what the shadow passes do (couldn’t find proper documentation neither).
As a minimal example which shows billboards at the vertex positions but draws the shadow of the underlying mesh.
Billboard shader from:
http://forum.unity3d.com/threads/169415-Billboard-Geometry-Shader
Shadow code from:
http://forum.unity3d.com/threads/216276-Modifying-vertex-position-shader-in-a-Surface-shader-Shadow-problems
Shader "Custom/GS Billboard"
{
Properties
{
_SpriteTex ("Base (RGB)", 2D) = "white" {
}
_Size ("Size", Range(0, 3)) = 0.5
}
SubShader
{
Pass
{
Tags {
"RenderType"="Opaque" }
LOD 200
CGPROGRAM
#pragma target 5.0
#pragma vertex VS_Main
#pragma fragment FS_Main
#pragma geometry GS_Main
#include "UnityCG.cginc"
// **************************************************************
// Data structures *
// **************************************************************
struct GS_INPUT
{
float4 pos : POSITION;
float3 normal : NORMAL;
float2 tex0 : TEXCOORD0;
}
;
struct FS_INPUT
{
float4 pos : POSITION;
float2 tex0 : TEXCOORD0;
}
;
// **************************************************************
// Vars *
// **************************************************************
float _Size;
float4x4 _VP;
Texture2D _SpriteTex;
SamplerState sampler_SpriteTex;
// **************************************************************
// Shader Programs *
// **************************************************************
// Vertex Shader ------------------------------------------------
GS_INPUT VS_Main(appdata_base v)
{
GS_INPUT output = (GS_INPUT)0;
output.pos = mul(_Object2World, v.vertex);
output.normal = v.normal;
output.tex0 = float2(0, 0);
return output;
}
// Geometry Shader -----------------------------------------------------
[maxvertexcount(4)]
void GS_Main(point GS_INPUT p[1], inout TriangleStream<FS_INPUT> triStream)
{
//get up vector
float3 up = float3(0, 1, 0);
//get look vector
float3 look = _WorldSpaceCameraPos - p[0].pos;
look.y = 0;
look = normalize(look);
//get right vector
float3 right = cross(up, look);
//half the size please..
float halfS = 0.5f * _Size;
//offsets
float4 v[4];
v[0] = float4(p[0].pos + halfS * right - halfS * up, 1.0f);
v[1] = float4(p[0].pos + halfS * right + halfS * up, 1.0f);
v[2] = float4(p[0].pos - halfS * right - halfS * up, 1.0f);
v[3] = float4(p[0].pos - halfS * right + halfS * up, 1.0f);
float4x4 vp = mul(UNITY_MATRIX_MVP, _World2Object);
FS_INPUT pIn;
pIn.pos = mul(vp, v[0]);
pIn.tex0 = float2(1.0f, 0.0f);
triStream.Append(pIn);
pIn.pos = mul(vp, v[1]);
pIn.tex0 = float2(1.0f, 1.0f);
triStream.Append(pIn);
pIn.pos = mul(vp, v[2]);
pIn.tex0 = float2(0.0f, 0.0f);
triStream.Append(pIn);
pIn.pos = mul(vp, v[3]);
pIn.tex0 = float2(0.0f, 1.0f);
triStream.Append(pIn);
}
// Fragment Shader -----------------------------------------------
float4 FS_Main(FS_INPUT input) : COLOR
{
return _SpriteTex.Sample(sampler_SpriteTex, input.tex0);
}
ENDCG
}
// Pass to render object as a shadow caster
Pass {
Name "ShadowCaster"
Tags {"LightMode" = "ShadowCaster" }
Fog {Mode Off}
ZWrite On ZTest LEqual Cull Off
Offset 1, 1
CGPROGRAM
#pragma target 5.0
#pragma vertex vert
#pragma fragment frag
#pragma multi_compile_shadowcaster
#pragma fragmentoption ARB_precision_hint_fastest
#include "UnityCG.cginc"
struct v2f {
V2F_SHADOW_CASTER;
};
v2f vert( appdata_base v )
{
v2f o;
TRANSFER_SHADOW_CASTER(o)
return o;
}
float4 frag( v2f i ) : COLOR
{
SHADOW_CASTER_FRAGMENT(i)
}
ENDCG
}
// Pass to render object as a shadow collector
Pass {
Name "ShadowCollector"
Tags {"LightMode" = "ShadowCollector" }
Fog {Mode Off}
ZWrite On ZTest LEqual
CGPROGRAM
#pragma target 5.0
#pragma vertex vert
#pragma fragment frag
#pragma fragmentoption ARB_precision_hint_fastest
#pragma multi_compile_shadowcollector
#define SHADOW_COLLECTOR_PASS
#include "UnityCG.cginc"
struct appdata {
float4 vertex : POSITION;
};
struct v2f {
V2F_SHADOW_COLLECTOR;
};
v2f vert (appdata v){
v2f o;
TRANSFER_SHADOW_COLLECTOR(o)
return o;
}
fixed4 frag (v2f i) : COLOR
{
SHADOW_COLLECTOR_FRAGMENT(i)
}
ENDCG
}//end pass
}//end subshader
//Fallback "Diffuse"
}//end shader