Retrieving float values from framebuffer depth map - c++

I have rendered a depth map to a framebuffer in the following way:
// the framebuffer
glGenFramebuffers(1, &depthMapFBO);
// completion: attacching a texture
glGenTextures(1, &depthMap);
glBindTexture(GL_TEXTURE_2D, depthMap);
glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT32F, SCR_WIDTH, SCR_HEIGHT, 0, GL_DEPTH_COMPONENT, GL_FLOAT, NULL); // i.e. allocate memory, to be filled later at rendering
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_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
// bind framebuffer and attach depth texture
glBindFramebuffer(GL_FRAMEBUFFER, depthMapFBO);
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, depthMap, 0);
glDrawBuffer(GL_NONE); // i.e. explicitly tell we want no color data
glReadBuffer(GL_NONE); // i.e. explicitly tell we want no color data
glBindFramebuffer(GL_FRAMEBUFFER, 0);
Note the use of GL_DEPTH_COMPONENT32F because I want a high precision.
Now I want to put the values stored in the depth buffer of the framebuffer into an array, preserving the precision. How to do so? Here is what I had in mind:
glBindFramebuffer(GL_FRAMEBUFFER, depthMapFBO);
glClear(GL_DEPTH_BUFFER_BIT);
[ render the scene to framebuffer]
GLfloat * d= new GLfloat[conf::SCR_WIDTH * conf::SCR_HEIGHT];
glReadPixels(0, 0, conf::SCR_WIDTH, conf::SCR_HEIGHT, GL_DEPTH_COMPONENT, GL_FLOAT, d);
for (int i{ 0 }; i < conf::SCR_HEIGHT; ++i) {
for (int j{ 0 }; j < SCR_WIDTH; ++j) {
std::cout << d[i * SCR_WIDTH + j] << " ";
}
std::cout << std::endl;
}
However, this always prints 0.956376. Why so? I know I still have to re-linearize the depths... but why is always printed a constant value, and how can I fix this? Furthermore, is my approach correct, with regards to the lossless retrieval of information? Thanks in advance.
The same thing happens with:
GLfloat * d= new GLfloat[conf::SCR_WIDTH * conf::SCR_HEIGHT * 4];
glBindTexture(GL_TEXTURE_2D, depthMap);
glGetTexImage(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT, GL_FLOAT, d);

Related

Changing internal format causes texture to have incorrect parameters

I set up framebuffer texture on which to draw a scene on as follows:
glGenFramebuffers(1, &renderFBO);
glGenTextures(1, &renderTexture);
glBindTexture(GL_TEXTURE_2D, renderTexture);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA32F, W_WIDTH, W_HEIGHT, 0, GL_RGBA, GL_FLOAT, NULL);
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_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
int width, height;
glGetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_WIDTH, &width);
glGetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_HEIGHT, &height);
cout << "width: " << width << " height: " << height << endl;
glBindFramebuffer(GL_FRAMEBUFFER, renderFBO);
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, renderTexture, 0);
glBindFramebuffer(GL_FRAMEBUFFER, 0);
By validating width and height, they do indeed have the correct dimensions, 1024, 768.
Now I am trying to set up a second texture, to be used as a counter, meaning I am trying to count the occurences of every color value, by incrementing the appropriate texel in the texture. Since I am trying to count the colors, I use a 2D texture of size 256 x 3. In each cell I want a single unsigned integer, showing the number of times a specific color value has appeared up until that point. For instance, if the color (255,5,3) was encountered, I would to increment the numbers inside tex[255][0], tex[5][0], tex[3][0]
num_bins = 256;
GLuint* hist_data = new GLuint[num_bins * color_components]();
glGenTextures(1, &tex_output);
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, tex_output);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexImage2D(GL_TEXTURE_2D, 0, GL_R32UI, 256, 3, 0, GL_RED, GL_UNSIGNED_INT, hist_data);
glBindImageTexture(0, tex_output, 0, GL_FALSE, 0, GL_READ_WRITE, GL_R32UI);
int width, height;
glGetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_WIDTH, &width);
glGetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_HEIGHT, &height);
cout << "width: " << width << " height: " << height << endl;
I used the sized and base internal format correspondence shown in the opengl specification. However when this code executes the output values are width=0, height=0. The input data doesn't seem to be the issue, because I tried providing NULL as the last argument and it still didn't work. What am I missing here?
EDIT:
Incrementation of the values in the texture is supposed to happen inside the following compute shader:
#version 450
layout(local_size_x = 1, local_size_y = 1) in;
layout(rgba32f, binding = 0) uniform image2D img_input;
layout(r32ui, binding = 1) uniform uimage2D img_output;
void main() {
// grabbing pixel value from input image
vec4 pixel_color = imageLoad(img_input, ivec2(gl_GlobalInvocationID.xy));
vec3 rgb = round(pixel_color.rgb * 255);
ivec2 r = ivec2(rgb.r, 0);
ivec2 g = ivec2(rgb.g, 1);
ivec2 b = ivec2(rgb.b, 2);
uint inc = 1;
imageAtomicAdd(img_output, r, inc);
imageAtomicAdd(img_output, g, inc);
imageAtomicAdd(img_output, b, inc);
}
You get a GL_INVALID_OPERATION error, because the texture format argument doesn't correspond with the internal format of the texture. For an unsigned integral format you have to use GL_RED_INTEGER instead of GL_RED (see glTexImage2D):
glTexImage2D(GL_TEXTURE_2D, 0, GL_R32UI, 256, 3, 0, GL_RED, GL_UNSIGNED_INT, hist_data);
glTexImage2D(GL_TEXTURE_2D, 0, GL_R32UI, 256, 3, 0, GL_RED_INTEGER, GL_UNSIGNED_INT, hist_data);
I recommend using Debug Output, it saves a lot of time and lets you find such errors quickly.

OpenGL Clear multiple 3D texture

I have 4 3D textures and I am writing on them using imageStore in a single call, everything works fine. The only problem is how I clear them in each frame. This is how I create them
for (int i = 0; i < MIPLEVELS; ++i){
glGenTextures(1, &volumeTexture[i]);
glBindTexture(GL_TEXTURE_3D, volumeTexture[i]);
glTexImage3D(GL_TEXTURE_3D, 0, GL_RGBA8, volumeDimensions / (1 << i), volumeDimensions / (1 << i), volumeDimensions / (1 << i), 0, GL_RGBA, GL_UNSIGNED_BYTE, 0);
glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_BORDER);
glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_BORDER);
glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_BORDER);
glBindTexture(GL_TEXTURE_3D, 0);
glGenFramebuffers(1, &volumeFbo[i]);
glBindFramebuffer(GL_FRAMEBUFFER, volumeFbo[i]);
glFramebufferTexture(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, volumeTexture[i], 0);
glBindFramebuffer(GL_FRAMEBUFFER, 0);
}
for (int i = 0; i < MIPLEVELS; ++i){
glBindFramebuffer(GL_FRAMEBUFFER, volumeFbo[i]);
glClearColor(0, 0, 0, 0);
glClear(GL_COLOR_BUFFER_BIT);
}
and this is what I do to clear them each frame
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
for (int i = 0; i < MIPLEVELS; ++i){
glBindFramebuffer(GL_FRAMEBUFFER, volumeFbo[i]);
glClearColor(0, 0, 0, 0);
glClear(GL_COLOR_BUFFER_BIT);
}
glBindFramebuffer(GL_FRAMEBUFFER, 0);
As you can see I am using 4 different FBOs which is a big waste. I tried using 4 targets but they don't get cleared. I did it this way:
I binded a single FBO and created 4 targets using glFrameBufferTexture3D and then each frame I called
glBindFramebuffer(GL_FRAMEBUFFER, volumeFbo[0]);
GLenum buffers[] = { GL_COLOR_ATTACHMENT0, GL_COLOR_ATTACHMENT1, GL_COLOR_ATTACHMENT2, GL_COLOR_ATTACHMENT3 };
glDrawBuffers(4, buffers);
glClearColor(0, 0, 0, 0);
glClear(GL_COLOR_BUFFER_BIT);
But nothing happened.
I believe there are two ways of solving this issue.
You either do a loop where you attach each texture as GL_COLOR_ATTACHMENT0 and clear each texture.
Otherwise, you can also use the glClearBuffer family of textures:
https://www.opengl.org/sdk/docs/man3/xhtml/glClearBuffer.xml

I'm rendering to texture,but renderbuffer is black

I'm trying to render to texture.Using opengl-es 2.0.I wanna make Black and white postprocessing.But all I see, is black texture.On scene I have lightsources, and two spheres.But when I'm trying to render my texture that attached to framebuffer, I see black square.
this->frameBuffersCount = 3;
this->frameBuffers = new int[frameBuffersCount];
glGenFramebuffers(frameBuffersCount, (GLuint*)this->frameBuffers);
this->texturesCount = this->frameBuffersCount * 2;
this->bufferTextures = new int[this->texturesCount];
glGenTextures(this->texturesCount, (GLuint*)this->bufferTextures);
for(int i = 0; i < this->texturesCount / 2; ++i)
{
glBindTexture(GL_TEXTURE_2D, this->bufferTextures[2*i]);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, screenWidth, screenHeight, 0, GL_RGB, GL_UNSIGNED_BYTE, 0);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glBindTexture(GL_TEXTURE_2D,0);
glBindTexture(GL_TEXTURE_2D, this->bufferTextures[2*i + 1]);
glTexImage2D(GL_TEXTURE_2D, 0,GL_DEPTH_COMPONENT, screenWidth, screenHeight, 0, GL_DEPTH_COMPONENT, GL_UNSIGNED_INT, 0);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glBindTexture(GL_TEXTURE_2D,0);
}
for(int i = 0; i < this->frameBuffersCount; ++i)
{
glBindFramebuffer(GL_FRAMEBUFFER, this->frameBuffers[i]);
glFramebufferTexture2D(GL_FRAMEBUFFER,
GL_COLOR_ATTACHMENT0,
GL_TEXTURE_2D,
this->bufferTextures[2*i],
0);
glFramebufferTexture2D(GL_FRAMEBUFFER,
GL_DEPTH_ATTACHMENT,
GL_TEXTURE_2D,
this->bufferTextures[2*i + 1],
0);
glBindFramebuffer(GL_FRAMEBUFFER, 0);
}
this->ordinaryQuad = new ModelVertex[4];
this->ordinaryQuad[0].UV = Vector2(0.0,0.0);
this->ordinaryQuad[0].position = Vector3(-1, -1, 0.0);
this->ordinaryQuad[1].UV = Vector2(0.0,1.0);
this->ordinaryQuad[1].position = Vector3(-1.0, 1.0, 0.0);
this->ordinaryQuad[2].UV = Vector2(1.0,1.0);
this->ordinaryQuad[2].position = Vector3(1.0, 1.0, 0.0);
this->ordinaryQuad[3].UV = Vector2(1.0,0.0);
this->ordinaryQuad[3].position = Vector3(1.0, -1.0, 0.0);
This is rendering code.
void EffectManager::applyBnW()
{
glBindFramebuffer(GL_FRAMEBUFFER, this->frameBuffers[0]);
auto res = glCheckFramebufferStatus(GL_FRAMEBUFFER);
if(res == GL_FRAMEBUFFER_COMPLETE)
{
SceneManager::GetInstance().DrawScene();
glDisable(GL_DEPTH_TEST);
unsigned short indices[6] = {0,2,1,2,0,3};
Shaders shaders;
shaders.Init("../Resources/Shaders/BlackAndWhiteVS.vs", "../Resources/Shaders/BlackAndWhiteFS.fs", 0);
glUseProgram(shaders.program);
unsigned int hVBuff,hInBuff;
glGenBuffers(1, &hVBuff);
glGenBuffers(1, &hInBuff);
glBindBuffer(GL_ARRAY_BUFFER, hVBuff);
glBufferData(GL_ARRAY_BUFFER, 4 * sizeof(SEngine::ModelVertex), this->ordinaryQuad, GL_STATIC_DRAW);
//glBindBuffer(GL_ARRAY_BUFFER, 0);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, hInBuff);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, 6 * sizeof(unsigned short), indices, GL_STATIC_DRAW);
//glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, this->bufferTextures[0]);
glGenerateMipmap(GL_TEXTURE_2D);
if(shaders.positionAttribute != -1)
{
glEnableVertexAttribArray(shaders.positionAttribute);
glVertexAttribPointer(shaders.positionAttribute, 3, GL_FLOAT, GL_FALSE, sizeof(SEngine::ModelVertex), 0);
}
if(shaders.UVAttribute != -1)
{
glEnableVertexAttribArray(shaders.UVAttribute);
glVertexAttribPointer(shaders.UVAttribute, 2, GL_FLOAT, GL_FALSE, sizeof(SEngine::ModelVertex), (void*)(sizeof(Vector3)));
}
if(shaders.samplerUniform != -1)
{
glUniform1i(shaders.samplerUniform, 0);
}
glBindFramebuffer(GL_FRAMEBUFFER, 0);
glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_SHORT, (void*)0);
//glDrawArrays(GL_TRIANGLES,0,4);
}
What is wrong?
Not a clear answer can be given since there is not enough information/code provided in your question.
Did you clear the depth buffer ?
When you generated the color in the fragment shader for the rendered objects, did you correctly calculate the White color?
One way I do in these situations to help me debug the issue is to remove potential error areas.
Clear the framebuffer to Red color and Alpha channel = 1.0
Clear depth buffer
Hard code gl_FragColor to vec4(1,1,1,1)
By doing this you can see if the output is all red? Then the issue is with the object rendering, such as transformation, clipping, depth rejection or other reason.
If you can see the objects with White color? Then you know it's the issue with your fragment shader
I would also recommend you to remove the line
glGenerateMipmap(GL_TEXTURE_2D);
As from what I can see in your code, it does not add any extra. If not this is the root-cause to your error.
Generating mipmaps on the texture that still being used and attached to a framebuffer object is not very effecient, especially if the driver internally would have to reallocate the memory for being able to store the new mipmap levels.
Solved.It was problems with index buffer and I forget to disable depth_test.

unable to read depth values from depth texture attached to FBO

I am unable to read correct depth values from depth texture using glreadpixels function. FBO status is complete. other render targets also look fine after blitting to another FBO.
code snippet:
// Create the FBO
glGenFramebuffers(1, &m_fbo);
glBindFramebuffer(GL_FRAMEBUFFER, m_fbo);
// Create the gbuffer textures
glGenTextures(GBUFFER_NUM_TEXTURES, m_textures);
glGenTextures(1, &m_depthTexture);
for (unsigned int i = 0 ; i < GBUFFER_NUM_TEXTURES ; i++) {
glBindTexture(GL_TEXTURE_2D, m_textures[i]);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA16F, fboWidth, fboHeight, 0, GL_RGBA, GL_FLOAT, NULL);
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0 + i, GL_TEXTURE_2D, m_textures[i], 0);
}
// depth
glBindTexture(GL_TEXTURE_2D, m_depthTexture);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
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_COMPARE_MODE, GL_NONE);
glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT32F, fboWidth, fboHeight, 0, GL_DEPTH_COMPONENT, GL_FLOAT,
NULL);
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, m_depthTexture, 0);
GLenum DrawBuffers[] = { GL_COLOR_ATTACHMENT0, GL_COLOR_ATTACHMENT1 };
glDrawBuffers(GBUFFER_NUM_TEXTURES, DrawBuffers);
GLenum Status = glCheckFramebufferStatus(GL_FRAMEBUFFER);
if (Status != GL_FRAMEBUFFER_COMPLETE) {
printf("FB error, status: 0x%x\n", Status);
return 0;
}
// drawing something with depth test enabled.
// Now i am using glreadpixels functions to read depth values from depth texture.
int w = 4, h = 1;
GLfloat windowDepth[4];
glBindFramebuffer(GL_FRAMEBUFFER, m_fbo);
glReadPixels(x, y, w, h, GL_DEPTH_COMPONENT, GL_FLOAT, windowDepth);
You are drawing to a depth texture. The appropriate function to call to read a texture into client memory is glGetTexImage (...).
Now, since there is no glGetTexSubImage (...), you need to allocate enough client storage to hold an entire LOD of the depth texture. Something like this will probably do the trick:
GLuint w = fboWidth, h = fboHeight;
GLfloat windowDepth [w * h];
glBindTexture (GL_TEXTURE_2D, m_depthTexture);
glGetTexImage (GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT, GL_FLOAT, windowDepth);
Keep in mind that unlike glReadPixels (...), glGetTexImage (...) does not perform pixel transfer conversion. That is, your format and data type must be an exact match with the types used when the texture was created, the GL will not convert your data.
With that out of the way, can I ask why you are reading the depth buffer into client memory in the first place? You appear to be using deferred shading, so I can see why you need a depth texture, but it is less clear why you need a copy of the depth buffer outside of shaders. You will have a hard time achieving interactive frame rates if you copy the depth buffer each frame.

OpenGL ping ponging with two textures on the same framebuffer

I'm trying to render to two textures, rendering from the first to the second, and then from the second to the first etc. The problem is that when I'm rendering the first texture to the second, it works fine but rendering the second to the first leaves a white texture, when it's supposed to be a purple one. I'm working with Qt and OpenGL.
Both textures are bound to the same FBO, and I'm switching them through glDrawBuffer(GL_COLOR_ATTACHMENT_i)
Here is my initialization code:
void GlWidget::initializeGL() {
glewInit();
src = true;
glEnable(GL_DEPTH_TEST);
glEnable(GL_TEXTURE_2D);
//glEnable(GL_CULL_FACE);
// Generate the texture to be drawn
tex = new float[256*256*4];
for(int i = 0; i < 256*256*4; i++){
if (i % 4 == 0){
tex[i] = 0.5;
}else if (i % 4 == 1){
tex[i] = 0.3;
}else if (i % 4 == 2){
tex[i] = 0.5;
}else if (i % 4 == 3){
tex[i] = 0;
}
}
glGenTextures(1, &texture);
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, texture);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA32F, 256, 256, 0, GL_RGBA, GL_FLOAT, tex);
glGenTextures(1, &targetTex);
glActiveTexture(GL_TEXTURE1);
glBindTexture(GL_TEXTURE_2D, targetTex);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA32F, 256, 256, 0, GL_RGBA, GL_FLOAT, NULL);
glGenFramebuffers(1, &fb);
glBindFramebuffer(GL_FRAMEBUFFER, fb);
//Attach 2D texture to this FBO
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture, 0);
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT1, GL_TEXTURE_2D, targetTex, 0);
glDrawBuffer (GL_COLOR_ATTACHMENT1);
//-------------------------
glGenRenderbuffers(1, &depth_rb);
glBindRenderbuffer(GL_RENDERBUFFER_EXT, depth_rb);
glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT24, 256, 256);
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT_EXT, GL_RENDERBUFFER, depth_rb);
glBindFramebuffer(GL_FRAMEBUFFER, 0);
shaderProgram.addShaderFromSourceFile(QGLShader::Vertex, ":/vertexShader.vsh");
shaderProgram.addShaderFromSourceFile(QGLShader::Fragment, ":/fragmentShader.fsh");
shaderProgram.link();
vertices << QVector3D(-1, -1, -2) << QVector3D(-1, 1, -2) << QVector3D(1, 1, -2) << QVector3D(1, -1, -2);
texCoords << QVector2D(0, 0) << QVector2D(0, 1) << QVector2D(1, 1) << QVector2D(1, 0);
}
And here is my drawing code:
void GlWidget::render_to_screen () {
glBindFramebuffer(GL_FRAMEBUFFER, 0);
qglClearColor(QColor(Qt::blue));
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
if(src){
glActiveTexture(GL_TEXTURE0);
}else{
glActiveTexture(GL_TEXTURE1);
}
shaderProgram.enableAttributeArray("textureCoordinates");
shaderProgram.enableAttributeArray("vertex");
glDrawArrays(GL_QUADS, 0, vertices.size());
shaderProgram.disableAttributeArray("vertex");
shaderProgram.disableAttributeArray("textureCoordinates");
}
void GlWidget::paintGL()
{
qDebug() << "Updating";
glBindFramebuffer(GL_FRAMEBUFFER, fb);
if(src) {
glDrawBuffer(GL_COLOR_ATTACHMENT1);
glActiveTexture(GL_TEXTURE0);
}else {
glDrawBuffer(GL_COLOR_ATTACHMENT0);
glActiveTexture(GL_TEXTURE1);
}
src = !src;
qglClearColor(QColor(Qt::white));
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
QMatrix4x4 mMatrix;
QMatrix4x4 vMatrix;
shaderProgram.bind();
shaderProgram.setUniformValue("mvpMatrix", pMatrix * vMatrix * mMatrix);
shaderProgram.setAttributeArray ("textureCoordinates", texCoords.constData ());
shaderProgram.enableAttributeArray("textureCoordinates");
shaderProgram.setAttributeArray("vertex", vertices.constData());
shaderProgram.enableAttributeArray("vertex");
glDrawArrays(GL_QUADS, 0, vertices.size());
shaderProgram.disableAttributeArray("vertex");
shaderProgram.disableAttributeArray("textureCoordinates");
render_to_screen ();
shaderProgram.release();
}
I'm supposed to be getting a blue screen with a purple quad in the center, instead I'm getting a white quad in the center. What am I doing wrong here?
I see several places in your code where you set the active texture. But setting the active texture means nothing as far as what texture unit the program will pull from. That's decided by the texture image unit set into the sampler uniform that's accessing the texture. You need to change that uniform, not the active texture.
Or better yet, just bind the other texture to the context. There's no need to set the active texture image unit; just bind the texture you want to sample from. Really, there's no point in any of the glActiveTexture calls you're making.