OpenGL Framebuffer ColorAttachment для вычисления шейдера - PullRequest
0 голосов
/ 30 июня 2018

Я хочу поместить Color Attachment моего пользовательского кадрового буфера в вычислительный шейдер для простой обработки изображений, но у меня только черный экран. Вот мой пример кода

Создание цветового вложения

glGenFramebuffers(1, &this->fbo);
glBindFramebuffer(GL_FRAMEBUFFER, this->fbo);
glGenTextures(1, &this->textureColorBuffer);
glBindTexture(GL_TEXTURE_2D, this->textureColorBuffer);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA32F, this->width(), this->height(), 0, 
GL_RGB, GL_UNSIGNED_BYTE, NULL);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, 
this->textureColorBuffer, 0);

Компиляция и связывание шейдера

cshader = glCreateShader(GL_COMPUTE_SHADER);
const char *csSrc[] = {
    "#version 440\n",
    "layout (binding = 0, rgba32f) uniform image2D destTex;\
     layout (binding = 1, rgba32f) uniform image2D sourceTex;\
     layout (local_size_x = 16, local_size_y = 16, local_size_z = 1) in;\
     void main() {\              
            vec4 texel;\
            ivec2 storePos = ivec2(gl_GlobalInvocationID.xy);\
            texel = imageLoad(sourceTex, storePos);\
            texel = vec4(1.0) - texel;\
            imageStore(destTex, storePos, texel);\
    }"
};
glShaderSource(cshader, 2, csSrc, NULL);
glCompileShader(cshader);


cshaderprogram = glCreateProgram();
glAttachShader(cshaderprogram, cshader);
glLinkProgram(cshaderprogram);

Вызов шейдера и рисование текстуры в квад. Шейдер - простой шейдер с переключением цвета, для тестирования.

glUseProgram(cshaderprogram);
glUniform1i(0, 0);
glActiveTexture(GL_TEXTURE0);
glBindImageTexture(0, outputTexture, 0, GL_FALSE, 0, GL_WRITE_ONLY, 
GL_RGBA32F);


glActiveTexture(GL_TEXTURE1);
glBindImageTexture(0, textureColorBuffer, 0, GL_FALSE, 0, GL_READ_ONLY, 
GL_RGBA32F);
glUniform1i(1, 1);
glDispatchCompute(width() / 16, height() / 16, 1);

glMemoryBarrier(GL_SHADER_STORAGE_BARRIER_BIT);
screenProgram.bind();
glBindFramebuffer(GL_FRAMEBUFFER, 0);
glBindVertexArray(screenVao);
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, outputTexture);
glDrawArrays(GL_TRIANGLES, 0, 6);

Я могу правильно отобразить textureColorBuffer для четырехугольника и записать текстуру. Я думаю, что проблема, которую я не знаю, как читать из кадрового буфера.

Надеюсь, вы мне поможете. Если есть еще вопросы, просто задавайте.

1 Ответ

0 голосов
/ 30 июня 2018

Точка привязки sourceTex равна 1, а не 0:

layout (binding = 1, rgba32f) uniform image2D sourceTex;

Таким образом, вы должны привязать текстуру к блоку изображения 1

glBindImageTexture( 1, // <------- 1 instead of 0
    textureColorBuffer, 0, GL_FALSE, 0, GL_READ_ONLY, GL_RGBA32F); 

Примечание, Единицы изображения и Единицы текстуры - это разные вещи.


Конечно, вы также можете использовать форму сэмплера текстуры в шейдере coumpute. Если destTex и sourceTex имеют одинаковый размер, вы можете использовать texelFetch с gl_GlobalInvocationID для поиска sourceTex:

layout (local_size_x = 16, local_size_y = 16, local_size_z = 1) in;

layout (binding = 0, rgba32f) uniform image2D destTex;
layout (binding = 0) uniform sampler2D sourceTex; 

void main()
{       
    ivec2 pos = ivec2(gl_GlobalInvocationID.xy);       

    vec4 texel = texelFetch(sourceTex, pos, 0);

    texel = vec4(1.0) - texel;
    imageStore(destTex, pos, texel);
}

В приведенном выше фрагменте используется блок изображения 0 для destTex и блок текстуры 0 для sourceTex.


Кстати, вы уверены, что хотите сделать

texel = vec4(1.0) - texel;

Обратите внимание, что если альфа-канал texel равен 1,0, он станет полностью прозрачным.

...