PDA

View Full Version : help with view and projection setup.

blubee
08-05-2015, 01:41 PM
I wrote a pretty long question here: http://stackoverflow.com/questions/31842366/setting-up-opengl-view-and-projection-transformations

but I'll also add some of the questions details down below.

I am making some basic steps towards rendering with opengl. I wrote some shaders as well as a some math functions to do the linear algebra.

I can get a quad that's 2d tris to render on screen but when it comes to applying any sort of transformations I see nothing.

Here is the relevant code as to the matrix data that I am sending to the gpu, etc.

**setup matricies**

mat4identity(&vm);
vec3f eye = {0, 0, 0};
vec3f center = {0, 0, -1};
vec3f up = {0, 1, 0};

mat4LookAt(&vm, &eye, &center, &up);
mat4print("lookat",&vm);

mat4OrthoProjection(&opm, 200, 0, 200, 0, 0.001, 1000.0);
mat4print("2d projection",&opm);

**render code**

glUseProgram(sp);
glBindVertexArray(vao1);

pMat = getUniformLocation(sp, "proj");
vMat = getUniformLocation(sp, "view");
transMat = getUniformLocation(sp, "transform");

glUniformMatrix4dv(pMat, 1, GL_FALSE, opm.m);
glUniformMatrix4dv(vMat, 1, GL_FALSE, vm.m);
glUniformMatrix4dv(transMat, 1, GL_FALSE, tm.m);

glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0);

glBindVertexArray(0);

the mat4 is a column major struct in c.

**mat4 lookat function**

mat4* lookat(vec3f* eye, vec3f* center, vec3f* up) {
vec3f x = {1, 0, 0};
vec3f y = {0, 1, 0};
vec3f z = {0, 0, 1};

z = vec3fsub(eye, center);
vec3fnorm(z);
x = vec3fcross(y, z);
y = vec3fcross(z, x);
vec3fnorm(x);
vec3fnorm(y);

double x1, y1, z1;
x1 = vec3fdotr(&x, eye);
y1 = vec3fdotr(&y, eye);
z1 = vec3fdotr(&z, eye);

double data[] = { (&x)->p[0], (&y)->p[0], (&z)->p[0], 0,
(&x)->p[1], (&y)->p[1], (&z)->p[1], 0,
(&x)->p[2], (&y)->p[2], (&z)->p[2], 0,
x1, y1, z1, 1 };
return makeMat4(data);

}

**orthographic projection code**

mat4* mat4Projection(double r, double l, double t, double b, double n, double f)
{
double data[] = { (2*n)/(r-l), 0, (r+l)/(r-l), 0,
0, (2*n)/(t-b), (t+b)/(t-b), 0,
0, 0, (-(f+n))/(f-n), (-2*(f*n))/(f-n),
0, 0, -1, 1 };
return makeMat4(data);
}

I also try to send down just a simple transform matrix that moves the objects 20 units in the +z direction. Running the above code and printing out the matrices along the way I get these results.

lookat matrix
[ 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 ]

2d projection matrix
[ 0.010000 0.000000 0.000000 -1.000000 ]
[ 0.000000 0.010000 0.000000 -1.000000 ]
[ 0.000000 0.000000 -0.002000 -1.000002 ]
[ 0.000000 0.000000 0.000000 1.000000 ]

translation matrix
[ 1.000000 0.000000 0.000000 0.000000 ]
[ 0.000000 1.000000 0.000000 0.000000 ]
[ 0.000000 0.000000 1.000000 20.000000 ]
[ 0.000000 0.000000 0.000000 1.000000 ]

The error could be at this line when I am sending the data to the gpu

glUniformMatrix4dv(pMat, 1, GL_FALSE, opm.m);

but again I am not sure. This is the vertex shader:

#version 330 core

uniform mat4 view;
uniform mat4 proj;

in vec3 position;

void main()
{
gl_Position = proj * view * vec4(position.x, position.y, position.z, 1.0);
}

removing the proj and view transformations I get the rectangle in the middle of the screen. Using either projection or view transformations and I can't see anything on screen, just the clear background.

deltayoung
08-05-2015, 06:03 PM
**orthographic projection code**

mat4* mat4Projection(double r, double l, double t, double b, double n, double f)
{
double data[] = { (2*n)/(r-l), 0, (r+l)/(r-l), 0,
0, (2*n)/(t-b), (t+b)/(t-b), 0,
0, 0, (-(f+n))/(f-n), (-2*(f*n))/(f-n),
0, 0, -1, 1 };
return makeMat4(data);
}

The matrix content in data[] looks like a perspective projection matrix to me. And if that's the case, all of the entries except the last one at the bottom right are correct. The bottom right entry should be 0, instead of 1. Could that be the source of error?

blubee
08-06-2015, 04:24 AM
I checked but that doesn't seem to be the problem. I am trying to debug the code but I don't have any reference to check against so I am going piece by piece.

mat4identity(&vm);
vec3f eye = {0, 0, 0};
vec3f center = {0, 0, -1};
vec3f up = {0, 1, 0};

mat4LookAt(&vm, &eye, &center, &up);

I pass these values into the lookat function:

eye [ x: 0.000000 y: 0.000000 z: 0.000000 ]
center [ x: 0.000000 y: 0.000000 z: -1.000000 ]
up [ x: 0.000000 y: 1.000000 z: 0.000000 ]

do the calculations to get the forward, up and right vectors.

vec3f f, u, r;
f = vec3fsub(eye, center);
f = vec3fnorm(f);

u = vec3fnorm(up);

r = vec3fcross(u, f);
r = vec3fnorm(r);

which gives me:

forward [ x: 0.000000 y: 0.000000 z: 1.000000 ]
up [ x: 0.000000 y: 1.000000 z: 0.000000 ]
righ nr [ x: 1.000000 y: 0.000000 z: 0.000000 ]

float data[] = {
r->p[0], u->p[0], f->p[0], -(vec3fdotr(r, eye)),
r->p[1], u->p[1], f->p[1], -(vec3fdotr(u, eye)),
r->p[2], u->p[2], f->p[2], -(vec3fdotr(f, eye)),
0, 0, 0, 1 };
copyMatrix(out, data);

rendering without the projection matrix everything is fine, if I try to render with an projection matrix I see nothing.

If I try to render with orthographic matrix

void mat4OrthoProjection(mat4* out, float r, float l, float t, float b, float n, float f)
{
float data[] = { (2)/(r-l), 0, 0, -(r+l)/(r-l),
0, (2)/(t-b), 0, -(t+b)/(t-b),
0, 0, (2/(f-n)), -(f+n)/(f-n),
0, 0, 0, 0 };
copyMatrix(out, data);
}

I see something like this
2040

removing the projection matrix from my shader and I get the image below.
2041

the two other parts of my code that I think could affect this is my functions
r = vec3fcross(u, f);
r = vec3fnorm(r)

which looks like this:
cross

vec3f vec3fcross(const vec3f* a, const vec3f* b)
{
vec3f out;
out.p[0] = a->p[1] * b->p[2] - b->p[1] * a->p[2];
out.p[1] = a->p[2] * b->p[0] - b->p[2] * a->p[0];
out.p[2] = a->p[0] * b->p[1] - b->p[0] * a->p[1];
}

vec3fnorm

vec3f void vec3fnorm(vec3f* in)
{
t = sqrtf(in->p[0] * in->p[0] + in->p[1] * in->p[1] + in->p[2] * in->p[2]);
if(t != 0)
{
out->p[0] = in->p[0]/t;
out->p[1] = in->p[1]/t;
out->p[2] = in->p[2]/t;
}
}

GClements
08-06-2015, 04:33 AM
If I try to render with orthographic matrix

void mat4OrthoProjection(mat4* out, float r, float l, float t, float b, float n, float f)
{
float data[] = { (2)/(r-l), 0, 0, -(r+l)/(r-l),
0, (2)/(t-b), 0, -(t+b)/(t-b),
0, 0, (2/(f-n)), -(f+n)/(f-n),
0, 0, 0, 0 };
copyMatrix(out, data);
}

That is even worse than the perspective matrix, as it sets w to zero.

blubee
08-06-2015, 07:36 AM
@CGIelements can you help me understand or at least point me to where I can get the answer to this. It's obvious that I am having problems understanding what am I doing wrong?

deltayoung
08-06-2015, 08:28 AM
Your projection matrix in the first post was not an orthographic projection, but close to a perspective projection matrix. Here is the correct form I meant:

mat4* mat4Projection(double r, double l, double t, double b, double n, double f)
{
double data[] = { (2*n)/(r-l), 0, (r+l)/(r-l), 0,
0, (2*n)/(t-b), (t+b)/(t-b), 0,
0, 0, (-(f+n))/(f-n), (-2*(f*n))/(f-n),
0, 0, -1, 1 0 };
return makeMat4(data);
}

And your projection matrix in the later post was similar to an orthographic projection, but the last row with all 0's can't be right, as pointed out by GClements. I'd try it with the following correction:

If I try to render with orthographic matrix

void mat4OrthoProjection(mat4* out, float r, float l, float t, float b, float n, float f)
{
float data[] = { (2)/(r-l), 0, 0, -(r+l)/(r-l),
0, (2)/(t-b), 0, -(t+b)/(t-b),
0, 0, (2/(f-n)), -(f+n)/(f-n),
0, 0, 0, 0 1 };
copyMatrix(out, data);
}

If trying out these 2 options doesn't work for you, then the error will be somewhere else beyond my knowledge :)

GClements
08-06-2015, 09:16 AM
@CGIelements can you help me understand or at least point me to where I can get the answer to this. It's obvious that I am having problems understanding what am I doing wrong?

You can find some standard projection projection matrices in the OpenGL 2 reference pages (https://www.opengl.org/sdk/docs/man2/), specifically glOrtho (https://www.opengl.org/sdk/docs/man2/xhtml/glOrtho.xml) and gluOrtho2D (https://www.opengl.org/sdk/docs/man2/xhtml/gluOrtho2D.xml) for orthographic projections and glFrustum (https://www.opengl.org/sdk/docs/man2/xhtml/glFrustum.xml) and gluPerspective (https://www.opengl.org/sdk/docs/man2/xhtml/gluPerspective.xml) for perspective projections.

For an orthographic projection, the W coordinate of the transformed vertex should be constant, so the bottom row of the matrix should be [0 0 0 1]. For a perspective projection, the W coordinate of the transformed vertex should be proportional to the Z coordinate of the original vertex, so the bottom row should be [0 0 k 0] for some k (k is typically -1; a negative value results in the eye-space +Z axis pointing out of the screen, i.e. a right-handed coordinate system).

blubee
08-06-2015, 11:06 AM
I spent some more time and got the orthographic projection to work. I also think the perspective projection is also correct but atm I am a bit confused as how to bring my models back to the center of the view.

Here's the way I setup the matrices.

void mat4Projection(mat4* out, float r, float l, float t, float b, float n, float f)

{
float data[] = { (2*n)/(r-l), 0, (r+l)/(r-l), 0,
0, (2*n)/(t-b), (t+b)/(t-b), 0,
0, 0, (-(f+n))/(f-n), (-2*(f*n))/(f-n),
0, 0, -1, 0 };
copyMatrix(out, data);
}

void mat4OrthoProjection(mat4* out, float r, float l, float t, float b, float n, float f)
{
float data[] = { (2)/(r-l), 0, 0, -((r+l)/(r-l)),
0, (2)/(t-b), 0, -((t+b)/(t-b)),
0, 0, (-2/(f-n)), -((f+n)/(f-n)),
0, 0, 0, 1 };
copyMatrix(out, data);
}

calling ortho like this:

mat4OrthoProjection(&opm, -100, 100, -100, 100, 0.001, 1000.0);

If I scale up my model by an appropriate amount I can see it in the middle of the screen again.

If I change the left, right, top and bottom values from -100 to 100 to say something like
0 to 200

then I lose track my model in the scene. I think this is the same problem that I am having with the perspective projection atm. Not being able to locate the model in the scene.

GClements
08-06-2015, 01:00 PM
void mat4Projection(mat4* out, float r, float l, float t, float b, float n, float f)

void mat4OrthoProjection(mat4* out, float r, float l, float t, float b, float n, float f)

calling ortho like this:

mat4OrthoProjection(&opm, -100, 100, -100, 100, 0.001, 1000.0);

Your parameters have l and r swapped and t and b swapped. This will typically result in the view being rotated by 180 degrees.

If I change the left, right, top and bottom values from -100 to 100 to say something like
0 to 200 then I lose track my model in the scene.
Values of -100,100,-100,100 (for l,r,b,t) will place the eye-space origin in the centre of the viewport ((l+r)/2,(b+t)/2 is at the centre of the viewport). Values of 0,200,0,200 will place the eye-space origin in the lower-left corner (or the upper-right corner with the parameters swapped).