2016-11-30 111 views
0

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

我无法将我的纹理对象转换为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; 
} 

rgb,并a是锯齿状INT阵列从0到255接着创建整型缓冲器和纹理。

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长方形,并验证它存在,但由于某种原因,它没有显示在最终输出中。

enter image description here

这给了我有理由相信,我不能正确地将我的纹理成一个OpenGL纹理glTexImage2D

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

更新1:

Here我看见他们用float数组做了类似的事情,所以我想我转换到0-255 0-1 float数组,并传递它作为像这样的图像数据:

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()); 

它的工作原理!

enter image description here

我要离开的问题开放然而,由于我想了解为什么INT缓冲区不能正常工作:)

回答

3

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

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

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

+1

更正:OpenGL类型被称为GL_UNSIGNED_BYTE,而不是GL_UNSIGNED_CHAR –

+0

@AntonReshetnikov编辑。 – Xirema