question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

Webgl passing a big Int32 uniform is difficult

See original GitHub issue

Is your feature request related to a problem? Please describe. I’m trying to pass a big Uint32 as uniform. The max value of that int can be a 9-digit number. It is used in my case to compare a specific id to the id of the geometry object currently being rendered.

The problem is that an uniform can only be a float32 (or a vector of float, which is not of interest here) Float can have at most a 7-digit precision or up to 2^23. So trying to pass a 9-digit number to my shaders failed for my use case.

As an alternative, I tried to trick that limitation by passing my integer as a Float32, relying on the underlying bits. In the uniform callback, it looks like that:

const focusArrayBuffer = new ArrayBuffer(Float32Array.BYTES_PER_ELEMENT);
const selectedFeature = new DataView(focusArrayBuffer);

selectedFeature.setInt32(0, someInt32Value);

const uniforms = {
    u_selectedId: function(framestate){
         return selectedFeature.getFloat32(0);
    }
}

I thought I had it, until I tested a default value of 0. And unfortunately, a few other geometry with non-zero ids reacted to that. In particular the values 2339002 or 2339006. Despite the fact that:

b = new ArrayBuffer(Float32Array.BYTES_PER_ELEMENT);
v = new DataView(b,0);
v.setUint32(0,2339002)
v.getFloat32(0) // output: 3.277639910652676e-39
v.setUint32(0,2339006)
v.getFloat32(0) // output: 3.277645515846533e-39

The output here are different from 0 or from each other but they seem to be passed with the same value to the shaders.

And the precision in the shaders are precision highp float for both of them. So I don’t get why that failed to pass the proper value to the shaders…

Describe the solution you’d like Being able to pass a int32 instead of a float would be much simpler here.

Issue Analytics

  • State:closed
  • Created 3 years ago
  • Comments:5 (2 by maintainers)

github_iconTop GitHub Comments

1reaction
FractalWirecommented, Jun 7, 2020

Well in theory, I think I should be able to trick it. After all, a float32 is just 32 bits in memory. If 3.277639910652676e-39 is different from 2339002, they both have the same binary representation. So that’s what I’m trying to do here, passing a float32 to the shaders that have the same binary representation as a big int32.

Since it’s likely that you don’t have that many features in your source, you could look into using the feature index in the source, or another deliberate identifying method.

My end goal is to represent around 100 000 vectors in Openlayers. That is fairly lower than 2^23. However, those 100 000 vectors might get reloaded periodically and 2^23 / 100000 = 83.89... Which means I can have at most 83 reloads before hitting the float limit and entering the bug zone. So using ol_uid won’t work for me here and I need to use my own smaller identifier I guess.

Note that in the webgl points renderer, the hit detection shader will receive the feature index in the opacity attribute.

Considering the use case above, there might be a (very) rare bug in the hit detection once the 2^23 id is reached.

Au passage: salut de la part d’un autre Olivier Guyot 😉

0reactions
stale[bot]commented, Aug 8, 2020

This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contributions.

Read more comments on GitHub >

github_iconTop Results From Across the Web

THREE.js - large array of int as Uniform - Stack Overflow
Textures are large arrays. Passing integers in textures is a little harder but not impossible (for WebGL2 see below).
Read more >
WebGL Precision Issues
This article is about various precision issues in WebGL. lowp , mediump , highp. In the first article on this site we created...
Read more >
Counting Uniforms in WebGL - Bocoup
According to the OpenGL wiki, a uniform is “a global GLSL ... You pass it a shader program and it returns an object...
Read more >
Making GLSL Execution Uniform to Prevent WebGL-based ...
Such WebGL-based fingerprinting is hard to defend against, because the client browser executes a program written in. OpenGL Shading Language (GLSL).
Read more >
Hassles with array access in WebGL, and a couple of ...
(Or OpenGL ES - I'm not sure where exactly the "blame" lies.) Take the following fragment shader code: uniform float uMyArray[16]; ... void...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found