iOS:用openGLES繪制各種常見圖案(三角形,四邊形,圓形等)

首先是初始化openGL
設置layer

- (void)setupLayer
{
CAEAGLLayer *eaglLayer = (CAEAGLLayer *)self.layer;

// CALayer 默認是透明的,必須將它設為不透明才能讓其可見
eaglLayer.opaque = YES;

// 設置描繪屬性,在這里設置不維持渲染內容以及顏色格式為 RGBA8
eaglLayer.drawableProperties = [NSDictionary dictionaryWithObjectsAndKeys:
                                [NSNumber numberWithBool:YES], kEAGLDrawablePropertyRetainedBacking, kEAGLColorFormatRGBA8, kEAGLDrawablePropertyColorFormat, nil];
//設置放大倍數
[self setContentScaleFactor:[[UIScreen mainScreen] scale]];
}

設置上下文

- (void)setupContext{
// 指定 OpenGL 渲染 API 的版本,在這里我們使用 OpenGL ES 2.0
_context = [[EAGLContext alloc] initWithAPI:kEAGLRenderingAPIOpenGLES2];

 // 設置為當前上下文
if (!_context || ![EAGLContext setCurrentContext:_context]) {
    
    NSLog(@"Failed to initialize OpenGLES 2.0 context");
    
    exit(1);
}
}

設置緩沖區

- (void)setupBuffer{
glDeleteFramebuffers(1, &_viewFramebuffer);

_viewRenderbuffer = 0;

glDeleteRenderbuffers(1, &_viewRenderbuffer);

_viewRenderbuffer = 0;

glGenFramebuffers(1, &_viewFramebuffer);

glGenRenderbuffers(1, &_viewRenderbuffer);

// 設置為當前 framebuffer
glBindFramebuffer(GL_FRAMEBUFFER, _viewFramebuffer);

glBindRenderbuffer(GL_RENDERBUFFER, _viewRenderbuffer);

// 為 顏色緩沖區 分配存儲空間
[_context renderbufferStorage:GL_RENDERBUFFER fromDrawable:(id<EAGLDrawable>)self.layer];

// 將 _colorRenderBuffer 裝配到 GL_COLOR_ATTACHMENT0 這個裝配點上
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, _viewRenderbuffer);

glGetRenderbufferParameteriv(GL_RENDERBUFFER, GL_RENDERBUFFER_WIDTH, &_backingWidth);

glGetRenderbufferParameteriv(GL_RENDERBUFFER, GL_RENDERBUFFER_HEIGHT, &_backingHeight);
}

著色器配置文件:

#define VSH @"attribute vec4 Position;\
attribute vec4 SourceColor;\
varying vec4 DestinationColor;\
void main(void) {\
DestinationColor = SourceColor;\
gl_Position = Position;\
}"

#define FSH @"varying lowp vec4 DestinationColor;\
void main(void) {\
gl_FragColor = DestinationColor;\
}"

三角形和矩形的渲染

- (void)render {

glClearColor(0, 1.0, 0.0, 1.0);

glClear(GL_COLOR_BUFFER_BIT);

CGFloat scale = [[UIScreen mainScreen] scale]; //獲取視圖放大倍數,可以把scale設置為1試試

glViewport(0, 0, self.frame.size.width * scale, self.frame.size.height * scale); //設置視口大小

//加載shader
self.myProgram = [self loadShaders:VSH frag:FSH];

//鏈接
glLinkProgram(self.myProgram);

GLint linkSuccess;

glGetProgramiv(self.myProgram, GL_LINK_STATUS, &linkSuccess);

if (linkSuccess == GL_FALSE) { //連接錯誤
    
    GLchar messages[256];
    
    glGetProgramInfoLog(self.myProgram, sizeof(messages), 0, &messages[0]);
    
    NSString *messageString = [NSString stringWithUTF8String:messages];
    
    NSLog(@"error:%@", messageString);
    
    return ;
    
}else {
    
    NSLog(@"link ok");
    
    glUseProgram(self.myProgram); //成功便使用,避免由于未使用導致的的bug
}

GLuint position = glGetAttribLocation(self.myProgram, "Position");

GLuint textCoor = glGetAttribLocation(self.myProgram, "SourceColor");

const GLfloat Vertices[] = {
    -0.5f,-0.5f,0,0,0,0,// 左下,黑色
    0.5f,-0.5f,0,1,0,0, // 右下,紅色
    0.5f,0.5f,0,0,1,0,  // 右上,綠色
    -0.5f,0.5f,0,0,0,1, // 左上,藍色
};

// 索引數組,指定好了繪制三角形的方式
// 與glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);一樣。
const GLubyte Indices[] = {
    0,1,2, // 三角形0
    0,2,3  // 三角形1
};

GLuint vertexBuffer;

glGenBuffers(1, &vertexBuffer);
// 綁定vertexBuffer到GL_ARRAY_BUFFER目標
glBindBuffer(GL_ARRAY_BUFFER, vertexBuffer);
// 為VBO申請空間,初始化并傳遞數據
glBufferData(GL_ARRAY_BUFFER, sizeof(Vertices), Vertices, GL_STATIC_DRAW);

// 給_positionSlot傳遞vertices數據
glVertexAttribPointer(position, 3, GL_FLOAT, GL_FALSE, sizeof(GLfloat) * 6, NULL);

glEnableVertexAttribArray(position);

// 取出Colors數組中的每個坐標點的顏色值,賦給_colorSlot
glVertexAttribPointer(textCoor, 4, GL_FLOAT, GL_FALSE, sizeof(GLfloat) * 6, (float *)NULL + 3);

glEnableVertexAttribArray(textCoor);

if (_drawType == 1) {
    // Draw triangle
    if (_isHollow) glDrawArrays(GL_LINE_LOOP, 0, 4);   //GL_LINE_LOOP不帶填充
    
    else  glDrawElements(GL_TRIANGLES, sizeof(Indices)/sizeof(Indices[0]), GL_UNSIGNED_BYTE, Indices);
}else{

    glDrawArrays(_isHollow ? GL_LINE_LOOP : GL_TRIANGLES, 0, 3);   //GL_LINE_LOOP不帶填充
}

[self.context presentRenderbuffer:GL_RENDERBUFFER];
}

至于圓形,因為要把圓切割成100份,和矩形有些不一樣

 - (void)renderCircular {

glClearColor(0, 1.0, 1.0, 1.0);

glClear(GL_COLOR_BUFFER_BIT);

CGFloat scale = [[UIScreen mainScreen] scale]; //獲取視圖放大倍數,可以把scale設置為1試試

glViewport(0, 0, self.frame.size.width * scale, self.frame.size.height * scale); //設置視口大小

//加載shader
self.myProgram = [self loadShaders:VSH frag:FSH];

//鏈接
glLinkProgram(self.myProgram);

GLint linkSuccess;

glGetProgramiv(self.myProgram, GL_LINK_STATUS, &linkSuccess);

if (linkSuccess == GL_FALSE) { //連接錯誤
    
    GLchar messages[256];
    
    glGetProgramInfoLog(self.myProgram, sizeof(messages), 0, &messages[0]);
    
    NSString *messageString = [NSString stringWithUTF8String:messages];
    
    NSLog(@"error:%@", messageString);
    
    return ;
    
}else {
    
    NSLog(@"link ok");
    
    glUseProgram(self.myProgram); //成功便使用,避免由于未使用導致的的bug
}

GLuint position = glGetAttribLocation(self.myProgram, "Position");

GLuint textCoor = glGetAttribLocation(self.myProgram, "SourceColor");

GLint vertCount = 101; //分割份數

Vertex vertext[vertCount];

float delta = 2.0*M_PI/vertCount;

float a = 0.8; //水平方向的半徑
float b = a * self.frame.size.width / self.frame.size.height;

for (int i = 0; i < vertCount; i++) {
    GLfloat x = a * cos(delta * i);
    GLfloat y = b * sin(delta * i);
    GLfloat z = 0.0;
    vertext[i] = (Vertex){x, y, z, x, y, x+y};
    
    printf("%f , %f\n", x, y);
}

GLuint vertexBuffer;

glGenBuffers(1, &vertexBuffer);
// 綁定vertexBuffer到GL_ARRAY_BUFFER目標
glBindBuffer(GL_ARRAY_BUFFER, vertexBuffer);
// 為VBO申請空間,初始化并傳遞數據
glBufferData(GL_ARRAY_BUFFER, sizeof(vertext), vertext, GL_STATIC_DRAW);

// 給_positionSlot傳遞vertices數據
glVertexAttribPointer(position, 3, GL_FLOAT, GL_FALSE, sizeof(GLfloat) * 6, NULL);

glEnableVertexAttribArray(position);

// 取出Colors數組中的每個坐標點的顏色值,賦給_colorSlot
glVertexAttribPointer(textCoor, 4, GL_FLOAT, GL_FALSE, sizeof(GLfloat) * 6, (float *)NULL + 3);

glEnableVertexAttribArray(textCoor);

glDrawArrays(_isHollow ? GL_LINE_LOOP : GL_TRIANGLE_FAN, 0, vertCount);//GL_LINE_LOOP 不帶填充

[self.context presentRenderbuffer:GL_RENDERBUFFER];
}

效果圖:


1782258-b1baee1ba0a400e7.png
WechatIMG18.png
1782258-068214f7c72b54c4.png

無填充:


A89F966D-3184-4BEE-AADA-145514F7D367.jpeg
60672747-676A-4282-AB91-0C6CE173B1C6.jpeg
7F588FAD-626C-41BC-940D-442F7B8BE291.jpeg

github代碼地址

?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 230,501評論 6 544
  • 序言:濱河連續發生了三起死亡事件,死亡現場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發現死者居然都...
    沈念sama閱讀 99,673評論 3 429
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事?!?“怎么了?”我有些...
    開封第一講書人閱讀 178,610評論 0 383
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 63,939評論 1 318
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 72,668評論 6 412
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發上,一...
    開封第一講書人閱讀 56,004評論 1 329
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 44,001評論 3 449
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 43,173評論 0 290
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當地人在樹林里發現了一具尸體,經...
    沈念sama閱讀 49,705評論 1 336
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 41,426評論 3 359
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發現自己被綠了。 大學時的朋友給我發了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 43,656評論 1 374
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 39,139評論 5 364
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質發生泄漏。R本人自食惡果不足惜,卻給世界環境...
    茶點故事閱讀 44,833評論 3 350
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 35,247評論 0 28
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 36,580評論 1 295
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 52,371評論 3 400
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 48,621評論 2 380

推薦閱讀更多精彩內容