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;
}
zNear
andzFar
values. Or, if your eye point is at the origin, try moving it along the +z axis. – Pat Lillis