• Why WebGL / Why GPU?
  • 现代的图像系统
    • The Pipeline
    • GPU
    • WebGL & OpenGL关系
  • WebGL绘图步骤
    • 创建WebGL上下文
    • 创建WebGL Program(The Shaders)
    • 将数据存到缓冲区中(Data to Frame Buffer)
    • 读取缓冲区数据到GPU(Frame Buffer to GPU)
    • 输出结果(Output)
  • WebGL太复杂?其他方式
    • canvas 2D
    • Mesh.js
    • Earcut
    • 3D Meshing
  • 图形变换(Transforms)
    • 平移
    • 旋转
    • 缩放
    • 线性变换(旋转+缩放)
  • 3D Matrix
  • Read more
  • 总结感想

将自己在掘金上发的笔记搬了过来:WebGL基础、个人博客

Why WebGL / Why GPU?

  • WebGL是什么?

    • GPU ≠ WebGL ≠ 3D
  • WebGL为什么不像其他前端技术那么简单?

现代的图像系统

  • 光栅(Raster):几乎所有的现代图形系统都是基于光栅来绘制图形的,光栅就是指构成图像的像素阵列
  • 像素(Pixel)一个像素对应图像上的一个点,它通常保存图像上的某个具体位置的颜色等信息。
  • 帧缓存(Frame Buffer):在绘图过程中,像素信息被存放于帧缓存中,帧缓存是一块内存地址。
  • CPU (Central Processing Unit):中央处理单元,负责逻辑计算
  • GPU (Graphics Processing Unit):图形处理单元,负责图形计算

  • 如上图,现代图像的渲染如图过程
  1. 轮廓提取/ meshing
  2. 光栅化
  3. 帧缓存
  4. 渲染

The Pipeline

GPU

  • GPU由大量的小运算单元构成
  • 每个运算单元只负责处理很简单的计算
  • 每个运算单元彼此独立
  • 因此所有计算可以并行处理

WebGL & OpenGL关系

OpenGL, OpenGL ES, WebGL, GLSL, GLSL ES API Tables (umich.edu)

WebGL绘图步骤

步骤

  1. 创建WebGL上下文
  2. 创建WebGL Program
  3. 将数据存入缓冲区
  4. 将缓冲区数据读取到GPU
  5. GPU执行WebGL程序,输出结果

如图,针对几个单词进行解释:

  • Raw Vertices & Primitives 原始顶点&原语
  • Vertex Processor 顶点着色器
  • 运算后送到 片元着色器 进行处理:Fragment Processor

创建WebGL上下文

const canvas = document.querySelector('canvas');
const gl = canvas.getContext('webgl');
// 创建上下文, 注意兼容
function create3DContext(canvas, options) {const names = ['webgl', 'experimental-webgL','webkit-3d','moz-webgl'];  // 特性判断if(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;
}

创建WebGL Program(The Shaders)

  1. Vertex Shader(顶点着色器)

    通过类型数组position,并行处理每个顶点的位置

    attribute vec2 position;// vec2 二维向量
    void main() {gl_PointSize = 1.0;gl_Position = vec4(position, 1.0, 1.0);
    }
    
  2. Fragment Shader(片元着色器)

    为顶点轮廓包围的区域内所有像素进行着色

    precision mediump float;
    void main() {gl_FragColor = vec4(1.0, 0.0, 0.0, 1.0);//对应rgba(255,0,0,1.0),红色
    }
    

其具体步骤如下:

  1. 创建顶点着色器和片元着色器代码:

    // 顶点着色器程序代码
    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);
    }
    `;
    
  2. 使用 createShader() 创建着色器对象

  3. 使用 shaderSource() 设置着色器的程序代码

  4. 使用 compileShader() 编译一个着色器

    // 顶点着色器
    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);
    
  5. 使用**createProgram()** 创建 WebGLProgram 对象

  6. 使用 attachShader()WebGLProgram 添加一个片段或者顶点着色器。

  7. 使用 **linkProgram() **链接给定的WebGLProgram,从而完成为程序的片元和顶点着色器准备GPU代码的过程。

  8. 使用 useProgram() 将定义好的WebGLProgram 对象添加到当前的渲染状态

    // 创建着色器程序并链接
    const program = gl.createProgram();
    gl.attachShader(program, vertexShader);
    gl.attachShader(program, fragmentShader);
    gl.linkProgram(program);gl.useProgram(program);
    

将数据存到缓冲区中(Data to Frame Buffer)

  • 坐标轴:webGL的坐标系统是归一化的,浏览器和canvas2D的坐标系统是以左上角为坐标原点,y轴向下,x轴向右,坐标值相对于原点。而webGL的坐标系是以绘制画布的中心点为原点正常的笛卡尔坐标系

通过一个顶点数组表示其顶点,使用 createBuffer() 创建并初始化一个用于储存顶点数据或着色数据的WebGLBuffer对象并返回bufferId,然后使用 bindBuffer() 将给定的 bufferId 绑定到目标并返回,最后使用**bufferData()**,将数据绑定至buffer中。

// 顶点数据
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(Frame Buffer to GPU)

  • getAttribLocation() 返回了给定WebGLProgram对象中某属性的下标指向位置。

  • vertexAttribPointer() 告诉显卡从当前绑定的缓冲区(bindBuffer()指定的缓冲区)中读取顶点数据。

  • enableVertexAttribArray() 可以打开属性数组列表中指定索引处的通用顶点属性数组。

const vPosition = gl.getAttribLocation(program, 'position'); // 获取顶点着色器中的position变量的地址
gl.vertexAttribPointer(vPosition, 2, gl.FLOAT, false, 0, 0); // 给变量设置长度和类型
gl.enableVertexAttribArray(vPosition); // 激活这个变量

输出结果(Output)

Output

drawArrays() 从向量数组中绘制图元

// output
gl.clear(gl.COLOR_BUFFER_BIT);  //清除缓冲的数据
gl.drawArrays(gl.TRIANGLES, 0, points.length / 2);

WebGL太复杂?其他方式

canvas 2D

看看人家canvas2D,绘制同样的三角形:

// canvas 简单粗暴,都封装好了
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();

Mesh.js

mesh-js/mesh.js: A graphics system born for visualization

【第二届青训营-寒假前端场】- 「WebGL基础」笔记相关推荐

  1. 【第二届青训营-寒假前端场】- 「前端动画实现」笔记

    动画的基本原理 动画是什么 动画发展史 计算机动画 前端动画分类 css动画 animation-name animation-duration animation-timing-function a ...

  2. 【第二届青训营-寒假前端场】- 「小游戏开发」笔记

    前端场景下的游戏开发 开发角色和链路 为什么要用游戏引擎 前端过渡到游戏开发 游戏引擎 市面上常见游戏引擎 特定类型的客户端游戏引擎 The NVL Maker **RPG Maker** Web游戏 ...

  3. 【第二届青训营-寒假前端场】- 「构建Webpack知识体系」笔记

    本节课重点内容 什么是Webpack Webpack打包核心流程 示例 步骤 关键配置项(如何使用?) 使用Webpack处理CSS/less等 思考题 使用Webpack接入Babel 思考题 使用 ...

  4. 第五届字节跳动青训营寒假 —— 前端专场

    第五届字节跳动青训营寒假 -- 前端专场 文章目录 第五届字节跳动青训营寒假 -- 前端专场 青训营 - 前端练习题 每日一练 编程题 前端编程题 [342. 4的幂](https://leetcod ...

  5. 第五届字节跳动青训营 - 寒假专场 【前端后端】

    青训营 是 字节跳动 ByteTech 社区发起的技术系列培训 & 人才选拔项目,面向在校大学生,旨在培养优秀且具有职业竞争力的开发工程师.青训营全程完全免费,不收取费用. 面向人群:在校大学 ...

  6. 字节青训营第一课之go语言入门的笔记和总结

    有幸参加了字节跳动举办的青训营活动,主要是go语言的编程实践,我将会整理课程的笔记和总结,欢迎关注! 1Go语言简介 由于Go语言有语法简单.高性能等特点,因此国内外各大公司如谷歌.腾讯.字节等都在使 ...

  7. 字节青训营Go语言学习第一天--基础语言+实战案例

    文章目录 走进Go语言基础语言 2.2基础语言-变量 2.3基础语法- if else 2.4基础语法-循环 基础语法-switch 基础语法-数组 基础语法-切片 基础语法-map 基础语法-ran ...

  8. 前后端免费学 | 第六届字节跳动青训营报名啦

    线上活动,全程免费 报名时间:2023年6月2日 - 2023年7月10日 报名地址:点我报名,暑假一起学技术呀... 前言 其实去年我就想参加青训营的,但是那时的我刚转完专业,觉得自己太菜了,单方面 ...

  9. 字节跳动青训营--前端day7

    文章目录 前言 一.Node.js 的应用场景 (why) 1. 前端工程化 2. web服务端应用 3. Electron跨端桌面应用 二.Node.js 运行时结(what) 1. V8 ,lib ...

最新文章

  1. vs2015自动窗口(查看变量的值)
  2. 将字符串中的URL 解析,获取内容
  3. 如何跟面试公司谈论薪资?
  4. 【C语言】通过原子操作实现加减乘除操作Ⅱ
  5. C# 笔记1 - 操作目录
  6. c#Winform程序CPU占用高的原因和解决方法(转载)
  7. 计算机社团自评报告怎么写,社团自我评价
  8. Ubuntu下的“千千静听”-Audacious
  9. java正则表达式 手机_Java正则表达式
  10. printf(%d%d%d%d\n, a,b,c);
  11. linux aio进程简介,Linux AIO机制
  12. java定时器整点报时_单片机 整点报时 定时小闹钟程序
  13. RAM,SRAM,SDRAM工作原理(很长)
  14. npm installl preinstall
  15. 家用电梯的曳引式电梯井道尺寸及配置
  16. MyIE 增加了RSS功能
  17. host ntrip 千寻rtk_【千寻新姿势】南方工程之星5.0连接千寻FindCM服务设置教程
  18. HMM 隐马尔可夫模型
  19. office365的订阅用户 为什么还提示我激活
  20. 通讯公司Kakao推出自己的区块链并进行测试

热门文章

  1. 58同城 反爬虫机制及处理
  2. App地推效果统计,自动业绩结算
  3. App地推渠道归属:解决地推中存在的难题
  4. Django项目 no signature found for builtin错误原因
  5. RGB图像之灰度级和通道的理解
  6. codeblocks使用教程(codeblocks使用教程调试)
  7. 随机森林(RandomForest,RF)网格搜索法调参
  8. Hyperledger Fabric共识机制
  9. libjpeg与turbo libjpeg的使用
  10. COSCon'21 人工智能(A)论坛介绍