SlideShare a Scribd company logo
2013/7/8
大阪スタジオ
安井彰一
3D描画基礎知識
目次
•
レンダリングパイプライン
•
深度
•
座標系
•
描画順
•
データ
•
影
•
シェーダ
説明に入る前に
●
ポリゴン
– 3つの頂点で構成される”板”
レンダリングパイプライン
描画開始
頂点計算
(Vertex Shader)
ピクセル計算
(Pixel Shader)
(Fragment Shader)
クリッピング
ビューポート変換
走査・補完
描画終了
描画開始
●
描画に必要なデータ転送
– 頂点データ
●
座標/テクスチャUV/頂点色/などなど
– テクスチャ
– 姿勢行列(WVP Matrix)
– アニメーション行列(Bone Matrix)(Joint Matrix)
– その他シェーダに必要なパラメータ
あれ?マテリアルは?
●
頂点色やテクスチャUV
反射率などのパラメータのこと
●
頂点データやPixelShader用の
パラメータとして指定するものを
マテリアルと呼称しています
●
シェーダによっては不要
頂点データの構造
●
頂点データの配列
– struct VERTEX {
FLOAT x, y, z; // 座標
FLOAT rhw; // 頂点計算済みフラグ
DWORD color; // 頂点色
FLOAT tu, tv; // テクスチャUV
};
– シェーダによって必要なパラメータが違う
●
頂点インデックスの配列
頂点インデックス
頂点データは
複数のポリゴンで
共有することが多い
テクスチャ
●
ポリゴンに貼り付ける画像
●
複数枚のテクスチャを貼り付ける
– 法線マップ/バンプマップ/などなど
●
転送に時間がかかる
UV値とST値
●
どちらもテクスチャ上の位置を示す値
●
UV値
– 0.0〜1.0 で表すテクスチャ上の座標
– 直感的
●
ST値
– 0.0〜1.0 で表すテクスチャトランスフォーム後の
テクスチャ上の座標
– あまり使わない
テクスチャトランスフォーム
●
テクスチャにも行列をかけることができます
●
位置/回転/拡縮 の変換を行う
姿勢行列(WVP Matrix)
●
World x View x Projection = WVP
●
World Matrix
– オブジェクトの位置/回転/拡縮を格納した行列
●
View Matrix
– カメラの位置/回転/拡縮を格納した行列の逆行列
●
Projection Matrix
– 射影変換行列
●
この行列を使えばCPU側でも深度(後述)が計算できる
World Matrix
●
位置(Translate)
●
回転(Rotate)
●
拡縮(Scale)
cosθ -sinθ
sinθ cosθ
x y z
cosθ sinθ
-sinθ cosθ
cosθ -sinθ
sinθ cosθ
x
y
z
※右手座標系の場合
行列のかける順番
●
移動->回転
●
回転->移動
原点
原点
View Matrix
●
カメラの姿勢行列の逆行列
●
なぜ逆行列?
どちらも見え方は同じ
カメラという概念が消える分、
GPUにとっては逆行列の方が都合がいい
カメラを動かす 逆行列
Projection Matrix
●
透視射影行列 ( Perspective Projection )
– 近くのものほど大きく見える変換
– 通常はこちら
●
並行射影行列 ( Orthogonal Projection )
– 近くても遠くても同じ見え方の変換
– UIなどはこちら
Bone Matrix
●
モデル内のオブジェクトの親子関係
●
骨
図を使った比較
並行射影透視射影
頂点計算
●
頂点が画面のどの位置にあるのかを計算
●
頂点のBoneからの座標 x Bone x WVP
– シェーダによってはそれ以外の計算を行うことも
●
頂点色やUV値を計算することも
●
法線(Normal)を計算する
– 影の計算(後述)ですごく重要
– 影以外の意味としてもすごく重要
– 特殊なことをやりたければ法線使えばなんとかなる
クリッピング
●
画面外のポリゴンについて
描画処理しないようにする処理
●
頂点計算はされてしまったあとなので
CPU側で弾く処理も重要
– バウンディングボックスによるクリッピング(CPU)
が一般的かも?
– LOD(Level of Detail)による処理低減も
●
LOD : 遠くのオブジェクト用のモデルデータ
ビューポート変換
●
よくテレビであるワイプを想像すればOK
●
2人プレイなど画面分割での描画
走査・補完
●
描画することになったポリゴンを
画面上のピクセル単位に分割する処理
●
頂点色の補完も行われる
●
深度による描画スキップも行われる
ピクセル計算
●
ポリゴンの専有する画面上の
各ピクセルの色を計算する
●
シェーダと言われて想像するのは
多分こちらの方だと思う
●
各ピクセルの処理が故に
一番処理負荷がかかる部分
描画終了
●
計算されたピクセルの情報を
既に描画済みのピクセルと合成して
結果を出力先に書き込む
– αブレンドはこのタイミング
深度
●
Depth Buffer / Z Buffer
– 同じものです
●
手前のポリゴンが奥のポリゴンに
上書きされないようにする機構
●
DepthBuffer用のテクスチャに
深度情報を書き込む
深度の仕組み
深度1
深度0
深度2
これを踏まえて
描画順番の鉄則...
描画順番の鉄則
●
不透明なオブジェクトは
手前から描画する
– 消えた部分の描画コストがもったいない
深度1 深度0
描画順番の鉄則
●
半透明なオブジェクトは
奥から描画する
– 奥のオブジェクトを先に描画しないと
消えてしまう
深度2
描画順による描画結果の違い
モデルを半透明にする際の小技
●
腕と胴など、表面同士の描画順は
モデルデータに依存するため
制御が難しい
●
更に背景のオブジェクトとの
αブレンドによって、
あるはずのパーツが消える
または、見えないはずのパーツが見える
– 先ほどの例と同じ問題
モデルを半透明にする際の小技
1.深度のみをレンダリング
(ピクセルの描画は行わない)
2.深度と等しいピクセルのみを
再度レンダリング
- DEPTH_TEST = EQUAL
3.最前面のピクセルだけ描画が可能
- それ以外の場合はその時考えましょう
深度の精度
●
深度は0.0〜1.0の範囲をとる
(どちらが奥かは設定次第)
●
ZClipNear〜ZClipFar と対応している
●
ほとんどの場合、手前もしくは奥に
深度の描画結果が固まっている
●
もったいない!
●
ZClipNear/Farは適切に設定しましょう
座標系
●
左手座標系(DirectX)
– Z+方向が奥
●
右手座標系(OpenGLなど)
– Z+方向が手前
●
ポリゴンの表判定が逆
●
行列のかける順番が違う
– 行列の中の値の位置も違う
●
詳しくはGoogle先生に
データ
●
モデルデータ
– ポリゴン
●
各ジョイントからの相対座標で格納されている
●
アニメーションデータ
– 行列
●
原点からジョイントまでの
変換マトリクスが格納されている
●
親子関係がデータになっているわけではない
●
デザイナによって作成される
Weight
●
複数のジョイントに属する頂点
●
どのジョイントからどの程度
影響を受けるのかを表す値
●
デザイナさんの作業で
一番大変な部分(らしい)
– 調整して曲げて伸ばしてを繰り返して
違和感のでない用に調整するとのこと
●
でも頂点シェーダを
書く人以外に馴染みはない(多分)
影
●
3Dの中で最も大切なもの
法線(Normal)
●
任意の頂点が向いている向き
●
頂点データとしても指定できるし、
法線マップと呼ばれるテクスチャでも
指定することができる
●
Unityではなぜか
バンプマップ(高低マップ)と
混同されている・・・
シェーダ
●
好きなように描画できるようにする
プログラムのこと
●
HLSL(High-Level Shader Language)
が主流かも?
●
GLSL(OpenGL Shading Language)
もあるにはある
●
Cg言語(C for Graphics)や
アセンブラを直接書く方法も
シェーダの紹介
●
を、しようかと思いましたが、
最新のシェーダ事情について
調べる時間がなかったため
割愛させて頂きます
●
最新ではないですが
読み物として面白いサイトを紹介します
– 3Dグラフィックス・マニアックス
http://news.mynavi.jp/column/graphics/index.html
– 3Dゲームファンのためのグラフィックス講座
http://game.watch.impress.co.jp/docs/series/3dcg/index2013.html
質疑応答
ご清聴ありがとうございました。

More Related Content

3D描画基礎知識