若文章读完,请多练习文章里函数的写法。
1.创建你的项目并新建MyGLView
2.修改你创建的MyGLView添加如下变量(变量后面会有介绍)
@interface MyGLView ()
{
CAEAGLLayer *_eaglLayer; //OpenGL内容只会在此类layer上描绘
EAGLContext *_context; //OpenGL渲染上下文
GLuint _renderBuffer; //
GLuint _frameBuffer; //
}
3.在 MyGLView.m 中添加如下函数:
+(Class)layerClass{
//OpenGL内容只会在此类layer上描绘
return [CAEAGLLayer class];
}
因为OpenGLES的描绘必须在CAEAGLLayer上才能显示出来,所以我们需要重写这个函数,修改view默认的layer返回类型
4.设置_eaglLayer的属性,添加如下函数:
- (void)setupLayer
{
_eaglLayer = (CAEAGLLayer*) self.layer;
// CALayer 默认是透明的,透明对性能影响大,设置为不透明对性能最好
_eaglLayer.opaque = YES;
// 设置描绘属性,在这里设置不维持渲染内容以及颜色格式为 RGBA8
_eaglLayer.drawableProperties = [NSDictionary dictionaryWithObjectsAndKeys:
[NSNumber numberWithBool:NO], kEAGLDrawablePropertyRetainedBacking, kEAGLColorFormatRGBA8, kEAGLDrawablePropertyColorFormat, nil];
}
5.设置渲染上下文 _context 属性,添加如下函数:
- (void)setupContext {
// 指定 OpenGLES 渲染API的版本,在这里我们使用OpenGLES 3.0,由于3.0兼容2.0并且功能更强,为何不用更好的呢
//注:在iOS上,可以支持opengles3.0的最低环境是iphone5s ios7.0.
EAGLRenderingAPI api = kEAGLRenderingAPIOpenGLES3;
_context = [[EAGLContext alloc] initWithAPI:api];
if (!_context) {
NSLog(@"Failed to initialize OpenGLES 3.0 context");
}
// 设置为当前上下文
[EAGLContext setCurrentContext:_context];
}
6.设置 _renderBuffer,添加如下函数:
-(void)setupRenderBuffer{
glGenRenderbuffers(1, &_renderBuffer); //
glBindRenderbuffer(GL_RENDERBUFFER, _renderBuffer);
[_context renderbufferStorage:GL_RENDERBUFFER fromDrawable:_eaglLayer];
}
7.设置 _frameBuffer,添加如下函数:
-(void)setupFrameBuffer{
glGenFramebuffers(1, &_frameBuffer);
glBindFramebuffer(GL_FRAMEBUFFER, _frameBuffer);
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, _renderBuffer);
}
8.buffer介绍
1). buffer分为frame buffer和render buffer两大类,其中frame buffer相当于render buffer的管理者,frame buffer object即称为FBO,常用于做离屏渲染缓冲等。render buffer则又可分为三类,color buffer / depth buffer / stencil buffer。
2). 生成frame buffer object的API函数:
glGenFramebuffers(1, &framebuffer);
glBindFramebuffer(GL_FRAMEBUFFER, framebuffer);
生成render buffer的API函数,render buffer的生成函数是一样的,buffer句柄类型只有在进行分配buffer空间的时候才会确定:
glGenRenderbuffers(1, &renderbuffer);
glBindRenderbuffer(GL_RENDERBUFFER, renderbuffer);
3). frame buffer仅仅是管理者,不需要分配空间;render buffer的存储空间的分配,对于不同的render buffer,使用不同的API进行分配,而只有分配空间的时候,render buffer句柄才确定其类型
(1). 最基本的是color buffer,调用EGALContext的OC方法为其分配空间
/* Attaches an EAGLDrawable as storage for the OpenGL ES renderbuffer object bound to <target> */
- (BOOL)renderbufferStorage:(NSUInteger)target fromDrawable:(id<EAGLDrawable>)drawable;
(2). 而depth buffer则可以直接调用openGL本身的API进行分配
glRenderbufferStorage(GL_RENDERBUFFER,GL_DEPTH_COMPONENT16, width, height);
4). 上面(1)(2)函数是用于生成render buffer的存储空间,生成空间之后,则需要将renderbuffer跟framebuffer进行绑定,调用glFramebufferRenderbuffer函数进行绑定,后面的绘制才能起作用
5). 接下来可以调用OpenGL的函数进行绘制处理,最后则需要调用EGALContext的OC方法进行最终的渲染绘制,这里渲染的是color buffer,这个方法会讲buffer渲染到CALayer上面
- (BOOL)presentRenderbuffer:(NSUInteger)target;
6). 还有一个需要注意的地方是在退出的时候,需要调用glDelegateFramebuffers或者glDeleteRenderbuffers函数删除frame
buffer或者render buffer
9.开始渲染,添加如下函数:
-(void)render
{
//设置清屏颜色,默认是黑色,如果你的运行结果是黑色,问题就可能在这儿
glClearColor(0.3, 0.5, 0.8, 1.0);
/*
glClear指定清除的buffer
共可设置三个选项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);
[_context presentRenderbuffer:_renderBuffer];
}
10.重写 initWithFrame 方法,并调用上述函数:
-(instancetype)initWithFrame:(CGRect)frame{
if (self==[super initWithFrame:frame]) {
[self setupLayer];
[self setupContext];
[self setupRenderBuffer];
[self setupFrameBuffer];
[self render];
}
return self;
}
11.使用与运行结果:
在你的ViewController中导入MyGLView头文件并在viewDidLoad方法中添加如下代码:
MyGLView *openGLView = [[MyGLView alloc]initWithFrame:self.view.bounds];
self.view = openGLView;
// [self.view addSubview:openGLView];
运行结果如下:
运行结果.png
接下来的文章会使用到OpenGLES的坐标点,这里先介绍下在OpenGL里,它的坐标表现:
坐标系.png它的x、y、z的范围都在-1到1之间,坐标原点在图中正方体的中心。如图画的一个白色三角形,它的三个坐标分别是:(-0.5,0.5,0.0)、(-0.5,-0.5,0.0)和(0.5,-0.5,0.0),请对着图好好理解理解.
所有教程代码在此 : https://github.com/qingmomo/iOS-OpenGLES-
网友评论