FrameBufferRenderBuffer.hpp 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639
  1. /*
  2. Copyright (c) 2005,
  3. Aaron Lefohn (lefohn@cs.ucdavis.edu)
  4. Adam Moerschell (atmoerschell@ucdavis.edu)
  5. All rights reserved.
  6. This software is licensed under the BSD open-source license. See
  7. http://www.opensource.org/licenses/bsd-license.php for more detail.
  8. *************************************************************
  9. Redistribution and use in source and binary forms, with or
  10. without modification, are permitted provided that the following
  11. conditions are met:
  12. Redistributions of source code must retain the above copyright notice,
  13. this list of conditions and the following disclaimer.
  14. Redistributions in binary form must reproduce the above copyright notice,
  15. this list of conditions and the following disclaimer in the documentation
  16. and/or other materials provided with the distribution.
  17. Neither the name of the University of Californa, Davis nor the names of
  18. the contributors may be used to endorse or promote products derived
  19. from this software without specific prior written permission.
  20. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
  21. "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
  22. LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
  23. FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
  24. THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
  25. INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  26. DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
  27. GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
  28. INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
  29. WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  30. (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
  31. THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
  32. OF SUCH DAMAGE.
  33. */
  34. #ifndef __FRAMEBUFFERRENDERBUFFER_HPP__
  35. #define __FRAMEBUFFERRENDERBUFFER_HPP__
  36. #include <GL/glew.h>
  37. #include <iostream>
  38. /*!
  39. FramebufferObject Class. This class encapsulates the FramebufferObject
  40. (FBO) OpenGL spec. See the official spec at:
  41. http://oss.sgi.com/projects/ogl-sample/registry/EXT/framebuffer_object.txt
  42. for details.
  43. A framebuffer object (FBO) is conceptually a structure containing pointers
  44. to GPU memory. The memory pointed to is either an OpenGL texture or an
  45. OpenGL RenderBuffer. FBOs can be used to render to one or more textures,
  46. share depth buffers between multiple sets of color buffers/textures and
  47. are a complete replacement for pbuffers.
  48. Performance Notes:
  49. 1) It is more efficient (but not required) to call Bind()
  50. on an FBO before making multiple method calls. For example:
  51. FramebufferObject fbo;
  52. fbo.Bind();
  53. fbo.AttachTexture(GL_TEXTURE_2D, texId0, GL_COLOR_ATTACHMENT0_EXT);
  54. fbo.AttachTexture(GL_TEXTURE_2D, texId1, GL_COLOR_ATTACHMENT1_EXT);
  55. fbo.IsValid();
  56. To provide a complete encapsulation, the following usage
  57. pattern works correctly but is less efficient:
  58. FramebufferObject fbo;
  59. // NOTE : No Bind() call
  60. fbo.AttachTexture(GL_TEXTURE_2D, texId0, GL_COLOR_ATTACHMENT0_EXT);
  61. fbo.AttachTexture(GL_TEXTURE_2D, texId1, GL_COLOR_ATTACHMENT1_EXT);
  62. fbo.IsValid();
  63. The first usage pattern binds the FBO only once, whereas
  64. the second usage binds/unbinds the FBO for each method call.
  65. 2) Use FramebufferObject::Disable() sparingly. We have intentionally
  66. left out an "Unbind()" method because it is largely unnecessary
  67. and encourages rendundant Bind/Unbind coding. Binding an FBO is
  68. usually much faster than enabling/disabling a pbuffer, but is
  69. still a costly operation. When switching between multiple FBOs
  70. and a visible OpenGL framebuffer, the following usage pattern
  71. is recommended:
  72. FramebufferObject fbo1, fbo2;
  73. fbo1.Bind();
  74. ... Render ...
  75. // NOTE : No Unbind/Disable here...
  76. fbo2.Bind();
  77. ... Render ...
  78. // Disable FBO rendering and return to visible window
  79. // OpenGL framebuffer.
  80. FramebufferObject::Disable();
  81. */
  82. class FramebufferObject
  83. {
  84. public:
  85. /// Ctor/Dtor
  86. FramebufferObject();
  87. virtual ~FramebufferObject();
  88. /// Bind this FBO as current render target
  89. void Bind();
  90. /// Bind a texture to the "attachment" point of this FBO
  91. virtual void AttachTexture( GLenum texTarget,
  92. GLuint texId,
  93. GLenum attachment = GL_COLOR_ATTACHMENT0_EXT,
  94. int mipLevel = 0,
  95. int zSlice = 0 );
  96. /// Bind an array of textures to multiple "attachment" points of this FBO
  97. /// - By default, the first 'numTextures' attachments are used,
  98. /// starting with GL_COLOR_ATTACHMENT0_EXT
  99. virtual void AttachTextures( int numTextures,
  100. GLenum texTarget[],
  101. GLuint texId[],
  102. GLenum attachment[] = NULL,
  103. int mipLevel[] = NULL,
  104. int zSlice[] = NULL );
  105. /// Bind a render buffer to the "attachment" point of this FBO
  106. virtual void AttachRenderBuffer( GLuint buffId,
  107. GLenum attachment = GL_COLOR_ATTACHMENT0_EXT );
  108. /// Bind an array of render buffers to corresponding "attachment" points
  109. /// of this FBO.
  110. /// - By default, the first 'numBuffers' attachments are used,
  111. /// starting with GL_COLOR_ATTACHMENT0_EXT
  112. virtual void AttachRenderBuffers( int numBuffers, GLuint buffId[],
  113. GLenum attachment[] = NULL );
  114. /// Free any resource bound to the "attachment" point of this FBO
  115. void Unattach( GLenum attachment );
  116. /// Free any resources bound to any attachment points of this FBO
  117. void UnattachAll();
  118. /// Is this FBO currently a valid render target?
  119. /// - Sends output to std::cerr by default but can
  120. /// be a user-defined C++ stream
  121. ///
  122. /// NOTE : This function works correctly in debug build
  123. /// mode but always returns "true" if NDEBUG is
  124. /// is defined (optimized builds)
  125. #ifndef NDEBUG
  126. bool IsValid( std::ostream& ostr = std::cerr );
  127. #else
  128. bool IsValid( std::ostream& ostr = std::cerr ) {
  129. return true;
  130. }
  131. #endif
  132. /// BEGIN : Accessors
  133. /// Is attached type GL_RENDERBUFFER_EXT or GL_TEXTURE?
  134. GLenum GetAttachedType( GLenum attachment );
  135. /// What is the Id of Renderbuffer/texture currently
  136. /// attached to "attachement?"
  137. GLuint GetAttachedId( GLenum attachment );
  138. /// Which mipmap level is currently attached to "attachement?"
  139. GLint GetAttachedMipLevel( GLenum attachment );
  140. /// Which cube face is currently attached to "attachment?"
  141. GLint GetAttachedCubeFace( GLenum attachment );
  142. /// Which z-slice is currently attached to "attachment?"
  143. GLint GetAttachedZSlice( GLenum attachment );
  144. /// END : Accessors
  145. GLuint GetAttachedTextureID() const { return m_attachedTexture; }
  146. /// BEGIN : Static methods global to all FBOs
  147. /// Return number of color attachments permitted
  148. static int GetMaxColorAttachments();
  149. /// Disable all FBO rendering and return to traditional,
  150. /// windowing-system controlled framebuffer
  151. /// NOTE:
  152. /// This is NOT an "unbind" for this specific FBO, but rather
  153. /// disables all FBO rendering. This call is intentionally "static"
  154. /// and named "Disable" instead of "Unbind" for this reason. The
  155. /// motivation for this strange semantic is performance. Providing
  156. /// "Unbind" would likely lead to a large number of unnecessary
  157. /// FBO enablings/disabling.
  158. static void Disable();
  159. /// END : Static methods global to all FBOs
  160. protected:
  161. void _GuardedBind();
  162. void _GuardedUnbind();
  163. void _FramebufferTextureND( GLenum attachment, GLenum texTarget,
  164. GLuint texId, int mipLevel, int zSlice );
  165. static GLuint _GenerateFboId();
  166. private:
  167. GLuint m_fboId;
  168. GLint m_savedFboId;
  169. GLuint m_attachedTexture;
  170. };
  171. #include <iostream>
  172. using namespace std;
  173. FramebufferObject::FramebufferObject()
  174. : m_fboId(_GenerateFboId()),
  175. m_savedFboId(0)
  176. {
  177. // Bind this FBO so that it actually gets created now
  178. _GuardedBind();
  179. _GuardedUnbind();
  180. }
  181. FramebufferObject::~FramebufferObject()
  182. {
  183. glDeleteFramebuffersEXT(1, &m_fboId);
  184. }
  185. void FramebufferObject::Bind()
  186. {
  187. glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, m_fboId);
  188. }
  189. void FramebufferObject::Disable()
  190. {
  191. glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
  192. }
  193. void
  194. FramebufferObject::AttachTexture( GLenum texTarget, GLuint texId,
  195. GLenum attachment, int mipLevel, int zSlice )
  196. {
  197. _GuardedBind();
  198. /*
  199. #ifndef NDEBUG
  200. if( GetAttachedId(attachment) != texId ) {
  201. #endif
  202. */
  203. _FramebufferTextureND( attachment, texTarget,
  204. texId, mipLevel, zSlice );
  205. m_attachedTexture = texId;
  206. /*
  207. #ifndef NDEBUG
  208. }
  209. else {
  210. cerr << "FramebufferObject::AttachTexture PERFORMANCE WARNING:\n"
  211. << "\tRedundant bind of texture (id = " << texId << ").\n"
  212. << "\tHINT : Compile with -DNDEBUG to remove this warning.\n";
  213. }
  214. #endif
  215. */
  216. _GuardedUnbind();
  217. }
  218. void
  219. FramebufferObject::AttachTextures( int numTextures, GLenum texTarget[], GLuint texId[],
  220. GLenum attachment[], int mipLevel[], int zSlice[] )
  221. {
  222. for(int i = 0; i < numTextures; ++i) {
  223. AttachTexture( texTarget[i], texId[i],
  224. attachment ? attachment[i] : (GL_COLOR_ATTACHMENT0_EXT + i),
  225. mipLevel ? mipLevel[i] : 0,
  226. zSlice ? zSlice[i] : 0 );
  227. }
  228. }
  229. void
  230. FramebufferObject::AttachRenderBuffer( GLuint buffId, GLenum attachment )
  231. {
  232. _GuardedBind();
  233. #ifndef NDEBUG
  234. if( GetAttachedId(attachment) != buffId ) {
  235. #endif
  236. glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, attachment,
  237. GL_RENDERBUFFER_EXT, buffId);
  238. #ifndef NDEBUG
  239. }
  240. else {
  241. cerr << "FramebufferObject::AttachRenderBuffer PERFORMANCE WARNING:\n"
  242. << "\tRedundant bind of Renderbuffer (id = " << buffId << ")\n"
  243. << "\tHINT : Compile with -DNDEBUG to remove this warning.\n";
  244. }
  245. #endif
  246. _GuardedUnbind();
  247. }
  248. void
  249. FramebufferObject::AttachRenderBuffers( int numBuffers, GLuint buffId[], GLenum attachment[] )
  250. {
  251. for(int i = 0; i < numBuffers; ++i) {
  252. AttachRenderBuffer( buffId[i],
  253. attachment ? attachment[i] : (GL_COLOR_ATTACHMENT0_EXT + i) );
  254. }
  255. }
  256. void
  257. FramebufferObject::Unattach( GLenum attachment )
  258. {
  259. _GuardedBind();
  260. GLenum type = GetAttachedType(attachment);
  261. switch(type) {
  262. case GL_NONE:
  263. break;
  264. case GL_RENDERBUFFER_EXT:
  265. AttachRenderBuffer( 0, attachment );
  266. break;
  267. case GL_TEXTURE:
  268. AttachTexture( GL_TEXTURE_2D, 0, attachment );
  269. break;
  270. default:
  271. cerr << "FramebufferObject::unbind_attachment ERROR: Unknown attached resource type\n";
  272. }
  273. _GuardedUnbind();
  274. }
  275. void
  276. FramebufferObject::UnattachAll()
  277. {
  278. int numAttachments = GetMaxColorAttachments();
  279. for(int i = 0; i < numAttachments; ++i) {
  280. Unattach( GL_COLOR_ATTACHMENT0_EXT + i );
  281. }
  282. }
  283. GLint FramebufferObject::GetMaxColorAttachments()
  284. {
  285. GLint maxAttach = 0;
  286. glGetIntegerv( GL_MAX_COLOR_ATTACHMENTS_EXT, &maxAttach );
  287. return maxAttach;
  288. }
  289. GLuint FramebufferObject::_GenerateFboId()
  290. {
  291. GLuint id = 0;
  292. glGenFramebuffersEXT(1, &id);
  293. return id;
  294. }
  295. void FramebufferObject::_GuardedBind()
  296. {
  297. // Only binds if m_fboId is different than the currently bound FBO
  298. glGetIntegerv( GL_FRAMEBUFFER_BINDING_EXT, &m_savedFboId );
  299. if (m_fboId != (GLuint)m_savedFboId) {
  300. glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, m_fboId);
  301. }
  302. }
  303. void FramebufferObject::_GuardedUnbind()
  304. {
  305. // Returns FBO binding to the previously enabled FBO
  306. if (m_fboId != (GLuint)m_savedFboId) {
  307. glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, (GLuint)m_savedFboId);
  308. }
  309. }
  310. void
  311. FramebufferObject::_FramebufferTextureND( GLenum attachment, GLenum texTarget,
  312. GLuint texId, int mipLevel,
  313. int zSlice )
  314. {
  315. if (texTarget == GL_TEXTURE_1D) {
  316. glFramebufferTexture1DEXT( GL_FRAMEBUFFER_EXT, attachment,
  317. GL_TEXTURE_1D, texId, mipLevel );
  318. }
  319. else if (texTarget == GL_TEXTURE_3D) {
  320. glFramebufferTexture3DEXT( GL_FRAMEBUFFER_EXT, attachment,
  321. GL_TEXTURE_3D, texId, mipLevel, zSlice );
  322. }
  323. else {
  324. // Default is GL_TEXTURE_2D, GL_TEXTURE_RECTANGLE_ARB, or cube faces
  325. glFramebufferTexture2DEXT( GL_FRAMEBUFFER_EXT, attachment,
  326. texTarget, texId, mipLevel );
  327. }
  328. }
  329. #ifndef NDEBUG
  330. bool FramebufferObject::IsValid( ostream& ostr )
  331. {
  332. _GuardedBind();
  333. bool isOK = false;
  334. GLenum status;
  335. status = glCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT);
  336. switch(status) {
  337. case GL_FRAMEBUFFER_COMPLETE_EXT: // Everything's OK
  338. isOK = true;
  339. break;
  340. case GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT_EXT:
  341. ostr << "glift::CheckFramebufferStatus() ERROR:\n\t"
  342. << "GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT_EXT\n";
  343. isOK = false;
  344. break;
  345. case GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT_EXT:
  346. ostr << "glift::CheckFramebufferStatus() ERROR:\n\t"
  347. << "GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT_EXT\n";
  348. isOK = false;
  349. break;
  350. case GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS_EXT:
  351. ostr << "glift::CheckFramebufferStatus() ERROR:\n\t"
  352. << "GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS_EXT\n";
  353. isOK = false;
  354. break;
  355. case GL_FRAMEBUFFER_INCOMPLETE_FORMATS_EXT:
  356. ostr << "glift::CheckFramebufferStatus() ERROR:\n\t"
  357. << "GL_FRAMEBUFFER_INCOMPLETE_FORMATS_EXT\n";
  358. isOK = false;
  359. break;
  360. case GL_FRAMEBUFFER_INCOMPLETE_DRAW_BUFFER_EXT:
  361. ostr << "glift::CheckFramebufferStatus() ERROR:\n\t"
  362. << "GL_FRAMEBUFFER_INCOMPLETE_DRAW_BUFFER_EXT\n";
  363. isOK = false;
  364. break;
  365. case GL_FRAMEBUFFER_INCOMPLETE_READ_BUFFER_EXT:
  366. ostr << "glift::CheckFramebufferStatus() ERROR:\n\t"
  367. << "GL_FRAMEBUFFER_INCOMPLETE_READ_BUFFER_EXT\n";
  368. isOK = false;
  369. break;
  370. case GL_FRAMEBUFFER_UNSUPPORTED_EXT:
  371. ostr << "glift::CheckFramebufferStatus() ERROR:\n\t"
  372. << "GL_FRAMEBUFFER_UNSUPPORTED_EXT\n";
  373. isOK = false;
  374. break;
  375. default:
  376. ostr << "glift::CheckFramebufferStatus() ERROR:\n\t"
  377. << "Unknown ERROR\n";
  378. isOK = false;
  379. }
  380. _GuardedUnbind();
  381. return isOK;
  382. }
  383. #endif // NDEBUG
  384. /// Accessors
  385. GLenum FramebufferObject::GetAttachedType( GLenum attachment )
  386. {
  387. // Returns GL_RENDERBUFFER_EXT or GL_TEXTURE
  388. _GuardedBind();
  389. GLint type = 0;
  390. glGetFramebufferAttachmentParameterivEXT(GL_FRAMEBUFFER_EXT, attachment,
  391. GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE_EXT,
  392. &type);
  393. _GuardedUnbind();
  394. return GLenum(type);
  395. }
  396. GLuint FramebufferObject::GetAttachedId( GLenum attachment )
  397. {
  398. _GuardedBind();
  399. GLint id = 0;
  400. glGetFramebufferAttachmentParameterivEXT(GL_FRAMEBUFFER_EXT, attachment,
  401. GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME_EXT,
  402. &id);
  403. _GuardedUnbind();
  404. return GLuint(id);
  405. }
  406. GLint FramebufferObject::GetAttachedMipLevel( GLenum attachment )
  407. {
  408. _GuardedBind();
  409. GLint level = 0;
  410. glGetFramebufferAttachmentParameterivEXT(GL_FRAMEBUFFER_EXT, attachment,
  411. GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL_EXT,
  412. &level);
  413. _GuardedUnbind();
  414. return level;
  415. }
  416. GLint FramebufferObject::GetAttachedCubeFace( GLenum attachment )
  417. {
  418. _GuardedBind();
  419. GLint level = 0;
  420. glGetFramebufferAttachmentParameterivEXT(GL_FRAMEBUFFER_EXT, attachment,
  421. GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE_EXT,
  422. &level);
  423. _GuardedUnbind();
  424. return level;
  425. }
  426. GLint FramebufferObject::GetAttachedZSlice( GLenum attachment )
  427. {
  428. _GuardedBind();
  429. GLint slice = 0;
  430. glGetFramebufferAttachmentParameterivEXT(GL_FRAMEBUFFER_EXT, attachment,
  431. GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_3D_ZOFFSET_EXT,
  432. &slice);
  433. _GuardedUnbind();
  434. return slice;
  435. }
  436. /*!
  437. Renderbuffer Class. This class encapsulates the Renderbuffer OpenGL
  438. object described in the FramebufferObject (FBO) OpenGL spec.
  439. See the official spec at:
  440. http://oss.sgi.com/projects/ogl-sample/registry/EXT/framebuffer_object.txt
  441. for complete details.
  442. A "Renderbuffer" is a chunk of GPU memory used by FramebufferObjects to
  443. represent "traditional" framebuffer memory (depth, stencil, and color buffers).
  444. By "traditional," we mean that the memory cannot be bound as a texture.
  445. With respect to GPU shaders, Renderbuffer memory is "write-only." Framebuffer
  446. operations such as alpha blending, depth test, alpha test, stencil test, etc.
  447. read from this memory in post-fragement-shader (ROP) operations.
  448. The most common use of Renderbuffers is to create depth and stencil buffers.
  449. Note that as of 7/1/05, NVIDIA drivers to do not support stencil Renderbuffers.
  450. Usage Notes:
  451. 1) "internalFormat" can be any of the following:
  452. Valid OpenGL internal formats beginning with:
  453. RGB, RGBA, DEPTH_COMPONENT
  454. or a stencil buffer format (not currently supported
  455. in NVIDIA drivers as of 7/1/05).
  456. STENCIL_INDEX1_EXT
  457. STENCIL_INDEX4_EXT
  458. STENCIL_INDEX8_EXT
  459. STENCIL_INDEX16_EXT
  460. */
  461. class Renderbuffer
  462. {
  463. public:
  464. /// Ctors/Dtors
  465. Renderbuffer();
  466. Renderbuffer(GLenum internalFormat, int width, int height);
  467. ~Renderbuffer();
  468. void Bind();
  469. void Unbind();
  470. void Set(GLenum internalFormat, int width, int height);
  471. GLuint GetId() const;
  472. static GLint GetMaxSize();
  473. private:
  474. GLuint m_bufId;
  475. static GLuint _CreateBufferId();
  476. };
  477. #include <iostream>
  478. using namespace std;
  479. Renderbuffer::Renderbuffer()
  480. : m_bufId(_CreateBufferId())
  481. {}
  482. Renderbuffer::Renderbuffer(GLenum internalFormat, int width, int height)
  483. : m_bufId(_CreateBufferId())
  484. {
  485. Set(internalFormat, width, height);
  486. }
  487. Renderbuffer::~Renderbuffer()
  488. {
  489. glDeleteRenderbuffersEXT(1, &m_bufId);
  490. }
  491. void Renderbuffer::Bind()
  492. {
  493. glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, m_bufId);
  494. }
  495. void Renderbuffer::Unbind()
  496. {
  497. glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, 0);
  498. }
  499. void Renderbuffer::Set(GLenum internalFormat, int width, int height)
  500. {
  501. int maxSize = Renderbuffer::GetMaxSize();
  502. if (width > maxSize || height > maxSize ) {
  503. cerr << "Renderbuffer::Renderbuffer() ERROR:\n\t"
  504. << "Size too big (" << width << ", " << height << ")\n";
  505. return;
  506. }
  507. // Guarded bind
  508. GLint savedId = 0;
  509. glGetIntegerv( GL_RENDERBUFFER_BINDING_EXT, &savedId );
  510. if (savedId != (GLint)m_bufId) {
  511. Bind();
  512. }
  513. // Allocate memory for renderBuffer
  514. glRenderbufferStorageEXT(GL_RENDERBUFFER_EXT, internalFormat, width, height );
  515. // Guarded unbind
  516. if (savedId != (GLint)m_bufId) {
  517. glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, savedId);
  518. }
  519. }
  520. GLuint Renderbuffer::GetId() const
  521. {
  522. return m_bufId;
  523. }
  524. GLint Renderbuffer::GetMaxSize()
  525. {
  526. GLint maxAttach = 0;
  527. glGetIntegerv( GL_MAX_RENDERBUFFER_SIZE_EXT, &maxAttach );
  528. return maxAttach;
  529. }
  530. GLuint Renderbuffer::_CreateBufferId()
  531. {
  532. GLuint id = 0;
  533. glGenRenderbuffersEXT(1, &id);
  534. return id;
  535. }
  536. #endif // __FRAMEBUFFERRENDERBUFFER_HPP__
粤ICP备19079148号