Textures in WebGL shaders
Above, you should see a square displaying red and green in a checkerboard pattern.
It is heavily blurred, because it shows a 2x2 checkerboard scaled up to 200x200 pixels.
This image is created using WebGL.
The 2x2 checkerboard is a tiny WebGL “texture”,
created in JavaScript, then uploaded to the graphics driver.
The fragment shader then accesses the texture,
indexing into it with the position of the fragment.
The texture is configured with its magnification filter set to gl.LINEAR
,
which causes the blurring.
Here is our fragment shader.
The function texture2D
samples from a texture.
That is, it takes a texture and a coordinate,
and gives you the color of the texture at that coordinate.
Note its second parameter treats the texture as entirely within the unit square!
We therefore map our 200x200 clip space down to the unit square.
uniform sampler2D smplr;
void main(void) {
gl_FragColor = texture2D(smplr, vec2(gl_FragCoord.x/200.0, gl_FragCoord.y/200.0));
}
In JavaScript, we create the texture from a Uint8Array
of RGBA pixels:
gl.activeTexture(gl.TEXTURE0); // We only have one texture in this program
var tex = gl.createTexture();
gl.bindTexture(gl.TEXTURE_2D, tex); // TEXTURE0 is now `tex`
gl.texImage2D( // upload a checkerboard pattern to `tex`
gl.TEXTURE_2D,
0, // level
gl.RGBA, // internal format
2, // width
2, // height
0, // border
gl.RGBA, // format
gl.UNSIGNED_BYTE, // type
new Uint8Array([
255, 0, 0, 255,
0, 255, 0, 255,
0, 255, 0, 255,
255, 0, 0, 255,
])
);
If you try to use this texture, WebGL will complain that the texture is unrenderable! It’s badly documented, but you need to set some parameters for the texture:
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR);
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);
Before we draw something with our shader program prog
,
we need to set its smplr
uniform variable to refer to this uploaded texture:
const samplerLoc = gl.getUniformLocation(prog, "smplr");
gl.uniform1i(samplerLoc, 0); // Note 0, not gl.TEXTURE0
Then, when we draw stuff, the fragment shader will consult our texture, and draw its checkerboard pattern.
Tagged . All content copyright James Fisher 2017. This post is not associated with my employer.