Skip to content

WebGLLights state and its hashing produce unintended material reinitialization #14121

@Usnul

Description

@Usnul

WebGLLights is used to store lighting state.
WebGLLights.hash property is used to determine whether or not a material needs to be re-built.

} else if ( materialProperties.lightsHash !== lights.state.hash ) {
properties.update( material, 'lightsHash', lights.state.hash );
programChange = false;

The way hash is built, it includes unique reference to WebGLLights instance:

state.hash = state.id + ',' + directionalLength + ',' + pointLength + ',' + spotLength + ',' + rectAreaLength + ',' + hemiLength + ',' + shadows.length;

constructor:

var count = 0;
function WebGLLights() {
var cache = new UniformsCache();
var state = {
id: count ++,

this means that if you have 2 instances of WebGLLights and they are identical, except for id - you will end up rebuilding materials as you switch between these instances - inefficient.

Another problem with the current approach is that it is probabilistic, it's possible that hash remains the same even though lighting has changed.

I propose following:

  • remove id from hash calculation
  • use a fast hashing function to compute 64bit hash(javascript number is IEEE 64-bit Float) instead of using a string
  • pass more than just number of lights into the hash (as long as that makes sense).

Metadata

Metadata

Assignees

No one assigned

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions