Three.js: Allow ShaderChunk overrides in materials (feature request/idea)

Created on 19 Feb 2018  路  3Comments  路  Source: mrdoob/three.js

I know that the challenge of customizable materials has been discussed quite a bit, but here is a feature I would love to see to that end. I've included proposed (incomplete) code changes, and I could try doing the PR, but I am not sure if the idea is well conceived.

Problem:

I often run into situations where I want to use an existing material, e.g. THREE.MeshPhongMaterial and modify the shaders. Rebuilding such materials from scratch as a THREE.ShaderMaterial is cumbersome, but my current solution.

This tool I found allows you to insert code into existing shaders, which is nice, though a bit hacky.
https://www.npmjs.com/package/three-material-modifier
But in some cases I would like to modify a line or more.

Proposed Solution:

Materials allow a shaderChunks argument to be passed, which is an object containing glsl strings that override ShaderChunks used by ShaderLib. For example:

var shaderChunks = {
//monochrome just from R channel of texture
map_fragment:  "diffuseColor *= vec4(vec3(texture2D( map, vUv ).x),1.0);"
};
var material = new THREE.MeshBasicMaterial({shaderChunks:shaderChunks});

Implementation

I started making some changes to see how hard it would be:
https://github.com/nhalloran/three.js/commit/7795a9af5c3df1cf919c84d8fdff8c49be74278d
https://github.com/nhalloran/three.js/commit/44d35a5fbcf996f779f5e33e548b043912bcb109

But a tricky part would be the handling the #includes in the ShaderLib directory
https://github.com/mrdoob/three.js/tree/dev/src/renderers/shaders/ShaderLib

I'm not exactly sure how those are built....

Would love feedback before going any further towards a PR.

Suggestion

Most helpful comment

Have you checked out Material.onBeforeCompile() (see #11475)? It allows you to modify built-in materials via a callback function.

There is also an example that illustrates the approach: https://threejs.org/examples/webgl_materials_modified.html

All 3 comments

Have you checked out Material.onBeforeCompile() (see #11475)? It allows you to modify built-in materials via a callback function.

There is also an example that illustrates the approach: https://threejs.org/examples/webgl_materials_modified.html

@nhalloran
Maybe also check out this PR and pitch in with some thoughts. So far i've not seen anyone use onBeforeCompile but i've seen a lot of:

THREE.ShaderChunk.some_chunk = myChunk

It seems intuitive and natural that you would pass bits, or chunks of data into the material. Even the name ShaderChunk sounds appropriate for this.

https://github.com/mrdoob/three.js/pull/13198

myMaterial.shader.chunks.fog_fragment = myFogFragment
myMaterial.shader.uniforms.vertex.myVertFloat = { type: 'f', value: 1 }
myMaterial.shader.attributes.index = { type: 'f' }
//etc..

It's very unlikely that onBeforeCompile will ever change. I'd love to compare notes if you find a good way of using it.

Please use Material.onBeforeCompile() for such use cases for now. Alternatively, have a look at the experimental NodeMaterial.

Was this page helpful?
0 / 5 - 0 ratings