Shader Accumulation using Three.js

Currently, I am in the process of developing a path tracer using THREE.js. The approach involves rendering a full-screen quad with path tracing taking place in the pixel shader.

To achieve a higher sampling rate, one option is to sample one path for each pixel and then combine the resulting images by averaging them out over multiple shader passes.

While I have been successful in generating the necessary images, I am struggling with how to accumulate them. My initial thought is to utilize two render targets: one for the latest sampled image and another for the average of all previously displayed images.

However, I am unsure of how to extract data from a WebGLRenderTarget and use it to manipulate the data within another render target. Is this even feasible with Three.js? I have been exploring FrameBuffer Objects as a potential solution and going through MrDoob's FBO example at , which seems promising but I'm uncertain if I am on the right track.

Answer №1

It appears that the challenge lies in the inability to read and write from the same buffer simultaneously. When you render something in one frame, you must then output to the accum buffer. However, when it comes to performing calculations in the next frame and saving them to the same buffer, WebGL does not currently support this functionality.

An alternative approach would be to utilize two buffers. Within the shader where you output your data and perform calculations, include an additional texture sampler to read from the previous frame's buffer, save to the next buffer, and then alternate between the two. This method ensures that you always have access to your accumulated values, allowing for various mathematical operations to be applied. It is crucial to ensure that you are reading from the correct buffer at each frame.

For tasks like these, three.js offers a post-processing plugin which can greatly simplify the process.

var flipFlop = true;
var buffer1 = THREE.WebGLRenderTarget(BUFFERSIZE, BUFFERSIZE, {minFilter: THREE.LinearFilter, magFilter: THREE.LinearFilter, format: THREE.RGBAFormat, type: THREE.FloatType});
var buffer2 = THREE.WebGLRenderTarget(BUFFERSIZE, BUFFERSIZE, {minFilter: THREE.LinearFilter, magFilter: THREE.LinearFilter, format: THREE.RGBAFormat, type: THREE.FloatType});


function render() {
    // If we are in frame1 read buffer from frame0 and add it to whatever you compute
    yourComputeShaderMaterial.uniforms._accumulationBuffer.value = flipFlop ? buffer2 : buffer1;

    if (flipFlop) // Frame 0
        renderer.render(scene, camera, buffer1);
    else // Frame 1
        renderer.render(scene, camera, buffer2); 

    // Get whatever just renderered in this frame and use it
    yourEndShader.uniforms._accumulationBuffer.value = !flipFlop ? buffer2 : buffer1;

    // Switch frame
    flipFlop = !flipFlop;
}

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

Organizing data in a table with AngularJS

I have recently started learning AngularJS and am currently working on sorting my table by clicking on the table headers. When a header is clicked, I want the rows to be sorted based on that specific header. If you'd like to see my code in action, he ...

Switching Bootstrap Navbar Active State with JavaScript

I have encountered an issue with using the "active" class on my navbar navigation items in Bootstrap 4. When I click on the links, the active state does not switch as intended. I have tried incorporating JavaScript solutions from similar questions but have ...

How can you access the URL of an ajax request in JavaScript/jQuery once the request has been completed?

I am currently working on a web program using JavaScript that involves making multiple ajax calls. I am faced with the challenge of figuring out how to retrieve the URL after making an ajax call to the specified URL. These ajax calls are made within a for ...

Update the base path from /docs/ to /home/ for Docusaurus websites

I have been attempting to change the default docs path to home in order to organize all my "documentation" files under the home directory like home/doc1. I referred to this guide: and made modifications to my docusaurus.config.js file as follows: module.e ...

Is there a solution to successfully retrieving the value of res from the readCsv() method instead of it returning undefined?

In this scenario, I have a file uploader that accepts .json and .csv files. When the upload button is clicked, the HomeComponent calls the service dataparser which has two functions: readJson and readCsv. One function returns an observable while the other ...

Prevent scrolling on browser resize event

I am working on a basic script that adds a fixed class to a specific div (.filter-target) when the user scrolls beyond a certain point on the page. However, I am wondering how I can prevent the scroll event from triggering if the user resizes their brows ...

Calculate the total value of a specific field within an array of objects

When pulling data from a csv file and assigning it to an object array named SmartPostShipments [], calculating the total number of elements in the array using the .length property is straightforward. However, I also need to calculate the sum of each field ...

Saving data between refreshes in AngularJS can be achieved by utilizing services or local

In my application, I have a single object stored in $rootScope. I need to find a way to save its state when the user refreshes the app either by pressing F5 or manually. While I've come across examples using $cookies in Angular, they only allow for sa ...

Testing reactive streams with marble diagrams and functions

Upon returning an object from the Observable, one of its properties is a function. Even after assigning an empty function and emitting the object, the expectation using toBeObservable fails due to a non-deep match. For testing purposes, I am utilizing r ...

Displaying a Variety of Images using React and HTML

I've encountered an issue with rendering images that have large file sizes. Whenever I try to upload and display multiple large image files, the performance becomes extremely slow. So my question is: Should the backend handle providing a URL for ver ...

Tips for stopping Vue.js automatic merging of CSS classes

Recently, I embarked on my journey with Vue.js and have been thoroughly enjoying the experience. However, I've stumbled upon a challenge that has me stumped. Despite searching high and low and studying the documentation, I haven't found a solutio ...

Another way to display mjpeg using an img tag and Basic Authentication

Recently, there was an update in Chromium that included a new security measure. This update now prohibits the use of basic authentication in elements like the source attribute of an Image element. For more information on this change, you can visit https:// ...

Utilizing jquery to showcase the information in a neat and organized table

Having an input text box and a button, I am looking to display dummy data in a table when any number is entered into the input field and the button is clicked. Here is what I have tried: My Approach $("button#submitid").click(function () { $(&quo ...

Tips for managing lag caused by large raw image re-renders in a React application

When trying to change the background position of a user-uploaded background image that is in raw Data URI format using CSS, I noticed that re-rendering becomes slow if the image size exceeds 1mb. This issue does not occur with smaller images. Is there a ...

Tips for automatically breaking or paginating HTML in order to ensure that the resulting PDF mirrors the paginated HTML layout

I'm looking to implement a feature that automatically breaks or paginates HTML content in order to ensure that the resulting PDF matches the appearance of the original HTML. Requirement: If HTML content exceeds the size of an A4 paper, it should be s ...

What is preventing me from adding any style to this specific element?

Currently, I am in the process of creating a stopwatch for solving Rubik's cube. Within this project, there is a div element named "records" that is meant to display the time after a button is clicked. However, I am facing an issue where I am unable t ...

The functionality of hiding elements using the .hide() function in Javascript is affected by Qualtrics

My Qualtrics survey has a side-by-side question with 30 rows. The first 20 rows will only appear if something is entered in text boxes from previous questions, while the last 10 rows have display logic that ensures at least 10 rows are shown in total. For ...

Mastering the art of iterating through an array of objects in Vue/Nuxt

<template> <div> <h1>Greetings from the World</h1> <div> <span :for="day in days">{{ day }} </span> </div> </div> </template> <script> expo ...

Looping through data returned from Ajax call and displaying it as HTML in CodeIgniter using JQuery

Just dipping my toes into the world of JQuery AJAX, here's what I've got so far: $(document).ready(function() { $("#city").change(function() { var city_id = $("#city").val(); if (city_id != '') { $.ajax({ type ...

Manipulating data with Angular's array object

I am having an issue with posting an object array. I anticipate the post to be in JSON format like this: {"campaign":"ben", "slots":[ { "base_image": "base64 code here" } ] } However, when I attempt to post ...