https://i.sstatic.net/RhsdW.gif
Before I delve into this topic, I want to give credit to Martin Schuhfuß for his valuable insights that led to this solution.
Disclaimer
As a non-expert in JavaScript programming, I want to clarify that my approach is not the only way to tackle this issue. My explanation is meant to be interpreted in a broad sense, as the implementation may vary based on individual architecture.
Architecture
In this example, I am employing an Object-Oriented Programming (OOP) method, but feel free to adapt the solution to suit your preferred method.
Method
Building upon Martin's example, we noticed the capability of adding the composer property/object to our scene object, allowing scenes to inherit similar composer effects. However, in my scenario with multiple scenes featuring different composer effects, I needed to rethink the approach.
1. Creating a Composer object.
I established an object to contain composer objects, maintaining the 'composer' naming convention for referencing my effects.
This.composer = {};
2. Developing a function to initialize RenderPasses for the respective scenes.
Prior to utilizing the composer, it is essential to define and initialize the RenderPasses. RenderPasses enable us to apply desired effects (known as shaders). In my case with two scenes, I had to create:
- Two RenderPasses.
- One RenderPass duplicating the scene.
- Another RenderPass implementing a sepia effect to its scene.
Sample Code:
this.init = function() {
stackoverflow.webgl.pass.base = new THREE.RenderPass(stackoverflow.webgl.scene.default,
stackoverflow.webgl.camera);
stackoverflow.webgl.pass.base2 = new THREE.RenderPass(stackoverflow.webgl.scene.test,
stackoverflow.webgl.camera);
stackoverflow.webgl.pass.sepia = new
THREE.ShaderPass(THREE.SepiaShader);
stackoverflow.webgl.pass.sepia.renderToScreen = true;
stackoverflow.webgl.pass.copy = new THREE.ShaderPass(THREE.CopyShader);
stackoverflow.webgl.pass.copy.renderToScreen = true;
}
Note: File names had to be altered for legal reasons, but the functionality remains intact as part of a larger object.
3. Creating a start function and assigning composers to scenes.
This function serves as a demonstration of unifying all components. The code snippet showcases:
// Creating an object as a reference for EffectComposer objects
this.composer = {};
// Designating the desired scene
this.activeScene = this.scene.default;
// Wrapper function for initialization
this.start = function () {
// Initializing RenderPasses
stackoverflow.webgl.pass.init();
// Setting up the WebGLRenderer scene (as per personal method)
stackoverflow.webgl.renderer.default.setup;
// Creating composers for scenes
this.composer.ui = new THREE.EffectComposer(stackoverflow.webgl.renderer.default.init);
this.composer.ui2 = new THREE.EffectComposer(stackoverflow.webgl.renderer.default.init);
// Assigning composers to scenes
this.scene.default.composer = stackoverflow.webgl.composer.ui;
this.scene.test.composer = stackoverflow.webgl.composer.ui2;
// Validating the setup
console.log(this.scene.default);
console.log(this.scene.test);
console.log(this.composer);
// Adding passes (function 'render') - customize based on code structure
stackoverflow.webgl.render();
}
4. Integrating pass declarations into the architecture.
Following the setup, adding pass declarations is necessary for the effects to manifest.
this.render = function () {
stackoverflow.webgl.composer.ui.addPass(stackoverflow.webgl.pass.base);
stackoverflow.webgl.composer.ui.addPass(stackoverflow.webgl.pass.copy);
stackoverflow.webgl.composer.ui2.addPass(stackoverflow.webgl.pass.base2);
stackoverflow.webgl.composer.ui2.addPass(stackoverflow.webgl.pass.sepia);
};
5. Implementing the EffectComposer render method.
This line of code must be inserted where composer processing occurs, tailored to the setup.
stackoverflow.webgl.activeScene.composer.render();
Ensure the 'activeScene' part references the current scene for seamless scene transitions.
6. Creating a button to toggle between scenes.
Using dat.gui, I added two buttons for toggling between scenes.
Customize buttons or functions as per your preference.
// Update 'activeScene' value accordingly
// Button 1 switches to scene 2
stackoverflow.webgl.activeScene = stackoverflow.webgl.scene.test;
// Button 2 reverts to scene 1
stackoverflow.webgl.activeScene = stackoverflow.webgl.scene.default;
Conclusion
This methodology represents my approach to achieving the desired effect. Feel free to contribute alternative or improved methods to enrich the discussion.