MENU
Image Texture
Step 1: Pass the texture coordinates to the shaders.
Include the texture coordinates in the buffer object. In the vertex shader, pass the texture coordinates to the fragment shader as varying variables. In the fragment shader, retrieve the texels (texture elements) by calling texture2D(). The texture coordinates range from (0.0,0.0) to (1.0,1.0), corresponding to the lower-left and upper-right corners.
Step 2: Create a texture object.
This is done by calling createTexture().
A texture object can be deleted by calling deleteTexture(texture).
isTexture(texture) returns true if 'texture' is a texture object.
Step 3: Get the location of the texture sampler in the fragment shader.
This is done by calling getUniformLocation(program,sampler).
Step 4: Load the image file.
Create a new Image object with 'new Image()' and specify the source with 'img.src'. Because images are loaded asynchronously, subsequent operations should be called after the image has been loaded completely. Use 'img.onload' to achieve this. The final drawing should be called only after all texture images have been loaded.
Step 5: Flip the y-axis.
Because the image coordinate system is such that greater y values lie below, you need to flip the y-axis. This is done by calling pixelStorei(pname, param) where 'pname' can be 'UNPACK_FLIP_Y_WEBGL' or 'UNPACK_PREMULTIPLY_ALPHA_WEBGL', and 'param' can be non-zero(true) or zero(false;default).
Step 6: Activate a texture unit.
This is done by calling activeTexture(texUnit), where 'texUnit' can be TEXTURE1, TEXTURE2...By default at least eight texture units are supported.
Step 7: Bind the texture object to the active texture unit.
This is done by calling bindTexture(target, texture_obj) where 'target' can be 'TEXTURE_2D' or 'TEXTURE_CUBE_MAP'.
Step 8: Assign an image in the client memory.
This is done by calling texImage2D(target, level, internalformat, format, type, image), where 'target' can be 'TEXTURE_2D' or 'TEXTURE_CUBE_MAP', level is the mipmapping level. 'internalformat' and 'format' must be the same.
After the assignment, you may choose to replace a rectangular portion of the existing texture by calling texSubImage2D(target, level, xOffset, yOffset, format, type, image). The offset subimage 'image' must not extend beyond the existing texture.
Alternatively, you may choose to assign a portion of the current framebuffer(canvas output) as the texture by calling copyTexImage2D(target, level, internalformat, x, y, width, height, 0). Similar to texSubImage2D(), copyTexSubImage2D(target, level, xoffset, yoffset, x, y, width, height) replaces a portion of the existing texture with a portion of the existing framebuffer.
internalformat/ format |
Components in a texel |
RGB | red, green, blue |
RGBA | red, green, blue, alpha |
ALPHA | 0.0, 0.0 , 0.0 , alpha |
LUMINANCE | L,L,L,1 L:luminance |
LUMINANCE_ALPHA | L,L,L, alpha |
type | description |
UNSIGNED_BYTE | Each component has 1 byte. |
UNSIGNED_SHORT_5_6_5 | RGB: each component has 5,6,5 bits respectively. |
UNSIGNED_SHORT_4_4_4_4 | RGBA: each component has 4,4,4,4 bits respectively. |
UNSIGNED_SHORT_5_5_5_1 | RGBA: each RGB component has 5 bits, and A has 1 bit. |
Step 9 : Set the texture parameters.
This is done by calling texParameteri(target,pname, param), where 'target' can be 'TEXTURE_2D' or 'TEXTURE_CUBE_MAP'.
pname | param |
TEXTURE_MAG_FILTER: magnification | NEAREST: uses the texel nearest the center of the textured pixel. LINEAR: uses the weighted average of the four texels nearest the center of the textured pixel. |
TEXTURE_MIN_FILTER: minification (NEAREST_MIPMAP_LINEAR) |
|
TEXTURE_WRAP_S: wrapping in s-axis |
REPEAT: repeats the image MIRRORED_REPEAT: repeats the image in a mirrored manner CLAMP_TO_EDGE: uses the edge color and allows non-power-of-two image sizes |
TEXTURE_WRAP_T: wrapping in t-axis |
In order for 'TEXTURE_WRAP_S' and 'TEXTURE_WRAP_T' to show their effects, the mapping texture coordinates in the fragment shader should extend beyond 1.0.
Step 10: Pass the texture unit to the shader.
This is done by calling uniform1i(samplerLocation, textureUnit).
RESETRUNFULL
//webgl-library.js
function loadTexture(gl, n, texture, u_Sampler, image, aTexture, texUnit) {
gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, 1); // Flip the y-axis
gl.activeTexture(aTexture);
gl.bindTexture(gl.TEXTURE_2D, texture);
gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, image);
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR);
gl.uniform1i(u_Sampler, texUnit);
gl.clear(gl.COLOR_BUFFER_BIT);
}
<!DOCTYPE html><html>
<head>
<script src="/shared/webgl-library.js"></script>
<script id="shader-vs" type="x-shader/x-vertex">
attribute vec4 a_Position;
attribute vec2 a_TexCoord;
varying vec2 v_TexCoord;
void main() {
gl_Position = a_Position;
v_TexCoord = a_TexCoord;
}
</script>
<script id="shader-fs" type="x-shader/x-fragment">
#ifdef GL_ES
precision mediump float;
#endif
uniform sampler2D u_Sampler0;
uniform sampler2D u_Sampler1;
varying vec2 v_TexCoord;
void main() {
vec4 c0 = texture2D(u_Sampler0, v_TexCoord);
vec4 c1 = texture2D(u_Sampler1, v_TexCoord);
gl_FragColor = c0 * c1;
}
</script>
<script type="text/javascript">
function WebGLStart() {
var canvas = document.getElementById('cv');
var gl = canvas.getContext('webgl');
initShaders(gl, "shader-vs", "shader-fs");
var n=initVertexBuffers(gl);
gl.clearColor(0.0, 0.0, 0.0, 1.0);
initTextures(gl, n);
}
function initVertexBuffers(gl) {
var verticesTexCoords = new Float32Array([ // Vertex coordinate --> Texture coordinate
-0.9, 0.9, 0.0, 1.0,
-0.9,-0.9, 0.0, 0.0,
0.9, 0.9, 1.0, 1.0,
0.9,-0.9, 1.0, 0.0,
]);
var n = 4; // The number of vertices
var vertexTexCoordBuffer = gl.createBuffer();
gl.bindBuffer(gl.ARRAY_BUFFER, vertexTexCoordBuffer);
gl.bufferData(gl.ARRAY_BUFFER, verticesTexCoords, gl.STATIC_DRAW);
var FSIZE = verticesTexCoords.BYTES_PER_ELEMENT;
var a_Position = gl.getAttribLocation(gl.program, 'a_Position');
gl.vertexAttribPointer(a_Position, 2, gl.FLOAT,false, FSIZE*4, 0);
gl.enableVertexAttribArray(a_Position);
var a_TexCoord=gl.getAttribLocation(gl.program, 'a_TexCoord');
gl.vertexAttribPointer(a_TexCoord, 2, gl.FLOAT, false, FSIZE*4, FSIZE*2);
gl.enableVertexAttribArray(a_TexCoord);
return n;
}
function initTextures(gl, n) {
var texture0 = gl.createTexture();
var texture1 = gl.createTexture();
var u_Sampler0 = gl.getUniformLocation(gl.program, 'u_Sampler0');
var u_Sampler1 = gl.getUniformLocation(gl.program, 'u_Sampler1');
var img0 = new Image();
var img1 = new Image();
img0.onload = function(){
loadTexture(gl, n, texture0, u_Sampler0, img0, gl.TEXTURE0,0);
};
img1.onload = function(){
loadTexture(gl, n, texture1, u_Sampler1, img1, gl.TEXTURE1,1);
gl.drawArrays(gl.TRIANGLE_STRIP, 0, n);
};
img0.src = '/shared/webgl_dog.jpeg';
img1.src = '/shared/webgl_circle.gif';
}
</script>
</head>
<body onload="WebGLStart();">
<canvas id="cv" style="border: none;" width="500" height="500"></canvas>
</body>
</html>