While drawing a simple cube using opengl and glfw, the faces of the cube appear to be transparent.
Here’s the code. Use the arrow keys to rotate. I’ve just encapsulated into a class, in my program.
Using Visual C++ Ultimate 2010.
#include "GAME.h"
using namespace std;
GAME::GAME()
{
glfwInit();
glEnable(GL_DEPTH_TEST);
glEnable(GL_COLOR_MATERIAL);
glEnable(GL_LIGHTING);
glEnable(GL_LIGHT0);
glEnable(GL_LIGHT1);
glEnable(GL_NORMALIZE);
}
int GAME::execute()
{
glfwOpenWindow(640, 320, 16, 16, 16, 16, 16, 16, GLFW_WINDOW);
glfwSetWindowTitle("Viraj");
glClearColor(1.0, 1.0, 1.0, 1.0);
glfwSetKeyCallback(events);
running = true;
while(glfwGetWindowParam(GLFW_OPENED))
{
glfwPollEvents();
loop();
render();
}
return 0;
}
void GAME::events(int key, int action)
{
switch(key)
{
case GLFW_KEY_UP:
glRotatef(10, 1, 0, 0);
break;
case GLFW_KEY_DOWN:
glRotatef(-10, 1, 0, 0);
break;
case GLFW_KEY_RIGHT:
glRotatef(10, 0, 1, 0);
break;
case GLFW_KEY_LEFT:
glRotatef(-10, 0, 1, 0);
break;
}
}
int GAME::loop()
{
return 0;
}
int GAME::render()
{
int win_width;
int win_height;
glfwGetWindowSize(&win_width, &win_height);
const float win_aspect = (float)win_width / (float)win_height;
glViewport(0, 0, win_width, win_height);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
//glOrtho(-win_aspect, win_aspect, -1., 1., -1., 1.);
gluPerspective(90, win_aspect, 1, 100.0);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
gluLookAt(0, 0, 3.0, 0, 0, 0, 0.0, 1.0, 0.0);
glEnable(GL_DEPTH_TEST);
glEnable(GL_COLOR_MATERIAL);
glEnable(GL_LIGHTING);
glEnable(GL_LIGHT0);
glEnable(GL_LIGHT1);
glEnable(GL_NORMALIZE);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glBegin(GL_QUADS);
glRotatef(-1, 0, 1, 0);
glColor3f(0.0f, 0.0f, 0.0f);
//Front
glVertex3f(0.0, 0.0, 0.0);
glVertex3f(1.0, 0.0, 0.0);
glVertex3f(1.0, 1.0, 0.0);
glVertex3f(0.0, 1.0, 0.0);
glColor3f(1.0f, 0.0f, 0.0f);
//Left
glVertex3f(1.0, 0.0, 0.0);
glVertex3f(1.0, 0.0, -1.0);
glVertex3f(1.0, 1.0, -1.0);
glVertex3f(1.0, 1.0, 0.0);
glColor3f(0.0f, 1.0f, 0.0f);
//Back
glVertex3f(1.0, 0.0, -1.0);
glVertex3f(1.0, 1.0, -1.0);
glVertex3f(0.0, 1.0, -1.0);
glVertex3f(0.0, 0.0, -1.0);
glColor3f(0.0f, 0.0f, 1.0f);
//Right
glVertex3f(0.0, 0.0, -1.0);
glVertex3f(0.0, 1.0, -1.0);
glVertex3f(0.0, 1.0, 0.0);
glVertex3f(0.0, 0.0, 0.0);
glColor3f(1.0f, 0.0f, 1.0f);
//Top
glVertex3f(0.0, 1.0, -0.0);
glVertex3f(0.0, 1.0, -1.0);
glVertex3f(1.0, 1.0, -1.0);
glVertex3f(1.0, 1.0, 0.0);
glColor3f(1.0f, 1.0f, 0.0f);
//Bottom
glVertex3f(0.0, 0.0, 0.0);
glVertex3f(1.0, 0.0, 0.0);
glVertex3f(1.0, 0.0, -1.0);
glVertex3f(0.0, 0.0, -1.0);
glEnd();
glfwSwapBuffers();
return 0;
}
I’m sorry to tell you, but your code is broken on several levels. Let me break it down for you:
Here lies the first error: GLFW is a C library, and it needs to be initialized exactly once. The call to
glfwInit()belongs into the main function, not a class constructor. The other function calls are OpenGL calls, however they require an active OpenGL context. At this point of the program there is no OpenGL context however, so all the calls you do have not effect at all.Again the nature of GLFW doesn’t go along with being used as part of a class. You can have only one window in GLFW and there’s only one event loop. This doesn’t map so well to classes and objects. You can have of course a class
EventLoopor similar, but you wouldn’t use it like that.And then there is this next one line I’m surprised it actually compiled:
eventsif a member function of classGAME, and unless this is a static member function, you can not use a class member function as callback, especially not to a C library, which doesn’t know classes. How should it know, which instance that event function belongs to? C++ doesn’t have the concept of closures or delegates, which was required for this (other languages do, for that very reason).What comes now is a classical newbie misconception:
The matrix manipulation calls make only sense withing the drawing code. Calling glRotate here will just mess with the matrix stack, but every sane OpenGL rendering function will initialize all state so some sane values at the beginning.
What you want to do in a event handler is accumulating all input into variables, which you later use in the drawing code to setup and control rendering.
If this is meant to loop, why is there no loop?
Only one detail missing: You need to set the viewport here. No big deal:
glViewport(0, 0, win_width, win_height);Now this is actually good! You do setup the projection matrix in the render function. Way to go, stick to this pattern!
UPDATE However the next line is wrong:
gluLookAtis a function meant to be performed on the modelview matrix. The modelview matrix is responsible for both placing models in world space and aligning the world to the view, hence the transformation aremodel→world, world→viewof which you can reduce away the interimworldstep so it’s onlymodel→view.Here you would call
glLoadIdentity(); gluLookAt(...);. It should become obvious now, why doing matrix manipulations in event handlers makes no sense.You should actually set the modelview matrix, with all transformations done from scratch here.
It’s a bit unusual to call
glClearafter setting up the matrices, viewport, etc., but not wrong. You may leave it that way.However before you begin rendering, you should, acutually must set all OpenGL state required. Remember those “initializing” OpenGL calls in the constructor. They belong here.
If you want lighting you need to supply normals. But I’d not bother adding a large bunch of
glNormalcalls up there: The Immediate Mode (glBegin, glEnd) is outdated, I strongly recommend you learn about Vertex Arrays and Vertex Buffer Objects.Summarizing: Get the GLFW calls out of the class. GLFW is not object oriented. Just use it globally from the
mainfunction. Passing events to classes is in order, but you can’t use class member functions as callbacks to GLFW. You need to write some helper functionYou may also have the
GAMEclass manage a static list of all instances and provide a static member function, that passes the event to all instances in the list. Or use a singleton (however I think singletons are an anti pattern, and should be avoided).