fixed: compile issue
[opensg.git] / Examples / Simple / shaderstoragebufferobject.cpp
blobd69e5b3d53b250c75a9ffbf4d78025b045a71844
1 // OpenSG Tutorial Example: ShaderStorageBufferObject
2 //
3 // This example shows how to create a shader storage block and binding it
4 // to a shader storage buffer object.
5 //
6 // The example does use the ShaderStorageBufferObjChunk which allows the
7 // host application to provide the shader storage block member values
8 // directly to the chunk. The layout of the shader storage block is determined
9 // by the shader code. Any of the layout values of the specification (shared,
10 // packed, std140, std430) are allowed.
12 // Internally, the shader storage block is queried for the offsets,
13 // array and matrix strides of the block variables.
16 #include <sstream>
17 #include <boost/random/mersenne_twister.hpp>
18 #include <boost/random/uniform_int_distribution.hpp>
20 #ifdef OSG_BUILD_ACTIVE
21 // Headers
22 #include <OSGGLUT.h>
23 #include <OSGConfig.h>
24 #include <OSGSimpleGeometry.h>
25 #include <OSGGLUTWindow.h>
26 #include <OSGSimpleSceneManager.h>
27 #include <OSGBaseFunctions.h>
28 #include <OSGTransform.h>
29 #include <OSGGroup.h>
31 // new headers:
32 #include <OSGGLEXT.h>
33 #include <OSGShaderProgramChunk.h>
34 #include <OSGShaderProgram.h>
35 #include <OSGShaderVariableOSG.h>
36 #include <OSGChunkMaterial.h>
37 #include <OSGMaterialGroup.h>
38 #include <OSGMaterialChunkOverrideGroup.h>
39 #include <OSGShaderStorageBufferObjChunk.h>
40 #include <OSGPolygonChunk.h>
41 #include <OSGDepthChunk.h>
42 #include <OSGShaderProgramVariableChunk.h>
44 #else
45 // Headers
46 #include <OpenSG/OSGGLUT.h>
47 #include <OpenSG/OSGConfig.h>
48 #include <OpenSG/OSGSimpleGeometry.h>
49 #include <OpenSG/OSGGLUTWindow.h>
50 #include <OpenSG/OSGSimpleSceneManager.h>
51 #include <OpenSG/OSGBaseFunctions.h>
52 #include <OpenSG/OSGTransform.h>
53 #include <OpenSG/OSGGroup.h>
55 // new headers:
56 #include <OpenSG/OSGGLEXT.h>
57 #include <OpenSG/OSGShaderProgramChunk.h>
58 #include <OpenSG/OSGShaderProgram.h>
59 #include <OpenSG/OSGShaderVariableOSG.h>
60 #include <OpenSG/OSGChunkMaterial.h>
61 #include <OpenSG/OSGMaterialGroup.h>
62 #include <OpenSG/OSGMaterialChunkOverrideGroup.h>
63 #include <OpenSG/OSGShaderStorageBufferObjChunk.h>
64 #include <OpenSG/OSGPolygonChunk.h>
65 #include <OpenSG/OSGDepthChunk.h>
66 #include <OpenSG/OSGShaderProgramVariableChunk.h>
67 #endif
70 // USE_TEST_FP_SHADER
71 // ------------------
72 // Activate a test mode that does test the material and light at index 0,
73 // respectively, against specific values set by the application. If all
74 // values are read correctly in the shader the geometry is colored in green.
75 // Otherwise the geometry is colored red indicating failure.
77 //#define USE_TEST_FP_SHADER
80 // The SimpleSceneManager to manage simple applications
82 OSG::SimpleSceneManagerRefPtr mgr;
85 // simple light data structure
87 struct Light
89 enum Type
91 directional_light = 0,
92 point_light,
93 spot_light,
94 no_light
97 Light()
98 : position(0.f, 0.f, 0.f)
99 , spot_direction(0.f, 1.f, 0.f)
100 , Ia(1.f, 1.f, 1.f)
101 , Id(1.f, 1.f, 1.f)
102 , Is(1.f, 1.f, 1.f)
103 , attenuation(1.f, 0.f, 0.f)
104 , spot_cos_cutoff(cosf(45.f))
105 , spot_exponent(1.f)
106 , type(no_light)
109 static Light create_light(Type e)
111 Light l;
112 l.type = e;
114 switch (e) {
115 case directional_light: l.spot_direction = OSG::Vec3f(1.f, 0.f, 0.f);
116 break;
117 case point_light: l.position = OSG::Pnt3f(0.f, 0.2f, 0.f);
118 break;
119 case spot_light: l.position = OSG::Pnt3f(0.f, 0.2f, 0.f); l.spot_direction = OSG::Pnt3f(0.f, 0.f, 0.f) - l.position;
120 break;
121 default:
122 break;
124 return l;
127 OSG::Pnt3f position; // in object space
128 OSG::Vec3f spot_direction; // in object space, also used for dir of directional lights (see shader code)
129 OSG::Color3f Ia; // ambient max. Intensity
130 OSG::Color3f Id; // diffuse max. Intensity
131 OSG::Color3f Is; // specular max. Intensity
133 OSG::Vec3f attenuation; // (constant, linear, quadratic) with constant >= 1 and linear,quadratic >= 0
134 OSG::Real32 spot_cos_cutoff; // cosine cut of angle
135 OSG::Real32 spot_exponent; // [0-128]
136 OSG::Int32 type; // directional_light, point_light, spot_light, no_light
139 typedef std::vector<Light> VecLightsT; // multiple lights
141 const std::size_t num_lights = 2; // simple example with just one light
143 VecLightsT initialize_lights() // helper to create lights
145 VecLightsT lights;
147 lights.push_back(Light::create_light(Light::directional_light));
148 lights.push_back(Light::create_light(Light::point_light));
150 assert(lights.size() == num_lights);
152 return lights;
155 VecLightsT lights = initialize_lights(); // the lights
159 // Simple material data structure
161 struct Material
163 Material()
164 : ambient (0.f, 0.f, 0.f)
165 , diffuse (0.f, 0.f, 0.f)
166 , specular(0.f, 0.f, 0.f)
167 , emissive(0.f, 0.f, 0.f)
168 , opacity(1.f)
169 , shininess(100.f)
172 OSG::Color3f ambient;
173 OSG::Color3f diffuse;
174 OSG::Color3f specular;
175 OSG::Color3f emissive;
177 OSG::Real32 opacity;
178 OSG::Real32 shininess;
181 typedef std::vector<Material> VecMaterialsT; // multiple materials
183 VecMaterialsT initialize_materials(std::size_t num) // helper to create materials
185 VecMaterialsT materials;
187 for (std::size_t i = 0; i < num; ++i)
189 Material m;
191 m.ambient = OSG::Color3f(0.1f, 0.1f, 0.1f);
192 m.diffuse.setRandom();
193 m.specular = OSG::Color3f(0.9f, 0.9f, 0.9f);
194 m.emissive = OSG::Color3f(0.0f, 0.0f, 0.0f);
195 m.opacity = 1.f;
196 m.shininess = 80.f;
198 materials.push_back(m);
201 return materials;
204 const std::size_t num_materials = 5000; // any numnber of materials
205 VecMaterialsT materials = initialize_materials(num_materials); // the material database
209 // Simple geometry state data structure
211 struct GeomState
213 GeomState()
214 : material_index(0)
217 OSG::UInt32 material_index;
221 // transform point from world space to eye space
223 OSG::Pnt3f transform_to_eye_space(const OSG::Pnt3f& p, OSG::SimpleSceneManager* pSSM)
225 if (!pSSM || !pSSM->getWindow() || pSSM->getWindow()->getMFPort()->size() == 0)
226 return p;
228 OSG::Viewport* pPort = mgr->getWindow()->getPort(0);
230 OSG::Pnt3f p_es;
232 OSG::Matrix view;
233 OSG::Int16 width = pPort->calcPixelWidth();
234 OSG::Int16 height = pPort->calcPixelHeight();
236 pPort->getCamera()->getViewing(view, width, height);
238 view.multFull( p, p_es);
240 return p_es;
244 // transform vector from world space to eye space
246 OSG::Vec3f transform_to_eye_space(const OSG::Vec3f& v, OSG::SimpleSceneManager* pSSM)
248 if (!pSSM || !pSSM->getWindow() || pSSM->getWindow()->getMFPort()->size() == 0)
249 return v;
251 OSG::Viewport* pPort = mgr->getWindow()->getPort(0);
253 OSG::Vec3f v_es;
255 OSG::Matrix view;
256 OSG::Int16 width = pPort->calcPixelWidth();
257 OSG::Int16 height = pPort->calcPixelHeight();
259 pPort->getCamera()->getViewing(view, width, height);
261 view.multFull( v, v_es);
263 return v_es;
267 // The light state
269 void update_light_state(OSG::ShaderStorageBufferObjChunk* ssbo, const VecLightsT& vLights)
271 if (ssbo) {
272 for (std::size_t i = 0; i < vLights.size(); ++i) {
273 std::stringstream stream;
274 stream << "Lights.light[" << i << "]." << std::flush;
275 std::string name;
276 #ifndef USE_TEST_FP_SHADER
277 OSG::Pnt3f position_es = transform_to_eye_space(vLights[i].position, mgr);
278 OSG::Vec3f spot_direction_es = transform_to_eye_space(vLights[i].spot_direction, mgr);
280 name = stream.str() + "position"; ssbo->setVec3 (name, position_es);
281 name = stream.str() + "spot_direction"; ssbo->setVec3 (name, spot_direction_es);
282 name = stream.str() + "Ia"; ssbo->setVec3 (name, vLights[i].Ia);
283 name = stream.str() + "Id"; ssbo->setVec3 (name, vLights[i].Id);
284 name = stream.str() + "Is"; ssbo->setVec3 (name, vLights[i].Is);
285 name = stream.str() + "attenuation"; ssbo->setVec3 (name, vLights[i].attenuation);
286 name = stream.str() + "spot_cos_cutoff"; ssbo->setFloat(name, vLights[i].spot_cos_cutoff);
287 name = stream.str() + "spot_exponent"; ssbo->setFloat(name, vLights[i].spot_exponent);
288 name = stream.str() + "type"; ssbo->setInt (name, vLights[i].type);
289 #else
290 name = stream.str() + "position"; ssbo->setVec3 (name, OSG::Pnt3f(1.1f, 2.2f, 3.3f));
291 name = stream.str() + "spot_direction"; ssbo->setVec3 (name, OSG::Vec3f(4.4f, 5.5f, 6.6f));
292 name = stream.str() + "Ia"; ssbo->setVec3 (name, OSG::Color3f(0.2f, 0.2f, 0.2f));
293 name = stream.str() + "Id"; ssbo->setVec3 (name, OSG::Color3f(0.4f, 0.4f, 0.4f));
294 name = stream.str() + "Is"; ssbo->setVec3 (name, OSG::Color3f(0.6f, 0.6f, 0.6f));
295 name = stream.str() + "attenuation"; ssbo->setVec3 (name, OSG::Vec3f(0.8f, 0.8f, 0.8f));
296 name = stream.str() + "spot_cos_cutoff"; ssbo->setFloat(name, 0.8f);
297 name = stream.str() + "spot_exponent"; ssbo->setFloat(name, 12.3f);
298 name = stream.str() + "type"; ssbo->setInt (name, Light::point_light);
299 #endif
304 OSG::ShaderStorageBufferObjChunkTransitPtr create_light_state(const VecLightsT& vLights)
306 OSG::ShaderStorageBufferObjChunkRefPtr ssbo = OSG::ShaderStorageBufferObjChunk::create();
308 ssbo->setBlockName("Lights");
309 ssbo->setUsage(GL_STREAM_DRAW);
311 for (std::size_t i = 0; i < vLights.size(); ++i) {
312 std::stringstream stream;
313 stream << "Lights.light[" << i << "]." << std::flush;
314 std::string name;
316 name = stream.str() + "position"; ssbo->addVec3 (name);
317 name = stream.str() + "spot_direction"; ssbo->addVec3 (name);
318 name = stream.str() + "Ia"; ssbo->addVec3 (name);
319 name = stream.str() + "Id"; ssbo->addVec3 (name);
320 name = stream.str() + "Is"; ssbo->addVec3 (name);
321 name = stream.str() + "attenuation"; ssbo->addVec3 (name);
322 name = stream.str() + "spot_cos_cutoff"; ssbo->addFloat(name);
323 name = stream.str() + "spot_exponent"; ssbo->addFloat(name);
324 name = stream.str() + "type"; ssbo->addInt (name);
327 update_light_state(ssbo, vLights);
329 return OSG::ShaderStorageBufferObjChunkTransitPtr(ssbo);
333 // The material state
335 void update_material_database_state(OSG::ShaderStorageBufferObjChunk* ssbo, const VecMaterialsT& vMaterials)
337 if (ssbo) {
338 for (std::size_t i = 0; i < vMaterials.size(); ++i) {
339 std::stringstream stream;
340 stream << "Materials.material[" << i << "]." << std::flush;
341 std::string name;
342 #ifndef USE_TEST_FP_SHADER
343 name = stream.str() + "ambient"; ssbo->setVec3 (name, vMaterials[i].ambient);
344 name = stream.str() + "diffuse"; ssbo->setVec3 (name, vMaterials[i].diffuse);
345 name = stream.str() + "specular"; ssbo->setVec3 (name, vMaterials[i].specular);
346 name = stream.str() + "emissive"; ssbo->setVec3 (name, vMaterials[i].emissive);
347 name = stream.str() + "opacity"; ssbo->setFloat(name, vMaterials[i].opacity);
348 name = stream.str() + "shininess"; ssbo->setFloat(name, vMaterials[i].shininess);
349 #else
350 name = stream.str() + "ambient"; ssbo->setVec3 (name, OSG::Color3f(0.1f,0.2f,0.3f));
351 name = stream.str() + "diffuse"; ssbo->setVec3 (name, OSG::Color3f(0.2f,0.4f,0.6f));
352 name = stream.str() + "specular"; ssbo->setVec3 (name, OSG::Color3f(0.4f,0.6f,0.8f));
353 name = stream.str() + "emissive"; ssbo->setVec3 (name, OSG::Color3f(0.6f,0.8f,1.0f));
354 name = stream.str() + "opacity"; ssbo->setFloat(name, 0.7f);
355 name = stream.str() + "shininess"; ssbo->setFloat(name, 25.4f);
356 #endif
361 OSG::ShaderStorageBufferObjChunkTransitPtr create_material_database_state(const VecMaterialsT& vMaterials)
363 OSG::ShaderStorageBufferObjChunkRefPtr ssbo = OSG::ShaderStorageBufferObjChunk::create();
365 ssbo->setBlockName("Materials");
366 ssbo->setUsage(GL_STATIC_DRAW);
368 for (std::size_t i = 0; i < vMaterials.size(); ++i) {
369 std::stringstream stream;
370 stream << "Materials.material[" << i << "]." << std::flush;
371 std::string name;
373 name = stream.str() + "ambient"; ssbo->addVec3 (name);
374 name = stream.str() + "diffuse"; ssbo->addVec3 (name);
375 name = stream.str() + "specular"; ssbo->addVec3 (name);
376 name = stream.str() + "emissive"; ssbo->addVec3 (name);
377 name = stream.str() + "opacity"; ssbo->addFloat(name);
378 name = stream.str() + "shininess"; ssbo->addFloat(name);
381 update_material_database_state(ssbo, vMaterials);
383 return OSG::ShaderStorageBufferObjChunkTransitPtr(ssbo);
387 // The geometry material state
389 void update_geometry_material_state(OSG::ShaderStorageBufferObjChunk* ssbo, const GeomState& geom_state)
391 if (ssbo) {
392 #ifndef USE_TEST_FP_SHADER
393 ssbo->setInt("GeomState.material_index", geom_state.material_index);
394 #else
395 ssbo->setInt("GeomState.material_index", 7);
396 #endif
400 OSG::ShaderStorageBufferObjChunkTransitPtr create_geometry_material_state(const GeomState& geom_state)
402 OSG::ShaderStorageBufferObjChunkRefPtr ssbo = OSG::ShaderStorageBufferObjChunk::create();
404 ssbo->setBlockName("GeomState");
405 ssbo->setUsage(GL_DYNAMIC_DRAW);
407 ssbo->addInt("GeomState.material_index");
409 update_geometry_material_state(ssbo, geom_state);
411 return OSG::ShaderStorageBufferObjChunkTransitPtr(ssbo);
415 // vertex shader program.
417 std::string get_vp_program();
420 // fragment shader program for bump mapping in surface local coordinates
422 std::string get_fp_program();
425 // random number generator
427 boost::random::mt19937 generator;
428 boost::random::uniform_int_distribution<> dist(0, num_materials-1);
431 // a separate transformation for every object
433 OSG::TransformRefPtr cyltrans, tortrans;
436 // Shader storage buffer objects corresponding to transient shader blocks
438 OSG::ShaderStorageBufferObjChunkRefPtr ssbo_light_state = NULL;
439 OSG::ShaderStorageBufferObjChunkRefPtr ssbo_geom_state_1 = NULL;
440 OSG::ShaderStorageBufferObjChunkRefPtr ssbo_geom_state_2 = NULL;
443 // forward declaration so we can have the interesting stuff upfront
445 int setupGLUT(int *argc, char *argv[]);
448 // redraw the window
450 void display(void)
452 // light spot direction and light position must be provided in eye space
453 update_light_state(ssbo_light_state, lights);
455 // create the matrix
456 OSG::Matrix m;
457 OSG::Real32 t = glutGet(GLUT_ELAPSED_TIME );
459 // set the transforms' matrices
460 m.setTransform(OSG::Vec3f(0, 0, OSG::osgSin(t / 1000.f) * 1.5),
461 OSG::Quaternion( OSG::Vec3f (1, 0, 0), t / 500.f));
463 cyltrans->setMatrix(m);
465 m.setTransform(OSG::Vec3f(OSG::osgSin(t / 1000.f), 0, 0),
466 OSG::Quaternion( OSG::Vec3f (0, 0, 1), t / 1000.f));
468 tortrans->setMatrix(m);
470 OSG::commitChanges();
472 mgr->redraw();
476 // Initialize GLUT & OpenSG and set up the scene
478 int main(int argc, char **argv)
480 // OSG init
481 OSG::osgInit(argc,argv);
483 // GLUT init
484 int winid = setupGLUT(&argc, argv);
486 // open a new scope, because the pointers below should go out of scope
487 // before entering glutMainLoop.
488 // Otherwise OpenSG will complain about objects being alive after shutdown.
490 // the connection between GLUT and OpenSG
491 OSG::GLUTWindowRefPtr gwin = OSG::GLUTWindow::create();
492 gwin->setGlutId(winid);
493 gwin->init();
495 // create the SimpleSceneManager helper
496 mgr = OSG::SimpleSceneManager::create();
497 mgr->setWindow(gwin);
499 // create a pretty simple graph: a Group with two Transforms as children,
500 // each of which carries a single Geometry.
502 // The scene
504 OSG::NodeRefPtr scene = OSG::Node::create();
506 // The cylinder and its transformation
507 OSG::NodeRefPtr cyl = OSG::Node::create();
508 OSG::GeometryRefPtr cylgeo = OSG::makeCylinderGeo( 1.4f, .3f, 24,
509 true, true, true );
511 cyl->setCore(cylgeo);
513 cyltrans = OSG::Transform::create();
515 OSG::NodeRefPtr cyltransnode = OSG::Node::create();
516 cyltransnode->setCore (cyltrans);
517 cyltransnode->addChild(cyl );
519 // add it to the scene
520 scene->addChild(cyltransnode);
522 // The torus and its transformation
523 OSG::NodeRefPtr torus = OSG::Node::create();
524 OSG::GeometryRefPtr torusgeo = OSG::makeTorusGeo( .2f, 1, 24, 36 );
526 torus->setCore(torusgeo);
528 tortrans = OSG::Transform::create();
530 OSG::NodeRefPtr tortransnode = OSG::Node::create();
531 tortransnode->setCore (tortrans);
532 tortransnode->addChild(torus );
534 // add it to the scene
535 scene->addChild(tortransnode);
538 // create the shader program
540 OSG::ShaderProgramChunkRefPtr prog_chunk = OSG::ShaderProgramChunk::create();
541 OSG::ShaderProgramRefPtr vertShader = OSG::ShaderProgram::createVertexShader();
542 OSG::ShaderProgramRefPtr fragShader = OSG::ShaderProgram::createFragmentShader();
544 vertShader->setProgram(get_vp_program());
545 fragShader->setProgram(get_fp_program());
548 // binding the unifrom block to a buffer binding point can be performed
549 // either by calling the shaders's addShaderStorageBlock method or by
550 // adding a 'shader storage block' variable to a ShaderProgramVariableChunk.
551 // In the following we use both variants for illustration.
553 fragShader->addShaderStorageBlock("Materials", 1); // block binding point
554 fragShader->addShaderStorageBlock("Lights", 2); // block binding point
557 // The following is replaced by adding ShaderProgramVariableChunk objects
558 // to the chunk material. See below...
560 // fragShader->addShaderStorageBlock("GeomState", 3); // block binding point
562 prog_chunk->addShader(vertShader);
563 prog_chunk->addShader(fragShader);
566 // create shader storage buffer objects and corresponding materials
568 OSG::ShaderStorageBufferObjChunkRefPtr ssbo_material_database = create_material_database_state(materials);
569 ssbo_light_state = create_light_state(lights);
571 OSG::PolygonChunkRefPtr polygon_chunk = OSG::PolygonChunk::create();
572 polygon_chunk->setFrontMode(GL_FILL);
573 polygon_chunk->setBackMode(GL_FILL);
574 polygon_chunk->setCullFace(GL_NONE);
576 OSG::DepthChunkRefPtr depth_chunk = OSG::DepthChunk::create();
577 depth_chunk->setEnable(true);
579 OSG::ChunkMaterialRefPtr prog_state = OSG::ChunkMaterial::create();
580 prog_state->addChunk(ssbo_material_database, 1); // buffer binding point 1
581 prog_state->addChunk(ssbo_light_state, 2); // buffer binding point 2
582 prog_state->addChunk(prog_chunk);
583 prog_state->addChunk(polygon_chunk);
584 prog_state->addChunk(depth_chunk);
586 OSG::ShaderProgramVariableChunkRefPtr shader_var_chunk = OSG::ShaderProgramVariableChunk::create();
587 shader_var_chunk->addShaderStorageBlock("GeomState", 3);
589 GeomState geom1; geom1.material_index = dist(generator);
590 OSG::ChunkMaterialRefPtr geom1_state = OSG::ChunkMaterial::create();
591 ssbo_geom_state_1 = create_geometry_material_state(geom1);
592 geom1_state->addChunk(ssbo_geom_state_1, 3); // buffer binding point 3
593 geom1_state->addChunk(shader_var_chunk); // block binding point
595 GeomState geom2; geom2.material_index = dist(generator);
596 OSG::ChunkMaterialRefPtr geom2_state = OSG::ChunkMaterial::create();
597 ssbo_geom_state_2 = create_geometry_material_state(geom2);
598 geom2_state->addChunk(ssbo_geom_state_2, 3); // buffer binding point 3
599 geom2_state->addChunk(shader_var_chunk); // block binding point
601 cylgeo ->setMaterial(geom1_state);
602 torusgeo->setMaterial(geom2_state);
604 OSG::MaterialChunkOverrideGroupRefPtr mgrp = OSG::MaterialChunkOverrideGroup::create();
605 mgrp->setMaterial(prog_state);
606 scene->setCore(mgrp);
608 OSG::commitChanges();
610 mgr->setRoot(scene);
612 // show the whole scene
613 mgr->showAll();
616 // GLUT main loop
617 glutMainLoop();
619 return 0;
623 // GLUT callback functions
627 // react to size changes
629 void reshape(int w, int h)
631 mgr->resize(w, h);
632 glutPostRedisplay();
636 // react to mouse button presses
638 void mouse(int button, int state, int x, int y)
640 if (state)
641 mgr->mouseButtonRelease(button, x, y);
642 else
643 mgr->mouseButtonPress(button, x, y);
645 glutPostRedisplay();
649 // react to mouse motions with pressed buttons
651 void motion(int x, int y)
653 mgr->mouseMove(x, y);
654 glutPostRedisplay();
658 // react to keys
660 void keyboard(unsigned char k, int x, int y)
662 switch(k)
664 case 27:
666 // clean up global variables
667 cyltrans = NULL;
668 tortrans = NULL;
669 mgr = NULL;
671 ssbo_light_state = NULL;
672 ssbo_geom_state_1 = NULL;
673 ssbo_geom_state_2 = NULL;
675 OSG::osgExit();
676 exit(0);
678 break;
680 case 'm':
682 GeomState geom1; geom1.material_index = dist(generator);
683 GeomState geom2; geom2.material_index = dist(generator);
685 update_geometry_material_state(ssbo_geom_state_1, geom1);
686 update_geometry_material_state(ssbo_geom_state_2, geom2);
688 glutPostRedisplay();
690 break;
692 case 's':
694 mgr->setStatistics(!mgr->getStatistics());
696 break;
701 // setup the GLUT library which handles the windows for us
703 int setupGLUT(int *argc, char *argv[])
705 glutInit(argc, argv);
706 glutInitDisplayMode(GLUT_RGB | GLUT_DEPTH | GLUT_DOUBLE);
708 int winid = glutCreateWindow("OpenSG");
710 glutReshapeFunc(reshape);
711 glutDisplayFunc(display);
712 glutMouseFunc(mouse);
713 glutMotionFunc(motion);
714 glutKeyboardFunc(keyboard);
716 // call the redraw function whenever there's nothing else to do
717 glutIdleFunc(display);
719 return winid;
723 // vertex shader program.
725 std::string get_vp_program()
727 std::string vp_program =
728 "\n"
729 "#version 330 compatibility\n"
730 "\n"
731 "#extension GL_ARB_separate_shader_objects: enable\n"
732 "#extension GL_ARB_shader_storage_buffer_object: enable\n"
733 "\n"
734 "smooth out vec3 vNormalES; // eye space normal\n"
735 "smooth out vec3 vPositionES; // eye space position\n"
736 "\n"
737 "void main()\n"
738 "{\n"
739 " //\n"
740 " // multiply the object space vertex position with the modelview matrix \n"
741 " // to get the eye space vertex position\n"
742 " //\n"
743 " vPositionES = (gl_ModelViewMatrix * gl_Vertex).xyz;\n"
744 "\n"
745 " //\n"
746 " // multiply the object space normal with the normal matrix (transpose of the inverse \n"
747 " // model view matrix) to get the eye space normal\n"
748 " //\n"
749 " vNormalES = gl_NormalMatrix * gl_Normal;\n"
750 "\n"
751 " //\n"
752 " // multiply the combiend modelview projection matrix with the object space vertex\n"
753 " // position to get the clip space position\n"
754 " //\n"
755 " gl_Position = ftransform();\n"
756 "}\n"
757 "\n"
759 return vp_program;
763 // fragment shader program for bump mapping in surface local coordinates
765 std::string get_fp_program()
767 #ifndef USE_TEST_FP_SHADER
768 std::string fp_program =
769 "\n"
770 "#version 330 compatibility\n"
771 "\n"
772 "#extension GL_ARB_separate_shader_objects: enable\n"
773 "#extension GL_ARB_shader_storage_buffer_object: enable\n"
774 "\n"
775 "smooth in vec3 vNormalES; // eye space normal\n"
776 "smooth in vec3 vPositionES; // eye space position\n"
777 "\n"
778 "const int num_lights = 2;\n"
779 "const int num_materials = 5000;\n"
780 "\n"
781 "const int directional_light = 0;\n"
782 "const int point_light = 1;\n"
783 "const int spot_light = 2;\n"
784 "const int no_light = 3;\n"
785 "\n"
786 "struct Light\n"
787 "{\n"
788 " vec3 position; // in eye space\n"
789 " vec3 spot_direction; // in eye space\n"
790 "\n"
791 " vec3 Ia; // ambient max. Intensity\n"
792 " vec3 Id; // diffuse max. Intensity\n"
793 " vec3 Is; // specular max. Intensity\n"
794 "\n"
795 " vec3 attenuation; // (constant, linear, quadratic) with constant >= 1 and linear,quadratic >= 0\n"
796 " \n"
797 " float spot_cos_cutoff; // cosine cut of angle\n"
798 "\n"
799 " float spot_exponent; // [0-128]\n"
800 " int type; // directional_light, point_light, spot_light, no_light\n"
801 "};\n"
802 "\n"
803 "layout (std430) buffer Lights\n"
804 "{\n"
805 " Light light[num_lights];\n"
806 "} lights;\n"
807 "\n"
808 "struct Material\n"
809 "{\n"
810 " vec3 ambient;\n"
811 " vec3 diffuse;\n"
812 " vec3 specular;\n"
813 " vec3 emissive;\n"
814 "\n"
815 " float opacity;\n"
816 " float shininess;\n"
817 "};\n"
818 "\n"
819 "layout (std430) buffer Materials\n"
820 "{\n"
821 " Material material[num_materials];\n"
822 "} materials;\n"
823 "\n"
824 "\n"
825 "layout (std430) buffer GeomState\n"
826 "{\n"
827 " int material_index;\n"
828 "} geom_state;\n"
829 "\n"
830 "const vec3 cCameraPositionES = vec3(0,0,0); // eye is at vec3(0,0,0) in eye space!\n"
831 "\n"
832 "layout(location = 0) out vec4 vFragColor;\n"
833 "\n"
834 "//\n"
835 "// directional light contribution\n"
836 "//\n"
837 "vec3 directionalLight(\n"
838 " in int i, // light identifier, i.e. current light\n"
839 " in int j, // material identifier\n"
840 " in vec3 n, // vertex normal in eye space\n"
841 " in vec3 v) // view direction in eye space\n"
842 "{\n"
843 " if (lights.light[i].type != directional_light)\n"
844 " return vec3(0.0, 0.0, 0.0);\n"
845 "\n"
846 " //\n"
847 " // the light direction in eye space\n"
848 " //\n"
849 " vec3 l = -lights.light[i].spot_direction; // we carry the directional light direction in the spot_direction slot\n"
850 "\n"
851 " //\n"
852 " // the half vector\n"
853 " //\n"
854 " vec3 h = normalize(l + v);\n"
855 "\n"
856 " float n_dot_l = max(0.0, dot(n, l));\n"
857 " float n_dot_h = max(0.0, dot(n, h));\n"
858 "\n"
859 " float m = materials.material[j].shininess;\n"
860 "\n"
861 " float pf; // power factor\n"
862 "\n"
863 " if (n_dot_l == 0.0)\n"
864 " pf = 0.0;\n"
865 " else\n"
866 " pf = pow(n_dot_h, m);\n"
867 "\n"
868 " return materials.material[j].emissive \n"
869 " + lights.light[i].Ia * materials.material[j].ambient \n"
870 " + lights.light[i].Id * materials.material[j].diffuse * n_dot_l // / PI\n"
871 " + lights.light[i].Is * materials.material[j].specular * (m+8)*0.0125 * pf; // * (m+8)/(8*PI)\n"
872 "}\n"
873 "\n"
874 "//\n"
875 "// point light contribution\n"
876 "//\n"
877 "vec3 pointLight(\n"
878 " in int i, // light identifier, i.e. current light\n"
879 " in int j, // material identifier\n"
880 " in vec3 n, // vertex normal in eye space\n"
881 " in vec3 v, // view direction in eye space\n"
882 " in vec3 p) // vertex position in eye space\n"
883 "{\n"
884 " if (lights.light[i].type != point_light)\n"
885 " return vec3(0.0, 0.0, 0.0);\n"
886 "\n"
887 " vec3 l = vec3(lights.light[i].position) - p; // direction from surface to light position\n"
888 " float d = length(l); // distance from surface to light source\n"
889 " l = normalize(l); // normalized direction from surface to light position\n"
890 "\n"
891 " //\n"
892 " // the half vector\n"
893 " //\n"
894 " vec3 h = normalize(l + v);\n"
895 "\n"
896 " float n_dot_l = max(0.0, dot(n, l));\n"
897 " float n_dot_h = max(0.0, dot(n, h));\n"
898 "\n"
899 " float m = materials.material[j].shininess;\n"
900 "\n"
901 " float pf; // power factor\n"
902 "\n"
903 " if (n_dot_l == 0.0)\n"
904 " pf = 0.0;\n"
905 " else\n"
906 " pf = pow(n_dot_h, m);\n"
907 "\n"
908 " //\n"
909 " // Compute attenuation\n"
910 " //\n"
911 " float attenuation = 1.0 / (lights.light[i].attenuation.x + \n"
912 " (lights.light[i].attenuation.y * d) + \n"
913 " (lights.light[i].attenuation.z * d * d));\n"
914 "\n"
915 " attenuation = clamp(attenuation, 0.0, 1.0);\n"
916 "\n"
917 " return materials.material[j].emissive \n"
918 " + attenuation * lights.light[i].Ia * materials.material[j].ambient \n"
919 " + attenuation * lights.light[i].Id * materials.material[j].diffuse * n_dot_l // / PI\n"
920 " + attenuation * lights.light[i].Is * materials.material[j].specular * (m+8)*0.0125 * pf; // * (m+8)/(8*PI)\n"
921 "}\n"
922 "\n"
923 "//\n"
924 "// spot light contribution\n"
925 "//\n"
926 "vec3 spotLight(\n"
927 " in int i, // light identifier, i.e. current light\n"
928 " in int j, // material identifier\n"
929 " in vec3 n, // vertex normal in eye space\n"
930 " in vec3 v, // view direction in eye space\n"
931 " in vec3 p) // vertex position in eye space\n"
932 "{\n"
933 " if (lights.light[i].type != spot_light)\n"
934 " return vec3(0.0, 0.0, 0.0);\n"
935 "\n"
936 " vec3 l = vec3(lights.light[i].position) - p; // direction from surface to light position\n"
937 " float d = length(l); // distance from surface to light source\n"
938 " l = normalize(l); // normalized direction from surface to light position\n"
939 " \n"
940 " vec3 s = lights.light[i].spot_direction; // spot direction\n"
941 "\n"
942 " //\n"
943 " // the half vector\n"
944 " //\n"
945 " vec3 h = normalize(l + v);\n"
946 "\n"
947 " float n_dot_l = max(0.0, dot(n, l));\n"
948 " float n_dot_h = max(0.0, dot(n, h));\n"
949 " float l_dot_s = dot(-l, s);\n"
950 "\n"
951 " float m = materials.material[j].shininess;\n"
952 "\n"
953 " float pf; // power factor\n"
954 "\n"
955 " if (n_dot_l == 0.0)\n"
956 " pf = 0.0;\n"
957 " else\n"
958 " pf = pow(n_dot_h, m);\n"
959 "\n"
960 " //\n"
961 " // Compute attenuation\n"
962 " //\n"
963 " float attenuation = 1.0 / (lights.light[i].attenuation.x + \n"
964 " (lights.light[i].attenuation.y * d) + \n"
965 " (lights.light[i].attenuation.z * d * d));\n"
966 "\n"
967 " attenuation = clamp(attenuation, 0.0, 1.0);\n"
968 "\n"
969 " if (l_dot_s < lights.light[i].spot_cos_cutoff) \n"
970 " attenuation = 0.0;\n"
971 " else\n"
972 " attenuation *= pow(l_dot_s, lights.light[i].spot_exponent);\n"
973 "\n"
974 " return materials.material[j].emissive \n"
975 " + attenuation * lights.light[i].Ia * materials.material[j].ambient \n"
976 " + attenuation * lights.light[i].Id * materials.material[j].diffuse * n_dot_l // / PI\n"
977 " + attenuation * lights.light[i].Is * materials.material[j].specular * (m+8)*0.0125 * pf; // * (m+8)/(8*PI)\n"
978 "}\n"
979 "\n"
980 "void main()\n"
981 "{\n"
982 " //\n"
983 " // normalize the eye space normal\n"
984 " //\n"
985 " vec3 N = normalize(vNormalES);\n"
986 "\n"
987 " //\n"
988 " // get the view vector and normalize it\n"
989 " //\n"
990 " vec3 V = normalize(cCameraPositionES - vPositionES);\n"
991 "\n"
992 " //\n"
993 " // Integrate over all lights: Any unused light does not contribute and each light\n"
994 " // contribute either from the directional light, the point light or the spot light.\n"
995 " //\n"
996 " vec3 color = vec3(0.0, 0.0, 0.0);\n"
997 " for (int i = 0; i < num_lights; ++i) {\n"
998 " color += directionalLight(i, geom_state.material_index, N, V) \n"
999 " + pointLight(i, geom_state.material_index, N, V, vPositionES) \n"
1000 " + spotLight(i, geom_state.material_index, N, V, vPositionES);\n"
1001 " }\n"
1002 " vFragColor = vec4(color, materials.material[geom_state.material_index ].opacity);\n"
1003 "}\n"
1004 "\n"
1006 #else
1007 std::string fp_program =
1008 "\n"
1009 "#version 330 compatibility\n"
1010 "\n"
1011 "#extension GL_ARB_separate_shader_objects: enable\n"
1012 "#extension GL_ARB_shader_storage_buffer_object: enable\n"
1013 "\n"
1014 "smooth in vec3 vNormalES; // eye space normal\n"
1015 "smooth in vec3 vPositionES; // eye space position\n"
1016 "\n"
1017 "const int num_lights = 2;\n"
1018 "const int num_materials = 5000;\n"
1019 "\n"
1020 "const int directional_light = 0;\n"
1021 "const int point_light = 1;\n"
1022 "const int spot_light = 2;\n"
1023 "const int no_light = 3;\n"
1024 "\n"
1025 "struct Light\n"
1026 "{\n"
1027 " vec3 position; // in eye space\n"
1028 " vec3 spot_direction; // in eye space\n"
1029 "\n"
1030 " vec3 Ia; // ambient max. Intensity\n"
1031 " vec3 Id; // diffuse max. Intensity\n"
1032 " vec3 Is; // specular max. Intensity\n"
1033 "\n"
1034 " vec3 attenuation; // (constant, linear, quadratic) with constant >= 1 and linear,quadratic >= 0\n"
1035 "\n"
1036 " float spot_cos_cutoff; // cosine cut of angle\n"
1037 " float spot_exponent; // [0-128]\n"
1038 " int type; // directional_light, point_light, spot_light, no_light\n"
1039 "};\n"
1040 "\n"
1041 "layout (std430) buffer Lights\n"
1042 "{\n"
1043 " Light light[num_lights];\n"
1044 "} lights;\n"
1045 "\n"
1046 "struct Material\n"
1047 "{\n"
1048 " vec3 ambient;\n"
1049 " vec3 diffuse;\n"
1050 " vec3 specular;\n"
1051 " vec3 emissive;\n"
1052 "\n"
1053 " float opacity;\n"
1054 " float shininess;\n"
1055 "};\n"
1056 "\n"
1057 "layout (std430) buffer Materials\n"
1058 "{\n"
1059 " Material material[num_materials];\n"
1060 "} materials;\n"
1061 "\n"
1062 "\n"
1063 "layout (std430) buffer GeomState\n"
1064 "{\n"
1065 " int material_index;\n"
1066 "} geom_state;\n"
1067 "\n"
1068 "layout(location = 0) out vec4 vFragColor;\n"
1069 "\n"
1070 "\n"
1071 "void main()\n"
1072 "{\n"
1073 "\n"
1074 " int type = lights.light[0].type;\n"
1075 " vec3 position = lights.light[0].position;\n"
1076 " vec3 spot_direction = lights.light[0].spot_direction;\n"
1077 " vec3 Ia = lights.light[0].Ia;\n"
1078 " vec3 Id = lights.light[0].Id;\n"
1079 " vec3 Is = lights.light[0].Is;\n"
1080 " vec3 attenuation = lights.light[0].attenuation;\n"
1081 " float spot_cos_cutoff = lights.light[0].spot_cos_cutoff;\n"
1082 " float spot_exponent = lights.light[0].spot_exponent;\n"
1083 "\n"
1084 " vec3 ambient = materials.material[0].ambient;\n"
1085 " vec3 diffuse = materials.material[0].diffuse;\n"
1086 " vec3 specular = materials.material[0].specular;\n"
1087 " vec3 emissive = materials.material[0].emissive;\n"
1088 " float opacity = materials.material[0].opacity;\n"
1089 " float shininess = materials.material[0].shininess;\n"
1090 "\n"
1091 " int material_index = geom_state.material_index;\n"
1092 "\n"
1093 " vec4 error = vec4(1.0, 0.0, 0.0, 1.0);\n"
1094 " vec4 color = vec4(0.0, 1.0, 0.0, 1.0);\n"
1095 "\n"
1096 " if (type != point_light)\n"
1097 " color = error;\n"
1098 "\n"
1099 " if (position != vec3(1.1, 2.2, 3.3))\n"
1100 " color = error;\n"
1101 "\n"
1102 " if (spot_direction != vec3(4.4, 5.5, 6.6))\n"
1103 " color = error;\n"
1104 "\n"
1105 " if (Ia != vec3(0.2, 0.2, 0.2))\n"
1106 " color = error;\n"
1107 "\n"
1108 " if (Id != vec3(0.4, 0.4, 0.4))\n"
1109 " color = error;\n"
1110 "\n"
1111 " if (Is != vec3(0.6, 0.6, 0.6))\n"
1112 " color = error;\n"
1113 "\n"
1114 " if (attenuation != vec3(0.8, 0.8, 0.8))\n"
1115 " color = error;\n"
1116 "\n"
1117 " if (spot_cos_cutoff != 0.8)\n"
1118 " color = error;\n"
1119 "\n"
1120 " if (spot_exponent != 12.3)\n"
1121 " color = error;\n"
1122 "\n"
1123 " if (ambient != vec3(0.1, 0.2, 0.3))\n"
1124 " color = error;\n"
1125 "\n"
1126 " if (diffuse != vec3(0.2, 0.4, 0.6))\n"
1127 " color = error;\n"
1128 "\n"
1129 " if (specular != vec3(0.4, 0.6, 0.8))\n"
1130 " color = error;\n"
1131 "\n"
1132 " if (emissive != vec3(0.6, 0.8, 1.0))\n"
1133 " color = error;\n"
1134 "\n"
1135 " if (opacity != 0.7)\n"
1136 " color = error;\n"
1137 "\n"
1138 " if (shininess != 25.4)\n"
1139 " color = error;\n"
1140 "\n"
1141 " if (material_index != 7)\n"
1142 " color = error;\n"
1143 "\n"
1144 "\n"
1145 " vFragColor = color;\n"
1146 "}\n"
1147 "\n"
1149 #endif
1150 return fp_program;