I'm writing a simple geometry shader to create 3D "primitives" in place of a single point. I am performing all of the world-view-projection conversions within the geometry shader after creating the triangle strips to form the 3D primitive. Unfortunately, it seems to be creating the triangles in projection space, and giving me incorrect results. The following pictures demonstrate this problem. Any advice on how to work around this problem?

As can be seen here, the second top face seems to be rendered as if it was pulled off the top and splayed out.

Here is the geometry shader I am using, and a set of coordinates I use to generate these faces

static float3 cube_coords[8] =
{

float3(1, -1, 1),
float3(-1, -1, 1),
float3(1, 1, 1),
float3(-1, 1, 1),

float3(1, 1, 1),
float3(-1, 1, 1),
float3(1, 1, -1),
float3(-1, 1, -1),

};

[maxvertexcount(8)]
void GSMain(point GSInput input[1], inout TriangleStream< GSOutput > output)
{
GSOutput p;

for(unsigned int j = 0; j < 2; j++)
{
for(unsigned int i = 0; i < 4; i++)
{
p.Pos = input[0].Pos;
p.Pos += float4(cube_coords[i + (4*j)],1.0);
p.Pos = mul(p.Pos, worldViewProjection);
p.Color = input[0].Color;
p.Light = input[0].Light;
p.Norm = normals[j];
output.Append(p);
}
output.RestartStrip();
}
}

• Have you taken a look at the perspective matrix / equivalent which you're using? To me it looks like the perspective is wrong and that the field of view isn't wide enough. – Polar Mar 10 '13 at 13:38
• I am currently using Pi/2 as my field of view, I am able to successfully draw a cube using a predefined vert buffer/index buffer no problem, its only when generating the new verts in the geometry shader. – Evan Mar 10 '13 at 15:25
• Are you certain that you should be specifying your field of view in radians, not degrees? – Polar Mar 10 '13 at 17:24
• I am using the XNA math library, and using XMMatrixPerspectiveFovLH() to create my projection matrix, it claims to take radians. – Evan Mar 10 '13 at 18:32

I have encountered the answer to this question myself. I had simply made a mix-up involving column major vs row major matrices, and the order in which i was multiplying them against my position within the geometry shader.

Before going into geometry shader loop, coordinates you provide are not cube coordinates if it's what you are trying to achieve.

float3(1, -1, 1),
float3(-1, -1, 1),
float3(1, 1, 1),
float3(-1, 1, 1),

float3(1, 1, 1),
float3(-1, 1, 1),
float3(1, 1, -1),
float3(-1, 1, -1),


5th point covers 3rd point and 6th point covers 4th point.

Edit: Sorry just realized I misunderstood the question.

Edit2: Not sure it's what causes the problem but vertex positions leaving the geometry shader must be transformed to homogeneous clip space. This is how it's usually done: (pseudocode)

struct VStoGS
{
float3 position : POSITION;
//other stuff
};

struct GStoPS
{
float4 positionH : SV_POSITION; //for homogeneous clip space transform
float3 positionW : POSITION; //for world space transform
//other stuff
};


foreachvertex
{
gsOutput[i].positionW = mul(float4(vertex[i].pos, 1.0f), world).xyz;
gsOutput[i].positionH = mul(float4(vertex[i].pos, 1.0f, worldViewProj);
//other stuff
}


Edit3: positionW is only needed for extra stuff in PS so that's not it.

• These are simply two of the six faces that would be used for a cube, representing a front and top face – Evan Mar 9 '13 at 19:08
• Hmm, so what is the purpose of outputting two positions in this case? The pixel shader only receives the vertices that have been rasterized i thought. So what is done with the secondary world space coordinates? – Evan Mar 9 '13 at 21:20
• Ok now I got lost. Had to look back at some projects. I used secondary POSITION for vertor to eye for lighting. Which should is not needed in your example I guess. I was convinced there is something more done with it. SV_POSITION should be enough and looks properly in your code so forget it. – Lufi Mar 9 '13 at 21:46