Question

I'm trying to make a 3D square frustum by drawing vertices:

int xPts[] = { 1.0,  1.0, -1.0, -1.0,  2.0,  2.0, -2.0, -2.0 };
int yPts[] = { 1.0,  1.0,  1.0,  1.0, -1.0, -1.0, -1.0, -1.0 };
int zPts[] = { 1.0, -1.0, -1.0,  1.0,  2.0, -2.0, -2.0,  2.0 };

int sideA[] = { 0, 3, 7, 4 };
int sideB[] = { 0, 1, 5, 4 };
int sideC[] = { 2, 3, 7, 6 };
int sideD[] = { 1, 2, 6, 5 };

glPolygonMode(GL_FRONT, GL_FILL);

glPushMatrix();
    glTranslatef(xLoc, yLoc, zLoc);

    glRotatef(xRotation, 1, 0, 0);
    glRotatef(yRotation, 0, 1, 0);
    glRotatef(zRotation, 0, 0, 1);

    glScalef(xSize, ySize, zSize);

    glBegin(GL_POLYGON);
        for (int i = 0; i < 4; i++) {
            glVertex3f(xPts[i], yPts[i], zPts[i]);
        }

        for (int i = 4; i < 8; i++) {
            glVertex3f(xPts[i], yPts[i], zPts[i]);
        }

        for (int i = 0; i < 4; i++) {
            glVertex3f(xPts[sideA[i]], yPts[sideA[i]], zPts[sideA[i]]);
        }

        for (int i = 0; i < 4; i++) {
            glVertex3f(xPts[sideB[i]], yPts[sideB[i]], zPts[sideB[i]]);
        }

        for (int i = 0; i < 4; i++) {
            glVertex3f(xPts[sideC[i]], yPts[sideC[i]], zPts[sideC[i]]);
        }

        for (int i = 0; i < 4; i++) {
            glVertex3f(xPts[sideD[i]], yPts[sideD[i]], zPts[sideD[i]]);
        }
    glEnd();
glPopMatrix();

This successfully draws a square frustum which I can rotate, scale, and translate no problem. However, the shading is off. It's supposed to be a bright yellow but all of the sides look like they've been evenly shaded. You can see my shading is working in general for all of my other lovely shapes.

Am I going about the building of my square frustum entirely wrong? How do I get the shading to apply to it properly?

enter image description here

Was it helpful?

Solution

You also need to set normals using glNormal3f, otherwise no lighting/shading can be computed. The easiest way to compute these in your case is by simply calculating the cross product of two neighboring edges for each of the six planes. So if you have some vector math library at hand, the code for the first normal would look about this:

Vector3f v1(xPts[0], yPts[0], zPts[0]);
Vector3f v2(xPts[1], yPts[1], zPts[1]);
Vector3f v3(xPts[2], yPts[2], zPts[2]);
Vector3f edge1 = v1 - v2;
Vector3f edge2 = v3 - v2;
Vector3f normal = edge2.cross(edge1).normalize();
glNormal3f(normal.x, normal.y, normal.z);
for (int i = 0; i < 4; i++)
  glVertex3f(xPts[i], yPts[i], zPts[i]);

// ...

(Of course you do want to put this into a function instead of copying it for all six polygons...)

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top