Question

i try to get a basic OpenGL program working. I created two methods which create a modelview matrix (very rudimental at the moment, it only moves my object on the Z-Axis) and a projection Matrix.

My proplem is, that as far as i understood OpenGL my Projection Matrix should place Vertices with positive Z-Coordinates on the screen and the ones with negative Coordinates behind the screen.

But what i experience is, that i need to move the cube i draw in the negative z-direction if i want it to be shown. Can you explain, why this is? Where am i wrong? Or is there an error in my code?

I Use this function to create my projection matrix:

void Perspective(float *a, float fov, float aspect, float zNear, float zFar)
{
    for(int i = 0; i < 16; i++)
        a[i] = 0.0f;

    float f = 1.0f/float(tan(fov / 2.0f * (M_PI / 180.0f)));

    a[0 + 4 * 0] = f / aspect;
    a[1 + 4 * 1] = f;
    a[2 + 4 * 2] = (zNear + zFar) / (zNear - zFar);
    a[2 + 4 * 3] = 2.0f * zNear *+ zFar / (zNear - zFar);
    a[3 + 4 * 2] = -1.0f;
}

And this one for the Modelview (i pass varying offsets, they swing around 0, and z around -2):

void Modelview(float *mv, float scale, float xOff, float yOff, float zOff)
{
    for(int i = 0; i < 16; i++)
        mv[i] = 0.0f;

    mv[0 + 4 * 0] = scale;
    mv[0 + 4 * 3] = xOff;
    mv[1 + 4 * 1] = scale;
    mv[1 + 4 * 3] = yOff;
    mv[2 + 4 * 2] = scale;
    mv[2 + 4 * 3] = zOff;
    mv[3 + 4 * 3] = 1.0f;
}

The matrices are both passed correctly to opengl, i calculate the vertex position by:

gl_Position = modelview * projection * vertex_position;

Here is the whole code, in case anyone needs it:

main.h

#include <stdio.h>
#include <cmath>
#include <cstring>
#include <string>
#include <vector>
#include <algorithm>
#include <GL/glew.h>
#include <GL/glut.h>

#include "util.h"

GLuint positionBufferObject, program;
GLint projectionLoc, modelviewLoc, vertexLoc, colorLoc;
float zNear = 0.1f, zFar = 100.0f;
float projection[16], modelview[16];

const Vertex vertices[] =
{
    Vertex(
                Vector4f(0.25f,  0.25f, 0.25f, 1.0f),
                ColorRGBA(0.0f, 0.0f, 1.0f, 1.0f)),
        Vertex(
                Vector4f(0.25f,  -0.25f, 0.25f, 1.0f),
                ColorRGBA(0.0f, 0.0f, 1.0f, 1.0f)),
        Vertex(
                Vector4f(-0.25f,  0.25f, 0.25f, 1.0f),
                ColorRGBA(0.0f, 0.0f, 1.0f, 1.0f)),

        Vertex(
                Vector4f(0.25f,  -0.25f, 0.25f, 1.0f),
                ColorRGBA(0.0f, 0.0f, 1.0f, 1.0f)),
        Vertex(
                Vector4f(-0.25f,  -0.25f, 0.25f, 1.0f),
                ColorRGBA(0.0f, 0.0f, 1.0f, 1.0f)),
        Vertex(
                Vector4f(-0.25f,  0.25f, 0.25f, 1.0f),
                ColorRGBA(0.0f, 0.0f, 1.0f, 1.0f)),

        Vertex(
                Vector4f(0.25f, 0.25f, -0.25f, 1.0f),
                ColorRGBA(0.8f, 0.8f, 0.8f, 1.0f)),
        Vertex(
                Vector4f(-0.25f, 0.25f, -0.25f, 1.0f),
                ColorRGBA(0.8f, 0.8f, 0.8f, 1.0f)),
        Vertex(
                Vector4f(0.25f, -0.25f, -0.25f, 1.0f),
                ColorRGBA(0.8f, 0.8f, 0.8f, 1.0f)),

        Vertex(
                Vector4f(0.25f, -0.25f, -0.25f, 1.0f),
                ColorRGBA(0.8f, 0.8f, 0.8f, 1.0f)),
        Vertex(
                Vector4f(-0.25f, 0.25f, -0.25f, 1.0f),
                ColorRGBA(0.8f, 0.8f, 0.8f, 1.0f)),
        Vertex(
                Vector4f(-0.25f, -0.25f, -0.25f, 1.0f),
                ColorRGBA(0.8f, 0.8f, 0.8f, 1.0f)),

        Vertex(
                Vector4f(-0.25f, 0.25f, 0.25f, 1.0f),
                ColorRGBA(0.0f, 1.0f, 0.0f, 1.0f)),
        Vertex(
                Vector4f(-0.25f, -0.25f, 0.25f, 1.0f),
                ColorRGBA(0.0f, 1.0f, 0.0f, 1.0f)),
        Vertex(
                Vector4f(-0.25f, -0.25f, -0.25f, 1.0f),
                ColorRGBA(0.0f, 1.0f, 0.0f, 1.0f)),

        Vertex(
                Vector4f(-0.25f, 0.25f, 0.25f, 1.0f),
                ColorRGBA(0.0f, 1.0f, 0.0f, 1.0f)),
        Vertex(
                Vector4f(-0.25f, -0.25f, -0.25f, 1.0f),
                ColorRGBA(0.0f, 1.0f, 0.0f, 1.0f)),
        Vertex(
                Vector4f(-0.25f, 0.25f, -0.25f, 1.0f),
                ColorRGBA(0.0f, 1.0f, 0.0f, 1.0f)),

        Vertex(
                Vector4f(0.25f,  0.25f, 0.25f, 1.0f),
                ColorRGBA(0.5f, 0.5f, 0.0f, 1.0f)),
        Vertex(
                Vector4f(0.25f, -0.25f, -0.25f, 1.0f),
                ColorRGBA(0.5f, 0.5f, 0.0f, 1.0f)),
        Vertex(
                Vector4f(0.25f, -0.25f, 0.25f, 1.0f),
                ColorRGBA(0.5f, 0.5f, 0.0f, 1.0f)),

        Vertex(
                Vector4f(0.25f, 0.25f, 0.25f, 1.0f),
                ColorRGBA(0.5f, 0.5f, 0.0f, 1.0f)),
        Vertex(
                Vector4f(0.25f, 0.25f, -0.25f, 1.0f),
                ColorRGBA(0.5f, 0.5f, 0.0f, 1.0f)),
        Vertex(
                Vector4f(0.25f, -0.25f, -0.25f, 1.0f),
                ColorRGBA(0.5f, 0.5f, 0.0f, 1.0f)),

        Vertex(
                Vector4f(0.25f, 0.25f, -0.25f, 1.0f),
                ColorRGBA(1.0f, 0.0f, 0.0f, 1.0f)),
        Vertex(
                Vector4f(0.25f,  0.25f, 0.25f, 1.0f),
                ColorRGBA(1.0f, 0.0f, 0.0f, 1.0f)),
        Vertex(
                Vector4f(-0.25f, 0.25f, 0.25f, 1.0f),
                ColorRGBA(1.0f, 0.0f, 0.0f, 1.0f)),

        Vertex(
                Vector4f(0.25f, 0.25f, -0.25f, 1.0f),
                ColorRGBA(1.0f, 0.0f, 0.0f, 1.0f)),
        Vertex(
                Vector4f(-0.25f, 0.25f, 0.25f, 1.0f),
                ColorRGBA(1.0f, 0.0f, 0.0f, 1.0f)),
        Vertex(
                Vector4f(-0.25f, 0.25f, -0.25f, 1.0f),
                ColorRGBA(1.0f, 0.0f, 0.0f, 1.0f)),

        Vertex(
                Vector4f(0.25f, -0.25f, -0.25f, 1.0f),
                ColorRGBA(0.0f, 1.0f, 1.0f, 1.0f)),
        Vertex(
                Vector4f(-0.25f, -0.25f, 0.25f, 1.0f),
                ColorRGBA(0.0f, 1.0f, 1.0f, 1.0f)),
        Vertex(
                Vector4f(0.25f, -0.25f, 0.25f, 1.0f),
                ColorRGBA(0.0f, 1.0f, 1.0f, 1.0f)),

        Vertex(
                Vector4f(0.25f, -0.25f, -0.25f, 1.0f),
                ColorRGBA(0.0f, 1.0f, 1.0f, 1.0f)),
        Vertex(
                Vector4f(-0.25f, -0.25f, -0.25f, 1.0f),
                ColorRGBA(0.0f, 1.0f, 1.0f, 1.0f)),
        Vertex(
                Vector4f(-0.25f, -0.25f, 0.25f, 1.0f),
                ColorRGBA(0.0f, 1.0f, 1.0f, 1.0f)),

        Vertex(
                Vector4f(-1.0f, 0, -1.0f, 1.0f),
                ColorRGBA(1.0f, 0.0f, 0.0f, 1.0f)),
        Vertex(
                Vector4f(0.0f, 1.0, -1.0f, 1.0f),
                ColorRGBA(0.0f, 1.0f, 0.0f, 1.0f)),
        Vertex(
                Vector4f(1.0f, 0, -1.0f, 1.0f),
                ColorRGBA(0.0f, 0.0f, 1.0f, 1.0f))
};

const float vertexData[] =
{
     0.0f,    0.5f, 0.0f, 1.0f,
     0.5f, -0.366f, 0.0f, 1.0f,
    -0.5f, -0.366f, 0.0f, 1.0f,
     1.0f,    0.0f, 0.0f, 1.0f,
     0.0f,    1.0f, 0.0f, 1.0f,
     0.0f,    0.0f, 1.0f, 1.0f,
};

std::string strVertexShader = "simple.vert";

std::string strFragmentShader = "simple.frag";

void init();

void display();

void resize(int w, int h);

void InitializeProgram();

void InitializeVertexBuffer();

void InitializeGlutCallbacks();

void Perspective(float *a, float fov, float aspect, float zNear, float zFar);

void Modelview(float *mv, float scale, float xOff, float yOff, float zOff);

void ComputePositionOffsets(float &fXOffset, float &fYOffset, float &fZOffset, float &scale);

void PrintMat4(float *mat);

main.cpp

#include "main.h"

int main(int argc, char **argv)
{
    glutInit(&argc, argv);

        glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGBA | GLUT_DEPTH);
        glutInitWindowSize(640, 480);
        glutInitWindowPosition(100, 100);
        glutCreateWindow("Test");

        GLenum res = glewInit();
        if(res != GLEW_OK)
        {
                fprintf(stderr, "Error: '%s'\n", glewGetErrorString(res));
                return -1;
        }

        init();

        glutMainLoop();

        return 0;
}

void display()
{
        glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
        glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

        float fXOffset = 0.0f, fYOffset = 0.0f, fZOffset = 0.0f, scale = 0.0f;
        ComputePositionOffsets(fXOffset, fYOffset, fZOffset, scale);

        Modelview(modelview, scale, fXOffset, fYOffset, -2.0f + fZOffset);

        glUseProgram(program);

        glUniformMatrix4fv(projectionLoc, 1, GL_FALSE, &projection[0]);
        glUniformMatrix4fv(modelviewLoc, 1, GL_FALSE, &modelview[0]);

        glBindBuffer(GL_ARRAY_BUFFER, positionBufferObject);

        glEnableVertexAttribArray(vertexLoc);
        glEnableVertexAttribArray(colorLoc);

        glVertexAttribPointer(vertexLoc, sizeof(Vector4f)/sizeof(float), GL_FLOAT, GL_FALSE, sizeof(Vertex), (void*)0);
        glVertexAttribPointer(colorLoc, sizeof(ColorRGBA)/sizeof(float), GL_FLOAT, GL_FALSE, sizeof(Vertex), (void*)(sizeof(Vertex)/2));

        glDrawArrays(GL_TRIANGLES, 0, sizeof(vertices)/sizeof(Vertex));

        glDisableVertexAttribArray(vertexLoc);
        glDisableVertexAttribArray(colorLoc);

        glUseProgram(0);

        glutSwapBuffers();
        glutPostRedisplay();
}

void resize(int w, int h)
{
        glViewport(0, 0, w, h);
        Perspective(projection, 90.0f, float(w)/float(h), zNear, zFar);
        PrintMat4(projection);
}

void InitializeProgram()
{
        std::vector<GLuint> shaderList;

        shaderList.push_back(CreateShader(GL_VERTEX_SHADER, strVertexShader));
        shaderList.push_back(CreateShader(GL_FRAGMENT_SHADER, strFragmentShader));

        program = CreateProgram(shaderList);

        vertexLoc = glGetAttribLocation(program, "vertex_position");
        colorLoc = glGetAttribLocation(program, "vertex_color");

        modelviewLoc = glGetUniformLocation(program, "modelview");
        projectionLoc = glGetUniformLocation(program, "projection");

        std::for_each(shaderList.begin(), shaderList.end(), glDeleteShader);
}

void InitializeVertexBuffer()
{
        glGenBuffers(1, &positionBufferObject);

        glBindBuffer(GL_ARRAY_BUFFER, positionBufferObject);
        glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);
        glBindBuffer(GL_ARRAY_BUFFER, 0);
}

void InitializeGlutCallbacks()
{
        glutDisplayFunc(display);
        glutReshapeFunc(resize);
}

void init()
{
        InitializeProgram();
        InitializeVertexBuffer();

        InitializeGlutCallbacks();

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

        glEnable(GL_DEPTH_TEST);
}

void Perspective(float *a, float fov, float aspect, float zNear, float zFar)
{
        for(int i = 0; i < 16; i++)
                a[i] = 0.0f;

        float f = 1.0f/float(tan(fov / 2.0f * (M_PI / 180.0f)));

        a[0 + 4 * 0] = f / aspect;
        a[1 + 4 * 1] = f;
        a[2 + 4 * 2] = (zNear + zFar) / (zNear - zFar);
        a[2 + 4 * 3] = 2.0f * zNear *+ zFar / (zNear - zFar);
        a[3 + 4 * 2] = -1.0f;
}

void Modelview(float *mv, float scale, float xOff, float yOff, float zOff)
{
        for(int i = 0; i < 16; i++)
                mv[i] = 0.0f;

        mv[0 + 4 * 0] = scale;
        mv[0 + 4 * 3] = xOff;
        mv[1 + 4 * 1] = scale;
        mv[1 + 4 * 3] = yOff;
        mv[2 + 4 * 2] = scale;
        mv[2 + 4 * 3] = zOff;
        mv[3 + 4 * 3] = 1.0f;
}

void ComputePositionOffsets(float &fXOffset, float &fYOffset, float &fZOffset, float &scale)
{
        float elapsedTime = glutGet(GLUT_ELAPSED_TIME) / 1000.0f;
        float timeScale = 3.14159f * 2.0f;

        float xLoopDuration = 8.0f;
        float yLoopDuration = 3.0f;
        float zLoopDuration = 2.0f;
        float scaleLoopDuration = 10.0f;
        float xLoopProgress = fmodf(elapsedTime, xLoopDuration) / xLoopDuration;
        float yLoopProgress = fmodf(elapsedTime, yLoopDuration) / yLoopDuration;
        float zLoopProgress = fmodf(elapsedTime, zLoopDuration) / zLoopDuration;
        float scaleLoopProgress = fmodf(elapsedTime, scaleLoopDuration) /scaleLoopDuration;

        fXOffset = sinf(xLoopProgress * timeScale) * 0.5f;
        fYOffset = sinf(yLoopProgress * timeScale) * 0.5f;
        fZOffset = sinf(zLoopProgress * timeScale) * 0.5f;
        scale = 1/(1 + sinf(scaleLoopProgress * timeScale) * 0.5f);
}

void PrintMat4(float *mat)
{
        for(int i = 0; i < 4; i++)
        {
                for(int j = 0; j < 4; j++)
                {
                        std::cout << mat[j * 4 + i] << "\t";
                }
                std::cout << std::endl;
        }
        std::cout << std::endl;
}
Was it helpful?

Solution

A few things:

First, you seem to be setting the "eye" of your projection matrix at [0, 0 -1], pushing your "camera" towards the back of your screen. If this is the case, it's only normal that you have to move your objects beyond that point to have them appear.

The culprit line is (I think, your variable names aren't particularily clear :-/):

a[3 + 4 * 2] = -1.0f;

I'd try and change it to

a[3 + 4 * 2] = 1.0f;

and see if that makes a difference.

Second, depending on what you're rendering, your "camera" might just happen to be inside your mesh. Since you have backface culling enabled, you would see absolutely nothing because all visible faces are culled and moving your model further away would put un-culled faces in view. To see if this is the issue, change the line

glEnable(GL_CULL_FACE);

to

glDisable(GL_CULL_FACE);

and see if your "camera" is inside your mesh.

Third, your mesh might be between your "camera" and your near plane. Trying playing with zNear and see if it makes a difference. zFar is probably correct as your objects appear when you move them away.

EDIT: So I looked into it in more detail and tried to figure out your projection matrix. According to this great explaination of the math behind perspective projections, your projection matrix generation code seems correct to generate a matrix that looks down -Z. Basically, your code works as expected, since OpenGL, by default, uses a right-handed coordinate system.

If you want to be able to offset your objects in +Z because the negative values annoy you, you can create a View matrix that performs a 180 degrees rotation around the Y axis and multiply it with your projection matrix. You'd then get

finalCoordinates = projection * view * model * vertex;

TL;DR: your code works as expected.

OTHER TIPS

I didn't check on your code but here's one simple answer: As OpenGL uses a so called right-handed coordinate system, negative z-values indicate the direction "into" the screen whereas a positive z-value means "out of the screen" (ie. use your right hand, point you thumb to the right -> positive x axis. Your first finger points up, right angle to your thumb -> positive y-axis. And last but not least: your middlefinger, right-angled to your first finger and your thump, points towards you -> positive z-axis!)

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top