【问题标题】:rgba arrays to OpenGL texturergba 数组到 OpenGL 纹理
【发布时间】:2016-11-30 17:22:42
【问题描述】:

对于我的游戏的 gui,我有一个自定义纹理对象,用于存储纹理的 rgba 数据。我的游戏注册的每个 GUI 元素都会添加到最终的 GUI 纹理中,然后在后处理后将该纹理覆盖到帧缓冲区上。

我在将纹理对象转换为 openGL 纹理时遇到问题。

首先我创建一个一维 int 数组,该数组为 rgbargbargba... etc.

public int[] toIntArray(){
    int[] colors = new int[(width*height)*4];

    int i = 0;
    for(int y = 0; y < height; ++y){
        for(int x = 0; x < width; ++x){

            colors[i] = r[x][y];
            colors[i+1] = g[x][y];
            colors[i+2] = b[x][y];
            colors[i+3] = a[x][y];

            i += 4;
        }
    }
    return colors;
}

其中rgba 是从 0 到 255 的锯齿状 int 数组。接下来我创建 int 缓冲区和纹理。

id = glGenTextures();

glBindTexture(GL_TEXTURE_2D, id);

glPixelStorei(GL_UNPACK_ALIGNMENT, 1);

glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);

IntBuffer iBuffer = BufferUtils.createIntBuffer(((width * height)*4));

int[] data = toIntArray();
iBuffer.put(data);
iBuffer.rewind();

glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_INT, iBuffer);

glBindTexture(GL_TEXTURE_2D, 0);

之后,我在纹理的左上角添加一个 50x50 的红色方块,并将纹理绑定到帧缓冲区着色器并渲染显示我的帧缓冲区的全屏矩形。

frameBuffer.unbind(window.getWidth(), window.getHeight());

postShaderProgram.bind();

glEnable(GL_TEXTURE_2D);
glActiveTexture(GL_TEXTURE1);
glBindTexture(GL_TEXTURE_2D, guiManager.texture()); // this gets the texture id that was created

postShaderProgram.setUniform("gui_texture", 1);

mesh.render();

postShaderProgram.unbind();

然后在我的片段着色器中,我尝试显示 GUI:

#version 330

in  vec2 Texcoord;
out vec4 outColor;

uniform sampler2D texFramebuffer;
uniform sampler2D gui_texture;

void main()
{
    outColor = texture(gui_texture, Texcoord);
}

但它输出的只是一个黑色窗口!

我在左上角添加了一个红色的 50x50 矩形并验证它存在,但由于某种原因它没有显示在最终输出中。

这让我有理由相信我没有正确地将我的纹理转换为带有 glTexImage2D 的 opengl 纹理。

你能看出我做错了什么吗?

更新 1:

Here我看到他们使用浮点数组做类似的事情,所以我尝试将我的 0-255 转换为 0-1 浮点数组并将其作为图像数据传递,如下所示:

public float[] toFloatArray(){
    float[] colors = new float[(width*height)*4];

    int i = 0;
    for(int y = 0; y < height; ++y){
        for(int x = 0; x < width; ++x){

            colors[i] = (( r[x][y] * 1.0f) / 255);
            colors[i+1] = (( g[x][y] * 1.0f) / 255);
            colors[i+2] = (( b[x][y] * 1.0f) / 255);
            colors[i+3] = (( a[x][y] * 1.0f) / 255);

            i += 4;
        }
    }
    return colors;
}

...

glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_FLOAT, toFloatArray());

而且它有效!

我将保留这个问题,因为我想了解为什么 int 缓冲区不起作用:)

【问题讨论】:

    标签: opengl textures lwjgl


    【解决方案1】:

    当您将GL_UNSIGNED_INT 指定为“主机”数据的类型时,OpenGL 期望为每种颜色分配 32 位。由于 OpenGL 仅将默认帧缓冲区中的输出颜色映射到[0.0f, 1.0f] 范围内,因此它将获取您的输入颜色值(映射在[0, 255] 范围内)并将所有这些值除以 int 的最大大小(约 4.2十亿)以获得屏幕上显示的最终颜色。作为一个练习,使用您的原始代码,将屏幕的“清晰”颜色设置为白色,然后查看屏幕上绘制的黑色矩形。

    你有两个选择。第一个是将颜色值转换为GL_UNSIGNED_INT指定的范围,这意味着对于每个颜色值,将它们乘以Math.pow((long)2, 24),并相信乘以该值的整数溢出将正确运行(因为Java没有' t 有无符号整数类型)。

    另一个更安全的选择是将每个 0-255 值存储在 byte[] 对象中(不要使用 charchar 在 C/C++ 中是 1 个字节/ OpenGL,但在 Java 中是 2 个字节)并将元素的类型指定为 GL_UNSIGNED_BYTE

    【讨论】:

    • 更正:OpenGL类型被称为GL_UNSIGNED_BYTE,而不是GL_UNSIGNED_CHAR
    • @AntonReshetnikov 已编辑。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2021-01-15
    • 2015-07-15
    • 1970-01-01
    • 2013-01-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多