Surprising outcomes arise when the results of Three.js EffectComposers are combined, as the Additive and Subtractive effects interact in unexpected

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!

Answer №1

Success! I finally discovered the solution. It turns out, within the finalComposer, I needed to adjust the render target of motifsCompositeComposer from renderTarget2 to renderTarget1. My hypothesis is that this is due to the absence of a copypass after the additive pass in motifsCompositeComposer, which would have switched the result to the second render target.

effectSubtractive.uniforms.tDiffuse1.value = lightComposer.renderTarget2;
effectSubtractive.uniforms.tDiffuse2.value = motifsCompositeComposer.renderTarget1; // <---***Take note of the change to renderTarget1
finalComposer.addPass( effectSubtractive );
finalComposer.addPass( effectCopy );

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Sequelize JS - Opting for the On clause in join operations

Seeking guidance on selecting the appropriate ON clause for a join. I am working with two tables - packages and users. The package table contains two fields/columns (owner_id, helper_id) that serve as foreign keys to the same users table. My goal is to per ...

Encountered an issue with the ProgressPlugin: TypeError - Unable to access property 'tap' of an undefined element

Encountering a Problem with npm run build Here's the issue at hand Compiling client E:\ui\sheraspace_ui\node_modules\webpack\lib\ProgressPlugin.js:223 compilation.hooks.addEntry.tap("ProgressPlugin", entryAdd ...

What is the most effective way to transfer a variable between two javascript files?

I am currently working on customizing the code from a github repository found at Github repo for integration with Google App Engine. However, I have encountered an issue when trying to pass a variable from /app.js to /books/crud.js. Although I have success ...

What is the best way to export a React Material-UI component with two separate styles objects in Material-UI V1?

We are currently utilizing material-ui version 1 and composing Higher Order Components (HOC) with the recompose utility. Our issue arises from having two separate styles objects - one defined within the component itself, and another general style object th ...

Creating a two-column grid layout using Bootstrap 4 is a simple and efficient process. Let's see how

I've been struggling to get this to display side by side in a two-column grid. Even after following Bootstrap tutorials, I can't seem to make it work. Check out the code below: <div class="row"> <div class="col-md-8 ...

Can Javascript be used to open a new window, send POST parameters to it, and pass the request as application/json?

I have a browser client application built with JavaScript that manages a large amount of state data. Sometimes, this data needs to be organized into a structured object and sent to a new window for further processing. Currently, I am using a solution wher ...

Is there a way to incorporate expandable content on a Drupal node page using Javascript?

Is there a Drupal Module available that can display a trimmed version of content on the node page and expand it when clicking on a "Read More" link? Thank you! ...

Encapsulating the React Material-ui Datepicker and Timepicker OnChange event callback functionging

I'm new to React and currently incorporating Material-UI into my project for additional UI components. I've noticed some repetitive code that I'm finding difficult to refactor due to constraints within a Material-UI component's implemen ...

Utilize JavaScript to connect WhatsApp with the website

I am looking to use Javascript to enable opening WhatsApp on both iOS and Android devices. Below is the code I have attempted: window.open("https://wa.me/15551234567"); window.open("https://api.whatsapp.com/send?phone=15551234567"); ...

Using an xmlhttprequest to retrieve a PDF file functions properly in synchronous mode, but encounters issues in

Today I'm experimenting with some code that scrapes PDFs from a chrome extension by detecting user-clicked links. I've noticed that synchronous xmlhttprequests work perfectly for both HTML documents and PDFs. However, I seem to be facing an issue ...

Utilize array.prototype.reduce() with strings

I'm puzzled about how the reduce operation is carried out on a string. Initially, a new Str instance is created with the desired string as a parameter. Following that, the split method is used to divide the string into an array of strings. A method c ...

What steps should I take when dealing with two dynamic variables in a mediator script within the WSO2 ESB?

I'm facing an issue with my if condition - it doesn't work properly when the value is static. However, when I make `annee2` and `annee1` static (for example =2019), it works fine. Here's the code snippet: <script language="js"&g ...

Creating a Full Page Background Image That Fits Perfectly Without Resizing or Cropping

Can someone help me achieve the same effect as the website linked below, where the background image fades instead of being a slideshow? The image should be 100% in width and height without any cropping. I have managed to set this up with the codes provided ...

Making AJAX requests with Laravel using the XMLHttpRequest object is a

When using Laravel to upload a file and create a progress bar with ajax requests, the form action routes to the controller in this way: <form action="{{ URL::route('upload-file-form-post') }}" method="POST" enctype="multipart/form-data"> ...

JQuery isn't functioning properly on dynamically generated divs from JavaScript

I'm currently tackling an assignment as part of my learning journey with The Odin Project. You can check it out here: Despite creating the divs using JavaScript or jQuery as specified in the project requirements, I am unable to get jQuery's .hov ...

What is the method for incorporating a CSRF token into BootstrapTable when using the POST data method?

How can I include a CSRF token in bootstrapTable when using the POST method for data? I am working on a project and trying to add a CSRF token in bootstrapTable. There is some information about CSRF on bootstrap-table.com. Can anyone help me with this iss ...

I am encountering a problem with the $invalid property in AngularJS

Hey there, I've got a coding dilemma involving three number inputs, which I will refer to as the first input, second input, and third input for clarity. Here's the setup: <div> <form name="formOpenMax"> <div clas ...

Is there a clash between jquery_ujs and Kaminari AJAX functionality in Rails 4?

After some investigation, it seems that there is a conflict between jquery_ujs and Kaminari's AJAX support in my Rails 4 application. Within my application.js file, I have included the following: //= require jquery //= require jquery_ujs //= require ...

What benefits and drawbacks come with setting up JS libraries in resource files compared to package.json?

Configurations for JavaScript libraries such as Babel, Nyc, Eslint, and many others can be specified in resource files or within the package.json. For example, Babel can be set up in a .babelrc file or through a babel entry in the package.json. What are ...

steps to extract routing into its own component

Is it possible to extract this routing logic into a separate component? I attempted to use map but it didn't work I want to have only a single route, and change the 'path' when a specific link is clicked const Home = ({ code }) => { re ...