【问题标题】:Texture wont appear FreeGLUT纹理不会出现 FreeGLUT
【发布时间】:2020-08-20 20:28:30
【问题描述】:

我有一个简单的平原(正方形),上面有灯光和材质,我想在上面放一个地球纹理。但什么也没有出现。我检查过,认为它正确加载了 RGB 数据,所以我的猜测是这条线有问题(数据是 *char,图像是 BMP24)

glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, outWidth, outHeight, 0, GL_RGB, GL_UNSIGNED_BYTE, (GLvoid*)data);

这是一个 .bmp 加载函数:

GLuint LoadTexture(const char* imagepath) {
    printf("Reading image %s\n", imagepath);
    unsigned int outWidth = -1;
    unsigned int outHeight = -1;
    unsigned char header[54];
    unsigned int dataPos;
    unsigned int imageSize;

    FILE* file;
    if (errno_t err = fopen_s(&file, imagepath, "rb") != 0) {
        perror("Can't Open file");
        return 0;
    }

    // If less than 54 byes are read, problem
    if (fread(header, 1, 54, file) != 54) {
        printf("Not a correct BMP file\n");
        return NULL;
    }
    // A BMP files always begins with "BM"
    if (header[0] != 'B' || header[1] != 'M') {
        printf("Not a correct BMP file\n");
        return NULL;
    }
    // Make sure this is a 24bpp file
    if (*(int*)&(header[0x1E]) != 0) { printf("Not a correct BMP file\n");    return NULL; }
    if (*(int*)&(header[0x1C]) != 24) { printf("Not a correct BMP file\n");    return NULL; }

    // Read the information about the image
    dataPos = *(int*)&(header[0x0A]);
    outWidth = *(int*)&(header[0x12]);
    outHeight = *(int*)&(header[0x16]);
    imageSize = *(int*)&(header[0x22]);

    // Some BMP files are misformatted, guess missing information
    if (imageSize == 0)    imageSize = outWidth * outHeight * 3; // 3 : one byte for each Red, Green and Blue component
    if (dataPos == 0)      dataPos = 54; // The BMP header is done that way

    // Read the actual data from the file into the buffer
    unsigned char* data = new unsigned char[imageSize];
    fread(data, 3, imageSize, file);


    // Everything is in memory now, the file wan be closed
    fclose(file);

    GLuint tex;
    glGenTextures(1, &tex);
    glBindTexture(GL_TEXTURE_2D, tex);
    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, outWidth, outHeight, 0, GL_RGB, GL_UNSIGNED_BYTE, (GLvoid*)data);

    return tex;
}

这里是主要和显示功能:

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

    float ratio = 0.75;
    glEnable(GL_TEXTURE_2D);
    glBindTexture(GL_TEXTURE_2D, earthTextureData);

    glBegin(GL_QUADS);
    glVertex3f(-0.5, -0.5, 0);
    glVertex3f(-0.5, 0.5, 0);
    glVertex3f(0.5, 0.5, 0);
    glVertex3f(0.5, -0.5, 0);
    glEnd();

    glDisable(GL_TEXTURE_2D);

    glutSwapBuffers();
}


int main(int argc, char **argv)
{
    glutInit(&argc, argv);
    glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGBA);
    glutInitWindowPosition(100, 100);
    glutInitWindowSize(1200, 800);
    glutCreateWindow("app");

    init(); // custome initilizing
    initLighting();

    earthTextureData = LoadTexture("Texture/globe.bmp");

    glutDisplayFunc(render);
    glutReshapeFunc(reshape);
    glutMotionFunc(mouseMove);
    glutKeyboardFunc(keyboard);
    glutIdleFunc(idle);

    glutMainLoop();
}

我玩过代码,有时(当我使用 int 而不是 char* 时)我得到一个覆盖所有内容的红色材料,但不知道究竟是什么原因造成的

更新:必须更改几行才能使其正常工作(对于 bmp24 文件):

1-编辑这一行: fread(data, 1, imageSize, file);

2- 添加这一行: glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);

3- 编辑此行(使颜色正确显示): glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, outWidth, outHeight, 0, GL_BGR_EXT, GL_UNSIGNED_BYTE, (GLvoid*)data);

4-添加 UV 坐标(查找 glTexCoord)

【问题讨论】:

    标签: c++ opengl glut texture-mapping freeglut


    【解决方案1】:

    您错过了通过glTexParameter 设置纹理参数。

    如果您不生成mipmaps(由glGenerateMipmap),那么设置GL_TEXTURE_MIN_FILTER 很重要。由于默认过滤器为GL_NEAREST_MIPMAP_LINEAR,因此如果不将缩小功能更改为GL_NEARESTGL_LINEAR,纹理将是mipmap 不完整的。

    当图像加载到纹理对象时,GL_UNPACK_ALIGNMENT 必须设置为 1。
    默认情况下GL_UNPACK_ALIGNMENT 为 4,因此假定图像的每一行对齐到 4 个字节。 BMP 文件的像素一般都是 3 字节大小,并且是紧密打包的,这样会导致错位。

    GLuint tex;
    glGenTextures(1, &tex);
    glBindTexture(GL_TEXTURE_2D, tex);
    
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
    
    glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, outWidth, outHeight, 0, GL_RGB, GL_UNSIGNED_BYTE, (GLvoid*)data);
    glPixelStorei(GL_UNPACK_ALIGNMENT, 4);
    

    当然,在指定顶点坐标(glVertex)之前,您必须通过glTexCoord设置纹理参数,如另一个答案中所述:

    glBindTexture(GL_TEXTURE_2D, earthTextureData);
    
    glEnable(GL_TEXTURE_2D);
    glBegin(GL_QUADS);
    
    glTexCoord2f(0.0, 0.0);
    glVertex3f(-0.5, -0.5, 0);
    
    glTexCoord2f(0.0, 1.0);
    glVertex3f(-0.5, 0.5, 0);
    
    glTexCoord2f(1.0, 1.0);
    glVertex3f(0.5, 0.5, 0);
    
    glTexCoord2f(1.0, 0.0);
    glVertex3f(0.5, -0.5, 0);
    
    glEnd();
    glDisable(GL_TEXTURE_2D);
    

    【讨论】:

    • 嗨,非常感谢,它现在已修复,我需要添加 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);加上编辑 fread(data, 1, imageSize, file);并添加 glTexCoord2f。现在它的工作
    【解决方案2】:

    你必须告诉 OpenGL UV 坐标在哪里以及如何放置纹理。这可以在您的渲染函数中完成。

    UV 坐标范围为 0.0 - 1.0,并告诉 OpenGL 如何将纹理放置到渲染上。

    Here is a good picture that illustrates uv coordinates well

    这样的事情应该可以工作:

    void render(void) {
        glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
    
        float ratio = 0.75;
        glEnable(GL_TEXTURE_2D);
        glBindTexture(GL_TEXTURE_2D, earthTextureData);
    
        glBegin(GL_QUADS);
        glTexCoord3f(0.0, 0.0, 0.0);
        glVertex3f(-0.5, -0.5, 0);
    
        glTexCoord3f(0.0, 1.0, 0.0);
        glVertex3f(-0.5, 0.5, 0);
    
        glTexCoord3f(1.0, 1.0, 0.0);
        glVertex3f(0.5, 0.5, 0);
    
        glTexCoord3f(1.0, 0.0, 0);
        glVertex3f(0.5, -0.5, 0);
        glEnd();
    
        glDisable(GL_TEXTURE_2D);
    
        glutSwapBuffers();
    }
    

    【讨论】:

    • 你好,感谢重播,我试过了,好像没有太大变化,还是无法加载纹理。
    猜你喜欢
    • 1970-01-01
    • 2012-05-05
    • 2014-11-16
    • 1970-01-01
    • 1970-01-01
    • 2012-08-17
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多