`
yuanjinxiu
  • 浏览: 660236 次
文章分类
社区版块
存档分类
最新评论

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

 
阅读更多

前面介绍了类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是否支持这些功能,才能使用它,否则会出错的。

分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics