`
wsqwsq000
  • 浏览: 674773 次
  • 性别: Icon_minigender_1
  • 来自: 深圳
社区版块
存档分类
最新评论

OpenGL ES --FrameBuffer

 
阅读更多

 

 

OpenGL ES --FrameBuffer

 

FrameBuffer对象被用来存放渲染的结果,FrameBuffer可以使你对颜色,模型,色深等的创建精确。

下面是创建FrameBuffer的方法:

1:创建framebuffer对象。

2:创建一个或多个对象 (renderbuffers or textures),对他们进行存储分配,将它们付着到framebuffer的付着点上去。

3:测试framebuffer的完整性。

 

下面是Sample Code

 

生成一个OfferScreen Framebuffer对象

 

1:生成并绑定framebuffer

GLuint framebuffer;
glGenFramebuffers(1, &framebuffer);
glBindFramebuffer(GL_FRAMEBUFFER, framebuffer);
2:生成colorRenderbuffer,分配内存,付着到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的完整性。(同上)

 

 

渲染 Core Animation Layer:

在iOS里面都是由Core Animation Layer来作显示效果的,但是OpenGL ES没有直接使用CAEAGLLayer而是定义一个UIView的子类,UIView可以被CAEAGLLayer支持

下面是生成OpenGL ES的View步骤:
1:生成一个UIView的子类用来做OpenGL ES的View;
2:重写(override)layerClass方法,使得你的View使用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的绘制频率。

 

 

 

分享到:
评论
1 楼 wangyuchun_799 2011-11-17  
写的非常好,希望能继续更新啊,已经留下了你的文章。期待更新⋯⋯

相关推荐

Global site tag (gtag.js) - Google Analytics