Sprites not displayed on Chrome with no hardware acceleration

Description of the problem

When hardware acceleration is disabled, sprites are not displayed on Chrome.

Should see a big rubber duck the following examples, while it’s all black on Chrome without HA.

Three.js version
  • Dev
  • r118
Browser
  • Chrome
  • Firefox
  • Internet Explorer
OS
  • All of them
  • Windows
  • macOS
  • Linux
  • Android
  • iOS
Hardware Requirements (graphics card, VR Device, …)

No graphic card (e.g. virtualized environment) or hardware acceleration set to off on Chrome.

2 thoughts on “Sprites not displayed on Chrome with no hardware acceleration

  1. The root of the problem is this line:

    sprite.scale.set(50, 50);

    sprite.scale is actually a Vector3, so it expects 3 arguments, but you’re passing 2.

    That results in:

    sprite.scale.x = 50;
    sprite.scale.y = 50;
    sprite.scale.z = undefined;

    Then, sprite.matrix becomes [50, 0, 0, 0, 0, 50, 0, 0, NaN, NaN, NaN, 0, 0, 0, 0, 1].

    Seems like SwiftShader (the renderer used when hardware acceleration is disabled) breaks when passing NaNs.

    I think the solution here is to implement more default parameters:

    	set: function ( x = 0, y = 0, z = 0 ) {
    
    		this.x = x;
    		this.y = y;
    		this.z = z;
    
    		return this;
    
    	},

    Another solution would be to try to do this.scale = new Vector2() in the Sprite constructor…

  2. Then, sprite.matrix becomes [50, 0, 0, 0, 0, 50, 0, 0, NaN, NaN, NaN, 0, 0, 0, 0, 1].

    Seems like SwiftShader (the renderer used when hardware acceleration is disabled) breaks when passing NaNs.

    @mrdoob I assume this is a vertex transform matrix, passed directly to the shaders as a uniform variable? For the API side, the following spec quote applies:

    Any representable floating-point value is legal as input to a GL command that
    requires floating-point data. The result of providing a value that is not a floating-
    point number to such a command is unspecified, but must not lead to GL interrup-
    tion or termination. In IEEE arithmetic, for example, providing a negative zero or a
    denormalized number to a GL command yields predictable results, while providing
    a NaN or an infinity yields unspecified results.
    

    As for how they should be handled by GLSL shaders:

    Operations and built-in functions that operate on a NaN are not required to
    return a NaN as the result.
    

    It’s not clear to me that SwiftShader “breaks” when passing it NaNs. It’s quite likely that it propagates NaNs in a more IEEE 754 recommended manner, while most GPUs treat them as zero, or inifinity, and this just-so-happens to produce a more desirable output. But it can fail at any time on GPUs or drivers that adhere more closely to IEEE 754. It would be great if someone could take a deeper look at where things start to deviate from expectations.

    In any case, one should avoid NaNs to achieve reliable results.

    I bet there is a lot of more stuff that does not work if you disable hardware acceleration.

    In general, the engine assumes hardware acceleration is enabled and there is no support without it.

    @Mugen87 While this currently uses the OpenGL ES driver implementation, SwiftShader has a certified conformant Vulkan 1.1 implementation for the CPU. If something doesn’t work it’s not uncommon to be an application or engine bug. If a SwiftShader bug is suspected, please file an issue.