4

I'm writing a program to draw a cube on OpenGL and rotate it continuously on mouse clicks. At particular angles, I'm able to see through the cube (transparent). I've enabled Depth Test, so I don't know why this is happening. I am not sure if I have enabled it correctly.

In this image, the hidden faces are still visible

#include <math.h>
#include <vector>
#include <Windows.h>
#include <gl\glut.h>

using namespace std;


void myInit() {
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
    glClearColor(0, 0, 0, 1);
    glOrtho(-2, 2, -2, 2, 2, -2);
    glMatrixMode(GL_MODELVIEW);
}

float Cube[][3] = { {-1, -1, -1}, {1, -1, -1}, {1, 1, -1}, {-1, 1, -1}, {-1, -1, 1}, {1, -1, 1}, {1, 1, 1}, {-1, 1, 1} };
float Colors[][3] = { {0, 0, 0}, {1, 0, 0}, {0, 1, 0}, {0, 0, 1}, {1, 1, 0}, {0, 1, 1}, {1, 0, 1}, {1, 1, 1} };

int axis = 0, theta[3] = {0, 0, 0};

void draw_face (int a, int b, int c, int d) {
    glBegin(GL_QUADS);
        glColor3fv(Colors[a]);
        glVertex3fv(Cube[a]);
        glColor3fv(Colors[b]);
        glVertex3fv(Cube[b]);
        glColor3fv(Colors[c]);
        glVertex3fv(Cube[c]);
        glColor3fv(Colors[d]);
        glVertex3fv(Cube[d]);
    glEnd();
}

void draw_cube () {
    draw_face(0, 3, 2, 1);
    draw_face(2, 3, 7, 6);
    draw_face(0, 4, 7, 3);
    draw_face(1, 2, 6, 5);
    draw_face(4, 5, 6, 7);
    draw_face(0, 1, 5, 4);
}

void spin_cube() {
    theta[axis] += 2;
    if (theta[axis] > 360)
        theta[axis] = -360;
    glutPostRedisplay();
}

void idle_func() {
    Sleep(10);
    spin_cube();
}

void mouse_func(int button, int state, int x, int y) {
    if (button == GLUT_LEFT_BUTTON && state == GLUT_DOWN)
        axis = 0;
    else if (button == GLUT_MIDDLE_BUTTON && state == GLUT_DOWN)
        axis = 1;
    else if (button == GLUT_RIGHT_BUTTON && state == GLUT_DOWN)
        axis = 2;
}

void myDrawing() {
    glClear(GL_COLOR_BUFFER_BIT);
    glPushMatrix();
    glRotatef(theta[0], 1, 0, 0);
    glRotatef(theta[1], 0, 1, 0);
    glRotatef(theta[2], 0, 0, 1);
    draw_cube();
    glPopMatrix();
    glFlush();
    glutSwapBuffers();
}

int main(int argc, char *argv[]) {
    glutInit(&argc, argv);
    glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB);
    glEnable(GL_DEPTH_TEST);
    glutInitWindowSize(500, 500);
    glutInitWindowPosition(0, 0);
    glutCreateWindow("sample");
    glutDisplayFunc(myDrawing);
    glutIdleFunc(idle_func);
    glutMouseFunc(mouse_func);
    myInit();
    glutMainLoop();
}
Rabbid76
  • 202,892
  • 27
  • 131
  • 174
acr1997
  • 43
  • 5
  • 1
    It looks like you didn't enable depth test. Try to add `glEnable(GL_DEPTH_TEST);` in `myInit()`. – Scheff's Cat Nov 19 '19 at 15:10
  • 1
    In `myDrawing()` you do `glClear(GL_COLOR_BUFFER_BIT);`. This should be `glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);`. (This other Q reminded me to look for this as well: [SO: glEnable(GL_DEPTH_TEST) - nothing rendered](https://stackoverflow.com/q/10042412/7478597).) ;-) – Scheff's Cat Nov 19 '19 at 15:13
  • 1
    For transparency see [OpenGL - How to create Order Independent transparency?](https://stackoverflow.com/a/37783085/2521214) ... but as you want the exact opposite you need to enable `GL_DEPTH_TEST`... however if you have enbled `GL_CULL_FACE ` then the faces winding must be consistent with `glFrontFace` setting `GL_CW/GL_CCW` if its not then you see the cube sort of inside out from certain sides which is your case I think... You can extract correct cube from here [complete GL+GLSL+VAO/VBO C++ example](https://stackoverflow.com/a/31913542/2521214) look for `vao_pos[]` QUADs table – Spektre Nov 19 '19 at 21:54

1 Answers1

7

Multiple issues:

  1. You aren't requesting a depth buffer from GLUT:

    glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB);
    

    Solution: OR in GLUT_DEPTH to make sure GLUT requests some depth buffer bits from the OS during GL context creation:

    glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB | GLUT_DEPTH);
    
  2. You're calling glEnable(GL_DEPTH_TEST) before GLUT has created a GL context:

    glutInit(&argc, argv);
    glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB);
    // no GL context yet
    glEnable(GL_DEPTH_TEST);
    

    Solution: Move the glEnable() to after glutCreateWindow() so it has a current GL context to work with:

    glutInit(&argc, argv);
    glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB | GLUT_DEPTH);
    glutInitWindowSize(500, 500);
    glutInitWindowPosition(0, 0);
    glutCreateWindow("sample");
    glEnable(GL_DEPTH_TEST);
    ...
    
  3. You never clear the depth buffer:

    void myDrawing() {
        // where's GL_DEPTH_BUFFER_BIT?
        glClear(GL_COLOR_BUFFER_BIT);
        ...
    

    Solution: OR in GL_DEPTH_BUFFER_BIT to your glClear() argument:

    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
    

All the fixes together:

#include <cmath>
#include <vector>
#include <GL/glut.h>

using namespace std;

void myInit() {
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
    glClearColor(0, 0, 0, 1);
    glOrtho(-2, 2, -2, 2, 2, -2);
    glMatrixMode(GL_MODELVIEW);
}

float Cube[][3] = { {-1, -1, -1}, {1, -1, -1}, {1, 1, -1}, {-1, 1, -1}, {-1, -1, 1}, {1, -1, 1}, {1, 1, 1}, {-1, 1, 1} };
float Colors[][3] = { {0, 0, 0}, {1, 0, 0}, {0, 1, 0}, {0, 0, 1}, {1, 1, 0}, {0, 1, 1}, {1, 0, 1}, {1, 1, 1} };

int axis = 0, theta[3] = {0, 0, 0};

void draw_face (int a, int b, int c, int d) {
    glBegin(GL_QUADS);
        glColor3fv(Colors[a]);
        glVertex3fv(Cube[a]);
        glColor3fv(Colors[b]);
        glVertex3fv(Cube[b]);
        glColor3fv(Colors[c]);
        glVertex3fv(Cube[c]);
        glColor3fv(Colors[d]);
        glVertex3fv(Cube[d]);
    glEnd();
}

void draw_cube () {
    draw_face(0, 3, 2, 1);
    draw_face(2, 3, 7, 6);
    draw_face(0, 4, 7, 3);
    draw_face(1, 2, 6, 5);
    draw_face(4, 5, 6, 7);
    draw_face(0, 1, 5, 4);
}

void spin_cube() {
    theta[axis] += 2;
    if (theta[axis] > 360)
        theta[axis] = -360;
    glutPostRedisplay();
}

void idle_func() {
    Sleep(10);
    spin_cube();
}

void mouse_func(int button, int state, int x, int y) {
    if (button == GLUT_LEFT_BUTTON && state == GLUT_DOWN)
        axis = 0;
    else if (button == GLUT_MIDDLE_BUTTON && state == GLUT_DOWN)
        axis = 1;
    else if (button == GLUT_RIGHT_BUTTON && state == GLUT_DOWN)
        axis = 2;
}

void myDrawing() {
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
    glPushMatrix();
    glRotatef(theta[0], 1, 0, 0);
    glRotatef(theta[1], 0, 1, 0);
    glRotatef(theta[2], 0, 0, 1);
    draw_cube();
    glPopMatrix();
    glFlush();
    glutSwapBuffers();
}

int main(int argc, char *argv[]) {
    glutInit(&argc, argv);
    glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB | GLUT_DEPTH);
    glutInitWindowSize(500, 500);
    glutInitWindowPosition(0, 0);
    glutCreateWindow("sample");
    glEnable(GL_DEPTH_TEST);
    glutDisplayFunc(myDrawing);
    glutIdleFunc(idle_func);
    glutMouseFunc(mouse_func);
    myInit();
    glutMainLoop();
}
genpfault
  • 51,148
  • 11
  • 85
  • 139