【第二届青训营-寒假前端场】- 「WebGL基础」笔记
- 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):图形处理单元,负责图形计算。
- 如上图,现代图像的渲染如图过程
- 轮廓提取/ meshing
- 光栅化
- 帧缓存
- 渲染
The Pipeline
GPU
- GPU由大量的小运算单元构成
- 每个运算单元只负责处理很简单的计算
- 每个运算单元彼此独立
- 因此所有计算可以并行处理
WebGL & OpenGL关系
OpenGL, OpenGL ES, WebGL, GLSL, GLSL ES API Tables (umich.edu)
WebGL绘图步骤
步骤
- 创建WebGL上下文
- 创建WebGL Program
- 将数据存入缓冲区
- 将缓冲区数据读取到GPU
- 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)
Vertex Shader(顶点着色器)
通过类型数组position,并行处理每个顶点的位置
attribute vec2 position;// vec2 二维向量 void main() {gl_PointSize = 1.0;gl_Position = vec4(position, 1.0, 1.0); }
Fragment Shader(片元着色器)
为顶点轮廓包围的区域内所有像素进行着色
precision mediump float; void main() {gl_FragColor = vec4(1.0, 0.0, 0.0, 1.0);//对应rgba(255,0,0,1.0),红色 }
其具体步骤如下:
创建顶点着色器和片元着色器代码:
// 顶点着色器程序代码 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); } `;
使用
createShader()
创建着色器对象使用
shaderSource()
设置着色器的程序代码使用
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);
使用**
createProgram()
** 创建WebGLProgram
对象使用
attachShader()
往WebGLProgram
添加一个片段或者顶点着色器。使用 **
linkProgram()
**链接给定的WebGLProgram
,从而完成为程序的片元和顶点着色器准备GPU代码的过程。使用
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基础」笔记相关推荐
- 【第二届青训营-寒假前端场】- 「前端动画实现」笔记
动画的基本原理 动画是什么 动画发展史 计算机动画 前端动画分类 css动画 animation-name animation-duration animation-timing-function a ...
- 【第二届青训营-寒假前端场】- 「小游戏开发」笔记
前端场景下的游戏开发 开发角色和链路 为什么要用游戏引擎 前端过渡到游戏开发 游戏引擎 市面上常见游戏引擎 特定类型的客户端游戏引擎 The NVL Maker **RPG Maker** Web游戏 ...
- 【第二届青训营-寒假前端场】- 「构建Webpack知识体系」笔记
本节课重点内容 什么是Webpack Webpack打包核心流程 示例 步骤 关键配置项(如何使用?) 使用Webpack处理CSS/less等 思考题 使用Webpack接入Babel 思考题 使用 ...
- 第五届字节跳动青训营寒假 —— 前端专场
第五届字节跳动青训营寒假 -- 前端专场 文章目录 第五届字节跳动青训营寒假 -- 前端专场 青训营 - 前端练习题 每日一练 编程题 前端编程题 [342. 4的幂](https://leetcod ...
- 第五届字节跳动青训营 - 寒假专场 【前端后端】
青训营 是 字节跳动 ByteTech 社区发起的技术系列培训 & 人才选拔项目,面向在校大学生,旨在培养优秀且具有职业竞争力的开发工程师.青训营全程完全免费,不收取费用. 面向人群:在校大学 ...
- 字节青训营第一课之go语言入门的笔记和总结
有幸参加了字节跳动举办的青训营活动,主要是go语言的编程实践,我将会整理课程的笔记和总结,欢迎关注! 1Go语言简介 由于Go语言有语法简单.高性能等特点,因此国内外各大公司如谷歌.腾讯.字节等都在使 ...
- 字节青训营Go语言学习第一天--基础语言+实战案例
文章目录 走进Go语言基础语言 2.2基础语言-变量 2.3基础语法- if else 2.4基础语法-循环 基础语法-switch 基础语法-数组 基础语法-切片 基础语法-map 基础语法-ran ...
- 前后端免费学 | 第六届字节跳动青训营报名啦
线上活动,全程免费 报名时间:2023年6月2日 - 2023年7月10日 报名地址:点我报名,暑假一起学技术呀... 前言 其实去年我就想参加青训营的,但是那时的我刚转完专业,觉得自己太菜了,单方面 ...
- 字节跳动青训营--前端day7
文章目录 前言 一.Node.js 的应用场景 (why) 1. 前端工程化 2. web服务端应用 3. Electron跨端桌面应用 二.Node.js 运行时结(what) 1. V8 ,lib ...
最新文章
- vs2015自动窗口(查看变量的值)
- 将字符串中的URL 解析,获取内容
- 如何跟面试公司谈论薪资?
- 【C语言】通过原子操作实现加减乘除操作Ⅱ
- C# 笔记1 - 操作目录
- c#Winform程序CPU占用高的原因和解决方法(转载)
- 计算机社团自评报告怎么写,社团自我评价
- Ubuntu下的“千千静听”-Audacious
- java正则表达式 手机_Java正则表达式
- printf(%d%d%d%d\n, a,b,c);
- linux aio进程简介,Linux AIO机制
- java定时器整点报时_单片机 整点报时 定时小闹钟程序
- RAM,SRAM,SDRAM工作原理(很长)
- npm installl preinstall
- 家用电梯的曳引式电梯井道尺寸及配置
- MyIE 增加了RSS功能
- host ntrip 千寻rtk_【千寻新姿势】南方工程之星5.0连接千寻FindCM服务设置教程
- HMM 隐马尔可夫模型
- office365的订阅用户 为什么还提示我激活
- 通讯公司Kakao推出自己的区块链并进行测试