我目前正在发现three.js的EffectComposer
,我正在寻找使用蒙版隐藏另一个对象的一部分的方法。
假设您有一个简单的场景:相机和圆柱体之间的立方体。立方体将扮演面具的角色并隐藏其背后的圆柱体:
我玩了以下ThreeJS的例子并尝试调整它们以获得我想要的结果,但没有成功:
问题来自于我猜的使用传球。
我尝试了两种解决方案(请查看下面的代码段以了解添加的通道类型):
1 - 添加maskPass然后再添加renderPass,以便只在我的面具中绘制我的场景渲染
composer = new THREE.EffectComposer(renderer, renderTarget);
composer.addPass(maskPass1);
composer.addPass(renderPass);
composer.addPass(clearMaskPass);
composer.addPass(outputPass);
2 - 添加renderPass,然后添加反转蒙版,并使用clearPass删除像素
maskPass1.inverse = true;
composer = new THREE.EffectComposer(renderer, renderTarget);
composer.addPass(renderPass);
composer.addPass(maskPass1);
composer.addPass(clearPass);
composer.addPass(clearMaskPass);
composer.addPass(outputPass);
下面,您会看到一段代码片段,展示了我迄今为止所做的工作。我只使用DotScreenPass
来查看maskPass的效果。
在下面的图片中,您会看到我使用左侧代码段获得的结果以及我想要的右侧结果
var composer, renderer;
var box, torus;
init();
animate();
function init() {
// Setup renderer
renderer = new THREE.WebGLRenderer({antialias: false});
renderer.setClearColor(0xe0e0e0);
renderer.setPixelRatio(window.devicePixelRatio);
renderer.setSize(window.innerWidth, window.innerHeight);
renderer.autoClear = false;
document.body.appendChild(renderer.domElement);
// Setup scenes
var camera = new THREE.PerspectiveCamera(50, window.innerWidth / window.innerHeight, 1, 1000);
camera.position.z = 10;
var scene1 = new THREE.Scene();
var scene2 = new THREE.Scene();
// Add objects
box = new THREE.Mesh(new THREE.BoxGeometry(4, 4, 4));
box.rotateY(Math.PI / 6);
box.rotateX(-Math.PI / 6);
scene1.add(box);
torus = new THREE.Mesh(new THREE.TorusGeometry(3, 1, 16, 32), new THREE.MeshBasicMaterial({
color: 0xff0000
}));
scene2.add(torus);
// Create passes for composer
var clearPass = new THREE.ClearPass();
var clearMaskPass = new THREE.ClearMaskPass();
var maskPass1 = new THREE.MaskPass(scene1, camera);
var maskPass2 = new THREE.MaskPass(scene2, camera);
maskPass1.inverse = true
var renderPass = new THREE.RenderPass(scene2, camera);
var screenDotPass = new THREE.DotScreenPass();
var outputPass = new THREE.ShaderPass(THREE.CopyShader);
outputPass.renderToScreen = true;
var renderTarget = new THREE.WebGLRenderTarget(window.innerWidth, window.innerHeight, {
minFilter: THREE.LinearFilter,
magFilter: THREE.LinearFilter,
format: THREE.RGBFormat,
stencilBuffer: true
});
// Create composer and add passes
composer = new THREE.EffectComposer(renderer, renderTarget);
composer.addPass(renderPass);
composer.addPass(maskPass1);
composer.addPass(screenDotPass);
composer.addPass(clearMaskPass);
composer.addPass(outputPass);
}
function animate() {
requestAnimationFrame(animate);
var time = performance.now() * 0.001;
renderer.clear();
composer.render(time);
}

body
{
background-color: #000;
margin: 0px;
overflow: hidden;
}

<div id="container"></div>
<script src="https://cdn.rawgit.com/mrdoob/three.js/master/build/three.js"></script>
<script src="https://cdn.rawgit.com/mrdoob/three.js/master/examples/js/shaders/CopyShader.js"></script>
<script src="https://cdn.rawgit.com/mrdoob/three.js/master/examples/js/shaders/DotScreenShader.js"></script>
<script src="https://cdn.rawgit.com/mrdoob/three.js/master/examples/js/postprocessing/EffectComposer.js"></script>
<script src="https://cdn.rawgit.com/mrdoob/three.js/master/examples/js/postprocessing/ClearPass.js"></script>
<script src="https://cdn.rawgit.com/mrdoob/three.js/master/examples/js/postprocessing/TexturePass.js"></script>
<script src="https://cdn.rawgit.com/mrdoob/three.js/master/examples/js/postprocessing/ShaderPass.js"></script>
<script src="https://cdn.rawgit.com/mrdoob/three.js/master/examples/js/postprocessing/MaskPass.js"></script>
<script src="https://cdn.rawgit.com/mrdoob/three.js/master/examples/js/postprocessing/DotScreenPass.js"></script>
<script src="https://cdn.rawgit.com/mrdoob/three.js/master/examples/js/postprocessing/RenderPass.js"></script>
<script src="https://cdn.rawgit.com/mrdoob/three.js/master/examples/js/postprocessing/DotScreenPass.js"></script>
<script src="https://cdn.rawgit.com/mrdoob/three.js/master/examples/js/Detector.js"></script>
<script src="https://cdn.rawgit.com/mrdoob/three.js/master/examples/js/libs/stats.min.js"></script>
&#13;
答案 0 :(得分:1)
经过进一步的研究,我找到了两个解决方案,但他们没有使用EffectComposer(这对我来说不是问题)。
这个想法如下:
谢谢@WestLangley这个问题:How to write to zbuffer only with three.js
var composer, renderer;
var box, sphere;
var scene1, scene2;
var camera;
init();
animate();
function init() {
// Setup renderer
renderer = new THREE.WebGLRenderer({
antialias: false
});
renderer.setClearColor(0xe5e5e5);
renderer.setPixelRatio(window.devicePixelRatio);
renderer.setSize(window.innerWidth, window.innerHeight);
// VERY IMPORTANT
renderer.autoClear = false ;
document.body.appendChild(renderer.domElement);
// Setup scenes
camera = new THREE.PerspectiveCamera(50, window.innerWidth / window.innerHeight, 1, 1000);
camera.position.z = 15;
scene1 = new THREE.Scene();
scene2 = new THREE.Scene();
// Add objects
box = new THREE.Mesh(new THREE.BoxGeometry(4, 4, 4), new THREE.MeshBasicMaterial({
color: 0x008800
}));
box.rotateY(Math.PI / 6);
box.rotateX(-Math.PI / 6);
box.position.z += 1;
scene1.add(box);
sphere = new THREE.Mesh(new THREE.SphereGeometry(4, 16, 16), new THREE.MeshBasicMaterial({
color: 0xff0000
}));
scene2.add(sphere);
}
function animate() {
requestAnimationFrame(animate);
// Manually clear the renderer
renderer.clear();
// Sets which color components to enable or to disable when drawing or rendering to a WebGLFramebuffer
renderer.context.colorMask(false, false, false, false); // R, G, B, A
renderer.render(scene1, camera);
// Enable back the writing into the color and alpha component
renderer.context.colorMask(true, true, true, true);
renderer.render(scene2, camera);
}
我没有测试过这个解决方案,但jsfiddle看起来很不错!
请参阅此问题:Three.js usage with stencil buffer
相关的jsfiddle:http://jsfiddle.net/g29k91qL/21/