-
-
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
MMDLoader: Implement MMDToonMaterial. #21922
Conversation
hmm..., the e2e test failed, I'll try to fix it. |
Thank you and nice work! I would like to look into more deeply later but the basic direction looks good to me. Would you mind if putting the screenshots of before and after? It will show to other devs how good this change is.
Thanks for recovering specular support. I really wanted it. Mapping 1.0 to 5.0 sounds ok to me so far. We can modify it later if needed. Just FYI, we directly set MMD shininess to https://github.com/mrdoob/three.js/blob/r111/examples/jsm/loaders/MMDLoader.js#L1065
I think you need to update screenshots for MMD examples with |
hmm..., my reference model is a R18 one, might not suitable to put here 😂 I'll try to find a safer PMX model and take screen shot. The model in examples (miku_v2.pmd) is a PMD file, so the envMap part will remain unchanged. |
IMO, the MMD examples now look a bit too shiny and overlit. |
Should I push a commit to set |
That model in the original MMD from https://ascii.jp/elem/000/000/714/714544/2/ I agree with @Mugen87, the new MMD examples looks a bit too shinny. In the screenshot comparison @bill42362 posted, "webgl_loader_mmd But in the current Three.js examples, the model looks less shinny than your screenshot. How did you make the screenshot? Did you use older Three.js? |
Ah, ok I think you copied from https://github.com/mrdoob/three.js/blob/dev/examples/screenshots/webgl_loader_mmd.jpg
From the example model looking, I want to say yes. But it still somehow looks a bit brighter than the original MMD and our old example. https://raw.githack.com/mrdoob/three.js/r111/examples/index.html?q=mmd#webgl_loader_mmd |
Updated code and screenshots with the second example of my last comment. It's always ok to revert to any commit here. |
Thanks for the screenshot. Probably it looks good.
Not sure about MMD Sphere map(matcap) spec in the detail but I guess it would be good only with view direction? And we can update it later if needed. I added comments for non-big deal like code formatting. The last thing I want to discuss is |
That's actually my start point, but after that I found that if I override the |
Update codes according to comments except the filename comment. |
Matcaps are view-dependent. Scene lights are view-independent. It seems odd to me to use them simultaneously. It does seem reasonable for |
Maybe that's the reason why PMX spec call it And in https://gist.github.com/felixjones/f8a06bd48f9da9a4539f#material-data it also noted as
If we use scene light direction to compute "matcap" also, which means everything are view-independent, would that be more reasonable? In this example it also looks like the matcap is view-independent, which the texture changes when the camera stays. |
If you render a sphere with a matcap, the rendered image does not change when the camera is rotated around the object. It is as if the "baked lights" are children of the camera, and hence move with the camera. |
Hm, ok. Then let's go with
Yes.
I'm sure MMD toon material supports both scene lights and sphere map (matcap). https://seiga.nicovideo.jp/seiga/im2077494 (in Japanese) Even if it sounds odd, I want our |
Move map filename store position from texture object to material |
examples/jsm/loaders/MMDLoader.js
Outdated
@@ -1198,19 +1204,28 @@ class MaterialBuilder { | |||
if ( material.textureIndex !== - 1 ) { | |||
|
|||
params.map = this._loadTexture( data.textures[ material.textureIndex ], textures ); | |||
params.map.name = material.name; |
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.
Setting texture's name as material's name is a bit weird to me... Do you want to use the name for the mapping?
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.
uh, that's a mistake, I'll remove it.
Remove extra texture name assign. |
* Combining steps: | ||
* * Declare matcap uniform. | ||
* * Add gradientmap_pars_fragment. | ||
* * Combine dotNL and gradient irradiances as total irradiance. |
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.
I guess this comment Combine dotNL and gradient irradiances as total irradiance
is outdated?
Because irradiances are calculated only from gradient now.
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.
yes
examples/jsm/loaders/MMDLoader.js
Outdated
parameters.uniforms.specular.value = parameters.specular; | ||
parameters.uniforms.shininess.value = parameters.shininess; | ||
parameters.uniforms.emissive.value = parameters.emissive; | ||
parameters.uniforms.gradientMap.value = parameters.gradientMap; |
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.
Should we have getters and setters like
get shininess() {
return this.uniforms.shininess.value;
}
set shininess(value) {
this.uniforms.shininess.value = value;
}
...
?
Otherwise users need to be aware that new MMD toon material is based on ShaderMaterial
and they need to rewrite their code from material.param = value
to material.uniforms.param.value = value
. I don't think we should break the compatibility.
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.
Not use setter/getter on production before, let me try it.
Update comment and use setter/getters to improve compatibility. @takahirox not sure if I'm doing right of the setter/getters, please take a look when you have time. |
Object.defineProperties( this, { | ||
|
||
[ uniformName ]: { | ||
|
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.
I think it would be simpler to use Object.defineProperty
Object.defineProperty( this, uniformName, {
get: ...,
set: ...
} );
examples/jsm/loaders/MMDLoader.js
Outdated
} ); | ||
|
||
this.uniforms = UniformsUtils.clone( MMDToonShader.uniforms ); | ||
for ( const uniformName in this.uniforms ) { |
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.
I first thought of using getter/setter in class like
class MMDToonMaterial {
constructor(params) {
...
}
get foo() {
return this.uniforms.foo.value;
}
set foo(value) {
this.uniforms.foo.value = value;
}
}
but your Object.defineProperty
approach would be simpler.
You set up getter/setter for all uniforms but uniform includes some properties which don't need to be exposed like directionalLightShadows
. So I think it would be better to set up getter/setter only for properties which should be exposed.
const propertyNames = [
...
];
for ( const propName of propertyNames ) {
...
}
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.
Would it be better if I choose like this?
const excludedProtertyNames = [
'directionalLightShadows',
...
];
for ( const propertyName of propertyNames ) {
if ( !excludedProtertyNames.includes( propertyName ) ) {
...
}
}
Make it default expose in case there will be more uniforms need to be exposed from MeshToon/Phong/MatcapMaterial in the future?
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.
I think it's pros and cons. Cons of the exclude approach is if new uniforms which shouldn't be exposed will be added to toon/phong/matcap uniforms they will be exposed.
Personally I prefer mine because it would be easier to notice the need for the update. But no strong opinion.
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.
I think yours should be better since it should be more understandable for someone wan't to modify this code.
Updated property exposing pattern. |
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.
Looking good to me. Awesome work!
Thanks! |
Related issue: #19609, #19517
Description
This PR basically follow's what described in #19609, implementing
MMDToonMaterial
insideMMDLoader
.Specifically, the
MMDToonMaterial
is extended fromShaderMaterial
, useMeshPhongMaterial
's shader, then merge lighting algorithms and uniforms fromMeshToonShader
andMeshMatcapMaterial
.Shader merging detail
MeshPhongMaterial
's vertex shader.MeshPhongMaterial
's fragment shader as following:matcap
uniform.gradientmap_pars_fragment
. (fromMMDToonMaterial
)lights_toon_pars_fragment
.(Replace
lights_phong_pars_fragment
withlights_mmd_toon_pars_fragment
)mmd_toon_matcap_fragment
, which copy and modified frommeshmatcap_frag
.Discussion
.envMap
of models other than PMD to.matcap
.As @WestLangley pointed, the envMap of of my reference model (PMX) is actually point to a matcap image. So here I move
.envMap
to.matcap
, and leave.envMap
empty. Not sure what's PMD file's spec, so just leave it as is. (maybe the.envMap
should referecne toscene.background
?).specular
color and.shininess
value from MMD models.Since
MeshPhongMaterial
support these two values, we could read these values from MMD models now. The.specular
value is just copy from model file. However, the.shininess
seems like a [0~1] range, and if I just map1.0
to30
(default ofMeshPhongMaterial
) it would be too bright. Here I choose to map1.0
to5
since it looks good on my reference model. Any suggestions?Please leave your comment.