gazebosim / gz-rendering

C++ library designed to provide an abstraction for different rendering engines. It offers unified APIs for creating 3D graphics applications.
https://gazebosim.org
Apache License 2.0
56 stars 51 forks source link

Point light attenuation/falloff does not work when cast_shadows is enabled #591

Open azeey opened 2 years ago

azeey commented 2 years ago

Environment

Description

with cast_shadows = true, I get a sharp circle determined by the range (4m) of the light. image

with cast_shadows = false, the light falls of smoothly, but the box does not have a shadow. image

Steps to reproduce

  1. Run the attached file (test.sdf.txt) in ign gazebo.
  2. Change <cast_shadows> to true or false.
darksylinc commented 2 years ago

This may actually be a different (but related) error.

Without cast_shadows

When cast_shadows is disabled Forward+ (from now on F+) algorithm is used by the lighting system. Very big lights can cause severe performance degradation; but small lights usually end up cut "abruptly".

Lights theoretically travel through infinity, so any radius that limits is range is going to be arbitrary. Using Light::setAttenuationBasedOnRadius helps cutting the arbitrariness by providing a minimum luminance threshold (i.e. pretend the light cuts off once % of luminance is reached) but it still gives you less flexibility.

As a hack/workaround, ForwardPlusBase::setFadeAttenuationRange is enabled by default; which will smoothly attenuate when getting close to the light's radius; regardless of PBR parameters of physical attenuation.

TL;DR The light's attenuation settings are honoured, but an extra (much more aggressive) fade is applied on top unless ForwardPlusBase::setFadeAttenuationRange( false ) is called.

The range is not part of the attenuation equation. but setFadeAttenuationRange( true ) (the default setting) hacks it on top to be considered.

With cast_shadows

When cast_shadows is enabled, regular Forward is used (without the +). Because in this case light's size has no direct impact on performance; we don't use the hack; and the light's attenuation settings are honoured without any hacks.

The range is not part of the attenuation equation.

Solution?

That will depend on the intention. The physically correct solution is to call setFadeAttenuationRange( false ) and either use a very aggressive attenuation or a very large radius to avoid blockiness-like artifacts (light curring suddenly)

Other solutions is to just be aware of this and tweak the attenuation until they both agree.

jrutgeer commented 1 year ago

Expected behavior: Point light attenuation/falloff to work regardless of cast_shadows.

I can confirm that is is not only related to point lights: spot light shows the same behaviour (left with, right without shadow):

image