-
-
Notifications
You must be signed in to change notification settings - Fork 35.6k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Modification of LightMap and addition of AOMap to Materials. #6263
Conversation
…gment shaders to make things cleaner.
I'll have a detailed look at this PR as soon as I can. |
This is not what light maps are intended to be used for. Light maps are not baked shadow maps, rather they represent by definition incoming light to a surface. They can represent shadows by the absence of light though. Here is what the lightmap example looks like with this change: You can see there are still shadows, but these shadows are represented by the absence of light in the light map, rather than the modulation of existing light. The reason why the modulation of outgoingLight is problematic is that it violates the idea of the separability of light sources. Lighting for the most part has an "associative property", where each light is independent of the others. Light maps are just precomputed lights and they should exhibit the same "associative property." And you apply them such that you can have a real-time light or a baked light and they generally are the same thing (you only loose directionality effects with baked lights.) IBL is different than light maps. Light maps are baked onto objects with a specific UV mapping. A light map generally is not reused on multiple parts of an object, it is unique per object surface. An IBL setup is generally an environment, usually spherical that is is queried from the surface normal of an object for its lighting -- thus it is accessed via the surface normal and not a specific UV mapping on the object. If you have multiple IBL light probes, then they are queried based on surface position and surface normal. You have have LDR and HDR versions of both IBL and lightMaps. IBL is additive as well as it follows the "associative property", but IBL is accessed very differently. IBL, LightMaps, and AmbientOcclusion are used in UE4 and Unity5. |
That is a good idea. I will use the ambientOcclusion to modify all " indirect diffuse http://www.frostbite.com/wp-content/uploads/2014/11/course_notes_moving_frostbite_to_pbr.pdf Is that okay? |
This is excellent. Thank you for the clarification regarding light maps. Here is how I would implement the
I would also highly recommend changing the variable names to match terminology that is common in the literature:
Also, in my view, a hemi-light is a model of indirect light -- I know one could argue otherwise. If you agree, then the hemi-light should be included in the indirect lighting calculation, and be modulated by the aoMap. Furthermore, since it has a specular term, that term would be part of indirect specular. This can be handled in a separate PR. You will have to remove AO from |
These suggestions, while useful, will make this PR significantly more complex and harder to review. Why don't we split this into two parts. I'd suggest sticking with this current PR (with any little polish like naming) that has the old-style AmbientOcclusion that affects everything like the old lightMap implementation. Remember the goal fo this PR was primarily to make lightMaps correct, and I only added ambientOcclusion so that those that wanted the old lightMap mode, could use that instead (even though I know it is still wrong theoretically.) We can then review the lightMap and AmbinetOcclusion setup. And then we can do another PR that improves AmbientOcclusion to affect only indirect lighting. Is that okay? |
Absolutely! |
Here is an issue where we can discuss the separate from indirect diffuse from indirect/direct specular: |
I added aoMap to every material that already had lightMap. We can remove them from these two materials or leave them -- I think the overhead is almost nothing to keeping them around when they are not used. I think the oaMap makes as much sense as a lightMap -- so we would suggest either keeping both or removing both on a per material basis. |
As far as I would keep |
Just to be clear, lightMaps are generally considered to be non-directional light -- you generally bake the global illumination solution into lightMaps because you can not get it from local lighting calculations. And both MeshBasicMaterial and MeshLambertMaterial have light maps and thus that would be included in the oa calculation. /have a good weekend! |
Actually I suspect it is a rare case that lightMaps and oaMaps are used together, even if possible. One will likely just bake oa into the lightMap instead of having two. Thus I will remove oaMap from Lambert (which should be Gouroud) and Basic. |
Good. It is settled! : - ) |
That is a great way of thinking about it: "Light maps are baked GI". |
I've just removed aoMap/Scale from Basic and Lambert materials. I also added a lightScale parameter to Phong so that one can adjust the lightMap intensity -- I think the name is a little confusing (it sounds like it could scale all lights, but it follows the naming pattern already established for normalMap/normalScale and bumpMap/bumpScale) but the parameter is really useful. |
That it is. A compromise would be to break the pattern and call it Otherwise, this is good-to-go. |
I've renamed the variable. :) |
if ( data.aoMap !== undefined ) { | ||
|
||
material.aoMap = getTexture( data.aoMap ); | ||
if ( data.aoScale ) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
For clarity and robustness I would change this if ( data. aoScale !== undefined )
.
"lightMapScale" : { type: "f", value: 1 }, | ||
|
||
"aoMap" : { type: "t", value: null }, | ||
"aoScale" : { type: "f", value: 1 }, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This should be aoMapScale
.
I'm not sure about |
It is not an opacity. I think So is |
|
I think we are going to have to pick the better of some not-so-good alternatives... |
I addressed @mrdoob's suggestions. I choose |
@@ -65,6 +69,10 @@ THREE.MeshPhongMaterial = function ( parameters ) { | |||
this.map = null; | |||
|
|||
this.lightMap = null; | |||
this.lightMapIntensity = null; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Shouldn't this be 1.0
?
BTW I also sorted the shaders alphabetically in |
Modification of LightMap and addition of AOMap to Materials.
Nice! Thanks! |
This PR requires some discussion I believe.
Previously we were treating lightMap as something that modulates the outgoingLight from a surface. This is not the normal definition of a lightMap as treated in other game engines. Usually a lightMap contributes outgoing light from a surface via being modulated with the surface color. Thus I have made this change.
But to accommodate the previous use case of lightMap (where it modulated the outgoingLight), I've added ambientOcclusionMap which does directly modulate the outgoingLight from a surface. I have added an ambientOcclusionScale as well that varies the degree to which the light is modulated by the ambientOcclusionMap - where 0 is no darkening, while 1 is full darkening based on the map. Values greater than 1 are allowed but could lead to non-physical results.
To be specific, the way that ambientOcclusionMap has been implemented is that it modulates the outgoingLight after the main lighting equation, thus it modulates both diffuse and specular and emissive contributions. It is arguable whether this is fully correct, but it does minimic exactly the previous implementation for the outgoingLight modulating lightMap.
With this change ThreeJS treats both lightMaps and ambientOcclusionMaps in a similar fashion to other game engines.
While doing this change I have pulled apart the handling of both UV and UV2 varyings in the fragment and vertex shaders. They are no longer part of map and the lightmap glsl shaders pieces, but rather are the own pieces. This is clearer but these two variables (UV and UV2) are really shared varyings, not tied to a specific map.
/ping @WestLangley