每天学一点:webGL和threeJs (一)

152 阅读4分钟

一、什么是webGl?

webGL是基于openGL的标准之上的2d\3d矢量图形渲染的JS API, 可以直接访问GPU进行硬件加速渲染,远超传统仅使用CPU来渲染的2d cavans绘图,但任然是通过 HTML5 的 <canvas> 元素工作。所以在学webGL遇到查找资料时你可能查到了openGL的相关的问题答案资料,别错过也是很有帮助的。

二、向量/矢量(Vector)

它们都代表有方向的量。矢量在物理中是值某个方向受到力的大小。向量在数学中代表一个坐标点,它可以是二维或者三维坐标的一个点。比如[0,0]这个坐标在二维中X轴0, Y轴0 对应的一个坐标点,比如[0,0,0]这个坐标在三维中X轴0, Y轴0,Z轴0对应的一个坐标点,这些坐标点就是矢量,很多个或者一组坐标点构成一个图形叫矢量图形。如下图所示,无数个三维空间点最终可以组成很多立体图形。

image.png

三、webGL和threeJS中的右手坐标系(如下图所示):

image.png

四、在三维坐标系中如何缩放、平移、旋转三维模型(Model)?

当我们在三维空间有了点、线、面、体组成的某个图形,比如说一只狗的模型如何实现对图形进行缩放、平移、旋转位置变换。那么只需要变换模型上所有对应的点。二维/三维空间中点位置的变换本身就是数学中线性代数问题。而矩阵(Matrix)与向量(Vector)的运算是线性代数中的基本操作,主要包括加法、减法、乘法以及转置等。 比如说向右边平移一个空间点A[0,0,0],右平移10个单位,那么我们就对点A的x轴加10得到[10,0,0],平移空间点如此模型同理,进行加法或者减法平移。但是缩放、旋转的话是进行乘除运算实现线性变换。

image.png

五、webGL硬件加速

前言:从学前端之初一直牵引着我作为前端开发不断前进的问题,从浏览器地址栏输入地址后到浏览器显示内容后都发生了什么。那么二维平面的浏览器页面又是如何将3d模型如何渲染到屏幕上的,换句话说在三维空间中N多个空间点组成的物体,如何呈现在二维平面上而且让你看起来它是三维的物体。

  1. webGL的渲染管线(interview重点

    WebGL 渲染管线(Rendering Pipeline)描述了从 3D 数据到最终 2D 屏幕图像的整个处理流程。它基于 OpenGL ES 的图形管线设计(Graphic pipeline )

    graph LR
    A[CPU准备数据:顶点坐标、纹理等]
    A --> B[数据传输至GPU显存]
    B --> C[顶点着色器:处理顶点位置、变换]
    C --> D[图元装配:生成三角形等图元]
    D --> E[光栅化:将图元转换为像素]
    E --> F[片段着色器:计算像素颜色、纹理采样]
    F --> G[合成输出到帧缓冲区]

  2. 总结整个渲染管线的每个“工序”依次是:

    顶点着色器——图元装配——几何着色器——光栅化——片段着色器——测试与混合

  3. GPU(图形处理器)和webGL的关系

    专为并行计算设计,擅长处理大量顶点、像素的并行渲染任务(如顶点着色、片段着色、纹理映射)。 WebGL 通过着色器(Shader)实现 GPU 编程:开发者用 GLSL(OpenGL Shading Language)编写顶点着色器和片段着色器,控制 GPU 如何处理图形数据。

示例代码流程

const positions = new Float32Array([...]);
const buffer = gl.createBuffer();
gl.bindBuffer(gl.ARRAY_BUFFER, buffer);
gl.bufferData(gl.ARRAY_BUFFER, positions, gl.STATIC_DRAW);

// 2. 编写着色器(GLSL)
const vertexShader = `
  attribute vec3 aPosition;
  void main() {
    gl_Position = projectionMatrix * viewMatrix * modelMatrix * vec4(aPosition, 1.0);
  }`;

const fragmentShader = `
  void main() {
    gl_FragColor = vec4(1.0, 0.0, 0.0, 1.0); // 红色
  }`;

// 3. 渲染循环
function render() {
  gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);
  gl.drawArrays(gl.TRIANGLES, 0, 3);
  requestAnimationFrame(render);
}

六、结语

当我们在从0-1的学习过程中需要学习新概念,什么是顶点着色器,什么是图元,怎么还需要装配,什么是光栅化,片段又是什么等等一系列疑惑不解。我们学习js\css\html ,比如css的布局什么是内边距,什么是外边距我们直接写几行简单代码可以立即出现效果,非常直白的看到代码作用瞬间明白它的概念。别放弃不要着急慢慢去理解,有困难说明我们正在进步。下篇文章将继续完成webGL的渲染管线每个工序步骤,细节描述了从 3D 数据到最终 2D 屏幕图像的整个处理流程,将一步一步的对webGL进行学习,为我们开展threeJS学习做铺垫,再当我们实战3d渲染项目时将会知其所以然的信手拈来。