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

有帮助吗?

解决方案

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...)

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top