- Home /
Vertex Billboard Shader Depth?
Hi there,
So I'm currently testing out an RTS idea and have been looking for efficient ways of displaying large numbers of models in a scene. Much experimentation has ended up with me doing this:
1.Capturing a model on camera
2.Writing Camera to a Render Texture
3.Using a basic mesh with a vertex shader to display multiple billboards (this displays a seperate billboard on each of the mesh's vertices)
4.Using the model camera's render texture as the billboard texture
This actually worked pretty well initially as you can see:
Unfortunately there seems to be a depth issue when the mesh is viewed from opposite it's normals like so:
So here is my question, Is there a way to solve this while keeping the vertex shader?
Any help would be greatly appreciated, Gonna post the shader code here in case there is anything wrong with it
_SpriteTex ("Base (RGBA)", 2D) = "white" {}
_Size ("Size", Range(0, 3)) = 0.5
}
SubShader
{
Tags { }
ZWrite Off
Blend SrcAlpha OneMinusSrcAlpha
// Cull Back
// Offset 1, 1
LOD 200
Pass
{
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;
float3 viewT : TEXCOORD1;
};
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 = normalize(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)
{
float3 up = float3(0, 1, 0);
float3 look = _WorldSpaceCameraPos - p[0].pos;
look.y = 0;
look = normalize(look);
float3 right = cross(up, look);
float halfS = 0.5f * _Size;
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
}
}
Fallback "Diffuse"
}
Answer by Graphics_Dev · Feb 16, 2016 at 03:00 PM
Read this page...
http://docs.unity3d.com/Manual/SL-CullAndDepth.html
Although I haven't done much with shaders recently, I'm pretty confident you will need to turn ZWrite on (line 9).
Let me know if this helps :)
Hi Graphics, thanks for getting back to me!
I had Zwrite On previously and it seems to have its own issue as you can see here:
Hard to demonstrate when its not running but with Zwrite On the see through effect dissapears but now the "men" to the rear are partially or totally obscured by those in front despite the transparency(there should be three uniform rows here).
again the unit displays correctly if viewed from the normal facing side(if that makes sense). I tried having two duplicate meshes facing opposite directions but that didnt make a difference(which makes sense since it seems to be on the shader side).
I'm very close to a workable method and I'm desperate to know if im chasing thin air so I can change approach. :)
Hi Graphics, tried with all the ztest modes and it was either the same or the billboards disappeared. Thanks for the suggestion anyway!
In conjunction with ZWrite being on, this appears to be some of the fun of transparent texture layering. I would recommend adding in a line to Clip() the pixels in the RenderTexture with a low enough (zero?) opacity. I can't guarantee success from that, but it should serve as a more definite way of preventing occlusion when dealing with transparency.
Hi Eno, Didnt know there was a clip function, I'l see if I can work it into the current shader and get back to you :)