在OpenGL中,繪製一個長方體,須要將每一個頂點的座標放在一個數組中。保存座標時有一些技巧(因爲字母下標很差表示,所以將下標表示爲單引號,如A1將在後文中表示爲A' ):服務器
(1)將對立面座標保存在相鄰的位置,如座標的保存順序爲:前面(A'ABB'),後面(D'DCC'),上面(D'A'B'C'),下面(DABC),左面(D'A'AD),右面(C'B'BC)。由於對立面的座標除了其垂直的那根軸的座標相反之外,其餘座標值同樣:如前面和後面(垂直於z軸),x和y的座標如出一轍,z軸的座標值恰好相反。ide
//前面
-1.0, 1.0, 1.0,
-1.0, -1.0, 1.0,
1.0, -1.0, 1.0,
1.0, 1.0, 1.0,
//後面
-1.0, 1.0, -1.0,
-1.0, -1.0, -1.0,
1.0, -1.0, -1.0,
1.0, 1.0, -1.0,函數
(2)對立面按相同的頂點和順序保存座標。如前面(A'ABB')和後面(D'DCC'),因爲是對立面,因此前面由A‘開始逆時針保存座標,而對立面後面則從D’開始按逆時針保存座標。這樣就能夠按照第(1)條的方式保存座標數據了。測試
(3)保存座標時,沒有固定的順序,如前面,能夠從A‘開始保存,也能夠從A, B, B'開始保存。動畫
如,將上圖的一張圖片貼到長方體的一個面上(以正面爲例)。一張圖片在OpenGL ES中表示的時候,長度和寬度都是1,表示上圖的座標爲(0,1)(0,0)(1,0)(1,1)若是隻想截取圖片的一部分,能夠本身設置座標值,如,我要截取左下角的1/4圖片,那麼座標就是(0,0.5)(0,0)(0.5,0)(0.5,0.5)。特別須要注意的是,貼圖的開始座標,大小和方向都會影響貼圖的實際效果:.net
(1)(0,1)(0,0)(1,0)(1,1)和(0,0)(1,0)(1,1)(0,1)都表示了這張圖片,可是在貼圖時的實際方向是不同的(旋轉角度不一樣)指針
(2)(0,1)(0,0)(1,0)(1,1)貼到長方體上,實際上恰好和原圖的方向相反(即原圖的上邊將成爲貼圖後的下邊),要正確顯示這張圖片的座標應該是orm
(1,0)(1,1)(0,1)(0,0)(逆時針)
(3)表示圖片的寬度和高度都是1
(4)要想表示原圖的一部分,能夠修改對應的座標值
(5)若是貼圖的格式爲gif動畫,那麼只會顯示第一幀圖片
(6)貼圖的長寬應爲2的n次方,如2,4,8,16,64,128……不然,圖片將不能顯示出來。
OpenGL ES之glEnable和glDisable函數
glEnable/glDisable —— 開啓和關閉服務器端GL功能
void glEnable(GLenum cap);
void glDisable(GLenum cap);
cap 指明一個GL功能的標識符。
glEnable/glDisable能夠用來開啓和關閉各類功能。使用glIsEnabled或glGet 來獲取當前設置的GL功能。GL_DITHER和GL_MULTISAMPLE的初始值爲GL_TURE,其餘功能的初始值都是GL_FALSE。
glEnable/glDisable都只接受一個cap參數,cap 的取值能夠是:
GL_ALPHA_TEST
alpha測試功能,參考glAlphaFunc函數。
GL_BLEND
混合功能,將片元顏色和顏色緩衝區的顏色進行混合,參考glBlendFunc。
GL_COLOR_LOGIC_OP
將當前的邏輯操做應用於通過計算的片元顏色和顏色緩衝區值,參考glLogicOp。
GL_CLIP_PLANEi
剪切用戶定義的剪裁面i,參考glClipPlane。
GL_COLOR_MATERIAL
使用環境和漫反射材質來跟蹤當前顏色。
GL_CULL_FACE
根據在窗口座標中的彎曲來剔除多邊形。
GL_DEPTH_TEST
進行深度比較和更新深度緩衝。注意,即便深度緩衝區存在而且表示深度緩衝區的掩碼也不爲0,可是若是深度測試被禁止的話,也是不會更新深度緩衝區的。參考glDepthFunc和glDepthRange。
GL_DITHER
在寫入顏色緩衝區以前抖動顏色組件。
GL_FOG
將一個霧(fog)顏色混合進一個貼圖後的顏色,參考glFog。
GL_LIGHTi
使用光i進行光照方程式計算,參考 glLightModel和 glLight。
GL_LIGHTING
使用當前光照計算頂點顏色。不然只是將當前的顏色和頂點簡單的關聯在一塊兒,參考glMaterial, glLightModel, 和glLight.
GL_LINE_SMOOTH
使用正確的過濾來繪製線,參考glLineWidth.
GL_MULTISAMPLE
使用多個片元採樣來計算最終的像素顏色,參考glSampleCoverage。
GL_NORMALIZE
在轉換以後和光照以前將法線向量標準化成單位長度。一般這個功能效率要比GL_RESCALE_NORMAL低。參考glNormal和 glNormalPointer.
GL_POINT_SMOOTH
使用合適的過濾器來繪製點,參考glPointSize.
GL_POINT_SPRITE_OES
激活點精靈。參考glPointSize和 glTexEnv。
GL_POLYGON_OFFSET_FILL
在深度對比以前,給多邊形片元的深度值加上一個偏移量。參考glPolygonOffset。
GL_RESCALE_NORMAL
在轉換以後和光照以前,經過一個由模型矩陣計算出來的因子來對法線向量進行縮放。若是模型矩陣縮放空間保持一致,那麼和存儲轉換後的法線爲單位長度的效果是同樣的。這個功能一般要比GL_NORMALIZE的效率高。參考glNormal和glNormalPointer。
GL_SAMPLE_ALPHA_TO_COVERAGE
計算一個臨時的覆蓋值,該值的每一位都由相應的採樣位置的alpha值決定。臨時覆蓋值和片元覆蓋值進行與操做。
GL_SAMPLE_ALPHA_TO_ONE
使用最大的可展示的alpha值來代替每個採樣alpha值。
GL_SAMPLE_COVERAGE
片元覆蓋值和臨時覆蓋值進行與操做。若是GL_SAMPLE_COVERAGE_INVERT的值被設置爲 GL_TRUE,那麼將會反轉覆蓋值。參考glSampleCoverage。
GL_SCISSOR_TEST
丟棄在剪切區域外的片元,參考glScissor。
GL_STENCIL_TEST
進行模板測試和模板緩衝區更新。參考glStencilFunc,glStencilMask,glStencilOp。
GL_TEXTURE_2D
對活動的材質單元進行二維貼圖。參考glActiveTexture, glTexImage2D,glCompressedTexImage2D, glCopyTexImage2D.
GL_CLIP_PLANEi 和GL_POINT_SPRITE_OES只在GL 1.1和更高版本中才被支持。
OpenGL ES支持兩種變換方式:
geometric transformation 幾何變換,即當對象發平生移、縮放、旋轉等變換操做時,相對於原來的座標點進行變換。
coordinate transformation 座標變換,即當對象發平生移、縮放、旋轉等變換操做時,對象自己不動,而座標系統進行變換。
glCullFace —— 指明前面或後面的多邊形是否要剔除
void glCullFace(GLenum mode);
mode 指明前面或後面的多邊形是否要剔除(就是不顯示)。可使用的標識符有GL_FRONT,GL_BACK, 和GL_FRONT_AND_BACK。初始值是GL_BACK。
指明當剔除功能啓用時,前面或後面的多邊形是否要剔除(由mode 指定的那一面)。使用帶GL_CULL_FACE參數的glEnable 和 glDisable函數來啓用和關閉剔除功能。剔除功能默認是關閉的。
若是 mode的值爲GL_FRONT_AND_BACK,那麼多邊形將不會被繪製到屏幕上,但其餘圖元如點和線仍是會繪製到屏幕上的。
GL_INVALID_ENUM 若是傳入mode參數的值是不可接受的。
glDrawElements —— 渲染數組數據中的圖元
void glDrawElements(GLenum mode, GLsizei count, GLenum type, const GLvoid * indices);
mode 指定要渲染的圖元類型,可選的值有 GL_POINTS,GL_LINE_STRIP, GL_LINE_LOOP, GL_LINES,
GL_TRIANGLE_STRIP,GL_TRIANGLE_FAN,GL_TRIANGLES。
count 指定要渲染的元素個數。
type 指定indices數組中的元素類型。必須是GL_UNSIGNED_BYTE或者GL_UNSIGNED_SHORT。
indices 指向保存索引的數組。
glDrawElements能夠經過很是少的子程序調用來指定多個幾何圖元。
如 果mode的值爲GL_FRONT_AND_BACK,那麼多邊形將不會被繪製到屏幕上,但其餘圖元如點和線仍是會繪製到屏幕上的。
GL_INVALID_ENUM 若是傳入mode參數的值是不可接受的。
-(void)setClipping { float aspectRatio; const float zNear = 0.1; //1 指定了近裁面的距離 const float zFar = 1000; //2 指定了遠裁面的距離 const float fieldOfView = 60.0; //3 設定視角爲60度。 GLfloat size; CGRect frame = [[UIScreen mainScreen] bounds]; //4 獲取屏幕的尺寸大小 aspectRatio=(float)frame.size.width/(float)frame.size.height; //5 根據屏幕的尺寸計算最終屏幕的縱橫比例 //Set the OpenGL projection matrix. glMatrixMode(GL_PROJECTION); //6 將當前矩陣從模型視圖矩陣設置成投影矩陣 glLoadIdentity(); size = zNear * tanf(GLKMathDegreesToRadians (fieldOfView) / 2.0); //7 計算錐形視角的左右上下的限制值 glFrustumf(-size, size, -size /aspectRatio, size /aspectRatio, zNear, zFar); //8 計算的左右上下以及近剪裁面和遠剪裁面的值傳進glFrustumf函數 glViewport(0, 0, frame.size.width, frame.size.height); //9 設置視口,通常爲屏幕的大小 //Make the OpenGL ModelView matrix the default. glMatrixMode(GL_MODELVIEW); //10 將當前的矩陣從投影矩陣設置爲模型視圖矩陣 }
glFrustumf中文API文檔參考OpenGL ES之glFrustum函數
第一、2行指定了近裁面和遠裁面的距離。這兩個值的意思是,任何遠於1000或近於0.1的對象都將被過濾掉。你可能會問一千什麼?就是一千!單位看你本身設想。你能夠把它想象成光年,或者英尺,都無所謂。不信的話你本身隨便設置一下試試。
第3行設定視角爲60度。
第4行獲取屏幕的尺寸大小。
第5行根據屏幕的尺寸計算最終屏幕的縱橫比例。它的高度和寬度的值決定了相對高度的視域(FOV),若是將其翻轉的話,將變成相對於寬度的視域。若是咱們要設置一個60度視域,就像一個寬角度鏡頭,那麼它將基於窗口的高度而非寬度。當渲染到一個非正方形的屏幕上時尤其重要。
因爲glfrustumf影響的是投影矩陣,因此咱們須要確認將當前矩陣從模型視圖矩陣設置成投影矩陣。第6行就是要作這個滴。
第7行計算錐形視角的左右上下的限制值。你能夠把它想象成3D空間中的虛擬窗口。原點在屏幕中央,因此x軸和y軸的值都是從-size到+size。這就是爲何會有GLKMathDegreesToRadians (fieldOfView) / 2.0將窗口分爲兩部分——視角的角度是從-30度到+30度的。乘以zNear就能夠計算出近剪裁面在座標軸各個方向上的大小。這就是正切函數的做用了,眼睛在z軸上,到原點的距離是zNear,視域被z軸分爲上下兩部分各爲30度,因此就能夠明白size就是近剪裁面在x和y軸上的長度。
第8行將計算的左右上下以及近剪裁面和遠剪裁面的值傳進glFrustumf函數。這裏下邊和上邊的值都除以了aspectRatio(屏幕寬高比),而左右邊沒有,這是由於調用glLoadIdentity函數標準化投影矩陣的時候將全部的頂點數據都標準化到了-1~1的範圍內,屏幕寬度和高度實際大小不同,但都被標準化成了1。因此若是左右值和上下值同樣的話獲得的就是一個寬度比較大而高度比較小的長方形,而不是預期的正方形,因此左右值不變,而上下值要除以寬高比。
第9行用來設置視口,通常爲屏幕的大小。不過你能夠根據須要來設置座標和寬度、高度。
第10行爲將當前的矩陣從投影矩陣設置爲模型視圖矩陣。
因爲設置投影視角的方法基本上是固定的,只不過須要調整一下近剪裁面和遠剪裁面以及視角的大小,因此能夠將setClipping函數進一步封裝爲:
-(void)setClippingWithNear:(const float)zNear far:(const float)zFar angle:(const float) fieldOfView { float aspectRatio; GLfloat size; CGRect frame = [[UIScreen mainScreen] bounds]; //4 aspectRatio=(float)frame.size.width/(float)frame.size.height; //5 //Set the OpenGL projection matrix. glMatrixMode(GL_PROJECTION); //6 glLoadIdentity(); size = zNear * tanf(GLKMathDegreesToRadians (fieldOfView) / 2.0); //7 glFrustumf(-size, size, -size /aspectRatio, size /aspectRatio, zNear, zFar); //8 glViewport(0, 0, frame.size.width, frame.size.height); //9 //Make the OpenGL ModelView matrix the default. glMatrixMode(GL_MODELVIEW); //10 }
glLight —— 設置光源參數
void glLightf(GLenum light, GLenum pname, GLfloat param);
void glLightx(GLenum light, GLenum pname, GLfixed param);
light 指定一個光。光的數量要看具體的實現,可是至少要支持8個。標識符的形式如GL_LIGHTi,其中i大於等於0,小於GL_MAX_LIGHT。
pname 爲light指定一個單值光源參數。可取的值有
GL_SPOT_EXPONENT,
GL_SPOT_CUTOFF,
GL_CONSTANT_ATTENUATION,
GL_LINEAR_ATTENUATION, 和
GL_QUADRATIC_ATTENUATIONparam 指定光源light的pname參數的值
light 指定一個光。光的數量要看具體的實現,可是至少要支持8個。標識符的形式如GL_LIGHTi,其中i大於等於0,小於GL_MAX_LIGHT。
pname 爲light指定一個光源參數。可取的值有
GL_AMBIENT,
GL_DIFFUSE,
GL_SPECULAR,
GL_POSITION,
GL_SPOT_CUTOFF,
GL_SPOT_DIRECTION,
GL_SPOT_EXPONENT,
GL_CONSTANT_ATTENUATION,
GL_LINEAR_ATTENUATION, and
GL_QUADRATIC_ATTENUATION
param 指定光源light的pname參數的值或指向一組值的數組指針
glLight用來設置獨立光源參數的值。light用來命名光,而且是形式如GL_LIGHTi的標識符,其中i大於等於0,小於GL_MAX_LIGHT。pname用來指定十種光源的某一種,光源也是使用標示符來表示的。params要麼是一個單值要麼是一個指向包含新值的數組指針。
調用帶GL_LIGHTING參數的glEnable和glDisable函數來開啓和關閉光照計算。初始時,光照是關閉的。光源i調用帶GL_LIGHTi參數的glEnable和glDisable函數來開啓和關閉。
十個光源參數以下:
GL_AMBIENT
params包含四個定點或浮點數值來指定環境RGBA光強度。初始環境光強度爲(0,0,0,1)。
GL_DIFFUSE
params包含四個定點或浮點數值來指定漫反射RGBA光強度。GL_LIGHT0的初始值爲(1,1,1,1),對於其它的光,初始值都是(0,0,0,0)。
GL_SPECULAR
params包含四個定點或浮點數值來指定鏡面反射RGBA光強度。GL_LIGHT0的初始值爲(1,1,1,1),對於其它的光,初始值都是(0,0,0,0)。
GL_POSITION
params包含四個定點或浮點數值來指定在奇次對象座標系統中的光的位置。當glLight被調用時,由模型視圖矩陣對點進行轉換,而且存儲在眼睛座標系統(eye coordinates)中。若是位置的w組件的值爲0,那麼該光將被認爲是定向光源。漫反射和鏡面光照要使用到光的方向,但考慮到衰減被關閉,所以並非它的真正的位置。不然,漫反射和鏡面光照計算將基於眼睛座標系統中的光的真實位置,此時要開啓衰減。初始位置爲(0,0,1,0),因此初始時光源是定向的,而且平行於z軸,在-z軸方向。
GL_SPOT_EXPONENT
params是一個指定光照強度的單定點或浮點數值。取值範圍是[0, 128]。有效的光照強度是經過光照方向和光到被光照的頂點方向的夾角的cos值進行衰減獲得的,直到點光指數的值。所以點光指數越大,聚光效果就越好,此處不考慮點光的切角問題。初始點光指數爲0,獲得的是一個均勻的光照分佈。
GL_SPOT_DIRECTION
params包含三個定點或浮點數值來指定在奇次對象座標系統中的光照方向。當glLight被調用時,點光的方向由上3*3模型視圖矩陣來轉換,並存儲在眼睛座標系統中。它只在GL_SPOT_CUTOFF不是180時纔是有效的,這是初始設定的。初始方向是(0,0,-1)。
GL_SPOT_CUTOFF
params是一個單定點或浮點數值來指定一個光源的最大擴展角度。取值範圍是[0, 90]和特定值180.若是光線方向和光到被照射頂點的方向之間的夾角比點光的切角大,那麼,光照將被徹底掩蓋。不然,它的強度由點光指數和衰減因子控制。初始點光切角是180,獲得的是一個均勻光照分佈。
GL_CONSTANT_ATTENUATION,GL_LINEAR_ATTENUATION,GL_QUADRATIC_ATTENUATION
params是一個單定點或浮點數值來指定三個光照衰減因子之一。取值範圍是非負數。若是光是可定位的而不是定向的,它的強度由常數因子總和的倒數來衰減,線性因子與光和被照射頂點之間的距離有關,平方因子與該距離的平方有關。初始衰減因子爲(1,0,0),即沒有衰減。
GL_LIGHTi = GL_LIGHT0 + i 。
GL_INVALID_ENUM 若是傳入light或pname參數的值是不可接受的。
glNormalPointer —— 定義一個法線數組
void glNormalPointer(GLenum type, GLsizei stride, const GLvoid * pointer);
type 指明數組中每一個座標的數據類型,可選的標識符有
GL_BYTE,
GL_SHORT,和
GL_FIXED 。默認值是GL_FLOAT。
stride 指定連續法線間的字節偏移。若是取值爲0,說明數組中法線是連續不間斷保存的。初始值爲0。
pointer 一個指向數組中第一個法線的第一個座標的指針。
glNormalPointer指明渲染時使用到的法線數組的數據位置。type指明法線座標的數據類型。stride指明兩個相鄰的法線數據間的字節偏移,這將容許頂點數據和頂點屬性數據保存在同一個數組中或不一樣的數組中。在某些實現中,單個數組保存的效率會更高。
glNormalPointer 一般在客戶端實現。
GL_INVALID_ENUM 若是傳入type參數的值是不可接受的。
GL_INVALID_VALUE 若是stride的值爲負數。
glNormal —— 設置當前法線數組
void glNormal3f(GLfloat nx, GLfloat ny, GLfloat nz);
void glNormal3x(GLfixed nx, GLfixed ny, GLfixed nz);
nx, ny, nz 指定新的當前法線的x, y, z座標。初始值爲(0,0,1)。
glNormal指定的法線不須要爲單位長度。若是開啓了GL_NORMALIZE,由glNormal指定的任何長度的法線都將在轉換後被標準化。若是開啓了 GL_RESCALE_NORMAL,法線將會經過派生自模型視圖矩陣的縮放因子進行縮放。GL_RESCALE_NORMAL須要原來指定的法線爲單位長度。調用帶GL_NORMALIZE或GL_RESCALE_NORMAL參數的glEnable和glDisable函數來開啓和關閉標準化,默認標準化是被關閉的。
glLightModel —— 設置光照模型參數
void glLightModelf(GLenum pname, GLfloat param);
void glLightModelx(GLenum pname, GLfixed param);
pname 指定一個單值光照模型參數。必須是GL_LIGHT_MODEL_TWO_SIDE。
param 指定要設置的參數值
pname 指定一個單值光照模型參數。必須是GL_LIGHT_MODEL_TWO_SIDE或者GL_LIGHT_MODEL_AMBIENT。
params 指定要設置的參數指針。
GL_LIGHT_MODEL_AMBIENT
params包含四個定點或浮點值來指定整個場景的環境光強度。初始值是(0.2,0.2,0.2,1.0)。
GL_LIGHT_MODEL_TWO_SIDE
params是一個單定點或浮點數來指定多邊形要不要進行一邊或兩邊的光照計算。它對點和線的光照計算沒有任何做用。若是params的值是0,一邊的光照被指定,前面和後面的多邊形將被賦予相同的計算顏色。若是params的值不是0,那麼兩邊的光照都被指定。在這種狀況下,在光照方程式使用到背面多邊形的頂點以前,背面多邊形的頂點法線將被反轉。前面多邊形頂點將一直被光照,而且法線也不會改變。初始值是0。注意,能夠被前面和後面多邊形共享的材質屬性只有一種。頂點的光照顏色是材料發射強度,材料環境反射係數和光照模型全景環境光強度的乘積,每一個開啓的光源的分佈的顏色總和。每一個光源都包含三個重要特性的總和:環境光,漫反射,和鏡面反射。環境光源分佈是材料環境光反射係數和光的環境強度的乘積。
glFrontFace —— 定義前面和背面多邊形
void glFrontFace(GLenum mode);
mode 指明前面多邊形的方向。可選的值有GL_CW和GL_CCW。默認值是GL_CCW。
在一個所有由不透明封閉表面組成的場景中,背面多邊形是永遠看不見的。剔除這些不可見的多邊形對於加速圖形的渲染有很大的益處。開啓和關閉剔除功能能夠調用帶GL_CULL_FACE參數的glEnable和glDisable函數。默認剔除功能是關閉的。若是一個虛構的對象的頂點是按照多邊形內部順時針的方向進行繪製的,那麼能夠稱這個多邊形基於窗口座標的投影是順時針的。反之,則爲逆時針。
glFrontFace就是用來指定多邊形在窗口座標中的方向是逆時針仍是順時針的。GL_CCW說明逆時針多邊形爲正面,而GL_CW說明順時針多邊形爲正面。默認是逆時針多邊形爲正面
GL_INVALID_ENUM 若是傳入mode參數的值是不可接受的。