OpenGL棋盘格纹理渲染时无法显示的问题排查
OpenGL长颈鹿模型棋盘格纹理不显示问题修复
问题描述
尝试使用GLubyte、glTexImage2D和glTexCoord2f为长颈鹿模型添加棋盘格纹理,此前设置的材质可正常生效,但纹理完全无法显示。
当前渲染效果:
预期效果:模型表面呈现黑白棋盘格纹理。
完整问题代码
#include <glut.h> float angle[4]; float LightAngle; bool LowerFrontLegDown = true; bool LowerBackLegDown = true; GLfloat corners[8][3] = { {-0.5,0.5,-0.5},{0.5,0.5,-0.5}, {0.5,-0.5,-0.5},{-0.5,-0.5,-0.5}, {-0.5,0.5,0.5},{0.5,0.5,0.5}, {0.5,-0.5,0.5},{-0.5,-0.5,0.5} }; GLfloat normals[][3] = { {0.0,0.0,1.0}, {1.0,0.0,0.0}, {0.0,-1.0,0.0}, {0.0,1.0,0.0}, {0.0,0.0,-1.0}, {-1.0,0.0,0.0} }; typedef struct materialStruct { GLfloat ambient[4]; GLfloat diffuse[4]; GLfloat specular[4]; GLfloat shininess; }; materialStruct brassMaterial = { { 0.33, 0.22, 0.03, 1.00 }, { 0.78, 0.57, 0.11, 1.00 }, { 0.99, 0.91, 0.81, 1.00 }, 27.80 }; materialStruct redPlasticMaterial = { { 0.30, 0.00, 0.00, 1.00 }, { 0.60, 0.00, 0.00, 1.00 }, { 0.80, 0.60, 0.60, 1.00 }, 32.00 }; materialStruct* currentMaterial; void setMaterial(materialStruct* materials) { glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT, materials->ambient); glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, materials->diffuse); glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, materials->specular); glMaterialf(GL_FRONT_AND_BACK, GL_SHININESS, materials->shininess); } void drawFace(int a, int b, int c, int d) { glBegin(GL_POLYGON); glTexCoord2f(0.0, 0.0); glVertex3fv(corners[a]); glTexCoord2f(0.0, 1.0); glVertex3fv(corners[b]); glTexCoord2f(1.0, 1.0); glVertex3fv(corners[c]); glTexCoord2f(1.0, 0.0); glVertex3fv(corners[d]); glEnd(); } void ArrayCube() { glNormal3fv(normals[0]); drawFace(0, 3, 2, 1); glNormal3fv(normals[1]); drawFace(3, 0, 4, 7); glNormal3fv(normals[2]); drawFace(2, 3, 7, 6); glNormal3fv(normals[3]); drawFace(1, 2, 6, 5); glNormal3fv(normals[4]); drawFace(4, 5, 6, 7); glNormal3fv(normals[5]); drawFace(5, 4, 0, 1); } void rotate() { angle[0] += 1.0; if (angle[0] > 360) angle[0] -= 360; if (LowerFrontLegDown) angle[1] -= 0.2; else angle[1] += 0.2; if (angle[1] < 315) LowerFrontLegDown = false; if (angle[1] > 360) LowerFrontLegDown = true; angle[0] += 1.0; if (angle[0] > 360) angle[0] -= 360; if (LowerBackLegDown) angle[1] -= 0.2; else angle[1] += 0.2; if (angle[1] < 315) LowerBackLegDown = false; if (angle[1] > 360) LowerBackLegDown = true; glutPostRedisplay(); } void MainBody() { glPushMatrix(); glScalef(1.25, 0.25, 0.5); ArrayCube(); glPopMatrix(); } void LowerNeck() { glPushMatrix(); glTranslatef(0.5, 0.25, 0); glScalef(0.15, 0.5, 0.15); ArrayCube(); glPopMatrix(); } void UpperNeck() { glPushMatrix(); glTranslatef(0.5, 0.75, 0); glScalef(0.15, 0.5, 0.15); ArrayCube(); glPopMatrix(); } void Head() { glPushMatrix(); glRotatef(90, 0.0, 0.0,1.0); glTranslatef(1, -0.6, 0); glScalef(0.1, 0.4, 0.15); ArrayCube(); glPopMatrix(); } void RightHorn() { glPushMatrix(); glRotatef(0, 0.0, 0.0,1); glTranslatef(0.5, 1.15, 0.035); glScalef(0.05, 0.15, 0.05); ArrayCube(); glPopMatrix(); } void LeftHorn() { glPushMatrix(); glRotatef(0, 0.0, 0.0, 1); glTranslatef(0.5, 1.15, -0.035); glScalef(0.05, 0.15, 0.05); ArrayCube(); glPopMatrix(); } void FrontUpperRightLeg() { glPushMatrix(); glTranslatef(0.5, -0.35, 0.15); glScalef(0.15, 0.5, 0.15); ArrayCube(); glPopMatrix(); } void FrontLowerRightLeg() { glPushMatrix(); glTranslatef(0.5, -0.75, 0.15); glRotatef(angle[1], 0.0, 0.0, 1.0); glScalef(0.15, 0.5, 0.15); ArrayCube(); glPopMatrix(); } void FrontUpperLeftLeg() { glPushMatrix(); glTranslatef(0.5, -0.35, -0.15); glScalef(0.15, 0.5, 0.15); ArrayCube(); glPopMatrix(); } void FrontLowerLeftLeg() { glPushMatrix(); glTranslatef(0.5, -0.75, -0.15); glRotatef(angle[1], 0.0, 0.0, 1.0); glScalef(0.15, 0.5, 0.15); ArrayCube(); glPopMatrix(); } void BackUpperRightLeg() { glPushMatrix(); glTranslatef(-0.5, -0.35, -0.15); glScalef(0.15, 0.5, 0.15); ArrayCube(); glPopMatrix(); } void BackLowerRightLeg() { glPushMatrix(); glTranslatef(-0.5, -0.75, -0.15); glRotatef(angle[1], 0.0, 0.0, 1.0); glScalef(0.15, 0.5, 0.15); ArrayCube(); glPopMatrix(); } void BackUpperLeftLeg() { glPushMatrix(); glTranslatef(-0.5, -0.35, 0.15); glScalef(0.15, 0.5, 0.15); ArrayCube(); glPopMatrix(); } void BackLowerLeftLeg() { glPushMatrix(); glTranslatef(-0.5, -0.75, 0.15); glRotatef(angle[1], 0.0, 0.0, 1.0); glScalef(0.15, 0.5, 0.15); ArrayCube(); glPopMatrix(); } void Tail() { glPushMatrix(); glTranslatef(-0.65, -0.25, 0); glScalef(0.05, 0.75, 0.05); ArrayCube(); glPopMatrix(); } void DrawGiraffe() { MainBody(); LowerNeck(); UpperNeck(); Head(); RightHorn(); LeftHorn(); FrontUpperRightLeg(); FrontLowerRightLeg(); FrontUpperLeftLeg(); FrontLowerLeftLeg(); BackUpperRightLeg(); BackLowerRightLeg(); BackUpperLeftLeg(); BackLowerLeftLeg(); Tail(); } void display() { glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); glMatrixMode(GL_MODELVIEW); glLoadIdentity(); gluLookAt(0.6, 0.6, 0.6, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0); DrawGiraffe(); glutSwapBuffers(); } void init() { glClearColor(0.0, 0.0, 0.0, 0.0); glEnable(GL_DEPTH_TEST); glEnable(GL_TEXTURE_2D); glEnable(GL_LIGHTING); glEnable(GL_LIGHT0); currentMaterial = &redPlasticMaterial; setMaterial(currentMaterial); glColor3f(1.0, 1.0, 1.0); glMatrixMode(GL_PROJECTION); glLoadIdentity(); glOrtho(-1.0, 1.0, -1.0, 1.0, -1.0, 2.5); GLfloat light_pos[] = {2.0,2.0,2.0, 1.0}; glLightfv(GL_LIGHT0, GL_POSITION, light_pos); } int main(int argc, char** argv) { angle[0] = 0; angle[1] = 360; angle[2] = 315; angle[3] = 0; GLubyte image[64][64][3]; int i, j, r, c; for(i = 0;i < 64; i++){ for(j = 0;j < 64; j++){ c = ((((i&0x8)== 0)^((j&0x8))==0))*255; image[i][j][0] = (GLubyte) c; image[i][j][1] = (GLubyte) c; image[i][j][2] = (GLubyte) c; } } glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, 64, 64, 0, GL_RGB, GL_UNSIGNED_BYTE, image); glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); glutInit(&argc, argv); glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB); glutInitWindowSize(500, 500); glutInitWindowPosition(0, 0); glutCreateWindow("Giraffe"); glutDisplayFunc(display); glutIdleFunc(rotate); init(); glutMainLoop(); }
问题分析与修复方案
1. OpenGL上下文初始化顺序错误
在main函数中,纹理创建代码(glTexImage2D、glTexParameterf)调用早于glutCreateWindow,此时OpenGL上下文尚未建立,所有纹理相关调用不会生效。
修复:将纹理生成代码移到init函数中,确保在OpenGL上下文创建后执行:
void init() { glClearColor(0.0, 0.0, 0.0, 0.0); glEnable(GL_DEPTH_TEST); glEnable(GL_TEXTURE_2D); glEnable(GL_LIGHTING); glEnable(GL_LIGHT0); // 添加纹理初始化代码 GLubyte image[64][64][3]; int i, j, c; for(i = 0;i < 64; i++){ for(j = 0;j < 64; j++){ c = ( ((i&0x8)==0) ^ ((j&0x8)==0) ) ? 255 : 0; image[i][j][0] = (GLubyte) c; image[i][j][1] = (GLubyte) c; image[i][j][2] = (GLubyte) c; } } glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, 64, 64, 0, GL_RGB, GL_UNSIGNED_BYTE, image); glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); // 设置纹理混合模式,让纹理与光照材质结合 glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); currentMaterial = &redPlasticMaterial; setMaterial(currentMaterial); glColor3f(1.0, 1.0, 1.0); glMatrixMode(GL_PROJECTION); glLoadIdentity(); glOrtho(-1.0, 1.0, -1.0, 1.0, -1.0, 2.5); GLfloat light_pos[] = {2.0,2.0,2.0, 1.0}; glLightfv(GL_LIGHT0, GL_POSITION, light_pos); }
2. 纹理与光照混合未启用
启用GL_LIGHTING后,默认纹理环境模式是GL_REPLACE,会完全覆盖材质颜色,但实际需要纹理与材质颜色混合显示,需设置为GL_MODULATE。
修复:在init中添加glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
3. 棋盘格生成逻辑错误
原代码中c = ((((i&0x8)== 0)^((j&0x8))==0))*255的括号位置错误,导致异或运算逻辑失效,生成的是单一颜色而非棋盘格。
修复:调整括号位置,正确计算棋盘格颜色:c = ( ((i&0x8)==0) ^ ((j&0x8)==0) ) ? 255 : 0;
4. 移除main中无效的纹理代码
将main函数中原有的纹理生成代码删除,避免无效调用。
修复后效果
模型表面会正确显示黑白棋盘格纹理,同时保留原有的光照材质效果。
内容的提问来源于stack exchange,提问作者Fenrir Gaming
相关产品推荐
相关产品推荐

