Three.js: [EffectComposer] Problema con 2 RenderPass consecutivos

Creado en 1 feb. 2012  ·  18Comentarios  ·  Fuente: mrdoob/three.js

El enlace

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

El código

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

El contexto

Tengo dos escenas con el mismo objeto / cámara / luz. Uno con textura difusa (http://demo.bkcore.com/threejs/webgl_tron.html) y otro con textura luminosa (las áreas brillantes son blancas sobre negro).

Mi canalización de renderizado es el siguiente:
Primero renderizo la escena luminosa y le aplico un desenfoque H / V, luego almaceno la salida en un frameBuffer usando un SavePass.
Entonces quiero renderizar la escena difusa.
Y finalmente mezcle eso con el búfer de marco resplandor.

La cuestión

Mi glow sampler2D está pasando bien a mi sombreador finalPass, pero como puede ver en la demostración, la segunda llamada de RenderPass para la escena difusa no funciona bien. Solo emite negro.

Intenté renderizar la escena difusa en una sola pasada de Render y eso funciona. Es cuando lo uso como un segundo RenderPass que no funciona.

Algunas ideas ?

Gracias.
Thibaut D.

Question

Comentario más útil

Parece que la demostración original ya no funciona:

FWIW Hice una demostración simplificada de la aplicación selectiva de FX y la composición a través de Additive Blend (usando Three.js v79) aquí: https://www.airtightinteractive.com/demos/selective-fx/

Todos 18 comentarios

Creo que se debe a que el búfer de profundidad se destruye, ver # 1017.

Para su caso de uso, lo que puede funcionar en su lugar es usar dos compositores (y por lo tanto, dos destinos de renderizado completamente separados, cada uno con su propio búfer de profundidad).

Algo como esto:

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

Ahora la capa difusa estará disponible como muestra de textura normal tDiffuse en finalComposer y la capa luminosa que proporcionará desde glowComposer .

Será glowComposer.renderTarget1 o glowComposer.renderTarget2 dependiendo de la cantidad particular de pases y si los pases cambian los búferes delanteros y traseros, lo más simple es probar ambos y ver cuál funciona.

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

Lo intenté, pero obtuve un resultado muy inesperado.

Este es el código que propusiste:
http://demo.bkcore.com/threejs/webgl_tron_glow_swap.html
El tDiffuse del renderModel sigue siendo negro.

Y este es exactamente el mismo código, con solo los dos pases de render intercambiados (la escena difusa está en el compositor resplandor y la escena resplandor en el compositor final):
http://demo.bkcore.com/threejs/webgl_tron_glow_swap2.html
Por supuesto, no es el efecto que estoy buscando, ya que el difuso está borroso y no el brillo, pero como puede ver, los muestreadores tGlow y tDiffuse están funcionando ...

Y todo lo que hice fue intercambiar (líneas 130 y 175):
nuevo THREE.RenderPass (escena, cámara);
con
nuevo TRES.RenderPass (escena luminosa, cámara luminosa);

Es bastante sorprendente.

Debe usar el formato RGBA para los objetivos de renderizado si usa la transparencia.

Bueno, estoy de acuerdo, pero no estoy usando ninguna transparencia ya que mi pase de brillo se vuelve blanco sobre negro y mi pase difuso bien ... difuso sobre negro. Luego los compongo con una adición para que no se necesite transparencia.

Aún así, solo para estar seguro, cambié el formato de RT a RGBA, pero eso no cambió nada.

El problema extraño aquí es que hacer mi escena / cámara RenderPass después de mi escena luminosa / cámara luminosa RenderPass no funciona, mientras que hago mi escena / cámara RenderPass antes de mi escena luminosa / cámara luminosa RenderPass.

Mmmm, parece un problema de intercambio de geometría para diferentes materiales (ver # 1211).

Prueba esto:

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

    // ...
}

Si ! Eso fue todo.

Mis dos muestreadores ahora están llenos correctamente. Gracias :)

EDITAR

Hum ... Otro comportamiento extraño, mis dos muestreadores son buenos, cuando lo hago

gl_FragColor = texel;

Obtengo la difusión correctamente (http://demo.bkcore.com/threejs/webgl_tron_glow_swap2.html)

Cuando lo hago

gl_FragColor = glow;

Consigo el brillo correctamente.

Pero cuando trato de hacer una simple mezcla de aditivos en ambos
gl_FragColor = texel + resplandor;
Solo obtengo el brillo (http://demo.bkcore.com/threejs/webgl_tron_glow_swap.html).

Lo siento por hacer tantas preguntas, he intentado que esto funcione, pero fue en vano ...

EDIT2

De hecho parece que haciendo

gl_FragColor = texel + glow;

Se parece más a esto con respecto a la salida de renderizado:

gl_FragColor = glow + glow;

Es como si el texel vec4 fuera reemplazado inexplicablemente por el glow vec4. Suena loco.

Necesitas poner texturas en diferentes unidades de textura:

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

¡Verano!

En caso de que alguien esté interesado en la representación de brillo selectivo con Three.js, acabo de publicar un pequeño artículo al respecto: http://bkcore.com/blog/3d/webgl-three-js-animated-selective-glow.html

Espero eso ayude.

Agradable ;)

Alternativamente, en lugar de la clonación de geometría, otra opción más barata sería utilizar materiales más similares (de modo que la geometría en ambas pasadas necesitaría los mismos búferes).

En este caso, en lugar de utilizar material básico para el paso luminoso, puede probar el material Lambert sin iluminación difusa, solo con luz ambiental.

Algo como esto:

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

// ...

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

De hecho, está funcionando a la perfección.

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

Actualizaré mi artículo sobre esta solución. Gracias !

Estoy portando este código a r60 y extrañamente me encuentro con el mismo problema al encadenar los compositores de efectos. Tengo el pase godray funcionando si lo renderizo en la pantalla. Pero el pase final solo genera el modelo. ¡La salida del oclcomposer al canal de textura "tadd" parece estar bien cuando no uso un Compositor de efectos separado! Lo intenté con renderer.PreserveDrawingBuffer = true pero tampoco funcionó. Intenté configurar el borrado automático en falso, pero no fue así.

Si renderizo el oclcomposer después del compositor final y hago que godray pase la salida a la pantalla, puedo ver los godrays pero no los modelos.

En lugar de dirigir la salida del oclcomposer al canal tadd en la pasada final, si lo canalizo a un MeshBasicMaterial y creo un quad texturizado y lo agrego a la escena principal, ahora puedo ver el modelo y los godrays (en un plano), no el efecto que quiero pero me dice que la textura de la tubería está funcionando.

// 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 Tengo el mismo problema con la última versión. ¿Has averiguado algo?

Sí, lo hice funcionar - Aquí está el código

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

¡Muchas gracias!
Era la línea con finalPass.uniforms[ 'tAdd' ].value . Tenía finalPass.uniforms[ 'tAdd' ].texture antes.

Hola bbiswas, ¿puedes agregar dónde creaste g_occlusion_buffer para esta parte?

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

Parece que la demostración original ya no funciona:

FWIW Hice una demostración simplificada de la aplicación selectiva de FX y la composición a través de Additive Blend (usando Three.js v79) aquí: https://www.airtightinteractive.com/demos/selective-fx/

¿Fue útil esta página
0 / 5 - 0 calificaciones