PDA

View Full Version : using nvidia HW PCF



Dragon89
05-27-2007, 04:49 AM
how would on use nvidia hw pcf?

also im unsure how i would use a regular depthmap for shadowmaps.. right now i simply convert the depth to fit a rgba8 texture liek this...


//FBO
size = 2048.0;
GLint type = GL_RGBA8;

glActiveTexture(GL_TEXTURE10);

// Setup our FBO
glGenFramebuffersEXT(1, &fbo);
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, fbo);

// Create the render buffer for depth
glGenRenderbuffersEXT(1, &depthBuffer);
glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, depthBuffer);
glRenderbufferStorageEXT(GL_RENDERBUFFER_EXT, GL_DEPTH_COMPONENT, size, size);

// Now setup a texture to render to
glGenTextures(1, &img);
glBindTexture(GL_TEXTURE_2D, img);
glTexImage2D(GL_TEXTURE_2D, 0, type, size, size, 0, GL_RGB, GL_UNSIGNED_BYTE, NULL);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);



// And attach it to the FBO so we can render to it
glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_TEXTURE_2D, img, 0);

// Attach the depth render buffer to the FBO as it's depth attachment
glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, GL_RENDERBUFFER_EXT, depthBuffer);

glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0); // Unbind the FBO for now

GLenum status = glCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT);

/// WRITE TO SHADOWMAP

// FRAGMENT

varying float Depth;

void main()
{
const vec4 bitSh = vec4( 256*256*256, 256*256, 256, 1);
const vec4 bitMsk = vec4( 0, 1.0/256.0, 1.0/256.0, 1.0/256.0);

float dist = Depth;

vec4 comp;
comp=dist*bitSh;

comp=fract(comp);
comp-=comp.xxyz*bitMsk;

gl_FragColor= vec4(comp);

}

// CALCULATE SHADOWS

// FRAGMENT

varying vec4 ProjShadow;
varying float Depth;

uniform sampler2D Shadow;


const vec4 bitShifts = vec4(1.0/(256.0*256.0*256.0),1.0/(256.0*256.0), 1.0/256.0, 1);

float GetShadow(vec2 TexCoord)
{
vec4 shadmap = texture2D(Shadow,TexCoord);
float shad = dot(shadmap , bitShifts);
return (shad < Depth+0.0065);
}




i dont think is the best way to do it... but as i said im unsure how to write to a 32bit depthmap and use HW pcf

martinsm
05-27-2007, 05:16 AM
I think nvidia hw pcf is ONLY available to textures with GL_DEPTH_COMPONENT internal format and GL_LINEAR min/mag filter.

Dragon89
05-27-2007, 05:21 AM
ok.. but my problem is taht i dont know how to use GL_DEPTH_COMPONENT... how do i send info to it in the fragment shader? does it work with glortho where near = 0.0 and far = 1.0... what settings should the FBO use?

Vexator
05-27-2007, 05:39 AM
for your fbo you should use perspective projection. when creating your depth texture set these parameters:


glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_COMPARE_FUNC, GL_LEQUAL );
glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_COMPARE_MODE, GL_COMPARE_R_TO_TEXTURE );in your fragment shader you can then declare your texture as sampler2DShadow instead of the regular sampler2D. this will automatically perform the depth comparison for you.

Dragon89
05-27-2007, 06:25 AM
Originally posted by Vexator:
for your fbo you should use perspective projection. when creating your depth texture set these parameters:


glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_COMPARE_FUNC, GL_LEQUAL );
glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_COMPARE_MODE, GL_COMPARE_R_TO_TEXTURE );in your fragment shader you can then declare your texture as sampler2DShadow instead of the regular sampler2D. this will automatically perform the depth comparison for you. so basicly is et the FBO liek this..


size = 2048.0;
GLint type = GL_DEPTH_COMPONENT;

glActiveTexture(GL_TEXTURE10);

// Setup our FBO
glGenFramebuffersEXT(1, &amp;fbo);
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, fbo);

// Create the render buffer for depth
glGenRenderbuffersEXT(1, &amp;depthBuffer);
glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, depthBuffer);
glRenderbufferStorageEXT(GL_RENDERBUFFER_EXT, GL_DEPTH_COMPONENT, size, size);

// Now setup a texture to render to
glGenTextures(1, &amp;img);
glBindTexture(GL_TEXTURE_2D, img);
glTexImage2D(GL_TEXTURE_2D, 0, type, size, size, 0, type, GL_UNSIGNED_BYTE, NULL);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);

glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_COMPARE_FUNC, GL_LEQUAL );
glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_COMPARE_MODE, GL_COMPARE_R_TO_TEXTURE );

// And attach it to the FBO so we can render to it
glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_TEXTURE_2D, img, 0);

// Attach the depth render buffer to the FBO as it's depth attachment
glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, GL_RENDERBUFFER_EXT, depthBuffer);

glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0); // Unbind the FBO for now

GLenum status = glCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT); but how do i set up the shader when rendering to the FBO... is it just gl_FragColor = Depth... ?how are the values stored in the depth buffer.. are they 0.0-1.0 or realworld values?

also i want to use ortho projection since my lightsource is parallel...

when i call the shadow2Dproj function in the shader are they with pcf or only with bilinear filtering?

Dragon89
05-27-2007, 11:30 AM
just as a side note... how would i do bilinear filtering in the fragment shader.. i think ive got pcf right..


float shadow = GetPCF(ProjShadow.xy/ProjShadow.w);
float GetShadow(vec2 TexCoord)
{
vec4 shadmap = texture2D(Shadow,TexCoord);
float shad = dot(shadmap , bitShifts);
return (shad < Depth+0.0058);
}

float GetPCF(vec2 TexCoord)
{
float offset = 1.0/512.0;
float shadow1 = 0.0;
shadow1 += GetShadow(TexCoord+vec2(-offset ,offset));
shadow1 += GetShadow(TexCoord+vec2(0 ,offset));
shadow1 += GetShadow(TexCoord+vec2(offset ,offset));
shadow1 += GetShadow(TexCoord+vec2(-offset ,0));
shadow1 += GetShadow(TexCoord+vec2(0 ,0));
shadow1 += GetShadow(TexCoord+vec2(offset ,0));
shadow1 += GetShadow(TexCoord+vec2(-offset ,-offset));
shadow1 += GetShadow(TexCoord+vec2(0 ,-offset));
shadow1 += GetShadow(TexCoord+vec2(offset ,-offset));
shadow1 /= 9.0;

return shadow1;
}

Korval
05-27-2007, 02:04 PM
In PCF, you don't filter the color. You filter the results of the comparison.

So if you're in the middle of a 2x2 texel quad, and 3 of them say "not shadow" and one of them says "shadow", the number you should use to multiply against the light color is "0.75".

Further, you only need 4 accesses for bilinear, not 9. And the average should be weighted based on how close the offset is to each texel.

Dragon89
05-27-2007, 02:24 PM
i guess my code was a bit unclear.. the function GetShadow return either 1 or 0 depending on if the color is in shadow or not...which is correct pcf right?

but i sitll dontknow how to do the bilnear filtering.. do i filter the depth values from the shadowmap? or the result from the pcf filtering? also i have no idea how to calculate the weigth or the offsets needed for bilinear filtering... ive tried simply using 1/shadowmap size as offset... which might be right,, but i still dont know how to get the weights... also isnt the offsets somehow related to the pcf filtering?

Dragon89
05-29-2007, 05:05 AM
ok.. ive converted my shadowmap into the rgba16 format...and simply put the depth intto single colorchannel... which should support linear filtering.. and ive set the filtering mode to GL_LINEAR.. but it still doesnt look good.. what am i doin wrong?

http://img260.imageshack.us/img260/3621/49118329al5.jpg

ZbuffeR
05-29-2007, 11:01 AM
http://www.opengl.org/cgi-bin/ubb/ultimatebb.cgi?ubb=get_topic&f=3&t=015245#000001