2016-11-30 121 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