前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >WebGL基础笔记

WebGL基础笔记

作者头像
赤蓝紫
发布2023-01-02 16:59:10
1.1K0
发布2023-01-02 16:59:10
举报
文章被收录于专栏:clzclz

WebGL 基础笔记

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

1. 简介

WebGL 代码有两部分:

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

CPU 和 GPU

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

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

2. 流程

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

image-20220121161752150
image-20220121161752150

创建 WebGL 上下文

代码语言:javascript
复制
const canvas = document.querySelector("canvas");
const gl = canvas.getContext("webgl");

创建 WebGL 程序(GLSL,顶点着色器、片元着色器)

顶点着色器(Vertex Shader):

image-20220121163200070
image-20220121163200070

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

image-20220121163223930
image-20220121163223930
image-20220121163501575
image-20220121163501575

将数据存入缓冲区

image-20220121163750505
image-20220121163750505

将缓冲区数据读取到 GPU

image-20220121164109751
image-20220121164109751

GPU 执行 WebGL 程序,输出结果

image-20220121164208556
image-20220121164208556

完整代码:

代码语言:javascript
复制
// 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);	// 类似rgba
  }    
`;

// 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
image-20220121165503382

canvas 2D 版本:

代码语言:javascript
复制
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
image-20220121175100166

Earcut

代码语言:javascript
复制
// 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
image-20220121184608412

4. 变换

  • 平移
  • 旋转
  • 缩放
image-20220121203813648
image-20220121203813648

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

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

挖了个大坑

6. 相关链接

本文参与?腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2022-01-24,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客?前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与?腾讯云自媒体分享计划? ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • WebGL 基础笔记
    • 1. 简介
      • 2. 流程
        • 3. 多边形
          • 4. 变换
            • 5. 3D 标准模型的四个齐次矩阵
              • 6. 相关链接
              领券
              问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档
              http://www.vxiaotou.com