繁体   English   中英

rgba数组到OpenGL纹理

[英]rgba arrays to OpenGL texture

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

我无法将我的Texture对象转换为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:

在这里,我看到他们使用浮点数组做类似的事情,所以我尝试将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缓冲区不起作用:)

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

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

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

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM