EmscriptenでビルドしたWebGLアプリをNode.jsで動かす

2 min read読了の目安(約2100字

EDIT: 普通にHappy-DOM不要だった... https://github.com/okuoku/emtestapp/commit/a7dd4417b12d04db33f65f7666905ef6e91af740

前回:

https://qiita.com/okuoku/items/60ea7bb9c20b38505531

前回は出画が確認できなかったが、今回はちゃんと絵が出た。画面表示と入出力はまだ無い。

OpenGLは (0,0) が左下にあるため、単純にフレームバッファをコピーすると上下が反転してしまう。

ちゃんと書けている。(動作させているのは、 ImGUIのEmscriptenサンプル https://github.com/ocornut/imgui/tree/1fb26d18c42cf90d4fb3f99da453912cccb6c3d3/examples/example_emscripten_opengl3 )

コードはGitHubに置いておいた:

https://github.com/okuoku/emtestapp/tree/fe2592e3388b9355626bc0abbaf0d854aa077aeb

作戦

作戦は前回と同じく、Node.JSにDOM実装ライブラリを読ませ、ブラウザ環境をfakeして動かすことにする。使用したライブラリもほぼ前回同様。

Happy-DOM

今回は前回使用したjsdomではなく、Happy-DOMという実装を使ってみた。最近Happy-DOMは <script> タグの中身を eval するようになったので、今回のような目的に使えるんじゃないかと思ったので。

https://github.com/capricorn86/happy-dom/issues/142

... 残念ながらこれはハズレで、確かに eval はされるが、 単にNodeJSの実行コンテキストで eval するだけで、 globalが全然ブラウザにならないためあまり意味が無かった。jsdomはちゃんとこの辺は配慮されていたのでちょっと残念。

ブラウザ風のglobalの提供

// Boot
const scr = wnd.document.createElement("script");

global.my_window = wnd;
global.my_fetch = fake_fetch;
global.my_doc = wnd.document;
global.my_module = my_module;
global.my_screen = my_screen;
global.fake_settimeout = fake_settimeout;

scr.textContent = "var window = global.my_window; var navigator = window.navigator; var fetch = global.my_fetch; var document = global.my_doc; var Module = global.my_module; var screen = global.my_screen; var setTimeout = global.fake_settimeout; \n" + bootstrap;
wnd.document.head.appendChild(scr);

幸いというか当然というか、 eval は元のNode.js環境の eval そのものなので、 global を経由してオブジェクトの引き渡しができる。というわけで、今回は、実行するスクリプトの冒頭に var でグローバル変数として追加する方法を取った。

かんそう

前回のUnity WebGLに比べると、(元々Emscripten自体はNodeJSでの動作も想定しているので、)本当に何もしないで動いてとてもかんたんだった(KONAMI)

もういっそのことDOM実装は使わなくても良いんじゃないかな。。