Passing data to shader using texture

Hi there,

I want to pass timeseries data into a shader. Because the data is potentially quite long, I am trying to do so by writing the data to a texture, then passing the texture to my shader. I’m finding the texture doesn’t get passed into the shader correctly.

Here’s a small sketch showing this.

Here’s a class I’ve written to manage the texture.

class TextureArray {
  constructor(length, gl) {
    this.data = new Float32Array(length)
    this.gl = gl

    const texture = gl.createTexture()
    gl.bindTexture(gl.TEXTURE_2D, texture)
    gl.texImage2D(gl.TEXTURE_2D, 0, gl.R32F, this.data.length, 1, 0, gl.RED, gl.FLOAT, this.data)
    gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE)
    gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE)
    gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR)
    gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR)
    this.texture = texture
  }

  push(x) {
    for (let i = this.data.length - 1; i > 0; i -= 1) {
      this.data[i] = this.data[i - 1]
    }
    this.data[0] = x

    const gl = this.gl
    gl.bindTexture(gl.TEXTURE_2D, this.texture)
    gl.texSubImage2D(gl.TEXTURE_2D, 0, 0, 0, this.data.length, 1, gl.RED, gl.FLOAT, this.data)
  }
}

Then, I pass this texture to the shader using the following code:

s = createShader(vs, fs)
shader(s)
const uniform = s.uniforms["meow"]
const location = uniform.location
s.useProgram()
gl.activeTexture(gl.TEXTURE0 + uniform.samplerIndex)
gl.bindTexture(gl.TEXTURE_2D, a.texture)
gl.uniform1i(location, uniform.samplerIndex)

However, in the shader the meow texture only contains zero values (no matter how I initialize the input texture array). I was wondering if anyone here sees something wrong with the code. Thanks!

Try using a p5.Framebuffer to create your textures (updating their pixels array) and then using that for data. I have an example of that here, passing a bunch of points into a shader: 2.5d blob test - OpenProcessing

1 Like

Note that because p5 pre-multiplies textures by their alpha value, if you try to pass in data on all four channels, the alpha will wipe out the other values. You can disable this with

let gl = myFB.gl;
gl.pixelStorei(gl.UNPACK_PREMULTIPLY_ALPHA_WEBGL, false);
myFB.updatePixels();

@davepagurek, perhaps we could add an optional parameter to updatePixels() to temporarily disable the alpha pre-multiply to better support data textures.