You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.22 23:51:24