如何用FragmentHighlighter实现纯高亮颜色(openbim-components+THREE.js)
解决IFCjs FragmentHighlighter高亮颜色混合问题
问题本质
FragmentHighlighter的工作逻辑是在原网格上叠加带高亮材质的新网格,而非替换原网格材质,所以当原元素非白色时,两个网格的颜色会混合显示,导致高亮效果不纯。
可行解决方案
方案1:高亮时临时隐藏/透明化原网格(最直接)
利用FragmentHighlighter的高亮/取消高亮事件,动态修改对应原fragment的可见性或透明度,确保只有高亮网格显示:
// 获取你的FragmentHighlighter实例 const highlighter = components.highlighter; // 监听高亮触发事件 highlighter.onHighlight.add((fragments) => { fragments.forEach(fragment => { // 保存原状态,用于取消高亮时恢复 fragment.userData.originalVisible = fragment.visible; fragment.userData.originalOpacity = fragment.material.opacity; // 隐藏原网格,或者设置透明度为0 fragment.visible = false; // 或者 fragment.material.opacity = 0; }); }); // 监听取消高亮事件 highlighter.onUnhighlight.add((fragments) => { fragments.forEach(fragment => { fragment.visible = fragment.userData.originalVisible; // fragment.material.opacity = fragment.userData.originalOpacity; }); });
方案2:调整高亮材质的渲染层级与深度设置
通过修改高亮材质的renderOrder和深度相关属性,让高亮网格强制渲染在原网格之上,覆盖原颜色:
const highlighter = new FragmentHighlighter(components); const highlightMat = highlighter.material; // 设置高亮颜色 highlightMat.color.set('#888888'); // 关闭深度测试,让高亮网格忽略原网格的深度 highlightMat.depthTest = false; // 禁止写入深度缓冲,避免影响其他元素 highlightMat.depthWrite = false; // 提高渲染优先级,确保先渲染原网格,再渲染高亮网格 highlightMat.renderOrder = 1; // 确保原网格的renderOrder为默认的0(如果有自定义过,需调整)
方案3:使用模板缓冲实现精确高亮(适合复杂场景)
通过THREE.js的模板缓冲,让高亮仅在原元素的区域渲染,完全覆盖原颜色:
// 第一步:启用渲染器的模板缓冲 components.renderer.threeRenderer.stencilBuffer = true; // 第二步:配置原元素材质的模板规则 components.scene.ifcLoader.settings.material = (model) => { const mat = new THREE.MeshStandardMaterial({ color: model.color }); // 写入模板值1 mat.stencilWrite = true; mat.stencilFunc = THREE.AlwaysStencilFunc; mat.stencilZPass = THREE.ReplaceStencilOp; mat.stencilRef = 1; return mat; }; // 第三步:配置高亮材质的模板规则 const highlightMat = new THREE.MeshBasicMaterial({ color: '#888888', // 只在模板值等于1的区域渲染 stencilWrite: false, stencilFunc: THREE.EqualStencilFunc, stencilRef: 1, }); // 第四步:初始化高亮工具时使用自定义材质 const highlighter = new FragmentHighlighter(components, { material: highlightMat });
为什么你的尝试没生效
polygonOffset:这个属性是用来解决Z轴打架(两个网格位置完全重叠导致闪烁)的,无法解决颜色混合问题,因为两个网格依然会同时渲染。- 调整
depthTest:如果只单独设置高亮或原网格的depthTest,会导致要么高亮网格被原网格遮挡,要么原网格被高亮网格完全覆盖但其他元素渲染异常,需要配合renderOrder和depthWrite一起调整才会生效。
内容的提问来源于stack exchange,提问作者Daniel Kovalenko
相关产品推荐
相关产品推荐

