iOS --- OpenGLES之初步认识

来源:互联网 发布:淘宝卖家刷钻 编辑:程序博客网 时间:2024/05/16 10:01

iOS上绘制图形的方式很多,UIKit,CoreGraphics,SpriteKit,OpenGL ES,Metal等。OpenGL ES是一套非常底层但使用非常广泛的C语言API,专为移动设备定制,可在不同的手机系统或浏览器上使用,渲染效果非常好。

OpenGLES

援引Apple的OpenGLES_ProrogrammingGuide中的一段简介:

The Open Graphics Library (OpenGL) is used for visualizing 2D and 3D data. It is a multipurpose open-standard graphics library that supports applications for 2D and 3D digital content creation, mechanical and architectural design, virtual prototyping, flight simulation, video games, and more. You use OpenGL to configure a 3D graphics pipeline and submit data to it. Vertices are transformed and lit, assembled into primitives, and rasterized to create a 2D image. OpenGL is designed to translate function calls into graphics commands that can be sent to underlying graphics hardware. Because this underlying hardware is dedicated to processing graphics commands, OpenGL drawing is typically very fast.
OpenGL for Embedded Systems (OpenGL ES) is a simplified version of OpenGL that eliminates redundant functionality to provide a library that is both easier to learn and easier to implement in mobile graphics hardware.
OpenGL ES allows an app to harness the power of the underlying graphics processor. The GPU on iOS devices can perform sophisticated 2D and 3D drawing, as well as complex shading calculations on every pixel in the final image. You should use OpenGL ES if the design requirements of your app call for the most direct and comprehensive access possible to GPU hardware. Typical clients for OpenGL ES include video games and simulations that present 3D graphics.

OpenGL可用于渲染2D和3D图像,是一个多用途的开源图形库。OpenGL设计用来将函数命令转换成图形命令,发送到GPU中。GPU正是被设计用来处理图形命令的,所以OpenGL的绘制非常高效。
OpenGLES是OpenGL的简化版本,抛弃了冗余的文件及命令,使之专用于嵌入式设备。OpenGLES使得移动APP能充分利用GPU的强大运算能力。iOS设备上的GPU能执行更精确的2D和3D绘制,以及更加复杂的针对每个像素的图形脚本(shader)计算。

使用OpenGL ES需要在项目的Build Phases中引入QuartzCore和OpenGLES框架。其基本的使用步骤都是大致固定的。
OpenGLES是一个状态机,可看到很多如glEnable*,glBind*等的函数,使用方式大致类似于切换场景、设置状态、使用命令等。
建立工程后,在implementation文件中添加如下实例变量:

EAGLContext *_eaglContext; // OpenGL context,管理使用opengl es进行绘制的状态,命令及资源CAEAGLLayer *_eaglLayer;GLuint _colorRenderBuffer; // 渲染缓冲区GLuint _frameBuffer; // 帧缓冲区

EAGLContext

An EAGLContext object manages an OpenGL ES rendering context—the state information, commands, and resources needed to draw using OpenGL ES. To execute OpenGL ES commands, you need a current rendering context.
Drawing resources, such as textures and renderbuffers, are managed for the EAGLContext object by an EAGLSharegroup object associated with the context. When you initialize a new EAGLContext object, you can choose to have it create a new sharegroup, or you can use one obtained from a previously created context.
Before drawing to a context, you must bind a complete framebuffer object to the context. For more information on configuring rendering contexts,

EAGLContext对象管理着OpenGLES的渲染context,即所有绘制的状态,命令及资源信息,并控制GPU去执行渲染运算。
绘制如textures及renderbuffers的过程,是由一个与context绑定的EAGLSharegroup对象来管理的。当初始化一个EAGLContext对象的时候,可选择新建一个sharegroup,或者使用已有的,这一点我们往往采用系统默认即可。在绘制到context之前,我们要先绑定一个完整的framebuffer对象到context中。

- (void)setupOpenGLContext {    _eaglContext = [[EAGLContext alloc] initWithAPI:kEAGLRenderingAPIOpenGLES2]; //选择OpenGLES API版本    [EAGLContext setCurrentContext:_eaglContext]; //设置为当前上下文。}

CAEAGLLayer

The CAEAGLLayer class supports drawing OpenGL content in iPhone applications. If you plan to use OpenGL for your rendering, use this class as the backing layer for your views by returning it from your view’s layerClass class method. The returned CAEAGLLayer object is a wrapper for a Core Animation surface that is fully compatible with OpenGL ES function calls.
Prior to designating the layer’s associated view as the render target for a graphics context, you can change the rendering attributes you want using the drawableProperties property. This property lets you configure the color format for the rendering surface and whether the surface retains its contents.
Because an OpenGL ES rendering surface is presented to the user using Core Animation, any effects and animations you apply to the layer affect the 3D content you render. However, for best performance, do the following:
1. Set the layer’s opaque attribute to TRUE.
2. Set the layer bounds to match the dimensions of the display.
3. Make sure the layer is not transformed.
4. Avoid drawing other layers on top of the CAEAGLLayer object. If you must draw other, non OpenGL content, you might find the performance cost acceptable if you place transparent 2D content on top of the GL content and also make sure that the OpenGL content is opaque and not transformed.
5. When drawing landscape content on a portrait display, you should rotate the content yourself rather than using the CAEAGLLayer transform to rotate it.

必须在CAEAGLLayer上才能绘制OpenGLES内容。

- (void)setupCAEAGLLayer {    _eaglLayer = [CAEAGLLayer layer];    _eaglLayer.frame = self.view.frame;    _eaglLayer.opaque = YES; //CALayer默认是透明的    // 描绘属性:这里不维持渲染内容    // kEAGLDrawablePropertyRetainedBacking:若为YES,则使用glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA)计算得到的最终结果颜色的透明度会考虑目标颜色的透明度值。    // 若为NO,则不考虑目标颜色的透明度值,将其当做1来处理。    // 使用场景:目标颜色为非透明,源颜色有透明度,若设为YES,则使用glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA)得到的结果颜色会有一定的透明度(与实际不符)。若未NO则不会(符合实际)。    _eaglLayer.drawableProperties = [NSDictionary dictionaryWithObjectsAndKeys:[NSNumber numberWithBool:NO],kEAGLDrawablePropertyRetainedBacking,kEAGLColorFormatRGBA8,kEAGLDrawablePropertyColorFormat, nil];    [self.view.layer addSublayer:_eaglLayer];}

如果在viewController中,使用[self.view.layer addSublayer:eaglLayer];
如果在view中,可以直接重写UIView的layerClass类方法即可

+ (Class)layerClass {     return [CAEAGLLayer class];}

RenderBuffer

RenderBuffer用于存储渲染的内容,其使用格式比较固定,如下:

- (void)setupRenderBuffer {    if (_colorRenderBuffer) {        glDeleteRenderbuffers(1, &_colorRenderBuffer);        _colorRenderBuffer = 0;    }    // 生成一个renderBuffer,id是_colorRenderBuffer    glGenRenderbuffers(1, &_colorRenderBuffer);    // 设置为当前renderBuffer,则后面引用GL_RENDERBUFFER,即指的是_colorRenderBuffer    glBindRenderbuffer(GL_RENDERBUFFER, _colorRenderBuffer);    //为color renderbuffer 分配存储空间    [_eaglContext renderbufferStorage:GL_RENDERBUFFER fromDrawable:_eaglLayer];}

renderBuffer对象本身不能直接使用,不能挂载到GPU上而直接输出内容的,要使用frameBuffer。

FrameBuffer

OpenGlES的FrameBuffer包含:renderBuffer,depthBuffer,stencilBuffer和accumulationBuffer。

- (void)setupFrameBuffer {    if (_frameBuffer) {        glDeleteFramebuffers(1, &_frameBuffer);        _frameBuffer = 0;    }    // FBO用于管理colorRenderBuffer,离屏渲染    glGenFramebuffers(1, &_frameBuffer);    //设置为当前framebuffer    glBindFramebuffer(GL_FRAMEBUFFER, _frameBuffer);    // 将 _colorRenderBuffer 装配到 GL_COLOR_ATTACHMENT0 这个装配点上    glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, _colorRenderBuffer);}

先设置renderbuffer,然后设置framebuffer,顺序不能互换。

glClearColor

// 设置清屏颜色glClearColor(0.0f, 0.0f, 1.0f, 1.0f);// 用来指定要用清屏颜色来清除由mask指定的buffer,此处是color bufferglClear(GL_COLOR_BUFFER_BIT);

glClear的填色动作类似photoshop中的油桶,用GL_COLOR_BUFFER_BIT声明要清理哪一个缓冲区。

屏幕渲染 ##

// 将指定renderBuffer渲染在屏幕上[_eaglContext presentRenderbuffer:GL_RENDERBUFFER];

以上代码,会呈现一个完全蓝色的屏幕区域,结果如图:

这里写图片描述

参考文章

[OpenGL ES 01]OpenGL ES之初体验
(译)OpenGL ES2.0 – Iphone开发指引

0 0
原创粉丝点击