2
votes

I am noob to WebGL, and I am trying to understand how WebGL textures works by reading this tutorial: WebGL Image Processing Continued.

There is another example in the same tutorial serie which is using two textures by setting the uniforms for both input textures units 0 and 1 explicitly:

// set which texture units to render with.
gl.uniform1i(u_image0Location, 0);  // texture unit 0
gl.uniform1i(u_image1Location, 1);  // texture unit 1

But in the first example, the fragment shader is using the sampler2D u_image for the input texture, so i would expect there shall be in code something like:

gl.uniform1i(gl.getUniformLocation(program, "u_image"), 0);

...but i can't find it. How this works? Just guessing: is the texture unit 0 used as default for all 2D samplers in all WebGL programs? Then, why is gl.uniform1i(u_image0Location, 0); needed in the second example?

EDIT:

So far, what i have understand from the tutorial mentioned above - just correct me if i am wrong:

There are a least two ways to use textures:

  1. input textures, where i can read from - here, i need to pass to the fragment shader the location (i.e. "u_image")
  2. output textures, where i can write to - this is the texture currently bound (in the tutorial mentioned above, to the texture unit 0)

I am not able to fully understand how this example works because the u_image uniform is not set and moreover in the code there isn't any gl.activeTexture() call

EDIT 2:

Thanks to Rabbid76 I believe I found further clarification in a comment of gman (the Author of the tutorial mentioned above) in this answer to that question:

You need the framebuffers. By attaching a texture to a framebuffer and then binding that framebuffer you're making the shader write to the texture.

1
@Rabbid76: THX, in the referenced example, the drawing destination textures are bound by using: gl.bindTexture(gl.TEXTURE_2D, textures[ii % 2]); so i guess the current texture unit is always 0 and will never change, My doubt are how the input textures works...deblocker
@Rabbid76: edited my questiondeblocker

1 Answers

1
votes
  1. input textures, where i can read from - here, i need to pass to the fragment shader the location (i.e. "u_image")

Yes, textures can be used this way.

If you want to use different textures in a fragment shader, then you have to bind the textures to different texture units. And you have to set the index of the texture unit to the texture sampler uniform variable.

The texture unit where the texture is bound to, can be set by WebGLRenderingContext.activeTexture():

var textureObj = gl.createTexture();
.....

var texUnit = 0; // texture unit 0 in this example
gl.activeTexture(gl.TEXTURE0 + texUnit);
gl.bindTexture(gl.TEXTURE_2D, textureObj);

After the program is linked (linkProgram), the location of the texture sampler uniform can be retrieved:

u_image0Location = gl.getUniformLocation(program, "u_image");

After the program has become the activ program (useProgram), the texture sampler uniform can be set:

gl.uniform1i(u_image0Location, texUnit);


  1. output textures, where i can write to - this is the texture currently bound (in the tutorial mentioned above, to the texture unit 0)

No, completely wrong. There is nothing like an output texture and for sure the texture which is bound to texture unit 0 is not the output texture.

In the fragment shader you write to gl_FragColor. The color you write to gl_FragColor is stored to the frame buffer at the fragments position.

If you wat to write to a texture, then you have to attach a texture to the frame buffer by WebGLRenderingContext.framebufferTexture2D():

var vp_w, vp_h; // withd and height of the viewport

var fbTexObj = gl.createTexture();
gl.bindTexture(gl.TEXTURE_2D, fbTexObj );
gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, vp_w, vp_h, 0, gl.RGBA, gl.UNSIGNED_BYTE, null);
.....

var fbo = gl.createFramebuffer();
gl.bindFramebuffer(gl.FRAMEBUFFER, fbo);

gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, fbTexObj, 0);

Note, when you bind (gl.bindTexture) and specify (gl.texImage2D) fbTexObj any texture unit can be active.