Search Unity

Inverse square fallof with unity lights.

Discussion in 'General Graphics' started by pointcache, Jun 20, 2016.

  1. pointcache

    pointcache

    Joined:
    Sep 22, 2012
    Posts:
    579
    Petter_G likes this.
  2. pointcache

    pointcache

    Joined:
    Sep 22, 2012
    Posts:
    579
    I dont know what this is

    The red area has almost exaclty same light amount, while green has steep fade, like a border, when in reality it has to be constant brightness loss like the pink line, without these "steps"
     
  3. Martin_H

    Martin_H

    Joined:
    Jul 11, 2015
    Posts:
    4,436
    @jack riddell : wasn't there something similar you had to deal with for your particle shader?
     
  4. jack-riddell

    jack-riddell

    Joined:
    Feb 11, 2014
    Posts:
    326
    Unity uses a lookup texture to calculate light falloff. it can roughly be approximated using this equation

    clamp(1.0 / (1.0 + (DistanceSquared *QuadraticAttenuation)) * (1 - (DistanceSquared / LightRange)), 0, 1)

    that equation isn't an exact match but it was close enough for this particle shader package
    https://www.assetstore.unity3d.com/en/#!/content/60561
    the attached videos will give you an idea of how close the lighting is
     
    NeatWolf likes this.
  5. raphael-ernaelsten-heaj

    raphael-ernaelsten-heaj

    Joined:
    Mar 9, 2016
    Posts:
    78
    Good question is : Where does that insanely come from???
     
  6. jack-riddell

    jack-riddell

    Joined:
    Feb 11, 2014
    Posts:
    326
    the issue is that inverse square never drops to 0 so at some point you need to cut it off, additionaly for artist control sometimes you want a bright light that has a limited range.
     
  7. raphael-ernaelsten-heaj

    raphael-ernaelsten-heaj

    Joined:
    Mar 9, 2016
    Posts:
    78
    A very straightforward implementation like (1.0f - saturate(distance/range))² would have done a better and more plausible job IMAO
    There must be reasons slipping out of hands...
     
  8. Martin_H

    Martin_H

    Joined:
    Jul 11, 2015
    Posts:
    4,436
    Maybe @Aras can shed some light (haha) on this.
     
  9. pointcache

    pointcache

    Joined:
    Sep 22, 2012
    Posts:
    579
    kekus majoris :) im glad im not the only one who sees the issue here, because in dark realistic games the lighting is crucial to level design, and having such unrealistic light is just .. well simply put not usable for realistic light. I could in theory replace all standard shaders with new lightmodel, but as i already did a lot of such stupid things that means insane amount of maintenance and complexity, which i dont have time for.
    So yeah, this needs to be fixed, or at least "real" lights be provided as alternative light model.
     
  10. OCASM

    OCASM

    Joined:
    Jan 12, 2011
    Posts:
    328
    For deferred you can do this:

    • Take \DefaultResourcesExtra\Internal-DeferredShading.shader and \CGIncludes\UnityDeferredLibrary.cginc and put them in a folder in your project.
    • Open UnityDeferredLibrary.cginc and after line 143 put this: atten = atten * atten;
    • Do that again after line 168 (before the little #else / #endif).
    • Go to Edit > Project Settings > Graphics. In the first option, "Deferred", select "Custom shader" and put your "Internal-DeferredShading.shader" in there.
    That's it.
     
    NeatWolf likes this.
  11. AcidArrow

    AcidArrow

    Joined:
    May 20, 2010
    Posts:
    11,799
    Enlighten also doesn't treat emissive surfaces as having inverse square falloff either (especially in gamma space).

    These things need a bit of sorting out.
     
  12. jack-riddell

    jack-riddell

    Joined:
    Feb 11, 2014
    Posts:
    326
    All the falloff is done using a lookup texture, if you found a way to replace it you might be able to fix all your light falloff problems?
     
  13. pointcache

    pointcache

    Joined:
    Sep 22, 2012
    Posts:
    579
    yeah like if i find a way to fix unity behavior i dont like, for example by decompiling whole engine and rebuilding it myself, i potentially could do that, doesnt mean its the smartest thing to do.
     
  14. NeatWolf

    NeatWolf

    Joined:
    Sep 27, 2013
    Posts:
    924
    Would it work with the combo forward+linear+shadowmap(lightmapped+realtime)+single pass stereo rendering (VR), of course by changing the appropriate files?

    Is it going to work with lightmapping as well (progressive)?

    I've found some interesting functions/lookup texture (Frostbite 4) I'd love to test.
     
  15. OCASM

    OCASM

    Joined:
    Jan 12, 2011
    Posts:
    328
    To be honest I don't know if that even works anymore. At this point I think it makes more sense to look into scriptable render pipelines, specially for experimentation.
     
    NeatWolf likes this.
  16. Reanimate_L

    Reanimate_L

    Joined:
    Oct 10, 2009
    Posts:
    2,788
    Last edited: Aug 23, 2018
    NeatWolf likes this.
  17. NeatWolf

    NeatWolf

    Joined:
    Sep 27, 2013
    Posts:
    924
    D'oh!

    I was hoping to have to change just the falloff function somewhere. I guess/hope writing some extremely simple RP is going to do the job, I should have a look at some tuts and have a crash course on it, hoping to find a -totally standard- template to build things from.

    If anyone else has a better, 2-4 lines long faster solution, I'd be glad to know it :)

    Under the hoods I see native physical light falloff and color temperature support - for realtime lights only, but getting to write a "simple" falloff function/lookup texture that works for both realtime and baked seems to be far from this.
     
  18. Reanimate_L

    Reanimate_L

    Joined:
    Oct 10, 2009
    Posts:
    2,788
    Adapting SRP might be the better way i guess, since legacy renderer system are quite a black box since the early version of unity version (i think, i totally forgot it's been too long). And they create SRP to open the black box to everyone
     
  19. NeatWolf

    NeatWolf

    Joined:
    Sep 27, 2013
    Posts:
    924
    I couldn't check the page before, looks like that's almost what I'm looking for.
    There's a really neat asset, Bakery that almost does the same (but, needs a totally different setup, i.e. new light Components and an still an early rough integration with realtime lights, it's very architectural focused on the lightmapper atm), but would love to achieve comparable results with what's already available.

    Inverse square with falloff is the closest match, I'm going to begin with that. Thanks for the hint! :)
     
  20. NeatWolf

    NeatWolf

    Joined:
    Sep 27, 2013
    Posts:
    924
    Ok, after some testing, here are the results.
    The whole scene is static, exception made for the spheres, strategically positioned near the center, near the falloff and slightly inside the Range value.

    This is currently working for baked lightmapping only, using the little snippet from the page suggested by @Reanimate_L
    To make it relevant, both direct and indirect lighting have been baked, so I switched to VertexLit rendering, Linear color space, Forward rendering, Hdr on, no tonemapping nor filters, Light Mix mode: Subtractive.

    There's a single light at the centre of the scene, intensity 1, ind.mul 1, mixed, soft baked shadows 0.1, realtime soft (of course not showing because of the settings)

    The lightmapper is the incremental one, with 64/64 samples, texel density 10, 4 bounces, no external lights/ambient lights contribution. A quick draft.

    For comparison:

    Legacy:


    Inv.Square with NO falloff (ideally infinite):


    Inv.Square (with falloff)


    no difference in baking time.
    Of course the dynamic objects (spheres) are not lit appropriately in the last screens, but possibly using Shadowmask mix mode they could inherit some of the probes contribution.

    Then, I got curious: what if I ramped up the intensity, as common for HDR scenes and light sources?

    Here's the "surprise". I set the intensity of the light to 4, always with Range 10.

    Legacy:


    Inv. square NO falloff:


    Inv.Square with falloff:


    Now, if you look closely, the last "no falloff" light gets clamped at 10 no matter what!
    This results in a hard light contour. So, probably for optimization reasons, Range still counts.

    So, I ramped up range to 1000000 (1M) and got an unexpected result:


    I lowered the radius to 1000 but the result was extra-splotchy, even after increasing the overall settings of the lightmapper.

    So, my assumption is that some weird scaling or math precision issue blows out at large ranges.

    My conclusion:
    just use the Inv square with falloff setting, which looks good enough, and probably benefits of some extra optimization with realtime shadows, especially when calculating shadowmaks for mixed lights.

    Now I should only try to replycate the fast tweak suggested by @OCASM, but for forward rendering - but since there's no such option I guess I'm going to scavenge a bit in the same foldere. I've seen Bakery doing the same thing, patching realtime lights by modifyng those files to make the realtime lights properly blend with his lightmapper.

    Fact is: I have no idea of the actual formula used to calculate the Inv.SquareWithFalloff!
    Has anyone got some official source or has "discovered" the way to calculate it properly?

    @Jack-riddel, do you believe it could be @raphael-ernaelsten-heaj's formula as suggested above?

    that is: (1.0f - saturate(distance/range))² ?
     
    Last edited: Aug 25, 2018
  21. NeatWolf

    NeatWolf

    Joined:
    Sep 27, 2013
    Posts:
    924
    Found it :)

    in AutoLight.inc:

    1)
    search for #ifdef POINT
    inside UNITY_LIGHT_ATTENUATION
    replace fixed destName = destName = tex2D(_LightTexture0, dot(lightCoord, lightCoord).rr).r * shadow; with fixed destName = <YourPointAttenFunc> * shadow;

    (...or with your own lookup texture :p)

    same for spotlights/cookie lights right below:

    2)
    search for #ifdef SPOT
    inside UNITY_LIGHT_ATTENUATION
    replace fixed destName = (lightCoord.z > 0) * UnitySpotCookie(lightCoord) * UnitySpotAttenuate(lightCoord.xyz) * shadow; with fixed destName = (lightCoord.z > 0) * UnitySpotCookie(lightCoord) * <YourSpotAttenFunc> * shadow;

    or at least, I guess so, I'm still in pinkshaderland with the SpotAttenFunc since I'd love to have it softer both in lenght and radius.
    I guess I'd also need to replace:
    Code (CSharp):
    1. inline fixed UnitySpotCookie(unityShadowCoord4 LightCoord)
    2. {
    3.     return tex2D(_LightTexture0, LightCoord.xy / LightCoord.w + 0.5).w;
    4. }
    ...but I feel I'm putting my hands where I shouldn't, I'm grabbing funcs from here and there without the required knowledge.
    Also, you know this better than me, these changes affect the whole Unity install.
    I'm going to begin tinkering on SRPs on another project :)