Should lightmaps be effected by physicallyCorrectLights? (they are currently)
See original GitHub issueIn a scene with no lights, and no environment map I would expect an object with a lightmap to look quite close to the raytraced result in Blender when using a lightmap generated from that scene in Blender. (assuming you select a similar tone mapping and output encoding in both, and used an HDR lightmap).
With physicallyCorrectLights
disabled, the result is quite close:
left Three (Mozilla Hubs) | right Blender
with it enabled the object is a good deal darker than expected:
Digging into the code this difference makes sense as when physicallyCorrectLights
is disabled the lightmap value is multiplied by PI. https://github.com/mrdoob/three.js/blob/dev/src/renderers/shaders/ShaderChunk/lights_fragment_maps.glsl.js#L11
I admittedly don’t fully understand all the math going on here, but from what I understand the multiplication by PI here when physicallyCorrectLights
is disabled is to cancel out the multiplication by 1/PI in the BRDF_Diffuse_Lambert
, but does it actually make sense for 1/PI to be applied to lightmap data? Based on what I am seeing I am starting to think this is already “factored in” when raytracing the lightmap… I also noticed that with a MeshBasicMaterial the result is the same “correct” brightness whether or not physicallyCorrectLights
is enabled. I know it is an “unlit” material, but I would expect purely pre-computed indirect diffuse light to behave the same in either case with no other lighting in the scene.
There are a whole lot of factors at play in computing the final output color both in three and in Blender, so it’s possible there is something fundamentally incorrect about my assumption that things should even be able to look the same. But the fact that things look almost entirely correct when simply multiplying the lightmap values by PI (to cancel out the 1/PI) makes me think otherwise.
From reading through a lot of the discussions on the different iterations of the physically based lighting (and adding, removing, and adding again of the 1/PI term in the BRDFs) I kept running into @WestLangley and @bhouston, so maybe one of you two may be able to shed some light (pun intended) on the expected behavior here? I would also particularly like to understand what @WestLangley meant by // factor of PI should not be present; included here to prevent breakage
which was added as a comment many years ago and then subsequently propagated to a few other places, and eventually ended up now in the #ifndef PHYSICALLY_CORRECT_LIGHTS
I referenced above.
Its a bit tricky to provide a working example of this exact model since its using a GLTF with some custom extensions. I can put together a simplified example if it would be helpful but I don’t think the exact model or lightmap matters very much, its really a question of what precisely is the expected data in lightmaps and if that data should be effected by the physicallyCorrectLights
setting.
Issue Analytics
- State:
- Created 2 years ago
- Comments:24 (4 by maintainers)
Top GitHub Comments
@cptSwing
Well, this is unfortunate…
For
Physical
,Standard
,Phong
, andLambert
– materials that “respond to light” – light maps in three.js only brighten the scene.For
MeshBasicMaterial
, which does not respond to light, support for light maps was added long ago and retained for backwards-compatibility. In that case, if the product of the light map value and the light map intensity is less than 1, it will render darker than the equivalent scene having no light map at all.Granted, this is confusing, but it was a way to shoehorn light map support into
MeshBasicMaterial
.Sorry for butting in here, but as I’ve seen this mentioned a couple of times all over the web: This does not refer to the actual shader math when adding a lightmap texture’s effect to the render, does it? From my experimenting, a lightmap in threejs seems to be multiplied with the final result (ie darkening the underlying albedo), not adding to it, yes?