Cube drawn with OpenGL lacks depth/perspective?
Asked Answered
A

2

9

I am trying to draw a simple cube in OpenGL and GLFW.

In the code below, I can draw the cube, but it just appears as a simple rectangle. What is happening here?

#if defined(_WIN32) || defined(_WIN64)
#include <windows.h>
#endif

#include <stdio.h>
#include <stdlib.h>
#include <iostream>
#include <fstream>

#define GLEW_STATIC
#include <GL/glew.h>
#include <GL/gl.h>
#include <GLFW/glfw3.h>

const char* gameTitle = "TEST";
GLFWwindow* window;

GLfloat vertices[] =
{
    -1, -1, -1,   -1, -1,  1,   -1,  1,  1,   -1,  1, -1,
     1, -1, -1,    1, -1,  1,    1,  1,  1,    1,  1, -1,
    -1, -1, -1,   -1, -1,  1,    1, -1,  1,    1, -1, -1,
    -1,  1, -1,   -1,  1,  1,    1,  1,  1,    1,  1, -1,
    -1, -1, -1,   -1,  1, -1,    1,  1, -1,    1, -1, -1,
    -1, -1,  1,   -1,  1,  1,    1,  1,  1,    1, -1,  1
};

GLfloat colors[] =
{
    0, 0, 0,   0, 0, 1,   0, 1, 1,   0, 1, 0,
    1, 0, 0,   1, 0, 1,   1, 1, 1,   1, 1, 0,
    0, 0, 0,   0, 0, 1,   1, 0, 1,   1, 0, 0,
    0, 1, 0,   0, 1, 1,   1, 1, 1,   1, 1, 0,
    0, 0, 0,   0, 1, 0,   1, 1, 0,   1, 0, 0,
    0, 0, 1,   0, 1, 1,   1, 1, 1,   1, 0, 1
};

static void controls(GLFWwindow* window, int key, int scancode, int action, int mods)
{
    if(action == GLFW_PRESS)
        if(key == GLFW_KEY_ESCAPE)
            glfwSetWindowShouldClose(window, GL_TRUE);
}

bool initWindow(const int resX, const int resY)
{
    if(!glfwInit())
    {
        fprintf(stderr, "Failed to initialize GLFW\n");
        return false;
    }
    glfwWindowHint(GLFW_SAMPLES, 4); // 4x antialiasing

    // Open a window and create its OpenGL context
    window = glfwCreateWindow(resX, resY, gameTitle, NULL, NULL);

    if(window == NULL)
    {
        fprintf(stderr, "Failed to open GLFW window.\n");
        glfwTerminate();
        return false;
    }

    glfwMakeContextCurrent(window);
    glfwSetKeyCallback(window, controls);

    // Get info of GPU and supported OpenGL version
    printf("Renderer: %s\n", glGetString(GL_RENDERER));
    printf("OpenGL version supported %s\n", glGetString(GL_VERSION));

    glEnable(GL_DEPTH_TEST); // Depth Testing
    glDepthFunc(GL_LEQUAL);
    glDisable(GL_CULL_FACE);
    glCullFace(GL_BACK);
    return true;
}

static void drawCube()
{
    static float alpha = 0;
    glMatrixMode(GL_PROJECTION_MATRIX);
    glLoadIdentity();
    glTranslatef(0,0,-2);
    glMatrixMode(GL_MODELVIEW_MATRIX);
    //attempt to rotate cube
    //glRotatef(alpha, 1, 0, 0);

    /* We have a color array and a vertex array */
    glEnableClientState(GL_VERTEX_ARRAY);
    glEnableClientState(GL_COLOR_ARRAY);
    glVertexPointer(3, GL_FLOAT, 0, vertices);
    glColorPointer(3, GL_FLOAT, 0, colors);

    /* Send data : 24 vertices */
    glDrawArrays(GL_QUADS, 0, 24);

    /* Cleanup states */
    glDisableClientState(GL_COLOR_ARRAY);
    glDisableClientState(GL_VERTEX_ARRAY);
    alpha += 0.1;
}

static void display()
{
    glClearColor(0.0, 0.8, 0.3, 1.0);
    while(!glfwWindowShouldClose(window))
    {
        // Draw stuff
        glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
        drawCube();

        // Update Screen
        //glFlush();
        glfwSwapBuffers(window);

        // Check for any input, or window movement
        glfwPollEvents();

        // Scale to window size
        GLint windowWidth, windowHeight;
        glfwGetWindowSize(window, &windowWidth, &windowHeight);
        glViewport(0, 0, windowWidth, windowHeight);
    }
}

int main(int argc, char** argv)
{
    if(initWindow(1024, 620))
    {
        display();
    }
    printf("Goodbye!\n");
    glfwDestroyWindow(window);
    glfwTerminate();
    return 0;
}

I've tried "glTransformf(0,0,-10);", but if I do anything less than -2, than the cube disappears. at -2, the front face side appears. at the default position of 0, I can see the back side of the cube.

Also, when I try to rotate it, all that shows up is a rectangle moving from the top of the window, to the bottom. Seems very odd.

Why is the program is behaving this way?

Andris answered 4/6, 2014 at 15:2 Comment(1)
in case you are curious, you are drawing directly into clip-space, a 2x2x2 cube centered at the origin, as described here: https://mcmap.net/q/1171845/-ambigious-opengl-default-camera-position (that is why you observe sides "disappearing" as they move out of that view volume)Florettaflorette
T
15
  1. You never set a (meaningful) projection matrix.
  2. Abuse not the projection matrix stack.
  3. Don't set your matrices in drawCube(), single responsibility principle and all that.
  4. Set your viewport before trying to draw.
  5. C++ has c-prefixed versions (stdio.h -> cstdio) of the C headers. Use those instead.

All together:

#include <GL/glew.h>
#include <GLFW/glfw3.h>

#include <cstdio>

void controls(GLFWwindow* window, int key, int scancode, int action, int mods)
{
    if(action == GLFW_PRESS)
        if(key == GLFW_KEY_ESCAPE)
            glfwSetWindowShouldClose(window, GL_TRUE);
}

GLFWwindow* initWindow(const int resX, const int resY)
{
    if(!glfwInit())
    {
        fprintf(stderr, "Failed to initialize GLFW\n");
        return NULL;
    }
    glfwWindowHint(GLFW_SAMPLES, 4); // 4x antialiasing

    // Open a window and create its OpenGL context
    GLFWwindow* window = glfwCreateWindow(resX, resY, "TEST", NULL, NULL);

    if(window == NULL)
    {
        fprintf(stderr, "Failed to open GLFW window.\n");
        glfwTerminate();
        return NULL;
    }

    glfwMakeContextCurrent(window);
    glfwSetKeyCallback(window, controls);

    // Get info of GPU and supported OpenGL version
    printf("Renderer: %s\n", glGetString(GL_RENDERER));
    printf("OpenGL version supported %s\n", glGetString(GL_VERSION));

    glEnable(GL_DEPTH_TEST); // Depth Testing
    glDepthFunc(GL_LEQUAL);
    glDisable(GL_CULL_FACE);
    glCullFace(GL_BACK);
    return window;
}

void drawCube()
{
    GLfloat vertices[] =
    {
        -1, -1, -1,   -1, -1,  1,   -1,  1,  1,   -1,  1, -1,
        1, -1, -1,    1, -1,  1,    1,  1,  1,    1,  1, -1,
        -1, -1, -1,   -1, -1,  1,    1, -1,  1,    1, -1, -1,
        -1,  1, -1,   -1,  1,  1,    1,  1,  1,    1,  1, -1,
        -1, -1, -1,   -1,  1, -1,    1,  1, -1,    1, -1, -1,
        -1, -1,  1,   -1,  1,  1,    1,  1,  1,    1, -1,  1
    };

    GLfloat colors[] =
    {
        0, 0, 0,   0, 0, 1,   0, 1, 1,   0, 1, 0,
        1, 0, 0,   1, 0, 1,   1, 1, 1,   1, 1, 0,
        0, 0, 0,   0, 0, 1,   1, 0, 1,   1, 0, 0,
        0, 1, 0,   0, 1, 1,   1, 1, 1,   1, 1, 0,
        0, 0, 0,   0, 1, 0,   1, 1, 0,   1, 0, 0,
        0, 0, 1,   0, 1, 1,   1, 1, 1,   1, 0, 1
    };

    static float alpha = 0;
    //attempt to rotate cube
    glRotatef(alpha, 0, 1, 0);

    /* We have a color array and a vertex array */
    glEnableClientState(GL_VERTEX_ARRAY);
    glEnableClientState(GL_COLOR_ARRAY);
    glVertexPointer(3, GL_FLOAT, 0, vertices);
    glColorPointer(3, GL_FLOAT, 0, colors);

    /* Send data : 24 vertices */
    glDrawArrays(GL_QUADS, 0, 24);

    /* Cleanup states */
    glDisableClientState(GL_COLOR_ARRAY);
    glDisableClientState(GL_VERTEX_ARRAY);
    alpha += 1;
}

void display( GLFWwindow* window )
{
    while(!glfwWindowShouldClose(window))
    {
        // Scale to window size
        GLint windowWidth, windowHeight;
        glfwGetWindowSize(window, &windowWidth, &windowHeight);
        glViewport(0, 0, windowWidth, windowHeight);

        // Draw stuff
        glClearColor(0.0, 0.8, 0.3, 1.0);
        glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

        glMatrixMode(GL_PROJECTION_MATRIX);
        glLoadIdentity();
        gluPerspective( 60, (double)windowWidth / (double)windowHeight, 0.1, 100 );

        glMatrixMode(GL_MODELVIEW_MATRIX);
        glTranslatef(0,0,-5);

        drawCube();

        // Update Screen
        glfwSwapBuffers(window);

        // Check for any input, or window movement
        glfwPollEvents();
    }
}

int main(int argc, char** argv)
{
    GLFWwindow* window = initWindow(1024, 620);
    if( NULL != window )
    {
        display( window );
    }
    glfwDestroyWindow(window);
    glfwTerminate();
    return 0;
}
Truckage answered 4/6, 2014 at 15:32 Comment(3)
Very Helpful! Thanks a lot. One thing that's weird though, is that the smaller the horizontal size of the window, the faster the cubes spin. Is this just an FPS thing, or what is causing it?Andris
Sounds like you're fill-rate limited. The fewer pixels the GPU has to touch the faster it can draw a frame.Truckage
Starting from GLFW verison 3.0 the GLU header is not included automatically so if you want to use the glu functions in the app you have to define it first before including glfw3 header file like this #define GLFW_INCLUDE_GLU and then on next line add this #include <GLFW/glfw3.h>Tympanites
W
5

I believe your problem is that you're basically using orthographic projection, or certainly something that's not perspective, which is what will give the cube more of the "3D" appearance I think you're looking for.

Try something like the following to set a correct perspective projection matrix:

glMatrixMode(GL_PROJECTION_MATRIX);
glLoadIdentity();
gluPerspective(45, windowWidth / windowHeight, 0.1f, 100.0f);

// Draw calls.
West answered 4/6, 2014 at 15:34 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.