Is it possible to create a fixed position shader background in three.js?

Trying to incorporate a pixel shader as a background in three.js without affecting the camera rotation with OrbitControls. Most implementations use a 2D plane, but I want it to remain fixed in the scene. Is there a way to achieve this with two separate canvas layers in three.js, or another method?

var planeMaterial = new THREE.ShaderMaterial( { 
    uniforms: uniforms,
    vertexShader: document.getElementById('vertexShader').textContent,
    fragmentShader: document.getElementById('fragmentShader').textContent
} );

var plane = new THREE.Mesh(geometry, planeMaterial);
plane.position.z = -500;
scene.add(plane);

Check out this example for reference: http://jsfiddle.net/5zTz3/2/

Answer №1

To enhance the rendering process, consider placing the shader material in a separate scene with its own camera. After that, make sure to utilize

renderer.render(shadertoyScene, shadertoyCamera);
followed by
renderer.render(regularScene, orbitControlCamera);
.

'use strict';

/* global THREE */

function main() {
  const canvas = document.querySelector('#c');
  const renderer = new THREE.WebGLRenderer({canvas});
  renderer.autoClear = false;

  const shadertoyCamera = new THREE.OrthographicCamera(
    -1, // left
    1, // right
    1, // top
    -1, // bottom
    -1, // near,
    0, // far
 );
  const shadertoyScene = new THREE.Scene();
  const plane = new THREE.PlaneBufferGeometry(2, 2);

  const fragmentShader = `
#include <common>

uniform vec3 iResolution;
uniform float iTime;

// By iq: https://www.shadertoy.com/user/iq  
// license: Creative Commons Attribution-NonCommercial-ShareAlike 3.0 Unported License.
void mainImage( out vec4 fragColor, in vec2 fragCoord )
{
   // Normalized pixel coordinates (from 0 to 1)
   vec2 uv = fragCoord/iResolution.xy;

   // Time varying pixel color
   vec3 col = 0.5 + 0.5*cos(iTime+uv.xyx*40.0+vec3(0,2,4));

   // Output to screen
   fragColor = vec4(col,1.0);
}

void main() {
   mainImage(gl_FragColor, gl_FragCoord.xy);
}
 `;
 const uniforms = {
   iTime: { value: 0 },
   iResolution:  { value: new THREE.Vector3() },
 };
 const material = new THREE.ShaderMaterial({
   fragmentShader,
   uniforms,
 });
 shadertoyScene.add(new THREE.Mesh(plane, material));
 
 const fov = 75;
 const aspect = 2;  // the canvas default
 const near = 0.1;
 const far = 100;
 const camera = new THREE.PerspectiveCamera(fov, aspect, near, far);
 camera.position.z = 3;

 const controls = new THREE.OrbitControls(camera, canvas);
 controls.target.set(0, 0, 0);
 controls.update();

 const scene = new THREE.Scene();

 {
   const color = 0xFFFFFF;
   const intensity = 1;
   const light = new THREE.DirectionalLight(color, intensity);
   light.position.set(-1, 2, 4);
   scene.add(light);
 }

 const boxWidth = 1;
 const boxHeight = 1;
 const boxDepth = 1;
 const geometry = new THREE.BoxGeometry(boxWidth, boxHeight, boxDepth);

 function makeInstance(geometry, color, x) {
   const material = new THREE.MeshPhongMaterial({color});

   const cube = new THREE.Mesh(geometry, material);
   scene.add(cube);

   cube.position.x = x;

   return cube;
 }

 const cubes = [
   makeInstance(geometry, 0x44aa88,  0),
   makeInstance(geometry, 0x8844aa, -2),
   makeInstance(geometry, 0xaa8844,  2),
 ]; 

 function resizeRendererToDisplaySize(renderer) {
   const canvas = renderer.domElement;
   const width = canvas.clientWidth;
   const height = canvas.clientHeight;
   const needResize = canvas.width !== width || canvas.height !== height;
   if (needResize) {
     renderer.setSize(width, height, false);
   }
   return needResize;
 }

 function render(time) {
   time *= 0.001;  // convert to seconds

   if (resizeRendererToDisplaySize(renderer)) {
     const canvas = renderer.domElement;
     camera.aspect = canvas.clientWidth / canvas.clientHeight;
     camera.updateProjectionMatrix();
   }
   
   const canvas = renderer.domElement;
   uniforms.iResolution.value.set(canvas.width, canvas.height, 1);
   uniforms.iTime.value = time;

   renderer.render(shadertoyScene, shadertoyCamera);
   renderer.render(scene, camera);

   requestAnimationFrame(render);
 }

 requestAnimationFrame(render);
}

main();
body {
 margin: 0;
}
#c {
 width: 100vw;
 height: 100vh;
 display: block;
}
<canvas id="c"></canvas>
<script src="https://threejsfundamentals.org/threejs/resources/threejs/r105/three.min.js"></script>
<script src="https://threejsfundamentals.org/threejs/resources/threejs/r105/js/controls/OrbitControls.js"></script>

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

Adjusting the maxContentLength and maxBodyLength values in Axios

While utilizing the "Axios" library to invoke a WCF method with file information and content as parameters, I encountered an issue. The file is read and transmitted as a base64 encoded string. However, when the file size surpasses a specific limit, Axios t ...

Angular SPA boasting an impressive one million pages

Currently, I am in the process of transitioning my webshop, which contains numerous products, to an Angular SPA application using ngRoute and HTML5 mode. I have come up with a method where I receive some of my routes from the server as a JSON object, but s ...

Encountering an issue when trying to download a PDF from an Angular 6 frontend using a Spring Boot API - receiving an error related to

When I directly call the Spring Boot API in the browser, it successfully creates and downloads a PDF report. However, when I try to make the same GET request from Angular 6, I encounter the following error: Here is the code snippet for the Spring Boot (Ja ...

Creating dynamic backend routes in NextJS is a great way to add flexibility to

Is there a way for me to implement dynamic backend routes? I am working on an image hosting platform where users should be able to save their images on the server under unique domains like http://localhost/<random_id>. An example link would look so ...

Tips on invoking a method from a JavaScript object within an AJAX request

Considering the following code snippet: var submit = { send:function (form_id) { var url = $(form_id).attr("action"); $.ajax({ type: "POST", url: url, data: $(form_id).serialize(), dataType: 'json', succes ...

Creating a flexible grid layout using Flexbox and JavaScript media queries to dynamically adjust container size

I enjoy working on Etch-a-Sketch projects from The Odin Project, but I am looking to take it a step further than just the assignment. I want to challenge myself by achieving this solely with Flexbox and JavaScript, without involving CSS Grid. When I se ...

Error: The data from the intermediate value cannot be parsed using the parseFromString() method and replaced with another value,

I'm working on a project where I need to display parsed HTML content within an element. However, before displaying it, I need to make some changes to the HTML using the `replace` method. But unfortunately, I encountered a TypeError: (intermediate valu ...

AJAX response for form validation

I need to validate my contact form when the submit button is clicked. If all fields are valid, I want to display a Processing message using AJAX, followed by a success message with the entered name. The content of my Form is: <form onsubmit="return va ...

Understanding the res.render method in JavaScript can be a bit tricky at first

In my spare time, I have been immersing myself in coding lessons and have encountered some puzzling aspects of the code: Firstly, there is a confusion surrounding the action attribute in HTML Secondly, this particular piece of code is causing me some b ...

Chartist JS: line graph dipping beneath the X-axis

I am currently using the Chartist JS jQuery plugin and encountering an issue where one of the functions is extending below the x-axis even though it does not have any negative points. Is there a way to resolve this issue? Please refer to the image for bet ...

The HTML code may fade away, but the JavaScript is still up and running behind the

Switching between different div elements in my HTML document is a challenge. Here's the code I currently have: <div id="screen1" class="current"> <div id="press_any_key_to_continue"> <font style="font-family: verdana" color="yellow ...

Slow rendering occurs with unthrottled range input, even with proper throttling applied

I'm currently seeking some general guidelines because I'm unsure where to turn for help at the moment. The issue I am facing involves an uncontrolled input[type=range] slider that performs very slowly when there are numerous steps (works fine wi ...

Chip input component in React

I've recently upgraded to React 17 and encountered an issue with chip input fields like material-ui-chip-input not working properly. I've tried various npm packages, but none of them seem to be compatible with React version 17. Does anyone know ...

What is the best way to show the totals on a calculator screen?

As part of my work, I created a calculator to help potential clients determine their potential savings. Everything seems to be working fine, except for the total fees not appearing for all the boxes. I believe I might be missing the correct process to add ...

Unable to transfer bootstrap form data from the view to the controller due to issues with bootstrap validations

Scenario I have integrated a bootstrap form into my codeigniter application with bootstrap validation to ensure data accuracy. I want the submit button to work properly so that users can successfully submit the form and be redirected to the action page ...

How to store angular 2 table information generated using ngFor

I am currently working on a project where I need to create an editable table using data retrieved from the back end. My goal now is to save any updated data. I attempted to use formControl, but it seems to only save the data in the last column. Below is a ...

What exactly entails static site generation?

I have been exploring the concept of static site generation (SSG). The interesting question that arises is how SSG can fetch data at build time. In my latest application, I implemented an event handler to retrieve data based on a user's search keyword ...

Newbie: Troubleshooting Vue Errors - "Vue is not recognized"

I'm currently at the beginning stages of learning Vue and am practicing implementing it. However, I keep encountering the errors "vue was used before it was defined" and "Vue is not defined". Below are excerpts from my HTML and JS files for reference. ...

Within the ASP.NET Framework 4, it is necessary to enable the Listbox control to trigger an event when a user double

Currently, I am developing a project in ASP.NET 4. I have encountered a situation where the regular ListBox in version 4.5 includes an attribute named OnMouseDoubleClick. However, since I am using ASP.Net 4, I am looking for the best approach to replicat ...

Cover the entire screen with numerous DIV elements

Situation: I am currently tackling a web design project that involves filling the entire screen with 60px x 60px DIVs. These DIVs act as tiles on a virtual wall, each changing color randomly when hovered over. Issue: The challenge arises when the monitor ...