PDA

View Full Version : Bind FBO's depth texture to a compute shader



Goossen
12-30-2016, 07:59 AM
I've been trying to render to an FBO and render two FBO's to the screen, but have been unsuccessfull to do a depth test at the merge of the two FBO's. I've tried merging the textures with an compute shader, but I am unable to read the values of the depth textures(all values are value 1, but depth test is working when I render to the FBO). Does anybody knows what I am doing wrong, or knows an other method to merge two FBO's?

This is how I create the 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;
}
This is how I render to the 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();
I have tried to bind the textures with glBindTexture(all values read where 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]);
}
I have tried to bind the textures with glBindTexture(all values read where 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]);
}

GClements
12-30-2016, 10:05 AM
I have tried to bind the textures with glBindTexture(all values read where 1):

I don't see any glUniform() calls to associate the sampler2D and image2D variables with the corresponding texture units or image units.



I have tried to bind the textures with glBindTexture(all values read where 0):

You can't bind depth-format textures as images. And you can't use texture views to treat a depth-format texture as a colour-format texture. So if you want to access the data as an image, you'll have to copy it between textures via a PBO.

Goossen
12-30-2016, 12:55 PM
I don't see any glUniform() calls to associate the sampler2D and image2D variables with the corresponding texture units or image units.PBO.
I didn't include the constructor of the class MergeFrames, where I bind these indices and compile the shader, sorry.



You can't bind depth-format textures as images. And you can't use texture views to treat a depth-format texture as a colour-format texture. So if you want to access the data as an image, you'll have to copy it between textures via a PBO.
Thank you, I definitely will give that a try. When googling I found that depth textures could be used as images, but the only suggestion that I did find was to use glReadPixels and that write a copy back to the GPU, which is not a option because of performance reasons.

GClements
12-30-2016, 03:57 PM
the only suggestion that I did find was to use glReadPixels and that write a copy back to the GPU
If you use a PBO, the data won't need to leave video memory (which also means that glReadPixels can be enqueued rather than blocking).

Goossen
01-02-2017, 07:27 AM
Thank you, I got the code working.