I think a good and natural angular falloff for spotlight involves 2 things:
It should bound the light within the spot angle (the angle you set on light component)
It should falloff naturally from the maximum intensity (1.0) to minimum intensity (0.0).
One thing I don’t like about Unity LWRP’s angular falloff, that it shows a clear “ring” around the maximum intensity (1.0), and the “ring” persists even if you lower the light intensity (0.2).
I understand part of this is just how our eye perceive contrasts, but it feels wrong to me nonetheless, when compared to some real world lights (like the one on your phone, or street light).
So in my custom pipeline I went with something like this, I use a falloff that doesn’t reach its peak easily, so overall it’s much darker at default intensity (1.0), but even if I set the intensity much higher (4.0, 8.0), the light doesn’t “overblown” so easily.
My questions are:
(A) Does Spotlight angular falloff basically come down to creative choice? See wikipedia for how reflector focus light beams differently.
(B) Are there a general set of “good” angular falloff for different kind of spotlights? While the generally rules are func(saturate(cos(Angle) - cos(SpotLightAngle) / cos(PenumbraAngle) - cos(SpotLightAngle))), a torchlight can look very different from a street light.
(C) How do you implement multiple types of spotlights? Basically we need some way to distinguish one type of spotlight from another; but AFAIK, Unity Light component doesn’t allow for custom light type, so even though I can pass arbitrary number via light buffer, the pipeline can’t tell one type of spotlight from another, because I have no way to indicate that in Light component. Is attaching an extra component my only workaround?
I suspect the falloff on the LWRP/URP spot lights was chosen because it’s cheap to calculate vs any particular aesthetic choices, beyond having a variable inner falloff angle which is supported but currently not exposed as best I can tell.
In terms of what a spotlight looks like, there’s a lot of variability in the real world due to the reflectors, optics, and the aperture being used. It’s hard to support the full range of these efficiently. Unity’s built in lighting system uses cookies, which is an excellent way of supporting a lot of different looks, but isn’t as friendly to use or as efficient to render. What Unity has fairly well replicates a theoretically perfect reflector and aperture setup, albeit with a kind of ugly falloff curve on the cone. A smoothstep would go a long way in making it look less harsh.
@bgolus Thx, I think the problem comes down to how best pass the specific spotlight variant to pipeline. The lighting data is provided by SRP culling result, which gives us this:
(I am on 2018 LTS but it’s largely the same data)
At best we have Light component data, but not the GameObject, finding it at every frame is costly and caching light object is probably anti-pattern.
I think we will have to make do with a specific light function, and use light cookie creatively (Not currently supported in my custom SRP, will have to investigate).