Using Three.js to send an array of textures to a shaderMaterial

Query: How can I efficiently pass and access a list of textures in shaders, specifically targeting the nth texture within a fragment shader based on a varying value passed from the vertex shader?

In my current project involving a Three.js scene, I am tasked with representing multiple images. Each image utilizes one of several textures, with each texture serving as an atlas containing various thumbnails. To streamline performance, I am implementing a custom shaderMaterial but encountering difficulties in handling multiple textures within the shaders.

The objective is to transmit a collection of textures along with the number of vertices per texture to determine the appropriate texture for each image's vertices or pixels. Initially, I attempted to achieve this by passing the following information:

// Define a texture loader for file loading
var loader = new THREE.TextureLoader();

// Specify the URLs for the textures
var catUrl = 'https://s3.amazonaws.com/duhaime/blog/tsne-webgl/assets/cat.jpg';
var dogUrl = 'https://s3.amazonaws.com/duhaime/blog/tsne-webgl/assets/dog.jpg';

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

    verticesPerTexture: new Float32Array([4.0]), // vertex count per texture

    textures: {
      type: 'tv', // texture array type
      value: [loader.load(catUrl), loader.load(dogUrl)],
    }
  },
  vertexShader: document.getElementById('vertex-shader').textContent,
  fragmentShader: document.getElementById('fragment-shader').textContent
});

However, the vertex shader encounters issues utilizing the uniforms to indicate to the fragment shader which texture should be used. It appears that vertex shaders are unable to pass sampler2D objects as varyings to the fragment shader. What approach should be taken to successfully transfer a list of textures to the shaders?

Synopsis of code snippet (incomplete due to unsuccessful texture list transmission):

...

Answer №1

Upon reflection, here is an alternative approach you can experiment with, resembling the process of working with pre-existing materials:

function generateCustomMaterial ( texture ) {
    return new ShaderMaterial({
        uniforms: {
            customTexture: { value: texture }
        }
    })
}

var material1 = generateCustomMaterial( dogTexture );
var material2 = generateCustomMaterial( catTexture );

geometry.faces[ 0 ].materialIndex = 0;
geometry.faces[ 1 ].materialIndex = 0;
geometry.faces[ 2 ].materialIndex = 1;
geometry.faces[ 3 ].materialIndex = 1;

var customizedMesh = new Mesh( geometry, [ material1, material2 ] );

Answer №2

Your approach in the vertex shader assumes that 'main' functions as a for loop, updating 'vertexIdx' and 'textureIdx' for each vertex sequentially. However, shaders operate in parallel, processing all vertices simultaneously. Therefore, sharing computed data between vertices is not possible.

To address this issue, utilize an attribute on the geometry:

geometry.addAttribute( 'texIndex', new THREE.BufferAttribute( [ 0, 0, 0, 0, 1, 1, 1, 1 ], 1 ) )

You may need to pass this attribute through the vertex shader using a varying variable:

attribute int texIndex;
varying int vTexIndex;
void main () { vTexIndex = texIndex; }

Lastly, in the fragment shader:

varying int vTexIndex;
uniform sampler2D textures[ 2 ];
...
sampler2D tex = textures[ vTexIndex ];

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

Enhancing a blog entry in Meteor.js

Recently, I embarked on a journey to learn Meteor.js in hopes of creating a newsfeed feature that allows me to add, edit, and delete content. As of now, I am facing challenges with the editing process. imports/api/news/methods.js Meteor.methods({ ...

populate the empty slots in an array with the correct numbers

Having two pre-sorted arrays as shown below: [1,2,4,5,8] [x,x,x,x,x] The goal is to fill in the missing elements with 'y' in the corresponding array, resulting in: [1,2,3,4,5,6,7,8] [x,x,y,x,x,y,y,x] Although the data arrives separately, they ...

Issues with Jquery Ajax POST request not resolving

Can you explain why the success code is not being executed in this request? $(document).ready(function(){ var post_data = []; $('.trade_window').load('signals.php?action=init'); setInterval(function(){ ...

What is an alternative way to show the contents of a JSON file without directly accessing it

Recently, I stumbled upon an amazing website - where I have been exploring to learn something new. The website prominently features the use of Ajax and some fascinating javascript without any additional libraries. Within a single javascript file on this ...

When Vue 3 is paired with Vite, it may result in a blank page being rendered if the

Issue with Rendering Counter in Vite Project After setting up a new project using Vite on an Arch-based operating system, I encountered a problem when attempting to create the simple counter from the Vue documentation. The element does not render as expec ...

In Next.js, the 404 error page is displayed using getInitialProps

Currently, I am learning how to redirect users in getInitialProps by following a helpful example. Here is the link to the example I am referring to However, I encountered an issue where when I try to return a 404 error using the code snippet provided, in ...

Harnessing the Power of JSON in Rails to Enhance Your jQuery UI Autocomplete Form

In the context of a rails application, I have been exploring different methods to fetch data from a JSON file. Despite my efforts, I have not been able to find a solution that suits my requirements. The static data I have is quite extensive, consisting of ...

ajax ignores output from php

I've been working on passing PHP echo values through AJAX, but I've encountered a problem where the if and else conditions are being skipped in the success function of AJAX. Even when the if condition is met, the else statements are still being e ...

Issues arise with AJAX post

I have run into an issue with my jQuery and Codeigniter setup while trying to update the database via AJAX. Despite having the following code in place, nothing seems to be happening or getting sent to my controller when the button is clicked... Snippet of ...

Using Ng If with a boolean value to dynamically update the title of a webpage

On my Stock page, I have multiple fields labeled as Title 1. https://i.sstatic.net/FpCsW.png When I run a console.log, it indicates that I am on the first page! ngOnInit() { this.currentPortfolio = this.shrd.getData('currentPortfolio'); ...

Merging two separate observableArray into a single entity in knockout js

I am currently working on merging two distinct arrays into a general array and then connecting it using foreach. My View Model: self.cancelledItem1 = ko.computed(function () { return ko.utils.arrayFilter(self.items(), function (item) { ...

Is there a more productive approach to creating numerous React components?

I am currently working on a page where I need to render 8 components. The only thing that differs between each component is the values that are being iterated... <Item classModifier="step" image={Step1} heading={Copy.one.heading} /> <Item ...

What is the process for the Rebol programming language to independently implement an asynchronous pluggable protocol for reading

This post outlines the process of incorporating an asynchronous pluggable protocol in Rebol that can be accessed through Firefox, Internet Explorer, or the command line For instance, if I were to define the reb:// protocol, I could enter it into a browser ...

Is there a way to fix the issue of ContextMenu not appearing at the right position within a scrollable

I have a div within an iframe that needs to display a context menu when right-clicked. The div's length may exceed the visible area, making it scrollable. However, the issue I am facing is that the context menu appears in a different position than whe ...

Tips for populating a dropdown list with data from the backend and selecting the desired value using Angular

I am currently working on an Angular 8 application that utilizes Material design. My goal is to populate a dropdown list with data retrieved from the backend. The API call code snippet is as follows: returnQrCodes$ : Observable<QRCodeDefinitionSelect ...

Using React's higher order component (HOC) in TypeScript may trigger warnings when transitioning from non-TypeScript environments

I have a simple HOC component implemented in React with TypeScript. export const withFirebase = <P extends object>( Component: React.ComponentType<P> ) => class WithFirebase extends React.Component<P> { render() { return ...

Utilizing Directives for DOM Manipulation in AngularJS

At this moment, I have a functional Angular app that is working properly. However, I am currently performing DOM manipulation within my controller instead of utilizing directives as recommended. My concern is, how can I correctly implement this functionali ...

Detecting when an object exits the proximity of another object in ThreeJS

In my ThreeJS project, I have planes (Object3D) flying inside a sphere (Mesh). My goal is to detect when a plane collides with the border of the sphere so that I can remove it and respawn it in a different location within the sphere. I am wondering how I ...

D3 - Error: Unable to access property 'text' of an undefined method

I want to create a visual representation of significant events that have occurred in the United States over the past 30 years. Below is a snippet of code I am using for this project: var mevent = svg.append("text") .attr("class", "year event") .at ...

Encountering a typescript error: Attempting to access [key] in an unsafe manner on an object of

I have recently developed a thorough equality checking function. However, I am encountering an issue with the highlighted lines in my code. Does anyone have any suggestions on how to rectify this problem (or perhaps explain what the error signifies)? Her ...