Closed BKcore closed 12 years ago
I think it's because depth buffer gets destroyed, see #1017.
For your use case, what may work instead is to use two composers (and thus two fully separate render targets, each with own depth buffer).
Something like this:
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
Now diffuse layer will be available as regular tDiffuse
texture sampler in finalComposer
and glow layer you will supply from glowComposer
.
It will be either glowComposer.renderTarget1
or glowComposer.renderTarget2
depending on particular number of passes and whether passes switch front and back buffers, simplest is to try both and see which works.
finalshader.uniforms[ 'tGlow' ].texture = glowComposer.renderTarget1;
I tried that, but got a very unexpected result.
This, is the code you proposed : http://demo.bkcore.com/threejs/webgl_tron_glow_swap.html The tDiffuse from the renderModel is still black.
And this, is the exact same code, with just the two render pass swapped (the diffuse scene is in the glow composer, and the glow scene in the final composer) : http://demo.bkcore.com/threejs/webgl_tron_glow_swap2.html It is of course not the effet I'm looking for since the diffuse is blurred and not the glow, but as you can see both tGlow and tDiffuse samplers are working...
And all I did was to swap (line 130 & 175) : new THREE.RenderPass( scene, camera ); with new THREE.RenderPass( glowscene, glowcamera );
It's quite startling.
You need to use RGBA
format for render targets if you use transparency.
Well, I agree, but I'm not using any transparency since my glow pass renders white on black and my diffuse pass well... diffuse on black. I then compose them with an addition so transparency is not needed.
Still, just to be sure, I changed the RT's format to RGBA, but that didn't change anything.
The strange issue here, is that doing my scene/camera RenderPass after my glowscene/glowcamera RenderPass does not work, while doing my scene/camera RenderPass before my glowscene/glowcamera RenderPass does.
Hmmm, seems like geometry sharing issue for different materials (see #1211).
Try this:
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 );
// ...
}
Yes ! That was it.
My two samplers are now correctly filled. Thank you :)
Hum... Yet another strange behaviour, my two samplers are good, when I do
gl_FragColor = texel;
I get the diffuse correctly (http://demo.bkcore.com/threejs/webgl_tron_glow_swap2.html)
When I do
gl_FragColor = glow;
I get the glow correctly.
But when I try to do a simple additive blend on both gl_FragColor = texel + glow; I only get the glow (http://demo.bkcore.com/threejs/webgl_tron_glow_swap.html).
Sorry for asking so many questions, I've been trying to get this to work but to no avail..
In fact it seems that doing
gl_FragColor = texel + glow;
Looks more like this regarding rendering output :
gl_FragColor = glow + glow;
It's like the texel vec4 gets unexplicably replaced by the glow vec4. Sounds crazy.
You need to put textures in different texture units:
uniforms: {
tDiffuse: { type: "t", value: 0, texture: null },
tGlow: { type: "t", value: 1, texture: null }
},
Perfect! http://demo.bkcore.com/threejs/webgl_tron_glow.html
Thank you again :)
Yay!
In case anyone is interrested in selective glow rendering with Three.js, I just published a small article about it : http://bkcore.com/blog/3d/webgl-three-js-animated-selective-glow.html
Hope it helps.
Nice ;)
Alternatively, instead of geometry cloning, another cheaper option would be to use more similar materials (so that geometry in both passes would need the same buffers).
In this case, instead of using Basic material for glow pass, you could try Lambert material with zero diffuse lighting, just with ambient light.
Something like this:
glowScene.add( new THREE.AmbientLight( 0xffffff ) );
// ...
var gmat = new THREE.MeshLambertMaterial( { map: gtex, ambient: 0xffffff, color: 0x000000 } );
var gmesh = new THREE.Mesh( geometry, gmat );
Indeed, that's working perfectly.
http://demo.bkcore.com/threejs/webgl_tron_glow_seq.html
I'll update my article regarding this solution. Thank you !
I'm porting this code to r60 and strangely coming across the same issue with chaining the effect composers. I have the godray pass working if I render it to screen. But the final pass only outputs the model. The oclcomposer output to the "tadd" texture channel seems to come in okay when I don't use a separate Effect Composer!! I've tried with renderer.PreserveDrawingBuffer = true but that didn't work either. I've tried setting autoclear to false but that wasn't it.
If I render the oclcomposer after the final composer and make the godray pass output to screen, I can see the godrays but no models.
Instead of directing the oclcomposer output to the tadd channel in final pass, if I pipe it to a MeshBasicMaterial and create a textured quad and add it to the main scene, now I can see the model and the godrays (on a plane), not the effect I want but it tells me that the texture piping is working.
// 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 I have the same issue with the latest version. Have you found out anything?
Yes I did get it working - Here's the code
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 );
Thanks a lot!
It was the line with finalPass.uniforms[ 'tAdd' ].value
. I had finalPass.uniforms[ 'tAdd' ].texture
before.
Hey bbiswas, can you add where you created g_occlusion_buffer for this part:
var renderModelOcl = new THREE.RenderPass( g_occlusion_buffer, g_occlusion_camera );
Seems like the original demo is no longer working:
FWIW I made a stripped-down demo of selectively applying FX and composing via Additive Blend (using Three.js v79) here: https://www.airtightinteractive.com/demos/selective-fx/
The link
http://demo.bkcore.com/threejs/webgl_tron_glow.html
The code
The context
I got two scenes with the same object/camera/light. One with the diffuse texture (http://demo.bkcore.com/threejs/webgl_tron.html) and one with a glow texture (glowing areas are white on black).
My rendering pipeline is as follow : I first render the glow scene and apply a H/V blur to it, then store the output into a frameBuffer using a SavePass. Then I want to render the diffuse scene. And finally mix that with the glow framebuffer.
The issue
My glow sampler2D is passing well to my finalPass shader, but as you can see in the demo, the second RenderPass call for the diffuse scene is not performing well. It only outputs black.
I tried to render the diffuse scene in a single Render pass and that works. It's when I use it as a second RenderPass that it's not working.
Any ideas ?
Thank you. Thibaut D.