Ticket #211: 29FBOTexture_Cluster.cpp

File 29FBOTexture_Cluster.cpp, 13.7 kB (added by rstanchak, 11 months ago)

Modified tutorial file to work in cluster setting

Line 
1 // OpenSG FBO example: 29FBOTexture.cpp
2 //
3 // Shows how to use the FBOViewport for render-to-texture
4 //
5
6 #include <OpenSG/OSGGLUT.h>
7 #include <OpenSG/OSGConfig.h>
8 #include <OpenSG/OSGSimpleSceneManager.h>
9 #include <OpenSG/OSGGLUTWindow.h>
10 #include <OpenSG/OSGGradientBackground.h>
11 #include <OpenSG/OSGSceneFileHandler.h>
12 #include <OpenSG/OSGSimpleGeometry.h>
13 #include <OpenSG/OSGImage.h>
14 #include <OpenSG/OSGTextureChunk.h>
15 #include <OpenSG/OSGFBOViewport.h>
16 #include <OpenSG/OSGSimpleTexturedMaterial.h>
17 #include <OpenSG/OSGMatrixUtility.h>
18 #include <OpenSG/OSGPointLight.h>
19 #include <OpenSG/OSGQuaternion.h>
20 #include <OpenSG/OSGGeoFunctions.h>
21 #include <OpenSG/OSGImageFunctions.h>
22 #include <OpenSG/OSGTwoSidedLightingChunk.h>
23 #include <OpenSG/OSGComponentTransform.h>
24 #include <OpenSG/OSGImageFileType.h>
25 #include <OpenSG/OSGTextureTransformChunk.h>
26 #include <OpenSG/OSGRemoteAspect.h>
27
28 #include "FlexiviewWindow.hpp"
29
30 OSG_USING_NAMESPACE
31
32 // globals
33 SimpleSceneManager *mgr          (NULL);
34 FBOViewportPtr      fboVP        (NullFC);
35 TransformPtr        fboSceneTrans(NullFC);
36 NodePtr             fboCamBeacon (NullFC);
37 GeometryPtr         flagGeo      (NullFC);
38 FlexiviewWindow     _win;
39 RenderAction *        fboRA;
40
41 // flag parameters
42 const float flagHeight   = 8.0f;
43 const float flagWidth    = 16.0f;
44 const int   flagGeoHor   = (int)flagWidth  * 3;
45 const int   flagGeoVert  = (int)flagHeight / 2;
46 const float flagWaveDamp = 0.06f;
47
48 const float poleHeight   = 24.0f;
49 const float poleDia      = poleHeight * 0.01f;
50
51 // fbo size
52 const int   fboWidth     = (int)flagWidth  * 32;
53 const int   fboHeight    = (int)flagHeight * 32;
54
55 // forward declarations
56 Matrix showAll(NodePtr root, PerspectiveCameraPtr cam);
57 void animateFlag(Real32 t);
58 void spinFBOScene(Real32 t);
59 SimpleTexturedMaterialPtr createWoodMaterial();
60 NodePtr buildFlag(TextureChunkPtr fboTexture, const int &flagHor, const int &flagVert);
61 NodePtr buildFBOScene(int argc, char **argv );
62 void setupFBO(TextureChunkPtr fboTexture, WindowPtr gwin, NodePtr fboScene );
63          
64 // redraw the window
65 void display(void)
66 {
67     // get the current time
68         Real32 t = glutGet(GLUT_ELAPSED_TIME)*0.1;
69
70
71         // animate flag
72     animateFlag(t);
73
74         // spin the fbo scene
75     spinFBOScene(t);
76
77         //fboVP->render(fboRA);
78
79         // render main scene
80         mgr->redraw();
81         _win.redraw();
82 }
83
84 // react to size changes
85 void reshape(int w, int h)
86 {
87         ::mgr->resize(w,h);
88         glutPostRedisplay();
89 }
90
91 // react to mouse button presses
92 void mouse(int button, int state, int x, int y)
93 {
94         if (state)
95                 ::mgr->mouseButtonRelease(button, x, y);
96         else
97                 ::mgr->mouseButtonPress(button, x, y);
98
99         glutPostRedisplay();
100 }
101
102 // react to mouse motions with pressed buttons
103 void motion(int x, int y)
104 {
105         ::mgr->mouseMove(x, y);
106         glutPostRedisplay();
107 }
108
109 // react to keys
110 void keyboard(unsigned char k, int, int)
111 {
112     switch(k)
113     {
114     case 27:    exit(1);
115     default:    break;
116     }
117 }
118
119 int main(int argc, char **argv)
120 {
121         // OpenSG init
122     osgInit(argc,argv);
123
124     // GLUT init
125     glutInit(&argc, argv);
126     glutInitWindowSize(800,600);
127     glutInitDisplayMode(GLUT_RGB | GLUT_DEPTH | GLUT_DOUBLE);
128
129     int winid = glutCreateWindow("OpenSG " OSG_VERSION_STRING " FBO example");
130
131     // register GLUT callbacks
132     glutReshapeFunc(reshape);
133     glutDisplayFunc(display);
134     glutIdleFunc(display);
135     glutMouseFunc(mouse);
136     glutMotionFunc(motion);
137     glutKeyboardFunc(keyboard);
138
139
140         // create a GLUTWindow
141     _win.init(winid, argc, argv);
142         beginEditCP(_win.osgWindow);//Window
143                 _win.osgWindow->init();
144         endEditCP(_win.osgWindow);
145
146         // create the texture that is used as render target by the sub-scene
147         // and as texture in the main scene
148         TextureChunkPtr fboTexture = TextureChunk::create();
149         beginEditCP(fboTexture);
150             fboTexture->setEnvMode(GL_MODULATE);
151         endEditCP(fboTexture);
152          
153         // create the main scene
154     NodePtr mainScene = buildFlag(fboTexture, ::flagGeoHor, ::flagGeoVert);
155
156     // create the fbo scene
157     NodePtr fboScene  = buildFBOScene(argc, argv);
158    
159     // create and setup the FBO
160     setupFBO(fboTexture, _win.osgWindow, fboScene);
161        
162         // create the SimpleSceneManager helper
163         ::mgr = new SimpleSceneManager;
164        
165     // create the window and initial camera/viewport
166         ::mgr->setWindow(_win.osgWindow);
167
168         // tell the manager what to manage
169         ::mgr->setRoot(mainScene);
170
171         // show the whole scene
172         ::mgr->showAll();
173
174         // set a nicer background
175         GradientBackgroundPtr bkg = GradientBackground::create();
176         beginEditCP(bkg);
177                 bkg->addLine(Color3f(0.7, 0.7, 0.8), 0);
178                 bkg->addLine(Color3f(0.0, 0.1, 0.3), 1);
179         endEditCP(bkg);
180         _win.osgWindow->getPort(0)->setBackground(bkg);
181        
182     // enable logo
183     mgr->useOpenSGLogo();
184    
185         beginEditCP(_win.osgWindow);//Window
186                 _win.osgWindow->addPort( fboVP );
187         endEditCP(_win.osgWindow);
188
189 #if 0
190         fboRA = RenderAction::create();
191
192         // create a stupid glut window so FBO works
193         GLUTWindowPtr gwin = GLUTWindow::create();
194         beginEditCP(gwin);
195                 gwin->setId(winid);
196                 gwin->init();
197         endEditCP(gwin);
198         fboRA->setWindow(gwin.getCPtr());
199 #endif
200
201     // make sure the window is setup before rendering to the FBO
202     mgr->redraw();
203
204     // enter the GLUT main loop
205         glutMainLoop();
206
207         return 0;
208 }
209
210 // copied from SimpleSceneManager
211 Matrix showAll(NodePtr root, PerspectiveCameraPtr cam)
212 {
213     root->updateVolume();
214
215     Vec3f min,max;
216     root->getVolume().getBounds( min, max );
217     Vec3f d = max - min;
218
219     if(d.length() < Eps) // Nothing loaded? Use a unity box
220     {
221         min.setValues(-1.f,-1.f,-1.f);
222         max.setValues( 1.f, 1.f, 1.f);
223         d = max - min;
224     }
225
226     Real32 dist = osgMax(d[0],d[1]) / (2 * osgtan(cam->getFov() / 2.f));
227
228     Vec3f up(0,1,0);
229     Pnt3f at((min[0] + max[0]) * .5f,(min[1] + max[1]) * .5f,(min[2] + max[2]) * .5f);
230     Pnt3f from = at;
231     from[2]+=(dist+fabs(max[2]-min[2])*0.5f);
232
233     // set the camera to go from 1% of the object to twice its size
234     Real32 diag = osgMax(osgMax(d[0], d[1]), d[2]);
235     beginEditCP(cam);
236         cam->setFar  (10 * diag);
237     endEditCP(cam);
238
239     Matrix m;
240     MatrixLookAt(m, from, at, up);
241
242     return m;
243 }
244
245 void animateFlag( Real32 t )
246 {
247     // get positions
248     GeoPositions3fPtr pos = GeoPositions3fPtr::dcast(::flagGeo->getPositions());
249     beginEditCP(pos, GeoPositions3f::GeoPropDataFieldMask);
250         Pnt3f offset(-0.5f * flagWidth, 3, 0);
251         float t2 = 8.0f * t;
252         for(UInt32 i = 0; i < pos->getSize(); ++i)
253         {
254             Pnt3f p = pos->getValue(i);
255             float v = p.dist(offset);
256             // the flag geometry is centered at the origin
257             // we need to offset the wave calculations
258             float x = p[0] - offset.x();
259             // make a wave, dampened towards the poleS
260             p[2]  = x * flagWaveDamp * osgsin(v-t2);
261             pos->setValue(p, i);
262         }
263     endEditCP(pos, GeoPositions3f::GeoPropDataFieldMask);   
264    
265     // correct normals
266     calcVertexNormals(::flagGeo);
267 }
268
269 void spinFBOScene( Real32 t )
270 {
271     beginEditCP(::fboSceneTrans, Transform::MatrixFieldMask);
272         Matrix m;
273         Quaternion q;
274         q.setValueAsAxisDeg(0, 1, 0, t * 16.66f);
275         m.setRotate(q);
276         ::fboSceneTrans->setMatrix(m);
277     endEditCP(::fboSceneTrans, Transform::MatrixFieldMask);
278 }
279
280
281 // create a wood texture
282 SimpleTexturedMaterialPtr createWoodMaterial()
283 {
284     SimpleTexturedMaterialPtr mat = SimpleTexturedMaterial::create();
285     beginEditCP(mat);
286         ImagePtr img = Image::create();
287         createNoise(img, Image::OSG_L_PF, 7, 64);
288         mat->setImage(img);
289         mat->setEnvMode(GL_MODULATE);
290         mat->setDiffuse(Color3f(0.9f, 0.57f, 0.1f));
291         mat->setSpecular(Color3f(0.2f, 0.2f, 0.1f));
292         TextureTransformChunkPtr ttrans = TextureTransformChunk::create();
293         beginEditCP(ttrans);
294             Matrix m;
295             m.setScale(2.0, 8.0, 2.0);
296             ttrans->setMatrix(m);
297         endEditCP(ttrans);
298         mat->addChunk(ttrans);
299     endEditCP(mat);
300
301     return mat;
302 }
303
304 NodePtr buildFlag(TextureChunkPtr fboTexture, const int &flagHor, const int &flagVert)
305 {
306     NodePtr flagScene = makeCoredNode<Group>();
307    
308     ::flagGeo = makePlaneGeo(flagWidth, flagHeight, flagHor, flagVert);
309    
310     // disable caching as we will change this geometry every frame
311     beginEditCP(::flagGeo);
312         ::flagGeo->setVbo(false);
313         ::flagGeo->setDlistCache(false);
314     endEditCP(::flagGeo);
315
316     SimpleMaterialPtr fboMaterial = SimpleMaterial::create();
317     beginEditCP(fboMaterial);
318         fboMaterial->addChunk(fboTexture);
319        
320         // add a light glossy effect (environment noise-map)
321         {
322             ImagePtr noise = Image::create();
323             createNoise(noise, Image::OSG_I_PF, 5, 256);
324             beginEditCP(noise);
325                 // make noise image darker (as it will be GL_ADDed)
326                 for(int i = 0; i < noise->getSize(); ++i)
327                   noise->getData()[i] >>= 2; // *= 0.125
328             endEditCP(noise);
329             TextureChunkPtr gloss = TextureChunk::create();
330             beginEditCP(gloss);
331                 gloss->setImage(noise);
332                 gloss->setEnvMode(GL_ADD);
333             endEditCP(gloss);
334             TexGenChunkPtr envMap = TexGenChunk::create();
335             beginEditCP(envMap);
336                 envMap->setGenFuncS(GL_SPHERE_MAP);
337                 envMap->setGenFuncT(GL_SPHERE_MAP);
338             endEditCP(envMap);
339             // add for use with 2nd texture unit
340             fboMaterial->addChunk(gloss, 1);
341             fboMaterial->addChunk(envMap, 1);
342         }
343  
344         fboMaterial->addChunk(TwoSidedLightingChunk::create());
345         fboMaterial->setSpecular(Color3f(0.7f, 0.7f, 0.7f));
346         fboMaterial->setDiffuse(Color3f(0.22f, 0.2f, 0.2f));
347     endEditCP(fboMaterial);
348
349
350     beginEditCP(::flagGeo);
351         ::flagGeo->setMaterial(fboMaterial);
352     endEditCP(::flagGeo);
353
354     // create transform node to hook up the flag to the pole
355     ComponentTransformPtr flagTrans;
356     NodePtr flag = makeCoredNode<ComponentTransform>(&flagTrans);
357     beginEditCP(flagTrans);
358         Vec3f v(0.5f * flagWidth, 0.5f * (poleHeight - flagHeight) , 0.0f);
359         flagTrans->setTranslation(v);
360     endEditCP(flagTrans);
361
362     // attach flag-geometry to transform-node
363     beginEditCP(flag);
364         flag->addChild(makeNodeFor(::flagGeo));
365     endEditCP(flag);
366
367     // build flag pole
368     NodePtr pole = makeCylinder(poleHeight, poleDia, 24, true, true, true);
369     MaterialPtr woodMat = createWoodMaterial();
370     GeometryPtr cyl = GeometryPtr::dcast(pole->getCore());
371     beginEditCP(cyl);
372         cyl->setMaterial(woodMat);
373     endEditCP(cyl);
374
375     // attach objects to group node
376     beginEditCP(flagScene);
377         flagScene->addChild(flag);
378         flagScene->addChild(pole);
379     endEditCP(flagScene);
380
381     return flagScene;
382 }
383
384 NodePtr buildFBOScene( int argc, char ** argv )
385 {
386     PointLightPtr light;
387     NodePtr fboRoot = makeCoredNode<PointLight>(&light);
388     ::fboCamBeacon = makeNodeFor(Transform::create());
389
390     // attach camera beacon to root node
391     beginEditCP(fboRoot);
392         fboRoot->addChild(::fboCamBeacon);
393     endEditCP(fboRoot);
394
395     // set camera beacon as light beacon (-> headlight)
396     beginEditCP(light);
397         light->setBeacon(::fboCamBeacon);
398         light->setOn(true);
399     endEditCP(light);
400
401     // load given model, the cow, or make a torus
402     NodePtr scene;
403     if(argc >= 2)
404         scene = SceneFileHandler::the().read(argv[1]);
405     else
406         scene = SceneFileHandler::the().read("Data/cow.obj.gz");
407
408     // fallback if loading failed
409     if(!scene)
410         scene = makeTorus(0.3, 4, 16, 64);
411
412     NodePtr fboScene = makeCoredNode<Transform>(&::fboSceneTrans);
413     beginEditCP(fboScene);
414     beginEditCP(fboRoot);
415         fboScene->addChild(scene);
416         fboRoot->addChild(fboScene);
417     endEditCP(fboRoot);
418     endEditCP(fboScene);
419
420     return fboRoot;
421 }
422
423 void setupFBO( TextureChunkPtr fboTexture, WindowPtr gwin, NodePtr fboScene )
424 {
425     // setup FBO
426     ImagePtr img = Image::create();
427     beginEditCP(img);
428         img->set(Image::OSG_RGBA_PF, ::fboWidth, ::fboHeight);
429     endEditCP(img);
430     beginEditCP(fboTexture);
431         fboTexture->setMinFilter(GL_LINEAR);
432         fboTexture->setMagFilter(GL_LINEAR);
433         fboTexture->setTarget(GL_TEXTURE_2D);
434         fboTexture->setInternalFormat(GL_RGBA8);
435         fboTexture->setImage(img);
436     endEditCP(fboTexture);
437
438
439     // add background
440     GradientBackgroundPtr bg = GradientBackground::create();
441     beginEditCP(bg);
442         // flag of neutral-moresnet
443         bg->addLine(Color3f(0.0, 0.0, 0.8), 0.000);
444         bg->addLine(Color3f(0.0, 0.0, 0.8), 0.333);
445
446         bg->addLine(Color3f(0.8, 0.8, 0.8), 0.333);
447         bg->addLine(Color3f(0.8, 0.8, 0.8), 0.666);
448
449         bg->addLine(Color3f(0.0, 0.0, 0.0), 0.666);
450         bg->addLine(Color3f(0.0, 0.0, 0.0), 1.000);
451     endEditCP(bg);
452
453
454     // setup camera
455     PerspectiveCameraPtr fboCam = PerspectiveCamera::create();
456     beginEditCP(fboCam);
457         // we already compensated aspect ratio with the texture/fbo sizes
458         fboCam->setAspect(1.0);
459         fboCam->setFov(osgdegree2rad(60));
460         fboCam->setNear(0.01);
461         fboCam->setFar(100);
462         fboCam->setBeacon(::fboCamBeacon);
463     endEditCP(fboCam);
464
465     // create FBOViewport
466     ::fboVP = FBOViewport::create();
467     beginEditCP(::fboVP);
468         ::fboVP->setSize(0, 0, ::fboWidth - 1, ::fboHeight - 1);
469         ::fboVP->setStorageWidth(::fboWidth);
470         ::fboVP->setStorageHeight(::fboHeight);
471         ::fboVP->setBackground(bg);
472         ::fboVP->setCamera(fboCam);
473         ::fboVP->setParent(gwin);
474         // attach texture as render target
475         ::fboVP->getTextures().push_back(fboTexture);
476         ::fboVP->setRoot(fboScene);
477                 ::fboVP->setFboOn(true);
478     endEditCP(::fboVP);
479
480     // set the fbo camera to show the whole model
481     TransformPtr trans = TransformPtr::dcast(::fboCamBeacon->getCore());
482     beginEditCP(trans, Transform::MatrixFieldMask);
483         trans->setMatrix(showAll(fboScene, fboCam));
484     endEditCP(trans, Transform::MatrixFieldMask);
485 }