共计 3931 个字符,预计需要花费 10 分钟才能阅读完成。
WebGL
- WebGL 是什么:WebGL(Web Graphics Library)是一种 3D 绘图协定,这种绘图技术标准容许把 JavaScript 和 OpenGL ES 2.0 联合在一起,通过减少 OpenGL ES 2.0 的一个 JavaScript 绑定,WebGL 能够为 HTML5 Canvas 提供硬件 3D 减速渲染
- GPU ≠ WebGL ≠ 3D
- WebGL 很大水平上在和 GPU 打交道但不仅仅是 GPU 渲染
- WebGL 不仅仅是绘制 3D,把浏览器作为一个桥梁,是浏览器上的 OpenGL
古代计算机图形学零碎
- 光栅(Raster):简直所有的古代图形系统都是基于光栅来绘制图形的,光栅就是指形成图像的像素阵列
- 像素(Pixel):一个像素对应图像上的一个点,它通常保留图像上的某个具体位置的色彩等信息
- 帧缓存(Frame Buffer):在绘图过程中,像素信息被寄存在帧缓存中,帧缓存是一块内存地址
- CPU(Central Processing Unit):地方处理单元,负责逻辑计算
- GPU(Graphics Processing Unit):图形处理单元,负责图形计算。GPU 由大量的小运算单元形成,每个运算单元只负责解决很简略的计算。每个运算单元彼此独立。因而所有计算能够并行处理
- CPU VS GPU : CPU 适宜解决简单计算工作,不适宜解决数量十分大的简略工作,则这种工作交给 GPU 来解决
- WebGL 和 OpenGL 的关系:WebGL 是 OpenGL 在浏览器上的一种实现
-
图形计算渲染过程:
- 轮廓提取 / meshing
- 光栅化
- 帧缓存
- 渲染
利用 WebGL 进行图形渲染
-
利用 WebGL 绘图步骤:
- 创立 WebGL 上下文
- 创立 WebGL Program
- 将数据存入缓冲区
- 将缓冲区数据读取到 GPU
- GPU 执行 WebGL 程序,输入后果
-
创立 WebGL 上下文
- 在 HTML 中创立一个宽高 1000 的 canvas 画布:
<canvas id="canvas" width="1000" height="1000"></canvas>
-
在 JavaScript 中获取 DOM 后调用
getContext('webgl')
获取对应的上下文const canvas = document.getElementById("canvas"); const gl = canvas.getContext('webgl');
-
canvas.getContext() 函数接管的参数在不同浏览器中会不同。因为晚期 WebGL 的 context,还不能通过正式的名称
webgl
来获取,必须应用experimental-webgl
来获取 context 对象,当初很多浏览器也反对 webgl2 等其余参数,所以能够封装成一个具备个性检测的函数function create3DContext(canvas,options) {const names = ['webgl', 'experimental-webgl','webkit-3d', 'moz-webgl']; if (options && options.webgl2) names.unshift('webgl2'); let context = null; for (let ii = 0; ii < names.length; ++ii) { try {context = canvas.getContext(names[ii], options); } catch (e) {// no-empty} if (context) {break;} } return context; }
- 在 HTML 中创立一个宽高 1000 的 canvas 画布:
-
创立 WebGL Program
-
顶点着色器 Vertex Shader : 用于解决顶点的地位
attribute vec2 position; void main(){ gl_PointSize = 1.0; gl_Position = vec4(position,1.0,1.0); }
-
片元着色器 Fragment Shader : 并行处理顶点突围内的所有像素,解决次数更多。色彩取值 从 0.0 – 1.0 的浮点范畴
precision mediump float; void main(){gl_FragColor = vec4(1.0,0.0,0.0,1.0); }
-
Create Program
// 顶点着色器代码 const vertexShaderCode = ` attribute vec2 position; void main(){ gl_PointSize = 1.0; gl_Position = vec4(position,1.0,1.0); } `; // 片元着色器代码 const fragmentShaderCode = ` 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, vertexShaderCode); gl.compileShader(vertexShader); // 片元着色器 const fragmentShader = gl.createShader(gl.FRAGMENT_SHADER); gl.shaderSource(fragmentShader, fragmentShaderCode); gl.compileShader(fragmentShader); // 创立程序 const program = gl.createProgram(); gl.attachShader(program, vertexShader); gl.attachShader(program, fragmentShader); gl.linkProgram(program); gl.useProgram(program);
-
创立并应用着色器的相干步骤:
- 创立着色器对象
gl.createShader()
- 向着色器对象中填充着色器程序的源代码
gl.shaderSource()
- 编译着色器
gl.compileShader()
- 创立程序对象
gl.createProgram()
- 为程序对象调配着色器
gl.attachShader()
- 连贯程序对象
gl.linkProgram()
- 应用程序对象
gl.useProgram()
- 创立着色器对象
-
-
将数据存入缓冲区(Frame Buffer)
- 坐标系:canvas 和浏览器的坐标轴都是左上角为原点,x 轴向右为正方向,y 轴向下为正方向。在 WebGL 的坐标体系中,是一个以绘制画布的核心为原点,范畴从 -1 到 1。在 3D 的状况下,z 轴正方向是向外的
- 坐标系:canvas 和浏览器的坐标轴都是左上角为原点,x 轴向右为正方向,y 轴向下为正方向。在 WebGL 的坐标体系中,是一个以绘制画布的核心为原点,范畴从 -1 到 1。在 3D 的状况下,z 轴正方向是向外的
-
绘制一个三角形:
-
用浮点类型数组示意顶点数据,创立 buffer 后将返回的 bufferid 绑定到上下文,最初绑定数据到缓冲区
const points = new Float32Array([ -1, -1, 0, 1, 1, -1, ]); const bufferId = gl.createBuffer(); gl.bindBuffer(gl.ARRAY_BUFFER, bufferId); gl.bufferData(gl.ARRAY_BUFFER, points, gl.STATIC_DRAW);
-
-
将缓冲区数据读取到 GPU
-
做一个指针的绑定
const vPosition = gl.getAttribLocation(program,'position'); // 获取顶点着色器中的 position 变量的地址 gl.vertexAttribPointer(vPosition, 2, gl.FLOAT, false,0, 0); // 给变量设置长度和类型 gl.enableVertexAttribArray(vPosition); // 激活这个变量
-
-
GPU 执行 WebGL 程序,输入后果
-
革除缓冲区数据,再以三角形图元形式绘制三角形,gl.drawArrays() 的三个参数,第一个是绘制的模式(三角形),第二个是绘制的 points 的起始下标,最初一个是绘制的顶点个数,因为每个点是一个二维的向量,length 为 6,所以绘制三角形须要除以 2
gl.clear(gl.COLOR_BUFFER_BIT); // 革除缓冲区 gl.drawArrays(gl.TRIANGLES, 0 ,points.length / 2); // 绘制
- 后果
-
其余形式绘制图形
-
用 canvas 2D 绘制三角形
- 在 HTML 中创立一个宽高 1000 的 canvas 画布:
<canvas id="canvas" width="1000" height="1000"></canvas>
-
在 JavaScript 中获取 canvas 后通过 beginPath,moveTo,lineTo 等 API 绘制出图形
const canvas = document.getElementById('canvas'); const ctx = canvas.getContext('2d'); ctx.beginPath(); ctx.moveTo(250, 0); ctx.lineTo(500, 500); ctx.lineTo(0, 500); ctx.fillStyle = 'red'; ctx.fill();
- 在 HTML 中创立一个宽高 1000 的 canvas 画布:
Read More
- The book of shaders
- Mesh.js
- glsl-doodle
- SpriteJS
- ThreeJS
- shadertoy
WebGL 和 canvas
- WebGL 能够看成 OpenGL 的在浏览器上的一种实现,OpenGL 则是能够间接调用计算机 GPU 算力的一个 3d API。canvas 是在浏览器上的 2d 画布,通过 WebGL 转译光栅后在 canvas 上显示进去
- 相比 canvas,WebGL 性能更好。如果须要实现简单成果,倡议应用 WebGL
- WebGL 能够压缩雷同材质的图形,通过 GPU 一次渲染成千上万个图形,而 canvas 通过浏览器渲染,性能较差