Search code examples
c++visual-studioopenglglut

OpenGL Color half of a cube


I am trying to color half of a cube to look like its filled with water. In the code below I draw the cube with the white edges:

void initGL() {
    glClearColor(0.0f, 0.0f, 0.0f, 1.0f); 
    glClearDepth(1.0f); 
    glEnable(GL_DEPTH_TEST);
    glDepthFunc(GL_LEQUAL); 
    glShadeModel(GL_SMOOTH);
    glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST); 
}

void display() {
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
    glMatrixMode(GL_MODELVIEW);
    glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
    glLoadIdentity(); 

    glTranslatef(-3.0f, 0.0f, -9.0f); 

    glBegin(GL_QUADS);
    glBegin(GL_LINES);

    glColor3f(1.0f, 1.0f, 1.0f); 
    glVertex3f(1.0f, 1.0f, -1.0f);
    glVertex3f(-1.0f, 1.0f, -1.0f);
    glVertex3f(-1.0f, 1.0f, 1.0f);
    glVertex3f(1.0f, 1.0f, 1.0f);

    glColor3f(1.0f, 1.0f, 1.0f); 
    glVertex3f(1.0f, -1.0f, 1.0f);
    glVertex3f(-1.0f, -1.0f, 1.0f);
    glVertex3f(-1.0f, -1.0f, -1.0f);
    glVertex3f(1.0f, -1.0f, -1.0f);

    glColor3f(1.0f, 1.0f, 1.0f); 
    glVertex3f(1.0f, 1.0f, 1.0f);
    glVertex3f(-1.0f, 1.0f, 1.0f);
    glVertex3f(-1.0f, -1.0f, 1.0f);
    glVertex3f(1.0f, -1.0f, 1.0f);

    glColor3f(1.0f, 1.0f, 1.0f); 
    glVertex3f(1.0f, -1.0f, -1.0f);
    glVertex3f(-1.0f, -1.0f, -1.0f);
    glVertex3f(-1.0f, 1.0f, -1.0f);
    glVertex3f(1.0f, 1.0f, -1.0f);

    glColor3f(1.0f, 1.0f, 1.0f); 
    glVertex3f(-1.0f, 1.0f, 1.0f);
    glVertex3f(-1.0f, 1.0f, -1.0f);
    glVertex3f(-1.0f, -1.0f, -1.0f);
    glVertex3f(-1.0f, -1.0f, 1.0f);

    glColor3f(1.0f, 1.0f, 1.0f); 
    glVertex3f(1.0f, 1.0f, -1.0f);
    glVertex3f(1.0f, 1.0f, 1.0f);
    glVertex3f(1.0f, -1.0f, 1.0f);
    glVertex3f(1.0f, -1.0f, -1.0f);
    glEnd(); 
    glutSwapBuffers();

}

but I don't know how to color half of it without erasing the white edges. And besides that I had to animate it so water could go up and down.


Solution

  • Note, that things like glBegin, glEnd are deprecated (even glVertexPointer and glEnableClientState). Read about Fixed Function Pipeline and Vertex Specification.


    But based on your code, I recommend to define an array of vertex data (glVertexPointer) and to client-side capability (glEnableClientState), to solve your issue. Further define arrays of indices and use glDrawElements to render (indexed) primitives from array data.

    Define the vertex coordinates:

    GLfloat water_height = -0.5f;
    GLfloat vertices[] =
    {
        -1.0f, -1.0f,         -1.0f,  // 0
         1.0f, -1.0f,         -1.0f,  // 1
         1.0f, -1.0f,          1.0f,  // 2
        -1.0f, -1.0f,          1.0f,  // 3
    
        -1.0f,  1.0f,         -1.0f,  // 5
         1.0f,  1.0f,         -1.0f,  // 6
         1.0f,  1.0f,          1.0f,  // 7
        -1.0f,  1.0f,          1.0f,  // 8
    
        -1.0f,  water_height, -1.0f,  // 9
         1.0f,  water_height, -1.0f,  // 10
         1.0f,  water_height,  1.0f,  // 11
        -1.0f,  water_height,  1.0f   // 12
    };
    

    Define the indices for the "water" quads:

    // 6 quad indices for the 6 sides of the water cube
    GLuint water_indices[] = 
    { 
        0, 1, 2, 3,
        0, 1, 9, 8,
        1, 2, 10, 9,
        2, 3, 11, 10,
        3, 0, 8, 11,
        8, 9, 10, 11
    };
    

    Define the indices for the edges:

    // 8 edges for the part of the cube which is not filled with water 
    GLuint edge_indices[] = 
    { 
        4, 5, 
        5, 6,
        6, 7,
        7, 4,
        4, 8,
        5, 9,
        6, 10,
        7, 11
    };
    

    Draw the quads and the lines:

    glVertexPointer( 3, GL_FLOAT, 0, vertices );
    glEnableClientState( GL_VERTEX_ARRAY );
    
    glColor4f( 0.3f, 0.5f, 1.0f, 1.0f );
    glDrawElements( GL_QUADS, 6 * 4, GL_UNSIGNED_INT, water_indices );
    
    glColor4f( 1.0f, 1.0f, 1.0f, 1.0f );
    glDrawElements( GL_LINES, 8 * 2, GL_UNSIGNED_INT, edge_indices );
    
    glDisableClientState( GL_VERTEX_ARRAY );
    

    Preview:

    water