Transfer shader program with buffers from shadertoy to three.js

Currently, I am delving into the world of webgl and shaders to enhance my understanding and skills. My objective is to create animations for website backgrounds. I have successfully imported basic examples from shadertoy into three.js and have been experimenting with them. However, I am facing challenges with more advanced examples, specifically this one:

When porting shader programs to three.js, the following steps are necessary:

  1. Create a basic three.js setup with new THREE.PlaneGeometry()
  2. Define uniforms for iTime and iResolution
  3. Create script tags for vertex and fragment shaders
  4. Insert the content from shadertoy (image section) into the fragment shader
  5. Add generic script in the vertex shader
  6. Change the names to gl_FragColor and gl_FragCoord
  7. Update the function name to void main(void)

If the shader uses a texture in one or more channels, then:

  1. Load the texture with new THREE.TextureLoader() and create a uniform for iChannel0

While the basic examples work well with the above steps, the linked example includes:

  • Buffer A
  • Buffer B

Both of these buffers have their own shader programs and main functions. How can I handle these to effectively port them to three.js?

As of now, my progress looks like this:

var container;
var camera, scene0, scene1, scene2, renderer;
var uniforms0, uniforms1, uniforms2;
var startTime;
var renderTarget0, renderTarget1;

var clock = new THREE.Clock();

// Rest of the JavaScript code follows...
body {
   margin:0;
   padding:0;
   overflow:hidden;
}
<script src="//threejs.org/build/three.min.js"></script>
<div id="container"></div>

<!--  BREAK --->

<script id="vs0" type="x-shader/x-vertex">
  void main() {
    vec4 mvPosition = modelViewMatrix * vec4(position, 1.0 );
    gl_Position = projectionMatrix * mvPosition;
  }
</script>
<script id="fs0" type="x-shader/x-fragment">

    // Fragment shader code goes here...

</script>

<!--  BREAK --->

<script id="vs1" type="x-shader/x-vertex">
  void main() {
    vec4 mvPosition = modelViewMatrix * vec4(position, 1.0 );
    gl_Position = projectionMatrix * mvPosition;
  }
</script>
<script id="fs1" type="x-shader/x-fragment">

    // Another fragment shader code...

</script>

<!--  BREAK --->

<script id="vs2" type="x-shader/x-vertex">
  void main() {
    vec4 mvPosition = modelViewMatrix * vec4(position, 1.0 );
    gl_Position = projectionMatrix * mvPosition;
  }
</script>
<script id="fs2" type="x-shader/x-fragment">

    // Yet another fragment shader code...

</script>

Answer №1

This demonstration showcases the use of multiple renders per frame. Here's how it operates:

  1. Render shaderA to a buffer
  2. Pass the output to shaderB
  3. Render shaderB to a buffer
  4. Pass the output to shaderC
  5. Render shaderC to the canvas

To achieve this in Three.js, you will require a WebGLRenderTarget as an intermediary step to transfer the output from one render as a texture to the next shader. Below is the pseudocode with only 2 renders, which can be expanded upon if more are needed:

var renderer = new WebGLRenderer(w, h, ...);

var scene0 = new Scene();
var scene1 = new Scene();

var plane0 = new THREE.PlaneBufferGeometry(1, 1);
var plane1 = new THREE.PlaneBufferGeometry(1, 1);

// ... further setup of materials, shaders, etc

// Add plane mesh to their respective scenes
scene0.add(planeMesh0);
scene1.add(planeMesh1);

// One camera should suffice if both are in the same position.
var cam = new Camera();

// renderTarget will hold the initial buffer
var renderTarget = new WebGLRenderTarget(w, h);

update() {
    // This pass will render the first shader
    // Its output will be displayed on the texture of renderTarget
    renderer.render(scene0, cam, renderTarget);

    // The output of the first render pass is assigned to the second plane
    plane1.uniforms.texture.value = rendertarget.texture;

    // Now we render the second shader to the canvas
    renderer.render(scene1, cam);
}

Remember to render separate scenes in each pass to prevent recursion issues. Therefore, each plane must be added to a distinct scene. For more information on WebGLRenderTarget, refer to the official documentation

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

Executing Actions Prior to Redirecting

I am working on implementing a timer process using a custom JQuery plugin that will redirect to the login page after a specific number of minutes. Additionally, when the timer reaches zero, I need to execute a task, which in this case involves making a cal ...

How can PHP effectively interpret JSON strings when sent to it?

When working with JavaScript, I am using JSON.stringify which generates the following string: {"grid":[{"section":[{"id":"wid-id-1-1"},{"id":"wid-id-1-4"}]},{"section":[{"id":"wid-id-1-5"}]},{"section":[{"id":"wid-id-1-2"},{"id":"wid-id-1-3"}]}]} I am ma ...

Invoking PHP function within a specific class using Ajax

I am currently utilizing Zend Framework. My PHP class is structured as follows: FileName : AdminController.php Path : /admin/AdminController.php Ajax Function : function exportToExcel() { $.ajax({ url: "/admin/AdminController/testFunction", ty ...

The statement ""x=x || 4" will result in a `ReferenceError: x is not defined` because the

What is the reason behind receiving a ReferenceError: x is not defined error when using x = x || 4 or even x=(x||5), while var x = x || 4 operates as intended? ...

What is the best way to use an Infinite scroll plugin to automatically fetch additional data from a database as the user scrolls down

In my Laravel Blade View, I am showcasing around 280 products from the database using the code snippet below. @if (get_setting('best_selling') == 1) <section class="mb-4"> <div class="container"> ...

Managing a database update when server actions involve various form types

My UI dashboard contains multiple forms like "edit title" and "edit description", each with just one input element. I am looking to streamline database updates and server actions in next js 14, utilizing useFormState on the front end. While I have achieve ...

JavaScript - Attempting to Add Objects to Array Unsuccessful

After seeing this question raised multiple times, I am determined to find a solution. In my current project, I am tasked with displaying a list of orders and implementing a filter by date functionality. However, I keep encountering an error when trying to ...

An issue arose upon restarting my Eclipse software

Upon restarting my Eclipse, I encountered the following error message: "Plug-in com.android.ide.eclipse.adt was unable to load class com.android.ide.eclipse.adt.internal.editors.common.CommonXmlEditor." As a beginner, could you advise me on how to addres ...

The system encountered an error while trying to access the property "slug

I am currently working on a project that involves using next.js and wordpress. I have set up my api.js file, but I encountered an issue when trying to access the [slug] property from another component. The error message displayed is "Typerror: Cannot read ...

Using npm webpack-mix to execute a JavaScript function stored in a separate file

Currently, I am facing a challenge with accessing a function that is defined in the table.js file from within my index.html. Here is a snippet of the code: table.js let table; function set_table(table) { this.table = table; consol ...

The MongoDB .push operation is returning a null value

Take a look at the GitHub repository where I am actively working: https://github.com/Stick-z/first-media-app I'm currently in the process of creating a website and focusing on the backend development. One of my tasks involves setting up a jokes array ...

Getting the Angular component class reference within a triggered Highcharts selection event callback - what's the best approach?

It seems like I'm facing a common javascript closure issue, but let me illustrate it with a specific example as I'm struggling to grasp it in an Angular context. In my Angular component, I'm using the Highcharts library to visualize data. W ...

Validation in Angular2 is activated once a user completes typing

My goal is to validate an email address with the server to check if it is already registered, but I only want this validation to occur on blur and not on every value change. I have the ability to add multiple controls to my form, and here is how I have st ...

The Django CSRF token is inaccessible for retrieval

I'm in the process of developing a website using Vue.js for the frontend and Django for the backend. I've made sure to include the csrf token in every request from the frontend to the backend to prevent any 403 Forbidden errors. All requests are ...

Is it possible to execute appendChild in the context of JS-DOM-creation?

Hey there, I'm a newbie trying my hand at DOM creation. I've encountered a strange issue with appendChild - the first and second tries work fine, but I'm completely stuck on the third attempt. Here's my HTML: <html> <head> ...

Using jQuery to create a seamless transition in font size as you scroll

Currently, I have a jQuery animation function in place to adjust the font size of the .header-wrap text when the document is scrolled beyond 50px. While this method does work, I am not completely satisfied with it as the transition is not very smooth. Idea ...

Tips for including a JSON file within the utils directory of a Node.js project

I have a JavaScript file located in the utils folder of my Node.js project. This JS file is responsible for retrieving data from a database. However, at the moment, I only have mock data stored in a local JSON file. Now, I need to figure out how to load th ...

An insightful guide on effectively binding form controls in Angular using reactive forms, exploring the nuances of formControlName and ngModel

Here is the code snippet: list.component.html <form nz-form [formGroup]="taskFormGroup" (submit)="saveFormData()"> <div nz-row *ngFor="let remark of checklist> <div nz-col nzXXl="12" *ngFor="let task of remark.tasks" styl ...

The getElementByID function will return null in this instance, as it has not been loaded

Hello everyone, I am facing an issue while trying to access an element by its ID in JavaScript as it keeps returning null. This problem arises because the element is not fully loaded when the DOM is initially created, due to a plugin called Restrict Conte ...

JavaScript code for displaying data sequentially one at a time

Hey there, I've developed a function that pulls data from a jsonp file. However, I'm looking to display this data one by one - starting with the vendor's name followed by their policyUrl. If you want to check out the source code, click on t ...