cocos2d-x之OpenGL概述

Norton-Linux核心研究發表於2020-04-07

概述

cocos2d-x底層實現依賴OpenGL,這是一個圖形庫,可以操作顯示卡,因此,在處理比較複雜的遊戲,消耗較大的遊戲時,處理的效率會很高。而像android自帶的canvas工具,就不能提供這種效率,因為它不是直接操作顯示卡的。當然,android自帶的一些畫圖工具,可以做一些簡單的遊戲開發,如下棋,貪食蛇,連連看等。

OpenGL1.0是固定管線的,內建functions設定所有渲染狀態:燈光,頂點,顏色,攝像機。

OpenGL2.0是針對可程式設計管線的,需要手動設定著色器(shader)。shader包括vertexShader和textureShader,可以處理頂點和紋理的數值,這樣,在顯示卡將要顯示前,就可以對物件的座標和顏色進行修改,輕易地實現很多特效:如波紋。可以通過shader對燈光、陰影的細節進行處理,而1.0是無法對這些細節進行處理的。


cocos2d-x使用的OpenGL技術,大概就如下面所述,因為是2d圖形引擎,所以,比較少用到3D的OpenGL API,因此,本文算是粗略涵蓋了cocos2d-x涉及到OpenGL的內容。

cocos2d-x也使用了DirectX庫,其實和OpenGL的渲染流程,原理是一樣的,只是API的命名方式不同。因此,可以從OpenGL中借鑑設計原理。

使用流程

1.準備view,如android中的MySurfaceView

2.建立OpenGl context

3.建立render buffer

是OpenGL物件,用於存放渲染過的影像。螢幕區域這麼大的尺寸作為約束。

4.建立frame buffer

是OpenGL物件,存放幀,它包含了render buffer . depth buffer , stencil buffer 和 accumulation buffer

深度緩衝區depth buffer:3D渲染時候,受到Z軸影響,會有遮擋現象,需要儲存深度資訊進行深度比較,以保證遮擋關係正確。

渲染流程

注意渲染流程的一個特點:先傳入指標,再傳入值。所以,我們會看到多次對頂點,或者對某個變數進行操作。我所指的指標,可能是glxxxHandle,glxxxLocation,glxxxPointer。然後把先前準備好的數值:glBufferData,glUniform4fv。這些變數的意思會在下面看到。

編寫著色器——shader程式

包括頂點著色器vertex.sh和片元著色器frag.sh。直接由顯示卡GPU執行,而不是由CPU執行。GPU的圖形處理能力高於CPU的,因此openg2.0 比 1.0效率高好多。shader程式可以儲存在任意文件格式中,甚至可以儲存在字串裡,因為我們只需要獲取程式內容,而不管它是什麼格式。

頂點著色器中
1.使用了4個變數存放頂點位置,這是因為在進行矩陣運算時候,比x,y,z多一個變數w“方便矩陣運算”。
2.使用了varing對顏色進行宣告,該關鍵字的功能是可以實現“漸變色”,即我們雖然只指定了4個頂點的顏色,但是頂點間的區域是按照頂點間的色差進行漸變的。

片元著色器中
varing lowp vec4 DestinationColor;   //表示低精度運算的向量,把lowp改為highp關鍵字,則表示高精度運算..一般手機進行低精度運算即可。

這兩個著色器,是在執行的時候才編譯,而且是通過OpenGL庫來編譯的。因為OpenGL是跨平臺的,進行執行時編譯,比較適合,這樣可以把編譯出來的程式碼相容到不同的平臺。


OpenGL系統函式

glCreateShader
glShaderSource //獲取shader原始碼
glCompileShader  //編譯shader
glGetShaderiv/glGetShaderInfoLog  //檢測編譯是否成功,得到錯誤資訊
glCreateProgram    //建立program
glAttachShader  //繫結兩個shader到program
glLinkProgram   //將兩個shader連結成一個完成的program
glGetProgramiv,glGetProgramInfoLog   //檢測是否連結成功
glUseProgram    //讓OpenGl執行Program
glGetAttribLocation  //獲取shader中的傳入變數,後期將傳遞值到shader中計算
glEnableVertexAttribArray  //啟用資料,不啟用的話,glGetAttribLocation的資料就不會被傳入program

頂點資料(準備階段)
glGenBuffers   //建立頂點緩衝物件
glBindBuffer    //繫結緩衝區,告訴OpenGL這是指GL_ARRAY_BUFFER陣列緩衝區
glBufferData  //繫結資料到緩衝區

渲染圖形(著色階段)
glVertexAttribPointer   // 向shader提供輸入引數值(上面的只是準備了頂點資料,還沒輸入到著色器)
glDrawElement   // 繪製圖形,每個頂點都會呼叫vertex shader , 每個“畫素”都會呼叫frag shader

這樣就完成渲染了。

投影矩陣

uniform mat4 Projection;      //mat4是4個變數的矩陣變數,uniform關鍵字會影響所有的頂點的位置變數。
gl_Position = Projection * Position;
glGetUniformLocation ;  //獲取vertex shader中的Projection的指標(下面的函式會為這個指標傳入值)
glUniformMatrix4fv   //為shader傳入變數的值

模型檢視矩陣

unifrom mat4 ModelView;
gl_Position = Projection* ModelView*Position;
每個物體都有一個模型檢視矩陣,用來控制模型的旋轉/平移/縮放。

紋理資料

attribute vec2 TexCoordIn;
varying vec2 TexCoordOut;
TexCoordOut = TexCoordIn;

varying lowp vec2 TexCoordOut;
unifrom sampler2D Texture ;  // 讀取一張圖片
gl_FragColor =  DesitinationColor *  texture2D(Texture, TexCoordOut);   //呼叫系統函式texture2D,根據紋理座標TexCoordOut,顯示Texuture圖片(二維陣列)。//DestinationColor是原來的顏色,乘不乘都可以,只是一個混合運算。

glGenTexutures ;   //建立紋理(指標)
glBindTexture ;    //繫結紋理後,下面的程式碼都使用該紋理,直至重新呼叫一次該繫結glBindTexture
glTexParameteri;  //設定紋理過濾(紋理比物件小或者大時候的處理方式,min map 等)
glTexImage2D;  // 設定紋理資料 (讀取一個二位陣列,即圖形的資料)
glActiveTexture;  //啟用紋理資料(繪製)

glBindTexture; //再次繫結紋理
glUnifrom1i ;  //向frag shader 傳遞紋理“資料”
至此,圖片就能被成功貼到物件上

OpenGL的文字顯示

一般是通過每個平臺下的drawString把文字繪製到圖片上,然後把這個圖片紋理貼到四方形上。android呼叫的是canvas,windows上是呼叫GDI繪製,cocos2d呼叫xx二維API繪製。

相關文章