> 文章列表 > 从WebGL到Babylonjs

从WebGL到Babylonjs

从WebGL到Babylonjs

从WebGL到Babylonjs

一、关于WebGL

  • 前世今生 OpenGL => OpenGL ES => WebGL
  • 本质:通过js代码去调用OpenGL的一系列Api

二、WebGL程序的构成

1、一个简单的webgl程序

const canvas = document.querySelector('canvas');
const gl = canvas.getContext('webgl2');
const vertexShaderSource = `#version 300 es
in vec4 position;
void main() {gl_Position = position;
}`;
const fragmentShaderSource = `#version 300 es
precision highp float;
out vec4 outColor;
void main() {outColor = vec4(0, 1, 0.5, 1);
}`
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 prg = gl.createProgram();
gl.attachShader(prg, vertexShader);
gl.attachShader(prg, fragmentShader);
gl.linkProgram(prg);const triangleVAO = gl.createVertexArray();
gl.bindVertexArray(triangleVAO);const vertexPositions = new Float32Array([0, 0.7, 0.5, -0.7, -0.5, -0.7]);const positionBuffer = gl.createBuffer();
gl.bindBuffer(gl.ARRAY_BUFFER, positionBuffer);
gl.bufferData(gl.ARRAY_BUFFER, vertexPositions, gl.STATIC_DRAW);const positionLoc = gl.getAttribLocation(prg, 'position')
gl.enableVertexAttribArray(positionLoc);
gl.vertexAttribPointer(positionLoc, 2, gl.FLOAT, false, 0, 0);
gl.useProgram(prg);gl.drawArrays(gl.TRIANGLES, 0, 3);

最终输出
从WebGL到Babylonjs

可以看到、为了画一个三角形花了四十行代码,看起来很多,但是大部分是webgl相关的操作(上面以gl.开头的代码)
写起来是非常麻烦和不易理解的
如果对webgl的具体执行流程感兴趣可以访问这个在线网站
[https://webgl2fundamentals.org/webgl/lessons/resources/webgl-state-diagram.html?exampleId=samplers#no-help]
从WebGL到Babylonjs

2、为了更好的理解,我们可以把WebGL程序分成两个部分

2.1 js代码

  • 数据的准备(模型加载、纹理图像加载)
  • 向GPU传输数据

2.2 着色器代码

  • 顶点着色器(VertexShader)

负责处理顶点数据,顶点位置变换

  • 片元着色器(FragmentShader)

负责一个着色函数,让每一个像素点都经过这个函数处理,最终变成一个新的像素值

可以把他们理解为两个函数,分别对顶点和像素数据进行一些操作

三、WebGL(OpenGL)的渲染管线(Render PipeLine)

  • 完整流程
    从WebGL到Babylonjs

    白色部分大多是GPU自动处理的,而绿色部分是可由开发人员自由控制的,我们对GPU的操作也大都集中在这两个部分。
    上面的完整渲染管线看起来非常复杂,当经过简化之后大概就是下面这张图,看起来非常简洁明了
    从WebGL到Babylonjs

    通俗的解释一下:

  • 模型数据进入显存之后,首先会经过顶点着色器,一般在这里处理模型顶点位置的变换

  • 接下来经过片元着色器,在这里根据灯光、材质、贴图等数据计算出最终的颜色

  • 最后输出到屏幕

四、Babylonjs

4.1 和WebGL的区别

  • WebGL:一系列的API
  • Babylonjs:对WebGL更高一级的抽象
    比如在Babylon中新建一个立方体,看似只有一行代码, 但是在背后它可能就自动帮你完成了顶点数据准备,着色器创建、编译,数据绑定、数据传输...等工作

4.2 几个主要的概念

从WebGL到Babylonjs

  • Engine:负责与WebGL的直接交互
  • Scene:一个大的场景树,管理着所有Mesh、Light、Camera等
  • Camera:相机,决定着观察者的视角,本质就是一个矩阵
  • Light:灯光,点亮场景,可以理解为片元着色器里面的一个输入参数
  • Mesh:网格,一个可渲染对象,包含了单次渲染的必要数据
    • Material:片元着色器里面的一群输入参数
    • Geometry:存储着顶点的位置数据等

4.3 与webgl的对应关系

在渲染时,可以理解为每个mesh都执行了一遍render方法
在渲染当前mesh的时候,把当前mesh相对应的顶点、贴图数据、program等设置为激活状态,然后调用一次drawCall指令,GPU就会安装预定好的渲染管线结合mesh的这些数据开始绘制
当场景中的mesh遍历完之后,一个完整的render就结束了

我们知道babylonjs是对webgl一层抽象,但是不管你再怎么花里胡哨抽象,在最终落实到渲染的时候还是得转换成一个标准的webgl程序,最终通过渲染管线把数据转换成像素输出到屏幕。
落实到webgl的渲染管线上,他们的大致对应关系将如下图所示
从WebGL到Babylonjs

  • Mesh上挂载的Geometry和Texture将会送入到显存中,其中顶点数据将会送给接下来的顶点着色器使用,Texture将会给到片元着色器使用;
  • Camera将会成为MVP矩阵的一部分,决定着顶点的输出位置
  • Light、Material等将会决定着片元着色器的输出颜色

五、学习资源推荐

(注:部分网站需要🪜)

1、WebGL

  • WebGL2理论基础(推荐) https://webgl2fundamentals.org/webgl/lessons/zh_cn/
  • WebGL程序运行状态可视化(推荐) https://webgl2fundamentals.org/webgl/lessons/resources/webgl-state-diagram.html?exampleId=triangle#no-help
  • WebGL规范(官方、很全) https://registry.khronos.org/webgl/specs/latest/2.0/
  • 图形学基础概念 https://math.hws.edu/eck/cs424/graphicsbook-1.3/

2、着色器学习

  • 基础概念(推荐) https://thebookofshaders.com/
  • 在线运行网站 https://glslsandbox.com/

3、Babylonjs

  • 文档 https://doc.babylonjs.com/journey/theFirstStep
  • 实验场(在线运行代码)https://playground.babylonjs.com/
  • 沙盒(快速查看模型)https://playground.babylonjs.com/