【问题标题】:Three.js: Apply SSAO (Screen Space Ambient Occlusion) to Displacement mapThree.js:将SSAO(Screen Space Ambient Occlusion)应用于置换贴图
【发布时间】:2018-02-18 08:02:59
【问题描述】:

我是否在我的 Three.js 项目中正确实现了屏幕空间环境光遮蔽,并且运行完美,如下所示:

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

var pars = { minFilter: THREE.LinearFilter, magFilter: THREE.LinearFilter, format: THREE.RGBAFormat, stencilBuffer: true }; //Stancilbuffer true because not effect transparent object
depthRenderTarget = new THREE.WebGLRenderTarget(window.innerWidth, window.innerHeight, pars);
depthRenderTarget.texture.name = "SSAOShader.rt";
ssaoPass = new THREE.ShaderPass(THREE.SSAOShader);
///////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['radius'].value = radius;
ssaoPass.uniforms['aoClamp'].value = aoClamp;
ssaoPass.uniforms['lumInfluence'].value = lumInfluence;

但是,当我使用displacementMap 设置材质(在没有启用SSAO 的情况下正常运行)时,结果就是这样。请注意,SSAO 已“正确”应用于原始球体(带有奇怪的透明人工制品),但我需要将其应用于球体的“置换顶点”)

这是我的作曲家通行证:

   //Main render scene pass
    postprocessingComposer.addPass(renderScene);

    //Post processing pass
    if (ssaoPass) {
        postprocessingComposer.addPass(ssaoPass);
    }

这是 composer 的渲染循环

if (postprocessingComposer) {

    if (ssaoPass) {

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

        //Render composer
        scene.overrideMaterial = null;
        postprocessingComposer.render();

        renderer.clearDepth();
        renderer.render(sceneOrtho, cameraOrtho);
    }
    else {
        //Render loop with post processing (no SSAO, becasue need more checks, see above)
        renderer.clear();
        postprocessingComposer.render();        
        renderer.clearDepth();
        renderer.render(sceneOrtho, cameraOrtho);
    }
}
else {
    //Simple render loop (no post-processing)
    renderer.clear();
    renderer.render(scene, camera);
    renderer.clearDepth();
    renderer.render(sceneOrtho, cameraOrtho);
}

如何使用置换贴图归档应用到网格的正确屏幕空间环境光遮蔽?谢谢。

[更新]: 经过一些工作后,我尝试使用置换贴图对场景中的每个子项执行此过程,以定义一个新的场景覆盖材质,该材质等于具有子材质置换贴图参数的 depthMaterial。

                    var myDepthMaterial = new THREE.MeshDepthMaterial({
                        depthPacking: THREE.RGBADepthPacking,
                        displacementMap: child.material.displacementMap,
                        displacementScale: child.material.displacementScale,
                        displacementBias: child.material.displacementBias
                    });
                    child.onBeforeRender = function (renderer, scene, camera, geometry, material, group) {
                        scene.overrideMaterial = myDepthMaterial;     
                    };

这个解决方案听起来不错,但不起作用。

【问题讨论】:

    标签: three.js webgl texture-mapping pbr


    【解决方案1】:

    您正在使用带有置换贴图的 SSAO。实例化深度材质时需要指定置换贴图。

    depthMaterial = new THREE.MeshDepthMaterial( {
    
        depthPacking: THREE.RGBADepthPacking,
    
        displacementMap: displacementMap,
        displacementScale: displacementScale,
        displacementBias: displacementBias
    
    } );
    

    three.js r.87

    【讨论】:

    • 嗨,我很困惑对不起。所以我需要为场景中实现displacementMap的每个材质创建一个depthMaterial?
    • 嗯,这有点棘手。看看你是否可以证明这个答案对于单个网格是正确的......然后,对于多个网格,也许你可以通过mesh.onBeforeRender = function( renderer, scene, camera, geometry, material, group ) { scene.overrideMaterial = this.overrideMaterial; };重置scene.overrideMaterial只是一个假设......
    • 不起作用,因为在渲染循环中,我需要使用简单的 redner 场景渲染一般深度缓冲区,然后将 depthbuffer 设置为 null,然后将 composer.render 设置为空。看我上面的代码,你会看到的。您的解决方案覆盖材料但不产生 depthbuffer = null
    • @WestLangey 您的第一个解决方案(depthMaterial)使用灯光处理(实际上您需要对 PointLights 使用 customDistanceMaterial,对其他灯光使用 customDepthMaterial)。但我需要将其应用于 SSAO。所以我尝试了你的第二个解决方案(onBeforeRender 方法)但不起作用,因为在渲染过程中,我需要进行 2 次渲染:一次使用深度材料,第二次使用标准流程作曲家渲染。如果我使用 onBeforeRender 它定义一个进程(第一个进程)的行为。我也尝试了 onAfterRender 来重置状态,但我无法存档结果。
    • 我想你可以自己解决这个问题。试试if ( scene.overrideMaterial !== null ) scene.overrideMaterial = this.overrideMaterial;
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2019-05-18
    • 2023-03-26
    • 2022-01-15
    • 1970-01-01
    • 1970-01-01
    • 2013-02-27
    • 2013-07-05
    相关资源
    最近更新 更多