纹理不出现在OpenGl中[已关闭]

wko9yo5t  于 2022-11-04  发布在  其他
关注(0)|答案(1)|浏览(132)

已关闭。此问题需要更多的focused。当前不接受答案。
**想要改进此问题吗?**更新问题,使其仅关注editing this post的一个问题。

5个月前关闭。
Improve this question
main Function

int main(int argc, char* argv[])
{
    _mesh1 = new Mesh("obj\\Earth_2K.obj", "obj\\Diffuse_2K_Earth.png");
    _mesh2 = new Mesh("obj\\Moon 2K.obj", "obj\\Diffuse_2K_Moon.png");
    glutInit(&argc, argv);
    glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB | GLUT_DEPTH);
    glutInitWindowSize(WIDTH, HEIGHT);
    glutCreateWindow("Univers Drawing");
    glutDisplayFunc(RenderScene);
    glutReshapeFunc(ChangeSize);
    glutIdleFunc(glIdle);
    SetupRC();
    glutMainLoop();

    return 0;
}

在main函数中声明的Mesh类对象。将对象和纹理文件交给此对象以读取顶点、纹理元素和面值。
Mesh class constructor

Mesh(char* obj, char* texture) {
        open(obj);
        loadTexture(texture, _textureIndex);
    }

在这段代码中,Open函数负责加载obj文件并创建一个mesh,到目前为止没有问题,但是之后的纹理出现了问题。
loadTexture Fuction

void Mesh::loadTexture(char* file, GLuint& texture_index) {
    glGenTextures(1, &texture_index);

    FILE* fp;
    fopen_s(&fp, file, "rb");
    if (!fp) {
        printf("ERROR : No %s.\n fail to bind %d\n", file, texture_index);
    }
    int width, height, channel;
    unsigned char *image = stbi_load_from_file(fp, &width, &height, &channel, 4);
    fclose(fp);

    glBindTexture(GL_TEXTURE_2D, texture_index);
    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, image);
    glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
    glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
    glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
    glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
    glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, GL_MODULATE);
}

这个函数负责设置纹理,texture_index是Mesh类头文件中声明的GLuint类型变量,stbi_load_from_file是stb_image库的使用,在我看来这里没有问题,因为一个一个打印obj没有问题。
RenderScene Function

void RenderScene(void)
{
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

    // World Transfrom

    glPushMatrix();
    glLoadIdentity();

    ///////////////////Drawing//////////////////////////////////////////////////////
    // Figure0 Draw
    glPushMatrix();
    glLoadIdentity();
    glColor3f(1.0f, 0.0f, 0.0f);
    glutSolidSphere(10, 15, 15);
    glPopMatrix();

    // Figure1 Draw 
    glPushMatrix();
    glLoadIdentity();
    glEnable(GL_LIGHTING);
    glEnable(GL_LIGHT0);
    glRotatef(0.0f, 0.0f, 1.0f, 0.0f);
    glRotatef(Sphere1_degree, 0.0f, 1.0f, 0.0f);
    glTranslatef(70.0f, 0.0f, 0.0f);        
    _mesh1->drawSolid(_smoothing);
    glPopMatrix();

    // Figure2 Draw 
    glPushMatrix();
    glLoadIdentity();
    glRotatef(-45.0f, 0.0f, 0.0f, 1.0f);
    glRotatef(Sphere2_degree, 0.0f, 1.0f, 0.0f);
    glTranslatef(60.0f, 0.0f, 0.0f);    
    _mesh2->drawSolid(_smoothing);
    glPopMatrix();
    ////////////////////////////////////////////////////////////////////////////////
    glPopMatrix();

    glutSwapBuffers();
}

这个函数是main函数中glutDisplayFunc(RenderScene);的内容。这个函数的代码代表了两个对象如何绕着一个中心圆旋转。这是我困惑的地方。
我想我应该做glBindTexture(GL_TEXTURE_2D, _mesh1->_textureIndex);,但我不知道用哪段代码做。
drawSolid Function

void Mesh::drawSolid(bool smoothing) {
    glPushMatrix();
    glEnable(GL_TEXTURE_2D);
    glBindTexture(GL_TEXTURE_2D, _textureIndex);
    glEnable(GL_LIGHTING);
    smoothing == true ? glEnable(GL_SMOOTH) : glEnable(GL_FLAT);
    for (auto f : _faces) {
        // get texture coord
        glBegin(GL_POLYGON);
        if(!smoothing)
            glNormal3f(f->_normal.x(), f->_normal.y(), f->_normal.z());
        _textureCoords[f->_texelPos[0]];
        for (int i = 0; i < 4; i++) {
            auto t = _textureCoords[f->_texelPos[i]];
            auto v = f->_vertices[i];
            glTexCoord2f((GLfloat)t->x(), (GLfloat)t->y());
            if (smoothing)
                glNormal3f(v->_normal.x(), v->_normal.y(), v->_normal.z());
            glVertex3f(v->x(), v->y(), v->z());
        }           
        glEnd();
    }
    glDisable(GL_LIGHTING);
    glDisable(GL_TEXTURE_2D);
    glPopMatrix();
}

在这个函数中,有一个叫做smoothing的变量,它只是一个决定如何进行平滑方法的角色。重要的是,我在这段代码中明确地进行了glBindTexture(GL_TEXTURE_2D, _textureIndex);,但是纹理并没有正常出现。
"我所得到的结果"

obj逐个打印以调试loadTexture函数。

ljsrvy3e

ljsrvy3e1#

在创建OpenGL上下文之前,您不能使用任何OpenGL指令。OpenGL上下文是用OpenGL窗口创建的。因此,在用glutCreateWindow创建窗口之后,需要调用_mesh1 = new Mesh(...)

int main(int argc, char* argv[])
{
    glutInit(&argc, argv);
    glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB | GLUT_DEPTH);
    glutInitWindowSize(WIDTH, HEIGHT);
    glutCreateWindow("Univers Drawing");

    _mesh1 = new Mesh("obj\\Earth_2K.obj", "obj\\Diffuse_2K_Earth.png");
    _mesh2 = new Mesh("obj\\Moon 2K.obj", "obj\\Diffuse_2K_Moon.png");

    // [...]
}

在绘制网格之前,必须在drawSolid方法中设置白色:

void Mesh::drawSolid(bool smoothing) {
    glColor3f(1.0f, 1.0f, 1.0f);  

    // [...]
}

说明:
激活纹理时,默认情况下纹理元素的颜色与当前颜色相乘,因为默认情况下纹理环境模式(GL_TEXTURE_ENV_MODE)为GL_MODULATE。请参见glTexEnv
这会导致纹理的纹理像素颜色与您通过glColor4f设置的最后一种颜色“混合”。
在渲染纹理之前设置“白色”颜色,以解决您的问题:

glColor3f(1.0f, 1.0f, 1.0f);

同样,您可以将环境模式改为GL_REPLACE

glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);

启用照明(GL_LIGHTING)后,将从材质参数(glMaterial)中获取关联的颜色。
如果仍要使用当前颜色属性(由glColor设置),则必须启用GL_COLOR_MATERIAL并设置颜色材质参数(glColorMaterial):

glEnable(GL_LIGHTING);
glEnable(GL_LIGHT0);
glEnable(GL_COLOR_MATERIAL);

相关问题