Reedbeta said:
Your code looks fine to me. Could we see the source for BuildBackfaceShadowPolygon()?
I assume the yellow dot in the second image is the light?

The yellow dot is the position of a light which has shadows turned off.
I simplified the BuildBackfaceShadowPolygon() in the sample code purposely since it is quite complex, it actually calls: CreateContourList();
Code is at bottom (quite a bit of code).
Now the funny thing is that my shadow volumes are ALWAYS correct. No matter what object or where my camera is it is always good and no faces on the shadow volume duplicate themselves. That is when I render my shadow volume as a actual object and display the normals. All the normals are outward, there are no cracks in my volume, and the backfaces of the polygon are capping the volume correctly.
However, when I render my volume to the stencil buffer, there are times when it is correct, then there are times when it does not seems to decrement the buffer.
If i place one plane above another, and a stationary light positioned above it, when I 'circle strafe' around the objects half the circle it works, the other half you can see the volume being rendered.
void CShadow::CreateContourList(std::vector<CMesh> &pengineObjects, CVector3 lightPosition, int lightNumber)
{
glEnable(GL_STENCIL_TEST);
glStencilFunc(GL_ALWAYS, 0x0, 0xffff);
glEnable(GL_DEPTH_TEST);
glDepthFunc(GL_LESS);
glColorMask(GL_FALSE,GL_FALSE,GL_FALSE,GL_FALSE);
glDepthMask(GL_FALSE);
glEnable(GL_CULL_FACE);
// Go through each mesh object
for (unsigned int mesh = 0; mesh < pengineObjects.size(); mesh++)
{
// Go through each face group
for (int faceGroup = 0; faceGroup < pengineObjects[mesh].NbFacesGroups; faceGroup++)
{
for (int face = 0; face < pengineObjects[mesh].Groups[faceGroup].NbFaces; face++)
{
CVector3 vertexA = pengineObjects[mesh].Vertices[pengineObjects[mesh].Groups[faceGroup].Vertices_Index[(face*3)]];
CVector3 vertexB = pengineObjects[mesh].Vertices[pengineObjects[mesh].Groups[faceGroup].Vertices_Index[(face*3)+1]];
CVector3 vertexC = pengineObjects[mesh].Vertices[pengineObjects[mesh].Groups[faceGroup].Vertices_Index[(face*3)+2]];
CVector3 normalA = pengineObjects[mesh].Normals[pengineObjects[mesh].Groups[faceGroup].Normals_Index[(face*3)]];
CVector3 normalB = pengineObjects[mesh].Normals[pengineObjects[mesh].Groups[faceGroup].Normals_Index[(face*3)+1]];
CVector3 normalC = pengineObjects[mesh].Normals[pengineObjects[mesh].Groups[faceGroup].Normals_Index[(face*3)+2]];
CVector3 faceAverage = (vertexA + vertexB + vertexC) / 3;
CVector3 faceNormal = (normalA + normalB + normalC) / 3;
faceNormal = Normalize(faceNormal);
CVector3 IncidentLightDir = faceAverage - lightPosition;
float dot = Dot(IncidentLightDir, faceNormal);
if (dot >= 0.0)
{
glCullFace(GL_BACK);
glStencilOp(GL_KEEP, GL_KEEP, GL_INCR);
BuildBackfaceShadowPolygon(pengineObjects, mesh, faceGroup, face, 1);
glCullFace(GL_FRONT);
glStencilOp(GL_KEEP, GL_KEEP, GL_DECR);
BuildBackfaceShadowPolygon(pengineObjects, mesh, faceGroup, face, 1);
glCullFace(GL_BACK);
}
}
}
// Make all contour edges extend to become the shadow volume
for (unsigned int edge = 0; edge < pengineObjects[mesh].Edges.size()-1; edge++)
{
CVector3 vertexA, vertexB;
// Get relevant data
CVector3 faceAVertexA = pengineObjects[mesh].Edges[edge].vertexA;
CVector3 faceAVertexB = pengineObjects[mesh].Edges[edge].vertexB;
CVector3 faceAAverage = pengineObjects[mesh].Edges[edge].faceAAverage;
CVector3 faceANormal = Normalize(pengineObjects[mesh].Edges[edge].faceANormal);
if (pengineObjects[mesh].Edges[edge].numConnectedFaces == 2)
{
// Get relevant data
CVector3 faceBVertexA = pengineObjects[mesh].Edges[edge].vertexB;
CVector3 faceBVertexB = pengineObjects[mesh].Edges[edge].vertex2B;
CVector3 faceBAverage = pengineObjects[mesh].Edges[edge].faceBAverage;
CVector3 faceBNormal = Normalize(pengineObjects[mesh].Edges[edge].faceBNormal);
// Get light direction
CVector3 IncidentLightDirA = faceAAverage - lightPosition;
IncidentLightDirA = Normalize(IncidentLightDirA);
CVector3 IncidentLightDirB = faceBAverage - lightPosition;
IncidentLightDirB = Normalize(IncidentLightDirB);
float dot1 = Dot(IncidentLightDirA, faceANormal);
float dot2 = Dot(IncidentLightDirB, faceBNormal);
//glFrontFace(GL_CCW);
if (dot1 >= 0 && dot2 < 0)
{
vertexA = faceAVertexA;
vertexB = faceAVertexB;
}
else if (dot2 >= 0 && dot1 < 0)
{
vertexA = faceAVertexB;
vertexB = faceAVertexA;
}
}
else
{
// Get light direction
CVector3 IncidentLightDir = faceAAverage - lightPosition;
IncidentLightDir = Normalize(IncidentLightDir);
float dot = Dot(IncidentLightDir, faceANormal);
if (dot >= 0.0)
{
vertexA = faceAVertexA;
vertexB = faceAVertexB;
}
else
{
vertexA = faceAVertexB;
vertexB = faceAVertexA;
}
}
glCullFace(GL_BACK);
glStencilOp(GL_KEEP, GL_KEEP, GL_INCR);
BuildShadowPolygon(pengineObjects, lightPosition, mesh, edge, vertexA, vertexB, 1);
glCullFace(GL_FRONT);
glStencilOp(GL_KEEP, GL_KEEP, GL_DECR);
BuildShadowPolygon(pengineObjects, lightPosition, mesh, edge, vertexA, vertexB, 1);
glCullFace(GL_BACK);
}
}
}
void CShadow::BuildShadowPolygon(std::vector<CMesh> &pengineObjects, CVector3 lightPosition, int mesh, int edge, CVector3 vertexA, CVector3 vertexB, bool drawNormal)
{
CVector3 vertex1, vertex2, vertex3, vertex4;
vertex1 = vertexA;
vertex2 = vertexB;
vertex3 = vertexB + 0.5 * (vertexB - lightPosition);
vertex4 = vertexA + 0.5 * (vertexA - lightPosition);
glColor3f (1,0,0);
glBegin(GL_QUADS);
glVertex3f(vertex1.x, vertex1.y, vertex1.z);
glVertex3f(vertex2.x, vertex2.y, vertex2.z);
glVertex3f(vertex3.x, vertex3.y, vertex3.z);
glVertex3f(vertex4.x, vertex4.y, vertex4.z);
glEnd();
}
void CShadow::BuildBackfaceShadowPolygon(std::vector<CMesh> &pengineObjects, int mesh, int faceGroup, int face, bool drawNormal)
{
glColor3f (1,0,0);
CVector3 vertex1 = pengineObjects[mesh].Vertices[pengineObjects[mesh].Groups[faceGroup].Vertices_Index[(face*3)]];
CVector3 vertex2 = pengineObjects[mesh].Vertices[pengineObjects[mesh].Groups[faceGroup].Vertices_Index[(face*3)+1]];
CVector3 vertex3 = pengineObjects[mesh].Vertices[pengineObjects[mesh].Groups[faceGroup].Vertices_Index[(face*3)+2]];
glBegin(GL_TRIANGLES);
glVertex3f(vertex1.x, vertex1.y, vertex1.z);
glVertex3f(vertex2.x, vertex2.y, vertex2.z);
glVertex3f(vertex3.x, vertex3.y, vertex3.z);
glEnd();
}