2014-01-27 8 views
8

Ich versuche eine Tiefenstruktur in einen Compute Shader zu sampeln und in eine andere Textur zu kopieren.Sample Depth Buffer im OpenGL Compute Shader

Das Problem ist, dass ich richtige Werte nicht bekommen, wenn ich aus der Tiefen Textur lesen:

Ich habe versucht, wenn die Anfangswerte der Tiefen Textur zu überprüfen, korrekt waren (mit GDebugger), und sie sind. Es ist also die imageLoad GLSL-Funktion, die falsche Werte abruft.

das ist mein GLSL Compute Shader:

layout (binding=0, r32f) readonly uniform image2D depthBuffer; 
layout (binding=1, rgba8) writeonly uniform image2D colorBuffer; 

// we use 16 * 16 threads groups 
layout (local_size_x = 16, local_size_y = 16) in; 

void main() 
{ 
    ivec2  position = ivec2(gl_GlobalInvocationID.xy); 
    // Sampling from the depth texture 
    vec4  depthSample = imageLoad(depthBuffer, position); 
    // We linearize the depth value 
    float  f = 1000.0; 
    float  n = 0.1; 
    float  z = (2 * n)/(f + n - depthSample.r * (f - n)); 
    // even if i try to call memoryBarrier(), barrier() or memoryBarrierShared() here, i still have the same bug 
    // and finally, we try to create a grayscale image of the depth values 
    imageStore(colorBuffer, position, vec4(z, z, z, 1)); 
} 

und das ist, wie ich die Tiefe Textur bin zu schaffen und die Farbtextur:

// generate the deth texture 
glGenTextures(1, &_depthTexture); 
glBindTexture(GL_TEXTURE_2D, _depthTexture); 
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); 
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); 
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); 
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); 
glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT32F, wDimensions.x, wDimensions.y, 0, GL_DEPTH_COMPONENT, GL_FLOAT, NULL); 

// generate the color texture 
glGenTextures(1, &_colorTexture); 
glBindTexture(GL_TEXTURE_2D, _colorTexture); 
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); 
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); 
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); 
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); 
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, wDimensions.x, wDimensions.y, 0, GL_RGBA, GL_FLOAT, NULL); 

ich die Tiefe Textur mit Tiefenwerten füllen (Binde es an einen Bildspeicher und render die Szene) und dann rufe ich meinen compute Shader auf diese Weise:

mit:

  1. wDimensions = Größe des Kontextes (und der Framebuffer)
  2. WORK_GROUP_SIZE = 16

Sie haben keine Ahnung, warum ich gültige Tiefenwerte nicht bekommen?

EDIT:

Dies ist, was die Farbtextur aussieht, wenn ich eine Kugel machen:

IMG http://i41.tinypic.com/2rqll4l.png

und es scheint, dass glClear (GL_DEPTH_BUFFER_BIT) tut alles tun: Auch wenn ich rufe es juste vor dem glDispatchCompute() ich habe immer noch das selbe Bild ... Wie kann das möglich sein?

+1

Zum einen: 'GL_DEPTH_COMPONENT16' ist kein Floating-Point-Bildformat. Es ist ein Fixpunkt (z.B. 'GL_R16').Es gibt nur 1 Fließkomma-Tiefen-Bildformat (gut 2, wenn Sie gepackte Tiefe + Schablone zählen) und das ist 32-Bit: 'GL_DEPTH_COMPONENT32F' –

+0

Sie haben Recht, jetzt bekomme ich Werte, aber sie scheinen nicht gut. – Paul

+1

* Wie kann das möglich sein? * Viele wirklich seltsame Dinge passieren, wenn Sie keine Speicherbarrieren mit Compute-Shadern verwenden. Da sie auf Speicher in einer sehr allgemeinen Weise zugreifen, ist es für den GL schwierig, Vorgänge, die vor/nach dem Compute-Shader abgeschlossen werden müssen, ordnungsgemäß zu planen und zu synchronisieren. Die normale Grafikpipeline hat eine klare Definition davon, welche Operationen abhängig sind, etc. compute shaders brechen dies völlig, da sie keine tatsächliche Stufe in der Grafikpipeline sind, sondern völlig unabhängig. –

Antwort

7

Tatsächlich entdeckte ich, dass Sie eine Tiefe Textur als Bild zu einem Compute Shader senden können, nicht einmal mit dem Schlüsselwort readonly.

Also habe ich ersetzt:

glBindImageTexture(0, _depthTexture, 0, GL_FALSE, 0, GL_READ_ONLY, GL_R32F); 

von:

glActiveTexture(GL_TEXTURE0); 
glBindTexture(GL_TEXTURE_2D, _depthTexture); 

und in meinem Compute-Shader:

layout (binding=0, r32f) readonly uniform image2D depthBuffer; 

von:

layout (binding = 0) uniform sampler2D depthBuffer; 

und es zu probieren Ich schreibe gerade:

ivec2  position = ivec2(gl_GlobalInvocationID.xy); 
vec2  screenNormalized = vec2(position)/vec2(ctxSize); // ctxSize is the size of the depth and color textures 
vec4  depthSample = texture2D(depthBuffer, screenNormalized); 

und es funktioniert sehr gut, wie dieser

+0

Kannst du mir bitte sagen, wo du herausgefunden hast, dass du Tiefen Texturen nicht als image2D senden kannst? Ich bin in einer ähnlichen Situation, aber ich möchte die Tiefe Textur schreiben, so Sampler2D wird nicht für mich arbeiten. – Makx

+1

Ich habe auch dieses seltsame Verhalten bemerkt, um den depthbuffer nicht als image2D benutzen zu können. Aber ich kann keine offizielle Notiz finden, dass Sie es nicht sollten -.- – cguenther

Verwandte Themen