PDA

View Full Version : Projection Depth Problem



bcthund
11-27-2010, 05:16 PM
I got this odd problem that seems to have cropped up after everything was working just fine and I can't trace back to where the problem is.

I have a shader class to load and initialize my shaders, and a matrix class to do all my matrix calculations. I have 5 triangles being drawn with 4 draw commands. When in the Orthographic view everything looks just fine. It's 3 triangles that each get smaller in size sitting on top of 2 triangles creating a base:
http://www.bcthund.net/image/programming/cpp/depth_problem/ortho.png

However once I switch to Perspective mode it tuns into this:
http://www.bcthund.net/image/programming/cpp/depth_problem/perspective.png

This WAS working with no problems but at some point the perspective mode stopped working right. I thought that it was a depth test problem but I don't see how that could be the case since the only difference between orthographic and perspective mode is one matrix multiplication.

Does anyone have any suggestions as to what might cause this kind of problem?

Alfonse Reinheart
11-27-2010, 05:43 PM
Does anyone have any suggestions as to what might cause this kind of problem?

Your perspective matrix. It looks like it is reversing the depth of the objects. What code do you use to generate one, and what does your pre-perspective coordinate system look like?

bcthund
11-27-2010, 06:30 PM
The initial state is an Identity Matrix set with the code:


void Matrix::LoadIdentity(Matrix44f m)
{
static Matrix44f identity = { 1.0f, 0.0f, 0.0f, 0.0f,
0.0f, 1.0f, 0.0f, 0.0f,
0.0f, 0.0f, 1.0f, 0.0f,
0.0f, 0.0f, 0.0f, 1.0f };

memcpy(m, identity, sizeof(Matrix44f));
}


This is the code that sets the perspective matrix:


myMatrix.SetPerspective(35.0f, float(1024)/float(768), 1.0f, 1000.0f);



void Matrix::SetPerspective(float fFov, float fAspect, float fNear, float fFar)
{
float xmin, xmax, ymin, ymax; // Dimensions of near clipping plane

// Do the Math for the near clipping plane
ymax = fNear * float(tan( fFov * M_PI / 360.0 ));
ymin = -ymax;
xmin = ymin * fAspect;
xmax = -xmin;

// Construct the projection matrix
LoadIdentity(projMatrix);
projMatrix[0] = (2.0f * fNear)/(xmax - xmin);
projMatrix[5] = (2.0f * fNear)/(ymax - ymin);
projMatrix[8] = (xmax + xmin) / (xmax - xmin);
projMatrix[9] = (ymax + ymin) / (ymax - ymin);
projMatrix[10] = -((fFar + fNear)/(fFar - fNear));
projMatrix[11] = -1.0f;
projMatrix[14] = -((2.0f * fFar * fNear)/(fFar - fNear));
projMatrix[15] = 0.0f;
}


The perspective matrix is applied to the final ModelViewMatrix with a matrix Muliplication:


myMatrix.Multiply( *mModelViewProjection,
myMatrix.GetProjectionMatrix(),
myMatrix.mModelView);



void Matrix::Multiply(Matrix44f product, const Matrix44f a, const Matrix44f b )
{
for (int i = 0; i < 4; i++) {
float ai0=A(i,0), ai1=A(i,1), ai2=A(i,2), ai3=A(i,3);
P(i,0) = ai0 * B(0,0) + ai1 * B(1,0) + ai2 * B(2,0) + ai3 * B(3,0);
P(i,1) = ai0 * B(0,1) + ai1 * B(1,1) + ai2 * B(2,1) + ai3 * B(3,1);
P(i,2) = ai0 * B(0,2) + ai1 * B(1,2) + ai2 * B(2,2) + ai3 * B(3,2);
P(i,3) = ai0 * B(0,3) + ai1 * B(1,3) + ai2 * B(2,3) + ai3 * B(3,3);
}
}


Here are the results of outputting the different parts of the matrix.

The mModelView matrix contains the translations and rotations. When in orthographic mode:


1.000000 | 0.000000 | 0.000000 | 0.000000
0.000000 | 1.000000 | 0.000000 | 0.000000
0.000000 | 0.000000 | 1.000000 | 0.000000
0.000000 | 0.000000 | 0.000000 | 1.000000


The mModelView matrix when in perspective mode:


2.378696 | 0.000000 | 0.000000 | 0.000000
0.000000 | 3.171595 | 0.000000 | 0.000000
0.000000 | 0.000000 | -1.002002 | 1.002002
0.000000 | 0.000000 | -2.002002 | 2.002002


The mModelViewProjection matrix, this is the matrix that stores the final view matrix regardless which mode we are in.
When in orthographic mode:


1.000000 | 0.000000 | 1.000000 | 0.000000
-1.804688 | -1.809082 | 0.000000 | 0.000000
0.000000 | 0.000000 | -0.200000 | 0.350000
0.000000 | 0.000000 | 0.000000 | 0.000000


When in perspective mode:


2.378696 | 0.000000 | 1.000000 | 0.000000
-1.046876 | -1.051239 | 0.000000 | 0.000000
0.000000 | 0.000000 | -0.200000 | 0.350000
0.000000 | 0.000000 | 0.000000 | 0.000000

david_f_knight
11-27-2010, 07:51 PM
It looks like it is a depth test problem to me, as well. Are you sure the depth test is enabled (and that you have a depth buffer)? I don't see any problem with your math or matrices, but even if there was some problem with that, that shouldn't cause the problem you see. That's because the two gray triangles that form the base have the same vertices as the smallest and largest colored triangles. Whatever your transformation matrices do, they will affect identical vertices identically. What you're seeing appears to be a last-drawn triangle on top, as if there were no depth buffer at all (or as if it is disabled, or as if it had been cleared between draw calls).

bcthund
11-27-2010, 08:07 PM
I have played with the depth buffer a lot, turning it on and off, changing the DepthFunc, and changing the drawing order of the primitives. They all do something a little different with the same basic problem.

I set the screen mode with:


SDL_GL_SetAttribute( SDL_GL_RED_SIZE, 5 );
SDL_GL_SetAttribute( SDL_GL_GREEN_SIZE, 5 );
SDL_GL_SetAttribute( SDL_GL_BLUE_SIZE, 5 );
SDL_GL_SetAttribute( SDL_GL_DEPTH_SIZE, 16 );
SDL_GL_SetAttribute( SDL_GL_DOUBLEBUFFER, 2 );
screen=SDL_SetVideoMode( 1024, 768, 16, SDL_OPENGL );
glEnable(GL_DEPTH_TEST);
glDepthFunc( GL_LEQUAL );

glGetError() reports no errors at start up.

If I change the draw order of the primitives you CAN see the order that they are drawn in as if the depth buffer wasn't functioning:
http://www.bcthund.net/image/programming/cpp/depth_problem/depth.png
The above screenshot uses GL_LEQUAL, where the earlier one used GL_LESS. If the depth buffer wasn't working wouldn't glDepthFunc have no effect?

Alfonse Reinheart
11-27-2010, 08:15 PM
Are your matrices in column-major or row-major order, and how are you uploading them to the shader?

bcthund
11-27-2010, 08:39 PM
I'm still learning how to use matrix manipulations, as far as I know they are column major. Most of the math is straight from the SuperBible 5th edition. The identity matrix function had a comment that said it was in column major.

I think this is what you are referring to:


GLint iUniLoc = myShader.getUniform("mvpMatrix");
mvpMatrix = mModelViewProjection;
glUniformMatrix4fv(iUniLoc, 1, GL_FALSE, *mvpMatrix);

Alfonse Reinheart
11-27-2010, 08:51 PM
The identity matrix function had a comment that said it was in column major.

That's not sufficient information. Identity matrices are the same regardless of column/row major.

You could just change that GL_FALSE to GL_TRUE and see what happens. Or you could use someone else's matrix library, one that actually specifies the layout of matrices.

bcthund
11-27-2010, 08:59 PM
I know Identity Matrices are the same, but everything else in my code should correspond because it came from the same place.

I have tried changing GL_FALSE to GL_TRUE, changing it to true collapses the model in perspective mode and when in orthographic it does some really weird morphing of the scene. As if it's trying to display it in perspective but it's still stuck to a flat surface.

david_f_knight
11-27-2010, 09:17 PM
If the depth buffer wasn't working wouldn't glDepthFunc have no effect?Yes, you are correct. With that new information you have provided, it seems to me that the Z coordinates of all your vertices are the same. That effectively disables the depth buffer (or, renders it irrelevant), and could explain the difference you are seeing between GL_LEQUAL and GL_LESS. That brings us back to your mModelViewProjection matrix. There are a few issues. First, OpenGL matrices are column-major (but with at least the newest versions, you can pass a transpose flag telling OpenGL whether you have defined them row-major or column-major), so you need to make sure that you are defining your matrices appropriately for that and passing the correct value for the transpose flag (if you are using a version that has the transpose flag). It looks to me like you are doing that correctly, but I am guessing.

Another issue is something I noticed with your orthographic mModelViewProjection matrix. Typically, the fourth row of such matrices will be [0 0 0 1]. (The essential issue being that only the fourth value is non-zero.) Given I don't know whether your matrices are transposed or not (I assumed they were) your fourth column may be the fourth row I refer to. In any case, neither your fourth row nor your fourth column is [0 0 0 1].

Another issue is how you define projMatrix[8] and projMatrix[9]. Their values will always be zero, because you have defined them such that their numerators are the sum of additive inverses.

Anyway, as I look at your code defining your projection matrix, it doesn't look like something I am familiar with. You might try something more like:

| 1/tan_view_ang 0 0 0 |
| 0 fAspect/tan_view_ang 0 0 |
| 0 0 (fFar+fNear)/(fFar-fNear) -2*fFar*fNear/(fFar-fNear) |
| 0 0 1 0 |
And for the orthographic projection matrix, try the same as above, except make the fourth row [0 0 0 1].

david_f_knight
11-27-2010, 09:27 PM
Another thing... in your second post, your mModelView matrix when in perspective mode looks all screwy to me. If you only have translations and rotations, as you wrote, then the fourth row should be [0 0 0 1].

bcthund
11-27-2010, 09:45 PM
Your right, my matrices were all screwed up ans I did kinda suspect as much. I think I have half-solved the issue. I got the primitives to appear with correct depth testing, but at first they were behind the "camera" view so I couldn't see them.

I moved all my matrix variables out of the matrix class and printed the matrix information again and it looked correct this time. Upon playing with the controls I was able to get the primitives back into view and they appeared correct.

So apparently I have some problems with how I am managing my matrices in the class.

I think I can get the rest from this point. Thank you for all the help, I really appreciate it.

Matrix code:



mModelView
-----------------------------------------------------
-0.904072 | 0.204897 | -0.375061 | 0.000000
0.000000 | 0.877583 | 0.479426 | 0.000000
0.427380 | 0.433435 | -0.793398 | 0.000000
0.000000 | 0.000000 | -1.659999 | 1.000000

mModelViewProjection
-----------------------------------------------------
-2.150512 | 0.649850 | 0.375812 | 0.375061
0.000000 | 2.783336 | -0.480385 | -0.479426
1.016608 | 1.374681 | 0.794986 | 0.793398
0.000000 | 0.000000 | -0.338680 | 1.659999

mvpMatrix
-----------------------------------------------------
-2.150512 | -0.904072 | 0.000000 | 0.000000
-0.000014 | 0.000000 | 0.000000 | 1.000000
0.000000 | -0.600000 | 0.000000 | 0.000000
0.000000 | 0.000000 | -1.432485 | -1.432562


http://www.bcthund.net/image/programming/cpp/depth_problem/working.png