青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品

麒麟子

~~

導航

<2008年12月>
30123456
78910111213
14151617181920
21222324252627
28293031123
45678910

統計

常用鏈接

留言簿(12)

隨筆分類

隨筆檔案

Friends

WebSites

積分與排名

最新隨筆

最新評論

閱讀排行榜

評論排行榜

Computing Tangent Space Basis Vectors for an Arbitrary Mesh

原文地址:http://www.terathon.com/code/tangent.html

為一個任意網格模型計算其切線空間的基本向量(即切線空間的T B N三個向量)

Modern bump mapping (also known as normal mapping) requires that tangent plane basis vectors be calculated for each vertex in a mesh. This article presents the theory behind the computation of per-vertex tangent spaces for an arbitrary triangle mesh and provides source code that implements the proper mathematics.

現在的bump mapping(或者normal mapping)需要每個頂點的切面的基本向量。這篇文章描述了逐頂點計算任意三角模型的切線空間原理,并且提供了實現這個數學理論的源代碼。

 

Mathematical Derivation 數學來源

[This derivation also appears in Mathematics for 3D Game Programming and Computer Graphics, 2nd ed., Section 6.8.]

 

We want our tangent space to be aligned such that the x axis corresponds to the u direction in the bump map and the y axis corresponds to the v direction in the bump map. That is, if Q represents a point inside the triangle, we would like to be able to write

我們想我們的切線空間像這樣對齊,比如; X軸相當于bump圖中的U方向,而Y軸相當于bump圖中的V方向。于是,如果Q表示三角形上的一點,則我們可以得出如下等式

QP0 = (uu0)T + (vv0)B,

 

where T and B are tangent vectors aligned to the texture map, P0 is the position of one of the vertices of the triangle, and (u0, v0) are the texture coordinates at that vertex. The letter B stands for bitangent, but in many places it is stilled called binormal because of a mix-up in terms when tangent-space bump mapping first became widespread. (See “Bitangent versus Binormal” below.)

等式中的T是與紋理對應的切線向量,P0 是三角形的其中一個頂點。(u0, v0) 是對應頂點的紋理坐標。 B表示副(雙)切線(bitangent),但是由于在切線空間的bump mapping第一次被傳播開來的時候,有人混淆這個定義,所以在許多地方它始終被稱為副法線(binormal )。(參見下面的Bitangent VS Binormal)

 

Suppose that we have a triangle whose vertex positions are given by the points P0, P1, and P2, and whose corresponding texture coordinates are given by (u0, v0), (u1, v1), and (u2, v2). Our calculations can be made much simpler by working relative to the vertex P0, so we let

假設三角形的三個頂點分別為P0, P1, and P2, 其分別對應的紋理坐標為(u0, v0), (u1, v1), and (u2, v2). 。那我們的計算就可以簡化下為下面的方程式組

Q1 = P1P0
Q2 = P2P0

(s1, t1) = (u1u0, v1v0)
(s2, t2) = (u2u0, v2v0).

We need to solve the following equations for T and B.

于是,我們最終要解決的就是下面這個方程式

Q1 = s1T + t1B
Q2 = s2T + t2B

This is a linear system with six unknowns (three for each T and B) and six equations (the x, y, and z components of the two vector equations). We can write this in matrix form as follows.

這個有著6個未知數的線性方程組(T,B是向量,每個有三個量)。我們可以把它寫成如下的矩陣方式

image

Multiplying both sides by the inverse of the (s, t) matrix, we have

兩邊都乘以(s,t)的逆矩陣

image .

 

This gives us the (unnormalized) T and B tangent vectors for the triangle whose vertices are P0, P1, and P2. To find the tangent vectors for a single vertex, we average the tangents for all triangles sharing that vertex in a manner similar to the way in which vertex normals are commonly calculated. In the case that neighboring triangles have discontinuous texture mapping, vertices along the border are generally already duplicated since they have different mapping coordinates anyway. We do not average tangents from such triangles because the result would not accurately represent the orientation of the bump map for either triangle.

由此,我們解出等式后,就得到了未單位化的T和B。 為了找到單個頂點的切線向量,我們平均共享這個頂點的所有切三角形的的切線。法線也可以通過類似的方式計算出來。 而在這種情況下,相鄰的兩個三角形則會形成不連續的紋理映射,處于邊緣的頂點由于有不同的紋理坐標而經常被復制。我們沒有平均這些三角形的切線,因為我們的計算結果就可以不精確地描述每個三角形的切線朝向。

 

Once we have the normal vector N and the tangent vectors T and B for a vertex, we can transform from tangent space into object space using the matrix

一旦我們得到了一個頂點的法向量N和切線T和B。我們就可以用它們來構造一個由正切空間到對象空間的矩陣。

image

To transform in the opposite direction (from object space to tangent space—what we want to do to the light direction), we can simply use the inverse of this matrix. It is not necessarily true that the tangent vectors are perpendicular to each other or to the normal vector, so the inverse of this matrix is not generally equal to its transpose. It is safe to assume, however, that the three vectors will at least be close to orthogonal, so using the Gram-Schmidt algorithm to orthogonalize them should not cause any unacceptable distortions. Using this process, new (still unnormalized) tangent vectors T′ and B′ are given by

為了向反方向變換(從對象空間變換到正切空間,[法線貼圖時]我們需這樣處理光照方向),我們可以簡單地使用這個矩陣的逆矩陣。 但我們要注意切線向量并非總是與其它兩個向量,或法向量垂直的。于是,我們的逆矩陣并非總是等于其轉置矩陣。但是,可以安全地認為,這三個向量是非常接近正交關系的。 所以使用我們可以使用Gram-Schmidt算法來對其進行正交化,就不會出現不可接受的誤差了。

T′ = T − (N · T)N
B′ = B − (N · B)N − (T′ · B)T′/T2

Normalizing these vectors and storing them as the tangent and bitangent for a vertex lets us use the matrixto transform the direction to light from object space into tangent space. Taking the dot product of the transformed light direction with a sample from the bump map then produces the correct Lambertian diffuse lighting value.

單位化這些向量并將其存為一個頂點的tangent 和bitangent 。

于是,我們可以用下面這個矩陣將光方向從對象空間轉換到切線空間。然后將轉換后的光照方向和bump圖中的采樣值點乘,然后再處理某些矯正因子就可以完成光照的計算。

image

It is not necessary to store an extra array containing the per-vertex bitangent since the cross product N × T′ can be used to obtain mB′, where m = ±1 represents the handedness of the tangent space. The handedness value must be stored per-vertex since the bitangent B′ obtained from N × T′ may point in the wrong direction. The value of m is equal to the determinant of the matrix in Equation (*). One may find it convenient to store the per-vertex tangent vector T′ as a four-dimensional entity whose w coordinate holds the value of m. Then the bitangent B′ can be computed using the formula

我們也不必要存儲bitangent這個值。因為N × T′可以得出我們的mB′,這里的m = ±1,表示切空間的左右手坐標系習慣。表示左右手坐標系習慣的這個值必須逐頂點存儲。因為bitangent B′ 是由N × T′計算得來,就可能指向錯誤的方向。m的值必須要和(*)中的決定保持一致。 所以我們可以用T′的w分量來存儲m值。最后B′的值就可以向下面一樣計算

B′ = T’(N × T′),

 

where the cross product ignores the w coordinate. This works nicely for vertex programs by avoiding the need to specify an additional array containing the per-vertex m values.

向量的叉乘忽略了w分量,因此不會造成任何影響。這樣就可以很好地寫頂點程序,而不用另外用空間來存儲m值。

 

Bitangent versus Binormal

The term binormal is commonly used as the name of the second tangent direction (that is perpendicular to the surface normal and u-aligned tangent direction). This is a misnomer. The term binormal pops up in the study of curves and completes what is known as a Frenet frame about a particular point on a curve. Curves have a single tangent direction and two orthogonal normal directions, hence the terms normal and binormal. When discussing a coordinate frame at a point on a surface, there is one normal direction and two tangent directions, which should be called the tangent and bitangent.

(上面講的就是binormalbitangent的區別)。

Source Code

The code below generates a four-component tangent T in which the handedness of the local coordinate system is stored as ±1 in the w-coordinate. The bitangent vector B is then given by B = (N × T) · Tw.

下面的代碼產生了一個4維的T,其第4個分量用于存儲左右手坐標系習慣。B 是由 B = (N × T) · Tw.計算而來。

#include "Vector4D.h"


struct Triangle
{
    unsigned 
short  index[3];
}
;


void CalculateTangentArray(long vertexCount, const Point3D *vertex, const Vector3D *normal,
                           
const Point2D *texcoord, long triangleCount, const Triangle *triangle, Vector4D *tangent)
{
    Vector3D 
*tan1 = new Vector3D[vertexCount * 2];
    Vector3D 
*tan2 = tan1 + vertexCount;
    ZeroMemory(tan1, vertexCount 
* sizeof(Vector3D) * 2);

    
for (long a = 0; a < triangleCount; a++)
    
{
        
long i1 = triangle->index[0];
        
long i2 = triangle->index[1];
        
long i3 = triangle->index[2];

        
const Point3D& v1 = vertex[i1];
        
const Point3D& v2 = vertex[i2];
        
const Point3D& v3 = vertex[i3];

        
const Point2D& w1 = texcoord[i1];
        
const Point2D& w2 = texcoord[i2];
        
const Point2D& w3 = texcoord[i3];

        
float x1 = v2.x - v1.x;
        
float x2 = v3.x - v1.x;
        
float y1 = v2.y - v1.y;
        
float y2 = v3.y - v1.y;
        
float z1 = v2.z - v1.z;
        
float z2 = v3.z - v1.z;

        
float s1 = w2.x - w1.x;
        
float s2 = w3.x - w1.x;
        
float t1 = w2.y - w1.y;
        
float t2 = w3.y - w1.y;

        
float r = 1.0F / (s1 * t2 - s2 * t1);
        Vector3D sdir((t2 
* x1 - t1 * x2) * r, (t2 * y1 - t1 * y2) * r,
            (t2 
* z1 - t1 * z2) * r);
        Vector3D tdir((s1 
* x2 - s2 * x1) * r, (s1 * y2 - s2 * y1) * r,
            (s1 
* z2 - s2 * z1) * r);

        tan1[i1] 
+= sdir;
        tan1[i2] 
+= sdir;
        tan1[i3] 
+= sdir;

        tan2[i1] 
+= tdir;
        tan2[i2] 
+= tdir;
        tan2[i3] 
+= tdir;

        triangle
++;
    }


    
for (long a = 0; a < vertexCount; a++)
    
{
        
const Vector3D& n = normal[a];
        
const Vector3D& t = tan1[a];

        
// Gram-Schmidt orthogonalize
        tangent[a] = (t - n * Dot(n, t)).Normalize();

        
// Calculate handedness
        tangent[a].w = (Dot(Cross(n, t), tan2[a]) < 0.0F? -1.0F : 1.0F;
    }


    delete[] tan1;
}


How to cite this article

Lengyel, Eric. “Computing Tangent Space Basis Vectors for an Arbitrary Mesh”. Terathon Software 3D Graphics Library, 2001. http://www.terathon.com/code/tangent.html

posted on 2010-12-20 23:17 麒麟子 閱讀(1854) 評論(0)  編輯 收藏 引用 所屬分類: GPU and Graphic

青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品
  • <ins id="pjuwb"></ins>
    <blockquote id="pjuwb"><pre id="pjuwb"></pre></blockquote>
    <noscript id="pjuwb"></noscript>
          <sup id="pjuwb"><pre id="pjuwb"></pre></sup>
            <dd id="pjuwb"></dd>
            <abbr id="pjuwb"></abbr>
            国产视频在线观看一区二区| 久久国产福利| 在线视频日韩精品| 亚洲日本aⅴ片在线观看香蕉| 狠狠色丁香婷综合久久| 国产真实精品久久二三区| 奶水喷射视频一区| 欧美v国产在线一区二区三区| 猫咪成人在线观看| 久久精品av麻豆的观看方式| 亚洲美女精品久久| 在线免费观看日韩欧美| 欧美日韩亚洲一区二区三区四区| 欧美亚洲视频一区二区| 欧美一区1区三区3区公司| 亚洲欧美日韩国产中文| 欧美一区二区高清| 一区二区三区回区在观看免费视频| 久久成人亚洲| 亚洲欧美制服另类日韩| 欧美有码在线视频| 久久精品女人的天堂av| 久久精品一区二区三区不卡牛牛| 亚洲综合色噜噜狠狠| 亚洲午夜国产成人av电影男同| 亚洲视频自拍偷拍| 久久国产黑丝| 亚洲人成亚洲人成在线观看图片| 亚洲在线视频一区| 在线视频亚洲欧美| 一区二区三区亚洲| …久久精品99久久香蕉国产| 国语自产精品视频在线看| 亚洲国产一二三| 麻豆精品91| 亚洲精品日产精品乱码不卡| 亚洲一区二区视频| 久久www成人_看片免费不卡| 久久米奇亚洲| 蜜臀av在线播放一区二区三区| 久久蜜桃精品| 亚洲伦理精品| 国产精品美女主播| 欧美三区在线视频| 黄色一区三区| 欧美国产精品人人做人人爱| 国产一区二区三区最好精华液| 欧美激情视频免费观看| 麻豆成人综合网| 狠狠操狠狠色综合网| 夜色激情一区二区| 西西裸体人体做爰大胆久久久| 久久米奇亚洲| 欧美日韩免费| 在线观看国产欧美| 久久久久久午夜| 性欧美大战久久久久久久久| 欧美国产视频在线| 亚洲黄页视频免费观看| 美日韩精品视频| 中文欧美在线视频| 欧美欧美午夜aⅴ在线观看| 一区二区三区在线视频播放| 亚洲午夜女主播在线直播| 卡通动漫国产精品| 亚洲欧美日韩精品久久亚洲区| 国产精品黄页免费高清在线观看| 亚洲欧美国产一区二区三区| 欧美日韩第一页| 欧美一区二区三区男人的天堂| 亚洲美女在线视频| 国产精品美女一区二区| 亚洲成在人线av| 另类国产ts人妖高潮视频| 在线中文字幕日韩| 欧美激情中文字幕一区二区| 欧美一区二区观看视频| 亚洲精品专区| 亚洲自拍电影| 嫩草国产精品入口| 日韩午夜三级在线| 亚洲综合精品四区| 老司机成人在线视频| 欧美精品日韩一本| 久久成人精品一区二区三区| 在线视频日韩精品| 亚洲美女精品成人在线视频| 欧美一级在线视频| 99视频精品全部免费在线| 欧美一级午夜免费电影| 欧美激情第一页xxx| 免费美女久久99| 欧美电影免费观看| 久久综合亚州| 国产欧美日本一区二区三区| 欧美大学生性色视频| 激情欧美一区二区| 欧美激情视频一区二区三区不卡| 欧美成人三级在线| 日韩小视频在线观看| 夜夜爽www精品| 欧美亚州在线观看| 亚洲精品在线看| 亚洲精品日韩综合观看成人91| 亚洲精品中文字| 欧美大片免费久久精品三p| 欧美影院成人| 国产精品视频久久| 亚洲一区二区av电影| 亚洲一区在线观看视频 | 亚洲精品久久久蜜桃| 国产精品欧美久久| 亚洲国产精品日韩| 亚洲精品国久久99热| 欧美成人精品一区二区三区| 亚洲国产成人精品视频| 影音先锋欧美精品| 久久躁狠狠躁夜夜爽| 嫩草影视亚洲| 亚洲特色特黄| 1769国产精品| 欧美精品一区二区三| 午夜日韩在线| 亚洲人成网站在线播| 亚洲深爱激情| 亚洲免费不卡| 亚洲一区二区三区精品在线| 国产婷婷精品| 欧美午夜www高清视频| 久久成人精品| 国产精品自在线| 一区二区三区四区蜜桃| 一本在线高清不卡dvd | 亚洲一区二区免费视频| 亚洲人成啪啪网站| 亚洲字幕在线观看| 国产精品毛片a∨一区二区三区|国| 欧美大香线蕉线伊人久久国产精品| 亚洲人成啪啪网站| 免播放器亚洲一区| 亚洲女女女同性video| 久久精品人人做人人综合| 亚洲精品资源美女情侣酒店| 伊人久久av导航| 好男人免费精品视频| 激情综合电影网| 欧美日韩成人综合在线一区二区 | 国产精品青草综合久久久久99 | 日韩一级黄色片| 欧美亚洲一区二区三区| 久久免费99精品久久久久久| 久久影院亚洲| 一区二区三区视频在线播放| 亚洲视频欧美视频| 欧美一区二区三区四区在线 | 亚洲视频在线观看免费| 一色屋精品亚洲香蕉网站| 99re8这里有精品热视频免费| 亚洲欧美综合精品久久成人| 欧美一区二区三区久久精品茉莉花 | 午夜精品一区二区三区在线视| 欧美顶级大胆免费视频| 日韩亚洲成人av在线| 午夜在线精品偷拍| 男女精品视频| 欧美三级日本三级少妇99| 美女视频黄免费的久久| 美女91精品| 欧美成人免费网| 99视频精品在线| 欧美亚洲在线| 韩国一区电影| 亚洲天堂成人在线观看| 日韩视频一区二区在线观看 | 午夜久久99| 亚洲激情啪啪| 欧美成人一区二区三区| 欧美精品一区二区三区一线天视频| 久久大逼视频| 欧美视频亚洲视频| 亚洲第一级黄色片| 久久九九99视频| 亚洲欧美日韩综合aⅴ视频| 国产精品亚洲精品| 亚洲欧美中文另类| 欧美一级片一区| 欧美日韩在线视频观看| 老巨人导航500精品| 欧美成人精品福利| 亚洲一区综合| 欧美高清视频一区二区三区在线观看 | 国内精品写真在线观看| 久久一区二区三区四区| 欧美激情网站在线观看| 亚洲每日在线| 国产精品视频xxx| 久久综合激情| 激情成人中文字幕| 欧美激情一区二区| 亚洲国产裸拍裸体视频在线观看乱了中文 |