three.js具有多个renderpass的后处理maskpass永远无法工作

时间:2018-06-27 06:16:12

标签: three.js

我正在为此努力:

postprocessing renderPass_1, maskPass, renderPass_2, desired result

代码如下:

<!DOCTYPE html>
<html lang="en">
    <head>
        <meta charset="utf-8">
        <meta name="viewport" content="width=device-width, user-scalable=no, minimum-scale=1.0, maximum-scale=1.0">
        <style>
            body {
                background-color: #000;
                margin: 0px;
                overflow: hidden;
            }
        </style>
    </head>
    <body>
        <div id="container"></div>
        <script src="../build/three.js"></script>
        <script src="js/shaders/CopyShader.js"></script>
        <script src="js/postprocessing/EffectComposer.js"></script>
        <script src="js/postprocessing/ClearPass.js"></script>
        <script src="js/postprocessing/ShaderPass.js"></script>
        <script src="js/postprocessing/MaskPass.js"></script>
        <script src="js/postprocessing/RenderPass.js"></script>
        <script src="js/Detector.js"></script>

        <script>

            if ( ! Detector.webgl ) Detector.addGetWebGLMessage();

            var composer, renderer;
            var box_mask, box_1, box_2;

            init();
            animate();

            function init() {

                var camera_mask = new THREE.PerspectiveCamera( 50, window.innerWidth / window.innerHeight, 1, 1000 );
                camera_mask.position.z = 6;
                var camera_1 = new THREE.PerspectiveCamera( 50, window.innerWidth / window.innerHeight, 1, 1000 );
                camera_1.position.z = 6;
                var camera_2 = new THREE.PerspectiveCamera( 50, window.innerWidth / window.innerHeight, 1, 1000 );
                camera_2.position.z = 6;

                var scene_mask = new THREE.Scene();
                var scene_1 = new THREE.Scene();
                var scene_2 = new THREE.Scene();

                scene_mask.background = new THREE.Color( 0x000000 );
                scene_1.background = new THREE.Color( 0xffffff );
                scene_2.background = new THREE.Color( 0x000000 );

                var box_mask_1 = new THREE.CircleGeometry( 2, 4 );
                var box_mask_2 = new THREE.CircleGeometry( 2, 4 );

                var singleGeometry_mask = new THREE.Geometry();

                var boxMesh_mask_1 = new THREE.Mesh(box_mask_1);
                boxMesh_mask_1.position.z = 1;
                var boxMesh_mask_2 = new THREE.Mesh(box_mask_2);
                boxMesh_mask_2.rotation.y = Math.PI;
                boxMesh_mask_2.position.z = -1;

                boxMesh_mask_1.updateMatrix(); // as needed
                singleGeometry_mask.merge(boxMesh_mask_1.geometry, boxMesh_mask_1.matrix);
                boxMesh_mask_2.updateMatrix(); // as needed
                singleGeometry_mask.merge(boxMesh_mask_2.geometry, boxMesh_mask_2.matrix);

                var material_mask = new THREE.MeshBasicMaterial({color: 0xffffff});
                box_mask = new THREE.Mesh(singleGeometry_mask, material_mask);

                scene_mask.add( box_mask );

                var box_1_1 = new THREE.CircleGeometry( 2, 4 );
                var box_1_2 = new THREE.CircleGeometry( 2, 4 );

                var singleGeometry_1 = new THREE.Geometry();

                var boxMesh_1_1 = new THREE.Mesh(box_1_1);
                boxMesh_1_1.position.z = -1;
                var boxMesh_1_2 = new THREE.Mesh(box_1_2);
                boxMesh_1_2.rotation.y = Math.PI;
                boxMesh_1_2.position.z = 1;

                boxMesh_1_1.updateMatrix();
                singleGeometry_1.merge(boxMesh_1_1.geometry, boxMesh_1_1.matrix);
                boxMesh_1_2.updateMatrix();
                singleGeometry_1.merge(boxMesh_1_2.geometry, boxMesh_1_2.matrix);

                var material_1 = new THREE.MeshBasicMaterial({color: 0x000000});
                box_1 = new THREE.Mesh(singleGeometry_1, material_1);

                scene_1.add( box_1 );

                var box_2_1 = new THREE.CircleGeometry( 2, 4 );
                var box_2_2 = new THREE.CircleGeometry( 2, 4 );

                var singleGeometry_2 = new THREE.Geometry();

                var boxMesh_2_1 = new THREE.Mesh(box_2_1);
                boxMesh_2_1.position.z = -1;
                var boxMesh_2_2 = new THREE.Mesh(box_2_2);
                boxMesh_2_2.rotation.y = Math.PI;
                boxMesh_2_2.position.z = 1;

                boxMesh_2_1.updateMatrix();
                singleGeometry_2.merge(boxMesh_2_1.geometry, boxMesh_2_1.matrix);

                boxMesh_2_2.updateMatrix();
                singleGeometry_2.merge(boxMesh_2_2.geometry, boxMesh_2_2.matrix);

                var material_2 = new THREE.MeshBasicMaterial({color: 0xffffff});
                box_2 = new THREE.Mesh(singleGeometry_2, material_2);

                scene_2.add( box_2 );

                renderer = new THREE.WebGLRenderer();
                renderer.setClearColor( 0xffffff );
                renderer.setPixelRatio( window.devicePixelRatio );
                renderer.setSize( window.innerWidth, window.innerHeight );
                renderer.autoClear = false;
                document.body.appendChild( renderer.domElement );

                var clearPass = new THREE.ClearPass();
                var clearMaskPass = new THREE.ClearMaskPass();
                var maskPass = new THREE.MaskPass( scene_mask, camera_mask );
                var renderPass_1 = new THREE.RenderPass( scene_1, camera_1 );
                var renderPass_2 = new THREE.RenderPass( scene_2, camera_2 );
                var outputPass = new THREE.ShaderPass( THREE.CopyShader );
                outputPass.renderToScreen = true;

                var parameters = {
                    minFilter: THREE.LinearFilter,
                    magFilter: THREE.LinearFilter,
                    format: THREE.RGBFormat,
                    stencilBuffer: true
                };

                var renderTarget = new THREE.WebGLRenderTarget( window.innerWidth, window.innerHeight, parameters );

                composer = new THREE.EffectComposer( renderer , renderTarget );
                composer.addPass( clearPass );
                composer.addPass( renderPass_1 );
                composer.addPass( maskPass );
                composer.addPass( renderPass_2 );
                composer.addPass( clearMaskPass );
                composer.addPass( outputPass );

            }

            function animate() {

                requestAnimationFrame( animate );

                var time = performance.now() * 0.001  * 2;

                box_mask.rotation.y = time;
                box_1.rotation.y = time;
                box_2.rotation.y = time;

                renderer.clear();
                composer.render( time );

            }

        </script>
    </body>
</html>

这永远都行不通:

composer.addPass( clearPass );
composer.addPass( renderPass_1 );
composer.addPass( maskPass );
composer.addPass( renderPass_2 );
composer.addPass( clearMaskPass );
composer.addPass( outputPass );

如果我用THREE.TexturePass切换出“ renderPass_2”,则它起作用了,但这不是我想要的。

这是codepen:

https://codepen.io/oxbits/pen/yEQLGK?editors=0010

任何人都可以将两个renderPass与一个蒙版结合起来吗?

我应该使用其他方法吗?

2 个答案:

答案 0 :(得分:2)

我终于可以正常工作了!虽然我不确定如何...

看看:

https://codepen.io/anon/pen/PyJObz

一个窍门是在第二个渲染中不使用场景背景。相反,我必须创建一个背景网格。

以下代码:

<!DOCTYPE html>
<html lang="en">
    <head>
        <meta charset="utf-8">
        <meta name="viewport" content="width=device-width, user-scalable=no, minimum-scale=1.0, maximum-scale=1.0">
        <style>

            html, body, canvas {
    margin: 0px;
    overflow: hidden;
}
#fps {
    position: absolute;
    top: 0px;
    left: 0px;
    color: #fff;
    z-index: 50;
}
        </style>
    </head>
    <body>
        <div id="container"></div>
        <script src="../build/three.js"></script>
        <script src="js/shaders/CopyShader.js"></script>
        <script src="js/postprocessing/EffectComposer.js"></script>
        <script src="js/postprocessing/ClearPass.js"></script>
        <script src="js/postprocessing/ShaderPass.js"></script>
        <script src="js/postprocessing/MaskPass.js"></script>
        <script src="js/postprocessing/RenderPass.js"></script>
        <script src="js/Detector.js"></script>
        <script src="https://code.jquery.com/jquery-3.3.1.min.js"></script>


        <script>

            // if ( ! Detector.webgl ) Detector.addGetWebGLMessage();

            let scene       = null;
            let normal      = null;
            let outline     = null;
            let outScene    = null;
            let maskScene   = null;
            let light       = null;
            let renderer    = null;
            let composer    = null;
            let camera1     = null;
            let camera2     = null;
            let camera3     = null;
            let mesh1       = null;
            let mesh2       = null;
            let mesh3       = null;
            let bg_mesh = null;
            let renderTarget = null;

            let screenWidth  = window.innerWidth;
            let screenHeight = window.innerHeight;

            const clock = new THREE.Clock;

            let elapsedTime = 0;
            let frameCount  = 0;

            const init = function() {

                // SCENE

                scene     = new THREE.Scene;
                maskScene = new THREE.Scene;
                outScene  = new THREE.Scene;
                setModel();

                // SCENE CAMERA

                camera1 = new THREE.PerspectiveCamera(40, screenWidth/screenHeight, 1, 1000);
                camera1.position.set(0, 0, 10);
                scene.add(camera1);

                camera2 = new THREE.PerspectiveCamera(40, screenWidth/screenHeight, 1, 1000);
                camera2.position.set(0, 0, 10);
                outScene.add(camera2);

                camera3 = new THREE.PerspectiveCamera(40, screenWidth/screenHeight, 1, 1000);
                camera3.position.set(0, 0, 10);
                maskScene.add(camera3);

                    scene.background = new THREE.Color( 0xffffff );

                // RENDERER

                renderer = new THREE.WebGLRenderer({
                    width: screenWidth,
                    height: screenHeight,
                    antialias: true
                });

                renderer.setSize(screenWidth, screenHeight);
                renderer.setClearColor(0x000000);
                renderer.autoClear = false;
                renderer.gammaInput = true;
                renderer.gammaOutput = true;

                document.body.appendChild(renderer.domElement);

                // POSTPROCESSING

                const renderTargetParameters = {
                    minFilter:      THREE.LinearFilter,
                    magFilter:      THREE.LinearFilter,
                    format:         THREE.RGBAFormat,
                    stencilBuffer:  true
                };

                renderTarget = new THREE.WebGLRenderTarget(window.innerWidth, window.innerHeight, renderTargetParameters);

                composer    = new THREE.EffectComposer(renderer);
                composer.renderTarget1.stencilBuffer = true;
                composer.renderTarget2.stencilBuffer = true;

                normal      = new THREE.RenderPass(scene, camera1);
                outline     = new THREE.RenderPass(outScene, camera2);
                outline.clear = false;

                const mask        = new THREE.MaskPass(maskScene, camera3);
                mask.inverse = false;
                const clearMask   = new THREE.ClearMaskPass;
                const copyPass    = new THREE.ShaderPass(THREE.CopyShader);
                copyPass.renderToScreen = true;

                composer.addPass(normal);
                composer.addPass(mask);
                composer.addPass(outline);
                composer.addPass(clearMask);
                composer.addPass(copyPass);

                // EVENTS

                return window.addEventListener('resize', onWindowResize, false);
            };

            var setModel = function() {

                    var box_mask_1 = new THREE.CircleGeometry( 2, 4 );
                    var box_mask_2 = new THREE.CircleGeometry( 2, 4 );

                    var singleGeometry_mask = new THREE.Geometry();

                    var boxMesh_mask_1 = new THREE.Mesh(box_mask_1);
                    boxMesh_mask_1.position.z = 1;
                    var boxMesh_mask_2 = new THREE.Mesh(box_mask_2);
                    boxMesh_mask_2.rotation.y = Math.PI;
                    boxMesh_mask_2.position.z = -1;

                    boxMesh_mask_1.updateMatrix(); // as needed
                    singleGeometry_mask.merge(boxMesh_mask_1.geometry, boxMesh_mask_1.matrix);
                    boxMesh_mask_2.updateMatrix(); // as needed
                    singleGeometry_mask.merge(boxMesh_mask_2.geometry, boxMesh_mask_2.matrix);


                    var box_1_1 = new THREE.CircleGeometry( 2, 4 );
                    var box_1_2 = new THREE.CircleGeometry( 2, 4 );

                    var singleGeometry_1 = new THREE.Geometry();

                    var boxMesh_1_1 = new THREE.Mesh(box_1_1);
                    boxMesh_1_1.position.z = -1;
                    var boxMesh_1_2 = new THREE.Mesh(box_1_2);
                    boxMesh_1_2.rotation.y = Math.PI;
                    boxMesh_1_2.position.z = 1;

                    boxMesh_1_1.updateMatrix();
                    singleGeometry_1.merge(boxMesh_1_1.geometry, boxMesh_1_1.matrix);
                    boxMesh_1_2.updateMatrix();
                    singleGeometry_1.merge(boxMesh_1_2.geometry, boxMesh_1_2.matrix);


                    var box_2_1 = new THREE.CircleGeometry( 2, 4 );
                    var box_2_2 = new THREE.CircleGeometry( 2, 4 );

                    var singleGeometry_2 = new THREE.Geometry();

                    var boxMesh_2_1 = new THREE.Mesh(box_2_1);
                    boxMesh_2_1.position.z = -1;
                    var boxMesh_2_2 = new THREE.Mesh(box_2_2);
                    boxMesh_2_2.rotation.y = Math.PI;
                    boxMesh_2_2.position.z = 1;

                    boxMesh_2_1.updateMatrix();
                    singleGeometry_2.merge(boxMesh_2_1.geometry, boxMesh_2_1.matrix);

                    boxMesh_2_2.updateMatrix();
                    singleGeometry_2.merge(boxMesh_2_2.geometry, boxMesh_2_2.matrix);

                    const matColor = new THREE.MeshBasicMaterial({
                    color: 0x000000});
                mesh1 = new THREE.Mesh(singleGeometry_1, matColor); // geometry, matColor);
                scene.add(mesh1);

                // flat mask
                const matFlat = new THREE.MeshBasicMaterial({
                    color: 0x000000});
                mesh2 = new THREE.Mesh(singleGeometry_mask, matFlat);
                maskScene.add(mesh2);

                    const matColor2 = new THREE.MeshBasicMaterial({
                    color: 0xffffff});
                mesh3 = new THREE.Mesh(singleGeometry_2, matColor2);
                outScene.add(mesh3);

                    const matColor3 = new THREE.MeshBasicMaterial({
                    color: 0x000000});

                    bg_mesh = new THREE.Mesh(new THREE.CircleGeometry( 100, 4 ), matColor3);
                    outScene.add(bg_mesh);
                    bg_mesh.position.set(0, 0, -10);

            };

            var onWindowResize = function() {

                screenWidth  = window.innerWidth;
                screenHeight = window.innerHeight;

                camera1.aspect = screenWidth / screenHeight;
                camera2.aspect = camera1.aspect;
                camera3.aspect = camera1.aspect;

                camera1.updateProjectionMatrix();
                camera2.updateProjectionMatrix();
                camera3.updateProjectionMatrix();

                return renderer.setSize(screenWidth, screenHeight);
            };

            var animate = function() {

                updateFps();
                requestAnimationFrame(animate);
                return render();
            };

            var render = function() {

                const now = Date.now();
                const delta = clock.getDelta();

                if (mesh1) {
                    mesh1.rotation.y += 0.015;
                    mesh2.rotation.y = mesh1.rotation.y;
                    mesh3.rotation.y = mesh1.rotation.y;
                }

                return composer.render();
            };

            var updateFps = function() {

                elapsedTime += clock.getDelta();
                frameCount++;

                if (elapsedTime >= 1) {
                    $('#fps').html(frameCount);
                    frameCount  = 0;
                    return elapsedTime = 0;
                }
            };


            init();
            animate();

        </script>
    </body>
</html>

答案 1 :(得分:0)

只是因为我不知道您的情况的具体细节,但我之前使用过作曲家...

如果仅在maskPass之后添加texturePass,然后将renderPass1作为下一个保留,怎么办?

作曲家的工作原理是通过一系列缓冲区来应用操作,因此在两次操作之间,您有时必须执行texturePass才能将当前输出复制回输入以进行下一次传递...

但这只是一个猜测,以防万一没有其他人回答。...