2

I need to access a buffer from my shader. The buffer is created from an array. (In the real scenario, the array has 10k+ (variable) numbers.)

var myBuffer = gl.createBuffer();
gl.bindBuffer(gl.ARRAY_BUFFER, myBuffer);
gl.bufferData(gl.ARRAY_BUFFER, new Uint8Array([1,2,3,4,5,6,7]), gl.STATIC_DRAW);

How do I send it so it's usable by the shader?

precision mediump float;
uniform uint[] myBuffer;//???

void main() {
    gl_FragColor = vec4(myBuffer[0],myBuffer[1],0,1);
}

Normally, if it were a attribute, it'd be

gl.vertexAttribPointer(myBuffer, 2, gl.UNSIGNED_BYTE, false, 4, 0);

but I need to be able to access the whole array from any shader pixel, so it's not a vertex attribute.

5
  • 2
    Have you tried with loading your array to a texture ? Using Sampler2D object I hope you will have access to whole array.. Commented Mar 31, 2016 at 5:03
  • Is that the way you're supposed to do it? I thought Sampler2D was for images and buffer for random custom binary data. Commented Mar 31, 2016 at 5:07
  • How can you create a Sampler2D object from an array? Commented Mar 31, 2016 at 5:52
  • Nevermind, got it: gl.texImage2D(gl.TEXTURE_2D,0, gl.RGBA, width, height, 0, gl.RGBA, gl.UNSIGNED_BYTE, data); Commented Mar 31, 2016 at 6:04
  • We are creating a texture object only. while giving data to glTexImage2D, pass your data instead of image data. In fragment shader , using sampler object access the content. Commented Mar 31, 2016 at 6:22

1 Answer 1

4

Use a texture if you want random access to lots of data in a shader.

If you have 10000 values you might make a texture that's 100x100 pixels. you can then get each value from the texture with something like

uniform sampler2D u_texture;

vec2 textureSize = vec2(100.0, 100.0);

vec4 getValueFromTexture(float index) {
   float column = mod(index, textureSize.x);
   float row    = floor(index / textureSize.x);
   vec2 uv = vec2(
      (column + 0.5) / textureSize.x,
      (row    + 0.5) / textureSize.y);
   return texture2D(u_texture, uv);
}

Make sure your texture filtering is set to gl.NEAREST.

Of course if you make textureSize a uniform you could pass in the size of the texture.

As for why the + 0.5 part see this answer

You can use normal gl.RGBA, gl.UNSIGNED_BYTE textures and add/multiply the channels together to get a large range of values. Or, you could use floating point textures if you don't want to mess with that. You need to enable floating point textures.

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.