プログラミング: 2013年5月アーカイブ

(前回の記事の続きです)

さて、自作のWebGLのゲームをenchant.jsベースで作り直そう、とした場合にですね。
問題となってくることがあると書きました。

それはなにかというと、enchant.jsのWebGLプラグインである「gl.enchant.js」を使うべきか否かという問題です。
gl.enchant.jsはenchant.jsのお作法ベースで簡単にWebGLの機能が使えますよ。という、いわばシーングラフベースに近い3Dライブラリなんですが、
これがまた自由度が低い低い、非常に割り切った設計になっています。

(以下はgl.enchant.jsのバージョン0.3.7の仕様)
・プリミティブの形式はgl.trianglesのみ(ストリップとかファンとかは使えない)
・デプステストやカリングの有無を切り替えられない(有効で決めうちされている)
・自前のシェーダーが使えない(gl.enchan.js内部で独自のシェーダーが使われている)
・ライティングが標準で有効(オフにできない)
・シェーダーを切り替えられないので、マルチテクスチャとか当然できない。

ほんとに、「ボク3D初めて!」な人向けのライブラリですね。
glコンテキストを取得すれば、色々できるのでしょうが、glコンテキストを引き渡してくれるメソッドも無い模様。

一応、任意形状のポリゴンを描画する機能はあるようですが、いかんともしがたい作りです。

とはいえ、改造してしまえばそれなりに便利そうなんじゃないかというのも事実。
というか開発した人が「そういうことやりたかったらぜひ改造してください」的なノリみたいなw

gl.enchant.jsの補助プラグインで、MMDプラグインとかCOLLADAプラグインとかあるしなー。これらの中身まだちょろとしか見ていないんですが、
これらがちゃんと動いているのは、gl.enchant.jsのドノーマルの機能を使っているのではなく、
実際、gl.enchant.jsのメソッドを上書きして、シェーダーをプラグイン独自のものに切り替えたりとかして、色々やっているわけです。

正直、enchant.jsベースにしつつも3D描画についてはglコンテキストを抜き出してgl直打ちした方が自由度は高いんでしょうけども、
gl.enchant.jsベースにすれば、コーディングの作法がenchant.jsベースの作法に統一できるし、シーングラフベースのAPIはいろいろ楽なことも確かです。

問題はパフォーマンスと細かい制御なんですが、
・前者については、作ろうとしているゲームが、FPSやアクションみたいに、べらぼうにシビアな描画パフォーマンスを要求するようなゲームではない。
・後者については、gl.enchant.jsを改造すればいいんじゃね? もしくは機能を上書きするプラグインを開発すればいいんじゃね?

ということで、検討を重ねた結果、gl.enchant.jsベースでやってみようかという方向に傾き中です。

しかしなー。どうなんだろうなー。エフェクトツールの「BISHAMON」がそのうちWebGLランタイムをリリースするらしいし、
そうしたら多分、絶対glを直接いじらないと使えないようなランタイムだろうから、
gl.enchant.jsと併用するには、BISHAMON.gl.enchant.jsみたいなプラグインを自作しないとダメだろうなw

うーん。色々大変になりそうだ……。この判断が吉と出るか凶と出るか……w

っと、その前にまだこのことをbeiさんと相談していないんだった(汗)
こういうことはちゃんと話し合った上で決めないとダメだよな^^;

前回の記事で、WebGLによる3D描画と、enchant.jsによる2D描画を組み合わせることを検討しているという話をしましたが、一つ問題があります。

ゲームループの問題です。

現在、私のWebGLゲームプログラムはrequestAnimationFrameによる自前のループを持っています。まぁゲームなんだから当然ですよね。

で、2D描画をenchant.jsにやらせようと、enchant.jsを軌道(game.start())すると、そう、enchant.jsのゲームループ(requestAnimationFrame)も回るのです。

つまり、ゲームループが2重に発生してしまう。

以下の清水氏による記事では、
http://d.hatena.ne.jp/shi3z/20130521/1369101883

< 引用ここから>

enchant.jsはフレームワークとライブラリの間にあるギリギリの線を狙っている。
 enchant.jsはしかし厳密にはライブラリである。

 なぜかというと、

enchant();

window.onload=function(){
core = new Core(320,320); //ここでコアを初期化する
}

 このように、ライブラリの導入からコアの起動までをユーザが記述する必要があるからだ。
 純粋なフレームワークなら、window.onloadの処理は隠蔽する。

< /引用ここまで>

厳密にはライブラリ、とのことで、その思想含め、「なるほどなぁ」と思いましたが、
やはりenchant.js自身でゲームループを管理している以上、「やはりフレームワークなんじゃないか」という気もするわけです(笑)

で、解決方法ですが、考えられるのは以下の二つですね。

A) enchant.jsを改造して、自前のゲームループを使わせるようにする。
B) 思い切って、ゲームループはenchant.jsに任せてしまう。

いろいろ考えたんですが、A)の改造をした場合、enchant.jsのバージョンアップのたびに改造しなきゃなりません。(いっそゲームループ関連をカスタマイズできるようにしたものをPull Requestしてしまうという手もありますが……多分絶対はねられると思う)

B)の場合、それならもう全部enchant.jsベースでゲームを作り直した方がいいんじゃね? という話にもなります。

実際、enchant.jsはプラグイン含め、日を追うごとにどんどん高機能化・多機能化しており、乗っかってしまった方が、ゲームに求められるもろもろの諸機能を自作するより開発効率は間違いなく上がるでしょう。(パフォーマンス面はちょっと気になるんですけどね)

なので、今のところ、ゲーム全体をenchant.jsベースに作り直してしまおうという方向に傾きつつあります。

ただ、これはこれでまた別の気になる問題があります。それについてはまた後ほど……。

WebGLでのゲーム開発。ぼちぼちと進んでいます。

ゲームのジャンルは何かというとRPGなのですが、最近のRPGといえば、キャラクター同士の会話シーンがありますね。ノベルゲームとかADVゲームみたいなゲームによくある、キャラクターの立ち絵があって、画面下にメッセージボックスがある感じの。

ああいうのは、WebGLで描画するより、2D Canvasで描画する方がいろいろとやりやすいです。

とはいえ、それでも2D Canvasを直に触るのもめんどいので、enchant.jsを採用しました。enchant.js、そういうノベルゲームを簡単に作れるプラグインがありますし(そのプラグインまで実際に採用するかは別にして)

最近のenchant.jsは、デフォルトではDOMベースではなく、Canvasベースの描画システムです。

さてさて、本題はここから。
WebGLは、jpgやpngといった画像ファイルだけでなく、2D Canvasもテクスチャとして利用できるのです。

ということは、enchant.jsで描画した2D Canvasを、WebGLのテクスチャとして利用できるはずなのです。

実際に、こちらのサイト様のコードをベースに、実験してみました。
http://edotprintstacktrace.blogspot.jp/2012/01/html5-canvas-2d-context-webgl.html

実験結果がこちらの動画。
http://www.screencast.com/t/P6rMKeKn

通常のテクスチャ(犬の画像)に、マルチテクスチャでenchant.jsで描画したCanvasテクスチャ(クマ)を合成しています。

enchant.jsのCanvasの中で、描画していない部分(クマの周り)は、アルファが0なので、アルファ抜きもできているわけです。
試してませんが、当然アルファブレンディングもできるはずですね。

というわけで、WebGLと2D Canvasの描画の使い分け、おすすめです。

WebGLであるゲームの開発をやっているんですが、テクスチャ関連で以下のエラーが出てくるんですよ(ちなみにブラウザはChrome)。

RENDER WARNING: texture bound to texture unit 0 is not renderable. It maybe non-power-of-2 and have incompatible texture filtering or is not 'texture complete'

もうね。何かと思って。テクスチャサイズは256x64だし、フィルタリングの指定も間違ってないし。色々ググったり試行錯誤して辿り着いたオチが……。

「テクスチャ画像の読み込みが完了していない状態でレンダリングを行ったから」

あー、たしかに or is not 'texture complete' って書いてあるけどさ……。
ふつー、non-power-of-2の方に注目しちゃうだろ。
おいら、まさかなーあるわけないよなーとか考えながらも画像サイズを256x256に変えてみたりとかアホみたいなことしちゃったじゃまいか。

何が ~ or ~ だ。どっちの原因なのかそこまでちゃんとチェックして、適切にエラーを出せ、と。

WebGLの画像ファイル読み込みは非同期なので、ちょっと横着して、テクスチャの読み込みが完了する前に描画命令しちゃうのはよくある事だと思うのですよ。

そういうケースも考えて、シンプルに「まだロード完了してないよん」とか言ってくれればいいのに、「non-power-of-2」とかいうからもう誤解しちゃったじゃんよ。

こういう「原因は〜〜〜かもしれないし〜〜〜かもしれません」的なエラーって設計した人はどういうつもりで作ったんだろう。
仕様的に判断が難しいというのは考えづらい気がするんだよなー。

このアーカイブについて

このページには、2013年5月以降に書かれたブログ記事のうちプログラミングカテゴリに属しているものが含まれています。

前のアーカイブはプログラミング: 2013年3月です。

最近のコンテンツはインデックスページで見られます。過去に書かれたものはアーカイブのページで見られます。