为啥我的 OpenGL 纹理不起作用?

Posted

技术标签:

【中文标题】为啥我的 OpenGL 纹理不起作用?【英文标题】:Why don't my OpenGL textures work?为什么我的 OpenGL 纹理不起作用? 【发布时间】:2012-11-24 16:13:44 【问题描述】:

我正在尝试恢复我在大学工作的一个旧项目。

这是一个基本的 OpenGL 动画,带有一些相机控件和模型加载。我已经让它工作了,但我不知道为什么没有为“天空盒”或“云平面”加载纹理。

我确信几年前他们使用几乎相同的代码。我所做的最大改变是从 SDL 移植到 GLUT,但我不知道这会对事情产生什么影响。

以下是一些与渲染天空盒相关的行:

glBindTexture(GL_TEXTURE_2D, skybox[i]);

glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);

glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);

glVertexPointer(3, GL_FLOAT, 0, face);
glTexCoordPointer(2, GL_FLOAT, 0, texture);
glDrawArrays(GL_QUADS, 0, 4);

我没有收到任何警告或运行时异常。纹理根本不显示。

我的代码中有这样的内容:glEnableClientState(GL_TEXTURE_COORD_ARRAY);glEnable(GL_TEXTURE_2D);

有什么想法吗?我真的很想让它再次正常工作。

完整来源在这里:

//Camera start location and rotation, boundaries are -0.5 -> +0.5 in each axis.
#define CAMERA_START_X -0.6
#define CAMERA_START_Y -0.2
#define CAMERA_START_Z -1.8
#define CAMERA_START_R 330
#define CAMERA_START_MOMENTUM 0.15

//Camera keyboard-event motion speed per second, independent of frame rate or machine.
#define CAMERA_ROTATION 100
#define CAMERA_ELEVATION 2
#define CAMERA_MOMENTUM 0.1

//Cloud plane configuration constants.
#define CLOUDS 12
#define CLOUD_SECTIONS 3
#define CLOUD_INNER_PLANES 0.2
#define CLOUD_OUTER_PLANES 0.8

//Frame rate, lowering the frame rate may improve performance on older computers.
#define FPS 60

//Other global constants.
#define PI 3.141592
#define SCALE_FACTOR 0.0001

//Print OpenGL errors to console if true.
#define DEBUG false

#include <GLUT/glut.h>
#include "glm.h"
#include <math.h>
#include <stdlib.h>
#include <stdio.h>

//*****************************************
//           Global Variables
//*****************************************

//Use glm's texture id variable to maintain consistency.
extern GLenum _glmTextureTarget;

//Models.
GLMmodel* eagle;
GLMmodel* airplane;

//Cloud plane.
float cloudPlaneV[CLOUDS][CLOUDS][7][CLOUD_SECTIONS][3];
GLuint cloudTexture;

//Camera location and rotation.
float cameraX = CAMERA_START_X * SCALE_FACTOR;
float cameraY = CAMERA_START_Y * SCALE_FACTOR;
float cameraZ = CAMERA_START_Z * SCALE_FACTOR;
float cameraR = CAMERA_START_R;

//Key event values for camera control.
float rotationDirection = 0;
float elevationDirection = 0;
float momentumDirection = 0;

//Skybox texture indices.
GLuint skybox[6];

//Skybox vertices.
GLfloat vertices[8][3] =
  -1, -1, -1, // 0: left,  bottom, back
   -1, -1, +1, // 1: left,  bottom, front
   -1, +1, -1, // 2: left,  top,    back
   -1, +1, +1, // 3: left,  top,    front
   +1, -1, -1, // 4: right, bottom, back
   +1, -1, +1, // 5: right, bottom, front
   +1, +1, -1, // 6: right, top,    back
   +1, +1, +1;// 7: right, top,    front

//Skybox cube faces.
GLubyte faces[6][4] =
  1, 0, 2, 3, // 0: west
   4, 5, 7, 6, // 1: east
   4, 0, 1, 5, // 2: below
   7, 3, 2, 6, // 3: above
   5, 1, 3, 7, // 4: south
   0, 4, 6, 2;// 5: north

//Standard texture winding.
GLfloat texture[4][2] =
  0.0, 0.0, // 0: left,  bottom
   1.0, 0.0, // 1: right, bottom
   1.0, 1.0, // 2: right, top
   0.0, 1.0;// 3: left,  top

//Animation variables.
bool fullscreen = 0;
float window_w, window_h;
bool forceReshape = false;
int frame = -1;
bool paused = false;
float momentum = CAMERA_START_MOMENTUM * SCALE_FACTOR;
float momentumBeforePause;

float planePriorX = 0, planePriorY = 0, planePriorZ = 0;
float planePostX = 0, planePostY = 0, planePostZ = 0;
float planeRotX = 0, planeRotY = 0, planeRotZ = 0;

float eaglePriorX = -0.5, eaglePriorY = 0.03, eaglePriorZ = 0.1;
float eaglePostX = 0, eaglePostY = 0, eaglePostZ = 0;
float eagleRotX = 0, eagleRotY = 0, eagleRotZ = 0;

//*****************************************
//           Loading Objects
//*****************************************

void loadObjects() 
  eagle = glmReadOBJ("resources/models/eagle.obj");
  glmVertexNormals(eagle, 180.0, false);
  glmUnitize(eagle);

  airplane = glmReadOBJ("resources/models/airplane.obj");
  glmVertexNormals(airplane, 180.0, false);
  glmUnitize(airplane);


//*****************************************
//               Camera
//*****************************************

void updateCamera() 
  //Reset position and rotation.
  glLoadIdentity();

  //Camera rotation.
  cameraR += rotationDirection * CAMERA_ROTATION / FPS;
  if (cameraR < 0) cameraR += 360;
  if (cameraR > 360) cameraR -= 360;

  //Camera location.
  momentum += momentumDirection * CAMERA_MOMENTUM * SCALE_FACTOR / FPS;
  if (momentum < 0) momentum = 0;
  cameraX += momentum * -sin(cameraR * PI / 180);
  cameraY += elevationDirection * CAMERA_ELEVATION * SCALE_FACTOR / FPS;
  cameraZ += momentum * cos(cameraR * PI / 180);

  //Move the world, not the camera.
  glRotatef(cameraR, 0, 1, 0);
  glTranslatef(cameraX, cameraY, cameraZ);


//*****************************************
//                Skybox
//*****************************************

void loadSkybox() 
  GLfloat width = 600, height = 600;
  skybox[0] = glmLoadTexture("resources/textures/skybox/west.jpeg",   GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE, &width, &height);
  skybox[1] = glmLoadTexture("resources/textures/skybox/east.jpeg",   GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE, &width, &height);
  skybox[2] = glmLoadTexture("resources/textures/skybox/bottom.jpeg", GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE, &width, &height);
  skybox[3] = glmLoadTexture("resources/textures/skybox/top.jpeg",    GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE, &width, &height);
  skybox[4] = glmLoadTexture("resources/textures/skybox/south.jpeg",  GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE, &width, &height);
  skybox[5] = glmLoadTexture("resources/textures/skybox/north.jpeg",  GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE, &width, &height);


//Draws the skybox.
void drawSkybox() 
  //Disable lighting, enable textures.
  glDisable(GL_LIGHTING);
  glEnableClientState(GL_TEXTURE_COORD_ARRAY);

  //Augment such that camera is at the center.
  GLfloat center[8][3];
  for (int i = 0; i < 8; i++) 
    center[i][0] = vertices[i][0] - cameraX;
    center[i][1] = vertices[i][1] - cameraY;
    center[i][2] = vertices[i][2] - cameraZ;
  

  //Draw eace face.
  GLfloat face[4][3];
  for (int i = 0; i < 6; i++) 
    for (int j = 0; j < 4; j++) 
      for (int k = 0; k < 3; k++) 
        face[j][k] = center[faces[i][j]][k];
      
    

    glBindTexture(GL_TEXTURE_2D, skybox[i]);

    glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
    glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);

    glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP);
    glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);

    glVertexPointer(3, GL_FLOAT, 0, face);
    glTexCoordPointer(2, GL_FLOAT, 0, texture);
    glDrawArrays(GL_QUADS, 0, 4);
  

  //Enable lighting, disable textures.
  glEnable(GL_LIGHTING);
  glDisableClientState(GL_TEXTURE_COORD_ARRAY);


//*****************************************
//             Cloud Plane
//*****************************************

void calculateCloudPlane() 
  //Calculate the increment.
  float incr = 2 * PI / CLOUD_SECTIONS;

  //Use cosArr and sinArr to reuse the sine and cosine calculation.
  float cosArr[CLOUD_SECTIONS + 1], sinArr[CLOUD_SECTIONS + 1];
  for (int i = 0; i < CLOUD_SECTIONS + 1; i++) 
    cosArr[i] = cos(i * incr);
    sinArr[i] = sin(i * incr);
  

  //Calculate a circle.
  float circle[CLOUD_SECTIONS][3];
  for (int i = 0; i < CLOUD_SECTIONS; i++) 
    circle[i][0] = cosArr[i];
    circle[i][1] = 0;
    circle[i][2] = sinArr[i];
  

  //Calculate a cloud from the circle.
  float cloud[7][CLOUD_SECTIONS][3];
  float xScale, zScale, xTrans, zTrans;
  for (int i = 0; i < 7; i++) 
    switch (i) 
      //Scale everything down quite a bit, we only want a light covering.
      case 0: xScale = 0.0625; zScale = 0.0625; xTrans = 0; zTrans = 0;
      break;
      case 1: xScale = 0.0625; zScale = 0.0625; xTrans = 0.0625; zTrans = 0;
      break;
      case 2: xScale = 0.0625; zScale = 0.0625; xTrans = -0.0625; zTrans = 0;
      break;
      case 3: xScale = 0.0625; zScale = 0.0625; xTrans = 0.0625 * cos(60 * PI / 180); zTrans = 0.0625 * sin(60 * PI / 180);
      break;
      case 4: xScale = 0.0625; zScale = 0.0625; xTrans = 0.0625 * cos(120 * PI / 180); zTrans = 0.0625 * sin(120 * PI / 180);
      break;
      case 5: xScale = 0.0625; zScale = 0.0625; xTrans = 0.0625 * cos(240 * PI / 180); zTrans = 0.0625 * sin(240 * PI / 180);
      break;
      case 6: xScale = 0.0625; zScale = 0.0625; xTrans = 0.0625 * cos(300 * PI / 180); zTrans = 0.0625 * sin(300 * PI / 180);
      break;
    
    for (int j = 0; j < CLOUD_SECTIONS; j++) 
      cloud[i][j][0] = circle[j][0] * xScale + xTrans;
      cloud[i][j][1] = circle[j][1];
      cloud[i][j][2] = circle[j][2] * zScale + zTrans;
    
  

  //Calculate a cloud plane from the cloud.
  for (int i = 0; i < CLOUDS; i++) 
    for (int j = 0; j < CLOUDS; j++) 
      for (int k = 0; k < 7; k++) 
        for (int l = 0; l < CLOUD_SECTIONS; l++) 
          cloudPlaneV[i][j][k][l][0] = cloud[k][l][0] - CLOUDS / 2 + i;
          cloudPlaneV[i][j][k][l][1] = cloud[k][l][1];
          cloudPlaneV[i][j][k][l][2] = cloud[k][l][2] - CLOUDS / 2 + j;
        
      
    
  

  //Load texture.
  float width = 256, height = 256;
  cloudTexture = glmLoadTexture("resources/textures/cloud.jpeg", GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE, &width, &height);


//Draws 4 planes containing 'cloud' type objects with parameters defined as constants above.
void drawCloudPlane() 
  glPushMatrix();
  glDisable(GL_LIGHTING);
  glEnableClientState(GL_TEXTURE_COORD_ARRAY);

  //Move the plane with camera, utilises integer truncation.
  int xOffset = -cameraX / SCALE_FACTOR;
  float yOffset = -cameraY / SCALE_FACTOR;
  int zOffset = -cameraZ / SCALE_FACTOR;
  glTranslatef(xOffset, yOffset, zOffset);

  //Bind data pointers.
  glBindTexture(GL_TEXTURE_2D, cloudTexture);
  glVertexPointer(3, GL_FLOAT, 0, cloudPlaneV);
  glTexCoordPointer(2, GL_FLOAT, 0, texture);

  //Top plane.
  glPushMatrix();
  glTranslatef(0, CLOUD_OUTER_PLANES, 0);
  for (int i = 0; i < CLOUDS * CLOUDS * 7; i++) 
    glDrawArrays(GL_POLYGON, i * CLOUD_SECTIONS, CLOUD_SECTIONS);
  
  glPopMatrix();

  //2nd plane.
  glPushMatrix();
  glTranslatef(0, CLOUD_INNER_PLANES, 0);
  for (int i = 0; i < CLOUDS * CLOUDS * 7; i++) 
    glDrawArrays(GL_POLYGON, i * CLOUD_SECTIONS, CLOUD_SECTIONS);
  
  glPopMatrix();

  //3rd plane.
  glPushMatrix();
  glTranslatef(0, -CLOUD_INNER_PLANES, 0);
  for (int i = 0; i < CLOUDS * CLOUDS * 7; i++) 
    glDrawArrays(GL_POLYGON, i * CLOUD_SECTIONS, CLOUD_SECTIONS);
  
  glPopMatrix();

  //Bottom plane.
  glPushMatrix();
  glTranslatef(0, -CLOUD_OUTER_PLANES, 0);
  for (int i = 0; i < CLOUDS * CLOUDS * 7; i++) 
    glDrawArrays(GL_POLYGON, i * CLOUD_SECTIONS, CLOUD_SECTIONS);
  
  glPopMatrix();

  glEnable(GL_LIGHTING);
  glDisableClientState(GL_TEXTURE_COORD_ARRAY);
  glPopMatrix();


//*****************************************
//                Lights
//*****************************************

//Set up lights at points on the skybox that match the textures.
void setupLights() 
  glEnable(GL_LIGHTING);
  glEnable(_glmTextureTarget);
  glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
  glEnable(GL_RESCALE_NORMAL);

  //Set global ambience.
  GLfloat global_ambient[] = 0.5, 0.5, 0.5, 1;
  glLightModelfv(GL_LIGHT_MODEL_AMBIENT, global_ambient);

  //Set up a light source at the sun's location.
  glEnable(GL_LIGHT0);
  GLfloat light0_ambient[] = 0, 0, 0, 1;
  GLfloat light0_diffuse[] = 0.5, 0.5, 0.5, 1;
  GLfloat light0_specular[] = 0.7, 0.7, 0.7, 1;
  GLfloat light0_position[] = -1, 1, -1, 1;

  glLightfv(GL_LIGHT0, GL_AMBIENT, light0_ambient);
  glLightfv(GL_LIGHT0, GL_DIFFUSE, light0_diffuse);
  glLightfv(GL_LIGHT0, GL_SPECULAR, light0_specular);
  glLightfv(GL_LIGHT0, GL_POSITION, light0_position);

  //Set up a light source at the sun's reflection.
  //The reflection is half as bright as the sun.
  glEnable(GL_LIGHT1);
  GLfloat light1_ambient[] = 0, 0, 0, 1;
  GLfloat light1_diffuse[] = 0.25, 0.25, 0.25, 1;
  GLfloat light1_specular[] = 0.35, 0.35, 0.35, 1;
  GLfloat light1_position[] = -1, -1, -1, 1;

  glLightfv(GL_LIGHT1, GL_AMBIENT, light1_ambient);
  glLightfv(GL_LIGHT1, GL_DIFFUSE, light1_diffuse);
  glLightfv(GL_LIGHT1, GL_SPECULAR, light1_specular);
  glLightfv(GL_LIGHT1, GL_POSITION, light1_position);


//This augments the lighting to match the skybox, required after camera rotation.
void augmentLights() 
  GLfloat light0_position[] = -1 / SCALE_FACTOR, 1 / SCALE_FACTOR, -1 / SCALE_FACTOR, 1;
  glLightfv(GL_LIGHT0, GL_POSITION, light0_position);

  GLfloat light1_position[] = -1 / SCALE_FACTOR, -1 / SCALE_FACTOR, -1 / SCALE_FACTOR, 1;
  glLightfv(GL_LIGHT1, GL_POSITION, light1_position);


//*****************************************
//              Main Scene
//*****************************************

void drawEagle() 
  glPushMatrix();

  //Scale the eagle down to size.
  glScalef(0.5, 0.5, 0.5);

  //Face forward.
  glRotatef(180, 0, 1, 0);

  glmDraw(eagle, GLM_SMOOTH | GLM_MATERIAL);

  glPopMatrix();


void drawAirplane() 
  glPushMatrix();

  //Rotate the plane so that it faces forward.
  glRotatef(270, 1, 0, 0);
  glRotatef(90, 0, 0, 1);

  glmDraw(airplane, GLM_SMOOTH | GLM_MATERIAL | GLM_TEXTURE);

  glPopMatrix();


//Keeps angles within bounds - prevents overflow.
void bounds(float &angle) 
  if (angle > 360) angle -= 360;
  if (angle < 0) angle += 360;


void drawScene() 
  glPushMatrix();

  //Set the animation control variables.
  if (!paused) frame++;
  int ticks = frame % 1440;
  if (frame % 1440 == 0) 
    ticks = 0;

    //Reset animation object positions and rotations.
    planePriorX = 0, planePriorY = 0, planePriorZ = 0;
    planePostX = 0, planePostY = 0, planePostZ = 0;
    planeRotX = 0, planeRotY = 0, planeRotZ = 0;

    eaglePriorX = -0.5, eaglePriorY = 0.03, eaglePriorZ = -0.1;
    eaglePostX = 0, eaglePostY = 0, eaglePostZ = 0;
    eagleRotX = 0, eagleRotY = 0, eagleRotZ = 0;
  

  //Apply scene transformations.
  glRotatef(30, 0, 1, 0);
  glTranslatef(0, 0, -1500 * frame * SCALE_FACTOR);

  //Make sure angles are in bounds.
  bounds(planeRotX); bounds(planeRotY); bounds(planeRotZ);
  bounds(eagleRotX); bounds(eagleRotY); bounds(eagleRotZ);

  if (!paused) 
    //Airplane transformation events.
    //Constant swaying.
    planeRotZ -= 0.5 * cos(ticks * 2 * PI / 180);
    planePostY -= 0.01 * cos(ticks * PI / 180);

    //Spin upside-down.
    if (ticks >= 180 && ticks < 360) planeRotZ -= PI * 0.5 * sin(ticks * PI / 180);

    //Spin back round.
    if (ticks >= 360 && ticks < 540) planeRotZ += PI * 0.5 * sin(ticks * PI / 180);

    //Dive.
    if (ticks >= 720 && ticks < 900) 
      planeRotX -= 0.25 * PI * sin(ticks * 2 * PI / 180);
      planePriorY -= 0.005 * PI * sin(ticks * PI / 180);
      planePriorZ -= 0.01 * PI * sin(ticks * 0.5 * PI / 180);
    

    //Loop-the-loop
    if (ticks >= 900 && ticks < 1220) 
      planeRotX += 1;
      planePriorY += 0.015 * PI * sin((ticks - 180) * PI / 180);
      planePriorZ -= 0.015 * PI * cos((ticks - 180) * PI / 180);
    

    //Reset position.
    if (ticks >= 1220 && ticks < 1440) 
      // These values were found by minimising errors using binary division.
      planeRotX -= 0.1262345 * PI * sin(ticks * PI / 180);
      planePriorY -= 0.002379563 * PI * sin(ticks * 0.5 * PI / 180);
      planePriorZ -= 0.003826425 * PI * sin(ticks * 0.5 * PI / 180);
    

    //Eagle transformation events.
    //Set default position.
    eaglePriorX = -1;
    eaglePriorZ = 0.4;

    //Set start position over left wing.
    if (ticks >= 0 && ticks < 180) 
      eaglePriorX = -0.5;
      eaglePriorY = 0.03;
      eaglePriorZ = -0.1;
    

    //Move a little with the wing.
    if (ticks >= 0 && ticks < 90) 
      eagleRotZ -= cos(ticks * 2 * PI / 180);
      eaglePostY -= 0.009 * sin(ticks * 2 * PI / 180);
    

    //Move back, up and left.
    if (ticks >= 90 && ticks < 180) 
      eaglePriorX -= (float)0.5 / 90 * (ticks - 90);
      eaglePriorZ += (float)0.5 / 90 * (ticks - 90);
      eaglePostY += 0.009 * sin((ticks - 90) * 2 * PI / 180);
    

    //Swaying.
    if (ticks >= 90 && ticks < 1350) 
      eagleRotZ -= 0.6 * cos((ticks + 90) * PI / 180);
      eaglePostY -= 0.01 * cos((ticks + 90) * 2 * PI / 180);
    

    //Avoid plane collision.
    if (ticks >= 360 && ticks < 540) eagleRotZ += 0.25 * PI * sin(ticks * 2 * PI / 180);

    //Glide from side to side.
    if (ticks >= 720 && ticks < 1080) eaglePriorX += 0.4 * PI * sin(ticks * 0.5 * PI / 180);

    //Move back to start position.
    if (ticks >= 1350 && ticks < 1440) 
      eaglePriorX += (float)0.5 / 90 * (ticks - 1350);
      eaglePriorZ -= (float)0.5 / 90 * (ticks - 1350);
    

    //Avoid plane collision.
    if (ticks >= 1400 && ticks < 1420) eaglePriorY += 0.01;
    if (ticks >= 1420 && ticks < 1440) eaglePriorY -= 0.01;
  

  //Apply the transformations then draw the airplane.
  glPushMatrix();
  glTranslatef(planePriorX, planePriorY, planePriorZ);
  glRotatef(planeRotX, 1, 0, 0);
  glRotatef(planeRotY, 0, 1, 0);
  glRotatef(planeRotZ, 0, 0, 1);
  glTranslatef(planePostX, planePostY, planePostZ);
  drawAirplane();
  glPopMatrix();

  //Apply the transformations then draw the eagle.
  glPushMatrix();
  glTranslatef(eaglePriorX, eaglePriorY, eaglePriorZ);
  glRotatef(eagleRotX, 1, 0, 0);
  glRotatef(eagleRotY, 0, 1, 0);
  glRotatef(eagleRotZ, 0, 0, 1);
  glTranslatef(eaglePostX, eaglePostY, eaglePostZ);
  drawEagle();
  glPopMatrix();
  glPopMatrix();


//*****************************************
//                 GLUT
//*****************************************

//Initialisation function.
void init(int argc, char **argv) 
  //Initialise GLUT.
  glutInit(&argc, argv);

  // Use doule buffering.
  glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB | GLUT_DEPTH);
  glutInitWindowSize(760, 760);

  //Create window.
  glutCreateWindow("Come Fly With Me - by Chris Patuzzo");

  //Set up camera.
  glMatrixMode(GL_PROJECTION);
  glLoadIdentity();
  gluPerspective(90, 1, 0.00001, 1 / SCALE_FACTOR);
  glMatrixMode(GL_MODELVIEW);

  //Set the clear color.
  glClearColor(0, 0, 0, 1);

  //Use z-buffer, lighting, normal scaling.
  glEnable(GL_DEPTH_TEST);

  //Set up two lights; the sun and its reflection.
  setupLights();

  //Use vertex arrays.
  glEnableClientState(GL_VERTEX_ARRAY);
  glEnable(GL_TEXTURE_2D);

  //Load skybox and objects.
  loadSkybox();
  loadObjects();

  //Calculate cloud plane.
  calculateCloudPlane();


void reshape(int width, int height) 
  int min = (width > height) ? height : width;
  glViewport((width - min) / 2, (height - min) / 2, min, min);


//Main display loop.
void display() 
  //Clear buffers.
  glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

  //Augment camera, draw skybox.
  updateCamera();
  drawSkybox();

  //Scale the world and reset light positions.
  glScalef(SCALE_FACTOR, SCALE_FACTOR, SCALE_FACTOR);
  augmentLights();

  //Draw the plane containing clouds and the main scene.
  drawCloudPlane();
  drawScene();

  //Swap buffers.
  glutSwapBuffers();


void timer(int n) 
  if (DEBUG) 
    printf("%s\n", gluErrorString(glGetError()));
    fflush(stdout);
  

  if (forceReshape) 
    float w = glutGet(GLUT_WINDOW_WIDTH);
    float h = glutGet(GLUT_WINDOW_HEIGHT);

    reshape(w, h);
  

  glutPostRedisplay();
  glutTimerFunc(1000 / FPS, timer, 0);


void keyDown(unsigned char key, int x, int y) 
  switch (key) 
    case 'q': exit(0);

    case 'w': momentumDirection++;  break;
    case 'a': rotationDirection--;  break;
    case 's': momentumDirection--;  break;
    case 'd': rotationDirection++;  break;
    case '=': elevationDirection--; break;
    case '-': elevationDirection++; break;

    case '0': momentum = 0; break;

    case ' ':
      if (paused) 
        paused = false;
        momentum = momentumBeforePause;
      
      else 
        paused = true;
        momentumBeforePause = momentum;
        momentum = 0;
      
    break;


    case 'r':
      //Reset the camera.
      cameraX = CAMERA_START_X * SCALE_FACTOR;
      cameraY = CAMERA_START_Y * SCALE_FACTOR;
      cameraZ = CAMERA_START_Z * SCALE_FACTOR;
      cameraR = CAMERA_START_R;

      momentum = CAMERA_START_MOMENTUM * SCALE_FACTOR;
      rotationDirection  = 0;
      elevationDirection = 0;
      momentumDirection  = 0;

      //Reset animation frame, set unpaused.
      frame = -1;
      paused = false;

      //Reset animation object positions and rotations.
      planePriorX = 0, planePriorY = 0, planePriorZ = 0;
      planePostX = 0, planePostY = 0, planePostZ = 0;
      planeRotX = 0, planeRotY = 0, planeRotZ = 0;

      eaglePriorX = -0.5, eaglePriorY = 0.03, eaglePriorZ = -0.1;
      eaglePostX = 0, eaglePostY = 0, eaglePostZ = 0;
      eagleRotX = 0, eagleRotY = 0, eagleRotZ = 0;
    break;

    case 'p':
      //Pause the animation.
      paused = true;
      momentumBeforePause = momentum;
      momentum = 0;

      //Set frame.
      frame = 605;

      //Move the camera.
      cameraX = 0.004524;
      cameraY = 0.000052;
      cameraZ = 0.007764;
      cameraR = 306;

      //Reset animation object positions and rotations.
      planePriorX = 0, planePriorY = -0.871533, planePriorZ = -1.577791;
      planePostX = 0, planePostY = -0.44244, planePostZ = 0;
      planeRotX = 312, planeRotY = 0, planeRotZ = 13.651090;

      eaglePriorX = -1, eaglePriorY = 0.03, eaglePriorZ = 0.4;
      eaglePostX = 0, eaglePostY = -0.293748, eaglePostZ = 0;
      eagleRotX = 0, eagleRotY = 0, eagleRotZ = 18.295479;
    break;

    case 'y':
      //Pause the animation.
      paused = true;
      momentumBeforePause = momentum;
      momentum = 0;

      //Set frame.
      frame = 224;

      //Move the camera.
      cameraX = 0.001829;
      cameraY = -0.000004;
      cameraZ = 0.00298;
      cameraR = 138;

      //Reset animation object positions and rotations.
      planePriorX = 0, planePriorY = 0, planePriorZ = 0;
      planePostX = 0, planePostY = -0.5829, planePostZ = 0;
      planeRotX = 0, planeRotY = 0, planeRotZ = 267.401611;

      eaglePriorX = -1, eaglePriorY = 0.03, eaglePriorZ = 0.4;
      eaglePostX = 0, eaglePostY = 0.000001, eaglePostZ = 0;
      eagleRotX = 0, eagleRotY = 0, eagleRotZ = 43.981647;
    break;

    case 'u':
      //Pause the animation.
      paused = true;
      momentumBeforePause = momentum;
      momentum = 0;

      //Set frame.
      frame = -1;

      //Move the camera.
      cameraX = 0.000094;
      cameraY = -0.000036;
      cameraZ = -0.000103;
      cameraR = 42;

      //Reset animation object positions and rotations.
      planePriorX = 0, planePriorY = 0, planePriorZ = 0;
      planePostX = 0, planePostY = 0, planePostZ = 0;
      planeRotX = 0, planeRotY = 0, planeRotZ = 0;

      eaglePriorX = -0.5, eaglePriorY = 0.03, eaglePriorZ = -0.1;
      eaglePostX = 0, eaglePostY = 0, eaglePostZ = 0;
      eagleRotX = 0, eagleRotY = 0, eagleRotZ = 0;
    break;

    case 'h':
      printf("\n\n*** Controls ***\n\nW: Accelerate\nS: Decelerate\nA: Turn left\nD: Turn right\n=: Increase elevation\n-: Decrease elevation\n0: Stop moving\nSpace: Pause animation\n\nF: Fullscreen\nP: Set viewpoint A\nU: Set viewpoint B\nY: Set viewpoint C\n\nH: Help\nR: Reset\nQ: Quit");
    break;

    case 'f':
      if (fullscreen) 
        glutReshapeWindow(window_w, window_h);
        fullscreen = false;
      
      else 
        window_w = glutGet(GLUT_WINDOW_WIDTH);
        window_h = glutGet(GLUT_WINDOW_HEIGHT);

        glutFullScreen();
        fullscreen = true;
      

      forceReshape = true;
    break;
  


void keyUp(unsigned char key, int x, int y) 
  switch (key) 
    case 'w': momentumDirection--;  break;
    case 'a': rotationDirection++;  break;
    case 's': momentumDirection++;  break;
    case 'd': rotationDirection--;  break;
    case '=': elevationDirection++; break;
    case '-': elevationDirection--; break;
  


//Entry point.
int main(int argc, char **argv) 
  init(argc, argv);
  glutDisplayFunc(display);
  glutTimerFunc(1000 / 60, timer, 0);
  glutSetKeyRepeat(0);
  glutKeyboardFunc(keyDown);
  glutKeyboardUpFunc(keyUp);
  glutReshapeFunc(reshape);
  glutMainLoop();

  return 0;

【问题讨论】:

“我没有收到任何警告或运行时异常。”那是因为 OpenGL 不会警告你或抛出异常。相反,操作设置全局状态,您可以查询该状态以查看操作是否成功。您应该始终这样做,即使这会使您的代码不太清晰。 The biggest change I've made is porting from SDL to GLUT, but I don't see how that would affect things. 您没有看到切换工具包和代码中所需的大量更改可能会“影响事物”吗? 【参考方案1】:

谢谢立方。

我添加了一个调试 sn-p 来帮助追踪问题:

if (DEBUG) 
  printf("%s\n", gluErrorString(glGetError()));
  fflush(stdout);

使用二进制除法,我很快发现这一行出错了'invalid enumerant':

glEnable(GL_VERTEX_ARRAY);

这是因为它应该是:

glEnableClientState(GL_VERTEX_ARRAY);

我今天学到了宝贵的一课。

【讨论】:

如果这能解决您的问题,请随时接受您自己的答案!这样人们就知道如果遇到同样的问题,这就是他们正在寻找的答案。 +1:就这样,世界又多了一位高效且有用的软件开发人员。 :)

以上是关于为啥我的 OpenGL 纹理不起作用?的主要内容,如果未能解决你的问题,请参考以下文章

多个 OpenGL 纹理在某些情况下不起作用?

OpenGL VBO球体纹理加载不起作用

使用 GLFW3 在 OpenGL 上下文之间共享纹理不起作用

在 OpenGL ES 1.1 中使用顶点缓冲区对象绘图不起作用

Opengl为啥这个着色器不起作用?

为啥变换矩阵在 OpenGL 中不起作用