view paper/cerium.tex @ 5:d655863e53b0

*** empty log message ***
author akira
date Sat, 16 Feb 2008 12:37:47 +0900
parents 3f96fdc6d522
children c03a8cdfc8b3
line wrap: on
line source

\chapter{レンダリングエンジンの提案}
\section{Cerium}
我々は独自のレンダリングエンジンを持つことにした。そのレンダリングエンジンをCeriumとする。Ceriumは次の3つから構成される。\\
\begin{itemize}
\item シーングラフ
\item レンダリングエンジン
\item タスクマネージャ
\end{itemize}
シーングラフとレンダリングエンジンが結合して初めて画面上に描画が可能となり、その二つをタスクマネージャがSPU上で実行させる仕様となっている。シーングラフは杉山千秋くんが作成し、タスクマネージャは宮國渡くんが作成した。
\subsection{シーングラフ}
ゲームの中の一つの場面(Scene)を構成するオブジェクトやその振る舞い、ゲームのルールの集合をSceneGraphとする。SceneGraphの各ノードがゲームの一部であるオブジェクトの振る舞いやゲームのルールとなり、ノードをたどり実行することでゲームの中の一つの場面となる。SceneGraphはゲームプログラムとしての条件を満たす物なので、一つのScene Graphで小さなゲームといえる。
\subsection{レンダリングエンジン}
レンダリングエンジンはOSMesaの機能を簡素化し、よりシンプルに使いやすく設計されたフレームワークである。
OSMesaではいろいろな機能を付加し続けた結果、様々計算の部分でコピーがたくさん行われていた。それはCPUに多大な負荷を与えるとともに動作が遅くなる大きな要因となっていた。\\
そこで我々が提案するレンダリングエンジンはシーングラフから、ポリンゴンの各頂点をうけとり、頂点からspanを生成し、spanに対応するテクスチャを生成するシンプルな物を目指す。
\subsection{タスクマネージャ}
タスクマネージャとはその名の通り、タスクを管理する物である。SPUは256kbという小さなデータ量しかもてない。そのため、なんどもSPUで違う動作をさせるためにはSPUのプログラムをロードしなければならない。プログラムのロードを逐次的に行うことも可能だがSPUのプログラムは必要なときに必要な実行プログラムがSPUにロードされていることが望ましい。そこで我々はSPURSの考えを基にタスクマネージャを作成した。\\
\section{Ceriumの実装}
\subsection{シーングラフ}
シーングラフはゲームのシーンを構成するオブジェクトやその振る舞いの記述である。シーングラフはxmlをパースするところか始まる。blenderから生成されるxmlは以下のような構造を持っている。\\
\input{src/cube-p.xml}
このxmlにはblenderで記述されたすべてのオブジェクトの情報が記述されている。一つのオブジェクトに対し、サーフェイスの名前とサイズ、親のポリゴンの名前、それに対してcoordinate(ポリゴン情報)とtexture(ポリゴンに対応するテクスチャ座標)、テクスチャの$RGB\alpha$情報があり、シーングラフではそのxml情報をパースしてすべての情報をレンダリングエンジンに必要な構造体に直す。その上で、親子関係を考慮した回転や拡大縮小などを行う。\\
%rotateや親子関係などを実装している。
親子関係とは自転と公転のようなもので、例えば地球が自転すると、それに伴って月が公転するようなことである。それは子に対して親への変換行列がかけられている。それをスタック上に積んで計算する必要がある。(図\ref{fig:stack})\\
\begin{figure}[htb]
\begin{center}
\includegraphics{./fig/stack.eps}
\end{center}
\caption{親子関係のstack}
\label{fig:stack}
\end{figure}
\\
親子関係などで計算されたポリゴンがレンダリングエンジンに渡される。しかし、それだけではなく、回転などの状態を残したアップデートされたポリゴンパックを保持して置く必要がある。
\subsection{レンダリングエンジン}
レンダリングエンジンは2つに分けることができる。spanを生成する部分と与えられたspanからテクスチャの生成する部分である。
\subsubsection{spanを生成する部分}
spanを生成するとき、シーングラフから必要な情報(polygonpack)が渡される。\\
\input{src/polygonpack.h}
polygonpackは光源の情報とテクスチャの情報と頂点の情報から構成される。TRIANGLEPACKというものがポリゴンに相当する物で、3つの頂点とそのポリゴンに対応するテクスチャの情報が格納されているアドレス、テクスチャの高さと幅が与えられている。3つの頂点にはx座標、y座標、z座標、テクスチャのx相対比、テクスチャのy相対比が与えられる。
この与えられたpolygonpackの情報からspanの情報を出力する。spanを生成するコードはつぎのようになっている。\\
\begin{figure}[htb]
\begin{center}
\includegraphics{./fig/half_triangle.eps}
\end{center}
\caption{span生成時のポリゴン分割}
\label{fig:half_triangle}
\end{figure}
\input{src/polygonpack.cpp}
spanを生成するコードではポリゴンを上下二つの三角形に分割して計算している。
vMid1という関数で図\ref{fig:half_triangle}のvMid10の部分にあたる部分の座標を計算し、上の三角形の頂点座標をhalf\_triangleという関数に渡している。half\_triangleではy座標ごとに右端と左端のx、z座標、テクスチャのx、y相対値を計算した後で、spanを生成している。しかし、このspan情報を単にPPUに送り返すと、PPUでspanをソートする必要が出てくる。それはOSMesaのときと同じく、SPUのメモリ量とzバッフぁ問題があるからである。そこで、PPUにDMA転送する前にy座標を8ごとにspanのリストを生成し、PPUに送信する。y座標が8毎にとっている理由はSPUが持てるzバッファが8ぐらいだろうという見解からくるものである。それを送信すると、PPUは次のようなメモリ空間を持つことになる。\\
\begin{figure}[htb]
\begin{center}
\includegraphics[width=15cm]{./fig/ppu_memory_span.eps}
\end{center}
\caption{ppuにできるspanのメモリ空間}
\label{fig:ppu_memory}
\end{figure}
\\
縦に並んだ空間がPPUによってリストにされる。
\subsubsection{spanからテクスチャを計算する部分}
spanは次のような情報(spanpack)からテクスチャを計算し描画する。
\input{src/spanpack.h}
spanはテクスチャ情報のアドレスと高さと幅、それに加えてポリゴンのあるy座標に対するx、y、start\_z、tex\_x1、tex\_y1(左端のピクセル情報)とlength(spanの長さ)とend\_z、tex\_x2、tex\_y2(右端のピクセル情報)を持つ。(図\ref{fig:span})\\
\begin{figure}[htb]
\begin{center}
\includegraphics{./fig/span.eps}
\end{center}
\caption{span情報}
\label{fig:span}
\end{figure}
その情報からテクスチャを計算して、ピクセル毎のRGB$\alpha$情報を取得する。しかし、SPUはメモリが256kbしかないため、すべてのテクスチャを送ることが不可能となる場合がある。それらを考慮し、テクスチャを分割する必要がある。
テクスチャは8x8の大きさに分割される。(図\ref{fig:div_texture})\\
\begin{figure}[htb]
\begin{center}
\includegraphics{./fig/div_texture.eps}
\end{center}
\caption{分割されたテクスチャ}
\label{fig:div_texture}
\end{figure}
spanはそれぞれのテクスチャに沿ってspanを生成される。つまり、span一つにつき、分割したテクスチャ一つがDMAされる。
\subsection{タスクマネージャ}
タスクマネージャはSPUで実行される関数をタスクとしてQueueに登録し、タスクマネージャに実行命令が下ると、Queueに登録されたタスクが依存関係をみながら、実行されていくライブラリである。
以下にタスクマネージャを使った実装例を記述する。
\input{src/manager.cpp}
タスクマネージャはPPUで実行するかSPUで実行するかを明示的に書くことができる。またSPUを使う場合はSPUコアをいくつ使うかということも指定することができる。そうすると、以下のようなことができる可能性もある。\\
\begin{figure}[htb]
\begin{center}
\includegraphics[width=15cm]{./fig/pipeline3.eps}
\end{center}
\caption{タスクマネージャが行うパイプライン}
\label{fig:pipeline3}
\end{figure}
これはシーングラフからポリゴンを生成するSGU2PGCとポリゴンからspanを生成するPGP2SPPとspanからテクスチャを生成しレンダリングするSPP2RENの関係を表す図である。これら一連の流れは順に1、2、3というふうになる。一番左端にあるb2はポリゴンの構造体を表す。そのポリゴン構造体はSGU2PGCに使われるという図である。つまり、タスクマネージャを用いて、ダブルバッファとパイプラインを用いても、ポリゴンのPPUはポリゴンの構造体二つとspanの構造体二つでレンダリングができることを示している。\\
\section{評価}
今回我々はCell上で動作するゲームフレームワークを作成した。今回のフレームワークの作成により、ゲーム班はシーングラフの一部を作り直し、親子関係を考慮したオブジェクトを生成するだけである程度のゲームが作れるようになった。それだけでなく、そのフレームワークを使うことはCellアーキテクチャの勉強をすることにもつながる。