You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何用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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.27 15:16:22