My program is a rain particle system. After processing a list of positions of rain particles, I passed them to the geometry shader for generating a billboard for each position.
If I use a simple method to generate the billboard, (it is a rectangle, not really a billboard), it work well and I can see them in the render target. This simple method proves that the input positions for the geometry shader are right. The below HLSL source implement this simple billboard.
[maxvertexcount(4)]
void GSMAIN( point GS_INPUT input[1], inout TriangleStream<PS_INPUT> SpriteStream )
{
//Transform to view space
float4 viewposition = mul(float4(input[0].position, 1.0f), WorldViewMatrix);
// Emit two new triangles
for (int i = 0; i < 4; i++)
{
// Transform to clip space
//g_positions is an array of four deltal vectors in the form: (-scale, +scale, 0, 0)..
output.position = mul(viewposition + g_positions[i], ProjMatrix);
output.texcoords = g_texcoords[i];
output.color = color;
SpriteStream.Append(output);
}
SpriteStream.RestartStrip();
}
But if I changed to create a real billboard, it shows nothing. My method is based the velocity vector of rain drop. The implementation is in below:
[maxvertexcount(4)]
void GSMAIN( point GS_INPUT input[1], inout TriangleStream<PS_INPUT> SpriteStream )
{
PS_INPUT output;
//Velocity of raindrop = Rate + original velocity
//The billboard will stays along this vector
float3 velocityVector = input[0].speed.xyz/FrameRate + TotalVelocity;
//ViewPosition: the position of camera
GenRainSpriteVertices(input[0].position, velocityVector, ViewPosition, pos);
for(int i = 0; i < 4; i++)
{
output.position = mul(float4(pos[i], 1.0f), WorldViewProjMatrix);
output.texcoords = g_texcoords[0];
output.color = color;
SpriteStream.Append(output);
}
}
///////////////////////////////////////////////////
//The function generating billboard from
//1. Point Position
//2. Eye Position
//3. Velocity vector
///////////////////////////////////////////////////
void GenRainSpriteVertices(float3 worldPos, float3 velVec, float3 eyePos, out float3 outPos[4])
{
float height = g_SpriteSize / 2.0;
float width = height / 10.0;
velVec = normalize(velVec);
float3 eyeVec = eyePos - worldPos;
float3 eyeOnVelVecPlane = eyePos - ((dot(eyeVec, velVec)) * velVec);
float3 projectedEyeVec = eyeOnVelVecPlane - worldPos;
float3 sideVec = normalize(cross(projectedEyeVec, velVec));
outPos[0] = worldPos - (sideVec * 0.5*width);
outPos[1] = outPos[0] + (sideVec * width);
outPos[2] = outPos[0] + (velVec * height);
outPos[3] = outPos[2] + (sideVec * width);
}
I tried to use Nsight and Graphics Diagnostics in VS2012 to debug, and all of them show that the geometry shader generated the right vertices. The following pictures are from Visual Studio and Nsight, which present the result after the geometry shader finished its job.
And the next result is from Nsight:
For some reason, the generated vertices in the geometry shader are discarded in the pixel shader. Why might this be?