WebGL基础笔记

简介: WebGL基础笔记

WebGL基础笔记

个人参加字节跳动的青训营时写的笔记。这部分是月影老师讲的WebGL基础。

1. 简介

WebGL代码有两部分:

  • 运行在CPU上的JavaScript
  • 运行在GPU上的GLSL

CPU和GPU

  • CPU适合比较复杂的任务,不适合量大但每个单元比较简单的任务
  • GPU有大量的小运算单元构成,每个运算单元只负责处理简单的计算,每个运算单元彼此独立。所有计算可以并行处理。适合量大但每个单元比较简单的任务。

图像的处理适合交给GPU,因为图像会有很多的像素点需要处理。

2. 流程

这部分只能说似懂非懂(任重而道远啊),先贴一下课上的示例代码,方便之后看。

image-20220121161752150

  1. 创建WebGL上下文

    const canvas = document.querySelector('canvas');
    const gl = canvas.getContext('webgl');
  2. 创建WebGL程序(GLSL,顶点着色器、片元着色器)

    顶点着色器(Vertex Shader):

    image-20220121163200070

    片元着色器(Fragment Shader):顶点之间的轮廓中的所有像素都会经过片元着色器处理。(并行处理)

    image-20220121163223930

    image-20220121163501575

  3. 将数据存入缓冲区

    image-20220121163750505

  4. 将缓冲区数据读取到GPU

    ![image-20220121164109751]()

  5. GPU执行WebGL程序,输出结果

    image-20220121164208556

完整代码:

// 1. 创建WebGL上下文
const canvas = document.querySelector('canvas');
const gl = canvas.getContext('webgl');
​
// 2. 创建WebGL程序
​
// 2.1 顶点着色器
const vertex = `
  attribute vec2 position;
​
  void main() {
    gl_PointSize = 1.0;
    gl_Position = vec4(position, 1.0, 1.0);
  }
`;
​
// 2.2 片元着色器
const fragment = `
  precision mediump float;
​
  void main()
  {
    gl_FragColor = vec4(1.0, 0.0, 0.0, 1.0);
  }    
`;
​
// 2.3 加载、编译、使用着色器
const vertexShader = gl.createShader(gl.VERTEX_SHADER);
gl.shaderSource(vertexShader, vertex);
gl.compileShader(vertexShader);
​
const fragmentShader = gl.createShader(gl.FRAGMENT_SHADER);
gl.shaderSource(fragmentShader, fragment);
gl.compileShader(fragmentShader);
​
​
const program = gl.createProgram();
gl.attachShader(program, vertexShader);
gl.attachShader(program, fragmentShader);
gl.linkProgram(program);
gl.useProgram(program);
​
const points = new Float32Array([
  -1, -1,
  0, 1,
  1, -1,
]);
​
// 3. 将数据存入缓存区
const bufferId = gl.createBuffer();
gl.bindBuffer(gl.ARRAY_BUFFER, bufferId);
gl.bufferData(gl.ARRAY_BUFFER, points, gl.STATIC_DRAW);
​
// 4. 将缓冲区数据读取到GPU
const vPosition = gl.getAttribLocation(program, 'position');
gl.vertexAttribPointer(vPosition, 2, gl.FLOAT, false, 0, 0);
gl.enableVertexAttribArray(vPosition);
​
// 5. GPU执行WebGL程序
gl.clear(gl.COLOR_BUFFER_BIT);
gl.drawArrays(gl.TRIANGLES, 0, points.length / 2);  // points中有六个点,实际上只有三个点,所以需要除以2

效果:

image-20220121165503382

canvas 2D版本:

const canvas = document.querySelector('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();

效果和上图所示一样。(比原生WebGL简单好多)

3. 多边形

多边形需要进行三角划分

image-20220121175100166

Earcut

// 1. 创建WebGL上下文
const canvas = document.querySelector('canvas');
const gl = canvas.getContext('webgl');
​
// 2. 创建WebGL程序
​
// 2.1 顶点着色器
const vertex = `
  attribute vec2 position;
​
  void main() {
    gl_PointSize = 1.0;
    gl_Position = vec4(position, 1.0, 1.0);
  }
`;
​
// 2.2 片元着色器
const fragment = `
  precision mediump float;
​
  void main()
  {
    gl_FragColor = vec4(0.0, 1.0, 1.0, 1.0);
  }    
`;
​
// 2.3 加载、编译、使用着色器
const vertexShader = gl.createShader(gl.VERTEX_SHADER);
gl.shaderSource(vertexShader, vertex);
gl.compileShader(vertexShader);
​
const fragmentShader = gl.createShader(gl.FRAGMENT_SHADER);
gl.shaderSource(fragmentShader, fragment);
gl.compileShader(fragmentShader);
​
​
const program = gl.createProgram();
gl.attachShader(program, vertexShader);
gl.attachShader(program, fragmentShader);
gl.linkProgram(program);
gl.useProgram(program);
​
// 顶点集
const vertices = [
  [-1, -1],
  [-1, 0],
  [0, 0],
  [0, -1],
];  
​
const points = vertices.flat();  // 点集
const triangles = earcut(points);  // 三角形集(三角划分后的三角性)
​
const position = new Float32Array(points);
const cells = new Uint16Array(triangles);
​
// 3. 将数据存入缓存区,这时候需要分点和三角形来分别存
const pointBuffer = gl.createBuffer();
gl.bindBuffer(gl.ARRAY_BUFFER, pointBuffer);
gl.bufferData(gl.ARRAY_BUFFER, position, gl.STATIC_DRAW);
​
const cellsBuffer = gl.createBuffer();
gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, cellsBuffer);
gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, cells, gl.STATIC_DRAW);
​
// 4. 将缓冲区数据读取到GPU
const vPosition = gl.getAttribLocation(program, 'position');
gl.vertexAttribPointer(vPosition, 2, gl.FLOAT, false, 0, 0);
gl.enableVertexAttribArray(vPosition);
​
// 5. GPU执行WebGL程序
gl.clear(gl.COLOR_BUFFER_BIT);
gl.drawElements(gl.TRIANGLES, cells.length, gl.UNSIGNED_SHORT, 0);  // 这部分还不是很明白
​

效果:

image-20220121184608412

4. 变换

  • 平移
  • 旋转
  • 缩放

image-20220121203813648

5. 3D标准模型的四个齐次矩阵

  • 投影矩阵
  • 模型矩阵
  • 视图矩阵
  • 法向量矩阵

挖了个大坑

6. 相关链接

相关实践学习
部署Stable Diffusion玩转AI绘画(GPU云服务器)
本实验通过在ECS上从零开始部署Stable Diffusion来进行AI绘画创作,开启AIGC盲盒。
目录
相关文章
|
Web App开发 前端开发 JavaScript
WebGL:开始学习 / 理解 WebGL / WebGL 需要掌握哪些知识 / 应用领域 / 前端值得学WebGL吗
WebGL:开始学习 / 理解 WebGL / WebGL 需要掌握哪些知识 / 应用领域 / 前端值得学WebGL吗
510 0
|
3月前
|
移动开发 JavaScript 前端开发
ThreeJs简介
这篇文章介绍了Three.js的基础知识,包括其相对于WebGL的优势以及如何使用Three.js创建基本的3D场景。
99 1
|
5月前
|
Apache 图形学
WebGL☀️Unity WebGL适配到各平台的教程
WebGL☀️Unity WebGL适配到各平台的教程
|
8月前
|
移动开发 前端开发 JavaScript
游戏开发技术- 请谈谈WebGL与Canvas的区别,以及在什么情况下更适合使用WebGL。
WebGL和Canvas都是网页游戏开发的关键技术。Canvas是2D绘图API,适合初学者和简单的2D游戏,而WebGL是基于OpenGL的3D渲染标准,用于复杂3D图形和游戏,提供GPU硬件加速。当涉及3D渲染、高级视觉效果或高性能需求时,WebGL是更好的选择。对于轻量级2D应用,Canvas就足够了。某些游戏引擎支持两者自动切换,以实现最佳性能和兼容性。
622 4
|
8月前
|
前端开发 JavaScript 程序员
webgl学习笔记1_创建场景
webgl学习笔记1_创建场景
60 0
|
JavaScript 前端开发 数据可视化
6 个用于 3D 网页图形渲染的最佳 WebGL 库
现代前端、游戏和Web开发正是WebGL可以转化为数字杰作的东西。使用GPU绘制在浏览器屏幕上生成的矢量元素,WebGL创建交互式Web图形,从而获得用户体验。视觉元素的质量和复杂性使该工具在HTML或CSS等其他方法中脱颖而出。
617 0
|
存储 缓存 前端开发
WebGL简介
WebGL简介
141 0
WebGL简介
|
存储 前端开发 JavaScript
WebGL 基础概念
WebGL 基础概念
171 0
WebGL 基础概念
|
移动开发 JavaScript 前端开发
webgl入门指南(一)
本文适合对图形感兴趣的小伙伴阅读。
webgl入门指南(一)
|
监控 前端开发 索引
如何用webgl(three.js)搭建一个3D库房,3D密集架,3D档案室,-第二课
闲话少叙,我们接着第一课继续讲(http://www.cnblogs.com/yeyunfei/p/7899613.html),很久没有做技术分享了。很多人问第二课有没有,我也是抽空写一下第二课。 第一课程提到了在库房的基础上添加上下架 消防 温湿度等等控制 刚好 最近有接到一个客户的需求 是和库房...
2285 0