Creating a multitude of Point Lights resulted in a "THREE.WebGLShader Error: Too many uniforms" message appearing

Context

I've been working on creating a ring of lights with the following function implementation

function createLightRing(radius, options) {

  let nopIsDefault = false;
  
  ...

However, upon running it, I encountered this error

THREE.WebGLProgram: shader error:  0 35715 false gl.getProgramInfoLog invalid shaders  THREE.WebGLShader: gl.getShaderInfoLog() fragment
ERROR: too many uniforms
1: #version 300 es
2: #define varying in
3: out highp vec4 pc_fragColor;
4: #define gl_FragColor pc_fragColor
5: #define gl_FragDepthEXT gl_FragDepth
6: #define texture2D texture
7: #define textureCube texture
...

It's frustrating that my intention was just to create a simple ring :(

My Attempts

  • Reducing the radius
  • Lowering the quality

Highlighted CODE!!!

You can find the live code on repl.it, check it out here

The Function:

function createLightRing(radius, options) {

  let nopIsDefault = false;

  let lights = [];

  const defaultOptions = {
    start: 0,
    end: 360,
    copyLights: [],
    color: 0xffffff, // White
    lightType: "PointLight",
    intensity: 1,
    copyLightMap: "loop", // loops the arrays from colors and other values like it
    rotation: new p5.Vector(0, 0, 0),
    target: null,
    quality: 6,
    numberOfPoints: null,
    override: false
  }

  // applying the default options
  options = {...defaultOptions, ...options}

  const copyLightMap = options.copyLightMap.toString().toLowerCase();
  
  // executed only if "numberOfPoints" exists
  if (!options.numberOfPoints) {
    options.numberOfPoints = (options.end - options.start) * options.quality

    nopIsDefault = true;
  }


  // Mode 1 (soft / soft-(force / end) / 1, forces the loop to end when it finishes looping through "copyLights", but ensures completing the loop. TL;DR: Sets "numberOfPoints" to "copyLights"'s length)
  if (copyLightMap == '1' || copyLightMap == 'soft' || copyLightMap == 'soft-end' || copyLightMap == 'soft-force') {  
    options.numberOfPoints = options.copyLights.length

    nopIsDefault = true;
  }

  // updating "quality" to the right value
  options.quality = nopIsDefault ? options.quality : options.numberOfPoints / (options.end - options.start)

  for (let i = options.start; i <= options.end; i += 1 / options.quality) {
        
    let light;
    let dontCheck = false;
    let realI = (1 / options.quality) * i;


    const x = radius * cos(i);
    const y = radius * sin(i);


    // try to create a light with the specified type
    try {
      light = new THREE[options.lightType]();
    }
    // if it fails, use the default
    catch(err) {
      light = new THREE[defaultOptions.lightType]();
    }

    light = setLightProperties(light, options);     // initializes the light properties

    // run the switch only if both "copyLights" has at least one element and it can run in the first place
    if (options.copyLights[0] && dontCheck) {

      const copyLightMap = options.copyLightMap.toString().toLowerCase();

      switch (copyLightMap) {
        
        // Mode 0 (force / end / 0, forces the loop to end when done)
        case 'force':
        case 'end':
        case '0':
          if (realI < circleLoop) {
            dontCheck = true;
            break;
          }

          light = options.copyLights[realI];
          break;
        
        // Mode 2 (loop / 2, go back to beginning copyLights when there are no more values left in it)
        case 'loop':
        case '2':
          light = options.copyLights[realI % options.copyLights.lenght];
          break;
      }
    
    }

    if (options.override) {

      light = setLightProperties(light, options);   // updates light's properties

    }

    light.position.set(x, y, 0);   // sets the light's position

    lights.push(light);   // adds the new light to the array
  }

  return lights;
}

You can find all other details about my work on repl.it, so feel free to explore!

Answer №1

Your error lies in the abundance of uniforms in your shader, which is too much for the browser or platform you are currently using.

To check this issue, visit:

Look under Vertex Shader and Fragment Shader, where you will find a "Max _____ Uniform Vectors:" indicating the limit imposed on the size of your uniforms based on your browser or GPU. These values are determined by GL constants and can be accessed through them. Here is a demonstration on how to retrieve these values:

const canvas1 = document.createElement('canvas')
const gl1 = canvas1.getContext('webgl')
if (gl1) {
  document.getElementById('wg1-mvuv').innerText = gl1.getParameter(gl1.MAX_VERTEX_UNIFORM_VECTORS)
  document.getElementById('wg1-mfuv').innerText = gl1.getParameter(gl1.MAX_FRAGMENT_UNIFORM_VECTORS)
}

const canvas2 = document.createElement('canvas')
const gl2 = canvas2.getContext('webgl2')
if (gl2) {
  document.getElementById('wg2-mvuv').innerText = gl2.getParameter(gl2.MAX_VERTEX_UNIFORM_VECTORS)
  document.getElementById('wg2-mfuv').innerText = gl2.getParameter(gl2.MAX_FRAGMENT_UNIFORM_VECTORS)
}
html * {
  font-family: monospace;
}

td {
  border: 1px black solid;
}
<table>
  <caption>WebGL</caption>
  <tr>
    <td>GL_MAX_VERTEX_UNIFORM_VECTORS</td>
    <td id="wg1-mvuv">UNSUPPORTED</td>
  </tr>
  <tr>
    <td>GL_MAX_FRAGMENT_UNIFORM_VECTORS</td>
    <td id="wg1-mfuv">UNSUPPORTED</td>
  </tr>
</table>

<table>
  <caption>WebGL 2</caption>
  <tr>
    <td>GL_MAX_VERTEX_UNIFORM_VECTORS</td>
    <td id="wg2-mvuv">UNSUPPORTED</td>
  </tr>
  <tr>
    <td>GL_MAX_FRAGMENT_UNIFORM_VECTORS</td>
    <td id="wg2-mfuv">UNSUPPORTED</td>
  </tr>
</table>

Check if you are feeding large arrays into a uniform or if your final shader code contains an excessive number of uniforms. WebGL inspector browser plugins can aid in viewing the final shader code. It’s advisable to keep your shader concise and then expand it as memory permits.

This issue tends to surface more frequently on mobile platforms with limited memory resources

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

Iterating over an object while omitting certain elements

Is there a way to insert a separator at a specific position in JSX? For example, I have a list that displays text when an item is clicked: https://i.sstatic.net/s71yE.png Here is the code: <Accordion> {items.map((item, index) => ( <Acco ...

Trouble displaying image due to issues with javascript, html, Angular, and the IMDb API integration

I have been working on displaying images from the IMDb API in my project. Everything works perfectly fine when I test it locally, but once I deploy the project to a server, the images do not load initially. Strangely, if I open the same image in a new tab ...

Struggling with the allocation of scope to a variable for manipulation

Struggling with assigning a scope object to a JavaScript variable in order to make some minor adjustments before sending it to my API. Surprisingly, any modifications made to the JavaScript variable end up changing the original scope object. var recruitin ...

Tips for staying on the same page when hovering over a table

My hover table contains multiple pages, with each row offering various actions one can take with an item. After performing an action, the page refreshes and returns to the first page of the table. Is there a way to stay on the same page after executing a ...

Assistance required for posting Jquery files

Attempted to upload a file using jQuery with a hidden form and an Input element, triggering the file browser with jQuery. The changed input is then sent to a PHP server script. Encountered an issue where submitting the form with $("form1").submit(); worke ...

How to Use Ember.js with MongoDB for Querying Data Using "AND"

I've been making great progress on my Emberjs application, but I've hit a roadblock that's leaving me stumped. Despite scouring the web for answers, I can't seem to find a solution. The issue at hand involves a dropdown feature in my a ...

What causes the undefined value in my HapiJS test utilizing the Lab library?

Currently, I am diving into the HapiJS tutorial to build a server and incorporate unit testing. 'use strict' const Hapi = require('@hapi/hapi') module.exports = async (host, port, router) => { if (!host) { const error = new E ...

Using multiple widgets for a single form field in a Django application

Below is the form structure I am working with: class ExcipientForm(ModelForm): class Meta: model = Excipient fields = ( "Excipient_type", "Excipient_concentration", ) widge ...

transforming array elements into properties of a React component

My text component contains the code below return ( <FormControl variant="outlined" className={classes.formControl}> <Grid container> <TextField id={props.id} label={props.label} d ...

How to remove decimal points from the x-axis in jqPlot

Is there a way to show only whole numbers on the x-axis in jqPlot? At the moment, it shows: 0.5, 1, 1.5, 2, 2.5, etc. I'm looking for a method to make it display integers exclusively in the x-axis labels. ...

Unusual outcome observed when inputting a random number into HTML using JavaScript

In my HTML file, I am trying to input a number within 50% of a target level into the "Attribute" field. Here is the code: <!DOCTYPE html> <html> <body> <input type = "number" name = "playerLevel" onchan ...

Error: Unable to locate module '@emotion/react' in 'E:frontend ode_modules@muistyled-engine' directory

I've been trying to import a box component from @mui/material/Box. After installing Material-UI 5 using npm i @mui/material, I encountered the error message Module not found: Can't resolve '@emotion/react' in 'E:\frontend&bsol ...

Guide on how to replace a built-in method of JavaScript's native objects

Imagine having the window object's alert method and wanting to improve it with a stylish alert box. Furthermore, preserving the current alert method for switching back after our application completes. We attempted something like this code snippet be ...

Learn how to execute JavaScript code in Selenium without launching a web browser

I am currently using the Selenium API for web scraping on pages that contain JavaScript code. Is there a way to retrieve the code without having to open a web browser? I am still learning how to use this API Is this even feasible? ...

Contrasting the use of jQuery versus AJAX for updating static page text

While I haven't fully grasped the concept of AJAX yet, my understanding is that it can be beneficial for updating specific parts of a webpage. Does using AJAX only make sense when you require server interaction? I am looking to replace text on a webp ...

What is the process of installing an npm module from a local directory?

I recently downloaded a package from Github at the following link: list.fuzzysearch.js. After unzipping it to a folder, I proceeded to install it in my project directory using the command: npm install Path/to/LocalFolder/list.fuzzysearch.js-master -S Howe ...

determine variances between two Java script objects

I need help with comparing two JavaScript objects to find the differences. The code I am using in the function is not giving me the desired output. function compare() { var Json1 = [ { name: "ABC", value: "5" }, { name: "DEF", value: "85712264" ...

Issue encountered while trying to import a .ts file into a .js file

I have some .js files and I want to incorporate certain .ts files into them. However, when I attempt to import these files, I encounter some strange errors. Here is the import statement in my .js file: import {AuthComponent} from './auth/auth.compon ...

Generate dynamic DIV elements and populate them with content

Can you assist me in getting this code to function properly? My goal is to dynamically create elements inside a div and fill each element with a value fetched from the database through a server-side function. I'm unsure if there's a better approa ...

ideas/tips for interpreting JavaScript

Looking for a solution to convert synchronous JavaScript function calls into asynchronous ones? Here's the scenario: If you have a code snippet like this: someSyncFunction(); console.log("function complete") You want it converted to: someAsyncFunc ...