2016-07-18 6 views
1

残念ながら多くのチュートリアルでは、どのようなタイプのノーマルマッピングでもTBNマトリックスは事実上必須であると記載されていますが、その理由について詳しく説明しません。接線ベクトル/接線ベクトルを使用しない通常のマッピング

正規行列

は、任意の変換が正確に指している前に、「静止位置」にあるクワッドの表面法線場合だのは、私は後でそれによって変換することができ、画面上の簡単なクワッド、上のバンプ/ノーマルマッピングを適用する必要があると仮定しましょう正のz方向(opengl)は、通常のテクスチャマップから読み込んだベクトルをモデル行列で変換するだけでは十分ではありませんか?

vec3 bumpnormal = texture2D(texture, Coord.xy); 
bumpnormal = mat3(model) * bumpnormal; //assuming no scaling occured 

私たちは実際に次の質問

に私をリードしており、異なる向きを有する座標どのように異なる同じテクスチャと顔のカウントに取ることなく、キューブでbumpnormalを計算した場合は、物事がどのように変化するかを理解しません

モデル全体が、モデルの異なる部分で前記テクスチャ座標を何も繰り返さずに単一の法線マップテクスチャのみを使用すると仮定すると、各頂点について格納された正接/ TBN matrix altogheterを使用して、モデルのマトリックスで単純にバンプノーマルを変換することで同じ結果を得ることができますか? そのような場合は、なぜそれが推奨されるソリューションではありませんか?

答えて

6

変形前の「静止位置」のクワッドサーフェスの法線が正のz方向(opengl)を正確に指している場合は、モデルを使って通常のテクスチャマップから読み込んだベクトルを変換するだけでは不十分ですマトリックス?

あなたは法線マップは(1、0、0)であるから取得した値を言ってみましょう。つまり、マップの法線が正しいことを意味します。

だから...正確にどこですか?それともポイントまで、私たちが「正しい」と言うときには、どのようなスペースがありますか?

ここで、右はモデル空間の+ Xであるとすぐに考えるかもしれません。しかし、それはそうではありません。どうして?

のテクスチャ座標のためです。

モデル空間の行列が時計回りにモデル空間のZ軸を中心に90度回転し、その行列で法線を変換すると、得られる法線は(1、0、0 )を(0、-1,0)に設定する。それが期待されることです。

正方形の方が+ Zの方がZ軸を中心に90度回転している場合は、回転と同じ結果が得られません。テクスチャ座標?結局のところ、モデル空間にUとVが意味するものを定義するテクスチャ座標は、の相対です。

正方形の右上のテクスチャ座標が(1,1)、左下が(0,0)の場合、テクスチャ空間の「右」はモデル空間の「右」を意味します。しかし、(1,1)が右下に(0,0)が左上になるようにマッピングを変更すると、テクスチャ空間の「右」が「下」(-Y)になりますモデル空間。

モデル空間位置からテクスチャ上の位置へのマッピングであるテクスチャ座標を無視すると、(1,0,0)の法線はまだモデル空間内で「右」を指しています。しかし、あなたのテクスチャマッピングは、それがモデル空間で(0、-1、0)を指し示すべきであると言います。モデル空間自体を回転させた場合と同じように。

接平面法線マップでは、テクスチャに格納される法線は、テクスチャがサーフェス上にどのようにマッピングされるかを基準にしています。モデル空間から接線空間(テクスチャマッピングの空間)へのマッピングを定義するのは、TBN行列のためのものです。

これは、オブジェクトと法線の間のマッピングがより複雑になるにつれて、より複雑になります。あなたはクワッドの場合のためにそれを偽造することができますが、一般的な人物の場合、それはアルゴリズム的である必要があります。結局のところ、マッピングは一定ではありません。異なる三角形が異なるテクスチャ座標を使用するため、ストレッチとスキューが必要です。

ここでは、モデル空間に明示的にある法線を生成するオブジェクト空間ノーマルマップがあります。これにより、接平面空間の基底行列の必要性が回避されます。しかし、それは密接に使用されるオブジェクトへの法線マップを結び付けます。 2つの別々のオブジェクトで通常のマップを使用できるだけでなく、基本的なテクスチャ座標アニメーションを行うことさえできません。そして、三角形がサイズを変えることが多いので、骨量のスキニングを行っていると、ほとんど機能しません。

+0

徹底的に、ポイントまで、ありがとう –

1

http://www.thetenthplanet.de/archives/1180

vec3 perturb_normal(vec3 N, vec3 V, vec2 texcoord) 
{ 
    // assume N, the interpolated vertex normal and 
    // V, the view vector (vertex to eye) 
    vec3 map = texture2D(mapBump, texcoord).xyz; 
#ifdef WITH_NORMALMAP_UNSIGNED 
    map = map * 255./127. - 128./127.; 
#endif 
#ifdef WITH_NORMALMAP_2CHANNEL 
    map.z = sqrt(1. - dot(map.xy, map.xy)); 
#endif 
#ifdef WITH_NORMALMAP_GREEN_UP 
    map.y = -map.y; 
#endif 
    mat3 TBN = cotangent_frame(N, -V, texcoord); 
    return normalize(TBN * map); 
} 

基本的に私はあなたがこの方法を説明していると思います。私が同意するものは、ほとんどの点で優れています。空間変換の混乱に陥るのではなく、後の計算をはるかにクリーンにします。

接線のスペースにすべてを計算するのではなく、正しいワールドスペースノーマルが何であるかを見つけるだけです。それが私のプロジェクトで使っていることです。私はこの方法を見つけたことをとてもうれしく思っています。

+1

"*これは、空間変換の混乱に陥るのではなく、はるかにクリーンな計算を行います。*"あなたがここで行ったことと通常の正接空間正規計算の唯一の違いは、マトリックス?法線を正接空間からモデル空間に変換する場合は、頂点ごとのデータから3つのベクトルを補間して法線を変換できます。それらは単純に通常のTBN行列の逆数を表します。これは後処理としてオフラインで実行できます。 –

+1

これとは逆の理由はパフォーマンスです。あなたのやり方は、行列をモデル空間に掛け、次に別の変換をビュー空間に展開し、最終的に照明を行います。ビューを接平面に変換すると、1つの行列乗算しかできません。 –

+0

ありがとう。とにかく、現代的なハードウェアの方がパフォーマンスは優れています。 – Yudrist

関連する問題