OpenGL ES學(xué)習(xí)筆記之四(創(chuàng)建球體)

今天我們創(chuàng)建一個(gè)球體做祝,后期會(huì)在此基礎(chǔ)上實(shí)現(xiàn)一個(gè)全景視頻播放器。之前的三篇筆記我們都是通過(guò)兩種方式來(lái)實(shí)現(xiàn)OpenGL ES的學(xué)習(xí)富蓄,即一種方式是使用GLKit另一種方式不使用GLKit像街。這是為了方便理解OpenGL ES才這樣做的筹裕,因?yàn)樘O(píng)果對(duì)OpenGL ES進(jìn)行了部分封裝使其使用起來(lái)更方便了较鼓,但如果直接用GLKit學(xué)習(xí)不利于對(duì)OpenGL ES的理解所以前面我都是在實(shí)現(xiàn)同一個(gè)功能的時(shí)候用兩種方式來(lái)實(shí)現(xiàn)椎木。兩種方式的區(qū)別基本上在前三篇的學(xué)習(xí)中已經(jīng)講解的差多了,基本沒(méi)有其他區(qū)別了博烂,所以以后的學(xué)習(xí)筆記不再使用兩種方式來(lái)實(shí)現(xiàn)而是直接用GLKit來(lái)實(shí)現(xiàn)香椎,下面進(jìn)入正題。

學(xué)習(xí)的代碼都在我的github倉(cāng)庫(kù)歡迎大家學(xué)習(xí)指教禽篱!

一畜伐、生成頂點(diǎn)數(shù)據(jù)

這次我們的代碼也是在上一次學(xué)習(xí)筆記的基礎(chǔ)之上修改來(lái)的,這里只講不同點(diǎn)躺率。上次實(shí)現(xiàn)的立方體和這次實(shí)現(xiàn)的球體已經(jīng)很像了玛界。只要傳入的頂點(diǎn)數(shù)據(jù)不一樣就可以了!其實(shí)學(xué)到這里你會(huì)發(fā)現(xiàn)OpenGL ES只是入門(mén)難悼吱,入門(mén)后里面的東西很簡(jiǎn)單慎框。有點(diǎn)跑題了,現(xiàn)在用代碼實(shí)現(xiàn)頂點(diǎn)數(shù)據(jù)舆绎。我們先要知道以下知識(shí):

  • 我們可以通過(guò)三角函數(shù)實(shí)現(xiàn)一個(gè)圓的坐標(biāo)數(shù)據(jù)
  • 如果我們把多個(gè)圓疊放在一起就可以實(shí)現(xiàn)一他圓柱體
  • 如果我們把這多個(gè)疊放圓的半徑也按三角函數(shù)的方式實(shí)現(xiàn)就可以實(shí)現(xiàn)一個(gè)球體

通過(guò)上面的分析我們大體已經(jīng)知道怎么生成這個(gè)球體的數(shù)據(jù)了鲤脏,全靠頂點(diǎn)來(lái)實(shí)現(xiàn)球體有點(diǎn)不現(xiàn)實(shí),我們可以通過(guò)少量的頂點(diǎn)連接成的三角形來(lái)實(shí)現(xiàn)球體吕朵。頂點(diǎn)越多生成的球體越平滑但也不是沒(méi)有極限,當(dāng)頂點(diǎn)大于一定值的時(shí)候再多的頂點(diǎn)也看不出差別來(lái)反而會(huì)影響性能窥突。所以我們這里有81 x 81個(gè)頂點(diǎn)來(lái)實(shí)現(xiàn)一個(gè)球體努溃。生成頂點(diǎn)的方法如下:

#define kDevidCount 80

/**
 繪制一個(gè)球的頂點(diǎn)

 @param num 傳入要生成的頂點(diǎn)的一層的個(gè)數(shù)(最后生成的頂點(diǎn)個(gè)數(shù)為 num * num)
 @return 返回生成后的頂點(diǎn)
 */
- (Vertex *)getBallDevidNum:(GLint) num{
    
    if (num % 2 == 1) {
        return 0;
    }
    
    GLfloat delta = 2 * M_PI / num; // 分割的份數(shù)
    GLfloat ballRaduis = 0.8; // 球的半徑
    GLfloat pointZ;
    GLfloat pointX;
    GLfloat pointY;
    GLfloat textureY;
    GLfloat textureX;
    GLfloat textureYdelta = 1.0 / (num / 2);
    GLfloat textureXdelta = 1.0 / num;
    GLint layerNum = num / 2.0 + 1; // 層數(shù)
    GLint perLayerNum = num + 1; // 要讓點(diǎn)再加到起點(diǎn)所以num + 1
    
    Vertex * cirleVertex = malloc(sizeof(Vertex) * perLayerNum * layerNum);
    memset(cirleVertex, 0x00, sizeof(Vertex) * perLayerNum * layerNum);
    
    // 層數(shù)
    for (int i = 0; i < layerNum; i++) {
        // 每層的高度(即pointY),為負(fù)數(shù)讓其從下向上創(chuàng)建
        pointY = -ballRaduis * cos(delta * i);
        
        // 每層的半徑
        GLfloat layerRaduis = ballRaduis * sin(delta * i);
        // 每層圓的點(diǎn),
        for (int j = 0; j < perLayerNum; j++) {
            // 計(jì)算
            pointX = layerRaduis * cos(delta * j);
            pointZ = layerRaduis * sin(delta * j);
            textureX = textureXdelta * j;
            textureY = textureYdelta * i;
            
            cirleVertex[i * perLayerNum + j] = (Vertex){pointX, pointY, pointZ, textureX, textureY};
        }
    }
    
    return cirleVertex;
}


// 頂點(diǎn)數(shù)據(jù)索引
- (GLuint *)getBallVertexIndex:(GLint)num{
    
    // 每層要多原點(diǎn)兩次
    GLint sizeNum = sizeof(GLuint) * (num + 1) * (num + 1);
    
    GLuint * ballVertexIndex = malloc(sizeNum);
    memset(ballVertexIndex, 0x00, sizeNum);
    GLint layerNum = num / 2 + 1;
    GLint perLayerNum = num + 1; // 要讓點(diǎn)再加到起點(diǎn)所以num + 1
    
    for (int i = 0; i < layerNum; i++) {
       
        if (i + 1 < layerNum) {
            
            for (int j = 0; j < perLayerNum; j++) {
                
                // i * perLayerNum * 2每層的下標(biāo)是原來(lái)的2倍
                ballVertexIndex[(i * perLayerNum * 2) + (j * 2)] = i * perLayerNum + j;
                // 后一層數(shù)據(jù)
                ballVertexIndex[(i * perLayerNum * 2) + (j * 2 + 1)] = (i + 1) * perLayerNum + j;
            }
        } else {
            
            for (int j = 0; j < perLayerNum; j++) {
                // 后最一層數(shù)據(jù)單獨(dú)處理
                ballVertexIndex[i * perLayerNum * 2 + j] = i * perLayerNum + j;
            }
        }
    }
    
    return ballVertexIndex;
}

在原來(lái)設(shè)置VBO數(shù)據(jù)的方法里設(shè)置上面的方法來(lái)生成頂點(diǎn)數(shù)據(jù)和頂點(diǎn)索引數(shù)據(jù)阻问。代碼如下:

/**
 設(shè)置頂點(diǎn)緩存VBO
 */
- (void)setupBufferVBO {
    
    // 獲取球的頂點(diǎn)和索引
    _cirleVertex = [self getBallDevidNum:kDevidCount];
    _vertextIndex = [self getBallVertexIndex:kDevidCount];
    
    // 設(shè)置VBO
    glGenBuffers(1, &_bufferVBO);
    glBindBuffer(GL_ARRAY_BUFFER, _bufferVBO);
    glBufferData(GL_ARRAY_BUFFER, sizeof(Vertex) * (kDevidCount + 1) * (kDevidCount / 2 + 1), _cirleVertex, GL_STATIC_DRAW);
    
    glGenBuffers(1, &_bufferIndexVBO);
    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, _bufferIndexVBO);
    glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(GLuint) * kDevidCount * (kDevidCount + 1), _vertextIndex, GL_STATIC_DRAW);
    
    glEnableVertexAttribArray(GLKVertexAttribPosition);
    glVertexAttribPointer(GLKVertexAttribPosition, 3, GL_FLOAT, GL_FALSE, sizeof(Vertex), (GLvoid *)NULL);
   
    // 設(shè)置紋理坐標(biāo)
    glEnableVertexAttribArray(GLKVertexAttribTexCoord0);
    glVertexAttribPointer(GLKVertexAttribTexCoord0, 2, GL_FLOAT, GL_FALSE, sizeof(Vertex), (GLfloat *)NULL + 3);
    // 釋放頂點(diǎn)數(shù)據(jù)
    free(_cirleVertex);
    free(_vertextIndex);
}

二梧税、修改渲染方法

由于頂點(diǎn)數(shù)據(jù)的大小變化了,渲染方法里也得修改新的頂點(diǎn)數(shù)據(jù)個(gè)數(shù)的計(jì)算方法称近,代碼如下:

- (void)glkView:(GLKView *)view drawInRect:(CGRect)rect{
    
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
    
    [self.effect prepareToDraw];
    
    // 繪制一個(gè)球
    glDrawElements(GL_TRIANGLE_STRIP, kDevidCount * (kDevidCount + 1), GL_UNSIGNED_INT, 0);
}

由于這次是用的GLKit所以代碼會(huì)簡(jiǎn)單很多第队,渲染方法里的代碼也很少,其他的代碼可以看上一篇筆記∨俑眩現(xiàn)在看一下運(yùn)行結(jié)果凳谦。

球體.gif

球體上面的紋理可能不太合適,大家可以在網(wǎng)上搜一個(gè)地球的紋理試一下效果會(huì)比現(xiàn)在好一點(diǎn)衡未。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末尸执,一起剝皮案震驚了整個(gè)濱河市家凯,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌如失,老刑警劉巖绊诲,帶你破解...
    沈念sama閱讀 222,183評(píng)論 6 516
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異褪贵,居然都是意外死亡掂之,警方通過(guò)查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,850評(píng)論 3 399
  • 文/潘曉璐 我一進(jìn)店門(mén)脆丁,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)板惑,“玉大人,你說(shuō)我怎么就攤上這事偎快》氤耍” “怎么了?”我有些...
    開(kāi)封第一講書(shū)人閱讀 168,766評(píng)論 0 361
  • 文/不壞的土叔 我叫張陵晒夹,是天一觀的道長(zhǎng)裆馒。 經(jīng)常有香客問(wèn)我,道長(zhǎng)丐怯,這世上最難降的妖魔是什么喷好? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 59,854評(píng)論 1 299
  • 正文 為了忘掉前任,我火速辦了婚禮读跷,結(jié)果婚禮上梗搅,老公的妹妹穿的比我還像新娘。我一直安慰自己效览,他們只是感情好无切,可當(dāng)我...
    茶點(diǎn)故事閱讀 68,871評(píng)論 6 398
  • 文/花漫 我一把揭開(kāi)白布。 她就那樣靜靜地躺著丐枉,像睡著了一般哆键。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上瘦锹,一...
    開(kāi)封第一講書(shū)人閱讀 52,457評(píng)論 1 311
  • 那天籍嘹,我揣著相機(jī)與錄音,去河邊找鬼弯院。 笑死辱士,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的听绳。 我是一名探鬼主播颂碘,決...
    沈念sama閱讀 40,999評(píng)論 3 422
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼辫红!你這毒婦竟也來(lái)了凭涂?” 一聲冷哼從身側(cè)響起祝辣,我...
    開(kāi)封第一講書(shū)人閱讀 39,914評(píng)論 0 277
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎切油,沒(méi)想到半個(gè)月后蝙斜,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 46,465評(píng)論 1 319
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡澎胡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,543評(píng)論 3 342
  • 正文 我和宋清朗相戀三年孕荠,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片攻谁。...
    茶點(diǎn)故事閱讀 40,675評(píng)論 1 353
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡稚伍,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出戚宦,到底是詐尸還是另有隱情个曙,我是刑警寧澤,帶...
    沈念sama閱讀 36,354評(píng)論 5 351
  • 正文 年R本政府宣布受楼,位于F島的核電站垦搬,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏艳汽。R本人自食惡果不足惜猴贰,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 42,029評(píng)論 3 335
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望河狐。 院中可真熱鬧米绕,春花似錦、人聲如沸馋艺。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 32,514評(píng)論 0 25
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)丈钙。三九已至非驮,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間雏赦,已是汗流浹背。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 33,616評(píng)論 1 274
  • 我被黑心中介騙來(lái)泰國(guó)打工芙扎, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留星岗,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 49,091評(píng)論 3 378
  • 正文 我出身青樓戒洼,卻偏偏與公主長(zhǎng)得像俏橘,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子圈浇,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,685評(píng)論 2 360

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