Hello!,
Thank you for writing & maintaining this awesome library! :)
I am fairly new to threejs / webGL: So maybe there is a fundamental concept I am missing here, but when I try to use a Mask Pass with a different scene than my main render I get a blank screen. Is this possible? The output of a pass should be able to be the input for the next pass, correct?
Thanks in advance!
this.pixelRatio = this.width / this.height;
this.cameraZoom = 120;
var params = {
exposure: 2,
bloomStrength: .8,
bloomThreshold: 0,
bloomRadius: .03,
cameraZoom: this.cameraZoom
};
// Camera
this.camera = new THREE.OrthographicCamera(-this.width,
this.width,
this.height,
-this.height,
-1000,
1000);
this.camera.zoom = this.cameraZoom;
this.camera.lookAt(new THREE.Vector3(0, 0, 0));
this.camera.updateProjectionMatrix();
// Renderer
this.webGLRenderer = new THREE.WebGLRenderer({ antialias: true, alpha: true });
this.webGLRenderer.setClearColor(new THREE.Color(0x000000, 0));
this.webGLRenderer.setPixelRatio(this.pixelRatio);
this.webGLRenderer.setSize(this.width , this.height);
this.webGLRenderer.autoClear = false;
this.appendChild(this.webGLRenderer.domElement);
// Scene Creation
this.sceneHexGradient = new THREE.Scene();
this.sceneBlackoutMask = new THREE.Scene();
this.sceneBlackoutMask.background = new THREE.Color(0xffffff, 0);
this.sceneHexGradient.add(this.camera);
this.sceneBlackoutMask.add(this.camera);
// Orbit
this.orbitControls = new OrbitControls(this.camera, this.webGLRenderer.domElement);
this.orbitControls.maxPolarAngle = Math.PI * 0.5;
this.orbitControls.minDistance = 1;
this.orbitControls.maxDistance = 10;
// Draw onto Scenes
this.drawGradientToScene(this.sceneHexGradient);
this.drawHexToScene(this.sceneHexGradient);
this.drawBlackoutMaskToScene(this.sceneBlackoutMask);
// Update default values to be more visible
var bloomEffect = new BloomEffect({
resolutionScale: 0.5,
distinction: .4
});
bloomEffect.blendMode.opacity.value = 10;
this.clearPass = new ClearPass();
this.clearMaskPass = new ClearMaskPass();
this.hexgradientPass = new RenderPass(this.sceneHexGradient, this.camera);
this.blackoutMaskPass = new MaskPass(this.sceneBlackoutMask, this.camera);
this.bloomEffectPass = new EffectPass(this.camera, bloomEffect);
this.outlineEffectPass = new EffectPass(this.camera, outlineEffect);
this.outputPass = new ShaderPass(CopyShader);
// Render To Screen
this.blackoutMaskPass.renderToScreen = true;
this.hexgradientPass.renderToScreen = true;
this.hexgradientPass.clear = false;
this.bloomEffectPass.renderToScreen = true;
var parameters = {
minFilter: THREE.LinearFilter,
magFilter: THREE.LinearFilter,
format: THREE.RGBFormat,
stencilBuffer: true
};
this.renderTarget = new THREE.WebGLRenderTarget(this.width, this.height, parameters);
this.composer = new EffectComposer(this.webGLRenderer, this.renderTarget);
this.composer.setSize(this.width, this.height);
this.composer.addPass(this.clearPass);
// Adding this mask clears the screen no matter
// what the renderToScreen settings are above
this.composer.addPass(this.blackoutMaskPass);
this.composer.addPass(this.hexgradientPass);
this.composer.addPass(this.clearMaskPass);
this.composer.addPass(this.bloomEffectPass);
this.composer.addPass(this.outputPass);
this.render();
Hi!
I am fairly new to threejs / webGL
If you're just starting, you should first try to implement a simple post processing chain to get the hang of it. For example, create an EffectComposer instance and add a simple RenderPass that renders a basic scene to screen. Then add an effect and make sure that the output looks as expected. Note that the EffectComposer from this library is not the same as the one from the three.js examples; it's constructor signature is different. If you intend to use a MaskPass, you'll have to enable the stencil buffer as follows:
const composer = new EffectComposer(renderer, {
stencilBuffer: true
});
It's important to go step-by-step with this to understand what's going on. Post processing can be tricky to debug, too.
maybe there is a fundamental concept I am missing
In essence, the postprocessing library provides a small framework that allows you to apply fullscreen effects to your scenes. The EffectComposer uses two internal render targets to store intermediate render results. Don't worry about creating your own render targets unless you're trying to implement advanced effect chains. For common chains, you'll only have to decide which pass should render to screen. Once a pass renders to screen, no intermediate result will be stored and the post processing chain pretty much ends there. If you have multiple passes that render to screen, you'll likely get a blank screen.
Judging by the title of this issue, the following discussions might be relevant: #105, #106.
Also note that the MaskPass doesn't play nice with bloom. Preventing portions of the scene from being affected by the BloomEffect is an advanced compositing problem.
Hi @vanruesc!,
Thanks a ton for the reply and links! Cheers.
I guess I should've said how "new" I was. I have been able to get this scene to render with the mask passes (from this library) fine. I also have been able to get the UnrealBloomPass working fine with a MaskPass from threejs. Here is a link to an example (code is uncompressed in the source).
I have been searching under the hood on both repos for the differences. Either way, I would love to get the BloomPass and MaskPass working together as in the link above. Any ideas? If I find out anything I will be sure to update this thread.
Thanks again for your time & library! :)
I would love to get the BloomPass and MaskPass working together as in the link above. Any ideas?
Thanks for the example! In this case, you can ignore the links I've posted earlier as they deal with a different problem.
I'm short on time right now and can't go into detail, but I'll get back to you soon!
@vanruesc - Sounds good, Thank you!
Sorry for the delay!
Check out this example: https://jsfiddle.net/oazrcft8/1/
The idea here is to use a simple plane mesh for masking. The mesh that's being used for masking is scaled based on time. Since the bloom effect is a blur effect, the mask needs to be disabled before it runs or else it would be cut off at the edges of the mask. The render setup looks like this:
ClearPass.RenderPass doesn't clear the buffers.ClearMaskPass.I hope this helps.
@vanruesc - Thank you so much for your help!
Cool, glad I could help!