The blending scene in Three.js is flickering with the EffectComposer

I'm a beginner in three.js and I am facing challenges in achieving a specific effect: rendering 2 scenes and blending them with a shader. The first TexturePass is working fine, but the second one is flickering like a strobe light. You can see the result here.

Below is the code snippet:

THREE.Custom = THREE.Custom || {};

// Shader code obtained from https://github.com/stemkoski/stemkoski.github.com/blob/master/Three.js/js/shaders/AdditiveBlendShader.js
THREE.Custom.AdditiveShader = {
    uniforms: {
        tDiffuse: { type: "t", value: null },
        tAdd: { type: "t", value: null },
        fCoeff: { type: "f", value: 1.0 }
    },

    vertexShader: [
        "varying vec2 vUv;",

        "void main() {",
            "vUv = uv;",
            "gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );",
        "}"
    ].join("\n"),

    fragmentShader: [
        "uniform sampler2D tDiffuse;",
        "uniform sampler2D tAdd;",
        "uniform float fCoeff;",

        "varying vec2 vUv;",

        "void main() {",
            "vec4 texel = texture2D( tDiffuse, vUv );",
            "vec4 add = texture2D( tAdd, vUv );",
            "gl_FragColor = texel + add * fCoeff, 1.0;",
        "}"
    ].join("\n")
};

var TestBlending = (function (){

    var canvasWidth, canvasHeight, canvasRatio;

    var clock = new THREE.Clock();
    var container, camera, scene1, scene2, renderer;

    var stats, statsDisplay = true;
    var box1, box2;

    var composerFinal, composerScene1, composerScene2, composerBlending, renderTarget;
    var composerDebugScene1, composerDebugScene2;

    var delta;


    function createScene1 () {

        scene1 = new THREE.Scene();
        scene1.name = "scene1";

        var light = new THREE.DirectionalLight( 0xffffff, 1 );
        light.position.set( 0, 10, 20 );
        light.name = "light1";

        scene1.add(light);

        var material = new THREE.MeshPhongMaterial( { color: 0xcc00cc } );
        var geometry = new THREE.BoxGeometry( 1, 1, 1 );
        box1 = new THREE.Mesh( geometry, material );
        scene1.add( box1 );


    }
    function createScene2 () {

        scene2 = new THREE.Scene();
        scene2.name = "scene2";

        var light = new THREE.DirectionalLight( 0xffffff, 1 );
        light.position.set( 0, 10, 20 );
        light.name = "light2";

        scene2.add(light);

        var material = new THREE.MeshPhongMaterial( { color: 0x33cc33 } );
        var geometry = new THREE.BoxGeometry( 1, 1, 1 );
        box2 = new THREE.Mesh( geometry, material );
        scene...

If you're able to provide any assistance with this issue, it would be greatly appreciated. Thank you.

Answer №1

An identified problem is the duplication of the target texture for processing.pass.renderScene1. The target texture is added twice - once as a separate pass to composerBlending, and it is also utilized in processing.pass.blending.

To address this issue, a new blending shader should be created that does not rely on the default diffuse texture tDiffuse:

THREE.Custom.AdditiveShader = {
  uniforms: {
      tBase: { type: "t", value: null },
      tAdd: { type: "t", value: null },
      fCoeff: { type: "f", value: 1.0 }
  },

  vertexShader: [
      "varying vec2 vUv;",
      
      "void main() {",
          "vUv = uv;",
          "gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );",
      "}"
  ].join("\n"),

  fragmentShader: [
      "uniform sampler2D tBase;",
      "uniform sampler2D tAdd;",
      "uniform float fCoeff;",

      "varying vec2 vUv;",

      "void main() {",
          "vec4 texel = texture2D( tBase, vUv );",
          "vec4 add = texture2D( tAdd, vUv );",
          "gl_FragColor = texel + add * fCoeff;",
      "}"
  ].join("\n")
}; 

After creating the blending shader, manually assign the two textures generated by the scene passes to the uniform sampler variables of the blending pass:

composerBlending = new THREE.EffectComposer(renderer, renderTarget);
processing.pass.blending.uniforms['tBase'].value = composerScene1.renderTarget2.texture;
processing.pass.blending.uniforms['tAdd'].value = composerScene2.renderTarget2.texture;
composerBlending.addPass(processing.pass.blending);


Review the code snippet above for implementation details.

THREE.Custom = THREE.Custom || {};

// Custom AdditiveShader definition
THREE.Custom.AdditiveShader = {
    uniforms: {
        tBase: { type: "t", value: null },
        tAdd: { type: "t", value: null },
        fCoeff: { type: "f", value: 1.0 }
    },

    // Vertex Shader
    vertexShader: [
        "varying vec2 vUv;",

        "void main() {",
            "vUv = uv;",
            "gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );",
        "}"
    ].join("\n"),

    // Fragment Shader
    fragmentShader: [
        "uniform sampler2D tBase;",
        "uniform sampler2D tAdd;",
        "uniform float fCoeff;",

        "varying vec2 vUv;",

        "void main() {",
            "vec4 texel = texture2D(tBase, vUv);",
            "vec4 add = texture2D(tAdd, vUv);",
            "gl_FragColor = texel + add * fCoeff;",
        "}"
    ].join("\n")
};

// TestBlending module initialization
var TestBlending = (function (){

    // Initialization variables
    ...

})();
TestBlending.init();
<script src="https://threejs.org/build/three.min.js"></script>
<script src="https://threejs.org/examples/js/controls/OrbitControls.js"></script>
...
<div id="test_blending"></div>

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

Bootstrap Item Carousel - A Sleek Way to Showcase

I'm trying to figure out how to stop the infinite auto-scrolling and make it display per page when clicking the right arrow. Any ideas? $('.carousel.carousel-multi .item').each(function () { var next = $(this).next(); if (!next.leng ...

Categorize elements in an array based on a specific keyword

Struggling with my AngularJS (1) application, I can't seem to figure out how to split an array of items into separate arrays grouped by item. In simpler terms, I have an array with different items and I want to group them by their uuid like this: [ ...

Updating values dynamically using AJAX within a v-for loop

I'm struggling to figure out how to change the value of an attribute in a v-for loop. For instance, I would like the index to be used as the name of the related product: HTML <div v-for="(index, publication) in publications"> {{ index | nam ...

HTML and JavaScript are not communicating properly

Need help with creating a slideshow using JavaScript. The code works on JSFiddle, but not in my local environment. Can someone point out where I might be going wrong? HTML5 <!DOCTYPE html> <html> <head> <title>slider</titl ...

Is there a way to access the HTML and CSS source code without using the inspect feature

I'm working on a project that involves an "edit box" where users can write text, add emojis, change the background color, insert images, and more. After users finish creating their content, I want them to be able to send it via email. This means I ne ...

The search function in Typeahead is not activating the API request while typing

Having some trouble implementing a typeahead search feature in my nodejs application with mysql. I can't seem to figure out what's wrong with my code. When I manually access http://localhost:5000/search?key=s, I'm able to see the results an ...

Vue and Axios encountered a CORS error stating that the 'Access-Control-Allow-Origin' header is missing on the requested resource

I've encountered the error above while using Axios for a GET request to an external API. Despite consulting the Mozilla documentation, conducting thorough research, and experimenting with different approaches, I haven't made any progress. I&apos ...

Encountering an issue when trying to generate a button in Angular

I am currently using JavaScript to dynamically create a button in Angular. While I have been successful in creating the button, I am encountering an error when attempting to change the classname. The error message I am receiving is: Property 'clas ...

Express application displays "Cannot GET /" when navigating with query parameters

I am encountering an issue while developing a basic Node.js Express application. The problem arises when routing requests with query parameters. Below is a snippet of the code: const express = require('express'); const app = express(); app.g ...

Identifying the Operating System and Applying the Appropriate Stylesheet

I am trying to detect the Windows operating system and assign a specific stylesheet for Windows only. Below is the code snippet I have been using: $(function() { if (navigator.appVersion.indexOf("Win")!=-1) { $(document ...

Preventing duplication of code execution in recycled PHP elements

Currently, I have implemented a generic toolbar that is used on multiple pages of my web application by using PHP include. This toolbar contains log in/log out functionality and checks the log in status upon loading to update its UI accordingly. Initially ...

Using custom class instances or objects within Angular controllers is a simple process

Using three.js, I have created a class called threeDimView that houses my scene, camera, and other elements. In my JavaScript code, I instantiate a global object of this class named threeDimView_. threeDimView_ = new threeDimView(); Now, I wish to displa ...

Jquery code that mimics pressing a key downwards is not functioning properly to execute a keyboard shortcut

I would like to express my gratitude in advance for any time and effort dedicated to this matter. So, here's the situation: I have a script that is meant to simulate a key press event after 3 seconds once the page is loaded. The goal was to trigger a ...

Storing images from a URL in a database using Node.js

I recently started working with nodejs and I'm facing a challenge in saving an image obtained from a url (via api). Through my research, I found that using the createWriteStream method from nodejs could help me extract the image from the url and save ...

Improving methods for handling AJAX requests in PHP

I am facing an issue with a JavaScript file that sends an AJAX request to a PHP file to fetch data from a database. When the PHP file does not find any record based on the query, it returns a message like "no match found" instead of a JSON object in the ...

Turn off sticky sidebar feature for mobile-friendly layout

I have encountered an issue with my script that I need assistance with. I am trying to disable this script for responsive or mobile view, but despite trying various methods, it is not functioning as expected. <script type="text/javascript"> $(func ...

Obtaining data from a callback function within a NodeJS application

There is a function in my code that performs a backend call to retrieve an array of names. The function looks something like this: module.exports.getTxnList = function(index, callback) { ....some operations ..... .... callback(null, respon ...

One issue that may arise is when attempting to use ngOnDestroy in Angular components while rearranging user transitions

Encountered an issue recently with Angular - when the user navigates from component A to component B, component A remains active unless ngOnDestroy is triggered. However, if the user visits component B before going to component A and then leaves, ngOnDes ...

Shifting JavaScript from Client to Server in Node/Express: A Step-by-Step Guide

Within my .handlebars file, I have a combination of HTML and JS code (provided below). The code represents a basic form which users can expand by clicking on a "New Form Field" button. Clicking on this button will simply add a new text field to the form. U ...

Adjusting the timeout for a particular operation according to its unique identifier

I am looking for a solution to call a method that posts an answer after an input change in my Angular project. I want to reset the timeout if another input change occurs to avoid multiple posts. Is there a smart way to achieve this? My project involves po ...