1. 程式人生 > >OpenGL 正交投影、透視除法、透視投影

OpenGL 正交投影、透視除法、透視投影

正交投影(Orthographic projection)、透視除法(perspective division)、透視投影(Perspective Projection) 在3D世界中正交投影矩陣 被 透視投影矩陣所代替。 歸一化裝置座標 OpenGL的座標空間是[-1, 1],x,y軸超過該區域的都將被切掉 看不見。 手機畫素是 1280 X 720,歸一化後 座標空間從[1280X720],對映到[-1,1] 問題:導致物體變形,因為 x,y軸座標長度都是1 - (-1)= 2,但x,y軸畫素數量不同。y軸畫素多,單位座標就會變長。 辦法:是短的軸對映為1,長的軸根據與短軸的比例 對映。[0, 1280] ,[0, 720]----》[-1280/720 , 1280/720],[-1, 1]。這個空間被稱作虛擬座標空間
。 在虛擬座標空間上操作頂點,為了OpenGL最終正確渲染,渲染前還需 將虛擬座標 對映為 歸一裝置座標。 而這個對映叫做正交投影(orthographic projection) 二維世界 正交投影(歸 一化裝置座標,不變形)

該方法位於Matrix中

@Override public void onSurfaceChanged(GL10 gl, int width, int height) { gl.glViewport(0, 0, width, height); final float aspectRatio = width > height ? (float) width / (float) height : (float) height / (float) width; if (width > height) { Matrix.orthoM(projectionMatrix, 0, -aspectRatio, aspectRatio, -1f, 1f, -1f, 1f); } else { Matrix.orthoM(projectionMatrix, 0, -1f, 1f, -aspectRatio, aspectRatio, -1f, 1f); } } 投影后的特點是 物體的遠近,不影響投影的大小。 三維世界
透視除法 歸一化裝置之前,OpenGL執行的額外操作 透視除法 w分量除以x,y,z分量(w預設值是1),產生三維幻想 透視效應
上圖點座標都是(-1, -1, 0),但是設定w後,(x,y,z,w)實際是(x/w, y/w, z/w),w越大越趨向於 歸一化裝置座標的中心(0, 0, 0)。 其中z的數都為0,單憑w值就營造出三維效果。 透視投影矩陣(Perspective Projection) 不應指定投影除法中點的w值,而要通過矩陣生成。 視椎體(Frustum) 由透視投影矩陣和投影除法創造(如下圖) 遠端(far side): 近端(near side): Focal Point:following the lines that extend from the large end to the small end of the frustum and then following them past the small end util they meet together. Focal Length: represent by the value of z, The distance between the focal point and the small end of the frustum. 通用投影矩陣:調整視野,螢幕寬高比 以下公式 通過物體與焦點的距離(z)來對映w,z越大,w越大,物體越小

透視投影Android Matrix有兩個方法, frustumM() 有缺陷,影響某些型別的投影 perspectiveM(), 從Android的ICS(Ice Cream Sandwich)引入 所以最好自己寫perspectiveM: r1 public static void perspectiveM (float[] m, float yFovInDegrees, float aspect, float n, float f) { final float angleInRadians = (float) (yFovInDegrees * Math.PI / 180.0); final float a = (float) (1.0 / Math.tan(angleInRadians / 2.0)); m[0] = a / aspect; m[1] = 0f; m[2] = 0f; m[3] = 0f; m[4] = 0f; m[5] = a; m[6] = 0f; m[7] = 0f; m[8] = 0f; m[9] = 0f; m[10] = -((f+n) / (f-n)); m[11] = -1f; m[12] = 0f; m[13] = 0f; m[14] = -((2f * f * n) / (f - n)); m[15] = 0f; } 較寬的視野會引起形變

正交投影與透視投影區別 正交投影中平行的光 照射到與其平行的物體就變成點或者線了,看不到平行物體的側面(就是圖中的小旗子) 透視投影中平行的光實際上發散出去的(就像人眼看平行的鐵軌,明明是平行的,但是透視效果確實兩個平行鐵軌越遠越相較於某一點),實際的光是不平行的 當然就可以看到物體的側面。

模型矩陣 用於移動物體,將模型矩陣合併到投影矩陣中 private final float[] modelMatrix = new float[16]; onSurfaceChanged() { setIdentityM(modelMatrix, 0); translateM(modelMatrix, 0, 0f, 0f, -2f); } 旋轉矩陣

tow transformation steps and three different coordinate spaces; Clip Space 4component of coordinates x,y,z,w Any coordinate show rang in [-w, w], or it wil be cliped and can't be visible. And is Clip space Projection matrix W越大離螢幕越遠 Depth buffer: the component Z as Depth buffer