2010-12-07 10 views
4

Ich habe ein Problem beim Übergeben von Vertex-Attributen an das laufende Shader-Programm. Ich würde gerne zwei Attribute übergeben, die Position und eine RGBA-Farbe. Das Binden der Attributposition funktioniert für die Position. Es funktioniert jedoch nicht für die Farbe. Daher wird die gesamte Geometrie schließlich schwarz dargestellt. DieseGLSL 1.5 & OpenGL 3.3: Farbe an Vertex-Shader übergeben scheint zu scheitern

ist, was ich tue:

GLuint programHandler; 

// create program 
// compile & attach vertex shader 
// compile & attach fragment shader 

glBindAttribLocation(programHandler, 0, "InPosition"); 
glBindAttribLocation(programHandler, 1, "InColor"); 
glBindFragDataLocation(programHandler, 1, "FragColor"); 

glLinkProgram(programHandler); 
glUseProgram(programHandler); 

// initialize uniform variables 

// I'm trying to get the attribute locations now. 
// I expect location "0" for InPosition and location "1" for InColor. 
// In fact, it gets me a "-1" for InColor. I simply cannot see the reason for that behaviour 

GLint positionLocation = glGetAttribLocation(programHandler, "InPosition"); // returns 0 
GLint colorLocation = glGetAttribLocation(programHandler, "InColor"); // returns -1 

glEnableVertexAttribArray(positionLocation); 
glEnableVertexAttribArray(colorLocation); // fails! 

Mein Vertex-Shader ist sehr einfach. Alles, was ich wirklich tun Umwandlung Ecken und Führen des Farbshader an das Fragment:

#version 150 core 
precision highp float; 

// input 
in vec4 PassColor; 

// output 
out vec4 FragColor; 

void main(void) { 
    FragColor = PassColor; 
} 

Warum Bindung „InPosition“ Arbeit und „InColor“:

#version 150 core 

// input 
uniform mat4 ModelviewMatrix; 
uniform mat4 ProjectionMatrix; 
in vec3 InPosition; 
in vec4 InColor; 

// output 
out vec4 PassColor; 

void main(void) { 
    // passing color through to fragment shader 
    PassColor = InColor; 

    // transformation 
    gl_Position = ProjectionMatrix * ModelviewMatrix * vec4(InPosition, 1.0); 
} 

Mein Fragment-Shader einfach die Farbe zurückgeben soll nicht? Ich bin mir bewusst, dass der GLSL-Compiler den Shader-Code optimiert, so dass nicht verwendete Variablen nicht gebunden werden können. Aber ich sehe nicht, warum die Farbe hier draußen optimiert werden sollte. Schließlich benutze ich es, indem ich es an den Fragment-Shader übergebe.

+0

Irgendwelche 'glGetError()' 's da draußen? Was ist deine GPU und Treiberversion? – Kos

Antwort

1

Ein blinder Schuss, ich glaube, das ist falsch:

glBindFragDataLocation(programHandler, 0, "FragColor"); 
+0

Ich sehe. Was aber, wenn ich mehrere Renderziele rendern möchte? Ich rende derzeit auf eine Textur, die an ein Frame-Buffer-Objekt angehängt ist. Ursprünglich wollte ich mehr als nur diese eine Textur als Farbpuffer anfügen. Das ist der Grund für die "1" als zweites Argument. Ich glaube, dass gl_FragData [] Array veraltet ist. Wie würde ich es richtig binden und dies im Fragment-Shader deklarieren? – Walter

+0

Es ist korrekt, aber es wird auf das zweite Render-Ziel gerendert, wenn es eines gibt. Wenn es nicht zwei Renderziele gibt, würde es einen Fehler geben. –

+0

Also nehme ich an, ich würde COLOR_ATTACHMENT1 über FragColor [1] in meinem GLSL-Fragment-Shader adressieren. Ich denke, um das zu tun, müsste ich FragColor etwas wie folgt deklarieren: "out vec4 FragColor [8];" (Angenommen, es sind 8 Farbpuffer vorhanden). Ist das korrekt? Müsste ich auch jeden Fragendatenort wie "glBindFragDataLocation (programHandler, i," FragColor [i] ") binden;"? – Walter

0

das Fragment-Shader, um mehrere Farbebenen schreiben soll, dann muss ein Frame-Buffer sein If:

glBindFragDataLocation(programHandler, 1, "FragColor"); 

Es sollte erstellt, die mehrere Farbebenen angehängt hat, wo die Fragmente geschrieben werden können.

die Farbebenen entweder Puffer machen werden kann, kann

GLuint renderbuffer[2]; 
glGenRenderbuffers(2, &renderbuffer[0]); 
glBindRenderbuffer(GL_RENDERBUFFER, renderbuffer[0]); 
glRenderbufferStorage(GL_RENDERBUFFER, GL_RGBA8, width, height); 
glBindRenderbuffer(GL_RENDERBUFFER, renderbuffer[1]); 
glRenderbufferStorage(GL_RENDERBUFFER, GL_RGBA8, width, height); 

oder sie Texturen sein.

GLuint colorTexture[2]; 
glGenTextures(2, &colorTexture[0]); 
glBindTexture(GL_TEXTURE_2D, colorTexture[0]); 
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL); 
glBindTexture(GL_TEXTURE_2D, colorTexture[1]); 
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL); 

Die Texturen oder die Render-Puffer müssen an den Framebuffer angehängt werden.

render Puffer

GLuint frameBuffer; 
glGenFramebuffers(1, &frameBuffer); 
glBindFramebuffer(GL_FRAMEBUFFER, frameBuffer); 
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, renderbuffer[0]); 
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, renderbuffer[1]); 

Textures

GLuint frameBuffer; 
glGenFramebuffers(1, &frameBuffer); 
glBindFramebuffer(GL_FRAMEBUFFER, frameBuffer); 
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, colorTexture[0], 0); 
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT1, GL_TEXTURE_2D, colorTexture[1], 0); 

Hinweis, natürlich rendern Puffer und Texturen können gemischt werden, und kann auf verschiedene Farbebenen von ein und dem gleichen Rahmen angebracht werden, Puffer.
Wenn ein Tiefenpuffer oder sogar ein Schablonenpuffer benötigt wird, muss ein GL_DEPTH_ATTACHMENT, GL_STENCIL_ATTACHMENT oder GL_DEPTH_STENCIL_ATTACHMENT an den Framebuffer angehängt werden.

Wenn der farme Puffer mit glCheckFramebufferStatus ausgewertet werden kann erfolgreich abgeschlossen wurde:

if (glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE) 
{ 
    // error 
} 

Die maximale Anzahl von Farbpuffern, die an einen einzigen Rahmenpuffer befestigt werden kann, indem sie durch die OGL Funktion glGetIntegerv, bestimmt werden, mit dem Parameter GL_MAX_COLOR_ATTACHMENTS:

GLint maxColAttchemnts = 0; 
glGetIntegerv(GL_MAX_COLOR_ATTACHMENTS, &maxColAttchemnts); 

Nicht alle Farb Anhänge bei gleichzeitig aktiviert werden müssen. Ein Array von Puffern, in die Ausgaben der Fragment-Shader-Daten geschrieben werden, kann mit glDrawBuffers definiert werden.

GLenum drawBuffers[] = { GL_COLOR_ATTACHMENT1 }; 
glDrawBuffers(1, &drawBuffers[0]); 

im Fragment-Shader hat einen out Variablen für jede aktive Farb Befestigung deklariert werden.

out fragColor0; 
out fragColor1; 

void main() 
{ 
    .... 
    fragColor0 = ....; 
    .... 
    fragColor1 = ....; 
} 

Die Bindung eines out Variable auf den Index eines Farbbefestigungsrahmenpuffer explizit durch glBindFragDataLocation angegeben werden können. Dies muss geschehen, bevor das Shader-Programm verknüpft wird.

In modernen OpenGL-Puffer-Index, dass eine bestimmte Ausgabe schreibt, kann explizit von Layout-Standorten angegeben werden. Dies erlaubt den Verzicht auf die Verwendung von glBindFragDataLocation.

layout(location = 0) out fragColor0; 
layout(location = 1) out fragColor1; 
Verwandte Themen