# Dual Paraboloid shadow mapping and tesselataion issue

This topic is 2462 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

## Recommended Posts

I was expecting to have issue with tesselation and dual paraboloids mapping before using this technique, but such a worse result was not expected at all. Seams can be easily seen on this screenshot: And it comes with such tesselation: It's becoming even worse when light is close to shadow receivers. Just for infromation, maybe it's important, i'm using VSM and shadow map resolution is limited to 1024x1024.

##### Share on other sites
Hi! Yes, it's very hard to get high quality results. The first thing I'd point out is that your floor shouldn't need to be tesselated at all (unless it's going to be casting on something else).

That paper talks about the simple fix so that you don't need to tesselate receivers (only casters). The basic idea is that you do the WorldSpace -> Paraboloid transformation in the pixel shader during your lighting pass. That avoids having the paraboloid co-ordinates interpolated incorrectly.

You still might have some problems, though ... I can't really tell if that table is going to cast correct shadows. I think it will, but I'd like to see new screen shots after you move the shadow lookup math into the pixel shader. Good luck!

##### Share on other sites
Thanks for the link! Exactly what I was looking for. I'll post how it will work.

##### Share on other sites
Shadow lookup done correctly with transformation inside pixel shader. Issue in generation phase where I simply use HLSL's clip function to cull pixels that dont belong to needed hemisphere, looks like culling should be done using alpha test as in Brabec's paper.
Tesselating casters on hardware is not possible for me as I limited to DX9, actually dont understand their logic - hardware tesselation requires geometric shaders but if you have them you can render to cubemap in one render instead of six, than why one will be using paraboloids, as even for hemisphere light cubemap would be a better solution.
In worst case I'll be using paraboloid only for hemispherical lights, it's much faster than cubemap anyway on DX9.

[Edited by - Viik on November 29, 2008 4:03:03 PM]

##### Share on other sites
Yes, I think you should use the alpha-test technique to do the clipping. When we mentioned the hardware tesselation, we were actually talking about Xbox 360. That's still DX9 hardware (no geometry shaders), but the GPU can do automatic tesselation. For PCs, you're right that it doesn't make much sense.

Even with some of the changes you must make, it's definitely faster than using cubemaps!

##### Share on other sites
Maybe one point to note as well is that you don't even need to worry about the cracks between paraboloids if you just point one of the paraboloids downward. Then the crack will by somewhere like the equator of your scene, where it will likely be much less noticeable.

##### Share on other sites
Quote:
 Maybe one point to note as well is that you don't even need to worry about the cracks between paraboloids if you just point one of the paraboloids downward. Then the crack will by somewhere like the equator of your scene, where it will likely be much less noticeable.

That's definately an option. Especially for static lights. Just want to achive more "general" solution.
I'm getting better results with "culling" on shadow lookup phase instead of depth render phase.
Didnt used "alpha" approach like in Brabeck's paper - as I see it requires to store separate alpha on depth render phase. I'm using VSM and that's already consumes G32R32F texture, adding alpha would require 4 channel buffer and two of them would be wasted (32 bit for alpha is too much) and actually two such textures needed. So, I completely droped culling on depth render and did a proper texture lookup on shadow render, choosing proper paraboloid texture. It works quite OK, but there are still small bug:

"Small black line just under the light" - it's solely because of the choosing right "texture", it's still there with/without blur or VSM.

float3	LightVec = normalize(IN.pos - LightPos);	float3  P = mul(LightVec, (float3x3)ParaboloidBasis);	float	myDepth = length(IN.pos - LightPos);	float2	moments;	bool	branch = (P.z >= 0.0f); //forward or backward	if(branch)	{		float2 	front;			front.x = (P.x / (2*(1 + P.z))) + 0.5;			front.y = 1-((P.y / (2*(1 + P.z))) + 0.5);		float2 	forward = tex2D(ShadowSampler, front).xy;			moments = forward;	}	else	{		float2 	back;			back.x = (P.x / (2*(1 - P.z))) + 0.5;			back.y = 1-((P.y / (2*(1 - P.z))) + 0.5);		float2 	backward = tex2D(ShadowSampler, back).zw;			moments = backward;	}	float	VSM = VSMFactor(moments, myDepth);

Quote:
 ...When we mentioned the hardware tesselation, we were actually talking about Xbox 360. That's still DX9 hardware (no geometry shaders), but the GPU can do automatic tesselation. For PCs, you're right that it doesn't make much sense.Even with some of the changes you must make, it's definitely faster than using cubemaps!

Didn't realized that it's actually your article ))) Missed a last paragraph where you mention that it's form Xbox 360.
According to your article, correct blurring of paraboloid might be an expensive operation. I used guassian separate blur of 5x5 tap in texture space. If I do it in paraboloid space that would lead to at least 10 vector x matrix multiplications, to get all needed samples.

[Edited by - Viik on December 1, 2008 7:34:43 AM]

##### Share on other sites
Haha. I wouldn't worry about "correct blurring". We never implemented that. We used PCF on a previous game, and we're using VSM now, with a regular (texture-space) 5x5 separable gaussian blur. I'm not sure about that black line. Our lookup is done very similar to yours (we have both hemispheres in a single texture, and pick the correct one + lookup in the pixel shader).

Of course, we still have light cracks between the hemispheres, but we always rotate our lights so that the hemispheres point "up" and "down". Most of our lights are above the scene, so it's rare that people can see the crack. It's still on our list of things to debug, although we've tried several times without luck. =(

##### Share on other sites
Small black line was because of the black border used in sampler. Now it works like a sharm, except sometimes on depth render stage geometry from back paraboloid projected on front (i'm not using any kind of clipping), but that would be easy to fix just do clipping with small bias.
Thanks again to everybody for your help.

##### Share on other sites
Hi Viik,
How did you perform the transformation in the pixel shader?
Are you supposed to just code the world position transformation code in the pixel shader instead of the vertex shader?
When I tried this, the texture just comes out black. Btw, I am still not up to the shadow mapping phase of dual paraboloid (still just testing the reflection mapping) so forgive me if this is not in the correct topic.

 DPOutput DP_VS(float3 pos : POSITION0, float3 normal : NORMAL0, float2 texcoord: TEXCOORD0) { DPOutput output = (DPOutput)0; float4 posWorld = mul(float4(pos,1), World); float4 viewPos = mul(posWorld, View); output.Position = mul(float4(pos,1.0f), WorldViewProj); output.Texcoords = texcoord; output.Normal = mul(float4(normal,0), (float3x3)WorldInvTrans); output.WorldPos = posWorld; output.Position = output.Position/output.Position.w; output.Position.z = output.Position.z*Direction; float L = length(output.Position.xyz); output.Position = output.Position/L; output.z = output.Position.z; output.Position.z = output.Position.z + 1; output.Position.x = output.Position.x/output.Position.z; output.Position.y = output.Position.y/output.Position.z; output.Position.z = (L - 0.1f)/(1000-0.1f); output.Position.w = 1; return output; } 

Thanks,

Gary

1. 1
Rutin
29
2. 2
3. 3
4. 4
5. 5

• 13
• 13
• 11
• 10
• 13
• ### Forum Statistics

• Total Topics
632959
• Total Posts
3009467
• ### Who's Online (See full list)

There are no registered users currently online

×