openscenegraph
FrameBufferObject
Go to the documentation of this file.
1/* -*-c++-*- OpenSceneGraph - Copyright (C) 1998-2006 Robert Osfield
2 *
3 * This library is open source and may be redistributed and/or modified under
4 * the terms of the OpenSceneGraph Public License (OSGPL) version 0.0 or
5 * (at your option) any later version. The full license is in LICENSE file
6 * included with this distribution, and on the openscenegraph.org website.
7 *
8 * This library is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * OpenSceneGraph Public License for more details.
12*/
13
14// initial FBO support written by Marco Jez, June 2005.
15
16#ifndef OSG_FRAMEBUFFEROBJECT
17#define OSG_FRAMEBUFFEROBJECT 1
18
19#include <osg/GL>
20#include <osg/Texture>
21#include <osg/buffered_value>
22#include <osg/Camera>
23
24#ifndef GL_EXT_framebuffer_object
25#define GL_EXT_framebuffer_object 1
26#define GL_FRAMEBUFFER_EXT 0x8D40
27#define GL_RENDERBUFFER_EXT 0x8D41
28// #define GL_STENCIL_INDEX_EXT 0x8D45 // removed in rev. #114 of the spec
29#define GL_STENCIL_INDEX1_EXT 0x8D46
30#define GL_STENCIL_INDEX4_EXT 0x8D47
31#define GL_STENCIL_INDEX8_EXT 0x8D48
32#define GL_STENCIL_INDEX16_EXT 0x8D49
33#define GL_RENDERBUFFER_WIDTH_EXT 0x8D42
34#define GL_RENDERBUFFER_HEIGHT_EXT 0x8D43
35#define GL_RENDERBUFFER_INTERNAL_FORMAT_EXT 0x8D44
36#define GL_RENDERBUFFER_RED_SIZE_EXT 0x8D50
37#define GL_RENDERBUFFER_GREEN_SIZE_EXT 0x8D51
38#define GL_RENDERBUFFER_BLUE_SIZE_EXT 0x8D52
39#define GL_RENDERBUFFER_ALPHA_SIZE_EXT 0x8D53
40#define GL_RENDERBUFFER_DEPTH_SIZE_EXT 0x8D54
41#define GL_RENDERBUFFER_STENCIL_SIZE_EXT 0x8D55
42#define GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE_EXT 0x8CD0
43#define GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME_EXT 0x8CD1
44#define GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL_EXT 0x8CD2
45#define GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE_EXT 0x8CD3
46#define GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_3D_ZOFFSET_EXT 0x8CD4
47#define GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LAYER_EXT 0x8CD4
48#define GL_COLOR_ATTACHMENT0_EXT 0x8CE0
49#define GL_COLOR_ATTACHMENT1_EXT 0x8CE1
50#define GL_COLOR_ATTACHMENT2_EXT 0x8CE2
51#define GL_COLOR_ATTACHMENT3_EXT 0x8CE3
52#define GL_COLOR_ATTACHMENT4_EXT 0x8CE4
53#define GL_COLOR_ATTACHMENT5_EXT 0x8CE5
54#define GL_COLOR_ATTACHMENT6_EXT 0x8CE6
55#define GL_COLOR_ATTACHMENT7_EXT 0x8CE7
56#define GL_COLOR_ATTACHMENT8_EXT 0x8CE8
57#define GL_COLOR_ATTACHMENT9_EXT 0x8CE9
58#define GL_COLOR_ATTACHMENT10_EXT 0x8CEA
59#define GL_COLOR_ATTACHMENT11_EXT 0x8CEB
60#define GL_COLOR_ATTACHMENT12_EXT 0x8CEC
61#define GL_COLOR_ATTACHMENT13_EXT 0x8CED
62#define GL_COLOR_ATTACHMENT14_EXT 0x8CEE
63#define GL_COLOR_ATTACHMENT15_EXT 0x8CEF
64#define GL_DEPTH_ATTACHMENT_EXT 0x8D00
65#define GL_STENCIL_ATTACHMENT_EXT 0x8D20
66#define GL_FRAMEBUFFER_COMPLETE_EXT 0x8CD5
67#define GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT_EXT 0x8CD6
68#define GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT_EXT 0x8CD7
69#define GL_FRAMEBUFFER_INCOMPLETE_DUPLICATE_ATTACHMENT_EXT 0x8CD8
70#define GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS_EXT 0x8CD9
71#define GL_FRAMEBUFFER_INCOMPLETE_FORMATS_EXT 0x8CDA
72#define GL_FRAMEBUFFER_INCOMPLETE_DRAW_BUFFER_EXT 0x8CDB
73#define GL_FRAMEBUFFER_INCOMPLETE_READ_BUFFER_EXT 0x8CDC
74#define GL_FRAMEBUFFER_UNSUPPORTED_EXT 0x8CDD
75#define GL_FRAMEBUFFER_BINDING_EXT 0x8CA6
76#define GL_RENDERBUFFER_BINDING_EXT 0x8CA7
77#define GL_MAX_COLOR_ATTACHMENTS_EXT 0x8CDF
78#define GL_MAX_RENDERBUFFER_SIZE_EXT 0x84E8
79#define GL_INVALID_FRAMEBUFFER_OPERATION_EXT 0x0506
80#endif
81
82#ifndef GL_EXT_framebuffer_blit
83#define GL_EXT_framebuffer_blit 1
84#define GL_DRAW_FRAMEBUFFER_BINDING_EXT 0x8CA6
85#define GL_READ_FRAMEBUFFER_EXT 0x8CA8
86#define GL_DRAW_FRAMEBUFFER_EXT 0x8CA9
87#define GL_READ_FRAMEBUFFER_BINDING_EXT 0x8CAA
88#endif
89
90#ifndef GL_EXT_framebuffer_multisample
91#define GL_EXT_framebuffer_multisample 1
92#define GL_RENDERBUFFER_SAMPLES_EXT 0x8CAB
93#define GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE_EXT 0x8D56
94#define GL_MAX_SAMPLES_EXT 0x8D57
95#endif
96
97#ifndef GL_MAX_SAMPLES_EXT
98// Workaround for Centos 5 and other distros that define
99// GL_EXT_framebuffer_multisample but not GL_MAX_SAMPLES_EXT
100#define GL_MAX_SAMPLES_EXT 0x8D57
101#endif
102
103#ifndef GL_NV_framebuffer_multisample_coverage
104#define GL_NV_framebuffer_multisample_coverage 1
105#define GL_RENDERBUFFER_COVERAGE_SAMPLES_NV 0x8CAB
106#define GL_RENDERBUFFER_COLOR_SAMPLES_NV 0x8E10
107#define GL_MAX_MULTISAMPLE_COVERAGE_MODES_NV 0x8E11
108#define GL_MULTISAMPLE_COVERAGE_MODES_NV 0x8E12
109#endif
110
111#ifndef GL_EXT_packed_depth_stencil
112#define GL_EXT_packed_depth_stencil 1
113#define GL_DEPTH_STENCIL_EXT 0x84F9
114#define GL_UNSIGNED_INT_24_8_EXT 0x84FA
115#define GL_DEPTH24_STENCIL8_EXT 0x88F0
116#define GL_TEXTURE_STENCIL_SIZE_EXT 0x88F1
117#endif
118
119namespace osg
120{
121
122/**************************************************************************
123 * RenderBuffer
124 **************************************************************************/
125
126class OSG_EXPORT RenderBuffer: public Object
127{
128 public:
129 RenderBuffer();
130 RenderBuffer(int width, int height, GLenum internalFormat, int samples=0, int colorSamples=0);
131 RenderBuffer(const RenderBuffer& copy, const CopyOp& copyop = CopyOp::SHALLOW_COPY);
132
133 META_Object(osg, RenderBuffer);
134
135 inline int getWidth() const;
136 inline int getHeight() const;
137 inline void setWidth(int w);
138 inline void setHeight(int h);
139 inline void setSize(int w, int h);
140 inline GLenum getInternalFormat() const;
141 inline void setInternalFormat(GLenum format);
142 inline int getSamples() const;
143 inline int getColorSamples() const;
144 inline void setSamples(int samples);
145 inline void setColorSamples(int colorSamples);
146
147 GLuint getObjectID(unsigned int contextID, const GLExtensions *ext) const;
148 inline int compare(const RenderBuffer &rb) const;
149
150 static int getMaxSamples(unsigned int contextID, const GLExtensions* ext);
151
152 /** Resize any per context GLObject buffers to specified size. */
153 virtual void resizeGLObjectBuffers(unsigned int maxSize);
154
155 /** If State is non-zero, this function releases any associated OpenGL objects for
156 * the specified graphics context. Otherwise, releases OpenGL objexts
157 * for all graphics contexts. */
158 virtual void releaseGLObjects(osg::State* = 0) const;
159
160 protected:
161 virtual ~RenderBuffer();
162 RenderBuffer &operator=(const RenderBuffer &) { return *this; }
163
164 inline void dirtyAll() const;
165
166 private:
167 mutable buffered_value<GLuint> _objectID;
168 mutable buffered_value<int> _dirty;
169
170 GLenum _internalFormat;
171 int _width;
172 int _height;
173 // "samples" in the framebuffer_multisample extension is equivalent to
174 // "coverageSamples" in the framebuffer_multisample_coverage extension.
175 int _samples;
176 int _colorSamples;
177 };
178
179 // INLINE METHODS
180
181 inline int RenderBuffer::getWidth() const
182 {
183 return _width;
184 }
185
186 inline int RenderBuffer::getHeight() const
187 {
188 return _height;
189 }
190
191 inline void RenderBuffer::setWidth(int w)
192 {
193 _width = w;
194 dirtyAll();
195 }
196
197 inline void RenderBuffer::setHeight(int h)
198 {
199 _height = h;
200 dirtyAll();
201 }
202
203 inline void RenderBuffer::setSize(int w, int h)
204 {
205 _width = w;
206 _height = h;
207 dirtyAll();
208 }
209
210 inline GLenum RenderBuffer::getInternalFormat() const
211 {
212 return _internalFormat;
213 }
214
215 inline void RenderBuffer::setInternalFormat(GLenum format)
216 {
217 _internalFormat = format;
218 dirtyAll();
219 }
220
221 inline int RenderBuffer::getSamples() const
222 {
223 return _samples;
224 }
225
226 inline int RenderBuffer::getColorSamples() const
227 {
228 return _colorSamples;
229 }
230
231 inline void RenderBuffer::setSamples(int samples)
232 {
233 _samples = samples;
234 dirtyAll();
235 }
236
237 inline void RenderBuffer::setColorSamples(int colorSamples)
238 {
239 _colorSamples = colorSamples;
240 dirtyAll();
241 }
242
243 inline void RenderBuffer::dirtyAll() const
244 {
245 _dirty.setAllElementsTo(1);
246 }
247
248 inline int RenderBuffer::compare(const RenderBuffer &rb) const
249 {
250 if (&rb == this) return 0;
251 if (_internalFormat < rb._internalFormat) return -1;
252 if (_internalFormat > rb._internalFormat) return 1;
253 if (_width < rb._width) return -1;
254 if (_width > rb._width) return 1;
255 if (_height < rb._height) return -1;
256 if (_height > rb._height) return 1;
257 return 0;
258 }
259
260/**************************************************************************
261 * FrameBufferAttachement
262 **************************************************************************/
263class Texture1D;
264class Texture2D;
265class Texture2DMultisample;
266class Texture3D;
267class Texture2DArray;
268class TextureCubeMap;
269class TextureRectangle;
270
271class OSG_EXPORT FrameBufferAttachment
272{
273 public:
274 FrameBufferAttachment();
275 FrameBufferAttachment(const FrameBufferAttachment& copy);
276
277 explicit FrameBufferAttachment(RenderBuffer* target);
278 explicit FrameBufferAttachment(Texture1D* target, unsigned int level = 0);
279 explicit FrameBufferAttachment(Texture2D* target, unsigned int level = 0);
280 explicit FrameBufferAttachment(Texture2DMultisample* target, unsigned int level = 0);
281 explicit FrameBufferAttachment(Texture3D* target, unsigned int zoffset, unsigned int level = 0);
282 explicit FrameBufferAttachment(Texture2DArray* target, unsigned int layer, unsigned int level = 0);
283 explicit FrameBufferAttachment(TextureCubeMap* target, unsigned int face, unsigned int level = 0);
284 explicit FrameBufferAttachment(TextureRectangle* target);
285 explicit FrameBufferAttachment(Camera::Attachment& attachment);
286
287 ~FrameBufferAttachment();
288
289 FrameBufferAttachment&operator = (const FrameBufferAttachment& copy);
290
291 bool isMultisample() const;
292 void createRequiredTexturesAndApplyGenerateMipMap(State& state, const GLExtensions* ext) const;
293 void attach(State &state, GLenum target, GLenum attachment_point, const GLExtensions* ext) const;
294 int compare(const FrameBufferAttachment &fa) const;
295
296 RenderBuffer* getRenderBuffer();
297 const RenderBuffer* getRenderBuffer() const;
298
299 Texture* getTexture();
300 const Texture* getTexture() const;
301
302 unsigned int getCubeMapFace() const;
303 unsigned int getTextureLevel() const;
304 unsigned int getTexture3DZOffset() const;
305 unsigned int getTextureArrayLayer() const;
306
307 void resizeGLObjectBuffers(unsigned int maxSize);
308 void releaseGLObjects(osg::State* = 0) const;
309
310 private:
311 // use the Pimpl idiom to avoid dependency from
312 // all Texture* headers
313 struct Pimpl;
314 Pimpl* _ximpl;
315 };
316
317/**************************************************************************
318 * FrameBufferObject
319 **************************************************************************/
320class OSG_EXPORT FrameBufferObject: public StateAttribute
321{
322 public:
323 typedef std::map<Camera::BufferComponent, FrameBufferAttachment> AttachmentMap;
324 typedef std::vector<GLenum> MultipleRenderingTargets;
325
326 typedef Camera::BufferComponent BufferComponent;
327
328 FrameBufferObject();
329 FrameBufferObject(const FrameBufferObject& copy, const CopyOp& copyop = CopyOp::SHALLOW_COPY);
330
331 META_StateAttribute(osg, FrameBufferObject, FRAME_BUFFER_OBJECT);
332
333 inline const AttachmentMap& getAttachmentMap() const;
334
335
336 void setAttachment(BufferComponent attachment_point, const FrameBufferAttachment &attachment);
337 inline const FrameBufferAttachment& getAttachment(BufferComponent attachment_point) const;
338 inline bool hasAttachment(BufferComponent attachment_point) const;
339
340 inline bool hasMultipleRenderingTargets() const { return !_drawBuffers.empty(); }
341 inline const MultipleRenderingTargets& getMultipleRenderingTargets() const { return _drawBuffers; }
342
343 bool isMultisample() const;
344
345 int compare(const StateAttribute &sa) const;
346
347 void apply(State &state) const;
348
349 inline GLuint getHandle(unsigned int contextID) const
350 {
351 return _fboID[contextID];
352 }
353
354 enum BindTarget
355 {
356 READ_FRAMEBUFFER = GL_READ_FRAMEBUFFER_EXT,
357 DRAW_FRAMEBUFFER = GL_DRAW_FRAMEBUFFER_EXT,
358 READ_DRAW_FRAMEBUFFER = GL_FRAMEBUFFER_EXT
359 };
360
361 /** Bind the FBO as either the read or draw target, or both. */
362 void apply(State &state, BindTarget target) const;
363
364 /** Resize any per context GLObject buffers to specified size. */
365 virtual void resizeGLObjectBuffers(unsigned int maxSize);
366
367 /** If State is non-zero, this function releases any associated OpenGL objects for
368 * the specified graphics context. Otherwise, releases OpenGL objexts
369 * for all graphics contexts. */
370 virtual void releaseGLObjects(osg::State* = 0) const;
371
372 protected:
373 virtual ~FrameBufferObject();
374 FrameBufferObject& operator = (const FrameBufferObject&) { return *this; }
375
376 void updateDrawBuffers();
377
378 inline void dirtyAll();
379
380 GLenum convertBufferComponentToGLenum(BufferComponent attachment_point) const;
381
382 private:
383 AttachmentMap _attachments;
384
385 // Buffers passed to glDrawBuffers when using multiple render targets.
386 MultipleRenderingTargets _drawBuffers;
387
388 mutable buffered_value<int> _dirtyAttachmentList;
389 mutable buffered_value<int> _unsupported;
390 mutable buffered_value<GLuint> _fboID;
391
392};
393
394// INLINE METHODS
395
396inline const FrameBufferObject::AttachmentMap &FrameBufferObject::getAttachmentMap() const
397{
398 return _attachments;
399}
400
401inline bool FrameBufferObject::hasAttachment(FrameBufferObject::BufferComponent attachment_point) const
402{
403 return _attachments.find(attachment_point) != _attachments.end();
404}
405
406inline const FrameBufferAttachment &FrameBufferObject::getAttachment(FrameBufferObject::BufferComponent attachment_point) const
407{
408 return _attachments.find(attachment_point)->second;
409}
410
411inline void FrameBufferObject::dirtyAll()
412{
413 _dirtyAttachmentList.setAllElementsTo(1);
414}
415
416class OSG_EXPORT GLRenderBufferManager : public GLObjectManager
417{
418public:
419 GLRenderBufferManager(unsigned int contextID);
420 virtual void deleteGLObject(GLuint globj);
421};
422
423class OSG_EXPORT GLFrameBufferObjectManager : public GLObjectManager
424{
425public:
426 GLFrameBufferObjectManager(unsigned int contextID);
427 virtual void deleteGLObject(GLuint globj);
428};
429
430}
431
432#endif
433