1 // OpenSG Tutorial Example: Shadows
3 // This example shows realtime shadows via shadow maps.
5 #ifdef OSG_BUILD_ACTIVE
9 #include <OSGSimpleGeometry.h>
10 #include <OSGGLUTWindow.h>
11 #include <OSGBaseFunctions.h>
13 #include <OSGSpotLight.h>
14 #include <OSGDirectionalLight.h>
15 #include <OSGPointLight.h>
16 #include <OSGPerspectiveCamera.h>
17 #include <OSGGradientBackground.h>
18 #include <OSGSolidBackground.h>
19 #include <OSGRenderAction.h>
21 #include <OSGSimpleMaterial.h>
22 #include <OSGTextureObjChunk.h>
23 #include <OSGTextureEnvChunk.h>
24 #include <OSGTransform.h>
26 #include <OSGSimpleSceneManager.h>
27 #include <OSGSceneFileHandler.h>
30 #include <OSGSimpleShadowMapEngine.h>
32 #include <OpenSG/OSGConfig.h>
34 #include <OpenSG/OSGGLUT.h>
35 #include <OpenSG/OSGSimpleGeometry.h>
36 #include <OpenSG/OSGGLUTWindow.h>
37 #include <OpenSG/OSGBaseFunctions.h>
39 #include <OpenSG/OSGSpotLight.h>
40 #include <OpenSG/OSGDirectionalLight.h>
41 #include <OpenSG/OSGPointLight.h>
42 #include <OpenSG/OSGPerspectiveCamera.h>
43 #include <OpenSG/OSGGradientBackground.h>
44 #include <OpenSG/OSGSolidBackground.h>
45 #include <OpenSG/OSGRenderAction.h>
46 #include <OpenSG/OSGImage.h>
47 #include <OpenSG/OSGSimpleMaterial.h>
48 #include <OpenSG/OSGTextureObjChunk.h>
49 #include <OpenSG/OSGTextureEnvChunk.h>
50 #include <OpenSG/OSGTransform.h>
51 #include <OpenSG/OSGGroup.h>
52 #include <OpenSG/OSGSimpleSceneManager.h>
53 #include <OpenSG/OSGSceneFileHandler.h>
56 #include <OpenSG/OSGSimpleShadowMapEngine.h>
61 This tutorial has quite a few global objects, to simplify the cleanup at
62 program exit we put them all in a struct.
67 OSG::SimpleSceneManagerRefPtr mgr
;
69 OSG::GLUTWindowRefPtr gwin
;
71 OSG::NodeRefPtr rootNode
;
72 OSG::SpotLightRefPtr spot1_core
;
73 OSG::SpotLightRefPtr spot2_core
;
74 OSG::DirectionalLightRefPtr dir_core
;
75 OSG::PointLightRefPtr point1_core
;
76 OSG::PointLightRefPtr point2_core
;
77 OSG::TransformRefPtr box_trans
;
78 OSG::TransformRefPtr cylinder1_trans
;
79 OSG::TransformRefPtr cylinder2_trans
;
93 cylinder1_trans(NULL
),
99 GlobalObjects
*globals
= NULL
;
101 const OSG::UInt32 SM_RESOLUTION
= 1024;
103 // forward declaration so we can have the interesting stuff upfront
104 int setupGLUT( int *argc
, char *argv
[] );
106 // Initialize GLUT & OpenSG and set up the scene
107 int main(int argc
, char **argv
)
109 printf("Press key '1' or '2' to switch between one and two light sources.\n");
111 OSG::osgInit(argc
,argv
);
113 globals
= new GlobalObjects
;
115 // open a new scope, because the pointers below should go out of scope
116 // before entering glutMainLoop.
117 // Otherwise OpenSG will complain about objects being alive after shutdown.
120 int winid
= setupGLUT(&argc
, argv
);
121 globals
->gwin
= OSG::GLUTWindow::create();
124 Construct a scene with a ground plane, some objects and two lights.
125 Nothing very interesting at this point.
126 See further down for the part relevant to shadows.
129 globals
->rootNode
= OSG::makeCoredNode
<OSG::Group
>();
130 OSG::NodeRefPtr scene
= OSG::makeCoredNode
<OSG::Group
>();
133 OSG::TransformRefPtr point1_trans
;
134 OSG::NodeRefPtr point1
= OSG::makeCoredNode
<OSG::PointLight
>(&globals
->point1_core
);
135 OSG::NodeRefPtr point1_beacon
= OSG::makeCoredNode
<OSG::Transform
>(&point1_trans
);
137 point1_trans
->editMatrix().setTranslate(0.0, 0.0, 15.0);
139 globals
->point1_core
->setAmbient(0.15f
,0.15f
,0.15f
,1);
140 globals
->point1_core
->setDiffuse(0.4f
,0.4f
,0.4f
,1);
141 globals
->point1_core
->setSpecular(0.0f
,0.0f
,0.0f
,1);
142 globals
->point1_core
->setBeacon(point1_beacon
);
143 globals
->point1_core
->setOn(true);
145 OSG::TransformRefPtr point2_trans
;
146 OSG::NodeRefPtr point2
= OSG::makeCoredNode
<OSG::PointLight
>(&globals
->point2_core
);
147 OSG::NodeRefPtr point2_beacon
= OSG::makeCoredNode
<OSG::Transform
>(&point2_trans
);
149 point2_trans
->editMatrix().setTranslate(2.5, 2.5, 15.0);
151 globals
->point2_core
->setAmbient(0.15f
,0.15f
,0.15f
,1);
152 globals
->point2_core
->setDiffuse(0.4f
,0.4f
,0.4f
,1);
153 globals
->point2_core
->setSpecular(0.0f
,0.0f
,0.0f
,1);
154 globals
->point2_core
->setBeacon(point2_beacon
);
155 globals
->point2_core
->setOn(true);
157 point1
->addChild(point2
);
158 point2
->addChild(scene
);
163 OSG::NodeRefPtr plane
= OSG::makePlane(25.0, 25.0, 128, 128);
165 OSG::UChar8 imgdata
[] =
166 { 255,0,0, 0,255,0, 0,0,255, 255,255,0 };
167 OSG::ImageRefPtr plane_img
= OSG::Image::create();
168 plane_img
->set(OSG::Image::OSG_RGB_PF
, 2, 2, 1, 1, 1, 0, imgdata
);
170 OSG::TextureObjChunkRefPtr plane_tex
= OSG::TextureObjChunk::create();
171 plane_tex
->setImage(plane_img
);
172 plane_tex
->setMinFilter(GL_LINEAR
);
173 plane_tex
->setMagFilter(GL_LINEAR
);
174 plane_tex
->setWrapS(GL_REPEAT
);
175 plane_tex
->setWrapT(GL_REPEAT
);
177 OSG::TextureEnvChunkRefPtr plane_tex_env
= OSG::TextureEnvChunk::create();
178 plane_tex_env
->setEnvMode(GL_MODULATE
);
180 OSG::SimpleMaterialRefPtr plane_mat
= OSG::SimpleMaterial::create();
181 plane_mat
->setAmbient(OSG::Color3f(0.3f
,0.3f
,0.3f
));
182 plane_mat
->setDiffuse(OSG::Color3f(1.0f
,1.0f
,1.0f
));
183 plane_mat
->addChunk(plane_tex
);
184 plane_mat
->addChunk(plane_tex_env
);
186 OSG::GeometryRefPtr plane_geo
= dynamic_cast<OSG::Geometry
*>(plane
->getCore());
187 plane_geo
->setMaterial(plane_mat
);
190 OSG::NodeRefPtr box_trans_node
= OSG::makeCoredNode
<OSG::Transform
>(&globals
->box_trans
);
191 globals
->box_trans
->editMatrix().setTranslate(0.0, 0.0, 2.0);
193 OSG::NodeRefPtr box
= OSG::makeBox(8.0f
, 8.0f
, 0.8f
, 10, 10 , 10);
194 box_trans_node
->addChild(box
);
196 OSG::SimpleMaterialRefPtr box_mat
= OSG::SimpleMaterial::create();
197 box_mat
->setAmbient(OSG::Color3f(0.0f
,0.0f
,0.0f
));
198 box_mat
->setDiffuse(OSG::Color3f(0.0f
,0.0f
,1.0f
));
200 OSG::GeometryRefPtr box_geo
= dynamic_cast<OSG::Geometry
*>(box
->getCore());
201 box_geo
->setMaterial(box_mat
);
204 OSG::NodeRefPtr cylinder1_trans_node
= OSG::makeCoredNode
<OSG::Transform
>(&globals
->cylinder1_trans
);
205 globals
->cylinder1_trans
->editMatrix().setTranslate(0.0, 0.0, 5.0);
207 OSG::NodeRefPtr cylinder1
= OSG::makeCylinder(10.0f
, 0.4f
, 32, true, true ,true);
208 cylinder1_trans_node
->addChild(cylinder1
);
210 OSG::SimpleMaterialRefPtr cylinder1_mat
= OSG::SimpleMaterial::create();
211 cylinder1_mat
->setAmbient(OSG::Color3f(0.0,0.0,0.0));
212 cylinder1_mat
->setDiffuse(OSG::Color3f(1.0,0.0,0.0));
214 OSG::GeometryRefPtr cylinder1_geo
= dynamic_cast<OSG::Geometry
*>(cylinder1
->getCore());
215 cylinder1_geo
->setMaterial(cylinder1_mat
);
218 OSG::NodeRefPtr cylinder2_trans_node
= OSG::makeCoredNode
<OSG::Transform
>(&globals
->cylinder2_trans
);
219 globals
->cylinder2_trans
->editMatrix().setTranslate(0.0, 0.0, 8.0);
221 OSG::NodeRefPtr cylinder2
= OSG::makeCylinder(10.0f
, 0.4f
, 32, true, true ,true);
222 cylinder2_trans_node
->addChild(cylinder2
);
224 OSG::SimpleMaterialRefPtr cylinder2_mat
= OSG::SimpleMaterial::create();
225 cylinder2_mat
->setAmbient(OSG::Color3f(0.0,0.0,0.0));
226 cylinder2_mat
->setDiffuse(OSG::Color3f(0.0,1.0,0.0));
228 OSG::GeometryRefPtr cylinder2_geo
= dynamic_cast<OSG::Geometry
*>(cylinder2
->getCore());
229 cylinder2_geo
->setMaterial(cylinder2_mat
);
232 scene
->addChild(plane
);
233 scene
->addChild(box_trans_node
);
234 scene
->addChild(cylinder1_trans_node
);
235 scene
->addChild(cylinder2_trans_node
);
237 globals
->rootNode
->addChild(point1
);
238 globals
->rootNode
->addChild(point1_beacon
);
239 globals
->rootNode
->addChild(point2_beacon
);
241 globals
->gwin
->setGlutId(winid
);
242 globals
->gwin
->init();
246 Shadows are implemented as LightEngines (every Light can have one
247 to augment it's regular effect).
250 // create the engines
251 OSG::SimpleShadowMapEngineRefPtr ssme1
= OSG::SimpleShadowMapEngine::create();
252 OSG::SimpleShadowMapEngineRefPtr ssme2
= OSG::SimpleShadowMapEngine::create();
254 // add them to the light sources
255 globals
->point1_core
->setLightEngine(ssme1
);
256 globals
->point2_core
->setLightEngine(ssme2
);
258 ssme1
->setWidth (SM_RESOLUTION
);
259 ssme1
->setHeight(SM_RESOLUTION
);
260 ssme1
->setShadowColor(OSG::Color4f(0.1f
, 0.1f
, 0.1f
, 1.0f
));
262 ssme2
->setWidth (SM_RESOLUTION
);
263 ssme2
->setHeight(SM_RESOLUTION
);
266 globals
->rootNode
->updateVolume();
267 globals
->rootNode
->getVolume ().getBounds( min
, max
);
269 OSG::commitChanges();
271 // create the SimpleSceneManager helper
272 globals
->mgr
= OSG::SimpleSceneManager::create();
274 globals
->mgr
->setWindow(globals
->gwin
);
275 globals
->mgr
->setRoot (globals
->rootNode
);
277 globals
->mgr
->turnHeadlightOff();
279 globals
->mgr
->showAll();
289 // GLUT callback functions
292 //do Animation-Calculations here
295 static OSG::Real64 t0
= OSG::getSystemTime();
297 OSG::Real64 t
= OSG::getSystemTime() - t0
;
299 OSG::Real32 rotb
= t
* 10.0;
303 OSG::Real32 rotc1
= t
* 20.0;
307 OSG::Real32 rotc2
= t
* 40.0;
312 q
.setValueAsAxisDeg(0,0,1, rotb
);
313 globals
->box_trans
->editMatrix().setRotate(q
);
315 q
.setValueAsAxisDeg(0,0,1, rotc1
);
316 globals
->cylinder1_trans
->editMatrix().setRotate(q
);
318 q
.setValueAsAxisDeg(0,0,1, rotc2
);
319 globals
->cylinder2_trans
->editMatrix().setRotate(q
);
321 globals
->mgr
->redraw();
327 globals
->mgr
->redraw();
330 // react to size changes
331 void reshape(int w
, int h
)
333 globals
->mgr
->resize( w
, h
);
337 // react to mouse button presses
338 void mouse(int button
, int state
, int x
, int y
)
341 globals
->mgr
->mouseButtonRelease( button
, x
, y
);
343 globals
->mgr
->mouseButtonPress( button
, x
, y
);
347 // react to mouse motions with pressed buttons
348 void motion(int x
, int y
)
350 globals
->mgr
->mouseMove( x
, y
);
355 void keyboard(unsigned char k
, int x
, int y
)
361 // clean up global variables
373 globals
->point1_core
->setOn(true);
374 globals
->point1_core
->setAmbient(0.3f
,0.3f
,0.3f
,1);
375 globals
->point1_core
->setDiffuse(0.8f
,0.8f
,0.8f
,1);
377 globals
->point2_core
->setOn(false);
383 globals
->point1_core
->setAmbient(0.15f
,0.15f
,0.15f
,1);
384 globals
->point1_core
->setDiffuse(0.4f
,0.4f
,0.4f
,1);
385 globals
->point1_core
->setOn(true);
387 globals
->point2_core
->setAmbient(0.15f
,0.15f
,0.15f
,1);
388 globals
->point2_core
->setDiffuse(0.4f
,0.4f
,0.4f
,1);
389 globals
->point2_core
->setOn(true);
395 OSG::SceneFileHandler::the()->write(globals
->rootNode
, "shadow.osb.gz", true);
401 // setup the GLUT library which handles the windows for us
402 int setupGLUT(int *argc
, char *argv
[])
404 glutInit(argc
, argv
);
405 glutInitDisplayMode(GLUT_RGB
| GLUT_DEPTH
| GLUT_DOUBLE
);
407 //Set WindowSize here
408 glutInitWindowSize(640,640);
409 int winid
= glutCreateWindow("Shadow-Scene");
411 glutReshapeFunc(reshape
);
412 glutDisplayFunc(display
);
413 glutMouseFunc(mouse
);
414 glutMotionFunc(motion
);
415 glutKeyboardFunc(keyboard
);
416 glutIdleFunc(Animate
);