Extend and combine effects for built in materials

Three.js is awesome and has some awesome built-in materials. However, i often find myself having to implement some effect on top of these materials.

The feature to extend built-in materials has been requested by many developers over the years. There have been many PRs submitted over the years to tackle this but unfortunately none of them landed.

Last year we were given onBeforeCompile and it allows us to do some of this stuff, at the cost of extreme frustration :slight_smile:

Some examples that are part of three.js also have this requirement. GLTFLoader extends StandardMaterial to change it’s lighting morel. Some users want .transform to be on uv channels rather than textures etc. etc.

I’ve made a demo that shows how these various effects could be combined to a single material:

  1. GLTFLoader's Specular Glossiness Standard material
  2. ability to transform each map channel individually (you can have the same texture in map specularMap but apply different repeats/offsets
  3. simple instancing from examples three.js examples

The idea is to hide all of the stuff that make these effects run and expose to the user a simple interface

In case of spec gloss

myMaterial.roughnessMap //this is gone
myMaterial.glossinessMap //this is available

This demo:

  1. changes the roughness/metalic standard material to be spec gloss
  2. adds transform properties to arbitrary Map props, (any material can be provided, including the extended one)
  3. adds simple instancing from the lambert example (can be applied to any material, not just lambert)

It has the same texture in map and specularMap slots, but the specular map one can be transformed through dat.gui.


Here it is with the GLTFLoader, it skips 2 and just adds either 3 or 1 and 3.

The code to do all three looks like this [WIP] tiny api and example how to combine material extensions by pailhead · Pull Request #14206 · mrdoob/three.js · GitHub, but unfortunately requires some 30 lines to be added to the core :frowning:

I’d really like to get some feedback on the api.

I didn’t quite digest the api

the idea is this:

var myMaterial = new Some_built_in_Material()

decorateMaterialWithFOO( myMaterial )
decorateMaterialWithBAR( myMaterial )
decorateMaterialWithBAZ( myMaterial )

//now my material has extra things

myMaterial.foo.copy(new THREE.Vector2(2,2))
myMaterial.bar = new Texture()
myMaterial.baz = new Color()

Also the example combines 3 “extensions” and then applies yet another 4th “inline” extension on top of the extended materials, so even that part is possible. I think i was also able to serialize this with no problems.