Weird Depth Testing?

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);

[ATTACH=CONFIG]812[/ATTACH]

Any thoughts?

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

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)));
}

[ATTACH=CONFIG]820[/ATTACH]

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 are absent because your [var]depth[/var] 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).

[QUOTE=GClements;1262849]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 are absent because your [var]depth[/var] 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).[/QUOTE]

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?

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.

[QUOTE=GClements;1262854]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.[/QUOTE]

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.

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).

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().

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?

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.

Okay. I’ll try a test case method when I find some time and report back.