【问题标题】:Unable to render a texture on a quad无法在四边形上渲染纹理
【发布时间】:2015-08-30 08:04:43
【问题描述】:

我正在尝试使用 OpenGL 为图形编写一个 C++ 中的简单游戏。在我的游戏中,我有在屏幕上呈现为白色方块的对象。我希望能够将图像作为纹理绑定到这些对象,以便我可以在屏幕上渲染图像而不是白色方块。图片的格式没有限制,虽然我一直在使用.png或.bmp进行测试。

我的一个对象类 Character.h 存储了一个名为 _texture 的 GLuint* 成员变量和一个名为 _data 的无符号 char* 成员变量(分别作为图像句柄和像素数据)。 Character.h 中的这个函数旨在将图像作为纹理绑定到 Character 对象:

void loadTexture(const char* fileName)
    {
        /* read pixel data */
        FILE* file;
        file = fopen(fileName, "rb");
        if (file == NULL) {cout << "ERROR: Image file not found!" << endl;}
        _data = (unsigned char*)malloc(_dimension * _dimension * 3);
        fread(_data, _dimension * _dimension * 3, 1, file);
        fclose(file);
        /* bind texture */
        glGenTextures(1, &_texture); // _texture is a member variable of type GLuint
        glBindTexture(GL_TEXTURE_2D, _texture);
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
        glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, _dimension, _dimension, 0, GL_RGB, GL_UNSIGNED_BYTE, _data); // _dimension = 64.0f.
    }

一旦图像被绑定,我就会尝试使用这个函数(这是一个单独的类中的静态函数)渲染 Character 对象:

static void drawTexturedRectangle(float x, float y, float w, float h, GLuint texture, unsigned char* data)
    {
        /* fractions are calculated to determine the position onscreen that the object is drawn at */
        float xFraction = (x / GlobalConstants::SCREEN_WIDTH) * 2;
        float yFraction = (y / GlobalConstants::SCREEN_HEIGHT) * 2;
        float wFraction = (w / GlobalConstants::SCREEN_WIDTH) * 2;
        float hFraction = (h / GlobalConstants::SCREEN_HEIGHT) * 2;
        glEnable(GL_TEXTURE_2D);
        glClear(GL_COLOR_BUFFER_BIT);
        glBindTexture(GL_TEXTURE_2D, texture);
        glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, w, h, 0, GL_RGB, GL_UNSIGNED_BYTE, data);
        glPushMatrix();
        glEnable(GL_BLEND);
        glBegin(GL_QUADS);
        glTexCoord2f(0.0f, 0.0f); glVertex2f(xFraction, yFraction); // bottom left corner
        glTexCoord2f(0.0f, 1.0f); glVertex2f(xFraction, yFraction + hFraction); // top left corner
        glTexCoord2f(1.0f, 1.0f); glVertex2f(xFraction + wFraction, yFraction + hFraction); // top right corner
        glTexCoord2f(1.0f, 0.0f); glVertex2f(xFraction + wFraction, yFraction); // bottom right corner
        glEnd();
        glDisable(GL_BLEND);
        glPopMatrix();
    }

无论我如何处理这个问题,我似乎都无法让我的程序执行任何操作,只能渲染一个没有纹理的纯白色方块。我已检查以确保变量文件、_texture、_dimension 和 _data 都包含值。谁能发现我可能做错了什么?

【问题讨论】:

  • 我不认为这是您的问题的原因,但是您不应该在每次要绘制纹理时调用glTexImage2D - 在加载纹理时调用一次。之后,你可以丢弃客户端内存中的数据,因为你已经把它交给了OpenGL,它会管理它,你只需要再次绑定纹理告诉OpenGL你要使用它。
  • 我不知道你的其余代码,但在调用loadTexture() 函数之前,请尝试确保你有一个glEnable( GL_TEXTURE_2D ); 调用。

标签: c++ opengl textures texturing


【解决方案1】:

我认为您不能只将原始文件输入到 glTexImage2D,除非您以该格式存储纹理文件(您可能不这样做)。 glTexImage2D 需要一个巨大的数组字节(代表纹素颜色),但文件格式通常不存储这样的图像。甚至bmp里面也有一些头信息。

使用 DevIL 或 SOIL 等第 3 方图像加载器库来加载您的纹理!这些库可以将最常见的图像文件格式(png、jpg、tga、...)转换为可以输入到 OpenGL 的字节流!

附带说明: 调用 glTexImage2D(..., data) 后,数据的内容被复制到 GPU 内存 (VRAM) 中。从这一点开始,您只需使用它的 id 绑定纹理,因为它已经在 VRAM 中。在每一帧中调用 glTexImage2D() 会将每一帧中的整个纹理重新上传到 vram 中,从而导致很大的性能损失。

【讨论】:

  • 非常感谢 agnu17!我让它使用 SOIL 工作。 loadTexture 方法简单地变成: _texture = SOIL_load_OGL_texture(fileName, SOIL_LOAD_AUTO, SOIL_CREATE_NEW_ID, SOIL_FLAG_INVERT_Y);我读过这可能只适用于 8 位 .png,无论出于何种原因。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-01-03
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多