Add ClusterShadingStage
[opensg.git] / Examples / Advanced / computeshader6.cpp
blobb096fa6b0fddd1488197f1609b15c9cd0617b08b
1 // OpenSG Tutorial Example: ComputeShader5
2 //
3 // This example shows a simple particle system that uses the
4 // compute shader to calculate the evolution of the system.
5 //
6 // What is interesting is that the shader storage buffer block
7 // used by the compute shader for the particle positions is binded
8 // as an array buffer for the draw task thus streaming GL_POINTS
9 // into the drawing shaders.
12 #include <sstream>
13 #include <boost/foreach.hpp>
14 #include <boost/random.hpp>
16 #ifdef OSG_BUILD_ACTIVE
17 // Headers
18 #include <OSGGLUT.h>
19 #include <OSGConfig.h>
20 #include <OSGSimpleGeometry.h>
21 #include <OSGGLUTWindow.h>
22 #include <OSGSimpleSceneManager.h>
23 #include <OSGBaseFunctions.h>
24 #include <OSGTransform.h>
25 #include <OSGGroup.h>
27 // new headers:
28 #include <OSGGLEXT.h>
29 #include <OSGShaderProgramChunk.h>
30 #include <OSGShaderProgram.h>
31 #include <OSGShaderVariableOSG.h>
32 #include <OSGChunkMaterial.h>
33 #include <OSGMaterialGroup.h>
34 #include <OSGMaterialChunkOverrideGroup.h>
35 #include <OSGMultiPropertySSBOChunk.h>
36 #include <OSGShaderStorageBufferObjRefChunk.h>
37 #include <OSGShaderProgramVariableChunk.h>
38 #include <OSGAlgorithmComputeElement.h>
39 #include <OSGComputeShaderAlgorithm.h>
40 #include <OSGComputeShaderChunk.h>
41 #include <OSGShaderProgram.h>
42 #include <OSGShaderProgramVariables.h>
43 #include <OSGTypedGeoIntegralProperty.h>
44 #include <OSGTypedGeoVectorProperty.h>
45 #include <OSGGeoVectorBufferProperty.h>
47 #else
48 // Headers
49 #include <OpenSG/OSGGLUT.h>
50 #include <OpenSG/OSGConfig.h>
51 #include <OpenSG/OSGSimpleGeometry.h>
52 #include <OpenSG/OSGGLUTWindow.h>
53 #include <OpenSG/OSGSimpleSceneManager.h>
54 #include <OpenSG/OSGBaseFunctions.h>
55 #include <OpenSG/OSGTransform.h>
56 #include <OpenSG/OSGGroup.h>
58 // new headers:
59 #include <OpenSG/OSGGLEXT.h>
60 #include <OpenSG/OSGShaderProgramChunk.h>
61 #include <OpenSG/OSGShaderProgram.h>
62 #include <OpenSG/OSGShaderVariableOSG.h>
63 #include <OpenSG/OSGChunkMaterial.h>
64 #include <OpenSG/OSGMaterialGroup.h>
65 #include <OpenSG/OSGMaterialChunkOverrideGroup.h>
66 #include <OpenSG/OSGMultiPropertySSBOChunk.h>
67 #include <OpenSG/OSGShaderStorageBufferObjRefChunk.h>
68 #include <OpenSG/OSGShaderProgramVariableChunk.h>
69 #include <OpenSG/OSGAlgorithmComputeElement.h>
70 #include <OpenSG/OSGComputeShaderAlgorithm.h>
71 #include <OpenSG/OSGComputeShaderChunk.h>
72 #include <OpenSG/OSGShaderProgram.h>
73 #include <OpenSG/OSGShaderProgramVariables.h>
74 #include <OpenSG/OSGTypedGeoIntegralProperty.h>
75 #include <OpenSG/OSGTypedGeoVectorProperty.h>
76 #include <OpenSG/OSGGeoVectorBufferProperty.h>
77 #endif
79 const OSG::Real32 world_size = 500.0;
80 const OSG::UInt32 particle_count = 6000000;
81 const OSG::UInt32 attractor_count = 12;
82 const OSG::Real32 attractor_time = 5.0f;
83 const OSG::Real32 attractor_factor = 100.0f;
84 const OSG::Real32 delta_time = 100.0f;
86 const OSG::Vec3i work_group_count(particle_count / 128, 1,1);
88 const OSG::Real32 position_max = 4.0f;
89 const OSG::Real32 velocity_max = 0.3f;
90 const OSG::Real32 attractor_max = 60.0f;
92 boost::uniform_real<float> position_distribution ( -position_max, position_max);
93 boost::uniform_real<float> velocity_distribution ( -velocity_max, velocity_max);
94 boost::uniform_real<float> attractor_distribution(-attractor_max, attractor_max);
95 boost::uniform_01<float> lifetime_distribution;
97 typedef boost::mt19937 RNGType;
98 RNGType rng(time(0));
100 boost::variate_generator< RNGType, boost::uniform_real<float> > position_die(rng, position_distribution);
101 boost::variate_generator< RNGType, boost::uniform_real<float> > velocity_die(rng, velocity_distribution);
102 boost::variate_generator< RNGType, boost::uniform_real<float> > attractor_die(rng, attractor_distribution);
103 boost::variate_generator< RNGType, boost::uniform_01<float> > lifetime_die(rng, lifetime_distribution);
106 // The SimpleSceneManager to manage simple applications
108 OSG::SimpleSceneManagerRefPtr mgr;
111 // Simulation data
113 struct Attractor
115 Attractor() : position(0.f, 0.f, 0.f), mass(0.f) {}
116 OSG::Pnt3f position;
117 OSG::Real32 mass;
118 static OSG::UInt32 position_id;
119 static OSG::UInt32 mass_id;
121 OSG::UInt32 Attractor::position_id = 0;
122 OSG::UInt32 Attractor::mass_id = 0;
124 typedef std::vector<OSG::Pnt4f> VecPositionsT;
125 typedef std::vector<OSG::Vec4f> VecVelocitiesT;
126 typedef std::vector<OSG::Real32> VecLifetimesT;
127 typedef std::vector<Attractor> VecAttractorsT;
129 VecPositionsT initialize_positions(std::size_t num)
131 VecPositionsT positions;
132 positions.resize(num);
134 for (std::size_t i = 0; i < num; ++i)
136 OSG::Pnt4f p(position_die(), position_die(), position_die(), 1.f);
137 positions[i] = p;
140 return positions;
143 VecVelocitiesT initialize_velocities(std::size_t num)
145 VecVelocitiesT velocities;
146 velocities.resize(num);
148 for (std::size_t i = 0; i < num; ++i)
150 OSG::Vec4f v(velocity_die(), velocity_die(), velocity_die(), 0.f);
151 velocities[i] = v;
154 return velocities;
157 VecLifetimesT initialize_lifetimes(std::size_t num)
159 VecLifetimesT lifetimes;
160 lifetimes.resize(num);
162 for (std::size_t i = 0; i < num; ++i)
164 lifetimes[i] = lifetime_die();
167 return lifetimes;
170 VecAttractorsT initialize_attractors(std::size_t num)
172 VecAttractorsT attractors;
173 attractors.resize(num);
175 for (std::size_t i = 0; i < num; ++i)
177 OSG::Pnt3f p(
178 attractor_die(),
179 attractor_die(),
180 attractor_die() / attractor_factor);
181 attractors[i].position = p;
182 attractors[i].mass = 0.f;
185 return attractors;
188 void update_attractors(VecAttractorsT& attractors)
190 for (std::size_t i = 0; i < attractors.size(); ++i)
192 OSG::Pnt3f p(
193 attractor_die(),
194 attractor_die(),
195 attractor_die() / attractor_factor);
196 attractors[i].position = p;
197 attractors[i].mass = 0.f;
201 VecPositionsT positions = initialize_positions (particle_count);
202 VecVelocitiesT velocities = initialize_velocities(particle_count);
203 VecLifetimesT lifetimes = initialize_lifetimes (particle_count);
204 VecAttractorsT attractors = initialize_attractors(attractor_count);
206 OSG::GeoPnt4fPropertyTransitPtr create_position_property(const VecPositionsT& positions)
208 OSG::GeoPnt4fPropertyRefPtr properties = OSG::GeoPnt4fProperty::create();
210 properties->setUseVBO(true);
212 BOOST_FOREACH(const OSG::Pnt4f pnt, positions)
214 properties->push_back(pnt);
217 return OSG::GeoPnt4fPropertyTransitPtr(properties);
220 OSG::GeoVec4fPropertyTransitPtr create_velocity_property(const VecVelocitiesT& velocities)
222 OSG::GeoVec4fPropertyRefPtr properties = OSG::GeoVec4fProperty::create();
224 properties->setUseVBO(true);
226 BOOST_FOREACH(const OSG::Vec4f vec, velocities)
228 properties->push_back(vec);
231 return OSG::GeoVec4fPropertyTransitPtr(properties);
234 OSG::GeoVec1fPropertyTransitPtr create_lifetime_property(const VecLifetimesT& lifetimes)
236 OSG::GeoVec1fPropertyRefPtr properties = OSG::GeoVec1fProperty::create();
238 properties->setUseVBO(true);
240 BOOST_FOREACH(OSG::Real32 val, lifetimes)
242 properties->push_back(OSG::Vec1f(val));
245 return OSG::GeoVec1fPropertyTransitPtr(properties);
248 OSG::MultiPropertySSBOChunkTransitPtr create_attractor_ssbo_chunk(const VecAttractorsT& attractors)
250 OSG::MultiPropertySSBOChunkRefPtr attractorChunk = OSG::MultiPropertySSBOChunk::create();
252 OSG::UInt32 vec3_id, float_id;
254 vec3_id = attractorChunk->addMember(OSG::MultiPropertySSBOChunk:: VEC3_T);
255 float_id = attractorChunk->addMember(OSG::MultiPropertySSBOChunk::FLOAT_T);
257 attractorChunk->setUsage(GL_STATIC_DRAW);
259 Attractor::position_id = vec3_id++;
260 Attractor:: mass_id = float_id++;
262 BOOST_FOREACH(const Attractor& a, attractors)
264 OSG::UInt32 idx = attractorChunk->addProperty();
266 attractorChunk->setVec3Property (idx, Attractor::position_id, a.position.subZero());
267 attractorChunk->setFloatProperty(idx, Attractor:: mass_id, a.mass);
270 return OSG::MultiPropertySSBOChunkTransitPtr(attractorChunk);
273 void update_attractor_state(OSG::MultiPropertySSBOChunk* attractorChunk, const VecAttractorsT& attractors)
275 if (attractorChunk)
277 if (attractorChunk->getNumProperties() != attractors.size())
279 attractorChunk->clearProperties();
281 BOOST_FOREACH(const Attractor& a, attractors)
283 OSG::UInt32 idx = attractorChunk->addProperty();
285 attractorChunk->setVec3Property (idx, Attractor::position_id, a.position.subZero());
286 attractorChunk->setFloatProperty(idx, Attractor:: mass_id, a.mass);
289 else
291 for (OSG::UInt32 idx = 0; idx < attractors.size(); ++idx)
293 const Attractor& a = attractors[idx];
295 attractorChunk->setVec3Property (idx, Attractor::position_id, a.position.subZero());
296 attractorChunk->setFloatProperty(idx, Attractor:: mass_id, a.mass);
302 OSG::ShaderStorageBufferObjRefChunkTransitPtr create_ssbo_ref_chunk(OSG::UInt32 glId)
304 OSG::ShaderStorageBufferObjRefChunkRefPtr chunk = OSG::ShaderStorageBufferObjRefChunk::create();
306 chunk->setOsgGLId(glId);
308 return OSG::ShaderStorageBufferObjRefChunkTransitPtr(chunk);
312 // compute, vertex and fragment shader program.
314 std::string get_cp_program();
315 std::string get_vp_program();
316 std::string get_fp_program();
318 const OSG::UInt32 position_binding_point = 1;
319 const OSG::UInt32 velocity_binding_point = 2;
320 const OSG::UInt32 lifetime_binding_point = 3;
321 const OSG::UInt32 attractor_binding_point = 4;
324 // Proerties and shader storage buffer objects corresponding to the shader blocks
326 OSG::GeoVectorPropertyRefPtr geoprops_position = NULL;
327 OSG::GeoVectorPropertyRefPtr geoprops_velocity = NULL;
328 OSG::GeoVectorPropertyRefPtr geoprops_lifetime = NULL;
330 OSG::ShaderStorageBufferObjRefChunkRefPtr ssbo_position = NULL;
331 OSG::ShaderStorageBufferObjRefChunkRefPtr ssbo_velocity = NULL;
332 OSG::ShaderStorageBufferObjRefChunkRefPtr ssbo_lifetime = NULL;
334 OSG::MultiPropertySSBOChunkRefPtr ssbo_attractor = NULL;
336 OSG::ShaderProgramRefPtr compShader = NULL;
339 // The computation core
341 void createSimulationData()
343 geoprops_position = create_position_property(positions );
344 geoprops_velocity = create_velocity_property(velocities);
345 geoprops_lifetime = create_lifetime_property(lifetimes );
347 ssbo_position = create_ssbo_ref_chunk(geoprops_position->getGLId());
348 ssbo_velocity = create_ssbo_ref_chunk(geoprops_velocity->getGLId());
349 ssbo_lifetime = create_ssbo_ref_chunk(geoprops_lifetime->getGLId());
351 ssbo_attractor = create_attractor_ssbo_chunk(attractors);
354 OSG::AlgorithmComputeElementTransitPtr createComputation()
356 OSG::ChunkMaterialRefPtr data_state = OSG::ChunkMaterial::create();
357 data_state->addChunk(ssbo_position, position_binding_point);
358 data_state->addChunk(ssbo_velocity, velocity_binding_point);
359 data_state->addChunk(ssbo_lifetime, lifetime_binding_point);
360 data_state->addChunk(ssbo_attractor, attractor_binding_point);
362 compShader = OSG::ShaderProgram::create();
363 compShader->setShaderType(GL_COMPUTE_SHADER);
364 compShader->setProgram(get_cp_program());
365 compShader->addUniformVariable("dt", 0.f);
366 compShader->addShaderStorageBlock("Positions", position_binding_point);
367 compShader->addShaderStorageBlock("Velocities", velocity_binding_point);
368 compShader->addShaderStorageBlock("Lifetimes", lifetime_binding_point);
369 compShader->addShaderStorageBlock("Attractors", attractor_binding_point);
371 OSG::ComputeShaderChunkRefPtr compShaderChunk = OSG::ComputeShaderChunk::create();
372 compShaderChunk->addComputeShader(compShader);
373 compShaderChunk->setVariables(compShader->getVariables());
375 OSG::ComputeShaderAlgorithmRefPtr compShaderAlgo = OSG::ComputeShaderAlgorithm::create();
376 compShaderAlgo->setUseMemoryBarrier(true);
377 compShaderAlgo->setMemoryBarrier(GL_SHADER_STORAGE_BARRIER_BIT);
378 compShaderAlgo->setComputeShader(compShaderChunk);
379 compShaderAlgo->setDispatchConfig(work_group_count);
380 compShaderAlgo->setChunkMaterial(data_state);
382 OSG::AlgorithmComputeElementRefPtr algoCompElement = OSG::AlgorithmComputeElement::create();
383 algoCompElement->setAlgorithm(compShaderAlgo);
385 return OSG::AlgorithmComputeElementTransitPtr(algoCompElement);
389 // The scene to be rendered
391 OSG::NodeTransitPtr createScene()
393 OSG::NodeRefPtr scene = OSG::Node::create();
395 OSG::GeometryRefPtr geometry = OSG::Geometry::create();
396 geometry->setDlistCache(false);
397 geometry->setUseVAO(true);
398 geometry->setUseAttribCalls(true);
400 OSG::NodeRefPtr geomNode = OSG::makeNodeFor(geometry);
402 OSG::GeoUInt8PropertyRefPtr types = OSG::GeoUInt8Property ::create();
403 OSG::GeoUInt32PropertyRefPtr lengths = OSG::GeoUInt32Property::create();
405 types ->addValue(GL_POINTS);
406 lengths->addValue(particle_count);
408 types ->setUseVBO(true);
409 lengths ->setUseVBO(true);
411 types ->setUsage(OSG::GeoProperty::UsageSystemSet);
412 lengths ->setUsage(OSG::GeoProperty::UsageSystemSet);
414 geometry->setTypes (types);
415 geometry->setLengths (lengths);
417 geometry->setProperty (geoprops_position, 0);
418 geometry->setProperty (geoprops_lifetime, 1);
420 OSG::BoxVolume& volume = geomNode->editVolume();
422 volume.setBounds(OSG::Pnt3f(-world_size,-world_size,-world_size), OSG::Pnt3f(world_size,world_size,world_size));
423 volume.setStatic(true);
425 scene->addChild(geomNode);
428 // create the shader program
430 OSG::ShaderProgramChunkRefPtr prog_chunk = OSG::ShaderProgramChunk::create();
431 OSG::ShaderProgramRefPtr vertShader = OSG::ShaderProgram::createVertexShader();
432 OSG::ShaderProgramRefPtr fragShader = OSG::ShaderProgram::createFragmentShader();
434 vertShader->setProgram(get_vp_program());
435 fragShader->setProgram(get_fp_program());
437 vertShader->addOSGVariable("OSGModelViewMatrix");
438 vertShader->addOSGVariable("OSGProjectionMatrix");
440 prog_chunk->addShader(vertShader);
441 prog_chunk->addShader(fragShader);
443 OSG::ChunkMaterialRefPtr prog_state = OSG::ChunkMaterial::create();
444 prog_state->addChunk(prog_chunk);
446 OSG::MaterialChunkOverrideGroupRefPtr mgrp = OSG::MaterialChunkOverrideGroup::create();
447 mgrp->setMaterial(prog_state);
448 scene->setCore(mgrp);
450 return OSG::NodeTransitPtr(scene);
454 // forward declaration so we can have the interesting stuff upfront
456 int setupGLUT(int *argc, char *argv[]);
457 void releaseGLUT();
458 void print_help();
461 // Initialize GLUT & OpenSG and set up the scene
463 int main(int argc, char **argv)
465 // OSG init
466 OSG::osgInit(argc,argv);
468 // GLUT init
469 int winid = setupGLUT(&argc, argv);
471 print_help();
473 // open a new scope, because the pointers below should go out of scope
474 // before entering glutMainLoop.
475 // Otherwise OpenSG will complain about objects being alive after shutdown.
477 // the connection between GLUT and OpenSG
478 OSG::GLUTWindowRefPtr gwin = OSG::GLUTWindow::create();
479 gwin->setGlutId(winid);
480 gwin->init();
482 // create the SimpleSceneManager helper
483 mgr = OSG::SimpleSceneManager::create();
484 mgr->setWindow(gwin);
486 createSimulationData();
488 OSG::NodeRefPtr root = OSG::makeNodeFor(createComputation());
490 root->addChild(createScene());
492 mgr->setRoot(root);
494 OSG::commitChanges();
496 // show the whole scene
497 mgr->showAll();
500 // GLUT main loop
501 glutMainLoop();
503 return 0;
507 // GLUT callback functions
510 OSG::TimeStamp time_stamp = 0;
511 OSG::Real32 simulation_time = 0;
514 // redraw the window
516 void display(void)
518 if (time_stamp == 0)
519 time_stamp = OSG::getTimeStamp();
521 OSG::TimeStamp now = OSG::getTimeStamp();
522 OSG::Time elapsed = OSG::getTimeStampMsecs(now - time_stamp);
524 OSG::Real32 dt = elapsed / 1000.f;
526 simulation_time += dt;
528 if (compShader)
529 compShader->updateUniformVariable("dt", delta_time * OSG::Real32(elapsed) / 1000.f);
531 if (simulation_time >= attractor_time)
533 update_attractors(attractors);
534 update_attractor_state(ssbo_attractor, attractors);
536 simulation_time = 0.f;
539 OSG::commitChanges();
541 mgr->redraw();
543 time_stamp = now;
548 // react to size changes
550 void reshape(int w, int h)
552 mgr->resize(w, h);
553 glutPostRedisplay();
557 // react to mouse button presses
559 void mouse(int button, int state, int x, int y)
561 if (state)
562 mgr->mouseButtonRelease(button, x, y);
563 else
564 mgr->mouseButtonPress(button, x, y);
566 glutPostRedisplay();
570 // react to mouse motions with pressed buttons
572 void motion(int x, int y)
574 mgr->mouseMove(x, y);
575 glutPostRedisplay();
579 // react to keys
581 void keyboard(unsigned char k, int x, int y)
583 switch(k)
585 case 27:
587 // clean up global variables
588 mgr = NULL;
590 geoprops_position = NULL;
591 geoprops_lifetime = NULL;
593 ssbo_position = NULL;
594 ssbo_velocity = NULL;
595 ssbo_lifetime = NULL;
596 ssbo_attractor = NULL;
598 compShader = NULL;
600 releaseGLUT();
602 OSG::osgExit();
603 exit(0);
605 break;
607 case 's':
609 mgr->setStatistics(!mgr->getStatistics());
611 break;
616 // setup the GLUT library which handles the windows for us
618 int setupGLUT(int *argc, char *argv[])
620 glutInit(argc, argv);
621 glutInitDisplayMode(GLUT_RGB | GLUT_DEPTH | GLUT_DOUBLE);
622 glutInitWindowSize(1000, 800);
624 int winid = glutCreateWindow("OpenSG");
626 glutReshapeFunc(reshape);
627 glutDisplayFunc(display);
628 glutMouseFunc(mouse);
629 glutMotionFunc(motion);
630 glutKeyboardFunc(keyboard);
632 // call the redraw function whenever there's nothing else to do
633 glutIdleFunc(display);
635 return winid;
638 void releaseGLUT()
640 glutReshapeFunc(NULL);
641 glutDisplayFunc(NULL);
642 glutMouseFunc(NULL);
643 glutMotionFunc(NULL);
644 glutKeyboardFunc(NULL);
645 glutIdleFunc(NULL);
648 void print_help()
650 std::cout << "Esc : quit example" << std::endl;
654 // compute shader program.
656 std::string get_cp_program()
658 using namespace std;
659 stringstream ost;
661 ost << "#version 430 compatibility"
662 << endl << ""
663 << endl << "layout (local_size_x = 128, local_size_y = 1, local_size_z = 1) in;"
664 << endl << ""
665 << endl << "layout (std430, binding = 1) buffer Positions"
666 << endl << "{"
667 << endl << " vec4 positions[];"
668 << endl << "};"
669 << endl << ""
670 << endl << "layout (std430, binding = 2) buffer Velocities"
671 << endl << "{"
672 << endl << " vec4 velocities[];"
673 << endl << "};"
674 << endl << ""
675 << endl << "layout (std430, binding = 3) buffer Lifetimes"
676 << endl << "{"
677 << endl << " float lifetimes[];"
678 << endl << "};"
679 << endl << ""
680 << endl << "struct Attractor"
681 << endl << "{"
682 << endl << " vec3 position;"
683 << endl << " float mass;"
684 << endl << "};"
685 << endl << ""
686 << endl << "layout (std430, binding = 4) buffer Attractors"
687 << endl << "{"
688 << endl << " Attractor attractors[];"
689 << endl << "};"
690 << endl << ""
691 << endl << "// Delta time"
692 << endl << "uniform float dt;"
693 << endl << ""
694 << endl << "//"
695 << endl << "// See: http://byteblacksmith.com/improvements-to-the-canonical-one-liner-glsl-rand-for-opengl-es-2-0/"
696 << endl << "//"
697 << endl << "highp float rand(vec2 v)"
698 << endl << "{"
699 << endl << " highp float a = 12.9898;"
700 << endl << " highp float b = 78.233;"
701 << endl << " highp float c = 43758.5453;"
702 << endl << " highp float d = dot(v.xy, vec2(a,b));"
703 << endl << " highp float e = mod(d, 3.14);"
704 << endl << " return fract(sin(e) * c);"
705 << endl << "}"
706 << endl << ""
707 << endl << "vec3 calcForceFor(vec3 forcePoint, vec3 pos)"
708 << endl << "{"
709 << endl << " float gauss = 10000.0;"
710 << endl << " float e = 2.71828183;"
711 << endl << " float k_weak = 1.0;"
712 << endl << ""
713 << endl << " vec3 dir = forcePoint - pos.xyz;"
714 << endl << " float g = pow (e, -pow(length(dir), 2) / gauss);"
715 << endl << " vec3 f = normalize(dir) * k_weak * (1+ mod(rand(dir.xy), 10) - mod(rand(dir.yz), 10)) / 10.0 * g;"
716 << endl << ""
717 << endl << " return f;"
718 << endl << "}"
719 << endl << ""
720 << endl << "void main(void)"
721 << endl << "{"
722 << endl << " uint index = gl_GlobalInvocationID.x;"
723 << endl << ""
724 << endl << " vec3 forcePoint = vec3(0);"
725 << endl << ""
726 << endl << " for (int i = 0; i < attractors.length(); i++)"
727 << endl << " {"
728 << endl << " forcePoint += attractors[i].position;"
729 << endl << " }"
730 << endl << ""
731 << endl << " vec3 vel = velocities[index].xyz;"
732 << endl << " vec3 pos = positions[index].xyz;"
733 << endl << " float lifetime = lifetimes[index];"
734 << endl << ""
735 << endl << " float k_v = 1.5;"
736 << endl << ""
737 << endl << " vec3 f = calcForceFor(forcePoint, pos) + rand(pos.xz)/100.0;"
738 << endl << ""
739 << endl << " vec3 v = normalize(vel + (f * dt)) * k_v;"
740 << endl << ""
741 << endl << " v += (forcePoint-pos) * 0.00005;"
742 << endl << ""
743 << endl << " vec3 s = pos + v * dt;"
744 << endl << ""
745 << endl << " lifetime -= 0.0001 * dt;"
746 << endl << ""
747 << endl << " if (lifetime <= 0)"
748 << endl << " {"
749 << endl << " s = -s + rand(s.xy)*20.0 -rand(s.yz)*20.0;"
750 << endl << " lifetime = 0.99;"
751 << endl << " }"
752 << endl << ""
753 << endl << ""
754 << endl << " lifetimes[index] = lifetime;"
755 << endl << " positions[index] = vec4(s, 1.0);"
756 << endl << " velocities[index] = vec4(v, 0.0);"
757 << endl << "}"
758 << endl << ""
759 << endl;
761 return ost.str();
765 // vertex shader program.
767 std::string get_vp_program()
769 using namespace std;
770 stringstream ost;
772 ost << "#version 430 compatibility"
773 << endl << ""
774 << endl << "layout (location = 0) in vec4 vertPos;"
775 << endl << "layout (location = 1) in float lifetime;"
776 << endl << ""
777 << endl << "uniform mat4 OSGModelViewMatrix;"
778 << endl << "uniform mat4 OSGProjectionMatrix;"
779 << endl << ""
780 << endl << "out float color;"
781 << endl << ""
782 << endl << "void main()"
783 << endl << "{"
784 << endl << " color = lifetime;"
785 << endl << " gl_Position = OSGProjectionMatrix * OSGModelViewMatrix * vertPos;"
786 << endl << "}"
787 << endl << ""
788 << endl;
790 return ost.str();
794 // fragment shader program for bump mapping in surface local coordinates
796 std::string get_fp_program()
798 using namespace std;
799 stringstream ost;
801 ost << "#version 430 compatibility"
802 << endl << ""
803 << endl << "in float color;"
804 << endl << ""
805 << endl << "layout(location = 0) out vec4 vFragColor;"
806 << endl << ""
807 << endl << "void main()"
808 << endl << "{"
809 << endl << " if (color < 0.1)"
810 << endl << " {"
811 << endl << " vFragColor = mix(vec4(vec3(0.0),1.0), vec4(0.0,0.5,1.0,1.0), color*10.0);"
812 << endl << " }"
813 << endl << " else if (color > 0.9)"
814 << endl << " {"
815 << endl << " vFragColor = mix(vec4(0.6,0.05,0.0,1.0), vec4(vec3(0.0),1.0), (color-0.9)*10.0);"
816 << endl << " }"
817 << endl << " else"
818 << endl << " {"
819 << endl << " vFragColor = mix(vec4(0.0,0.5,1.0,1.0), vec4(0.6,0.05,0.0,1.0), color);"
820 << endl << " }"
821 << endl << "}"
822 << endl << ""
823 << endl;
825 return ost.str();