3
\$\begingroup\$

I'm trying to troubleshoot a problem with my simple OpenGL test program, which I've written in C. I've written some math routines to do the matrix manipulation, but even after copying known working perspective functions, I cannot get anything to appear on screen.

The program is simply:

The only geometry is a simple cube centered around the origin, here is the render loop:

int renderer_draw_frame(float delta_time)
{
    glClearColor(0.2f, 0.3f, 0.2f, 1.0f);
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

    glUseProgram(prog);

    /* bind textures */
    glActiveTexture(GL_TEXTURE0);
    glBindTexture(GL_TEXTURE_2D, tile_tex);
    glUniform1i(glGetUniformLocation(spo_prog(spo), "Tex1"), 0);

    vec3f eye = { 0.0f, 0.0f, 3.0f };
    vec3f target = { 0.0f, 0.0f, 0.0f };
    vec3f up = { 0.0f, 1.0f, 0.0f };

    mat4f model_mat = mat4f_translate(0.0f, 0.0f, 0.0f);
    mat4f view_mat = look_at(eye, target, up);
    proj_mat = mat4f_projection(45.0f, (float)win_width / (float)win_height, 0.1f, 100.0f);

    glUniformMatrix4fv(modelLoc, 1, GL_FALSE, &model_mat.f[0]);
    glUniformMatrix4fv(viewLoc, 1, GL_FALSE, &view_mat.f[0]);
    glUniformMatrix4fv(projLoc, 1, GL_FALSE, &proj_mat.f[0]);

    glBindVertexArray(VAO);
    glDrawArrays(GL_TRIANGLES, 0, 36);
    glBindVertexArray(0);
    return 0;
}

mat4f and vec3f is just this:

typedef struct mat4f mat4f;
struct mat4f
{
    float f[4 * 4];
};

typedef struct vec3f vec3f;
struct vec3f
{
    float x;
    float y;
    float z;
};

The math routines in question:

#define M4(m,i,j) m.f[mat4f_idx(i,j)]
#define PI 3.14159265359f

mat4f mat4f_projection(float fov, float ratio, float near, float far)
{
    float d2r = PI / 180.0f;
    float ys = 1.0f / tanf(d2r * fov / 2.0f);
    float xs = ys / ratio;
    float nf = near - far;
    mat4f r = { 0 };
    M4(r, 0, 0) = xs;
    M4(r, 1, 1) = ys;
    M4(r, 2, 2) = (far + near) / nf;
    M4(r, 2, 3) = -1.0f;
    M4(r, 3, 2) = 2 * far * near / nf;
    return r;
}

mat4f look_at(vec3f eye, vec3f center, vec3f up)
{
    vec3f zaxis = vec3f_normalize(vec3f_subv(eye, center));
    vec3f xaxis = vec3f_normalize(vec3f_crossp(vec3f_normalize(up), zaxis));
    vec3f yaxis = vec3f_crossp(zaxis,xaxis);

    mat4f trans = mat4f_id(1.0f, 1.0f, 1.0f, 1.0f);
    M4(trans, 0, 3) = -eye.x;
    M4(trans, 1, 3) = -eye.y;
    M4(trans, 2, 3) = -eye.z;
    mat4f rot = mat4f_id(1.0f, 1.0f, 1.0f, 1.0f);
    M4(rot, 0, 0) = xaxis.x;
    M4(rot, 0, 1) = xaxis.y;
    M4(rot, 0, 2) = xaxis.z;
    M4(rot, 1, 0) = yaxis.x;
    M4(rot, 1, 1) = yaxis.y;
    M4(rot, 1, 2) = yaxis.z;
    M4(rot, 2, 0) = zaxis.x;
    M4(rot, 2, 1) = zaxis.y;
    M4(rot, 2, 2) = zaxis.z;
    return mat4f_mul(rot, trans);
}

Finally, the simple vertex shader:

#version 330 core

layout (location = 0) in vec3 position; //attrib pos 0
layout (location = 1) in vec2 texCoord; //attrib pos 1

out vec2 TexCoord;

uniform mat4 model;
uniform mat4 view;
uniform mat4 projection;

void main()
{
    gl_Position = projection * view * model * vec4(position, 1.0f);
    TexCoord = vec2(texCoord.x, 1.0f - texCoord.y);
}

Here is what I see:

Projection View

If I change the shader as so:

void main()
{
    gl_Position = view * model * vec4(position, 1.0f);
    TexCoord = vec2(texCoord.x, 1.0f - texCoord.y);
}

I see:

Model View

Why does it completely disappear in projection view? I've tried changed the view look at parameter but I can't ever see anything through projection view. I've tried several different implementations, currently gluPerspective (the one above is pretty much that function copied).

I've been at this all night and I can't seem to get a grasp on what went wrong. Can someone gives me some pointers on where to go next?

\$\endgroup\$
  • \$\begingroup\$ Your multiplication order seems correct. Are you doing the matrix computation to learn how it works or you could do with using a library (glm for example) ? \$\endgroup\$ – CpCd0y Sep 30 '16 at 8:33
  • \$\begingroup\$ What is the code for your macro mat4f_idx(i,j)? \$\endgroup\$ – Stephane Hockenhull Sep 30 '16 at 13:51
  • \$\begingroup\$ For learning the math mostly. mat4f_idx is uint8_t mat4f_idx(uint8_t i, uint8_t j) { return (i * 4) + j; } I found what could be causing it, -nan in the projection matrix output. I thought it was my math that was wrong this whole time, but it looks like an aspect ratio value of 0 caused by uninitialized width and height variables. \$\endgroup\$ – Brian Sep 30 '16 at 16:41
3
\$\begingroup\$

This was caused by an uninitialized variable being fed into the projection function:

static int win_width; //is 0 at initialization
static int win_height; //is 0 at initialization

int renderer_init(int width,int height)
{
     <....>
     mat4f proj_mat;
     proj_mat = mat4f_projection(45.0f, (float)win_width / (float)win_height, 0.1f, 100.0f);
     <.....>
}

Caused the projection function to fail because of a division by zero (I believe). The matrix output was:

M(0,0): -nan(ind) M(0,1): 0.000000 M(0,2): 0.000000 M(0,3): 0.000000
M(1,0): 0.000000 M(1,1): 2.414213 M(1,2): 0.000000 M(1,3): 0.000000
M(2,0): 0.000000 M(2,1): 0.000000 M(2,2): -1.002002 M(2,3): -1.000000
M(3,0): 0.000000 M(3,1): 0.000000 M(3,2): -0.200200 M(3,3): 0.000000

In the projection function, M(0,0) is set by:

mat4f mat4f_projection(float fov, float ratio, float near, float far)
{
    float d2r = PI / 180.0f;
    float ys = 1.0f / tanf(d2r * fov / 2.0f);
    float xs = ys / ratio; // divide by zero
    < .... >
    M4(r, 0, 0) = xs;
}

I already had the static window width and height variables there, so setting them fixed the issue:

int renderer_init(int width,int height)
{
    win_width = width;
    win_height = height;
    < ... >
}

Resultant matrix (correct this time):

M(0,0): 1.810660 M(0,1): 0.000000 M(0,2): 0.000000 M(0,3): 0.000000
M(1,0): 0.000000 M(1,1): 2.414213 M(1,2): 0.000000 M(1,3): 0.000000
M(2,0): 0.000000 M(2,1): 0.000000 M(2,2): -1.002002 M(2,3): -1.000000
M(3,0): 0.000000 M(3,1): 0.000000 M(3,2): -0.200200 M(3,3): 0.000000

Picture: Fixed Projection

If these matrices or projection code helps someone, you are more than welcome to use them. The problem was that I focused on the math instead of the simpler case of the variables not being initialized and it gave me tunnel vision. Instead of simply looking at the matrix to figure out what was wrong.

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.