1 // OpenSG Tutorial Example: MultiStandardLight
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 the standard OpenGL light abstraction. Of course the
17 // shader code's responsibilty is to make usage of the provided light data
18 // attrubutes, and the writer of the shader can implement whatever light model
19 // he likes on the given light buffer layout.
21 // The MultiPropertyUBOChunk and MultiPropertySSBOChunk do also provides means
22 // to conviently create shader buffer data. They are, however, not as
23 // specialized as the MultiLightChunk.
24 // They have a simple interface for the data layout preparation but allows only
25 // a restricted subset of layout structure that the std140 uniform buffer block
26 // repspectively the std430 shader storage buffer block specifications allows.
28 // In this example a MultiPropertySSBOChunk is used to model a material database
29 // with the simple basic material properties. The material database shader
30 // buffer is shared by all geometry that is rendered by the example.
32 // The MultiPropertyUBOChunk is used to provide geometry state data to the
33 // fragment shader. That is, each geometry gets its own chunk, but for the
34 // purpose of the example only the material index to be used for the particular
35 // geometry is added to chunk.
37 // Additionally, the example runs riot with boost random number generators.
38 // Hopefully, that does not distract the reader.
40 // Different aspects of the example can be manipulated at runtime like the
41 // number of lights and their range and intensity parameters as well as the
42 // number of geometries simulated and their material among many others.
44 // The examples uses a HDR2Stage core for managing the mapping of the
45 // accumulated intensities into the feasible region of the final screen
46 // render target. It does use mostly default settings for this stage.
48 // At last the example provides a bezier curve abstraction for generating
49 // the light and object pathes.
52 // multistandardlight.cpp
53 // multicinemalight.cpp
54 // uniformbufferobject_std140.cpp
55 // shaderstoragebufferobject_std430.cpp
56 // multipropertyubochunk_test.cpp
57 // multipropertyssbochunk_test.cpp
61 #include <boost/functional/hash.hpp>
62 #include <boost/unordered_set.hpp>
63 #include <boost/foreach.hpp>
64 #include <boost/random.hpp>
65 #include <boost/tuple/tuple.hpp>
66 #include "boost/tuple/tuple_comparison.hpp"
68 #ifdef OSG_BUILD_ACTIVE
71 #include <OSGConfig.h>
72 #include <OSGSimpleGeometry.h>
73 #include <OSGGLUTWindow.h>
74 #include <OSGSimpleSceneManager.h>
75 #include <OSGBaseFunctions.h>
76 #include <OSGTransform.h>
82 #include <OSGHDR2Stage.h>
83 #include <OSGInverseTransform.h>
84 #include <OSGShaderProgramChunk.h>
85 #include <OSGShaderProgram.h>
86 #include <OSGShaderVariableOSG.h>
87 #include <OSGChunkMaterial.h>
88 #include <OSGMaterialGroup.h>
89 #include <OSGMaterialChunkOverrideGroup.h>
90 #include <OSGMatrixUtility.h>
91 #include <OSGMultiLightChunk.h>
92 #include <OSGMultiPropertyUBOChunk.h>
93 #include <OSGMultiPropertySSBOChunk.h>
94 #include <OSGPolygonChunk.h>
95 #include <OSGDepthChunk.h>
96 #include <OSGShaderProgramVariableChunk.h>
97 #include <OSGBlendChunk.h>
98 #include <OSGPolygonChunk.h>
99 #include <OSGTwoSidedLightingChunk.h>
103 #include <OpenSG/OSGGLUT.h>
104 #include <OpenSG/OSGConfig.h>
105 #include <OpenSG/OSGSimpleGeometry.h>
106 #include <OpenSG/OSGGLUTWindow.h>
107 #include <OpenSG/OSGSimpleSceneManager.h>
108 #include <OpenSG/OSGBaseFunctions.h>
109 #include <OpenSG/OSGTransform.h>
110 #include <OpenSG/OSGGroup.h>
113 #include <OpenSG/OSGGLEXT.h>
114 #include <OpenSG/OSGTime.h>
115 #include <OpenSG/OSGHDR2Stage.h>
116 #include <OpenSG/OSGInverseTransform.h>
117 #include <OpenSG/OSGShaderProgramChunk.h>
118 #include <OpenSG/OSGShaderProgram.h>
119 #include <OpenSG/OSGShaderVariableOSG.h>
120 #include <OpenSG/OSGChunkMaterial.h>
121 #include <OpenSG/OSGMaterialGroup.h>
122 #include <OpenSG/OSGMaterialChunkOverrideGroup.h>
123 #include <OpenSG/OSGMatrixUtility.h>
124 #include <OpenSG/OSGMultiLightChunk.h>
125 #include <OpenSG/OSGMultiPropertyUBOChunk.h>
126 #include <OpenSG/OSGMultiPropertySSBOChunk.h>
127 #include <OpenSG/OSGPolygonChunk.h>
128 #include <OpenSG/OSGDepthChunk.h>
129 #include <OpenSG/OSGShaderProgramVariableChunk.h>
130 #include <OpenSG/OSGBlendChunk.h>
131 #include <OpenSG/OSGPolygonChunk.h>
132 #include <OpenSG/OSGTwoSidedLightingChunk.h>
135 // ============================================================================
137 // Part I: Declaration of the example scene and some helpers:
138 // - constants that governs the example
139 // - random number generators
140 // - smooth cubic Bezier spline curve
142 // ============================================================================
144 OSG::SimpleSceneManagerRefPtr mgr
;
146 const OSG::Int32 num_geometries
= 16;
147 const OSG::Int32 num_grid_boxes
= 100;
148 const OSG::Int32 num_curve_knots
= 40;
149 const OSG::Int32 num_passes
= 4;
150 const std::size_t num_materials
= 5000;
151 const OSG::Int32 max_num_lights
= 1024;
152 const OSG::Real32 world_size
= 10.f
;
153 const OSG::Real32 box_factor
= 1.5f
;
155 OSG::Real32 simulation_delta
= 0.0001f
;
156 OSG::Real32 elapse_time_limit
= 10.f
;
158 const OSG::Real32 max_light_power
= 10.f
;
160 const OSG::Real32 quadraticAttFactor
= 1.2f
;
161 const OSG::Real32 linearAttFactor
= 1.2f
;
162 const OSG::Real32 spotExponentFactor
= 1.2f
;
164 typedef boost::mt19937 RNGType
;
165 RNGType
rng(time(0));
167 boost::uniform_int
<> box_dist(0, num_grid_boxes
-1);
168 boost::variate_generator
<RNGType
, boost::uniform_int
<> > box_idx_die(rng
, box_dist
);
170 boost::uniform_int
<> die_dist(1, 6);
171 boost::variate_generator
<RNGType
, boost::uniform_int
<> > classic_die(rng
, die_dist
);
173 boost::uniform_int
<> geom_dist(0, 7);
174 boost::variate_generator
<RNGType
, boost::uniform_int
<> > geom_idx_die(rng
, geom_dist
);
176 boost::uniform_01
<float> unit_distribution
;
177 boost::variate_generator
< RNGType
, boost::uniform_01
<float> > unit_die(rng
, unit_distribution
);
179 boost::uniform_real
<float> small_distribution(0.1f
, 1.f
);
180 boost::variate_generator
< RNGType
, boost::uniform_real
<float> > small_die(rng
, small_distribution
);
182 boost::uniform_real
<float> light_range_distribution(0.2f
, 0.7f
);
183 boost::variate_generator
< RNGType
, boost::uniform_real
<float> > light_range_die(rng
, light_range_distribution
);
185 std::vector
<OSG::Pnt3f
> dice_knots(bool close_curve
);
187 OSG::Vec3f
dice_unit_vector()
191 while (v
.length() < OSG::Eps
)
193 -1.f
+ 2.f
* unit_die(),
194 -1.f
+ 2.f
* unit_die(),
195 -1.f
+ 2.f
* unit_die());
202 class CubicBezierCurve
205 CubicBezierCurve(const OSG::Pnt3f
& p0
, const OSG::Pnt3f
& p1
, const OSG::Pnt3f
& p2
, const OSG::Pnt3f
& p3
);
206 CubicBezierCurve(const CubicBezierCurve
& rhs
);
208 CubicBezierCurve
& operator=(const CubicBezierCurve
& rhs
);
210 OSG::Pnt3f
operator() (OSG::Real32 t
) const;
211 OSG::Vec3f
tangent (OSG::Real32 t
) const;
212 OSG::Vec3f
normal (OSG::Real32 t
) const;
213 OSG::Vec3f
binormal (OSG::Real32 t
) const;
214 OSG::Matrix
frame (OSG::Real32 t
, bool position_only
) const;
215 OSG::Real32
length (OSG::UInt32 numSeg
= 10) const;
218 OSG::Vec3f
fst_derivative (OSG::Real32 t
) const;
219 OSG::Vec3f
sec_derivative (OSG::Real32 t
) const;
220 OSG::Vec3f
thr_devivative (OSG::Real32 t
) const;
226 class SmoothCubicBezierSpline
229 typedef std::vector
<OSG::Pnt3f
> points_t
;
231 SmoothCubicBezierSpline(const points_t
& knots
);
232 SmoothCubicBezierSpline(const SmoothCubicBezierSpline
& rhs
);
234 SmoothCubicBezierSpline
& operator=(const SmoothCubicBezierSpline
& rhs
);
236 OSG::Pnt3f
operator() (OSG::Real32 t
) const;
237 OSG::Vec3f
tangent (OSG::Real32 t
) const;
238 OSG::Vec3f
normal (OSG::Real32 t
) const;
239 OSG::Vec3f
binormal (OSG::Real32 t
) const;
240 OSG::Matrix
frame (OSG::Real32 t
, bool position_only
= false) const;
241 OSG::Real32
length (OSG::UInt32 numSeg
= 10) const;
244 void calc_ctrl_pnts (points_t
& p1
, points_t
& p2
) const;
245 std::size_t index (OSG::Real32 t
) const;
246 OSG::Real32
t_ (OSG::Real32 t
, std::size_t idx
) const;
249 std::vector
<OSG::Pnt3f
> knots
;
250 std::vector
<OSG::Real32
> intervals
;
251 std::vector
<CubicBezierCurve
> curves
;
254 // ============================================================================
256 // Part II: Declaration of
257 // - struct Light and type VecLightsT,
258 // - struct Material and type VecMaterialsT,
259 // - struct GeomState
260 // and corresponding initialization routines.
262 // ============================================================================
265 // simple light data structure
271 directional_light
= OSG::MultiLight::DIRECTIONAL_LIGHT
,
272 point_light
= OSG::MultiLight::POINT_LIGHT
,
273 spot_light
= OSG::MultiLight::SPOT_LIGHT
,
274 cinema_light
= OSG::MultiLight::CINEMA_LIGHT
277 OSG::MultiLight::Type
getType() const { return static_cast<OSG::MultiLight::Type
>(type
); }
279 explicit Light(Type e
);
282 static Light
create_light(Type e
, OSG::UInt32 material_idx
);
284 OSG::Pnt3f position
; // light position in object space for point and spot lights
285 OSG::Vec3f direction
; // direction of directional light or spot light in object space
286 OSG::Vec3f ambientIntensity
; // the ambient light intensity
287 OSG::Vec3f diffuseIntensity
; // the diffuse light intensity
288 OSG::Vec3f specularIntensity
; // the specular light intensity
289 OSG::Real32 constantAttenuation
; // the intensity of the light
290 OSG::Real32 linearAttenuation
; // the intensity of the light
291 OSG::Real32 quadraticAttenuation
; // the intensity of the light
292 OSG::Real32 spotlightAngle
; // the cone angle in case of a spot light
293 OSG::Real32 spotExponent
; // the spot exponent governs the attenuation of the light
294 OSG::Int32 type
; // the type of light: see OSG::MultiLight::LightType
295 bool enabled
; // on/off state of the light
297 OSG::NodeRefPtr beacon
; // the light beacon that if defined evaluates the position parameter
298 OSG::TransformRefPtr transform
; // the beacons transform core
299 SmoothCubicBezierSpline curve
; // the path that the light will follow
302 typedef std::vector
<Light
> VecLightsT
; // multiple lights
303 VecLightsT lights
; // the lights of the scene
306 : position(0.f
, 0.f
, 0.f
)
307 , direction(0.f
, 0.f
, 1.f
)
308 , ambientIntensity(1.f
,1.f
,1.f
)
309 , diffuseIntensity(1.f
,1.f
,1.f
)
310 , specularIntensity(1.f
,1.f
,1.f
)
311 , constantAttenuation(1.f
)
312 , linearAttenuation(0.0001f
)
313 , quadraticAttenuation(0.000001f
)
314 , spotlightAngle(20.f
)
320 , curve(dice_knots(true))
330 // Simple material data structure
335 : ambient (0.f
, 0.f
, 0.f
)
336 , diffuse (0.f
, 0.f
, 0.f
)
337 , specular(0.f
, 0.f
, 0.f
)
338 , emissive(0.f
, 0.f
, 0.f
)
343 OSG::Color3f ambient
;
344 OSG::Color3f diffuse
;
345 OSG::Color3f specular
;
346 OSG::Color3f emissive
;
349 OSG::Real32 shininess
;
351 static OSG::UInt32 ambient_id
;
352 static OSG::UInt32 diffuse_id
;
353 static OSG::UInt32 specular_id
;
354 static OSG::UInt32 emissive_id
;
355 static OSG::UInt32 opacity_id
;
356 static OSG::UInt32 shininess_id
;
359 OSG::UInt32
Material:: ambient_id
= 0;
360 OSG::UInt32
Material:: diffuse_id
= 0;
361 OSG::UInt32
Material:: specular_id
= 0;
362 OSG::UInt32
Material:: emissive_id
= 0;
363 OSG::UInt32
Material:: opacity_id
= 0;
364 OSG::UInt32
Material::shininess_id
= 0;
366 typedef std::vector
<Material
> VecMaterialsT
; // multiple materials
368 VecMaterialsT
initialize_materials(std::size_t num
) // helper to create materials
370 OSG_ASSERT(num
> max_num_lights
+ 1);
372 VecMaterialsT
mat(num
);
374 for (std::size_t i
= max_num_lights
+1; i
< num
; ++i
)
376 mat
[i
].ambient
= OSG::Color3f(0.001f
, 0.001f
, 0.001f
);
377 mat
[i
].diffuse
.setRandom();
378 mat
[i
].specular
= OSG::Color3f(0.9f
, 0.9f
, 0.9f
);
379 mat
[i
].emissive
= OSG::Color3f(0.0f
, 0.0f
, 0.0f
);
380 mat
[i
].opacity
= 1.f
;
381 mat
[i
].shininess
= 320.f
* small_die();
383 //int r = classic_die();
385 // mat[i].opacity = small_die();
389 // special grey material for box
391 mat
[0].ambient
= OSG::Color3f(0.001f
, 0.001f
, 0.001f
);
392 mat
[0].diffuse
= OSG::Color3f(0.7f
, 0.7f
, 0.7f
);
393 mat
[0].specular
= OSG::Color3f(0.9f
, 0.9f
, 0.9f
);
394 mat
[0].emissive
= OSG::Color3f(0.0f
, 0.0f
, 0.0f
);
395 mat
[0].opacity
= 1.f
;
396 mat
[0].shininess
= 100.f
;
401 VecMaterialsT materials
= initialize_materials(num_materials
); // the material database
404 // we reserve the first max_num_lights + 1 materials for the light simulation and
407 boost::uniform_int
<OSG::UInt32
> material_dist(max_num_lights
+1, num_materials
-1);
408 boost::variate_generator
<RNGType
, boost::uniform_int
<OSG::UInt32
> > material_idx_die(rng
, material_dist
);
411 // Simple geometry state data structure
419 OSG::UInt32 material_index
;
421 static OSG::UInt32 material_index_id
;
424 OSG::UInt32
GeomState::material_index_id
= 0;
426 // ============================================================================
428 // Part III: Creation and update of the light state
430 // ============================================================================
432 OSG::MultiLightChunkTransitPtr
create_light_state(const VecLightsT
& vLights
)
434 OSG::MultiLightChunkRefPtr lightChunk
= OSG::MultiLightChunk::create();
436 lightChunk
->setUsage(GL_DYNAMIC_DRAW
);
437 lightChunk
->setLayoutType(
438 OSG::MultiLight::OPENGL_LAYOUT
|
439 OSG::MultiLight::RANGE_LAYOUT
);
440 lightChunk
->setAutoCalcRanges(true);
442 BOOST_FOREACH(const Light
& light
, vLights
)
444 OSG::UInt32 idx
= lightChunk
->addLight(light
.getType());
446 lightChunk
->setPosition (idx
, light
.position
);
447 lightChunk
->setDirection (idx
, light
.direction
);
448 lightChunk
->setAmbientIntensity (idx
, light
.ambientIntensity
);
449 lightChunk
->setDiffuseIntensity (idx
, light
.diffuseIntensity
);
450 lightChunk
->setSpecularIntensity (idx
, light
.specularIntensity
);
451 lightChunk
->setAttenuation (idx
, OSG::Vec3f(light
.constantAttenuation
,
452 light
.linearAttenuation
,
453 light
.quadraticAttenuation
));
454 lightChunk
->setSpotlightAngle (idx
, light
.spotlightAngle
);
455 lightChunk
->setSpotExponent (idx
, light
.spotExponent
);
456 lightChunk
->setEnabled (idx
, light
.enabled
);
457 lightChunk
->setType (idx
, light
.getType());
458 lightChunk
->setBeacon (idx
, light
.beacon
);
461 return OSG::MultiLightChunkTransitPtr(lightChunk
);
464 void update_light_state(OSG::MultiLightChunk
* lightChunk
, const VecLightsT
& vLights
)
468 if (lightChunk
->numLights() != vLights
.size())
470 lightChunk
->clearLights();
472 BOOST_FOREACH(const Light
& light
, vLights
)
474 OSG::UInt32 idx
= lightChunk
->addLight(light
.getType());
476 lightChunk
->setPosition (idx
, light
.position
);
477 lightChunk
->setDirection (idx
, light
.direction
);
478 lightChunk
->setAmbientIntensity (idx
, light
.ambientIntensity
);
479 lightChunk
->setDiffuseIntensity (idx
, light
.diffuseIntensity
);
480 lightChunk
->setSpecularIntensity (idx
, light
.specularIntensity
);
481 lightChunk
->setAttenuation (idx
, OSG::Vec3f(light
.constantAttenuation
,
482 light
.linearAttenuation
,
483 light
.quadraticAttenuation
));
484 lightChunk
->setSpotlightAngle (idx
, light
.spotlightAngle
);
485 lightChunk
->setSpotExponent (idx
, light
.spotExponent
);
486 lightChunk
->setEnabled (idx
, light
.enabled
);
487 lightChunk
->setType (idx
, light
.getType());
488 lightChunk
->setBeacon (idx
, light
.beacon
);
493 for (OSG::UInt32 idx
= 0; idx
< vLights
.size(); ++idx
)
495 const Light
& light
= vLights
[idx
];
497 lightChunk
->setPosition (idx
, light
.position
);
498 lightChunk
->setDirection (idx
, light
.direction
);
499 lightChunk
->setAmbientIntensity (idx
, light
.ambientIntensity
);
500 lightChunk
->setDiffuseIntensity (idx
, light
.diffuseIntensity
);
501 lightChunk
->setSpecularIntensity (idx
, light
.specularIntensity
);
502 lightChunk
->setAttenuation (idx
, OSG::Vec3f(light
.constantAttenuation
,
503 light
.linearAttenuation
,
504 light
.quadraticAttenuation
));
505 lightChunk
->setSpotlightAngle (idx
, light
.spotlightAngle
);
506 lightChunk
->setSpotExponent (idx
, light
.spotExponent
);
507 lightChunk
->setEnabled (idx
, light
.enabled
);
508 lightChunk
->setType (idx
, light
.getType());
509 lightChunk
->setBeacon (idx
, light
.beacon
);
515 // ============================================================================
517 // Part IV: Some routines for handling of the memory buffer and the the
518 // creation on the MultiPropertySSBOChunk objects:
520 // i) create_material_database_state,
521 // update_material_database_state
523 // ii) create_geometry_material_state,
524 // update_geometry_material_state
526 // ============================================================================
529 // i) the material shader storage buffer object
531 OSG::MultiPropertySSBOChunkTransitPtr
create_material_database_state(const VecMaterialsT
& vMaterials
)
533 OSG::MultiPropertySSBOChunkRefPtr materialChunk
= OSG::MultiPropertySSBOChunk::create();
535 OSG::UInt32 vec3_id
, float_id
;
537 vec3_id
= materialChunk
->addMember(OSG::MultiPropertySSBOChunk:: VEC3_T
, 4);
538 float_id
= materialChunk
->addMember(OSG::MultiPropertySSBOChunk::FLOAT_T
, 2);
540 materialChunk
->setUsage(GL_STATIC_DRAW
);
542 Material:: ambient_id
= vec3_id
++;
543 Material:: diffuse_id
= vec3_id
++;
544 Material:: specular_id
= vec3_id
++;
545 Material:: emissive_id
= vec3_id
;
547 Material:: opacity_id
= float_id
++;
548 Material::shininess_id
= float_id
;
550 BOOST_FOREACH(const Material
& mat
, vMaterials
)
552 OSG::UInt32 idx
= materialChunk
->addProperty();
554 materialChunk
->setVec3Property (idx
, Material:: ambient_id
, mat
.ambient
);
555 materialChunk
->setVec3Property (idx
, Material:: diffuse_id
, mat
.diffuse
);
556 materialChunk
->setVec3Property (idx
, Material:: specular_id
, mat
.specular
);
557 materialChunk
->setVec3Property (idx
, Material:: emissive_id
, mat
.emissive
);
559 materialChunk
->setFloatProperty(idx
, Material:: opacity_id
, mat
.opacity
);
560 materialChunk
->setFloatProperty(idx
, Material::shininess_id
, mat
.shininess
);
563 return OSG::MultiPropertySSBOChunkTransitPtr(materialChunk
);
566 void update_material_database_state(OSG::MultiPropertySSBOChunk
* materialChunk
, const VecMaterialsT
& vMaterials
)
570 if (materialChunk
->getNumProperties() != vMaterials
.size())
572 materialChunk
->clearProperties();
574 BOOST_FOREACH(const Material
& mat
, vMaterials
)
576 OSG::UInt32 idx
= materialChunk
->addProperty();
578 materialChunk
->setVec3Property (idx
, Material:: ambient_id
, mat
.ambient
);
579 materialChunk
->setVec3Property (idx
, Material:: diffuse_id
, mat
.diffuse
);
580 materialChunk
->setVec3Property (idx
, Material:: specular_id
, mat
.specular
);
581 materialChunk
->setVec3Property (idx
, Material:: emissive_id
, mat
.emissive
);
583 materialChunk
->setFloatProperty(idx
, Material:: opacity_id
, mat
.opacity
);
584 materialChunk
->setFloatProperty(idx
, Material::shininess_id
, mat
.shininess
);
589 for (OSG::UInt32 idx
= 0; idx
< vMaterials
.size(); ++idx
)
591 const Material
& mat
= vMaterials
[idx
];
593 materialChunk
->setVec3Property (idx
, Material:: ambient_id
, mat
.ambient
);
594 materialChunk
->setVec3Property (idx
, Material:: diffuse_id
, mat
.diffuse
);
595 materialChunk
->setVec3Property (idx
, Material:: specular_id
, mat
.specular
);
596 materialChunk
->setVec3Property (idx
, Material:: emissive_id
, mat
.emissive
);
598 materialChunk
->setFloatProperty(idx
, Material:: opacity_id
, mat
.opacity
);
599 materialChunk
->setFloatProperty(idx
, Material::shininess_id
, mat
.shininess
);
606 // ii) the geomertry shader storage buffer object
608 OSG::MultiPropertyUBOChunkTransitPtr
create_geometry_material_state(const GeomState
& geom_state
)
610 OSG::MultiPropertyUBOChunkRefPtr geomStateChunk
= OSG::MultiPropertyUBOChunk::create();
612 GeomState::material_index_id
= geomStateChunk
->addMember(OSG::MultiPropertyUBOChunk::UINT_T
, 1);
613 geomStateChunk
->setUsage(GL_DYNAMIC_DRAW
);
615 OSG::UInt32 idx
= geomStateChunk
->addProperty();
616 geomStateChunk
->setUIntProperty(idx
, GeomState::material_index_id
, geom_state
.material_index
);
618 return OSG::MultiPropertyUBOChunkTransitPtr(geomStateChunk
);
621 void update_geometry_material_state(OSG::MultiPropertyUBOChunk
* geomStateChunk
, const GeomState
& geom_state
)
625 if (geomStateChunk
->getNumProperties() != 1)
627 geomStateChunk
->clearProperties();
629 OSG::UInt32 idx
= geomStateChunk
->addProperty();
630 geomStateChunk
->setUIntProperty(idx
, GeomState::material_index_id
, geom_state
.material_index
);
634 geomStateChunk
->setUIntProperty( 0, GeomState::material_index_id
, geom_state
.material_index
);
639 // ============================================================================
641 // Part V: The application finally starts here
643 // ============================================================================
646 // vertex shader program.
648 std::string
get_vp_program();
651 // fragment shader program for bump mapping in surface local coordinates
653 std::string
get_fp_program();
658 OSG::NodeRefPtr scene_node
= NULL
;
663 OSG::HDR2StageRefPtr hdr_stage
= NULL
;
664 OSG::NodeRefPtr hdr_node
= NULL
;
667 // The material database for all visible geometry: objects, lights, stage box
669 OSG::MultiPropertySSBOChunkRefPtr ssbo_material_database
= NULL
;
672 // The mulit light chunk
674 OSG::MultiLightChunkRefPtr multi_light_chunk
= NULL
;
677 // The block binding point for the geom state
679 OSG::ShaderProgramVariableChunkRefPtr shader_var_chunk
= NULL
;
682 // Shader Storage buffer objects corresponding to transient shader blocks
684 std::vector
<OSG::MultiPropertyUBOChunkRefPtr
> ubo_geom_states
;
687 // A separate transformation for each object and a spline for the trajectory
689 std::vector
<OSG::NodeRefPtr
> geom_nodes
;
690 std::vector
<OSG::TransformRefPtr
> geom_trafos
;
691 std::vector
<SmoothCubicBezierSpline
> geom_curves
;
696 void setup_hdr_stage()
700 hdr_stage
->setApplyGamma (true);
701 hdr_stage
->setAccurateGamma (true);
703 hdr_stage
->setAdjustLuminance (false);
705 hdr_stage
->setPerformBloom (false);
706 hdr_stage
->setBloomBackground (false);
708 hdr_stage
->setForceBackground (true);
709 hdr_stage
->setUse_ITU_R_BT_709 (true);
710 hdr_stage
->setMipmapLevel (-1);
712 hdr_stage
->setTarget (OSG::HDR2Stage::COMPOSITE_TEXTURE
);
713 hdr_stage
->setCarryDepth (true);
715 hdr_stage
->setColorBufferInternalFormat (GL_RGBA16F
);
716 hdr_stage
->setColorBufferPixelFormat (GL_RGBA
);
717 hdr_stage
->setColorBufferType (GL_FLOAT
);
719 hdr_stage
->setDepthBufferInternalFormat (GL_DEPTH24_STENCIL8
);
720 hdr_stage
->setDepthBufferPixelFormat (GL_DEPTH_STENCIL
);
721 hdr_stage
->setDepthBufferType (GL_UNSIGNED_INT_24_8
);
723 hdr_stage
->setLumBufferInternalFormat (GL_R32F
);
724 hdr_stage
->setLumBufferPixelFormat (GL_RED
);
725 hdr_stage
->setLumBufferType (GL_FLOAT
);
727 hdr_stage
->setImageBufferInternalFormat (GL_RGB16F
);
728 hdr_stage
->setImageBufferPixelFormat (GL_RGB
);
729 hdr_stage
->setImageBufferType (GL_FLOAT
);
731 hdr_stage
->setNumSamples (0);
733 hdr_stage
->setBloomThreshold (2.0f
);
734 hdr_stage
->setBloomMagnitude (0.0f
);
735 hdr_stage
->setToneMappingMode (OSG::HDR2Stage::REINHARD_TONE_MAPPING
);
736 hdr_stage
->setExposure (0.0f
);
737 hdr_stage
->setKeyValue (0.18f
);
738 hdr_stage
->setAutoExposureMode (OSG::HDR2Stage::MANUAL
);
739 hdr_stage
->setWhiteLevel (5.0f
);
740 hdr_stage
->setFilmicShoulderStrenght (0.15f
);
741 hdr_stage
->setFilmicLinearStrength (0.5f
);
742 hdr_stage
->setFilmicLinearAngle (0.1f
);
743 hdr_stage
->setFilmicToeStrength (0.2f
);
744 hdr_stage
->setFilmicToeNumerator (0.02f
);
745 hdr_stage
->setFilmicToeDenominator (0.3f
);
746 hdr_stage
->setFilmicLinearWhite (11.2f
);
747 hdr_stage
->setSaturation (1.0f
);
748 hdr_stage
->setDragoBias (0.85f
);
749 hdr_stage
->setTau (1.25f
);
750 hdr_stage
->setNumTaps (4);
751 hdr_stage
->setBlurGaussSigma (0.8f
);
752 hdr_stage
->setUseLinChromCorrection (true);
756 void removeHDRStage()
758 OSG::GroupRefPtr group
= OSG::Group::create();
759 hdr_node
->setCore(group
);
764 void createHDRStage()
768 hdr_stage
= OSG::HDR2Stage::create();
773 hdr_node
->setCore(hdr_stage
);
779 void deinitialize_lights()
781 BOOST_FOREACH(const Light
& light
, lights
)
783 scene_node
->subChild(light
.beacon
);
789 void initialize_lights(OSG::UInt32 num
) // helper to create lights
791 deinitialize_lights();
793 for (OSG::UInt32 i
= 0; i
< num
; ++i
)
796 int n
= classic_die();
799 type
= Light::point_light
;
801 type
= Light::spot_light
;
803 lights
.push_back(Light::create_light(type
, i
+1));
804 scene_node
->addChild(lights
[i
].beacon
);
808 Light
Light::create_light(
809 Type e
, // type of the light
810 OSG::UInt32 material_idx
) // index in to the material storage for light animation
814 l
.beacon
= OSG::makeCoredNode
<OSG::Transform
>(&l
.transform
);
817 OSG::Real32 L
= box_factor
* world_size
;
819 l
.direction
= dice_unit_vector();
821 OSG::Color3f c
; c
.setRandom();
822 l
.ambientIntensity
= c
;
823 l
.diffuseIntensity
= c
;
824 l
.specularIntensity
= c
;
827 // If we fix the constant factor to 1 we alway get attenuation <= 1
830 // a = 1/(c + l*d + q*d^2)
833 l
.constantAttenuation
= 1.f
;
834 l
.linearAttenuation
= OSG::Eps
;
835 l
.quadraticAttenuation
= OSG::Eps
;
839 materials
[material_idx
] = mat
;
845 OSG::GeometryRefPtr geometry
= OSG::makeSphereGeo(3, 0.1f
);
846 OSG::NodeRefPtr node
= OSG::makeNodeFor(geometry
);
848 GeomState geom
; geom
.material_index
= material_idx
; // material index used for light animiation
849 OSG::ChunkMaterialRefPtr geom_state
= OSG::ChunkMaterial::create();
850 OSG::MultiPropertyUBOChunkRefPtr ubo_geom_state
= create_geometry_material_state(geom
);
851 geom_state
->addChunk(ubo_geom_state
, 3); // buffer binding point 3
852 geom_state
->addChunk(shader_var_chunk
); // block binding point
854 geometry
->setMaterial(geom_state
);
856 l
.beacon
->addChild(node
);
860 case directional_light
:
867 l
.spotlightAngle
= 90.f
* small_die();
868 l
.spotExponent
= 1.f
;
870 GeomState geom
; geom
.material_index
= material_idx
; // material index used for light animiation
871 OSG::ChunkMaterialRefPtr geom_state
= OSG::ChunkMaterial::create();
872 OSG::MultiPropertyUBOChunkRefPtr ubo_geom_state
= create_geometry_material_state(geom
);
873 geom_state
->addChunk(ubo_geom_state
, 3); // buffer binding point 3
874 geom_state
->addChunk(shader_var_chunk
); // block binding point
876 OSG::Real32 r
= 0.1f
;
877 OSG::Real32 h
= r
/ OSG::osgTan(OSG::osgDegree2Rad(l
.spotlightAngle
));
878 OSG::GeometryRefPtr geometry
= OSG::makeConeGeo(h
, r
, 24, true, true);
879 geometry
->setMaterial(geom_state
);
881 OSG::TransformRefPtr cone_trans
= OSG::Transform::create();
882 OSG::Matrix spot_mat
;
883 bool result
= OSG::MatrixLookAt(spot_mat
, l
.direction
, OSG::Pnt3f(0,0,0), OSG::Vec3f(0,1,0));
885 OSG::MatrixLookAt(spot_mat
, l
.direction
, OSG::Pnt3f(0,0,0), OSG::Vec3f(1,0,0));
886 cone_trans
->setMatrix(spot_mat
);
888 OSG::Real32 ang
= -90.f
;
889 OSG::Vec3f
rotVec(1,0,0);
891 OSG::TransformRefPtr rot_trans
= OSG::Transform::create();
893 rot_mat
.setRotate(OSG::Quaternion(rotVec
, OSG::osgDegree2Rad(ang
)));
894 rot_trans
->setMatrix(rot_mat
);
896 OSG::NodeRefPtr cone_trans_node
= OSG::makeNodeFor(cone_trans
);
897 OSG::NodeRefPtr rot_trans_node
= OSG::makeNodeFor(rot_trans
);
898 OSG::NodeRefPtr cone_node
= OSG::makeNodeFor(geometry
);
900 l
.beacon
->addChild(cone_trans_node
);
902 cone_trans_node
->addChild(rot_trans_node
);
903 rot_trans_node
->addChild(cone_node
);
905 //OSG::GeometryRefPtr geometry_test = OSG::makeCylinderGeo(30, .01f, 24, true, true, true );
906 //geometry_test->setMaterial(geom_state);
908 //OSG::TransformRefPtr test_trans = OSG::Transform::create();
909 //OSG::Matrix test_mat;
910 //test_mat.setTranslate(OSG::Vec3f(0,-15,0));
911 //test_trans->setMatrix(test_mat);
913 //OSG::NodeRefPtr test_rot_trans_node = OSG::makeNodeFor(rot_trans);
914 //OSG::NodeRefPtr test_trans_node = OSG::makeNodeFor(test_trans);
915 //OSG::NodeRefPtr test_node = OSG::makeNodeFor(geometry_test);
916 //cone_trans_node->addChild(test_rot_trans_node);
917 //test_rot_trans_node->addChild(test_trans_node);
918 //test_trans_node->addChild(test_node);
929 OSG::NodeTransitPtr
createBox()
931 OSG::NodeRefPtr box_root
= OSG::makeCoredNode
<OSG::Group
>();
933 OSG::Real32 L
= box_factor
* world_size
;
934 OSG::GeometryRefPtr box_plane
= OSG::makePlaneGeo(2.f
*L
, 2.f
*L
, 128, 128);
936 OSG::NodeRefPtr box_bottom
= OSG::makeNodeFor(box_plane
);
937 OSG::NodeRefPtr box_left
= OSG::makeNodeFor(box_plane
);
938 OSG::NodeRefPtr box_right
= OSG::makeNodeFor(box_plane
);
939 OSG::NodeRefPtr box_far
= OSG::makeNodeFor(box_plane
);
941 OSG::TransformRefPtr box_bottom_trans
= OSG::Transform::create();
942 OSG::TransformRefPtr box_left_trans
= OSG::Transform::create();
943 OSG::TransformRefPtr box_right_trans
= OSG::Transform::create();
944 OSG::TransformRefPtr box_far_trans
= OSG::Transform::create();
946 OSG::Matrix mat_bottom
, mat_left
, mat_right
, mat_far
;
948 mat_bottom
.setTransform(OSG::Vec3f(0.f
, -L
, 0.f
), OSG::Quaternion( OSG::Vec3f(1, 0, 0), OSG::osgDegree2Rad(270.f
)));
949 mat_left
.setTransform(OSG::Vec3f( -L
, 0.f
, 0.f
), OSG::Quaternion( OSG::Vec3f(0, 1, 0), OSG::osgDegree2Rad(90.f
)));
950 mat_right
.setTransform(OSG::Vec3f( L
, 0.f
, 0.f
), OSG::Quaternion( OSG::Vec3f(0, 1, 0), OSG::osgDegree2Rad(270.f
)));
951 mat_far
.setTransform(OSG::Vec3f(0.f
, 0.f
, -L
), OSG::Quaternion( OSG::Vec3f(0, 0, 1), OSG::osgDegree2Rad( 0.f
)));
953 box_bottom_trans
->setMatrix(mat_bottom
);
954 box_left_trans
->setMatrix(mat_left
);
955 box_right_trans
->setMatrix(mat_right
);
956 box_far_trans
->setMatrix(mat_far
);
958 OSG::NodeRefPtr box_bottom_trans_node
= OSG::makeNodeFor(box_bottom_trans
);
959 OSG::NodeRefPtr box_left_trans_node
= OSG::makeNodeFor(box_left_trans
);
960 OSG::NodeRefPtr box_right_trans_node
= OSG::makeNodeFor(box_right_trans
);
961 OSG::NodeRefPtr box_far_trans_node
= OSG::makeNodeFor(box_far_trans
);
963 box_bottom_trans_node
->addChild(box_bottom
);
964 box_left_trans_node
->addChild(box_left
);
965 box_right_trans_node
->addChild(box_right
);
966 box_far_trans_node
->addChild(box_far
);
968 box_root
->addChild(box_bottom_trans_node
);
969 box_root
->addChild(box_left_trans_node
);
970 box_root
->addChild(box_right_trans_node
);
971 box_root
->addChild(box_far_trans_node
);
973 GeomState geom
; geom
.material_index
= 0; // grey box material index
974 OSG::ChunkMaterialRefPtr geom_state
= OSG::ChunkMaterial::create();
975 OSG::MultiPropertyUBOChunkRefPtr ubo_geom_state
= create_geometry_material_state(geom
);
976 geom_state
->addChunk(ubo_geom_state
, 3); // buffer binding point 3
977 geom_state
->addChunk(shader_var_chunk
); // block binding point
979 OSG::PolygonChunkRefPtr polygonChunk
= OSG::PolygonChunk::create();
980 polygonChunk
->setFrontMode(GL_SMOOTH
);
981 polygonChunk
->setBackMode(GL_SMOOTH
);
982 polygonChunk
->setOffsetFactor(1.f
);
983 polygonChunk
->setOffsetBias(1.f
);
984 polygonChunk
->setOffsetFill(true);
985 polygonChunk
->setCullFace(GL_NONE
);
986 geom_state
->addChunk(polygonChunk
);
987 geom_state
->setTransparencyMode(OSG::Material::TransparencyForceOpaque
);
989 OSG::TwoSidedLightingChunkRefPtr twoSidedLightingChunk
= OSG::TwoSidedLightingChunk::create();
990 geom_state
->addChunk(twoSidedLightingChunk
);
992 box_plane
->setMaterial(geom_state
);
994 return OSG::NodeTransitPtr(box_root
);
997 OSG::NodeTransitPtr
createGeometry()
999 int idx
= geom_idx_die();
1001 OSG::GeometryRefPtr geometry
;
1006 geometry
= OSG::makeConeGeo(3.f
* small_die(), 1.f
* small_die(), 24, true, true);
1009 geometry
= OSG::makeBoxGeo(3.f
* small_die(), 3.f
* small_die(), 3.f
* small_die(), 1, 1, 1);
1012 geometry
= OSG::makeCylinderGeo(3.f
* small_die(), .3f
, 24, true, true, true );
1015 geometry
= OSG::makeSphereGeo(6, 3.f
* small_die());
1018 geometry
= OSG::makeTorusGeo(0.6f
* small_die(), 2.f
* small_die(), 24, 36);
1020 case 5: // ellipsoide
1021 geometry
= OSG::makeLatLongEllipsoidGeo(24, 36, 2.f
* small_die(), 1.f
* small_die());
1024 geometry
= OSG::makeConicalFrustumGeo(2.f
* small_die(), 2.f
* small_die(), 2.f
* small_die(), 6, true, true, true);
1027 geometry
= OSG::makeTeapotGeo(24, 1.f
* small_die());
1031 OSG::NodeRefPtr geomNode
= OSG::makeNodeFor(geometry
);
1033 OSG::TransformRefPtr trafoCore
= OSG::Transform::create();
1034 OSG::NodeRefPtr transNode
= OSG::makeNodeFor(trafoCore
);
1035 transNode
->addChild(geomNode
);
1037 GeomState geom
; geom
.material_index
= material_idx_die();
1038 OSG::ChunkMaterialRefPtr geom_state
= OSG::ChunkMaterial::create();
1039 OSG::MultiPropertyUBOChunkRefPtr ubo_geom_state
= create_geometry_material_state(geom
);
1040 geom_state
->addChunk(ubo_geom_state
, 3); // buffer binding point 3
1041 geom_state
->addChunk(shader_var_chunk
); // block binding point
1043 OSG::PolygonChunkRefPtr polygonChunk
= OSG::PolygonChunk::create();
1044 polygonChunk
->setFrontMode(GL_SMOOTH
);
1045 polygonChunk
->setBackMode(GL_SMOOTH
);
1046 polygonChunk
->setOffsetFactor(1.f
);
1047 polygonChunk
->setOffsetBias(1.f
);
1048 polygonChunk
->setOffsetFill(true);
1050 OSG::Real32 opacity
= materials
[geom
.material_index
].opacity
;
1053 polygonChunk
->setCullFace(GL_NONE
);
1055 OSG::BlendChunkRefPtr blendChunk
= OSG::BlendChunk::create();
1056 blendChunk
->setSrcFactor (GL_SRC_ALPHA
);
1057 blendChunk
->setDestFactor(GL_ONE_MINUS_SRC_ALPHA
);
1058 geom_state
->addChunk(blendChunk
);
1059 geom_state
->setTransparencyMode(OSG::Material::TransparencyForceTransparent
);
1061 OSG::TwoSidedLightingChunkRefPtr twoSidedLightingChunk
= OSG::TwoSidedLightingChunk::create();
1062 geom_state
->addChunk(twoSidedLightingChunk
);
1065 polygonChunk
->setCullFace(GL_BACK
);
1066 geom_state
->setTransparencyMode(OSG::Material::TransparencyForceOpaque
);
1069 geom_state
->addChunk(polygonChunk
);
1071 geometry
->setMaterial(geom_state
);
1073 geom_nodes
.push_back(transNode
);
1074 geom_trafos
.push_back(trafoCore
);
1075 ubo_geom_states
.push_back(ubo_geom_state
);
1077 geom_curves
.push_back(SmoothCubicBezierSpline(dice_knots(true)));
1079 return OSG::NodeTransitPtr(transNode
);
1083 // forward declaration so we can have the interesting stuff upfront
1085 int setupGLUT (int *argc
, char *argv
[]);
1090 // Initialize GLUT & OpenSG and set up the scene
1092 int main(int argc
, char **argv
)
1095 OSG::osgInit(argc
,argv
);
1098 int winid
= setupGLUT(&argc
, argv
);
1102 // open a new scope, because the pointers below should go out of scope
1103 // before entering glutMainLoop.
1104 // Otherwise OpenSG will complain about objects being alive after shutdown.
1106 // the connection between GLUT and OpenSG
1107 OSG::GLUTWindowRefPtr gwin
= OSG::GLUTWindow::create();
1108 gwin
->setGlutId(winid
);
1111 // create the SimpleSceneManager helper
1112 mgr
= OSG::SimpleSceneManager::create();
1113 mgr
->setWindow(gwin
);
1116 hdr_node
= OSG::makeCoredNode
<OSG::Group
>();
1117 scene_node
= OSG::makeCoredNode
<OSG::Group
>();
1119 hdr_node
->addChild(scene_node
);
1121 mgr
->setRoot(hdr_node
);
1126 // create the shader program
1128 OSG::ShaderProgramChunkRefPtr prog_chunk
= OSG::ShaderProgramChunk::create();
1129 OSG::ShaderProgramRefPtr vertShader
= OSG::ShaderProgram::createVertexShader();
1130 OSG::ShaderProgramRefPtr fragShader
= OSG::ShaderProgram::createFragmentShader();
1132 vertShader
->setProgram(get_vp_program());
1133 fragShader
->setProgram(get_fp_program());
1135 fragShader
->addOSGVariable("OSGViewMatrix");
1138 // binding the shader storage block to a buffer binding point can be performed
1139 // either by calling the shaders's addShaderStorageBlock method or by
1140 // adding a 'buffer block' variable to a ShaderProgramVariableChunk.
1141 // In the following we use both variants for illustration.
1143 fragShader
->addShaderStorageBlock("Materials", 1); // block binding point
1144 fragShader
->addShaderStorageBlock("Lights", 2); // block binding point
1147 // The following is replaced by adding ShaderProgramVariableChunk objects
1148 // to the chunk material. See below...
1150 // fragShader->addShaderStorageBlock("GeomState", 3); // block binding point
1152 prog_chunk
->addShader(vertShader
);
1153 prog_chunk
->addShader(fragShader
);
1156 // The block binding is added to each ChunkMaterial in order to provide the state
1157 // shader uniform block for the geometery shown in the scene
1159 shader_var_chunk
= OSG::ShaderProgramVariableChunk::create();
1160 shader_var_chunk
->addUniformBlock("GeomState", 3); // block binding point
1163 // Because we animate the lights by simple geometry, the lights initialization must be happens
1164 // after the creation of the 'shader_var_chunk' block binding point.
1165 // Additionally, it must happens before we call 'create_light_state', since here we do need the
1166 // already defined lights.
1168 initialize_lights(1);
1171 // create shader storage buffer objects and corresponding materials
1173 ssbo_material_database
= create_material_database_state(materials
);
1174 multi_light_chunk
= create_light_state(lights
);
1176 //multi_light_chunk->setEyeSpace(true);
1178 OSG::PolygonChunkRefPtr polygon_chunk
= OSG::PolygonChunk::create();
1179 polygon_chunk
->setFrontMode(GL_FILL
);
1180 polygon_chunk
->setBackMode(GL_FILL
);
1181 polygon_chunk
->setCullFace(GL_NONE
);
1183 OSG::DepthChunkRefPtr depth_chunk
= OSG::DepthChunk::create();
1184 depth_chunk
->setEnable(true);
1186 OSG::ChunkMaterialRefPtr prog_state
= OSG::ChunkMaterial::create();
1187 prog_state
->addChunk(ssbo_material_database
, 1); // buffer binding point 1
1188 prog_state
->addChunk(multi_light_chunk
, 2); // buffer binding point 2
1189 prog_state
->addChunk(prog_chunk
);
1190 prog_state
->addChunk(polygon_chunk
);
1191 prog_state
->addChunk(depth_chunk
);
1193 scene_node
->addChild(createBox());
1195 for (OSG::Int32 i
= 0; i
< num_geometries
; ++i
)
1196 scene_node
->addChild(createGeometry());
1198 OSG::MaterialChunkOverrideGroupRefPtr mgrp
= OSG::MaterialChunkOverrideGroup::create();
1199 mgrp
->setMaterial(prog_state
);
1200 scene_node
->setCore(mgrp
);
1202 OSG::commitChanges();
1204 // show the whole scene
1215 // GLUT callback functions
1219 // redraw the window
1221 OSG::TimeStamp time_stamp
= 0;
1222 OSG::Real32 simulation_param
= 0.f
;
1223 bool simulate_geometry
= true;
1224 bool simulate_lights
= true;
1228 // create the matrix
1231 if (time_stamp
== 0)
1232 time_stamp
= OSG::getTimeStamp();
1234 OSG::Time elapsed
= OSG::getTimeStampMsecs(OSG::getTimeStamp() - time_stamp
);
1236 if (elapsed
> elapse_time_limit
)
1238 simulation_param
+= simulation_delta
;
1239 if (simulation_param
>= 1.f
)
1240 simulation_param
= 0.f
;
1242 if (simulate_geometry
)
1244 std::size_t numCurves
= geom_curves
.size();
1246 OSG_ASSERT(numCurves
== geom_trafos
.size());
1248 for (std::size_t i
= 0; i
< numCurves
; ++i
)
1250 m
= geom_curves
[i
].frame(simulation_param
);
1251 geom_trafos
[i
]->setMatrix(m
);
1255 if (simulate_lights
)
1257 BOOST_FOREACH(Light
& light
, lights
)
1259 m
= light
.curve
.frame(simulation_param
, true);
1260 light
.transform
->setMatrix(m
);
1264 time_stamp
= OSG::getTimeStamp();
1267 OSG::commitChanges();
1273 // react to size changes
1275 void reshape(int w
, int h
)
1278 glutPostRedisplay();
1282 // react to mouse button presses
1284 void mouse(int button
, int state
, int x
, int y
)
1287 mgr
->mouseButtonRelease(button
, x
, y
);
1289 mgr
->mouseButtonPress(button
, x
, y
);
1291 glutPostRedisplay();
1295 // react to mouse motions with pressed buttons
1297 void motion(int x
, int y
)
1299 mgr
->mouseMove(x
, y
);
1300 glutPostRedisplay();
1306 void keyboard(unsigned char k
, int x
, int y
)
1312 // clean up global variables
1320 multi_light_chunk
= NULL
;
1321 shader_var_chunk
= NULL
;
1324 geom_trafos
.clear();
1325 geom_curves
.clear();
1327 ubo_geom_states
.clear();
1341 simulate_geometry
= !simulate_geometry
;
1347 simulate_lights
= !simulate_lights
;
1353 elapse_time_limit
*= 2.f
;
1359 elapse_time_limit
/= 2.f
;
1365 simulation_delta
*= 2.f
;
1371 simulation_delta
/= 2.f
;
1377 initialize_lights(1);
1378 update_light_state(multi_light_chunk
, lights
);
1379 update_material_database_state(ssbo_material_database
, materials
);
1381 simulation_delta
= 0.0001f
;
1382 elapse_time_limit
= 10.f
;
1384 simulate_geometry
= true;
1385 simulate_lights
= true;
1387 glutPostRedisplay();
1393 BOOST_FOREACH(Light
& light
, lights
)
1394 light
.linearAttenuation
*= linearAttFactor
;
1396 update_light_state(multi_light_chunk
, lights
);
1397 glutPostRedisplay();
1403 BOOST_FOREACH(Light
& light
, lights
)
1404 if (light
.linearAttenuation
/ linearAttFactor
>= OSG::Eps
)
1405 light
.linearAttenuation
/= linearAttFactor
;
1407 update_light_state(multi_light_chunk
, lights
);
1408 glutPostRedisplay();
1414 BOOST_FOREACH(Light
& light
, lights
)
1415 light
.quadraticAttenuation
*= quadraticAttFactor
;
1417 update_light_state(multi_light_chunk
, lights
);
1418 glutPostRedisplay();
1424 BOOST_FOREACH(Light
& light
, lights
)
1425 if (light
.quadraticAttenuation
/ quadraticAttFactor
>= OSG::Eps
)
1426 light
.quadraticAttenuation
/= quadraticAttFactor
;
1428 update_light_state(multi_light_chunk
, lights
);
1429 glutPostRedisplay();
1435 BOOST_FOREACH(Light
& light
, lights
)
1436 light
.spotExponent
*= spotExponentFactor
;
1438 update_light_state(multi_light_chunk
, lights
);
1439 glutPostRedisplay();
1445 BOOST_FOREACH(Light
& light
, lights
)
1446 if (light
.spotExponent
/ spotExponentFactor
>= OSG::Eps
)
1447 light
.spotExponent
/= spotExponentFactor
;
1449 update_light_state(multi_light_chunk
, lights
);
1450 glutPostRedisplay();
1456 initialize_lights(1);
1457 update_light_state(multi_light_chunk
, lights
);
1458 update_material_database_state(ssbo_material_database
, materials
);
1459 glutPostRedisplay();
1465 if (lights
.size() > 1)
1467 OSG::UInt32 num
= static_cast<OSG::UInt32
>(lights
.size() / 2);
1468 initialize_lights(num
);
1469 update_light_state(multi_light_chunk
, lights
);
1470 update_material_database_state(ssbo_material_database
, materials
);
1471 glutPostRedisplay();
1478 if (lights
.size() <= max_num_lights
)
1480 OSG::UInt32 num
= static_cast<OSG::UInt32
>(lights
.size() * 2);
1481 initialize_lights(num
);
1482 update_light_state(multi_light_chunk
, lights
);
1483 update_material_database_state(ssbo_material_database
, materials
);
1484 glutPostRedisplay();
1491 if (geom_nodes
.size() > 1)
1493 OSG::UInt32 num
= static_cast<OSG::UInt32
>(geom_nodes
.size() / 2);
1495 BOOST_FOREACH(OSG::Node
* node
, geom_nodes
)
1496 scene_node
->subChild(node
);
1499 geom_trafos
.clear();
1500 geom_curves
.clear();
1501 ubo_geom_states
.clear();
1503 for (OSG::UInt32 i
= 0; i
< num
; ++i
)
1504 scene_node
->addChild(createGeometry());
1506 glutPostRedisplay();
1513 if (geom_nodes
.size() <= 4.f
* num_geometries
)
1515 OSG::UInt32 num
= static_cast<OSG::UInt32
>(geom_nodes
.size() * 2);
1517 BOOST_FOREACH(OSG::Node
* node
, geom_nodes
)
1518 scene_node
->subChild(node
);
1521 geom_trafos
.clear();
1522 geom_curves
.clear();
1523 ubo_geom_states
.clear();
1525 for (OSG::UInt32 i
= 0; i
< num
; ++i
)
1526 scene_node
->addChild(createGeometry());
1528 glutPostRedisplay();
1535 BOOST_FOREACH(OSG::MultiPropertyUBOChunk
* ubo_geom_state
, ubo_geom_states
)
1537 GeomState geom
; geom
.material_index
= material_idx_die();
1538 update_geometry_material_state(ubo_geom_state
, geom
);
1541 glutPostRedisplay();
1547 mgr
->setStatistics(!mgr
->getStatistics());
1553 OSG::HDR2Stage
* core
= dynamic_cast<OSG::HDR2Stage
*>(hdr_node
->getCore());
1559 glutPostRedisplay();
1566 // setup the GLUT library which handles the windows for us
1568 int setupGLUT(int *argc
, char *argv
[])
1570 glutInit(argc
, argv
);
1571 glutInitDisplayMode(GLUT_RGB
| GLUT_DEPTH
| GLUT_DOUBLE
);
1572 glutInitWindowSize(1000, 800);
1574 int winid
= glutCreateWindow("OpenSG");
1576 glutReshapeFunc(reshape
);
1577 glutDisplayFunc(display
);
1578 glutMouseFunc(mouse
);
1579 glutMotionFunc(motion
);
1580 glutKeyboardFunc(keyboard
);
1582 // call the redraw function whenever there's nothing else to do
1583 glutIdleFunc(display
);
1590 glutReshapeFunc(NULL
);
1591 glutDisplayFunc(NULL
);
1592 glutMouseFunc(NULL
);
1593 glutMotionFunc(NULL
);
1594 glutKeyboardFunc(NULL
);
1600 std::cout
<< "Esc : quit example" << std::endl
;
1601 std::cout
<< "Space : toogle geometry simulation on/off" << std::endl
;
1602 std::cout
<< "h : toogle HDR stage usage on/off" << std::endl
;
1603 std::cout
<< "l : toogle light simulation on/off" << std::endl
;
1604 std::cout
<< "m : assign new color to geometry" << std::endl
;
1605 std::cout
<< "r : reset the example" << std::endl
;
1606 std::cout
<< "s : toogle statistics on/off" << std::endl
;
1607 std::cout
<< "1 : only one light" << std::endl
;
1608 std::cout
<< "2 : half number of lights" << std::endl
;
1609 std::cout
<< "3 : double number of lights" << std::endl
;
1610 std::cout
<< "4 : half number of geometry objects" << std::endl
;
1611 std::cout
<< "5 : double number of geometry objects" << std::endl
;
1612 std::cout
<< "e/E : speed up/down simulation" << std::endl
;
1613 std::cout
<< "o/O : double/half simulation time interval" << std::endl
;
1614 std::cout
<< "a/A : increase/decrease linear attenuation factor" << std::endl
;
1615 std::cout
<< "q/Q : increase/decrease quadratic attenuation factor" << std::endl
;
1616 std::cout
<< "x/X : increase/decrease spot exponent" << std::endl
;
1619 // ============================================================================
1621 // Part VI: Cubic Bezier spline curve implementation
1623 // ============================================================================
1625 CubicBezierCurve::CubicBezierCurve(
1626 const OSG::Pnt3f
& p0
,
1627 const OSG::Pnt3f
& p1
,
1628 const OSG::Pnt3f
& p2
,
1629 const OSG::Pnt3f
& p3
)
1631 p
[0] = p0
; p
[1] = p1
; p
[2] = p2
; p
[3] = p3
;
1634 CubicBezierCurve::CubicBezierCurve(const CubicBezierCurve
& rhs
)
1636 p
[0] = rhs
.p
[0]; p
[1] = rhs
.p
[1]; p
[2] = rhs
.p
[2]; p
[3] = rhs
.p
[3];
1639 CubicBezierCurve
& CubicBezierCurve::operator=(const CubicBezierCurve
& rhs
)
1643 p
[0] = rhs
.p
[0]; p
[1] = rhs
.p
[1]; p
[2] = rhs
.p
[2]; p
[3] = rhs
.p
[3];
1648 OSG::Pnt3f
CubicBezierCurve::operator()(OSG::Real32 t
) const
1650 OSG_ASSERT(0.f
<= t
&& t
<= 1.f
);
1652 OSG::Real32 e
= 1.f
- t
;
1653 OSG::Real32 sq_e
= e
* e
;
1654 OSG::Real32 sq_t
= t
* t
;
1656 return e
* sq_e
* p
[0]
1657 + 3.f
* t
* sq_e
* p
[1].subZero()
1658 + 3.f
* sq_t
* e
* p
[2].subZero()
1659 + t
* sq_t
* p
[3].subZero();
1662 OSG::Vec3f
CubicBezierCurve::tangent(OSG::Real32 t
) const
1664 OSG::Vec3f tangent
= fst_derivative(t
);
1665 tangent
.normalize();
1670 OSG::Vec3f
CubicBezierCurve::normal(OSG::Real32 t
) const
1672 OSG::Vec3f normal
= binormal(t
);
1673 normal
.crossThis(tangent(t
));
1679 OSG::Vec3f
CubicBezierCurve::binormal(OSG::Real32 t
) const
1681 OSG::Vec3f binormal
= fst_derivative(t
);
1682 binormal
.crossThis(sec_derivative(t
));
1683 binormal
.normalize();
1685 while (OSG::osgAbs(binormal
.length() - 1.f
) >= OSG::Eps
)
1687 if (t
+ OSG::Eps
<= 1.f
)
1689 else if (t
- OSG::Eps
>= 0.f
)
1694 binormal
= fst_derivative(t
);
1695 binormal
.crossThis(sec_derivative(t
));
1696 binormal
.normalize();
1702 OSG::Matrix
CubicBezierCurve::frame(OSG::Real32 t
, bool position_only
) const
1707 OSG::Vec3f P
= (*this)(t
).subZero();
1711 mat
.setTranslate(P
);
1715 OSG::Vec3f T
= tangent(t
);
1716 OSG::Vec3f N
= normal(t
);
1717 OSG::Vec3f B
= binormal(t
);
1720 OSG::Real32 lT
= T
.length();
1721 OSG::Real32 lN
= N
.length();
1722 OSG::Real32 lB
= B
.length();
1724 OSG::Real32 v1
= T
.dot(N
);
1725 OSG::Real32 v2
= T
.dot(B
);
1726 OSG::Real32 v3
= N
.dot(B
);
1728 OSG_ASSERT(OSG::osgAbs(T
.length() - 1.f
) < OSG::Eps
);
1729 OSG_ASSERT(OSG::osgAbs(N
.length() - 1.f
) < OSG::Eps
);
1730 OSG_ASSERT(OSG::osgAbs(B
.length() - 1.f
) < OSG::Eps
);
1732 mat
.setValue(T
,N
,B
,P
);
1738 OSG::Real32
CubicBezierCurve::length(OSG::UInt32 numSeg
) const
1740 OSG_ASSERT(numSeg
>= 2);
1742 OSG::Real32 d
= 1.f
/ numSeg
;
1744 OSG::Real32 l
= 0.f
;
1746 OSG::Pnt3f p0
= operator()(0.f
);
1750 OSG::Pnt3f p1
= operator()(t
);
1752 l
+= (p1
- p0
).length();
1759 OSG::Vec3f
CubicBezierCurve::fst_derivative(OSG::Real32 t
) const
1761 OSG::Vec3f v10
= p
[1] - p
[0];
1762 OSG::Vec3f v21
= p
[2] - p
[1];
1763 OSG::Vec3f v32
= p
[3] - p
[2];
1765 OSG::Real32 e
= 1.f
- t
;
1766 OSG::Real32 sq_e
= e
* e
;
1767 OSG::Real32 sq_t
= t
* t
;
1769 return 3.f
* sq_e
* v10
+ 6.f
* e
* t
* v21
+ 3.f
* sq_t
* v32
;
1772 OSG::Vec3f
CubicBezierCurve::sec_derivative(OSG::Real32 t
) const
1774 OSG::Vec3f v210
= p
[2] - 2.f
* p
[1] + p
[0].subZero();
1775 OSG::Vec3f v321
= p
[3] - 2.f
* p
[2] + p
[1].subZero();
1777 OSG::Real32 e
= 1.f
- t
;
1779 return 6.f
* e
* v210
+ 6.f
* t
* v321
;
1782 OSG::Vec3f
CubicBezierCurve::thr_devivative(OSG::Real32 t
) const
1784 OSG::Vec3f v21
= p
[2] - p
[1];
1785 OSG::Vec3f v30
= p
[3] - p
[0];
1787 return -18.f
* v21
+ 6.f
* v30
;
1791 SmoothCubicBezierSpline::SmoothCubicBezierSpline(const std::vector
<OSG::Pnt3f
>& knots
)
1794 OSG_ASSERT(knots
.size() > 3);
1798 calc_ctrl_pnts(p1
, p2
);
1800 std::size_t n
= knots
.size() - 1;
1802 std::vector
<OSG::Real32
> lengths(n
);
1803 OSG::Real32 L
= 0.f
;
1805 for (std::size_t i
= 0; i
< n
; ++i
)
1807 curves
.push_back(CubicBezierCurve(knots
[i
], p1
[i
], p2
[i
], knots
[i
+1]));
1809 lengths
[i
] = curves
[i
].length();
1813 OSG_ASSERT(L
> 0.f
);
1815 OSG::Real32 d
= 1.f
/ L
;
1817 intervals
.resize(n
);
1819 intervals
[0] = d
* lengths
[0];
1821 for (std::size_t i
= 1; i
< n
-1; ++i
)
1823 intervals
[i
] = intervals
[i
-1] + d
* lengths
[i
];
1826 intervals
[n
-1] = 1.f
;
1829 SmoothCubicBezierSpline::SmoothCubicBezierSpline(const SmoothCubicBezierSpline
& rhs
)
1831 , intervals(rhs
.intervals
)
1832 , curves(rhs
.curves
)
1836 SmoothCubicBezierSpline
& SmoothCubicBezierSpline::operator=(const SmoothCubicBezierSpline
& rhs
)
1841 intervals
= rhs
.intervals
;
1842 curves
= rhs
.curves
;
1847 OSG::Pnt3f
SmoothCubicBezierSpline::operator()(OSG::Real32 t
) const
1849 std::size_t idx
= index(t
);
1850 return curves
[idx
](t_(t
, idx
));
1853 OSG::Vec3f
SmoothCubicBezierSpline::tangent(OSG::Real32 t
) const
1855 std::size_t idx
= index(t
);
1856 return curves
[idx
].tangent(t_(t
, idx
));
1859 OSG::Vec3f
SmoothCubicBezierSpline::normal(OSG::Real32 t
) const
1861 std::size_t idx
= index(t
);
1862 return curves
[idx
].normal(t_(t
, idx
));
1865 OSG::Vec3f
SmoothCubicBezierSpline::binormal(OSG::Real32 t
) const
1867 std::size_t idx
= index(t
);
1868 return curves
[idx
].binormal(t_(t
, idx
));
1871 OSG::Matrix
SmoothCubicBezierSpline::frame(OSG::Real32 t
, bool position_only
) const
1873 std::size_t idx
= index(t
);
1874 return curves
[idx
].frame(t_(t
, idx
), position_only
);
1877 OSG::Real32
SmoothCubicBezierSpline::length(OSG::UInt32 numSeg
) const
1879 OSG::Real32 l
= 0.f
;
1880 BOOST_FOREACH(const CubicBezierCurve
& c
, curves
)
1882 l
+= c
.length(numSeg
);
1887 void SmoothCubicBezierSpline::calc_ctrl_pnts(points_t
& p1
, points_t
& p2
) const
1889 namespace tp
= boost::tuples
;
1890 typedef tp::tuple
<OSG::Real32
, OSG::Real32
, OSG::Real32
> tuple_t
;
1891 typedef std::vector
<tuple_t
> tuples_t
;
1893 std::size_t n
= knots
.size()-1;
1898 tuples_t
a(n
), b(n
), c(n
), d(n
);
1900 a
[0] = tp::make_tuple(0.f
, 0.f
, 0.f
);
1901 b
[0] = tp::make_tuple(2.f
, 2.f
, 2.f
);
1902 c
[0] = tp::make_tuple(1.f
, 1.f
, 1.f
);
1903 d
[0] = tp::make_tuple(
1904 knots
[0].x() + 2.f
* knots
[1].x(),
1905 knots
[0].y() + 2.f
* knots
[1].y(),
1906 knots
[0].z() + 2.f
* knots
[1].z());
1908 for (std::size_t i
= 1; i
< n
-1; ++i
)
1910 a
[i
] = tp::make_tuple(1.f
, 1.f
, 1.f
);
1911 b
[i
] = tp::make_tuple(4.f
, 4.f
, 4.f
);
1912 c
[i
] = tp::make_tuple(1.f
, 1.f
, 1.f
);
1913 d
[i
] = tp::make_tuple(
1914 4.f
* knots
[i
].x() + 2.f
* knots
[i
+1].x(),
1915 4.f
* knots
[i
].y() + 2.f
* knots
[i
+1].y(),
1916 4.f
* knots
[i
].z() + 2.f
* knots
[i
+1].z());
1919 a
[n
-1] = tp::make_tuple(2.f
, 2.f
, 2.f
);
1920 b
[n
-1] = tp::make_tuple(7.f
, 7.f
, 7.f
);
1921 c
[n
-1] = tp::make_tuple(0.f
, 0.f
, 0.f
);
1922 d
[n
-1] = tp::make_tuple(
1923 8.f
* knots
[n
-1].x() + 2.f
* knots
[n
].x(),
1924 8.f
* knots
[n
-1].y() + 2.f
* knots
[n
].y(),
1925 8.f
* knots
[n
-1].z() + 2.f
* knots
[n
].z());
1927 for (std::size_t i
= 1; i
< n
; ++i
)
1929 tuple_t m
= tp::make_tuple(
1930 a
[i
].get
<0>() / b
[i
-1].get
<0>(),
1931 a
[i
].get
<1>() / b
[i
-1].get
<1>(),
1932 a
[i
].get
<2>() / b
[i
-1].get
<2>());
1934 b
[i
] = tp::make_tuple(
1935 b
[i
].get
<0>() - m
.get
<0>() * c
[i
-1].get
<0>(),
1936 b
[i
].get
<1>() - m
.get
<1>() * c
[i
-1].get
<1>(),
1937 b
[i
].get
<2>() - m
.get
<2>() * c
[i
-1].get
<2>());
1939 d
[i
] = tp::make_tuple(
1940 d
[i
].get
<0>() - m
.get
<0>() * d
[i
-1].get
<0>(),
1941 d
[i
].get
<1>() - m
.get
<1>() * d
[i
-1].get
<1>(),
1942 d
[i
].get
<2>() - m
.get
<2>() * d
[i
-1].get
<2>());
1946 d
[n
-1].get
<0>() / b
[n
-1].get
<0>(),
1947 d
[n
-1].get
<1>() / b
[n
-1].get
<1>(),
1948 d
[n
-1].get
<2>() / b
[n
-1].get
<2>());
1950 for (long long i
= n
-2; i
>= 0; --i
)
1953 (d
[i
].get
<0>() - c
[i
].get
<0>() * p1
[i
+1].x()) / b
[i
].get
<0>(),
1954 (d
[i
].get
<1>() - c
[i
].get
<1>() * p1
[i
+1].y()) / b
[i
].get
<1>(),
1955 (d
[i
].get
<2>() - c
[i
].get
<2>() * p1
[i
+1].z()) / b
[i
].get
<2>());
1958 for (std::size_t i
= 0; i
< n
-1; ++i
)
1961 2.f
* knots
[i
+1].x() - p1
[i
+1].x(),
1962 2.f
* knots
[i
+1].y() - p1
[i
+1].y(),
1963 2.f
* knots
[i
+1].z() - p1
[i
+1].z());
1967 0.5f
* knots
[n
].x() - p1
[n
-1].x(),
1968 0.5f
* knots
[n
].y() - p1
[n
-1].y(),
1969 0.5f
* knots
[n
].z() - p1
[n
-1].z());
1972 std::size_t SmoothCubicBezierSpline::index(OSG::Real32 t
) const
1974 OSG_ASSERT(0.f
<= t
&& t
<= 1.f
);
1976 std::vector
<OSG::Real32
>::const_iterator iter
= std::lower_bound(intervals
.begin(), intervals
.end(), t
);
1977 std::size_t r
= iter
- intervals
.begin();
1981 OSG::Real32
SmoothCubicBezierSpline::t_(OSG::Real32 t
, std::size_t idx
) const
1983 OSG_ASSERT(idx
< intervals
.size());
1985 OSG::Real32 t0
= 0.f
;
1986 OSG::Real32 t1
= 1.f
;
1988 if (idx
> 0) t0
= intervals
[idx
-1];
1989 t1
= intervals
[idx
];
1991 OSG::Real32 r
= (t
- t0
) / (t1
- t0
);
1996 // ============================================================================
1998 // Part VII: dice_knots helper implementation
2000 // ============================================================================
2002 typedef boost::tuples::tuple
<int, int, int> index_t
;
2004 struct index_hash_t
: public std::unary_function
<index_t
, std::size_t>
2006 std::size_t operator()(const index_t
& v
) const
2008 std::size_t seed
= 0;
2009 boost::hash_combine(seed
, v
.get
<0>());
2010 boost::hash_combine(seed
, v
.get
<1>());
2011 boost::hash_combine(seed
, v
.get
<2>());
2016 std::vector
<OSG::Pnt3f
> dice_knots(bool close_curve
)
2019 // idea: sample a number if different cube boxes from the scene and
2020 // take randomly one point from each cube. That guarantees that
2021 // the knot points do not clump and that they are all unequal.
2023 namespace tp
= boost::tuples
;
2025 boost::unordered_set
<index_t
, index_hash_t
> indices
;
2027 while (indices
.size() < num_curve_knots
)
2029 indices
.insert(tp::make_tuple(box_idx_die(), box_idx_die(), box_idx_die()));
2032 OSG::Real32 l
= 2 * world_size
/ num_grid_boxes
;
2034 std::vector
<OSG::Pnt3f
> knots
;
2036 BOOST_FOREACH(const index_t
& idx
, indices
)
2039 p
[0] = -world_size
+ idx
.get
<0>() * l
+ unit_die() * l
;
2040 p
[1] = -world_size
+ idx
.get
<1>() * l
+ unit_die() * l
;
2041 p
[2] = -world_size
+ idx
.get
<2>() * l
+ unit_die() * l
;
2047 knots
.push_back(knots
.front());
2052 // ============================================================================
2054 // Part VIII: The shader programs
2056 // ============================================================================
2059 // vertex shader program.
2061 std::string
get_vp_program()
2063 using namespace std
;
2067 ost
<< "#version 440 compatibility"
2069 << endl
<< "#extension GL_ARB_separate_shader_objects: enable"
2070 << endl
<< "#extension GL_ARB_shader_storage_buffer_object: enable"
2072 << endl
<< "smooth out vec3 vNormalES; // eye space normal"
2073 << endl
<< "smooth out vec3 vPositionES; // eye space position"
2075 << endl
<< "void main()"
2078 << endl
<< " // multiply the object space vertex position with the modelview matrix "
2079 << endl
<< " // to get the eye space vertex position"
2081 << endl
<< " vPositionES = (gl_ModelViewMatrix * gl_Vertex).xyz;"
2084 << endl
<< " // multiply the object space normal with the normal matrix (transpose of the inverse "
2085 << endl
<< " // model view matrix) to get the eye space normal"
2087 << endl
<< " vNormalES = gl_NormalMatrix * gl_Normal;"
2090 << endl
<< " // multiply the combiend modelview projection matrix with the object space vertex"
2091 << endl
<< " // position to get the clip space position"
2093 << endl
<< " gl_Position = ftransform();"
2102 // fragment shader program for bump mapping in surface local coordinates
2104 std::string
get_fp_program()
2106 using namespace std
;
2110 ost
<< "#version 440 compatibility"
2112 << endl
<< "#extension GL_ARB_separate_shader_objects: enable"
2113 << endl
<< "#extension GL_ARB_shader_storage_buffer_object: enable"
2115 << endl
<< "smooth in vec3 vNormalES; // eye space normal"
2116 << endl
<< "smooth in vec3 vPositionES; // eye space position"
2118 << endl
<< "const int num_materials = 5000;"
2120 << endl
<< "const int POINT_LIGHT = 1; // defined in OSGMultiLightChunk.h"
2121 << endl
<< "const int DIRECTIONAL_LIGHT = 2;"
2122 << endl
<< "const int SPOT_LIGHT = 3;"
2123 << endl
<< "const int CINEMA_LIGHT = 4;"
2125 << endl
<< "uniform mat4 OSGViewMatrix;"
2127 << endl
<< "struct Light"
2129 << endl
<< " vec3 position; // in world space"
2130 << endl
<< " vec3 direction; // in world space"
2131 << endl
<< " vec3 Ia;"
2132 << endl
<< " vec3 Id;"
2133 << endl
<< " vec3 Is;"
2134 << endl
<< " float const_attenuation;"
2135 << endl
<< " float linear_attenuation;"
2136 << endl
<< " float quadratic_attenuation;"
2137 << endl
<< " float rangeCutOn;"
2138 << endl
<< " float rangeCutOff;"
2139 << endl
<< " float cosSpotlightAngle;"
2140 << endl
<< " float spotExponent;"
2141 << endl
<< " int type; // specific type of light: POINT_LIGHT, DIRECTIONAL_LIGHT, SPOT_LIGHT or CINEMA_LIGHT"
2142 << endl
<< " bool enabled; // on/off state of light"
2145 << endl
<< "layout (std430) buffer Lights"
2147 << endl
<< " Light light[];"
2148 << endl
<< "} lights;"
2150 << endl
<< "struct Material"
2152 << endl
<< " vec3 ambient;"
2153 << endl
<< " vec3 diffuse;"
2154 << endl
<< " vec3 specular;"
2155 << endl
<< " vec3 emissive;"
2157 << endl
<< " float opacity;"
2158 << endl
<< " float shininess;"
2161 << endl
<< "layout (std430) buffer Materials"
2163 << endl
<< " Material material[num_materials];"
2164 << endl
<< "} materials;"
2167 << endl
<< "layout (std140) uniform GeomState"
2169 << endl
<< " int material_index;"
2170 << endl
<< "} geom_state;"
2172 << endl
<< "const vec3 cCameraPositionES = vec3(0,0,0); // eye is at vec3(0,0,0) in eye space!"
2174 << endl
<< "layout(location = 0) out vec4 vFragColor;"
2177 << endl
<< "// Calculate the attenuation of the light based on its"
2178 << endl
<< "// constant, linear and quadratic attenuation factors"
2179 << endl
<< "// and the distance d of the light to the current point."
2181 << endl
<< "float calcAttenuation(in float c, in float l, in float q, in float d)"
2183 << endl
<< " return 1.0 / (c + l*d + q*d*d);"
2187 << endl
<< "// Calculate the attenuation with respect to the spot light cone."
2188 << endl
<< "// Parameters:"
2189 << endl
<< "// cutoff : cosine of the spot cutoff angle"
2190 << endl
<< "// exponent : the spot exponent"
2191 << endl
<< "// l : normalized direction between fragment and light position"
2192 << endl
<< "// s : normalized light direction"
2194 << endl
<< "float spotAttenuation(in float cutoff, in float exponent, in vec3 l, in vec3 s)"
2196 << endl
<< " float attenuation = 0.0;"
2197 << endl
<< " float l_dot_s = dot(-l, s);"
2198 << endl
<< " if (l_dot_s >= cutoff)"
2199 << endl
<< " attenuation = pow(l_dot_s, exponent);"
2200 << endl
<< " return attenuation;"
2204 << endl
<< "// directional light contribution"
2206 << endl
<< "vec3 directionalLight("
2207 << endl
<< " in int i, // light identifier, i.e. current light"
2208 << endl
<< " in int j, // material identifier"
2209 << endl
<< " in vec3 n, // vertex normal in eye space"
2210 << endl
<< " in vec3 v) // view direction in eye space"
2212 << endl
<< " if (!lights.light[i].enabled)"
2213 << endl
<< " return vec3(0.0, 0.0, 0.0);"
2216 << endl
<< " // the light direction in eye space"
2218 << endl
<< " vec4 direction = OSGViewMatrix * vec4(lights.light[i].direction, 0.0);"
2219 << endl
<< " vec3 l = -direction.xyz;"
2222 << endl
<< " // the half vector"
2224 << endl
<< " vec3 h = normalize(l+v);"
2226 << endl
<< " float n_dot_l = max(0.0, dot(n, l));"
2227 << endl
<< " float n_dot_h = max(0.0, dot(n, h));"
2229 << endl
<< " float m = materials.material[j].shininess;"
2231 << endl
<< " float pf; // power factor"
2233 << endl
<< " if (n_dot_l == 0.0)"
2234 << endl
<< " pf = 0.0;"
2236 << endl
<< " pf = pow(n_dot_h, m);"
2238 << endl
<< " return materials.material[j].emissive"
2239 << endl
<< " + lights.light[i].Ia * materials.material[j].ambient"
2240 << endl
<< " + lights.light[i].Id * materials.material[j].diffuse * n_dot_l"
2241 << endl
<< " + lights.light[i].Is * materials.material[j].specular * (m+8)*0.0125 * pf;"
2245 << endl
<< "// point light contribution"
2247 << endl
<< "vec3 pointLight("
2248 << endl
<< " in int i, // light identifier, i.e. current light"
2249 << endl
<< " in int j, // material identifier"
2250 << endl
<< " in vec3 n, // vertex normal in eye space"
2251 << endl
<< " in vec3 v, // view direction in eye space"
2252 << endl
<< " in vec3 p) // vertex position in eye space"
2254 << endl
<< " if (!lights.light[i].enabled)"
2255 << endl
<< " return vec3(0.0, 0.0, 0.0);"
2257 << endl
<< " vec4 position = OSGViewMatrix * vec4(lights.light[i].position, 1.0);"
2258 << endl
<< " vec3 l = position.xyz - p; // dir from surface to light position"
2259 << endl
<< " float d = length(l); // dist from surface to light source"
2261 << endl
<< " if (lights.light[i].rangeCutOff < d)"
2262 << endl
<< " return vec3(0.0, 0.0, 0.0);"
2264 << endl
<< " l = normalize(l); // norm direction from surf to light"
2267 << endl
<< " // the half vector"
2269 << endl
<< " vec3 h = normalize(l+v);"
2271 << endl
<< " float n_dot_l = max(0.0, dot(n, l));"
2272 << endl
<< " float n_dot_h = max(0.0, dot(n, h));"
2274 << endl
<< " float m = materials.material[j].shininess;"
2276 << endl
<< " float pf; // power factor"
2278 << endl
<< " if (n_dot_l == 0.0)"
2279 << endl
<< " pf = 0.0;"
2281 << endl
<< " pf = pow(n_dot_h, m);"
2283 << endl
<< " float attenuation = calcAttenuation("
2284 << endl
<< " lights.light[i].const_attenuation,"
2285 << endl
<< " lights.light[i].linear_attenuation,"
2286 << endl
<< " lights.light[i].quadratic_attenuation,"
2289 << endl
<< " return materials.material[j].emissive"
2290 << endl
<< " + attenuation * lights.light[i].Ia * materials.material[j].ambient"
2291 << endl
<< " + attenuation * lights.light[i].Id * materials.material[j].diffuse * n_dot_l"
2292 << endl
<< " + attenuation * lights.light[i].Is * materials.material[j].specular * (m+8)*0.0125 * pf;"
2296 << endl
<< "// spot light contribution"
2298 << endl
<< "vec3 spotLight("
2299 << endl
<< " in int i, // light identifier, i.e. current light"
2300 << endl
<< " in int j, // material identifier"
2301 << endl
<< " in vec3 n, // vertex normal in eye space"
2302 << endl
<< " in vec3 v, // view direction in eye space"
2303 << endl
<< " in vec3 p) // vertex position in eye space"
2305 << endl
<< " if (!lights.light[i].enabled)"
2306 << endl
<< " return vec3(0.0, 0.0, 0.0);"
2308 << endl
<< " vec4 position = OSGViewMatrix * vec4(lights.light[i].position, 1.0);"
2309 << endl
<< " vec3 l = position.xyz - p; // dir from surface to light position"
2310 << endl
<< " float d = length(l); // dist from surface to light source"
2312 << endl
<< " if (lights.light[i].rangeCutOff < d)"
2313 << endl
<< " return vec3(0.0, 0.0, 0.0);"
2315 << endl
<< " l = normalize(l); // norm dir from surface to light"
2317 << endl
<< " vec4 direction = OSGViewMatrix * vec4(lights.light[i].direction, 0.0);"
2318 << endl
<< " vec3 s = direction.xyz;"
2319 << endl
<< " s = normalize(s);"
2322 << endl
<< " // the half vector"
2324 << endl
<< " vec3 h = normalize(l+v);"
2326 << endl
<< " float n_dot_l = max(0.0, dot(n, l));"
2327 << endl
<< " float n_dot_h = max(0.0, dot(n, h));"
2329 << endl
<< " float m = materials.material[j].shininess;"
2331 << endl
<< " float pf; // power factor"
2333 << endl
<< " if (n_dot_l == 0.0)"
2334 << endl
<< " pf = 0.0;"
2336 << endl
<< " pf = pow(n_dot_h, m);"
2338 << endl
<< " float attenuation = calcAttenuation("
2339 << endl
<< " lights.light[i].const_attenuation,"
2340 << endl
<< " lights.light[i].linear_attenuation,"
2341 << endl
<< " lights.light[i].quadratic_attenuation,"
2344 << endl
<< " attenuation *= spotAttenuation(lights.light[i].cosSpotlightAngle, lights.light[i].spotExponent, l, s);"
2346 << endl
<< " return materials.material[j].emissive"
2347 << endl
<< " + attenuation * lights.light[i].Ia * materials.material[j].ambient"
2348 << endl
<< " + attenuation * lights.light[i].Id * materials.material[j].diffuse * n_dot_l"
2349 << endl
<< " + attenuation * lights.light[i].Is * materials.material[j].specular * (m+8)*0.0125 * pf;"
2352 << endl
<< "void main()"
2355 << endl
<< " // normalize the eye space normal"
2357 << endl
<< " int frontCond = -(1 - int(gl_FrontFacing)*2);"
2358 << endl
<< " vec3 N = frontCond * normalize(vNormalES);"
2361 << endl
<< " // get the view vector and normalize it"
2363 << endl
<< " vec3 V = normalize(cCameraPositionES - vPositionES);"
2366 << endl
<< " // Integrate over all lights: Any unused light does not contribute and each light"
2367 << endl
<< " // contribute either from the directional light, the point light or the spot light."
2369 << endl
<< " vec3 color = vec3(0.0, 0.0, 0.0);"
2371 << endl
<< " int num_lights = lights.light.length();"
2373 << endl
<< " for (int i = 0; i < num_lights; ++i)"
2375 << endl
<< " switch (lights.light[i].type)"
2377 << endl
<< " case POINT_LIGHT: color += pointLight(i, geom_state.material_index, N, V, vPositionES); break;"
2378 << endl
<< " case DIRECTIONAL_LIGHT: color += directionalLight(i, geom_state.material_index, N, V); break;"
2379 << endl
<< " case SPOT_LIGHT: color += spotLight(i, geom_state.material_index, N, V, vPositionES); break;"
2382 << endl
<< " vFragColor = vec4(color, materials.material[geom_state.material_index].opacity);"