ムラサメ研究ブログ

主にゲームやプログラミングのログ

WebAssembly Windows環境構築

Windows環境を作るにあたって

公式ページでは下記のように http://webassembly.org/getting-started/developers-guide/

The instructions on this page are applicable to Linux and Mac OS X systems. Similar instructions for Windows systems are forthcoming.

Windows環境の構築については まだ手順がなさそうなので 挑戦してみます

構築

基本的には公式の LinuxMac環境構築を参考にします http://webassembly.org/getting-started/developers-guide/

ChromeのWebAssembly有効化

chrome://flags/#enable-webassembly と Chromeで入力し WebAssemblyを有効にし 再起動させる!

emsdkをインストール

https://kripken.github.io/emscripten-site/index.html

ダウンロードページよりWindowsバイナリを入手しインストール インストール時にパスも通してくれるので 私は通した。

emsdkのパッケージ更新

Linuxの手順で行うと、gitがないと怒られたので、gitも入れます

> emsdk update
> emsdk install git-1.9.4
> emsdk install clang-incoming-64bit emscripten-incoming-64bit sdk-incoming-64bit
> emsdk activate clang-incoming-64bit emscripten-incoming-64bit sdk-incoming-64bit

一通り環境整ったはずなので テストします

emsdk テスト

上記の公式をもとに、Cでソースをかきます たとえば hello.c を作成

#include<stdio.h>
int main(int argc, char ** argv ){
  printf("Hello, world!\n");
}

ビルドします

> emcc hello.c -s WASM=1 -o hello.html

結構コンパイル時間かかったし Warningもいっぱい出ましたが無事ファイルが複数できました before.js、hello.html、hello.js、hello.js.temp.js の4ファイルが私の環境ではできました。 このうちの hello.htmlが目的のものなので ブラウザで表示しましょう。

Apache等あればそこで表示してもいいです 公式では pythonを使って

> python -m SimpleHTTPServer 8080

ブラウザより localhost:8080/hello.html

をたたくと、Emscriptenウインドウに Hello,World! が表示されるはず。 表示されたら成功! おめでとう!

とのことらしいですが、期待していたバイナリが出ていないような・・・

> emcc -O2 hello.c -s WASM=1 -o hello.html

と、最適化オプションつけると hello.wasm、load-wasm-worker.js、hello.html.mem などの 怪しいものが出てきます・・

このあたり 一度調査必要ですね

とりあえず公式的には環境完成のようです

おれはMacbookをやめるぞ!ジョジョーーッ!!

Macbookやめました

まずはMacbookを手に入れる所から

Macbookが必要になった事

私はずっとWindowsを愛用してきた。もちろん CygwinLinuxを内部にインストールしLinuxも使っていた Macさんの事は話で聞いていたものの、特にWindowsでも困ったことがないし、仕事もWindowsで十分食ってたので Macさんは触ったことがありませんでした

ところが iPhoneが出て、iPhone用のアプリを開発するために Macが必要になりました 2011年の暮れに、当時常駐案件を請けていたM社にて ”自作のレンダリングエンジンをAndroidiPhoneに移植してくれ” というオーダーが下った

自作のレンダリングエンジンは DirectX11と8086アセンブラSIMD、CUDA等を使って書かれており Android/iOSに移植するには 3Dエンジンを OpenGLES2.0(開発当初は 1.5しか出てなかったので1.5)に変更し 8086アセンブラを ARMに変更。 MASM記法からGas記法にも変更・・ SIMDは Arm用のNEONに書き換え CUDAは GPGPUは当時はスマホで安定して使えなかったため廃止

こんな 大変なオーダーだったんですが一番困ったのは iPhoneアプリ開発にはMacが必須! 私はMac持ってないし触ったこともなかった事

Macbook買うぞ

2011年も終盤にさしかかった時に仕事のために購入を決定した 仕事で使うので AirではなくProにした サイズは 15インチがちょうどバランスが良いと思った

Retinaが出たばかりの頃で、Retinaモデルは非Retinaモデルかで悩んだが、Retina基板が必要なため 非Retinamモデルにはあった光学ドライブRetinaモデルではなくなっていた 光学ドライブは仕事に不要なので 分解しドライブを外し、かわりにSSDを装着させ 256GBのSSD+1TBのHDD でFusionDriveを作る改造をすることにした。当然SSDは評判の高いIntelのSpeedDemonだ! ついでにメモリも搭載可能なMAXに増やして RAMドライブを作り ボクの考えた最高のMacbookProを手に入れた!

MacbookProとの生活

初めてのMacで戸惑うかと思ったが、実はWindows8よりも Windowsらしく、Windows7とまったく同じように使えた。 さらに Bashが付いていて CygwinWindowsよりも快適であった! 肝心のC++コンパイラ XCODEは VisualStudioに比べると格段に貧弱であったり、いろいろ不満点が無いわけではないが MBPとの生活はとても良かった 仕事にいくにも 遊びにいくにも、常に背中には MBPを背負い。 重さも2キロ少しで、軽い筋トレ程度である 電源アダプタは1個8千円もして 足元みられてるなーと思ったが、家用、職場用、持ち運び用と 3個買った。 2011年の暮れから Android/iOSの仕事をたくさん請けて、Macbookが無ければ仕事にならない状態だった

少し状況がかわってきた

2013年の頭から、iOS技術者というのが増え、iOSの開発しかしない(出来ない)人があふれてきたように思う 私の周りでは、どちらかというと Android技術者が不足していたため ほぼAndroid一本になる 2014年頃からは ゲームサーバー案件で、JavaC++を使った案件も増えた UNITYやcocos2d-x、WebGL案件もこなした。 この頃から Macが必須ではなくなっていたが、MBPはかわいいし、パフォーマンスも良かったので愛用していた

先天性の病気みつかる

買った当初から困った現象があった スリープしたあとレジュームできず落ちたり、起動しているが画面がつかなかったり 急に再起動したり けっこう困っていたが、我慢できないレベルではないので我慢していたが 購入から3年以上すぎてから Appleはビデオに関するロジックボードの不具合をみとめ 無料修理をはじめた ところが 私のMacbookは 買った初日に魔改造したため、無料修理の対象外らしく 交換してもらえなかったし 仕事も常に回っていたので 1日たりともMBPを手放せる状態ではなかった

そして伝説に

2015年に 何度か立ち上がらなくなり ごまかして使っていたが 2016年6月 完全に沈黙してしまった 一応 AppleStoreで話きいてくるが きっと修理ダメだろう。 金だせば修理してくれると思うけど このまま文鎮にするぞ! 安らかに眠れ R.I.P SSDとHDDとメモリだけ 取り出そう

交代要員1 Lavie Tab W

2015年 MBPが調子わるいので、万が一の事を考え 予備マシンの検討をした 同じくMacbookにするのが最初の考えだったが iOS案件を2年請けてなかった事 必要になれば買えばいいや とのことで、使用目的を完全にしぼることにした。

当時は打ち合わせも多く、お客さんのところによく出入りしていたため 軽くて移動させても壊れにくいPC SSD搭載のタブレットPCに決めた 各社タブレットPCがあったが、最も軽く タッチペンワコム搭載で 高性能な Lavie Tab W に決定した 重さはなんと500gちょい! キーボードつけても900g程度! 旅行にもちょうどいいね! 魔改造して SIMを挿せるようにする予定だったが、テザリングでいいやってことで 改造していない タブレットPCゆえに スペックは低く、開発には向かないが なんとか開発につかえた JavaScript等の案件には十分だった

ただ、OSがあえての32bit(メモリを効率的に使うためにスペック低いマシンでは多い)のため 開発ツールが動かないものが多いのが難点

RazerBladeとの出会い

UnrealEngine4の仕事を始めた。当然 タブレットPCで動くわけもなく。 ただただUE4が快適に動くPCを探した MacOSでは UE4はちゃんと動かないため WindowsのゲーミングPCしか選択肢がなかった 色々なゲーミングPCをみたが、問題は重量と形状だった。 たいていのゲーミングPCは重い! 筋力で解決すればよいが、限界がある。毎日4キロのPCなんて持って歩きたくない そして ゲーミングPCといえば あえてのゴツいデザインが多く、カバンに入れて持ち運ぶのが面倒だった

そして 色々悩んでいたら 見つけました! 軽くて、シンプルデザインで、スペックすごく高い奴 Windows版のMacbook、黒いMacbookともいわれる RazerBlade 重さは 2キロちょいと Macbookと同じか少し重い程度で CPUはcore i7 6世代。GPUはなんと Geforce GTX 1060搭載。 しかも ビデオに低負荷状態の時は 省エネの オンチップGPU Intel 530を使うという とても賢い仕様

ところが問題は、日本では発売されていないの事! Amazon.comで購入を試みたが、あと一歩のところで リチウムイオンの輸出規制などで購入拒否される 色々な輸入方法を探していたら、公式が日本で通販をはじめた! ただし 入荷未定・・

すると ツクモがRazer専門店をオープンするとのニュースが! 初日にいき PCを買おうと現金もっていくも 入荷するかわかりません。予約だけ承っております・・・

とりあえず 予約だけしておいた

そして 本当に年末。12月の末に、日本の公式ページにて 販売開始アナウンス! 価格は 税込み26万 MacbookProの新型と同じぐらい。許容範囲だ

迷わず買った

その数日後にツクモより、販売決定したとの連絡があった

そして 今 RazerBladeから書いている。

ドラクエもFFも すべてのベンチマークが、超快適になる。 すごいノートPCだ UE4もUNITYもサクサク動く すべてにおいてパーフェクトだ そして Macbookとちがい、ゲームができる!

すごい! RazerBlade 最高!

こうして Macbookを辞めた

WebAssembly 調査!

新年一発目は WebAssembly

今年(会社自体は6月はじまりなので 2016年度下期)に、会社の方針として C++アセンブラの高度な技術を一番の武器に活動することを決めました もちろん今までのようにゲームが主軸になると思いますが ゲーム&ビジネス限定せず 今まで以上にC++を頑張ろうとおもいます

そんな中で気になるものが WebAssembly

今までJavaScriptしか動かなかったブラウザにおいて、ネイティブに近いバイナリフォーマットが制定されたようです 一言でいうと とても速くなるらしいですが、ほかにも色々な似たテクノロジがあるので 簡単にまとめます。 間違ってる部分あったらごめん

最初のJavaScript

元来ブラウザは静的な表現しか出来なかったが、JavaScriptの登場により、動的に変更する事ができるようになった Mozillaが開発したが、すぐさま IESafariと追従し、後にGoogleChromeを作った際も対応していた 当初は 個人のホームページで遊び要素程度に思っていたが、ブラウザを使ったビジネスアプリやサービスが増え JavaScriptは主役になったが、インタプリタ実行のため非常に遅かった

Flash(ShockWave)

Adobe ブラウザ上でネイティブのように動くVMの先駆け 息が長くほとんどのブラウザでサポートされていたが、突然Macが対応を終了しHTML5

JavaApplet

Sun ブラウザ上で動くJavaVM

ActiveX

Microsoft。 他のブラウザが対応しなかったため IEの特定バージョンでしか動かない COMテクノロジ(.netの前身)VM上で動く

v8エンジン

GoogleJavaScriptを高速実行するためのエンジンを開発 JITコンパイルにより ロード時にネイティブコードに変換されるため 実行速度は非常に速い また サーバサイドにJavaScriptを使った node.jsも作られる

HTML5WebGL

HTMLが色々と見直され 色々と高速かつ便利になり、Flash等のVMが不要になった ブラウザ上で高速な描画が可能に。 OpenGLES2.0とほぼ同機能がJavaScriptで提供された。

ES6

JavaScriptは、小さなものを作るには楽だが、大規模開発には色々と問題がある 変数は基本的に全部グローバルであり、ネームスペースの概念がない オブジェクト指向に慣れている人には Classが存在しないのも使い勝手が悪い それらの問題を解決するために、JavaScriptの新しい規格が登場した しかも Babelなどを使い、ES5にトランスパイル可能なので 古いブラウザでも実行可能に

NaCl

Googleが作った。 LLVM技術を使い、Emscripten等で C++からブラウザ用のネイティブバイナリを作り、ブラウザ上でネイティブ実行される ネイティブなので当然とても速い ただし、対応していないブラウザでは実行することができない WebAssemblyと同じ思想のように思えるし、WebAssemblyよりも速いかもしれないが Chrome以外に搭載されず 消える運命に。

Asm.js

Mozilla製。 NaClに対抗して作られた 型情報付きのJavaScriptサブセット JITコンパイルにより劇的に高速になったJavaScriptだが、型情報がないためネイティブには全く歯が立たなかった。 型情報を追加することで、ネイティブのおよそ1.5倍程度の速度まで迫ることができた しかも 非対応ブラウザでも普通のJavaScriptとして動作する ただし、人間が手で書くには困難なため、C++等からEmscriptenを使い変換する

WebAssembly

GoogleMozillaMicrosoftApple が共同開発!! NaClに似た思想で、JavaScriptバイナリにする おそらく NaClと違い完全にネイティブコードにせず、中間言語にとどめ 各社ブラウザがJITコンパイル しやすくしている Asm.jsと同じく 型情報も持っている。ネイティブと比較し1.1~1,2倍程度らしい ここで勘違いしてはいけないのは、バイナリになったから実行速度が上がるわけではない事。 元々JITコンパイルされているので、JavaScriptは実行速度は速い 速くなるのは バイナリコードになりデータ量が少なくなったことと、中間言語なのでコンパイル時間が劇的に向上する事によるものである おそらく、ロード時以外はあまりAsm.jsと変わりがないと思われる 今現在は C++からLLVM経由でコンパイルする事しかできないが 順次色々な言語で対応される Rustが対応開始したらしい

まとめると

今まで色々とJavaScriptの高速化や ネイティブアプリの実行があったが、ブラウザ各社の足並みが揃わず終了したが WebAssemblyはほぼすべてのブラウザメーカーが共同開発しているため、期待がもてる JavaScriptはAsm.jsで 型付け可能になり十分高速化されたが 中間言語バイナリ化することで データロード速度、コンパイル速度が向上した 現在は C++からコンパイルする必要がある

現状出来る事

C++で出来ることはだいたい出来るようです STL、pthread、OpenGLSDL・・・ などなど

今後追加予定

共有メモリを使った高度なスレッド ゼロコスト 例外処理 fixed-width SIMD GC/DOM などなど 新機能が追加予定のようです

現状でも色々できそう

次はWindowsでビルド環境つくるぞ

今度記事かくけど、Macやめましたので Windows10で環境構築しようとおもいます

http://webassembly.org/getting-started/developers-guide/

The instructions on this page are applicable to Linux and Mac OS X systems. Similar instructions for Windows systems are forthcoming.

公式ページでは LinuxMacでの手順はあるが、Windowsは また今度ね! とのことだが おそらくWindowsでも問題ないので 挑戦する!

Begin 2017年

2017年はじまりました まず2016年の振り返りを形式上行う

2015年に スマホのマージャンゲームのソーシャルサーバ&マッチングサーバを請けたものの残り作業で 1月2月は、そちらの作業に費やした

3月あたりは休暇を取りつつ、大手のゲームメーカーより JavaScriptWebGL向けのゲームのモック作成の仕事

5月から激動。大手ゲームメーカーの案件を受託し UnrealEngine4でゲーム開発 フロントの開発と、サーバー側のスーパーバイザーやモック、仕様などを行い従業員もMAX8人いれ 大がかりなプロジェクトになった そのまま 12月までその案件一筋で活動する まったく動いていなかったプロジェクトをチームビルディングを半分変更し立て直し ゲームとして見せられるものは作った 本当は今年も継続する予定だったが、技術ではない 社内政治的なものにまきこまれ 継続不可能になったりして、今考えても 社長としての正解はどれだったか判らない。

2017年は 絶賛プロジェクトを探し中 ありがたいことに 10ほどすぐに案件の話があったが 元々1月というのは 案件の話はくるが決まることが少ない。 実質2月からの仕事を選ぶ期間と思っている

今 色々な案件をもらい、持ち帰りにするか常駐にするか、事業内容で色々と悩んでいる

2017年は 残ってくれたみんなに 安心してもらうために、安定したチームつくりを目指そうと思う あとは会社の強みを決める 色々話した結果

C++アセンブラに強い ゲームエンジンカーネルが作れる C++による超高速リアルタイムサーバが作れる

このあたりかなー と思い、それらに合致する案件2社を第一希望に据えて交渉中

2017年もC++、WebAssembly 等を中心に頑張ります

【今更だが】 CComPtrのoperator&でassertで落ちる場合は read目的なら .p()を使うといいぞ

はじめに

なぜいまさらCOMなのか? と言われると DirectXを触っているからである

CComPtrとは?

COMオブジェクトを扱いやすいようにした テンプレート。 いわゆるスマートポインタ

COMは、shared_ptrのような参照カウント方式のスマートポインタだが、shared_ptrと明らかに違うのは 参照カウントのメンバとメソッドが、shared_ptrの場合は shared_ptrが持っているが COMの場合は オブジェクトのベースクラス IUnknownオブジェクトが持っている点である ゆえに COMオブジェクトを shared_ptrで運用するのは あまり効果的でない

boost::intrusive_ptr は、オブジェクトに参照カウントを保持するスマートポインタに対応しているので CComPtrにかえて使うことも出来る

基本的には

void intrusive_ptr_add_ref(IUnknown* p) { p->AddRef(); }
void intrusive_ptr_release(IUnknown* p) { p->Release(); }

のように、参照カウンタアクセス関数を置き換えれば良い

CComPtrを使う

基本的には、今まで生ポインタで扱っていたものを置き換えればよい

ID3D11Device                *device;
ID3D11DeviceContext         *context;

D3D11CreateDevice( ほげほげ, &device, ほげ, &context )


...

context->Release();
device->Release();

CComPtr<ID3D11Device>                 device;
CComPtr<ID3D11DeviceContext>          context;

D3D11CreateDevice( ほげほげ, &device, ほげ, &context )

と、するだけでよい。

変わったのは CComPtr を使い、スマートポインタにしたこと (x)->Release() がなくなったこと

の2点。

CComPtrでは、値の代入時に Addref()が呼ばれ参照カウントをインクリメントし スコープから消えると Release()が呼び出され参照カウントがデクリメントされる ので、Releaseをする必要がない。

たとえ例外等でRelease呼ぶ前にスコープが消滅しても Releaseが呼ばれるようになった とても安全!

もちろんこの後 device->ほげ と、通常のポインタと同じように使うことが出来る

operator&問題

上記の CreateDeviceでは、新規にオブジェクトを作成したので問題が生じなかったが たとえば オブジェクトのポインタを必要とする時は問題が発生する

通常は、元々中身はCOMオブジェクトへのポインタであり、Create時以外は ポインタのポインタを使うことがないのだが DirectXでいえば、バッファー、テクスチャ配列、レンダーターゲット配列等で ポインタのポインタが必要となるケースが有る たとえば

ID3D11Buffer      *vertexbuffer;

...
device->CreateBuffer(&bd, &InitDatta, &vertexbuffer);

...
context->IASetVertexBuffers(0, 1, &vertexbuffer, &stride, &offset);

を愚直にCComPtrにすると

CComPtr<ID3D11Buffer>     vertexbuffer;

...
device->CreateBuffer(&bd, &InitDatta, &vertexbuffer);

...
context->IASetVertexBuffers(0, 1, &vertexbuffer, &stride, &offset);

となるが、device->CreateBuffer の部分で、DebugAssertion Failed! が発生する

f:id:murasame-labo:20161212153806p:plain

コードを追っかけると

    T** operator&() throw()
    {
        ATLASSERT(p==NULL);
        return &p;
    }

CComPtrでアドレスを取る時(operator&)は、内部ポインタが 非NULL時は Assertで落ちるようになっている

おそらく、内部ポインタが存在する時に Create等でポインタを書き換えると元のポインタがリークするので そのための警告と思えるが 今回の IASetVertexBuffersは、ポインタを書き換える事はない。単純な参照なので Assertを突破したい

が、スマートポインタ等でよくある get()等がみつからない この場合は ポインタの内部メンバ pを直接参照するといい

CComPtr<ID3D11Buffer>     vertexbuffer;

...
device->CreateBuffer(&bd, &InitDatta, &vertexbuffer.p);

...
context->IASetVertexBuffers(0, 1, &vertexbuffer, &stride, &offset);

これで問題ないコードができた

Unreal4.14 ノンフォトリアルに挑戦中

はじめに

一般的に Unrealといえばフォトリアルなものに強く、アニメなどの ノンフォトリアル(NPR)には弱い というイメージが有り たしかに当たってるのだけど

GUILTY GEAR Xrd -SIGN- にて、UnrealEngine3ではあるが、かなり完成度の高い NPRが動いています

頑張れば出来るんです

NPRに関しては フォワードレンダリングのほうが圧倒的に有利なのですが まずはデファードで何処まで出来るか追求したいですね

でも自分でコードかかないよ!

アンリアルフェス2015で下田さんの発表した NPR アンリアルフェス2015横浜で公開したNPR、トゥーンのアルゴリズムと使い方詳しく解説するよ(*´∀`)う - Qiita

これを実装していこうとおもいます

NPR_Materials

という名前です

UnrealDeveloppersNetworkに入らないとダウンロードできそうにないのかね・・・ おこられたら消そう

とりあえず NPR_Materials Ver0.2をダウンロードし Contentフォルダにコピーします すると コンテンツブラウザに表示されるように・・

f:id:murasame-labo:20161206192954p:plain

導入方法

PP_NPRを右クリックし CreateMaterialInstanceを行う PP_NPR_Inst が作成される

Volume PostProcessVolumeにて ポストプロセスを作成し f:id:murasame-labo:20161206205759p:plain

BlendablesのArrayに 先程作った マテリアルインスタンスを設定 f:id:murasame-labo:20161206205742p:plain

実行

f:id:murasame-labo:20161206205913p:plain

な・・なんと たったこれだけで、アウトラインと トゥーンシェーディングができてしまう 簡単!!

その後は Qiitaを見て色々と調整しましょう

アウトラインはけっこうキレイに出ていますね! トゥーンも 法線いじればキレイに出そうです

ポケモン サンムーン戦記

ゲームのプレイ日記も書くよ! ゲームプログラマやさかい

Myポケモン戦記

最初

ムーンに決定。理由は同じシェアハウスに住んでいる住民がサンを買ったので ニャビーで始める。理由は シェアハウス住民がモクローだったので 火にした

最初は捕まえたポケモンで適当PT 最初の固定PTは ニャビー、コイル、キャモメ

とにかく、コイルが頑丈で強い。はがね&デンキ すばらしい 地面は4倍食らうけど、地面以外にはめっぽう強い コイルを序盤に得たのは大きかった

マケンカニー、ニャースを追加 マクノシタが頑丈強く 固定入り。 現時点で ニャビー、コイル、キャモメ、マケンカニ、ニャースマクノシタ

そろそろ卵を持ち歩くため かくとう&水かぶってる マケンカニを捨てる 水と戦うために アマカジ、ネマシュ育てる ニャースニャビーにお別れ

コイル、キャモメマクノシタ を固定にし その他は色々と使い分ける この期間が結構長い。なにげに良いパーティーだと思う

ゴース手に入れた。結構期待できる。 マクノシタに限界が見えたので、ヌイコグマに変更 サトシゲッコウガも操れるようになったので そろそろパーティーへ 暫くつかってないニャビー 使いたいけどあまりバランス的に必要じゃない スターマン手に入った。有能

今後の育成

コイル(デンキ、はがね) ゴース(どく、ゴースト) キャモメ(みず、ひこう) ヌイコグマ(ノーマル、かくとう) タマザラシ(みず、こおり) ディグダ(じめん、はがね)

が、今そこそこ育ってるなかでバランス良さげだけど、今後バランスPT見直したい。

その他強い&育っている ニャヒート、ゲッコウガ は育てる

ネマシュ、マクノシタ、アママイコ あたりは レベルそこそこあるので 育てる

コイル(デンキ、はがね) ゴース(どく、ゴースト) ヌイコグマ(ノーマル、かくとう) ドジョッチ(みず、じめん) デリバード(ひこう、こおり)

このあたりも オールマイティー