Render to texture + GL_DEPTH_TEST = Black screen

Good evening everyone!

First posting, let’s see how much I can do wrong (I hope this is at least the right sub-forum). Also, this post will be a bit longer, so please bear with me.

Disclaimer: Yes, I first had a look at Google before bothering you with this. Yes, I have cleared the depth buffer and tried many different depth funcs.

The problem: For a game, I want to render to a texture and apply some post-processing to it. The game is in 2D and I already applied render-to-texture to it, but apparently I did it wrong, because as soon as I switch the depth testing on (which I forgot), the screen is black. And yes, I need the depth testing because the game will have different layers.

For some reason, I can’t link a tutorial I applied before, so here’s my code:

Header:


GLuint screenRenderFBO, screenRenderTexture, screenRenderDepthFBO;

Initialisation, along with comments from tutorial:


// The framebuffer, which regroups 0, 1, or more textures, and 0 or 1 depth
glGenFramebuffers(1, &screenRenderFBO);
glBindFramebuffer(GL_FRAMEBUFFER, screenRenderFBO);

// The texture we're going to render to
glActiveTexture(GL_TEXTURE0 + RENDER_TO_TEXTURE_OFFSET);
glGenTextures(1, &screenRenderTexture);

// "Bind" the newly created texture : all future texture functions will modify this texture
glBindTexture(GL_TEXTURE_2D, screenRenderTexture);

// Give an empty image to OpenGL
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, BASIC_RES, BASIC_RES, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);

// Poor filtering. Needed !
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
checkGLError();

// The depth buffer
glGenRenderbuffers(1, &screenRenderDepthFBO);
glBindRenderbuffer(GL_RENDERBUFFER, screenRenderDepthFBO);
glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT, BASIC_RES, BASIC_RES);
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, screenRenderDepthFBO);

// Set "renderedTexture" as our colour attachement #0
glFramebufferTexture(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, screenRenderTexture, 0);

// Set the list of draw buffers.
GLenum DrawBuffers[1] = { GL_COLOR_ATTACHMENT0 };
glDrawBuffers(1, DrawBuffers); // "1" is the size of DrawBuffers

// Always check that our framebuffer is ok
if(glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE)
{
    std::cout << "Framebuffer could not be created!" << std::endl;
}

Drawcall (own code + comments, tutorial not very precise here):


glBindFramebuffer(GL_FRAMEBUFFER, screenRenderFBO);
glViewport(0, 0, BASIC_RES, BASIC_RES); // small resolution

glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

glEnable(GL_DEPTH_TEST); // <----- this causes the complete scene to go black
glDepthFunc(GL_???); // Anything can be inserted here, GL_NOTEQUAL causes the frame to flicker (every 2nd frame image, the other black). GL_ALWAYS works, but that's not what I want...

glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);

glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);

drawObjects(); // scene rendered here

// Render to the screen
glBindFramebuffer(GL_FRAMEBUFFER, 0);
glActiveTexture(GL_TEXTURE0 + RENDER_TO_TEXTURE_OFFSET);

toScreenShader->renderBegin(); // selfmade wrapper class for shader access
glUniform1i(toScreen_texture, RENDER_TO_TEXTURE_OFFSET);

glViewport(0, 0, windowSize[0], windowSize[1]); // real window is larger than texture
toScreenVbo->draw();

toScreenShader->renderEnd();

As the comment says, the depth test causes everything to go black. No openGL error was generated during the whole process.

Some questions here could be:
[ol]
[li]How can the depth test alone make the whole scene black, if the render to texture procedure itself seems to work?
[/li][li]Is the methodology wrong, i.e. are two FBOs and one textures right? I have tried other approaches with a depth texture, but without success. Or is there a completely other way to achieve this?
[/li][li]How can I insert all possible values into the depth func, and even (almost) contrary values like GEQUAL and LEQUAL always print a black screen?
[/li][/ol]

Does anyone have an idea what could be going on here? Any help would be much appreciated! If there’s anything I forgot to mention, please let me know.

Best regards,
Brokenmind

After almost three weeks, I just wanted to say the problem is still there and I couldn’t find a solution yet.
The only alternative would be drawing everything without depth test so the drawing order would be essential, which can hardly be realised properly…

The reason you haven’t gotten a reply is that its not obvious from your example what the problem is. What you need to do is to pull out the relevant section of code into a small GLUT standalone test program that illustrates the problem. Then post it.

Folks here will try it and probably tell you what’s going wrong. However, in the process of whittling down your code to the relevant portion, you will very likely find the bug. For instance, you think this is a depth issue, right? Get rid of alpha blending (i.e. turn it off). Get rid of the multiple textures – heck, get rid of texturing altogether. Once you have it whittled down, the problem is very likely going to jump right out at you.

Are you setting the clear depth, depth mask, or using stencil test? These and more are questions a standalone test program would answer.

I hoped that it would more or less be an obvious mistake in the procedure that you could point out. A GLUT standalone program will hardly be possible because I’m not even using GLUT and don’t have any experience with it.

If I understood you correctly, you are advising me to get rid of the whole drawing procedure and all textures (except for render-to-texture because without it, everything works) and try to reproduce the error with the standard red-and-blue triangles? That’s something I haven’t thought of so far, thanks for the suggestion! But as I already analysed every single line twice and thrice, I doubt the error will “jump right out at me” :wink:

As for your questions:
Clear depth:

glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

Depth mask: I set it to GL_TRUE, which didn’t have any effect (I also read it’s true by default).

Stencil test: With this, I have little to no experience, so I don’t think I am using it.

I will try to provide a standalone program.

I only suggest GLUT because it makes it super-easy to slam your GL code into a program that will bring up a GL window and let you draw with very little trouble. Here’s super-simple example you can paste your code into. Just toss your code into the display() function.


#include <stdio.h>
#include <GL/glut.h>
#include <math.h>
 
float theta = 0;
 
void display ();
 
void idle ();
 
void mouse (int button, int state, int x, int y);
 
int main (int argc, char** argv)
{
    glutInit (&argc, argv);
    glutInitDisplayMode (GLUT_DOUBLE |GLUT_RGB);
    glutInitWindowPosition (100, 100);
    glutInitWindowSize (500, 500);
    glutCreateWindow ("Double Buffer Testing");
    glutDisplayFunc (display);
    glutIdleFunc(idle);
 
    glClearColor (1, 1, 1,1);
    glMatrixMode (GL_PROJECTION);
    glLoadIdentity ();
    gluOrtho2D (-1, 1, -1, 1);
    glMatrixMode (GL_MODELVIEW);
 
    glutMainLoop();
    return 0;
}
 
void display ()
{
    glClear (GL_COLOR_BUFFER_BIT);
    glColor3f (1, 0, 0);
 
    glBegin (GL_POLYGON);
    float thetar = theta * (3.14159 / 180.0);
    glVertex2f (cosf (thetar), sinf (thetar));
    glVertex2f (-sinf (thetar), cosf(thetar));
    glVertex2f (-cosf (thetar), -sinf (thetar));
    glVertex2f (sinf (thetar), -cosf (thetar));
    glEnd ();
 
    glutSwapBuffers();
 
}
 
void idle ()
{
    theta += 2;
    if (theta > 360) theta -= 360;
    glutPostRedisplay ();
}


If I understood you correctly, you are advising me to get rid of the whole drawing procedure and all textures (except for render-to-texture because without it, everything works) and try to reproduce the error with the standard red-and-blue triangles?

Yes, or just start throwing out code until it the problem shows up or stops exhibiting itself, to nail down what code is relevant to the problem.

Clear depth:

glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

I meant are you calling glClearDepth()? If so, look at what you’re setting it to. If not, you’re good because it’s 1 by default, which causes a clear of the depth buffer to be preset to the far clip value.