Sign in to follow this  
DigiBen

Unity Yann's Lerp Shadow Mapping Technique

Recommended Posts

DigiBen    144
I was reading the other day about shadows on gamedev and came around the posts that Yann made for getting good results for shadow mapping. He gave some basic psuedo code for doing a type of PCF shadow mapping, but instead of just taking surrounding pixels of the shadow map and adding them together, he does a linear interpolation of some sort. I tried doing something like that with GLSL with the small snippet he gave (and the other person corrected). Here is the post: http://www.gamedev.net/community/forums/topic.asp?topic_id=256459 The other person posting named Ysaneya showed pictures on how his shadow mapping was banding too much. So Yann gave this code (after Ysaneya's corrections):
// Offset the texcoords by half a texel
ofstex = fragment.texcoord[0] - (0.5 / mapsize)

// Texel size
tsize = 1.0 / mapsize

// Get four shadowmap samples at the corners
s1 = ShadowSample(ofstex.x, ofstex.y)
s2 = ShadowSample(ofstex.x+tsize.x, ofstex.y)
s3 = ShadowSample(ofstex.x, ofstex.y+tsize.y)
s4 = ShadowSample(ofstex.x+tsize.x, ofstex.y+tsize.y)

// Get the fractional xy position of the fragment within the texel
fpos = fraction(fragment.texcoord[0] * mapsize)

// Interpolate the texel shadow factor
r1 = lerp(s1, s2, fpos.x)
r2 = lerp(s3, s4, fpos.x)
shadowfactor = lerp(r2, r1, fpos.y)
I tried to do this in GLSL and got this:
void main ()
{
	vec4 color = gl_Color;

	vec3 shadowUV_OG = projCoord.xyz / projCoord.q;

	vec3 shadowUV = shadowUV_OG - (0.5 / 512.0);
	
	float mapScale = 1.0 / 512.0;
 
	vec4 s1 = shadow2D(shadowMap, shadowUV);
	vec4 s2 = shadow2D(shadowMap, shadowUV.xyz + vec3( mapScale,        0,0));
       	vec4 s3 = shadow2D(shadowMap, shadowUV.xyz + vec3(        0, mapScale,0));
       	vec4 s4 = shadow2D(shadowMap, shadowUV.xyz + vec3( mapScale, mapScale,0));
	
	vec3 fractPos = fract(shadowUV_OG * 512.0);

	float r1 = s1.x + fractPos.x * (s2.x - s1.x);
	float r2 = s3.x + fractPos.x * (s4.x - s3.x);
	float shadowFactor = r2 + fractPos.y * (r1 - r2);

	gl_FragColor = color * shadowFactor;
}
But I get these results on shadows (this is a sphere's shadow): Is my interpretation of the psuedo code wrong? I am not sure about the fract() function in GLSL if that is what he means. Any help would be great.

Share this post


Link to post
Share on other sites
Guest Anonymous Poster   
Guest Anonymous Poster
I might be way off, but just by looking at the screen shot, it seems to me that the interpolation weights are inverted.

Share this post


Link to post
Share on other sites
Guest Anonymous Poster   
Guest Anonymous Poster
Try:
float r1 = s2.x + fractPos.x * (s1.x - s2.x);
float r2 = s4.x + fractPos.x * (s3.x - s4.x);

Share this post


Link to post
Share on other sites
DigiBen    144
Hey cool, that KINDA worked :)

Now it looks like this:





It looks like there is shaded spheres in the outside pixels. Weird. If you look at the other guy's pictures in the post I mention at the top, the Coliseum image has banding, but the guy said it looked better than the bands but didn't give a final image. I imagine it looked better than this :) Any thoughts?

Share this post


Link to post
Share on other sites
Guest Anonymous Poster   
Guest Anonymous Poster
Looking at your pic again, it seems like your shadow map resolution is alot less than 512.
I suggest that you change the shader constants to the resoultion of your texture.

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this