three实例化模型颜色混合同步普通模型颜色混合效果
1.普通模型:贴图颜色*材质颜色
2.实例化模型:贴图颜色*材质颜色*单例颜色
如果想要在实例化模型中还原普通模型的颜色混合效果,则需要把材质颜色始终设置为(1,1,1)使其在着色器颜色混合时不生效,这样下来 贴图*单例颜色 就与 普通模型的颜色混合效果一致了
方案核心点:
1.首先需要清除实例材质的颜色,并且将材质颜色填充到instanceColor数组中,避免影响模型的初始样子
2.启用颜色混合时,把材质设置为(1,1,1)然后修改instanceColor为目标颜色,混合在着色器中进行
具体步骤:
记录材质初始颜色:
for (const mesh of iconModel.meshes) {
data.index = mesh.count;
//记录材质颜色,在实例化模型中使用实例color代替材质color来进行颜色混合的关键步骤
!mesh.userData.materiaColor && (mesh.userData.materiaColor = mesh.material?.color?.clone() || mesh.material[0]?.color?.clone());
mesh.setColorAt(data.index, mesh.userData.materiaColor);
mesh.instanceColor.needsUpdate = true;
// 填充数组
// this.instanceOpacity.setX(data.index, Math.max(0, Math.min(1, opacity)));
mesh.count++;
}
重写instancedMesh的setColorAt方法:(支持颜色与透明度)
mesh.setColorAt = function (index, color, opacity = 1) {
//设置实例颜色
if (color !== null) {
if (!this.clearedMaterialColor) {
//如果设置实例颜色,则清除材质颜色
if (Array.isArray(this.material)) {
for (const eachMate of this.material) {
eachMate.color.set(0xffffff);
// eachMate.needsUpdate = true;
}
} else {
this.material.color.set(0xffffff);
// this.material.needsUpdate = true;
}
this.clearedMaterialColor = true;
}
color.toArray(this.instanceColor.array, index * 3);
}
if (opacity !== null) {
this.instanceOpacity.setX(index, Math.max(0, Math.min(1, opacity)));
this.instanceOpacity.needsUpdate = true;
}
}.bind(mesh);
着色器修改-实例材质替换:
if (Array.isArray(child.material)) {
material = [];
for (const eachMate of child.material) {
const newMate = eachMate.clone();
newMate.onBeforeCompile = _onMaterialBeforeCompile;
material.push(newMate);
}
} else {
material = child.material.clone();
material.onBeforeCompile = _onMaterialBeforeCompile;
}
着色器代码:
const _onMaterialBeforeCompile = function (parameters, renderer) {
let vertexShader = parameters.vertexShader;
//#region vertex color
vertexShader = vertexShader.replace(
'#include <color_pars_vertex>',
`
#if defined( USE_COLOR ) || defined( USE_INSTANCING_COLOR )
attribute float instanceOpacity;
varying vec4 vColor;
#endif
`
);
vertexShader = vertexShader.replace(
'#include <color_vertex>',
`
#if defined( USE_COLOR ) || defined( USE_INSTANCING_COLOR )
vColor = vec4( 1.0 );
#endif
#ifdef USE_COLOR
vColor.xyz *= color.xyz;
#endif
#ifdef USE_INSTANCING_COLOR
vColor.xyz *= instanceColor.xyz;
vColor.w *= instanceOpacity;
#endif
`
);
parameters.vertexShader = vertexShader;
let fragmentShader = parameters.fragmentShader;
//#region fragment color
fragmentShader = fragmentShader.replace(
'#include <color_pars_fragment>',
`
#ifdef USE_COLOR
varying vec4 vColor;
#endif
`
);
const useInstanceColor = `
diffuseColor *= vColor;
`;
fragmentShader = fragmentShader.replace('#include <color_fragment>', ` ${useInstanceColor}`);
//#endregion
parameters.fragmentShader = fragmentShader;
};

浙公网安备 33010602011771号