Zfxengine Development Note Bump Mapping (2)

Source: Internet
Author: User

I_dovelemon

Date: 2014/9/13

Source: CSDN

Topics: Bump Mapping, Tangent Space, Normal map, Height map


Introduction

In the previous article, I described how to create a normal map from a height diagram. And promises to tell you about the important tools in 3D geometry, tangent space, in the background. Today, we are here to tell you about the next part of the work.


Tangent Space

As we know, in the previous article, the normals in the described normal map are in the space of the texture diagram, which is also in tangent spaces. When we are doing light calculations, we need to place the light vector and the normal of the pixel in a space for light calculation. In general, the illumination vectors of light sources are in world space, and the normals are in tangent space. If we were to convert the normals of each pixel from tangent space to the world coordinate space when we were doing light calculations, we would have to do this for all the pixels, but if we did this with the light vector, we just had to vertex You can do it once in a shader. Therefore, it is natural for us to try to convert the light source vector into the same tangent space as the normal pixel.

Coordinate space transformation is the basic knowledge of 3D graphics. If the reader doesn't understand it, see the 3D coordinate transformation in my blog. In order to be able to coordinate the transformation, we need the coordinate space of the normal of the pixel to tangent space's base coordinates in the model coordinate spaces, so that we can easily transform the vector in the model coordinate space into tangent space.

So, how do you create three base vectors for tangent space?

The x-axis in Tangent space is aligned with the U-axis direction of the bump map, while the y-axis aligns with the V-axis direction of the bump map. That is, if the Q point represents a point in the triangle, then we can use the following equation to represent:

Q-p0 = (u-u0) T + (V-v0) B, (equation 1)

The T and B here are vectors aligned with the bump map. P0 is a vertex of a triangle, and (u0,v0) represents the texture coordinates of a P0 vertex. And the following B is Bitangent, some books also called Binormal.

Suppose we have a triangle whose three vertices are P0, P1, P2, and their corresponding texture coordinates are (u0,v0), (U1,V1), (U2,V2), respectively. For the sake of convenience, we will P0 as a reference point here. So, let's assume:

Q1 = P1-p0

Q2 = P2-p0

And

(S1, T1) = (u1-u0, v1-v0)

(s2, t2) = (u2-u0, v2-v0)

Since equation 1 above represents a bit of a relationship in a triangle, the same function can be satisfied for Point P1 and P2, which is to say:

Q1 = s1t + t1b

Q2 = s2t + t2b

We use matrices to solve the equation above and get the following matrix equation:

Both sides are multiplied by the inverse matrix of the (s,t) matrix, resulting in the following matrix equation:

(Equation 2)

Well, from the matrix equation above, we can get two vectors t and b.

With the t,b,n vector, we can use the following matrix to transform the coordinates of tangent space into the coordinate space of the model:

The matrix above is the transformation of the coordinates in tangent space into the model coordinate space, but what we need here is to transform the coordinates in the model coordinate space into the tangent space coordinates. So we need the inverse matrix of the matrix above. (This is actually imprecise because the n vector we used above is the normal vector direction of the vertex, which is slightly different from the n vectors in the actual tangent space, but negligible.) Since these three vectors are perpendicular to each other, then this matrix is the orthogonal matrix, and the inverse matrix of the orthogonal matrix equals its transpose matrix, so the following is the final matrix that transforms the coordinates in the model coordinate space into the tangent space:


Calculate Tangent Space

The following two functions are used to calculate the tangent vector in the vertex's tangent space coordinate vector.

<span style= "Font-family:microsoft Yahei;" >void calctangent (zfxtvertex* v) {    for (int i = 0; i < 8; i + +)     {   &N bsp;    calctangent (&v[i*3],&v[i*3+1],&v[i*3+2]);    }}//end for calctangentvoid  calctangent (Zfxtvertex *t1, Zfxtvertex *t2, Zfxtvertex *t3) {    ZFXVector VC, VcA, VcB;    float fu21 = t2->tu-t1->tu,        fv21 = T2-&GT;TV-T1-&G T;tv,        fu31 = t3->tu-t1->tu,        fv31 = t3- &GT;TV-T1-&GT;TV;    //x-component of Tangent vector    vca.set (t2->x-t1->x, FU2 1, fv21);    vcb.set (t3->x-t1->x, fu31, fv31);    vc.cross (VcA, VcB);     if (Fabs (vc.x) > 0.0001f)     {        t1->vcu[0] =- vc.y/vc.x;    }    //y-component of Tangent vector    vca.set (t2->y-t1->y, Fu21, fv21);    vcb.set (T3->y-t1->y, fu31, fv31);    vc.cross (VcA, VcB);  & nbsp  if (Fabs (vc.x) > 0.0001f)     {        t1->vcu[1] =-vc.y/vc.x ;    }    //z-component of Tangent vector    vca.set (t2->z-t1->z, Fu21, fv21);    vcb.set (T3->z-t1->z, fu31, fv31);    vc.cross (VcA, VcB);  & nbsp  if (Fabs (vc.x) > 0.0001f)     {        t1->vcu[2] =-vc.y/vc.x ;    }    zfxvector Normalv (t1->vcu[0],t1->vcu[1],t1->vcu[2]);    normalv.normalize ();    t2->vcu[0] = t3->vcu[0] = t1->vcu[0] = normalV.x;   & NBSP;T2-&GT;VCU[1] = t3->vcu[1] = T1->vCU[1] = normalv.y;    t2->vcu[2] = t3->vcu[2] = t1->vcu[2] = normalv.z;} End for Calctangent</span>

The formula is fully used in the above conclusion formula and the other calculation, as long as the cross expansion, you can understand. In the function, I only calculated the T vector, not the T and B vectors as in the theory above. Because, I'm going to use the normal direction of the vertex as the n vector of tangent space, so after having T and N, we can get the B vector with the cross product operation. This decision is also reflected in the vertex structure I define, as follows:
<span style= "Font-family:microsoft Yahei;"  >/*** Define the Tangent Vertex format*/typedef struct zfxtvertex_type{float x, y, z; float vcn[3]; float tu, TV; float VCU[3];    Tangent vector}zfxtvertex;</span>
function is very simple, as long as the formula, copied copy can be, there is no need to say more.


Program Examples

             Now that we know how to calculate tangent space, let's use this method to build a model of the same type, which is the creation code for the model:

<span style= "Font-family:microsoft Yahei;" >hresult Createroom (zfxtvertex* V, word* index) {//create a wallzfxvector normal;//triangle 1v[0].x = -100; v[0].y = 1 00; V[0].z = +; V[0].vcn[0] = 0; V[0].VCN[1] = 0; V[0].VCN[2] = 1; v[0].tu = 0.0f; v[0].tv = 0.0f; v[1].x = 100; V[1].Y = 100; V[1].z = +; V[1].vcn[0] = 0; V[1].VCN[1] = 0; V[1].VCN[2] = 1; v[1].tu = 1.0f; v[1].tv = 0.0f; v[2].x = 100; V[2].Y =-100; V[2].z = +; V[2].vcn[0] = 0; V[2].VCN[1] = 0; V[2].VCN[2] = 1; v[2].tu = 1.0f; v[2].tv = 1.0f;//triangle 2v[3].x =-100; V[3].Y = 100; V[3].z = +; V[3].vcn[0] = 0; V[3].VCN[1] = 0; V[3].VCN[2] = 1; v[3].tu = 0.0f; v[3].tv = 0.0f; v[4].x = 100; V[4].Y =-100; V[4].z = +; V[4].vcn[0] = 0; V[4].VCN[1] = 0; V[4].VCN[2] = 1; v[4].tu = 1.0f; v[4].tv = 1.0f; v[5].x =-100; V[5].Y =-100; V[5].z = +; V[5].vcn[0] = 0; V[5].VCN[1] = 0; V[5].VCN[2] = 0; v[5].tu = 0.0f; v[5].tv = 1.0f;//triangle 3v[6].x =-100; V[6].Y =-100; V[6].z = v[6].vcn[0] = 0; V[6].VCN[1] = 1; V[6].VCN[2] = 0; v[6].tu = 0.0f; v[6].tv = 0.0f; v[7].x = 100; V[7].Y =-100; V[7].z = +; V[7].vcn[0] = 0; V[7].VCN[1] = 1; V[7].VCN[2] = 0; v[7].tu = 1.0f; v[7].tv = 0.0f; v[8].x = 100; V[8].Y =-100; V[8].z = -100; v[8].vcn[0] = 0; V[8].VCN[1] = 1; V[8].VCN[2] = 0; v[8].tu = 1.0f; v[8].tv = 1.0f;//triangle 4v[9].x =-100; V[9].Y =-100; V[9].z = +; V[9].vcn[0] = 0; V[9].VCN[1] = 1; V[9].VCN[2] = 0; v[9].tu = 0.0f; v[9].tv = 0.0f; v[10].x = 100; V[10].Y =-100; V[10].z = -100; v[10].vcn[0] = 0; V[10].VCN[1] = 1; V[10].VCN[2] = 0; v[10].tu = 1.0f; v[10].tv = 1.0f; v[11].x =-100; V[11].Y =-100; V[11].z = -100; v[11].vcn[0] = 0; V[11].VCN[1] = 1; V[11].VCN[2] = 0; v[11].tu = 0.0f; v[11].tv = 1.0f;//triangle 5v[12].x =-100; V[12].Y = 100; V[12].z = -100; v[12].vcn[0] = 1; V[12].VCN[1] = 0; V[12].VCN[2] = 0;v[12].tu = 0.0f; v[12].tv = 0.0f; v[13].x =-100; V[13].Y = 100; V[13].z = +; v[13].vcn[0] = 1; V[13].VCN[1]= 0; V[13].VCN[2] = 0; v[13].tu = 1.0f; v[13].tv = 0.0f; v[14].x =-100; V[14].Y =-100; V[14].z = +; v[14].vcn[0] = 1; V[14].VCN[1] = 0; V[14].VCN[2] = 0; v[14].tu = 1.0f; v[14].tv = 1.0f;//triangle 6v[15].x =-100; V[15].Y = 100; V[15].z = -100; v[15].vcn[0] = 1; V[15].VCN[1] = 0; V[15].VCN[2] = 0;v[15].tu = 0.0f; v[15].tv = 0.0f; v[16].x =-100; V[16].Y =-100; V[16].z = +; v[16].vcn[0] = 1; V[16].VCN[1] = 0; V[16].VCN[2] = 0; v[16].tu = 1.0f; v[16].tv = 1.0f; v[17].x =-100; V[17].Y =-100; V[17].z = -100; v[17].vcn[0] = 1; V[17].VCN[1] = 0; V[17].VCN[2] = 0; v[17].tu = 0.0f; v[17].tv = 1.0f;//triangle 7v[18].x = 100; V[18].Y = 100; V[18].z = +; V[18].vcn[0] =-1; V[18].VCN[1] = 0; V[18].VCN[2] = 0; v[18].tu = 0.0f; v[18].tv = 0.0f; v[19].x = 100; V[19].Y = 100; V[19].z = -100; v[19].vcn[0] = 1; V[19].VCN[1] = 0;  V[19].VCN[2] = 0;v[19].tu = 1.0f; v[19].tv = 0.0f; v[20].x = 100; V[20].Y =-100; V[20].z = -100; v[20].vcn[0] = 1; V[20].VCN[1] = 0; V[20].VCN[2] = 0; v[20].tu = 1.0f; v[20].tv = 1.0f;//triangle 8v[21].x = 100; V[21].Y = 100; V[21].z = +; V[21].vcn[0] =-1; V[21].VCN[1] = 0; V[21].VCN[2] = 0; v[21].tu = 0.0f; v[21].tv = 0.0f; v[22].x = 100; V[22].Y =-100; V[22].z = -100; v[22].vcn[0] = 1; V[22].VCN[1] = 0; V[22].VCN[2] = 0; v[22].tu = 1.0f; v[22].tv = 1.0f;v[23].x = 100; V[23].Y =-100; V[23].z = +; V[23].vcn[0] =-1; V[23].VCN[1] = 0; V[23].VCN[2] = 0; v[23].tu = 0.0f; v[23].tv = 1.0f;//calculate the Tangent vectorcalctangent (v); for (int i = 0; i <; i + +) index[i] = i; return 0;} End for Createroom</span>

After constructing the 24 vertex data, we calculate the T-vector in tangent space and save the array.

Well, after the calculations are done, we'll render them through the following functions:

<span style= "Font-family:microsoft Yahei;" >void Renderomnipass (UINT BID, uint vsID, uint PsID, uint nLight) {Zfxmatrix mattenu;static float n = 0.0f; Zfxvector pos_1 (100.0f, -100.0f, 0.0f); Zfxvector pos_2 ( -100.0f, 100.0f, 0.0f); Zfxvector pos; if (nLight = = 1) pos = pos_1; elsepos = pos_2; Zfxmatrix mrotate;mrotate.identity (); Mrotate.rotatey (n); n + = 0.01f;pos = pos * mrotate;//set the help vector to C30zfxvec Tor Vhelp (0.5f, 0.5f, 0.5f); if (FAILED (G_pdevice->setshaderconstant (sht_vertex,dt_float, 1, &vhelp))) return;//set the light color to c0zfxcolor Lightcolor = {1.0f, 1.0f, 1.0f, 1.0f};if (FAILED (G_pdevice->setshaderconstan T (sht_pixel,dt_float, 0, 1, &lightcolor)) return, if (FAILED (G_pdevice->activatevshader (VsID, Vid_ut))) return ; if (FAILED (G_pdevice->activatepshader (PsID))) return; Zfxmatrix mw;mw.identity (); G_pdevice->setworldtransform (&AMP;MW);//set the light position to C25zfxmatrix InvM; Invm.inverseof (mW);p OS = pos * INVM; if (FAILED (g_pdevice->setsHaderconstant (Sht_vertex, Dt_float, 1, &pos))) return;//set the world_transform to C31zfxmatrix Transm; transM.tr Ansposeof (MW), if (FAILED (G_pdevice->setshaderconstant (Sht_vertex,dt_float, 4, &AMP;TRANSM))) return; g_ Pdevice->useadditiveblending (True); if (FAILED (G_pdevice->getvertexcachemanager ()->render (BID)) return; G_pdevice->useadditiveblending (false);} End for Renderomnipass</span>

There is nothing too troublesome in the above function. The only thing to note is that we need to transform the light source into the coordinate space of the model, because we want to light the light in the model's coordinate space. Here is the vertex Shader and pixel Shader for this instance program:
<span style= "Font-family:microsoft Yahei;" >vs.1.1                 dcl_position  v0dcl_normal    v3dcl_texcoord  v7dcl_tangent v8m4x4   oPos, V0, C0  ; Transform Positionmov R5, V8mov R7, v3; Calculate Binormal V as; Crossproduct of U and Nmul R0,r5.zxyw,-r7.yzxw;mad R6,r5.yzxw,-r7.zxyw,-r0;; Build vector to_lightsub R2, C25, V0; Transform To_light vectordp3 r8.x, r5.xyz, R2dp3 r8.y, r6.xyz, R2dp3 r8.z, R7.XYZ, R2; Normalize transformed To_light vectordp3 r8.w, R8, R8rsq R8.W, R8.wmul R8, R8, R8.W; *.5 +. 5mad od0.xyz, r8.xyz, c30.x, c30.x   mov ot0.xy, V7.xymov ot1.xy, v7.xy</span>

<span style= "Font-family:microsoft Yahei;" >ps.1.1                 Tex t0 Tex T1                dp3 R1, t1_bx2, v0_bx2      mul r0, C0, T0mul r0, R1, r0</span>

I use assembly Shader here, if you do not understand the words also have no relationship, with the above on the tangent space calculation, the reader should be able to completely use HLSL for lighting calculation.


The final program is as follows:


All right, today's notes are over!

Zfxengine Development Note Bump Mapping (2)

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.