OpenGL ES 2.0 Making the Hardware Work for You


顯示控制

iOS 系統(tǒng)會(huì)通過一個(gè)稱之為 Core Animation Compositor (核心動(dòng)畫合成器[系統(tǒng)組件])去控制最終在屏幕顯示的圖像递递。

--> 核心動(dòng)畫層可以同時(shí)擁有多個(gè)圖層迁匠;

--> 圖層保存了所有的繪制結(jié)果年扩;

--> Core Animation Compositor 是由 OpenGL ES 來(lái)控制圖形處理、圖層的合成魂爪、幀緩存數(shù)據(jù)的快速交換擅耽;


Frame Buffers 和 Layers 的關(guān)系

--> pixel color render buffer司恳,是 Frame Buffers 與 Layers 交換數(shù)據(jù)的地方(共享);

--> other render buffers俩功,是可選的幻枉,但一個(gè) OpenGL ES 程序至少包含一個(gè);


例子:三角形

--诡蜓?-> 如果用 UIKit 直接做會(huì)怎樣熬甫?

----> Try It ...
ViewController.view + UIImageView
前者,設(shè)置背景色為黑色蔓罚;
后者椿肩,添加進(jìn)前者中成為子控件;
1)后者直接設(shè)置 .image 為 一張白色的圖片(自己要制作一張圖片)脚粟;
2)后者不設(shè)置圖片覆旱,設(shè)置顏色為白色,再 .layer 設(shè)置貝賽爾曲線進(jìn)行剪切(要自己計(jì)算坐標(biāo)核无,并進(jìn)行繪制)扣唱;

---->

--?-> 使用 OpenGL ES 直接進(jìn)行繪制团南?

首先噪沙,分析圖像的組成:

  • 背景色是純黑色的;
  • 圖中有一個(gè)白色的直角三角形吐根;
    • 因?yàn)?OpenGL ES 實(shí)際繪制的圖形是根據(jù)坐標(biāo)點(diǎn)來(lái)進(jìn)行填充的正歼,而且三角形是由三個(gè)頂點(diǎn)連線組成的,所以 OpenGL ES 繪制的時(shí)候需要 三個(gè)坐標(biāo)點(diǎn)拷橘;
      ----> Just Do It ...

類的綁定:


Controller --> OpenGLES_Ch2_1ViewController

view --> GLKView

核心代碼:


OpenGLES_Ch2_1ViewController.h

完整代碼:

//
//  OpenGLES_Ch2_1ViewController.m
//  OpenGLES_Ch2_1
//

#import "OpenGLES_Ch2_1ViewController.h"

@implementation OpenGLES_Ch2_1ViewController

@synthesize baseEffect;

/////////////////////////////////////////////////////////////////
// This data type is used to store information for each vertex
typedef struct {
   GLKVector3  positionCoords;
}
SceneVertex;

/////////////////////////////////////////////////////////////////
// Define vertex data for a triangle to use in example
static const SceneVertex vertices[] = 
{
   {{-0.5f, -0.5f, 0.0}}, // lower left corner
   {{ 0.5f, -0.5f, 0.0}}, // lower right corner
   {{-0.5f,  0.5f, 0.0}}, // upper left corner
};


/////////////////////////////////////////////////////////////////
// Called when the view controller's view is loaded
// Perform initialization before the view is asked to draw
- (void)viewDidLoad
{
   [super viewDidLoad];
   
   // Verify the type of view created automatically by the
   // Interface Builder storyboard
   GLKView *view = (GLKView *)self.view;
   NSAssert([view isKindOfClass:[GLKView class]],
      @"View controller's view is not a GLKView");
   
   // Create an OpenGL ES 2.0 context and provide it to the
   // view
   view.context = [[EAGLContext alloc] 
      initWithAPI:kEAGLRenderingAPIOpenGLES2];
   
   // Make the new context current
   [EAGLContext setCurrentContext:view.context];
   
   // Create a base effect that provides standard OpenGL ES 2.0
   // Shading Language programs and set constants to be used for 
   // all subsequent rendering
   self.baseEffect = [[GLKBaseEffect alloc] init];
   self.baseEffect.useConstantColor = GL_TRUE;
   self.baseEffect.constantColor = GLKVector4Make(
      1.0f, // Red
      1.0f, // Green
      1.0f, // Blue
      1.0f);// Alpha
   
   // Set the background color stored in the current context 
   glClearColor(0.0f, 0.0f, 0.0f, 1.0f); // background color
   
   // Generate, bind, and initialize contents of a buffer to be 
   // stored in GPU memory
   glGenBuffers(1,                // STEP 1
      &vertexBufferID);
   glBindBuffer(GL_ARRAY_BUFFER,  // STEP 2
      vertexBufferID); 
   glBufferData(                  // STEP 3
      GL_ARRAY_BUFFER,  // Initialize buffer contents
      sizeof(vertices), // Number of bytes to copy
      vertices,         // Address of bytes to copy
      GL_STATIC_DRAW);  // Hint: cache in GPU memory
}


/////////////////////////////////////////////////////////////////
// GLKView delegate method: Called by the view controller's view
// whenever Cocoa Touch asks the view controller's view to
// draw itself. (In this case, render into a frame buffer that
// shares memory with a Core Animation Layer)
- (void)glkView:(GLKView *)view drawInRect:(CGRect)rect
{
   [self.baseEffect prepareToDraw];
   
   // Clear Frame Buffer (erase previous drawing)
   glClear(GL_COLOR_BUFFER_BIT);
   
   // Enable use of positions from bound vertex buffer
   glEnableVertexAttribArray(      // STEP 4
      GLKVertexAttribPosition);
      
   glVertexAttribPointer(          // STEP 5
      GLKVertexAttribPosition, 
      3,                   // three components per vertex
      GL_FLOAT,            // data is floating point
      GL_FALSE,            // no fixed point scaling
      sizeof(SceneVertex), // no gaps in data
      NULL);               // NULL tells GPU to start at 
                           // beginning of bound buffer
                                   
   // Draw triangles using the first three vertices in the 
   // currently bound vertex buffer
   glDrawArrays(GL_TRIANGLES,      // STEP 6
      0,  // Start with first vertex in currently bound buffer
      3); // Use three vertices from currently bound buffer
}


/////////////////////////////////////////////////////////////////
// Called when the view controller's view has been unloaded
// Perform clean-up that is possible when you know the view 
// controller's view won't be asked to draw again soon.
- (void)viewDidUnload
{
   [super viewDidUnload];
   
   // Make the view's context current
   GLKView *view = (GLKView *)self.view;
   [EAGLContext setCurrentContext:view.context];
    
   // Delete buffers that aren't needed when view is unloaded
   if (0 != vertexBufferID)
   {
      glDeleteBuffers (1,          // STEP 7 
                       &vertexBufferID);  
      vertexBufferID = 0;
   }
   
   // Stop using the context created in -viewDidLoad
   ((GLKView *)self.view).context = nil;
   [EAGLContext setCurrentContext:nil];
}

@end

---->完整分析

繪制的整體過程:
【標(biāo)記 Buffers --> 綁定 Buffers --> 初始化 Buffers --> 使能 Buffers --> 計(jì)算所有點(diǎn)的偏移量 --> 繪制 Buffers --> 刪除 Buffers 】

OpenGLES_Ch2_1ViewController.h 文件


分析:

  • 因?yàn)镺penGL ES 2.0 繪制的第一步需要一個(gè)標(biāo)記局义,所以需要定義一個(gè) GLuint 變量作為標(biāo)記

GLuint 的定義:typedef uint32_t GLuint; (位于 OpenGLES/gltypes.h)

  • GLKBaseEffect ,基本的效果類
GLKit

OpenGLES_Ch2_1ViewController.m 文件:


分析(viewDidload):


viewDidload

【步驟:判定當(dāng)前 View 是否是 GLKView --> 設(shè)置上下文環(huán)境(Context) --> 設(shè)置基本渲染效果(baseEffect) --> 準(zhǔn)備繪制的數(shù)據(jù)(標(biāo)記 Buffers --> 綁定 Buffers --> 初始化 Buffers ) 】

判定 View
Context
  • 1喜爷、view.context 的定義: GLKit/GLKView.h -->@property (nonatomic, retain) EAGLContext *context;

  • 2、initWithAPI:定義:OpenGLES/EAGL.h --> - (instancetype) initWithAPI:(EAGLRenderingAPI) api;

  • 3萄唇、EAGLRenderingAPI的定義:

typedef NS_ENUM(NSUInteger, EAGLRenderingAPI)
{
    kEAGLRenderingAPIOpenGLES1 = 1,
    kEAGLRenderingAPIOpenGLES2 = 2,
    kEAGLRenderingAPIOpenGLES3 = 3,
};

因?yàn)楝F(xiàn)在 OpenGL ES 已經(jīng)更新到 3.0了所以有三個(gè)選項(xiàng)檩帐,因?yàn)楸疚牡睦邮?基于OpenGL ES 2.0 所以要選擇 kEAGLRenderingAPIOpenGLES2 (注意這個(gè)不能選錯(cuò));

  • 4另萤、setCurrentContext 的定義: + (BOOL) setCurrentContext:(EAGLContext*) context;湃密,可以監(jiān)聽返回值,設(shè)置是否成功四敞;
設(shè)置 BaseEffect
- 1泛源、BaseEffect  的屬性
- 2、`constantColor` 填充色(設(shè)置填充色的前提是`self.baseEffect.useConstantColor = GL_TRUE;`忿危,開啟填充色)达箍,如果把 Green 置零
準(zhǔn)備繪制的數(shù)據(jù)
- 1、`glClearColor`铺厨,設(shè)置(view)背景色幻梯,定義 -->  `GL_API void           GL_APIENTRY glClearColor (GLfloat red, GLfloat green, GLfloat blue, GLfloat alpha);`修改顏色值觀察變化 
填充色
背景色
- 2、`glGenBuffers`努释,添加標(biāo)記碘梢,定義`GL_API void  GL_APIENTRY glGenBuffers (GLsizei n, GLuint* buffers);`, GLsizei  `typedef int32_t  GLsizei;`

第一個(gè)參數(shù)是表明伐蒂,有多少個(gè)標(biāo)記煞躬;

第二個(gè)參數(shù)是表明,標(biāo)記數(shù)是多少逸邦;

- 3恩沛、`glBindBuffer`,添加綁定雷客,定義`GL_API void  GL_APIENTRY glBindBuffer (GLenum target, GLuint buffer);` GLenum `typedef uint32_t GLenum;`

第一個(gè)參數(shù)是表明,要綁定的 Buffers 類型(有兩個(gè)值:GL_ARRAY_BUFFER桥狡, GL_ELEMENT_ARRAY_BUFFER

- 4搅裙、`glBufferData`,`定義:GL_API void   GL_APIENTRY glBufferData (GLenum target, GLsizeiptr size, const GLvoid* data, GLenum usage);`

第一個(gè)參數(shù)裹芝,何種類型的 Buffers 部逮;

第二個(gè)參數(shù),GLsizeiptr typedef intptr_t GLsizeiptr; (就是 long)嫂易, 拷貝多少字節(jié)的數(shù)據(jù)兄朋;

第三個(gè)參數(shù), 數(shù)據(jù)的指針怜械;

第四個(gè)參數(shù)颅和,繪制的類型(STATIC 是表明 Buffers 的內(nèi)容是靜態(tài)的傅事,不再改變;DYNAMIC 表明 Buffers 的內(nèi)容是頻繁更新的)峡扩;

- 5享完、`vertices`,因?yàn)槲覀兪且L制 三角形有额,所以有三個(gè)坐標(biāo)點(diǎn)(頂點(diǎn)):

坐標(biāo)值
其中`GLKVector3` 定義 :

(Union,共用體)

--> 因?yàn)?OpenGL ES 的坐標(biāo)范圍為:【-1,1】,三角形在坐標(biāo)系下的展示為:
坐標(biāo)系的展示

數(shù)據(jù)的準(zhǔn)備已經(jīng)做完彼绷,那么現(xiàn)在就可以進(jìn)行圖形繪制了巍佑。

繪制的方法是,- (void)glkView:(GLKView *)view drawInRect:(CGRect)rect 這個(gè)方法是 GLKView 的代理方法寄悯;

Dash 中查看代理方法:


只有一個(gè)代理方法萤衰,在 Controller 需要重新繪制 View 的時(shí)候都會(huì)調(diào)用這個(gè)代理方法,進(jìn)行繪制猜旬。

【繪制步驟:繪制前準(zhǔn)備 --> 擦除之前的繪制 --> 繪制最新的】

  • 繪制前準(zhǔn)備脆栋,[self.baseEffect prepareToDraw];

查看 prepareToDraw 方法:


同步繪制前所有的更改,保證現(xiàn)在要繪制的圖形就是最新的修改洒擦;

  • 擦除之前的繪制

// Clear Frame Buffer (erase previous drawing) glClear(GL_COLOR_BUFFER_BIT);

glClear 的定義是:GL_API void GL_APIENTRY glClear (GLbitfield mask);椿争;

GLbitfield,定義 :typedef uint32_t GLbitfield;有以下三個(gè)值選擇:

因?yàn)楝F(xiàn)在我們繪制的圖形是 2D 的而且只填充了顏色參數(shù)熟嫩,所以直接選擇 GL_COLOR_BUFFER_BIT 選項(xiàng)即可秦踪;

  • 繪制最新的


【使能 Buffers --> 計(jì)算所有點(diǎn)的偏移量 --> 繪制 Buffers 】

- 使能 Buffers `glEnableVertexAttribArray`,函數(shù)的定義是:

GL_API void GL_APIENTRY glEnableVertexAttribArray (GLuint index) __OSX_AVAILABLE_STARTING(__MAC_NA,__IPHONE_3_0);

繪制的選項(xiàng)


因?yàn)槲覀兪且宰鴺?biāo)點(diǎn)進(jìn)行繪制的掸茅,所以選擇 GLKVertexAttribPosition

- 計(jì)算所有點(diǎn)的偏移量 `glVertexAttribPointer` 椅邓, 函數(shù)定義為 `GL_API void           GL_APIENTRY glVertexAttribPointer (GLuint indx, GLint size, GLenum type, GLboolean normalized, GLsizei stride, const GLvoid* ptr)  __OSX_AVAILABLE_STARTING(__MAC_NA,__IPHONE_3_0);`

其中,GLint typedef int32_t GLint; ; GLboolean typedef uint8_t GLboolean; ; GLvoid typedef void GLvoid;

參數(shù)分析:

第一個(gè)參數(shù)昧狮,表明資源數(shù)據(jù)的類型景馁;

第二個(gè)參數(shù),表明一個(gè)坐標(biāo)點(diǎn)中有多少個(gè)元素逗鸣;

第三個(gè)參數(shù)合住,表明元素的類型是什么;

第四個(gè)參數(shù)撒璧,表明有沒有使用縮放聊疲;

第五個(gè)參數(shù),表明坐標(biāo)點(diǎn)有多少個(gè)字節(jié)沪悲;

第六個(gè)參數(shù)获洲,表明從坐標(biāo)數(shù)據(jù)緩沖區(qū)的起始位開始;

  • 繪制三角形


    glDrawArrays 定義:GL_API void GL_APIENTRY glDrawArrays (GLenum mode, GLint first, GLsizei count);第一個(gè)參數(shù)殿如,表明要求 GPU 繪制一個(gè)三角形贡珊;第二個(gè)參數(shù)最爬,表明起始坐標(biāo)下標(biāo);第三個(gè)參數(shù)门岔,表明有多少個(gè)坐標(biāo)要繪制爱致;

  • 刪除 Buffers

【步驟:保證當(dāng)前 View.context 是正在使用的 context --> 刪除 Buffers --> 停用 Context】

  • 保證 context
  • 刪除 Buffers


glDeleteBuffers 定義: GL_API void GL_APIENTRY glDeleteBuffers (GLsizei n, const GLuint* buffers); 與 標(biāo)記的函數(shù)是一樣參數(shù),兩者要一一對(duì)應(yīng)起來(lái)寒随; 最后糠悯,把 vertexBufferID 置零,表明沒有使用這個(gè)標(biāo)記妻往;

  • 停用 context

設(shè)置當(dāng)前繪制的 context 為 nil 互艾,表明不再進(jìn)行繪制;

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末讯泣,一起剝皮案震驚了整個(gè)濱河市纫普,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌好渠,老刑警劉巖昨稼,帶你破解...
    沈念sama閱讀 221,273評(píng)論 6 515
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異拳锚,居然都是意外死亡假栓,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,349評(píng)論 3 398
  • 文/潘曉璐 我一進(jìn)店門霍掺,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)但指,“玉大人,你說(shuō)我怎么就攤上這事抗楔∑宓剩” “怎么了?”我有些...
    開封第一講書人閱讀 167,709評(píng)論 0 360
  • 文/不壞的土叔 我叫張陵连躏,是天一觀的道長(zhǎng)剩岳。 經(jīng)常有香客問我,道長(zhǎng)入热,這世上最難降的妖魔是什么拍棕? 我笑而不...
    開封第一講書人閱讀 59,520評(píng)論 1 296
  • 正文 為了忘掉前任,我火速辦了婚禮勺良,結(jié)果婚禮上绰播,老公的妹妹穿的比我還像新娘。我一直安慰自己尚困,他們只是感情好蠢箩,可當(dāng)我...
    茶點(diǎn)故事閱讀 68,515評(píng)論 6 397
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般谬泌。 火紅的嫁衣襯著肌膚如雪滔韵。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 52,158評(píng)論 1 308
  • 那天掌实,我揣著相機(jī)與錄音陪蜻,去河邊找鬼。 笑死贱鼻,一個(gè)胖子當(dāng)著我的面吹牛宴卖,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播邻悬,決...
    沈念sama閱讀 40,755評(píng)論 3 421
  • 文/蒼蘭香墨 我猛地睜開眼症昏,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來(lái)了拘悦?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,660評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤橱脸,失蹤者是張志新(化名)和其女友劉穎础米,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體添诉,經(jīng)...
    沈念sama閱讀 46,203評(píng)論 1 319
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡屁桑,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,287評(píng)論 3 340
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了栏赴。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片蘑斧。...
    茶點(diǎn)故事閱讀 40,427評(píng)論 1 352
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖须眷,靈堂內(nèi)的尸體忽然破棺而出竖瘾,到底是詐尸還是另有隱情,我是刑警寧澤花颗,帶...
    沈念sama閱讀 36,122評(píng)論 5 349
  • 正文 年R本政府宣布捕传,位于F島的核電站,受9級(jí)特大地震影響扩劝,放射性物質(zhì)發(fā)生泄漏庸论。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,801評(píng)論 3 333
  • 文/蒙蒙 一棒呛、第九天 我趴在偏房一處隱蔽的房頂上張望聂示。 院中可真熱鬧,春花似錦簇秒、人聲如沸鱼喉。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,272評(píng)論 0 23
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)蒲凶。三九已至气筋,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間旋圆,已是汗流浹背宠默。 一陣腳步聲響...
    開封第一講書人閱讀 33,393評(píng)論 1 272
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留灵巧,地道東北人搀矫。 一個(gè)月前我還...
    沈念sama閱讀 48,808評(píng)論 3 376
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像刻肄,于是被迫代替她去往敵國(guó)和親瓤球。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,440評(píng)論 2 359

推薦閱讀更多精彩內(nèi)容