这是我最近在 CodePen 上制作的 WebGL 演示案例 。它可以捕获网络摄像头的数据(或在无法访问网络摄像头时,从 placekitten 获取备用图像),并将其实时转换为 ASCII 图像艺术 。
文章插图
为了获得更多的复古性,我使用了 90 年代 DOS PC 中常见的 8x8 像素光栅字体(您可能会在某些 BIOS 中看到这种字体) 。
要将图像内容映射到特定字符,我通过使用亮度图选择最佳匹配 。我计算每个 4x4 正方形的像素 。在画板内向下滚动以查看亮度图:
文章插图
我还为这些字体创建了一个编辑器: https://terabaud.github.io/pi...
若干 WebGL 基础知识我将介绍 WebGL 的一些基础知识,但这里仅涉及部分问题 。获取有关详细指导,建议您访问 https://webglfundamentals.org
对于 WebGL,一个常见误解是把它当作浏览器中的 3D 引擎 。尽管 WebGL 技术能使我们在浏览器中提供 GPU 加速的 3D 内容,但 WebGL 本身不是 3D 引擎 。在 WebGL 之上,有专门用于 GPU 加速的 2D 或 3D 内容的图形库(例如用于 2D 的 Pixi,用于 3D 的 ThreeJS) 。
WebGL 本身是很基础的绘图标准库,并且是一个以 GPU 加速的方式,将点、线和三角形绘制到 html <canvas> 元素上的库 。
可以通过 getContext (类似于 2D canvas API )检索 WebGL 渲染上下文:
const canvas = document.querySelector('canvas');const gl = canvas.getContext('webgl') || canvas.getContext('experimental-webgl');
一个 WebGL 程序包含多个着色器组件,着色器是运行在 GPU 上的代码,它们不是用 JAVAScript 编写的,而是具有自己的语言,称为 GLSL(GL 着色器语言) 。GLSL 快速概览
- 类似 C语言,着色器程序包含 void main()
- 变量声明也像在 C 语言中一样
- 原始数据类型: int , float , double
- 向量: vec2 , vec3 , vec4 , ...
- 矩阵: mat2 , mat3 , mat4 , ...
- 访问纹理数据的类型: sampler2D
- 内置向量、矩阵运算
- 大量内置功能 , 例如,求取向量的长度( length(v) )
- 顶点着色器计算位置 。
- 片段着色器处理栅格化 。
【如何使用 WebGL 进行实时视频处理】在我的演示案例中,我使用 4 个矢量坐标来覆盖适合整个屏幕的矩形,所有工作都在片段着色器中完成 。
顶点着色器顾名思义,顶点着色器存在于顶点 。它从 JavaScript 代码提供的缓冲区中获取一堆数据,并根据这些数据计算在画布中的相应位置 。
以下代码段将数据从缓冲区拉入一个 attribute 变量,并将其传递给该 gl_Position 变量:
attribute vec3 position;void main() {gl_Position = vec4(position, 1.0);}
片段着色器precision highp float;void main() {vec2 p = gl_FragCoord.xy;gl_FragColor = vec4(1.0, .5 + .5 * sin(p.y), .5 + .5 * sin(p.x), 1.0);}
片段着色器针对每个片段(像素)并行运行 。在上面的示例中,片段着色器从 gl_FragCoord 变量读取当前像素坐标,并通过 gl_FragColor 中的 sin() 计算运行并输出颜色 。gl_FragColor 是一个 vec4 向量,其中包含(红色,绿色,蓝色,alpha),取值各为 0 .. 1 。
GLSL 变量的类型
attributeuniformvarying
上传图像数据您可以使用图像数据访问到着色器中的 WebGLRenderingContext,并将其上传到 纹理 中 。(另请参见: WebGL 基础知识:图像处理 )您可以使用 texImage2D 内部方法 WebGLRenderingContext 将图像数据上传到纹理中 。
// gl is the WebGLRenderingContext const texture = gl.createTexture()gl.activeTexture(gl.TEXTURE0 + textureIndex);gl.bindTexture(gl.TEXTURE_2D, texture);gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, img);// more info about these parameters in the webglfundamentalsgl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR);gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR);
您传递给 texImage2D 的图像数据,可以是 img 元素、视频元素、ImageData 等 。由于视频的图像数据不断变化,因此您必须在 requestAnimationFrame 动画循环内更新纹理 。以下是获取完成的 texSubImage2D。
推荐阅读
- 如何在手机上把aac音频换成mp3,手机怎么将aac转换mp3?
- 如何在Ubuntu系统中重置root密码
- 如何让您面色红润 吃什么补血
- 食疗养胃 10款食疗方教你如何养胃
- 星座性格|收入太低如何解决?砖家:“用私家车拉活,空的房子租出去收钱”
- 教您如何品普洱茶熟茶,教大家如何冲泡出更好的普洱茶
- 验孕棒的使用常识
- 使用小儿皮炎清有哪些注意事项呢?
- 黄茶如何冲泡,怎样品味黄茶
- 政府如何治理雾霾