跳到主要内容

WebGL 基础入门

什么是 WebGL​

WebGL 是一种 3D 绘图协议,衍生于 OpenGL ES2.0,可以结合 Html5 和 JS 在网页上绘制二维或三维的图形。浏览器可以直接运行 WebGL 程序,使用比较简单

实现的功能:

框架:

  • Three.js:JS 3D webgl 库
  • Babylon.js: web3D 图形引擎
  • kickjs;Web 的开源图形引擎和游戏引擎
  • ClayGL:构建可扩展的 Web3D 应用程序
  • PlayCanvas:网络游戏和 3D 图形引擎
  • Luma:Uber 的 3D WebGL 可视化库
  • A-Frame:用于构建 VR 体验的 Web 框架

使用 WebGL​

创建 Canvas 程序​

canvas

import { useEffect } from "react";

function App() {

  useEffect(() => {
    const canvas = document.getElementById("canvas");
    const ctx = canvas.getContext("2d");

    ctx.fillStyle = "red";
    ctx.fillRect(10, 10, 100, 100);
  }, [])

  return <canvas id="canvas" width="400" height="200"></canvas>
}

export default App;
预览

创建 WebGL 程序​

import { useEffect } from "react";

function App() {

  useEffect(() => {
    const canvas = document.querySelector("#glcanvas");
  // 初始化 WebGL 上下文
    const gl = canvas.getContext("webgl");

    // 确认 WebGL 支持性
    if (!gl) {
      alert("无法初始化 WebGL,你的浏览器、操作系统或硬件等可能不支持 WebGL。");
      return;
    }

    // 使用完全不透明的黑色清除所有图像
    gl.clearColor(1.0, 0.0, 0.0, 1.0);
    // 用上面指定的颜色清除缓冲区
    gl.clear(gl.COLOR_BUFFER_BIT);
  }, []);

  return <canvas id="glcanvas" width="100" height="100"></canvas>
}

export default App;
预览

绘制一个点​

绘制流程如下

webgl 程序运行流程

import { useEffect } from "react";

function App() {

  useEffect(() => {
    const canvas = document.querySelector("#glcanvas");
    // 初始化 WebGL 上下文
    const gl = canvas.getContext("webgl");

    // 1. 定义着色器代码
    // 顶点着色器代码
    const vertexShaderSource = `
      void main() {
        // 定义坐标 x y z w,结果等于 x/w y/w z/w
        gl_Position = vec4(0.0, 0.0, 0.0, 1.0);
        // 定义顶点大小
        gl_PointSize = 30.0;
      }
    `;
    // 片元着色器代码
    const fragmentShaderSource = `
      void main() {
        // 定义颜色值
        gl_FragColor = vec4(1.0, 0.0, 0.0, 1.0);
      }
    `;
    // 2. 创建着色器
    const vertexShader = gl.createShader(gl.VERTEX_SHADER);
    const fragmentShader = gl.createShader(gl.FRAGMENT_SHADER);

    // 3. 关联着色器与源码
    gl.shaderSource(vertexShader, vertexShaderSource);
    gl.shaderSource(fragmentShader, fragmentShaderSource);

    // 4. 编译着色器
    gl.compileShader(vertexShader);
    gl.compileShader(fragmentShader);

    // 5. 创建程序对象
    const program = gl.createProgram();

    // 6. 关联着色器与程序对象
    gl.attachShader(program, vertexShader);
    gl.attachShader(program, fragmentShader);
    gl.linkProgram(program);

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

    // 8. 绘制图行
    gl.drawArrays(gl.POINTS, 0, 1);
  }, []);

  return <canvas id="glcanvas" width="200" height="200" style={{ backgroundColor: "#666" }}></canvas>
}

export default App;
预览

可以将初始化着色器相关代码抽离出来

function initShader(gl, vertexShaderSource, fragmentShaderSource) {
// 创建着色器
const vertexShader = gl.createShader(gl.VERTEX_SHADER);
const fragmentShader = gl.createShader(gl.FRAGMENT_SHADER);

// 关联着色器与源码
gl.shaderSource(vertexShader, vertexShaderSource);
gl.shaderSource(fragmentShader, fragmentShaderSource);

// 编译着色器
gl.compileShader(vertexShader);
gl.compileShader(fragmentShader);

// 创建程序对象
const program = gl.createProgram();

// 关联着色器与程序对象
gl.attachShader(program, vertexShader);
gl.attachShader(program, fragmentShader);
gl.linkProgram(program);

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

return program;
}

坐标系​

canvas API 绘制用的是 2D 坐标系,只有 x 和 y 轴,中心点在 canvas 画布的左上角

二维坐标修

webgl API 绘制用的是 3D 坐标系,中心点在 canvas 画布的正中心

Alt text

画布关健坐标点的的信息,如下

Alt text