-
-
Notifications
You must be signed in to change notification settings - Fork 35.5k
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
MeshLambertMaterial: convert to per-fragment shading #24452
Conversation
It would be interesting to see the performance implications of this PR. Meaning before it is merged. I know from several users that they use |
I have conducted some tests with Lambert vs. Phong on a modern M1 Macbook Pro. Not exactly a low-end mobile gpu, but still good for testing performance. The benchmark was rendering a single torus not at 800x600 resolution with an pixel ratio of 10 to firmly test the speed of fillrate. MeshLambertMaterial was only 2% faster than MeshPhongMaterial. |
Sorry, but such a simple scene on such a powerful device is not a viable test case. This needs to be primarily tested with low and mid-range smart phones with a fragment shader bound code (so it's possible to measure a difference between gouraud and phong shading) |
A few ideas on what might be needed to measure this:
|
This makes sense. Sorry for wasting your time! |
Sorry if this has been discussed somewhere else that I've missed. I believe users are choosing MeshLambertMaterial today because it has better performance than Phong on GPU-bound mobile devices, presumably because of the per-vertex vs. per-fragment shading. Assuming we want to maintain both a per-fragment Lambert material and a per-vertex Gourad shader (#24467), we have several choices:
For bundle size reasons, I doubt we want (D). If users are indeed looking for per-vertex shading, rather than a Lambert shading model, then I don't think (A) has much benefit. I would be fine with (B) or (C). |
I have seen users use // I am trying to make the shader code more maintainable. Part of that is removing per-vertex materials from Core. Hence, Concurrently, per-vertex So, I'd say the current proposal would be considered as Option (E). // Option (F) would be to remove Lambert from Core and rename the newly-added |
TBH, I don't see the purpose of a separate per-fragment Lambert material. Why not directly using I understand the library will be easier to maintain if no materials with per-vertex lighting are part of the core. However, I have the feeling a decision is made without enough information about the performance benefits of per-vertex lighting. Hence, I think it's important to make a performance analysis before this PR is merged. |
Because it is not the same, but |
I what way would it be different? Sorry, I have not read the new lambert shader in detail yet. |
@Mugen87 Did you mean zero-shininess? Because even if shininess is zero, the fresnel goes to 1 at grazing angles. So specular reflections still remain. |
@WestLangley I think your (E) and my (A) are the same, right? I guess what I mean is, why keep Lambert in core at all, if it has primarily been used for performance of per-vertex shading and we're removing that "feature" from it? Why not move both to examples/jsm? |
Yes, if your (A) is referring to the new per-pixel Lambert with the normalMap support.
I think that is a false premise. Users use Lambert for the illumination model, too.
That is an option, too. But, instead, you could do Option (F), which is equivalent to just moving per-vertex Lambert from Core to the examples. |
Ok, thanks @WestLangley! It sounds like a primary goal here is to simplify what we're maintaining in core, and to not have the additional complexity of a per-vertex shader there. Moving per-vertex to MeshGouradMaterial in examples/jsm, and having MeshLambertMaterial be per-fragment could be the most direct way to improve things. Many users probably assumed MeshLambertMaterial was per-fragment anyway — the naming was a bit confusing, and this PR fixes that. I'm satisfied with keeping MeshLambertMaterial (now per-fragment) in core. 👍🏻 |
Exactly this 👍 |
Okay, I'm convinced^^, too. Since |
Yay! |
Thanks! |
I guess we no longer need this file? |
We do need it. Gouraud replicates legacy Lambert. |
Maybe we remove the chunk but copy the code directly into |
basically to support small lights, but this was going to happen eventually any way - see mrdoob/three.js#24452
* MeshLambertMaterial: per-fragment shading * Remove unnecessary shader chunk
* MeshLambertMaterial: per-fragment shading * Remove unnecessary shader chunk
basically to support small lights, but this was going to happen eventually any way - see mrdoob/three.js#24452
basically to support small lights, but this was going to happen eventually any way - see mrdoob/three.js#24452
This PR converts
MeshLambertMaterial
from Gouraud (per-vertex) shading to per-fragment shading.MeshLambertMaterial
now supports:Shadows are now correctly modeled as the absence of light, just as the other built-in materials that respond to light. The
shadowMask
approximation, which results in solid-black shadows, is no longer needed.No features have been removed. In particular, the legacy
specularMap
is still supported.It remains to see if per-vertex shading has a detrimental effect on mobile performance.
As suggested by @mrdoob offline, I will create a custom
ShaderMaterial
that uses Lambert illumination and Gouraud (per-vertex) shading, and add it to the/examples/jsm/materials/
directory. It will have the same feature set as the legacy version ofMeshLambertMaterial
.