Imagine having a scenario like this:
//some chunks i want to override for functionality FOO
const myNormalChunks = {
beginnormal_vertex,
defaultnormal_vertex,
normalmap_pars_fragment,
}
//a version of `MeshStandardMaterial` that does FOO instead of default
class StandardMaterialWithFOO extends THREE.MeshStandardMaterial{
constructor(params){
super(params)
this.onBeforeCompile = shader=> { /*replace chunks by name*/ }
}
}
Now you can use the FOO version of the material. But what if you wish to incorporate another version of the MeshStandardMaterial
that combines both FOO and BAR?
const BAR_onBeforeCompile = shader => {
/* 1. replace another chunk */
/* 2. add something after beginnormal_vertex */
}
class ShaderMaterialWithFOOandBAR extends StandardMaterialWithFOO {
constructor(params){
super(params)
this.onBeforeCompile = /* ??? */
}
}
- There might be a possibility to cleverly link these callbacks together.
- This method is not foolproof because there is no
#include <some_chunk>
directive after the initialonBeforeCompile
processes it, making it hard to track changes made.
The one solution I can think of to address this dilemma is through a comprehensive GLSL code containing all possible variations controlled by #ifdef
. However, personally, I prefer not to alter the global THREE.ShaderChunk
object.
someChunk = `
#ifdef isFOO
/* logic */
#endif
#ifdef isBAR
/* logic */
#endif
`
^ although effective, this approach seems laborious and prone to mistakes.
Additionally, consider something like:
const mySuperUberOneSizeFitAllOnBeforeCompile = shader =>{
if( isBAR ) {...}
if( isFOO ) {...}
}
However, this strategy falls short as three.js employs a caching mechanism that disregards such conditional statements. If multiple materials utilize the same callback, they will amalgamate into a single entity randomly chosen from that list.
Do you have any suggestions or innovative ideas to solve this issue?