一、什么是Javascript實現(xiàn)GPU加速?
CPU與GPU設(shè)計目標(biāo)不同,導(dǎo)致它們之間內(nèi)部結(jié)構(gòu)差異很大。
CPU需要應(yīng)對通用場景,內(nèi)部結(jié)構(gòu)非常復(fù)雜。
而GPU往往面向數(shù)據(jù)類型統(tǒng)一,且相互無依賴的計算。
所以,我們在Web上實現(xiàn)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 } };運行次數(shù):262144次
2.3、測試結(jié)論:
實例中,我們分別使用GPU和CPU進行色相轉(zhuǎn)換(防止光線影響識別準(zhǔn)確度),其余步驟均一致。
2.4、使用GPGPU意義:
GPU與CPU數(shù)據(jù)傳輸過程,與GPU實際運算耗時相當(dāng),所以使用GPU運算傳輸成本過高,實測在Android中具有較大優(yōu)勢。
本測試案例是從webAR項目中抽取,需要實時跟蹤用戶攝像頭處理視頻流(256*256),使用GPU計算意義非常大,否則無法實現(xiàn)實時跟蹤。
三、如何實現(xiàn)GPU通用計算?
3.1、首先,我們通過一張流程圖,演示原理:
3.2、實現(xiàn):
3.2.1、創(chuàng)建頂點著色器,只是傳遞了貼圖坐標(biāo)。
attribute vec4 position; varying vec2 vCoord; void main() { vCoord = position.xy * 0.5 + 0.5; gl_Position = position; }3.2.2、創(chuàng)建片元著色器,根據(jù)貼圖坐標(biāo)貼圖。
precision highp float; varying vec2 vCoord; uniform sampler2D map; void main(void) { vec4 color = texture2D(map, vCoord); gl_FragColor = color; }3.3.3、根據(jù)如上著色器代碼,創(chuàng)建程序?qū)ο螅兞縞ode是我們要傳入的用于計算的代碼。
// 綁定并編譯著色器程序 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); // 創(chuàng)建程序?qū)ο?var program = gl.createProgram(); gl.attachShader(program, vertexShader); gl.attachShader(program, fragmentShader); gl.linkProgram(program); gl.useProgram(program);3.3.4、傳入頂點數(shù)據(jù),創(chuàng)建一個面覆蓋整個畫布。
// 頂點數(shù)據(jù)傳輸 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、傳入原始數(shù)據(jù),本例中傳入我要處理的圖像數(shù)據(jù),作為貼圖,最終繪制到屏幕。
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);3.3.6、從最終繪制的畫面上,獲取顏色信息作為最終處理結(jié)果數(shù)據(jù)。
1 var pixels = new Uint8Array(gl.drawingBufferWidth * gl.drawingBufferHeight * 4); 2 gl.readPixels(0, 0, gl.drawingBufferWidth, gl.drawingBufferHeight, gl.RGBA, gl.UNSIGNED_BYTE, pixels);3.3.7、完整代碼:
四、有無現(xiàn)成類庫?
大家可以看到,我實現(xiàn)的gpu.js中,并沒有將javascript轉(zhuǎn)換成著色器語言(類C),而是用戶直接傳入著色器代碼。但是github上已有將javascript轉(zhuǎn)換為著色器語言的庫。
https://github.com/gpujs/gpu.js
為什么我沒有直接使用呢?
1、簡單的使用,2k可以實現(xiàn)的代碼,不想引入200k的庫;
2、數(shù)據(jù)輸入輸出可以由自己靈活控制;
3、著色器語言很簡單,特別只是使用基礎(chǔ)運算邏輯的代碼,沒必要由庫從Javascript轉(zhuǎn)換。
沒有WebGL基礎(chǔ)的同學(xué),建議直接使用https://github.com/gpujs/gpu.js,從本文理解整體邏輯;
有一定基礎(chǔ)的同學(xué),建議由自己定制,更為靈活。
另外,這個組件我沒打算深度封裝,也沒打算維護……嗯,就這樣。
作者:萬技師
出處:
原文鏈接:https://www.cnblogs.com/wanbo/p/9100962.html
轉(zhuǎn)載請在明顯位置注明原文鏈接,否則保留追究法律責(zé)任的權(quán)利。
評論
查看更多