8.1.4 缓冲区对象
一个纹理包含两个主要组成部分:纹理采样状态和包含纹理值得数据缓冲区。
纹理缓冲区也称为texBO 或 TBO。
纹理缓冲区能够直接填充来自其他渲染结果(例如变换反馈、像素读取操作或顶点数据)的数据。这样就节省了不少时间,因为应用程序能够直接从着色器一起的渲染调用中获取像素数据。这是为什么进行另外的我哪里绑定-------可以将一个缓冲区对象绑定到GL_TEXTURE_BUFFER缓冲区中一个纹理的绑定点。
texBO的另一个特性是宽松的大小限制。OpenGL规定纹理缓冲区的大小的最大值比1D纹理大64倍,但是在某些实现中纹理缓冲区的大小可能要大几万倍!
textBO 能够用来提供对片段着色器和顶点着色器中得顶点数组的访问。这在着色器需要关于临近几何图形的信息以作出运行时决策和计算的情况下可能非常有用。但是为了做到这一点,我们常常需要就爱那个texBO大小作为一个统一值传递到着色器中。
//绑定缓冲区,当纹理缓冲区被绑定到一个纹理或者GL_TEXTURE_BUFFER绑定点时会成为真正的纹理缓冲区
glBindBuffer(GL_TEXTURE_BUFFER,texBO[0]);
//填充缓冲区
glBufferData(GL_TEXTURE_BUFFER,sizeof(float)*count,fileData,GL_STATIC_DRAW);
glActiveTexture(GL_TEXTURE1);
glBindTexture(GL_TEXTURE_BUFFER,texBOTexture);
//texBO必须绑定到一个纹理单元上才能真正变得有用。要将一个texBO绑定到一个纹理上,如下。但首先要如上两行代码确保使用的纹理已经进行了绑定。
glTexBuffer(GL_TEXTURE_BUFFER,GL_R32F,texBO[0]);
纹理缓冲区不能在着色器中用普通采样器--------也就是sample1D和sample2D进行访问。取而代之的时,我们必须使用采样器sampleBuffer。获取采样的函数也不相同,使用
texelFetch从纹理缓冲区进行读取。
uniform sampleBuffer lumCurveSample;
void main(void){
......
诸如texture这样的传统采样函数接受的坐标范围为从0.0 到 1.0,但是texBO查询函数texelFetch则接受一个从0到缓冲区大小值得整数索引。如果纹理查询坐标已经进行了标准化,那么我们可以通过乘以texBO的大小值减去1的结果。然后将结果转化为整数的方式转换成索引。如下面的offset
int offset = int(vColor.r * (1024 -1));
lumFactor.r = texelFetch(lumCurveSampler,offset).r
}
------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
</pre><p></p><p></p><pre name="code" class="cpp">将帧缓冲区到一个对象所需要的状态进行了封装,叫做帧缓冲区对象(FBO)
可以创建多个帧缓冲区,也叫做FBO,并且直接渲染一个FBO,而不是窗口。使用这种离屏渲染,应用程序可以指向许多不同类型的渲染算法了,例如阴影贴图,应用辐射着色(radiosity)、反射、后期处理和许多特效。
帧缓冲区不受窗口大小的限制,他可以包含颜色缓冲区。
甚至可以将纹理绑定到一个FBO上,这就意味着可以直接渲染到一个纹理中。
帧缓冲区对象是一种容器,不存在与一个帧缓冲区对象相关联的的真正内存存储空间,可以保持其他确实有内存存储并且可以进行渲染的对象,比如纹理和渲染缓冲区。
采用这种方式,帧缓冲区对象保存OpenGL管线输出时将 需要的状态和表面 绑定 在一起。
----------使用FBO
// 创建FBO
GLuint fboname;
glGenFramebuffer(1,&fboname);
//绑定FBO
glBinaFrameBuffer(GL_DRAW_FRAMEBUFFER,fbnameme);
//销毁FBO
glDeleteFramebuffers(1,&fboname);
glBinaFrameBuffer(GL_DRAW_FRAMEBUFFER,0); ????????????
使用一个帧缓冲区进行读取,而使用另一个缓冲区进行绘制
解除绑定,并再次绑定到默认的FBO。一旦默认FBO被绑定,那么读取和写入就都再次绑定到了窗口的帧缓冲区。
----------渲染缓冲区对象
RBO 渲染缓冲区对象,专门为绑定到FBO设计的。
一个渲染缓冲区对象可以是颜色表面、模板表面或者深度/模板组合表面
【我的理解颜色缓冲区,深度缓冲区等等]】
创建和绑定RBO
glGenRenderBuffers(3,renderBufferNames);
glBindRenderBuffer(GL_RENDERBUFFER,renderBufferNames[0]);
RBO创建时没有初始存储的,就没有任何东西可以渲染
glBindRenderBuffer(GL_RENDERBUFFER,renderBufferNames[0]);
glRenderbufferStorage(GL_RENDERBUFFER,GL_RGB8,screenWidth,screenHeight);
glBindRenderBuffer(GL_RENDERBUFFER,depthBufferNames[0]);
glRenderbufferStorage(GL_RENDERBUFFER,GL_DEPTH_COMPONENT32,screenWidth,screenHeight);
前面的示例,渲染大小只要不超过这个最大值即可
(glGetIntegerv来查询OpenGL所支持的最大维度,宽度和高度都必须小于这个最大值。)
还可以glRenderbufferStorageMultiSample来创建多重采样的渲染缓冲区存储,这个函数接受附加的采样变量。这样可以在任何像素显示在屏幕之前进行离屏多重采样。
绑定RBO
试图绑定RBO之前,确保FBO已经被绑定
glBindFramebuffer(GL_DRAW_FRAMEBUFFER,fboname);
//一个帧缓冲区有多个绑定点可以绑定:一个深度绑定点、一个模板绑定点,以及多个颜色绑定点(可以使用glGetIntegerv查询GL_MAX_COLOR_ATTACHMENTS,来查出一次可以绑定多少颜色缓冲区。)
glFramebufferRenderBuffer(GL_DRAW_FRAMEBUFFER,GL_DEPTH_ATTACHMENT,GL_RENDERBUFFER,depthBufferName);
glFramebufferRenderBuffer(GL_DRAW_FRAMEBUFFER,GL_COLOR_ATTACHMENT0,GL_RENDERBUFFER,depthBufferNames[0]);
要获得对渲染缓冲区的访问,有两个重要步骤。
第一步是确保片段着色器设置正确,(着色器输出)
第二步确保输出被引导到正确地位置 (缓冲区映射)