Deferred Shading: depth pass

Hi all

I wasn’t sure where to post this, since the topic is advanced but I am not an expert in OpenGL.

Anyways, here it goes.

I am working on a deferred shader and I am trying to get the depth pass working but so far I can’t manage to draw in the screen with the frame buffer.

Here is the code:






void initFBO(int w, int h){

	GLenum FBOstatus;

	glActiveTexture(GL_TEXTURE0);

	glGenTextures(1, &depthTexture);

	glBindTexture(GL_TEXTURE_2D, depthTexture);


	glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST );
	glTexParameterf( 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 );
	glTexImage2D( GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT, w, h, 0, GL_DEPTH_COMPONENT, GL_FLOAT, 0 );

	//create FBO
	glGenFramebuffers(1, &FBO);
	glBindFramebuffer(GL_FRAMEBUFFER, FBO);

	glBindTexture(GL_TEXTURE_2D, depthTexture);
	glFramebufferTexture2DEXT( GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, GL_TEXTURE_2D, depthTexture, 0 );

	FBOstatus = glCheckFramebufferStatus(GL_FRAMEBUFFER);
	if(FBOstatus != GL_FRAMEBUFFER_COMPLETE) {
		printf("GL_FRAMEBUFFER_COMPLETE failed, CANNOT use FBO
");
        checkFramebufferStatus(FBOstatus);
	}

	glClear(GL_DEPTH_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);
	glBindFramebuffer(GL_FRAMEBUFFER, 0);
	glBindTexture(GL_TEXTURE_2D, 0);
}

void draw_depth(){
	glBindTexture(GL_TEXTURE_2D, depthTexture);
	glDepthMask(true);
	glmDraw(model, GLM_NONE);
}

void bindFBO() {
    glDisable(GL_TEXTURE_2D);
	glBindTexture(GL_TEXTURE_2D,0); //Bad mojo to unbind the framebuffer using the texture
    glBindFramebuffer(GL_FRAMEBUFFER, FBO);
    glClear(GL_DEPTH_BUFFER_BIT);
    //glColorMask(false,false,false,false);
    glEnable(GL_DEPTH_TEST);
}
void setTextures() {
    glEnable(GL_TEXTURE_2D);
	glBindTexture(GL_TEXTURE_2D,0); 
    glBindFramebuffer(GL_FRAMEBUFFER, 0);

	//glColorMask(true,true,true,true);
    glDisable(GL_DEPTH_TEST);
	glClear(GL_COLOR_BUFFER_BIT);
}
void display(void){
	
	bindFBO();

	glCullFace(GL_BACK);
	glEnable(GL_CULL_FACE);
	glDisable(GL_BLEND);
	
	glEnable(GL_DEPTH);
	glEnable(GL_DEPTH_TEST);
	//glDepthFunc(GL_DEPTH_TEST);
	glDepthFunc(GL_LESS);
	glDepthRange(0.0, 1.0);

	glDisable(GL_TEXTURE_2D);
	glColor4f(1.0f,1.0f,1.0f,1.0f);
	glClearColor(0.0f,0.0f,0.0f,1.0f);
	//glClearDepth(1.0);
	glColorMask(true,true,true,true);
	//glDepthMask(true);

	
	glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

	glMatrixMode(GL_PROJECTION);
	glLoadIdentity();
	gluPerspective(50.0, 1.0, 0.1, 10000.0);
	glMatrixMode(GL_MODELVIEW);
    glLoadIdentity();
    gluLookAt(0.0f, 0.0f, 10.0f, 0.0f, 0.0f, -1.0f, 0.0f, 1.0f, 0.0f);
	
	setTextures();
	
	draw_depth();

	glutPostRedisplay();
	glutSwapBuffers();
}

void init() {
	glEnable(GL_DEPTH_TEST);
    glClearColor(0.0f, 0.0f, 0.0f,1.0f);
}

//Loads the model by calling the corresponding glm function
void loadModel(){
	
	char file_path[200];
	char filename[50];
	std::cin >> filename;
	
	strcpy(file_path,path);
	strcat(file_path,filename);
	model = glmReadOBJ(file_path);
}

int main (int argc, char* argv[])
{
	glutInit(&argc, argv);
	glutInitDisplayMode(GLUT_DOUBLE | GLUT_DEPTH | GLUT_RGBA);
    width = 600;
    height = 600;
	glutInitWindowSize(width,height);
	glutCreateWindow("Deferred Shading");
	//glewInit();
	GLenum err = glewInit();
	if (GLEW_OK != err)
	{
		/* Problem: glewInit failed, something is seriously wrong. */
		cout << "glewInit failed, aborting." << endl;
		exit (1);
	}
	cout << "Status: Using GLEW " << glewGetString(GLEW_VERSION) << endl;
	cout << "OpenGL version " << glGetString(GL_VERSION) << " supported
" << endl;

	initFBO(width, height);
	init();

	//getting and loading the model
	loadModel();
	while(!model){
		printf( "
Model wasn't loaded. Try again.
" );
		loadModel();
	}

	glutDisplayFunc(display);

	glutMainLoop();
	return 0;
}


My guess is that either I am doing something wrong in the display function or it has something to do with the obj loader i am using, which is glm and rather old. It uses glBegin and glEnd to draw, but I am not sure if this should be done in another way.

Thanks

I am now displaying something but it is not what would be expected of a depth pass for deferred shading.
Does anyone has any idea?

Thanks

I’ve never implemented a deferred renderer, but as I understand the theory, you don’t really do a “depth” pass. You record the depth as a part of the rest of the g-buffer rendering. It’s simply a natural out-growth of the first part of the deferred stage.

Right before glCheckFramebufferStatus() :


glDrawBuffer(GL_NONE);
glReadBuffer(GL_NONE);

But, in deferred rendering you need the g-buffer; so instead of 0 color textures, you need 2+.
You may do a depth-prepass with simplified shaders and disabled color-write, but the best speedup would rather be “anti-portals”.

Anti- portals?
Can you elaborate please!?

Just a very-low-poly version of the scene; without normals/textures - just vec3 position per vertex. Shouldn’t protrude or z-fight with the real scene objects. Aids HiZ/Zcull.
Can z-sort those triangles quickly for reverse-painters’ algo;
Can use occlusion-queries a bit faster, too. (Or get even much faster occlusion-q results if you render into a smaller viewport).

Isn’t one of the benefits of deferred rendering that you don’t need to do that, since you only run the expensive fragment programs on exactly and only the visible samples?

Or are you trying to save the fillrate from writing a (potentially large) number of outputs?

I found this reference useful when implementing deferred rendering:

Deferred rendering in Stalker

I don’t understand the use of a depth pass, sounds like a different algorithm… Do you have a reference for what you’re up to?

Exactly, each pixel gets the full shader only once per light, no penalty for high depth complexity.

Works well with additive translucency effects like fire, light glow, etc… Never figured how to do lit transparency, though…

Also, since depth is certainly one of the things you will likely write to the gbuffer (you will use this later to get your world X,Y,Z pixel position), maybe that is what you are trying to visualize? Which is very difficult since the buffer is very nonlinear in z. You might need to scale the buffer nonlinearly to see anything that is in it. Most of the interesting values will be very near 1.0, I believe (or zero if I have forgotten)…

Or are you trying to save the fillrate from writing a (potentially large) number of outputs?

exactly.

There’s a LOT of tricks you can do to reduce the required number of targets. Under my renderer, the shapes/normals are rendered in one pass and then in the next the diffuse/specular/emissive are drawn out. The emissive is then abused as an accumulation buffer for the lighting passes.