root/OpenSceneGraph/trunk/src/osgVolume/MultipassTechnique.cpp @ 13949

Revision 13949, 25.8 kB (checked in by robert, 77 minutes ago)

Windows build fix

Line 
1/* -*-c++-*- OpenSceneGraph - Copyright (C) 1998-2009 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#include <osgVolume/MultipassTechnique>
15#include <osgVolume/VolumeTile>
16#include <osgVolume/VolumeScene>
17
18#include <osg/Geometry>
19#include <osg/ValueObject>
20#include <osg/io_utils>
21
22#include <osg/Program>
23#include <osg/Material>
24#include <osg/CullFace>
25#include <osg/TexGen>
26#include <osg/Texture1D>
27#include <osg/Texture2D>
28#include <osg/Texture3D>
29#include <osg/TransferFunction>
30
31#include <osgDB/ReadFile>
32#include <osgDB/WriteFile>
33
34namespace osgVolume
35{
36
37
38MultipassTechnique::MultipassTechnique()
39{
40}
41
42MultipassTechnique::MultipassTechnique(const MultipassTechnique& fft,const osg::CopyOp& copyop):
43    VolumeTechnique(fft,copyop)
44{
45}
46
47MultipassTechnique::~MultipassTechnique()
48{
49}
50
51osg::StateSet* MultipassTechnique::createStateSet(osg::StateSet* statesetPrototype, osg::Program* programPrototype, osg::Shader* shaderToAdd1, osg::Shader* shaderToAdd2)
52{
53    osg::ref_ptr<osg::StateSet> stateset = osg::clone(statesetPrototype, osg::CopyOp::SHALLOW_COPY);
54    osg::ref_ptr<osg::Program> program = osg::clone(programPrototype, osg::CopyOp::SHALLOW_COPY);
55    stateset->setAttribute(program.get());
56    if (shaderToAdd1) program->addShader(shaderToAdd1);
57    if (shaderToAdd2) program->addShader(shaderToAdd2);
58
59    return stateset.release();
60}
61
62void MultipassTechnique::init()
63{
64    OSG_INFO<<"MultipassTechnique::init()"<<std::endl;
65
66    if (!_volumeTile)
67    {
68        OSG_NOTICE<<"MultipassTechnique::init(), error no volume tile assigned."<<std::endl;
69        return;
70    }
71
72    if (_volumeTile->getLayer()==0)
73    {
74        OSG_NOTICE<<"MultipassTechnique::init(), error no layer assigend to volume tile."<<std::endl;
75        return;
76    }
77
78    if (_volumeTile->getLayer()->getImage()==0)
79    {
80        OSG_NOTICE<<"MultipassTechnique::init(), error no image assigned to layer."<<std::endl;
81        return;
82    }
83
84    OSG_NOTICE<<"MultipassTechnique::init() Need to set up"<<std::endl;
85
86    CollectPropertiesVisitor cpv(false);
87    if (_volumeTile->getLayer()->getProperty())
88    {
89        _volumeTile->getLayer()->getProperty()->accept(cpv);
90    }
91
92    osg::ref_ptr<osg::Geode> geode = new osg::Geode;
93
94    {
95        osg::Geometry* geom = new osg::Geometry;
96
97        osg::Vec3Array* coords = new osg::Vec3Array(8);
98        (*coords)[0] = osg::Vec3d(0.0,0.0,0.0);
99        (*coords)[1] = osg::Vec3d(1.0,0.0,0.0);
100        (*coords)[2] = osg::Vec3d(1.0,1.0,0.0);
101        (*coords)[3] = osg::Vec3d(0.0,1.0,0.0);
102        (*coords)[4] = osg::Vec3d(0.0,0.0,1.0);
103        (*coords)[5] = osg::Vec3d(1.0,0.0,1.0);
104        (*coords)[6] = osg::Vec3d(1.0,1.0,1.0);
105        (*coords)[7] = osg::Vec3d(0.0,1.0,1.0);
106        geom->setVertexArray(coords);
107
108        osg::Vec4Array* colours = new osg::Vec4Array(1);
109        (*colours)[0].set(1.0f,1.0f,1.0,1.0f);
110        geom->setColorArray(colours, osg::Array::BIND_OVERALL);
111
112        osg::DrawElementsUShort* drawElements = new osg::DrawElementsUShort(GL_QUADS);
113        // bottom
114        drawElements->push_back(3);
115        drawElements->push_back(2);
116        drawElements->push_back(1);
117        drawElements->push_back(0);
118
119        // bottom
120        drawElements->push_back(7);//7623
121        drawElements->push_back(6);
122        drawElements->push_back(2);
123        drawElements->push_back(3);
124
125        // left
126        drawElements->push_back(4);//4730
127        drawElements->push_back(7);
128        drawElements->push_back(3);
129        drawElements->push_back(0);
130
131        // right
132        drawElements->push_back(1);//1265
133        drawElements->push_back(2);
134        drawElements->push_back(6);
135        drawElements->push_back(5);
136
137        // front
138        drawElements->push_back(5);//5401
139        drawElements->push_back(4);
140        drawElements->push_back(0);
141        drawElements->push_back(1);
142
143        // top
144        drawElements->push_back(4);//4567
145        drawElements->push_back(5);
146        drawElements->push_back(6);
147        drawElements->push_back(7);
148
149        geom->addPrimitiveSet(drawElements);
150
151        geode->addDrawable(geom);
152
153    }
154
155    _transform = new osg::MatrixTransform;
156    _transform->addChild(geode.get());
157
158    // handle locators
159    Locator* masterLocator = _volumeTile->getLocator();
160    Locator* layerLocator = _volumeTile->getLayer()->getLocator();
161
162    osg::TransferFunction1D* tf = 0;
163
164    if (!masterLocator && layerLocator) masterLocator = layerLocator;
165    if (!layerLocator && masterLocator) layerLocator = masterLocator;
166
167    osg::Matrix geometryMatrix;
168    if (masterLocator)
169    {
170        geometryMatrix = masterLocator->getTransform();
171        _transform->setMatrix(geometryMatrix);
172        masterLocator->addCallback(new TransformLocatorCallback(_transform.get()));
173    }
174
175    osg::Matrix imageMatrix;
176    if (layerLocator)
177    {
178        imageMatrix = layerLocator->getTransform();
179    }
180
181    OSG_NOTICE<<"MultipassTechnique::init() : geometryMatrix = "<<geometryMatrix<<std::endl;
182    OSG_NOTICE<<"MultipassTechnique::init() : imageMatrix = "<<imageMatrix<<std::endl;
183
184    osg::ref_ptr<osg::StateSet> stateset = _transform->getOrCreateStateSet();
185
186    unsigned int texgenTextureUnit = 0;
187    unsigned int volumeTextureUnit = 2;
188
189    // set up uniforms
190    {
191        stateset->addUniform(new osg::Uniform("colorTexture",0));
192        stateset->addUniform(new osg::Uniform("depthTexture",1));
193
194        stateset->setMode(GL_ALPHA_TEST,osg::StateAttribute::ON);
195
196        float alphaFuncValue = 0.1;
197        if (cpv._isoProperty.valid())
198        {
199            alphaFuncValue = cpv._isoProperty->getValue();
200        }
201
202        if (cpv._sampleRatioProperty.valid())
203            stateset->addUniform(cpv._sampleRatioProperty->getUniform());
204        else
205            stateset->addUniform(new osg::Uniform("SampleRatioValue",1.0f));
206
207
208        if (cpv._transparencyProperty.valid())
209            stateset->addUniform(cpv._transparencyProperty->getUniform());
210        else
211            stateset->addUniform(new osg::Uniform("TransparencyValue",1.0f));
212
213
214        if (cpv._afProperty.valid())
215            stateset->addUniform(cpv._afProperty->getUniform());
216        else
217            stateset->addUniform(new osg::Uniform("AlphaFuncValue",alphaFuncValue));
218
219
220        if (cpv._isoProperty.valid())
221            stateset->addUniform(cpv._isoProperty->getUniform());
222        else
223            stateset->addUniform(new osg::Uniform("IsoSurfaceValue",alphaFuncValue));
224
225        if (cpv._tfProperty.valid())
226        {
227            tf = dynamic_cast<osg::TransferFunction1D*>(cpv._tfProperty->getTransferFunction());
228        }
229
230        osg::ref_ptr<osg::TexGen> texgen = new osg::TexGen;
231        texgen->setMode(osg::TexGen::OBJECT_LINEAR);
232        texgen->setPlanesFromMatrix( geometryMatrix * osg::Matrix::inverse(imageMatrix));
233
234        if (masterLocator)
235        {
236            osg::ref_ptr<TexGenLocatorCallback> locatorCallback = new TexGenLocatorCallback(texgen, masterLocator, layerLocator);
237            masterLocator->addCallback(locatorCallback.get());
238            if (masterLocator != layerLocator)
239            {
240                if (layerLocator) layerLocator->addCallback(locatorCallback.get());
241            }
242        }
243
244        stateset->setTextureAttributeAndModes(texgenTextureUnit, texgen.get(), osg::StateAttribute::ON);
245    }
246
247
248    // set up 3D texture
249    osg::ref_ptr<osg::Image> image_3d = _volumeTile->getLayer()->getImage();
250    osg::ref_ptr<osg::Texture3D> texture3D = new osg::Texture3D;
251    {
252        osg::Texture::InternalFormatMode internalFormatMode = osg::Texture::USE_IMAGE_DATA_FORMAT;
253#if 1
254        osg::Texture::FilterMode minFilter = osg::Texture::LINEAR;
255        osg::Texture::FilterMode magFilter = osg::Texture::LINEAR;
256#else
257        osg::Texture::FilterMode minFilter = osg::Texture::NEAREST;
258        osg::Texture::FilterMode magFilter = osg::Texture::NEAREST;
259#endif
260
261        // set up the 3d texture itself,
262        // note, well set the filtering up so that mip mapping is disabled,
263        // gluBuild3DMipsmaps doesn't do a very good job of handled the
264        // imbalanced dimensions of the 256x256x4 texture.
265        texture3D->setResizeNonPowerOfTwoHint(false);
266        texture3D->setFilter(osg::Texture3D::MIN_FILTER,minFilter);
267        texture3D->setFilter(osg::Texture3D::MAG_FILTER, magFilter);
268        texture3D->setWrap(osg::Texture3D::WRAP_R,osg::Texture3D::CLAMP_TO_BORDER);
269        texture3D->setWrap(osg::Texture3D::WRAP_S,osg::Texture3D::CLAMP_TO_BORDER);
270        texture3D->setWrap(osg::Texture3D::WRAP_T,osg::Texture3D::CLAMP_TO_BORDER);
271        texture3D->setBorderColor(osg::Vec4(0.0,0.0,0.0,0.0));
272        if (image_3d->getPixelFormat()==GL_ALPHA ||
273            image_3d->getPixelFormat()==GL_LUMINANCE)
274        {
275            texture3D->setInternalFormatMode(osg::Texture3D::USE_USER_DEFINED_FORMAT);
276            texture3D->setInternalFormat(GL_INTENSITY);
277        }
278        else
279        {
280            texture3D->setInternalFormatMode(internalFormatMode);
281        }
282        texture3D->setImage(image_3d);
283
284        stateset->setTextureAttributeAndModes(volumeTextureUnit, texture3D, osg::StateAttribute::ON);
285
286        osg::ref_ptr<osg::Uniform> baseTextureSampler = new osg::Uniform("volumeTexture", int(volumeTextureUnit));
287        stateset->addUniform(baseTextureSampler.get());
288
289        osg::ref_ptr<osg::Uniform> volumeCellSize = new osg::Uniform("volumeCellSize", osg::Vec3(1.0f/static_cast<float>(image_3d->s()),1.0f/static_cast<float>(image_3d->t()),1.0f/static_cast<float>(image_3d->r())));
290        stateset->addUniform(volumeCellSize.get());
291
292        OSG_NOTICE<<"Texture Dimensions "<<image_3d->s()<<", "<<image_3d->t()<<", "<<image_3d->r()<<std::endl;
293    }
294
295    if (tf)
296    {
297        OSG_NOTICE<<"Setting up TransferFunction"<<std::endl;
298
299        float tfScale = 1.0f;
300        float tfOffset = 0.0f;
301
302        ImageLayer* imageLayer = dynamic_cast<ImageLayer*>(_volumeTile->getLayer());
303        if (imageLayer)
304        {
305            tfOffset = (imageLayer->getTexelOffset()[3] - tf->getMinimum()) / (tf->getMaximum() - tf->getMinimum());
306            tfScale = imageLayer->getTexelScale()[3] / (tf->getMaximum() - tf->getMinimum());
307        }
308        else
309        {
310            tfOffset = -tf->getMinimum() / (tf->getMaximum()-tf->getMinimum());
311            tfScale = 1.0f / (tf->getMaximum()-tf->getMinimum());
312        }
313        osg::ref_ptr<osg::Texture1D> tf_texture = new osg::Texture1D;
314        tf_texture->setImage(tf->getImage());
315
316        tf_texture->setResizeNonPowerOfTwoHint(false);
317        tf_texture->setFilter(osg::Texture::MIN_FILTER, osg::Texture::LINEAR);
318        tf_texture->setFilter(osg::Texture::MAG_FILTER, osg::Texture::LINEAR);
319        tf_texture->setWrap(osg::Texture::WRAP_R,osg::Texture::CLAMP_TO_EDGE);
320
321        unsigned int transferFunctionTextureUnit = volumeTextureUnit+1;
322
323        stateset->setTextureAttributeAndModes(transferFunctionTextureUnit, tf_texture.get(), osg::StateAttribute::ON);
324        stateset->addUniform(new osg::Uniform("tfTexture",int(transferFunctionTextureUnit)));
325        stateset->addUniform(new osg::Uniform("tfOffset",tfOffset));
326        stateset->addUniform(new osg::Uniform("tfScale",tfScale));
327
328    }
329
330    // creates CullFace attributes to apply to front/back StateSet configurations.
331    osg::ref_ptr<osg::CullFace> front_CullFace = new osg::CullFace(osg::CullFace::BACK);
332    osg::ref_ptr<osg::CullFace> back_CullFace = new osg::CullFace(osg::CullFace::FRONT);
333
334
335
336    osg::ref_ptr<osg::Shader> computeRayColorShader = osgDB::readRefShaderFile(osg::Shader::FRAGMENT, "shaders/volume_compute_ray_color.frag");
337#if 0
338    if (!computeRayColorShader)
339    {
340        #include "Shaders/volume_compute_ray_color_frag.cpp";
341        computeRayColorShader = new osg::Shader(osg::Shader::FRAGMENT, volume_compute_ray_color_frag);
342    }
343#endif
344
345    osg::ref_ptr<osg::Shader> main_vertexShader = osgDB::readRefShaderFile(osg::Shader::VERTEX, "shaders/volume_multipass.vert");
346#if 0
347    if (!main_vertexShader)
348    {
349        #include "Shaders/volume_multipass_vert.cpp"
350        main_vertexShader = new osg::Shader(osg::Shader::VERTEX, volume_multipass_vert));
351    }
352#endif
353
354    osg::ref_ptr<osg::Shader> front_main_fragmentShader = osgDB::readRefShaderFile(osg::Shader::FRAGMENT, "shaders/volume_multipass_front.frag");
355#if 0
356    if (!front_main_fragmentShader)
357    {
358        #include "Shaders/volume_multipass_front_frag.cpp"
359        front_main_fragmentShader = new osg::Shader(osg::Shader::VERTEX, volume_multipass_front_frag));
360    }
361#endif
362
363
364    osg::ref_ptr<osg::Shader> back_main_fragmentShader = osgDB::readRefShaderFile(osg::Shader::FRAGMENT, "shaders/volume_multipass_back.frag");
365#if 0
366    if (!back_main_fragmentShader)
367    {
368        #include "Shaders/volume_multipass_back_frag.cpp"
369        back_main_fragmentShader = new osg::Shader(osg::Shader::VERTEX, volume_multipass_back_frag));
370    }
371#endif
372
373    // clear any previous settings
374    _stateSetMap.clear();
375
376    osg::ref_ptr<osg::StateSet> front_stateset_prototype = new osg::StateSet;
377    osg::ref_ptr<osg::Program> front_program_prototype = new osg::Program;
378    {
379        front_stateset_prototype->setAttributeAndModes(front_CullFace.get(), osg::StateAttribute::ON);
380
381        front_program_prototype->addShader(main_vertexShader.get());
382        front_program_prototype->addShader(front_main_fragmentShader.get());
383        front_program_prototype->addShader(computeRayColorShader.get());
384    }
385
386    osg::ref_ptr<osg::StateSet> back_stateset_prototype = new osg::StateSet;
387    osg::ref_ptr<osg::Program> back_program_prototype = new osg::Program;
388    {
389        back_stateset_prototype->setAttributeAndModes(back_CullFace.get(), osg::StateAttribute::ON);
390
391        back_program_prototype->addShader(main_vertexShader.get());
392        back_program_prototype->addShader(back_main_fragmentShader.get());
393        back_program_prototype->addShader(computeRayColorShader.get());
394    }
395
396    // STANDARD_SHADERS
397    {
398        // STANDARD_SHADERS without TransferFunction
399        {
400            osg::ref_ptr<osg::Shader> accumulateSamplesShader = osgDB::readRefShaderFile(osg::Shader::FRAGMENT, "shaders/volume_accumulateSamples_standard.frag");
401            #if 0
402            if (!accumulateSamplesShader)
403            {
404                #include "Shaders/volume_accumulateSamples_standard_frag.cpp";
405                accumulateSamplesShader = new osg::Shader(osg::Shader::FRAGMENT, volume_accumulateSamples_standard_frag);
406            }
407            #endif
408
409            // front
410            _stateSetMap[STANDARD_SHADERS|FRONT_SHADERS] = createStateSet(front_stateset_prototype.get(), front_program_prototype.get(), accumulateSamplesShader.get());
411
412            // back
413            _stateSetMap[STANDARD_SHADERS|BACK_SHADERS] = createStateSet(back_stateset_prototype.get(), back_program_prototype.get(), accumulateSamplesShader.get());
414        }
415
416        // STANDARD_SHADERS with TransferFunction
417        if (tf)
418        {
419            osg::ref_ptr<osg::Shader> accumulateSamplesShader = osgDB::readRefShaderFile(osg::Shader::FRAGMENT, "shaders/volume_accumulateSamples_standard_tf.frag");
420            #if 0
421            if (!accumulateSamplesShader)
422            {
423                #include "Shaders/volume_accumulateSamples_standard_tf_frag.cpp";
424                accumulateSamplesShader = new osg::Shader(osg::Shader::FRAGMENT, volume_accumulateSamples_standard_tf_frag);
425            }
426            #endif
427
428
429            // front
430            _stateSetMap[STANDARD_SHADERS|FRONT_SHADERS|TF_SHADERS] = createStateSet(front_stateset_prototype.get(), front_program_prototype.get(), accumulateSamplesShader.get());
431
432            // back
433            _stateSetMap[STANDARD_SHADERS|BACK_SHADERS|TF_SHADERS] = createStateSet(back_stateset_prototype.get(), back_program_prototype.get(), accumulateSamplesShader.get());
434        }
435    }
436
437    // ISO_SHADERS
438    if (cpv._isoProperty.valid())
439    {
440        // ISO_SHADERS without TransferFunction
441        {
442            osg::ref_ptr<osg::Shader> accumulateSamplesShader = osgDB::readRefShaderFile(osg::Shader::FRAGMENT, "shaders/volume_accumulateSamples_iso.frag");
443            #if 0
444            if (!accumulateSamplesShader)
445            {
446                #include "Shaders/volume_accumulateSamples_iso_frag.cpp";
447                accumulateSamplesShader = new osg::Shader(osg::Shader::FRAGMENT, volume_accumulateSamples_iso_frag);
448            }
449            #endif
450
451            // front
452            _stateSetMap[ISO_SHADERS|FRONT_SHADERS] = createStateSet(front_stateset_prototype.get(), front_program_prototype.get(), accumulateSamplesShader.get());
453
454            // back
455            _stateSetMap[ISO_SHADERS|BACK_SHADERS] = createStateSet(back_stateset_prototype.get(), back_program_prototype.get(), accumulateSamplesShader.get());
456        }
457
458        // ISO_SHADERS with TransferFunction
459        if (tf)
460        {
461            osg::ref_ptr<osg::Shader> accumulateSamplesShader = osgDB::readRefShaderFile(osg::Shader::FRAGMENT, "shaders/volume_accumulateSamples_iso_tf.frag");
462            #if 0
463            if (!accumulateSamplesShader)
464            {
465                #include "Shaders/volume_accumulateSamples_standard_iso_tf_frag.cpp";
466                accumulateSamplesShader = new osg::Shader(osg::Shader::FRAGMENT, volume_accumulateSamples_standard_iso_tf_frag);
467            }
468            #endif
469
470
471            // front
472            _stateSetMap[ISO_SHADERS|FRONT_SHADERS|TF_SHADERS] = createStateSet(front_stateset_prototype.get(), front_program_prototype.get(), accumulateSamplesShader.get());
473
474            // back
475            _stateSetMap[ISO_SHADERS|BACK_SHADERS|TF_SHADERS] = createStateSet(back_stateset_prototype.get(), back_program_prototype.get(), accumulateSamplesShader.get());
476        }
477    }
478
479    // MIP_SHADERS
480    if (cpv._mipProperty.valid())
481    {
482        // MIP_SHADERS without TransferFunction
483        {
484            osg::ref_ptr<osg::Shader> accumulateSamplesShader = osgDB::readRefShaderFile(osg::Shader::FRAGMENT, "shaders/volume_accumulateSamples_mip.frag");
485            #if 0
486            if (!accumulateSamplesShader)
487            {
488                #include "Shaders/volume_accumulateSamples_mip_frag.cpp";
489                accumulateSamplesShader = new osg::Shader(osg::Shader::FRAGMENT, volume_accumulateSamples_mip_frag);
490            }
491            #endif
492
493            // front
494            _stateSetMap[MIP_SHADERS|FRONT_SHADERS] = createStateSet(front_stateset_prototype.get(), front_program_prototype.get(), accumulateSamplesShader.get());
495
496            // back
497            _stateSetMap[MIP_SHADERS|BACK_SHADERS] = createStateSet(back_stateset_prototype.get(), back_program_prototype.get(), accumulateSamplesShader.get());
498        }
499
500        // MIP_SHADERS with TransferFunction
501        if (tf)
502        {
503            osg::ref_ptr<osg::Shader> accumulateSamplesShader = osgDB::readRefShaderFile(osg::Shader::FRAGMENT, "shaders/volume_accumulateSamples_mip_tf.frag");
504            #if 0
505            if (!accumulateSamplesShader)
506            {
507                #include "Shaders/volume_accumulateSamples_standard_mip_tf_frag.cpp";
508                accumulateSamplesShader = new osg::Shader(osg::Shader::FRAGMENT, volume_accumulateSamples_standard_mip_tf_frag);
509            }
510            #endif
511
512
513            // front
514            _stateSetMap[MIP_SHADERS|FRONT_SHADERS|TF_SHADERS] = createStateSet(front_stateset_prototype.get(), front_program_prototype.get(), accumulateSamplesShader.get());
515
516            // back
517            _stateSetMap[MIP_SHADERS|BACK_SHADERS|TF_SHADERS] = createStateSet(back_stateset_prototype.get(), back_program_prototype.get(), accumulateSamplesShader.get());
518        }
519    }
520
521    // LIT_SHADERS
522    if (cpv._lightingProperty.valid())
523    {
524        // LIT_SHADERS without TransferFunction
525        {
526            osg::ref_ptr<osg::Shader> accumulateSamplesShader = osgDB::readRefShaderFile(osg::Shader::FRAGMENT, "shaders/volume_accumulateSamples_lit.frag");
527            #if 0
528            if (!accumulateSamplesShader)
529            {
530                #include "Shaders/volume_accumulateSamples_lit_frag.cpp";
531                accumulateSamplesShader = new osg::Shader(osg::Shader::FRAGMENT, volume_accumulateSamples_lit_frag);
532            }
533            #endif
534
535            // front
536            _stateSetMap[LIT_SHADERS|FRONT_SHADERS] = createStateSet(front_stateset_prototype.get(), front_program_prototype.get(), accumulateSamplesShader.get());
537
538            // back
539            _stateSetMap[LIT_SHADERS|BACK_SHADERS] = createStateSet(back_stateset_prototype.get(), back_program_prototype.get(), accumulateSamplesShader.get());
540        }
541
542        // MIP_SHADERS with TransferFunction
543        if (tf)
544        {
545            osg::ref_ptr<osg::Shader> accumulateSamplesShader = osgDB::readRefShaderFile(osg::Shader::FRAGMENT, "shaders/volume_accumulateSamples_lit_tf.frag");
546            #if 0
547            if (!accumulateSamplesShader)
548            {
549                #include "Shaders/volume_accumulateSamples_standard_lit_tf_frag.cpp";
550                accumulateSamplesShader = new osg::Shader(osg::Shader::FRAGMENT, volume_accumulateSamples_standard_lit_tf_frag);
551            }
552            #endif
553
554
555            // front
556            _stateSetMap[LIT_SHADERS|FRONT_SHADERS|TF_SHADERS] = createStateSet(front_stateset_prototype.get(), front_program_prototype.get(), accumulateSamplesShader.get());
557
558            // back
559            _stateSetMap[LIT_SHADERS|BACK_SHADERS|TF_SHADERS] = createStateSet(back_stateset_prototype.get(), back_program_prototype.get(), accumulateSamplesShader.get());
560        }
561    }
562
563
564    if (cpv._sampleRatioWhenMovingProperty.valid())
565    {
566        _whenMovingStateSet = new osg::StateSet;
567        _whenMovingStateSet->addUniform(cpv._sampleRatioWhenMovingProperty->getUniform(), osg::StateAttribute::OVERRIDE | osg::StateAttribute::ON);
568    }
569
570}
571
572void MultipassTechnique::update(osgUtil::UpdateVisitor* /*uv*/)
573{
574//    OSG_NOTICE<<"MultipassTechnique:update(osgUtil::UpdateVisitor* nv):"<<std::endl;
575}
576
577void MultipassTechnique::cull(osgUtil::CullVisitor* cv)
578{
579    std::string traversalPass;
580    bool postTraversal = cv->getUserValue("VolumeSceneTraversal", traversalPass) && traversalPass=="Post";
581
582    // OSG_NOTICE<<"MultipassTechnique::cull()  traversalPass="<<traversalPass<<std::endl;
583
584    if (postTraversal)
585    {
586
587        int shaderMask = 0;
588        if (_volumeTile->getLayer()->getProperty())
589        {
590            CollectPropertiesVisitor cpv;
591            _volumeTile->getLayer()->getProperty()->accept(cpv);
592
593            if (cpv._tfProperty.valid())
594            {
595                shaderMask |= TF_SHADERS;
596            }
597
598            if (cpv._isoProperty.valid())
599            {
600                shaderMask |= ISO_SHADERS;
601            }
602            else if (cpv._mipProperty.valid())
603            {
604                shaderMask |= MIP_SHADERS;
605            }
606            else if (cpv._lightingProperty.valid())
607            {
608                shaderMask |= LIT_SHADERS;
609            }
610            else
611            {
612                shaderMask |= STANDARD_SHADERS;
613            }
614        }
615
616        int shaderMaskFront = shaderMask | FRONT_SHADERS;
617        int shaderMaskBack = shaderMask | BACK_SHADERS;
618
619        OSG_NOTICE<<"shaderMaskFront "<<shaderMaskFront<<std::endl;
620        OSG_NOTICE<<"shaderMaskBack  "<<shaderMaskBack<<std::endl;
621
622
623        osg::ref_ptr<osg::StateSet> front_stateset = _stateSetMap[shaderMaskFront];
624        osg::ref_ptr<osg::StateSet> back_stateset = _stateSetMap[shaderMaskBack];
625        osg::ref_ptr<osg::StateSet> moving_stateset = (_whenMovingStateSet.valid() && isMoving(cv)) ? _whenMovingStateSet : 0;
626
627        if (moving_stateset.valid())
628        {
629            // OSG_NOTICE<<"Using MovingStateSet"<<std::endl;
630            cv->pushStateSet(moving_stateset.get());
631        }
632
633        if (front_stateset.valid())
634        {
635            OSG_NOTICE<<"Have front stateset"<<std::endl;
636            cv->pushStateSet(front_stateset.get());
637            _transform->accept(*cv);
638            cv->popStateSet();
639        }
640
641        if (back_stateset.valid())
642        {
643            OSG_NOTICE<<"Have back stateset"<<std::endl;
644            cv->pushStateSet(back_stateset.get());
645            _transform->accept(*cv);
646            cv->popStateSet();
647        }
648
649        if (moving_stateset.valid())
650        {
651            // OSG_NOTICE<<"Using MovingStateSet"<<std::endl;
652            cv->popStateSet();
653        }
654    }
655    else
656    {
657        osg::NodePath& nodePath = cv->getNodePath();
658        for(osg::NodePath::reverse_iterator itr = nodePath.rbegin();
659            itr != nodePath.rend();
660            ++itr)
661        {
662            osgVolume::VolumeScene* vs = dynamic_cast<osgVolume::VolumeScene*>(*itr);
663            if (vs)
664            {
665                vs->tileVisited(cv, getVolumeTile());
666                break;
667            }
668        }
669    }
670}
671
672void MultipassTechnique::cleanSceneGraph()
673{
674    OSG_NOTICE<<"MultipassTechnique::cleanSceneGraph()"<<std::endl;
675}
676
677void MultipassTechnique::traverse(osg::NodeVisitor& nv)
678{
679    // OSG_NOTICE<<"MultipassTechnique::traverse(osg::NodeVisitor& nv)"<<std::endl;
680    if (!_volumeTile) return;
681
682    // if app traversal update the frame count.
683    if (nv.getVisitorType()==osg::NodeVisitor::UPDATE_VISITOR)
684    {
685        if (_volumeTile->getDirty()) _volumeTile->init();
686
687        osgUtil::UpdateVisitor* uv = dynamic_cast<osgUtil::UpdateVisitor*>(&nv);
688        if (uv)
689        {
690            update(uv);
691            return;
692        }
693
694    }
695    else if (nv.getVisitorType()==osg::NodeVisitor::CULL_VISITOR)
696    {
697        osgUtil::CullVisitor* cv = dynamic_cast<osgUtil::CullVisitor*>(&nv);
698        if (cv)
699        {
700            cull(cv);
701            return;
702        }
703    }
704
705
706    if (_volumeTile->getDirty())
707    {
708        OSG_INFO<<"******* Doing init ***********"<<std::endl;
709        _volumeTile->init();
710    }
711}
712
713
714} // end of osgVolume namespace
Note: See TracBrowser for help on using the browser.