初探WebGL 和 Three.js

前言:      

      在学习前端开发的过程中,曾经听说过 WebGL 和 Three.js ,但是由于工作相关业务极少涉及,因为还未用过,现在有点时间,决定来对他们进行一个初步了解。

      它们都是用于在网页上绘制 3D 图形的技术,但它们之间有很大的区别,首先我们来了解下他们分别是什么。

什么是 WebGL?

WebGL(Web Graphics Library) 是一种 JavaScript API,用于在 HTML5 <canvas> 元素上绘制 2D 和 3D 图形。WebGL 直接与计算机的 GPU(图形处理器)进行交互,这使得它非常强大,但也很复杂。

特点:

  • 低级别:WebGL 是一个底层 API,需要开发者编写大量代码来处理图形的各个方面。
  • 高性能:直接与 GPU 交互,可以实现高效的图形渲染。
  • 灵活性:提供了对图形渲染过程的全面控制。

什么是 Three.js?

Three.js 是一个基于 WebGL 的 JavaScript 库,它封装了 WebGL 的复杂性,提供了更高级别的 API,使开发者能够更容易地创建和显示 3D 图形。

特点:

  • 高级别:Three.js 封装了 WebGL 的复杂操作,使得创建 3D 场景变得简单。
  • 易用性:提供了大量预定义的几何体、材质、光源等,降低了开发难度。
  • 功能丰富:支持动画、物理、加载 3D 模型等功能。

WebGL 与 Three.js 的对比

1. 抽象层次
  • WebGL:作为底层 API,WebGL 提供了直接与 GPU 交互的能力。这意味着你需要编写大量代码来初始化上下文、创建缓冲区、编写着色器(Shader)等。这对初学者来说,学习曲线较陡。

  • Three.js:作为高级库,Three.js 封装了许多复杂的细节,使得 3D 图形的创建变得更加简单和直观。你只需调用几个函数,就可以创建和操作 3D 对象。

2. 初始化过程

WebGL 示例代码:

<!DOCTYPE html>
<html>
<head>
  <title>WebGL 示例</title>
</head>
<body>
  <canvas id="webgl-canvas" width="500" height="500"></canvas>
  <script>
    const canvas = document.getElementById('webgl-canvas');
    const gl = canvas.getContext('webgl');

    if (!gl) {
      console.error('WebGL not supported');
      throw 'WebGL not supported';
    }

    // 定义顶点着色器
    const vsSource = `
      attribute vec4 aVertexPosition;
      void main(void) {
        gl_Position = aVertexPosition;
      }
    `;

    // 定义片段着色器
    const fsSource = `
      void main(void) {
        gl_FragColor = vec4(1.0, 0.0, 0.0, 1.0);
      }
    `;

    // 创建和编译着色器
    function loadShader(gl, type, source) {
      const shader = gl.createShader(type);
      gl.shaderSource(shader, source);
      gl.compileShader(shader);
      if (!gl.getShaderParameter(shader, gl.COMPILE_STATUS)) {
        console.error('An error occurred compiling the shaders: ' + gl.getShaderInfoLog(shader));
        gl.deleteShader(shader);
        return null;
      }
      return shader;
    }

    const vertexShader = loadShader(gl, gl.VERTEX_SHADER, vsSource);
    const fragmentShader = loadShader(gl, gl.FRAGMENT_SHADER, fsSource);

    // 创建着色器程序
    const shaderProgram = gl.createProgram();
    gl.attachShader(shaderProgram, vertexShader);
    gl.attachShader(shaderProgram, fragmentShader);
    gl.linkProgram(shaderProgram);

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

    // 使用着色器程序
    gl.useProgram(shaderProgram);

    // 定义顶点位置
    const vertices = new Float32Array([
      1.0,  1.0,
     -1.0,  1.0,
      1.0, -1.0,
     -1.0, -1.0,
    ]);

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

    // 将顶点数据传递给着色器
    const vertexPosition = gl.getAttribLocation(shaderProgram, 'aVertexPosition');
    gl.enableVertexAttribArray(vertexPosition);
    gl.vertexAttribPointer(vertexPosition, 2, gl.FLOAT, false, 0, 0);

    // 绘制图形
    gl.clearColor(0.0, 0.0, 0.0, 1.0);
    gl.clear(gl.COLOR_BUFFER_BIT);
    gl.drawArrays(gl.TRIANGLE_STRIP, 0, 4);
  </script>
</body>
</html>

Three.js 示例代码:

<!DOCTYPE html>
<html>
<head>
  <title>Three.js 示例</title>
  <style>
    body { margin: 0; }
  </style>
</head>
<body>
  <script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/r128/three.min.js"></script>
  <script>
    // 创建场景
    const scene = new THREE.Scene();
    const camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 1000);
    const renderer = new THREE.WebGLRenderer();
    renderer.setSize(window.innerWidth, window.innerHeight);
    document.body.appendChild(renderer.domElement);

    // 创建立方体
    const geometry = new THREE.BoxGeometry();
    const material = new THREE.MeshBasicMaterial({ color: 0x00ff00 });
    const cube = new THREE.Mesh(geometry, material);
    scene.add(cube);

    camera.position.z = 5;

    // 渲染场景
    function animate() {
      requestAnimationFrame(animate);
      cube.rotation.x += 0.01;
      cube.rotation.y += 0.01;
      renderer.render(scene, camera);
    }
    animate();
  </script>
</body>
</html>
3. 着色器编程
  • WebGL:需要手动编写顶点着色器和片段着色器,使用 GLSL 语言。需要深入了解图形学知识。
  • Three.js:提供了多种材质和着色器,可以直接使用,无需手动编写 GLSL 代码。
4. 状态管理
  • WebGL:需要手动管理图形渲染状态,如绑定缓冲区、启用和禁用各种功能等。
  • Three.js:封装了状态管理,简化了开发过程,使得开发者可以专注于场景的构建和动画的实现。

总结

  • WebGL:适合那些希望深入了解图形学原理,并且需要对渲染过程进行精细控制的开发者。虽然学习曲线较陡,但能提供最大的灵活性和性能。

  • Three.js:适合希望快速上手 3D 开发,并且更注重开发效率和易用性的开发者。通过封装复杂的 WebGL 操作,Three.js 使得创建和管理 3D 场景变得更加简单和直观。

 

posted @ 2024-05-16 11:07  3408GoGoGo  阅读(130)  评论(0编辑  收藏  举报