Closed daveo1001 closed 4 years ago
We do not support shininess material on MeshPhongMaterial
. We could considering adding it though.
MeshPhongMaterial.specularMap
, which takes values in [ 0, 1 ], attenuates the specular component on a per-pixel-basis. When using it, you may have to set a fairly high MeshPhongMaterial.shininess
value to begin with.
Perhaps that is a work-around for you.
I thought shininess is here: https://github.com/mrdoob/three.js/blob/master/src/materials/MeshPhongMaterial.js#L59
And also here: https://github.com/mrdoob/three.js/blob/master/src/renderers/shaders/ShaderChunk/lights_phong_pars_fragment.glsl#L32
So I think it is supported.
Ah, I see the issue, "material.specularStrength" is applied to the whole of the Phong Specular BRDF instead of just applied to the shininess parameter. I'd suggest that we replace specularStrengthn with shinininessMap that modulates the shininess instead. I think that is actually much more useful and more physically correct.
@bhouston Our implementation of MeshPhongMaterial
is not a physically correct model in any respect. Personally, I do not think it matters. I would focus on the physical materials, instead.
But if you want to change the model, I would not oppose. The thing to do would be to add shininessMap
, which would be modulated by shininess
. Leave specularMap
, alone for backward-compatibility or remove it.
But if you want to change the model, I would not oppose. The thing to do would be to add
shininessMap
, which would be modulated byshininess
. LeavespecularMap
, alone for backward-compatibility or remove it.
👍
@WestLangley wrote:
@bhouston Our implementation of MeshPhongMaterial is not a physically correct model in any respect.
The ThreeJS implementation of BlinnPhong is not physically correct, that is true. Other renders do have much more physically correct implementations -- V-Ray and PRMan have really good implementations of BlinnPhong that are essentially as physically correct as MeshSTandardMAterial/MeshPhysicalMaterial -- they differ only in terms of parameterization.
The reason why ThreeJS's MeshPhongMaterial are so bad is because of three issues with our implementation:
(1) We are not energy conserving. Energy reflected by specular layer should not be made available to the diffuse layer. If specular is 1, 1, 1 (which means the surface is metallic and fully reflective) then the light getting to the diffuse layer should be 0,0,0. (This energy conservation is part of MeshStandardMaterial in the way that increasing metalness reduces the intensity of the diffuse layer.)
(2) ShininessMap should modulate shininess.
(3) SpecularMap should be a color map that modulates specularColor.
This would be useful to have right because then ThreeJS can load MTL, FBX and other BlinnPhong model using files with as full fidelity as other professional rendering packages.
Just as a point of reference in defense of properly implemented Blinn-Phong, V-Ray uses Blinn-Phong almost exclusively and its stuff looks amazing:
https://www.google.ca/search?q=v-ray+architecture&source=lnms&tbm=isch
@bhouston I agree, your suggestions make perfect sense. I wonder why it wasn't implemented that way in the first place...
There was a previous attempt to implement energy conservation in BlinnPhong -- I think it was relatively correct as it followed roughly how professional renderers do it. It is important to note that one doesn't have to use a Fresnel term in the energy conservation as it isn't done this way in Standard/Physical either when blending towards metallic just linearly decreases available light at the diffuse layer.
@mrdoob I didn't think so. I would like it very much if you did consider it. @WestLangley I'm already using the specular.map and it is enough to get by with what I'm doing but having a map for shininess to go with it would really make my day. @bhouston you're way smarter than me. keep it up!
This is turning out to be an enormous change. Here is some code for reference.
float specularStrength;
#ifdef USE_SPECULARMAP
vec4 texelSpecular = texture2D( specularMap, vUv );
specularStrength = texelSpecular.r;
#else
specularStrength = 1.0;
#endif
#ifdef ENVMAP_BLENDING_MULTIPLY
outgoingLight = mix( outgoingLight, outgoingLight * envColor.xyz, specularStrength * reflectivity );
#elif defined( ENVMAP_BLENDING_MIX )
outgoingLight = mix( outgoingLight, envColor.xyz, specularStrength * reflectivity );
#elif defined( ENVMAP_BLENDING_ADD )
outgoingLight += envColor.xyz * specularStrength * reflectivity;
#endif
Objective
specularMap
to modulate MeshPhongMaterial.specular
, assume specularMap
is RGB-valued, not grayscale. (easy)shininessMap
to modulate MeshPhongMaterial.shininess
. shininessMap
is grayscale. (also easy)Consequences
reflectivityMap
, too, but the ENVMAP_BLENDING modes are such a hack, I hate to go down that path. Why create such hacks when we have MeshStandard/PhysicalMaterial
available?MeshBasicMaterial
and MeshLambertMaterial
support specularMap
, and would either need to have that property renamed to reflectivityMap
or -- my preference -- remove the support for per-pixel reflectivity from those two materials -- and MeshPhongMaterial
, too, for that matter.Previously, we have wondered why we are supporting MeshPhongMaterial
when we have the properly-designed MeshStandardMaterial
to replace it. I think that is a good question.
#else
specularStrength = 1.0;
#endif
should not be constant, as with other parameters there should be a float available to override the texture. If one has the ability to use a texture containing values in the 0-1 range, why is the alternative locked to 1? Why not 0, or .5346?
This feature is under consideration for the glTF 2.0 Blinn-Phong extension (see discussion), so I will be interested in what is decided here as well. It was mentioned by @bhouston that our MeshPhong model is spec-gloss — is it possible to implement this with the PBR spec-gloss material already checked into GLTF2Loader?
/cc @takahirox
Previously, we have wondered why we are supporting MeshPhongMaterial when we have the properly-designed MeshStandardMaterial to replace it. I think that is a good question.
IMO, there is still need for more performance-tuned materials on mobile devices e.g. Cardboard/Daydream/GearVR.
The leaves no per-pixel map to modulate reflectivity. We could add a reflectivityMap, too, but the ENVMAP_BLENDING modes are such a hack, I hate to go down that path. Why create such hacks when we have MeshStandard/PhysicalMaterial available?
I don't think I follow... Is there something about this proposal that makes reflectivityMap
necessary? Or are you mentioning it to round out remaining foo
/fooMap
pairs?
@donmccurdy The implementation of "BlinnPhong" in Three.JS is fairly wrong compared to the correct implementation in V-Ray and other top quality renderers. I describe the real issues here and how to address them:
https://github.com/mrdoob/three.js/issues/9339#issuecomment-233160823
My recommendations are not that hard to implement and but it is a breaking change for a bunch of people who are already suing the incorrect BlinnPhong.
IMO, there is still need for more performance-tuned materials on mobile devices
I don't expect Phong
will suffice for that purpose.
I don't think I follow... Is there something about this proposal that makes reflectivityMap necessary? Or are you mentioning it to round out remaining foo/fooMap pairs?
What we are currently calling specularMap
would be changed from a single-channel map to a 3-channel map used for a different purpose. So, we either have to remove the current specular map functionality completely (from Basic
and Lambert
) or rename the former specularMap
to something else -- like reflectivityMap
.
I mentioned it because these are breaking changes.
IMO, there is still need for more performance-tuned materials on mobile devices
Properly implemented BlinnPhong should be computationally equivalent to properly implemented Physical materials within some small margin of error.
I don't expect Phong will suffice for that purpose.
Properly implemented BlinnPhong should be computationally equivalent to properly implemented Physical materials within some small margin of error.
Thanks @WestLangley @bhouston! In that case I don't have an opinion about maintaining MeshPhongMaterial alongside MeshStandardMaterial. Unlit shading is probably what I need to be looking at; I'd like to get that definition updated for glTF2.0. I will retire from this thread. 😬
For the record, I implemented .shininessMap
for MeshPhongMaterial
and ultimately abandoned it. It was difficult for me to get predictable results modulating .shininess
with a per-pixel map.
The primary reason is .shininess
is unbounded, and not a measure of "perceptual shininess". Hot spots are often over-bright to begin with, and modulating shininess can still result in an over-bright hot spot, with little perceptible visual difference. MeshStandardMaterial
has a much better parameterization; .roughness
is, in fact, "perceptual roughness".
Regarding an RGB.specularMap
, I now see little benefit to adding this. Such a feature may be useful in modeling metals, but MeshPhongMaterial
does not do a good job of representing metals, anyway. MeshStandardMaterial
, on the other hand, does. Consequently, I have abandoned adding an RGB .specularMap
to MeshPhongMaterial
.
My recommendation at this point is to leave MeshPhongMaterial
as-is. Sophisticated users can use MeshStandardMaterial.
I still would be in favor of renaming the current grayscale .specularMap
to .reflectivityMap
, as it modulates the .reflectivity
property in the MeshBasic/Lambert/Phong
materials.
Note, we use the property .specularMap
elsewhere. An RGB .specularMap
is used in the glTF Specular-Glossiness extension, where it modulates .specular
, the specular reflectance of the material.
I would suggest studying V-Ray, Blender's Cycles and Unity to figure out what they do and then take the average solution in terms of how things are modulated and what things are called.
This would achieve the most compatibility possible as these are the tools that I think have the most widely accepted Blinn-Phong shading models.
Closing in favor of #7290 which tracks the mentioned changes to specularMap
and reflectivityMap
.
Currently/To the best of my knowledge the only shininess setting for phong material is shininess (mtl Ns) but mtl supports a shininess map (map_Ns). I'm sure it's a pretty big deal but I'd be eternally grateful if this feature was added.
Three.js version
Browser
OS