Skip to main content
gamedev.net
🔒 Locked

Deferred Shading

Started by Enalis Aug 4, 2006 at 8:44 AM 4 replies 800+ views
Original Post
Enalis
Enalis
As you may have noticed I've been working on various shader effects. It is now in my interest to start combining and I've decided that deferred shading is the way to go. I just need a good place to start opengl wise. I understand how to write the shaders such that it works. Now I need to know how to set up my program to do that.
Douglas Eugene Reisinger II
Projects/Profile Site
hplus0603
hplus0603
Figure out what all the inputs are that your shaders will need. This may include world position, diffuse color, specularity, power, normal, etc.

Figure out how many textures you'll need to store that information. You can store, for example, position + power in one texture, normal in one texture, and color + specularity in one texture.

Render these quantities to the textures using multiple render targets (or to framebuffer, one at a time, using glCopyTexSubImage() to create the textures).

Last, clear screen to black. For each light in the world, calculate the screen bounds of that light, and render a quad covering those pixels, binding the light shader, and feeding the data textures to that shader.

Done.
enum Bool { True, False, FileNotFound };
Enalis
Enalis
Thank you, I think I understand now. Seriously! :)
Douglas Eugene Reisinger II
Projects/Profile Site
Enalis
Enalis
Ok, next question:
I started setting up deferred shading, the orange book or gl shader language programming guide says to use glDrawBuffers. I've read otherplaces though that I should use framebuffers, I'm looking for the fastest method that is supported by nvidia and ati's latest cards (so I don't want nvidia specific or ati specific code). I also heard of rendering directly to textures or and just copying the framebuffer to texture. Which method is the fastest or most commonly used if I am doing an initial pass to store depth values, a shadow pass per object per light, and a lighting/parallax pass per object per light, and finally post processing like bloom/hdr. I need to be able to use floating point buffers that can go above 1.0f for each component for the hdr. In other worlds I need more than the standard 8-bit/channel buffer. I know that framebuffer objects do this but what else?
Douglas Eugene Reisinger II
Projects/Profile Site
Enalis
Enalis
My first attempt at the first step in deferred shading, it, looks all black. The three textured quads.

Drawing Code
// this takes in the buffers needed to render to (empty textures), the number of //  passes which I'll be taking out, and width and height, size of the texturevoid DrawEverythingMixed(GLuint *textures, int passes, int width, int height){	cVector3 camVec = cVector3((camera.xPos - camera.xView), (camera.yPos - camera.yView), (camera.zPos - camera.zView));	// setup our aux buffers	fullScreenShader.TurnOn();	unsigned int *buffs = new unsigned int[3];	buffs[0] = GL_BACK_LEFT;	buffs[1] = GL_AUX0;	buffs[2] = GL_AUX1;	glDrawBuffers(3, buffs);	glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);	glActiveTexture(GL_TEXTURE0);	glBindTexture(GL_TEXTURE_2D, parallaxTestTextures[NORMAL_TEXTURE]);	glActiveTexture(GL_TEXTURE1);	glBindTexture(GL_TEXTURE_2D, parallaxTestTextures[HEIGHT_TEXTURE]);	fullScreenShader.SetFloat("specular", GLSL_UNIFORM, 0.75f);	fullScreenShader.SetFloat3("lightColor", GLSL_UNIFORM, 1.0f, 1.0f, 0.2f);	fullScreenShader.SetInt("normalMap", 0);	fullScreenShader.SetInt("heightMap", 1);	DrawSomeCrap();	glBindTexture(GL_TEXTURE_2D, textures[0]);	glReadBuffer(GL_BACK_LEFT);	glCopyTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA16, 0, 0, width, height, 0);	glBindTexture(GL_TEXTURE_2D, textures[1]);	glReadBuffer(GL_AUX0);	glCopyTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA16, 0, 0, width, height, 0);	glBindTexture(GL_TEXTURE_2D, textures[2]);	glReadBuffer(GL_AUX1);	glCopyTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA16, 0, 0, width, height, 0);		fullScreenShader.TurnOff();	glEnable(GL_TEXTURE_2D);	glActiveTexture(GL_TEXTURE0);	glBindTexture(GL_TEXTURE_2D, textures[0]);	glPushMatrix();	glBegin(GL_QUADS);	glTexCoord2f(0.0f, 0.0f);	glVertex3f(-7.5f, 0.0f, 0.0f);	glTexCoord2f(1.0f, 0.0f);	glVertex3f(-2.5f, 0.0f, 0.0f);	glTexCoord2f(1.0f, 1.0f);	glVertex3f(-2.5f, 5.0f, 0.0f);	glTexCoord2f(0.0f, 1.0f);	glVertex3f(-7.5f, 5.0f, 0.0f);	glEnd();	glBindTexture(GL_TEXTURE_2D, textures[1]);	glPushMatrix();	glBegin(GL_QUADS);	glTexCoord2f(0.0f, 0.0f);	glVertex3f(-2.5f, 0.0f, 0.0f);	glTexCoord2f(1.0f, 0.0f);	glVertex3f(2.5f, 0.0f, 0.0f);	glTexCoord2f(1.0f, 1.0f);	glVertex3f(2.5f, 5.0f, 0.0f);	glTexCoord2f(0.0f, 1.0f);	glVertex3f(-2.5f, 5.0f, 0.0f);	glEnd();	glBindTexture(GL_TEXTURE_2D, textures[2]);	glPushMatrix();	glBegin(GL_QUADS);	glTexCoord2f(0.0f, 0.0f);	glVertex3f(2.5f, 0.0f, 0.0f);	glTexCoord2f(1.0f, 0.0f);	glVertex3f(7.5f, 0.0f, 0.0f);	glTexCoord2f(1.0f, 1.0f);	glVertex3f(7.5f, 5.0f, 0.0f);	glTexCoord2f(0.0f, 1.0f);	glVertex3f(2.5f, 5.0f, 0.0f);	glEnd();	glPopMatrix();	glActiveTexture(GL_TEXTURE0);}


Now the fullScreenShader
// vertexvarying vec4 pos;void main(void){	gl_Position = ftransform();	pos = gl_Position;//	normBase = gl_Normal * gl_ModelViewMatrix;	gl_TexCoord[0] = gl_MultiTexCoord0;}// fragmentvarying vec4 pos;uniform float specular;uniform vec3 lightColor;uniform sampler2D normalMap;uniform sampler2D heightMap;void main(void){	// draw the typical textured output to visual framebuffer	gl_FragData[0].rgb = normalize(texture2D(normalMap, gl_TexCoord[0].st).rgb);	gl_FragData[0].a = specular;	// write "normalized vertex depth" to the depthmap's alpha.	gl_FragData[1].xyz = pos.xyz;	gl_FragData[1].a = texture2D(heightMap, gl_TexCoord[0].st).r;	gl_FragData[2].xyz = lightColor;	gl_FragData[2].w = 1.0;}
Douglas Eugene Reisinger II
Projects/Profile Site

Topic Locked

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

Sign in to reply to this topic.