2016-11-30 9 views
0

Für die GUI für mein Spiel habe ich eine benutzerdefinierte Textur-Objekt, das die rgba Daten für eine Textur speichert. Jedes GUI-Element, das von meinem Spiel registriert wird, fügt die endgültige GUI-Textur hinzu und dann wird diese Textur nach der Nachbearbeitung auf den Framebuffer gelegt.rgba Arrays zu OpenGL Textur

Ich habe Probleme, mein Texture-Objekt in eine OpenGL-Textur zu konvertieren.

Zunächst erstelle ich einen 1D-int-Array, das 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; 
} 

geht Wo r, g, b und a sind gezackt int Arrays von 0 bis 255. Weiter ich den int-Puffer und die Textur erstellen.

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

Danach habe ich fügen Sie ein 50x50 rotes Quadrat in der oberen linken Ecke der Textur, und binden Sie die Textur auf den Framebuffer-Shader und die Vollbild-rect machen, dass meine Framebuffer anzeigt.

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

Und dann in meiner Fragment-Shader, versuche ich die Anzeige der GUI:

#version 330 

in vec2 Texcoord; 
out vec4 outColor; 

uniform sampler2D texFramebuffer; 
uniform sampler2D gui_texture; 

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

Aber es gibt ein schwarzes Fenster!

Ich habe ein rotes 50x50 Rechteck in die obere linke Ecke eingefügt und verifiziert, dass es existiert, aber aus irgendeinem Grund wird es nicht in der endgültigen Ausgabe angezeigt.

enter image description here

Das hat mir Grund gibt zu glauben, dass ich meine Textur nicht mit glTexImage2D richtig in eine OpenGL Textur konvertieren.

Können Sie etwas sehen, was ich falsch mache?

Update 1:

Here Ich sah sie eine ähnliche Sache tun ein Schwimmer Array, so habe ich versucht, meine 0-255 zu einem 0-1 float-Array konvertiert und es als die Bilddaten übergeben, wie so :

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

Und es funktioniert!

enter image description here

Ich werde die Frage offen, aber lassen, wie ich lernen will, warum der int Puffer wurde nicht :)

Antwort

3

Arbeits Wenn Sie GL_UNSIGNED_INT als Typ des „Host“ angegeben Daten erwartet OpenGL 32 Bits für jede Farbe zugeordnet. Da OpenGL die Ausgabefarben im Standard-Framebuffer nur dem Bereich [0.0f, 1.0f] zuordnet, werden die Eingabefarbwerte (zugeordnet im Bereich [0, 255]) alle durch die maximale Größe eines int (etwa 4,2 Milliarden) geteilt die endgültige Farbe auf dem Bildschirm angezeigt. Wenn Sie Ihren ursprünglichen Code verwenden, stellen Sie die "Clear" -Farbe des Bildschirms auf Weiß und sehen Sie, dass ein schwarzes Rechteck auf dem Bildschirm gezeichnet wird.

Sie haben zwei Möglichkeiten.Die erste besteht darin, die Farbwerte in den durch GL_UNSIGNED_INT angegebenen Bereich zu konvertieren, was bedeutet, dass sie für jeden Farbwert mit Math.pow((long)2, 24) multipliziert werden und darauf vertrauen, dass der Ganzzahlüberlauf der Multiplikation mit diesem Wert korrekt funktioniert (da Java keine Ganzzahl ohne Vorzeichen hat) Arten).

Die andere, weit sicherere Option, ist auf jeden 0-255 Wert in einem byte[] Objekt zu speichern (do nicht Verwendung char. char ist 1 Byte in C/C++/OpenGL, aber ist 2 Bytes in Java) und Geben Sie den Typ der Elemente als GL_UNSIGNED_BYTE an.

+1

Korrektur: der OpenGL-Typ heißt GL_UNSIGNED_BYTE, nicht GL_UNSIGNED_CHAR –

+0

@AntonReshetnikov Bearbeitet. – Xirema