3D開發基礎之投影,變換,光照,紋理



一,攝像機及兩種投影

攝像機,可以理解爲視角,其設置主要給出3方面的信息,包括攝像機的位置,觀察的方向,up方向。
通過調用Matrix類的setLookAtM方法來完成對攝像機的設置,基本代碼:
Matrix.setLookAtM(
mVMatrix, //存儲生成矩陣元素的float[]類型數組
0, //填充起始偏移量
cx,cy,cz,
tx,ty,tz,
upx,upy,upz
);
通過調用Matrix類的orthoM方法完成對正交投影的設置,基本代碼如下:
Matrix.outhoM(
mProjMatrix, //存儲生成矩陣元素的float[]類型數組
0, //填充起始偏移量
left, right, //near面的,,
bottom, top,
near, far
);
通過調用Matrix類的frustumM方法完成對透視投影的設置,基本代碼如下:
Matrix.frustumM(
mProjMatrix, //存儲生成矩陣元素的float[]類型數組
0, //填充起始偏移量
left, right, //near面的,,
bottom, top,
near, far
);

二,各種變換
1,基本變換
P與一個特殊的變換矩陣M相乘即可完成一次基本變換,得到變換後點Q的齊次座標向量:

當矩陣M中的元素取適當值時,等式Q=MP就會有其特殊的幾何意義。例如,可以將三維空間中的點P平移,旋轉到點Q,這些變換的具體信息就存放在矩陣M中,因此通常稱矩陣M爲變換矩陣。當需要執行一系列的變換時,以此將變換矩陣乘以表示點位置的齊次座標向量即可。
基本變換實際上不是針對物體的,而是針對座標系進行的。OpenGL ES中變換的實現機制可以理解爲首先通過矩陣座標系進行變換,然後根據出入渲染管線的原始頂點座標在最終變換座標系中的位置來進行繪製。
2,平移矩陣
旋轉變換:

縮放變換:

三,卷繞和背面剪裁
     背面剪裁是指渲染管線在對構成立體物體的三角形圖元進行繪製時,僅當攝像機觀察點位於三角形正面的情況下才繪製三角形,若觀察點位於背面則不繪製。打開背面剪裁後在大部分情況下可以提高渲染效率,去除大量不必要的渲染工作。瞭解背面剪裁的功效後,很重要的一點就是如何確定攝像機是位於一個面的正面還是反面。在沒有做出特殊設置的情況下,OpenGL ES中規定當攝像機觀察一個三角形面時,若三角形中3個頂點的卷繞順序是逆時針則攝像機觀察其正面,反之攝像機觀察其反面。開發人員也可以通過設置告知渲染管線以順時針卷軸爲正面,以逆時針卷軸爲反面。下面爲背面剪裁及卷繞方式有關的語句:
GLES20.glEnable(GLES20.GL_CULL_FACE); //打開背面剪裁
GLES20.glDisable(GLES20.GL_CULL_FACE); //關閉背面剪裁
GLES20.glFrontFace(GLES20.GL_ccw); //設置逆時針卷繞爲正面。這是默認的,因此一般不用明確設置
GLES20.glFrontFace(GLES20.GL_CW); //設置順時針卷繞爲正面

四,光照
       OpenGL ES2.0中將光照分成了3種組成元素(也可以成爲3個通道),爲環境光,散射光,鏡面光。實際開發中,3個光照通道時分別採用不同的數學模型獨立計算的。
這小節靜是物理知識,沒啥好總結的。
五,紋理映射
      基本原理:啓用紋理映射功能後,如果想把一副紋理應用到相應的幾何圖元,就必須告知渲染系統如何進行紋理的映射。告知的方式就是爲圖元中的頂點指定恰當的紋理座標,紋理座標用浮點數表示,範圍一般爲0.0到1.0,下圖就給出了紋理映射的基本原理:
      紋理映射的基本思想就是首先爲圖元中的每個頂點指定恰當的紋理座標,然後通過紋理座標在紋理圖中可以確定選中的紋理區域,最後將選中的內容根據紋理座標映射到指定的圖元上。進行紋理映射的過程實際上就是爲右側三角形圖元中的每個片元着色,用於着色的顏色需要從左側的紋理圖中提取,具體過程如下:
        首先圖元中的每個頂點都需要在頂點着色器中通過易變變量將紋理座標傳入片元着色器
        經過頂點着色器後渲染管線的固定功能部分會根據情況進行插值計算,產生對應到每個片元的用於記錄紋理座標的易變變量值
        最後每個片元在片元着色器中根據其接收到的記錄紋理座標的易變變量值到紋理圖中提取出對應位置的顏色即可,提取顏色的過程一般稱之爲紋理採樣。
        OpenGL ES 中進行紋理映射時,規定紋理圖片尺寸的寬和高必須爲2的n次方。
紋理拉伸:
重複拉伸方式:
GLES20.glTexParameterf(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_WRAP_S,GLES20.GL_REPEAT); //設置S軸的拉伸方式爲重複
GLES20.glTexParameterf(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_WRAP_T,GLES20.GL_REPEAT); //設置T軸的拉伸方式爲重複
截取拉伸方式;
GLES20.glTexParameterf(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_WRAP_S,GLES20.GL_CLAMP_TO_EDGE); //設置S軸的拉伸方式爲截取
GLES20.glTexParameterf(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_WRAP_T,GLES20.GL_CLAMP_TO_EDGE); //設置T軸的拉伸方式爲截取

紋理採樣
       所謂紋理採樣就是根據片元的紋理座標到紋理圖中提取對應位置顏色的過程。但由於被渲染圖元中的片元數量與其對應紋理區域中像素的數量並不一定相同,也就是說通過紋理座標在紋理圖中並一定能找到與之完全對應的像素,這時候就需要採用一些策略使得紋理採樣可以順利進行下去,通常採用的策略有最近點採樣,線性採樣兩種。
最近點採樣是最簡單的一種採樣算法,其速度在各種採樣算法中也是最快的。
       紋理圖的橫邊和豎邊紋理座標的範圍都是0到1,而紋理圖本身是由一個一個離散的像素組成的。若將像素看成一個個小方快,則每個像素都站一定的紋理座標範圍。
根據片元的紋理座標可以很容易的計算出片元對應的紋理座標點位於紋理圖中的哪個像素中,最近點採樣就直接取此像素的顏色值爲採樣值。
      最近採樣有一個明顯的缺點,就是若把較小的紋理圖映射到較大的圖元中容易產生明顯的鋸齒。將較大的紋理圖映射到較小的圖元中時,也會有鋸齒但由於圖元整體較小,視覺就不那麼明顯了。加載紋理時,設置採用最近點採樣方式的代碼爲:
GLES20.glTexParameterf(GLES20.GL_TEXTURE_2D,GLES20.GL_TEXTURE_MAG_FILTER,GLES20.GL_NEAREST); //設置MAG時爲線性採樣
GLES20.glTexParameterf(GLES20.GL_TEXTURE_2D,GLES20.GL_TEXTURE_MIN_FILTER,GLES20.GL_NEAREST); //設置MIN時爲線性採樣

      線性採樣時的結果顏色並不一定僅來自紋理圖中的一個像素,其在採樣時會考慮到片元對應的紋理座標點附近的幾個像素。平滑過渡解決了鋸齒的問題,但有時線條邊緣會很模糊,因此實際開發中採用哪種採樣策略,需要根據具體的需求來確定。加載紋理時,設置採用線性採樣方式的代碼如下:
GLES20.glTexParameterf(GLES20.GL_TEXTURE_2D,GLES20.GL_TEXTURE_MAG_FILTER,GLES20.GL_LINEAR); //設置MAG時爲線性採樣
GLES20.glTexParameterf(GLES20.GL_TEXTURE_2D,GLES20.GL_TEXTURE_MIN_FILTER,GLES20.GL_LINEAR); //設置MIN時爲線性採樣

      MIN與MAG採樣:無論採樣哪種採樣方式都需要對MIN(GL_TEXTURE_MIN_FILTER)與MAG(GL_TEXTURE_MAG_FILTER)兩種情況分別進行設置。當紋理圖中的一個像素對應到待映射圖元上的多個片元時,採用MAG採樣;反之則採用MIN採樣。
      由於最近點採樣計算速度快,在MIN情況下一般鋸齒也不明顯,綜合效益高;而MAG方式若採用最近點採樣則鋸齒會很明顯,嚴重影響視覺效果。因此實際開發中一般情況下往往採用將MIN情況設置爲最近點採樣,將MAG情況設置爲線性採樣的組合。

      mipmap紋理技術:對遠處的事物而言紋理圖被縮小進行映射,自然很清楚,而近處的事物紋理圖可能需要被拉大進行映射,自然就發虛。因此,應該對遠處的事物採用尺寸較小分辨率的紋理,近處的採用尺寸較大的分辨率的紋理,這就是minpmap思想。mipmap僅需要在加載紋理時進行一些設置即可,其他的工作是由渲染管線自動完成的。開發中將採樣方式設置爲mipmap並自動生成一系列的mipmap紋理圖的基本代碼如下:
GLES20.glGenerateMipmap(GLES20.GL_TEXTURE_2D); //自動生成mipmap系列紋理
多重紋理和過程紋理
    對同一個圖元採用多幅紋理圖,這種技術稱之爲多重紋理。
    在多重紋理變化的邊界根據某種規則進行平滑過渡,這種技術稱之爲過程紋理。這種平滑過渡在很多情況下都會用到,如白天紋理和黑夜紋理的過渡,丘陵地形中根據海拔不同進行的紋理過度等。

一,攝像機及兩種投影

攝像機,可以理解爲視角,其設置主要給出3方面的信息,包括攝像機的位置,觀察的方向,up方向。
通過調用Matrix類的setLookAtM方法來完成對攝像機的設置,基本代碼:
Matrix.setLookAtM(
mVMatrix, //存儲生成矩陣元素的float[]類型數組
0, //填充起始偏移量
cx,cy,cz,
tx,ty,tz,
upx,upy,upz
);
通過調用Matrix類的orthoM方法完成對正交投影的設置,基本代碼如下:
Matrix.outhoM(
mProjMatrix, //存儲生成矩陣元素的float[]類型數組
0, //填充起始偏移量
left, right, //near面的,,
bottom, top,
near, far
);
通過調用Matrix類的frustumM方法完成對透視投影的設置,基本代碼如下:
Matrix.frustumM(
mProjMatrix, //存儲生成矩陣元素的float[]類型數組
0, //填充起始偏移量
left, right, //near面的,,
bottom, top,
near, far
);

二,各種變換
1,基本變換
P與一個特殊的變換矩陣M相乘即可完成一次基本變換,得到變換後點Q的齊次座標向量:
當矩陣M中的元素取適當值時,等式Q=MP就會有其特殊的幾何意義。例如,可以將三維空間中的點P平移,旋轉到點Q,這些變換的具體信息就存放在矩陣M中,因此通常稱矩陣M爲變換矩陣。當需要執行一系列的變換時,以此將變換矩陣乘以表示點位置的齊次座標向量即可。
基本變換實際上不是針對物體的,而是針對座標系進行的。OpenGL ES中變換的實現機制可以理解爲首先通過矩陣座標系進行變換,然後根據出入渲染管線的原始頂點座標在最終變換座標系中的位置來進行繪製。
2,平移矩陣
變換矩陣的基本格式爲:
旋轉變換:

縮放變換:

三,卷繞和背面剪裁
     背面剪裁是指渲染管線在對構成立體物體的三角形圖元進行繪製時,僅當攝像機觀察點位於三角形正面的情況下才繪製三角形,若觀察點位於背面則不繪製。打開背面剪裁後在大部分情況下可以提高渲染效率,去除大量不必要的渲染工作。瞭解背面剪裁的功效後,很重要的一點就是如何確定攝像機是位於一個面的正面還是反面。在沒有做出特殊設置的情況下,OpenGL ES中規定當攝像機觀察一個三角形面時,若三角形中3個頂點的卷繞順序是逆時針則攝像機觀察其正面,反之攝像機觀察其反面。開發人員也可以通過設置告知渲染管線以順時針卷軸爲正面,以逆時針卷軸爲反面。下面爲背面剪裁及卷繞方式有關的語句:
GLES20.glEnable(GLES20.GL_CULL_FACE); //打開背面剪裁
GLES20.glDisable(GLES20.GL_CULL_FACE); //關閉背面剪裁
GLES20.glFrontFace(GLES20.GL_ccw); //設置逆時針卷繞爲正面。這是默認的,因此一般不用明確設置
GLES20.glFrontFace(GLES20.GL_CW); //設置順時針卷繞爲正面

四,光照
       OpenGL ES2.0中將光照分成了3種組成元素(也可以成爲3個通道),爲環境光,散射光,鏡面光。實際開發中,3個光照通道時分別採用不同的數學模型獨立計算的。
這小節靜是物理知識,沒啥好總結的。
五,紋理映射
      基本原理:啓用紋理映射功能後,如果想把一副紋理應用到相應的幾何圖元,就必須告知渲染系統如何進行紋理的映射。告知的方式就是爲圖元中的頂點指定恰當的紋理座標,紋理座標用浮點數表示,範圍一般爲0.0到1.0,下圖就給出了紋理映射的基本原理:
      紋理映射的基本思想就是首先爲圖元中的每個頂點指定恰當的紋理座標,然後通過紋理座標在紋理圖中可以確定選中的紋理區域,最後將選中的內容根據紋理座標映射到指定的圖元上。進行紋理映射的過程實際上就是爲右側三角形圖元中的每個片元着色,用於着色的顏色需要從左側的紋理圖中提取,具體過程如下:
        首先圖元中的每個頂點都需要在頂點着色器中通過易變變量將紋理座標傳入片元着色器
        經過頂點着色器後渲染管線的固定功能部分會根據情況進行插值計算,產生對應到每個片元的用於記錄紋理座標的易變變量值
        最後每個片元在片元着色器中根據其接收到的記錄紋理座標的易變變量值到紋理圖中提取出對應位置的顏色即可,提取顏色的過程一般稱之爲紋理採樣。
        OpenGL ES 中進行紋理映射時,規定紋理圖片尺寸的寬和高必須爲2的n次方。
紋理拉伸:
重複拉伸方式:
GLES20.glTexParameterf(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_WRAP_S,GLES20.GL_REPEAT); //設置S軸的拉伸方式爲重複
GLES20.glTexParameterf(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_WRAP_T,GLES20.GL_REPEAT); //設置T軸的拉伸方式爲重複
截取拉伸方式;
GLES20.glTexParameterf(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_WRAP_S,GLES20.GL_CLAMP_TO_EDGE); //設置S軸的拉伸方式爲截取
GLES20.glTexParameterf(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_WRAP_T,GLES20.GL_CLAMP_TO_EDGE); //設置T軸的拉伸方式爲截取

紋理採樣
       所謂紋理採樣就是根據片元的紋理座標到紋理圖中提取對應位置顏色的過程。但由於被渲染圖元中的片元數量與其對應紋理區域中像素的數量並不一定相同,也就是說通過紋理座標在紋理圖中並一定能找到與之完全對應的像素,這時候就需要採用一些策略使得紋理採樣可以順利進行下去,通常採用的策略有最近點採樣,線性採樣兩種。
最近點採樣是最簡單的一種採樣算法,其速度在各種採樣算法中也是最快的。
       紋理圖的橫邊和豎邊紋理座標的範圍都是0到1,而紋理圖本身是由一個一個離散的像素組成的。若將像素看成一個個小方快,則每個像素都站一定的紋理座標範圍。
根據片元的紋理座標可以很容易的計算出片元對應的紋理座標點位於紋理圖中的哪個像素中,最近點採樣就直接取此像素的顏色值爲採樣值。
      最近採樣有一個明顯的缺點,就是若把較小的紋理圖映射到較大的圖元中容易產生明顯的鋸齒。將較大的紋理圖映射到較小的圖元中時,也會有鋸齒但由於圖元整體較小,視覺就不那麼明顯了。加載紋理時,設置採用最近點採樣方式的代碼爲:
GLES20.glTexParameterf(GLES20.GL_TEXTURE_2D,GLES20.GL_TEXTURE_MAG_FILTER,GLES20.GL_NEAREST); //設置MAG時爲線性採樣
GLES20.glTexParameterf(GLES20.GL_TEXTURE_2D,GLES20.GL_TEXTURE_MIN_FILTER,GLES20.GL_NEAREST); //設置MIN時爲線性採樣

      線性採樣時的結果顏色並不一定僅來自紋理圖中的一個像素,其在採樣時會考慮到片元對應的紋理座標點附近的幾個像素。平滑過渡解決了鋸齒的問題,但有時線條邊緣會很模糊,因此實際開發中採用哪種採樣策略,需要根據具體的需求來確定。加載紋理時,設置採用線性採樣方式的代碼如下:
GLES20.glTexParameterf(GLES20.GL_TEXTURE_2D,GLES20.GL_TEXTURE_MAG_FILTER,GLES20.GL_LINEAR); //設置MAG時爲線性採樣
GLES20.glTexParameterf(GLES20.GL_TEXTURE_2D,GLES20.GL_TEXTURE_MIN_FILTER,GLES20.GL_LINEAR); //設置MIN時爲線性採樣

      MIN與MAG採樣:無論採樣哪種採樣方式都需要對MIN(GL_TEXTURE_MIN_FILTER)與MAG(GL_TEXTURE_MAG_FILTER)兩種情況分別進行設置。當紋理圖中的一個像素對應到待映射圖元上的多個片元時,採用MAG採樣;反之則採用MIN採樣。
      由於最近點採樣計算速度快,在MIN情況下一般鋸齒也不明顯,綜合效益高;而MAG方式若採用最近點採樣則鋸齒會很明顯,嚴重影響視覺效果。因此實際開發中一般情況下往往採用將MIN情況設置爲最近點採樣,將MAG情況設置爲線性採樣的組合。

      mipmap紋理技術:對遠處的事物而言紋理圖被縮小進行映射,自然很清楚,而近處的事物紋理圖可能需要被拉大進行映射,自然就發虛。因此,應該對遠處的事物採用尺寸較小分辨率的紋理,近處的採用尺寸較大的分辨率的紋理,這就是minpmap思想。mipmap僅需要在加載紋理時進行一些設置即可,其他的工作是由渲染管線自動完成的。開發中將採樣方式設置爲mipmap並自動生成一系列的mipmap紋理圖的基本代碼如下:
GLES20.glGenerateMipmap(GLES20.GL_TEXTURE_2D); //自動生成mipmap系列紋理
多重紋理和過程紋理
    對同一個圖元採用多幅紋理圖,這種技術稱之爲多重紋理。
    在多重紋理變化的邊界根據某種規則進行平滑過渡,這種技術稱之爲過程紋理。這種平滑過渡在很多情況下都會用到,如白天紋理和黑夜紋理的過渡,丘陵地形中根據海拔不同進行的紋理過度等。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章