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