Hi GameDev.
Im currently having a problem with my geometry shader in which i want to billboard my particles to face the camera. Currently the bill boarding seems to work from most angles, however when i go to close to the particles they warp, and when at a certain position in which i look at the particles the bill board effect stops entirely until i have moved again.
Pictures to show, because my explanation skills are atrocious:
http://s720.photobucket.com/user/jbshadow1993/media/HELP.png.html
http://s720.photobucket.com/user/jbshadow1993/media/HELP2-1.png.html
In my eyes the calculation of the vectors for bill boarding is correct. However im skeptical about the need to multiply the new position of each vertex by the world matrix, as that had already been done in the vertex shader and been assigned to each new vertex generated.
Here is both vertex shader and geometry shader, hopefully its something stupid that i have missed or not understood correctly.
Any help is greatly appreciated.
cbuffer cbNeverChanges : register( b0 )
{
matrix g_view;
};
cbuffer cbChangeOnResize : register( b1 )
{
matrix g_proj;
};
//Camera position to work out billboarding
cbuffer cbCameraPos : register( b2 )
{
float4 g_camPos;
};
struct VS_Input
{
float4 pos : POSITION;
float2 tex0 : TEXCOORD0;
float4x4 InstWorld : WORLD;
float Size : SIZE;
uint InstID : SV_InstanceID;
};
struct GS_Input
{
float4 posL : POSITION1;
float4 posH : POSITION2;
float2 tex0 : TEXCOORD0;
float4x4 InstWorld : WORLD;
float Size : SIZE;
};
struct GS_Output
{
float4 Pos : SV_POSITION;
float2 TexCoords : TEXCOORD0;
};
GS_Input VS( VS_Input vertex )
{
GS_Input vsOut = ( GS_Input )0;
//Transform the vertex position
vsOut.posL = mul( vertex.pos, vertex.InstWorld );
vsOut.posH = mul( vsOut.posL, g_view );
vsOut.posH = mul( vsOut.posH, g_proj );
//Assign size so that it can be used in the gs
vsOut.Size = vertex.Size;
vsOut.InstWorld = vertex.InstWorld;
vsOut.tex0 = vertex.tex0;
return vsOut;
}
[maxvertexcount(4)]
void GS(point GS_Input input[1], inout TriangleStream<GS_Output> outputStream)
{
//calculate the look at vector
float3 lookVec = (float3)g_camPos - (float3)input[0].posL;
lookVec = normalize(lookVec);
//assign the up vec
float3 upVec = float3(0.0f, 1.0f, 0.0f);
//Calculate the right vector
float3 rightVec = normalize(cross(upVec, lookVec));
// To use so that the particle will rotate around its centre
float halfSize = input[0].Size / 2.0f;
//Get the up vector of the quad
float3 quadUpVec = normalize(cross(lookVec, rightVec));
//Times it by half the size to build quad from around the center
quadUpVec = quadUpVec * halfSize;
rightVec = rightVec * halfSize;
// Create the positions of the quad
float3 position[4];
//Top Left
position[0] = (float3)input[0].posL - rightVec + quadUpVec;
//Top Right
position[1] = (float3)input[0].posL + rightVec + quadUpVec;
//Bottom Left
position[2] = (float3)input[0].posL - rightVec - quadUpVec;
//Bottom Right
position[3] = (float3)input[0].posL + rightVec - quadUpVec;
float2 texcoords[4];
texcoords[0] = float2(1.0f, 0.0f);
texcoords[1] = float2(1.0f, 1.0f);
texcoords[2] = float2(0.0f, 0.0f);
texcoords[3] = float2(0.0f, 1.0f);
GS_Output newVertex;
for(int k = 0; k < 4; k++)
{
//Assign position
newVertex.Pos = mul(float4(position[k], 1.0f), input[0].InstWorld);
newVertex.Pos = mul(newVertex.Pos, g_view);
newVertex.Pos = mul(newVertex.Pos, g_proj);
newVertex.TexCoords = texcoords[k];
outputStream.Append(newVertex);
}
}
Thanks
TaintedGear