乐闻世界logo
搜索文章和话题

How to use textures in WebGL? What texture parameters need to be configured?

3月6日 21:57

WebGL Texture Overview

Textures in WebGL are images used to add surface details to 3D objects. Through texture mapping, 2D images can be applied to 3D geometry surfaces, making rendering results more realistic.

Texture Usage Process

1. Create Texture Object

javascript
const texture = gl.createTexture();

2. Bind Texture

javascript
// Bind to 2D texture target gl.bindTexture(gl.TEXTURE_2D, texture);

3. Upload Texture Data

javascript
// Method 1: Load from Image object gl.texImage2D( gl.TEXTURE_2D, // Target 0, // Level of detail (mipmap level) gl.RGBA, // Internal format gl.RGBA, // Source format gl.UNSIGNED_BYTE, // Data type image // Image object ); // Method 2: Upload pixel data directly gl.texImage2D( gl.TEXTURE_2D, 0, gl.RGBA, width, // Width height, // Height 0, // Border (must be 0) gl.RGBA, gl.UNSIGNED_BYTE, pixels // Uint8Array pixel data );

4. Configure Texture Parameters

javascript
// Texture wrapping 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); // Texture filtering gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR); gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR);

5. Generate Mipmap (Optional)

javascript
gl.generateMipmap(gl.TEXTURE_2D);

Texture Parameters Explained

Texture Wrapping

Controls behavior when texture coordinates exceed [0, 1] range:

ParameterDescription
gl.REPEATRepeat texture (default)
gl.CLAMP_TO_EDGEExtend edge pixels
gl.MIRRORED_REPEATMirror repeat
javascript
// S axis (horizontal) gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.REPEAT); // T axis (vertical) gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);

Visual effects:

shell
REPEAT: CLAMP_TO_EDGE: MIRRORED_REPEAT: |ABCD|ABCD| |AAAA|ABCD|DDDD| |ABCD|DCBA|ABCD| |ABCD|ABCD| |AAAA|ABCD|DDDD| |ABCD|DCBA|ABCD|

Texture Filtering

Controls interpolation method during texture sampling:

Magnification Filter (MAG_FILTER)

When texture is magnified (texture pixels < screen pixels):

ParameterDescription
gl.NEARESTNearest neighbor sampling, pixelated effect
gl.LINEARBilinear interpolation, smooth effect (recommended)

Minification Filter (MIN_FILTER)

When texture is minified (texture pixels > screen pixels):

ParameterDescription
gl.NEARESTNearest neighbor sampling
gl.LINEARBilinear interpolation
gl.NEAREST_MIPMAP_NEARESTNearest mipmap + nearest sampling
gl.LINEAR_MIPMAP_NEARESTNearest mipmap + linear interpolation
gl.NEAREST_MIPMAP_LINEARLinear between mipmaps + nearest sampling
gl.LINEAR_MIPMAP_LINEARTrilinear filtering (highest quality)
javascript
// Use linear filtering for magnification gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR); // Use trilinear mipmap filtering for minification gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR_MIPMAP_LINEAR);

Complete Texture Loading Example

javascript
function loadTexture(gl, url) { const texture = gl.createTexture(); gl.bindTexture(gl.TEXTURE_2D, texture); // Set temporary pixel (used before image loads) const level = 0; const internalFormat = gl.RGBA; const width = 1; const height = 1; const border = 0; const srcFormat = gl.RGBA; const srcType = gl.UNSIGNED_BYTE; const pixel = new Uint8Array([0, 0, 255, 255]); // Blue gl.texImage2D(gl.TEXTURE_2D, level, internalFormat, width, height, border, srcFormat, srcType, pixel); const image = new Image(); image.onload = function() { gl.bindTexture(gl.TEXTURE_2D, texture); gl.texImage2D(gl.TEXTURE_2D, level, internalFormat, srcFormat, srcType, image); // Check if image dimensions are power of 2 if (isPowerOf2(image.width) && isPowerOf2(image.height)) { // Power of 2, can use mipmap gl.generateMipmap(gl.TEXTURE_2D); gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR_MIPMAP_LINEAR); } else { // Not power of 2, disable mipmap, set wrap to CLAMP_TO_EDGE 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); gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR); } gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR); }; image.src = url; return texture; } function isPowerOf2(value) { return (value & (value - 1)) == 0; }

Using Textures in Shaders

Vertex Shader

glsl
attribute vec3 a_position; attribute vec2 a_texCoord; uniform mat4 u_mvpMatrix; varying vec2 v_texCoord; void main() { gl_Position = u_mvpMatrix * vec4(a_position, 1.0); v_texCoord = a_texCoord; // Pass texture coordinates to fragment shader }

Fragment Shader

glsl
precision mediump float; varying vec2 v_texCoord; uniform sampler2D u_texture; // Texture sampler void main() { gl_FragColor = texture2D(u_texture, v_texCoord); }

JavaScript Code

javascript
// Activate texture unit gl.activeTexture(gl.TEXTURE0); // Bind texture gl.bindTexture(gl.TEXTURE_2D, texture); // Set uniform variable (tell shader which texture unit to use) gl.uniform1i(textureLocation, 0); // Use TEXTURE0

Multiple Texture Binding

javascript
// Load multiple textures const texture1 = loadTexture(gl, 'texture1.jpg'); const texture2 = loadTexture(gl, 'texture2.png'); // Bind to different texture units during rendering gl.activeTexture(gl.TEXTURE0); gl.bindTexture(gl.TEXTURE_2D, texture1); gl.uniform1i(texture1Location, 0); gl.activeTexture(gl.TEXTURE1); gl.bindTexture(gl.TEXTURE_2D, texture2); gl.uniform1i(texture2Location, 1);
glsl
// Using multiple textures in fragment shader uniform sampler2D u_texture1; uniform sampler2D u_texture2; varying vec2 v_texCoord; void main() { vec4 color1 = texture2D(u_texture1, v_texCoord); vec4 color2 = texture2D(u_texture2, v_texCoord); gl_FragColor = mix(color1, color2, 0.5); // Blend two textures }

Texture Coordinate System

shell
(0, 1) -------- (1, 1) | | | Texture Image | | | (0, 0) -------- (1, 0)

Note: WebGL texture coordinate system origin is at bottom-left, while most image formats have origin at top-left.

Performance Optimization Tips

  1. Use Texture Atlas: Combine multiple small textures into one large texture to reduce binding switches
  2. Choose appropriate texture sizes:
    • Prefer power-of-2 dimensions (supports mipmap)
    • Don't use overly large textures (memory and bandwidth overhead)
  3. Use compressed texture formats: such as DXT, ETC, PVRTC
  4. Enable mipmap: Improves rendering quality and performance
  5. Reuse textures: Avoid loading the same texture multiple times
标签:WebGL