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
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.
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.
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 :)
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 ...
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 }
},
¡Perfecto!
http://demo.bkcore.com/threejs/webgl_tron_glow.html
Gracias de nuevo :)
¡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/
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/