2014-01-27 3 views
8

Я пытаюсь пробовать текстуру глубины в вычислительный шейдер и копировать ее в другую текстуру.Пример буфера глубины в вычисляющем шейдере OpenGL

Проблема заключается в том, что я не получаю правильные значения, когда я прочитал из глубины текстуры:

Я попытался проверить, если начальные значения глубины текстуры были правильными (с GDebugger), и они. Таким образом, функция imageLoad GLSL извлекает неправильные значения.

это мой 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)); 
} 

и это, как я создаю текстуру глубины и цвет текстуры:

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

Я заполнит глубину текстуры со значениями глубины (связать его с буфером кадров и визуализировать сцену), а затем я вызываю свой вычислительный шейдер следующим образом:

_computeShader.use(); 

// try to synchronize with the previous pass 
glMemoryBarrier(GL_ALL_BARRIER_BITS); 
// even if i call glFinish() here, the result is the same 

glBindImageTexture(0, _depthTexture, 0, GL_FALSE, 0, GL_READ_ONLY, GL_R32F); 
glBindImageTexture(1, _colorTexture, 0, GL_FALSE, 0, GL_WRITE_ONLY, GL_RGBA8); 

glDispatchCompute((wDimensions.x + WORK_GROUP_SIZE - 1)/WORK_GROUP_SIZE, 
        (wDimensions.y + WORK_GROUP_SIZE - 1)/WORK_GROUP_SIZE, 1); // we divide the compute into groups of 16 threads 

// try to synchronize with the next pass 
glMemoryBarrier(GL_ALL_BARRIER_BITS); 

с:

  1. wDimensions = размером контекста (и из фреймбуфера)
  2. WORK_GROUP_SIZE = 16

У вас есть представление о том, почему я не получаю правильные значения глубины?

EDIT:

Это то, что цвет текстуры выглядит, когда я вынести сферу:

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

и кажется, что glClear (GL_DEPTH_BUFFER_BIT) не делает ничего: Даже если я называю это juste перед glDispatchCompute() у меня все еще есть одно и то же изображение ... Как это возможно?

+1

С одной стороны: 'GL_DEPTH_COMPONENT16' не формат изображения с плавающей точкой. Это фиксированная точка (например, «GL_R16').Существует только 1 формат изображения с плавающей запятой (ну, если вы считаете, что упакованная глубина + трафарет), и это 32-бит: 'GL_DEPTH_COMPONENT32F' –

+0

Вы правы, теперь я получаю значения, но они кажутся не очень хорошими. – Paul

+1

* Как это возможно? * Много странных вещей случается, если вы не используете барьеры памяти с вычислительными шейдерами. Поскольку они получают доступ к памяти в очень общем режиме, GL трудно правильно планировать и синхронизировать операции, которые необходимо выполнить до/после вычислительного шейдера. Обычный графический конвейер имеет четкое определение того, какие операции зависят, и т. Д. Вычислительные шейдеры полностью нарушают это, поскольку они не являются фактическим этапом в графическом конвейере, но полностью независимы. –

ответ

7

Фактически, я обнаружил, что вы не можете отправить текстуру глубины в качестве изображения в вычислительный шейдер, даже с ключевым словом readonly.

Так я заменил:

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

по:

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

и в моем Compute Shader:

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

по:

layout (binding = 0) uniform sampler2D depthBuffer; 

и попробовать его я просто написать:

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

и она работает очень хорошо, как этот

+0

Не могли бы вы рассказать мне, где вы обнаружили, что вы не можете отправлять текстуры глубины как image2D? Я в аналогичной ситуации, но я хочу НАПРАВЛЯТЬ текстуру глубины, поэтому sampler2D не будет работать для меня. – Makx

+1

Я заметил, что это странное поведение не позволяет использовать глубину буфера как image2D. Но я не могу найти официальную заметку о том, что вы не должны это делать. – cguenther

Смежные вопросы