New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[EffectComposer] Issue with 2 consecutive RenderPass #1234
Comments
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 It will be either finalshader.uniforms[ 'tGlow' ].texture = glowComposer.renderTarget1; |
I tried that, but got a very unexpected result. This, is the code you proposed : 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) : And all I did was to swap (line 130 & 175) : It's quite startling. |
You need to use |
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 :) EDITHum... Yet another strange behaviour, my two samplers are good, when I do
I get the diffuse correctly (http://demo.bkcore.com/threejs/webgl_tron_glow_swap2.html) When I do
I get the glow correctly. But when I try to do a simple additive blend on both Sorry for asking so many questions, I've been trying to get this to work but to no avail.. EDIT2In fact it seems that doing
Looks more like this regarding rendering output :
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! 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! |
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.
The text was updated successfully, but these errors were encountered: