Three.js: [EffectComposer]连续2个RenderPass出现问题

创建于 2012-02-01  ·  18评论  ·  资料来源: mrdoob/three.js

链接

http://demo.bkcore.com/threejs/webgl_tron_glow.html

编码

glowcomposer = new THREE.EffectComposer( renderer, renderTarget );

glowcomposer.addPass( renderModelGlow ); // RenderPass
glowcomposer.addPass( hblur ); // ShaderPass
glowcomposer.addPass( vblur ); // ShaderPass
glowcomposer.addPass( effectSave ); // SavePass

glowcomposer.addPass( renderModel ); // RenderPass
glowcomposer.addPass( finalPass ); // ShaderPass

上下文

我有两个场景使用相同的对象/相机/灯光。 一种具有漫反射纹理(http://demo.bkcore.com/threejs/webgl_tron.html),一种具有发光纹理(发光区域为黑色白色)。

我的渲染管道如下:
我首先渲染发光场景并对其进行H / V模糊处理,然后使用SavePass将输出存储到frameBuffer中。
然后我要渲染漫反射场景。
最后,将其与发光帧缓冲区混合。

问题

我的辉光采样器2D可以很好地传递给我的finalPass着色器,但是正如您在演示中所看到的那样,漫反射场景的第二个RenderPass调用效果不佳。 它仅输出黑色。

我试图在单个“渲染”通道中渲染漫反射场景,并且可以正常工作。 当我将其用作第二个RenderPass时,它不起作用。

有任何想法吗 ?

谢谢。
蒂博特D.

Question

最有用的评论

似乎原始演示不再起作用:

FWIW我做了一个简化的演示,该演示选择性地应用FX并通过Additive Blend(使用Three.js v79)在此处进行合成: https ://www.airtightinteractive.com/demos/selective-fx/

所有18条评论

我认为这是因为深度缓冲区被破坏,请参阅#1017。

对于您的用例,可以使用两个作曲器(因此使用两个完全独立的渲染目标,每个目标都有自己的深度缓冲区)来代替。

像这样:

glowComposer = new THREE.EffectComposer( renderer, renderTargetGlow );

glowComposer.addPass( renderModelGlow ); // RenderPass
glowComposer.addPass( hblur ); // ShaderPass
glowComposer.addPass( vblur ); // ShaderPass

finalComposer = new THREE.EffectComposer( renderer, renderTargetFinal );
finalComposer.addPass( renderModel ); // RenderPass
finalComposer.addPass( finalPass ); // ShaderPass

现在,漫反射层将在finalComposer作为常规的tDiffuse纹理采样器提供,而发光层将从glowComposer

根据通行证的特定数量以及通行证是否切换前后缓冲区,将是glowComposer.renderTarget1glowComposer.renderTarget2 ,最简单的方法是同时尝试这两种方法,然后看看哪个可行。

finalshader.uniforms[ 'tGlow' ].texture = glowComposer.renderTarget1;

我尝试过,但是得到了非常意外的结果。

这是您建议的代码:
http://demo.bkcore.com/threejs/webgl_tron_glow_swap.html
renderModel的tDiffuse仍为黑色。

这是完全相同的代码,只交换了两个渲染通道(漫反射场景在glow编写器中,glow场景在最终编写器中):
http://demo.bkcore.com/threejs/webgl_tron_glow_swap2.html
因为漫反射模糊而不是发光,所以这当然不是我要查找的效果,但是如您所见,tGlow和tDiffuse采样器都在工作...

我所做的就是交换(第130和175行):
新的THREE.RenderPass(场景,相机);

新的THREE.RenderPass(glowscene,glowcamera);

真是令人吃惊。

如果使用透明度,则需要使用RGBA格式作为渲染目标。

好吧,我同意,但是我没有使用任何透明度,因为我的辉光通道在黑色上呈现白色,而漫反射通道在黑色上呈现良好。 然后,我将它们添加起来,因此不需要透明度。

不过,可以肯定的是,我将RT的格式更改为RGBA,但这没有任何改变。

这里的一个奇怪问题是,在我的glowscene / glowcamera RenderPass之后执行我的场景/相机RenderPass不起作用,而在我的glowscene / glowcamera RenderPass之前执行我的场景/相机RenderPass。

嗯,似乎是不同材质的几何共享问题(请参阅#1211)。

尝试这个:

function createScene( geometry, x, y, z, b ) {

    zmesh = new THREE.Mesh( geometry, new THREE.MeshFaceMaterial() );

    // ...

    var geometryClone = THREE.GeometryUtils.clone( geometry );
    var gmat = new THREE.MeshBasicMaterial( { map: gtex } );
    var gmesh = new THREE.Mesh( geometryClone, gmat );

    // ...
}

是的! 就是这样

现在,我的两个采样器已正确填充。 谢谢 :)

编辑

嗯...还有另一种奇怪的行为,当我这样做时,我的两个采样器都很好

gl_FragColor = texel;

我正确地获得了扩散(http://demo.bkcore.com/threejs/webgl_tron_glow_swap2.html)

当我做

gl_FragColor = glow;

我得到正确的光芒。

但是当我尝试对两者进行简单的添加剂混合时
gl_FragColor =纹素​​+发光;
我只得到光晕(http://demo.bkcore.com/threejs/webgl_tron_glow_swap.html)。

很抱歉问了这么多问题,我一直在努力使它起作用,但无济于事。

编辑2

实际上似乎在做

gl_FragColor = texel + glow;

关于渲染输出,看起来更像这样:

gl_FragColor = glow + glow;

就像texel vec4被发光vec4莫名其妙地取代了。 听起来很疯狂。

您需要以不同的纹理单位放置纹理:

uniforms: {
    tDiffuse: { type: "t", value: 0, texture: null },
    tGlow:    { type: "t", value: 1, texture: null }
},

完善!
http://demo.bkcore.com/threejs/webgl_tron_glow.html

再次感谢你 :)

夏季!

万一有人对Three.js进行选择性发光渲染感到困惑,我刚刚发表了一篇关于它的小文章: http ://bkcore.com/blog/3d/webgl-three-js-animated-selective-glow.html

希望能帮助到你。

不错;)

另外,代替几何克隆,另一个更便宜的选择是使用更多相似的材料(这样,两次通过中的几何都需要相同的缓冲区)。

在这种情况下,您可以尝试使用零散射光(仅使用环境光)替代Lambert材料,而不是使用Basic材料进行辉光传递。

像这样:

glowScene.add( new THREE.AmbientLight( 0xffffff ) );

// ...

var gmat = new THREE.MeshLambertMaterial( { map: gtex, ambient: 0xffffff, color: 0x000000 } );
var gmesh = new THREE.Mesh( geometry, gmat );

确实,这很好。

http://demo.bkcore.com/threejs/webgl_tron_glow_seq.html

我将更新有关该解决方案的文章。 谢谢 !

我正在将此代码移植到r60,并奇怪地通过链接效果作曲家遇到了同一问题。 如果将其渲染到屏幕上,我可以使用Godray通行证。 但是最后一遍只输出模型。 当我不使用单独的Effect Composer时,向“ tadd”纹理通道输出的oclcomposer似乎还可以! 我已经尝试过renderer.PreserveDrawingBuffer = true,但这也不起作用。 我试过将autoclear设置为false,但这不是。

如果我在最终的作曲家之后渲染oclcomposer,并使godray通过输出到屏幕上,则可以看到Godray,但是没有模型。

如果我不将oclcomposer输出引导到最后一遍的tadd通道,而是将其通过管道传递到MeshBasicMaterial并创建带纹理的四边形并将其添加到主场景,现在我可以看到模型和Godray(在平面上),而不是我想要的效果,但它告诉我纹理管道正在工作。

// COMPOSERS
//-------------------
var renderTargetParameters = { minFilter: THREE.LinearFilter, magFilter: THREE.LinearFilter, format: THREE.RGBAFormat, stencilBufer: false };

renderTargetOcl = new THREE.WebGLRenderTarget( SCREEN_WIDTH/2, SCREEN_HEIGHT/2, renderTargetParameters );

hblur = new THREE.ShaderPass( THREE.ShaderExtras[ "horizontalBlur" ] );
vblur = new THREE.ShaderPass( THREE.ShaderExtras[ "verticalBlur" ] );
var bluriness = 2;

hblur.uniforms[ 'h' ].value = bluriness / SCREEN_WIDTH*2;
vblur.uniforms[ 'v' ].value = bluriness / SCREEN_HEIGHT*2;

var renderModel = new THREE.RenderPass( scene, camera );
var renderModelOcl = new THREE.RenderPass( oclscene, oclcamera );

grPass = new THREE.ShaderPass( THREE.Extras.Shaders.Godrays );
grPass.needsSwap = true;
grPass.renderToScreen = false;

oclcomposer = new THREE.EffectComposer( renderer, renderTargetOcl );

oclcomposer.addPass( renderModelOcl );
oclcomposer.addPass( hblur );
oclcomposer.addPass( vblur );
oclcomposer.addPass( grPass );

var finalPass = new THREE.ShaderPass( THREE.Extras.Shaders.Additive );
finalPass.needsSwap = true;
finalPass.renderToScreen = true;
finalPass.uniforms[ 'tAdd' ].texture = oclcomposer.renderTarget1;

renderTarget = new THREE.WebGLRenderTarget( SCREEN_WIDTH, SCREEN_HEIGHT, renderTargetParameters );
finalcomposer = new THREE.EffectComposer( renderer, renderTarget );

finalcomposer.addPass( renderModel );
finalcomposer.addPass( finalPass );

//RENDER
//-----------
oclcomposer.render(0.1);
finalcomposer.render( 0.1 );

@bbis是最新版本的相同问题。 你发现什么了吗

是的,我确实可以正常工作-这是代码

var renderTargetOcl = new THREE.WebGLRenderTarget( webGL_window_width/4, webGL_window_height/4, renderTargetParameters );

            hblur = new THREE.ShaderPass( THREE.ShaderExtras[ "horizontalBlur" ] );
            vblur = new THREE.ShaderPass( THREE.ShaderExtras[ "verticalBlur" ] );

            var bluriness = 3;

            hblur.uniforms[ 'h' ].value = bluriness / webGL_window_width*2;
            vblur.uniforms[ 'v' ].value = bluriness / webGL_window_height*2;

            var renderModel = new THREE.RenderPass( scene, camera );
            var renderModelOcl = new THREE.RenderPass( g_occlusion_buffer, g_occlusion_camera );

            grPass = new THREE.ShaderPass( THREE.Extras.Shaders.Godrays );
            grPass.needsSwap = true;
            grPass.renderToScreen = false;

            g_volumetric_light_composer = new THREE.EffectComposer( webGLRenderer, renderTargetOcl );

            g_volumetric_light_composer.addPass( renderModelOcl );
            g_volumetric_light_composer.addPass( hblur );
            g_volumetric_light_composer.addPass( vblur );
            g_volumetric_light_composer.addPass( hblur );
            g_volumetric_light_composer.addPass( vblur );
            g_volumetric_light_composer.addPass( grPass );

            var finalPass = new THREE.ShaderPass( THREE.Extras.Shaders.Additive );
            finalPass.needsSwap = true;
            finalPass.renderToScreen = true;
            finalPass.uniforms[ 'tAdd' ].value = g_volumetric_light_composer.renderTarget1;

            finalcomposer.addPass( renderModel );
            finalcomposer.addPass( finalPass );

//in Render Loop



                g_occlusion_camera.position = camera.position;

                g_occlusion_camera.lookAt( new THREE.Vector3(0,0,0) );
                camera.lookAt( new THREE.Vector3(0,0,0)  );

                vlight.position = pointLight1.position;
                vlight.updateMatrixWorld();

                var lPos = THREE.Extras.Utils.projectOnScreen(pointLight1, camera);
                grPass.uniforms["fX"].value = lPos.x;
                grPass.uniforms["fY"].value = lPos.y;

                g_volumetric_light_composer.render(0.1);
                finalcomposer.render( 0.1 );

非常感谢!
这是finalPass.uniforms[ 'tAdd' ].value 。 我之前有finalPass.uniforms[ 'tAdd' ].texture

嗨,bbiswas,可以在此部分添加创建g_occlusion_buffer的位置:

var renderModelOcl = new THREE.RenderPass(g_occlusion_buffer,g_occlusion_camera);

似乎原始演示不再起作用:

FWIW我做了一个简化的演示,该演示选择性地应用FX并通过Additive Blend(使用Three.js v79)在此处进行合成: https ://www.airtightinteractive.com/demos/selective-fx/

此页面是否有帮助?
0 / 5 - 0 等级