Javascript如何实现GPU加速?

Javascript如何实现GPU加速?,第1张

由 Demi 于 星期四, 2018-09-06 16:10 发表

一、什么是Javascript实现GPU加速?

CPU与GPU设计目标不同,导致它们之间内部结构差异很大。
CPU需要应对通用场景,内部结构非常复杂。
而GPU往往面向数据类型统一,且相互无依赖的计算。
所以,我们在Web上实现3D场景时,通常使用WebGL利用GPU运算(大量顶点)。
但是,如果只是通用的计算场景呢?比如处理图片中大量像素信息,我们有办法使用GPU资源吗?这正是本文要讲的,GPU通用计算,简称GPGPU。

二、实例演示:色块识别。

如下图所示,我们识别图片中彩虹糖色块,给糖果添加表情。


2.1、实例地址(打开页面后,依次点击按钮“使用CPU计算”、“使用GPU计算”):

2.2、运行代码:

var rgb2hsv = funcTIon(r, g, b) { var max = Math.max(r, g, b), min = Math.min(r, g, b), d = max - min, h, s = (max === 0 ? 0 : d / max), v = max / 255; switch (max) { case min: h = 0; break; case r: h = (g - b) + d * (g < b ? 6: 0); h /= 6 * d; break; case g: h = (b - r) + d * 2; h /= 6 * d; break; case b: h = (r - g) + d * 4; h /= 6 * d; break; } return { h: self.hueIndexs[parseInt(h*360)], s: s, v: v } };

运行次数:262144次

2.3、测试结论:

实例中,我们分别使用GPU和CPU进行色相转换(防止光线影响识别准确度),其余步骤均一致。

Javascript如何实现GPU加速?,Javascript如何实现GPU加速?,第2张

2.4、使用GPGPU意义:

GPU与CPU数据传输过程,与GPU实际运算耗时相当,所以使用GPU运算传输成本过高,实测在Android中具有较大优势。

本测试案例是从webAR项目中抽取,需要实时跟踪用户摄像头处理视频流(256*256),使用GPU计算意义非常大,否则无法实现实时跟踪。

三、如何实现GPU通用计算?

3.1、首先,我们通过一张流程图,演示原理:

3.2、实现:

3.2.1、创建顶点着色器,只是传递了贴图坐标。

attribute vec4 posiTIon; varying vec2 vCoord; void main() { vCoord = posiTIon.xy * 0.5 + 0.5; gl_PosiTIon = position; }

3.2.2、创建片元着色器,根据贴图坐标贴图。

precision highp float; varying vec2 vCoord; uniform sampler2D map; void main(void) { vec4 color = texture2D(map, vCoord); gl_FragColor = color; }

3.3.3、根据如上着色器代码,创建程序对象,变量code是我们要传入的用于计算的代码。

// 绑定并编译着色器程序 var vertexShaderSource = '...'; var fragmentShaderSource = '...' + code + '...'; var vertexShader = gl.createShader(gl.VERTEX_SHADER); gl.shaderSource(vertexShader, vertexShaderSource); gl.compileShader(vertexShader); var fragmentShader = gl.createShader(gl.FRAGMENT_SHADER); gl.shaderSource(fragmentShader, fragmentShaderSource); gl.compileShader(fragmentShader); // 创建程序对象 var program = gl.createProgram(); gl.attachShader(program, vertexShader); gl.attachShader(program, fragmentShader); gl.linkProgram(program); gl.useProgram(program);

3.3.4、传入顶点数据,创建一个面覆盖整个画布。

// 顶点数据传输 var vertices = new Float32Array([-1.0, 1.0, -1.0, -1.0, 1.0, -1.0, 1.0, 1.0]); var vertexBuffer = gl.createBuffer(); gl.bindBuffer(gl.ARRAY_BUFFER, vertexBuffer); gl.bufferData(gl.ARRAY_BUFFER, vertices, gl.STATIC_DRAW); var aPosition = gl.getAttribLocation(program, 'position'); gl.vertexAttribPointer(aPosition, 2, gl.FLOAT, false, 0, 0); gl.enableVertexAttribArray(aPosition);

3.3.5、传入原始数据,本例中传入我要处理的图像数据,作为贴图,最终绘制到屏幕。

var gl = this.gl; var program = this.program; var texture = gl.createTexture(); var uMap = gl.getUniformLocation(program, 'map'); gl.activeTexture(gl.TEXTURE0); gl.bindTexture(gl.TEXTURE_2D, texture); gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, canvas); gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.NEAREST); gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST); gl.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.generateMipmap(gl.TEXTURE_2D); gl.uniform1i(uMap, 0); // 绘制 gl.clearColor(0, 0, 0, 1); gl.clear(gl.COLOR_BUFFER_BIT); gl.drawArrays(gl.TRIANGLE_FAN, 0, 4);

欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/dianzi/2716311.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-08-17
下一篇 2022-08-17

发表评论

登录后才能评论

评论列表(0条)

保存