Skip to main content
GameDev.net gamedev.net
🔒 Locked

EXT_framebuffer_object woes

Started by mpt Oct 27, 2005 at 11:58 PM 3 replies 1.8k views
Original Post
mpt
mpt
Hello, I'm trying to write a program to simulate depth of field using Cg shaders and framebuffer objects. The program is supposed to render the scene to a framebuffer object, then blur each pixel in the color buffer based on the value of the corresponding pixel in the depth buffer. However, as far as I can tell, either the depth buffer contains the same data as the color buffer (which doesn't make any sense), or I am sending the wrong data to the Cg shader. What am I doing wrong? I'm running this on an Nvidia GeForce 6800, driver version 77.77. I got most of the framebuffer-related code from the EXT_framebuffer_object documentation examples. Any help would be appreciated. Framebuffer initialization:
        glGenFramebuffersEXT(1, &fb);
        glGenTextures(1, &texid);
        glGenRenderbuffersEXT(1, &depth_rb);

        // initialize color texture
        glBindTexture(GL_TEXTURE_2D, texid);
        glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB8, 512, 512, 0, GL_RGB, GL_INT, NULL);

        // establish a mipmap chain for the texture
        glGenerateMipmapEXT(GL_TEXTURE_2D);

        // initialize depth renderbuffer
        glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, depth_rb);
        glRenderbufferStorageEXT(GL_RENDERBUFFER_EXT, GL_DEPTH_COMPONENT24, 512, 512);

        // setup framebuffer
        glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, fb);
        glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_TEXTURE_2D, texid, 0);
        glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, GL_RENDERBUFFER_EXT, depth_rb);

	// error checking
	GLenum status = glCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT);
	switch(status) {
		case GL_FRAMEBUFFER_COMPLETE_EXT:
			errorLog.Print("GL_FRAMEBUFFER_COMPLETE_EXT");
			break;
		case GL_FRAMEBUFFER_UNSUPPORTED_EXT:
			errorLog.OutputError("GL_FRAMEBUFFER_UNSUPPORTED_EXT  ...exiting");
			exit(0);
			break;
		default:
			errorLog.OutputError("Unknown Framebuffer Error  ...exiting");
			exit(0);
	}

Rendering code (in a loop): Sorry for the huge amount of code. Note that config.screenX = 512 and config.screenY = 512
	// Disable lighting in RTT mode
	glDisable(GL_LIGHTING);

	// set up depth parameters
	glClearDepth(1.0f);
	glDepthMask(GL_TRUE);
	glEnable(GL_DEPTH_TEST);
	glDepthFunc(GL_LESS);

	glBindTexture(GL_TEXTURE_2D, 0);

	// bind buffers and make attachments
	glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, fb);
	glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_TEXTURE_2D, texid, 0);
	glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, GL_RENDERBUFFER_EXT, depth_rb);

	//set up viewport, clear screen
	glViewport( 0, 0, config.screenX, config.screenY );
	glClearColor(0.96f, 0.96f, 0.86f, 1.0f);  // beige
	glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);	// clear screen and depth buffer

	persp_reshape();
	
	glMatrixMode(GL_MODELVIEW);
	glLoadIdentity();

	glPushMatrix();
	camera.setPerspective(); // position the camera

	// copy modelview matrix to vertex shader parameter
	modelViewMatrix = cgGetNamedParameter(cgv_program, "modelViewProj");
	if (modelViewMatrix == NULL)
		errorLog.OutputError("failed to bind matrix (NULL returned)");
	cgGLSetStateMatrixParameter(modelViewMatrix, CG_GL_MODELVIEW_PROJECTION_MATRIX, CG_GL_MATRIX_IDENTITY);

	// passthrough fragment program for initial render-to-texture
	cgGLLoadProgram(cgf_passthru);
	cgGLEnableProfile(CG_PROFILE_FP30);//cgf_profile);
	cgGLBindProgram(cgf_passthru);
	tex_2d = cgGetNamedParameter(cgf_passthru, "tex");

	// Draw objects
	// each Thing binds/unbinds its own texture in render()
	for (unsigned int i = 0; i < things.size(); ++i)
		things.render(true);

	// Draw floor
	glColor4f(1.0, 1.0, 1.0, 1.0);
	glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, wall_mat);
	cgGLSetTextureParameter(tex_2d, textures[0]);
	cgGLEnableTextureParameter(tex_2d);
	glBegin(GL_QUADS);
	glNormal3f(0.0f, 1.0f, 0.0f);
	glTexCoord2i(0, 0);
	glVertex3f(-100.0f, 0.0f, 100.0f);
	glTexCoord2i(1, 0);
	glVertex3f( 100.0f, 0.0f, 100.0f);
	glTexCoord2i(1, 1);
	glVertex3f( 100.0f, 0.0f, -200.0f);
	glTexCoord2i(0, 1);
	glVertex3f(-100.0f, 0.0f, -200.0f);
	glEnd();
	cgGLDisableTextureParameter(tex_2d);

	glPopMatrix();
	glFlush();

	// disable Cg profile
	cgGLDisableProfile(CG_PROFILE_FP30);

	// unbind framebuffer
	glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);

	//glDisable(GL_TEXTURE_2D);
	glDisable(GL_DEPTH_TEST);

	// Reset the screen and camera
	ortho_reshape();

	glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
	
	// Calculate uniform values (these don't change during shader execution)
	// User-controlled values are aperture, focaldistance, and planeinfocus

	// Calculate scale and bias (used to calculate CoC in fragment shader)
	GLdouble CoCscale = (lens.aperture * lens.focallength * lens.planeinfocus * (camera.zFar - camera.zNear)) /
						((lens.planeinfocus - lens.focallength) * camera.zNear * camera.zFar);
	GLdouble CoCbias = (lens.aperture * lens.focallength * (camera.zNear - lens.planeinfocus)) /
						((lens.planeinfocus * lens.focallength) * camera.zNear);

	// Enable the shader and set parameters
	cgGLLoadProgram(cgf_simpledof);
	cgGLEnableProfile(CG_PROFILE_FP30);//cgf_profile);
	cgGLBindProgram(cgf_simpledof);
	tex_color = cgGetNamedParameter(cgf_simpledof, "colortex");
	tex_depth = cgGetNamedParameter(cgf_simpledof, "depthtex");
	dofbias = cgGetNamedParameter(cgf_simpledof, "bias");
	dofscale = cgGetNamedParameter(cgf_simpledof, "scale");
	cgGLSetParameter1d(dofbias, CoCbias);
	cgGLSetParameter1d(dofscale, CoCscale);
	cgGLSetTextureParameter(tex_color, texid);
	cgGLSetTextureParameter(tex_depth, depth_rb);
	cgGLEnableTextureParameter(tex_color);
	cgGLEnableTextureParameter(tex_depth);

	// Bind framebuffer as texture
	glBindTexture(GL_TEXTURE_2D, texid);
	glGenerateMipmapEXT(GL_TEXTURE_2D); // automatically generate mipmaps

	// Render fullscreen quad w/ shader enabled
	glBegin(GL_QUADS);
	glTexCoord2f(0.f, 0.f);
	glVertex2i(0, 0);
	glTexCoord2f(1.f, 0.f);
	glVertex2i(config.screenX, 0);
	glTexCoord2f(1.f, 1.f);
	glVertex2i(config.screenX, config.screenY);
	glTexCoord2f(0.f, 1.f);
	glVertex2i(0, config.screenY);
	glEnd();

	// Disable the shader because we're done
	cgGLDisableTextureParameter(tex_depth);
	cgGLDisableTextureParameter(tex_color);
	cgGLDisableProfile(CG_PROFILE_FP30);	// Disable fragment profile
	cgGLDisableProfile(cgv_profile);	// Disable vertex profile

	glEnable(GL_DEPTH_TEST);
	glFlush();

Xanthos
Xanthos
I have noticed something strange in your code.
You seem to re-attach the color and depth buffers to the FBO each frame, but you are not generating a custum mipmap. You don`t need to do that with automatic mipmapping.

// obsolete?glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_TEXTURE_2D, texid, 0);glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, GL_RENDERBUFFER_EXT, depth_rb);


I think you mixed the two examples from the spec up(automatic and custom mipmapping). I don`t know if that is your problem. I have never used CG myself, so I could be totally off.

You could also have a problem with the mippmapping itself. Have you set the texture filters to LINEAR_MIPMAP_LINEAR?
like this:
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR_MIPMAP_LINEAR);


Also what exactly are your rendering results? Black screen, garbled textures or just no effect from the shader?
Cocalus
Cocalus
Quote:
Original post by Xanthos

glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR_MIPMAP_LINEAR);


You can't use Mipmaps for the Mag filter (I would think you would get an gl_error for it), you want

glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR_MIPMAP_LINEAR);

To be
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
mpt
mpt
Quote:
Original post by Xanthos
I have noticed something strange in your code.
You seem to re-attach the color and depth buffers to the FBO each frame, but you are not generating a custum mipmap. You don`t need to do that with automatic mipmapping.

// obsolete?glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_TEXTURE_2D, texid, 0);glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, GL_RENDERBUFFER_EXT, depth_rb);
The output is the same even when I comment out those lines. So that's not the problem.

Quote:
You could also have a problem with the mippmapping itself. Have you set the texture filters to LINEAR_MIPMAP_LINEAR?
like this:
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR_MIPMAP_LINEAR);

Also what exactly are your rendering results? Black screen, garbled textures or just no effect from the shader?
Whoops, I forgot to set those... but even with those set (well, with the Mag filter as GL_LINEAR) it still doesn't work properly.

It's not a black screen - the output changes strangely when I adjust the parameters. I know that the shader code is not the problem. I fiddled around with the shader output to try and see what it's reading from the depth buffer, and I've determined that, inside the shader at least, the depth buffer contains the same data as the color buffer. But that doesn't make any sense!

Am I passing the depth buffer to the shader incorrectly? I'm using the following code to pass its id:
	tex_depth = cgGetNamedParameter(cgf_simpledof, "depthtex");	cgGLSetTextureParameter(tex_depth, depth_rb);	cgGLEnableTextureParameter(tex_depth);

and the shader declaration is
      pixel simpledof(fragment IN,                      uniform float scale,                      uniform float bias,                      uniform sampler2D colortex,                      uniform sampler2D depthtex)

Topic Locked

This topic has been locked by a moderator. New replies are not allowed.

Sign in to reply to this topic.