WebGL 及其在 WebRTC 中的应用
一、前言
1、什么是 WebGL ?
WebGL 的全称是 Web Graphics Library,是一种 3D 绘图协议。
WebGL 允许把 JavaScript 和 OpenGL ES 2.0 结合在一起,通过增加 OpenGL ES 2.0 的一个JavaScript 绑定,WebGL 可以为 HTML5 Canvas 提供硬件 3D 加速渲染。Web 开发人员就可以借助系统显卡来在浏览器里更流畅地展示 3D 场景和模型,还能创建复杂的导航和数据视觉化。
2、OpenGL 与 GLSL
在了解 WebGL 之前,我们需了解下什么是 OpenGL 与 GLSL。
OpenGL(英语:Open Graphics Library,译名为开放图形库或者“开放式图形库”)是用于渲染 2D、3D 矢量图形的跨语言、跨平台的应用程序编程接口(API), GLSL 则是用来在 OpenGL
从上文中可以看到 WebGL 实际上是 JavaScript 操作一些 OpenGL 接口,也就意味着,可能会编写一部分 GLSL ES 2.0 的代码,没错你猜对了,WebGL 只是绑定了一层,内部的一些核心内容,例如着色器、材质、灯光等都是需要借助 GLSL ES 语法来操作的。
基于 WebGL 周边也衍生了众多的第三方库,比如开发应用类的 Three.js,开发游戏类的 Egert.js 等,都大大的降低了学习 WebGL 的成本,但是本着有问题解决问题,没问题制造问题再解决问题的程序猿态度,还是觉得应该稍微了解一下 WebGL 的一些基本概念,以便能更好的去理解不同框架带来的便捷以及优势!
二、WebGL 概述
今天还是用 5W1H 分析法,围绕 WebGL 给大家做一下介绍:
1、Who: 谁发明的?
WebGL 起源于 Mozilla 员工弗拉基米尔·弗基西维奇的一项称为 Canvas 3D 的实验项目。
2006 年,弗基西维奇首次展示了 Canvas 3D 的原型。
2007 年底在 Firefox 和 Opera 被实现。
在 2009 年初,非营利技术联盟 Khronos Group 启动了 WebGL 的工作组,最初的工作成员包括 Apple、Google、Mozilla、Opera
2011 年 3 月发布 WebGL 1.0 规范。截至2012年3月,工作组的主席由肯·罗素(Ken Russell,全名“Kenneth Bradley Russell”)担任。
WebGL 的早期应用包括 Zygote Body。
2、When: 什么时候开始广泛应用?
WebGL 2.0 规范的发展始于 2013 年,并于 2017 年 1 月完成。该规范基于 OpenGL ES 3.0产生,首度实现在 Firefox 51、Chrome 56 和 Opera 43 中。市面上除了反人类的 IE 外基本上均支持, 兼容性很好。
3、Where: 主要在什么地方(场景)使用?
3D 的数据可视化、3D 游戏开发、H5 广告 / Web 宣传页、图像处理等。
说一下 3D 的数据可视化。3D 的可视化利用技术和视觉感官从信息中提取价值。当我们分析典型 2D 格式的数据时,通常由电子表格或统计图中的数字组成,我们实际可以获取并用于规划,制定决策,定位客户等等的信息是有限的,3D可视化技术使我们能够看到在传统的图表看不到的内容。
4、Why: 为什么用它?
WebGL 完美地解决了现有的 Web 交互式三维动画的两个问题:
问题一:它通过 HTML脚本 本身实现 Web 交互式三维动画的制作,无需任何浏览器插件支持;
问题二:它利用底层的图形硬件加速功能进行的图形渲染,是通过统一的、标准的、跨平台的OpenGL 接口实现的。
5、How: 怎么使用?
检测浏览器是否支持 WebGL。使用前,可以通过检测页面可以看到 当前使用的浏览器对 WebGL的支持情况,包括支持的规范版本。
6、关于着色器
WebGL 只关心两件事:裁剪空间中的坐标值和颜色值。 你需要提供两个着色器来做这两件事,一个顶点着色器提供裁剪空间坐标值,一个片断着色器提供颜色值。
顶点着色器的作用是计算顶点的位置。根据计算出的一系列顶点位置,WebGL 可以对点、线和三角形在内的一些图元进行光栅化处理(把顶点数据转换为片元的过程,将图转化为一个个栅格组成的图象)。当对这些图元进行光栅化处理时需要使用片断着色器方法。片断着色器的作用是计算出当前绘制图元中每个像素的颜色值。
1)顶点着色器
// 一个属性值,将会从缓冲中获取数据
attribute vec4 a_position;
// 所有着色器都有一个main方法
void main() {
// gl_Position 是一个顶点着色器主要设置的变量
gl_Position = a_position;
}
2)片断着色器
// 片断着色器没有默认精度,所以我们需要设置一个精度
// mediump是一个不错的默认值,代表“medium precision”(中等精度)
precision mediump float;
void main() {
// gl_FragColor是一个片断着色器主要设置的变量
gl_FragColor = vec4(1, 0, 0.5, 1); // 返回“红紫色”
}
着色器语言使用的是 GLSL ES 语言,在 JavaScript 中无法直接执行,需要将之存放在字符串中,等待调用。
编译着色器中包含几个内置变量:gl_Position、gl_PointSize、gl_FragColor。
gl_Position: 为一种 vec4 类型的变量,且必须被赋值。四维坐标矢量,我们称之为齐次坐标,即(x,y,z,w),等价于三维坐标(x/w,y/w,z/w),w 相当于深度,没有特殊要求设置为 1.0即可;
gl_PointSize:表示顶点的尺寸,不填则默认显示为 1.0;
gl_FragColor:表示颜色,是片元着色器中唯一的内置变量,也是一个 vec4 类型变量,分别代表(R、G、B、A),不过颜色范围是从 0.0-1.0 对应 Javascript 中的 #00-#FF。
三、基本用法
1、创建 WebGL 对象
不同浏览器声明 WebGL 对象方式有所区别,虽然大部分浏览器都支持 experimental-webgl,而且以后会变成 WebGL,所以创建时做一下兼容处理:
var canvas = document.getElementById("glcanvas");
gl = canvas.getContext("webgl") || canvas.getContext("experimental-webgl");
2、创建顶点着色器
var VSHADER_SOURCE =
'void main() {\n' +
' gl_Position = vec4(0.0, 0.0, 0.0, 1.0);\n' +
' gl_PointSize = 10.0;\n' +
'}\n';
3、创建片元着色器
var FSHADER_SOURCE =
'void main() {\n' +
' gl_FragColor = vec4(1.0, 0.0, 0.0, 1.0);\n' +
'}\n';
着色器代码需要载入到一个程序中,WebGL 使用此程序才能调用着色器。
var program = gl.createProgram();
// 创建顶点着色器
var vShader = gl.createShader(gl.VERTEX_SHADER);
// 创建片元着色器
var fShader = gl.createShader(gl.FRAGMENT_SHADER);
// shader容器与着色器绑定
gl.shaderSource(vShader, VSHADER_SOURCE);
gl.shaderSource(fShader, FSHADER_SOURCE);
// 将GLSE语言编译成浏览器可用代码
gl.compileShader(vShader);
gl.compileShader(fShader);
// 将着色器添加到程序上
gl.attachShader(program, vShader);
gl.attachShader(program, fShader);
// 链接程序,在链接操作执行以后,可以任意修改shader的源代码,
//对shader重新编译不会影响整个程序,除非重新链接程序
gl.linkProgram(program);
// 加载并使用链接好的程序
gl.useProgram(program);
接着绘制一个点:
gl.clearColor(0.0,0.0,0.0,1.0);
gl.clear(gl.COLOR_BUFFER_BIT);
gl.drawArrays(gl.POINTS, 0 ,1);
四、美颜滤镜
我们已经了解了 WebGL 的一些基本概念和基本使用方法,下面我们将介绍 WebGL 的图像处理及其如何运用到 WebRTC。
要想做到例如美白、红润等效果,我们需要掌握大量的 WebGL 知识和图像算法,本次分享先让大家对滤镜有一个初步的认识,理解如何绘制图片。
图像处理
在 WebGL 中绘制图片需要使用纹理,和 WebGL 渲染时需要裁剪空间坐标相似, 渲染纹理时需要纹理坐标,而不是像素坐标。无论纹理是什么尺寸,纹理坐标范围始终是 0.0 到 1.0 。
因为我们只用画一个矩形(其实是两个三角形),所以需要告诉 WebGL 矩形中每个顶点对应的纹理坐标。 我们将使用一种特殊的叫做 varying
的变量将纹理坐标从顶点着色器传到片断着色器,它叫做“可变量”是因为它的值有很多个,WebGL 会用顶点着色器中的值进行插值,然后传给对应像素执行的片断着色器。
attribute vec2 a_texCoord;
...
varying vec2 v_texCoord;
void main() {
...
// 将纹理坐标传给片断着色器
// GPU会在点之间进行插值
v_texCoord = a_texCoord;
}
<script id="fragment-shader-2d" type="x-shader/x-fragment">
precision mediump float;
// 纹理
uniform sampler2D u_image;
// 从顶点着色器传入的纹理坐标
varying vec2 v_texCoord;
void main() {
// 在纹理上寻找对应颜色值
gl_FragColor = texture2D(u_image, v_texCoord);
}
</script>
1、添加滤镜
添加滤镜的关键点在于 shader(着色器),在片元着色器中我们可以看到这样一段代码:
void main() {
// 在纹理上寻找对应颜色值
gl_FragColor = texture2D(u_image, v_texCoord);
}
这里 texture2D(u_image, v_texCoord) 代表着图像解析后的 RGBA 值,当我们直接赋值给 gl_FragColor 时则原图输出,那么滤镜的核心也就在这里,我们需要对其进行改写,下面我们先从最简单的灰度滤镜效果做例子,从 RGB 色转为灰度色的算法我们可以很简单的从网上找出,这里取其中一种 Gray = R0.299 + G0.587 + B*0.114,实际运用如下:
void main () {
vec4 color = texture2D(u_image, v_texCoord);
float gray = 0.2989*color.r+0.5870*color.g+0.1140*color.b;
gl_FragColor = vec4(gray,gray,gray , color.a);
}
2、传输到 WebRTC
在完成滤镜后,又该如何将其传输到 WebRTC 中呢?
有的同学使用过 WebRTC 会知道 WebRTC 的传输离不开媒体流(MediaStream),MediaStream 是一个媒体内容的流,一个流包含几个轨道,比如视频和音频轨道。
前面我们提到了,WebGL 的使用是在 canvas 中进行的,我们可以通过 canvas 的 caputureStream API 获取到 mediaStream 对象,获取后即可进行传输。
五、总结
通过上述的学习,相信大家对 WebGL 的概念有了一定的了解。当然,要想实现复杂的美颜滤镜效果还有很多内容需要学习。
此外,即构在 Web 端提供了成熟的美颜功能,只需简单几步,即可实现不同的美颜效果,感兴趣的同学可以通过链接了解更多:开发者中心 - 即构科技
参考资料:
WebGL 及其在 WebRTC 中的应用的更多相关文章
- webrtc中APM(AudioProcessing module)的使用
一,实例化和配置 AudioProcessing* apm = AudioProcessing::Create(0); //这里的0指的是channelID,只是一个标注那个通道的表示 apm-> ...
- Android IOS WebRTC 音视频开发总结(八十七)-- WebRTC中丢包重传NACK实现分析
本文主要介绍WebRTC中丢包重传NACK的实现,作者:weizhenwei ,文章最早发表在编风网,微信ID:befoio 支持原创,转载必须注明出处,欢迎关注我的微信公众号blacker(微信ID ...
- Android IOS WebRTC 音视频开发总结(八十六)-- WebRTC中RTP/RTCP协议实现分析
本文主要介绍WebRTC中的RTP/RTCP协议,作者:weizhenwei ,文章最早发表在编风网,微信ID:befoio 支持原创,转载必须注明出处,欢迎关注我的微信公众号blacker(微信ID ...
- webrtc中的带宽自适应算法
转自:http://www.xuebuyuan.com/1248366.html webrtc中的带宽自适应算法分为两种: 1, 发端带宽控制, 原理是由rtcp中的丢包统计来动态的增加或减少带宽,在 ...
- WebRTC中的NetEQ
NetEQ使得WebRTC语音引擎能够快速且高解析度地适应不断变化的网络环境,确保了音质优美且缓冲延迟最小,其集成了自适应抖动控制以及丢包隐藏算法. WebRTC和NetEQ概述 WebRTC Web ...
- ULPFEC在WebRTC中的实现[转载]
一.WebRTC对抗网络丢包的两种手段 丢包重传(NACK)和前向纠错(FEC).FEC是一种前向纠错技术,发送端将负载数据加上一定的冗余纠错码一起发送,接收端根据接收到的纠错码对数据进行差错 ...
- webRTC中回声消除(AEC)模块编译时aec_rdft.c文件报错:
webRTC中回声消除(AEC)模块编译时aec_rdft.c文件报错. 原因是: 局部变量ip跟全局变量冲突的问题,可以将局部变量重新命名一下,就可以通过编译了. aec_rdft.c修改以后文件代 ...
- webRTC中语音降噪模块ANS细节详解(一)
ANS(adaptive noise suppression) 是webRTC中音频相关的核心模块之一,为众多公司所使用.从2015年开始,我在几个产品中使用了webRTC的3A(AEC/ANS/AG ...
- webRTC中语音降噪模块ANS细节详解(二)
上篇(webRTC中语音降噪模块ANS细节详解(一))讲了维纳滤波的基本原理.本篇先给出webRTC中ANS的基本处理过程,然后讲其中两步(即时域转频域和频域转时域)中的一些处理细节. ANS的基本处 ...
- webRTC中语音降噪模块ANS细节详解(三)
上篇(webRTC中语音降噪模块ANS细节详解(二))讲了ANS的处理流程和语音在时域和频域的相互转换.本篇开始讲语音降噪的核心部分,首先讲噪声的初始估计以及基于估计出来的噪声算先验信噪比和后验信噪比 ...
随机推荐
- mysql 与驱动版本对应关系
原链接:点我直达
- 全网最适合入门的面向对象编程教程:04 类和对象的 Python 实现-为自定义类添加方法(PySerial 库接收串口数据)
全网最适合入门的面向对象编程教程:04 类和对象的 Python 实现-为自定义类添加方法(PySerial 库接收串口数据) 摘要: 本文我们主要讲解了如何为自定义类添加方法,pyseria 库的基 ...
- ELK Stack - Elasticsearch · 搜索引擎 · 部署应用 · 内部结构 · 倒排索引 · 服务接入
系列目录 ELK Stack - Elasticsearch · 搜索引擎 · 全文检索 · 部署应用 · 内部结构 · 倒排索引 · 服务接入 ELK Stack - Kibana (待续) ELK ...
- [oeasy]python0122_日韩字符_日文假名_JIS_Shift_韩国谚文
日文假名和韩国谚文 回忆上次内容 上次回顾了非ascii的拉丁字符编码的进化过程 0-127 是 ascii 的领域 世界各地编码分布 拉丁字符扩展 ascii 共 16 种 由iso组织制定 从 ...
- ABC362
A link 判断即可... 点击查看代码 #include<bits/stdc++.h> using namespace std; int r,g,b; string c; signed ...
- 【Spring-Security】Re07 持久化的记住我
Security记住我功能底层实现依赖于SpringJDBC组件,如果有持久层框架的话,就由持久层框架实现 演示案例的选型,MysqlJdbc + MybatisStarter <depende ...
- 关于Isaac Gym的两个版本比较:IsaacGymEnvs/omni.isaac.gym
原文地址: https://zhuanlan.zhihu.com/p/590468555 重点: IsaacGymEnvs (IGE)和 omni.isaac.gym (OIG)是两个东西. 原文内容 ...
- 如何配置docker pull代理
参考: https://blog.csdn.net/vic_qxz/article/details/130061661 经过验证确实有效.
- 对于强化学习算法中的AC算法(Actor-Critic算法) 的一些理解
AC算法(Actor-Critic算法)最早是由<Neuronlike Adaptive Elements That Can Solve Difficult Learning Control P ...
- 【转载】 nvidia-smi - Persistence-M (Persistence Mode)
原文链接: https://blog.csdn.net/chengyq116/article/details/103224622 版权声明:本文为CSDN博主「Yongqiang Cheng」的原创文 ...