1觅捆、Mip貼圖
?
Mip貼圖簡介:
紋理對象可以從不同的視點距離進行觀察。在一個動態(tài)的場景中麻敌,當貼了紋理的物體遠離視點運動時栅炒,屏幕像素與紋理紋素之間的比率會變得非常低(屏幕像素/紋理紋素),因此紋理的采樣頻率也會變得非常低术羔。這樣會產生渲染圖像上的瑕疵赢赊,因為有紋理數據的下采樣(undersampling)的緣故。舉例來說级历,如果要渲染一面磚墻释移,可能會用到一張很大的紋理圖像(比如1024×1024個紋素),在觀察者距離墻很近的時候這樣是沒問題的寥殖。但是如果這面墻正在遠離觀察者運動玩讳,直到它在屏幕上變成了一個像素點,那么紋理采樣的結果可能會在某個過渡點上發(fā)生突然的變化(閃爍)嚼贡。
為了降低這個效果的影響锋边,可以對紋理貼圖進行提前濾波,并且將濾波后的圖像存儲為連續(xù)的低分辨率的版本(原始圖像為全分辨率)编曼。這就叫做mipmap豆巨,
Mipmap是目前應用最為廣泛的紋理映射技術之一。Willams將低一級圖像的每邊的分辨率取為高一級圖像的每邊的分辨率的二分之一(因此分辨率比例類推:1掐场、1/4往扔、1/16贩猎、1/64、...)萍膛,而同一級分辨率的紋理組則由紅吭服、綠、藍三個分量的紋理數組組成蝗罗。由于這一個查找表包含了同一紋理區(qū)域在不同分辨率下的紋理顏色值艇棕,因此被稱為Mipmap。
MIP來源于拉丁文中的multum in parvo(多級漸遠紋理)串塑,意為在一個小空間里的多數沼琉。Mipmap(有時候拼寫成mipmap)是一種電腦圖形圖像技術,用于在三維圖像的二維代替物中達到立體感效應桩匪。MIPmap技術與材質貼圖技術結合打瘪,根據距觀看者遠近距離的不同,以不同的分辨率將單一的材質貼圖以多重圖像的形式表現出來并代表平面紋理:尺寸最大的圖像放在前面顯著的位置傻昙,而相對較小的圖像則后退到背景區(qū)域闺骚。每一個不同的尺寸等級定義成一個MIPmap水平。MIPmap技術幫助避免了不想要的鋸齒邊緣(稱為鋸齒狀圖形)在圖像中出現妆档,這種鋸齒狀圖形可能是由于在不同分辨率下使用bitmap圖像產生的僻爽。
其實道理類似,紋理過大贾惦,每個紋素的大小相較于像素更小了胸梆,就導致每個像素覆蓋的區(qū)域實際上會包含多個紋素,但在片元著色階段只會進行一次「點采樣」纤虽,得到的結果顯然是不夠“精密”的乳绕。從信號學的角度上來理解,每個像素的采樣頻率遠遠低于紋理上的變化頻率逼纸,于是也會形成鋸齒的效果洋措。假設一張?zhí)貏e大的紋理貼在地面上,由于透視攝像機的近大遠小原理杰刽,會放大像素與紋素的信號頻率差距菠发,因此遠處的地面會形成一種叫做“摩爾紋”的效果。
既然是因為采樣頻率不夠贺嫂,那么解決這個問題一個最直觀的辦法就是 「超級采樣(Super Sampling)」 滓鸠,每個像素只采樣一次不足以覆蓋包含的所有紋素的話,那就多采樣幾次第喳,并將最終的采樣結果中和到一起糜俗,生成該像素的最終顏色。
超級采樣雖然的確能以較高的質量解決鋸齒問題,但計算成本實在是太高了悠抹!尤其是很遠處的像素珠月,為了抗鋸齒進行了大量的多重采樣,人眼看到的結果卻無法辨別細節(jié)楔敌,這無疑是一種嚴重的浪費啤挎,所以Mipmap便是更好的解決方式。
?
Mip貼圖使用場景:
Mip貼圖是一種強大的紋理技巧,它不僅可以提高渲染性能,而且可以改善場景的顯示質量.它使用標準紋理貼圖處理兩個常見的問題卵凑。
閃爍問題庆聘,當屏幕上被渲染物體的表面與它所應用的紋理圖像相比顯得非常小時,就會出現閃爍效果勺卢。類似閃光伙判,當紋理圖像采樣區(qū)域的移動幅度與它在屏幕大小相比顯得不成比例時,也會發(fā)生這種現象值漫。處于運動狀態(tài)時澳腹,會比較容易看到閃爍的負面效果织盼。
性能問題杨何,加載大的紋理內存并對它們進行過濾處理,但屏幕上實際只是顯示很少的一部分片段沥邻。紋理越大危虱,這個問題所造成的性能影響也就越明顯。
?
Mip貼圖的使用:
- 設置過濾方式
// GL_NEAREST(最鄰近過濾)
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
// GL_LINEAR(線性過濾)
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
// GL_NEAREST_MIPMAP_NEAREST(選擇最鄰近的Mip層唐全,并執(zhí)行最鄰近過濾)
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST_MIPMAP_NEAREST);
// GL_NEAREST_MIPMAP_LINEAR(在Mip層之間執(zhí)行線性插補埃跷,并執(zhí)行最鄰近過濾)
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST_MIPMAP_LINEAR);
// GL_NEAREST_MIPMAP_LINEAR(選擇最鄰近Mip層,并執(zhí)行線性過濾)
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_NEAREST);
// GL_LINEAR_MIPMAP_LINEAR(在Mip層之間執(zhí)行線性插補邮利,并執(zhí)行線性過濾弥雹,又稱為三線性過濾)
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
- 生成一組完整的mip貼圖
//為紋理對象生成一組完整的mip貼圖
//參數1:紋理維度,GL_TEXTURE_1D,GL_TEXTURE_2D,GL_TEXTURE_3D
glGenerateMipmap(GL_TEXTURE_2D);
常量 | 描述 |
---|---|
GL_NEAREST | 在Mip基層上執(zhí)行最鄰近過濾 |
GL_LINEAR | 在Mip基層執(zhí)行線性過濾 |
GL_NEAREST_MIPMAP_NEAREST | 在最鄰近Mip層延届,并執(zhí)行最鄰近過濾 |
GL_NEAREST_MIPMAP_LINEAR | 在Mip層之間執(zhí)行線性插補剪勿,并執(zhí)行最鄰近過濾 |
GL_LINEAR_MIPMAP_NEAREST | 選擇最鄰近Mip層,并執(zhí)行線性過濾 |
GL_LINEAR_MIPMAP_LINEAR | 在Mip層之間執(zhí)行線性插補方庭,并執(zhí)行線性過濾厕吉,又稱三線性Mip貼圖 |
參數GL_TEXTURE_MIN_FILTER負責控制mipmap層次大于0的時候,紋素構建的方式械念。這個參數總共有6個可以設置的參數值头朱。前2個值紋理放(magnification)的參數值是相同的:GL_NEAREST和GL_LINEAR。選擇這2個參數龄减,OpenGL會關閉mipmap并且僅僅使用紋理的基本層(0層)项钮。
其他4個參數分別是∶ GL_NEAREST_MIPMAP_ NEAREST、GL_NEAREST_MIPMAPLINEAR、GL_LINEAR_MIPMAP_NEAREST烁巫、 GL_LINEAR_MIPMAP_LINEAR鳖敷。注意每個模式參數都是由兩部分組成的,名稱的結構總是GL_{A}MIMPMAP{B}的形式程拭。這里的{A}和{B}都可以是NEAREST或者LINEAR中的一個定踱。第一部分{A}負責控制每個mipmap層次的紋素構成方式,它與GL_TEXTURE_MAG_FILTER中的設置是按照同樣的方式工作的恃鞋。第二部分{B}負責控制采樣點在兩個mipmap層次之間的融合方式崖媚。如果設置為NEAREST,那么計算只用到最近的mipmap層恤浪。如果設置為LINEAR畅哑,那么兩個最近的mipmap層數據之間會進行線性的插值計算。
glGenerateMipmap計算從零級數組派生的一組完整的mipmap數組水由。無論先前的內容如何荠呐,最多包括1x1維度紋理圖像的數組級別都將替換為派生數組。零級紋理圖像保持不變(原圖)砂客。
派生的mipmap數組的內部格式都與零級紋理圖像的內部格式相匹配泥张。通過將零級紋理圖像的寬度和高度減半來計算派生數組的尺寸,然后將每個陣列級別的尺寸減半鞠值,直到達到1x1尺寸紋理圖像媚创。
//設置mip貼圖基層
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, 0);
//設置mip貼圖最大層
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 0);
使用glTexParameteri()函數時,用到level參數彤恶,它指定圖像數據用于哪個mip層钞钙。第一層是0,后面依次類推声离。如果未使用Mip貼圖芒炼,就只加載第0層。默認情況下术徊,為了使用Mip貼圖本刽,mip層都要被加載,可以設置GL_TEXTURE_BASE_LEVEL和GL_TEXTURE_MAX_LEVEL紋理參數使用基層和最大層弧关。
雖然可以通過設置GL_TEXTURE_BASE_LEVEL和GL_TEXTURE_MAX_LEVEL紋理參數控制哪些mip層被加載盅安。但仍然可以使用GL_TEXTURE_MIN_LOD和GL_TEXTURE_MAX_LOD參數限制已加載的mip層使用范圍。
?
什么時候生成Mip貼圖:
只有minFilter等于以下四種模式世囊,才可以生成Mip貼圖别瞭。
- GL_NEAREST_MIPMAP_NEAREST具有非常好的性能,并且閃爍現象很弱株憾。
- GL_LINEAR_MIPMAP_NEAREST常用于對游戲加速蝙寨,它使用高質量的線性過濾器晒衩。
- GL_NEAREST_MIPMAP_LINEAR過濾器在Mip層之間執(zhí)行了一些額外的插值,以消除它們之間的過濾痕跡墙歪。
- GL_LINEAR_MIPMAP_LINEAR三線性Mip貼圖听系。紋理過濾的黃金準則,具有最高的精度虹菲。
一個常見的錯誤是將放大過濾的選項設置為多級漸遠紋理過濾選項之一靠胜,這樣是沒有任何效果的,因為多級漸遠紋理主要是使用在紋理被縮小的情況下的:紋理放大不會使用多級漸遠紋理毕源,為放大過濾設置多級漸遠紋理的選項會產生一個 GL_INVALID_ENUM 錯誤代碼浪漠。
?
OpenGL實現了Mip貼圖功能:
// 函數定義一個二維紋理映射。
glTexImage2D (GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, GLint border, GLenum format, GLenum type, const GLvoid *pixels);
// 參數target: 是常數GL_TEXTURE_2D霎褐。
// 參數level: 表示多級分辨率的紋理圖像的級數址愿,若只有一種分辨率,則level設為0冻璃。
// 參數internalformat: 是一個從1到4的整數响谓,指出選擇了R、G省艳、B娘纷、A中的哪些分量用于調整和混合,1表示選擇了R分量拍埠,2表示選擇了R和A兩個分量失驶,3表示選擇了R土居、G枣购、B三個分量,4表示選擇了R擦耀、G棉圈、B、A四個分量眷蜓。
// 參數width和height: 給出了紋理圖像的長度和寬度分瘾,
// 參數border: 為紋理邊界寬度,它通常為0吁系,width和height必須是2m+2b德召,這里m是整數,長和寬可以有不同的值汽纤,b是border的值上岗。紋理映射的最大尺寸依賴于OpenGL,但它至少必須是使用64x64(若帶邊界為66×66)蕴坪,若width和height設置為0肴掷,則紋理映射有效地關閉敬锐。
// 參數format和type: 描述了紋理映射的格式和數據類型,參數format可以是GL_COLOR_INDEX呆瞻、GL_RGB台夺、GL_RGBA、GL_RED痴脾、GL_GREEN颤介、GL_BLUE、GL_ALPHA赞赖、GL_LUMINANCE或GL_LUMINANCE_ALPHA(注意:不能用GL_STENCIL_INDEX和GL_DEPTH_COMPONENT)顽爹。類似地,參數type是GL_BYPE汇恤、GL_UNSIGNED_BYTE埠帕、GL_SHORT、 GL_UNSIGNED_SHORT话侄、GL_INT亏推、GL_UNSIGNED_INT、GL_FLOAT或GL_BITMAP年堆。
// 參數pixels: 包含了紋理圖像數據吞杭,這個數據描述了紋理圖像本身和它的邊界。
?
Mip貼圖的優(yōu)缺點:
Mipmap是一種典型的空間換時間的解決方案变丧,通過范圍查詢來替代之前雙線性差值所做的點查詢芽狗,它的好處就是速度快,但是也有缺點:結果不夠準確痒蓬、只能用于正方形(2的冪次方)貼圖童擎,以及增加了額外的存儲量(增量約為1/3)。
當計算出的層數恰好不是整數的時候(事實上經常會出現這種情況)攻晒,同一紋理上的不同Mip之間會出現明顯的斷層現象顾复,十分地不自然。
出現了這種不自然的過渡鲁捏,解決辦法依然是老辦法:「差值」 芯砸!
假設計算出的Mip層數是0.7,那么需要將該采樣點在第0層和第1層分別進行雙線性差值给梅,然后再將兩個Mip計算出的顏色結果再進行一次線性差值假丧,得到最終的顏色。我們管這種計算方法叫做:「三線性差值(Trilinear Interpolation)」动羽。
但是某些情況下包帚,使用三線性差值計算出的Mipmap顏色依舊會有問題。類似開放世界的第一人稱視角曹质,看向地平面很遠處的位置婴噩,可能會產生出over blur的效果擎场。還記得Mipmap的缺點嗎?它只能針對正方形紋理進行Mip分層几莽,當透視效果越明顯迅办,越遠處的像素對應紋理中的區(qū)域會越不接近正方形(更像長條的矩形,甚至連矩形都不是)章蚣,如果使用面積更大的正方形來包住這個區(qū)域站欺,此時的結果就會愈加不準確,造成了越遠處越模糊的感覺纤垂。
為了解決這個問題矾策,很多硬件都支持 「各項異性過濾」的特性,例如OpenGL中可以通過 GL_TEXTURE_MAX_ANISOTROPY_EXT 來設置紋理中各項異性過濾的數值峭沦。
如果正好是一個紋素的大小贾虽,也就是一個像素對應一個紋素,那么就選擇第0層的Mip
如果對應四個紋素的大小吼鱼,也就是一個像素對應4個紋素蓬豁,那么就選擇第1層的Mip
?
2、各向異性過濾
?
各向異性過濾簡介:
各向異性紋理過濾(Anisotropic texture filtering) 并不是OpenGL核心規(guī)范中的一部分菇肃,但它是一種得到廣泛使用的擴展地粪,可以極大提高紋理過濾操作的質量。
當幾何圖形進行紋理貼圖時琐谤,如果它的觀察方向和觀察點怡好垂直蟆技,那么這個過程是相當完整的。當我們從一個角度傾斜地觀察這個幾何圖形時斗忌,對周圍紋理單元進行常規(guī)采樣质礼,會導致一些紋理信息丟失(如下圖的軌道與我們的觀察視角不垂直,看上去顯得模糊)飞蹂。為了更加逼真和準確的采樣應該沿著包含紋理的平面方向進行延伸几苍。如果我們進行處理紋理過濾時,考慮了觀察角度陈哑,那么這個過濾方法就叫“各向異性過濾”。在Mip貼圖紋理過濾模型中伸眶,或者其它所有的基本紋理過濾我們都可以應用各向異性過濾惊窖。
?
各向異性過濾使用:
// 獲取各向異性過濾的最大數量
// 查詢當前系統(tǒng)支持的最大各向異性過濾的數值,數值越大厘贼,表示沿著最大變化方向所采樣的紋理單元越多界酒,顯示效果就越好:
GLfloat fLargest;
glGetFloatv(GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT, &fLargest);
// 設置紋理參數(各向異性采樣)
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, fLargest);
?
各向同性過濾:
各向異性過濾所應用的數量越大,沿著最大變化方向(沿最強的觀察點)所采樣的紋理單元就越多嘴秸。值1.0表示常規(guī)的紋理過濾(各向同性過濾)毁欣。各向異性過濾庇谆,是會增加額外的工作,包括其他紋理單元凭疮,很可能對性能造成影響饭耳。但是,在現代硬件上执解,應用這個特性對速度造成影響不大寞肖。最重要的是,目前它已經成為流行游戲衰腌、動畫和模擬程序的一個標準特性新蟆。
// 設置各向同性過濾,數量為1.0表示(各向同性采樣)
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, 1.0f);