OpenGLES_實(shí)戰(zhàn)04_教你繪制球體

學(xué)習(xí)是一件開(kāi)心的額事情

本節(jié)學(xué)習(xí)目標(biāo)

使用OpenGL繪制一個(gè)地球

上干貨

  • 第一步 創(chuàng)建一個(gè)工程
讓學(xué)習(xí)成為一種習(xí)慣
讓學(xué)習(xí)成為一種習(xí)慣
  • 第二步 創(chuàng)建GLKViewController類(lèi)型的控制器
讓學(xué)習(xí)成為一種習(xí)慣
  • 第三步 添加OpenGL ES 2.0的頭文件
讓學(xué)習(xí)成為一種習(xí)慣
  • 第四步 配置我們的GLKViewController 控制器
GLKView *glkView = (GLKView*)self.view;
glkView.drawableDepthFormat = GLKViewDrawableDepthFormat24;// 設(shè)置深度緩沖區(qū)格式
// 創(chuàng)建管理上下文
glkView.context = [[EAGLContext alloc]initWithAPI:kEAGLRenderingAPIOpenGLES2];
// 設(shè)置當(dāng)前上下文
[EAGLContext setCurrentContext:glkView.context];
  • 第五步 創(chuàng)建一個(gè)負(fù)責(zé)渲染的類(lèi)
@property(nonatomic,strong)GLKBaseEffect *baseEffect;
self.baseEffect = [[GLKBaseEffect alloc]init];
  • 第六步 生成球體的頂點(diǎn)坐標(biāo)和紋理坐標(biāo)和索引

下面是生成球體坐標(biāo)C語(yǔ)言方法

#define ES_PI  (3.14159265f)

int generateSphere(int numSlices, float radius, float **vertices,
            float **texCoords, uint16_t **indices, int *numVertices_out) {
int i;
int j;
int numParallels = numSlices / 2;
int numVertices = (numParallels + 1) * (numSlices + 1);
int numIndices = numParallels * numSlices * 6;
float angleStep = (2.0f * ES_PI) / ((float) numSlices);
if (vertices != NULL)
    *vertices = malloc(sizeof(float) * 3 * numVertices);
if (texCoords != NULL)
    *texCoords = malloc(sizeof(float) * 2 * numVertices);
if (indices != NULL)
    *indices = malloc(sizeof(uint16_t) * numIndices);
for (int i = 0; i < numParallels + 1; i++) {
    for (int j = 0; j < numSlices + 1; j++) {
        int vertex = (i * (numSlices + 1) + j) * 3;
        if (vertices) {
            (*vertices)[vertex + 0] = radius * sinf(angleStep * (float)i) *
            sinf(angleStep * (float)j);
            (*vertices)[vertex + 1] = radius * cosf(angleStep * (float)i);
            (*vertices)[vertex + 2] = radius * sinf(angleStep * (float)i) *
            cosf(angleStep * (float)j);
        }
        if (texCoords) {
            int texIndex = (i * (numSlices + 1) + j) * 2;
            (*texCoords)[texIndex + 0] = (float)j / (float)numSlices;
            (*texCoords)[texIndex + 1] = 1.0f - ((float)i / (float)numParallels);
        }
    }
}
if (indices != NULL) {
    uint16_t *indexBuf = (*indices);
    for (i = 0; i < numParallels ; i++) {
        for (j = 0; j < numSlices; j++) {
            *indexBuf++ = i * (numSlices + 1) + j;
            *indexBuf++ = (i + 1) * (numSlices + 1) + j;
            *indexBuf++ = (i + 1) * (numSlices + 1) + (j + 1);
            
            *indexBuf++ = i * (numSlices + 1) + j;
            *indexBuf++ = (i + 1) * (numSlices + 1) + (j + 1);
            *indexBuf++ = i * (numSlices + 1) + (j + 1);
        }
    }
}
if (numVertices_out) {
    *numVertices_out = numVertices;
}
return numIndices;
}

接下來(lái)定義上面函數(shù)需要的參數(shù)

GLfloat   *_vertexData; // 頂點(diǎn)數(shù)據(jù)
GLfloat   *_texCoords;  // 紋理坐標(biāo)
GLushort  *_indices;    // 頂點(diǎn)索引
 GLint    _numVetex;   // 頂點(diǎn)數(shù)量
GLuint  _texCoordsBuffer;// 紋理坐標(biāo)內(nèi)存標(biāo)識(shí)
GLuint  _numIndices; // 頂點(diǎn)索引的數(shù)量

調(diào)用上面方法生成頂點(diǎn)坐標(biāo),紋理坐標(biāo)励背,索引數(shù)組

 _numIndices = generateSphere(200, 1.0, &(_vertexData), &(_texCoords), &_indices, &_numVetex);
  • 第七步 將頂點(diǎn)坐標(biāo)歪玲,紋理坐標(biāo)懒闷,索引坐標(biāo)加載到GPU 中去
-(void)loadVertexData{

// 加載頂點(diǎn)坐標(biāo)數(shù)據(jù)
glGenBuffers(1, &_vertexBuffer); // 申請(qǐng)內(nèi)存
glBindBuffer(GL_ARRAY_BUFFER, _vertexBuffer); // 將命名的緩沖對(duì)象綁定到指定的類(lèi)型上去
glBufferData(GL_ARRAY_BUFFER, sizeof(GLfloat)*_numVetex*3,_vertexData, GL_STATIC_DRAW);
glEnableVertexAttribArray(GLKVertexAttribPosition);  // 綁定到位置上
glVertexAttribPointer(GLKVertexAttribPosition, 3, GL_FLOAT, GL_FALSE, 3*sizeof(GLfloat), NULL);

// 加載頂點(diǎn)索引數(shù)據(jù)
GLuint _indexBuffer;
glGenBuffers(1, &_indexBuffer);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, _indexBuffer);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, _numIndices*sizeof(GLushort), _indices, GL_STATIC_DRAW);



// 加載紋理坐標(biāo)
glGenBuffers(1, &_texCoordsBuffer);
glBindBuffer(GL_ARRAY_BUFFER, _texCoordsBuffer);
glBufferData(GL_ARRAY_BUFFER, sizeof(GLfloat)*_numVetex*2, _texCoords, GL_DYNAMIC_DRAW);
glEnableVertexAttribArray(GLKVertexAttribTexCoord0);
glVertexAttribPointer(GLKVertexAttribTexCoord0, 2, GL_FLOAT, GL_FALSE, 2*sizeof(GLfloat), NULL);

}
  • 第八步 將我們的地圖照片使用剛才創(chuàng)建的渲染類(lèi)GLKBaseEffect 加載到內(nèi)存中去
讓學(xué)習(xí)成為一種習(xí)慣
GLKTextureInfo *textureInfo =
[GLKTextureLoader textureWithCGImage:[UIImage imageNamed:@"earth-diffuse.jpg"].CGImage options:nil error:nil];
self.baseEffect.texture2d0.target = textureInfo.target;
self.baseEffect.texture2d0.name = textureInfo.name;
  • 第九步 在繪制之前,我們要設(shè)置一下 世界坐標(biāo)和繪制球體的自身坐標(biāo)
 // 設(shè)置世界坐標(biāo)和視角
float aspect = fabs(self.view.bounds.size.width / self.view.bounds.size.height);
GLKMatrix4 projectionMatrix = GLKMatrix4MakePerspective(GLKMathDegreesToRadians(65.0f), aspect, 0.1f, 100.0f);
self.baseEffect.transform.projectionMatrix = projectionMatrix;

// 設(shè)置模型坐標(biāo)
GLKMatrix4 modelViewMatrix = GLKMatrix4MakeTranslation(0.0f, -1.0f, -6.5f);
self.baseEffect.transform.modelviewMatrix =  modelViewMatrix;
  • 第十一步 我們?cè)O(shè)置個(gè)沿著Y軸旋轉(zhuǎn)的效果
// update方法系統(tǒng)會(huì)自動(dòng)調(diào)動(dòng)  
-(void)update{
 self.baseEffect.transform.modelviewMatrix = GLKMatrix4Rotate(self.baseEffect.transform.modelviewMatrix, 0.1, 0, 1, 0);
}
  • 第十二步 開(kāi)始繪制
-(void)glkView:(GLKView *)view drawInRect:(CGRect)rect{

// 清除顏色緩沖區(qū)
glClearColor(1.0, 0, 1.0, 1);
glClear(GL_COLOR_BUFFER_BIT);

// 繪制之前必須調(diào)用這個(gè)方法
[self.baseEffect prepareToDraw];
static int i =1;
if (i < _numIndices-2000){
    i = i+1000;
}else{
    i = _numIndices;
}

// 以畫(huà)單獨(dú)三角形的方式 開(kāi)始繪制
glDrawElements(GL_TRIANGLES, i,GL_UNSIGNED_SHORT, NULL);
}

代碼!

運(yùn)行一下:

讓學(xué)習(xí)成為一種習(xí)慣

總結(jié)

寫(xiě)這篇文章主要給初學(xué)者一個(gè)繪制球體的思路,蘋(píng)果給我們封裝的類(lèi),幫助我們簡(jiǎn)化了不少代碼,如果純OpenGL 做這樣一個(gè)練習(xí)代碼量還是挺多的乍楚。

代碼下載

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末扔字,一起剝皮案震驚了整個(gè)濱河市掂器,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌疫诽,老刑警劉巖,帶你破解...
    沈念sama閱讀 216,372評(píng)論 6 498
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件旦委,死亡現(xiàn)場(chǎng)離奇詭異奇徒,居然都是意外死亡,警方通過(guò)查閱死者的電腦和手機(jī)缨硝,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,368評(píng)論 3 392
  • 文/潘曉璐 我一進(jìn)店門(mén)摩钙,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人查辩,你說(shuō)我怎么就攤上這事胖笛⊥郑” “怎么了?”我有些...
    開(kāi)封第一講書(shū)人閱讀 162,415評(píng)論 0 353
  • 文/不壞的土叔 我叫張陵长踊,是天一觀的道長(zhǎng)功舀。 經(jīng)常有香客問(wèn)我,道長(zhǎng)身弊,這世上最難降的妖魔是什么辟汰? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 58,157評(píng)論 1 292
  • 正文 為了忘掉前任,我火速辦了婚禮阱佛,結(jié)果婚禮上帖汞,老公的妹妹穿的比我還像新娘。我一直安慰自己凑术,他們只是感情好翩蘸,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,171評(píng)論 6 388
  • 文/花漫 我一把揭開(kāi)白布。 她就那樣靜靜地躺著淮逊,像睡著了一般催首。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上泄鹏,一...
    開(kāi)封第一講書(shū)人閱讀 51,125評(píng)論 1 297
  • 那天郎任,我揣著相機(jī)與錄音,去河邊找鬼命满。 笑死,一個(gè)胖子當(dāng)著我的面吹牛绣版,可吹牛的內(nèi)容都是我干的胶台。 我是一名探鬼主播,決...
    沈念sama閱讀 40,028評(píng)論 3 417
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼杂抽,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼诈唬!你這毒婦竟也來(lái)了?” 一聲冷哼從身側(cè)響起缩麸,我...
    開(kāi)封第一講書(shū)人閱讀 38,887評(píng)論 0 274
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤铸磅,失蹤者是張志新(化名)和其女友劉穎,沒(méi)想到半個(gè)月后杭朱,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體阅仔,經(jīng)...
    沈念sama閱讀 45,310評(píng)論 1 310
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,533評(píng)論 2 332
  • 正文 我和宋清朗相戀三年弧械,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了八酒。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 39,690評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡刃唐,死狀恐怖羞迷,靈堂內(nèi)的尸體忽然破棺而出界轩,到底是詐尸還是另有隱情,我是刑警寧澤衔瓮,帶...
    沈念sama閱讀 35,411評(píng)論 5 343
  • 正文 年R本政府宣布浊猾,位于F島的核電站,受9級(jí)特大地震影響热鞍,放射性物質(zhì)發(fā)生泄漏葫慎。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,004評(píng)論 3 325
  • 文/蒙蒙 一碍现、第九天 我趴在偏房一處隱蔽的房頂上張望幅疼。 院中可真熱鬧,春花似錦昼接、人聲如沸爽篷。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 31,659評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)逐工。三九已至,卻和暖如春漂辐,著一層夾襖步出監(jiān)牢的瞬間泪喊,已是汗流浹背。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 32,812評(píng)論 1 268
  • 我被黑心中介騙來(lái)泰國(guó)打工髓涯, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留袒啼,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 47,693評(píng)論 2 368
  • 正文 我出身青樓纬纪,卻偏偏與公主長(zhǎng)得像蚓再,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子包各,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,577評(píng)論 2 353

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

  • 1 前言 一直想沿著圖像處理這條線建立一套完整的理論知識(shí)體系摘仅,同時(shí)積累實(shí)際應(yīng)用經(jīng)驗(yàn)。因此有了從使用AVFounda...
    RichardJieChen閱讀 5,662評(píng)論 5 12
  • 你好问畅,三角形 圖形渲染管線(Pipeline) 3D坐標(biāo)轉(zhuǎn)為2D坐標(biāo)的處理過(guò)程是由OpenGL的圖形渲染管線(Pi...
    IceMJ閱讀 7,439評(píng)論 2 13
  • 開(kāi)發(fā)基于 OpenGL 的應(yīng)用程序娃属,必須先了解 OpenGL 的庫(kù)函數(shù)。它采用 C 語(yǔ)言風(fēng)格护姆,提供大量的函數(shù)來(lái)進(jìn)行...
    sillen閱讀 3,067評(píng)論 0 4
  • 第五章-數(shù)據(jù) 本章我們會(huì)學(xué)到什么 如何創(chuàng)建緩沖和紋理矾端,用它們來(lái)存儲(chǔ)數(shù)據(jù),以及程式如何訪問(wèn)數(shù)據(jù)卵皂。 如何使得OpenG...
    葭五閱讀 4,538評(píng)論 2 13
  • 若我們都愛(ài)與過(guò)去聊天渐裂,那全世界都在失眠豺旬。
    北七海閱讀 171評(píng)論 0 0