Is FBO Size Tied To glViewport?

Moderator
Posts: 3,570
Joined: 2003.06
Post: #1
I'm finally trying to learn how to do shadow mapping with GLSL. I have the basic shader working (just basic lighting with diffuse and shadow right now) and I have the shadow map rendering nicely and it correctly places the shadows. Unfortunately it is *horribly* aliased, in part because I'm using a 512 x 512 shadow map. I can do some extra samples to anti-alias it a bit, but I get much improved results just using a bigger shadow map. So I tried to bump up the size of the shadow map to 1024 but then discovered that you can't just do that all willy-nilly since apparently you can't set glViewport to bigger than your window (or "drawable", is probably more correct terminology?), and my window starts off at a smaller size than 1024. If I try doing this then there's garbage in part of my texture until I make the window bigger or go to a higher resolution in full screen. After that everything is fine. Okay, seems to make sense that I'm limited there.

SO ... I figured, well then I guess I might be able to use an FBO and get whatever size I want (within the max tex size and performance of course), right? Apparently not. I switched to using an FBO for the shadow map texture instead of glCopyTexSubImage2D but I still get garbage in part of my texture until I change the size of the window. Am I not supposed to be doing things this way? What size can I get away with? How do I get the FBO to be the size I want without garbage at first? I'm new to this shadow mapping (and FBO) business, so any help and/or pointers would be greatly appreciated. Smile
Quote this message in a reply
Luminary
Posts: 5,143
Joined: 2002.04
Post: #2
FBO should work fine. You'll need to set glViewport appropriately as you switch from your window drawable to the FBO's drawable.

If it doesn't, post code Wink
Quote this message in a reply
Moderator
Posts: 3,570
Joined: 2003.06
Post: #3
It doesn't seem to be changing as it should, so I must be missing something. Here's some code (unrefined early development and experimentation). Not sure what else I should include. I added comments to help trace some of my thinking. I hope they aren't too non-sensical:

Code:
#define SHADOW_MAP_SIZE        1024

- (id)init
{
    NSBundle    *bundle;
    
    
    if(!(self = [super init])) return nil;
    bundle = [NSBundle bundleForClass:[self class]];
    if (![self loadVertexShader:[NSString stringWithContentsOfFile:[bundle pathForResource:@"Shadow" ofType:@"vert"]]
                fragmentShader:[NSString stringWithContentsOfFile:[bundle pathForResource:@"Shadow" ofType:@"frag"]]])
        return nil;
    
    // prepare shadow map FBO
    glGenFramebuffersEXT(1, &shadowMapFBO);
    glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, shadowMapFBO);
    glGenTextures(1, &shadowMapTexture);
    glBindTexture(GL_TEXTURE_2D, shadowMapTexture);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);
    glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, GL_TEXTURE_2D, shadowMapTexture, 0);
    glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT32, SHADOW_MAP_SIZE, SHADOW_MAP_SIZE, 0,
                    GL_DEPTH_COMPONENT, GL_UNSIGNED_BYTE, nil);
    glDrawBuffer(GL_NONE);
    glReadBuffer(GL_NONE);
    GLenum status = glCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT);
    switch (status)
    {
        case GL_FRAMEBUFFER_COMPLETE_EXT:
            //NSLog(@"FBO looks like it should work");
            break;
        default:
            NSLog(@"FBO setup error: 0x%X", status);
            break;
    }
    glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
    
    // create some matrices for the light
    // light perspective is 1 to 1 aspect and as narrow a z-buffer as possible for better floating point compares (supposedly)
    glPushMatrix();
    glLoadIdentity();
    gluPerspective(45.0f, 1.0f, 10.0f, 24.0f);
    glGetFloatv(GL_MODELVIEW_MATRIX, lightProjectionMatrix);
    glLoadIdentity();
    gluLookAt(10.0f, 10.0f, 10.0f, // lightPosX, lightPosY, lightPosZ,
                0.0f, 0.0f, 0.0f,
                0.0f, 1.0f, 0.0f);
    glGetFloatv(GL_MODELVIEW_MATRIX, lightViewMatrix);
    glPopMatrix();
    return self;
}

- (void)begin
{
    // bind FBO to render shadow map into
    glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, shadowMapFBO);
    
    // make sure that we aren't accessing the shadowMapTexture by accident, which would result in undefined behavior
    glBindTexture(GL_TEXTURE_2D, 0);
    
    // save the existing viewport and set a new one for the FBO rendering
    glPushAttrib(GL_VIEWPORT_BIT);
    glViewport(0, 0, SHADOW_MAP_SIZE, SHADOW_MAP_SIZE);
    glClearDepth(1.0f);
    glClear(GL_DEPTH_BUFFER_BIT);
    
    glMatrixMode(GL_PROJECTION);
    glPushMatrix();
    glLoadMatrixf(lightProjectionMatrix);
    
    glMatrixMode(GL_MODELVIEW);
    glPushMatrix();
    glLoadMatrixf(lightViewMatrix);
    
    // draw only back faces into the shadow map since they're in the shadows
    glCullFace(GL_FRONT);
    
    // don't want any color writes, just depth
    glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE);
    
    // only need flat shading
    glShadeModel(GL_FLAT);
    
    // returns to let the client render the scene for the light
}

- (void)lightEnd
{
    // we're done rendering the shadow map to the FBO so make the window the rendering target
    glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
    
    // restore the original viewport
    glPopAttrib();
    
    // bind shadow map texture to unit 1
    glActiveTextureARB(GL_TEXTURE1_ARB);
    glBindTexture(GL_TEXTURE_2D, shadowMapTexture);
    
    // setup the texture matrix for shadow mapping
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_MODE_ARB, GL_COMPARE_R_TO_TEXTURE_ARB);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_FUNC_ARB, GL_LEQUAL);
    glMatrixMode(GL_TEXTURE);
    
    // match the texture space to model space
    const GLfloat bias[] = {    0.5, 0.0, 0.0, 0.0,
                                0.0, 0.5, 0.0, 0.0,
                                0.0, 0.0, 0.5, 0.0,
                                0.5, 0.5, 0.5, 1.0 };
    glLoadMatrixf(bias);
    glMultMatrixf(lightProjectionMatrix);
    glMultMatrixf(lightViewMatrix);
    
    // clean up
    glActiveTextureARB(GL_TEXTURE0_ARB);
    glMatrixMode(GL_PROJECTION);
    glPopMatrix();
    glMatrixMode(GL_MODELVIEW);
    glPopMatrix();
    glCullFace(GL_BACK);
    glShadeModel(GL_SMOOTH);
    glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
    
    // simply turns on the shader, which we didn't need for the shadow map rendering above, but now we do
    // because the real scene is going to be rendered next
    [super begin];
    
    // tell shader to use texture unit1 for the shadow map and unit0 for the regular textures
    glUniform1iARB(glGetUniformLocationARB(programObject, "ShadowMap"), 1);
    glUniform1iARB(glGetUniformLocationARB(programObject, "TexMap"), 0);
    
    // returns to let the client render the scene normally
}
Quote this message in a reply
Luminary
Posts: 5,143
Joined: 2002.04
Post: #4
I'm not seeing anything obviously wrong in your code, but I'm thinking I'm just blind Wink

Here's a simple test: http://onesadcookie.com/~keith/BigFBOTest.tar.bz2

Code:
#include <stdlib.h>

#include <GLUT/glut.h>

#define WINDOW_SIZE 512
#define TEXTURE_SIZE 1024

GLuint texture;
GLuint fbo;

void display(void)
{
    glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, fbo);
    glViewport(0, 0, TEXTURE_SIZE, TEXTURE_SIZE);
    glClearColor(1.0, 0.0, 1.0, 0.0);
    glClear(GL_COLOR_BUFFER_BIT);
    glColor4f(1.0, 1.0, 0.0, 1.0);
    glBegin(GL_TRIANGLES);
        glVertex2f(-1.0f, -1.0f);
        glVertex2f(-0.0f, -1.0f);
        glVertex2f(-0.5f,  1.0f);
        glVertex2f( 0.0f, -1.0f);
        glVertex2f( 1.0f, -1.0f);
        glVertex2f( 0.5f,  1.0f);
    glEnd();
    glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
    
    glViewport(0, 0, glutGet(GLUT_WINDOW_WIDTH), glutGet(GLUT_WINDOW_HEIGHT));
    glClearColor(0.0, 1.0, 0.0, 0.0);
    glClear(GL_COLOR_BUFFER_BIT);
    glBindTexture(GL_TEXTURE_2D, texture);
    glEnable(GL_TEXTURE_2D);
    glBegin(GL_QUADS);
        glTexCoord2f(0.0, 0.0);
        glVertex2f(-1.0, -1.0);
        glTexCoord2f(1.0, 0.0);
        glVertex2f( 1.0, -1.0);
        glTexCoord2f(1.0, 1.0);
        glVertex2f( 1.0,  1.0);
        glTexCoord2f(0.0, 1.0);
        glVertex2f(-1.0,  1.0);
    glEnd();
    glDisable(GL_TEXTURE_2D);
    glBindTexture(GL_TEXTURE_2D, 0);
    
    glutSwapBuffers();
}

void idle(void)
{
    glutPostRedisplay();
}

int main(int argc, char** argv)
{
    glutInit(&argc, argv);
    
    glutInitDisplayMode(GLUT_RGBA | GLUT_DOUBLE);
    glutInitWindowSize(WINDOW_SIZE, WINDOW_SIZE);
    
    glutCreateWindow("GLUT Program");
    
    glGenTextures(1, &texture);
    glBindTexture(GL_TEXTURE_2D, texture);
    glTexImage2D(
        GL_TEXTURE_2D,
        0,
        GL_RGBA,
        TEXTURE_SIZE,
        TEXTURE_SIZE,
        0,
        GL_BGRA,
        GL_UNSIGNED_INT_8_8_8_8_REV,
        NULL);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
    glBindTexture(GL_TEXTURE_2D, 0);
    
    glGenFramebuffersEXT(1, &fbo);
    glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, fbo);
    glFramebufferTextureEXT(
        GL_FRAMEBUFFER_EXT,
        GL_COLOR_ATTACHMENT0_EXT,
        texture,
        0);
    glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
    
    glutDisplayFunc(display);
    glutIdleFunc(idle);
    
    glutMainLoop();
    return EXIT_SUCCESS;
}

It works* for me (Shows two complete upward-pointing yellow triangles on a red* background) on a Radeon X1600, 10.5.2+LGU1

*WTH, why is the background red? the ClearColor is set to magenta Wacko
Quote this message in a reply
Luminary
Posts: 5,143
Joined: 2002.04
Post: #5
The red background thing is a bug, the blue component of glClearColor is ignored for FBOs on all hardware (10.5.2, LGU1). Filed as Radar #5775254 if anyone cares.
Quote this message in a reply
Sage
Posts: 1,232
Joined: 2002.10
Post: #6
This is one case where it's your bug.

Remember that the default TexEnv is MODULATE, and look at your current color.
Quote this message in a reply
Sage
Posts: 1,232
Joined: 2002.10
Post: #7
Re: the OP, adding glGetIntegerv(GL_VIEWPORT, ...) might help you debug what's going wrong. Perhaps your push/pops aren't balanced?

Anyway, viewport is not FBO state. It is context state.
FBO-dependent state is enumerated in table 9.nnn in the FBO spec.
Quote this message in a reply
Luminary
Posts: 5,143
Joined: 2002.04
Post: #8
Doh Cry It's not my week for bugs-that-aren't-bugs Cry

To everyone who was in the IRC channel "checking my code for a stupid mistake" it's all your fault Wink Rasp
Quote this message in a reply
Moderator
Posts: 3,570
Joined: 2003.06
Post: #9
The GLUT test works as advertised. The only difference I see is that I'm rendering to a depth texture, which is significant, but the technique appears to be the same.

I tried the glGetIntegerv(GL_VIEWPORT, ...) idea and it says the viewport is what it is supposed to be, when it is supposed to be (tried it in a bunch of places).

I don't see any obvious unbalanced push/pops (of course they aren't usually obvious).

So if the FBO and the context states have nothing to do with each other, then why is the amount of garbage in my depth (shadow) texture directly proportional to the size of my window? As I grow the window, the garbage goes away and doesn't come back if I then shrink it. It's as if memory in the FBO texture just isn't being allocated or accessible until I grow the context's viewport large enough. I don't see how they could be tied together, but it really *appears* that way.

I also noticed that it appears that my shadow map texture disappears when I turn the shader off. That is, I can texture a quad with the shadow map texture while the shader is on, but not when it's off. The two issues could (very likely) be entirely unrelated, but I was able to texture with the shadow map back when I was using the glCopyTexSubImage2D technique with no shader.

Looks like I'll be sleuthing today...
Quote this message in a reply
Luminary
Posts: 5,143
Joined: 2002.04
Post: #10
I've updated the test to include depth as well, and it's still fine: http://onesadcookie.com/~keith/BigFBOTest.tar.bz2

Press any key to toggle displaying color vs. depth

Code:
#include <stdlib.h>

#include <GLUT/glut.h>

#define WINDOW_SIZE 512
#define TEXTURE_SIZE 1024

GLuint texture;
GLuint depth;
GLuint fbo;

GLuint whichTexture;

void display(void)
{
    glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, fbo);
    glViewport(0, 0, TEXTURE_SIZE, TEXTURE_SIZE);
    glClearColor(1.0, 0.0, 1.0, 1.0);
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
    glEnable(GL_DEPTH_TEST);
    glColor4f(1.0, 1.0, 0.0, 1.0);
    glBegin(GL_TRIANGLES);
        glVertex3f(-1.0f, -1.0f, -1.0f);
        glVertex3f(-0.0f, -1.0f, -1.0f);
        glVertex3f(-0.5f,  1.0f,  1.0f);
        glVertex3f( 0.0f, -1.0f, -1.0f);
        glVertex3f( 1.0f, -1.0f, -1.0f);
        glVertex3f( 0.5f,  1.0f,  1.0f);
    glEnd();
    glColor4f(1.0, 1.0, 1.0, 1.0);
    glDisable(GL_DEPTH_TEST);
    glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
    
    glViewport(0, 0, glutGet(GLUT_WINDOW_WIDTH), glutGet(GLUT_WINDOW_HEIGHT));
    glClearColor(0.0, 1.0, 0.0, 0.0);
    glClear(GL_COLOR_BUFFER_BIT);
    glBindTexture(GL_TEXTURE_2D, whichTexture);
    glEnable(GL_TEXTURE_2D);
    glBegin(GL_QUADS);
        glTexCoord2f(0.0, 0.0);
        glVertex2f(-1.0, -1.0);
        glTexCoord2f(1.0, 0.0);
        glVertex2f( 1.0, -1.0);
        glTexCoord2f(1.0, 1.0);
        glVertex2f( 1.0,  1.0);
        glTexCoord2f(0.0, 1.0);
        glVertex2f(-1.0,  1.0);
    glEnd();
    glDisable(GL_TEXTURE_2D);
    glBindTexture(GL_TEXTURE_2D, 0);
    
    glutSwapBuffers();
}

void idle(void)
{
    glutPostRedisplay();
}

void keyboard(unsigned char k, int x, int y)
{
    whichTexture = whichTexture == texture ? depth : texture;
}

int main(int argc, char** argv)
{
    glutInit(&argc, argv);
    
    glutInitDisplayMode(GLUT_RGBA | GLUT_DOUBLE);
    glutInitWindowSize(WINDOW_SIZE, WINDOW_SIZE);
    
    glutCreateWindow("GLUT Program");
    
    glGenTextures(1, &texture);
    glBindTexture(GL_TEXTURE_2D, texture);
    glTexImage2D(
        GL_TEXTURE_2D,
        0,
        GL_RGBA,
        TEXTURE_SIZE,
        TEXTURE_SIZE,
        0,
        GL_BGRA,
        GL_UNSIGNED_INT_8_8_8_8_REV,
        NULL);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
    glBindTexture(GL_TEXTURE_2D, 0);
    
    glGenTextures(1, &depth);
    glBindTexture(GL_TEXTURE_2D, depth);
    glTexImage2D(
        GL_TEXTURE_2D,
        0,
        GL_DEPTH_COMPONENT24_ARB,
        TEXTURE_SIZE,
        TEXTURE_SIZE,
        0,
        GL_DEPTH_COMPONENT,
        GL_UNSIGNED_INT,
        NULL);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
    glBindTexture(GL_TEXTURE_2D, 0);
    
    glGenFramebuffersEXT(1, &fbo);
    glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, fbo);
    glFramebufferTextureEXT(
        GL_FRAMEBUFFER_EXT,
        GL_COLOR_ATTACHMENT0_EXT,
        texture,
        0);
    glFramebufferTextureEXT(
        GL_FRAMEBUFFER_EXT,
        GL_DEPTH_ATTACHMENT_EXT,
        depth,
        0);
    glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
    
    whichTexture = depth;
    
    glutDisplayFunc(display);
    glutIdleFunc(idle);
    glutKeyboardFunc(keyboard);
    
    glutMainLoop();
    return EXIT_SUCCESS;
}
Quote this message in a reply
Moderator
Posts: 3,570
Joined: 2003.06
Post: #11
Yes, that works as advertised as well, but dammit, if I knew you were going to do that I wouldn't have already gone and done it myself! Rasp

Thanks though, I really appreciate it, big-time. Smile

Here was my somewhat more elaborate version. Change RENDER_DEPTH_TEXTURE to 0 to render a colored cube instead. [adding] I'm sure it probably spins at a million rotations per second on a faster machine, since I didn't do any time calculation [/]:
Code:
#include <stdlib.h>

#include <GLUT/glut.h>

#define WINDOW_SIZE 512
#define TEXTURE_SIZE 1024

#define RENDER_DEPTH_TEXTURE    1

GLuint texture;
GLuint depth_rb;
GLuint fbo;

GLfloat    xRot = 0.0f;
GLfloat yRot = 0.0f;

void RenderToTexture(void)
{
    glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, fbo);
    glViewport(0, 0, TEXTURE_SIZE, TEXTURE_SIZE);
    glClearColor(0.2, 0.2, 0.2, 1.0);
    glClearDepth(1.0f);
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
    glEnable(GL_DEPTH_TEST);
    
    glMatrixMode(GL_PROJECTION);
    glPushMatrix();
    glLoadIdentity();
    gluPerspective(45.0f, 1.0f, 6.0f, 10.0f);
    
    glMatrixMode(GL_MODELVIEW);
    glPushMatrix();
    glLoadIdentity();
    
    xRot += 0.1f;
    yRot += 0.3f;
    glTranslatef(0.0f, 0.0f, -8.0f);
    glRotatef(xRot, 1.0f, 0.0f, 0.0f);
    glRotatef(yRot, 0.0f, 1.0f, 0.0f);
    glBegin(GL_QUADS);
        glColor4f(1.0f, 0.0f, 0.0f, 1.0f);
        glVertex3f( 1.0f, 1.0f,-1.0f);
        glVertex3f(-1.0f, 1.0f,-1.0f);
        glVertex3f(-1.0f, 1.0f, 1.0f);
        glVertex3f( 1.0f, 1.0f, 1.0f);
        glColor4f(0.0f, 1.0f, 0.0f, 1.0f);
        glVertex3f( 1.0f,-1.0f, 1.0f);
        glVertex3f(-1.0f,-1.0f, 1.0f);
        glVertex3f(-1.0f,-1.0f,-1.0f);
        glVertex3f( 1.0f,-1.0f,-1.0f);
        glColor4f(0.0f, 0.0f, 1.0f, 1.0f);
        glVertex3f( 1.0f, 1.0f, 1.0f);
        glVertex3f(-1.0f, 1.0f, 1.0f);
        glVertex3f(-1.0f,-1.0f, 1.0f);
        glVertex3f( 1.0f,-1.0f, 1.0f);
        glColor4f(1.0f, 1.0f, 0.0f, 1.0f);
        glVertex3f( 1.0f,-1.0f,-1.0f);
        glVertex3f(-1.0f,-1.0f,-1.0f);
        glVertex3f(-1.0f, 1.0f,-1.0f);
        glVertex3f( 1.0f, 1.0f,-1.0f);
        glColor4f(0.5f, 0.5f, 0.5f, 1.0f);
        glVertex3f(-1.0f, 1.0f, 1.0f);
        glVertex3f(-1.0f, 1.0f,-1.0f);
        glVertex3f(-1.0f,-1.0f,-1.0f);
        glVertex3f(-1.0f,-1.0f, 1.0f);
        glColor4f(0.0f, 1.0f, 1.0f, 1.0f);
        glVertex3f( 1.0f, 1.0f,-1.0f);
        glVertex3f( 1.0f, 1.0f, 1.0f);
        glVertex3f( 1.0f,-1.0f, 1.0f);
        glVertex3f( 1.0f,-1.0f,-1.0f);
    glEnd();
    
    glMatrixMode(GL_PROJECTION);
    glPopMatrix();
    glMatrixMode(GL_MODELVIEW);
    glPopMatrix();
    glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
}

void display(void)
{
    RenderToTexture();
    
    glViewport(0, 0, glutGet(GLUT_WINDOW_WIDTH), glutGet(GLUT_WINDOW_HEIGHT));
    glClearColor(0.0, 0.0, 0.0, 1.0);
    glClear(GL_COLOR_BUFFER_BIT);
    glDisable(GL_DEPTH_TEST);
    
    glColor4f(1.0f, 1.0f, 1.0f, 1.0f);
    glBindTexture(GL_TEXTURE_2D, texture);
    glEnable(GL_TEXTURE_2D);
    glBegin(GL_QUADS);
        glTexCoord2f(0.0, 0.0);
        glVertex2f(-1.0, -1.0);
        glTexCoord2f(1.0, 0.0);
        glVertex2f( 1.0, -1.0);
        glTexCoord2f(1.0, 1.0);
        glVertex2f( 1.0,  1.0);
        glTexCoord2f(0.0, 1.0);
        glVertex2f(-1.0,  1.0);
    glEnd();
    glDisable(GL_TEXTURE_2D);
    glBindTexture(GL_TEXTURE_2D, 0);
    
    glutSwapBuffers();
}

void idle(void)
{
    glutPostRedisplay();
}

int main(int argc, char** argv)
{
    glutInit(&argc, argv);
    
    glutInitDisplayMode(GLUT_DEPTH | GLUT_RGBA | GLUT_DOUBLE);
    glutInitWindowSize(WINDOW_SIZE, WINDOW_SIZE);
    
    glutCreateWindow("GLUT Program");
    
    glShadeModel(GL_SMOOTH);
    glDepthFunc(GL_LEQUAL);
    
    glGenTextures(1, &texture);
    glBindTexture(GL_TEXTURE_2D, texture);
    if (RENDER_DEPTH_TEXTURE)
    {
        glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT32, TEXTURE_SIZE, TEXTURE_SIZE, 0,
                        GL_DEPTH_COMPONENT, GL_UNSIGNED_BYTE, NULL);
    }
    else
    {
        glTexImage2D(
            GL_TEXTURE_2D,
            0,
            GL_RGBA,
            TEXTURE_SIZE,
            TEXTURE_SIZE,
            0,
            GL_BGRA,
            GL_UNSIGNED_INT_8_8_8_8_REV,
            NULL);
    }
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
    glBindTexture(GL_TEXTURE_2D, 0);
    
    glGenFramebuffersEXT(1, &fbo);
    glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, fbo);
    if (RENDER_DEPTH_TEXTURE)
    {
        glFramebufferTextureEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, texture, 0);
        glDrawBuffer(GL_NONE);
        glReadBuffer(GL_NONE);
    }
    else
    {
        glFramebufferTextureEXT(
            GL_FRAMEBUFFER_EXT,
            GL_COLOR_ATTACHMENT0_EXT,
            texture,
            0);
         glGenRenderbuffersEXT(1, &depth_rb);
         glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, depth_rb);
         glRenderbufferStorageEXT(GL_RENDERBUFFER_EXT, GL_DEPTH_COMPONENT24, TEXTURE_SIZE, TEXTURE_SIZE);
         glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, GL_RENDERBUFFER_EXT, depth_rb);
    }
    glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
    
    glutDisplayFunc(display);
    glutIdleFunc(idle);
    
    glutMainLoop();
    return EXIT_SUCCESS;
}

This brought up another question about FBOs actually. I just started researching on it, but haven't found anything yet. When rendering the colored cube, is there a particular reason why the depth testing seems not to work when rendering to an FBO texture? Does it not have a depth buffer or something? Maybe there's a different type of attachment to be using. Or perhaps I missed something in my code... Whatever, it's not totally important to the problem at hand, but as long as I'm learning a little about FBOs I figure it's worth my trouble to find out what's up with that too, if I can.

[Edit] Never mind. This got fixed! Smile [/edit]

At any rate, the GLUT demos have me 99.9% convinced that it is completely my fault, whatever that may be. I guess I'll have to start restructuring the code and isolating things more carefully.
Quote this message in a reply
Sage
Posts: 1,232
Joined: 2002.10
Post: #12
It's doing exactly what you asked it to do; when RENDER_DEPTH_TEXTURE=0, you're not attaching anything to the FBO's depth attachment, hence you get no depth testing.

When you create a window, and provide a pixel format, there is some logic that looks at the pixel format and says "Oh, you asked for a color buffer-- let's allocate one. Oh, you asked for a depth buffer-- let's allocate one." And so on.

An FBO is a little container object which you attach buffers to. The pixel format logic is replaced with you explicitly allocating buffers and attaching them. See the spec for the overview, gory details, and examples.

You can inspect what you've got at any given moment, for example:
Code:
GLint bits[1];
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
glGetIntegerv(GL_DEPTH_BITS, bits);
printf("The window has %d depth bits\n", bits);
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, myFBOThatWasMadeEarlier);
glGetIntegerv(GL_DEPTH_BITS, bits);
printf("FBO %d has %d depth bits\n", myFBOThatWasMadeEarlier, bits);
Quote this message in a reply
Moderator
Posts: 3,570
Joined: 2003.06
Post: #13
arekkusu Wrote:An FBO is a little container object which you attach buffers to. The pixel format logic is replaced with you explicitly allocating buffers and attaching them. See the spec for the overview, gory details, and examples.
[shudders] That particular spec doc scares the bejeezus out of me. I've been trying to weed through some of it, but it's a challenge for me to say the least. BUT, thank you for pointing it out again, in addition to your explanation that I didn't get depth because I didn't tell it to attach a depth buffer. I got it working now, using one of the examples found in there. Smile I'll edit the above GLUT code to include it.

arekkusu Wrote:You can inspect what you've got at any given moment, for example:
Code:
GLint bits[1];
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
glGetIntegerv(GL_DEPTH_BITS, bits);
printf("The window has %d depth bits\n", bits);
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, myFBOThatWasMadeEarlier);
glGetIntegerv(GL_DEPTH_BITS, bits);
printf("FBO %d has %d depth bits\n", myFBOThatWasMadeEarlier, bits);

Ah yes, thanks for the reminder. I almost always forget to glGet important information which could give me some feedback instead of trying to blindly guess everything. Needs to be like: printf("FBO %d has %d depth bits\n", myFBOThatWasMadeEarlier, bits[0]); though, or else it just prints an address (minor detail).

Now that we got that settled, I still need to figure out what's up with my other shadow texture, so back to sleuthing I shall go...
Quote this message in a reply
Moderator
Posts: 3,570
Joined: 2003.06
Post: #14
Aha! Found the little bastard:

GL_SCISSOR_TEST was enabled. Uh huh. It's never the one you see that gets you... Sneaky

Thanks for the help guys. I finally gave up and decided to replace *all* of my drawing code with the GLUT test drawing code, which then led to the culprit within minutes.
Quote this message in a reply
Post Reply 

Possibly Related Threads...
Thread: Author Replies: Views: Last Post
  Small error with glViewport and gluPerspective? cjcaufield 1 3,253 Sep 20, 2009 01:10 AM
Last Post: DoG