1. OpenGL坐標(biāo)系統(tǒng)概述
?
OpenGL希望每次頂點著色后,我們的可見頂點都為標(biāo)準(zhǔn)化設(shè)備坐標(biāo)(Normalized Device Coordinate,NDC)。也就是說每個頂點的x,y,z都應(yīng)該在?1到1之間,超出這個范圍的頂點將是不可見的。
通常情況下我們會自己設(shè)定一個坐標(biāo)范圍,之后再在頂點著色器中將這些坐標(biāo)變換為表轉(zhuǎn)化設(shè)備坐標(biāo)。然后這些標(biāo)化設(shè)備坐標(biāo)傳入光柵器(Rasterizer),將它們變換為屏幕上的二維坐標(biāo)和像素。
將坐標(biāo)變換為標(biāo)準(zhǔn)化設(shè)備坐標(biāo),接著再轉(zhuǎn)化為屏幕坐標(biāo)的過程通常是分步進(jìn)行的,也就是類似于流水線那樣子。在流水線中,物體的頂點在最終轉(zhuǎn)化為屏幕坐標(biāo)之前還會被變換到多個坐標(biāo)系統(tǒng)(Coordinate System)。將物體的坐標(biāo)變換到幾個過渡坐標(biāo)系(Intermediate Coordinate System)的優(yōu)點在于,在這些特定的坐標(biāo)系統(tǒng)中,一些操作或運算更加方便和容易,這一點很快就會變得很明顯。對我們來說比較重要的總共有5個不同的坐標(biāo)系統(tǒng)
- 局部空間(Local Space,或者稱為物體空間(Object Space))
- 世界空間(World Space)
- 觀察空間(View Space,或者稱為視覺空間(Eye Space))
- 裁剪空間(Clip Space)
- 屏幕空間(Screen Space)
這就是一個頂點在最終被轉(zhuǎn)化為片段之前需要經(jīng)歷的所有不同狀態(tài)。為了將坐標(biāo)從一個坐標(biāo)系變換到另一個坐標(biāo)系,我們需要用到幾個變換矩陣,最重要的幾個分別是模型(Model)、觀察(View)、投影(Projection)三個矩陣。
物體頂點的起始坐標(biāo)再局部空間(Local Space),這里稱它為局部坐標(biāo)(Local Coordinate),它在之后會變成世界坐標(biāo)(world Coordinate),觀測坐標(biāo)(View Coordinate),裁剪坐標(biāo)(Clip Coordinate),并最后以屏幕坐標(biāo)(Screen Corrdinate)的形式結(jié)束。
3D場景轉(zhuǎn)換為最終的2D形式渲染到屏幕的大致流程:
局部坐標(biāo)系使用模型變換轉(zhuǎn)換到世界坐標(biāo)系,世界坐標(biāo)系經(jīng)過視變換轉(zhuǎn)換到照相機(jī)坐標(biāo)系后,需要進(jìn)行投影變換,將相機(jī)坐標(biāo)系轉(zhuǎn)換到裁剪坐標(biāo)系,再經(jīng)過透視除法后,變換到規(guī)范化設(shè)備坐標(biāo)系(NDC),最后進(jìn)行視口變換后,3D坐標(biāo)才變換到屏幕上的2D坐標(biāo)。


有以下幾點需要注意:
- 局部坐標(biāo)是對象相對于原點的坐標(biāo),也是物體的起始坐標(biāo)。
- 下一步將局部坐標(biāo)轉(zhuǎn)化為世界空間坐標(biāo),世界空間坐標(biāo)是一個處于更大空間范圍內(nèi)的。這些坐標(biāo)相對于世界的全局原點,它們會和其他物體一起相對于世界原點進(jìn)行擺放。
- 接下來將世界坐標(biāo)轉(zhuǎn)化為觀測坐標(biāo),使得每個坐標(biāo)都是從攝像機(jī)或者說觀察者角度進(jìn)行觀察的。
- 坐標(biāo)到達(dá)觀測空間后,我們需要將其投影到裁剪坐標(biāo)。裁剪坐標(biāo)會被處理從?1.0到1.0范圍內(nèi),并判斷哪些點將會出現(xiàn)在屏幕上。
- 最后,我們將裁剪坐標(biāo)變換為屏幕坐標(biāo),我們將使用一個叫做視口變換(Viewport Transform)的過程。視口變換將位于?1.0到1.0范圍的坐標(biāo)變換到由glViewport()函數(shù)所定義的坐標(biāo)范圍內(nèi)。最后變換出來的坐標(biāo)將會送到光柵器,將其轉(zhuǎn)化為片段。
在OpenGL中,模型變換、視變換,投影變換,這些變換可以由用戶根據(jù)需要自行指定,這些內(nèi)容在頂點著色器中完成。而透視除法、視口變換,這兩個步驟是OpenGL自動執(zhí)行的,在頂點著色器處理后的階段完成。
你可能已經(jīng)大致了解了每個坐標(biāo)空間的作用。我們之所以將頂點變換到各個不同的空間的原因是有些操作在特定的坐標(biāo)系統(tǒng)中才有意義且更方便。例如,當(dāng)需要對物體進(jìn)行修改的時候,在局部空間中來操作會更說得通;如果要對一個物體做出一個相對于其它物體位置的操作時,在世界坐標(biāo)系中來做這個才更說得通,等等。
2. 各種坐標(biāo)系
?
2D笛卡爾坐標(biāo)
2D笛卡爾坐標(biāo)是一個直角坐標(biāo)系,它由一個X軸和一個Y軸組成,X軸Y軸在同一個平面上互相垂直且有公共原點。在二維繪圖中,最為常用的坐標(biāo)系統(tǒng)是笛卡爾坐標(biāo)系統(tǒng)。
通常,兩條數(shù)軸分別置于水平位置與垂直位置,取向右與向上的方向分別為兩條數(shù)軸的正方向。水平的數(shù)軸叫做x軸或橫軸,垂直的數(shù)軸叫做y軸或縱軸,x軸y軸統(tǒng)稱為坐標(biāo)軸,它們的公共原點稱為坐標(biāo)系的原點。關(guān)于正負(fù)方向問題,我們可以根據(jù)實際需求自己定義。

?
3D笛卡爾坐標(biāo)系
三維笛卡爾坐標(biāo)系是在二維笛卡爾坐標(biāo)系的基礎(chǔ)上根據(jù)右手定則增加第三維坐標(biāo)(即Z軸)而形成的。Z軸代表了深度分量,它同時垂直于X,Y軸,是一條從屏幕中心朝向讀者的直線。
為了更好的觀察,我們將Y軸向做旋轉(zhuǎn),把X軸向下和后渲染.否則Z軸將直面我們,我們無法具體觀察到Z軸存在.我們可以用3個坐標(biāo)(X,Y,Z)來指定三維空間中的任意一個位置.

?
右手系
右手系(right-hand system)是在空間中規(guī)定直角坐標(biāo)系的方法之一。此坐標(biāo)系中x軸,y軸和z軸的正方向是如下規(guī)定的:把右手放在原點的位置,使大姆指,食指和中指互成直角,把大姆指指向x軸的正方向,食指指向y軸的正方向時,中指所指的方向就是z軸的正方向。
也可以按如下方法確定右手(左手)坐標(biāo)系:如果當(dāng)右手(左手)的大拇指指向第一個坐標(biāo)軸(x軸)的正向,而其余手指以第二個軸(y軸)繞第一軸轉(zhuǎn)動的方向握緊,就與第三個軸(z軸)重合,就稱此坐標(biāo)系為右手(左手)坐標(biāo)系。
- OpenGL坐標(biāo)系(物體、世界、照相機(jī)坐標(biāo)系)屬于右手坐標(biāo)系
- 設(shè)備坐標(biāo)系使用的是左手坐標(biāo)系

世界坐標(biāo)系
它是一個特殊的三維坐標(biāo)系,它建立了描述其他坐標(biāo)系所需要的參考系。也就是說,可以用世界坐標(biāo)系去描述其他所有坐標(biāo)系或者物體的位置。所以有很多人定義世界坐標(biāo)系是“我們所關(guān)心的最大坐標(biāo)系”,通過這個坐標(biāo)系可以去描述和刻畫所有想刻畫的實體。世界坐標(biāo)系又稱全局坐標(biāo)系或者宇宙坐標(biāo)系。
世界坐標(biāo)系是系統(tǒng)的絕對坐標(biāo)系,始終是固定不變的。如果我們將所有的物體導(dǎo)入到世界坐標(biāo)系中,默認(rèn)它們有可能會全擠在世界的原點(0, 0, 0)上,但是我們布置場景的時候一般希望物體分散到世界的各處,那么這時需要通過模型矩陣(Model Matrix)來實現(xiàn)。將物體變換到世界空間中,相當(dāng)于就是建立物體的頂點相對于世界原點的關(guān)系。
?
物體坐標(biāo)系
物體坐標(biāo)系與特定的物體關(guān)聯(lián),每個物體都有自己特定的坐標(biāo)系。不同物體之間的坐標(biāo)系相互獨立,可以相同,可以不同,沒有任何聯(lián)系。同時,物體坐標(biāo)系與物體綁定,綁定的意思就是物體發(fā)生移動或者旋轉(zhuǎn),物體坐標(biāo)系發(fā)生相同的平移或者旋轉(zhuǎn),物體坐標(biāo)系和物體之間運動同步,相互綁定。
物體坐標(biāo)系是以物體本身而言,比如,我先向你發(fā)指令,“向前走一步”,是向您的物體坐標(biāo)體系指令。我并不知道你會往哪個絕對的方向移動。比如說,當(dāng)你開車時,有人會說向左轉(zhuǎn),有人說向東。但是,向左轉(zhuǎn)是物體坐標(biāo)系的概念,而向東則是世界坐標(biāo)系中的。
在某種情況下,我們可以理解物體坐標(biāo)系為模型坐標(biāo)系。因為模型頂點的坐標(biāo)都是在模型坐標(biāo)系中描述的。
?
攝像機(jī)/照相機(jī)坐標(biāo)系
攝像機(jī)坐標(biāo)系。攝像機(jī)坐標(biāo)系是和觀察者密切相關(guān)的坐標(biāo)系。攝像機(jī)坐標(biāo)系和屏幕坐標(biāo)系相似,只不過一個處在三維環(huán)境中,一個處在二維環(huán)境中。攝像機(jī)坐標(biāo)系也是一種特殊的物體坐標(biāo)系。一般的攝像機(jī)坐標(biāo)系都是x軸向右,y軸向上,z軸向里。
觀察空間是將世界空間坐標(biāo)轉(zhuǎn)化為用戶視野前方的坐標(biāo)而產(chǎn)生的結(jié)果。因此觀察空間就是從攝像機(jī)的視角所觀察到的空間。而這通常是由一系列的位移和旋轉(zhuǎn)的組合來完成,平移/旋轉(zhuǎn)場景從而使得特定的對象被變換到攝像機(jī)的前方。這些組合在一起的變換通常存儲在一個觀察矩陣(View Matrix)里,它被用來將世界坐標(biāo)變換到觀察空間。
?
慣性坐標(biāo)系
這種坐標(biāo)系是在世界坐標(biāo)系和物體坐標(biāo)系之間的一種坐標(biāo)系。慣性坐標(biāo)系的原點和物體坐標(biāo)系的原點重合,但慣性坐標(biāo)系的坐標(biāo)軸是和世界坐標(biāo)系的坐標(biāo)軸平行的。為什么要引入慣性坐標(biāo)系呢?三維系統(tǒng)在運行時,不可避免的引入外部工具如3DMax做得模型,每個模型又有很多三角面,點組成。這些三角面和點得坐標(biāo)都是物體坐標(biāo)。所以系統(tǒng)中會由大量的從物體坐標(biāo)向世界坐標(biāo)的轉(zhuǎn)換。有了慣性坐標(biāo)系,可以簡化他們之間的轉(zhuǎn)換過程。從物體坐標(biāo)系轉(zhuǎn)換到慣性坐標(biāo)系只需要旋轉(zhuǎn)操作。從慣性坐標(biāo)系到世界坐標(biāo)系只需要平移操作。
?
齊次坐標(biāo)系
齊次坐標(biāo)就是將一個原本是n維的向量用一個n+1維向量來表示。在齊次坐標(biāo)下,旋轉(zhuǎn)/平移/仿射變換/透視變換都可以用同一個矩陣實現(xiàn),這在傳統(tǒng)笛卡爾坐標(biāo)系下是不可能的。
4D向量是由3D坐標(biāo)(x,y,z)和齊次坐標(biāo)w組成,寫作(x,y,z,w)。
在3D世界中為什么需要3D的齊次坐標(biāo)呢?簡單地說明一下,在一維空間中的一條線段上取一點x,然后我們想轉(zhuǎn)移x的位置,那我們應(yīng)該是x'=x+k,但我們能使用一維的矩陣來表示這變換嗎?不能,因為此時一維的矩陣只能讓x點伸縮。但如果變成了一維的齊次空間[k 1]就很容易地做到。同樣地,在二維空間中,某一圖形如果不使用二維的齊次坐標(biāo),則只能旋轉(zhuǎn)和伸縮,確不能平移。
因此,我們在3D坐標(biāo)中使用齊次坐標(biāo),是為了物體在矩陣變換中,除了伸縮旋轉(zhuǎn),還能夠平移,如下運算:

齊次坐標(biāo)w是什么意義: 設(shè)w=1,此時相當(dāng)于我們把3D的坐標(biāo)平移搬去了w=1的平面上,4D空間的點投影到w=1平面上,齊次坐標(biāo)映射的3D坐標(biāo)是(x/w,y/w,z/w),也就是(x,y,z)。(x,y,z)在齊次空間中有無數(shù)多個點與之對應(yīng)。所有點的形式是(kx,ky,kz,k),其軌跡是通過齊次空間原點的“直線”(其實每個點相當(dāng)于3D的坐標(biāo)世界)。
當(dāng)w=0時,有很大的意義,可解釋為無窮遠(yuǎn)的“點”,其意義是描述方向。這也是平移變換的開關(guān),當(dāng)w=0時,

此時不能平移變換了。這個現(xiàn)象是非常有用的,因為有些向量代表“位置”,應(yīng)當(dāng)平移,而有些向量代表“方向”,如表面的法向量,不應(yīng)該平移。從幾何意義上說,能將第一類數(shù)據(jù)當(dāng)作"點",第二類數(shù)據(jù)當(dāng)作"向量"??梢酝ㄟ^設(shè)置w的值來控制向量的意義。
?
3. 坐標(biāo)系相關(guān)
?
裁剪空間過程
在一個頂點著色器運行的最后,OpenGL期望所有的坐標(biāo)都能落在一個特定的范圍內(nèi),且任何在這個范圍之外的點都應(yīng)該被裁剪掉(Clipped)。被裁剪掉的坐標(biāo)就會被忽略,所以剩下的坐標(biāo)就將變?yōu)槠聊簧峡梢姷钠巍_@也就是裁剪空間(Clip Space)名字的由來。因為將所有可見的坐標(biāo)都指定在?1.0到1.0的范圍內(nèi)不是很直觀,所以我們會指定自己的坐標(biāo)集(Coordinate Set)并將它變換回標(biāo)準(zhǔn)化設(shè)備坐標(biāo)系,就像OpenGL期望的那樣。
為了將頂點坐標(biāo)從觀察變換到裁剪空間,我們需要定義一個投影矩陣(Projection Matrix),它指定了一個范圍的坐標(biāo),比如在每個維度上的?1000到1000。投影矩陣接著會將在這個指定的范圍內(nèi)的坐標(biāo)變換為標(biāo)準(zhǔn)化設(shè)備坐標(biāo)的范圍(?1.0,1.0)。所有在范圍外的坐標(biāo)不會被映射到在?1.0到1.0的范圍之間,所以會被裁剪掉。在上面這個投影矩陣所指定的范圍內(nèi),坐標(biāo)(1250,500,750)將是不可見的,這是由于它的??坐標(biāo)超出了范圍,它被轉(zhuǎn)化為一個大于1.0的標(biāo)準(zhǔn)化設(shè)備坐標(biāo),所以被裁剪掉了。
如果只是圖元(Primitive),例如三角形,的一部分超出了裁剪體積(Clipping Volume),則OpenGL會重新構(gòu)建這個三角形為一個或多個三角形讓其能夠適合這個裁剪范圍。
由投影矩陣創(chuàng)建的觀察箱(Viewing Box)被稱為平截頭體(Frustum),每個出現(xiàn)在平截頭體范圍內(nèi)的坐標(biāo)都會最終出現(xiàn)在用戶的屏幕上。將特定范圍內(nèi)的坐標(biāo)轉(zhuǎn)化到標(biāo)準(zhǔn)化設(shè)備坐標(biāo)系的過程(而且它很容易被映射到2D觀察空間坐標(biāo))被稱之為投影(Projection),因為使用投影矩陣能將3D坐標(biāo)投影(Project)到很容易映射到2D的標(biāo)準(zhǔn)化設(shè)備坐標(biāo)系中。
一旦所有頂點被變換到裁剪空間,最終的操作——透視除法(Perspective Division)將會執(zhí)行,在這個過程中我們將位置向量的x,y,z分量分別除以向量的齊次w分量;透視除法是將4D裁剪空間坐標(biāo)變換為3D標(biāo)準(zhǔn)化設(shè)備坐標(biāo)的過程。這一步會在每一個頂點著色器運行的最后被自動執(zhí)行。在這一階段之后,最終的坐標(biāo)將會被映射到屏幕空間中(使用glViewport中的設(shè)定),并被變換成片段。
將觀察坐標(biāo)變換為裁剪坐標(biāo)的投影矩陣可以為兩種不同的形式,每種形式都定義了不同的平截頭體。我們可以選擇創(chuàng)建一個正射投影矩陣(Orthographic Projection Matrix)或一個透視投影矩陣(Perspective Projection Matrix)。
?
正射投影
正射投影矩陣定義了一個類似立方體的平截頭箱,它定義了一個裁剪空間,在這空間之外的頂點都會被裁剪掉。創(chuàng)建一個正射投影矩陣需要指定可見平截頭體的寬、高和長度。在使用正射投影矩陣變換至裁剪空間之后處于這個平截頭體內(nèi)的所有坐標(biāo)將不會被裁剪掉。它的平截頭體看起來像一個容器:

上面的平截頭體定義了可見的坐標(biāo),它由由寬、高、近(Near)平面和遠(yuǎn)(Far)平面所指定。任何出現(xiàn)在近平面之前或遠(yuǎn)平面之后的坐標(biāo)都會被裁剪掉。正射平截頭體直接將平截頭體內(nèi)部的所有坐標(biāo)映射為標(biāo)準(zhǔn)化設(shè)備坐標(biāo),因為每個向量的??分量都沒有進(jìn)行改變;如果??分量等于1.0,透視除法則不會改變這個坐標(biāo)。
要創(chuàng)建一個正射投影矩陣,我們可以使用glOrtho函數(shù):
glOrtho (GLdouble left, GLdouble right, GLdouble bottom, GLdouble top, GLdouble zNear, GLdouble zFar);
前兩個參數(shù)指定了平截頭體的左右坐標(biāo),第三和第四參數(shù)指定了平截頭體的底部和頂部。通過這四個參數(shù)我們定義了近平面和遠(yuǎn)平面的大小,然后第五和第六個參數(shù)則定義了近平面和遠(yuǎn)平面的距離。這個投影矩陣會將處于這些??,??,??值范圍內(nèi)的坐標(biāo)變換為標(biāo)準(zhǔn)化設(shè)備坐標(biāo)。
正射投影矩陣直接將坐標(biāo)映射到2D平面中,即你的屏幕,但實際上一個直接的投影矩陣會產(chǎn)生不真實的結(jié)果,因為這個投影沒有將透視(Perspective)考慮進(jìn)去,使用正投影所以實際大小相同的物體在屏幕上都具有相同的大小,所以從屏幕上看不出來觀測點到物體的距離有多遠(yuǎn)。正投影比較適合平面圖形/2D圖形渲染時使用。
?
透視投影
如果需要渲染結(jié)果看起來真實,就需要透視投影矩陣來解決這個問題。
在生活中,我們會注意到離你越遠(yuǎn)的東西看起來越小。這個奇怪的效果稱之為透視(Perspective)。透視的效果在我們看一條無限長的高速公路或鐵路時尤其明顯,正如下面圖片顯示的那樣:

正如你看到的那樣,由于透視,這兩條線在很遠(yuǎn)的地方看起來會相交。這正是透視投影想要模仿的效果,它是使用透視投影矩陣來完成的。這個投影矩陣將給定的平截頭體范圍映射到裁剪空間,除此之外還修改了每個頂點坐標(biāo)的w值,從而使得離觀察者越遠(yuǎn)的頂點坐標(biāo)w分量越大。被變換到裁剪空間的坐標(biāo)都會在-w到w的范圍之間(任何大于這個范圍的坐標(biāo)都會被裁剪掉)。OpenGL要求所有可見的坐標(biāo)都落在-1.0到1.0范圍內(nèi),作為頂點著色器最后的輸出,因此,一旦坐標(biāo)在裁剪空間內(nèi)之后,透視除法就會被應(yīng)用到裁剪空間坐標(biāo)上,就是每個點的分量除以w進(jìn)行轉(zhuǎn)換:
out = (x/w, y/w, x/w);
頂點坐標(biāo)的每個分量都會除以它的??分量,距離觀察者越遠(yuǎn)頂點坐標(biāo)就會越小。這是也是??分量非常重要的另一個原因,它能夠幫助我們進(jìn)行透視投影。最后的結(jié)果坐標(biāo)就是處于標(biāo)準(zhǔn)化設(shè)備空間中的。
創(chuàng)建一個透視投影矩陣:
SetPerspective(float fFov, float fAspect, float fNear, float fFar)
同樣,SetPerspective所做的其實就是創(chuàng)建了一個定義了可視空間的大平截頭體,任何在這個平截頭體以外的東西最后都不會出現(xiàn)在裁剪空間體積內(nèi),并且將會受到裁剪。一個透視平截頭體可以被看作一個不均勻形狀的箱子,在這個箱子內(nèi)部的每個坐標(biāo)都會被映射到裁剪空間上的一個點。下面是一張透視平截頭體的圖片:

它的第一個參數(shù)定義了fFov的值,它表示的是視野(Field of View),其值通常是垂直方向上的視野角度大小,它設(shè)置了觀察空間的大小。如果想要一個真實的觀察效果,它的值通常設(shè)置為45.0f,但想要一個末日風(fēng)格的結(jié)果你可以將其設(shè)置一個更大的值。第二個參數(shù)設(shè)置了寬高比,由視口的寬除以高所得。第三和第四個參數(shù)設(shè)置了平截頭體的近和遠(yuǎn)平面。我們通常設(shè)置近距離為0.1f,而遠(yuǎn)距離設(shè)為100.0f。所有在近平面和遠(yuǎn)平面內(nèi)且處于平截頭體內(nèi)的頂點都會被渲染。
當(dāng)使用正射投影時,每一個頂點坐標(biāo)都會直接映射到裁剪空間中而不經(jīng)過任何精細(xì)的透視除法(它仍然會進(jìn)行透視除法,只是w分量沒有被改變(它保持為1),因此沒有起作用)。因為正射投影沒有使用透視,遠(yuǎn)處的物體不會顯得更小,所以產(chǎn)生奇怪的視覺效果。由于這個原因,正射投影主要用于二維渲染以及一些建筑或工程的程序,在這些場景中我們更希望頂點不會被透視所干擾。某些如 Blender 等進(jìn)行三維建模的軟件有時在建模時也會使用正射投影,因為它在各個維度下都更準(zhǔn)確地描繪了每個物體。
使用透視投影的話,遠(yuǎn)處的頂點看起來比較小,而在正射投影中每個頂點距離觀察者的距離都是一樣的。下面給出兩種投影方式的對比:


視口
窗口是以像素為單位度量。 在開始在窗口中繪制點,線,形狀之前,必須告訴OpenGL如何把指定坐標(biāo)映射為屏幕坐標(biāo).
坐標(biāo)系統(tǒng)必須從邏輯笛卡爾坐標(biāo)映射到物理屏幕像素坐標(biāo). 這個映射是通過一種叫做視口(viewPort)的設(shè)置來指定.> 在我們代碼中,我們會通過glViewPort函數(shù)來實現(xiàn)視口的設(shè)計. 視口就是窗口內(nèi)部用于繪制裁剪區(qū)域的客戶區(qū)域.
glViewport (GLint x, GLint y, GLsizei width, GLsizei height);
視口就是窗口中用來顯示圖形的一塊矩形區(qū)域,它可以和窗口等大,也可以比窗口大或者小。只有繪制在視口區(qū)域中的圖形才能被顯示,如果圖形有一部分超出了視口區(qū)域,那么那一部分是看不到的。

?
裁剪區(qū)域:就是視口矩形區(qū)域的最小最大x坐標(biāo)(left, right)和最小最大y坐標(biāo)(bottom, top),而不是窗口的最小最大x坐標(biāo)和y坐標(biāo)。通過glOrtho()函數(shù)設(shè)置,這個函數(shù)還需指定最近最遠(yuǎn)z坐標(biāo),形成一個立體的裁剪區(qū)域。
glOrtho (GLdouble left, GLdouble right, GLdouble bottom, GLdouble top, GLdouble zNear, GLdouble zFar);

?