1 // OpenSG Tutorial Example: MultiRangeLight
3 // This example introduces the MultiLightChunk, the MultiPropertySSBOChunk and
4 // the MultiPropertyUBOChunk. The first two chunks are derived from the
5 // ShaderStorageBufferObjStdLayoutChunk and easily permit the preparation
6 // of array buffers in shader code with std430 shader storage buffer block
7 // format. The third chunk is derived from the UniformBufferObjStd140Chunk
8 // and allows easy preparation of a std140 uniform array block.
10 // The MultiLightChunk models a light data structures for multiple lights.
11 // It supports a number of different light types and also gives the user
12 // freedom in the details of the data structure layout provided in shader code
13 // for these lights. It currently supports data for directional, point, spot
14 // and Ueber (cinema) lights. It is feasible to strip-down the light structure
15 // data layout somewhat if requested. This example actively only uses point and
16 // spot lights and uses a simple light abstraction with only a single light
17 // color and one intensity value. Additionally, it provides a range attribute
18 // that models the attenuation behavior of the light. Of course the shader
19 // code's responsibilty is to make usage of the provided light data attrubutes,
20 // and the writer of the shader can implement whatever light model he likes
21 // on the given light buffer layout.
23 // The MultiPropertyUBOChunk and MultiPropertySSBOChunk do also provides means
24 // to conviently create shader buffer data. They are, however, not as
25 // specialized as the MultiLightChunk.
26 // They have a simple interface for the data layout preparation but allows only
27 // a restricted subset of layout structure that the std140 uniform buffer block
28 // repspectively the std430 shader storage buffer block specifications allows.
30 // In this example a MultiPropertySSBOChunk is used to model a material database
31 // with the simple basic material properties. The material database shader
32 // buffer is shared by all geometry that is rendered by the example.
34 // The MultiPropertyUBOChunk is used to provide geometry state data to the
35 // fragment shader. That is, each geometry gets its own chunk, but for the
36 // purpose of the example only the material index to be used for the particular
37 // geometry is added to chunk.
39 // Additionally, the example runs riot with boost random number generators.
40 // Hopefully, that does not distract the reader.
42 // Different aspects of the example can be manipulated at runtime like the
43 // number of lights and their range and intensity parameters as well as the
44 // number of geometries simulated and their material among many others.
46 // The examples uses a HDR2Stage core for managing the mapping of the
47 // accumulated intensities into the feasible region of the final screen
48 // render target. It does use mostly default settings for this stage.
50 // At last the example provides a bezier curve abstraction for generating
51 // the light and object pathes.
54 // multirangelight.cpp
55 // multicinemalight.cpp
56 // uniformbufferobject_std140.cpp
57 // shaderstoragebufferobject_std430.cpp
58 // multipropertyubochunk_test.cpp
59 // multipropertyssbochunk_test.cpp
63 #include <boost/functional/hash.hpp>
64 #include <boost/unordered_set.hpp>
65 #include <boost/foreach.hpp>
66 #include <boost/random.hpp>
67 #include <boost/tuple/tuple.hpp>
68 #include "boost/tuple/tuple_comparison.hpp"
70 #ifdef OSG_BUILD_ACTIVE
73 #include <OSGConfig.h>
74 #include <OSGSimpleGeometry.h>
75 #include <OSGGLUTWindow.h>
76 #include <OSGSimpleSceneManager.h>
77 #include <OSGBaseFunctions.h>
78 #include <OSGTransform.h>
84 #include <OSGHDR2Stage.h>
85 #include <OSGInverseTransform.h>
86 #include <OSGShaderProgramChunk.h>
87 #include <OSGShaderProgram.h>
88 #include <OSGShaderVariableOSG.h>
89 #include <OSGChunkMaterial.h>
90 #include <OSGMaterialGroup.h>
91 #include <OSGMaterialChunkOverrideGroup.h>
92 #include <OSGMatrixUtility.h>
93 #include <OSGMultiLightChunk.h>
94 #include <OSGMultiPropertyUBOChunk.h>
95 #include <OSGMultiPropertySSBOChunk.h>
96 #include <OSGPolygonChunk.h>
97 #include <OSGDepthChunk.h>
98 #include <OSGShaderProgramVariableChunk.h>
99 #include <OSGBlendChunk.h>
100 #include <OSGPolygonChunk.h>
101 #include <OSGTwoSidedLightingChunk.h>
105 #include <OpenSG/OSGGLUT.h>
106 #include <OpenSG/OSGConfig.h>
107 #include <OpenSG/OSGSimpleGeometry.h>
108 #include <OpenSG/OSGGLUTWindow.h>
109 #include <OpenSG/OSGSimpleSceneManager.h>
110 #include <OpenSG/OSGBaseFunctions.h>
111 #include <OpenSG/OSGTransform.h>
112 #include <OpenSG/OSGGroup.h>
115 #include <OpenSG/OSGGLEXT.h>
116 #include <OpenSG/OSGTime.h>
117 #include <OpenSG/OSGHDR2Stage.h>
118 #include <OpenSG/OSGInverseTransform.h>
119 #include <OpenSG/OSGShaderProgramChunk.h>
120 #include <OpenSG/OSGShaderProgram.h>
121 #include <OpenSG/OSGShaderVariableOSG.h>
122 #include <OpenSG/OSGChunkMaterial.h>
123 #include <OpenSG/OSGMaterialGroup.h>
124 #include <OpenSG/OSGMaterialChunkOverrideGroup.h>
125 #include <OpenSG/OSGMatrixUtility.h>
126 #include <OpenSG/OSGMultiLightChunk.h>
127 #include <OpenSG/OSGMultiPropertyUBOChunk.h>
128 #include <OpenSG/OSGMultiPropertySSBOChunk.h>
129 #include <OpenSG/OSGPolygonChunk.h>
130 #include <OpenSG/OSGDepthChunk.h>
131 #include <OpenSG/OSGShaderProgramVariableChunk.h>
132 #include <OpenSG/OSGBlendChunk.h>
133 #include <OpenSG/OSGPolygonChunk.h>
134 #include <OpenSG/OSGTwoSidedLightingChunk.h>
137 // ============================================================================
139 // Part I: Declaration of the example scene and some helpers:
140 // - constants that governs the example
141 // - random number generators
142 // - smooth cubic Bezier spline curve
144 // ============================================================================
146 OSG::SimpleSceneManagerRefPtr mgr
;
148 const OSG::Int32 num_geometries
= 16;
149 const OSG::Int32 num_grid_boxes
= 100;
150 const OSG::Int32 num_curve_knots
= 40;
151 const OSG::Int32 num_passes
= 4;
152 const std::size_t num_materials
= 5000;
153 const OSG::Int32 max_num_lights
= 1024;
154 const OSG::Real32 world_size
= 10.f
;
155 const OSG::Real32 box_factor
= 1.5f
;
157 OSG::Real32 simulation_delta
= 0.0001f
;
158 OSG::Real32 elapse_time_limit
= 10.f
;
160 const OSG::Real32 max_light_power
= 10.f
;
162 const OSG::Real32 rangeFactor
= 1.05f
;
163 const OSG::Real32 intensityFactor
= 1.2f
;
165 typedef boost::mt19937 RNGType
;
166 RNGType
rng(time(0));
168 boost::uniform_int
<> box_dist(0, num_grid_boxes
-1);
169 boost::variate_generator
<RNGType
, boost::uniform_int
<> > box_idx_die(rng
, box_dist
);
171 boost::uniform_int
<> die_dist(1, 6);
172 boost::variate_generator
<RNGType
, boost::uniform_int
<> > classic_die(rng
, die_dist
);
174 boost::uniform_int
<> geom_dist(0, 7);
175 boost::variate_generator
<RNGType
, boost::uniform_int
<> > geom_idx_die(rng
, geom_dist
);
177 boost::uniform_01
<float> unit_distribution
;
178 boost::variate_generator
< RNGType
, boost::uniform_01
<float> > unit_die(rng
, unit_distribution
);
180 boost::uniform_real
<float> small_distribution(0.1f
, 1.f
);
181 boost::variate_generator
< RNGType
, boost::uniform_real
<float> > small_die(rng
, small_distribution
);
183 boost::uniform_real
<float> light_range_distribution(0.2f
, 0.7f
);
184 boost::variate_generator
< RNGType
, boost::uniform_real
<float> > light_range_die(rng
, light_range_distribution
);
186 std::vector
<OSG::Pnt3f
> dice_knots(bool close_curve
);
188 OSG::Vec3f
dice_unit_vector()
192 while (v
.length() < OSG::Eps
)
194 -1.f
+ 2.f
* unit_die(),
195 -1.f
+ 2.f
* unit_die(),
196 -1.f
+ 2.f
* unit_die());
203 class CubicBezierCurve
206 CubicBezierCurve(const OSG::Pnt3f
& p0
, const OSG::Pnt3f
& p1
, const OSG::Pnt3f
& p2
, const OSG::Pnt3f
& p3
);
207 CubicBezierCurve(const CubicBezierCurve
& rhs
);
209 CubicBezierCurve
& operator=(const CubicBezierCurve
& rhs
);
211 OSG::Pnt3f
operator() (OSG::Real32 t
) const;
212 OSG::Vec3f
tangent (OSG::Real32 t
) const;
213 OSG::Vec3f
normal (OSG::Real32 t
) const;
214 OSG::Vec3f
binormal (OSG::Real32 t
) const;
215 OSG::Matrix
frame (OSG::Real32 t
, bool position_only
) const;
216 OSG::Real32
length (OSG::UInt32 numSeg
= 10) const;
219 OSG::Vec3f
fst_derivative (OSG::Real32 t
) const;
220 OSG::Vec3f
sec_derivative (OSG::Real32 t
) const;
221 OSG::Vec3f
thr_devivative (OSG::Real32 t
) const;
227 class SmoothCubicBezierSpline
230 typedef std::vector
<OSG::Pnt3f
> points_t
;
232 SmoothCubicBezierSpline(const points_t
& knots
);
233 SmoothCubicBezierSpline(const SmoothCubicBezierSpline
& rhs
);
235 SmoothCubicBezierSpline
& operator=(const SmoothCubicBezierSpline
& rhs
);
237 OSG::Pnt3f
operator() (OSG::Real32 t
) const;
238 OSG::Vec3f
tangent (OSG::Real32 t
) const;
239 OSG::Vec3f
normal (OSG::Real32 t
) const;
240 OSG::Vec3f
binormal (OSG::Real32 t
) const;
241 OSG::Matrix
frame (OSG::Real32 t
, bool position_only
= false) const;
242 OSG::Real32
length (OSG::UInt32 numSeg
= 10) const;
245 void calc_ctrl_pnts (points_t
& p1
, points_t
& p2
) const;
246 std::size_t index (OSG::Real32 t
) const;
247 OSG::Real32
t_ (OSG::Real32 t
, std::size_t idx
) const;
250 std::vector
<OSG::Pnt3f
> knots
;
251 std::vector
<OSG::Real32
> intervals
;
252 std::vector
<CubicBezierCurve
> curves
;
255 // ============================================================================
257 // Part II: Declaration of
258 // - struct Light and type VecLightsT,
259 // - struct Material and type VecMaterialsT,
260 // - struct GeomState
261 // and corresponding initialization routines.
263 // ============================================================================
266 // simple light data structure
272 directional_light
= OSG::MultiLight::DIRECTIONAL_LIGHT
,
273 point_light
= OSG::MultiLight::POINT_LIGHT
,
274 spot_light
= OSG::MultiLight::SPOT_LIGHT
,
275 cinema_light
= OSG::MultiLight::CINEMA_LIGHT
278 OSG::MultiLight::Type
getType() const { return static_cast<OSG::MultiLight::Type
>(type
); }
280 explicit Light(Type e
);
283 static Light
create_light(Type e
, OSG::UInt32 material_idx
);
285 OSG::Pnt3f position
; // light position in object space for point and spot lights
286 OSG::Vec3f direction
; // direction of directional light or spot light in object space
287 OSG::Color3f color
; // the color of the light
288 OSG::Real32 intensity
; // the intensity of the light
289 OSG::Real32 range
; // the range of the light, i.e. the light sphere radius of influence
290 OSG::Real32 spotlightAngle
; // the cone angle in case of a spot light
291 OSG::Int32 type
; // the type of light: see OSG::MultiLight::LightType
292 bool enabled
; // on/off state of the light
294 OSG::NodeRefPtr beacon
; // the light beacon that if defined evaluates the position parameter
295 OSG::TransformRefPtr transform
; // the beacons transform core
296 SmoothCubicBezierSpline curve
; // the path that the light will follow
299 typedef std::vector
<Light
> VecLightsT
; // multiple lights
300 VecLightsT lights
; // the lights of the scene
303 : position(0.f
, 0.f
, 0.f
)
304 , direction(0.f
, 0.f
, 1.f
)
308 , spotlightAngle(20.f
)
313 , curve(dice_knots(true))
323 // Simple material data structure
328 : ambient (0.f
, 0.f
, 0.f
)
329 , diffuse (0.f
, 0.f
, 0.f
)
330 , specular(0.f
, 0.f
, 0.f
)
331 , emissive(0.f
, 0.f
, 0.f
)
336 OSG::Color3f ambient
;
337 OSG::Color3f diffuse
;
338 OSG::Color3f specular
;
339 OSG::Color3f emissive
;
342 OSG::Real32 shininess
;
344 static OSG::UInt32 ambient_id
;
345 static OSG::UInt32 diffuse_id
;
346 static OSG::UInt32 specular_id
;
347 static OSG::UInt32 emissive_id
;
348 static OSG::UInt32 opacity_id
;
349 static OSG::UInt32 shininess_id
;
352 OSG::UInt32
Material:: ambient_id
= 0;
353 OSG::UInt32
Material:: diffuse_id
= 0;
354 OSG::UInt32
Material:: specular_id
= 0;
355 OSG::UInt32
Material:: emissive_id
= 0;
356 OSG::UInt32
Material:: opacity_id
= 0;
357 OSG::UInt32
Material::shininess_id
= 0;
359 typedef std::vector
<Material
> VecMaterialsT
; // multiple materials
361 VecMaterialsT
initialize_materials(std::size_t num
) // helper to create materials
363 OSG_ASSERT(num
> max_num_lights
+ 1);
365 VecMaterialsT
mat(num
);
367 for (std::size_t i
= max_num_lights
+1; i
< num
; ++i
)
369 mat
[i
].ambient
= OSG::Color3f(0.001f
, 0.001f
, 0.001f
);
370 mat
[i
].diffuse
.setRandom();
371 mat
[i
].specular
= OSG::Color3f(0.9f
, 0.9f
, 0.9f
);
372 mat
[i
].emissive
= OSG::Color3f(0.0f
, 0.0f
, 0.0f
);
373 mat
[i
].opacity
= 1.f
;
374 mat
[i
].shininess
= 320.f
* small_die();
376 //int r = classic_die();
378 // mat[i].opacity = small_die();
382 // special grey material for box
384 mat
[0].ambient
= OSG::Color3f(0.001f
, 0.001f
, 0.001f
);
385 mat
[0].diffuse
= OSG::Color3f(0.7f
, 0.7f
, 0.7f
);
386 mat
[0].specular
= OSG::Color3f(0.9f
, 0.9f
, 0.9f
);
387 mat
[0].emissive
= OSG::Color3f(0.0f
, 0.0f
, 0.0f
);
388 mat
[0].opacity
= 1.f
;
389 mat
[0].shininess
= 100.f
;
394 VecMaterialsT materials
= initialize_materials(num_materials
); // the material database
397 // we reserve the first max_num_lights + 1 materials for the light simulation and
400 boost::uniform_int
<OSG::UInt32
> material_dist(max_num_lights
+1, num_materials
-1);
401 boost::variate_generator
<RNGType
, boost::uniform_int
<OSG::UInt32
> > material_idx_die(rng
, material_dist
);
404 // Simple geometry state data structure
412 OSG::UInt32 material_index
;
414 static OSG::UInt32 material_index_id
;
417 OSG::UInt32
GeomState::material_index_id
= 0;
419 // ============================================================================
421 // Part III: Creation and update of the light state
423 // ============================================================================
425 OSG::MultiLightChunkTransitPtr
create_light_state(const VecLightsT
& vLights
)
427 OSG::MultiLightChunkRefPtr lightChunk
= OSG::MultiLightChunk::create();
429 lightChunk
->setUsage(GL_DYNAMIC_DRAW
);
430 lightChunk
->setLayoutType(OSG::MultiLight::SIMPLE_LAYOUT
);
432 BOOST_FOREACH(const Light
& light
, vLights
)
434 OSG::UInt32 idx
= lightChunk
->addLight(light
.getType());
436 lightChunk
->setPosition (idx
, light
.position
);
437 lightChunk
->setDirection (idx
, light
.direction
);
438 lightChunk
->setColor (idx
, light
.color
);
439 lightChunk
->setIntensity (idx
, light
.intensity
);
440 lightChunk
->setRange (idx
, light
.range
);
441 lightChunk
->setSpotlightAngle (idx
, light
.spotlightAngle
);
442 lightChunk
->setEnabled (idx
, light
.enabled
);
443 lightChunk
->setType (idx
, light
.getType());
444 lightChunk
->setBeacon (idx
, light
.beacon
);
447 return OSG::MultiLightChunkTransitPtr(lightChunk
);
450 void update_light_state(OSG::MultiLightChunk
* lightChunk
, const VecLightsT
& vLights
)
454 if (lightChunk
->numLights() != vLights
.size())
456 lightChunk
->clearLights();
458 BOOST_FOREACH(const Light
& light
, vLights
)
460 OSG::UInt32 idx
= lightChunk
->addLight(light
.getType());
462 lightChunk
->setPosition (idx
, light
.position
);
463 lightChunk
->setDirection (idx
, light
.direction
);
464 lightChunk
->setColor (idx
, light
.color
);
465 lightChunk
->setIntensity (idx
, light
.intensity
);
466 lightChunk
->setRange (idx
, light
.range
);
467 lightChunk
->setSpotlightAngle (idx
, light
.spotlightAngle
);
468 lightChunk
->setEnabled (idx
, light
.enabled
);
469 lightChunk
->setType (idx
, light
.getType());
470 lightChunk
->setBeacon (idx
, light
.beacon
);
475 for (OSG::UInt32 idx
= 0; idx
< vLights
.size(); ++idx
)
477 const Light
& light
= vLights
[idx
];
479 lightChunk
->setPosition (idx
, light
.position
);
480 lightChunk
->setDirection (idx
, light
.direction
);
481 lightChunk
->setColor (idx
, light
.color
);
482 lightChunk
->setIntensity (idx
, light
.intensity
);
483 lightChunk
->setRange (idx
, light
.range
);
484 lightChunk
->setSpotlightAngle (idx
, light
.spotlightAngle
);
485 lightChunk
->setType (idx
, light
.getType());
486 lightChunk
->setEnabled (idx
, light
.enabled
);
487 lightChunk
->setBeacon (idx
, light
.beacon
);
493 // ============================================================================
495 // Part IV: Some routines for handling of the memory buffer and the the
496 // creation on the MultiPropertySSBOChunk objects:
498 // i) create_material_database_state,
499 // update_material_database_state
501 // ii) create_geometry_material_state,
502 // update_geometry_material_state
504 // ============================================================================
507 // i) the material shader storage buffer object
509 OSG::MultiPropertySSBOChunkTransitPtr
create_material_database_state(const VecMaterialsT
& vMaterials
)
511 OSG::MultiPropertySSBOChunkRefPtr materialChunk
= OSG::MultiPropertySSBOChunk::create();
513 OSG::UInt32 vec3_id
, float_id
;
515 vec3_id
= materialChunk
->addMember(OSG::MultiPropertySSBOChunk:: VEC3_T
, 4);
516 float_id
= materialChunk
->addMember(OSG::MultiPropertySSBOChunk::FLOAT_T
, 2);
518 materialChunk
->setUsage(GL_STATIC_DRAW
);
520 Material:: ambient_id
= vec3_id
++;
521 Material:: diffuse_id
= vec3_id
++;
522 Material:: specular_id
= vec3_id
++;
523 Material:: emissive_id
= vec3_id
;
525 Material:: opacity_id
= float_id
++;
526 Material::shininess_id
= float_id
;
528 BOOST_FOREACH(const Material
& mat
, vMaterials
)
530 OSG::UInt32 idx
= materialChunk
->addProperty();
532 materialChunk
->setVec3Property (idx
, Material:: ambient_id
, mat
.ambient
);
533 materialChunk
->setVec3Property (idx
, Material:: diffuse_id
, mat
.diffuse
);
534 materialChunk
->setVec3Property (idx
, Material:: specular_id
, mat
.specular
);
535 materialChunk
->setVec3Property (idx
, Material:: emissive_id
, mat
.emissive
);
537 materialChunk
->setFloatProperty(idx
, Material:: opacity_id
, mat
.opacity
);
538 materialChunk
->setFloatProperty(idx
, Material::shininess_id
, mat
.shininess
);
541 return OSG::MultiPropertySSBOChunkTransitPtr(materialChunk
);
544 void update_material_database_state(OSG::MultiPropertySSBOChunk
* materialChunk
, const VecMaterialsT
& vMaterials
)
548 if (materialChunk
->getNumProperties() != vMaterials
.size())
550 materialChunk
->clearProperties();
552 BOOST_FOREACH(const Material
& mat
, vMaterials
)
554 OSG::UInt32 idx
= materialChunk
->addProperty();
556 materialChunk
->setVec3Property (idx
, Material:: ambient_id
, mat
.ambient
);
557 materialChunk
->setVec3Property (idx
, Material:: diffuse_id
, mat
.diffuse
);
558 materialChunk
->setVec3Property (idx
, Material:: specular_id
, mat
.specular
);
559 materialChunk
->setVec3Property (idx
, Material:: emissive_id
, mat
.emissive
);
561 materialChunk
->setFloatProperty(idx
, Material:: opacity_id
, mat
.opacity
);
562 materialChunk
->setFloatProperty(idx
, Material::shininess_id
, mat
.shininess
);
567 for (OSG::UInt32 idx
= 0; idx
< vMaterials
.size(); ++idx
)
569 const Material
& mat
= vMaterials
[idx
];
571 materialChunk
->setVec3Property (idx
, Material:: ambient_id
, mat
.ambient
);
572 materialChunk
->setVec3Property (idx
, Material:: diffuse_id
, mat
.diffuse
);
573 materialChunk
->setVec3Property (idx
, Material:: specular_id
, mat
.specular
);
574 materialChunk
->setVec3Property (idx
, Material:: emissive_id
, mat
.emissive
);
576 materialChunk
->setFloatProperty(idx
, Material:: opacity_id
, mat
.opacity
);
577 materialChunk
->setFloatProperty(idx
, Material::shininess_id
, mat
.shininess
);
584 // ii) the geomertry shader storage buffer object
586 OSG::MultiPropertyUBOChunkTransitPtr
create_geometry_material_state(const GeomState
& geom_state
)
588 OSG::MultiPropertyUBOChunkRefPtr geomStateChunk
= OSG::MultiPropertyUBOChunk::create();
590 GeomState::material_index_id
= geomStateChunk
->addMember(OSG::MultiPropertyUBOChunk::UINT_T
, 1);
591 geomStateChunk
->setUsage(GL_DYNAMIC_DRAW
);
593 OSG::UInt32 idx
= geomStateChunk
->addProperty();
594 geomStateChunk
->setUIntProperty(idx
, GeomState::material_index_id
, geom_state
.material_index
);
596 return OSG::MultiPropertyUBOChunkTransitPtr(geomStateChunk
);
599 void update_geometry_material_state(OSG::MultiPropertyUBOChunk
* geomStateChunk
, const GeomState
& geom_state
)
603 if (geomStateChunk
->getNumProperties() != 1)
605 geomStateChunk
->clearProperties();
607 OSG::UInt32 idx
= geomStateChunk
->addProperty();
608 geomStateChunk
->setUIntProperty(idx
, GeomState::material_index_id
, geom_state
.material_index
);
612 geomStateChunk
->setUIntProperty( 0, GeomState::material_index_id
, geom_state
.material_index
);
617 // ============================================================================
619 // Part V: The application finally starts here
621 // ============================================================================
624 // vertex shader program.
626 std::string
get_vp_program();
629 // fragment shader program for bump mapping in surface local coordinates
631 std::string
get_fp_program();
636 OSG::NodeRefPtr scene_node
= NULL
;
641 OSG::HDR2StageRefPtr hdr_stage
= NULL
;
642 OSG::NodeRefPtr hdr_node
= NULL
;
645 // The material database for all visible geometry: objects, lights, stage box
647 OSG::MultiPropertySSBOChunkRefPtr ssbo_material_database
= NULL
;
650 // The mulit light chunk
652 OSG::MultiLightChunkRefPtr multi_light_chunk
= NULL
;
655 // The block binding point for the geom state
657 OSG::ShaderProgramVariableChunkRefPtr shader_var_chunk
= NULL
;
660 // Shader Storage buffer objects corresponding to transient shader blocks
662 std::vector
<OSG::MultiPropertyUBOChunkRefPtr
> ubo_geom_states
;
665 // A separate transformation for each object and a spline for the trajectory
667 std::vector
<OSG::NodeRefPtr
> geom_nodes
;
668 std::vector
<OSG::TransformRefPtr
> geom_trafos
;
669 std::vector
<SmoothCubicBezierSpline
> geom_curves
;
674 void setup_hdr_stage()
678 hdr_stage
->setApplyGamma (true);
679 hdr_stage
->setAccurateGamma (true);
681 hdr_stage
->setAdjustLuminance (false);
683 hdr_stage
->setPerformBloom (false);
684 hdr_stage
->setBloomBackground (false);
686 hdr_stage
->setForceBackground (true);
687 hdr_stage
->setUse_ITU_R_BT_709 (true);
688 hdr_stage
->setMipmapLevel (-1);
690 hdr_stage
->setTarget (OSG::HDR2Stage::COMPOSITE_TEXTURE
);
691 hdr_stage
->setCarryDepth (true);
693 hdr_stage
->setColorBufferInternalFormat (GL_RGBA16F
);
694 hdr_stage
->setColorBufferPixelFormat (GL_RGBA
);
695 hdr_stage
->setColorBufferType (GL_FLOAT
);
697 hdr_stage
->setDepthBufferInternalFormat (GL_DEPTH24_STENCIL8
);
698 hdr_stage
->setDepthBufferPixelFormat (GL_DEPTH_STENCIL
);
699 hdr_stage
->setDepthBufferType (GL_UNSIGNED_INT_24_8
);
701 hdr_stage
->setLumBufferInternalFormat (GL_R32F
);
702 hdr_stage
->setLumBufferPixelFormat (GL_RED
);
703 hdr_stage
->setLumBufferType (GL_FLOAT
);
705 hdr_stage
->setImageBufferInternalFormat (GL_RGB16F
);
706 hdr_stage
->setImageBufferPixelFormat (GL_RGB
);
707 hdr_stage
->setImageBufferType (GL_FLOAT
);
709 hdr_stage
->setNumSamples (0);
711 hdr_stage
->setBloomThreshold (2.0f
);
712 hdr_stage
->setBloomMagnitude (0.0f
);
713 hdr_stage
->setToneMappingMode (OSG::HDR2Stage::REINHARD_TONE_MAPPING
);
714 hdr_stage
->setExposure (0.0f
);
715 hdr_stage
->setKeyValue (0.18f
);
716 hdr_stage
->setAutoExposureMode (OSG::HDR2Stage::MANUAL
);
717 hdr_stage
->setWhiteLevel (5.0f
);
718 hdr_stage
->setFilmicShoulderStrenght (0.15f
);
719 hdr_stage
->setFilmicLinearStrength (0.5f
);
720 hdr_stage
->setFilmicLinearAngle (0.1f
);
721 hdr_stage
->setFilmicToeStrength (0.2f
);
722 hdr_stage
->setFilmicToeNumerator (0.02f
);
723 hdr_stage
->setFilmicToeDenominator (0.3f
);
724 hdr_stage
->setFilmicLinearWhite (11.2f
);
725 hdr_stage
->setSaturation (1.0f
);
726 hdr_stage
->setDragoBias (0.85f
);
727 hdr_stage
->setTau (1.25f
);
728 hdr_stage
->setNumTaps (4);
729 hdr_stage
->setBlurGaussSigma (0.8f
);
730 hdr_stage
->setUseLinChromCorrection (true);
734 void removeHDRStage()
736 OSG::GroupRefPtr group
= OSG::Group::create();
737 hdr_node
->setCore(group
);
742 void createHDRStage()
746 hdr_stage
= OSG::HDR2Stage::create();
751 hdr_node
->setCore(hdr_stage
);
757 void deinitialize_lights()
759 BOOST_FOREACH(const Light
& light
, lights
)
761 scene_node
->subChild(light
.beacon
);
767 void initialize_lights(OSG::UInt32 num
) // helper to create lights
769 deinitialize_lights();
771 for (OSG::UInt32 i
= 0; i
< num
; ++i
)
774 int n
= classic_die();
777 type
= Light::point_light
;
779 type
= Light::spot_light
;
781 lights
.push_back(Light::create_light(type
, i
+1));
782 scene_node
->addChild(lights
[i
].beacon
);
786 Light
Light::create_light(
787 Type e
, // type of the light
788 OSG::UInt32 material_idx
) // index in to the material storage for light animation
792 l
.beacon
= OSG::makeCoredNode
<OSG::Transform
>(&l
.transform
);
795 OSG::Real32 L
= box_factor
* world_size
;
797 l
.direction
= dice_unit_vector();
800 l
.intensity
= max_light_power
* small_die();
801 l
.range
= L
* light_range_die();
804 mat
.emissive
= l
.color
;
805 materials
[material_idx
] = mat
;
811 OSG::GeometryRefPtr geometry
= OSG::makeSphereGeo(3, 0.1f
);
812 OSG::NodeRefPtr node
= OSG::makeNodeFor(geometry
);
814 GeomState geom
; geom
.material_index
= material_idx
; // material index used for light animiation
815 OSG::ChunkMaterialRefPtr geom_state
= OSG::ChunkMaterial::create();
816 OSG::MultiPropertyUBOChunkRefPtr ubo_geom_state
= create_geometry_material_state(geom
);
817 geom_state
->addChunk(ubo_geom_state
, 3); // buffer binding point 3
818 geom_state
->addChunk(shader_var_chunk
); // block binding point
820 geometry
->setMaterial(geom_state
);
822 l
.beacon
->addChild(node
);
826 case directional_light
:
833 l
.spotlightAngle
= 90.f
* small_die();
835 GeomState geom
; geom
.material_index
= material_idx
; // material index used for light animiation
836 OSG::ChunkMaterialRefPtr geom_state
= OSG::ChunkMaterial::create();
837 OSG::MultiPropertyUBOChunkRefPtr ubo_geom_state
= create_geometry_material_state(geom
);
838 geom_state
->addChunk(ubo_geom_state
, 3); // buffer binding point 3
839 geom_state
->addChunk(shader_var_chunk
); // block binding point
841 OSG::Real32 r
= 0.1f
;
842 OSG::Real32 h
= r
/ OSG::osgTan(OSG::osgDegree2Rad(l
.spotlightAngle
));
843 OSG::GeometryRefPtr geometry
= OSG::makeConeGeo(h
, r
, 24, true, true);
844 geometry
->setMaterial(geom_state
);
846 OSG::TransformRefPtr cone_trans
= OSG::Transform::create();
847 OSG::Matrix spot_mat
;
848 bool result
= OSG::MatrixLookAt(spot_mat
, l
.direction
, OSG::Pnt3f(0,0,0), OSG::Vec3f(0,1,0));
850 OSG::MatrixLookAt(spot_mat
, l
.direction
, OSG::Pnt3f(0,0,0), OSG::Vec3f(1,0,0));
851 cone_trans
->setMatrix(spot_mat
);
853 OSG::Real32 ang
= -90.f
;
854 OSG::Vec3f
rotVec(1,0,0);
856 OSG::TransformRefPtr rot_trans
= OSG::Transform::create();
858 rot_mat
.setRotate(OSG::Quaternion(rotVec
, OSG::osgDegree2Rad(ang
)));
859 rot_trans
->setMatrix(rot_mat
);
861 OSG::NodeRefPtr cone_trans_node
= OSG::makeNodeFor(cone_trans
);
862 OSG::NodeRefPtr rot_trans_node
= OSG::makeNodeFor(rot_trans
);
863 OSG::NodeRefPtr cone_node
= OSG::makeNodeFor(geometry
);
865 l
.beacon
->addChild(cone_trans_node
);
867 cone_trans_node
->addChild(rot_trans_node
);
868 rot_trans_node
->addChild(cone_node
);
870 //OSG::GeometryRefPtr geometry_test = OSG::makeCylinderGeo(30, .01f, 24, true, true, true );
871 //geometry_test->setMaterial(geom_state);
873 //OSG::TransformRefPtr test_trans = OSG::Transform::create();
874 //OSG::Matrix test_mat;
875 //test_mat.setTranslate(OSG::Vec3f(0,-15,0));
876 //test_trans->setMatrix(test_mat);
878 //OSG::NodeRefPtr test_rot_trans_node = OSG::makeNodeFor(rot_trans);
879 //OSG::NodeRefPtr test_trans_node = OSG::makeNodeFor(test_trans);
880 //OSG::NodeRefPtr test_node = OSG::makeNodeFor(geometry_test);
881 //cone_trans_node->addChild(test_rot_trans_node);
882 //test_rot_trans_node->addChild(test_trans_node);
883 //test_trans_node->addChild(test_node);
894 OSG::NodeTransitPtr
createBox()
896 OSG::NodeRefPtr box_root
= OSG::makeCoredNode
<OSG::Group
>();
898 OSG::Real32 L
= box_factor
* world_size
;
899 OSG::GeometryRefPtr box_plane
= OSG::makePlaneGeo(2.f
*L
, 2.f
*L
, 128, 128);
901 OSG::NodeRefPtr box_bottom
= OSG::makeNodeFor(box_plane
);
902 OSG::NodeRefPtr box_left
= OSG::makeNodeFor(box_plane
);
903 OSG::NodeRefPtr box_right
= OSG::makeNodeFor(box_plane
);
904 OSG::NodeRefPtr box_far
= OSG::makeNodeFor(box_plane
);
906 OSG::TransformRefPtr box_bottom_trans
= OSG::Transform::create();
907 OSG::TransformRefPtr box_left_trans
= OSG::Transform::create();
908 OSG::TransformRefPtr box_right_trans
= OSG::Transform::create();
909 OSG::TransformRefPtr box_far_trans
= OSG::Transform::create();
911 OSG::Matrix mat_bottom
, mat_left
, mat_right
, mat_far
;
913 mat_bottom
.setTransform(OSG::Vec3f(0.f
, -L
, 0.f
), OSG::Quaternion( OSG::Vec3f(1, 0, 0), OSG::osgDegree2Rad(270.f
)));
914 mat_left
.setTransform(OSG::Vec3f( -L
, 0.f
, 0.f
), OSG::Quaternion( OSG::Vec3f(0, 1, 0), OSG::osgDegree2Rad(90.f
)));
915 mat_right
.setTransform(OSG::Vec3f( L
, 0.f
, 0.f
), OSG::Quaternion( OSG::Vec3f(0, 1, 0), OSG::osgDegree2Rad(270.f
)));
916 mat_far
.setTransform(OSG::Vec3f(0.f
, 0.f
, -L
), OSG::Quaternion( OSG::Vec3f(0, 0, 1), OSG::osgDegree2Rad( 0.f
)));
918 box_bottom_trans
->setMatrix(mat_bottom
);
919 box_left_trans
->setMatrix(mat_left
);
920 box_right_trans
->setMatrix(mat_right
);
921 box_far_trans
->setMatrix(mat_far
);
923 OSG::NodeRefPtr box_bottom_trans_node
= OSG::makeNodeFor(box_bottom_trans
);
924 OSG::NodeRefPtr box_left_trans_node
= OSG::makeNodeFor(box_left_trans
);
925 OSG::NodeRefPtr box_right_trans_node
= OSG::makeNodeFor(box_right_trans
);
926 OSG::NodeRefPtr box_far_trans_node
= OSG::makeNodeFor(box_far_trans
);
928 box_bottom_trans_node
->addChild(box_bottom
);
929 box_left_trans_node
->addChild(box_left
);
930 box_right_trans_node
->addChild(box_right
);
931 box_far_trans_node
->addChild(box_far
);
933 box_root
->addChild(box_bottom_trans_node
);
934 box_root
->addChild(box_left_trans_node
);
935 box_root
->addChild(box_right_trans_node
);
936 box_root
->addChild(box_far_trans_node
);
938 GeomState geom
; geom
.material_index
= 0; // grey box material index
939 OSG::ChunkMaterialRefPtr geom_state
= OSG::ChunkMaterial::create();
940 OSG::MultiPropertyUBOChunkRefPtr ubo_geom_state
= create_geometry_material_state(geom
);
941 geom_state
->addChunk(ubo_geom_state
, 3); // buffer binding point 3
942 geom_state
->addChunk(shader_var_chunk
); // block binding point
944 OSG::PolygonChunkRefPtr polygonChunk
= OSG::PolygonChunk::create();
945 polygonChunk
->setFrontMode(GL_SMOOTH
);
946 polygonChunk
->setBackMode(GL_SMOOTH
);
947 polygonChunk
->setOffsetFactor(1.f
);
948 polygonChunk
->setOffsetBias(1.f
);
949 polygonChunk
->setOffsetFill(true);
950 polygonChunk
->setCullFace(GL_NONE
);
951 geom_state
->addChunk(polygonChunk
);
952 geom_state
->setTransparencyMode(OSG::Material::TransparencyForceOpaque
);
954 OSG::TwoSidedLightingChunkRefPtr twoSidedLightingChunk
= OSG::TwoSidedLightingChunk::create();
955 geom_state
->addChunk(twoSidedLightingChunk
);
957 box_plane
->setMaterial(geom_state
);
959 return OSG::NodeTransitPtr(box_root
);
962 OSG::NodeTransitPtr
createGeometry()
964 int idx
= geom_idx_die();
966 OSG::GeometryRefPtr geometry
;
971 geometry
= OSG::makeConeGeo(3.f
* small_die(), 1.f
* small_die(), 24, true, true);
974 geometry
= OSG::makeBoxGeo(3.f
* small_die(), 3.f
* small_die(), 3.f
* small_die(), 1, 1, 1);
977 geometry
= OSG::makeCylinderGeo(3.f
* small_die(), .3f
, 24, true, true, true );
980 geometry
= OSG::makeSphereGeo(6, 3.f
* small_die());
983 geometry
= OSG::makeTorusGeo(0.6f
* small_die(), 2.f
* small_die(), 24, 36);
985 case 5: // ellipsoide
986 geometry
= OSG::makeLatLongEllipsoidGeo(24, 36, 2.f
* small_die(), 1.f
* small_die());
989 geometry
= OSG::makeConicalFrustumGeo(2.f
* small_die(), 2.f
* small_die(), 2.f
* small_die(), 6, true, true, true);
992 geometry
= OSG::makeTeapotGeo(24, 1.f
* small_die());
996 OSG::NodeRefPtr geomNode
= OSG::makeNodeFor(geometry
);
998 OSG::TransformRefPtr trafoCore
= OSG::Transform::create();
999 OSG::NodeRefPtr transNode
= OSG::makeNodeFor(trafoCore
);
1000 transNode
->addChild(geomNode
);
1002 GeomState geom
; geom
.material_index
= material_idx_die();
1003 OSG::ChunkMaterialRefPtr geom_state
= OSG::ChunkMaterial::create();
1004 OSG::MultiPropertyUBOChunkRefPtr ubo_geom_state
= create_geometry_material_state(geom
);
1005 geom_state
->addChunk(ubo_geom_state
, 3); // buffer binding point 3
1006 geom_state
->addChunk(shader_var_chunk
); // block binding point
1008 OSG::PolygonChunkRefPtr polygonChunk
= OSG::PolygonChunk::create();
1009 polygonChunk
->setFrontMode(GL_SMOOTH
);
1010 polygonChunk
->setBackMode(GL_SMOOTH
);
1011 polygonChunk
->setOffsetFactor(1.f
);
1012 polygonChunk
->setOffsetBias(1.f
);
1013 polygonChunk
->setOffsetFill(true);
1015 OSG::Real32 opacity
= materials
[geom
.material_index
].opacity
;
1018 polygonChunk
->setCullFace(GL_NONE
);
1020 OSG::BlendChunkRefPtr blendChunk
= OSG::BlendChunk::create();
1021 blendChunk
->setSrcFactor (GL_SRC_ALPHA
);
1022 blendChunk
->setDestFactor(GL_ONE_MINUS_SRC_ALPHA
);
1023 geom_state
->addChunk(blendChunk
);
1024 geom_state
->setTransparencyMode(OSG::Material::TransparencyForceTransparent
);
1026 OSG::TwoSidedLightingChunkRefPtr twoSidedLightingChunk
= OSG::TwoSidedLightingChunk::create();
1027 geom_state
->addChunk(twoSidedLightingChunk
);
1030 polygonChunk
->setCullFace(GL_BACK
);
1031 geom_state
->setTransparencyMode(OSG::Material::TransparencyForceOpaque
);
1034 geom_state
->addChunk(polygonChunk
);
1036 geometry
->setMaterial(geom_state
);
1038 geom_nodes
.push_back(transNode
);
1039 geom_trafos
.push_back(trafoCore
);
1040 ubo_geom_states
.push_back(ubo_geom_state
);
1042 geom_curves
.push_back(SmoothCubicBezierSpline(dice_knots(true)));
1044 return OSG::NodeTransitPtr(transNode
);
1048 // forward declaration so we can have the interesting stuff upfront
1050 int setupGLUT (int *argc
, char *argv
[]);
1055 // Initialize GLUT & OpenSG and set up the scene
1057 int main(int argc
, char **argv
)
1060 OSG::osgInit(argc
,argv
);
1063 int winid
= setupGLUT(&argc
, argv
);
1067 // open a new scope, because the pointers below should go out of scope
1068 // before entering glutMainLoop.
1069 // Otherwise OpenSG will complain about objects being alive after shutdown.
1071 // the connection between GLUT and OpenSG
1072 OSG::GLUTWindowRefPtr gwin
= OSG::GLUTWindow::create();
1073 gwin
->setGlutId(winid
);
1076 // create the SimpleSceneManager helper
1077 mgr
= OSG::SimpleSceneManager::create();
1078 mgr
->setWindow(gwin
);
1081 hdr_node
= OSG::makeCoredNode
<OSG::Group
>();
1082 scene_node
= OSG::makeCoredNode
<OSG::Group
>();
1084 hdr_node
->addChild(scene_node
);
1086 mgr
->setRoot(hdr_node
);
1091 // create the shader program
1093 OSG::ShaderProgramChunkRefPtr prog_chunk
= OSG::ShaderProgramChunk::create();
1094 OSG::ShaderProgramRefPtr vertShader
= OSG::ShaderProgram::createVertexShader();
1095 OSG::ShaderProgramRefPtr fragShader
= OSG::ShaderProgram::createFragmentShader();
1097 vertShader
->setProgram(get_vp_program());
1098 fragShader
->setProgram(get_fp_program());
1100 fragShader
->addOSGVariable("OSGViewMatrix");
1103 // binding the shader storage block to a buffer binding point can be performed
1104 // either by calling the shaders's addShaderStorageBlock method or by
1105 // adding a 'buffer block' variable to a ShaderProgramVariableChunk.
1106 // In the following we use both variants for illustration.
1108 fragShader
->addShaderStorageBlock("Materials", 1); // block binding point
1109 fragShader
->addShaderStorageBlock("Lights", 2); // block binding point
1112 // The following is replaced by adding ShaderProgramVariableChunk objects
1113 // to the chunk material. See below...
1115 // fragShader->addShaderStorageBlock("GeomState", 3); // block binding point
1117 prog_chunk
->addShader(vertShader
);
1118 prog_chunk
->addShader(fragShader
);
1121 // The block binding is added to each ChunkMaterial in order to provide the state
1122 // shader uniform block for the geometery shown in the scene
1124 shader_var_chunk
= OSG::ShaderProgramVariableChunk::create();
1125 shader_var_chunk
->addUniformBlock("GeomState", 3); // block binding point
1128 // Because we animate the lights by simple geometry, the lights initialization must be happens
1129 // after the creation of the 'shader_var_chunk' block binding point.
1130 // Additionally, it must happens before we call 'create_light_state', since here we do need the
1131 // already defined lights.
1133 initialize_lights(1);
1136 // create shader storage buffer objects and corresponding materials
1138 ssbo_material_database
= create_material_database_state(materials
);
1139 multi_light_chunk
= create_light_state(lights
);
1141 //multi_light_chunk->setEyeSpace(true);
1143 OSG::PolygonChunkRefPtr polygon_chunk
= OSG::PolygonChunk::create();
1144 polygon_chunk
->setFrontMode(GL_FILL
);
1145 polygon_chunk
->setBackMode(GL_FILL
);
1146 polygon_chunk
->setCullFace(GL_NONE
);
1148 OSG::DepthChunkRefPtr depth_chunk
= OSG::DepthChunk::create();
1149 depth_chunk
->setEnable(true);
1151 OSG::ChunkMaterialRefPtr prog_state
= OSG::ChunkMaterial::create();
1152 prog_state
->addChunk(ssbo_material_database
, 1); // buffer binding point 1
1153 prog_state
->addChunk(multi_light_chunk
, 2); // buffer binding point 2
1154 prog_state
->addChunk(prog_chunk
);
1155 prog_state
->addChunk(polygon_chunk
);
1156 prog_state
->addChunk(depth_chunk
);
1158 scene_node
->addChild(createBox());
1160 for (OSG::Int32 i
= 0; i
< num_geometries
; ++i
)
1161 scene_node
->addChild(createGeometry());
1163 OSG::MaterialChunkOverrideGroupRefPtr mgrp
= OSG::MaterialChunkOverrideGroup::create();
1164 mgrp
->setMaterial(prog_state
);
1165 scene_node
->setCore(mgrp
);
1167 OSG::commitChanges();
1169 // show the whole scene
1180 // GLUT callback functions
1184 // redraw the window
1186 OSG::TimeStamp time_stamp
= 0;
1187 OSG::Real32 simulation_param
= 0.f
;
1188 bool simulate_geometry
= true;
1189 bool simulate_lights
= true;
1193 // create the matrix
1196 if (time_stamp
== 0)
1197 time_stamp
= OSG::getTimeStamp();
1199 OSG::Time elapsed
= OSG::getTimeStampMsecs(OSG::getTimeStamp() - time_stamp
);
1201 if (elapsed
> elapse_time_limit
)
1203 simulation_param
+= simulation_delta
;
1204 if (simulation_param
>= 1.f
)
1205 simulation_param
= 0.f
;
1207 if (simulate_geometry
)
1209 std::size_t numCurves
= geom_curves
.size();
1211 OSG_ASSERT(numCurves
== geom_trafos
.size());
1213 for (std::size_t i
= 0; i
< numCurves
; ++i
)
1215 m
= geom_curves
[i
].frame(simulation_param
);
1216 geom_trafos
[i
]->setMatrix(m
);
1220 if (simulate_lights
)
1222 BOOST_FOREACH(Light
& light
, lights
)
1224 m
= light
.curve
.frame(simulation_param
, true);
1225 light
.transform
->setMatrix(m
);
1230 time_stamp
= OSG::getTimeStamp();
1233 OSG::commitChanges();
1239 // react to size changes
1241 void reshape(int w
, int h
)
1244 glutPostRedisplay();
1248 // react to mouse button presses
1250 void mouse(int button
, int state
, int x
, int y
)
1253 mgr
->mouseButtonRelease(button
, x
, y
);
1255 mgr
->mouseButtonPress(button
, x
, y
);
1257 glutPostRedisplay();
1261 // react to mouse motions with pressed buttons
1263 void motion(int x
, int y
)
1265 mgr
->mouseMove(x
, y
);
1266 glutPostRedisplay();
1272 void keyboard(unsigned char k
, int x
, int y
)
1278 // clean up global variables
1286 multi_light_chunk
= NULL
;
1287 shader_var_chunk
= NULL
;
1290 geom_trafos
.clear();
1291 geom_curves
.clear();
1293 ubo_geom_states
.clear();
1307 simulate_geometry
= !simulate_geometry
;
1313 simulate_lights
= !simulate_lights
;
1319 elapse_time_limit
*= 2.f
;
1325 elapse_time_limit
/= 2.f
;
1331 simulation_delta
*= 2.f
;
1337 simulation_delta
/= 2.f
;
1343 initialize_lights(1);
1344 update_light_state(multi_light_chunk
, lights
);
1345 update_material_database_state(ssbo_material_database
, materials
);
1347 simulation_delta
= 0.0001f
;
1348 elapse_time_limit
= 10.f
;
1350 simulate_geometry
= true;
1351 simulate_lights
= true;
1353 glutPostRedisplay();
1359 BOOST_FOREACH(Light
& light
, lights
)
1360 light
.range
*= rangeFactor
;
1362 update_light_state(multi_light_chunk
, lights
);
1363 glutPostRedisplay();
1369 BOOST_FOREACH(Light
& light
, lights
)
1370 if (light
.range
/ rangeFactor
>= OSG::Eps
)
1371 light
.range
/= rangeFactor
;
1373 update_light_state(multi_light_chunk
, lights
);
1374 glutPostRedisplay();
1380 BOOST_FOREACH(Light
& light
, lights
)
1381 light
.intensity
*= 1.2f
;
1383 update_light_state(multi_light_chunk
, lights
);
1384 glutPostRedisplay();
1390 BOOST_FOREACH(Light
& light
, lights
)
1391 if (light
.range
/ intensityFactor
>= OSG::Eps
)
1392 light
.intensity
/= intensityFactor
;
1394 update_light_state(multi_light_chunk
, lights
);
1395 glutPostRedisplay();
1401 initialize_lights(1);
1402 update_light_state(multi_light_chunk
, lights
);
1403 update_material_database_state(ssbo_material_database
, materials
);
1404 glutPostRedisplay();
1410 if (lights
.size() > 1)
1412 OSG::UInt32 num
= static_cast<OSG::UInt32
>(lights
.size() / 2);
1413 initialize_lights(num
);
1414 update_light_state(multi_light_chunk
, lights
);
1415 update_material_database_state(ssbo_material_database
, materials
);
1416 glutPostRedisplay();
1423 if (lights
.size() <= max_num_lights
)
1425 OSG::UInt32 num
= static_cast<OSG::UInt32
>(lights
.size() * 2);
1426 initialize_lights(num
);
1427 update_light_state(multi_light_chunk
, lights
);
1428 update_material_database_state(ssbo_material_database
, materials
);
1429 glutPostRedisplay();
1436 if (geom_nodes
.size() > 1)
1438 OSG::UInt32 num
= static_cast<OSG::UInt32
>(geom_nodes
.size() / 2);
1440 BOOST_FOREACH(OSG::Node
* node
, geom_nodes
)
1441 scene_node
->subChild(node
);
1444 geom_trafos
.clear();
1445 geom_curves
.clear();
1446 ubo_geom_states
.clear();
1448 for (OSG::UInt32 i
= 0; i
< num
; ++i
)
1449 scene_node
->addChild(createGeometry());
1451 glutPostRedisplay();
1458 if (geom_nodes
.size() <= 4.f
* num_geometries
)
1460 OSG::UInt32 num
= static_cast<OSG::UInt32
>(geom_nodes
.size() * 2);
1462 BOOST_FOREACH(OSG::Node
* node
, geom_nodes
)
1463 scene_node
->subChild(node
);
1466 geom_trafos
.clear();
1467 geom_curves
.clear();
1468 ubo_geom_states
.clear();
1470 for (OSG::UInt32 i
= 0; i
< num
; ++i
)
1471 scene_node
->addChild(createGeometry());
1473 glutPostRedisplay();
1480 BOOST_FOREACH(OSG::MultiPropertyUBOChunk
* ubo_geom_state
, ubo_geom_states
)
1482 GeomState geom
; geom
.material_index
= material_idx_die();
1483 update_geometry_material_state(ubo_geom_state
, geom
);
1486 glutPostRedisplay();
1492 mgr
->setStatistics(!mgr
->getStatistics());
1498 OSG::HDR2Stage
* core
= dynamic_cast<OSG::HDR2Stage
*>(hdr_node
->getCore());
1504 glutPostRedisplay();
1511 // setup the GLUT library which handles the windows for us
1513 int setupGLUT(int *argc
, char *argv
[])
1515 glutInit(argc
, argv
);
1516 glutInitDisplayMode(GLUT_RGB
| GLUT_DEPTH
| GLUT_DOUBLE
);
1517 glutInitWindowSize(1000, 800);
1519 int winid
= glutCreateWindow("OpenSG");
1521 glutReshapeFunc(reshape
);
1522 glutDisplayFunc(display
);
1523 glutMouseFunc(mouse
);
1524 glutMotionFunc(motion
);
1525 glutKeyboardFunc(keyboard
);
1527 // call the redraw function whenever there's nothing else to do
1528 glutIdleFunc(display
);
1535 glutReshapeFunc(NULL
);
1536 glutDisplayFunc(NULL
);
1537 glutMouseFunc(NULL
);
1538 glutMotionFunc(NULL
);
1539 glutKeyboardFunc(NULL
);
1545 std::cout
<< "Esc : quit example" << std::endl
;
1546 std::cout
<< "Space : toogle geometry simulation on/off" << std::endl
;
1547 std::cout
<< "h : toogle HDR stage usage on/off" << std::endl
;
1548 std::cout
<< "l : toogle light simulation on/off" << std::endl
;
1549 std::cout
<< "m : assign new color to geometry" << std::endl
;
1550 std::cout
<< "r : reset the example" << std::endl
;
1551 std::cout
<< "s : toogle statistics on/off" << std::endl
;
1552 std::cout
<< "1 : only one light" << std::endl
;
1553 std::cout
<< "2 : half number of lights" << std::endl
;
1554 std::cout
<< "3 : double number of lights" << std::endl
;
1555 std::cout
<< "4 : half number of geometry objects" << std::endl
;
1556 std::cout
<< "5 : double number of geometry objects" << std::endl
;
1557 std::cout
<< "e/E : speed up/down simulation" << std::endl
;
1558 std::cout
<< "o/O : double/half simulation time interval" << std::endl
;
1559 std::cout
<< "i/I : increase/decrease light intensity" << std::endl
;
1560 std::cout
<< "p/P : increase/decrease light range" << std::endl
;
1564 // ============================================================================
1566 // Part VI: Cubic Bezier spline curve implementation
1568 // ============================================================================
1570 CubicBezierCurve::CubicBezierCurve(
1571 const OSG::Pnt3f
& p0
,
1572 const OSG::Pnt3f
& p1
,
1573 const OSG::Pnt3f
& p2
,
1574 const OSG::Pnt3f
& p3
)
1576 p
[0] = p0
; p
[1] = p1
; p
[2] = p2
; p
[3] = p3
;
1579 CubicBezierCurve::CubicBezierCurve(const CubicBezierCurve
& rhs
)
1581 p
[0] = rhs
.p
[0]; p
[1] = rhs
.p
[1]; p
[2] = rhs
.p
[2]; p
[3] = rhs
.p
[3];
1584 CubicBezierCurve
& CubicBezierCurve::operator=(const CubicBezierCurve
& rhs
)
1588 p
[0] = rhs
.p
[0]; p
[1] = rhs
.p
[1]; p
[2] = rhs
.p
[2]; p
[3] = rhs
.p
[3];
1593 OSG::Pnt3f
CubicBezierCurve::operator()(OSG::Real32 t
) const
1595 OSG_ASSERT(0.f
<= t
&& t
<= 1.f
);
1597 OSG::Real32 e
= 1.f
- t
;
1598 OSG::Real32 sq_e
= e
* e
;
1599 OSG::Real32 sq_t
= t
* t
;
1601 return e
* sq_e
* p
[0]
1602 + 3.f
* t
* sq_e
* p
[1].subZero()
1603 + 3.f
* sq_t
* e
* p
[2].subZero()
1604 + t
* sq_t
* p
[3].subZero();
1607 OSG::Vec3f
CubicBezierCurve::tangent(OSG::Real32 t
) const
1609 OSG::Vec3f tangent
= fst_derivative(t
);
1610 tangent
.normalize();
1615 OSG::Vec3f
CubicBezierCurve::normal(OSG::Real32 t
) const
1617 OSG::Vec3f normal
= binormal(t
);
1618 normal
.crossThis(tangent(t
));
1624 OSG::Vec3f
CubicBezierCurve::binormal(OSG::Real32 t
) const
1626 OSG::Vec3f binormal
= fst_derivative(t
);
1627 binormal
.crossThis(sec_derivative(t
));
1628 binormal
.normalize();
1630 while (OSG::osgAbs(binormal
.length() - 1.f
) >= OSG::Eps
)
1632 if (t
+ OSG::Eps
<= 1.f
)
1634 else if (t
- OSG::Eps
>= 0.f
)
1639 binormal
= fst_derivative(t
);
1640 binormal
.crossThis(sec_derivative(t
));
1641 binormal
.normalize();
1647 OSG::Matrix
CubicBezierCurve::frame(OSG::Real32 t
, bool position_only
) const
1652 OSG::Vec3f P
= (*this)(t
).subZero();
1656 mat
.setTranslate(P
);
1660 OSG::Vec3f T
= tangent(t
);
1661 OSG::Vec3f N
= normal(t
);
1662 OSG::Vec3f B
= binormal(t
);
1665 OSG::Real32 lT
= T
.length();
1666 OSG::Real32 lN
= N
.length();
1667 OSG::Real32 lB
= B
.length();
1669 OSG::Real32 v1
= T
.dot(N
);
1670 OSG::Real32 v2
= T
.dot(B
);
1671 OSG::Real32 v3
= N
.dot(B
);
1673 OSG_ASSERT(OSG::osgAbs(T
.length() - 1.f
) < OSG::Eps
);
1674 OSG_ASSERT(OSG::osgAbs(N
.length() - 1.f
) < OSG::Eps
);
1675 OSG_ASSERT(OSG::osgAbs(B
.length() - 1.f
) < OSG::Eps
);
1677 mat
.setValue(T
,N
,B
,P
);
1683 OSG::Real32
CubicBezierCurve::length(OSG::UInt32 numSeg
) const
1685 OSG_ASSERT(numSeg
>= 2);
1687 OSG::Real32 d
= 1.f
/ numSeg
;
1689 OSG::Real32 l
= 0.f
;
1691 OSG::Pnt3f p0
= operator()(0.f
);
1695 OSG::Pnt3f p1
= operator()(t
);
1697 l
+= (p1
- p0
).length();
1704 OSG::Vec3f
CubicBezierCurve::fst_derivative(OSG::Real32 t
) const
1706 OSG::Vec3f v10
= p
[1] - p
[0];
1707 OSG::Vec3f v21
= p
[2] - p
[1];
1708 OSG::Vec3f v32
= p
[3] - p
[2];
1710 OSG::Real32 e
= 1.f
- t
;
1711 OSG::Real32 sq_e
= e
* e
;
1712 OSG::Real32 sq_t
= t
* t
;
1714 return 3.f
* sq_e
* v10
+ 6.f
* e
* t
* v21
+ 3.f
* sq_t
* v32
;
1717 OSG::Vec3f
CubicBezierCurve::sec_derivative(OSG::Real32 t
) const
1719 OSG::Vec3f v210
= p
[2] - 2.f
* p
[1] + p
[0].subZero();
1720 OSG::Vec3f v321
= p
[3] - 2.f
* p
[2] + p
[1].subZero();
1722 OSG::Real32 e
= 1.f
- t
;
1724 return 6.f
* e
* v210
+ 6.f
* t
* v321
;
1727 OSG::Vec3f
CubicBezierCurve::thr_devivative(OSG::Real32 t
) const
1729 OSG::Vec3f v21
= p
[2] - p
[1];
1730 OSG::Vec3f v30
= p
[3] - p
[0];
1732 return -18.f
* v21
+ 6.f
* v30
;
1736 SmoothCubicBezierSpline::SmoothCubicBezierSpline(const std::vector
<OSG::Pnt3f
>& knots
)
1739 OSG_ASSERT(knots
.size() > 3);
1743 calc_ctrl_pnts(p1
, p2
);
1745 std::size_t n
= knots
.size() - 1;
1747 std::vector
<OSG::Real32
> lengths(n
);
1748 OSG::Real32 L
= 0.f
;
1750 for (std::size_t i
= 0; i
< n
; ++i
)
1752 curves
.push_back(CubicBezierCurve(knots
[i
], p1
[i
], p2
[i
], knots
[i
+1]));
1754 lengths
[i
] = curves
[i
].length();
1758 OSG_ASSERT(L
> 0.f
);
1760 OSG::Real32 d
= 1.f
/ L
;
1762 intervals
.resize(n
);
1764 intervals
[0] = d
* lengths
[0];
1766 for (std::size_t i
= 1; i
< n
-1; ++i
)
1768 intervals
[i
] = intervals
[i
-1] + d
* lengths
[i
];
1771 intervals
[n
-1] = 1.f
;
1774 SmoothCubicBezierSpline::SmoothCubicBezierSpline(const SmoothCubicBezierSpline
& rhs
)
1776 , intervals(rhs
.intervals
)
1777 , curves(rhs
.curves
)
1781 SmoothCubicBezierSpline
& SmoothCubicBezierSpline::operator=(const SmoothCubicBezierSpline
& rhs
)
1786 intervals
= rhs
.intervals
;
1787 curves
= rhs
.curves
;
1792 OSG::Pnt3f
SmoothCubicBezierSpline::operator()(OSG::Real32 t
) const
1794 std::size_t idx
= index(t
);
1795 return curves
[idx
](t_(t
, idx
));
1798 OSG::Vec3f
SmoothCubicBezierSpline::tangent(OSG::Real32 t
) const
1800 std::size_t idx
= index(t
);
1801 return curves
[idx
].tangent(t_(t
, idx
));
1804 OSG::Vec3f
SmoothCubicBezierSpline::normal(OSG::Real32 t
) const
1806 std::size_t idx
= index(t
);
1807 return curves
[idx
].normal(t_(t
, idx
));
1810 OSG::Vec3f
SmoothCubicBezierSpline::binormal(OSG::Real32 t
) const
1812 std::size_t idx
= index(t
);
1813 return curves
[idx
].binormal(t_(t
, idx
));
1816 OSG::Matrix
SmoothCubicBezierSpline::frame(OSG::Real32 t
, bool position_only
) const
1818 std::size_t idx
= index(t
);
1819 return curves
[idx
].frame(t_(t
, idx
), position_only
);
1822 OSG::Real32
SmoothCubicBezierSpline::length(OSG::UInt32 numSeg
) const
1824 OSG::Real32 l
= 0.f
;
1825 BOOST_FOREACH(const CubicBezierCurve
& c
, curves
)
1827 l
+= c
.length(numSeg
);
1832 void SmoothCubicBezierSpline::calc_ctrl_pnts(points_t
& p1
, points_t
& p2
) const
1834 namespace tp
= boost::tuples
;
1835 typedef tp::tuple
<OSG::Real32
, OSG::Real32
, OSG::Real32
> tuple_t
;
1836 typedef std::vector
<tuple_t
> tuples_t
;
1838 std::size_t n
= knots
.size()-1;
1843 tuples_t
a(n
), b(n
), c(n
), d(n
);
1845 a
[0] = tp::make_tuple(0.f
, 0.f
, 0.f
);
1846 b
[0] = tp::make_tuple(2.f
, 2.f
, 2.f
);
1847 c
[0] = tp::make_tuple(1.f
, 1.f
, 1.f
);
1848 d
[0] = tp::make_tuple(
1849 knots
[0].x() + 2.f
* knots
[1].x(),
1850 knots
[0].y() + 2.f
* knots
[1].y(),
1851 knots
[0].z() + 2.f
* knots
[1].z());
1853 for (std::size_t i
= 1; i
< n
-1; ++i
)
1855 a
[i
] = tp::make_tuple(1.f
, 1.f
, 1.f
);
1856 b
[i
] = tp::make_tuple(4.f
, 4.f
, 4.f
);
1857 c
[i
] = tp::make_tuple(1.f
, 1.f
, 1.f
);
1858 d
[i
] = tp::make_tuple(
1859 4.f
* knots
[i
].x() + 2.f
* knots
[i
+1].x(),
1860 4.f
* knots
[i
].y() + 2.f
* knots
[i
+1].y(),
1861 4.f
* knots
[i
].z() + 2.f
* knots
[i
+1].z());
1864 a
[n
-1] = tp::make_tuple(2.f
, 2.f
, 2.f
);
1865 b
[n
-1] = tp::make_tuple(7.f
, 7.f
, 7.f
);
1866 c
[n
-1] = tp::make_tuple(0.f
, 0.f
, 0.f
);
1867 d
[n
-1] = tp::make_tuple(
1868 8.f
* knots
[n
-1].x() + 2.f
* knots
[n
].x(),
1869 8.f
* knots
[n
-1].y() + 2.f
* knots
[n
].y(),
1870 8.f
* knots
[n
-1].z() + 2.f
* knots
[n
].z());
1872 for (std::size_t i
= 1; i
< n
; ++i
)
1874 tuple_t m
= tp::make_tuple(
1875 a
[i
].get
<0>() / b
[i
-1].get
<0>(),
1876 a
[i
].get
<1>() / b
[i
-1].get
<1>(),
1877 a
[i
].get
<2>() / b
[i
-1].get
<2>());
1879 b
[i
] = tp::make_tuple(
1880 b
[i
].get
<0>() - m
.get
<0>() * c
[i
-1].get
<0>(),
1881 b
[i
].get
<1>() - m
.get
<1>() * c
[i
-1].get
<1>(),
1882 b
[i
].get
<2>() - m
.get
<2>() * c
[i
-1].get
<2>());
1884 d
[i
] = tp::make_tuple(
1885 d
[i
].get
<0>() - m
.get
<0>() * d
[i
-1].get
<0>(),
1886 d
[i
].get
<1>() - m
.get
<1>() * d
[i
-1].get
<1>(),
1887 d
[i
].get
<2>() - m
.get
<2>() * d
[i
-1].get
<2>());
1891 d
[n
-1].get
<0>() / b
[n
-1].get
<0>(),
1892 d
[n
-1].get
<1>() / b
[n
-1].get
<1>(),
1893 d
[n
-1].get
<2>() / b
[n
-1].get
<2>());
1895 for (long long i
= n
-2; i
>= 0; --i
)
1898 (d
[i
].get
<0>() - c
[i
].get
<0>() * p1
[i
+1].x()) / b
[i
].get
<0>(),
1899 (d
[i
].get
<1>() - c
[i
].get
<1>() * p1
[i
+1].y()) / b
[i
].get
<1>(),
1900 (d
[i
].get
<2>() - c
[i
].get
<2>() * p1
[i
+1].z()) / b
[i
].get
<2>());
1903 for (std::size_t i
= 0; i
< n
-1; ++i
)
1906 2.f
* knots
[i
+1].x() - p1
[i
+1].x(),
1907 2.f
* knots
[i
+1].y() - p1
[i
+1].y(),
1908 2.f
* knots
[i
+1].z() - p1
[i
+1].z());
1912 0.5f
* knots
[n
].x() - p1
[n
-1].x(),
1913 0.5f
* knots
[n
].y() - p1
[n
-1].y(),
1914 0.5f
* knots
[n
].z() - p1
[n
-1].z());
1917 std::size_t SmoothCubicBezierSpline::index(OSG::Real32 t
) const
1919 OSG_ASSERT(0.f
<= t
&& t
<= 1.f
);
1921 std::vector
<OSG::Real32
>::const_iterator iter
= std::lower_bound(intervals
.begin(), intervals
.end(), t
);
1922 std::size_t r
= iter
- intervals
.begin();
1926 OSG::Real32
SmoothCubicBezierSpline::t_(OSG::Real32 t
, std::size_t idx
) const
1928 OSG_ASSERT(idx
< intervals
.size());
1930 OSG::Real32 t0
= 0.f
;
1931 OSG::Real32 t1
= 1.f
;
1933 if (idx
> 0) t0
= intervals
[idx
-1];
1934 t1
= intervals
[idx
];
1936 OSG::Real32 r
= (t
- t0
) / (t1
- t0
);
1941 // ============================================================================
1943 // Part VII: dice_knots helper implementation
1945 // ============================================================================
1947 typedef boost::tuples::tuple
<int, int, int> index_t
;
1949 struct index_hash_t
: public std::unary_function
<index_t
, std::size_t>
1951 std::size_t operator()(const index_t
& v
) const
1953 std::size_t seed
= 0;
1954 boost::hash_combine(seed
, v
.get
<0>());
1955 boost::hash_combine(seed
, v
.get
<1>());
1956 boost::hash_combine(seed
, v
.get
<2>());
1961 std::vector
<OSG::Pnt3f
> dice_knots(bool close_curve
)
1964 // idea: sample a number if different cube boxes from the scene and
1965 // take randomly one point from each cube. That guarantees that
1966 // the knot points do not clump and that they are all unequal.
1968 namespace tp
= boost::tuples
;
1970 boost::unordered_set
<index_t
, index_hash_t
> indices
;
1972 while (indices
.size() < num_curve_knots
)
1974 indices
.insert(tp::make_tuple(box_idx_die(), box_idx_die(), box_idx_die()));
1977 OSG::Real32 l
= 2 * world_size
/ num_grid_boxes
;
1979 std::vector
<OSG::Pnt3f
> knots
;
1981 BOOST_FOREACH(const index_t
& idx
, indices
)
1984 p
[0] = -world_size
+ idx
.get
<0>() * l
+ unit_die() * l
;
1985 p
[1] = -world_size
+ idx
.get
<1>() * l
+ unit_die() * l
;
1986 p
[2] = -world_size
+ idx
.get
<2>() * l
+ unit_die() * l
;
1992 knots
.push_back(knots
.front());
1997 // ============================================================================
1999 // Part VIII: The shader programs
2001 // ============================================================================
2004 // vertex shader program.
2006 std::string
get_vp_program()
2008 using namespace std
;
2012 ost
<< "#version 440 compatibility"
2014 << endl
<< "#extension GL_ARB_separate_shader_objects: enable"
2015 << endl
<< "#extension GL_ARB_shader_storage_buffer_object: enable"
2017 << endl
<< "smooth out vec3 vNormalES; // eye space normal"
2018 << endl
<< "smooth out vec3 vPositionES; // eye space position"
2020 << endl
<< "void main()"
2023 << endl
<< " // multiply the object space vertex position with the modelview matrix "
2024 << endl
<< " // to get the eye space vertex position"
2026 << endl
<< " vPositionES = (gl_ModelViewMatrix * gl_Vertex).xyz;"
2029 << endl
<< " // multiply the object space normal with the normal matrix (transpose of the inverse "
2030 << endl
<< " // model view matrix) to get the eye space normal"
2032 << endl
<< " vNormalES = gl_NormalMatrix * gl_Normal;"
2035 << endl
<< " // multiply the combiend modelview projection matrix with the object space vertex"
2036 << endl
<< " // position to get the clip space position"
2038 << endl
<< " gl_Position = ftransform();"
2047 // fragment shader program for bump mapping in surface local coordinates
2049 std::string
get_fp_program()
2051 using namespace std
;
2055 ost
<< "#version 440 compatibility"
2057 << endl
<< "#extension GL_ARB_separate_shader_objects: enable"
2058 << endl
<< "#extension GL_ARB_shader_storage_buffer_object: enable"
2060 << endl
<< "smooth in vec3 vNormalES; // eye space normal"
2061 << endl
<< "smooth in vec3 vPositionES; // eye space position"
2063 << endl
<< "const int num_materials = 5000;"
2065 << endl
<< "const int POINT_LIGHT = 1; // defined in OSGMultiLightChunk.h"
2066 << endl
<< "const int DIRECTIONAL_LIGHT = 2;"
2067 << endl
<< "const int SPOT_LIGHT = 3;"
2068 << endl
<< "const int CINEMA_LIGHT = 4;"
2070 << endl
<< "uniform mat4 OSGViewMatrix;"
2072 << endl
<< "struct Light"
2074 << endl
<< " vec3 position; // in world space"
2075 << endl
<< " vec3 direction; // in world space"
2076 << endl
<< " vec3 color;"
2077 << endl
<< " float intensity;"
2078 << endl
<< " float range;"
2079 << endl
<< " float cosSpotlightAngle;"
2080 << endl
<< " int type; // specific type of light: POINT_LIGHT, DIRECTIONAL_LIGHT, SPOT_LIGHT or CINEMA_LIGHT"
2081 << endl
<< " bool enabled; // on/off state of light"
2084 << endl
<< "layout (std430) buffer Lights"
2086 << endl
<< " Light light[];"
2087 << endl
<< "} lights;"
2089 << endl
<< "struct Material"
2091 << endl
<< " vec3 ambient;"
2092 << endl
<< " vec3 diffuse;"
2093 << endl
<< " vec3 specular;"
2094 << endl
<< " vec3 emissive;"
2096 << endl
<< " float opacity;"
2097 << endl
<< " float shininess;"
2100 << endl
<< "layout (std430) buffer Materials"
2102 << endl
<< " Material material[num_materials];"
2103 << endl
<< "} materials;"
2106 << endl
<< "layout (std140) uniform GeomState"
2108 << endl
<< " int material_index;"
2109 << endl
<< "} geom_state;"
2111 << endl
<< "const vec3 cCameraPositionES = vec3(0,0,0); // eye is at vec3(0,0,0) in eye space!"
2113 << endl
<< "layout(location = 0) out vec4 vFragColor;"
2116 << endl
<< "// Calculate the attenuation of the light based on the light "
2117 << endl
<< "// range r and the distance d of the light to the current point."
2119 << endl
<< "float calcAttenuation(in float r, in float d)"
2121 << endl
<< " return 1.0 - smoothstep(0.75 * r, r, d);"
2125 << endl
<< "// Calculate the attenuation with respect to the spot light cone."
2126 << endl
<< "// Parameters:"
2127 << endl
<< "// minCosSpotAngle: the cosine of the spot light angle"
2128 << endl
<< "// l : normalized direction between fragment and light position"
2129 << endl
<< "// s : normalized light direction"
2131 << endl
<< "float spotAttenuation(in float minCosSpotAngle, in vec3 l, in vec3 s)"
2133 << endl
<< " float maxCosSpotAngle = mix(minCosSpotAngle, 1.0, 0.5);"
2134 << endl
<< " float l_dot_s = dot(-l, s);"
2135 << endl
<< " return smoothstep(minCosSpotAngle, maxCosSpotAngle, l_dot_s);"
2139 << endl
<< "// directional light contribution"
2141 << endl
<< "vec3 directionalLight("
2142 << endl
<< " in int i, // light identifier, i.e. current light"
2143 << endl
<< " in int j, // material identifier"
2144 << endl
<< " in vec3 n, // vertex normal in eye space"
2145 << endl
<< " in vec3 v) // view direction in eye space"
2147 << endl
<< " if (!lights.light[i].enabled)"
2148 << endl
<< " return vec3(0.0, 0.0, 0.0);"
2151 << endl
<< " // the light direction in eye space"
2153 << endl
<< " vec4 direction = OSGViewMatrix * vec4(lights.light[i].direction, 0.0);"
2154 << endl
<< " vec3 l = -direction.xyz;"
2157 << endl
<< " // the half vector"
2159 << endl
<< " vec3 h = normalize(l+v);"
2161 << endl
<< " float n_dot_l = max(0.0, dot(n, l));"
2162 << endl
<< " float n_dot_h = max(0.0, dot(n, h));"
2164 << endl
<< " float m = materials.material[j].shininess;"
2166 << endl
<< " float pf; // power factor"
2168 << endl
<< " if (n_dot_l == 0.0)"
2169 << endl
<< " pf = 0.0;"
2171 << endl
<< " pf = pow(n_dot_h, m);"
2173 << endl
<< " vec3 light_intensity = lights.light[i].intensity * lights.light[i].color;"
2175 << endl
<< " return materials.material[j].emissive"
2176 << endl
<< " + light_intensity * materials.material[j].ambient"
2177 << endl
<< " + light_intensity * materials.material[j].diffuse * n_dot_l"
2178 << endl
<< " + light_intensity * materials.material[j].specular * (m+8)*0.0125 * pf;"
2182 << endl
<< "// point light contribution"
2184 << endl
<< "vec3 pointLight("
2185 << endl
<< " in int i, // light identifier, i.e. current light"
2186 << endl
<< " in int j, // material identifier"
2187 << endl
<< " in vec3 n, // vertex normal in eye space"
2188 << endl
<< " in vec3 v, // view direction in eye space"
2189 << endl
<< " in vec3 p) // vertex position in eye space"
2191 << endl
<< " if (!lights.light[i].enabled)"
2192 << endl
<< " return vec3(0.0, 0.0, 0.0);"
2194 << endl
<< " vec4 position = OSGViewMatrix * vec4(lights.light[i].position, 1.0);"
2195 << endl
<< " vec3 l = position.xyz - p; // dir from surface to light position"
2196 << endl
<< " float d = length(l); // dist from surface to light source"
2198 << endl
<< " if (lights.light[i].range < d)"
2199 << endl
<< " return vec3(0.0, 0.0, 0.0);"
2201 << endl
<< " l = normalize(l); // norm direction from surf to light"
2204 << endl
<< " // the half vector"
2206 << endl
<< " vec3 h = normalize(l+v);"
2208 << endl
<< " float n_dot_l = max(0.0, dot(n, l));"
2209 << endl
<< " float n_dot_h = max(0.0, dot(n, h));"
2211 << endl
<< " float m = materials.material[j].shininess;"
2213 << endl
<< " float pf; // power factor"
2215 << endl
<< " if (n_dot_l == 0.0)"
2216 << endl
<< " pf = 0.0;"
2218 << endl
<< " pf = pow(n_dot_h, m);"
2220 << endl
<< " float attenuation = calcAttenuation(lights.light[i].range, d);"
2222 << endl
<< " vec3 light_intensity = attenuation * lights.light[i].intensity * lights.light[i].color;"
2224 << endl
<< " return materials.material[j].emissive"
2225 << endl
<< " + light_intensity * materials.material[j].ambient"
2226 << endl
<< " + light_intensity * materials.material[j].diffuse * n_dot_l"
2227 << endl
<< " + light_intensity * materials.material[j].specular * (m+8)*0.0125 * pf;"
2231 << endl
<< "// spot light contribution"
2233 << endl
<< "vec3 spotLight("
2234 << endl
<< " in int i, // light identifier, i.e. current light"
2235 << endl
<< " in int j, // material identifier"
2236 << endl
<< " in vec3 n, // vertex normal in eye space"
2237 << endl
<< " in vec3 v, // view direction in eye space"
2238 << endl
<< " in vec3 p) // vertex position in eye space"
2240 << endl
<< " if (!lights.light[i].enabled)"
2241 << endl
<< " return vec3(0.0, 0.0, 0.0);"
2243 << endl
<< " vec4 position = OSGViewMatrix * vec4(lights.light[i].position, 1.0);"
2244 << endl
<< " vec3 l = position.xyz - p; // dir from surface to light position"
2245 << endl
<< " float d = length(l); // dist from surface to light source"
2247 << endl
<< " if (lights.light[i].range < d)"
2248 << endl
<< " return vec3(0.0, 0.0, 0.0);"
2250 << endl
<< " l = normalize(l); // norm dir from surface to light"
2252 << endl
<< " vec4 direction = OSGViewMatrix * vec4(lights.light[i].direction, 0.0);"
2253 << endl
<< " vec3 s = direction.xyz;"
2254 << endl
<< " s = normalize(s);"
2257 << endl
<< " // the half vector"
2259 << endl
<< " vec3 h = normalize(l+v);"
2261 << endl
<< " float n_dot_l = max(0.0, dot(n, l));"
2262 << endl
<< " float n_dot_h = max(0.0, dot(n, h));"
2264 << endl
<< " float m = materials.material[j].shininess;"
2266 << endl
<< " float pf; // power factor"
2268 << endl
<< " if (n_dot_l == 0.0)"
2269 << endl
<< " pf = 0.0;"
2271 << endl
<< " pf = pow(n_dot_h, m);"
2273 << endl
<< " float attenuation = calcAttenuation(lights.light[i].range, d);"
2274 << endl
<< " attenuation *= spotAttenuation(lights.light[i].cosSpotlightAngle, l, s);"
2276 << endl
<< " vec3 light_intensity = attenuation * lights.light[i].intensity * lights.light[i].color;"
2278 << endl
<< " return materials.material[j].emissive"
2279 << endl
<< " + light_intensity * materials.material[j].ambient"
2280 << endl
<< " + light_intensity * materials.material[j].diffuse * n_dot_l"
2281 << endl
<< " + light_intensity * materials.material[j].specular * (m+8)*0.0125 * pf;"
2284 << endl
<< "void main()"
2287 << endl
<< " // normalize the eye space normal"
2289 << endl
<< " int frontCond = -(1 - int(gl_FrontFacing)*2);"
2290 << endl
<< " vec3 N = frontCond * normalize(vNormalES);"
2293 << endl
<< " // get the view vector and normalize it"
2295 << endl
<< " vec3 V = normalize(cCameraPositionES - vPositionES);"
2298 << endl
<< " // Integrate over all lights: Any unused light does not contribute and each light"
2299 << endl
<< " // contribute either from the directional light, the point light or the spot light."
2301 << endl
<< " vec3 color = vec3(0.0, 0.0, 0.0);"
2303 << endl
<< " int num_lights = lights.light.length();"
2305 << endl
<< " for (int i = 0; i < num_lights; ++i)"
2307 << endl
<< " switch (lights.light[i].type)"
2309 << endl
<< " case POINT_LIGHT: color += pointLight(i, geom_state.material_index, N, V, vPositionES); break;"
2310 << endl
<< " case DIRECTIONAL_LIGHT: color += directionalLight(i, geom_state.material_index, N, V); break;"
2311 << endl
<< " case SPOT_LIGHT: color += spotLight(i, geom_state.material_index, N, V, vPositionES); break;"
2314 << endl
<< " vFragColor = vec4(color, materials.material[geom_state.material_index].opacity);"