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

コンテキスト

同じオブジェクト/カメラ/ライトで2つのシーンを取得しました。 1つは拡散テクスチャ(http://demo.bkcore.com/threejs/webgl_tron.html)で、もう1つはグローテクスチャ(光る領域は黒地に白)です。

私のレンダリングパイプラインは次のとおりです:
最初にグローシーンをレンダリングし、それにH / Vブラーを適用してから、SavePassを使用して出力をframeBufferに格納します。
次に、拡散シーンをレンダリングします。
そして最後に、それをグローフレームバッファーと混合します。

問題

グローsampler2DはfinalPassシェーダーにうまく渡されていますが、デモでわかるように、拡散シーンの2番目のRenderPass呼び出しはうまく機能していません。 黒のみを出力します。

拡散シーンを1回のレンダーパスでレンダリングしようとしましたが、それは機能します。 それが機能しないのは、2番目のRenderPassとして使用したときです。

何か案は ?

ありがとうございました。
ティボーD。

Question

最も参考になるコメント

元のデモが機能しなくなったようです。

FWIWここで、FXを選択的に適用し、Additive Blendを介して(Three.js v79を使用して)作成する簡略化されたデモを作成しました: https ://www.airtightinteractive.com/demos/selective-fx/

全てのコメント18件

デプスバッファが破壊されたためだと思います。#1017を参照してください。

ユースケースの場合、代わりに機能するのは、2つのコンポーザーを使用することです(したがって、それぞれが独自の深度バッファーを持つ2つの完全に別個のレンダーターゲット)。

このようなもの:

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.renderTarget1またはglowComposer.renderTarget2いずれかになります。最も簡単なのは、両方を試してどちらが機能するかを確認することです。

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

私はそれを試しましたが、非常に予想外の結果が得られました。

これはあなたが提案したコードです:
http://demo.bkcore.com/threejs/webgl_tron_glow_swap.html
renderModelのtDiffuseはまだ黒です。

これはまったく同じコードですが、2つのレンダーパスだけが入れ替わっています(拡散シーンはグローコンポーザーにあり、グローシーンは最終コンポーザーにあります):
http://demo.bkcore.com/threejs/webgl_tron_glow_swap2.html
もちろん、ディフューズがぼやけていてグローではないので、私が探している効果ではありませんが、ご覧のとおり、tGlowとtDiffuseの両方のサンプラーが機能しています...

そして私がしたのは交換することだけでした(130行目と175行目):
new THREE.RenderPass(シーン、カメラ);

new THREE.RenderPass(glowscene、glowcamera);

それはかなり驚くべきことです。

透明度を使用する場合は、レンダーターゲットにRGBA形式を使用する必要があります。

同意しますが、グローパスは黒で白にレンダリングされ、拡散パスは黒で拡散するため、透明度は使用していません。 次に、透明度が不要になるように追加して作成します。

それでも、念のため、RTの形式をRGBAに変更しましたが、何も変更されませんでした。

ここでの奇妙な問題は、glowscene / glowcamera RenderPassの前にシーン/カメラRenderPassを実行しているのに、glowscene / glowcameraRenderPassの後にシーン/カメラ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 );

    // ...
}

はい ! それだけでした。

これで、2つのサンプラーが正しく充填されました。 ありがとうございました :)

編集

うーん...さらに別の奇妙な振る舞い、私の2つのサンプラーは良いです

gl_FragColor = texel;

ディフューズを正しく取得します(http://demo.bkcore.com/threejs/webgl_tron_glow_swap2.html)

私がする時

gl_FragColor = glow;

正しく輝きます。

しかし、私が両方で単純な添加剤ブレンドをしようとすると
gl_FragColor = texel + glow;
グロー(http://demo.bkcore.com/threejs/webgl_tron_glow_swap.html)しか得られません。

たくさんの質問をしてすみません、私はこれを機能させるように努めてきましたが、役に立ちませんでした。

EDIT2

実際、やっているようです

gl_FragColor = texel + glow;

出力のレンダリングに関しては、次のようになります。

gl_FragColor = glow + glow;

それは、テクセル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

それが役に立てば幸い。

いいね;)

あるいは、ジオメトリのクローンを作成する代わりに、より安価なオプションとして、より類似したマテリアルを使用することもできます(したがって、両方のパスのジオメトリに同じバッファが必要になります)。

この場合、グローパスに基本マテリアルを使用する代わりに、周囲光だけで、拡散照明がゼロのランバートマテリアルを試すことができます。

このようなもの:

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に移植していますが、奇妙なことに、エフェクトコンポーザーのチェーンで同じ問題が発生しています。 画面にレンダリングすると、ゴッドレイパスが機能します。 ただし、最終パスはモデルのみを出力します。 別のEffectComposerを使用しない場合、「tadd」テクスチャチャンネルへのoclcomposer出力は問題ないようです。 renderer.PreserveDrawingBuffer = trueで試しましたが、それも機能しませんでした。 autoclearをfalseに設定しようとしましたが、そうではありませんでした。

最終的なコンポーザーの後にoclcomposerをレンダリングし、godrayパスを画面に出力すると、godrayは表示されますが、モデルは表示されません。

最終パスでoclcomposer出力をtaddチャネルに送信する代わりに、MeshBasicMaterialにパイプしてテクスチャクワッドを作成し、メインシーンに追加すると、モデルとゴッドレイ(平面上)が表示されます。私が望む効果ですが、テクスチャパイプが機能していることがわかります。

// 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 );

@bbiswas最新バージョンでも同じ問題が発生します。 何か見つけましたか?

はい、動作しました-コードは次のとおりです

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 評価