我目前正在发现EffectComposerThree.js ,并且正在寻找使用掩码隐藏另一个对象的一部分的方法。
假设您有一个简单的场景:相机和圆柱体之间的立方体。立方体将起到遮罩的作用并将圆柱体隐藏在其后面:
我已经使用了以下 ThreeJS 示例,并尝试调整它们以获得我想要的结果,但没有成功:
我猜问题出在通行证的使用上。
我尝试了两种解决方案(检查下面的代码片段以了解添加的通行证的类型):
1-添加 maskPass,然后添加 renderPass,以便场景的渲染仅在蒙版内绘制
composer = new THREE.EffectComposer(renderer, renderTarget);
composer.addPass(maskPass1);
composer.addPass(renderPass);
composer.addPass(clearMaskPass);
composer.addPass(outputPass);
Run Code Online (Sandbox Code Playgroud)
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);
Run Code Online (Sandbox Code Playgroud)
下面,您将找到一个代码片段,显示我到目前为止所做的事情。我用了DotScreenPass只是为了看看maskPass的效果。
在下图中,您将看到我使用左侧代码片段得到的结果以及我想要的结果在右侧
composer = new THREE.EffectComposer(renderer, renderTarget);
composer.addPass(maskPass1);
composer.addPass(renderPass);
composer.addPass(clearMaskPass);
composer.addPass(outputPass);
Run Code Online (Sandbox Code Playgroud)
maskPass1.inverse = true;
composer = new THREE.EffectComposer(renderer, renderTarget);
composer.addPass(renderPass);
composer.addPass(maskPass1);
composer.addPass(clearPass);
composer.addPass(clearMaskPass);
composer.addPass(outputPass);
Run Code Online (Sandbox Code Playgroud)
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);
}Run Code Online (Sandbox Code Playgroud)
经过进一步研究,我找到了两个解决方案,但它们不使用 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);
}
Run Code Online (Sandbox Code Playgroud)
我没有测试这个解决方案,但 jsfiddle 看起来不错!
请参阅这个问题:Three.js 与模板缓冲区的使用
以及相关的 jsfiddle :http://jsfiddle.net/g29k91qL/21/