這篇文章我們同樣借助上篇文章《OpenGLES-02 繪制基本圖元(點(diǎn)兽狭、線环揽、三角形)》的代碼腊尚,使用另外一種畫法來(lái)繪制一個(gè)矩形吨拗。
修改render方法如下:
-(void)render
{
//設(shè)置清屏顏色,默認(rèn)是黑色,如果你的運(yùn)行結(jié)果是黑色婿斥,問(wèn)題就可能在這兒
glClearColor(0.3, 0.5, 0.8, 1.0);
/*
glClear指定清除的buffer
共可設(shè)置三個(gè)選項(xiàng)GL_COLOR_BUFFER_BIT劝篷,GL_DEPTH_BUFFER_BIT和GL_STENCIL_BUFFER_BIT
也可組合如:glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
這里我們只用了color buffer,所以只需清除GL_COLOR_BUFFER_BIT
*/
glClear(GL_COLOR_BUFFER_BIT);
// Setup viewport
glViewport(0, 0, self.frame.size.width, self.frame.size.height);
GLfloat vertices[] = {
// 第一個(gè)三角形
0.5f, 0.5f, 0.0f, // 右上角
0.5f, -0.5f, 0.0f, // 右下角
-0.5f, 0.5f, 0.0f, // 左上角
// 第二個(gè)三角形
0.5f, -0.5f, 0.0f, // 右下角
-0.5f, -0.5f, 0.0f, // 左下角
-0.5f, 0.5f, 0.0f // 左上角
};
glVertexAttribPointer(_positionSlot, 3, GL_FLOAT, GL_FALSE, 0, vertices);
glEnableVertexAttribArray(_positionSlot);
glDrawArrays(GL_TRIANGLES, 0, 6);
[_context presentRenderbuffer:_renderBuffer];
}
如上代碼所示民宿,我們繪制的矩形是由2個(gè)三角形組成的娇妓,一個(gè)三角形3個(gè)頂點(diǎn),共使用了6個(gè)頂點(diǎn)勘高,其中第2個(gè)頂點(diǎn)與第4個(gè)頂點(diǎn)相同(0.5,-0.5,0.0)峡蟋,第3個(gè)頂點(diǎn)與第6個(gè)頂點(diǎn)相同(-0.5,0.5,0.0)坟桅。
其實(shí)對(duì)于矩形來(lái)說(shuō)华望,它只有4個(gè)而不是6個(gè)頂點(diǎn),繪制這個(gè)矩形仅乓,我們指定了右下角和左上角兩次赖舟,這樣就產(chǎn)生了50%的額外開銷。還好我們這會(huì)兒只要畫一個(gè)矩形夸楣,當(dāng)我們要畫成千上萬(wàn)個(gè)矩形或者別的多邊形的時(shí)候宾抓,這樣的繪制方法產(chǎn)生的額外消耗會(huì)更多從而產(chǎn)生一大堆浪費(fèi)。
更好的解決方案是只儲(chǔ)存不同的頂點(diǎn)豫喧,并設(shè)定繪制這些頂點(diǎn)的順序石洗。這樣子我們只要儲(chǔ)存4個(gè)頂點(diǎn)就能繪制矩形了,之后只要指定繪制的順序就行了紧显。還好OpenGL有這樣的方式:
glDrawElements()讲衫;
glDrawElements 函數(shù)的原型為:glDrawElements(GLenum mode, GLsizei count, GLenum type, const GLvoid *indices);
第一個(gè)參數(shù) mode 為描繪圖元的模式,其有效值為:GL_POINTS, GL_LINES, GL_LINE_STRIP, GL_LINE_LOOP, GL_TRIANGLES, GL_TRIANGLE_STRIP, GL_TRIANGLE_FAN孵班。這些模式具體含義下面有介紹涉兽。
第二個(gè)參數(shù) count 為頂點(diǎn)索引的個(gè)數(shù)也就是招驴,type 是指頂點(diǎn)索引的數(shù)據(jù)類型,因?yàn)樗饕冀K是正值枷畏,索引這里必須是無(wú)符號(hào)型的非浮點(diǎn)類型别厘,因此只能是 GL_UNSIGNED_BYTE, GL_UNSIGNED_SHORT, GL_UNSIGNED_INT 之一,為了減少內(nèi)存的消耗拥诡,盡量使用最小規(guī)格的類型如 GL_UNSIGNED_BYTE触趴。
第三個(gè)參數(shù) indices 是存放頂點(diǎn)索引的數(shù)組。(indices 是 index 的復(fù)數(shù)形式袋倔,3D 里面很多單詞的復(fù)數(shù)都挺特別的雕蔽。)
索引緩沖對(duì)象(簡(jiǎn)稱EBO)的工作方式正是這樣的。和頂點(diǎn)緩沖對(duì)象一樣宾娜,EBO也是一個(gè)緩沖批狐,它專門儲(chǔ)存索引,OpenGL調(diào)用這些頂點(diǎn)的索引來(lái)決定該繪制哪個(gè)頂點(diǎn)前塔。所謂的索引繪制(Indexed Drawing)正是我們問(wèn)題的解決方案嚣艇。首先,我們先要定義(獨(dú)一無(wú)二的)頂點(diǎn)华弓,和繪制出矩形所需的索引:
GLfloat vertices[] = {
0.5f, 0.5f, 0.0f, // 右上角
0.5f, -0.5f, 0.0f, // 右下角
-0.5f, -0.5f, 0.0f, // 左下角
-0.5f, 0.5f, 0.0f // 左上角
};
GLubyte indices[] = { // 注意索引從0開始!
0, 1, 3, // 第一個(gè)三角形
1, 2, 3 // 第二個(gè)三角形
};
然后整個(gè)render函數(shù)的代碼該是這樣的:
-(void)render
{
//設(shè)置清屏顏色,默認(rèn)是黑色食零,如果你的運(yùn)行結(jié)果是黑色,問(wèn)題就可能在這兒
glClearColor(0.3, 0.5, 0.8, 1.0);
/*
glClear指定清除的buffer
共可設(shè)置三個(gè)選項(xiàng)GL_COLOR_BUFFER_BIT寂屏,GL_DEPTH_BUFFER_BIT和GL_STENCIL_BUFFER_BIT
也可組合如:glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
這里我們只用了color buffer贰谣,所以只需清除GL_COLOR_BUFFER_BIT
*/
glClear(GL_COLOR_BUFFER_BIT);
// Setup viewport
glViewport(0, 0, self.frame.size.width, self.frame.size.height);
GLfloat vertices[] = {
0.5f, 0.5f, 0.0f, // 右上角
0.5f, -0.5f, 0.0f, // 右下角
-0.5f, -0.5f, 0.0f, // 左下角
-0.5f, 0.5f, 0.0f // 左上角
};
GLubyte indices[] = { // 注意索引從0開始!
0, 1, 3, // 第一個(gè)三角形
1, 2, 3 // 第二個(gè)三角形
};
glVertexAttribPointer(_positionSlot, 3, GL_FLOAT, GL_FALSE, 0, vertices);
glEnableVertexAttribArray(_positionSlot);
glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_BYTE, indices); //6表示有6個(gè)索引數(shù)據(jù),可以使用sizeof(indices)/sizeof(GLubyte)來(lái)確定
[_context presentRenderbuffer:_renderBuffer];
}
兩種方式的運(yùn)行結(jié)果是一樣的,我們可以發(fā)現(xiàn)迁霎,運(yùn)行圖中的矩形是個(gè)長(zhǎng)方形吱抚,而我們給的坐標(biāo),照理來(lái)講應(yīng)該是正方形的考廉,這是因?yàn)槠聊坏膶捀弑炔煌乇瑢?duì)應(yīng)的openGL坐標(biāo)x、y坐標(biāo)也不一樣昌粤,后面我們會(huì)講到投影矩陣既绕,投影矩陣能修復(fù)這個(gè)問(wèn)題。
所有教程代碼在此 : https://github.com/qingmomo/iOS-OpenGLES-