OpenGL ES 圖形庫最終的結(jié)果是在二維平面上顯示 3D 物體(常稱作模型 Model)這是因?yàn)槟壳暗拇虿糠诛@示器還只能顯示二維圖形。但我們在構(gòu)造 3D 模型時(shí)必須要有空間想象能力,所有對模型的描述還是使用三維坐標(biāo)。也就是使用 3D 建模,而有 OpenGL ES 庫來完成從 3D 模型到二維屏幕上的顯示。
這個(gè)過程可以分成三個(gè)部分:
- 坐標(biāo)變換,坐標(biāo)變換通過使用變換矩陣來描述,因此學(xué)習(xí) 3D 繪圖需要了解一些空間幾何,矩陣運(yùn)算的知識(shí)。三維坐標(biāo)通常使用齊次坐標(biāo)來定義。變換矩陣操作可以分為視角(Viewing),模型(Modeling)和投影(Projection)操作,這些操作可以有選擇,平移,縮放,正側(cè)投影,透視投影等。
- 由于最終的 3D 模型需要在一個(gè)矩形窗口中顯示,因此在這個(gè)窗口之外的部分需要裁剪掉以提高繪圖效率,對應(yīng)3D 圖形,裁剪是將處在剪切面之外的部分扔掉。
- 在最終繪制到顯示器(2D 屏幕),需要建立起變換后的坐標(biāo)和屏幕像素之間的對應(yīng)關(guān)系,這通常稱為「視窗」坐標(biāo)變換(Viewport) transformation.
如果我們使用照相機(jī)拍照的過程做類比,可以更好的理解 3D 坐標(biāo)變換的過程。
http://wiki.jikexueyuan.com/project/opengl-es-guide/images/61.png" alt="" />
- 拍照時(shí)第一步是架起三角架並把相機(jī)的鏡頭指向需要拍攝的場景,對應(yīng)到 3D 變換為 viewing transformation (平移或是選擇 Camera )
- 然后攝影師可能需要調(diào)整被拍場景中某個(gè)物體的角度,位置,比如攝影師給架好三角架后給你拍照時(shí),可以要讓你調(diào)整站立姿勢或是位置。對應(yīng)到 3D 繪製就是 Modeling transformation (調(diào)整所繪模型的位置,角度或是縮放比例)。
- 之后攝影師可以需要調(diào)整鏡頭取景(拉近或是拍攝遠(yuǎn)景),相機(jī)取景框所能拍攝的場景會(huì)隨鏡頭的伸縮而變換,對應(yīng)到 3D 繪圖則為 Projection transformation(裁剪投影場景)。
- 按下快門後,對于數(shù)碼相機(jī)可以直接在屏幕上顯示當(dāng)前拍攝的照片,一般可以充滿整個(gè)屏幕(相當(dāng)于將坐標(biāo)做規(guī)範(fàn)化處理 NDC),此時(shí)你可以使用縮放放大功能顯示照片的部分。對應(yīng)到 3D 繪圖相當(dāng)于 viewport transformation (可以對最終的圖像縮放顯示等)
下圖為 Android OpenGL ES 坐標(biāo)變換的過程:
http://wiki.jikexueyuan.com/project/opengl-es-guide/images/62.png" alt="" />
- Object Coordinate System: 也稱作Local coordinate System,用來定義一個(gè)模型本身的坐標(biāo)系。
- World Coordinate System: 3d 虛擬世界中的絕對坐標(biāo)系,定義好這個(gè)坐標(biāo)系的原點(diǎn)就可以用來描述模型的實(shí)現(xiàn)的位置,Camera 的位置,光源的位置。
- View Coordinate System: 一般使用用來計(jì)算光照效果。
- Clip Coordinate System: 對 3D 場景使用投影機(jī)換裁剪視角。
- Normalized device coordinate System (NDC): 規(guī)范后坐標(biāo)系。
- Windows Coordinate System: 最后屏幕顯示的 2D 坐標(biāo)系統(tǒng),一般原點(diǎn)定義在屏幕左上角。
http://wiki.jikexueyuan.com/project/opengl-es-guide/images/63.png" alt="" />
對于 Viewing transformation (平移,選擇相機(jī))和 Modeling transformation(平移,選擇模型)可以合并起來看,只是應(yīng)為向左移動(dòng)相機(jī),和相機(jī)不同將模型右移的效果是等效的。
所以在 OpenGL ES 中,
- 使用 GL10.GL_MODELVIEW 來同時(shí)指定 viewing matrix 和 modeling matrix.
- 使用 GL10.GL_PROJECTION 指定投影變換,OpenGL 支持透視投影和正側(cè)投影(一般用于工程制圖)。
- 使用 glViewport 指定 Viewport 變換。
此時(shí)再看看下面的代碼,就不是很難理解了,后面就逐步介紹各種坐標(biāo)變換。
public void onSurfaceChanged(GL10 gl, int width, int height) {
// Sets the current view port to the new size.
gl.glViewport(0, 0, width, height);
// Select the projection matrix
gl.glMatrixMode(GL10.GL_PROJECTION);
// Reset the projection matrix
gl.glLoadIdentity();
// Calculate the aspect ratio of the window
GLU.gluPerspective(gl, 45.0f, (float) width / (float) height, 0.1f, 100.0f);
// Select the modelview matrix
gl.glMatrixMode(GL10.GL_MODELVIEW);
// Reset the modelview matrix
gl.glLoadIdentity();
}