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).

Instead of simply attaching one texture, this example illustrates how to merge two textures, resulting in a circular view.
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>