Quantcast
Channel: Node.jsタグが付けられた新着記事 - Qiita
Viewing all articles
Browse latest Browse all 8691

Electron上でVulkanを動かすことに成功しました(しかも現実的な範疇で)

$
0
0

この話の続きです。

https://qiita.com/nanikore55554/items/4ad9fca5d23f2c459f98

要約すると「Electron上でVulkanは動かせたけど、遅すぎて10fpsも出せませんでした。」という話です。

で、今回はなんとか現実的な範疇にまでプログラムを軽くする方法はないかと考え、実際にやってみた結果です。

1. そもそも何故重いのか?

前回も話しましたが、生の画像データ(RGBAのデータがそのまま入ってるconst char*型のデータ)からJpegへの変換が重すぎる事が原因です。とすれば、この部分をなくせば軽くなるはずです。

2. 生の画像データをElectron上で表示する方法

だが、ここで問題があります。Electron(正確にはウェブブラウザ)には生の画像を表示する方法がありません。これがあったからわざわざJpegへデータを変換していたのです。

しかし、回避方法があります。前回も触れたWebGLで表示する方法です。WebGLはUint8Array型のデータをテクスチャとして扱う事ができます。生の画像データを毎フレームごとにテクスチャにして表示すれば一々Jpegで変換する事なく表示する事ができるはずです。

3. 実際にやってみた方法

下記のQiitaにあるソースコードを参考にして作成しました。

https://qiita.com/aa_debdeb/items/4a95646e284987946019

このソースコードを改造して作成したソースを一部抜粋します。

sample.js
setInterval(()=>{//Vulkan部分を実際に表示する関数bar.main_loop();//Vulkanで生成した画像をスクリーンショットとして撮る関数bar.make_ss();gl.clearColor(0.0,0.0,0.0,1.0);//bar.send_raw_imageはスクリーンショットをjs側に送信する関数pixels=newUint8Array(bar.send_raw_image().buffer.slice(0,texWidth*texHeight*4));texture=gl.createTexture();gl.bindTexture(gl.TEXTURE_2D,texture);//texWidthは横幅、texHeightは縦幅gl.texImage2D(gl.TEXTURE_2D,0,gl.RGBA,texWidth,texHeight,0,gl.RGBA,gl.UNSIGNED_BYTE,pixels);gl.texParameteri(gl.TEXTURE_2D,gl.TEXTURE_MAG_FILTER,gl.LINEAR);gl.texParameteri(gl.TEXTURE_2D,gl.TEXTURE_MIN_FILTER,gl.LINEAR);gl.bindTexture(gl.TEXTURE_2D,null);gl.clear(gl.COLOR_BUFFER_BIT);//シェーダを用意する関数    gl.useProgram(program);gl.activeTexture(gl.TEXTURE0);gl.bindTexture(gl.TEXTURE_2D,texture);gl.uniform1i(uniforms['u_texture'],0);gl.drawArrays(gl.TRIANGLES,0,6);},32);

4. 結果

普通に30fpsが出ました。それどころか、60fpsも余裕で出来ます。

前回、10fpsも出なかった事を考えれば大きな進化です。

しかし、CPUへの負担は大きく、30fpsで8%、60fpsで20%以上CPUのリソースが使われました。

負担となっているのは
pixels = new Uint8Array(bar.send_raw_image().buffer.slice(0, texWidth*texHeight*4));
の部分です。ここをnew Uint8Array(texWidth*texHeight*4)にしたらCPUの負担が一気に1%以下へ減りました。この部分をどうにかすれば、もっとElectronでVulkanを動かす事が現実的になると考えられます。

5. もっと早くする方法がある?

実はもっと早く出来るかもしれない方法があります。前に述べたNVJpegを使ってエンコードし、Electronで表示する方法です。また試していませんが、libjpeg-turboを使うより早いらしいです。ただし、NVIDIA製のGPUでしか動かない(Electron最大の武器であるクロスプラットフォームが無くなる)という致命的な欠点があるので使って意味があるかどうかは微妙なところです。(どうも調べたら思ったより速度が上がるわけでも無さそうですし)

まぁ、Electronじゃないけど「HTMLで作るアプリは非常に作りやすい」という点だけに着目して専用のプラットフォームだけで動くHTML製ネイティブアプリを動かしている製品もありますけどね。あの携帯型ゲーム機とかゲーム機とかゲーム機とかな。
(詳しく知りたい人は「任○堂 react.js」と検索すると幸せになれるよ)。

6. 前回触れなかったこと

実はVulkanだとスクリーンショットを撮るプログラムが非常に軽い。

本来、スクリーンショットを撮るというのはCPUの負担の大きいものです。
一回だけ撮るのなら問題有りませんが、毎フレームごとに撮るとなるとかなり負担は相当増大します。しかし、今回のプログラムでは非常に軽かったです。

これを生かせばもっとヘンテコで有用なプログラムを作れるかもしれません。

最後に分かった事

1.やっぱりWebGLは凄いと思う
2.ただ、ここまで来たら何かきっかけがあればWebGPUはそんなに必要ないのかも?
3.各ウェブブラウザは生データの画像も表示できるようにすべきだと思う


Viewing all articles
Browse latest Browse all 8691

Trending Articles