root/OpenSceneGraph/trunk/examples/osgoit/DepthPeeling.cpp @ 13556

Revision 13556, 22.7 kB (checked in by robert, 37 hours ago)

From Alberto Luaces,"the current code uses the preprocessor for generating the plugin path in
a way that when CMAKE_INSTALL_PREFIX contains something along the lines
of

/usr/x86_64-linux-gnu/

it gets substituted as

/usr/x86_64-1-gnu/

that is, the string is preprocessed again, thereby making changes to
anything that matches any defined symbol, as "linux" in this example
(https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=763816).

Quoting that path directly in CMake scripts solves that problem.
"

Line 
1
2#include "DepthPeeling.h"
3
4#include <osg/Array>
5#include <osg/AlphaFunc>
6#include <osg/BlendFunc>
7#include <osg/Depth>
8#include <osg/Geode>
9#include <osg/Geometry>
10#include <osg/Vec3>
11#include <osg/MatrixTransform>
12#include <osg/Texture2D>
13#include <osg/TextureRectangle>
14#include <osg/TexGen>
15#include <osg/TexEnv>
16#include <osg/TexMat>
17#include <osg/TexGenNode>
18
19#include <osgViewer/Viewer>
20#include <osgViewer/ViewerEventHandlers>
21
22#include <osg/Math>
23
24#include <limits>
25#include <iostream>
26
27const char *DepthPeeling::PeelingShader =
28{
29    "#version 120\n"
30#ifdef USE_TEXTURE_RECTANGLE
31    "#extension GL_ARB_texture_rectangle : enable\n"
32    "uniform sampler2DRectShadow depthtex;\n"
33#else
34    "uniform sampler2DShadow depthtex;\n"
35#endif
36    "uniform bool depthtest;\n"  // depth test enable flag
37    "uniform float invWidth;\n"  // 1.0/width (shadow texture size)
38    "uniform float invHeight;\n" // 1.0/height (shadow texture size)
39    "uniform float offsetX;\n"   // viewport lower left corner (int)
40    "uniform float offsetY;\n"   // viewport lower left corner (int)
41    "\n"
42    "bool depthpeeling()\n"
43    "{\n"
44    "  if( depthtest ) {\n"
45    "    vec3 r0 = vec3((gl_FragCoord.x-offsetX)*invWidth,\n"
46    "                   (gl_FragCoord.y-offsetY)*invHeight,\n"
47    "                    gl_FragCoord.z);\n"
48#ifdef USE_TEXTURE_RECTANGLE
49    "    return shadow2DRect(depthtex, r0).r < 0.5;\n"
50#else
51    "    return shadow2D(depthtex, r0).r < 0.5;\n"
52#endif
53    "  }\n"
54    "  return false;\n"
55    "}\n"
56};
57
58class PreDrawFBOCallback : public osg::Camera::DrawCallback
59{
60public:
61  PreDrawFBOCallback( osg::FrameBufferObject* fbo, osg::FrameBufferObject* source_fbo, unsigned int width, unsigned int height, osg::Texture *dt, osg::Texture *ct ) :
62 _fbo(fbo), _source_fbo(source_fbo), _depthTexture(dt), _colorTexture(ct), _width(width), _height(height) {}
63
64  virtual void operator () (osg::RenderInfo& renderInfo) const
65  {
66      // switching only the frame buffer attachments is actually faster than switching the framebuffer
67#ifdef USE_PACKED_DEPTH_STENCIL
68#ifdef USE_TEXTURE_RECTANGLE
69     _fbo->setAttachment(osg::Camera::PACKED_DEPTH_STENCIL_BUFFER, osg::FrameBufferAttachment((osg::TextureRectangle*)(_depthTexture.get())));
70#else
71     _fbo->setAttachment(osg::Camera::PACKED_DEPTH_STENCIL_BUFFER, osg::FrameBufferAttachment((osg::Texture2D*)(_depthTexture.get())));
72#endif
73#else
74#ifdef USE_TEXTURE_RECTANGLE
75     _fbo->setAttachment(osg::Camera::DEPTH_BUFFER, osg::FrameBufferAttachment((osg::TextureRectangle*)(_depthTexture.get())));
76#else
77     _fbo->setAttachment(osg::Camera::DEPTH_BUFFER, osg::FrameBufferAttachment((osg::Texture2D*)(_depthTexture.get())));
78#endif
79#endif
80#ifdef USE_TEXTURE_RECTANGLE
81     _fbo->setAttachment(osg::Camera::COLOR_BUFFER0, osg::FrameBufferAttachment((osg::TextureRectangle*)(_colorTexture.get())));
82#else
83     _fbo->setAttachment(osg::Camera::COLOR_BUFFER0, osg::FrameBufferAttachment((osg::Texture2D*)(_colorTexture.get())));
84#endif
85
86     // check if we need to do some depth buffer copying from a source FBO into the current FBO
87     if (_source_fbo.get() != NULL)
88     {
89         osg::FBOExtensions* fbo_ext = osg::FBOExtensions::instance(renderInfo.getContextID(),true);
90         bool fbo_supported = fbo_ext && fbo_ext->isSupported();
91         if (fbo_supported && fbo_ext->glBlitFramebuffer)
92         {
93             // blit the depth buffer from the solid geometry fbo into the current transparency fbo
94             (_fbo.get())->apply(*renderInfo.getState(), osg::FrameBufferObject::DRAW_FRAMEBUFFER);
95             (_source_fbo.get())->apply(*renderInfo.getState(), osg::FrameBufferObject::READ_FRAMEBUFFER);
96
97//             glReadBuffer(GL_COLOR_ATTACHMENT0_EXT); // only needed to blit the color buffer
98//             glDrawBuffer(GL_COLOR_ATTACHMENT0_EXT); // only needed to blit the color buffer
99             fbo_ext->glBlitFramebuffer(
100                 0, 0, static_cast<GLint>(_width), static_cast<GLint>(_height),
101                 0, 0, static_cast<GLint>(_width), static_cast<GLint>(_height),
102#ifdef USE_PACKED_DEPTH_STENCIL
103                 GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT, GL_NEAREST);
104#else
105                 GL_DEPTH_BUFFER_BIT, GL_NEAREST);
106#endif
107             (_fbo.get())->apply(*renderInfo.getState(), osg::FrameBufferObject::READ_FRAMEBUFFER);
108             (_fbo.get())->apply(*renderInfo.getState(), osg::FrameBufferObject::DRAW_FRAMEBUFFER);
109         }
110     }
111     // switch to this fbo, if it isn't already bound
112     (_fbo.get())->apply( *renderInfo.getState() );
113  }
114protected:
115  osg::ref_ptr<osg::FrameBufferObject> _fbo;
116  osg::ref_ptr<osg::FrameBufferObject> _source_fbo;
117  osg::ref_ptr<osg::Texture> _depthTexture;
118  osg::ref_ptr<osg::Texture> _colorTexture;
119  unsigned int _width;
120  unsigned int _height;
121};
122
123
124class PostDrawFBOCallback : public osg::Camera::DrawCallback
125{
126public:
127  PostDrawFBOCallback(bool restore) : _restore(restore) {}
128
129  virtual void operator () (osg::RenderInfo& renderInfo) const
130  {
131    // only unbind the fbo if this is the last transparency pass
132    if (_restore)
133      osg::FBOExtensions::instance( renderInfo.getState()->getContextID(), false )->glBindFramebuffer( GL_FRAMEBUFFER_EXT, 0 );
134  }
135protected:
136  bool _restore;
137};
138
139
140DepthPeeling::CullCallback::CullCallback(unsigned int texUnit, unsigned int texWidth, unsigned int texHeight, unsigned int offsetValue) :
141    _texUnit(texUnit),
142    _texWidth(texWidth),
143    _texHeight(texHeight),
144    _offsetValue(offsetValue)
145{
146}
147
148void DepthPeeling::CullCallback::operator()(osg::Node* node, osg::NodeVisitor* nv)
149{
150    osgUtil::CullVisitor* cullVisitor = static_cast<osgUtil::CullVisitor*>(nv);
151    osgUtil::RenderStage* renderStage = cullVisitor->getCurrentRenderStage();
152    const osg::Viewport* viewport = renderStage->getViewport();
153
154    osg::Matrixd m(*cullVisitor->getProjectionMatrix());
155    m.postMultTranslate(osg::Vec3d(1, 1, 1));
156    m.postMultScale(osg::Vec3d(0.5, 0.5, 0.5));
157
158    // scale the texture coordinates to the viewport
159#ifdef USE_TEXTURE_RECTANGLE
160    m.postMultScale(osg::Vec3d(viewport->width(), viewport->height(), 1));
161#else
162#ifndef USE_NON_POWER_OF_TWO_TEXTURE
163    m.postMultScale(osg::Vec3d(viewport->width()/double(_texWidth), viewport->height()/double(_texHeight), 1));
164#endif
165#endif
166
167    if (_texUnit != 0 && _offsetValue)
168    {
169        // Kind of polygon offset: note this way, we can also offset lines and points.
170        // Whereas with the polygon offset we could only handle surface primitives.
171        m.postMultTranslate(osg::Vec3d(0, 0, -ldexp(double(_offsetValue), -24)));
172    }
173
174    osg::TexMat* texMat = new osg::TexMat(m);
175    osg::StateSet* stateSet = new osg::StateSet;
176    stateSet->setTextureAttribute(_texUnit, texMat);
177
178    if (_texUnit != 0)
179    {
180        //
181        // GLSL pipeline support
182        //
183
184#ifdef USE_TEXTURE_RECTANGLE
185        // osg::Uniform::SAMPLER_2D_RECT_SHADOW not yet available in OSG 3.0.1
186        // osg::Uniform* depthUniform = new osg::Uniform(osg::Uniform::SAMPLER_2D_RECT_SHADOW, "depthtex");
187        // depthUniform->set((int)_texUnit);
188        osg::Uniform* depthUniform = new osg::Uniform("depthtex", (int)_texUnit);
189        osg::Uniform *invWidthUniform = new osg::Uniform("invWidth", (float)1.0f);
190        osg::Uniform *invHeightUniform = new osg::Uniform("invHeight", (float)1.0f);
191#else
192        osg::Uniform* depthUniform = new osg::Uniform(osg::Uniform::SAMPLER_2D_SHADOW, "depthtex");
193        depthUniform->set((int)_texUnit);
194        osg::Uniform *invWidthUniform = new osg::Uniform("invWidth", (float)1.0f / _texWidth);
195        osg::Uniform *invHeightUniform = new osg::Uniform("invHeight", (float)1.0f / _texHeight);
196#endif
197        osg::Uniform *offsetXUniform = new osg::Uniform("offsetX", (float)viewport->x());
198        osg::Uniform *offsetYUniform = new osg::Uniform("offsetY", (float)viewport->y());
199
200        // uniforms required for any any GLSL implementation in the rendered geometry
201        stateSet->addUniform(depthUniform);
202        stateSet->addUniform(invWidthUniform);
203        stateSet->addUniform(invHeightUniform);
204        stateSet->addUniform(offsetXUniform);
205        stateSet->addUniform(offsetYUniform);
206    }
207
208    cullVisitor->pushStateSet(stateSet);
209    traverse(node, nv);
210    cullVisitor->popStateSet();
211}
212
213
214osg::Node* DepthPeeling::createQuad(unsigned int layerNumber, unsigned int numTiles)
215{
216    float tileSpan = 1;
217    float tileOffsetX = 0;
218    float tileOffsetY = 0;
219    if (_showAllLayers) {
220        tileSpan /= numTiles;
221        tileOffsetX = tileSpan * (layerNumber%numTiles);
222        tileOffsetY = 1 - tileSpan * (1 + layerNumber/numTiles);
223    }
224
225    osg::Vec3Array* vertices = new osg::Vec3Array;
226
227    vertices->push_back(osg::Vec3f(tileOffsetX           , tileOffsetY            , 0));
228    vertices->push_back(osg::Vec3f(tileOffsetX           , tileOffsetY  + tileSpan, 0));
229    vertices->push_back(osg::Vec3f(tileOffsetX + tileSpan, tileOffsetY  + tileSpan, 0));
230    vertices->push_back(osg::Vec3f(tileOffsetX + tileSpan, tileOffsetY            , 0));
231
232    osg::Vec3Array* colors = new osg::Vec3Array;
233    colors->push_back(osg::Vec3(1, 1, 1));
234
235    osg::Vec2Array* texcoords = new osg::Vec2Array;
236    texcoords->push_back(osg::Vec2f(0, 0));
237    texcoords->push_back(osg::Vec2f(0, 1));
238    texcoords->push_back(osg::Vec2f(1, 1));
239    texcoords->push_back(osg::Vec2f(1, 0));
240
241    osg::Geometry* geometry = new osg::Geometry;
242    geometry->setVertexArray(vertices);
243    geometry->setTexCoordArray(0, texcoords);
244
245    geometry->setColorArray(colors);
246    geometry->setColorBinding(osg::Geometry::BIND_OVERALL);
247
248    geometry->addPrimitiveSet(new osg::DrawArrays(GL_QUADS, 0, 4));
249
250    osg::Geode* geode = new osg::Geode;
251    geode->addDrawable(geometry);
252
253    return geode;
254}
255
256#include <osg/State>
257
258void DepthPeeling::createPeeling()
259{
260    int numTiles = ceil(sqrt(double(_numPasses)));
261
262    // cleanup any previous scene data
263    _root->removeChildren(0, _root->getNumChildren());
264
265    // create depth textures
266    _depthTextures.clear();
267    _depthTextures.resize(3);
268    for (unsigned int i = 0; i < 3; ++i) {
269#ifdef USE_TEXTURE_RECTANGLE
270        _depthTextures[i] = new osg::TextureRectangle;
271#else
272        _depthTextures[i] = new osg::Texture2D;
273#endif
274        _depthTextures[i]->setTextureSize(_texWidth, _texHeight);
275
276        _depthTextures[i]->setFilter(osg::Texture::MIN_FILTER, osg::Texture::NEAREST);
277        _depthTextures[i]->setFilter(osg::Texture::MAG_FILTER, osg::Texture::NEAREST);
278        _depthTextures[i]->setWrap(osg::Texture::WRAP_S, osg::Texture::CLAMP_TO_BORDER);
279        _depthTextures[i]->setWrap(osg::Texture::WRAP_T, osg::Texture::CLAMP_TO_BORDER);
280
281#ifdef USE_PACKED_DEPTH_STENCIL
282        _depthTextures[i]->setInternalFormat(GL_DEPTH24_STENCIL8_EXT);
283        _depthTextures[i]->setSourceFormat(GL_DEPTH_STENCIL_EXT);
284        _depthTextures[i]->setSourceType(GL_UNSIGNED_INT_24_8_EXT);
285#else
286        _depthTextures[i]->setInternalFormat(GL_DEPTH_COMPONENT);
287#endif
288
289        _depthTextures[i]->setShadowComparison(true);
290        _depthTextures[i]->setShadowAmbient(0.0); // The r value if the test fails
291        _depthTextures[i]->setShadowCompareFunc(osg::Texture::GREATER);
292        _depthTextures[i]->setShadowTextureMode(osg::Texture::INTENSITY);
293    }
294
295    // create the cameras for the individual depth peel layers
296    _colorTextures.clear();
297    _colorTextures.resize(_numPasses);
298    for (unsigned int i = 0; i < _numPasses; ++i) {
299
300        // create textures for the color buffers
301#ifdef USE_TEXTURE_RECTANGLE
302        osg::ref_ptr<osg::TextureRectangle> colorTexture = new osg::TextureRectangle;
303#else
304        osg::ref_ptr<osg::Texture2D> colorTexture = new osg::Texture2D;
305#endif
306        colorTexture->setTextureSize(_texWidth, _texHeight);
307        colorTexture->setFilter(osg::Texture::MIN_FILTER, osg::Texture::NEAREST);
308        colorTexture->setFilter(osg::Texture::MAG_FILTER, osg::Texture::NEAREST);
309        colorTexture->setWrap(osg::Texture::WRAP_S, osg::Texture::CLAMP_TO_BORDER);
310        colorTexture->setWrap(osg::Texture::WRAP_T, osg::Texture::CLAMP_TO_BORDER);
311        colorTexture->setInternalFormat(GL_RGBA);
312
313        _colorTextures[i] = colorTexture;
314    }
315
316    // create some uniform and cull callback objects
317    osg::Uniform *depthOff = new osg::Uniform("depthtest", (bool)false);
318    osg::Uniform *depthOn  = new osg::Uniform("depthtest", (bool)true);
319    CullCallback *ccb      = new CullCallback(_texUnit, _texWidth, _texHeight, _offsetValue);
320
321    // create a node for solid model rendering
322    osg::Group *pre_solidNode = new osg::Group;
323    pre_solidNode->addChild(_solidscene.get());
324
325    // create a node for non depth peeled transparent rendering (topmost layer)
326    osg::Group *transparentNodeNoPeel = new osg::Group;
327    transparentNodeNoPeel->addChild(_transparentscene.get());
328    transparentNodeNoPeel->getOrCreateStateSet()->addUniform(depthOff);
329    transparentNodeNoPeel->getOrCreateStateSet()->setRenderBinDetails(99, "RenderBin", osg::StateSet::OVERRIDE_RENDERBIN_DETAILS);
330
331    // create a node for depth peeled transparent rendering (any layers below).
332    osg::TexGenNode* transparentNodePeel = new osg::TexGenNode;
333    transparentNodePeel->setReferenceFrame(osg::TexGenNode::ABSOLUTE_RF);
334    transparentNodePeel->setTextureUnit(_texUnit);
335    transparentNodePeel->getTexGen()->setMode(osg::TexGen::EYE_LINEAR);
336    transparentNodePeel->addChild(_transparentscene.get());
337    transparentNodePeel->getOrCreateStateSet()->addUniform(depthOn);
338    transparentNodePeel->getOrCreateStateSet()->setRenderBinDetails(99, "RenderBin", osg::StateSet::OVERRIDE_RENDERBIN_DETAILS);
339
340    // only render fragments that are not completely transparent
341    transparentNodePeel->getOrCreateStateSet()->setAttributeAndModes(new osg::AlphaFunc(osg::AlphaFunc::GREATER, 0.01),
342                                    osg::StateAttribute::ON | osg::StateAttribute::OVERRIDE);
343
344    // generate texcoords for the depth texture, supporting the fixed function pipeline
345    transparentNodePeel->getOrCreateStateSet()->setTextureMode(_texUnit, GL_TEXTURE_GEN_S, osg::StateAttribute::ON);
346    transparentNodePeel->getOrCreateStateSet()->setTextureMode(_texUnit, GL_TEXTURE_GEN_T, osg::StateAttribute::ON);
347    transparentNodePeel->getOrCreateStateSet()->setTextureMode(_texUnit, GL_TEXTURE_GEN_R, osg::StateAttribute::ON);
348    transparentNodePeel->getOrCreateStateSet()->setTextureMode(_texUnit, GL_TEXTURE_GEN_Q, osg::StateAttribute::ON);
349
350    // use two FBOs, one for solid geometry - the other one for the transparency passes
351    // depth and color attachments will be switched as needed.
352    osg::ref_ptr<osg::FrameBufferObject> fbos[2] = {new osg::FrameBufferObject(), new osg::FrameBufferObject()};
353
354    // create the cameras for the individual depth peel layers
355    for (unsigned int i = 0; i < _numPasses; ++i) {
356
357        // get the pointers to the required fbo, color and depth textures for each camera instance
358        // we perform ping ponging between two depth textures
359        osg::FrameBufferObject *fbo0 = (i >= 1) ? fbos[0].get() : NULL;
360        osg::FrameBufferObject *fbo  = (i >= 1) ? fbos[1].get() : fbos[0].get();
361        osg::Texture *colorTexture     = _colorTextures[i].get();
362        osg::Texture *depthTexture     = (i >= 1) ? _depthTextures[1+(i-1)%2].get() : _depthTextures[i].get();
363        osg::Texture *prevDepthTexture = (i >= 2) ? _depthTextures[1+(i-2)%2].get() : NULL;
364
365        // all our peeling layer cameras are post render
366        osg::Camera* camera = new osg::Camera;
367        camera->setDataVariance(osg::Object::DYNAMIC);
368        camera->setInheritanceMask(osg::Camera::ALL_VARIABLES);
369        camera->setRenderOrder(osg::Camera::POST_RENDER, i);
370        camera->setClearMask(GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT);
371        camera->setClearColor(osg::Vec4f(0, 0, 0, 0));
372        camera->setComputeNearFarMode(osg::Camera::DO_NOT_COMPUTE_NEAR_FAR);
373        camera->setPreDrawCallback(new PreDrawFBOCallback(fbo, fbo0, _texWidth, _texHeight, depthTexture, colorTexture));
374        camera->setPostDrawCallback(new PostDrawFBOCallback(i == _numPasses - 1));
375        camera->setDrawBuffer(GL_COLOR_ATTACHMENT0_EXT);
376        camera->setReadBuffer(GL_COLOR_ATTACHMENT0_EXT);
377        camera->setAllowEventFocus(false);
378
379        // the peeled layers are rendered with blending forced off
380        // and the depth buffer is directly taken from camera 0 via framebuffer blit
381        if (i > 0) {
382            camera->getOrCreateStateSet()->setMode(GL_BLEND, osg::StateAttribute::OFF | osg::StateAttribute::OVERRIDE);
383            camera->setClearMask(GL_COLOR_BUFFER_BIT);
384        } else {
385            // camera 0 has to clear both the depth and color buffers
386            camera->setClearMask(GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT);
387        }
388
389        // add the correct geometry for each pass.
390        // the peeling passes also need read access to prevDepthTexture and a cull callback
391        if (0 == i) {        // solid geometry
392            camera->addChild(pre_solidNode);
393        } else if (1 == i) { // topmost layer peeling pass
394            camera->addChild(transparentNodeNoPeel);
395        } else {             // behind layers peeling passes
396            camera->addChild(transparentNodePeel);
397            // set depth (shadow) texture for depth peeling and add a cull callback
398            camera->getOrCreateStateSet()->setTextureAttributeAndModes(_texUnit, prevDepthTexture);
399            camera->addCullCallback(ccb);
400        }
401        _root->addChild(camera);
402    }
403
404    // create the composite camera that blends the peeled layers into the final scene
405    _compositeCamera = new osg::Camera;
406    _compositeCamera->setDataVariance(osg::Object::DYNAMIC);
407    _compositeCamera->setInheritanceMask(osg::Camera::READ_BUFFER | osg::Camera::DRAW_BUFFER);
408    _compositeCamera->setRenderOrder(osg::Camera::POST_RENDER, _numPasses);
409    _compositeCamera->setComputeNearFarMode(osg::Camera::COMPUTE_NEAR_FAR_USING_PRIMITIVES);
410    _compositeCamera->setClearMask(0);
411    _compositeCamera->setReferenceFrame(osg::Transform::ABSOLUTE_RF);
412    _compositeCamera->setViewMatrix(osg::Matrix());
413    _compositeCamera->setProjectionMatrix(osg::Matrix::ortho2D(0, 1, 0, 1));
414    _compositeCamera->setCullCallback(new CullCallback(0, _texWidth, _texHeight, 0));
415    osg::StateSet* stateSet = _compositeCamera->getOrCreateStateSet();
416    stateSet->setRenderBinDetails(100, "TraversalOrderBin", osg::StateSet::OVERRIDE_RENDERBIN_DETAILS);
417    _root->addChild(_compositeCamera.get());
418
419    // solid geometry is blended first, transparency layers are blended in back to front order.
420    // this order is achieved by rendering using a TraversalOrderBin (see camera stateset).
421    for (unsigned int i = _numPasses; i > 0; --i) {
422        osg::Node* geode = createQuad(i%_numPasses, numTiles);
423        osg::StateSet *stateSet = geode->getOrCreateStateSet();
424        stateSet->setTextureAttributeAndModes(0, _colorTextures[i%_numPasses].get(), osg::StateAttribute::ON);
425        stateSet->setAttribute(new osg::BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA), osg::StateAttribute::ON);
426        stateSet->setMode(GL_BLEND, osg::StateAttribute::ON);
427        stateSet->setMode(GL_LIGHTING, osg::StateAttribute::OFF);
428        osg::Depth* depth = new osg::Depth;
429        depth->setWriteMask( false );
430        stateSet->setAttributeAndModes( depth, osg::StateAttribute::ON );
431        stateSet->setMode(GL_DEPTH_TEST, osg::StateAttribute::OFF);
432        _compositeCamera->addChild(geode);
433    }
434}
435
436DepthPeeling::DepthPeeling(unsigned int width, unsigned int height) :
437    _numPasses(9),
438    _texUnit(2),
439    _texWidth(width),
440    _texHeight(height),
441    _showAllLayers(false),
442    _offsetValue(8),
443    _root(new osg::Group),
444    _solidscene(new osg::Group),
445    _transparentscene(new osg::Group)
446{
447    createPeeling();
448}
449
450void DepthPeeling::setSolidScene(osg::Node* scene)
451{
452    _solidscene->removeChildren(0, _solidscene->getNumChildren());
453    _solidscene->addChild(scene);
454}
455
456void DepthPeeling::setTransparentScene(osg::Node* scene)
457{
458    _transparentscene->removeChildren(0, _transparentscene->getNumChildren());
459    _transparentscene->addChild(scene);
460}
461
462osg::Node* DepthPeeling::getRoot()
463{
464    return _root.get();
465}
466
467void DepthPeeling::resize(int width, int height)
468{
469#ifdef USE_TEXTURE_RECTANGLE
470    for (unsigned int i = 0; i < 3; ++i)
471        _depthTextures[i]->setTextureSize(width, height);
472    for (unsigned int i = 0; i < _colorTextures.size(); ++i)
473        _colorTextures[i]->setTextureSize(width, height);
474    _texWidth = width;
475    _texHeight = height;
476#else
477#ifndef USE_NON_POWER_OF_TWO_TEXTURE
478    width = nextPowerOfTwo(width);
479    height = nextPowerOfTwo(height);
480#endif
481    _depthTextures[0]->setTextureSize(width, height);
482    _depthTextures[1]->setTextureSize(width, height);
483    for (unsigned int i = 0; i < _colorTextures.size(); ++i)
484        _colorTextures[i]->setTextureSize(width, height);
485    _texWidth = width;
486    _texHeight = height;
487#endif
488    createPeeling();
489}
490
491void DepthPeeling::setNumPasses(unsigned int numPasses)
492{
493    if (numPasses == _numPasses)
494        return;
495    if (numPasses == unsigned(-1))
496        return;
497    _numPasses = numPasses;
498    createPeeling();
499}
500unsigned int DepthPeeling::getNumPasses() const
501{
502    return _numPasses;
503}
504
505void DepthPeeling::setTexUnit(unsigned int texUnit)
506{
507    if (texUnit == _texUnit)
508        return;
509    _texUnit = texUnit;
510    createPeeling();
511}
512
513void DepthPeeling::setShowAllLayers(bool showAllLayers)
514{
515    if (showAllLayers == _showAllLayers)
516        return;
517    _showAllLayers = showAllLayers;
518    createPeeling();
519}
520bool DepthPeeling::getShowAllLayers() const
521{
522    return _showAllLayers;
523}
524
525void DepthPeeling::setOffsetValue(unsigned int offsetValue)
526{
527    if (offsetValue == _offsetValue)
528        return;
529    _offsetValue = offsetValue;
530    createPeeling();
531}
532unsigned int DepthPeeling::getOffsetValue() const
533{
534    return _offsetValue;
535}
536
537
538DepthPeeling::EventHandler::EventHandler(DepthPeeling* depthPeeling) :
539    _depthPeeling(depthPeeling)
540{ }
541
542
543/** Handle events, return true if handled, false otherwise. */
544bool DepthPeeling::EventHandler::handle(const osgGA::GUIEventAdapter& ea, osgGA::GUIActionAdapter&, osg::Object*, osg::NodeVisitor*)
545{
546    if (ea.getEventType() == osgGA::GUIEventAdapter::RESIZE) {
547        _depthPeeling->resize(ea.getWindowWidth(), ea.getWindowHeight());
548        return true;
549    }
550
551    if (ea.getEventType() == osgGA::GUIEventAdapter::KEYDOWN) {
552        switch (ea.getKey()) {
553        case 'm':
554            _depthPeeling->setNumPasses(_depthPeeling->getNumPasses() + 1);
555            return true;
556        case 'n':
557            _depthPeeling->setNumPasses(_depthPeeling->getNumPasses() - 1);
558            return true;
559        case 'p':
560            _depthPeeling->setOffsetValue(_depthPeeling->getOffsetValue() + 1);
561            return true;
562        case 'o':
563            _depthPeeling->setOffsetValue(_depthPeeling->getOffsetValue() - 1);
564            return true;
565        case 'l':
566            _depthPeeling->setShowAllLayers(!_depthPeeling->getShowAllLayers());
567            return true;
568        default:
569            return false;
570        };
571    }
572
573    return false;
574}
Note: See TracBrowser for help on using the browser.