environment mapping的技術(shù)可以不依賴ray-trace而實現(xiàn)復(fù)雜環(huán)境我反射,這種技術(shù)使用一個或多個紋理來模擬外部環(huán)境的反射,這種技術(shù)最適合于應(yīng)用到具有高亮鏡面的物體。
環(huán)境映射方法是從視點到反射物體某點P的一根光纖,根據(jù)P點的位置與法向n,計算得到反射光線r,不像光線跟蹤那樣真正去計算反射光線的最近交點,環(huán)境映射方法則用該反射光線作為一個索引,得到環(huán)境映射中的相應(yīng)的環(huán)境紋理。
其中計算映射到物體的紋理是通過計算視點到正方體表面點的向量的反向量
根據(jù)http://www.cnblogs.com/sssa2000/archive/2009/03/22/1419205.html中提到的:
在一個環(huán)境中生成球面貼圖的時候,由于環(huán)境相對于球體而言無限大,所以可以把球體看成是一個單位球體。同時,有由于相機(jī)位于無限遠(yuǎn)處,所以相機(jī)到球體上的各個點的向量可以看成是相互平行的。
于是很容易的想到:
1、生成視線向量V。
2、根據(jù)頂點法線生成反射向量R。
3、查找R和球面的交點。
4、根據(jù)交點求出UV坐標(biāo)。
R可以很容易的求出。為了求出UV,需要求出R和球面的交點E在球面的位置。這個時候回到生成球面紋理圖時候的場景,由于球面是單位球面,利用單位球面的一個性質(zhì):球面上的點的歸一化法線就是該點在球面上的位置。
我們只需要知道在生成球面紋理圖的時候,在球面上相同的點,當(dāng)反射向量也為R的時候該點的法線為多少即可。
根據(jù)向量加法原則,法線是視線向量和反射向量的和。為了模擬視點位于無限遠(yuǎn)處的情況,可以假象生成球面紋理圖的過程是位于View Space,這樣的話,Eye Vec就總是(0,0,1)。于是只需要把反射向量也轉(zhuǎn)化到View Space就可以得出球面的法線向量。
也可以這樣理解:
環(huán)境貼圖的坐標(biāo)和一般2D的貼圖的貼圖坐標(biāo)不同,首先它需要用三維向量(x,y,z)來定位,GPU以(x,y,z)中絕對值最大的那個軸來決定要采用哪站貼圖,假如坐標(biāo)為(1,0,0),X軸數(shù)值的絕對值最大,所以會采用X軸方向視角的兩貼圖的其中一個,又因為X>0,即正直,所以會用正X軸方向的貼圖。
選擇好貼圖以后,再把三維貼圖坐標(biāo)轉(zhuǎn)換成正常的二維坐標(biāo),轉(zhuǎn)換方法是把絕對值最大的數(shù)值除以其他兩個數(shù)值,再把得到的結(jié)果從-1到1的范圍使用公式f(x)=(x+1.0)*0.5轉(zhuǎn)換到0~1的范圍,假如貼圖坐標(biāo)是(2,0,0),那么會使用正x軸方向的貼圖,讀取坐標(biāo)位置為(0.5,0.5)的像素,
繪制渲染環(huán)境代碼
1
void draw_environment ()
{
2
static GLfloat xPlane[] =
{ 1.0f, 0.0f, 0.0f, 0.0f };
3
static GLfloat yPlane[] =
{ 0.0f, 1.0f, 0.0f, 0.0f };
4
static GLfloat zPlane[] =
{ 0.0f, 0.0f, 1.0f, 0.0f };
5
6
glEnable (GL_TEXTURE_GEN_S);
7
glEnable (GL_TEXTURE_GEN_T);
8
glEnable (GL_TEXTURE_GEN_R);
9
10
/**//* Bind to cube map texture */
11
glEnable (GL_TEXTURE_CUBE_MAP_ARB);
12
glBindTexture (GL_TEXTURE_CUBE_MAP_ARB, g_uiCubemapTexture);
13
14
//Setup auto texture coord generation
15
glTexGeni (GL_S, GL_TEXTURE_GEN_MODE, GL_OBJECT_LINEAR);
16
glTexGeni (GL_T, GL_TEXTURE_GEN_MODE, GL_OBJECT_LINEAR);
17
glTexGeni (GL_R, GL_TEXTURE_GEN_MODE, GL_OBJECT_LINEAR);
18
19
glTexGenfv (GL_S, GL_OBJECT_PLANE, xPlane);
20
glTexGenfv (GL_T, GL_OBJECT_PLANE, yPlane);
21
glTexGenfv (GL_R, GL_OBJECT_PLANE, zPlane);
22
23
glDisable (GL_DEPTH_TEST);
24
25
// glutSolidSphere (20.0f, 60, 30);
26
glutSolidCube (20.0f);
27
28
glEnable (GL_DEPTH_TEST);
29
30
glDisable (GL_TEXTURE_CUBE_MAP_ARB);
31
32
glDisable (GL_TEXTURE_GEN_S);
33
glDisable (GL_TEXTURE_GEN_T);
34
glDisable (GL_TEXTURE_GEN_R);
35
} 繪制反射場景:
1
void myDispaly()
{
2
GLfloat mat[16], invmat[16];
3
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
4
glMatrixMode (GL_TEXTURE);
5
glLoadIdentity ();
6
glMatrixMode (GL_MODELVIEW);
7
glLoadIdentity ();
8
glTranslatef (0.0, 0.0, -5.0);
9
10
glRotated (cam_rot.x, 1.0f, 0.0f, 0.0f);
11
glRotated (cam_rot.y, 0.0f, 1.0f, 0.0f);
12
glRotated (cam_rot.z, 0.0f, 0.0f, 1.0f);
13
draw_environment ();
14
15
16
glEnable (GL_TEXTURE_GEN_S);
17
glEnable (GL_TEXTURE_GEN_T);
18
glEnable (GL_TEXTURE_GEN_R);
19
20
glTexGeni (GL_S, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP);
21
glTexGeni (GL_T, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP);
22
glTexGeni (GL_R, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP);
23
24
25
26
glEnable (GL_TEXTURE_CUBE_MAP_ARB);
27
glBindTexture (GL_TEXTURE_CUBE_MAP_ARB, g_uiCubemapTexture);
28
29
glGetFloatv (GL_MODELVIEW_MATRIX, mat);
30
compute_matrix_inverse (mat, invmat);
31
32
glMatrixMode (GL_TEXTURE);
33
invmat[12] = 0.0f;
34
invmat[13] = 0.0f;
35
invmat[14] = 0.0f;
36
invmat[15] = 1.0f;
37
glLoadMatrixf (invmat);
38
39
40
41
glMatrixMode (GL_MODELVIEW);
42
glRotated(45,0,1,0);
43
glRotated(180,1,0,0);
44
glutSolidTeapot(1.0);
45
46
47
glDisable (GL_TEXTURE_CUBE_MAP_ARB);
48
49
50
glDisable (GL_TEXTURE_GEN_S);
51
glDisable (GL_TEXTURE_GEN_T);
52
glDisable (GL_TEXTURE_GEN_R);
53
glutSwapBuffers();
54
} 渲染結(jié)果:
旋轉(zhuǎn)場景:
參考:
http://www.nvidia.cn/object/cube_chs.htmlhttp://www.cnblogs.com/sssa2000/archive/2009/03/22/1419205.html