concept

Texture mapping can add skin to an image, mapping an image or image onto a geometric figure. Its function is to color each previously rasterized slice according to the texture image (the pixels that make up the texture image are also called strixels).

Texture coordinate system (left) and image coordinate system (right)

In the texture coordinate system, up is the positive direction of the Y-axis, and the picture coordinate system is the opposite

The texture coordinate system is the ideal state, the image coordinate system webGL uses when actually rendering textures. Therefore, the picture coordinate system should be used as a reference when passing geometric points and texture images to buffer objects.

Sampler type

The sampler can only be uniform variables. The only thing that can be assigned to a sampler variable is the texture unit number, which must be assigned using gl.Uniform1i ()

  • Sampler2d-2 dimensional plane sampler
  • SamplerCube – 3 – dimensional sampler
    /* fragmentShader */
    precision mediump float;
    uniform sampler2D u_sampler;
    varying vec2 v_textureCoord;
    void main() {
        gl_FragColor = texture2D(u_sampler, v_textureCoord);
    }
Copy the code

Texture unit

Webgl uses a mechanism called texture units to use multiple textures at the same time, and each texture unit has a cell number to manage a texture image. Even if the current program only needs one texture, you need to specify a texture unit for it.

The number of texture units supported by the system depends on the hardware and the browser’s WebGL implementation. By default, WebGL supports eight texture units, and some other systems support more. Built-in variables gl.texture0, GL.texture1, gl.texture2… , gl.texture7 each represents a texture unit

Texture types

  • Gl.texture_2d (2d texture)
  • Gl.texture_cube_map (cube texture)

Data format for texture data

format describe
gl.UNSIGNED_BYTE Unsigned integer, 1 byte for each color component
gl.UNSIGNED_SHORT_5_6_5 RGB: each component is 5,6,5 bits
gl.UNSIGNED_SHORT_4_4_4_4 RGBA: each component is 4,4,4,4 bits
gl.UNSIGNED_SHORT_5_5_5_1 RGBA: each component is 5,5,5,1 bit

webgl API

The name of the parameter describe
createTexture There is no Creating a texture object
activeTexture TexUnit – Specifies the texture unit Activate texture unit
bindTexture Target – Texture type

Texture – The bound texture unit
Bind texture objects
texParameteri target

pname

param
Configure texture images
texImage2D target

level

internalformat

format

type

image
Assigns a texture image to a texture object

The general process of implementing texture mapping

  • Prepare texture Image – New Image()
  • Configure texture mapping – how to place texture images on graphics
  • Load the texture image and configure it for use in WebGL
  • Remove the corresponding striene from the texture in the slice shader and assign the color of the striene to the slice

Texture mapping implementation

The effect

Start by implementing a rectangle

Add texture mapping

shader & js Code

/* Vertex shader a_pointPosition: vertex coordinates a_textureCoord: texture coordinates u_canvasSize: canvas canvas size v_textureCoord: texture coordinates passed to the pixel shader */
attribute vec2 a_pointPosition;
attribute vec2 a_textureCoord;
uniform vec2 u_canvasSize;
varying vec2 v_textureCoord;
void main() {
    float x = a_pointPosition.x;
    float y = a_pointPosition.y;

    x = x / u_canvasSize.x * 2.0 - 1.0;
    y = 1.0 - y / u_canvasSize.y * 2.0;

    gl_PointSize = 10.0;
    gl_Position = vec4(x, y, 0.0.1.0);

    v_textureCoord = a_textureCoord;
}
Copy the code
V_textureCoord: texture coordinates */
precision mediump float;
uniform sampler2D u_sampler;
varying vec2 v_textureCoord;
void main() {
    gl_FragColor = texture2D(u_sampler, v_textureCoord);
}
Copy the code
// js main logic
import WebGLProgram from '.. /gl/base.js'
import defineVertexShaderSource from './shader/vertexShader.js';
import defineFragmentShaderSource from './shader/fragmentShader.js';

import { getRandomColor } from '.. /utils/index.js'

const glProgram = new WebGLProgram({
    id: 'root',
    defineVertexShaderSource,
    defineFragmentShaderSource
});
const { gl, program } = glProgram;

const root = document.getElementById('root');

// Get the memory address of the GLSL variable
const positionLocation = gl.getAttribLocation(program, 'a_pointPosition');
const textureCoordLocation = gl.getAttribLocation(program, 'a_textureCoord')
const sizeLocation = gl.getUniformLocation(program, 'u_canvasSize');
const samplerLocation = gl.getUniformLocation(program, 'u_sampler');

// Pass the canvas canvas size into the vertex shader
gl.uniform2f(sizeLocation, root.width, root.height);

// Create a buffer object
const buffer = gl.createBuffer();
gl.bindBuffer(gl.ARRAY_BUFFER, buffer);
// Create a buffer index object
const indexBuffer = gl.createBuffer();
gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, indexBuffer);

const img = new Image();
img.src = './image/01.jpeg';

img.onload = function () {
    // Create a texture object
    const texture = gl.createTexture();
    // Activate the texture unit
    gl.activeTexture(gl.TEXTURE0);
    // Bind texture objects to the WebGL system
    gl.bindTexture(gl.TEXTURE_2D, texture);
    // Configures the way the texture image is mapped to the graph (zoom in, zoom out, stretch)
    gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.NEAREST);
    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);
    // Assign the texture image to the texture object
    gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, img);
    // Pass the number of the texture unit to the slice shader
    gl.uniform1i(samplerLocation, 0);

    render();
}

// Render function
function render() {
    // Populate the vertex buffer with data
    gl.bufferData(
        gl.ARRAY_BUFFER,
        new Float32Array([
            50.50.0.0.50.300.0.1.400.300.1.1.400.50.1.0,
        ]),
        gl.STATIC_DRAW
    );

    // Populate the index buffer with data
    gl.bufferData(
        gl.ELEMENT_ARRAY_BUFFER,
        new Uint16Array([
            0.1.3.2
        ]),
        gl.STATIC_DRAW
    )
    // Specifies the mapping between the data in the buffer object and the vertex variables
    gl.vertexAttribPointer(positionLocation, 2, gl.FLOAT, false.4 * 4.0);
    // Specify the mapping between data and texture variables in the buffer object
    gl.vertexAttribPointer(textureCoordLocation, 2, gl.FLOAT, false.4 * 4.4 * 2);
    // Enable variables
    gl.enableVertexAttribArray(positionLocation);
    gl.enableVertexAttribArray(textureCoordLocation);
    // Draw a rectangle with a triangle fan
    gl.drawElements(gl.TRIANGLE_STRIP, 4, gl.UNSIGNED_SHORT, 0);
}
Copy the code