fixed: auto_ptr -> unique_ptr
[opensg.git] / Examples / Advanced / multirangelightclustershadingstage.cpp
blobee01e7a9679d6e0a75b8aff6e02a01cd6e2916e4
1 // OpenSG Example: MultiRangeLightClusterShadingStage
2 //
3 // This example implements a forward cluster shading algorithm according to
4 // Ola Olsson et.al and Emil Persson
5 // https://newq.net/publications/more/s2015-many-lights-course
6 //
7 // It uses the MultiLightChunk for the light representation and the
8 // ClusterShadingStage core. It shows a simple scene that
9 // is filled with geometry and point, spot and cinema lights.
10 // Keyboard bindings allow to manipulate the setup in various ways.
12 // At startup you can see 128 lights and 256 geometries moving in the scene.
13 // On a NVidia GeForce GTX 560 rendering this scene renders smoothly.
14 // Pressing button 't' stops the clustering and the frame rate drops.
15 // After enabling clustering again by pressing 't' you can increase
16 // the number of lights to 512 by pressing key '3' two times. Now the
17 // frame rate miserable despite of the clustering. The reason is that
18 // the cluster population is now to hight. We can lower it by decreasing
19 // the range of influence of the lights by pressing key 'P' (shift) four
20 // times. Now the frame rate is somewhat reasonable. Switching clustering
21 // off by key 't' gets the GPU into considerable workload with resulting
22 // in a very poor frame rate.
24 // Remarks:
25 // - only tested on decsent NVidia GPUs
26 // - this example is a proof of concept
27 // - this example is not performance optimized
29 // Key bindings:
30 // Esc : quit example
31 // Space : toogle geometry simulation on/off
32 // 1 : only one light
33 // 2 : half number of lights
34 // 3 : double number of lights
35 // 4 : half number of geometry objects
36 // 5 : double number of geometry objects
37 // a : add directional test lights useful only if the view
38 // frustum is visualized
39 // b : show correct light geometry frustum
40 // c : cull lights on cpu. Only useful for testing
41 // e/E : speed up/down simulation
42 // h : toogle HDR stage usage on/off
43 // i/I : increase/decrease light intensity
44 // l : toogle light simulation on/off
45 // m : assign new color to geometry
46 // o/O : double/half simulation time interval
47 // p/P : increase/decrease light range
48 // r : reset the example
49 // s : toogle statistics on/off
50 // t : toogle usage of cluster shading on/off
51 // u : toggle spot direction line on/off
52 // U : toggle special spot direction cases
53 // v : toogle frustum visualization on/off
54 // x : recreate the lights with current spot dir case
57 #include <boost/functional/hash.hpp>
58 #include <boost/unordered_set.hpp>
59 #include <boost/foreach.hpp>
60 #include <boost/random.hpp>
61 #include <boost/tuple/tuple.hpp>
62 #include "boost/tuple/tuple_comparison.hpp"
63 #include <boost/multi_array.hpp>
65 #ifdef OSG_BUILD_ACTIVE
66 // Headers
67 #include <OSGGLUT.h>
68 #include <OSGConfig.h>
69 #include <OSGSimpleGeometry.h>
70 #include <OSGGLUTWindow.h>
71 #include <OSGSimpleSceneManager.h>
72 #include <OSGBaseFunctions.h>
73 #include <OSGTransform.h>
74 #include <OSGGroup.h>
76 // new headers:
77 #include <OSGGLEXT.h>
78 #include <OSGTime.h>
79 #include <OSGPlane.h>
80 #include <OSGMatrixCamera.h>
81 #include <OSGPerspectiveCamera.h>
82 #include <OSGOrthographicCamera.h>
83 #include <OSGHDR2Stage.h>
84 #include <OSGClusterShadingStage.h>
85 #include <OSGInverseTransform.h>
86 #include <OSGShaderProgramChunk.h>
87 #include <OSGShaderProgram.h>
88 #include <OSGShaderVariableOSG.h>
89 #include <OSGShaderProgramVariableChunk.h>
90 #include <OSGShaderProgramVariables.h>
91 #include <OSGShaderStorageBufferObjChunk.h>
92 #include <OSGShaderStorageBufferObjStdLayoutChunk.h>
93 #include <OSGUniformBufferObjChunk.h>
94 #include <OSGChunkMaterial.h>
95 #include <OSGMaterialGroup.h>
96 #include <OSGMaterialChunkOverrideGroup.h>
97 #include <OSGMatrixUtility.h>
98 #include <OSGMultiLightChunk.h>
99 #include <OSGMultiPropertyUBOChunk.h>
100 #include <OSGMultiPropertySSBOChunk.h>
101 #include <OSGPolygonChunk.h>
102 #include <OSGDepthChunk.h>
103 #include <OSGBlendChunk.h>
104 #include <OSGTextureObjChunk.h>
105 #include <OSGTextureEnvChunk.h>
106 #include <OSGTextureImageChunk.h>
107 #include <OSGTwoSidedLightingChunk.h>
108 #include <OSGAlgorithmComputeElement.h>
109 #include <OSGComputeShaderAlgorithm.h>
110 #include <OSGComputeShaderChunk.h>
111 #include <OSGGeoProperties.h>
112 #include <OSGSimpleLightGeometry.h>
113 #include <OSGSimpleCurve.h>
115 #else
116 // Headers
117 #include <OpenSG/OSGGLUT.h>
118 #include <OpenSG/OSGConfig.h>
119 #include <OpenSG/OSGSimpleGeometry.h>
120 #include <OpenSG/OSGGLUTWindow.h>
121 #include <OpenSG/OSGSimpleSceneManager.h>
122 #include <OpenSG/OSGBaseFunctions.h>
123 #include <OpenSG/OSGTransform.h>
124 #include <OpenSG/OSGGroup.h>
126 // new headers:
127 #include <OpenSG/OSGGLEXT.h>
128 #include <OpenSG/OSGTime.h>
129 #include <OpenSG/OSGPlane.h>
130 #include <OpenSG/OSGMatrixCamera.h>
131 #include <OpenSG/OSGPerspectiveCamera.h>
132 #include <OpenSG/OSGOrthographicCamera.h>
133 #include <OpenSG/OSGHDR2Stage.h>
134 #include <OpenSG/OSGClusterShadingStage.h>
135 #include <OpenSG/OSGInverseTransform.h>
136 #include <OpenSG/OSGShaderProgramChunk.h>
137 #include <OpenSG/OSGShaderProgram.h>
138 #include <OpenSG/OSGShaderVariableOSG.h>
139 #include <OpenSG/OSGShaderProgramVariableChunk.h>
140 #include <OpenSG/OSGShaderProgramVariables.h>
141 #include <OpenSG/OSGShaderStorageBufferObjChunk.h>
142 #include <OpenSG/OSGShaderStorageBufferObjStdLayoutChunk.h>
143 #include <OpenSG/OSGUniformBufferObjChunk.h>
144 #include <OpenSG/OSGChunkMaterial.h>
145 #include <OpenSG/OSGMaterialGroup.h>
146 #include <OpenSG/OSGMaterialChunkOverrideGroup.h>
147 #include <OpenSG/OSGMatrixUtility.h>
148 #include <OpenSG/OSGMultiLightChunk.h>
149 #include <OpenSG/OSGMultiPropertyUBOChunk.h>
150 #include <OpenSG/OSGMultiPropertySSBOChunk.h>
151 #include <OpenSG/OSGPolygonChunk.h>
152 #include <OpenSG/OSGDepthChunk.h>
153 #include <OpenSG/OSGBlendChunk.h>
154 #include <OpenSG/OSGTextureObjChunk.h>
155 #include <OpenSG/OSGTextureEnvChunk.h>
156 #include <OpenSG/OSGTextureImageChunk.h>
157 #include <OpenSG/OSGTwoSidedLightingChunk.h>
158 #include <OpenSG/OSGAlgorithmComputeElement.h>
159 #include <OpenSG/OSGComputeShaderAlgorithm.h>
160 #include <OpenSG/OSGComputeShaderChunk.h>
161 #include <OpenSG/OSGGeoProperties.h>
162 #include <OpenSG/OSGSimpleLightGeometry.h>
163 #include <OpenSG/OSGSimpleCurve.h>
164 #endif
166 // ============================================================================
168 // Part: Declaration of the example scene and some helpers:
169 // - constants that governs the example
170 // - random number generators
171 // - smooth cubic Bezier spline curve
173 // ============================================================================
175 const bool use_ortho_camera = false; // use a orthographic camera instead of the perspective camera
177 const OSG::Int32 init_num_geometries = 256; // the initial number of to be lit geometry
178 const OSG::Int32 max_num_geometries = 2048; // the maximal number of lit geometry
180 const OSG::Int32 num_grid_boxes = 100; // each light and geometry has a motion curve.
181 // Sample a number if different cube boxes from the scene and
182 // take randomly one point from each cube. That guarantees that
183 // the knot points do not clump and that they are all unequal.
184 const OSG::Int32 num_curve_knots = 40; // each motion curve has that number of knot points
186 const std::size_t num_materials = 5000; // material database has this number of entries
188 const OSG::Int32 init_num_lights = 128; // initial number if example lights
189 const OSG::Int32 max_num_lights = 2048; // maximal number of allowed lights
191 const OSG::Real32 max_light_power = 10.f; // light intensity is choosen randomly up to the maximal light power
193 const OSG::Real32 world_size = 10.f; // lights and geometry init positions are bounded in the world
194 const OSG::Real32 box_factor = 1.5f; // visualization box is drawn around the world
196 OSG::Real32 simulation_delta = 0.0001f; // determines the simulation speed (keys e/E)
197 OSG::Real32 elapse_time_limit = 10.f; // time in milliseconds after which a simulation step is performed (keys o/O)
201 const OSG::Real32 rangeFactor = 1.15f; // range multiplication factor (keys p/P)
202 const OSG::Real32 intensityFactor = 1.2f; // intensity multiplication factor (keys i/I)
204 const OSG::UInt32 block_size = 16; // number of compute shader threads per xy-direction
205 const OSG::UInt32 tile_size = 64; // number of pixel per cluster tile per xy-direction
206 const OSG::UInt32 num_cluster_z = 32; // number of clusters in the z direction
207 const OSG::Real32 near_plane_offset = 5.f; // clustering starts to (zNear + near_plane_offset)
209 const OSG::UInt32 light_index_list_size = 2097152; // Max number of light index list entries.
210 // If we have a screen size of 1920*1080 pixel and assume
211 // a 32 cluster in z-direction we have, with a tile size
212 // of 64 pixel, 30*17*32 = 16320 cluster. With 2^21 = 2097152
213 // light list entries we have on average space for around 64
214 // lights per cluster. The light list then occupy
215 // 2097152*4 bytes = 8388608 bytes of graphic memory.
217 const OSG::Vec3i work_group_size = OSG::Vec3i(block_size, block_size, 1);
218 // each compute shader work group has that thread layout
220 const OSG::UInt32 num_test_val_entries = 65536; // number of array elements in the TestData members.
221 // on default the test data is not transfered to the GPU
222 // and no test are performed. Test were used on example
223 // development and are leaved in for illustration purpose.
226 // Simulation parameters
228 OSG::TimeStamp time_stamp = 0; // time stamp is updated after each simulation step
229 OSG::Real32 simulation_param = 0.f; // value in range [0,1]. Used for motion curve evaluation
230 bool simulate_geometry = true; // motion of lit geometry
231 bool simulate_lights = true; // motion of shading lights
233 bool visualize_frustum = false;
235 OSG::SimpleSceneManagerRefPtr mgr; // the global scene manager
238 // The example makes use of many randomly choosen values for various parameters.
239 // Most parameters have specific ranges and types. Therefore the example provides
240 // special dices on uniform distributions over the ranges for the different parameters.
242 typedef boost::mt19937 RNGType;
243 RNGType rng(time(0));
245 boost::uniform_int<> box_dist(0, num_grid_boxes-1);
246 boost::variate_generator<RNGType, boost::uniform_int<> > box_idx_die(rng, box_dist);
248 boost::uniform_int<> die_dist(1, 6);
249 boost::variate_generator<RNGType, boost::uniform_int<> > classic_die(rng, die_dist);
251 boost::uniform_int<> geom_dist(0, 7);
252 boost::variate_generator<RNGType, boost::uniform_int<> > geom_idx_die(rng, geom_dist);
254 boost::uniform_01<float> unit_distribution;
255 boost::variate_generator< RNGType, boost::uniform_01<float> > unit_die(rng, unit_distribution);
257 boost::uniform_real<float> small_distribution(0.1f, 1.f);
258 boost::variate_generator< RNGType, boost::uniform_real<float> > small_die(rng, small_distribution);
260 boost::uniform_real<float> spot_distribution(5.f, 90.f);
261 boost::variate_generator< RNGType, boost::uniform_real<float> > spot_die(rng, spot_distribution);
263 boost::uniform_real<float> light_range_distribution(0.2f, 0.7f);
264 boost::variate_generator< RNGType, boost::uniform_real<float> > light_range_die(rng, light_range_distribution);
266 boost::uniform_real<float> light_ellipsis_roundness_distribution1(0.2f, 1.0f);
267 boost::variate_generator< RNGType, boost::uniform_real<float> > light_ellipsis_roundness_die1(rng, light_ellipsis_roundness_distribution1);
269 boost::uniform_real<float> light_ellipsis_roundness_distribution2(1.0f, 2.0f);
270 boost::variate_generator< RNGType, boost::uniform_real<float> > light_ellipsis_roundness_die2(rng, light_ellipsis_roundness_distribution2);
272 boost::uniform_real<float> light_ellipsis_roundness_distribution3(2.0f, 51.0f);
273 boost::variate_generator< RNGType, boost::uniform_real<float> > light_ellipsis_roundness_die3(rng, light_ellipsis_roundness_distribution3);
275 boost::uniform_real<float> light_ellipsis_twist_distribution(0.f, 360.0f);
276 boost::variate_generator< RNGType, boost::uniform_real<float> > light_ellipsis_twist_die(rng, light_ellipsis_twist_distribution);
278 boost::uniform_real<float> light_ellipsis_radius_distribution(0.1f, 2.0f);
279 boost::variate_generator< RNGType, boost::uniform_real<float> > light_ellipsis_radius_die(rng, light_ellipsis_radius_distribution);
281 boost::uniform_real<float> light_ellipsis_radius_ratio_distribution(1.01f, 1.5f);
282 boost::variate_generator< RNGType, boost::uniform_real<float> > light_ellipsis_radius_ratio_die(rng, light_ellipsis_radius_ratio_distribution);
284 std::vector<OSG::Pnt3f> dice_knots(bool close_curve);
286 OSG::Vec3f dice_unit_vector()
288 OSG::Vec3f v;
290 while (v.length() < OSG::Eps)
291 v.setValues(
292 -1.f + 2.f * unit_die(),
293 -1.f + 2.f * unit_die(),
294 -1.f + 2.f * unit_die());
296 v.normalize();
298 return v;
301 // ============================================================================
303 // Part: Declaration/Implementation of
304 // - struct Light and type VecLightsT,
305 // - struct Material and type VecMaterialsT,
306 // - struct GeomState
307 // and corresponding initialization routines.
309 // ============================================================================
312 // simple light data structure
314 struct Light : public OSG::MultiLight
316 explicit Light(Type e);
317 ~Light();
319 static Light create_light(Type e, OSG::Int32 test_dir_light_type = -1);
321 void create_light_geometry(OSG::UInt32 material_idx);
323 OSG::TransformRefPtr transform; // the beacons transform core
324 OSG::SmoothCubicBezierSpline curve; // the path that the light will follow
326 static bool cpu_cull_lights;
327 static bool cpu_calc_frustums;
328 static bool add_dir_test_lights;
329 static bool correct_light_geometry;
330 static bool use_light_index_list;
331 static bool show_spot_dir_line;
332 static int force_spot_dir;
333 static OSG::Vec3f dir_test_case_6;
334 static OSG::Vec3f dir_test_case_7;
335 static OSG::Vec3f dir_test_case_8;
338 bool Light::cpu_cull_lights = false;
339 bool Light::cpu_calc_frustums = false;
340 bool Light::add_dir_test_lights = false;
341 bool Light::correct_light_geometry = false;
342 bool Light::use_light_index_list = true;
343 bool Light::show_spot_dir_line = false;
344 int Light::force_spot_dir = 0;
345 OSG::Vec3f Light::dir_test_case_6 = OSG::Vec3f(0,0,-1);
346 OSG::Vec3f Light::dir_test_case_7 = OSG::Vec3f(0,0,-1);
347 OSG::Vec3f Light::dir_test_case_8 = OSG::Vec3f(0,0,-1);
349 typedef std::vector<Light> VecLightsT; // multiple lights
350 VecLightsT lights; // the lights of the scene
352 Light::Light(Type e)
353 : MultiLight(e)
354 , transform(NULL)
355 , curve(dice_knots(true))
358 Light::~Light()
360 beacon = NULL;
361 transform = NULL;
365 // Simple material data structure
367 struct Material
369 Material()
370 : ambient (0.f, 0.f, 0.f)
371 , diffuse (0.f, 0.f, 0.f)
372 , specular(0.f, 0.f, 0.f)
373 , emissive(0.f, 0.f, 0.f)
374 , opacity(1.f)
375 , shininess(100.f)
378 OSG::Color3f ambient;
379 OSG::Color3f diffuse;
380 OSG::Color3f specular;
381 OSG::Color3f emissive;
383 OSG::Real32 opacity;
384 OSG::Real32 shininess;
386 static OSG::UInt32 ambient_id;
387 static OSG::UInt32 diffuse_id;
388 static OSG::UInt32 specular_id;
389 static OSG::UInt32 emissive_id;
390 static OSG::UInt32 opacity_id;
391 static OSG::UInt32 shininess_id;
394 OSG::UInt32 Material:: ambient_id = 0;
395 OSG::UInt32 Material:: diffuse_id = 0;
396 OSG::UInt32 Material:: specular_id = 0;
397 OSG::UInt32 Material:: emissive_id = 0;
398 OSG::UInt32 Material:: opacity_id = 0;
399 OSG::UInt32 Material::shininess_id = 0;
401 typedef std::vector<Material> VecMaterialsT; // multiple materials
403 VecMaterialsT initialize_materials(std::size_t num) // helper to create materials
405 OSG_ASSERT(num > max_num_lights + 1);
407 VecMaterialsT mat(num);
409 for (std::size_t i = max_num_lights+1; i < num; ++i)
411 mat[i].ambient = OSG::Color3f(0.001f, 0.001f, 0.001f);
412 mat[i].diffuse.setRandom();
413 mat[i].specular = OSG::Color3f(0.9f, 0.9f, 0.9f);
414 mat[i].emissive = OSG::Color3f(0.0f, 0.0f, 0.0f);
415 mat[i].opacity = 1.f;
416 mat[i].shininess = 320.f * small_die();
418 //int r = classic_die();
419 //if (r <= 3)
420 // mat[i].opacity = small_die();
424 // special grey material for box
426 mat[0].ambient = OSG::Color3f(0.001f, 0.001f, 0.001f);
427 mat[0].diffuse = OSG::Color3f(0.7f, 0.7f, 0.7f);
428 mat[0].specular = OSG::Color3f(0.9f, 0.9f, 0.9f);
429 mat[0].emissive = OSG::Color3f(0.0f, 0.0f, 0.0f);
430 mat[0].opacity = 1.f;
431 mat[0].shininess = 100.f;
433 return mat;
436 VecMaterialsT materials = initialize_materials(num_materials); // the material database
439 // we reserve the first max_num_lights + 1 materials for the light simulation and
440 // the grey box.
442 boost::uniform_int<OSG::UInt32> material_dist(max_num_lights+1, num_materials-1);
443 boost::variate_generator<RNGType, boost::uniform_int<OSG::UInt32> > material_idx_die(rng, material_dist);
446 // Simple geometry state data structure
448 struct GeomState
450 GeomState()
451 : material_index(0)
454 OSG::UInt32 material_index;
456 static OSG::UInt32 material_index_id;
459 OSG::UInt32 GeomState::material_index_id = 0;
461 // ============================================================================
463 // Part: Creation and update of the light state
465 // ============================================================================
467 OSG::MultiLightChunkTransitPtr create_light_state(const VecLightsT& vLights)
469 OSG::MultiLightChunkRefPtr lightChunk = OSG::MultiLightChunk::create();
471 lightChunk->setUsage(GL_DYNAMIC_DRAW);
472 lightChunk->setLayoutType(OSG::MultiLight::SIMPLE_LAYOUT | OSG::MultiLight::CINEMA_LAYOUT);
474 lightChunk->setHasEyeToLightSpaceMatrix(true); // provide a struct entry for the transform from view space to light space
475 lightChunk->setHasCosSpotlightAngle (true); // provide a struct entry for the cosine of the spot light angle (defaults to true)
476 lightChunk->setHasSpotlightAngle (true); // provide a struct entry for the spot light angle itself (defaults to false)
478 //lightChunk->setEyeSpace(true);
480 BOOST_FOREACH(const Light& light, vLights)
482 lightChunk->addLight(light);
485 return OSG::MultiLightChunkTransitPtr(lightChunk);
488 void update_light_state(OSG::MultiLightChunk* lightChunk, const VecLightsT& vLights)
490 if (lightChunk)
492 if (lightChunk->numLights() != vLights.size())
494 lightChunk->clearLights();
496 BOOST_FOREACH(const Light& light, vLights)
498 lightChunk->addLight(light);
501 else
503 for (OSG::UInt32 idx = 0; idx < vLights.size(); ++idx)
505 const Light& light = vLights[idx];
506 lightChunk->updateLight(idx, light);
512 // ============================================================================
514 // Part: Some routines for handling of the memory buffer and the the
515 // creation on the MultiPropertySSBOChunk objects:
517 // i) create_material_database_state,
518 // update_material_database_state
520 // ii) create_geometry_material_state,
521 // update_geometry_material_state
523 // ============================================================================
526 // i) the material shader storage buffer object
528 OSG::MultiPropertySSBOChunkTransitPtr create_material_database_state(const VecMaterialsT& vMaterials)
530 OSG::MultiPropertySSBOChunkRefPtr materialChunk = OSG::MultiPropertySSBOChunk::create();
532 OSG::UInt32 vec3_id, float_id;
534 vec3_id = materialChunk->addMember(OSG::MultiPropertySSBOChunk:: VEC3_T, 4);
535 float_id = materialChunk->addMember(OSG::MultiPropertySSBOChunk::FLOAT_T, 2);
537 materialChunk->setUsage(GL_STATIC_DRAW);
539 Material:: ambient_id = vec3_id++;
540 Material:: diffuse_id = vec3_id++;
541 Material:: specular_id = vec3_id++;
542 Material:: emissive_id = vec3_id;
544 Material:: opacity_id = float_id++;
545 Material::shininess_id = float_id;
547 BOOST_FOREACH(const Material& mat, vMaterials)
549 OSG::UInt32 idx = materialChunk->addProperty();
551 materialChunk->setVec3Property (idx, Material:: ambient_id, mat.ambient);
552 materialChunk->setVec3Property (idx, Material:: diffuse_id, mat.diffuse);
553 materialChunk->setVec3Property (idx, Material:: specular_id, mat.specular);
554 materialChunk->setVec3Property (idx, Material:: emissive_id, mat.emissive);
556 materialChunk->setFloatProperty(idx, Material:: opacity_id, mat.opacity);
557 materialChunk->setFloatProperty(idx, Material::shininess_id, mat.shininess);
560 return OSG::MultiPropertySSBOChunkTransitPtr(materialChunk);
563 void update_material_database_state(OSG::MultiPropertySSBOChunk* materialChunk, const VecMaterialsT& vMaterials)
565 if (materialChunk)
567 if (materialChunk->getNumProperties() != vMaterials.size())
569 materialChunk->clearProperties();
571 BOOST_FOREACH(const Material& mat, vMaterials)
573 OSG::UInt32 idx = materialChunk->addProperty();
575 materialChunk->setVec3Property (idx, Material:: ambient_id, mat.ambient);
576 materialChunk->setVec3Property (idx, Material:: diffuse_id, mat.diffuse);
577 materialChunk->setVec3Property (idx, Material:: specular_id, mat.specular);
578 materialChunk->setVec3Property (idx, Material:: emissive_id, mat.emissive);
580 materialChunk->setFloatProperty(idx, Material:: opacity_id, mat.opacity);
581 materialChunk->setFloatProperty(idx, Material::shininess_id, mat.shininess);
584 else
586 for (OSG::UInt32 idx = 0; idx < vMaterials.size(); ++idx)
588 const Material& mat = vMaterials[idx];
590 materialChunk->setVec3Property (idx, Material:: ambient_id, mat.ambient);
591 materialChunk->setVec3Property (idx, Material:: diffuse_id, mat.diffuse);
592 materialChunk->setVec3Property (idx, Material:: specular_id, mat.specular);
593 materialChunk->setVec3Property (idx, Material:: emissive_id, mat.emissive);
595 materialChunk->setFloatProperty(idx, Material:: opacity_id, mat.opacity);
596 materialChunk->setFloatProperty(idx, Material::shininess_id, mat.shininess);
603 // ii) the geomertry shader storage buffer object
605 OSG::MultiPropertyUBOChunkTransitPtr create_geometry_material_state(const GeomState& geomState)
607 OSG::MultiPropertyUBOChunkRefPtr geomStateChunk = OSG::MultiPropertyUBOChunk::create();
609 GeomState::material_index_id = geomStateChunk->addMember(OSG::MultiPropertyUBOChunk::UINT_T, 1);
610 geomStateChunk->setUsage(GL_DYNAMIC_DRAW);
612 OSG::UInt32 idx = geomStateChunk->addProperty();
613 geomStateChunk->setUIntProperty(idx, GeomState::material_index_id, geomState.material_index);
615 return OSG::MultiPropertyUBOChunkTransitPtr(geomStateChunk);
618 void update_geometry_material_state(OSG::MultiPropertyUBOChunk* geomStateChunk, const GeomState& geomState)
620 if (geomStateChunk)
622 if (geomStateChunk->getNumProperties() != 1)
624 geomStateChunk->clearProperties();
626 OSG::UInt32 idx = geomStateChunk->addProperty();
627 geomStateChunk->setUIntProperty(idx, GeomState::material_index_id, geomState.material_index);
629 else
631 geomStateChunk->setUIntProperty( 0, GeomState::material_index_id, geomState.material_index);
636 // ============================================================================
638 // Part: The application finally starts here
640 // ============================================================================
642 // UBO block binding points
643 const OSG::UInt32 geom_binding_point = 0;
645 // SSBO block binding points
646 const OSG::UInt32 material_binding_point = 0;
649 // shader programs.
651 std::string get_vp_program();
652 std::string get_fp_program();
654 OSG::ShaderProgramRefPtr frag_shader = NULL;
657 // The scene
659 OSG::NodeRefPtr scene_node = NULL;
662 // Cluster visualisation root node
664 OSG::NodeRefPtr cluster_geometry_root_node = NULL;
667 // The ClusterShadingStage
669 OSG::ClusterShadingStageRefPtr cluster_shading_stage = NULL;
670 OSG::NodeRefPtr cluster_shading_node = NULL;
673 // A HDR stage
675 OSG::HDR2StageRefPtr hdr_stage = NULL;
676 OSG::NodeRefPtr hdr_node = NULL;
679 // The material database for all visible geometry: objects, lights, stage box
681 OSG::MultiPropertySSBOChunkRefPtr ssbo_material_database = NULL;
684 // The mulit light chunk
686 OSG::MultiLightChunkRefPtr multi_light_chunk = NULL;
689 // The shader program variable chunk for the geom state
691 OSG::ShaderProgramVariableChunkRefPtr shader_var_chunk = NULL;
694 // Shader Storage buffer objects corresponding to transient shader blocks
696 std::vector<OSG::MultiPropertyUBOChunkRefPtr> ubo_geom_states;
699 // A separate transformation for each object and a spline for the trajectory
701 std::vector<OSG::NodeRefPtr> geom_nodes;
702 std::vector<OSG::TransformRefPtr> geom_trafos;
703 std::vector<OSG::SmoothCubicBezierSpline> geom_curves;
706 // Simulate some movement in the scene
708 void update_simulation()
711 // Simulation code: If enough time has passed perform a simulation step.
714 if (time_stamp == 0) time_stamp = OSG::getTimeStamp();
716 OSG::Time elapsed = OSG::getTimeStampMsecs(OSG::getTimeStamp() - time_stamp);
718 if (elapsed > elapse_time_limit)
720 OSG::Matrix matSimulation;
722 simulation_param += simulation_delta;
723 if (simulation_param >= 1.f)
724 simulation_param = 0.f;
726 if (simulate_geometry)
728 std::size_t numCurves = geom_curves.size();
730 OSG_ASSERT(numCurves == geom_trafos.size());
732 for (std::size_t i = 0; i < numCurves; ++i)
734 matSimulation = geom_curves[i].getFrame(simulation_param);
735 geom_trafos[i]->setMatrix(matSimulation);
739 if (simulate_lights)
741 BOOST_FOREACH(Light& light, lights)
743 matSimulation = light.curve.getFrame(simulation_param, true);
744 light.transform->setMatrix(matSimulation);
749 time_stamp = OSG::getTimeStamp();
754 // Cluster shading stage ...
756 void setup_cluster_shading_stage()
758 if (cluster_shading_stage)
761 // The multi light chunk must be known by the cluster shading stage
763 cluster_shading_stage->setMultiLightChunk(multi_light_chunk);
766 // Some values that determine the computational efficiency
768 cluster_shading_stage->setMaxLightIndexListSize (light_index_list_size);
769 cluster_shading_stage->setMaxClusterLightCount (1024);
770 cluster_shading_stage->setBlockSize (block_size);
771 cluster_shading_stage->setTileSize (tile_size);
772 cluster_shading_stage->setNumClusterZ (num_cluster_z);
773 cluster_shading_stage->setNearPlaneOffset (near_plane_offset);
776 // UBO fragment/compute shader binding points
778 cluster_shading_stage->setDispatchDataBindingPnt(1);
779 cluster_shading_stage->setClusterDataBindingPnt (2);
782 // SSBO fragment/compute shader binding points
784 cluster_shading_stage->setLightBindingPnt (1);
785 cluster_shading_stage->setAffectedLightIndexListBindingPnt (2);
786 cluster_shading_stage->setFrustumBindingPnt (3);
787 cluster_shading_stage->setLightIndexListBindingPnt (4);
788 cluster_shading_stage->setLightIndexCounterBindingPnt (5);
791 // Texture image fragment shader binding point
793 cluster_shading_stage->setLightGridBindingPnt(0);
796 // Misc. flags
798 cluster_shading_stage->setCalcFrustumsOnCPU ( Light::cpu_calc_frustums);
799 cluster_shading_stage->setCullLighsOnCPU ( Light::cpu_cull_lights);
800 cluster_shading_stage->setDisabled (!Light::use_light_index_list);
804 void removeClusterShadingStage()
806 OSG::GroupRefPtr group = OSG::Group::create();
807 cluster_shading_node->setCore(group);
809 cluster_shading_stage = NULL;
812 void createClusterShadingStage()
814 if (!cluster_shading_stage)
816 cluster_shading_stage = OSG::ClusterShadingStage::create();
817 setup_cluster_shading_stage();
820 if (cluster_shading_node)
821 cluster_shading_node->setCore(cluster_shading_stage);
825 // HDR stage ...
827 void setup_hdr_stage()
829 if (hdr_stage)
831 hdr_stage->setApplyGamma (true);
832 hdr_stage->setAccurateGamma (true);
834 hdr_stage->setAdjustLuminance (false);
836 hdr_stage->setPerformBloom (false);
837 hdr_stage->setBloomBackground (false);
839 hdr_stage->setForceBackground (true);
840 hdr_stage->setUse_ITU_R_BT_709 (true);
841 hdr_stage->setMipmapLevel (-1);
843 hdr_stage->setTarget (OSG::HDR2Stage::COMPOSITE_TEXTURE);
844 hdr_stage->setCarryDepth (true);
846 hdr_stage->setColorBufferInternalFormat (GL_RGBA16F);
847 hdr_stage->setColorBufferPixelFormat (GL_RGBA);
848 hdr_stage->setColorBufferType (GL_FLOAT);
850 hdr_stage->setDepthBufferInternalFormat (GL_DEPTH24_STENCIL8);
851 hdr_stage->setDepthBufferPixelFormat (GL_DEPTH_STENCIL);
852 hdr_stage->setDepthBufferType (GL_UNSIGNED_INT_24_8);
854 hdr_stage->setLumBufferInternalFormat (GL_R32F);
855 hdr_stage->setLumBufferPixelFormat (GL_RED);
856 hdr_stage->setLumBufferType (GL_FLOAT);
858 hdr_stage->setImageBufferInternalFormat (GL_RGB16F);
859 hdr_stage->setImageBufferPixelFormat (GL_RGB);
860 hdr_stage->setImageBufferType (GL_FLOAT);
862 hdr_stage->setNumSamples (0);
864 hdr_stage->setBloomThreshold (2.0f);
865 hdr_stage->setBloomMagnitude (0.0f);
866 hdr_stage->setToneMappingMode (OSG::HDR2Stage::REINHARD_TONE_MAPPING);
867 hdr_stage->setExposure (0.0f);
868 hdr_stage->setKeyValue (0.18f);
869 hdr_stage->setAutoExposureMode (OSG::HDR2Stage::MANUAL);
870 hdr_stage->setWhiteLevel (5.0f);
871 hdr_stage->setFilmicShoulderStrenght (0.15f);
872 hdr_stage->setFilmicLinearStrength (0.5f);
873 hdr_stage->setFilmicLinearAngle (0.1f);
874 hdr_stage->setFilmicToeStrength (0.2f);
875 hdr_stage->setFilmicToeNumerator (0.02f);
876 hdr_stage->setFilmicToeDenominator (0.3f);
877 hdr_stage->setFilmicLinearWhite (11.2f);
878 hdr_stage->setSaturation (1.0f);
879 hdr_stage->setDragoBias (0.85f);
880 hdr_stage->setTau (1.25f);
881 hdr_stage->setNumTaps (4);
882 hdr_stage->setBlurGaussSigma (0.8f);
883 hdr_stage->setUseLinChromCorrection (true);
887 void removeHDRStage()
889 OSG::GroupRefPtr group = OSG::Group::create();
890 hdr_node->setCore(group);
892 hdr_stage = NULL;
895 void createHDRStage()
897 if (!hdr_stage)
899 hdr_stage = OSG::HDR2Stage::create();
900 setup_hdr_stage();
903 if (hdr_node)
904 hdr_node->setCore(hdr_stage);
908 // Lights...
910 void deinitialize_lights()
912 BOOST_FOREACH(const Light& light, lights)
914 scene_node->subChild(light.beacon);
917 lights.clear();
920 void initialize_lights(OSG::UInt32 num) // helper to create lights
922 deinitialize_lights();
924 for (OSG::UInt32 i = 0; i < num; ++i)
927 int n = classic_die();
928 Light::Type type;
930 switch (n)
932 case 1:
933 case 2:
934 type = OSG::MultiLight::POINT_LIGHT;
935 break;
936 case 3:
937 case 4:
938 type = OSG::MultiLight::SPOT_LIGHT;
939 break;
940 case 5:
941 case 6:
942 type = OSG::MultiLight::CINEMA_LIGHT;
943 break;
946 lights.push_back(Light::create_light(type));
948 lights[i].create_light_geometry(i+1);
950 scene_node->addChild(lights[i].beacon);
953 if (Light::add_dir_test_lights)
955 lights.push_back(Light::create_light(OSG::MultiLight::DIRECTIONAL_LIGHT, 0));
956 lights.push_back(Light::create_light(OSG::MultiLight::DIRECTIONAL_LIGHT, 1));
960 void change_spot_dir_lights()
962 for (std::size_t i = 0; i < lights.size(); ++i)
964 Light& light = lights[i];
966 switch (Light::force_spot_dir)
968 case 0: light.direction = dice_unit_vector(); break;
969 case 1: light.direction = OSG::Vec3f(0, 0,-1); break;
970 case 2: light.direction = OSG::Vec3f(1, 0, 0); break;
971 case 3: light.direction = OSG::Vec3f(0,-1, 0); break;
972 case 4: light.direction = OSG::Vec3f(1, 0,-1); break;
973 case 5: light.direction = OSG::Vec3f(1,-1,-1); break;
974 case 6:
976 static bool increase_flag = true;
978 light.direction = Light::dir_test_case_6;
979 light.direction.normalize();
981 OSG::Vec3f e1(1,0,-1);
982 OSG::Vec3f e2(0,0,-1);
984 if (Light::dir_test_case_6.equals(e1, OSG::Eps))
985 increase_flag = false;
986 if (Light::dir_test_case_6.equals(e2, OSG::Eps))
987 increase_flag = true;
989 if (increase_flag)
990 Light::dir_test_case_6 += OSG::Vec3f(0.1f, 0.f, 0.f);
991 else
992 Light::dir_test_case_6 -= OSG::Vec3f(0.1f, 0.f, 0.f);
994 break;
995 case 7:
997 static bool increase_flag = true;
999 light.direction = Light::dir_test_case_7;
1000 light.direction.normalize();
1002 OSG::Vec3f e1(1,-1,-1);
1003 OSG::Vec3f e2(0,0,-1);
1005 if (Light::dir_test_case_7.equals(e1, OSG::Eps))
1006 increase_flag = false;
1007 if (Light::dir_test_case_7.equals(e2, OSG::Eps))
1008 increase_flag = true;
1010 if (increase_flag)
1011 Light::dir_test_case_7 += OSG::Vec3f(0.1f, -0.1f, 0.f);
1012 else
1013 Light::dir_test_case_7 -= OSG::Vec3f(0.1f, -0.1f, 0.f);
1015 break;
1017 case 8:
1019 static bool increase_flag = true;
1021 light.direction = Light::dir_test_case_8;
1022 light.direction.normalize();
1024 OSG::Vec3f e1(0,-1, 0);
1025 OSG::Vec3f e2(0, 0,-1);
1027 if (Light::dir_test_case_8.equals(e1, OSG::Eps))
1028 increase_flag = false;
1029 if (Light::dir_test_case_8.equals(e2, OSG::Eps))
1030 increase_flag = true;
1032 if (increase_flag)
1033 Light::dir_test_case_8 += OSG::Vec3f(0.f, -0.1f, 0.1f);
1034 else
1035 Light::dir_test_case_8 -= OSG::Vec3f(0.f, -0.1f, 0.1f);
1037 break;
1039 case 9:
1042 break;
1045 lights[i].create_light_geometry(OSG::UInt32(i+1));
1049 Light Light::create_light(
1050 Type e, // type of the light
1051 OSG::Int32 test_dir_light_type) // for special testing directional lights
1053 Light l(e);
1055 l.beacon = OSG::makeCoredNode<OSG::Transform>(&l.transform);
1056 l.transform->setMatrix(OSG::Matrix::identity());
1058 OSG::Real32 L = box_factor * world_size;
1060 switch (Light::force_spot_dir)
1062 case 0: l.direction = dice_unit_vector(); break;
1063 case 1: l.direction = OSG::Vec3f(0, 0,-1); break;
1064 case 2: l.direction = OSG::Vec3f(1, 0, 0); break;
1065 case 3: l.direction = OSG::Vec3f(0,-1, 0); break;
1066 case 4: l.direction = OSG::Vec3f(1, 0,-1); break;
1067 case 5: l.direction = OSG::Vec3f(1,-1,-1); break;
1068 case 6: l.direction = OSG::Vec3f(0, 0,-1); break;
1069 case 7: l.direction = OSG::Vec3f(0, 0,-1); break;
1070 case 8: l.direction = OSG::Vec3f(0, 0,-1); break;
1071 case 9: break;
1074 Light::dir_test_case_6 = OSG::Vec3f(0,0,-1);
1075 Light::dir_test_case_7 = OSG::Vec3f(0,0,-1);
1076 Light::dir_test_case_8 = OSG::Vec3f(0,0,-1);
1078 l.color.setRandom();
1079 l.intensity = max_light_power * small_die();
1080 l.rangeCutOff = L * light_range_die();
1082 switch (e)
1084 case OSG::MultiLight::POINT_LIGHT:
1087 break;
1089 case OSG::MultiLight::DIRECTIONAL_LIGHT:
1091 if (Light::add_dir_test_lights)
1093 if (test_dir_light_type == 0)
1094 l.direction = OSG::Vec3f(0,0,-1);
1095 if (test_dir_light_type == 1)
1096 l.direction = OSG::Vec3f(0,0,1);
1098 l.intensity = 0.1f;
1101 break;
1103 case OSG::MultiLight::SPOT_LIGHT:
1105 l.spotlightAngle = spot_die();
1107 break;
1109 case OSG::MultiLight::CINEMA_LIGHT:
1111 l.innerSuperEllipsesWidth = light_ellipsis_radius_die();
1112 l.innerSuperEllipsesHeight = light_ellipsis_radius_die();
1114 float f = light_ellipsis_radius_ratio_die();
1116 l.outerSuperEllipsesWidth = f * l.innerSuperEllipsesWidth;
1117 l.outerSuperEllipsesHeight = f * l.innerSuperEllipsesHeight;
1119 int n = classic_die();
1120 switch (n)
1122 case 1:
1123 case 2:
1124 l.superEllipsesRoundness = light_ellipsis_roundness_die1();
1125 break;
1126 case 3:
1127 case 4:
1128 l.superEllipsesRoundness = light_ellipsis_roundness_die2();
1129 break;
1130 case 5:
1131 case 6:
1132 l.superEllipsesRoundness = light_ellipsis_roundness_die3();
1133 break;
1136 l.superEllipsesTwist = light_ellipsis_twist_die();
1138 //std::cout << "d = (" << l.direction.x() << ", " << l.direction.y() << ", " << l.direction.z() << ")" << std::endl;
1139 //std::cout << "a = " << l.innerSuperEllipsesWidth << std::endl;
1140 //std::cout << "b = " << l.innerSuperEllipsesHeight << std::endl;
1141 //std::cout << "A = " << l.outerSuperEllipsesWidth << std::endl;
1142 //std::cout << "B = " << l.outerSuperEllipsesHeight << std::endl;
1143 //std::cout << "r = " << l.superEllipsesRoundness << std::endl;
1144 //std::cout << "w = " << l.superEllipsesTwist << std::endl;
1146 break;
1148 default:
1149 break;
1152 return l;
1155 void Light::create_light_geometry(OSG::UInt32 material_idx)
1157 if (!beacon) return;
1159 beacon->clearChildren();
1161 Material mat;
1162 mat.emissive = color;
1163 mat.opacity = 0.7f;
1165 materials[material_idx] = mat;
1167 OSG::ChunkMaterialRefPtr geomState = OSG::ChunkMaterial::create();
1169 OSG::Real32 R = rangeCutOff;
1171 if (!correct_light_geometry)
1172 R = 0.5;
1174 switch (type)
1176 case OSG::MultiLight::POINT_LIGHT:
1178 OSG::GeometryRefPtr geometry = OSG::makeSphereGeo(3, R);
1179 OSG::NodeRefPtr node = OSG::makeNodeFor(geometry);
1181 GeomState geom; geom.material_index = material_idx; // material index used for light animiation
1182 OSG::MultiPropertyUBOChunkRefPtr uboGeomState = create_geometry_material_state(geom);
1183 geomState->addChunk(uboGeomState, geom_binding_point); // buffer binding point
1184 geomState->addChunk(shader_var_chunk); // block binding point
1186 geometry->setMaterial(geomState);
1188 beacon->addChild(node);
1191 // Test: Add mini sphere at the origin of the point light sphere
1194 // OSG::GeometryRefPtr geometry = OSG::makeSphereGeo(6, 0.1);
1195 // OSG::NodeRefPtr node = OSG::makeNodeFor(geometry);
1197 // GeomState geom; geom.material_index = material_idx; // material index used for light animiation
1198 // OSG::MultiPropertyUBOChunkRefPtr uboGeomState = create_geometry_material_state(geom);
1199 // geomState->addChunk(uboGeomState, geom_binding_point); // buffer binding point
1200 // geomState->addChunk(shader_var_chunk); // block binding point
1202 // geometry->setMaterial(geomState);
1204 // beacon->addChild(node);
1207 break;
1209 case OSG::MultiLight::DIRECTIONAL_LIGHT:
1212 break;
1214 case OSG::MultiLight::SPOT_LIGHT:
1216 GeomState geom; geom.material_index = material_idx; // material index used for light animiation
1217 OSG::MultiPropertyUBOChunkRefPtr uboGeomState = create_geometry_material_state(geom);
1218 geomState->addChunk(uboGeomState, geom_binding_point); // buffer binding point
1219 geomState->addChunk(shader_var_chunk); // block binding point
1221 OSG::Real32 h = R;
1223 OSG::GeometryRefPtr geometry = OSG::makeSpotGeo(h, OSG::osgDegree2Rad(spotlightAngle), 24, 24);
1224 geometry->setMaterial(geomState);
1226 OSG::TransformRefPtr coneTrans = OSG::Transform::create();
1228 OSG::Matrix rotMat;
1229 OSG::MatrixRotateTowards(rotMat, OSG::Vec3f(0.f, 1.f, 0.f), direction);
1230 coneTrans->setMatrix(rotMat);
1232 OSG::NodeRefPtr coneTransNode = OSG::makeNodeFor(coneTrans);
1233 OSG::NodeRefPtr coneNode = OSG::makeNodeFor(geometry);
1235 beacon->addChild(coneTransNode);
1236 coneTransNode->addChild(coneNode);
1239 // Create a help line to visualize the spot hit point on the wall
1241 if (Light::show_spot_dir_line)
1243 OSG::GeometryRefPtr line_geometry = OSG::makeCylinderGeo(30, 0.1f, 24, true, true, true );
1244 line_geometry->setMaterial(geomState);
1246 OSG::TransformRefPtr line_translation = OSG::Transform::create();
1247 OSG::Matrix matLineTrans;
1248 matLineTrans.setTranslate(OSG::Vec3f(0,-15,0));
1249 line_translation->setMatrix(matLineTrans);
1251 OSG::TransformRefPtr line_rotation = OSG::Transform::create();
1252 OSG::Matrix matLineRot;
1253 matLineRot.setRotate(OSG::Quaternion(OSG::Vec3f(1,0,0), OSG::Pi));
1254 line_rotation->setMatrix(matLineRot);
1256 OSG::NodeRefPtr lineRotationNode = OSG::makeNodeFor(line_rotation);
1257 OSG::NodeRefPtr lineTranslationNode = OSG::makeNodeFor(line_translation);
1258 OSG::NodeRefPtr lineGeometryNode = OSG::makeNodeFor(line_geometry);
1259 coneTransNode ->addChild(lineRotationNode);
1260 lineRotationNode ->addChild(lineTranslationNode);
1261 lineTranslationNode->addChild(lineGeometryNode);
1264 break;
1266 case OSG::MultiLight::CINEMA_LIGHT:
1268 GeomState geom; geom.material_index = material_idx; // material index used for light animiation
1269 OSG::MultiPropertyUBOChunkRefPtr uboGeomState = create_geometry_material_state(geom);
1270 geomState->addChunk(uboGeomState, geom_binding_point); // buffer binding point
1271 geomState->addChunk(shader_var_chunk); // block binding point
1273 OSG::Real32 h = R;
1275 OSG::GeometryRefPtr geometry = OSG::makeCinemaGeo(
1276 outerSuperEllipsesWidth,
1277 outerSuperEllipsesHeight,
1278 superEllipsesRoundness,
1279 OSG::osgDegree2Rad(superEllipsesTwist),
1280 h, 48, 48);
1281 geometry->setMaterial(geomState);
1283 OSG::Matrix matLSFromWS;
1285 OSG::Matrix matLightPos;
1286 matLightPos.setTranslate(position);
1288 OSG::Matrix matLightDir;
1289 OSG::Quaternion rotLightDir(OSG::Vec3f(0.f, 0.f, 1.f), -direction);
1290 matLightDir.setRotate(rotLightDir);
1292 matLSFromWS.mult (matLightPos);
1293 matLSFromWS.mult (matLightDir);
1295 OSG::Matrix matRot;
1296 matRot.setRotate(OSG::Quaternion(OSG::Vec3f(1,0,0), -0.5*OSG::Pi));
1298 matLSFromWS.mult(matRot);
1300 OSG::TransformRefPtr coneTrans = OSG::Transform::create();
1301 coneTrans->setMatrix(matLSFromWS);
1303 OSG::NodeRefPtr coneTransNode = OSG::makeNodeFor(coneTrans);
1304 OSG::NodeRefPtr coneNode = OSG::makeNodeFor(geometry);
1306 beacon->addChild(coneTransNode);
1307 coneTransNode->addChild(coneNode);
1310 // Create a help line to visualize the spot hit point on the wall
1312 if (Light::show_spot_dir_line)
1314 OSG::GeometryRefPtr line_geometry = OSG::makeCylinderGeo(30, 0.1f, 24, true, true, true );
1315 line_geometry->setMaterial(geomState);
1317 OSG::TransformRefPtr line_translation = OSG::Transform::create();
1318 OSG::Matrix matLineTrans;
1319 matLineTrans.setTranslate(OSG::Vec3f(0,-15,0));
1320 line_translation->setMatrix(matLineTrans);
1322 OSG::TransformRefPtr line_rotation = OSG::Transform::create();
1323 OSG::Matrix matLineRot;
1324 matLineRot.setRotate(OSG::Quaternion(OSG::Vec3f(1,0,0), OSG::Pi));
1325 line_rotation->setMatrix(matLineRot);
1327 OSG::NodeRefPtr lineRotationNode = OSG::makeNodeFor(line_rotation);
1328 OSG::NodeRefPtr lineTranslationNode = OSG::makeNodeFor(line_translation);
1329 OSG::NodeRefPtr lineGeometryNode = OSG::makeNodeFor(line_geometry);
1330 coneTransNode ->addChild(lineRotationNode);
1331 lineRotationNode ->addChild(lineTranslationNode);
1332 lineTranslationNode->addChild(lineGeometryNode);
1335 break;
1337 default:
1338 break;
1341 OSG::PolygonChunkRefPtr polygonChunk = OSG::PolygonChunk::create();
1342 polygonChunk->setFrontMode(GL_SMOOTH);
1343 polygonChunk->setBackMode(GL_SMOOTH);
1344 polygonChunk->setOffsetFactor(1.f);
1345 polygonChunk->setOffsetBias(1.f);
1346 polygonChunk->setOffsetFill(true);
1348 if (mat.opacity < 1.f)
1350 polygonChunk->setCullFace(GL_BACK);
1352 OSG::BlendChunkRefPtr blendChunk = OSG::BlendChunk::create();
1353 blendChunk->setSrcFactor (GL_SRC_ALPHA);
1354 blendChunk->setDestFactor(GL_ONE_MINUS_SRC_ALPHA);
1355 geomState->addChunk(blendChunk);
1356 geomState->setTransparencyMode(OSG::Material::TransparencyForceTransparent);
1358 OSG::TwoSidedLightingChunkRefPtr twoSidedLightingChunk = OSG::TwoSidedLightingChunk::create();
1359 geomState->addChunk(twoSidedLightingChunk);
1361 } else {
1362 polygonChunk->setCullFace(GL_BACK);
1363 geomState->setTransparencyMode(OSG::Material::TransparencyForceOpaque);
1366 geomState->addChunk(polygonChunk);
1369 OSG::NodeTransitPtr createBox()
1371 OSG::NodeRefPtr boxRoot = OSG::makeCoredNode<OSG::Group>();
1373 OSG::Real32 L = box_factor * world_size;
1374 OSG::GeometryRefPtr boxPlane = OSG::makePlaneGeo(2.f*L, 2.f*L, 128, 128);
1376 OSG::NodeRefPtr boxBottom = OSG::makeNodeFor(boxPlane);
1377 OSG::NodeRefPtr boxLeft = OSG::makeNodeFor(boxPlane);
1378 OSG::NodeRefPtr boxRight = OSG::makeNodeFor(boxPlane);
1379 OSG::NodeRefPtr boxFar = OSG::makeNodeFor(boxPlane);
1381 OSG::TransformRefPtr boxBottomTrans = OSG::Transform::create();
1382 OSG::TransformRefPtr boxLeftTrans = OSG::Transform::create();
1383 OSG::TransformRefPtr boxRightTrans = OSG::Transform::create();
1384 OSG::TransformRefPtr boxFarTrans = OSG::Transform::create();
1386 OSG::Matrix matBottom, matLeft, matRight, matFar;
1388 matBottom.setTransform(OSG::Vec3f(0.f, -L, 0.f), OSG::Quaternion( OSG::Vec3f(1, 0, 0), OSG::osgDegree2Rad(270.f)));
1389 matLeft .setTransform(OSG::Vec3f( -L, 0.f, 0.f), OSG::Quaternion( OSG::Vec3f(0, 1, 0), OSG::osgDegree2Rad(90.f)));
1390 matRight .setTransform(OSG::Vec3f( L, 0.f, 0.f), OSG::Quaternion( OSG::Vec3f(0, 1, 0), OSG::osgDegree2Rad(270.f)));
1391 matFar .setTransform(OSG::Vec3f(0.f, 0.f, -L), OSG::Quaternion( OSG::Vec3f(0, 0, 1), OSG::osgDegree2Rad( 0.f)));
1393 boxBottomTrans ->setMatrix(matBottom);
1394 boxLeftTrans ->setMatrix(matLeft);
1395 boxRightTrans ->setMatrix(matRight);
1396 boxFarTrans ->setMatrix(matFar);
1398 OSG::NodeRefPtr boxBottomTransNode = OSG::makeNodeFor(boxBottomTrans);
1399 OSG::NodeRefPtr boxLeftTransNode = OSG::makeNodeFor(boxLeftTrans);
1400 OSG::NodeRefPtr boxRightTransNode = OSG::makeNodeFor(boxRightTrans);
1401 OSG::NodeRefPtr boxFarTransNode = OSG::makeNodeFor(boxFarTrans);
1403 boxBottomTransNode ->addChild(boxBottom);
1404 boxLeftTransNode ->addChild(boxLeft);
1405 boxRightTransNode ->addChild(boxRight);
1406 boxFarTransNode ->addChild(boxFar);
1408 boxRoot->addChild(boxBottomTransNode);
1409 boxRoot->addChild(boxLeftTransNode);
1410 boxRoot->addChild(boxRightTransNode);
1411 boxRoot->addChild(boxFarTransNode);
1413 GeomState geom; geom.material_index = 0; // grey box material index
1414 OSG::ChunkMaterialRefPtr geomState = OSG::ChunkMaterial::create();
1415 OSG::MultiPropertyUBOChunkRefPtr uboGeomState = create_geometry_material_state(geom);
1416 geomState->addChunk(uboGeomState, geom_binding_point); // buffer binding point
1417 geomState->addChunk(shader_var_chunk); // block binding point
1419 OSG::PolygonChunkRefPtr polygonChunk = OSG::PolygonChunk::create();
1420 polygonChunk->setFrontMode(GL_SMOOTH);
1421 polygonChunk->setBackMode(GL_SMOOTH);
1422 polygonChunk->setOffsetFactor(1.f);
1423 polygonChunk->setOffsetBias(1.f);
1424 polygonChunk->setOffsetFill(true);
1425 polygonChunk->setCullFace(GL_NONE);
1426 geomState->addChunk(polygonChunk);
1428 geomState->setTransparencyMode(OSG::Material::TransparencyForceOpaque);
1430 OSG::TwoSidedLightingChunkRefPtr twoSidedLightingChunk = OSG::TwoSidedLightingChunk::create();
1431 geomState->addChunk(twoSidedLightingChunk);
1433 boxPlane->setMaterial(geomState);
1435 return OSG::NodeTransitPtr(boxRoot);
1438 OSG::NodeTransitPtr createGeometry()
1440 int idx = geom_idx_die();
1442 OSG::GeometryRefPtr geometry;
1444 switch (idx)
1446 case 0: // cone
1447 geometry = OSG::makeConeGeo(3.f * small_die(), 1.f * small_die(), 24, true, true);
1448 break;
1449 case 1: // box
1450 geometry = OSG::makeBoxGeo(3.f * small_die(), 3.f * small_die(), 3.f * small_die(), 1, 1, 1);
1451 break;
1452 case 2: // cylinder
1453 geometry = OSG::makeCylinderGeo(3.f * small_die(), .3f, 24, true, true, true );
1454 break;
1455 case 3: // sphere
1456 geometry = OSG::makeSphereGeo(6, 3.f * small_die());
1457 break;
1458 case 4: // torus
1459 geometry = OSG::makeTorusGeo(0.6f * small_die(), 2.f * small_die(), 24, 36);
1460 break;
1461 case 5: // ellipsoide
1462 geometry = OSG::makeLatLongEllipsoidGeo(24, 36, 2.f * small_die(), 1.f * small_die());
1463 break;
1464 case 6: // frustum
1465 geometry = OSG::makeConicalFrustumGeo(2.f * small_die(), 2.f * small_die(), 2.f * small_die(), 6, true, true, true);
1466 break;
1467 case 7: // teapot
1468 geometry = OSG::makeTeapotGeo(24, 1.f * small_die());
1469 break;
1472 OSG::NodeRefPtr geomNode = OSG::makeNodeFor(geometry);
1474 OSG::TransformRefPtr trafoCore = OSG::Transform::create();
1475 OSG::NodeRefPtr transNode = OSG::makeNodeFor(trafoCore);
1476 transNode->addChild(geomNode);
1478 GeomState geom; geom.material_index = material_idx_die();
1479 OSG::ChunkMaterialRefPtr geomState = OSG::ChunkMaterial::create();
1480 OSG::MultiPropertyUBOChunkRefPtr uboGeomState = create_geometry_material_state(geom);
1481 geomState->addChunk(uboGeomState, geom_binding_point); // buffer binding point
1482 geomState->addChunk(shader_var_chunk); // block binding point
1484 OSG::PolygonChunkRefPtr polygonChunk = OSG::PolygonChunk::create();
1485 polygonChunk->setFrontMode(GL_SMOOTH);
1486 polygonChunk->setBackMode(GL_SMOOTH);
1487 polygonChunk->setOffsetFactor(1.f);
1488 polygonChunk->setOffsetBias(1.f);
1489 polygonChunk->setOffsetFill(true);
1491 OSG::Real32 opacity = materials[geom.material_index].opacity;
1492 if (opacity < 1.f)
1494 polygonChunk->setCullFace(GL_BACK);
1496 OSG::BlendChunkRefPtr blendChunk = OSG::BlendChunk::create();
1497 blendChunk->setSrcFactor (GL_SRC_ALPHA);
1498 blendChunk->setDestFactor(GL_ONE_MINUS_SRC_ALPHA);
1499 geomState->addChunk(blendChunk);
1500 geomState->setTransparencyMode(OSG::Material::TransparencyForceTransparent);
1502 OSG::TwoSidedLightingChunkRefPtr twoSidedLightingChunk = OSG::TwoSidedLightingChunk::create();
1503 geomState->addChunk(twoSidedLightingChunk);
1505 } else {
1506 polygonChunk->setCullFace(GL_BACK);
1507 geomState->setTransparencyMode(OSG::Material::TransparencyForceOpaque);
1510 geomState->addChunk(polygonChunk);
1512 geometry->setMaterial(geomState);
1514 geom_nodes.push_back(transNode);
1515 geom_trafos.push_back(trafoCore);
1516 ubo_geom_states.push_back(uboGeomState);
1518 geom_curves.push_back(OSG::SmoothCubicBezierSpline(dice_knots(true)));
1520 return OSG::NodeTransitPtr(transNode);
1524 // forward declaration so we can have the interesting stuff upfront
1526 int setupGLUT (int *argc, char *argv[]);
1527 void print_state();
1528 void print_help();
1529 void releaseGLUT();
1532 // Initialize GLUT & OpenSG and set up the scene
1534 int main(int argc, char **argv)
1536 // OSG init
1537 OSG::osgInit(argc,argv);
1539 // GLUT init
1540 int winid = setupGLUT(&argc, argv);
1542 print_help();
1544 // open a new scope, because the pointers below should go out of scope
1545 // before entering glutMainLoop.
1546 // Otherwise OpenSG will complain about objects being alive after shutdown.
1548 // the connection between GLUT and OpenSG
1549 OSG::GLUTWindowRefPtr gwin = OSG::GLUTWindow::create();
1550 gwin->setGlutId(winid);
1551 gwin->init();
1553 // create the SimpleSceneManager helper
1554 mgr = OSG::SimpleSceneManager::create();
1555 mgr->setWindow(gwin);
1558 // Because we animate the lights by simple geometry, the lights initialization must be happens
1559 // after the creation of the 'shader_var_chunk' and after the creation of the scene node that
1560 // actually contains the geometry. Additionally, it must happens before we call 'create_light_state',
1561 // since here we do need the already defined lights.
1564 cluster_shading_node = OSG::makeCoredNode<OSG::Group>();
1565 hdr_node = OSG::makeCoredNode<OSG::Group>();
1568 // The block binding is added to each ChunkMaterial in order to provide the state
1569 // shader uniform block for the geometery shown in the scene
1571 shader_var_chunk = OSG::ShaderProgramVariableChunk::create();
1572 shader_var_chunk->addUniformBlock("GeomState", geom_binding_point);
1575 // The scene does contain all visible rendering. It will be append to the hdr node.
1577 scene_node = OSG::makeCoredNode<OSG::Group>();
1579 initialize_lights(init_num_lights);
1582 // create shader storage buffer objects and corresponding materials
1584 ssbo_material_database = create_material_database_state(materials);
1585 multi_light_chunk = create_light_state(lights);
1587 hdr_node ->addChild(cluster_shading_node);
1588 cluster_shading_node->addChild(scene_node);
1591 // The scene graph
1593 mgr->setRoot(hdr_node);
1595 if (use_ortho_camera)
1597 OSG::OrthographicCameraRefPtr orthoCamera = OSG::OrthographicCamera::create();
1598 mgr->setCamera(orthoCamera);
1601 createHDRStage();
1602 createClusterShadingStage();
1605 // create the shader program
1607 OSG::ShaderProgramChunkRefPtr progChunk = OSG::ShaderProgramChunk::create();
1608 OSG::ShaderProgramRefPtr vertShader = OSG::ShaderProgram::createVertexShader();
1609 frag_shader = OSG::ShaderProgram::createFragmentShader();
1611 vertShader->setProgram(get_vp_program());
1612 frag_shader->setProgram(get_fp_program());
1614 frag_shader->addOSGVariable("OSGViewMatrix");
1617 // binding the shader storage block to a buffer binding point can be performed
1618 // either by calling the shaders's addShaderStorageBlock method or by
1619 // adding a 'buffer block' variable to a ShaderProgramVariableChunk.
1620 // In the following we use both variants for illustration.
1622 frag_shader->addShaderStorageBlock("Materials",
1623 material_binding_point);
1625 progChunk->addShader( vertShader);
1626 progChunk->addShader(frag_shader);
1628 OSG::PolygonChunkRefPtr polygonChunk = OSG::PolygonChunk::create();
1629 polygonChunk->setFrontMode(GL_FILL);
1630 polygonChunk->setBackMode(GL_FILL);
1631 polygonChunk->setCullFace(GL_BACK);
1633 OSG::DepthChunkRefPtr depthChunk = OSG::DepthChunk::create();
1634 depthChunk->setEnable(true);
1636 OSG::ChunkMaterialRefPtr progState = OSG::ChunkMaterial::create();
1637 progState->addChunk(ssbo_material_database, material_binding_point);
1639 progState->addChunk(progChunk);
1640 progState->addChunk(polygonChunk);
1641 progState->addChunk(depthChunk);
1643 scene_node->addChild(createBox());
1645 cluster_geometry_root_node = OSG::makeCoredNode<OSG::Group>();
1646 scene_node->addChild(cluster_geometry_root_node);
1648 for (OSG::Int32 i = 0; i < init_num_geometries; ++i)
1649 scene_node->addChild(createGeometry());
1651 OSG::MaterialChunkOverrideGroupRefPtr mgrp = OSG::MaterialChunkOverrideGroup::create();
1652 mgrp->setMaterial(progState);
1653 scene_node->setCore(mgrp);
1655 OSG::commitChanges();
1657 print_state();
1659 // show the whole scene
1660 mgr->showAll();
1663 // GLUT main loop
1664 glutMainLoop();
1666 return 0;
1670 // GLUT callback functions
1674 // redraw the window
1676 void display(void)
1678 if (!mgr) return;
1681 // Simulation code
1683 update_simulation();
1685 OSG::commitChanges();
1687 mgr->redraw();
1691 // react to size changes
1693 void reshape(int w, int h)
1695 mgr->resize(w, h);
1697 glutPostRedisplay();
1701 // react to mouse button presses
1703 void mouse(int button, int state, int x, int y)
1705 if (state)
1706 mgr->mouseButtonRelease(button, x, y);
1707 else
1708 mgr->mouseButtonPress(button, x, y);
1710 glutPostRedisplay();
1714 // react to mouse motions with pressed buttons
1716 void motion(int x, int y)
1718 mgr->mouseMove(x, y);
1719 glutPostRedisplay();
1723 // react to keys
1725 void keyboard(unsigned char k, int x, int y)
1727 switch(k)
1729 case 27: // ESC
1731 // clean up global variables
1732 mgr = NULL;
1734 frag_shader = NULL;
1736 scene_node = NULL;
1737 cluster_geometry_root_node = NULL;
1739 cluster_shading_stage = NULL;
1740 cluster_shading_node = NULL;
1742 hdr_stage = NULL;
1743 hdr_node = NULL;
1745 ssbo_material_database = NULL;
1747 multi_light_chunk = NULL;
1748 shader_var_chunk = NULL;
1750 geom_nodes.clear();
1751 geom_trafos.clear();
1752 geom_curves.clear();
1754 ubo_geom_states.clear();
1756 materials.clear();
1757 lights.clear();
1759 releaseGLUT();
1761 OSG::osgExit();
1762 exit(0);
1764 break;
1766 case 32: // Space
1768 simulate_geometry = !simulate_geometry;
1769 std::cout << "simulate_geometry = " << simulate_geometry << std::endl;
1771 break;
1773 case '1':
1775 initialize_lights(1);
1776 update_light_state(multi_light_chunk, lights);
1777 update_material_database_state(ssbo_material_database, materials);
1778 glutPostRedisplay();
1780 break;
1782 case '2':
1784 if (lights.size() > 1)
1786 OSG::UInt32 num = static_cast<OSG::UInt32>(lights.size() / 2);
1787 initialize_lights(num);
1788 update_light_state(multi_light_chunk, lights);
1789 update_material_database_state(ssbo_material_database, materials);
1791 std::cout << "number if lights = " << num << std::endl;
1793 glutPostRedisplay();
1795 else
1797 std::cout << "minimal number if lights reached!" << std::endl;
1800 break;
1802 case '3':
1804 if (lights.size() <= max_num_lights)
1806 OSG::UInt32 num = static_cast<OSG::UInt32>(lights.size() * 2);
1807 initialize_lights(num);
1808 update_light_state(multi_light_chunk, lights);
1809 update_material_database_state(ssbo_material_database, materials);
1811 std::cout << "number if lights = " << num << std::endl;
1813 glutPostRedisplay();
1815 else
1817 std::cout << "maximal number if lights reached!" << std::endl;
1821 break;
1823 case '4':
1825 if (geom_nodes.size() > 1)
1827 OSG::UInt32 num = static_cast<OSG::UInt32>(geom_nodes.size() / 2);
1829 BOOST_FOREACH(OSG::Node* node, geom_nodes)
1830 scene_node->subChild(node);
1832 geom_nodes.clear();
1833 geom_trafos.clear();
1834 geom_curves.clear();
1835 ubo_geom_states.clear();
1837 for (OSG::UInt32 i = 0; i < num; ++i)
1838 scene_node->addChild(createGeometry());
1840 std::cout << "number if geometries = " << num << std::endl;
1842 glutPostRedisplay();
1844 else
1846 std::cout << "minimal number if geometries reached!" << std::endl;
1849 break;
1851 case '5':
1853 if (geom_nodes.size() <= max_num_geometries)
1855 OSG::UInt32 num = static_cast<OSG::UInt32>(geom_nodes.size() * 2);
1857 BOOST_FOREACH(OSG::Node* node, geom_nodes)
1858 scene_node->subChild(node);
1860 geom_nodes.clear();
1861 geom_trafos.clear();
1862 geom_curves.clear();
1863 ubo_geom_states.clear();
1865 for (OSG::UInt32 i = 0; i < num; ++i)
1866 scene_node->addChild(createGeometry());
1868 std::cout << "number if geometries = " << num << std::endl;
1870 glutPostRedisplay();
1872 else
1874 std::cout << "maximal number if geometries reached!" << std::endl;
1877 break;
1879 case 'a':
1881 Light::add_dir_test_lights = !Light::add_dir_test_lights;
1882 std::cout << "Light::add_dir_test_lights = " << Light::add_dir_test_lights << std::endl;
1884 initialize_lights(1);
1885 update_light_state(multi_light_chunk, lights);
1886 update_material_database_state(ssbo_material_database, materials);
1887 glutPostRedisplay();
1889 break;
1891 case 'b':
1893 Light::correct_light_geometry = !Light::correct_light_geometry;
1894 std::cout << "Light::correct_light_geometry = " << Light::correct_light_geometry << std::endl;
1896 for (std::size_t i = 0; i < lights.size(); ++i)
1898 Light& light = lights[i];
1899 light.create_light_geometry(OSG::UInt32(i+1));
1902 glutPostRedisplay();
1904 break;
1906 case 'c':
1908 Light::cpu_cull_lights = !Light::cpu_cull_lights;
1909 std::cout << "Light::cpu_cull_lights = " << Light::cpu_cull_lights << std::endl;
1911 cluster_shading_stage->setCullLighsOnCPU(Light::cpu_cull_lights);
1913 if (Light::cpu_cull_lights && !Light::cpu_calc_frustums)
1915 Light::cpu_calc_frustums = true;
1916 std::cout << "Light::cpu_calc_frustums = " << Light::cpu_calc_frustums << std::endl;
1917 cluster_shading_stage->setCalcFrustumsOnCPU(Light::cpu_calc_frustums);
1919 glutPostRedisplay();
1921 break;
1923 case 'C':
1925 Light::cpu_calc_frustums = !Light::cpu_calc_frustums;
1926 std::cout << "Light::cpu_calc_frustums = " << Light::cpu_calc_frustums << std::endl;
1928 cluster_shading_stage->setCalcFrustumsOnCPU(Light::cpu_calc_frustums);
1930 if (Light::cpu_cull_lights && !Light::cpu_calc_frustums)
1932 Light::cpu_cull_lights = false;
1933 std::cout << "Light::cpu_cull_lights = " << Light::cpu_cull_lights << std::endl;
1934 cluster_shading_stage->setCullLighsOnCPU(Light::cpu_cull_lights);
1936 glutPostRedisplay();
1938 break;
1940 case 'e':
1942 simulation_delta *= 2.f;
1944 break;
1946 case 'E':
1948 simulation_delta /= 2.f;
1950 break;
1952 case 'h':
1954 OSG::HDR2Stage* core = dynamic_cast<OSG::HDR2Stage*>(hdr_node->getCore());
1955 if (core)
1957 removeHDRStage();
1959 std::cout << "HDR is off" << std::endl;
1961 else
1963 createHDRStage();
1965 std::cout << "HDR is on" << std::endl;
1968 glutPostRedisplay();
1970 break;
1972 case 'i':
1974 BOOST_FOREACH(Light& light, lights)
1975 light.intensity *= 1.2f;
1977 update_light_state(multi_light_chunk, lights);
1978 glutPostRedisplay();
1980 break;
1982 case 'I':
1984 BOOST_FOREACH(Light& light, lights)
1985 if (light.rangeCutOff / intensityFactor >= OSG::Eps)
1986 light.intensity /= intensityFactor;
1988 update_light_state(multi_light_chunk, lights);
1989 glutPostRedisplay();
1991 break;
1993 case 'l':
1995 simulate_lights = !simulate_lights;
1996 std::cout << "simulate_lights = " << simulate_lights << std::endl;
1998 break;
2000 case 'm':
2002 BOOST_FOREACH(OSG::MultiPropertyUBOChunk* uboGeomState, ubo_geom_states)
2004 GeomState geom; geom.material_index = material_idx_die();
2005 update_geometry_material_state(uboGeomState, geom);
2008 glutPostRedisplay();
2010 break;
2012 case 'o':
2014 elapse_time_limit *= 2.f;
2016 break;
2018 case 'O':
2020 elapse_time_limit /= 2.f;
2022 break;
2024 case 'p':
2026 for (std::size_t i = 0; i < lights.size(); ++i)
2028 Light& light = lights[i];
2030 light.rangeCutOff *= rangeFactor;
2031 light.create_light_geometry(OSG::UInt32(i+1));
2034 update_light_state(multi_light_chunk, lights);
2035 glutPostRedisplay();
2037 break;
2039 case 'P':
2041 for (std::size_t i = 0; i < lights.size(); ++i)
2043 Light& light = lights[i];
2045 if (light.rangeCutOff / rangeFactor >= OSG::Eps)
2047 light.rangeCutOff /= rangeFactor;
2048 light.create_light_geometry(OSG::UInt32(i+1));
2052 update_light_state(multi_light_chunk, lights);
2053 glutPostRedisplay();
2055 break;
2057 case 'r':
2059 initialize_lights(init_num_lights);
2060 update_light_state(multi_light_chunk, lights);
2061 update_material_database_state(ssbo_material_database, materials);
2063 simulation_delta = 0.0001f;
2064 elapse_time_limit = 10.f;
2066 simulate_geometry = true;
2067 simulate_lights = true;
2069 std::cout << "example resetted" << std::endl;
2071 glutPostRedisplay();
2073 break;
2075 case 's':
2077 mgr->setStatistics(!mgr->getStatistics());
2079 break;
2081 case 't':
2083 Light::use_light_index_list = !Light::use_light_index_list;
2084 std::cout << "Light::use_light_index_list = " << Light::use_light_index_list << std::endl;
2085 cluster_shading_stage->setDisabled(!Light::use_light_index_list);
2086 glutPostRedisplay();
2088 break;
2090 case 'u':
2092 Light::show_spot_dir_line = !Light::show_spot_dir_line;
2093 std::cout << "Light::show_spot_dir_line = " << Light::show_spot_dir_line << std::endl;
2095 for (std::size_t i = 0; i < lights.size(); ++i)
2097 Light& light = lights[i];
2098 light.create_light_geometry(OSG::UInt32(i+1));
2101 glutPostRedisplay();
2103 break;
2105 case 'U':
2107 Light::force_spot_dir += 1;
2108 if (Light::force_spot_dir > 9)
2109 Light::force_spot_dir = 0;
2111 std::cout << "Light::force_spot_dir = ";
2113 switch (Light::force_spot_dir)
2115 case 0: std::cout << "dice"; break;
2116 case 1: std::cout << "(0, 0,-1)"; break;
2117 case 2: std::cout << "(1, 0, 0)"; break;
2118 case 3: std::cout << "(0,-1, 0)"; break;
2119 case 4: std::cout << "(1, 0,-1)"; break;
2120 case 5: std::cout << "(1,-1,-1)"; break;
2121 case 6: std::cout << "from (0,0,-1) to (1,0,-1)"; break;
2122 case 7: std::cout << "from (0,0,-1) to (1,-1,-1)"; break;
2123 case 8: std::cout << "from (0,0,-1) to (0,-1, 0)"; break;
2124 case 9: std::cout << "recreate"; break;
2127 std::cout << std::endl;
2129 break;
2131 case 'x':
2133 change_spot_dir_lights();
2134 update_light_state(multi_light_chunk, lights);
2135 update_material_database_state(ssbo_material_database, materials);
2136 glutPostRedisplay();
2138 break;
2144 // setup the GLUT library which handles the windows for us
2146 int setupGLUT(int *argc, char *argv[])
2148 glutInit(argc, argv);
2149 glutInitDisplayMode(GLUT_RGB | GLUT_DEPTH | GLUT_DOUBLE);
2150 glutInitWindowSize(1000, 800);
2152 int winid = glutCreateWindow("OpenSG");
2154 glutReshapeFunc(reshape);
2155 glutDisplayFunc(display);
2156 glutMouseFunc(mouse);
2157 glutMotionFunc(motion);
2158 glutKeyboardFunc(keyboard);
2160 // call the redraw function whenever there's nothing else to do
2161 glutIdleFunc(display);
2163 return winid;
2166 void releaseGLUT()
2168 glutReshapeFunc(NULL);
2169 glutMouseFunc(NULL);
2170 glutMotionFunc(NULL);
2171 glutKeyboardFunc(NULL);
2172 glutIdleFunc(NULL);
2175 void print_state()
2177 std::cout << "simulate_geometry = " << simulate_geometry << std::endl;
2178 std::cout << "simulate_lights = " << simulate_lights << std::endl;
2179 std::cout << "number if lights = " << lights.size() << std::endl;
2180 std::cout << "number if geometries = " << geom_nodes.size() << std::endl;
2181 std::cout << "Light::use_light_index_list = " << Light::use_light_index_list << std::endl;
2182 std::cout << "Light::add_dir_test_lights = " << Light::add_dir_test_lights << std::endl;
2183 std::cout << "Light::correct_light_geometry = " << Light::correct_light_geometry << std::endl;
2184 std::cout << "Light::show_spot_dir_line = " << Light::show_spot_dir_line << std::endl;
2185 std::cout << "Light::cpu_cull_lights = " << Light::cpu_cull_lights << std::endl;
2186 std::cout << "Light::cpu_calc_frustums = " << Light::cpu_calc_frustums << std::endl;
2187 std::cout << "HDR is " << (dynamic_cast<OSG::HDR2Stage*>(hdr_node->getCore()) != NULL ? "on" : "off") << std::endl;
2188 std::cout << "visualize_frustum = " << visualize_frustum << std::endl;
2191 void print_help()
2193 std::cout << "Esc : quit example" << std::endl;
2194 std::cout << "Space : toogle geometry simulation on/off" << std::endl;
2195 std::cout << "1 : only one light" << std::endl;
2196 std::cout << "2 : half number of lights" << std::endl;
2197 std::cout << "3 : double number of lights" << std::endl;
2198 std::cout << "4 : half number of geometry objects" << std::endl;
2199 std::cout << "5 : double number of geometry objects" << std::endl;
2200 std::cout << "a : add directional test lights" << std::endl;
2201 std::cout << "b : show correct light geometry" << std::endl;
2202 std::cout << "c : cull lights on cpu" << std::endl;
2203 std::cout << "C : calc frustums on cpu" << std::endl;
2204 std::cout << "e/E : speed up/down simulation" << std::endl;
2205 std::cout << "h : toogle HDR stage usage on/off" << std::endl;
2206 std::cout << "i/I : increase/decrease light intensity" << std::endl;
2207 std::cout << "l : toogle light simulation on/off" << std::endl;
2208 std::cout << "m : assign new color to geometry" << std::endl;
2209 std::cout << "o/O : double/half simulation time interval" << std::endl;
2210 std::cout << "p/P : increase/decrease light range" << std::endl;
2211 std::cout << "r : reset the example" << std::endl;
2212 std::cout << "s : toogle statistics on/off" << std::endl;
2213 std::cout << "t : toogle usage of cluster shading on/off" << std::endl;
2214 std::cout << "u : toggle spot direction line on/off" << std::endl;
2215 std::cout << "U : toggle special spot direction cases" << std::endl;
2216 std::cout << "x : recreate the lights with current spot dir case" << std::endl;
2219 // ============================================================================
2221 // Part: dice_knots helper implementation
2223 // ============================================================================
2225 typedef boost::tuples::tuple<int, int, int> index_t;
2227 struct index_hash_t : public std::unary_function<index_t, std::size_t>
2229 std::size_t operator()(const index_t& v) const
2231 std::size_t seed = 0;
2232 boost::hash_combine(seed, v.get<0>());
2233 boost::hash_combine(seed, v.get<1>());
2234 boost::hash_combine(seed, v.get<2>());
2235 return seed;
2239 std::vector<OSG::Pnt3f> dice_knots(bool close_curve)
2242 // idea: sample a number if different cube boxes from the scene and
2243 // take randomly one point from each cube. That guarantees that
2244 // the knot points do not clump and that they are all unequal.
2246 namespace tp = boost::tuples;
2248 boost::unordered_set<index_t, index_hash_t> indices;
2250 while (indices.size() < num_curve_knots)
2252 indices.insert(tp::make_tuple(box_idx_die(), box_idx_die(), box_idx_die()));
2255 OSG::Real32 l = 2 * world_size / num_grid_boxes;
2257 std::vector<OSG::Pnt3f> knots;
2259 BOOST_FOREACH(const index_t& idx, indices)
2261 OSG::Pnt3f p;
2262 p[0] = -world_size + idx.get<0>() * l + unit_die() * l;
2263 p[1] = -world_size + idx.get<1>() * l + unit_die() * l;
2264 p[2] = -world_size + idx.get<2>() * l + unit_die() * l;
2266 knots.push_back(p);
2269 if (close_curve)
2270 knots.push_back(knots.front());
2272 return knots;
2275 // ============================================================================
2277 // Part: The shader programs
2279 // ============================================================================
2282 // vertex shader program.
2284 std::string get_vp_program()
2286 using namespace std;
2288 stringstream ost;
2290 ost << "#version 440 compatibility"
2291 << endl << ""
2292 << endl << "#extension GL_ARB_shader_storage_buffer_object: enable"
2293 << endl << ""
2294 << endl << "smooth out vec3 vNormalES; // eye space normal"
2295 << endl << "smooth out vec3 vPositionES; // eye space position"
2296 << endl << ""
2297 << endl << "void main()"
2298 << endl << "{"
2299 << endl << " //"
2300 << endl << " // multiply the object space vertex position with the modelview matrix "
2301 << endl << " // to get the eye space vertex position"
2302 << endl << " //"
2303 << endl << " vPositionES = (gl_ModelViewMatrix * gl_Vertex).xyz;"
2304 << endl << ""
2305 << endl << " //"
2306 << endl << " // multiply the object space normal with the normal matrix (transpose of the inverse "
2307 << endl << " // model view matrix) to get the eye space normal"
2308 << endl << " //"
2309 << endl << " vNormalES = gl_NormalMatrix * gl_Normal;"
2310 << endl << ""
2311 << endl << " //"
2312 << endl << " // multiply the combiend modelview projection matrix with the object space vertex"
2313 << endl << " // position to get the clip space position"
2314 << endl << " //"
2315 << endl << " gl_Position = ftransform();"
2316 << endl << "}"
2317 << endl << ""
2318 << endl;
2320 return ost.str();
2324 // fragment shader program for bump mapping in surface local coordinates
2326 std::string get_fp_program()
2328 using namespace std;
2330 stringstream ost;
2333 << "#version 440 compatibility"
2334 << endl << ""
2335 << endl << "#extension GL_ARB_shader_storage_buffer_object: enable"
2336 << endl << "#extension GL_ARB_shader_image_load_store: enable"
2337 << endl << ""
2338 << endl << "smooth in vec3 vNormalES; // eye space normal"
2339 << endl << "smooth in vec3 vPositionES; // eye space position"
2340 << endl << ""
2341 << endl << "const int num_materials = " << num_materials << ";"
2342 << endl << ""
2343 << endl << "uniform mat4 OSGViewMatrix; // from world space to view space transformation"
2344 << endl << ""
2345 << cluster_shading_stage->getFragmentProgramSnippet()
2346 << endl << ""
2347 << endl << "struct Material"
2348 << endl << "{"
2349 << endl << " vec3 ambient;"
2350 << endl << " vec3 diffuse;"
2351 << endl << " vec3 specular;"
2352 << endl << " vec3 emissive;"
2353 << endl << ""
2354 << endl << " float opacity;"
2355 << endl << " float shininess;"
2356 << endl << "};"
2357 << endl << ""
2358 << endl << "layout (std430) buffer Materials"
2359 << endl << "{"
2360 << endl << " Material material[num_materials];"
2361 << endl << "} materials;"
2362 << endl << ""
2363 << endl << ""
2364 << endl << "layout (std140) uniform GeomState"
2365 << endl << "{"
2366 << endl << " uint material_index;"
2367 << endl << "} geom_state;"
2368 << endl << ""
2369 << endl << "const vec3 cCameraPositionES = vec3(0,0,0); // eye is at vec3(0,0,0) in eye space!"
2370 << endl << ""
2371 << endl << "layout(location = 0) out vec4 vFragColor;"
2372 << endl << ""
2373 << endl << "//"
2374 << endl << "// Calculate the attenuation of the light based on the light "
2375 << endl << "// range r and the distance d of the light to the current point."
2376 << endl << "//"
2377 << endl << "float calcAttenuation("
2378 << endl << " in const float r,"
2379 << endl << " in const float d)"
2380 << endl << "{"
2381 << endl << " //"
2382 << endl << " // Perform smooth Hermite interpolation between 0 and 1, when e0<x<e1"
2383 << endl << " // float t = clamp((x-e0)/(e1-e0),0.0,1.0);"
2384 << endl << " // smoothstep(e0,e1,x) = t*t*(3-2*t);"
2385 << endl << " //"
2386 << endl << " return 1.0 - smoothstep(0.75 * r, r, d);"
2387 << endl << "}"
2388 << endl << ""
2389 << endl << "//"
2390 << endl << "// Calculate the attenuation with respect to the spot light cone."
2391 << endl << "// Parameters:"
2392 << endl << "// minCosSpotAngle: the cosine of the spot light angle"
2393 << endl << "// l : normalized direction between fragment and light position"
2394 << endl << "// s : normalized light direction"
2395 << endl << "//"
2396 << endl << "float spotAttenuation("
2397 << endl << " in const float minCosSpotAngle,"
2398 << endl << " in const vec3 l,"
2399 << endl << " in const vec3 s)"
2400 << endl << "{"
2401 << endl << " //"
2402 << endl << " // Linear interpolate between x and y using weight a"
2403 << endl << " // mix(x,y,a) = x*(1-a)+y*a"
2404 << endl << " //"
2405 << endl << " float maxCosSpotAngle = mix(minCosSpotAngle, 1.0, 0.5);"
2406 << endl << " float l_dot_s = dot(-l, s);"
2407 << endl << " //"
2408 << endl << " // Perform smooth Hermite interpolation between 0 and 1, when e0<x<e1"
2409 << endl << " // float t = clamp((x-e0)/(e1-e0),0.0,1.0);"
2410 << endl << " // smoothstep(e0,e1,x) = t*t*(3-2*t);"
2411 << endl << " //"
2412 << endl << " return smoothstep(minCosSpotAngle, maxCosSpotAngle, l_dot_s);"
2413 << endl << "}"
2414 << endl << ""
2415 << endl << "//"
2416 << endl << "// cinema (uber) light super ellipses clipping"
2417 << endl << "// Parameters:"
2418 << endl << "// a : inner super ellipses width"
2419 << endl << "// b : inner super ellipses height"
2420 << endl << "// A : outer super ellipses width"
2421 << endl << "// B : outer super ellipses height"
2422 << endl << "// r : roundness parameter"
2423 << endl << "// theta : twist parameter"
2424 << endl << "// pos : fragment position in light space"
2425 << endl << "//"
2426 << endl << "// |x/a|^r + |y/b|^r = 1 <=> a*b*(|b*x|^r + |a*y|^r)^(-1/r) = 1"
2427 << endl << "//"
2428 << endl << "// smoothstep(e0,e1,x)"
2429 << endl << "// Perform smooth Hermite interpolation between 0 and 1, when e0<x<e1"
2430 << endl << "// float t = clamp((x-e0)/(e1-e0),0.0,1.0);"
2431 << endl << "// smoothstep(e0,e1,x) = t*t*(3-2*t);"
2432 << endl << "//"
2433 << endl << "float clipSuperEllipses("
2434 << endl << " in float a,"
2435 << endl << " in float b,"
2436 << endl << " in float A,"
2437 << endl << " in float B,"
2438 << endl << " in float r,"
2439 << endl << " in float theta,"
2440 << endl << " in vec3 pos)"
2441 << endl << "{"
2442 << endl << " float result = 1.0;"
2443 << endl << ""
2444 << endl << " vec2 P = pos.xy / pos.z;"
2445 << endl << " if (all(equal(P, vec2(0.0, 0.0))))"
2446 << endl << " return 1.0;"
2447 << endl << ""
2448 << endl << " float cos_theta = cos(-theta);"
2449 << endl << " float sin_theta = sin(-theta);"
2450 << endl << ""
2451 << endl << " float x = abs(cos_theta * P.x - sin_theta * P.y);"
2452 << endl << " float y = abs(sin_theta * P.x + cos_theta * P.y);"
2453 << endl << ""
2454 << endl << " if (r > 50) // basically a square"
2455 << endl << " {"
2456 << endl << " // Simpler case of a square"
2457 << endl << " result = (1.0 - smoothstep(a, A, x)) * (1.0 - smoothstep(b, B, y));"
2458 << endl << " }"
2459 << endl << " else"
2460 << endl << " {"
2461 << endl << " float q = pow(x/a, r) + pow(y/b, r);"
2462 << endl << " float Q = pow(x/A, r) + pow(y/B, r);"
2463 << endl << ""
2464 << endl << " if (q < 1) return 1.0;"
2465 << endl << " if (Q >= 1) return 0.0;"
2466 << endl << ""
2467 << endl << " result = 1.0 - smoothstep(q, Q, 1.0);"
2468 << endl << " }"
2469 << endl << ""
2470 << endl << " return result;"
2471 << endl << "}"
2472 << endl << ""
2473 << endl << "//"
2474 << endl << "// directional light contribution"
2475 << endl << "//"
2476 << endl << "vec3 directionalLight("
2477 << endl << " in const uint i, // light identifier, i.e. current light"
2478 << endl << " in const uint j, // material identifier"
2479 << endl << " in const vec3 n, // vertex normal in eye space"
2480 << endl << " in const vec3 v) // view direction in eye space"
2481 << endl << "{"
2482 << endl << " if (!lights.light[i].enabled)"
2483 << endl << " return vec3(0.0, 0.0, 0.0);"
2484 << endl << ""
2485 << endl << " //"
2486 << endl << " // Transform the light direction from world space into eye space for further considerations"
2487 << endl << " //"
2488 << endl << " vec4 direction = OSGViewMatrix * vec4(lights.light[i].direction, 0.0);"
2489 << endl << ""
2490 << endl << " vec3 l = -direction.xyz;"
2491 << endl << ""
2492 << endl << " //"
2493 << endl << " // the half vector"
2494 << endl << " //"
2495 << endl << " vec3 h = normalize(l+v);"
2496 << endl << ""
2497 << endl << " float n_dot_l = max(0.0, dot(n, l));"
2498 << endl << " float n_dot_h = max(0.0, dot(n, h));"
2499 << endl << ""
2500 << endl << " float m = materials.material[j].shininess;"
2501 << endl << ""
2502 << endl << " float pf; // power factor"
2503 << endl << ""
2504 << endl << " if (n_dot_l == 0.0)"
2505 << endl << " pf = 0.0;"
2506 << endl << " else"
2507 << endl << " pf = pow(n_dot_h, m);"
2508 << endl << ""
2509 << endl << " vec3 light_intensity = lights.light[i].intensity * lights.light[i].color;"
2510 << endl << ""
2511 << endl << " return materials.material[j].emissive"
2512 << endl << " + light_intensity * materials.material[j].ambient"
2513 << endl << " + light_intensity * materials.material[j].diffuse * n_dot_l"
2514 << endl << " + light_intensity * materials.material[j].specular * (m+8)*0.0125 * pf;"
2515 << endl << "}"
2516 << endl << ""
2517 << endl << "//"
2518 << endl << "// point light contribution"
2519 << endl << "//"
2520 << endl << "vec3 pointLight("
2521 << endl << " in const uint i, // light identifier, i.e. current light"
2522 << endl << " in const uint j, // material identifier"
2523 << endl << " in const vec3 n, // vertex normal in eye space"
2524 << endl << " in const vec3 v, // view direction in eye space"
2525 << endl << " in const vec3 p) // vertex position in eye space"
2526 << endl << "{"
2527 << endl << " if (!lights.light[i].enabled)"
2528 << endl << " return vec3(0.0, 0.0, 0.0);"
2529 << endl << ""
2530 << endl << " //"
2531 << endl << " // Transform the light position from world space into eye space for further considerations"
2532 << endl << " //"
2533 << endl << " vec4 position = OSGViewMatrix * vec4(lights.light[i].position, 1.0);"
2534 << endl << ""
2535 << endl << " vec3 l = position.xyz - p; // dir from surface to light position"
2536 << endl << " float d = length(l); // dist from surface to light source"
2537 << endl << ""
2538 << endl << " if (lights.light[i].rangeCutOff < d)"
2539 << endl << " return vec3(0.0, 0.0, 0.0);"
2540 << endl << ""
2541 << endl << " l = normalize(l); // norm direction from surf to light"
2542 << endl << ""
2543 << endl << " //"
2544 << endl << " // the half vector"
2545 << endl << " //"
2546 << endl << " vec3 h = normalize(l+v);"
2547 << endl << ""
2548 << endl << " float n_dot_l = max(0.0, dot(n, l));"
2549 << endl << " float n_dot_h = max(0.0, dot(n, h));"
2550 << endl << ""
2551 << endl << " float m = materials.material[j].shininess;"
2552 << endl << ""
2553 << endl << " float pf; // power factor"
2554 << endl << ""
2555 << endl << " if (n_dot_l == 0.0)"
2556 << endl << " pf = 0.0;"
2557 << endl << " else"
2558 << endl << " pf = pow(n_dot_h, m);"
2559 << endl << ""
2560 << endl << " float attenuation = calcAttenuation(lights.light[i].rangeCutOff, d);"
2561 << endl << ""
2562 << endl << " vec3 light_intensity = attenuation * lights.light[i].intensity * lights.light[i].color;"
2563 << endl << ""
2564 << endl << " return materials.material[j].emissive"
2565 << endl << " + light_intensity * materials.material[j].ambient"
2566 << endl << " + light_intensity * materials.material[j].diffuse * n_dot_l"
2567 << endl << " + light_intensity * materials.material[j].specular * (m+8)*0.0125 * pf;"
2568 << endl << "}"
2569 << endl << ""
2570 << endl << "//"
2571 << endl << "// spot light contribution"
2572 << endl << "//"
2573 << endl << "vec3 spotLight("
2574 << endl << " in const uint i, // light identifier, i.e. current light"
2575 << endl << " in const uint j, // material identifier"
2576 << endl << " in const vec3 n, // vertex normal in eye space"
2577 << endl << " in const vec3 v, // view direction in eye space"
2578 << endl << " in const vec3 p) // vertex position in eye space"
2579 << endl << "{"
2580 << endl << " if (!lights.light[i].enabled)"
2581 << endl << " return vec3(0.0, 0.0, 0.0);"
2582 << endl << ""
2583 << endl << " //"
2584 << endl << " // Transform the light position from world space into eye space for further considerations"
2585 << endl << " //"
2586 << endl << " vec4 position = OSGViewMatrix * vec4(lights.light[i].position, 1.0);"
2587 << endl << ""
2588 << endl << " vec3 l = position.xyz - p; // dir from surface to light position"
2589 << endl << " float d = length(l); // dist from surface to light source"
2590 << endl << ""
2591 << endl << " if (lights.light[i].rangeCutOff < d)"
2592 << endl << " return vec3(0.0, 0.0, 0.0);"
2593 << endl << ""
2594 << endl << " l = normalize(l); // norm dir from surface to light"
2595 << endl << ""
2596 << endl << " //"
2597 << endl << " // Transform the light direction from world space into eye space for further considerations"
2598 << endl << " //"
2599 << endl << " vec4 direction = OSGViewMatrix * vec4(lights.light[i].direction, 0.0);"
2600 << endl << ""
2601 << endl << " vec3 s = direction.xyz;"
2602 << endl << " s = normalize(s);"
2603 << endl << ""
2604 << endl << " //"
2605 << endl << " // the half vector"
2606 << endl << " //"
2607 << endl << " vec3 h = normalize(l+v);"
2608 << endl << ""
2609 << endl << " float n_dot_l = max(0.0, dot(n, l));"
2610 << endl << " float n_dot_h = max(0.0, dot(n, h));"
2611 << endl << ""
2612 << endl << " float m = materials.material[j].shininess;"
2613 << endl << ""
2614 << endl << " float pf; // power factor"
2615 << endl << ""
2616 << endl << " if (n_dot_l == 0.0)"
2617 << endl << " pf = 0.0;"
2618 << endl << " else"
2619 << endl << " pf = pow(n_dot_h, m);"
2620 << endl << ""
2621 << endl << " float attenuation = calcAttenuation(lights.light[i].rangeCutOff, d);"
2622 << endl << ""
2623 << endl << " attenuation *= spotAttenuation(lights.light[i].cosSpotlightAngle, l, s);"
2624 << endl << ""
2625 << endl << " vec3 light_intensity = attenuation * lights.light[i].intensity * lights.light[i].color;"
2626 << endl << ""
2627 << endl << " return materials.material[j].emissive"
2628 << endl << " + light_intensity * materials.material[j].ambient"
2629 << endl << " + light_intensity * materials.material[j].diffuse * n_dot_l"
2630 << endl << " + light_intensity * materials.material[j].specular * (m+8)*0.0125 * pf;"
2631 << endl << "}"
2632 << endl << ""
2633 << endl << "//"
2634 << endl << "// cinema light contribution"
2635 << endl << "//"
2636 << endl << "vec3 cinemaLight("
2637 << endl << " in const uint i, // light identifier, i.e. current light"
2638 << endl << " in const uint j, // material identifier"
2639 << endl << " in const vec3 n, // vertex normal in eye space"
2640 << endl << " in const vec3 v, // view direction in eye space"
2641 << endl << " in const vec3 p) // vertex position in eye space"
2642 << endl << "{"
2643 << endl << " if (!lights.light[i].enabled)"
2644 << endl << " return vec3(0.0, 0.0, 0.0);"
2645 << endl << ""
2646 << endl << " //"
2647 << endl << " // Transform the light position from world space into eye space for further considerations"
2648 << endl << " //"
2649 << endl << " vec4 position = OSGViewMatrix * vec4(lights.light[i].position, 1.0);"
2650 << endl << ""
2651 << endl << " vec3 l = position.xyz - p; // dir from surface to light position"
2652 << endl << " float d = length(l); // dist from surface to light source"
2653 << endl << ""
2654 << endl << " if (lights.light[i].rangeCutOff < d)"
2655 << endl << " return vec3(0.0, 0.0, 0.0);"
2656 << endl << ""
2657 << endl << " l = normalize(l); // norm dir from surface to light"
2658 << endl << ""
2659 << endl << " //"
2660 << endl << " // Transform the light direction from world space into eye space for further considerations"
2661 << endl << " //"
2662 << endl << " vec4 direction = OSGViewMatrix * vec4(lights.light[i].direction, 0.0);"
2663 << endl << ""
2664 << endl << " vec3 s = direction.xyz;"
2665 << endl << " s = normalize(s);"
2666 << endl << ""
2667 << endl << " //"
2668 << endl << " // the half vector"
2669 << endl << " //"
2670 << endl << " vec3 h = normalize(l+v);"
2671 << endl << ""
2672 << endl << " float n_dot_l = max(0.0, dot(n, l));"
2673 << endl << " float n_dot_h = max(0.0, dot(n, h));"
2674 << endl << ""
2675 << endl << " float m = materials.material[j].shininess;"
2676 << endl << ""
2677 << endl << " float pf; // power factor"
2678 << endl << ""
2679 << endl << " if (n_dot_l == 0.0)"
2680 << endl << " pf = 0.0;"
2681 << endl << " else"
2682 << endl << " pf = pow(n_dot_h, m);"
2683 << endl << ""
2684 << endl << " float attenuation = calcAttenuation(lights.light[i].rangeCutOff, d);"
2685 << endl << ""
2686 << endl << " vec3 p_LS = (lights.light[i].eyeToLightSpaceMatrix * vec4(p, 1.0)).xyz;"
2687 << endl << ""
2688 << endl << " attenuation *= clipSuperEllipses("
2689 << endl << " lights.light[i].innerSuperEllipsesWidth,"
2690 << endl << " lights.light[i].innerSuperEllipsesHeight,"
2691 << endl << " lights.light[i].outerSuperEllipsesWidth,"
2692 << endl << " lights.light[i].outerSuperEllipsesHeight,"
2693 << endl << " lights.light[i].superEllipsesRoundness,"
2694 << endl << " lights.light[i].superEllipsesTwist,"
2695 << endl << " p_LS);"
2696 << endl << ""
2697 << endl << " if (p_LS.z > 0.0) attenuation = 0.0;"
2698 << endl << ""
2699 << endl << " attenuation = clamp(attenuation, 0.0, 1.0);"
2700 << endl << ""
2701 << endl << " vec3 light_intensity = attenuation * lights.light[i].intensity * lights.light[i].color;"
2702 << endl << ""
2703 << endl << " return materials.material[j].emissive"
2704 << endl << " + light_intensity * materials.material[j].ambient"
2705 << endl << " + light_intensity * materials.material[j].diffuse * n_dot_l"
2706 << endl << " + light_intensity * materials.material[j].specular * (m+8)*0.0125 * pf;"
2707 << endl << "}"
2708 << endl << ""
2709 << endl << "void main()"
2710 << endl << "{"
2711 << endl << " //"
2712 << endl << " // normalize the eye space normal"
2713 << endl << " //"
2714 << endl << " int frontCond = -(1 - int(gl_FrontFacing)*2);"
2715 << endl << " vec3 N = frontCond * normalize(vNormalES);"
2716 << endl << ""
2717 << endl << " //"
2718 << endl << " // get the view vector and normalize it"
2719 << endl << " //"
2720 << endl << " vec3 V = normalize(cCameraPositionES - vPositionES);"
2721 << endl << ""
2722 << endl << " //"
2723 << endl << " // Integrate over all lights: Any unused light does not contribute and each light"
2724 << endl << " // contribute either from the directional light, the point light or the spot light."
2725 << endl << " //"
2726 << endl << " vec3 color = vec3(0.0, 0.0, 0.0);"
2727 << endl << ""
2728 << endl << " uint list_idx = 0;"
2729 << endl << " uint light_count = 0;"
2730 << endl << ""
2731 << endl << " if (clusteringData.enabled)"
2732 << endl << " {"
2733 << endl << " uvec2 grid_data = getGridData(gl_FragCoord.xy, vPositionES.z);"
2734 << endl << " "
2735 << endl << " list_idx = grid_data.x;"
2736 << endl << " light_count = grid_data.y;"
2737 << endl << " }"
2738 << endl << " else"
2739 << endl << " {"
2740 << endl << " light_count = affectedLightIndexList.idx.length();"
2741 << endl << " }"
2742 << endl << ""
2743 << endl << " for (uint i = 0; i < light_count; ++i)"
2744 << endl << " {"
2745 << endl << " uint light_idx = (clusteringData.enabled) ? lightIndexList.idx[list_idx+i] : affectedLightIndexList.idx[i];"
2746 << endl << ""
2747 << endl << " switch (lights.light[light_idx].type)"
2748 << endl << " {"
2749 << endl << " case POINT_LIGHT: color += pointLight(light_idx, geom_state.material_index, N, V, vPositionES); break;"
2750 << endl << " case DIRECTIONAL_LIGHT: color += directionalLight(light_idx, geom_state.material_index, N, V); break;"
2751 << endl << " case SPOT_LIGHT: color += spotLight(light_idx, geom_state.material_index, N, V, vPositionES); break;"
2752 << endl << " case CINEMA_LIGHT: color += cinemaLight(light_idx, geom_state.material_index, N, V, vPositionES); break;"
2753 << endl << " }"
2754 << endl << " }"
2755 << endl << " vFragColor = vec4(color, materials.material[geom_state.material_index].opacity);"
2756 << endl << "}"
2757 << endl << ""
2758 << endl;
2760 return ost.str();