root/OpenSceneGraph/trunk/examples/osgprerender/osgprerender.cpp @ 4414

Revision 4414, 11.9 kB (checked in by robert, 9 years ago)

Added support for TextureCubeMap? into osgUtil::RenderToTextureStage?.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
Line 
1#include <osg/GLExtensions>
2#include <osg/Node>
3#include <osg/Geometry>
4#include <osg/Notify>
5#include <osg/MatrixTransform>
6#include <osg/Texture2D>
7#include <osg/Stencil>
8#include <osg/ColorMask>
9#include <osg/Depth>
10#include <osg/Billboard>
11#include <osg/Material>
12
13#include <osgGA/TrackballManipulator>
14#include <osgGA/FlightManipulator>
15#include <osgGA/DriveManipulator>
16
17#include <osgUtil/TransformCallback>
18#include <osgUtil/SmoothingVisitor>
19
20#include <osgDB/Registry>
21#include <osgDB/ReadFile>
22
23#include <osgProducer/Viewer>
24
25
26// call back which cretes a deformation field to oscilate the model.
27class MyGeometryCallback :
28    public osg::Drawable::UpdateCallback,
29    public osg::Drawable::AttributeFunctor
30{
31    public:
32   
33        MyGeometryCallback(const osg::Vec3& o,
34                           const osg::Vec3& x,const osg::Vec3& y,const osg::Vec3& z,
35                           double period,double xphase,double amplitude):
36            _firstCall(true),
37            _startTime(0.0),
38            _time(0.0),
39            _period(period),
40            _xphase(xphase),
41            _amplitude(amplitude),
42            _origin(o),
43            _xAxis(x),
44            _yAxis(y),
45            _zAxis(z) {}
46   
47        virtual void update(osg::NodeVisitor* nv,osg::Drawable* drawable)
48        {
49            const osg::FrameStamp* fs = nv->getFrameStamp();
50            double referenceTime = fs->getReferenceTime();
51            if (_firstCall)
52            {
53                _firstCall = false;
54                _startTime = referenceTime;
55            }
56           
57            _time = referenceTime-_startTime;
58           
59            drawable->accept(*this);
60            drawable->dirtyBound();
61           
62            osg::Geometry* geometry = dynamic_cast<osg::Geometry*>(drawable);
63            if (geometry)
64            {
65                osgUtil::SmoothingVisitor::smooth(*geometry);
66            }
67           
68        }
69       
70        virtual void apply(osg::Drawable::AttributeType type,unsigned int count,osg::Vec3* begin)
71        {
72            if (type == osg::Drawable::VERTICES)
73            {
74                const float TwoPI=2.0f*osg::PI;
75                const float phase = -_time/_period;
76               
77                osg::Vec3* end = begin+count;
78                for (osg::Vec3* itr=begin;itr<end;++itr)
79                {
80                    osg::Vec3 dv(*itr-_origin);
81                    osg::Vec3 local(dv*_xAxis,dv*_yAxis,dv*_zAxis);
82                   
83                    local.z() = local.x()*_amplitude*
84                                sinf(TwoPI*(phase+local.x()*_xphase));
85                   
86                    (*itr) = _origin +
87                             _xAxis*local.x()+
88                             _yAxis*local.y()+
89                             _zAxis*local.z();
90                }
91            }
92        }
93
94        bool    _firstCall;
95
96        double  _startTime;
97        double  _time;
98       
99        double  _period;
100        double  _xphase;
101        float   _amplitude;
102
103        osg::Vec3   _origin;
104        osg::Vec3   _xAxis;
105        osg::Vec3   _yAxis;
106        osg::Vec3   _zAxis;
107       
108};
109
110osg::Node* createPreRenderSubGraph(osg::Node* subgraph, unsigned tex_width, unsigned tex_height, osg::CameraNode::RenderTargetImplementation renderImplementation)
111{
112    if (!subgraph) return 0;
113
114    // create a group to contain the flag and the pre rendering camera.
115    osg::Group* parent = new osg::Group;
116
117    // texture to render to and to use for rendering of flag.
118    osg::Texture2D* texture = new osg::Texture2D;
119    texture->setTextureSize(tex_width, tex_height);
120    texture->setInternalFormat(GL_RGBA);
121    texture->setFilter(osg::Texture2D::MIN_FILTER,osg::Texture2D::LINEAR);
122    texture->setFilter(osg::Texture2D::MAG_FILTER,osg::Texture2D::LINEAR);
123
124    // first create the geometry of the flag of which to view.
125    {
126        // create the to visualize.
127        osg::Geometry* polyGeom = new osg::Geometry();
128
129        polyGeom->setSupportsDisplayList(false);
130
131        osg::Vec3 origin(0.0f,0.0f,0.0f);
132        osg::Vec3 xAxis(1.0f,0.0f,0.0f);
133        osg::Vec3 yAxis(0.0f,0.0f,1.0f);
134        osg::Vec3 zAxis(0.0f,-1.0f,0.0f);
135        float height = 100.0f;
136        float width = 200.0f;
137        int noSteps = 20;
138
139        osg::Vec3Array* vertices = new osg::Vec3Array;
140        osg::Vec3 bottom = origin;
141        osg::Vec3 top = origin; top.z()+= height;
142        osg::Vec3 dv = xAxis*(width/((float)(noSteps-1)));
143
144        osg::Vec2Array* texcoords = new osg::Vec2Array;
145        osg::Vec2 bottom_texcoord(0.0f,0.0f);
146        osg::Vec2 top_texcoord(0.0f,1.0f);
147        osg::Vec2 dv_texcoord(1.0f/(float)(noSteps-1),0.0f);
148
149        for(int i=0;i<noSteps;++i)
150        {
151            vertices->push_back(top);
152            vertices->push_back(bottom);
153            top+=dv;
154            bottom+=dv;
155
156            texcoords->push_back(top_texcoord);
157            texcoords->push_back(bottom_texcoord);
158            top_texcoord+=dv_texcoord;
159            bottom_texcoord+=dv_texcoord;
160        }
161
162
163        // pass the created vertex array to the points geometry object.
164        polyGeom->setVertexArray(vertices);
165
166        polyGeom->setTexCoordArray(0,texcoords);
167
168
169        osg::Vec4Array* colors = new osg::Vec4Array;
170        colors->push_back(osg::Vec4(1.0f,1.0f,1.0f,1.0f));
171        polyGeom->setColorArray(colors);
172        polyGeom->setColorBinding(osg::Geometry::BIND_OVERALL);
173
174        polyGeom->addPrimitiveSet(new osg::DrawArrays(osg::PrimitiveSet::QUAD_STRIP,0,vertices->size()));
175
176        // new we need to add the texture to the Drawable, we do so by creating a
177        // StateSet to contain the Texture StateAttribute.
178        osg::StateSet* stateset = new osg::StateSet;
179
180        stateset->setTextureAttributeAndModes(0, texture,osg::StateAttribute::ON);
181
182        polyGeom->setStateSet(stateset);
183
184        polyGeom->setUpdateCallback(new MyGeometryCallback(origin,xAxis,yAxis,zAxis,1.0,1.0/width,0.2f));
185
186        osg::Geode* geode = new osg::Geode();
187        geode->addDrawable(polyGeom);
188       
189        parent->addChild(geode);
190
191    }
192
193
194    // then create the camera node to do the render to texture
195    {   
196        osg::CameraNode* camera = new osg::CameraNode;
197
198        // set up the background color and clear mask.
199        camera->setClearColor(osg::Vec4(0.1f,0.1f,0.3f,1.0f));
200        camera->setClearMask(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
201
202        const osg::BoundingSphere& bs = subgraph->getBound();
203        if (!bs.valid())
204        {
205            return subgraph;
206        }
207
208        float znear = 1.0f*bs.radius();
209        float zfar  = 3.0f*bs.radius();
210
211        // 2:1 aspect ratio as per flag geomtry below.
212        float proj_top   = 0.25f*znear;
213        float proj_right = 0.5f*znear;
214
215        znear *= 0.9f;
216        zfar *= 1.1f;
217
218        // set up projection.
219        camera->setProjectionMatrixAsFrustum(-proj_right,proj_right,-proj_top,proj_top,znear,zfar);
220
221        // set view
222        camera->setReferenceFrame(osg::Transform::ABSOLUTE_RF);
223        camera->setViewMatrixAsLookAt(bs.center()-osg::Vec3(0.0f,2.0f,0.0f)*bs.radius(),bs.center(),osg::Vec3(0.0f,0.0f,1.0f));
224
225        // set viewport
226        camera->setViewport(0,0,tex_width,tex_height);
227
228        // set the camera to render before the main camera.
229        camera->setRenderOrder(osg::CameraNode::PRE_RENDER);
230
231        // tell the camera to use OpenGL frame buffer object where supported.
232        camera->setRenderTargetImplmentation(renderImplementation);
233
234        // attach the texture and use it as the color buffer.
235        camera->attach(osg::CameraNode::COLOR_BUFFER, texture);
236
237        // add subgraph to render
238        camera->addChild(subgraph);
239
240        parent->addChild(camera);
241
242    }   
243
244    return parent;
245}
246
247int main( int argc, char **argv )
248{
249    // use an ArgumentParser object to manage the program arguments.
250    osg::ArgumentParser arguments(&argc,argv);
251
252    // set up the usage document, in case we need to print out how to use this program.
253    arguments.getApplicationUsage()->setDescription(arguments.getApplicationName()+" is the example which demonstrates pre rendering of scene to a texture, and then apply this texture to geometry.");
254    arguments.getApplicationUsage()->setCommandLineUsage(arguments.getApplicationName()+" [options] filename ...");
255    arguments.getApplicationUsage()->addCommandLineOption("-h or --help","Display this information");
256    arguments.getApplicationUsage()->addCommandLineOption("--fbo","Use Frame Buffer Object for render to texture, where supported.");
257    arguments.getApplicationUsage()->addCommandLineOption("--fb","Use FrameBuffer for render to texture.");
258    arguments.getApplicationUsage()->addCommandLineOption("--pbuffer","Use Pixel Buffer for render to texture, where supported.");
259    arguments.getApplicationUsage()->addCommandLineOption("--window","Use a seperate Window for render to texture.");
260    arguments.getApplicationUsage()->addCommandLineOption("--width","Set the width of the render to texture");
261    arguments.getApplicationUsage()->addCommandLineOption("--height","Set the height of the render to texture");
262   
263    // construct the viewer.
264    osgProducer::Viewer viewer(arguments);
265
266    // set up the value with sensible default event handlers.
267    viewer.setUpViewer(osgProducer::Viewer::STANDARD_SETTINGS);
268
269    // get details on keyboard and mouse bindings used by the viewer.
270    viewer.getUsage(*arguments.getApplicationUsage());
271
272    // if user request help write it out to cout.
273    if (arguments.read("-h") || arguments.read("--help"))
274    {
275        arguments.getApplicationUsage()->write(std::cout);
276        return 1;
277    }
278
279    unsigned tex_width = 1024;
280    unsigned tex_height = 512;
281    while (arguments.read("--width", tex_width)) {}
282    while (arguments.read("--height", tex_height)) {}
283
284    osg::CameraNode::RenderTargetImplementation renderImplementation = osg::CameraNode::FRAME_BUFFER_OBJECT;
285   
286    while (arguments.read("--fbo")) { renderImplementation = osg::CameraNode::FRAME_BUFFER_OBJECT; }
287    while (arguments.read("--pbuffer")) { renderImplementation = osg::CameraNode::PIXEL_BUFFER; }
288    while (arguments.read("--fb")) { renderImplementation = osg::CameraNode::FRAME_BUFFER; }
289    while (arguments.read("--window")) { renderImplementation = osg::CameraNode::SEPERATE_WINDOW; }
290
291
292    // any option left unread are converted into errors to write out later.
293    arguments.reportRemainingOptionsAsUnrecognized();
294
295    // report any errors if they have occured when parsing the program aguments.
296    if (arguments.errors())
297    {
298        arguments.writeErrorMessages(std::cout);
299        return 1;
300    }
301   
302    if (arguments.argc()<=1)
303    {
304        arguments.getApplicationUsage()->write(std::cout,osg::ApplicationUsage::COMMAND_LINE_OPTION);
305        return 1;
306    }
307
308   
309    // load the nodes from the commandline arguments.
310    osg::Node* loadedModel = osgDB::readNodeFiles(arguments);
311    if (!loadedModel)
312    {
313        return 1;
314    }
315   
316    // create a transform to spin the model.
317    osg::MatrixTransform* loadedModelTransform = new osg::MatrixTransform;
318    loadedModelTransform->addChild(loadedModel);
319
320    osg::NodeCallback* nc = new osgUtil::TransformCallback(loadedModelTransform->getBound().center(),osg::Vec3(0.0f,0.0f,1.0f),osg::inDegrees(45.0f));
321    loadedModelTransform->setUpdateCallback(nc);
322
323    osg::Group* rootNode = new osg::Group();
324    rootNode->addChild(createPreRenderSubGraph(loadedModelTransform,tex_width,tex_height, renderImplementation));
325
326
327    // add model to the viewer.
328    viewer.setSceneData( rootNode );
329
330
331    // create the windows and run the threads.
332    viewer.realize();
333
334    while( !viewer.done() )
335    {
336        // wait for all cull and draw threads to complete.
337        viewer.sync();
338
339        // update the scene by traversing it with the the update visitor which will
340        // call all node update callbacks and animations.
341        viewer.update();
342         
343        // fire off the cull and draw traversals of the scene.
344        viewer.frame();
345       
346    }
347   
348    // wait for all cull and draw threads to complete before exit.
349    viewer.sync();
350
351    return 0;
352}
Note: See TracBrowser for help on using the browser.