Skip to content

WebGL基础入门

案例教程[https://threelab.cn/openthree/#/codeMirror?navigation=WebGL&classify=base&id=Triangle]

一、WebGL的工作原理

(一)渲染管线概述

WebGL的渲染管线是将3D模型转换为2D图像的过程,这个过程可以分为几个主要阶段:

  1. 顶点处理

    • 顶点数据输入:顶点数据(如位置、颜色、纹理坐标等)被输入到顶点着色器。
    • 顶点着色器(Vertex Shader):顶点着色器对每个顶点进行处理,可以进行变换(如平移、旋转、缩放)、光照计算等操作。顶点着色器的输出是变换后的顶点位置和一些附加数据(如颜色、纹理坐标等)。
    • 图元装配(Primitive Assembly):将顶点组装成图元(如点、线、三角形)。
    • 裁剪(Clipping):将超出视口范围的图元裁剪掉。
    • 屏幕映射(Screen Mapping):将裁剪后的图元映射到屏幕坐标系中。
  2. 光栅化(Rasterization)

    • 片元生成:将图元分解为片元(Fragment),每个片元对应屏幕上的一个像素。
    • 片元着色器(Fragment Shader):片元着色器对每个片元进行处理,计算最终的像素颜色。可以进行纹理映射、光照计算等操作。
    • 深度测试(Depth Testing):确定片元是否被前面的物体遮挡,只有通过深度测试的片元才会被渲染到屏幕上。
    • 混合(Blending):将片元的颜色与帧缓冲区(Frame Buffer)中对应像素的颜色进行混合,最终生成屏幕上的像素颜色。

(二)顶点着色器和片元着色器的作用

  • 顶点着色器(Vertex Shader)

    • 输入:顶点数据(如位置、颜色、纹理坐标等)。
    • 处理:对每个顶点进行变换(如平移、旋转、缩放)、光照计算等操作。
    • 输出:变换后的顶点位置和一些附加数据(如颜色、纹理坐标等)。
    • 示例代码
      glsl
      attribute vec4 a_position; // 顶点位置
      attribute vec4 a_color;    // 顶点颜色
      varying vec4 v_color;      // 传递给片元着色器的颜色
      
      void main() {
          gl_Position = a_position; // 设置顶点位置
          v_color = a_color;        // 传递颜色到片元着色器
      }
  • 片元着色器(Fragment Shader)

    • 输入:顶点着色器传递过来的数据(如颜色、纹理坐标等)。
    • 处理:对每个片元进行处理,计算最终的像素颜色。可以进行纹理映射、光照计算等操作。
    • 输出:最终的像素颜色。
    • 示例代码
      glsl
      precision mediump float; // 精度声明
      varying vec4 v_color;    // 从顶点着色器接收的颜色
      
      void main() {
          gl_FragColor = v_color; // 设置片元颜色
      }

二、WebGL上下文

(一)获取WebGL上下文

要使用WebGL,首先需要获取WebGL上下文。这可以通过HTML中的<canvas>元素来实现。以下是一个简单的示例代码:

html
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>WebGL Example</title>
</head>
<body>
    <canvas id="webglCanvas" width="800" height="600"></canvas>
    <script>
        // 获取canvas元素
        const canvas = document.getElementById('webglCanvas');
        // 获取WebGL上下文
        const gl = canvas.getContext('webgl') || canvas.getContext('experimental-webgl');

        if (!gl) {
            alert('Your browser does not support WebGL');
        } else {
            console.log('WebGL context obtained');
        }
    </script>
</body>
</html>

(二)创建一个简单的WebGL程序

以下是一个完整的示例,展示如何创建一个简单的WebGL程序,绘制一个三角形:

html
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>WebGL Triangle Example</title>
</head>
<body>
    <canvas id="webglCanvas" width="800" height="600"></canvas>
    <script>
        // 获取canvas元素
        const canvas = document.getElementById('webglCanvas');
        // 获取WebGL上下文
        const gl = canvas.getContext('webgl') || canvas.getContext('experimental-webgl');

        if (!gl) {
            alert('Your browser does not support WebGL');
        }

        // 顶点着色器代码
        const vertexShaderSource = `
            attribute vec4 a_position;
            void main() {
                gl_Position = a_position;
            }
        `;

        // 片元着色器代码
        const fragmentShaderSource = `
            precision mediump float;
            void main() {
                gl_FragColor = vec4(1.0, 0.0, 0.0, 1.0); // 红色
            }
        `;

        // 创建顶点着色器
        const vertexShader = gl.createShader(gl.VERTEX_SHADER);
        gl.shaderSource(vertexShader, vertexShaderSource);
        gl.compileShader(vertexShader);

        // 创建片元着色器
        const fragmentShader = gl.createShader(gl.FRAGMENT_SHADER);
        gl.shaderSource(fragmentShader, fragmentShaderSource);
        gl.compileShader(fragmentShader);

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

        if (!gl.getProgramParameter(program, gl.LINK_STATUS)) {
            alert('Unable to initialize the shader program: ' + gl.getProgramInfoLog(program));
        }

        // 使用程序
        gl.useProgram(program);

        // 定义顶点数据
        const positions = [
            0.0, 0.5, 0.0, // 顶点1
            -0.5, -0.5, 0.0, // 顶点2
            0.5, -0.5, 0.0  // 顶点3
        ];

        // 创建缓冲区
        const positionBuffer = gl.createBuffer();
        gl.bindBuffer(gl.ARRAY_BUFFER, positionBuffer);
        gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(positions), gl.STATIC_DRAW);

        // 绑定顶点属性
        const positionLocation = gl.getAttribLocation(program, 'a_position');
        gl.enableVertexAttribArray(positionLocation);
        gl.vertexAttribPointer(positionLocation, 3, gl.FLOAT, false, 0, 0);

        // 清空画布
        gl.clearColor(0.0, 0.0, 0.0, 1.0); // 设置背景颜色为黑色
        gl.clear(gl.COLOR_BUFFER_BIT);

        // 绘制三角形
        gl.drawArrays(gl.TRIANGLES, 0, 3);
    </script>
</body>
</html>

三、Canvas元素

(一)在HTML中使用<canvas>元素

<canvas>元素是HTML5引入的一个用于绘图的元素,它提供了一个矩形区域,可以在其上进行图形绘制。<canvas>元素本身并不提供绘图功能,而是通过JavaScript来操作。

html
<canvas id="webglCanvas" width="800" height="600"></canvas>
  • id属性:用于通过JavaScript获取该元素。
  • widthheight属性:定义了<canvas>的大小。

(二)设置WebGL上下文

通过getContext方法获取WebGL上下文。getContext方法的参数可以是'webgl''experimental-webgl',后者用于兼容较旧的浏览器。

javascript
const canvas = document.getElementById('webglCanvas');
const gl = canvas.getContext('webgl') || canvas.getContext('experimental-webgl');

if (!gl) {
    alert('Your browser does not support WebGL');
}

通过这种方式,你可以在<canvas>元素上创建一个WebGL上下文,然后使用WebGL的API进行3D图形的绘制。

总结

WebGL是一种强大的3D图形技术,通过HTML的<canvas>元素和JavaScript的API,可以在网页中实现复杂的3D图形渲染。了解WebGL的渲染管线、顶点着色器和片元着色器的作用,以及如何获取WebGL上下文和创建简单的WebGL程序,是学习WebGL的基础。通过这些知识,你可以开始探索更复杂的3D图形应用。

Theme by threelab