While working on postprocessing in Three.js with EffectComposers and shader passes, I encountered some unexpected behavior when combining the WebGLRenderTargets (renderTarget2) from different composers. My setup involves five composers: three to render scenes (lightComposer
, motifsComposer
, selectedMotifsComposer
) and two for further combining of scenes via their composers' render targets (motifsCompositeComposer
, finalComposer
).
motifsComposer
and selectedMotifsComposer
both render the same scene but differ in a uniform change to apply different effects to clicked motifs by the user. Individually, they work fine and combine as expected with an additive shader pass in the motifCompositeComposer
. Similarly, lightComposer
works correctly when rendered on its own.
However, when I use a subtractive shader pass to combine the render targets from lightComposer
and motifsCompositeComposer
in the finalComposer
, I only see the result of the lightComposer
render target. I've tried various code permutations without success. I suspect there might be an alpha issue at play, but I'm uncertain how to rectify it. Here is the script for the AdditiveBlendShader I use, created by Lee Stemkoski. For the subtractive blend, I modified this script to change gl_FragColor = texel1 + texel2;
in the fragment shader to gl_FragColor = texel1 - texel2;
.
Composer setup:
// Light Composer
lightCloud = (a PointCloud with a BufferGeometry and ShaderMaterial);
lightScene.add( lightCloud );
var renderLight = new THREE.RenderPass( lightScene, lightCamera );
lightComposer.addPass( renderLight );
// Motif Point Cloud
gridOfMotifs = (a PointCloud with a BufferGeometry and ShaderMaterial);
motifScene.add( gridOfMotifs );
var renderMotifs = new THREE.RenderPass( motifScene, motifCamera );
// Motifs Composer
motifsComposer.addPass( renderMotifs );
// Selected Motifs Composer
gridOfMotifs.material.uniforms.uRenderSelectedMotifs.value = 1;
selectedMotifsComposer.addPass( renderMotifs );
selectedMotifsComposer.addPass( effectBloom );
// Motifs Composite Composer
effectAdditive.uniforms[ "tDiffuse1" ].value = motifsComposer.renderTarget2;
effectAdditive.uniforms[ "tDiffuse2" ].value = selectedMotifsComposer.renderTarget2;
motifsCompositeComposer.addPass( effectAdditive );
// Final Composer
effectSubtractive.uniforms[ "tDiffuse1" ].value = lightComposer.renderTarget2;
effectSubtractive.uniforms[ "tDiffuse2" ].value = motifsCompositeComposer.renderTarget2;
finalComposer.addPass( effectSubtractive );
finalComposer.addPass( effectCopy );
effectCopy.renderToScreen = true;
The render call looks like this:
renderer.clear();
lightComposer.render();
gridOfMotifs.material.uniforms.uRenderSelectedMotifs.value = 0;
motifsComposer.render();
gridOfMotifs.material.uniforms.uRenderSelectedMotifs.value = 1;
selectedMotifsComposer.render();
motifsCompositeComposer.render();
finalComposer.render();
...
In the end, I'm aiming to get the full grid of motifs subtracted (appearing in black) from the white light cloud. Your assistance in resolving this issue would be greatly appreciated!