• 13
• 27
• 9
• 9
• 20

# Deferred Shading: point light and bounding volume

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

## Recommended Posts

I'm implementing a simple deferred shading demo in DirectX11, taking inspiration from some know papers and this tutorial made for XNA.
Below you can see three screanshot of the demo, taken in three different modes, and the problem that I've is on the third mode:
1) Standard rendering
2) Deferred rendering, for each light a full screen pass is made. In this mode I obtains a frame rate more slow than standard rendering.

3) Deferred rendering, for each light I define a bounding volume (sphere), and I computes the illumination only on the geometry that is in this volume. But the result is horrible.

So the question is: where is the problem? What I'm doing is wrong?
Thanks.

##### Share on other sites
You'll need to apply an attenuation to the lighting that takes into consideration the size of the bounding sphere.
So the lighting won't appear to be "clipped", it will gradually fade out.

##### Share on other sites

You'll need to apply an attenuation to the lighting that takes into consideration the size of the bounding sphere.
So the lighting won't appear to be "clipped", it will gradually fade out.

I'm doing that but the result is the same, this is a piece of the PS (a very similar code is present on the tutorial that I've linked):

 // Attenuation float fAtten = 1.0 / dot(Attenuation, float3(1, lightDist, lightDist * lightDist)); // Diffuse output += max(0, (lightColor * dot(float4(normal, 1.f), lightDir) * fAtten)); // Specular output += max(0, (lightColor * specularIntensity * pow(dot(float4(normal, 1.f), halfAngle), specularPower) * fAtten)); float volumeAttenuation = saturate(1.0f - lightDist / lightRadius); return output * volumeAttenuation; 

##### Share on other sites

 // Attenuation float fAtten = 1.0 / dot(Attenuation, float3(1, lightDist, lightDist * lightDist)); // Diffuse output += max(0, (lightColor * dot(float4(normal, 1.f), lightDir) * fAtten)); // Specular output += max(0, (lightColor * specularIntensity * pow(dot(float4(normal, 1.f), halfAngle), specularPower) * fAtten)); float volumeAttenuation = saturate(1.0f - lightDist / lightRadius); return output * volumeAttenuation; 

I can only guess that your lightRadius value is too large, though this shouldn't be the case. Have you tried scaling it to see the effect it has?

##### Share on other sites

I can only guess that your lightRadius value is too large, though this shouldn't be the case. Have you tried scaling it to see the effect it has?

I'll show you two example:
- This with a lightRadius of 0.5f
]

- This with a lightRadius of 50.f

Maybe there's also a blending problem?

##### Share on other sites

[quote name='MajorTom' timestamp='1304808032' post='4807831']
I can only guess that your lightRadius value is too large, though this shouldn't be the case. Have you tried scaling it to see the effect it has?

I'll show you two example:
- This with a lightRadius of 0.5f
]

- This with a lightRadius of 50.f

Maybe there's also a blending problem?
[/quote]

It doesn't appear to be a blending problem. Try scaling the value in the shader i.e lightRadius*0.1f. Rather than scaling the geometry.
This might tell us if there's an issue with the attenuation code. It does seem a little odd though.

Are you applying the ambient lighting term for each light source? This would cause sharp edges also, as it's a constant value.
This should either be a single fullscreen pass or the colour used when clearing the render target. Just an idea.

##### Share on other sites
I've tried to use the same PS code presented in the tutorial that I've linked in the first post, this is the code:

 float4 PS(VS_OUTPUT input) : SV_TARGET0 { //obtain screen position input.screenPosition.xy /= input.screenPosition.w; //obtain textureCoordinates corresponding to the current pixel //the screen coordinates are in [-1,1]*[1,-1] //the texture coordinates need to be in [0,1]*[0,1] float2 texCoord = 0.5f * (float2(input.screenPosition.x,-input.screenPosition.y) + 1); //get normal data from the normalMap float4 normalData = normalTexture.Sample(pointSampler, texCoord); //tranform normal back into [-1,1] range float3 normal = 2.0f * normalData.xyz - 1.0f; //get specular power float specularPower = normalData.a * 255; //get specular intensity from the colorMap float specularIntensity = colorTexture.Sample(linearSampler, texCoord).a; //read depth float depthVal = depthTexture.Sample(pointSampler, texCoord).r; //compute screen-space position float4 position; position.xy = input.screenPosition.xy; position.z = depthVal; position.w = 1.0f; //transform to world space position = mul(position, InvertViewProjection); position /= position.w; //surface-to-light vector float3 lightVector = lightPosition - position; //compute attenuation based on distance - linear attenuation float attenuation = saturate(1.0f - length(lightVector)/lightRadius); //normalize light vector lightVector = normalize(lightVector); //compute diffuse light float NdL = max(0,dot(normal,lightVector)); float3 diffuseLight = NdL * Color.rgb; //reflection vector float3 reflectionVector = normalize(reflect(-lightVector, normal)); //camera-to-surface vector float3 directionToCamera = normalize(cameraPosition - position); //compute specular light float specularLight = specularIntensity * pow( saturate(dot(reflectionVector, directionToCamera)), specularPower); //take into account attenuation and lightIntensity. return attenuation * lightIntensity * float4(diffuseLight.rgb,specularLight); } 

and this is a result with a radius of 15.f:

I think that this code have some problems, and the attenuation is not correct. Some suggestions?
Thanks.

Edit: If you watch the screenshot you can see that the columns at the bottom have the same light intensity applied.

##### Share on other sites
Attenuation is supposed to have 3-components rather than 1 like you do it.

float fAtten = 1.0/dot(LightAttenuation, float4(1, fLightDist, fLightDist*fLightDist,0));

Thats how I'm doing it, and I get nice results. You have to try around a bit, but basically you set LightAtenuation in your application as a 4-component-vector, and set the 4th component to 0. But playing around with the other components will give you the effect that you want. Have a read here: MSDN

##### Share on other sites

Attenuation is supposed to have 3-components rather than 1 like you do it.

float fAtten = 1.0/dot(LightAttenuation, float4(1, fLightDist, fLightDist*fLightDist,0));

Thats how I'm doing it, and I get nice results. You have to try around a bit, but basically you set LightAtenuation in your application as a 4-component-vector, and set the 4th component to 0. But playing around with the other components will give you the effect that you want. Have a read here: MSDN

Yes, it's true. Infact in my past code I've used the formula that you've posted.
With this the attenuation works fine (as you can see in the screenshot), but I've the same cutting edge effect. How can I solve that? I must tune the attenuation parameters?