Open will-ca opened 2 years ago
Some additional note: This is probably not only for KHR_materials_emissive_strength (this extension is used only when factor > 1.0), but also for emissive factor (used when factor < 1.0)
Note that currently Three.JS, Babylon.JS, and the Khronos Viewer do not have exposure settings that display spec-compliant, physically-unitted luminances correctly by default.
The babylon.js and Khronos viewers do have (presumably correct) exposure options, but those sliders are not prominent in the UI. I'll add something similar to my three.js viewer soon. Auto exposure is certainly harder, so the issue remains that any scene exported with physically-based light units will probably need a manual exposure adjustment in viewers. Agreed that testing in Filament is likely to be a good choice.
I agree that supporting similar physical vs. unitless modes (as in https://github.com/KhronosGroup/glTF-Blender-IO/pull/1760) is likely to be useful for emissive.
I'm probably going to leave this for now, but FYI similarly to #1760, emissivity strengths will almost certainly also need to be adjusted to be spec compliant.
TL;DR What needs to be done:
Make sure
KHR_materials_emissive_strength
is being used.683/(2π)
. (UsePBR_WATTS_TO_LUMENS
constant defined for #1760.)2π
.That should look right. If it doesn't (and it may not), then everything below will need to be checked:
Target unit is cd/m^2 (nits). https://gltf-transform.donmccurdy.com/classes/extensions.materialsemissivestrength.html
Output should be something like the multiplication of Strength with... Actually, just strength, I guess, since Factor and Texture can map directly to the exported file... Or leave Strength the same but convert Factor? Either way: All three of Factor, Texture, and Strength need to be included, and a conversion coefficient needs to be applied exactly once to exactly one of them. https://github.com/KhronosGroup/gltf/tree/main/extensions/2.0/Khronos/KHR_materials_emissive_strength#physical-units https://registry.khronos.org/glTF/specs/2.0/glTF-2.0.html#additional-textures
Blender uses W/m^2. https://docs.blender.org/manual/en/latest/render/shader_nodes/shader/emission.html
If it is necessary to experimentally validate the unit on the Blender side, the technique I describe in this StackExchange answer and apply in this Github comment can be used: https://blender.stackexchange.com/a/222963/79413 https://github.com/KhronosGroup/glTF/pull/2214#issuecomment-1278292085
E.1
the emission strength in W/m^2 of a Sun lamp shining perpendicularly on a plane with maximum roughness.A.1
be the albedo of that diffuse plane.C.1
be the rendered pixel value of that diffuse plane.E.2
be the emission strength of an unrelated plane in an empty scene.C.2
be the rendered pixel value of that emissive plane.With linear colour space and no other light sources (including ambient), confirm
C.2 == C.1/A.1 * (E.2/E.1)
to verify that surface emission strength in Blender is in W/m^2.At that point, the conversion formula from the numeric values in Blender to numeric values that are glTF spec-compliant should be something like
f(e)=e*683/(2π)
. (Note: Online sources for converting lux to nits (which is a substep of this) seem to suggest usingπ
instead of2π
. I have no idea why they say that. The derivation should be(W/hemisphere/m**2) * (683lm/W) * (hemisphere/(2pi*sr))
. Play around I guess; GNU Units and Wolfram Alpha may help.)The Watts-to-lumens factor of
683
is a de facto industry/physical/scientific standard. It is based on the typical peak luminous efficiency for human vision, with coherent light at 555nm, and it also shows up in the modern (2019) SI definition of the "candela" base unit. It is also used in #1760 for import and export of punctual lights. https://github.com/KhronosGroup/glTF/pull/2214#issuecomment-1276762979 https://en.wikipedia.org/wiki/Luminous_efficacy#Explanation https://en.wikipedia.org/wiki/Luminous_efficiency_function#Details https://en.wikipedia.org/wiki/Candela#DefinitionNote that currently Three.JS, Babylon.JS, and the Khronos Viewer do not have exposure settings that display spec-compliant, physically-unitted luminances correctly by default. They operate on a unitless scale normalized to
1.0
for direct display output. This means that any GLTF files with lighting strengths specified in spec-compliant units will necessarily look extremely bright (Around683
times brighter than they should). https://github.com/KhronosGroup/glTF/pull/2214 https://github.com/KhronosGroup/glTF/pull/2128I believe that means that primarily three options are available for testing export results:
1/683
.683
scaling factor, or set it to1.0
, when testing the exporter code.gltf_viewer
application from Filament, which apparently does render with exposure according to physically based light units.With any of these three techniques, exported files in the viewer should appear basically the same as the source file in Blender.
Some kind of "compatibility mode" option will likely be included in #1760 to support unitless workflows by simply disabling the
683
lumens-to-watts coefficient. That should probably also apply to emissivity conversions.IDK if it might also be worth moving "683" to a global constant somewhere.Done. It's ingltf2_blender_conversions
.Uh.... It's really not that complicated.. In theory, but in practice I suppose there is just a lot that needs to be verified and double-checked. The good news is that we already went through most of it for punctual lights. So if the results look right on the first try with an algebraically and physically valid conversion formula (I.E. Just multiply by
683/(2π)
on export, and divide on import), then that should be good to go. If not... Then your guess is as good as mine how deep the rabbit hole will go. 🤷I may need this sooner or later, so if it hasn't been implemented yet by then I suppose I'll take another look at it at that point. Otherwise.... Good luck to whoever decides to tackle this, I guess. 😅 May your unit conversions be stable and your colour mappings standardized.