PDA

View Full Version : Weird Depth Testing?



ParagonArcade
12-01-2014, 09:22 PM
Using OpenGL 4.4 and GLSL,

I have an icosahedron at position (0, 0, 0) and a plane at height = 1 with camera at (0, 2, 0). The depth testing seems to be backwards. Don't know what to do. When I flip the depth test to GREATER, nothing draws.

...
glClearColor(0.0f, 0.0f, 0.0f, 0.0f);

glEnable(GL_CULL_FACE);
glCullFace(GL_BACK);
glFrontFace(GL_CW);

glEnable(GL_DEPTH_TEST);
glDepthFunc(GL_LESS);
glEnable(GL_DEPTH_CLAMP);

glEnable(GL_TEXTURE_2D);
...


1521


Any thoughts?

uwi2k2
12-05-2014, 10:36 AM
hi,

if you set glFrontFace to CW
and cull BACK you normaly see the inside of something ... assuming your data is normal vertex order ..

cu
kai

ParagonArcade
12-05-2014, 07:12 PM
For some reason I thought I tried this and it didn't work. I went back and wrote a function which inverts the normals of my object and its fixed. Thanks!

ParagonArcade
12-06-2014, 03:07 AM
For some reason I thought I tried this and it didn't work. I went back and wrote a function which inverts the normals of my object and its fixed. Thanks!

Maybe I spoke too soon. It's still doing it. The hallway on the right should be hidden by the wall. Its not being clipped either. It's the depth.



glEnable(GL_CULL_FACE);
glCullFace(GL_BACK);
glFrontFace(GL_CCW);

glEnable(GL_DEPTH_TEST);
glDepthFunc(GL_LESS);
glEnable(GL_DEPTH_CLAMP);

glEnable(GL_TEXTURE_2D);

...

createScreen("PARAGON 3D", false, 1366, 768, 1.0f, 1000.0f);

...

zNear = 1.0f;
zFar = 1000.0f;

...

Matrix4f Matrix4f::initProjection(float left, float right, float bottom, float top, float zNear, float zFar)
{
float width = right - left;
float height = top - bottom;
float depth = zNear - zFar;

m[0][0] = (2 * zNear) / width; m[0][1] = 0; m[0][2] = (right + left) / width; m[0][3] = 0;
m[1][0] = 0; m[1][1] = (2 * zNear) / height; m[1][2] = (top + bottom) / height; m[1][3] = 0;
m[2][0] = 0; m[2][1] = 0; m[2][2] = (-1.0f * zFar + zNear) / depth; m[2][3] = (-2.0f * zFar * zNear) / depth;
m[3][0] = 0; m[3][1] = 0; m[3][2] = -1.0f; m[3][3] = 0;

return *this;
}

...

void Level::generateLeft(int i, int j)
{
int size = mesh->getNumOfVertices();

mesh->addElement(size + 0); mesh->addElement(size + 1); mesh->addElement(size + 2);
mesh->addElement(size + 0); mesh->addElement(size + 2); mesh->addElement(size + 3);

int halfWidth = level->getWidth() / 2;
int halfHeight = level->getHeight() / 2;

//Left Plane
mesh->addVertex(Vertex(Vector3f((i - halfWidth - 0.5) * SPOT_W, SPOT_H, (j - halfHeight + 0.5) * SPOT_L), Vector3f(1, 1, 1), Vector3f(1, 0, 0), Vector2f(0, 0)));
mesh->addVertex(Vertex(Vector3f((i - halfWidth - 0.5) * SPOT_W, 0.0f, (j - halfHeight + 0.5) * SPOT_L), Vector3f(1, 1, 1), Vector3f(1, 0, 0), Vector2f(1, 0)));
mesh->addVertex(Vertex(Vector3f((i - halfWidth - 0.5) * SPOT_W, 0.0f, (j - halfHeight - 0.5) * SPOT_L), Vector3f(1, 1, 1), Vector3f(1, 0, 0), Vector2f(1, 1)));
mesh->addVertex(Vertex(Vector3f((i - halfWidth - 0.5) * SPOT_W, SPOT_H, (j - halfHeight - 0.5) * SPOT_L), Vector3f(1, 1, 1), Vector3f(1, 0, 0), Vector2f(0, 1)));
}


1532

GClements
12-06-2014, 05:31 PM
Matrix4f Matrix4f::initProjection(float left, float right, float bottom, float top, float zNear, float zFar)
{
float width = right - left;
float height = top - bottom;
float depth = zNear - zFar;

m[0][0] = (2 * zNear) / width; m[0][1] = 0; m[0][2] = (right + left) / width; m[0][3] = 0;
m[1][0] = 0; m[1][1] = (2 * zNear) / height; m[1][2] = (top + bottom) / height; m[1][3] = 0;
m[2][0] = 0; m[2][1] = 0; m[2][2] = (-1.0f * zFar + zNear) / depth; m[2][3] = (-2.0f * zFar * zNear) / depth;
m[3][0] = 0; m[3][1] = 0; m[3][2] = -1.0f; m[3][3] = 0;

return *this;
}


If this is supposed to behave like glFrustum, m[2][2] and m[2][3] are wrong. They should be


m[2][2] = (zFar + zNear) / depth; m[2][3] = (2.0f * zFar * zNear) / depth;

The minus signs which appear in the glFrustum manual page (https://www.opengl.org/sdk/docs/man2/xhtml/glFrustum.xml) are absent because your depth has the opposite sign to the denominator there.

If you're trying to construct a left-handed coordinate system for eye space (with the view direction along the positive Z axis rather than the negative Z axis), all 4 of the entries in column 2 (i.e. m[...][2]) need to be negated.

Also, your matrix is in row-major order, so it needs to be transposed (e.g. by setting transpose=GL_TRUE when calling glUniformMatrix4f).

ParagonArcade
12-06-2014, 07:04 PM
If this is supposed to behave like glFrustum, m[2][2] and m[2][3] are wrong. They should be


m[2][2] = (zFar + zNear) / depth; m[2][3] = (2.0f * zFar * zNear) / depth;

The minus signs which appear in the glFrustum manual page (https://www.opengl.org/sdk/docs/man2/xhtml/glFrustum.xml) are absent because your depth has the opposite sign to the denominator there.

If you're trying to construct a left-handed coordinate system for eye space (with the view direction along the positive Z axis rather than the negative Z axis), all 4 of the entries in column 2 (i.e. m[...][2]) need to be negated.

Also, your matrix is in row-major order, so it needs to be transposed (e.g. by setting transpose=GL_TRUE when calling glUniformMatrix4f).

Thank you for the response. I am piece-ing this all together from a youtube series which a great guide, but little changes are made which arent referenced I believe.

I corrected the code to the following and the depth testing works.



Matrix4f Matrix4f::initProjection(float left, float right, float bottom, float top, float zNear, float zFar)
{
float width = right - left;
float height = top - bottom;
float depth = zNear - zFar;

m[0][0] = (2 * zNear) / width; m[0][1] = 0; m[0][2] = (right + left) / width; m[0][3] = 0;
m[1][0] = 0; m[1][1] = (2 * zNear) / height; m[1][2] = (top + bottom) / height; m[1][3] = 0;
m[2][0] = 0; m[2][1] = 0; m[2][2] = (1.0f * zFar + zNear) / depth; m[2][3] = (2.0f * zFar * zNear) / depth;
m[3][0] = 0; m[3][1] = 0; m[3][2] = -1.0f; m[3][3] = 0;

return *this;
}


I want to create a right-handed system, so the right-hand rule applies, +i cross +j = +k; Will I need to transpose from row-major order no matter what? Or just for a left or right handed system?

GClements
12-06-2014, 08:16 PM
I want to create a right-handed system, so the right-hand rule applies, +i cross +j = +k; Will I need to transpose from row-major order no matter what? Or just for a left or right handed system?
The updated matrix matches that generated by glFrustum(), which results in eye-space being a right-handed coordinate system ("forward" is along the negative Z axis).

Regardless of left- or right-handed coordinate system, you need to either pass the matrix to OpenGL in column-major order (i.e. m[0][0] is followed by m[1][0] in memory) or have OpenGL transpose the matrix.

ParagonArcade
12-06-2014, 11:31 PM
The updated matrix matches that generated by glFrustum(), which results in eye-space being a right-handed coordinate system ("forward" is along the negative Z axis).

Regardless of left- or right-handed coordinate system, you need to either pass the matrix to OpenGL in column-major order (i.e. m[0][0] is followed by m[1][0] in memory) or have OpenGL transpose the matrix.

When I transposed the matrix, everything broke. What else would I need to change to get back to normal? Transpose all my other matrices? If so, what advantage to I gain?

Here is how I am passing the Matrix4f to the GLSL as a mat4 uniform as a float array.



float* Matrix4f::getFloats()
{
float* mat4x4 = new float[16];

for (int k = 0; k < 16; k++)
{
int i = k % 4;
int j = floor(k / 4);

mat4x4[k] = m[i][j];
}

return mat4x4;
}


Also, is there a limitation on the maximum amount of Uniforms one can send?

I think I might have reached the maximum or something. When I try to set a new "int" uniform, I lose some of my point lights, like the uniform data is corrupt.

GClements
12-07-2014, 07:54 PM
float* Matrix4f::getFloats()
{
float* mat4x4 = new float[16];

for (int k = 0; k < 16; k++)
{
int i = k % 4;
int j = floor(k / 4);

mat4x4[k] = m[i][j];
}

return mat4x4;
}


That's returning the matrix in column-major order, which is what OpenGL wants. If you were just casting m to a float* then it would be in row-major order and need to be transposed.

BTW, there's no need for the floor() in the above code; In C and C++, dividing two integers produces an integer result (any fractional part is discarded, i.e. the result is rounded toward zero).



Also, is there a limitation on the maximum amount of Uniforms one can send?

It depends upon the implementation. There is a required minimum value which depends upon the OpenGL version. You're guaranteed at least 16 vectors in the fragment shader and 128 vectors in the vertex shader. OpenGL 3 increased this to at least 256 vectors in each shader.

The actual values can be queried with glGetIntegerv().

ParagonArcade
12-17-2014, 09:18 AM
That's returning the matrix in column-major order, which is what OpenGL wants. If you were just casting m to a float* then it would be in row-major order and need to be transposed.

I once again went back and tried to visually transpose all my of matrices just for convenience. I wrote all of them out beforehand and then commented out the original ones. All the Matrix4f functions look correct, triple checked, but it only sorta worked cause my quaternion rotation system broke on my camera, translation works, projection works too, objects don't change sizes from improper matrices multiplication. For now I switched it back cause I need it to work right now. Any ideas what could be mixing me up?

GClements
12-17-2014, 08:56 PM
Any ideas what could be mixing me up?
No.

All that I can suggest is to construct a minimal test case which demonstrates the problem. It's hard to analyse fragments of code in isolation, and few people will bother to analyse a large program.

You may well find that constructing the test case results in something which works. In which case, looking at how the test case differs from the real program will provide a lead.

ParagonArcade
12-17-2014, 11:01 PM
Okay. I'll try a test case method when I find some time and report back.