GLSL: Utilizing varying amounts of textures in the sampler2D

Is there a way to dynamically pass an array of textures to shaders through a uniform sampler2D in Three.js?

In the code snippet below, I am attempting to send two textures to the shaders and initialize the uniform value texture with a length of 2. However, this is resulting in the following exception:

THREE.WebGLProgram: shader error: 0 gl.VALIDATE_STATUS false gl.getProgramInfoLog invalid shaders ERROR: 0:125: '' : constant expression required ERROR: 0:125: '' : array size must be a constant integer expression ERROR: 0:134: '[]' : array index out of range

I'm seeking advice on whether it's possible to vary the number of textures sent to a sampler2D uniform value. Any insights or solutions would be greatly appreciated!

/**
* Generate a scene object with a background color
**/

function getScene() {
  var scene = new THREE.Scene();
  scene.background = new THREE.Color(0xffffff);
  return scene;
}

/**
* Generate the camera to be used in the scene. Camera args:
*   [0] field of view: identifies the portion of the scene
*     visible at any time (in degrees)
*   [1] aspect ratio: identifies the aspect ratio of the
*     scene in width/height
*   [2] near clipping plane: objects closer than the near
*     clipping plane are culled from the scene
*   [3] far clipping plane: objects farther than the far
*     clipping plane are culled from the scene
**/

function getCamera() {
  var aspectRatio = window.innerWidth / window.innerHeight;
  var camera = new THREE.PerspectiveCamera(75, aspectRatio, 0.1, 1000);
  camera.position.set(0, 1, 10);
  return camera;
}

/**
* Generate the renderer to be used in the scene
**/

function getRenderer() {
  // Create the canvas with a renderer
  var renderer = new THREE.WebGLRenderer({antialias: true});
  // Add support for retina displays
  renderer.setPixelRatio(window.devicePixelRatio);
  // Specify the size of the canvas
  renderer.setSize(window.innerWidth, window.innerHeight);
  // Add the canvas to the DOM
  document.body.appendChild(renderer.domElement);
  return renderer;
}

/**
* Generate the controls to be used in the scene
* @param {obj} camera: the three.js camera for the scene
* @param {obj} renderer: the three.js renderer for the scene
**/

function getControls(camera, renderer) {
  var controls = new THREE.TrackballControls(camera, renderer.domElement);
  controls.zoomSpeed = 0.4;
  controls.panSpeed = 0.4;
  return controls;
}

/**
* Load image
**/

function loadImage() {

  var geometry = new THREE.BufferGeometry();

  /*
  Now we need to push some vertices into that geometry to identify the coordinates the geometry should cover
  */

...


</script>

Answer №1

GLSL, a language similar to C, does not allow for the allocation of C arrays using a variable for the size.

Instead, you can dynamically create your shader code strings to incorporate the number of textures directly into the code. In your situation, you will need to perform some replacement. Here is a simple example:

  var material = new THREE.ShaderMaterial({  
    uniforms: {

      verticesPerTexture: new Float32Array([4.0]), // storing the count of vertices per texture

      cat_texture: {
        type: 't',
        value: loader.load(catUrl),
      },

      dog_texture: {
        type: 't',
        value: loader.load(dogUrl),
      },

      textures: {
        type: 'tv', 
        value: textureArr,
      }
    },
    vertexShader: document.getElementById('vertex-shader').textContent,
    fragmentShader: document.getElementById('fragment-shader').textContent.replace(/!!!_TEXCOUNT_!!!/g,textureArr.length.toString());
  });
<script type='x-shader/x-fragment' id='fragment-shader'>
  precision highp float; 

  varying vec2 vUv; 
  varying float vTextureIdx; 

  uniform sampler2D textures[!!!_TEXCOUNT_!!!];

  void main() {
    int textureIndex = int(floor(vTextureIdx));

    if (int(floor(vTextureIdx)) == 0) {
      gl_FragColor = texture2D(textures[0], vUv);
    } else {
      gl_FragColor = texture2D(textures[1], vUv);
    }
  }
</script>

The replacement feature searches for the key !!!_TEXCOUNT_!!! and substitutes it with the actual number of textures in your array.

I also removed the unnecessary texture_num uniform and eliminated cat_texture and dog_texture since the textures are now stored in the textures array.

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

Retrieve the input field value using JavaScript within a PHP iteration loop

I've implemented an input box inside a while loop to display items from the database as IDs like 001,002,003,004,005 and so on. Each input box is accompanied by a button beneath it. My Desired Outcome 1) Upon clicking a button, I expect JavaScript t ...

Having trouble with data retrieval from MySQL using PHP and Angular on certain mobile devices, although it functions properly on desktops and laptops

The data retrieved from the mysql database is functioning properly on desktop and laptop, but not on mobile devices. The following HTML code is present in the html file: <table class="table table-default"> <thead> <tr> & ...

Encountering issues with parsing a JSON object while utilizing the templateHTMLrenderer feature in Django

I'm just starting out with django and JSON, and I'm attempting to send a list of patients in JSON using the code below: class JSONResponse(HttpResponse): """ An HttpResponse that converts content into JSON format. """ def __init_ ...

Encountering an issue while trying to communicate with a web

I've been following a tutorial on how to call a web service from a web page located at http://www.codeproject.com/KB/webservices/CallWebServiceFromHtml.aspx, but I'm encountering an error in the Firebug console: service is not defined Initia ...

Transfer external variables into the image's onload function

I am trying to retrieve image dimensions and then execute additional actions. Since the image onload function is asynchronous, I have decided to handle everything within the onload call. This is my current approach: function getMeta(url, callback) { v ...

Unable to generate a vertical navigation bar

When attempting to create a vertical menu, the final result doesn't align as expected. https://i.stack.imgur.com/2ok47.jpg This is the current code being used: $("#example-one").append("<li id='magic-line'></li>") ...

Removing a specific object from a MongoDB array by its unique identifier

I'm currently developing an application that focuses on playlists. Utilizing MongoDB with mongoose, I am storing videos within each playlist using an array structure as demonstrated below: { _id: ObjectId("61ca1d0ddb66b3c5ff93df9c"), name: "Playli ...

Ways to retain specific div elements following the execution of .html(data) command

Imagine I have a div structured in this way: <div id = "foo" style = "display: grid"> <div id = "bar"> keep me! </div> </div> If I use JQuery's .html(data) method like shown below: $('#foo').html(data); when m ...

Can you switch between displaying and concealing a dropdown in the same location based on chosen values?

I have four dropdowns listed, but I only want to display one at a time. Depending on the selected values, when I try to show a dropdown, it does not replace the current one; instead, it just appears next to the existing dropdown. Is there a way to keep th ...

Tips for attaching an event listener to activate a server-side email feature?

I have a setup with an express application that serves up a static index.html page. Additionally, there is a function in my app.js file that sends an email whenever the server starts running. My goal is to modify this so that the email is only sent when a ...

Is the validation for the 'prop' property missing in props?

Seeking assistance with react's forwardRef feature. Currently encountering errors related to missing props validation in FadeContents. Is there a way to resolve this issue? It seems like the props need to be defined somewhere in order to be used withi ...

Input captured through a scanner has been scanned into the text field

Currently, I am utilizing the Scanner (basic model) to scan barcodes. The scanned barcode is then captured in a textbox. Within the txtBarcode_TextChanged event, I retrieve the scanned barcode for further processing. Issue: Upon multiple scanner clicks, ...

Getting the css property scaleX with JQuery is as simple as executing the

I am struggling to print out the properties of a specific div element using jQuery. My goal is to have the different css properties displayed in an information panel on the screen. Currently, I am facing difficulties trying to show scaleX. Here is my curr ...

Separate an array in TypeScript based on the sign of each number, and then replace the empty spaces with null objects

Hey, I'm facing a little issue, I have an Array of objects and my goal is to split them based on the sign of numbers. The objects should then be dynamically stored in different Arrays while retaining their index and getting padded with zeros at the b ...

Troubleshooting: Next JS 13/14 - Server component failing to update data upon revisiting without requiring a refresh

After attempting to retrieve the most recent liked items from a server component in next, I noticed that the data only displays when manually refreshing the page. Even when I navigate away and return, the data is not refetched automatically - however, usin ...

NodeJS reports an invalid key length, while C# accepts the key length as valid

Currently, I am in the process of converting Rijndael decryption from C# to NodeJS. The Key (or Passphrase) being used is 13 characters long, while the IV used is 17 characters long. Note: The length choice for both Key and IV is beyond my control Disp ...

Steps for embedding a function within another function

One method I know is by using this hack: function executeFunction(func){ setInterval(func,0); } executeFunction("newFunction()"); However, I am searching for a more elegant solution. ...

A guide on incorporating React components from a locally installed npm package

Recently, I've been working on developing an npm package that contains a collection of React components that are essential for all my projects. Let me walk you through the folder structure and contents: / dist/ bundle.js src/ MyComponent.jsx ...

Implementing conditional dropdown menus with CodeIgniter

Explore the District Master Table: https://i.sstatic.net/n6kvV.jpg Dive into the District table: https://i.sstatic.net/uQqcW.jpg District Master District I need assistance with a form page that includes a Category dropdown. The district table stores d ...

Developing a personalized Avada form auto-scrolling algorithm

Our form, created using the Wordpress - Avada theme, needs an autoscroll feature. As users answer questions, the next question appears below, but this is not immediately visible on mobile devices. To address this, we require autoscroll functionality. The ...