让SSAO着色器与SkinnedMesh一起使用

时间:2016-06-03 13:14:01

标签: javascript three.js

我一直试图让SSAO后期处理着色器与最新的(r77)版本的three.js一起使用。我一直在使用EffectComposer,代码完全从示例页面重复:

http://threejs.org/examples/webgl_postprocessing_ssao.html

相关代码是:

var renderPass = new THREE.RenderPass( Engine.scene, Engine.camera );
ssaoPass = new THREE.ShaderPass( THREE.SSAOShader );
ssaoPass.renderToScreen = true;
// ...various ShaderPass setup parameters

Engine.effectComposer = new THREE.EffectComposer( Engine.renderer );

Engine.effectComposer.addPass(renderPass);
Engine.effectComposer.addPass(ssaoPass);

我遇到的问题是SSAO似乎不适用于SkinnedMeshes。在执行蒙皮计算之前,它似乎考虑了网格的位置。

看起来像这样:

Problem with SSAO on SkinnedMesh

有没有人对最新版本有这方面的经验?我到处都看了,但找不到任何关于如何开始解决这个问题的文档。

我在另一个SO帖子(ThreeJS SSAO Shader w/ Skinned/Animated Models)中发现了对此的修复,但该解决方案已被弃用。

提前致谢,并乐意在需要时详细介绍。

根据要求,以下是simple demo page的完整代码:

<!DOCTYPE html>
<html>
    <head>
        <meta charset="UTF-8">

        <script type="text/javascript" src="js/libs/jquery.min.js"></script>
        <script type="text/javascript" src="js/libs/three.min.js"></script>

        <script type="text/javascript" src="js/libs/postprocessing/CopyShader.js"></script>
        <script type="text/javascript" src="js/libs/postprocessing/EffectComposer.js"></script>
        <script type="text/javascript" src="js/libs/postprocessing/MaskPass.js"></script>
        <script type="text/javascript" src="js/libs/postprocessing/RenderPass.js"></script>
        <script type="text/javascript" src="js/libs/postprocessing/ShaderPass.js"></script>
        <script type="text/javascript" src="js/libs/postprocessing/DotScreenShader.js"></script>
        <script type="text/javascript" src="js/libs/postprocessing/SSAOShader.js"></script>

        <link rel="stylesheet" type="text/css" href="demo.css" />
    </head>
    <body>
        <div id="demo-container"></div>
    </body>
</html>
<script>

$(document).ready(function() {

    window.doPostPro = 0;

    scene = new THREE.Scene();

    camera = new THREE.PerspectiveCamera(75, window.innerWidth/window.innerHeight, 1, 1000);
    camera.position.set(0, 200, 200);
    camera.lookAt(new THREE.Vector3(0, 0, 0));

    clock = new THREE.Clock();

    // Setup the renderer.
    renderer = new THREE.WebGLRenderer({
        antialias: true
    });
    renderer.setPixelRatio( window.devicePixelRatio );
    renderer.setSize( window.innerWidth, window.innerHeight );
    renderer.setClearColor( 0xFFFFFF );

    function setupPostProcessing() {

        // Setup render pass
        var renderPass = new THREE.RenderPass( scene, camera );

        // Setup depth pass
        depthMaterial = new THREE.MeshDepthMaterial();
        depthMaterial.depthPacking = THREE.RGBADepthPacking;
        depthMaterial.blending = THREE.NoBlending;

        depthRenderTarget = new THREE.WebGLRenderTarget( window.innerWidth, window.innerHeight, {
            minFilter:      THREE.LinearFilter, 
            magFilter:      THREE.LinearFilter,
            stencilBuffer:  true
        });

        // Setup SSAO pass
        ssaoPass = new THREE.ShaderPass( THREE.SSAOShader );
        ssaoPass.renderToScreen = true;
        //ssaoPass.uniforms[ "tDiffuse" ].value will be set by ShaderPass
        ssaoPass.uniforms[ "tDepth" ].value = depthRenderTarget.texture;
        ssaoPass.uniforms[ 'size' ].value.set( window.innerWidth, window.innerHeight );
        ssaoPass.uniforms[ 'cameraNear' ].value = camera.near;
        ssaoPass.uniforms[ 'cameraFar' ].value = camera.far;
        //ssaoPass.uniforms[ 'onlyAO' ].value = ( postprocessing.renderMode == 1 );
        ssaoPass.uniforms[ 'aoClamp' ].value = 0.3;
        ssaoPass.uniforms[ 'lumInfluence' ].value = 0.5;

        // Add pass to effect composer
        effectComposer = new THREE.EffectComposer( renderer );
        effectComposer.addPass( renderPass );
        effectComposer.addPass( ssaoPass );
    };

    setupPostProcessing();

    // Load the mesh.
    var loader = new THREE.JSONLoader();
    loader.load( "js/zombie.js", function( geometry, materials ) {

        var originalMaterial = materials[ 0 ];
        originalMaterial.skinning = true;

        geometry.computeVertexNormals();

        var mesh = new THREE.SkinnedMesh(geometry, originalMaterial);

        window.animMixer = new THREE.AnimationMixer(mesh);
        var animAction = animMixer.clipAction(geometry.animations[0]);
        animAction.play();

        scene.add(mesh);
    });

    var ambientLight = new THREE.AmbientLight( 0xCCCCCC );
    scene.add( ambientLight );

    $("#demo-container").append( renderer.domElement );

    function render() {

        if ( doPostPro ) {

            // Render depth into depthRenderTarget
            scene.overrideMaterial = depthMaterial;
            renderer.render( scene, camera, depthRenderTarget, true );

            // Render renderPass and SSAO shaderPass
            scene.overrideMaterial = null;
            effectComposer.render();
        }
        else {

            renderer.render( scene, camera );
        }
    }

    function animate() {

        requestAnimationFrame( animate );

        if ( window.animMixer != undefined ) {

            var deltaTime = clock.getDelta();
            animMixer.update(deltaTime);            
        }

        render();
    }

    animate();

    $(document).keyup(function(e) {

        // P is pressed.
        if ( e.which == 80 ) {

            window.doPostPro = !window.doPostPro;
        }
    });

});



</script>

1 个答案:

答案 0 :(得分:0)

如果要进行蒙皮,并在渲染循环中使用此模式

// Render depth into depthRenderTarget
scene.overrideMaterial = depthMaterial;
renderer.render( scene, camera, depthRenderTarget, true );

你必须确保设置

depthMaterial.skinning = true;

事情是,如果场景中还有其他元素没有蒙皮,那么这样做会抛出错误。在这种情况下,这可能是一个必须解决的three.js设计问题。

three.js r.77