【问题标题】:How to put a transparent color mask on a 3D object in three.js?如何在three.js中的3D对象上放置透明颜色蒙版?
【发布时间】:2021-01-18 13:23:05
【问题描述】:

我一直在尝试将一个 3D 对象“淹没”在一个半透明的 3D 水平面中(没有显示整个水平面),并且在尝试了几个小时的自定义混合模式之后,我真的不明白怎么做。

在这里提琴:https://jsfiddle.net/mglonnro/p2ju4qbk/34/

    var camera, scene, renderer, geometry, material, mesh,
      surface_geometry, surface_material, surface_mesh,
      bottom_geometry, bottom_material, bottom_mesh;
    
    init();
    animate();
    
    function init() {
    
      scene = new THREE.Scene();
    
      camera = new THREE.PerspectiveCamera(50, window.innerWidth / window.innerHeight, 1, 10000);
      camera.position.set(0, 200, 500);
      camera.lookAt(0, 0, 0);
      scene.add(camera);
    
      geometry = new THREE.CubeGeometry(200, 200, 200);
      material = new THREE.MeshNormalMaterial();
      mesh = new THREE.Mesh(geometry, material);
      scene.add(mesh);
    
      bottom_geometry = new THREE.PlaneBufferGeometry(10000, 10000);
      bottom_material = new THREE.MeshBasicMaterial({
        color: 0xFFAAAA,
        side: THREE.DoubleSide
      });
      bottom_mesh = new THREE.Mesh(bottom_geometry, bottom_material);
      bottom_mesh.rotation.set(Math.PI / 2, 0, 0);
      bottom_mesh.position.set(0, -200, 0);
      scene.add(bottom_mesh);
    
      surface_geometry = new THREE.PlaneBufferGeometry(400, 400);
      surface_material = new THREE.MeshBasicMaterial({
        color: 0x0000ff,
        side: THREE.DoubleSide,
        transparent: true,
        opacity: 0.6
      });
    
      surface_mesh = new THREE.Mesh(surface_geometry, surface_material);
      surface_mesh.rotation.set(Math.PI / 2, 0, 0);
      scene.add(surface_mesh);
    
      renderer = new THREE.WebGLRenderer();
      renderer.setPixelRatio(window.devicePixelRatio);
      renderer.setSize(window.innerWidth, window.innerHeight);
    
      document.body.appendChild(renderer.domElement);
    
    }
    
    function animate() {
    
      requestAnimationFrame(animate);
      render();
    
    }
    
    function render() {
    
      mesh.rotation.x += 0.01;
      mesh.rotation.y += 0.02;
    
      renderer.render(scene, camera); 
    }

  1. 立方体被淹没了,它应该是,被透明水覆盖的部分看起来就像我想要的那样。

  2. 然而,问题是我只想渲染立方体及其水下部分,而不是水面的其余部分。

换句话说:

场景中有三个物体:

  • 最远的红色“底部”
  • 立方体,部分在上面,部分在 水下

有没有办法将它们混合在一起,以便水像素仅在它们位于立方体像素顶部时才呈现,而不是在它们仅在背景/底部顶部时呈现?

编辑:解决方案

  1. 向多维数据集添加模板写入功能:
    const stencilId = 1;
    geometry = new THREE.CubeGeometry(200, 200, 200);
    material = new THREE.MeshNormalMaterial({
        stencilWrite: true,
        stencilFunc: THREE.AlwaysStencilFunc,
        stencilZPass: THREE.ReplaceStencilOp,
        stencilRef: stencilId
    });

  1. 向表面添加模板测试功能:

     surface_material = new THREE.MeshBasicMaterial({
        color: 0x0000ff,
        side: THREE.DoubleSide,
        transparent: true,
        opacity: 0.6,
        stencilWrite: true,
        stencilFunc: THREE.EqualStencilFunc,
        stencilRef: stencilId
      });

  1. 意识到 jsfiddle 中的 three.js 版本太旧,无法支持模板并移至 codepen :)

【问题讨论】:

    标签: three.js


    【解决方案1】:

    模板测试是实现这一目标的自然方法。

    1. 所有上面应该有水的对象都会写入一些模板值。
    2. 水平面已将模板测试设置为此值。

    three.js has stencil example,但它使用 IncrementWrap 和 DecrementWrap 逻辑,您的情况不需要。

    我建议尝试ReplaceStencilOp 用于立方体,EqualStencilFunc 用于水。

    【讨论】:

      猜你喜欢
      • 2021-12-26
      • 1970-01-01
      • 1970-01-01
      • 2016-07-11
      • 1970-01-01
      • 1970-01-01
      • 2014-11-10
      • 2019-01-29
      • 1970-01-01
      相关资源
      最近更新 更多