【发布时间】: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);
}
-
立方体被淹没了,它应该是,被透明水覆盖的部分看起来就像我想要的那样。
-
然而,问题是我只想渲染立方体及其水下部分,而不是水面的其余部分。
换句话说:
场景中有三个物体:
- 最远的红色“底部”
- 立方体,部分在上面,部分在 水下
- 水
有没有办法将它们混合在一起,以便水像素仅在它们位于立方体像素顶部时才呈现,而不是在它们仅在背景/底部顶部时呈现?
编辑:解决方案
- 向多维数据集添加模板写入功能:
const stencilId = 1;
geometry = new THREE.CubeGeometry(200, 200, 200);
material = new THREE.MeshNormalMaterial({
stencilWrite: true,
stencilFunc: THREE.AlwaysStencilFunc,
stencilZPass: THREE.ReplaceStencilOp,
stencilRef: stencilId
});
- 向表面添加模板测试功能:
surface_material = new THREE.MeshBasicMaterial({
color: 0x0000ff,
side: THREE.DoubleSide,
transparent: true,
opacity: 0.6,
stencilWrite: true,
stencilFunc: THREE.EqualStencilFunc,
stencilRef: stencilId
});
- 意识到 jsfiddle 中的 three.js 版本太旧,无法支持模板并移至 codepen :)
【问题讨论】:
标签: three.js