OpenGL一些函數詳解(二)


OpenGL ES頂點數據繪制技巧

 

在OpenGL中,繪制一個長方體,需要將每個頂點的坐標放在一個數組中。保存坐標時有一些技巧(由於字母下標不好表示,因此將下標表示為單引號,如A1將在后文中表示為A' ):

(1)將對立面坐標保存在相鄰的位置,如坐標的保存順序為:前面(A'ABB'),后面(D'DCC'),上面(D'A'B'C'),下面(DABC),左面(D'A'AD),右面(C'B'BC)。因為對立面的坐標除了其垂直的那根軸的坐標相反以外,其他坐標值一樣:如前面和后面(垂直於z軸),x和y的坐標一模一樣,z軸的坐標值剛好相反。

        //前面
        -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貼圖坐標和方向

        如,將上圖的一張圖片貼到長方體的一個面上(以正面為例)。一張圖片在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)。特別需要注意的是,貼圖的開始坐標,大小和方向都會影響貼圖的實際效果:

(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)貼到長方體上,實際上剛好和原圖的方向相反(即原圖的上邊將成為貼圖后的下邊),要正確顯示這張圖片的坐標應該是

         (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幾何變換和坐標變換

OpenGL ES支持兩種變換方式:

geometric transformation     幾何變換,即當對象發生平移、縮放、旋轉等變換操作時,相對於原來的坐標點進行變換。

coordinate transformation    坐標變換,即當對象發生平移、縮放、旋轉等變換操作時,對象本身不動,而坐標系統進行變換。

 OpenGL ES之glCullFace函數

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參數的值是不可接受的。

OpenGL ES之glDrawElements 函數 

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參數的值是不可接受的。

OpenGL ES之glFrustumf設置投影視角詳解

 

-(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函數

        第1、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
}

 

OpenGL ES之glLight函數

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_ATTENUATION

param    指定光源light的pname參數的值

函數原型: 

void glLightfv(GLenum light,  GLenum pname,  const GLfloat * params); 
void glLightxv(GLenum light,  GLenum pname,  const GLfixed * params);

函數參數: 

             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參數的值是不可接受的。

OpenGL ES之glNormalPointer函數

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的值為負數。

 

OpenGL ES之glNormal函數

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函數來開啟和關閉標准化,默認標准化是被關閉的。

   

OpenGL ES之glLightModel函數

glLightModel —— 設置光照模型參數

函數原型:

void glLightModelf(GLenum pname,  GLfloat param);

void glLightModelx(GLenum pname,  GLfixed param);

函數參數:

pname  指定一個單值光照模型參數。必須是GL_LIGHT_MODEL_TWO_SIDE。

param   指定要設置的參數值

函數原型:

void glLightModelfv(GLenum pname,  const GLfloat * params); 
void glLightModelxv(GLenum pname,  const GLfixed * params); 

函數參數:

            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。注意,可以被前面和后面多邊形共享的材質屬性只有一種。頂點的光照顏色是材料發射強度,材料環境反射系數和光照模型全景環境光強度的乘積,每個開啟的光源的分布的顏色總和。每個光源都包含三個重要特性的總和:環境光,漫反射,和鏡面反射。環境光源分布是材料環境光反射系數和光的環境強度的乘積。

  

OpenGL ES之glFrontFace函數

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參數的值是不可接受的。

          

  


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM