Problem rendering textured quads with transparent areas
I'm working on a project in which i have to load and visualize point clouds (so around millions of points at a time). The best solution i found was to generate, in runtime, a series of meshes using the cloud's points as vertices, with the mesh topology property set to "points". This, though, got the points/vertices to be rendered ALWAYS as a single pixel on the screen, so kinda unusable. Then, as i started studying shader writing, i got that a good solution for my problem would've been to use a geometry shader that could generate a textured quad for each of the points, with a billboarding effect to make the quads always face the camera, and including a shader property that could allow me to increase or decrease the size of these quads at will. Being a noob at writing shaders, i looked around on the web for some example to use as a base, then i modified it to get a proper billboard effect and to use color data from the mesh vertices. I ended up with this:
Shader "Custom/GS Billboard"
{
Properties
{
_SpriteTex ("Base (RGB)", 2D) = "white" {}
_Size ("Size", Range(0, 3)) = 0.5
}
SubShader
{
Pass
{
Tags { "Queue" = "Transparent" "RenderType" = "Transparent"}
LOD 200
Blend SrcAlpha OneMinusSrcAlpha
CGPROGRAM
#pragma target 4.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;
fixed4 color : COLOR;
};
struct FS_INPUT
{
float4 pos : POSITION;
float2 tex0 : TEXCOORD0;
fixed4 color : COLOR;
};
// **************************************************************
// Vars *
// **************************************************************
float _Size;
float4x4 _VP;
Texture2D _SpriteTex;
SamplerState sampler_SpriteTex;
// **************************************************************
// Shader Programs *
// **************************************************************
// Vertex Shader ------------------------------------------------
GS_INPUT VS_Main(appdata_full v)
{
GS_INPUT output = (GS_INPUT)0;
output.pos = mul(unity_ObjectToWorld, v.vertex);
output.normal = v.normal;
output.tex0 = float2(0, 0);
output.color = v.color;
return output;
}
// Geometry Shader -----------------------------------------------------
[maxvertexcount(4)]
void GS_Main(point GS_INPUT p[1], inout TriangleStream<FS_INPUT> triStream)
{
float3 up = UNITY_MATRIX_V[1].xyz;
float3 right = UNITY_MATRIX_V[0].xyz * -1;
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, unity_WorldToObject);
FS_INPUT pIn;
pIn.color = p[0].color;
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 input.color * _SpriteTex.Sample(sampler_SpriteTex, input.tex0);
}
ENDCG
}
}
}
The quads are rendered and can be resized, but there is something wrong with the blending, since the transparent area of the texture of a quad seems to often "cover" the quad behind it. What am i doing wrong?
Here is a screen of what i get: