说我有类似的东西:
//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*/ }
}
}
现在我可以使用材料的FOO版本。但是如果我想添加同时执行FOO和BAR的MeshStandardMaterial
的另一个版本呢?
const BAR_onBeforeCompile = shader => {
/* 1. replace another chunk */
/* 2. add something after beginnormal_vertex */
}
class ShaderMaterialWithFOOandBAR extends StandardMaterialWithFOO {
constructor(params){
super(params)
this.onBeforeCompile = /* ??? */
}
}
#include <some_chunk>
处理之后没有onBeforeCompile
,我无法知道它被替换了什么。 我能想到解决这个问题的唯一方法是使用一些像GLSL代码这样的超级全局代码,每个可能的排列由#ifdef
控制?但我不想全局修改THREE.ShaderChunk
对象。
someChunk = `
#ifdef isFOO
/* logic */
#endif
#ifdef isBAR
/* logic */
#endif
`
^这似乎有点乏味,但容易出错。
还有类似的东西:
const mySuperUberOneSizeFitAllOnBeforeCompile = shader =>{
if( isBAR ) {...}
if( isFOO ) {...}
}
不起作用,因为three.js具有忽略这些条件的缓存机制。假设我有10个材料使用同一个回调,它们都将编译为单个,从该列表中随机选择。
任何建议,想法?
答案 0 :(得分:0)
function copyHashes(input, output) {
let key
for (key in input) {
output[key] = input[key]
}
}
class foo {
shaderStuff = {}
constructor(params) {
copyHashes({
beginnormal_vertex: "",
defaultnormal_vertex: "",
normalmap_pars_fragment: ""
},
this.shaderStuff)
this.onBeforeCompile = ()=>{
// perform the replacement using this.shaderStuff
}
}
}
class bar extends foo {
constructor(params) {
super(params)
copyHashes({
somethingelse_vertex: "",
other_pars_fragment: ""
},
this.shaderStuff)
// you assigned onBeforeCompile during the constructor
// so it wasn't inherited
this.onBeforeCompile = ()=>{
// perform the replacement using this.shaderStuff
// in this case, this.shaderStuff contains the FULL
// COMBINED list from both foo AND bar
}
}
}
正在发生的事情是每个班级都将自己的替代追加到shaderStuff
。我编写的方式,任何扩展类都将用自己的覆盖覆盖现有的覆盖。
如果这没有意义,或者我误解了这个问题,请告诉我。