当前位置: 首页 > 知识库问答 >
问题:

纹理不会出现自由重叠

上官霄
2023-03-14

我有一个简单的平原(正方形),上面有灯光和材料,我想在上面放一个地球纹理。但是什么都没有出现。我检查过,认为它正确加载了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,(GLval*)data);

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

共有2个答案

邹胜泫
2023-03-14

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

UV坐标范围在0.0到1.0之间,告诉OpenGL如何将纹理放置到渲染器上。

这是一张很好的图片,很好地说明了uv坐标

像这样的方法应该有用:

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();
}
牛智志
2023-03-14

您没有通过glTexParameter设置纹理参数。

如果不生成mipmap(通过glGenerateMipmap),则设置GL_纹理_MIN_过滤器很重要。由于默认过滤器是GL_NEAREST\u MIPMAP\u 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);
 类似资料:
  • 我正在尝试使用类来构建小行星类型的翻拍,我在这里有一个制作飞船的类: } 但是当它使用我的主类绘制时,精灵上的纹理是正常绘制的,但是当我按下w向前移动时,它会将我移动到右边。当我旋转它的时候,好像我的船的顶部在一边,这怎么可能呢? 编辑:似乎只是旋转图像90度顺时针固定它,但不幸的是,它默认为该角度。

  • 我有一对着色器程序,如果我的DataTextures是正方形(1:1),那么一切都很好,但是如果其中一个或两个都是2:1(宽度:高度)的比例,那么行为就会变得混乱。我可以使用未使用的填充来扩展每个缓冲区,以确保它们始终是方形的,但从长远来看,这似乎是不必要的昂贵(内存方面的),因为两个缓冲区中的一个在启动时非常大。在这种情况下,有没有办法处理2:1的缓冲区? 我有两个着色器程序: 第一个是单个fr

  • 我正在尝试同时渲染背景和我的角色动画和我的角色工具。这件事看起来很琐碎,但我还是搞不懂。这里是我现在为我的呈现所提供的代码。 现在,当我运行以下代码时(将切换到底部): 这是结果 我就是找不到一个模式,总是一个凌驾于另一个之上。我会非常感激我的失落。谢谢!!

  • 我有一个OpenGL纹理,我想在运行中更改纹理中像素的RGBA值。我想在CPU端做修改。我想创建一个函数,将纹理中选定坐标中的像素更改为选定的RGBA值。 我尝试了以下方法: 其中,和是修改像素的坐标,是红色、绿色、蓝色和阿尔法的整数数组。但是,我不确定我是否使用了正确的参数,因为当我使用此参数时,纹理不会改变。我想创建一个函数,使用将指定坐标中纹理中的像素颜色更改为指定颜色。

  • 有人能给我解释一下,我如何在OpenGL中渲染多个不同纹理的物体吗? 我认为我接近最终结果,但目前我被困在这里,我不知道下一步需要做什么。真的需要一些帮助! 目前,这就是我所拥有的: > < li> drawSphere():根据经度和纬度的数量绘制UV球体 int numberOfVerices = 0; SetupGeometry():该方法用于绑定顶点和纹理坐标。 DrawSphere(30