EmscriptenでビルドしたWebGLアプリをNode.jsで動かす
EDIT: 普通にHappy-DOM不要だった... https://github.com/okuoku/emtestapp/commit/a7dd4417b12d04db33f65f7666905ef6e91af740
前回:
前回は出画が確認できなかったが、今回はちゃんと絵が出た。画面表示と入出力はまだ無い。
OpenGLは (0,0) が左下にあるため、単純にフレームバッファをコピーすると上下が反転してしまう。
ちゃんと書けている。(動作させているのは、 ImGUIのEmscriptenサンプル https://github.com/ocornut/imgui/tree/1fb26d18c42cf90d4fb3f99da453912cccb6c3d3/examples/example_emscripten_opengl3 )
コードはGitHubに置いておいた:
作戦
作戦は前回と同じく、Node.JSにDOM実装ライブラリを読ませ、ブラウザ環境をfakeして動かすことにする。使用したライブラリもほぼ前回同様。
- Happy-DOM (
happy-dom
) https://github.com/capricorn86/happy-dom - headless-gl (
gl
) https://github.com/stackgl/headless-gl - pngjs(スクリーンショット用)
Happy-DOM
今回は前回使用したjsdomではなく、Happy-DOMという実装を使ってみた。最近Happy-DOMは <script>
タグの中身を eval
するようになったので、今回のような目的に使えるんじゃないかと思ったので。
... 残念ながらこれはハズレで、確かに 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実装は使わなくても良いんじゃないかな。。
Discussion