纹理映射 【转】
9.4 紋理對象
使用紋理對象來存儲紋理數據的步驟:
1) 生成紋理對象名稱
2) 將紋理對象綁定到紋理數據(包括圖像數據數組和紋理屬性), 即創建紋理對象.
3) 如果OpenGL實現高性能紋理工作集, 應檢查是否有足夠的空間來存儲所有的紋理對象. 如沒有足夠空間, 應設置每個紋理對象的優先級, 以確保最常用的紋理留在工作集中
4) 綁定和重新綁定紋理對象, 以便可以將其中的紋理映射到物體上.
9.4.1 生成紋理對象名稱
void glGenTextures(GLsizei n, GLint* textureNames);
功能: 通過數組textureNames返回n個未用的紋理對象名, 返回的名稱不必是相鄰的整數.
GLboolean glIsTexture(GLint textureName);
功能: 如textureName是已被綁定的紋理對象名, 且沒有被刪除, 則返回GL_TRUE, 如textureName為0, 或非0, 但不是已有紋理對象的名稱, 返回GL_FALSE.
注意: 如一倍glGenTextures()返回, 但未使用glBindTextures()綁定, 仍返回GL_FALSE.
9.4.2 創建和使用紋理對象
void glBindTexture(GLenum target, GLuint textureName);
功能: 完成下面幾項工作.
1) 如textureName為非零無符號整數, 首次被使用, 則創建一新的紋理對象, 并將其名稱設置為參數textureName的值.
2) 綁定一個已創建的紋理對象時, 該紋理對象將進入活動狀態.
3) 如textureName為0, OpenGL將停止使用紋理對象, 返回到未命名的默認紋理.
4) 首次被創建時, target指定了維數, 其取值為GL_TEXTURE_1D, GL_TEXTURE_2D, GL_TEXTURE_3D 或 GL_TEXTURE_CUBE_MAP.
5) 首次被創建時, 諸如縮小濾波方法, 放大濾波方法, 環繞模式, 邊框顏色, 紋理優先級等紋理屬性被設置為默認值.
例 9.7 綁定紋理對象: tebind.c
紋理駐留策略
如果有多個使用周期較短且大小相同的紋理, 可以調用函數glTexSubImage*()將不同的圖像加載到已有的紋理對象中.與刪除并重新創建紋理對象相比, 這樣做的效率可能更高
void glPrioritiesTextures(GLsizei n, const GLuint *textureNames, const GLclampf *priorities);
功能: 將n個紋理對象的優先級設置為指定的值, 數組textureNames指定了這些紋理對象的名稱, 數組priorities指定了優先級.
priorities: 指定了優先級, 將其值截取到[0.0, 1.0], 0對應的優先級最低, 1對應的優先級最高
函數glPrioritiesTextures()步要求textureNames中指定的紋理對象被綁定過.
函數glTexParameter*()也可用于設置單個紋理對象的優先級. 但僅限于當前綁定的紋理對象.
9.4.5 紋理函數
void glTexEnv(if)(GLenum target, GLenum pname, TYPE param);
void glTexEnv(if)v(GLenum target, GLenum pname, TYPE* param);
功能: 設置當前的紋理映射方式.
target: 必須為GL_TEXTURE_FILTER_CONTROL或GL_TEXTURE_ENV
pname: 如target為GL_TEXTURE_FILTER_CONTROL, pname必須為GL_TEXTURE_LOD_BIAS.
?????? 如target為GL_TEXTURE_ENV, pname可為GL_TEXTURE_ENV_MODE, GL_TEXTURE_ENV_COLOR
param: 如pname為GL_TEXTURE_LOD_BIAS, param是一個浮點數, 用于指定GL_TEXTURE_LOD_BIAS的值.
?????? 如pname為GL_TEXTURE_ENV_MODE,param的取值為GL_DECAL,GL_REPLACE,GL_MODULATE,GL_BLEND, GL_ADD或GL_COMBINE. 指定了如何將紋理值和片元的顏色值合并起來.
?????? 如pname為GL_TEXTURE_ENV_COLOR, 則參數pname是一個包含4個浮點數的數組, 這4個元素分別是R, G, B, A分量, 指定了一種用于GL_BLEND操作的顏色.
紋理映射方式和基本內部結構一起決定了如何應用紋素數據的各個分量.
紋理映射方式作用于被選擇的紋素數據分量和片元的顏色值.
函數glTexImage*D()指定紋理圖像時, 第三個參數指定了紋理的內部格式. 有6種基本內部格式:
GL_ALPHA, GL_LUMINANCE, GL_LUMINANCE_ALPHA, GL_INTENSITY, GL_RGB, GL_RGBA.
其他內部結構如GL_LUMINANCE6_ALPHA2和GL_R3_G3_B2, 對應于6種基本內部格式之一. 它們指定紋素數據分量的精度.
紋理映射計算是以RGBA方式進行的, 但有些內部格式不是RGB.
將各種紋理格式轉換為顏色值:
基本內部結構?????????? 轉換得到的RGBA顏色值
GL_ALPHA?????????? (0, 0, 0, A)
GL_LUMINANCE?????????? (1, 1, 1, 1)
GL_LUMINANCE_ALPHA?????? (1, 1, 1, A)
GL_INTENSITY?????????? (1, 1, 1, 1)
GL_RGB?????????????? (R, G, B, 1)
GL_RGBA?????????????? (R, G, B, A)
紋理映射方式替換, 調整和貼花
基本內部格式
GL_REPLACE
GL_MODULATE
GL_DECAL
GL_ALPHA
C = Cf
A = As
C = Cf
A = AfAs
未定義
GL_LUMINANCE
C = Cf(1 - Cs) + CcCs
A = Af
C = Cf + Cs
A = Af
未定義
GL_LUMINANCE_ALPHA
C = Cf(1 - Cs) + CcCs
A = AfAs
C = Cf + Cs
A = AfAs
未定義
GL_INTENSITY
C = Cf(1 - Cs) + CcCs
A = Af(1 - As) + AcAs
C = Cf + Cs
A = Af + As
未定義
GL_RGB
C = Cf(1 - Cs) + CcCs
A = Af
C = Cf + Cs
A = Af
C = Cs
A = Af
GL_RGBA
C = Cf(1 - Cs) + CcCs
A = AfAs
C = Cf + Cs
A = AfAs
C = Cf(1-As) + CsAs
A = Af
紋理映射方式混合和相加
基本內部格式
GL_BLEND
GL_ADD
GL_ALPHA
C = Cf
A = AfAs
C = Cf
A = AfAs
GL_LUMINANCE
C = Cf(1 - Cs) + CcCs
A = Af
C = Cf + Cs
A = Af
GL_LUMINANCE_ALPHA
C = Cf(1 - Cs) + CcCs
A = AfAs
C = Cf + Cs
A = AfAs
GL_INTENSITY
C = Cf(1 - Cs) + CcCs
A = Af(1 - As) + AcAs
C = Cf + Cs
A = Af + As
GL_RGB
C = Cf(1 - Cs) + CcCs
A = Af
C = Cf + Cs
A = Af
GL_RGBA
C = Cf(1 - Cs) + CcCs
A = AfAs
C = Cf + Cs
A = AfAs
各個下標的含義如下:
s表示計算得到的紋理顏色
f表示片元值
c表示GL_TEXTURE_ENV_COLOR的值
沒有下標的值表示通過計算得到的最終結果
紋理映射方式替換用紋理顏色替換片元的顏色,
紋理映射方式貼花類似于替換, 但它只適用于RGB和RGBA, 同時處理alpha的方式也不同.
內部格式為RGBA時, 紋理映射方式貼花將片元的顏色和紋理顏色混合起來, 混合比率由紋理的alpha決定, 片元的alpha不變.
紋理映射方式調整根據紋理圖像的內容對片元的顏色進行調整.
內部格式為GL_LUMINANCE, GL_LUMINANCE_ALPHA, GL_INTENSITY時, 各顏色分量乘以相同的值, 調整后的顏色位于片元顏色和黑色之間.
內部格式為GL_RGB和GL_RGBA時, 片元顏色的各個分量與紋理中相應的分量相乘, alpha值也同片元alpha相乘. 光照適合使用紋理映射方式調整.
紋理映射方式相加將紋理顏色和片元顏色相加, 如有alpha值, 其乘以片元的alpha值, 但內部格式為GL_INTENSITY時除外.這種情況紋理alpha值與片元alpha值相加.
紋理映射方式混合是唯一一種使用GL_TEXTURE_ENV_COLOR指定的顏色的映射方式.
它像使用alpha值那樣使用輝度,強度或顏色值將片元顏色和GL_TEXTURE_ENV_COLOR指定的顏色混合.
9.5 指定紋理坐標
紋理坐標可包含1-4個分量, 這些分量通常被稱為s, t, r和q坐標.
一維紋理, 使用s坐標. 二維紋理, 使用s和t坐標, 三維紋理, 使用s, t和r坐標. q坐標通常被設置為1, 用于創建齊次坐標.
void glTexCoord[1234][sifd](TYPE coords);
void glTexCoord[1234][sifd]v(TYPE* coords);
功能: 設置當前的紋理坐標(s,t,r,q),
9.5.1 計算合適的紋理坐標
由于映射的格式與紋理格式不符,容易造成扭曲的情況,這次要選擇恰當的紋理坐標來映射.
9.5.2 紋理的重復和截取
紋理坐標被指定為范圍[0, 1]之外的值時, 將截取紋理坐標或重復紋理圖像.
也可以使用環繞模式"鏡像(mirrored)"重復, 重復時翻轉紋理圖像.
例如: 在紋理坐標范圍[0,1]內,俺原來順序使用紋理數據, [1, 2]則相反順序使用紋理數據, [2, 3]又按原來的順序使用, 依次類推
另一種環繞模式是截取紋理坐標: 將大于1.0的坐標設置為1.0, 將小于0.0的坐標設置為0.0.
如何使用紋理邊框顏色:
1) 如果環繞模式為GL_REPEAT, 總是忽略邊框. 從對側選擇一個2X2紋素陣列來計算加權平均.
2) 如果環繞模式為GL_CLAMP, 將邊框紋素(或GL_TEXTURE_BORDER_COLOR的值)用于計算2X2加權平均.
3) 如果環繞模式為GL_CLAMP_TO_EDGE, 總是忽略邊框. 使用紋理邊緣或靠近紋理邊緣的紋素被用于紋理計算, 但不使用邊框上的紋素.
4) 如果環繞模式為GL_CLAMP_TO_BORDER, 紋理坐標超出了范圍[0, 1], 則只使用邊框紋素(如果沒有邊框, 使用邊框常量顏色)來計算紋理映射.
?? 在紋理坐標的上限和下限附近, 可能將邊框紋素和內部紋素作為樣本加入到2X2紋素陣列中.
環繞模式截取時, 為避免曲面其他部分受紋理的影響, 紋理邊緣的紋素的alpha值設置為0,
示例: 環繞模式為GL_REPEAT, 紋理坐標為 4.0上限
指定S和T方向重復環繞.
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
如果GL_REPEAT改為GL_CLAMP, 則效果如下
如S方向為GL_CLAMP, T方向為GL_REPTEAT, 效果如下
void glTexParameter[if](GLenum target, GLenum pname, TYPE param);
void glTexParameter[if]v(GLenum target, GLenum pname, TYPE* param);
功能: 設定紋理如何處理片段或者如何存儲紋理對象
pname的取值
param的取值
GL_TEXTURE_WRAP_S
GL_CLAMP,GL_CLAMP_TO_BORDER, GL_CLAMP_TO_EDGE, GL_MIRRORED_REPEAT, GL_REPEAT
GL_TEXTURE_WRAP_T
GL_CLAMP,GL_CLAMP_TO_BORDER, GL_CLAMP_TO_EDGE, GL_MIRRORED_REPEAT, GL_REPEAT
GL_TEXTURE_WRAP_R
GL_CLAMP,GL_CLAMP_TO_BORDER, GL_CLAMP_TO_EDGE, GL_MIRRORED_REPEAT, GL_REPEAT
GL_TEXTURE_MAG_FILTER
GL_NEAREST, GL_LINEAR
GL_TEXTURE_MIN_FILTER
GL_NEAREST, GL_LINEAR, GL_NEAREST_MIPMAP_NEAREST,
GL_NEAREST_MIPMAP_LINEAR,
GL_LINEAR_MIPMAP_NEAREST,
GL_LINEAR_MIPMAP_LINEAR
GL_TEXTURE_BORDER_COLOR
4個[0.0, 1.0]內的任何值
GL_TEXTURE_PRIORITY
[0.0, 1.0]內的任何值, 設置當前紋理對象的優先級
GL_TEXTURE_MIN_LOD
任何浮點數
GL_TEXTURE_MAX_LOD
任何浮點數
GL_TEXTURE_BASE_LEVEL
任何非負整數
GL_TEXTURE_MAX_LEVEL
任何非負整數
GL_DEPTH_TEXTURE_MODE
GL_LUMINANCE, GL_INTENSITY, GL_ALPHA
GL_TEXTURE_COMPARE_MODE
GL_NONE, GL_COMPARE_R_TO_TEXTURE
GL_TEXTURE_COMPARE_FUNC
GL_LEQUAL, GL_GEQUAL
GL_GENERATE_MIPMAP
GL_TRUE, GL_FALSE
GL_TEXTURE_BORDER_COLOR: 紋理映射計算使用的邊框信息.濾波方法為GL_NEAREST,環繞模式為GL_CLAMP_TO_BORDER時, 邊框顏色影響貼上紋理的物體.
???????????????????????? 當濾波方法為GL_LINEAR, 環繞模式為GL_CLAMP時, 邊框也會影響紋理映射.
???????????????????????? 環繞模式為GL_CLAMP_TO_EDGE或GL_REPEAT, 邊框顏色將被忽略.
9.6 自動生成紋理坐標
void glTexGen[ifd](GLenum coord, GLenum pname, TYPE param);
void glTexGen[ifd]v(GLenum coord, GLenum pname, TYPE *param);
功能: 指定用于自動生成紋理坐標的函數(function).
coord: 必須是GL_S, GL_T, GL_R, GL_Q. 指出生成s, t, r還是q紋理坐標.
pname: 為GL_TEXTURE_GEN_MODE, GL_OBJECT_PLANE, GL_EYE_PLANE
param: 如pname為GL_TEXTURE_GEN_MODE, param為一個整數, 取值為GL_OBJECT_LINEAR, GL_EYE_LINEAR, GL_SPHERE_MAP, GL_REFLECTION_MAP, GL_NORMAL_MAP
pname為其他值, param是一個指向數組的指針(向量版本), 數組中包含提供給紋理生成函數的參數值.
紋理圖像映射到固體物體上, 使用物體坐標指定參考較合適. GL_OBJECT_LINEAR.
移動的物體上生成動態的等高線時, 使用眼坐標GL_EYE_LINEAR較合適.
球形環境映射用GL_SPHERE_MAP較合適.
立方圖用GL_NORMAL_MAP.
9.6.1 創建等高線
使用GL_TEXTURE_GEN_MODE 和 GL_OBJECT_LINEAR時, 紋理生成函數是頂點的物體坐標(x0, y0, z0, w0)的線性組合:
生成的坐標 = p1x0 + p2y0 + p3z0 + p4w0
其中p1,p2,p3,p4是參數pname為GL_OBJECT_PLANE時, 參數param的值.如果p1, p2, p3和p4被歸一化, 計算的結果將是頂點到一個平面的距離.
例如: p2 = p3 = p4 = 0; p1 = 1, 計算結果為頂點到平面x = 0的距離.
例9.8 texgen.c
函數glEnable()使用參數GL_TEXTURE_GEN_S來啟用自動生成紋理坐標x.
函數glTexGen*()使用參數GL_OBJECT_LINEAR表示在模型的坐標系下計算紋理坐標. GL_EYE_LINEAR表示在眼坐標系下計算紋理坐標.
環境映射指的是渲染物體時, 將其視為全反射的, 使其表面的顏色為周圍環境反射到人眼中的顏色.
實現環境映射需要做的只是創建一個合適的紋理圖, 并讓OpenGL生成紋理坐標.
創建了用于環境映射的紋理后, 需要啟用OpenGL的環境映射算法
自動生成紋理坐標以支持環境映射的代碼:
glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_SPHERE_MAP);
glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_SPHERE_MAP);
glEnable(GL_TEXTURE_GEN_S);
glEnable(GL_TEXTURE_GEN_T);
紋理映射方法GL_SPHERE_MAP生成合適的環境映射紋理坐標.
9.6.3 立方圖紋理(cube map texture)
使用6個二維紋理圖來構成一個以原點為中心的紋理立方體.對于每個片元, 其紋理坐標(s, r, t)被視為方向向量, 而紋素表示從原點看到的紋理立方體上的東西.
要創建立方圖紋理, 可調用glTexImage2D()6次, 每次調用該函數時使用參數target指定立方體的面
GL_TEXTURE_CLUB_MAP_POSITIVE_X, GL_TEXTURE_CLUB_MAP_NEGATIVE_X, GL_TEXTURE_CLUB_MAP_POSITIVE_Y, GL_TEXTURE_CLUB_MAP_NEGATIVE_Y,
GL_TEXTURE_CLUB_MAP_POSITIVE_Z, GL_TEXTURE_CLUB_MAP_NEGATIVE_Z
立方圖有專用的紋理代理 GL_PROXY_TEXTURE_CUB_MAP
應將立方圖視為一個整體, 為其指定紋理參數和創建紋理對象, 而不是分別對6個禮方面指定紋理參數和創建紋理對象.
下述設置立方圖的環繞模式和濾波方法的代碼將參數target的值設置為GL_TEXTURE_CUBE_MAP
glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_S, GL_REPEAT);
glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_T, GL_REPEAT);
glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_R, GL_REPEAT);
glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
對于給定的片元, 根據紋理坐標(s, t, r)中哪個坐標值最大以及這個值的正負來決定使用哪個紋理,
前者決定主軸, 后者決定方向, 然后將其他兩個坐標值除以最大坐標值,得到新的坐標(s',t'),并據此來決定使用前面選中的紋理中的哪些紋素.
通常是調用函數glTexGen*()來自動生成立方圖紋理坐標, 并指定下述兩種紋理坐標生成模式之一: GL_REFLECTION_MAP和GL_NORMAL_MAP.
GL_REFLECTION_MAP適用于環境映射.
GL_NORMAL_MAP適用于渲染有定位光源和漫反射的場景.使用模型視點矩陣將頂點的發現向量變換為眼坐標(nx,ny,nz),并將其用作紋理坐標(s, t, r)
生成立方圖紋理坐標的代碼:
glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP);glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP);
glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP);
glEnable(GL_TEXTURE_GEN_S);
glEnable(GL_TEXTURE_GEN_T);
glEnable(GL_TEXTURE_GEN_R);
glEnable(GL_TEXTURE_CUBE_MAP);
9.7 多重紋理
多重紋理讓你在紋理操作流水線中依次將多個紋理應用于同一個多邊形.
1. 使用多重紋理的步驟
注意:在返回模式下使用多重紋理時, 只有第一個紋理單元的操作結果是確定的.
1) 對于每個紋理單元, 指定其紋理映射參數, 包括紋理圖像, 濾波方法, 映射方式, 紋理坐標生成方式和紋理矩陣.
?? 函數glGetIntegerv()使用參數GL_MAX_TEXTURE_UNITS 來了解OpenGL實現最多支持多少個紋理單元.
2) 指定頂點時, 使用函數glMultiTexCoord*()為每個頂點指定多組紋理坐標.每個紋理單元都需要一組坐標.每個紋理單元使用的坐標可能各不相同.
2. 建立紋理單元
使用多重紋理時, 需要有多個紋理單元. 每個紋理單元的功能都相同, 并存儲了各自的紋理處理參數.包括:
1)紋理圖像 2)濾波參數 3)紋理映射方式 4)紋理矩陣堆棧 5)紋理坐標生成模式 6)頂點數組(如果需要的話)
要設置紋理映射參數, 使用函數glActiveTexture()來指定要對其進行設置的紋理單元,
然后調用函數glTexImage*(), glTexParameter*(), glTexEnv*(), glTexGen*()和glBindTexture()來設置其紋理映射參數.
void glActiveTexture(GLenum texUnit);
功能: 選擇一個紋理單元, 接下來的紋理函數將修改該紋理單元.
texUnit: 為符號常量GL_TEXTUREi,其中i的取值范圍為0到k-1, k是OpenGL實現支持的最大紋理單元數.
3. 指定頂點及其紋理坐標
void glMultiTexCoord(1234)(sifd)(GLenum texUnit, TYPE coords);
void glMultiTexCoord(1234)v(sifd)(GLenum texUnit, TYPE* coords);
功能: 將參數coords中的紋理坐標(s, i, r, q)用于紋理單元texUnit, 參數texUnit的取值與函數glActiveTexture()中相同.
對位圖或圖像使用多重紋理時, 需要為每個光柵位置指定多組紋理坐標.
因此,每次調用函數glRasterPos*()或glWindowPos*()時, 為每個紋理單元調用函數glMultiTexCoord*().
4. 其他指定紋理坐標的方法
1) 自動生成紋理坐標(函數glTexGen*())
?? 使用函數glActiveTexture()來指定下面紋理坐標生成函數影響哪個紋理單元 glTexGen*(), glEnable(GL_TEXTURE_GEN_*), glDisable(GL_TEXTURE_GEN_*)
2) 使用頂點數組glTexCoordPointer()
?? 函數glClientActiveTexture()用于指出函數glTexCoordPointer()將為哪個紋理單元指定紋理坐標
void glClientActiveTexture(GLenum texUnit);
?? 功能: 指定要用頂點數組為哪個紋理單元指定紋理坐標.
?? texUnit: 取值與glActiveTexture相同.
5. 恢復到使用單個紋理單元
對處紋理單元0之外的所有紋理單元禁用紋理映射功能.
9.8 紋理組合函數
void glTexEnv[if](GLenum target, GLenum pname, TYPE param);
void glTexEnv[if]v(GLenum target, GLenum pname, TYPE* param);
功能: 設置當前紋理映射方式
target: 必須為GL_TEXTURE_FILTER_CONTROL 或 GL_TEXTURE_ENV.
pname: 如target為GL_TEXTURE_FILTER_CONTROL, pname必須為GL_TEXTURE_LOD_BIAS
param: pname為GL_TEXTURE_LOD_BIAS, param為浮點數, 用于指定GL_TEXTURE_LOD_BIAS的值.
如果紋理映射方式為GL_BLEND, 將使用GL_TEXTURE_ENV_COLOR的值來與片元混合, 因此必須設置它.
如果紋理映射方式為GL_COMBINE, 還可能需要設置GL_COMBINE_RGB, GL_COMBINE_ALPHA, GL_RGB_SCALE 或 GL_ALPHA_SCALE.
如果設置了GL_COMBINE_RGB, 可能還需要設置參數GL_SOURCEi_RGB 和 GL_OPERANDi_RGB(其中i為0, 1, 2)的值.
如果設置了GL_COMBINE_ALPHA, 可能還需要設置參數GL_SOURCEi_ALPHA 和 GL_OPERANDi_ALPHA(其中i為0, 1, 2)的值.
參數target為GL_TEXTURE_ENV時參數pname和param的取值
pname?????????????? param
GL_TEXTURE_ENV_MODE?????? GL_DECAL, GL_REPLACE, GL_MODULATE, GL_BLEND, GL_ADD, GL_COMBINE
GL_TEXTURE_ENV_COLOR?????? 包括4個浮點數的數組, 表示分量R, G, B, A的值
GL_COMBINE_RGB?????????? GL_REPLACE, GL_MODULATE, GL_ADD, GL_ADD_SIGNED, GL_INTERPOLATE, GL_SUBTRACT, GL_DONT3_RGB, GL_DOT3_RGBA
GL_COMBINE_ALPHA?????? GL_REPLACE, GL_MODULATE, GL_ADD, GL_ADD_SIGNED, GL_INTERPOLATE, GL_SUBTRACT
GL_SOURCEi_RGB,
GL_SOURCEi_ALPHA?????? GL_TEXTURE, GL_TEXTUREEx, GL_CONSTANT, GL_PRIMARTY_COLOR, GL_PREVIOUS
GL_OPERANDi_RGB?????????? GL_SRC_COLOR, GL_ONE_MINUS_SRC_COLOR, GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA
GL_OPERANDi_ALPHA?????? GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA
GL_RGB_SCALE?????????? 表示顏色分量縮放因子的浮點數
GL_ALPHA_SCALE?????????? 表示alpha分量縮放因子的浮點數
多重紋理, 不同的紋理單元中使用不同的組合函數, 執行步驟:
1) 使用合并函數, 首先必須調用函數glTexEnvf()
?? glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE);
2) 指定如何組合RGB, alpha值
參數param的值?????????? 組合函數
GL_REPLACE?????????? Arg0
GL_MODULATE(默認)?????? Arg0 * Arg1
GL_ADD?????????????? Arg0 + Arg1
GL_ADD_SIGNED?????????? Arg0 + Arg1 - 0.5
GL_INTERPOLATE?????????? Arg0 * Arg2 + Arg1 * (1 - Arg2)
GL_SUBTRACT?????????? Arg0 - Arg1
GL_DOT3_RGB??
GL_DOT3_RGBA?????????? 4*((Arg0r - 0.5)*(Arg1r - 0.5) + (Arg0g - 0.5)*(Arg1g - 0.5) + (Arg0b - 0.5)*(Arg1b - 0.5))
注意: 只能將參數GL_COMBINE_RGB的值設置為GL_DOT3_RGB和GL_DOT3_RGBA, 而不能將GL_COMBINE_ALPHA設置為這樣的值.
組合函數GL_DOT3_RGB和GL_DOT3_RGBA之間的差別很小, 前者將R, G, B的值都設置為計算結果, 后者將R, G, B, A的值都設置為計算結果.
3)GL_SOURCEi_RGB來指定組合函數的第i個參數的來源, 例如: 組合函數GL_SUBTRACT需要兩個參數.
指定組合函數的參數來源代碼:
glTexEnvf(GL_TEXTURE_ENV, GL_SOURCE0_RGB, GL_TEXTURE);
glTexEnvf(GL_TEXTURE_ENV, GL_SOURCE1_RGB, GL_PREVIOUS);
參數pname為GL_SOURCEi_RGB時, 參數param指定組合函數第i個參數的來源, 其可能取值如下:
GL_TEXTURE: 第i個參數來自當前紋理單元中的紋理
GL_TEXTUREn: 第i個參數來自第n個紋理單元中的紋理
GL_CONSTANT: 使用GL_TEXTURE_ENV_COLOR設置的常量顏色
GL_PRIMARY_COLOR: 片元進入紋理單元0時的顏色, 即片元最初的顏色.
GL_PREVIOUS: 前一個紋理單元輸出的片元顏色(對紋理單元0來說, 含義與GL_PRIMARY_COLOR相同)
4) 指定來源中的哪些值(RGB還是alpha), 以及如何使用它們.
GL_OPERAND/_RGB 指定如何使用來源GL_SOURCE/_RGB中的顏色值
GL_OPERAND/_ALPHA指定如何使用來源GL_SOURCEi_ALPHA中的ALPHA值
在RGB組合函數中使用alpha值的代碼
static GLfloat constColor[4] = { 0.1, 0.2, 0.3, 0.4 };
glTexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, constColor);
glTexEnvf(GL_TEXTURE_ENV, GL_SOURCE2_RGB, GL_CONSTANT);
glTexEnvf(GL_TEXTURE_ENV, GL_OPERAND2_RGB, GL_SRC_ALPHA);
上例另Arg2的R,G,B分量都為0.4
5) (可選)設置RGB或alpha縮放因子. 默認設置如下:
glTexEnvf(GL_TEXTURE_ENV, GL_RGB_SCALE, 1.0);
glTexEnvf(GL_TEXTURE_ENV, GL_ALPHA_SCALE, 1.0);
6) 繪制幾何體, 確定其頂點有合適的紋理坐標
插值組合函數
插值組合函數適合用于演示紋理組合函數的用法, 因為它有三個參數, 且支持多種指定來源和操作數的方式
插值組合函數: combiner.c
/* 用作常量紋理顏色 */
static GLfloat constColor[4] = {0.0, 0.0, 0.0, 0.0};
constColor[3] = 0.2;
glTexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, constColor);
glBindTexture(GL_TEXTURE_ENV, texName[0]);
glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE);
glTexEnvf(GL_TEXTURE_ENV, GL_COMBINE_RGB, GL_INTERPOLATE);
glTexEnvf(GL_TEXTURE_ENV, GL_SOURCE0_RGB, GL_TEXTURE);
glTexEnvf(GL_TEXTURE_ENV, GL_OPERAND0_RGB, GL_SRC_COLOR);
glTexEnvf(GL_TEXTURE_ENV, GL_SOURCE1_RGB, GL_PREVIOUS);
glTexEnvf(GL_TEXTURE_ENV, GL_OPERAND1_RGB, GL_SRC_COLOR);
glTexEnvf(GL_TEXTURE_ENV, GL_SOURCE2_RGB, GL_CONSTANT);
/* 接下來渲染幾何體 */
一個活動的紋理單元. 由于組合函數為GL_INTERPOLATE. 因此有三個參數: 使用下述公式將這些參數組合起來: Arg0 * Arg2 + Arg1 * (1 - Arg2)
Arg0: 來自GL_TEXTURE---與當前綁定的紋理對象(texName[0])相關聯的紋理圖像.
Arg1: GL_PREVIOUS---前一個紋理單元的輸出. 由于當前紋理單元0, 因此是片元最初的顏色值.
Arg2: GL_CONSTANT---常量顏色, 當前為(0.0, 0.0, 0.0, 0.2);
插值結果為紋理圖像和片元的加權混合. 由于GL_OPERAND2_RGB被設置為GL_SRC_ALPHA, 因此常量顏色的alpha值被用于計算權重(Arg2)
上例, 程序將20%的紋理顏色和經過平滑著色的多邊形顏色的80%混合起來.
9.9 執行紋理映射后應用輔助顏色
執行紋理映射后, 在計算霧效之前, 有時候可能將輔助顏色用于片元, 使得鏡面反射區域(highlight)顯得更真實
9.9.1 光照被禁用時的輔助顏色
光照被禁用,且顏色累積模式被啟用---使用glEnable()調用參數GL_COLOR_SUM. 把當前的輔助顏色(由函數glSecondaryColor*()設置)與經過紋理映射處理后的片元顏色相加.
void glSecondaryColor3(b s i f d ub us ui)(TYPE r, TYPE g, TYPE b);
void glSecondaryColor3(b s i f d ub us ui)v(const TYPE *values);
功能: 設置當前輔助顏色的紅, 綠, 黃分量的值。
9.9.2 光照被啟用時的輔助鏡面反射顏色
注意: 如果光照被啟用, 則不管GL_COLOR_SUM模式是否被啟用, 都將應用鏡面反射顏色, 并忽略函數glSecondaryColor*()設置的輔助顏色.
9.10 紋理矩陣堆棧
要修改當前的紋理矩陣, 需要將矩陣模式設置為GL_TEXTURE, 如下所示
glMatrixMode(GL_TEXTURE);?? /* 進入紋理矩陣模式 */
glRotated(...);
/* 其他矩陣操作 */
glMatrixMode(GL_MODELVIEW);?? /* 返回模型視圖模式 */
1. q坐標
將紋理坐標(s, t, r, q)乘以紋理矩陣后, 得到的向量(s', t', r', q')被視為齊次紋理坐標. 換句話說, 根據s'/q', t'/q', r'/q'在紋理圖像中查找紋素.
需要多種投影變換時, 可以使用q坐標.
9.11 深度紋理
(1) 從光源的角度渲染場景. 不管場景如何, 你只需要深度值, 復制深度緩存中的值, 將其存儲到一個紋理圖中, 以創建一個陰影圖
(2) 生成紋理坐標, 其中(s, t)坐標表示陰影圖中的位置, 第三個紋理坐標r是距離光源的距離.
??? 再次繪制場景, 繪制時將r值同深度紋理值進行比較, 以判斷片元被光源照射還是位于陰影中.
9.11.1 創建陰影圖
第一步是創建一個由深度值組成的紋理圖. 為此, 將視點放在光源處, 并渲染場景.
范例中: 調用函數glGetLightfv()來獲得當前的光源位置, 然后計算向上向量, 并使用它來進行視點變換.
??????? 視口的大小設置成與紋理圖相同, 然后, 設置合適的透視矩陣和視點矩陣, 渲染場景中的物體, 并將深度圖像復制到紋理內存中,用作陰影圖.
??????? 最后, 將視口的位置和大小恢復到原來的設置.
1) 投影矩陣決定了燈罩的形狀. 函數gluPerspective()的參數lightFovy和lightAspect決定了燈罩的大小.lightFovy越小, 越接近于聚光燈. 其值越大, 越接近于泛光燈.
2) 光源的近裁剪面和遠裁剪面用于控制深度值的準確度. 近裁剪面和遠裁剪面之間的距離越小, 深度值的準確度越高.
3) 在深度緩存中建立深度值后, 需要復制它們, 并以內部格式GL_DEPTH_COMPONENT將它們存儲到紋理圖中.
?? 范例使用函數glCopyTexImage2D()根據深度緩存的內容創建了一個紋理圖像. 和其他紋理一樣, 紋理圖像的寬度和高度必須是2的冪
轉載于:https://www.cnblogs.com/mazhenyu/p/4798718.html
總結
- 上一篇: mac 安装Navicat Premiu
- 下一篇: Linux 下编译安装软件,找不到共享库