返回

WebGL纹理转换:掌控你画布的视界

前端

准备好在WebGL世界中释放你的创造力了吗?纹理变换是让你的场景生机勃勃的必备技巧。从简单的旋转和缩放,到复杂的透视投影,本文将引导你领略WebGL纹理变换的奥秘,帮助你在画布上创造令人惊叹的视觉效果。

基础知识:顶点着色器和片元着色器

在WebGL中,纹理变换是通过顶点着色器和片元着色器实现的。顶点着色器负责处理顶点(对象的构建基块)的位置和属性,而片元着色器则控制着每个像素的最终外观。

纹理坐标:为纹理赋予生命

为了应用纹理,你需要为每个顶点指定纹理坐标。这些坐标决定了纹理图像中对应每个顶点的位置。通过操纵纹理坐标,你可以实现旋转、缩放和平移等纹理变换。

创建顶点数组对象和绑定它

为了存储和操作顶点数据,你需要创建一个顶点数组对象(VAO)。VAO将顶点位置、颜色、法线和其他属性绑定在一起。在渲染之前,你需要使用 createVertexArray()bindVertexArray() 函数创建和绑定VAO。

创建缓冲区对象并绑定它

缓冲区对象(VBO)用于存储顶点数据。你可以使用 createBuffer()bindBuffer() 函数创建和绑定一个VBO。然后,可以使用 bufferData() 函数将顶点数据上传到VBO。

指定顶点属性:纹理坐标

使用 vertexAttribPointer() 函数,你可以指定VBO中纹理坐标的格式和偏移量。这将告诉WebGL如何从VBO中读取纹理坐标。

矩阵的力量:平移、旋转和缩放

通过使用变换矩阵,你可以平移、旋转和缩放纹理。变换矩阵本质上是4x4矩阵,它包含控制变换操作的元素。

  • 平移: translate() 函数接受一个x、y和z值,用于移动对象。
  • 旋转: rotate() 函数接受一个旋转角度和一个轴向量,用于旋转对象。
  • 缩放: scale() 函数接受一个x、y和z值,用于缩放对象。

透视投影:带来深度的幻觉

透视投影用于创建3D效果的错觉。它将3D场景投影到2D画布上,使对象看起来更近或更远。使用 perspective() 函数可以设置透视投影矩阵。

示例代码:旋转纹理

以下是旋转纹理的示例代码:

// 创建顶点着色器
const vertexShader = `
    attribute vec2 a_position;
    attribute vec2 a_texCoord;

    varying vec2 v_texCoord;

    void main() {
        gl_Position = vec4(a_position, 0.0, 1.0);
        v_texCoord = a_texCoord;
    }
`;

// 创建片元着色器
const fragmentShader = `
    precision mediump float;

    varying vec2 v_texCoord;

    uniform sampler2D u_texture;

    void main() {
        gl_FragColor = texture2D(u_texture, v_texCoord);
    }
`;

// 创建WebGL程序
const program = gl.createProgram();
gl.attachShader(program, vertexShader);
gl.attachShader(program, fragmentShader);
gl.linkProgram(program);
gl.useProgram(program);

// 创建顶点数据
const vertices = [
    -1.0, -1.0,  0.0, 0.0,
     1.0, -1.0,  1.0, 0.0,
     1.0,  1.0,  1.0, 1.0,
    -1.0,  1.0,  0.0, 1.0,
];

// 创建缓冲区对象
const vertexBuffer = gl.createBuffer();
gl.bindBuffer(gl.ARRAY_BUFFER, vertexBuffer);
gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(vertices), gl.STATIC_DRAW);

// 创建顶点数组对象
const vertexArray = gl.createVertexArray();
gl.bindVertexArray(vertexArray);

// 启用顶点属性
const positionAttributeLocation = gl.getAttribLocation(program, "a_position");
gl.enableVertexAttribArray(positionAttributeLocation);
gl.vertexAttribPointer(positionAttributeLocation, 2, gl.FLOAT, false, 16, 0);

const texCoordAttributeLocation = gl.getAttribLocation(program, "a_texCoord");
gl.enableVertexAttribArray(texCoordAttributeLocation);
gl.vertexAttribPointer(texCoordAttributeLocation, 2, gl.FLOAT, false, 16, 8);

// 加载纹理
const texture = gl.createTexture();
gl.bindTexture(gl.TEXTURE_2D, texture);
gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, image);

// 旋转纹理
const rotationMatrix = mat4.create();
mat4.rotateZ(rotationMatrix, rotationMatrix, -0.01);

// 设置变换矩阵
const uniformRotationMatrixLocation = gl.getUniformLocation(program, "u_rotationMatrix");
gl.uniformMatrix4fv(uniformRotationMatrixLocation, false, rotationMatrix);

// 绘制纹理
gl.drawArrays(gl.TRIANGLE_FAN, 0, 4);

结论

通过掌握纹理变换的艺术,你可以将你的WebGL场景提升到一个全新的水平。利用顶点着色器、片元着色器、矩阵和透视投影的力量,你可以创造出动态的、交互式的图像,让你的用户惊叹不已。