fixed: compile issue
[opensg.git] / Examples / Simple / fbotexture.cpp
blob7161cee5429a59c51280bf85db741722b50c1e37
1 // OpenSG Tutorial Example: FBO Texture
2 //
3 // This example shows how to use FrameBufferObject and SimpleStage to render
4 // a subtree of the scene graph to a texture and then use that texture
5 // when drawing another part of the scene.
6 //
7 // The scene graph constructed in this example looks like this:
8 //
9 // scene[Group] -+- fboScene[SimpleStage] --- fboScene --- {loaded model +
10 // | light and beacon}
11 // |
12 // +- flagScene[Group] --- {flag and pole}
14 // If you run this example and zoom in close to the flag or move it to the
15 // edge of the screen the model on it may stop rotating. This happens because
16 // the model actually is positioned about half way up the flag's pole and
17 // get's frustum culled if that part of the scene is outside the camera
18 // frustum.
20 #ifdef OSG_BUILD_ACTIVE
21 // Headers
22 #include <OSGGLUT.h>
23 #include <OSGConfig.h>
24 #include <OSGSimpleGeometry.h>
25 #include <OSGGLUTWindow.h>
26 #include <OSGSimpleSceneManager.h>
27 #include <OSGBaseFunctions.h>
28 #include <OSGTransform.h>
29 #include <OSGComponentTransform.h>
31 #include <OSGSimpleStage.h>
32 #include <OSGPointLight.h>
33 #include <OSGFrameBufferObject.h>
34 #include <OSGTextureBuffer.h>
35 #include <OSGRenderBuffer.h>
36 #include <OSGTextureObjChunk.h>
37 #include <OSGTextureEnvChunk.h>
38 #include <OSGTexGenChunk.h>
39 #include <OSGTwoSidedLightingChunk.h>
40 #include <OSGSceneFileHandler.h>
41 #include <OSGImageFunctions.h>
42 #include <OSGSimpleTexturedMaterial.h>
43 #include <OSGTextureTransformChunk.h>
44 #include <OSGGradientBackground.h>
45 #include <OSGPerspectiveCamera.h>
46 #else
47 // Headers
48 #include <OpenSG/OSGGLUT.h>
49 #include <OpenSG/OSGConfig.h>
50 #include <OpenSG/OSGSimpleGeometry.h>
51 #include <OpenSG/OSGGLUTWindow.h>
52 #include <OpenSG/OSGSimpleSceneManager.h>
53 #include <OpenSG/OSGBaseFunctions.h>
54 #include <OpenSG/OSGTransform.h>
55 #include <OpenSG/OSGComponentTransform.h>
57 #include <OpenSG/OSGSimpleStage.h>
58 #include <OpenSG/OSGPointLight.h>
59 #include <OpenSG/OSGFrameBufferObject.h>
60 #include <OpenSG/OSGTextureBuffer.h>
61 #include <OpenSG/OSGRenderBuffer.h>
62 #include <OpenSG/OSGTextureObjChunk.h>
63 #include <OpenSG/OSGTextureEnvChunk.h>
64 #include <OpenSG/OSGTexGenChunk.h>
65 #include <OpenSG/OSGTwoSidedLightingChunk.h>
66 #include <OpenSG/OSGSceneFileHandler.h>
67 #include <OpenSG/OSGImageFunctions.h>
68 #include <OpenSG/OSGSimpleTexturedMaterial.h>
69 #include <OpenSG/OSGTextureTransformChunk.h>
70 #include <OpenSG/OSGGradientBackground.h>
71 #include <OpenSG/OSGPerspectiveCamera.h>
72 #endif
74 // flag parameters
75 const OSG::Real32 flagHeight = 8.0f;
76 const OSG::Real32 flagWidth = 16.0f;
77 const OSG::UInt32 flagGeoHor = static_cast<OSG::UInt32>(flagWidth * 3);
78 const OSG::UInt32 flagGeoVert = static_cast<OSG::UInt32>(flagHeight / 2);
79 const OSG::Real32 flagWaveDamp = 0.06f;
81 const OSG::Real32 poleHeight = 24.0f;
82 const OSG::Real32 poleDia = poleHeight * 0.01f;
84 // fbo size -- you can increase these values to get a higher resolution image
85 const OSG::UInt32 fboWidth = static_cast<OSG::UInt32>(flagWidth * 32);
86 const OSG::UInt32 fboHeight = static_cast<OSG::UInt32>(flagHeight * 32);
88 // global variables
89 OSG::SimpleSceneManagerRefPtr mgr;
90 OSG::NodeRefPtr stageCamBeaconN;
91 OSG::TransformRefPtr stageCamBeacon;
93 OSG::NodeRefPtr modelTransN;
94 OSG::TransformRefPtr modelTrans;
96 // forward declaration so we can have the interesting stuff upfront
97 int setupGLUT (int *argc, char *argv[]);
98 OSG::NodeTransitPtr buildFBOScene(int argc, char *argv[]);
99 OSG::NodeTransitPtr buildScene (OSG::TextureObjChunkRefPtr fboTex);
102 Construct a scene that uses a Stage to render a subtree to an FBO (making
103 the result available as a texture) and use that in another subtree.
105 OSG::NodeTransitPtr buildStage(int argc, char *argv[])
108 Begin by setting up an FBO with a TextureBuffer, so we can capture
109 and reuse what is being rendered to the FBO.
112 OSG::ImageRefPtr fboTexImg = OSG::Image ::create();
113 OSG::TextureObjChunkRefPtr fboTex = OSG::TextureObjChunk ::create();
115 OSG::FrameBufferObjectRefPtr fbo = OSG::FrameBufferObject::create();
116 OSG::TextureBufferRefPtr texBuf = OSG::TextureBuffer ::create();
117 OSG::RenderBufferRefPtr depthBuf = OSG::RenderBuffer ::create();
119 // set up the texture ...
120 fboTexImg->set(OSG::Image::OSG_RGB_PF, fboWidth, fboHeight);
121 fboTex->setImage(fboTexImg);
123 // ... and add it to the texture buffer
124 texBuf->setTexture(fboTex);
126 // add a depth attachment, otherwise there is no depth buffer when
127 // rendering to the FBO
128 depthBuf->setInternalFormat(GL_DEPTH_COMPONENT24);
130 // make the fbo render to the texture
131 fbo->setColorAttachment(texBuf, 0);
132 fbo->setDepthAttachment(depthBuf );
133 fbo->editMFDrawBuffers()->push_back(GL_COLOR_ATTACHMENT0_EXT);
134 fbo->setWidth (fboWidth );
135 fbo->setHeight(fboHeight);
138 enable post processing for the FBO, this generates mip maps for the
139 texture if a mip map filter is active (the default for minFilter is
140 GL_LINEAR_MIPMAP_LINEAR).
141 Alternatively, one could set the texture filter to one that does not
142 require mip maps, e.g. call fboTex->setMinFilter(GL_LINEAR);
144 fbo->setPostProcessOnDeactivate(true);
147 Next we set up a Stage, which renders the subtree below it to its
148 render target (the FBO from above).
151 OSG::SimpleStageRefPtr stage = OSG::SimpleStage::create();
152 OSG::NodeRefPtr stageN = OSG::makeNodeFor(stage);
154 // add the scene to be rendered to the fbo as child of the Stage
155 OSG::NodeRefPtr fboSceneN = buildFBOScene(argc, argv);
156 stageN->addChild(fboSceneN);
158 // make the stage render to the FBO instead of the normal framebuffer
159 stage->setRenderTarget(fbo);
161 // use the full size of the target (this is like setting up the viewport
162 // of the stage)
163 stage->setSize(0.0f, 0.0f, 1.0f, 1.0f);
165 // set a different background for things on the stage ...
166 OSG::GradientBackgroundRefPtr gb = OSG::GradientBackground::create();
167 gb->addLine(OSG::Color3f(0.3f, 0.3f, 0.8f), 0.0f);
168 gb->addLine(OSG::Color3f(0.5f, 0.5f, 0.5f), 1.0f);
169 stage->setBackground(gb);
171 // ... and add a camera
172 OSG::PerspectiveCameraRefPtr stageCam = OSG::PerspectiveCamera::create();
173 stage->setCamera(stageCam);
175 stageCam->setBeacon(stageCamBeaconN);
176 stageCam->setNear ( 0.1f);
177 stageCam->setFar (1000.0);
178 stageCam->setFov ( 1.5);
180 // add the scene using the fbo
181 OSG::NodeRefPtr sceneN = buildScene(fboTex);
183 // place the stage and the scene using the fbo under a common group
184 OSG::NodeRefPtr rootN = OSG::makeCoredNode<OSG::Group>();
186 rootN->addChild(stageN);
187 rootN->addChild(sceneN);
189 return OSG::NodeTransitPtr(rootN);
193 // Initialize GLUT & OpenSG and set up the scene
194 int main(int argc, char **argv)
196 // OSG init
197 OSG::osgInit(argc,argv);
199 // GLUT init
200 int winid = setupGLUT(&argc, argv);
202 // open a new scope, because the pointers below should go out of scope
203 // before entering glutMainLoop.
204 // Otherwise OpenSG will complain about objects being alive after shutdown.
206 // the connection between GLUT and OpenSG
207 OSG::GLUTWindowRefPtr gwin = OSG::GLUTWindow::create();
208 gwin->setGlutId(winid);
209 gwin->init();
211 OSG::NodeRefPtr scene = buildStage(argc, argv);
213 OSG::commitChanges();
215 // create the SimpleSceneManager helper
216 mgr = OSG::SimpleSceneManager::create();
218 // tell the manager what to manage
219 mgr->setWindow(gwin );
220 mgr->setRoot (scene);
222 // show the whole scene
223 mgr->showAll();
226 // GLUT main loop
227 glutMainLoop();
229 return 0;
233 // GLUT callback functions
236 // react to size changes
237 void reshape(int w, int h)
239 mgr->resize(w, h);
240 glutPostRedisplay();
243 // react to mouse button presses
244 void mouse(int button, int state, int x, int y)
246 if (state)
247 mgr->mouseButtonRelease(button, x, y);
248 else
249 mgr->mouseButtonPress(button, x, y);
251 glutPostRedisplay();
254 // react to mouse motions with pressed buttons
255 void motion(int x, int y)
257 mgr->mouseMove(x, y);
258 glutPostRedisplay();
261 void update(void)
263 glutPostRedisplay();
266 // redraw the window
267 void display( void )
269 static OSG::Real64 t0 = OSG::getSystemTime();
271 // get the current time
272 OSG::Real64 t = OSG::getSystemTime() - t0;
274 OSG::Matrix m;
275 OSG::Quaternion q;
276 q.setValueAsAxisDeg(0, 1, 0, t * 10.f);
277 m.setRotate(q);
278 modelTrans->setMatrix(m);
281 OSG::commitChangesAndClear();
283 mgr->redraw();
286 // react to keys
287 void keyboard(unsigned char k, int , int )
289 switch(k)
291 case 27:
293 // clean up global variables
294 mgr = NULL;
295 stageCamBeaconN = NULL;
296 stageCamBeacon = NULL;
298 modelTransN = NULL;
299 modelTrans = NULL;
301 OSG::osgExit();
302 exit(0);
304 break;
308 // setup the GLUT library which handles the windows for us
309 int setupGLUT(int *argc, char *argv[])
311 glutInit(argc, argv);
312 glutInitDisplayMode(GLUT_RGB | GLUT_DEPTH | GLUT_DOUBLE);
314 int winid = glutCreateWindow("OpenSG");
316 glutReshapeFunc(reshape);
317 glutDisplayFunc(display);
318 glutMouseFunc(mouse);
319 glutMotionFunc(motion);
320 glutKeyboardFunc(keyboard);
322 // call the redraw function whenever there's nothing else to do
323 glutIdleFunc(update);
325 return winid;
329 Loads a model given on the command line or creates a fallback.
330 This scene is rendered to a texture (fboTexture) which is later used on
331 another object, however none of this happens in here, only the scene is
332 constructed.
334 OSG::NodeTransitPtr buildFBOScene(int argc, char *argv[])
336 OSG::NodeRefPtr modelN;
338 if(argc > 1)
339 modelN = OSG::SceneFileHandler::the()->read(argv[1]);
341 // no argument or loading failed -> use a torus
342 if(modelN == NULL)
343 modelN = OSG::makeTorus(0.3f, 4, 16, 64);
345 OSG::commitChanges();
346 OSG::Pnt3f bbMin, bbMax;
347 modelN->updateVolume();
348 modelN->getVolume().getBounds(bbMin, bbMax);
350 OSG::NodeRefPtr fboSceneN = OSG::makeCoredNode<OSG::Group>();
352 stageCamBeaconN = OSG::makeCoredNode<OSG::Transform>(&stageCamBeacon);
354 modelTransN = OSG::makeCoredNode<OSG::Transform>(&modelTrans);
356 // move the camera back
357 OSG::Real32 bbDia = (bbMax - bbMin).length();
358 stageCamBeacon->editMatrix().setTranslate(OSG::Vec3f(0.0f, 0.0f, bbDia));
360 OSG::PointLightRefPtr light;
361 OSG::NodeRefPtr lightN = OSG::makeCoredNode<OSG::PointLight>(&light);
362 light->setBeacon(stageCamBeaconN);
364 fboSceneN->addChild(lightN );
365 fboSceneN->addChild(stageCamBeaconN);
367 lightN->addChild(modelTransN);
369 modelTransN->addChild(modelN);
371 return OSG::NodeTransitPtr(fboSceneN);
374 // create a wood texture
375 OSG::SimpleTexturedMaterialTransitPtr createWoodMaterial(void)
377 OSG::SimpleTexturedMaterialRefPtr mat =
378 OSG::SimpleTexturedMaterial::create();
380 OSG::ImageRefPtr img = OSG::Image::create();
381 createNoise(img, OSG::Image::OSG_L_PF, 7, 64);
383 mat->setImage(img);
384 mat->setEnvMode(GL_MODULATE);
385 mat->setDiffuse(OSG::Color3f(0.9f, 0.57f, 0.1f));
386 mat->setSpecular(OSG::Color3f(0.2f, 0.2f, 0.1f));
388 OSG::TextureTransformChunkRefPtr ttrans =
389 OSG::TextureTransformChunk::create();
390 OSG::Matrix m;
391 m.setScale(2.0, 8.0, 2.0);
392 ttrans->setMatrix(m);
394 mat->addChunk(ttrans);
396 return OSG::SimpleTexturedMaterialTransitPtr(mat);
401 Builds a scene with a flag on a pole. The flag is textured with the
402 image of the fbo scene (fboTexture).
404 OSG::NodeTransitPtr buildScene(OSG::TextureObjChunkRefPtr fboTex)
406 OSG::NodeRefPtr flagScene = OSG::makeCoredNode<OSG::Group>();
407 OSG::GeometryRefPtr flagGeo = OSG::makePlaneGeo(flagWidth, flagHeight,
408 flagGeoHor, flagGeoVert);
410 // disable caching as we will change this geometry every frame
411 flagGeo->setDlistCache(false);
413 OSG::SimpleMaterialRefPtr flagMat = OSG::SimpleMaterial ::create();
414 OSG::TextureEnvChunkRefPtr fboTexEnv = OSG::TextureEnvChunk::create();
416 fboTexEnv->setEnvMode(GL_REPLACE);
418 flagMat->addChunk(fboTex );
419 flagMat->addChunk(fboTexEnv);
421 // add a light glossy effect (environment noise-map)
422 if (0)
424 OSG::ImageRefPtr noise = OSG::Image::create();
425 createNoise(noise, OSG::Image::OSG_I_PF, 5, 256);
427 // make noise image darker (as it will be GL_ADDed)
428 for(OSG::UInt32 i = 0; i < noise->getSize(); ++i)
429 noise->editData()[i] >>= 2; // *= 0.125
431 OSG::TextureObjChunkRefPtr glossObj = OSG::TextureObjChunk::create();
432 OSG::TextureEnvChunkRefPtr glossEnv = OSG::TextureEnvChunk::create();
434 glossObj->setImage(noise);
435 glossEnv->setEnvMode(GL_ADD);
437 OSG::TexGenChunkRefPtr envMap = OSG::TexGenChunk::create();
438 envMap->setGenFuncS(GL_SPHERE_MAP);
439 envMap->setGenFuncT(GL_SPHERE_MAP);
441 // add for use with 2nd texture unit
442 flagMat->addChunk(glossObj, 1);
443 flagMat->addChunk(glossEnv, 1);
444 flagMat->addChunk(envMap, 1);
447 flagMat->addChunk(
448 OSG::StateChunkRefPtr(OSG::TwoSidedLightingChunk::create()));
449 flagMat->setSpecular(OSG::Color3f(0.4f, 0.4f, 0.4f));
450 flagMat->setDiffuse (OSG::Color3f(0.7f, 0.7f, 0.7f));
452 flagGeo->setMaterial(flagMat);
454 // create transform node to hook up the flag to the pole
455 OSG::ComponentTransformRefPtr flagTrans;
456 OSG::NodeRefPtr flagTransN =
457 OSG::makeCoredNode<OSG::ComponentTransform>(&flagTrans);
459 OSG::Vec3f v(0.5f * flagWidth, 0.5f * (poleHeight - flagHeight) , 0.0f);
460 flagTrans->setTranslation(v);
462 // attach flag-geometry to transform-node
463 flagTransN->addChild(OSG::NodeRefPtr(OSG::makeNodeFor(flagGeo)));
465 // build flag pole
466 OSG::GeometryRefPtr pole = OSG::makeCylinderGeo(poleHeight, poleDia, 24, true, true, true);
467 OSG::NodeRefPtr poleN = OSG::makeNodeFor(pole);
468 OSG::MaterialRefPtr woodMat = createWoodMaterial();
470 pole->setMaterial(woodMat);
472 // attach objects to group node
473 flagScene->addChild(flagTransN);
474 flagScene->addChild(poleN );
476 return OSG::NodeTransitPtr(flagScene);