00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035 #include "framebuffer.h"
00036
00037 #include "perf/perf.h"
00038
00039
00040 namespace glut {
00041
00042
00043
00044 Framebuffer::~Framebuffer(void) throw() { }
00045
00046
00047
00048
00049
00050
00051
00052
00053
00054
00055
00056
00057
00058
00059
00060
00061 class FBuffer : public Framebuffer {
00062 public:
00063 FBuffer(void) throw();
00064 ~FBuffer(void) throw();
00065
00066
00067 void initialize(IN int width, IN int height);
00068
00069
00070 int getWidth(void) const throw() { return m_width; }
00071 int getHeight(void) const throw() { return m_height; }
00072 void setupForRendering(IN int textureId,
00073 IN const render_context_t& rc);
00074 void endRendering(void) throw();
00075
00076 private:
00077
00078 int m_width;
00079 int m_height;
00080 GLuint m_fbufId;
00081 GLuint m_rbufId;
00082 };
00083
00084
00085
00086 FBuffer::FBuffer
00087 (
00088 void
00089 )
00090 throw()
00091 {
00092 m_width = m_height = 0;
00093 m_fbufId = 0;
00094 m_rbufId = 0;
00095 }
00096
00097
00098
00099 FBuffer::~FBuffer
00100 (
00101 void
00102 )
00103 throw()
00104 {
00105 if (m_rbufId) {
00106 glDeleteRenderbuffersEXT(1, &m_rbufId);
00107 }
00108 if (m_fbufId) {
00109 glDeleteFramebuffersEXT(1, &m_fbufId);
00110 }
00111 }
00112
00113
00114
00115 void
00116 FBuffer::initialize
00117 (
00118 IN int width,
00119 IN int height
00120 )
00121 {
00122 ASSERT(width > 1, "bad width: %d", width);
00123 ASSERT(height > 1, "bad height: %d", height);
00124
00125
00126 m_width = width;
00127 m_height = height;
00128
00129
00130 ASSERT(!m_fbufId, "already have framebuffer?");
00131 glGenFramebuffersEXT(1, &m_fbufId);
00132 ASSERT(m_fbufId, "failed to create OpenGL framebuffer");
00133 glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, m_fbufId);
00134
00135
00136 ASSERT(!m_rbufId, "already have a renderbuffer?");
00137 glGenRenderbuffersEXT(1, &m_rbufId);
00138 ASSERT(m_rbufId, "failed to create OpenGL renderbuffer");
00139 glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, m_rbufId);
00140 glRenderbufferStorageEXT(GL_RENDERBUFFER_EXT, GL_DEPTH_COMPONENT,
00141 m_width, m_height);
00142 glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT,
00143 GL_DEPTH_ATTACHMENT_EXT, GL_RENDERBUFFER_EXT, m_rbufId);
00144
00145
00146 const int nullFramebuffer = 0;
00147 glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, nullFramebuffer);
00148 }
00149
00150
00151
00152 void
00153 FBuffer::setupForRendering
00154 (
00155 IN int textureId,
00156 IN const render_context_t& rc
00157 )
00158 {
00159 ASSERT(textureId, "null");
00160
00161
00162
00163
00164
00165 glBindTexture(GL_TEXTURE_2D, textureId);
00166 const int levelOfDetail = 0;
00167 int width, height;
00168 glGetTexLevelParameteriv(GL_TEXTURE_2D, levelOfDetail, GL_TEXTURE_WIDTH,
00169 &width);
00170 glGetTexLevelParameteriv(GL_TEXTURE_2D, levelOfDetail, GL_TEXTURE_HEIGHT,
00171 &height);
00172
00173 ASSERT_THROW(width == m_width && height == m_height,
00174 "Incoming texture size does not match framebuffer. Texture size: "
00175 << width << " x " << height << ", framebuffer size: " << m_width
00176 << " x " << m_height);
00177
00178
00179 ASSERT(m_fbufId, "should have valid framebuffer");
00180 glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, m_fbufId);
00181
00182
00183 const int mipmapLevel = 0;
00184 glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT,
00185 GL_TEXTURE_2D, textureId, mipmapLevel);
00186
00187
00188 GLenum status = glCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT);
00189 ASSERT_THROW(GL_FRAMEBUFFER_COMPLETE_EXT == status,
00190 "Framebuffer is not complete, status = " << status);
00191
00192
00193 glMatrixMode(GL_PROJECTION);
00194 glPushMatrix();
00195 glPushAttrib(GL_VIEWPORT_BIT);
00196
00197
00198 camera_t camera = rc.camera;
00199 camera.setAspect(m_width, m_height);
00200 setOpenGLProjection(camera);
00201 glViewport(0, 0, m_width, m_height);
00202 }
00203
00204
00205
00206 void
00207 FBuffer::endRendering
00208 (
00209 void
00210 )
00211 throw()
00212 {
00213
00214 const int nullFramebuffer = 0;
00215 glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, nullFramebuffer);
00216
00217
00218 const int mipmapLevel = 0;
00219 const int nullTexture = 0;
00220 glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT,
00221 GL_TEXTURE_2D, nullTexture, mipmapLevel);
00222
00223
00224 glPopAttrib();
00225 glMatrixMode(GL_PROJECTION);
00226 glPopMatrix();
00227 }
00228
00229
00230
00231
00232
00233
00234
00235
00236
00237 smart_ptr<Framebuffer>
00238 Framebuffer::create
00239 (
00240 IN int width,
00241 IN int height
00242 )
00243 {
00244 ASSERT(width > 1, "Bad width: %d", width);
00245 ASSERT(height > 1, "Bad height: %d", height);
00246
00247 smart_ptr<FBuffer> local = new FBuffer;
00248 ASSERT(local, "out of memory");
00249
00250 local->initialize(width, height);
00251
00252 return local;
00253 }
00254
00255
00256
00257 };
00258