Where do material's properties come?

Where does ‘map’ come from?
Why material’s ‘uniforms.map.value’ assigned when material’s ‘map’ assigned?
I feel very confused and I tried but haven’t found the source.
I have a ShaderMaterial with uniforms merged from THREE.UniformsLib.common. I print the material and find it has properties ‘map’ & ‘normalMap’ & others. But after ‘myMaterial.map = myTex’, the map in uniforms is still null. This is different with MeshStandardMaterial.

Should I only use ‘uniforms.map.value’? If that, the useless properties make me feel confused.:pleading_face:

1 Like

Typically you would either:

a) use default materials like MeshStandardMaterial and MeshBasicMaterial, setting material.map and material.normalMap and so on. These materials manage their WebGL uniforms automatically.
b) use custom ShaderMaterial and set material.uniforms.* manually.

I’m don’t think there’s a reason to mix the two in one material, but feel free to share more code or a demo if this still doesn’t make sense.

1 Like

Thanks for your reply! I wonder how those materials manager their uniforms and I want my ShaderMaterial perform as same. I found nothing helpful in MeshStandardMaterial.js and Material.js.:blush:

This is in the depths of WebGLRenderer, see

You can do that if you subclass ShaderMaterial and use Object.defineProperty with getters and setters in the constructor. That way you can have your own shorthands.

You may also want to investigate possible usages of onBeforeCompile. (Maybe it is even possible to use this with subclasses of built-in materials. I have not tried.)

1 Like

In my understanding, myShaderMaterial.map = myTex should work if WebGLRenderer help me assign value to uniforms, but it doesn’t work. donmccurdy and some other people suggest set material.uniforms.* manually. Does WebGLRenderer only process default materials?

I plan to use getters and setters if there are not better way. I will look at the use of onBeforeCompile, thank you!

WebGLRenderer does not perform the mapping material properties to uniform values for custom material properties. Hence, you should directly set the values to the uniform objects.

Does WebGLRenderer define USE_MAP for default materials? :thinking:
My ShaderMaterial is an extension of PBR and it has more uniforms then MeshStandardMaterial (with all uniforms from it), and I would set or remove the maps many times on the runtime. It is much more convenient to set map then set uniforms.map.value and USE_MAP manually. I want it perform just like MeshStandardMaterial when assign values. But it would be too much getters and setters if by that way. If there is no better practice then get&set, I think I would set values and defines directly.

Yes:

2 Likes

This new fiddle demonstrates an example of extending MeshStandardMaterial with a custom property which functions as an extra uniform: Edit fiddle - JSFiddle - Code Playground

@pailhead does something similar in a blog post on Medium.

1 Like

WOW! It’s really helpful!:laughing: Thank you very much!:smiling_face_with_three_hearts::smiling_face_with_three_hearts::smiling_face_with_three_hearts:

1 Like