首先是初始化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
网友评论