返回

让你的浏览器给图片贴上纹理,WebGL轻松实现图片显示

前端

WebGL,全称 Web Graphics Library,是一个 JavaScript API,用于在浏览器中呈现交互式 3D 图形。WebGL 广泛应用于游戏、可视化和虚拟现实等领域。

在上一节中,我们已经学会了绘制具有渐变色的三角形。本节中,我们将继续为三角形的顶点增加纹理坐标信息,从而使用图片作为纹理来显示图片。

纹理映射

纹理映射是图形学中的一种技术,用于将纹理(例如图片)应用到三维模型的表面上。纹理映射可以使模型看起来更加逼真和细节丰富。

在 WebGL 中,纹理映射可以通过纹理坐标来实现。纹理坐标是一组数字,用于指定纹理在模型表面上的位置和大小。纹理坐标的范围通常为 0 到 1,其中 0 表示纹理的左上角,1 表示纹理的右下角。

实现图片显示

为了在 WebGL 中显示图片,我们需要执行以下步骤:

  1. 加载图片。
  2. 创建纹理对象。
  3. 将图片数据上传到纹理对象。
  4. 为三角形添加纹理坐标信息。
  5. 在着色器中使用纹理坐标信息。
  6. 绘制三角形。

加载图片

图片可以通过 HTML 的 <img> 标签来加载。

<img id="image" src="image.png">

创建纹理对象

纹理对象可以通过 WebGL 的 createTexture() 函数来创建。

var texture = gl.createTexture();

将图片数据上传到纹理对象

图片数据可以通过 WebGL 的 texImage2D() 函数来上传到纹理对象。

gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, image);

为三角形添加纹理坐标信息

纹理坐标信息可以通过 WebGL 的 texCoordPointer() 函数来添加。

gl.texCoordPointer(2, gl.FLOAT, 0, textureCoordinates);

在着色器中使用纹理坐标信息

纹理坐标信息可以在着色器中使用 texture2D() 函数来使用。

var color = texture2D(texture, textureCoordinates);

绘制三角形

三角形可以通过 WebGL 的 drawArrays() 函数来绘制。

gl.drawArrays(gl.TRIANGLES, 0, 3);

完整代码

完整的代码如下所示:

<!DOCTYPE html>
<html>
<head>
  
</head>
<body>
  <canvas id="canvas" width="500" height="500"></canvas>

  <script>
    var gl = canvas.getContext("webgl");

    // 加载图片
    var image = new Image();
    image.onload = function() {
      // 创建纹理对象
      var texture = gl.createTexture();

      // 将图片数据上传到纹理对象
      gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, image);

      // 为三角形添加纹理坐标信息
      var textureCoordinates = [
        0.0, 0.0,
        1.0, 0.0,
        0.0, 1.0
      ];
      gl.texCoordPointer(2, gl.FLOAT, 0, textureCoordinates);

      // 在着色器中使用纹理坐标信息
      var vertexShaderSource = `
        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;
        }
      `;
      var fragmentShaderSource = `
        precision mediump float;

        uniform sampler2D u_texture;
        varying vec2 v_texCoord;

        void main() {
          gl_FragColor = texture2D(u_texture, v_texCoord);
        }
      `;
      var vertexShader = gl.createShader(gl.VERTEX_SHADER);
      gl.shaderSource(vertexShader, vertexShaderSource);
      gl.compileShader(vertexShader);
      var fragmentShader = gl.createShader(gl.FRAGMENT_SHADER);
      gl.shaderSource(fragmentShader, fragmentShaderSource);
      gl.compileShader(fragmentShader);
      var program = gl.createProgram();
      gl.attachShader(program, vertexShader);
      gl.attachShader(program, fragmentShader);
      gl.linkProgram(program);
      gl.useProgram(program);

      // 绘制三角形
      var positionBuffer = gl.createBuffer();
      gl.bindBuffer(gl.ARRAY_BUFFER, positionBuffer);
      var positions = [
        -1.0, -1.0,
        1.0, -1.0,
        -1.0, 1.0
      ];
      gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(positions), gl.STATIC_DRAW);
      var positionAttributeLocation = gl.getAttribLocation(program, "a_position");
      gl.enableVertexAttribArray(positionAttributeLocation);
      gl.vertexAttribPointer(positionAttributeLocation, 2, gl.FLOAT, false, 0, 0);

      var textureBuffer = gl.createBuffer();
      gl.bindBuffer(gl.ARRAY_BUFFER, textureBuffer);
      gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(textureCoordinates), gl.STATIC_DRAW);
      var textureAttributeLocation = gl.getAttribLocation(program, "a_texCoord");
      gl.enableVertexAttribArray(textureAttributeLocation);
      gl.vertexAttribPointer(textureAttributeLocation, 2, gl.FLOAT, false, 0, 0);

      gl.drawArrays(gl.TRIANGLES, 0, 3);
    };
    image.src = "image.png";
  </script>
</body>
</html>

运行示例

将上述代码保存为 HTML 文件,然后在浏览器中打开即可看到效果。

本节中,我们学习了如何利用 WebGL 为三角形添加纹理坐标信息,并使用图片作为纹理来显示图片。