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

Three.js需求:让始终渲染的网格遮挡区域显示不同颜色

实现带遮挡变色效果的始终可见网格(Three.js 着色器方案)

核心思路是手动在片元着色器中进行深度测试:通过渲染器生成的场景深度纹理,对比当前网格片元与场景中其他物体的深度值,判断是否被遮挡,进而切换显示颜色。相比逐顶点射线检测,这种片元级方案效率更高,且能精确控制每个像素的颜色。

步骤1:配置渲染器生成深度纹理

首先需要让Three.js渲染器输出场景的深度纹理,后续着色器将通过这个纹理获取其他物体的深度信息:

const renderer = new THREE.WebGLRenderer();
// 开启必要的渲染配置
renderer.shadowMap.enabled = true;
renderer.outputEncoding = THREE.sRGBEncoding;
// 创建并绑定深度纹理
renderer.depthTexture = new THREE.DepthTexture();
renderer.depthTexture.format = THREE.DepthFormat;
renderer.depthTexture.type = THREE.UnsignedIntType;

步骤2:编写自定义着色器材质

创建包含深度测试逻辑的着色器,顶点着色器负责传递必要的坐标信息,片元着色器完成深度对比和颜色切换:

顶点着色器

varying vec4 vScreenPosition;
varying vec3 vWorldPosition;

void main() {
    vWorldPosition = (modelMatrix * vec4(position, 1.0)).xyz;
    vScreenPosition = projectionMatrix * modelViewMatrix * vec4(position, 1.0);
    gl_Position = vScreenPosition;
}

片元着色器

uniform sampler2D depthTexture;
uniform vec3 visibleColor;
uniform vec3 occludedColor;

varying vec4 vScreenPosition;

void main() {
    // 将裁剪空间坐标转换为NDC(归一化设备坐标)
    vec2 ndc = (vScreenPosition.xy / vScreenPosition.w) * 0.5 + 0.5;
    // 采样深度纹理,获取场景中该位置的深度值
    float sceneDepth = texture2D(depthTexture, ndc).r;
    // 获取当前片元的深度值(裁剪空间w分量转换)
    float currentDepth = vScreenPosition.z / vScreenPosition.w;
    currentDepth = currentDepth * 0.5 + 0.5; // 转换为[0,1]范围

    // 深度对比:如果当前片元深度大于场景深度,说明被遮挡
    vec3 finalColor = (currentDepth > sceneDepth + 0.001) ? occludedColor : visibleColor;
    gl_FragColor = vec4(finalColor, 1.0);
}

步骤3:创建网格并应用材质

保持你原本的depthTest=false和renderOrder=999设置,同时将深度纹理传入着色器uniform:

const geometry = new THREE.PlaneGeometry(5, 5);
const material = new THREE.ShaderMaterial({
    uniforms: {
        depthTexture: { value: renderer.depthTexture },
        visibleColor: { value: new THREE.Color(0x00ff00) }, // 未遮挡颜色
        occludedColor: { value: new THREE.Color(0x9933ff) } // 遮挡区域颜色
    },
    vertexShader: /* 上述顶点着色器代码 */,
    fragmentShader: /* 上述片元着色器代码 */,
    depthTest: false,
    renderOrder: 999
});

const mesh = new THREE.Mesh(geometry, material);
scene.add(mesh);

关键细节说明

  • 深度对比时添加了+0.001的偏移量,是为了避免因浮点精度问题导致的z-fighting(深度冲突)。
  • 深度纹理存储的是非线性深度值,这里通过裁剪空间的z/w转换为线性深度进行对比,结果更准确。
  • 该方案是片元级检测,能精确到每个像素,不会出现顶点检测带来的三角区域颜色断层问题。

内容的提问来源于stack exchange,提问作者z3db0y

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.15 10:42:20