BlogKLabは、多くのスマートフォン向けゲームを開発・提供しています。スマートフォン向けゲームの開発と運用は、Webソーシャルゲームと比べて格段に複雑で、またコンシューマゲーム開発とも異なったノウハウが求められる領域もあります。このブログでは、KLabのゲーム開発・運用の中で培われた様々な技術や挑戦とそのノウハウについて、広く紹介していきます。〜レンダリングの仕組みを追うpart1〜※この記事ではgitのタグ「v2.74」からブランチを生成してコードリーディングしています。CPUなのか?GPUなのか?前々から疑問に思っていた事がありました。Blenderの画面に表示されている3Dモデル、GPUでレンダリングされているのでしょうか?それともCPUでソフトウェアレンダリングされているのでしょうか?DCCツールはゲームと違い、モデルの頂点が頻繁に編集されるのでメインメモリからGPUメモリへのデータ転送コストが毎回発生するはずなのでこのような疑問を持ちました。マシン環境やDCCツールの機能によってもどちらが適切なのかは変わってるくるはずですが、Blenderはどのような実装になっているのでしょう?レンダリング部分のコードを突き止めるこの疑問の答えを出すためにレンダリング部分のコードを探し出してみましょう。OpenGLのドローコールが呼ばれていればGPUでレンダリングされていると見ていいでしょうし、CPUでピクセルの配列の色を決定しているようなコードが見つかればソフトウェアレンダリングが使われているということになります。最終的に該当部分をコメントアウトしてみて、3Dモデルが消えればそこが答えだと証明できるはずです。ShadingはSolidの状態でのレンダリングについて調べてみます。試しにそれっぽいキーワードでプロジェクト全体を検索してみるレンダリング部分のコードを見つけ出したいので、手始めに「render」や「draw」でソースコード全体を検索してみます。わかってはいましたけど大量に引っかかりますよね・・・。これを1つ1つ見ていくのは人間には無理でしょう。filesこれもやっぱり数が多い。filesおお!これくらいなら1つ1つ見ていく事も可能ですね!手がかりになりそうなenum値が見つかるするとこんなenum値が見つかります。ObjectMode;Blenderを使っている方ならお気付きかと思いますが、モード選択といかにも関係ありそうなenum値ですね。このenum値の中でObjectモードを指し示しているであろう「OB_MODE_OBJECT」で検索してみましょう。filesいかにも怪しいファイルがこの14個のファイルの中にdrawobject.cといういかにも怪しいファイルがあるのでこれを見てみる事にします。drawobject.cの中にはdraw_〜〜〜と名前のついた関数がたくさん存在します。この関数の中に該当するものがありそうです。レンダリング命令の周りのコードにOB_MODE_OBJECTの記述があるかは不明ですが、draw_object()とdraw_mesh_fancy()内にのみOB_MODE_OBJECTが書かれているのでとりあえず追ってみます。この2つの関数の先頭にブレイクポイントを張って実行してみると、2つとも引っかかるようです。いう構造で各関数が呼ばれている事です。dflag);となっており、OB_MESHの定義に飛んでみるとオブジェクトのタイプ(??)がいくつか定義されているのでこれは狙っているオブジェクトのレンダリング部分につながっているかもしれません。draw_mesh_object(...の行をコメントアウトして実行してみましょう。するとデフォルトで表示されているはずのキューブが丸ごと消えます!↓↓↓このコメントアウトを取り消して行を復活させ、今度はdraw_mesh_object()でdraw_mesh_fancy()を呼んでいる場所をコメントアウトしましょう。すると同じくキューブが丸ごと消えます。オブジェクト選択時のオレンジ色のアウトラインも一緒に消えてしまうので、アウトラインのレンダリングもdraw_mesh_fancy()に含まれていると言えます。ゴールは近い!!確認の意味も含めて、アウトラインを残してオブジェクトの面のみを消してみたいですね。Shadingの設定によって変わります。全体検索では大量に引っかかってしまった「solid」で今度はdraw_mesh_fancy()の中を検索してみます。するとヒットするのは9カ所。これくらいであれば1つ1つ追っていくのは簡単ですね。9カ所全て見ていくと、drawFacesSolid()といういかにもそれっぽい関数が4カ所で呼ばれているのがわかります。DRAW_MODIFIERS_PREVIEW)という条件なので違いそう3番目:if文の条件を見るとスカルプトに関連していそうなので除外4番目:if文的に2番目ではないかつ3番目ではないのでこれが正解のはず。よって4番目をコメントアウト。オレンジのアウトラインを残し、面のみが消えました!!さて、コメントアウトをもとにもどします。drawFacesSolidは関数ポインタになっているので、実際に呼ばれる関数を追ってみます。setMaterial)にたどり着きます。この中でOpenGLの命令であるglDrawArrays()が呼ばれているので、Objectモードに関してはソフトウェアレンダリングではなく、GPUを使ってレンダリングを行っている事がわかって当初の疑問が解消され・・・いや、待てよObjectモードについてはGPUレンダリングが行われているのがわかりました。最初に書いた「モデルの頂点が頻繁に編集されるのでメインメモリからGPUメモリへのデータ転送コストが毎回発生する」のは主にEditモードでした。いうわけで、part2につづきます。〜準備編〜プログラマのfmystBです。普段3D関連のプログラミングをする事が多いのですが、様々な局面でちょっとしたテスト用のモデルが欲しくなる事があります。アーティストに頼むほどでもない・・・。そんなときBlenderが使えると便利でして、日頃とてもお世話になっています。毎日のように仕事でBlenderに触れているうちに、内部の仕組みを知りたくなって来たのでコードリーディングにチャレンジしようと思います。宝が星の数ほどBlenderには数多くの3DCG技術が集約されているので、コードを読んで楽しい場所はたくさんあるはずです。Modifiersや物理シミュレーション部分のコードには特に興味があります。オブジェクトの形状を便利に編集できるModifiers機能には高度な幾何学が使われていると思いますし、物理シミュレーションにはプリレンダリングの技術が使われているのでリアルタイムレンダリングとは違ったアルゴリズムを知る事が出来るでしょう。他にも、マシン環境によっては有効となるCUDAオプションのコードを追いかけてみるのもGPGPUプログラマにとっては面白そうですし、Pythonハッカーな人はスクリプト機能の部分に興味があるかと思います。こんな注意書きがあります。once.」Blenderは規模が大きいだけに、一度に全てを知ろうとすれば泥沼にはまるようですね。興味がある部分に絞って理解を深めていくのが長続きするポイントのようです。この連載でも気の趣くままに、面白そうな部分だけピックアップして紹介していきます。環境としてはMacのXcodeを使い、ソースを読むだけではなくブレイクポイントを張りながら実行する事で動作を確認していきます。(後の記事でも触れるつもりですが、Blenderはいたる所で関数ポインタを使っているのでステップ実行せずに読み進めるのはキツいです><)ソースコードの管理はGitが使われており、ダウンロードからXcodeプロジェクトの生成まではこちらに書かれている通りです。コマンドラインのみでビルドする方法も書かれていますが、今回はXcodeでビルドしてBlenderを起動する事が目的なのでそこまでの設定が出来れば大丈夫です。ここで書かれている事の他に、Blenderは頻繁に更新されてしまうのでコードリーディング用のブランチをtagから作成しておくと便利です。この記事を書いている時点では2.74が最新安定板なので、「v2.74」というtagからブランチを作成してしばらくそこでコードリーディングを進めていきます。