2016-12-30 14 views
0

Я пытался отобразить FBO и отображать два FBO на экране, но не удалось выполнить глубинный тест при слиянии двух FBO. Я попытался объединить текстуры с вычислительным шейдером, но я не могу прочитать значения текстур глубины (все значения имеют значение 1, но проверка глубины работает при рендеринге FBO). Кто-нибудь знает, что я делаю неправильно, или знает другой метод, чтобы объединить два FBO?OpenGL: привязать текстуру глубины FBO к вычислительному шейдеру

Это, как я создаю FBO:

struct FBO { 
    uint color; 
    uint depth; 
    uint fbo; 
}; 
FBO createFBO(int width, int height) { 
    FBO fbo; 
    fbo.color = createFBOTexture(width, height, false); 
    fbo.depth = createFBOTexture(width, height, true); 
    fbo.fbo = generateFramebuffer(fbo.color, fbo.depth); 

    return fbo; 
} 
uint createFBOTexture(int width, int height, bool isDepthBuffer) { 
    uint texture; 
    glGenTextures(1, &texture); 
    glBindTexture(GL_TEXTURE_2D, texture); 

    if (isDepthBuffer) 
     glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT16, width, height, 0, GL_DEPTH_COMPONENT, GL_FLOAT, NULL); 
    else 
     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, width, height, 0, GL_RGBA, GL_FLOAT, NULL); 

    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); 
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_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); 

    int i = glGetError(); 
    if (i) 
    std::cout << "Error while creating the FBO: " << gluErrorString(i) << '\n'; 

    return texture; 
} 
uint generateFrameBuffer(uint color, uint depth) 
{ 
    int mipmapLevel = 0; 

    //Generate FBO 
    uint fbo; 
    glGenFramebuffers(1, &fbo); 
    glBindFramebuffer(GL_FRAMEBUFFER, fbo); 

    //Attatch textures to the FBO 
    glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, color, mipmapLevel); 
    glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, depth, mipmapLevel); 

    //Error check 
    int i = glCheckFramebufferStatus(GL_FRAMEBUFFER); 
    if (i != GL_FRAMEBUFFER_COMPLETE) 
     std::cout << "ERROR: frambuffer is not ok, status: " << i << '\n'; 
    else { 
     int i = glGetError(); 
     if (i) 
      std::cout << "Error while creating the FBO: " << gluErrorString(i) << '\n'; 
    } 
    glBindFramebuffer(GL_FRAMEBUFFER, 0); 

    return fbo; 
} 

Это, как я сделать к FBO:

glEnable(GL_DEPTH_TEST); 
glDepthMask(GL_TRUE); 

glBindFramebuffer(GL_FRAMEBUFFER, fbo_pointcloud.fbo); 
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); 
drawPointCloud(); //Here I draw points with the depreciated fixed pipeline 
glFlush(); 

Я попытался связать текстуры с glBindTexture (все значения чтения, где 1):

void MergeFrames::merge(TextureLoading::FBO tex0, TextureLoading::FBO tex1, GLuint result, int width, int height) 
{ 
    glUseProgram(shader); 

    //Bind depth textures 
    glActiveTexture(GL_TEXTURE0+0); 
    glBindTexture(GL_TEXTURE_2D, tex0.depth); 
    glActiveTexture(GL_TEXTURE0+1); 
    glBindTexture(GL_TEXTURE_2D, tex1.depth); 

    //Bind color textures 
    glBindImageTexture(2, tex0.color, 0, GL_FALSE, 0, GL_READ_ONLY, GL_RGBA8); 
    glBindImageTexture(3, tex1.color, 0, GL_FALSE, 0, GL_READ_ONLY, GL_RGBA8); 
    glBindImageTexture(4, result, 0, GL_FALSE, 0, GL_READ_WRITE, GL_RGBA8); 

    //Dispatch the shader 
    glDispatchCompute(ceilf(width/16.0f), ceilf(height/16.0f), 1); 
} 

электронн шейдер:

#version 430 

uniform sampler2D depthTex0; 
uniform sampler2D depthTex1; 
uniform layout(rgba8) readonly image2D colorTex0; 
uniform layout(rgba8) readonly image2D colorTex1; 
uniform layout(rgba8) writeonly image2D mergedColor; 

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

void main() { 
    ivec2 ID = ivec2(gl_GlobalInvocationID.xy); 
    ivec2 size = imageSize(colorTex0); 
    vec2 texCoords = vec2(float(ID.x)/float(size.x),float(ID.y)/float(size.y)); 

    float depths[2]; 
    vec4 colors[2]; 

    depths[0] = texture2D(depthTex0, texCoords).x; 
    depths[1] = texture2D(depthTex1, texCoords).x; 

    colors[0] = imageLoad(colorTex0, ID); 
    colors[1] = imageLoad(colorTex1, ID); 

    int i = int(depths[1] > depths[0]); 
    imageStore(mergedColor, ID, colors[i]); 
} 

Я попытался связать текстуры с glBindTexture (все значения чтения, где 0):

void MergeFrames::merge(TextureLoading::FBO tex0, TextureLoading::FBO tex1, GLuint result, int width, int height) 
{ 
    glUseProgram(shader); 

    glBindImageTexture(0, tex0.color, 0, GL_FALSE, 0, GL_READ_ONLY, GL_RGBA8); 
    glBindImageTexture(1, tex1.color, 0, GL_FALSE, 0, GL_READ_WRITE, GL_RGBA8); 
    glBindImageTexture(2, tex0.depth, 0, GL_FALSE, 0, GL_READ_ONLY, GL_R16); 
    glBindImageTexture(3, tex1.depth, 0, GL_FALSE, 0, GL_READ_ONLY, GL_R16); 
    glBindImageTexture(4, result, 0, GL_FALSE, 0, GL_READ_WRITE, GL_RGBA8); 

    glDispatchCompute(ceilf(width/16.0f), ceilf(height/16.0f), 1); 
} 

электронн шейдер:

#version 430 

uniform layout(rgba8) readonly image2D colorTex0; 
uniform layout(rgba8) readonly image2D colorTex1; 
uniform layout(r16) readonly image2D depthTex0; 
uniform layout(r16) readonly image2D depthTex1; 
uniform layout(rgba8) writeonly image2D mergedColor; 

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

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

    float depths[2]; 
    vec4 colors[2]; 

    colors[0] = imageLoad(colorTex0, ID); 
    depths[0] = imageLoad(depthTex0, ID).x; 

    colors[1] = imageLoad(colorTex1, ID); 
    depths[1] = imageLoad(depthTex1, ID).x; 

    int i = int(depths[1] < depths[0]); 
    imageStore(mergedColor, ID, colors[i]); 
} 

И это, как я связываю индексы (индексы отличаются в версии, где я использую sampler2D вместо image2D):

MergeFrames::MergeFrames() 
{ 
    shader = OpenGL::compileComputeShader("MergeFrames.comp"); 

    glUseProgram(shader); 

    glUniform1i(glGetUniformLocation(shader, "colorTex0"), 0); 
    glUniform1i(glGetUniformLocation(shader, "colorTex1"), 1); 
    glUniform1i(glGetUniformLocation(shader, "depthTex0"), 2); 
    glUniform1i(glGetUniformLocation(shader, "depthTex1"), 3); 
    glUniform1i(glGetUniformLocation(shader, "mergedColor"), 4); 
} 
+1

Вы вызываете 'createFBOBuffer', но публикуете код для' generateFramebuffer'. Ошибка? – ybungalobill

+0

Да, ошибка в моем посте. Я не знаю, как мне не удалось правильно скопировать код вставки. –

+1

Я не вижу код, где вы указываете шейдеру, какие индексы привязки должны использоваться для параметров сэмплера. Они будут принимать форму вызовов «glUniform1i». –

ответ

1

Я иду t код работает, копируя данные из текстуры глубины в текстуру с форматом GL_RED после рендеринга.