Rendering Pipeline의 이해
우리 지사장님을 위한 렌더링 파이프라인 소개.
아쉽지만 일어가 되는 분들한테만 도움이 될 것이삼.
양이 좀 되서 저걸 새로 다시 한글로 쓰기도 심히 압뷁이라...

 

 

 

 

 

 

 

 

 

Rendering






Pipeline






理解

 

 

 

 

 

 

 

 

 

 

 

 

朴 秉賢


目次

 

 

Rendering Pipelineとは

3Dを計算して描画する

Pipelineの特徴

Rendering Pipelineの速度

 

Direct 3DでのRendering Pipeline

Application Stage

Vertex DataPrimitive Data Stage

Tessellation Stage

Vertex Processing Stage

Geometry Processing Stage

Pixel Processing Stage

Pixel Rendering Stage

 

処理速度の向上のためにプログラマーが工夫すること

 

資料出所


Rendering Pipelineとは

 

 

3Dを計算して描画する

 

我々が目で感じられる現在の世界は3D(3Dimensional3次元)の世界である。しかしコンピューターの画面は縦、横で並んでいるPixelの集まりで構成されていて、これは2D(2Dimensional2次元)の世界である。そのため2Dのコンピューター画面に3Dの世界を描くためには、

     1枚、1枚、全ての絵を描く。

     仮想の3D環境を作り、それを2Dに変える計算はコンピューターに任せる。

という2種類の方法が考えられる。

 

アニメの世界では、すべてのStory、演出がはっきり決まっていて、見ている人には途中で視点などを変更することがまったくできない。だから全部描くこともできる。

しかしPlayerがどこにも行ける、どの方向でも見られる3Dゲームの世界ではその背景を全て用意することは完璧に不可能だ。同じ位置で背景を見ていても少し向きを変えることで風景は変わり、ちょっとだけ移動しても背景も一緒に変わってくるからである。

それで、仮想の3D空間を作り、最終的に2Dの画面に描くことを3D Renderingと呼び、その描画までの処理工程をRendering Pipelineという。

 

 

Pipeline構造の特徴

 

そもそもPipelineというのは何を示す言葉なのだろう?

 

まず辞書的意味では「送油管」のことである。「経路」の意味もある。(生産者から消費者に)「絶え間なく送られる商品」という意味も持っている。要すれば‘ある素材が通る、形が決まっている一方通行の道’になる。このPipeline構造には重要な特徴が含まれている。

     PipelineはいくつかのStageで構成されている。

     StageもひとつのPipelineになってその下にSub Stageを持つ場合もある

     先のStageで素材が進まないと、後のStageの素材も進めない。

     Stageを並列に並べられる場合、並べるStageの数をN倍に増やせるとそのStageの進行速度もN倍に増す。

 

ここで処理速度を重要視するRealtime Renderingでは適切で細かいStage分割によって、なるべく素材が進まなくて後の素材が渋滞状態になるBottleneck現象を避けながら処理速度向上を図る。3D Programmingは様々な独自の技術・トリックなどが氾濫していた時期が過ぎ、現在はこのPipeline構造が一番効率のいい方法として認められている。

 

 

Rendering Pipelineの速度

 

Pipelineの特徴によって、Rendering速度は次のように計算される。

 

3つの素材がStage 1, 2, 3で構成されているPipelineを通過する。

Stage 1, 2, 3の処理にかかる時間はそれぞれ30ms(ミリ秒), 60ms, 40msとする。

1番目の素材がStage 1を通ってStage 2に入るときに2番目の素材はStage 1に入れるので、すべての処理が終わるまでかかる時間は


{30ms(Stage 1) + 60ms(Stage 2) + 40ms(Stage 3)}
×3(素材数)

ではならない。

・そして2番目の素材がStage 1の処理を終えていても、まだ1番目の素材がStage 2で処理中なので、あと30msが過ぎて処理が終わるまでは、2番目の素材はStage 1でそのまま待ち状態になる。当然3番目の素材はStage 1にも入れないまま待ち状態である。

・それで、すべての処理が終わるまでかかる時間は


30ms(Stage 1) + {60ms(Stage 2)
×3(素材数)} + 40ms(Stage 3)

になる。

・つまり、素材数がNの処理にかかる時間は


30ms(Stage 1) + {60ms(Stage 2)
×N(素材数)} + 40ms(Stage 3)

になる。

・これで、処理時間を左右するのは一番遅いStageだということが分かる。

・ここで、Nの数がかなり大きくなると処理時間はほぼ


60ms(Stage 2)
×N(素材数)

に近づき、このPipeline1秒ごとに


1000(ms)
÷60(ms) 16.666

16.6回の処理を行うと言える。

・こうして導出した、このPipelineの速度は約16.6Hz(1秒に行う処理の数)である。

・つまり、作業にかかる総時間は、


          
(
素材数) ×(一番遅いStageの処理時間)

になり、Pipelineの処理速度は、


          
(1
) ÷(一番遅いStageの処理時間)

のようになるのが分かる。

 

Pipelineの並列化で得られる利益の例は次のようである。

 

・先程例を挙げたPipelineStage 2Pipeline3つに増やして同時に素材3つまで処理ができるようにすればStage 2を処理するのにかかる時間は


          
60ms(Stage 2)
÷3(Stage 2Pipeline) 20ms

に減る。こうなると一番遅い処理はStage 3(40ms)になり、

・新たにPipeline全体の処理速度を計ると、


          
1000(1
) ÷40(一番遅い、Stage 3の処理時間) 25(Hz)

に変わる。

・つまり、一番遅いStageを並列化させたことで16.6Hzから25Hzへの速度利益を得た。

Stageを並列化させること以外に、もっと細かいStageに分割することも同様に速度利益を得られる。

 

これが3D Renderingを行うときにPipeline構造が使われている理由である。それで、Realtime Renderingで速度を落とさないコツは、

Stageごとにかかる時間が少ないようにStageを分けること。

・早いStageと遅いStageの格差が大きくならないように処理を分担させること。

である。

 

しかし、残念ながらほとんどのStageAPI(Application Programming Interface:応用Programming Interface)により、Hardware的に自動に行われているため、プログラマーとしてPipeline構造自体に手を出すことはあまりない。それでは3D Renderingの速度向上を図るためにプログラマーが編集できるStageはどこなのか?

 

その前に、Rendering PipelineはどんなStageに別れていて、そのStageはどんな機能をするかという説明がまず必要だ。


Direct 3DでのRendering Pipeline

 

 

Direct3DGraphics Pipeline構造は次のようである。

画像出所:DirectX Documentation 自作

 

PipelineFixed(固定機能関数) PipelineProgrammerble Pipelineに分かれる。Programmerble Pipelineは‘Vertex ProcessingStageや‘Pixel ProcessingStageをそれぞれVertex ShaderPixel Shaderを使って、プログラマーが直接制御できるようになる。他のStage(Application Stage , Vertex DataPrimitive Data Stageは除く)は両方とも固定機能関数を使わないと制御できない。

その違いはなんだろうか?

DirectXで用意されている関数を使うと簡単に機能が使えるが、その種類に制限があるため、多様な表現をするのには基本命令だけでは足りない。それをユーザが直接調節できるようにしてくれるのがShaderである。ShaderDirectXの表現力は非常に広くなった。

DirectX 10からはここにGeometry Shaderが追加され、Vertex ProcessingGeometry Processing(Geometry Processingの最初段階になるとも考えられる)の間に位置する。Objectの形を変えたり、Geometry情報を格納して同じ形のObjectGeometry情報を読み込むだけで、Objectすべてを一々処理する必要をなくすなどの役割をする。

Shaderは表現を豊富にする機能だけではなく、Shaderに書かれた処理をGPUで行うため、CPUの負担を軽減してくれる利点もある。

 

 

Application Stage

 

ObjectWorld空間上置いておく位置の計算、衝突判定、入力処理、物理演算、AnimationSkinningなどの処理を行うStageである。

Vertex Processing Stageで行うWorld変換、View変換、Projection変換などに使われる行列を計算しておくのもこの段階で行われる。常にすべてSoftware上で実行されるので、プログラマーがすべて制御できる唯一な段階である。

Rendering Pipelineは最終のStageからだんだんHardware上で実装できるようになってきて、もはやApplication Stageだけを残している。しかし最近は物理演算カードも販売されているので、少しずつこのStageもいつかはHardware処理が基本になる日が来るかもしれない。

 

 

Vertex DataPrimitive Data Stage

 

頂点データ・Primitiveデータを入力、メモリーにセットするStageである。

頂点座標はLocal座標という概念としてそれぞれ独自的な座標に格納され、Vertex Processing StageWorld変換されてから同一座標空間に置かれるようになる。このStageではLocal座標状態の頂点情報(位置、色、Texture座標など)をメモリーに登録する。

Vertex Data3DObjectを安いコストで上手に表現するのは三角形が一番効率いい。その三角形の頂点情報を格納するところがVertex Bufferであり、このStageではVertex Bufferの情報をグラフィックメモリーにセットする。

Primitive Data:曲線情報などを含めているHigh Order Primitive(高水準Primitive)情報を登録する。NURBS(Non-Uniform Rational B-Spline:非一様有理B-SplineMAYAなどで主に使われる)基盤で作られたPatch方式のモデルデータ(線を格子状に編んで面を構成する事で形状を作る)に使われる。

DirectXとは違って、家庭用ゲームの開発環境では、Polygonの集まり、つまりメッシュ、ObjectなどをPrimitive Dataという。

 

 

Tessellation Stage

 

Tessellationという言葉は、曲面分割のことで、N-PatchDisplacement Mappingなどの技術がある。頂点情報の登録は以前のStageで終わっているが、Tessellation Stageでは頂点を新たに増やして、更に細かい表現ができるようにする。

しかし、家庭用ゲームの開発環境では、三角形を分割してRenderingしない頂点を欠かすことを言うので、注意が必要である。

 

画像出所:Blitzcode.NET                                            画像出所:X bit LABORATORIES

 

N-Patch:頂点の法線情報に基づいて、面を細かく分割して滑らかな曲線を表現する。

Displacement MappingTexturePixel情報に基づいて、頂点を増やしてDetailな表現を行う技術。

 

 

Vertex Processing Stage

 

このStageでそれぞれの頂点の位置、色が決まる。

World変換:Local座標の位置になっている頂点はWorld変換によってWolrd空間上に位置ことになる。

View変換:視点によって変わる座標値を計算するのがView変換であり、カメラ(視点)を原点としてすべてのObjectが再配置される。

Lighting, Shading:光源の位置と頂点の法線を計算して影による色の変更を計算し、頂点の色を決める。

Projection変換:3D空間を更に事実的に表現するためには遠近法を使う必要がある。目に見える範囲を図形で表したのがView Volumeと言うが、遠近法が適用されているときのView Volumeは四角錐の形になる。これを視錐台(View Frustum)という。

Projection変換は、この視錐台を極値が(-1, -1, -1)(1,1,1)の単位立方体に変換する。

 

 

Geometry Processing Stage

 

すべての過程がHardwareによって処理されていたが、DirectX 10から追加されたGeometry Shaderで、このStageにも手を触れることができるようになった。

Geometry ShadingGeometry情報を格納し、いつでもAccessできるようにする。

Clipping:正方形の中に入っていない頂点を削除する。はみ出ているところは切り取る。この過程中新しい頂点がを生成される。

・背面Culling画面の方向を向かっていないPolygonは削除する。

Rasterization:正方形の中に格納されている3D頂点を2Dに投影する。頂点と頂点の間(Fragment)の値も決定する。

 

 

Pixel Processing Stage

 

処理が終わった頂点情報とTextureを結合してPixelの値を決めるStage

Programmerble Pixel Shaderではその結合の方法をユーザが決める。

Textured SurfaceSurfaceは、Display Memoryの線形領域のことで、Textureをメモリーに登録するとこのSurfaceのひとつとして使われる。Texture情報を持っているSurfaceを指定する。

Texture SamplerTextureDetail(画質), Tiling(繰り返し)などを決める。

 

 

Pixel Rendering Stage

 

これで3D環境を画面に表示するためのすべての処理が終わり、次の作業を行いながら画面に描画する。値の計算は既に終了されていて、ここでは指定された順番通りに描画(および後に隠れているPixelは無視)する。

Alpha Test

Depth Test

Stencil Test

Alpha Blending

Pixel Fog


処理速度の向上のためにプログラマーが工夫すること

 

 

大体のProgrammingHardwareが処理を行っているため、一見プログラマーがRenderingの速度を左右するのにはあまり役に立たないように見えるかもしれない。しかしそれは大間違いである。

Realtime Rendering Pipelineにとって核心になるのはBottleneck現象を避けることである。そしてBottleneckが起こる第一の原因はデータの量、つまり頂点の数である。しかし、一応Vertex DataPrimitive Data Stageを通じてVRAMにセットされた頂点情報を勝手に減らすことが出せない。

それで結論は簡単である。Vertex DataPrimitive Data Stage以前のStageApplication Stageでいらない頂点はRenderingを行わない、次のStageに頂点情報を渡さないと言うことである。そのため、Geometry Processing StageClippingによって描画されない頂点は自動的に欠かしてくれるのにもかかわらず、Application Stageで可視性判別を行い、描画するObjectを事前に決める作業が必要になるわけである。

可視性判別には様々なアルゴリズムや方法が工夫されているので、ゲームに合わせて一番効率がいい手段を選ぶべきである。

もちろん、可視性判別だけではなく、Application Stageで行う色んな処理が最適化されているべきなのはあたりまえである。その他、プログラマーが直接制御するShader Codeにも重過ぎる処理や、無駄な処理などが発生しないように注意する必要がある。


資料出所

 

 

Graphics Programming

D3D Graphics Pipeline(現在は破棄されている)

http://cafe.naver.com/graphicsprogramming/8

内容がコピー本はここ

http://blog.naver.com/motonhj82/130021313766