第二人生的源码分析(五十七)OpenGL离屏渲染的相关函数

来源:互联网 发布:淘宝卖单肩包的好店 编辑:程序博客网 时间:2024/06/04 00:36

前面介绍了类LLRenderTarget的声明,并且大体地说明了每个函数的作用,但没有仔细地看到它是怎么样实现的,现在就来分析具体的实现细节。它的实现代码如下:

#001  BOOL LLRenderTarget::sUseFBO = FALSE;

#002 

 

下面是构造函数初始化成员变量。

#003  LLRenderTarget::LLRenderTarget()

#004  {

#005       mResX = mResY = mTex = mFBO = mDepth = 0;

#006       mUseDepth = FALSE;

#007       mUsage = GL_TEXTURE_2D;

#008  }

#009 

 

下面是析构函数释放资源。

#010  LLRenderTarget::~LLRenderTarget()

#011  {

#012       release();

#013  }

#014 

 

 

#015  void LLRenderTarget::allocate(U32 resx, U32 resy, U32 color_fmt, BOOL depth, U32 usage, BOOL force_fbo)

#016  {

 

分配区域的大小。

#017       mResX = resx;

#018       mResY = resy;

#019 

 

使用离屏对象。

#020       mUsage = usage;

 

使用深度对象。

#021       mUseDepth = depth;

 

释放以前分配的资源。

#022       release();

#023 

 

生成纹理。

#024       glGenTextures(1, (GLuint *) &mTex);

 

绑定纹理。

#025       glBindTexture(mUsage, mTex);

 

创建2D纹理。

#026       glTexImage2D(mUsage, 0, color_fmt, mResX, mResY, 0, color_fmt, GL_UNSIGNED_BYTE, NULL);

#027 

 

设置纹理大小缩放的采样方式。

#028       glTexParameteri(mUsage, GL_TEXTURE_MAG_FILTER, GL_LINEAR);

#029       glTexParameteri(mUsage, GL_TEXTURE_MIN_FILTER, GL_LINEAR);

#030 

 

设置纹理环绕。

#031       if (mUsage != GL_TEXTURE_RECTANGLE_ARB)

#032       {

#033              glTexParameteri(mUsage, GL_TEXTURE_WRAP_S, GL_MIRRORED_REPEAT);

#034              glTexParameteri(mUsage, GL_TEXTURE_WRAP_T, GL_MIRRORED_REPEAT);

#035       }

#036       else

#037       {

#038              // ATI doesn't support mirrored repeat for rectangular textures.

#039              glTexParameteri(mUsage, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);

#040              glTexParameteri(mUsage, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);

#041       }

#042 

#043       stop_glerror();

#044 

 

判断是否使用FBO对象。

#045       if (sUseFBO || force_fbo)

#046       {

 

生成深度离屏对象。

#047              if (depth)

#048              {

#049                     glGenRenderbuffersEXT(1, (GLuint *) &mDepth);

#050                     glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, mDepth);

#051                glRenderbufferStorageEXT(GL_RENDERBUFFER_EXT,GL_DEPTH_COMPONENT,mResX,mResY);

#052                     glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, 0);  

#053              }

#054 

 

生成一般的离屏对象mFBO

#055              glGenFramebuffersEXT(1, (GLuint *) &mFBO);

#056              glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, mFBO);

#057 

#058              if (mDepth)

#059              {

#060                     glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT,

#061                                                                            

#062  GL_RENDERBUFFER_EXT, mDepth);

#063              }

 

添加纹理对象。

#064              glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT,

#065                                          mUsage, mTex, 0);

#066 

#067 

#068              glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);

#069       }

#070  }

#071 

#072  void LLRenderTarget::release()

#073  {

#074       if (mFBO)

#075       {

 

删除离屏对象。

#076              glDeleteFramebuffersEXT(1, (GLuint *) &mFBO);

#077              mFBO = 0;

#078       }

#079 

#080       if (mTex)

#081       {

 

删除离屏纹理对象。

#082              glDeleteTextures(1, (GLuint *) &mTex);

#083              mTex = 0;

#084       }

#085 

#086       if (mDepth)

#087       {

 

删除深度离屏对象。

#088              glDeleteRenderbuffersEXT(1, (GLuint *) &mDepth);

#089              mDepth = 0;

#090       }

#091  }

#092 

#093  void LLRenderTarget::bindTarget()

#094  {

#095       if (mFBO)

#096       {

 

绑定离屏对象。

#097              glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, mFBO);

#098       }

#099 

 

设置视口的大小。

#100       glViewport(0, 0, mResX, mResY);

#101  }

#102 

#103  void LLRenderTarget::clear()

#104  {

#105       U32 mask = GL_COLOR_BUFFER_BIT;

#106       if (mUseDepth)

#107       {

#108              mask |= GL_DEPTH_BUFFER_BIT;

#109       }

 

清除离屏对象。

#110       if (mFBO)

#111       {

#112              glClear(mask);

#113       }

#114       else

#115       {

#116              LLGLEnable scissor(GL_SCISSOR_TEST);

#117              glScissor(0, 0, mResX, mResY);

#118              glClear(mask);

#119       }

#120  }

#121 

#122  void LLRenderTarget::bindTexture()

#123  {

#124       glBindTexture(mUsage, mTex);

#125  }

#126 

#127  void LLRenderTarget::flush()

#128  {

 

调用OPENGL函数显示。

#129       gGL.flush();

#130       if (!mFBO)

#131       {

#132              bindTexture();

#133              glCopyTexSubImage2D(mUsage, 0, 0, 0, 0, 0, mResX, mResY);

#134       }

#135  }

#136 

#137  BOOL LLRenderTarget::isComplete() const

#138  {

#139       return (mTex || mDepth) ? TRUE : FALSE;

#140  }

#141 

#142  void LLRenderTarget::getViewport(S32* viewport)

#143  {

#144       viewport[0] = 0;

#145       viewport[1] = 0;

#146       viewport[2] = mResX;

#147       viewport[3] = mResY;

#148  }

#149 

 

使用glGenFramebuffersEXT函数来创建离屏对象,glDeleteFramebuffersEXT函数来删除对象,使用glBindFramebufferEXT绑定当前使用的FrameBuffer对象。使用glFramebufferTexture2DEXT函数来指定纹理。使用函数glRenderbufferStorageEXT来指定离屏的大小。这些函数都是OPENGL比较新的API扩展,因此使用这些功能就需要检查OPENGL是否支持这些功能,才能使用它,否则会出错的。