unity glbindrenderbufferframebuffer 要包含什么库

【风宇冲】图形化调试
原创文章如需转载请注明:转载自
&&&&&&&&&&&&&&&&&&&&&&&
图形化调试&
图形化调试可以加速开发。
例如在战斗中,可能需要知道所有单位的仇恨值,如果这些信息全打log的话,很难有直观感受,
而如果在Scene窗口里,单位头顶有一个球,越红表示仇恨越高,越暗表示仇恨越低,那么调试起来比打log直观多了。
图形化调试】
Unity中图形化调试主要4种
Debug.Draw
Gizmos.Draw
Graphic.DrawMesh
只需在Scene窗口显示的调试图像
一直显示的 OnDrawGizmos +
Gizmos.Draw
选中显示的 OnDrawGizmosSelected +
Gizmos.Draw
脚本控制的 Update + Debug.Draw
需要在实际设备屏幕显示的调试图像
Update+Graphic.DrawMesh
OnRenderObject+GL
Graphic.DrawMesh和Debug.Draw&&
调用一致,都是在Update系里
Graphic.DrawMesh和GL&&&&&&
显示类似,都在各个窗口显示,并且可以设置材质。
四种方式比较
(1)Debug.Draw
=1=一般在Update/Fixed Update/LateUpdate里调用
=2=只在Scene窗口里显示
=3=并且不能设置材质
void&Update()
&&&&&&&&Debug.DrawLine&(worldPos1,&worldPos2,Color.yellow);
(2)Gizmos.Draw
=1=在OnDrawGizmos /OnDrawGizmosSelected里调用
=2=只在Scene窗口里显示
=3=并且不能设置材质
&&&&public&void&OnDrawGizmosSelected()&{
&&&&&&&&Gizmos.DrawLine(Vector3.zero,&new&Vector3(0,3f,0));
(3)Graphic.DrawMesh
=1=一般在Update/Fixed Update/LateUpdate里调用
=2=实际屏幕和Scene窗口都能显示
=3=可以设置材质
void&Update()
&&&&&&&&&&&&Graphics.DrawMesh(mesh,&worldPos,&worldRotation,&material,&0);
=1=一般在物体的OnRenderObject 或者相机的OnPostRender里调用
=2=实际屏幕和Scene窗口都能显示
=3=可以设置材质
一个GL.Begin/GL.End里的渲染是自动合并的,一般是一个Drawcall
画一些线,三角可以。用GL.TRIANGLES
显示整个Mesh的话会超卡。
例:渲染线框
void&OnRenderObject()
&&&&&&&&mat.SetPass(0);
GL.wireframe&=&true;
& GL.Color&(new&Color&(1,1,&0,&0.8F));
&&&&&&&&GL.PushMatrix();
&&&&&&&&GL.Begin(GL.TRIANGLES);
&&&&&&&&for(int&i=0;i&&/span&mesh.triangles.Length-2;i+=3)
&&&&&&&&&&&&GL.Vertex(mesh.vertices[mesh.triangles[i]]);
&&&&&&&&&&&&GL.Vertex(mesh.vertices[mesh.triangles[i+1]]);
&&&&&&&&&&&&GL.Vertex(mesh.vertices[mesh.triangles[i+2]]);
&&&&&&&&GL.End();
&&&&&&&&GL.PopMatrix();
&&&&&&&&&&&&&
GL.wireframe&=&false;
GL除了可以用来调试,可以拿来做功能,例如LineRenderer,地格等。
GL即Graphics Library。Low-Level Graphics
Library。计算matrices,发出类似OpenGL的immediate模式的渲染指令,和其他低级图像任务。Graphic.DrawMesh()比GL更高效。
GL立即绘制函数只用当前material的设置。因此除非你显示指定mat,否则mat可以是任何材质。并且GL可能会改变材质。
GL是立即执行的,如果你在Update()里调用,它们将在相机渲染前执行,相机渲染将会清空屏幕,GL效果将无法看到。
通常GL用法是
在camera上贴脚本,并在OnPostRender()里执行。
也可以挂在任何GameObject上,在OnRenderObject()里执行。
或者挂在物体上
1.GL的线等基本图元并没有uv.
所有是没有贴图纹理影射的,shader里仅仅做的是单色计算或者对之前的影像加以处理。
2.GL所使用的shader里必须有Cull off指令,否则显示会变成如下
3. 如果是线,颜色是GL.Color( new
Color(1,1,1,0.5f)
);设置的颜色
&如果是GL.TRIANGLES或者是GL.QUADS,则颜色是shader里的颜色。
GL.PushMatrix()
保存matrices至matrix stack上。
GL.PopMatrix()
从matrix stack上读取matrices。
GL.LoadPixelMatrix()
改变MVP矩阵,使得transform里的xy
直接对应像素,(0,0)表示屏幕viewport的左下角,z的范围是(-1,1),该函数改变camera的参数,所以需要GL.PushMatrix()保存和GL.PopMatrix()读取。
GL.Vertex3()的取值范围从左下角的(0,0,0)
至右上角的(Screen.width,Screen.height,0)
GL.LoadOrtho()
设置ortho perspective,即水平视角。After calling LoadOrtho, the viewing
frustum goes from (0,0,-1) to (1,1,100). 主要用于在纯2D里绘制图元。
GL.Vertex3()的取值范围从左下角的(0,0,0)
至右上角的(1,1,0)
OnPostRender()
只有物体上有激活的摄像机时,才会调用的函数,当摄像机完成渲染场景,绘制了所有物体以后调用。
OnPostRender可以变成co-routine,加yield语句即可。
WaitForEndOfFrame()
等待至 所有绘制之后,end of frame,
就在展示frame到屏幕之前。可以做截图。可以在任何物体上使用该函数。
例1:屏幕画线
using UnityE
using System.C
public class GLTest : MonoBehaviour
OnPostRender() {
&&if (!mat) {
&&Debug.LogError("Please
Assign a material on the inspector");
&&GL.PushMatrix();
//保存当前Matirx
&&mat.SetPass(0);
//刷新当前材质
&&GL.LoadPixelMatrix();//设置pixelMatrix
&&GL.Color(Color.yellow);
&&GL.Begin(GL.LINES);
&&GL.Vertex3(0,
&&GL.Vertex3(Screen.width,
Screen.height, 0);
&&GL.End();
&&GL.PopMatrix();//读取之前的Matrix
using System.IO;
using UnityE
using System.C
public class ScreenShot : MonoBehaviour
&&void Start()
&&StartCoroutine(UploadPNG()
&&IEnumerator UploadPNG() {
&&yield return new
WaitForEndOfFrame();
print ("yuuuuu");
&&int width =
&&int height =
&&Texture2D tex =
new Texture2D(width, height,
TextureFormat.RGB24, false);
&&tex.ReadPixels(new
Rect(0, 0, width, height),
&&tex.Apply();
&&byte[] bytes =
tex.EncodeToPNG();
File.WriteAllBytes(Application.dataPath+"/ss.png",bytes);
UnityEditor.AssetDatabase.Refresh();
例3:展示Alpha
using UnityE
using System.C
public class GLTest : MonoBehaviour
public Shader
public Texture2D t2d;
void Start()
mat = new Material(shader);
mat.mainTexture = t2d;
OnPostRender() {
&&if (!mat) {
&&Debug.LogError("Please
Assign a material on the inspector");
&&GL.PushMatrix();
&&mat.SetPass(0);
& GL.LoadOrtho();
& GL.Begin(GL.QUADS);
&&GL.Vertex3(0,
&&GL.Vertex3(1f,
&&GL.Vertex3(1f,
&&GL.Vertex3(0,
&&GL.End();
&&GL.PopMatrix();
Shader "Custom/GLDrawLine" {
Properties {
_MainTex ("Base (RGB)", 2D) =
"white" {}
SubShader {
Blend DstAlpha zero
Color(1,1,1,1)
已投稿到:
以上网友发言只代表其个人观点,不代表新浪网的观点或立场。OpenGL(九)使用 FrameBufferObject-GAD腾讯游戏开发者平台在Android上,Unity3d底层是调用opengl es库吗? - 知乎2被浏览98分享邀请回答还没有回答OpenGLES3.0之Fragmentbufferobjects(FBO)详解(一)_iOS开发_动态网站制作指南
OpenGLES3.0之Fragmentbufferobjects(FBO)详解(一)
来源:人气:688
   片段操作图
  这篇文章将介绍从写入帧缓冲和读取帧缓冲的方式。
  Buffers(缓冲)
  OpenGL ES支持三种缓冲:
  OpenGL ES
  && Color buffer颜色缓冲
  && Depth buffer深度缓冲
  && Stencil buffer缓冲
  创建缓冲区
  OpenGL ES 是一个交互式的渲染系统,假设每帧的开始,你希望初始化所有缓冲区中数据的默认值。调用glClear 函数来清除缓冲区内容,参数mask 指定清除的缓冲区。
你可能不要求清除每一个缓冲区,不在同时清除它们。但如果你想同时清除所有的缓冲区,只调用一次glClear 可以获得更好的性能。
 如果你的帧缓冲区中有多个绘制缓冲,你也可以清除指定的缓冲区,如下:
  为减少调用函数的次数,你可以同时清除深度和模板缓冲区内容,如下:
  使用掩码来控制写入缓冲区
  一般你可以控制对缓冲区的操作,哪部分可以写,哪部分不可写。在颜色缓冲区中,glColorMask 指定颜色缓冲区的组成里那部分可被更新。如果mask 被设为GL_FALSE,这个组成部分不能更新,默认值是GL_TRUE。对于深度同样
  读取和写入像素到帧缓冲区
  多渲染目标MRTs
  MRTs允许应用程序同时渲染多个颜色缓冲区。下面是流程
  1.创建帧缓冲对象framebuffer objects,使用
  glGenFramebuffers ( 1, &fbo );创建帧缓冲对象  glBindFramebuffer ( GL_FRAMEBUFFER, fbo );绑定为当前使用的帧缓冲对象。
  2.创建纹理对象
  glGenTextures(4,textureId);创建
  glBindTexture ( GL_TEXTURE_2D, textureId );绑定  glTexImage2D ( GL_TEXTURE_2D, 0, GL_RGBA,          textureWidth, textureHeight,  0, GL_RGBA, GL_UNSIGNED_BYTE, NULL );  // Set the filtering mode  glTexParameteri ( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER,  GL_NEAREST );  glTexParameteri ( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER,GL_NEAREST );
  3.帧缓冲对象绑定相关的纹理。
  glFramebufferTexture2D ( GL_DRAW_FRAMEBUFFER,               GL_COLOR_ATTACHMENT0,               GL_TEXTURE_2D,               textureId, 0 );
&  4.指定渲染的附加颜色
  glDrawBuffers(GLsizei n, const GLenum* bufs)
例如你可以使用4种颜色输出建立一个FBO对象
const GLenum attachments[4] = { GL_COLOR_ATTACHMENT0,
GL_COLOR_ATTACHMENT1,
GL_COLOR_ATTACHMENT2,
GL_COLOR_ATTACHMENT3
glDrawBuffers ( 4, attachments );
通过GL_MAX_COLOR_ATTACHMENTS你可以查询支持最多的颜色数,支持最小的数目是4.
  5.声明和使用着色器的输出
layout(location = 0) out vec4 fragData0;
layout(location = 1) out vec4 fragData1;
layout(location = 2) out vec4 fragData2;
layout(location = 3) out vec4 fragData3;
int InitFBO ( ESContext *esContext )
UserData *userData = esContext-&userD
GLint defaultFramebuffer = 0;
const GLenum attachments[4] =
GL_COLOR_ATTACHMENT0,
GL_COLOR_ATTACHMENT1,
GL_COLOR_ATTACHMENT2,
GL_COLOR_ATTACHMENT3
glGetIntegerv ( GL_FRAMEBUFFER_BINDING, &defaultFramebuffer );
// Setup fbo
glGenFramebuffers ( 1, &userData-&fbo );
glBindFramebuffer ( GL_FRAMEBUFFER, userData-&fbo );
// Setup four output buffers and attach to fbo
userData-&textureHeight = userData-&textureWidth = 400;
glGenTextures ( 4, &userData-&colorTexId[0] );
for (i = 0; i & 4; ++i)
glBindTexture ( GL_TEXTURE_2D, userData-&colorTexId[i] );
glTexImage2D ( GL_TEXTURE_2D, 0, GL_RGBA,
userData-&textureWidth, userData-&textureHeight,
0, GL_RGBA, GL_UNSIGNED_BYTE, NULL );
// Set the filtering mode
glTexParameteri ( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST );
glTexParameteri ( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST );
glFramebufferTexture2D ( GL_DRAW_FRAMEBUFFER, attachments[i],
GL_TEXTURE_2D, userData-&colorTexId[i], 0 );
glDrawBuffers ( 4, attachments );
if ( GL_FRAMEBUFFER_COMPLETE != glCheckFramebufferStatus ( GL_FRAMEBUFFER ) )
return FALSE;
// Restore the original framebuffer
glBindFramebuffer ( GL_FRAMEBUFFER, defaultFramebuffer );
return TRUE;
#version 300 es
ecision mediump float;
layout(location = 0) out vec4 fragData0;
layout(location = 1) out vec4 fragData1;
layout(location = 2) out vec4 fragData2;
layout(location = 3) out vec4 fragData3;
void main()
// first buffer will contain red color
fragData0 = vec4 ( 1, 0, 0, 1 );
// second buffer will contain green color
fragData1 = vec4 ( 0, 1, 0, 1 );
// third buffer will contain blue color
fragData2 = vec4 ( 0, 0, 1, 1 );
// fourth buffer will contain gray color
fragData3 = vec4 ( 0.5, 0.5, 0.5, 1 );
优质网站模板15237人阅读
计算机图形学(28)
但有改动。
OpenGL Frame BufferObject(FBO)
& & & &在OpenGL渲染管线中,几何数据和纹理经过多次转化和多次测试,最后以二维像素的形式显示在屏幕上。OpenGL管线的最终渲染目的地被称作帧缓存(framebuffer)。帧缓冲是一些二维数组和OpenG所使用的存储区的集合:颜色缓存、深度缓存、模板缓存和累计缓存。默认情况下,OpenGL将帧缓冲区作为渲染最终目的地。此帧缓冲区完全由window系统生成和管理。这个默认的帧缓存被称作“window系统生成”(window-system-provided)的帧缓冲区。
& & & &在OpenGL扩展中,GL_ARB_framebuffer_object提供了一种创建额外的非显示的帧缓冲区对象的接口。此种帧缓冲区被称为&由程序创建的帧缓冲区(application-created
framebuffer)&。这是为了区分window系统默认创建的帧缓冲区对象。通过使用帧缓存对象(FBO),OpenGL可以将显示输出重定向到程序帧缓存对象,而不是传统的“window系统生成”帧缓存。而且,它完全受OpenGL控制。
相似于window系统提供的帧缓存,一个FBO也包含一些存储颜色、深度和模板数据的区域。(注意:没有累积缓存)我们把FBO中这些逻辑缓存称之为“帧缓存关联图像”,它们是一些能够和一个帧缓存对象关联起来的二维像素数组。
有两种类型的“帧缓存关联图像”:纹理图像(texture
images)和渲染缓存图像(renderbuffer images)。如果纹理对象的图像数据关联到帧缓存,OpenGL执行的是“渲染到纹理”(render to texture)操作。如果渲染缓存的图像数据关联到帧缓存,OpenGL执行的是离线渲染(offscreen rendering)。
& & & &这里要提到的是,渲染缓存对象是在GL_ARB_framebuffer_object&扩展中定义的一种新的存储类型。在渲染过程中它被用作存储单幅二维图像。下面这幅图显示了帧缓存对象、纹理对象和渲染缓存对象之间的联系。多多个纹理对象或者渲染缓存对象能够通过关联点关联到一个帧缓存对象上。
& & & 下面这幅图显示了帧缓冲区对象与纹理对象、渲染缓冲区对象的关系。多个纹理对象或多个渲染缓冲区对象,可通过连接点(attachment points)连接到帧缓冲区对象上。
& & & & 在一个帧缓存对象中有多个颜色关联点(GL_COLOR_ATTACHMENT0_EXT,...,GL_COLOR_ATTACHMENTn_EXT),一个深度关联点(GL_DEPTH_ATTACHMENT_EXT),和一个模板关联点(GL_STENCIL_ATTACHMENT_EXT)。每个FBO中至少有一个颜色关联点,其数目与实体显卡相关。可以通过GL_MAX_COLOR_ATTACHMENTS_EXT来查询颜色关联点的最大数目。FBO有多个颜色关联点的原因是可以将颜色对象同时渲染到多个目标上。这种“多渲染目标”(multiple
rendertargets,MRT)可以通过GL_ARB_draw_buffers扩展实现。需要注意的是:FBO本身并没有任何图像存储区,只有多个关联点。
& & &帧缓冲区对象提供了高效的切换机制:从帧缓冲区对象中断开先前的帧缓冲区关联图像,连接一个新的帧缓冲区关联图像到帧缓冲区对象上。切换帧缓冲区关联图像比切换帧缓冲区对象快多了。帧缓冲区对象提供了glFramebufferTexture2D()来切换2D纹理对象,glFramebufferRenderbuffer()来切换渲染缓冲区对象。
创建FBO和产生VBO类似。
glGenFramebuffers()
void glGenFramebuffers(GLsizei n, GLuint* ids)
void glDeleteFramebuffers(GLsizei n, const GLuint* ids)
glGenFramebuffers()需要两个参数:第一个是要创建的帧缓存的数目,第二个是指向存储一个或者多个ID的变量或数组的指针。它返回未使用的FBO的ID。ID为0表示默认帧缓存,即window系统提供的帧缓存。
当FBO不再被使用时,FBO可以通过调用glDeleteFramebuffers()来删除。
glBindFramebuffer()
一旦一个FBO被创建,在使用它之前必须绑定。
void glBindFramebuffer(GLenum target, GLuint id)
第一个参数target应该是GL_FRAMEBUFFER,第二个参数是FBO的ID号。一旦FBO被绑定,之后的所有的OpenGL操作都会对当前所绑定的FBO造成影响。ID号为0表示缺省帧缓存,即默认的window提供的帧缓存。因此,在glBindFramebuffer()中将ID号设置为0可以解绑定当前FBO。
渲染缓存对象(Renderbuffer Object)
另外,渲染缓存是为离线渲染而新引进的。它允许将一个场景直接渲染到一个渲染缓存对象中,而不是渲染到纹理对象中。渲染缓存对象是用于存储单幅图像的数据存储区域。该图像按照一种可渲染的内部格式存储。它用于存储没有相关纹理格式的OpenGL逻辑缓存,比如模板缓存或者深度缓存。
glGenRenderbuffers()
void glGenRenderbuffers(GLsizei n, GLuint* ids)
void glDeleteRenderbuffers(GLsizei n, const Gluint* ids)
一旦一个渲染缓存被创建,它返回一个非零的正整数。ID为0是OpenGL保留值。
glBindRenderbuffer()
void glBindRenderbuffer(GLenum target, GLuint id)
和OpenGL中其他对象一样,在引用渲染缓存之前必须绑定当前渲染缓存对象。他target参数应该是GL_RENDERBUFFER。
glRenderbufferStorage()
void glRenderbufferStorage(GLenum target, GLenum internalFormat,
&&&&&&&&&&&&&&&&&&&&&&&&&&&&&GLsizei width, GLsizei height)
当一个渲染缓存被创建,它没有任何数据存储区域,所以我们还要为他分配空间。这可以通过用glRenderbufferStorage()实现。第一个参数必须是GL_RENDERBUFFER。第二个参数可以是用于颜色的(GL_RGB,GL_RGBA,etc.),用于深度的(GL_DEPTH_COMPONENT),或者是用于模板的格式(GL_STENCIL_INDEX)。Width和height是渲染缓存图像的像素维度。
width和height必须比GL_MAX_RENDERBUFFER_SIZE_EXT小,否则将会产生GL_UNVALID_VALUE错误。
glGetRenderbufferParameteriv()
void glGetRenderbufferParameteriv(GLenum target, GLenum param,GLint* value);
我们也可以得到当前绑定的渲染缓存对象的一些参数。Target应该是GL_RENDERBUFFER,第二个参数是所要得到的参数名字。最后一个是指向存储返回值的整型量的指针。渲染缓存的变量名有如下:
GL_RENDERBUFFER_WIDTH
GL_RENDERBUFFER_HEIGHT
GL_RENDERBUFFER_INTERNAL_FORMAT
GL_RENDERBUFFER_RED_SIZE
GL_RENDERBUFFER_GREEN_SIZE
GL_RENDERBUFFER_BLUE_SIZE
GL_RENDERBUFFER_ALPHA_SIZE
GL_RENDERBUFFER_DEPTH_SIZE
GL_RENDERBUFFER_STENCIL_SIZE
将图像和FBO关联
FBO本身没有图像存储区。我们必须帧缓存关联图像(纹理或渲染对象)关联到FBO。这种机制允许FBO快速地切换(分离和关联)帧缓存关联图像。切换帧缓存关联图像比在FBO之间切换要快得多。而且,它节省了不必要的数据拷贝和内存消耗。比如,一个纹理可以被关联到多个FBO上,图像存储区可以被多个FBO共享。
把2D纹理图像关联到FBO
glFramebufferTexture2D(GLenum target,
&&&&&&&&&&&&&&&&&&&&&&&&& GLenumattachmentPoint,
&&&&&&&&&&&&&&&&&&&&&&&&&GLenum textureTarget,
&&&&&&&&&&&&&&&&&&&&&&&&&GLuint textureId,
&&&&&&&&&&&&&&&&&&&&&&&&&GLint& level)
glFramebufferTexture2D()把一幅纹理图像关联到一个FBO。第一个参数一定是GL_FRAMEBUFFER_,第二个参数是关联纹理图像的关联点。一个帧缓冲区对象可以有多个颜色关联点(GL_COLOR_ATTACHMENT0, ..., GL_COLOR_ATTACHMENTn),L_DEPTH_ATTACHMENT, 和GL_STENCIL_ATTACHMENT。第三个参数textureTarget在多数情况下是GL_TEXTURE_2D。第四个参数是纹理对象的ID号。最后一个参数是要被关联的纹理的mipmap等级
如果参数textureId被设置为0,那么纹理图像将会被从FBO分离。如果纹理对象在依然关联在FBO上时被删除,那么纹理对象将会自动从当前帮的FBO上分离。然而,如果它被关联到多个FBO上然后被删除,那么它将只被从绑定的FBO上分离,而不会被从其他非绑定的FBO上分离。
把渲染缓存对象关联到FBO
void glFramebufferRenderbuffer(GLenum target,
&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&GLenum attachmentPoint,
&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&GLenum renderbufferTarget,
&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&GLuint renderbufferId)
通过调用glFramebufferRenderbuffer()可以关联渲染缓存图像。前两个参数和glFramebufferTexture2D()一样。第三个参数只能是GL_RENDERBUFFER,最后一个参数是渲染缓存对象的ID号。
如果参数renderbufferId被设置为0,渲染缓存图像将会从FBO的关联点分离。如果渲染缓存图像在依然关联在FBO上时被删除,那么纹理对象将会自动从当前绑定的FBO上分离,而不会从其他非绑定的FBO上分离。
检查FBO状态
一旦关联图像(纹理和渲染缓存)被关联到FBO上,在执行FBO的操作之前,你必须检查FBO的状态:完整或不完整。这可以通过调用glCheckFramebufferStatusEXT()来检查其状态。如果帧缓冲区状态是不完整的,那么任何绘制命令(glBegin(),glCopyTexImage2D()等等)都会失败。
GLenum glCheckFramebufferStatus(GLenum target)
glCheckFramebufferStatus()检查当前帧缓存的关联图像和帧缓存参数。这个函数不能在glBegin()/glEnd()之间调用。Target参数必须为GL_FRAMEBUFFER。它返回一个非零值。如果所有要求和准则都满足,它返回GL_FRAMEBUFFER_COMPLETE。否则,返回一个相关错误代码告诉我们哪条准则没有满足。
FBO完整性准则有:
(1)帧缓存关联图像的宽度和高度必须非零。
(2)如果一幅图像被关联到一个颜色关联点,那么这幅图像必须有颜色可渲染的内部格式(GL_RGBA, GL_DEPTH_COMPONENT, GL_LUMINANCE, etc)。
(3)如果一幅被图像关联到GL_DEPTH_ATTACHMENT,那么这幅图像必须有深度可渲染的内部格式(GL_DEPTH_COMPONENT,GL_DEPTH_COMPONENT24, etc)。
(4)如果一幅被图像关联到GL_STENCIL_ATTACHMENT,那么这幅图像必须有模板可渲染的内部格式(GL_STENCIL_INDEX,GL_STENCIL_INDEX8, etc)。
(5)FBO至少有一幅图像关联。
(6)被关联到FBO的缩影图像必须有相同的宽度和高度。
(7)被关联到颜色关联点上的所有图像必须有相同的内部格式。
注意:即使以上所有条件都满足,你的OpenGL驱动也可能不支持某些格式和参数的组合。如果一种特别的实现不被OpenGL驱动支持,那么glCheckFramebufferStatus()返回GL_FRAMEBUFFER_UNSUPPORTED。
示例:渲染到纹理
只渲染到深度缓冲区中。
使用模板渲染对象外轮廓
有时候,你需要产生动态纹理。比较常见的例子是产生镜面反射效果、动态环境贴图和阴影等效果。动态纹理可以通过把场景渲染到纹理来实现。渲染到纹理的一种传统方式是将场景绘制到普通的帧缓存上,然后调用glCopyTexSubImage2D()拷贝帧缓存图像至纹理。
使用FBO,我们能够将场景直接渲染到纹理,所以我们不必使用window系统提供的帧缓存。并且,我们能够去除额外的数据拷贝(从帧缓存到纹理);。
这个demo实现了使用FBO和不使用FBO两种情况下渲染到纹理的操作,并且比较了性能差异。除了能够获得性能上的提升,使用FBO的还有另外一个优点。在传统的渲染到纹理的模式中(不使用FBO),如果纹理分辨率比渲染窗口的尺寸大,超出窗口区域的部分将被剪切掉。然后,使用FBO就不会有这个问题。你可以产生比显示窗口大的帧缓存渲染图像。
以下代码在渲染循环开始之前,对FBO和帧缓存关联图像进行了初始化。注意只有一幅纹理图像被关联到FBO,但是,一个深度渲染图像被关联到FBO的深度关联点。实际上我们并没有使用这个深度缓存,但是FBO本身需要它进行深度测试。如果我们不把这个深度可渲染的图像关联到FBO,那么由于缺少深度测试渲染输出结果是不正确的。如果在FBO渲染期间模板测试也是必要的,那么也需要把额外的渲染图像和GL_STENCIL_ATTACHMENT_EXT关联起来。
// create a texture object
GLuint textureId;
glGenTextures(1, &textureId);
glBindTexture(GL_TEXTURE_2D, textureId);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_GENERATE_MIPMAP, GL_TRUE); // automatic mipmap
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, TEXTURE_WIDTH, TEXTURE_HEIGHT, 0,
GL_RGBA, GL_UNSIGNED_BYTE, 0);
glBindTexture(GL_TEXTURE_2D, 0);
// create a renderbuffer object to store depth info
GLuint rboId;
glGenRenderbuffersEXT(1, &rboId);
glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, rboId);
glRenderbufferStorageEXT(GL_RENDERBUFFER_EXT, GL_DEPTH_COMPONENT,
TEXTURE_WIDTH, TEXTURE_HEIGHT);
glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, 0);
// create a framebuffer object
GLuint fboId;
glGenFramebuffersEXT(1, &fboId);
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, fboId);
// attach the texture to FBO color attachment point
glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT,
GL_TEXTURE_2D, textureId, 0);
// attach the renderbuffer to depth attachment point
glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT,
GL_RENDERBUFFER_EXT, rboId);
// check FBO status
GLenum status = glCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT);
if(status != GL_FRAMEBUFFER_COMPLETE_EXT)
// switch back to window-system-provided framebuffer
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
渲染到纹理的过程和普通的绘制过程基本一样。我们只需要把渲染的目的地由window系统提供的帧缓存改成不可显示的应用程序创建的帧缓存(FBO)就可以了。
// set rendering destination to FBO
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, fboId);
// clear buffers
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
// draw a scene to a texture directly
// unbind FBO
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
// trigger mipmaps generation explicitly
// NOTE: If GL_GENERATE_MIPMAP is set to GL_TRUE, then glCopyTexSubImage2D()
// triggers mipmap generation automatically. However, the texture attached
// onto a FBO should generate mipmaps manually via glGenerateMipmapEXT().
glBindTexture(GL_TEXTURE_2D, textureId);
glGenerateMipmapEXT(GL_TEXTURE_2D);
glBindTexture(GL_TEXTURE_2D, 0);
...注意到,glGenerateMipmapEXT()也是作为FBO扩展的一部分,用来在改变了纹理图像的基级之后显式生成mipmap的。如果GL_GENERATE_MIPMAP被设置为GL_TRUE,那么glTex{Sub}Image2D()和 glCopyTex{Sub}Image2D()将会启用自动mipmap生成(在OpenGL版本1.4或者更高版本中)。然后,当纹理基级被改变时,FBO操作不会自动产生mipmaps。因为FBO不会调用glCopyTex{Sub}Image2D()来修改纹理。因此,要产生mipmap,glGenerateMipmapEXT()必须被显示调用。
&&相关文章推荐
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
访问:401730次
积分:5325
积分:5325
排名:第5321名
原创:154篇
转载:25篇
评论:48条
(4)(3)(4)(2)(1)(1)(2)(3)(4)(1)(1)(2)(1)(1)(4)(8)(1)(1)(2)(1)(1)(3)(8)(6)(1)(6)(2)(2)(18)(1)(2)(1)(3)(9)(4)(16)(4)(1)(1)(4)(1)(1)(1)(9)(31)(1)(2)(1)
(window.slotbydup = window.slotbydup || []).push({
id: '4740881',
container: s,
size: '200,200',
display: 'inlay-fix'}

我要回帖

更多关于 glbindrenderbuffer 的文章

更多推荐

版权声明:文章内容来源于网络,版权归原作者所有,如有侵权请点击这里与我们联系,我们将及时删除。

点击添加站长微信