2016-09-04 1 views
1

Ich versuche derzeit, verzögerte Schattierung in OpenGL 3.2 zu implementieren und ein Problem, das ich einfach nicht lösen kann, egal was ich versuche.Deferred Shading OpenGL-Implementierung

Ich implementierte es in zwei Schritten (Geometriepass und Lichtdurchgang) wie man es erwarten würde. Nach dem Kompilieren und Ausführen zeigt der Bildschirm die Szene, die ich vorbereitet habe, fast so, wie man es erwarten würde. Die Farben der Objekte sind korrekt und sie sind auch dort positioniert, wo und wie ich sie haben wollte.

Die Sache ist, dass die Lichtberechnungen keinen Einfluss auf die Farbe haben, was auch immer. Nach vielen Stunden fand ich heraus, dass die Texturen für die Positionen und Normalen den gleichen Inhalt enthalten wie die Farbtextur.

Wenn man die letzte Zeile im Lichtfragment-Shader von fragColor = lightIntensity * color; zu oder fragColor = lightIntensity * pos; ändert, hat das keinerlei Auswirkungen auf die Darstellung des Bildschirms.

Ich habe viel versucht, um herauszufinden, was schief geht, aber ehrlich gesagt keine Ahnung, was es sein könnte.
Es wäre toll, wenn mir jemand helfen könnte.

meine Methode machen sieht wie folgt aus:

void render() 
{ 

    //geometry pass 
    gBuffer->bindForWriting(); 
    geometryShader->use(true); 
    calculateGBuffer(); 


    //lighting pass 
    gBuffer->bindForReading(lightShader->programID()); 
    lightShader->use(true); 
    drawOnScreen(); 

} 

Die Initialisierung des gBuffer Objekt ist wie folgt:

void GBuffer::initializeFBO(int viewWidth, int viewHeight) 
{ 

    //initialize fbo and corresponding textures; 
    glGenFramebuffers(1, &fbo_ID); 
    glBindFramebuffer(GL_FRAMEBUFFER, fbo_ID); 

    glGenTextures(1, &colorTexture_ID); 
    glBindTexture(GL_TEXTURE_2D, colorTexture_ID); 
    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, viewWidth, viewHeight, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL); 
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); 
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); 
    glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, colorTexture_ID, 0); 

    glGenTextures(1, &posTexture_ID); 
    glBindTexture(GL_TEXTURE_2D, posTexture_ID); 
    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB16F, viewWidth, viewHeight, 0, GL_RGB, GL_FLOAT, NULL); 
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); 
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); 
    glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT1, GL_TEXTURE_2D, posTexture_ID, 0); 

    glGenTextures(1, &normTexture_ID); 
    glBindTexture(GL_TEXTURE_2D, normTexture_ID); 
    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB16F, viewWidth, viewHeight, 0, GL_RGB, GL_FLOAT, NULL); 
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); 
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); 
    glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT2, GL_TEXTURE_2D, normTexture_ID, 0); 

    GLuint attachments[3] = { GL_COLOR_ATTACHMENT0, GL_COLOR_ATTACHMENT1, GL_COLOR_ATTACHMENT2 }; 
    glDrawBuffers(3, attachments); 

    glGenRenderbuffers(1, &depthBuffer_ID); 
    glBindRenderbuffer(GL_RENDERBUFFER, depthBuffer_ID); 
    glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT, viewWidth, viewHeight); 
    glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, depthBuffer_ID); 



    //Check Status 
    if(glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE) 
     qDebug() << "error while initializing framebuffer" << glCheckFramebufferStatus(GL_FRAMEBUFFER); 
    else{ 
     qDebug() << "framebuffer successfully created"; 
     initialized = true; 
    } 

    glBindFramebuffer(GL_FRAMEBUFFER, 0); 

} 

Die Methoden bindForReading und bindForWriting:

void GBuffer::bindForWriting() 
{ 
    glBindFramebuffer(GL_FRAMEBUFFER, fbo_ID); 
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); 
} 

void GBuffer::bindForReading(GLuint programID) 
{ 
    glBindFramebuffer(GL_FRAMEBUFFER, 0); 
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); 

    glActiveTexture(GL_TEXTURE0); 
    glBindTexture(GL_TEXTURE_2D, colorTexture_ID); 
    GLuint samplerTexture_ID = glGetUniformLocation(programID, "colorTexture"); 
    glUniform1i(samplerTexture_ID, 0); 

    glActiveTexture(GL_TEXTURE1); 
    glBindTexture(GL_TEXTURE_2D, posTexture_ID); 
    samplerTexture_ID = glGetUniformLocation(programID, "positionTexture"); 
    glUniform1i(samplerTexture_ID, 1); 

    glActiveTexture(GL_TEXTURE2); 
    glBindTexture(GL_TEXTURE_2D, normTexture_ID); 
    samplerTexture_ID = glGetUniformLocation(programID, "normTexture"); 
    glUniform1i(samplerTexture_ID, 2); 

} 

Und dauern die 4 Shader:

Geometrie Vertex Shader:

#version 150 
#extension GL_ARB_separate_shader_objects : enable 
uniform mat4 MVPMatrix; 
uniform mat4 modelMatrix; 

in vec4 in_position; 
in vec4 in_color; 
in vec2 in_texcoord; 
in vec3 in_norm; 

out vec4 color_varying; 
out vec3 frag_position; 
out vec3 norm_vec; 
out vec2 texcoord_varying; 

void main() 
{ 
    gl_Position = MVPMatrix * in_position; 
    vec4 worldPosition = (modelMatrix * in_position); 
    frag_position = worldPosition.xyz; 
    norm_vec = in_norm; 

    color_varying = in_color; 
    texcoord_varying = in_texcoord; 
} 

Geometrie Fragment Shader:

#version 150 
#extension GL_ARB_explicit_attrib_location : enable 

in vec4 color_varying; 
in vec3 frag_position; 
in vec3 norm_vec; 
in vec2 texcoord_varying; 

layout (location = 0) out vec4 fragColor; 
layout (location = 1) out vec3 fragPosition; 
layout (location = 2) out vec3 frag_norm_vec; 

uniform sampler2D myTexture; 

void main() 
{ 
    vec4 texel = texture(myTexture, texcoord_varying); 
    fragColor = texel * color_varying; 
    fragPosition = frag_position; 
    frag_norm_vec = normalize(norm_vec); 
} 

Lighting Vertexshader:

#version 150 
#extension GL_ARB_explicit_attrib_location : enable 
layout (location = 0) in vec2 in_position; 

out vec2 texCoord; 

void main() 
{ 
    gl_Position = vec4(in_position, 0, 1.0f); 

    texCoord = in_position; 
    if(texCoord.x == -1.0f) 
     texCoord.x = 0.0f; 
    if(texCoord.y == -1.0f) 
     texCoord.y = 0.0f; 
} 

Lighting Fragment Shader (ohne Berechnung Beleuchtung, um es kürzer)

#version 150 
#extension GL_ARB_separate_shader_objects : enable 

out vec4 fragColor; 
in vec2 texCoord; 


uniform sampler2D colorTexture; 
uniform sampler2D positionTexture; 
uniform sampler2D normTexture; 

void main() 
{ 
    //extract fragment data from fbo 
    vec3 pos = texture(positionTexture, texCoord).rgb; 
    vec3 norm = texture(normTexture, texCoord).rgb; 
    vec4 color = texture(colorTexture, texCoord); 


    fragColor = lightIntensity * color; 
} 

Sry für den Code-Spamming, aber ich kann den Fehler nicht eingrenzen.

+1

"* Geometry Vertex Shader: *" Sei vorsichtig, wenn du Begriffe wie "Geometrie" neben "Shader" wirfst. Weil wir dafür eine Shaderbühne haben und meine erste Lektüre dieses Namens hat mich glauben lassen, dass du das benutzt hast. –

+1

"* OpenGL 3.1 *" Warum verwenden deine Shader dann '#version 150'? Das ist aus GL 3.2. Das ist nicht dein Problem, aber du solltest dir darüber im Klaren sein, welche Version von OpenGL du verwendest. –

+0

Oh .. natürlich entwickle ich unter Version 3.2, ich habe das bearbeitet. – hey0

Antwort

1

Das Problem ist höchstwahrscheinlich in der Reihenfolge der Operationen hier:

gBuffer->bindForReading(lightShader->programID()); 
lightShader->use(true); 

wo in bindForReading(), Sie Anrufe wie diese hier:

samplerTexture_ID = glGetUniformLocation(programID, "positionTexture"); 
glUniform1i(samplerTexture_ID, 1); 

Die glUniform*() Anrufe setzen einheitliche Werte auf die derzeit aktiv Programm.Da Sie die lightShader aktiv nach machen Sie diese Aufrufe vornehmen, werden die einheitlichen Werte auf dem zuvor aktiven Programm festgelegt, das wahrscheinlich nicht einmal diese Uniformen hat.

einfach eine Änderung der Reihenfolge dieser Anrufe könnte dies bereits fix:

lightShader->use(true); 
gBuffer->bindForReading(lightShader->programID()); 

Auch sind Sie GL_RGB16F als das Format von zwei Ihrer Puffer verwenden. Die OpenGL-Implementierung, die Sie verwenden, unterstützt dies möglicherweise, aber dies ist kein Format, das in der Spezifikation farbrenderbar sein muss. Wenn Sie möchten, dass Ihr Code plattformübergreifend funktioniert, sollten Sie GL_RGBA16F verwenden, das garantiert farbwiedergabefähig ist.