OpenGL ES --FrameBuffer
FrameBuffer对象被用来存放渲染的结果,FrameBuffer可以使你对颜色,模型,色深等的创建精确。
下面是创建FrameBuffer的方法:
1:创建framebuffer对象。
2:创建一个或多个对象 (renderbuffers or textures),对他们进行存储分配,将它们付着到framebuffer的付着点上去。
3:测试framebuffer的完整性。
下面是Sample Code
1:生成并绑定framebuffer
GLuint framebuffer; |
glGenFramebuffers(1, &framebuffer); |
glBindFramebuffer(GL_FRAMEBUFFER, framebuffer); |
GLuint colorRenderbuffer; |
glGenRenderbuffers(1, &colorRenderbuffer); |
glBindRenderbuffer(GL_RENDERBUFFER, colorRenderbuffer); |
glRenderbufferStorage(GL_RENDERBUFFER, GL_RGBA8, width, height); |
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, colorRenderbuffer); |
3:生成depthRenderbuffer,分配内存,付着到framebuffer上。
GLuint depthRenderbuffer; |
glGenRenderbuffers(1, &depthRenderbuffer); |
glBindRenderbuffer(GL_RENDERBUFFER, depthRenderbuffer); |
glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT16, width, height); |
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, depthRenderbuffer); |
4,检查framebuffer的完整性,在需要在frame属性被编辑后调用:
GLenum status = glCheckFramebufferStatus(GL_FRAMEBUFFER) ; |
if(status != GL_FRAMEBUFFER_COMPLETE) { |
NSLog(@"failed to make complete framebuffer object %x", status); |
} |
用framebuffer进行纹理渲染:
1:创建一个framebuffer对象。
2:创建目的纹理,并将其付着到framebuffer上。
// create the texture |
GLuint texture; |
glGenTextures(1, &texture); |
glBindTexture(GL_TEXTURE_2D, texture); |
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL); |
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture, 0); |
3:生成depthRenderbuffer,分配内存,付着到framebuffer上。(同上)
4:检查framebuffer的完整性。(同上)
CAEAGLLayer
作为它的底层。layerClass返回一个
CAEAGLLayer。
+ (Class) layerClass |
{ |
return [CAEAGLLayer class]; |
} |
3:在View 的初始化过程中,读取view的layer属性,代码如下:
myEAGLLayer = (CAEAGLLayer*)self.layer;
4:设置layer的属性。
为了最好的效果,设置opaque
= yes;使其不透明。
5:分配一个Context然后设置它为currentContext;
6:生成一个FrameBuffer(上面有详细叙述)
7:生成一个color renderbuffer,通过调用 Context的renderbufferStorage:fromDrawable:方法分配空间给他。下面是sampleCode:
GLuint colorRenderbuffer;
glGenRenderbuffers(1, &colorRenderbuffer);
glBindRenderbuffer(GL_RENDERBUFFER, colorRenderbuffer);
[myContext renderbufferStorage:GL_RENDERBUFFER fromDrawable:myEAGLLayer];
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, colorRenderbuffer);
注意:如果Layer的范围改变的时候,必须重新
reallocate renderbuffer,不然会和显示尺寸出现冲突。
8:读取的renderbuffer高度和宽度。
GLint width; |
GLint height; |
glGetRenderbufferParameteriv(GL_RENDERBUFFER, GL_RENDERBUFFER_WIDTH, &width); |
glGetRenderbufferParameteriv(GL_RENDERBUFFER, GL_RENDERBUFFER_HEIGHT, &height); |
9:生成和付着depth buffer;
10 :测试framebuffer。
绘制Framebuffer:
绘制FrameBuffer有两种方法:1:按需求绘制 2:在动画循环中绘制。
按需求绘制:适合不经常变化或者当用户有输入才进行相应的变化的状况。
注意:OpenGL ESview不应该使用DrawRect方法,而应该构造自己的方法去绘制。在数据变化,或者需要绘制的时候去调用自己的方法。
这样作的原因是为了防止UIKit在drwaRect的方法执行时被影响。
画循环中绘制:当你的数据很频繁的变化的话,请使用这种绘制方法。比如游戏,或者对动态效果要求很严格,需要有圆滑的动画的时候。
在iOS中,最好的方法是把你的绘制方法和CADisplayLink
对象设置在一起。这个对象可以使你的绘图频率和屏幕的刷新速率同期。下面使创建一个CADisplayLink的SampleCode:
displayLink = [myView.window.screen displayLinkWithTarget:self selector:@selector(drawFrame)]; |
[displayLink addToRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode]; |
在你的drawFrame方法中。请读取displaylink的timestamp属性。用来了解下次drawframe的时刻。用来计算你下次显示的数据。
在大多数情况下displaylink的启动频率大概使60Hz,根据硬件环境不同会有变化。但是动画不需要这么快的刷新频率(电影24Hz)。
你可以设置一个display link的 frameInterval
属性,来决定,屏幕每刷新几次进行一次描绘。加入frameInterval是3的话,大概就是20hz的绘制频率。