1 // OpenSG Tutorial Example: ComputeShader5
3 // This example shows a simple particle system that uses the
4 // compute shader to calculate the evolution of the system.
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.
13 #include <boost/foreach.hpp>
14 #include <boost/random.hpp>
16 #ifdef OSG_BUILD_ACTIVE
19 #include <OSGConfig.h>
20 #include <OSGSimpleGeometry.h>
21 #include <OSGGLUTWindow.h>
22 #include <OSGSimpleSceneManager.h>
23 #include <OSGBaseFunctions.h>
24 #include <OSGTransform.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>
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>
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>
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
;
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
;
115 Attractor() : position(0.f
, 0.f
, 0.f
), mass(0.f
) {}
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
);
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
);
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();
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
)
180 attractor_die() / attractor_factor
);
181 attractors
[i
].position
= p
;
182 attractors
[i
].mass
= 0.f
;
188 void update_attractors(VecAttractorsT
& attractors
)
190 for (std::size_t i
= 0; i
< attractors
.size(); ++i
)
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
)
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
);
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
[]);
461 // Initialize GLUT & OpenSG and set up the scene
463 int main(int argc
, char **argv
)
466 OSG::osgInit(argc
,argv
);
469 int winid
= setupGLUT(&argc
, argv
);
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
);
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());
494 OSG::commitChanges();
496 // show the whole scene
507 // GLUT callback functions
510 OSG::TimeStamp time_stamp
= 0;
511 OSG::Real32 simulation_time
= 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
;
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();
548 // react to size changes
550 void reshape(int w
, int h
)
557 // react to mouse button presses
559 void mouse(int button
, int state
, int x
, int y
)
562 mgr
->mouseButtonRelease(button
, x
, y
);
564 mgr
->mouseButtonPress(button
, x
, y
);
570 // react to mouse motions with pressed buttons
572 void motion(int x
, int y
)
574 mgr
->mouseMove(x
, y
);
581 void keyboard(unsigned char k
, int x
, int y
)
587 // clean up global variables
590 geoprops_position
= NULL
;
591 geoprops_lifetime
= NULL
;
593 ssbo_position
= NULL
;
594 ssbo_velocity
= NULL
;
595 ssbo_lifetime
= NULL
;
596 ssbo_attractor
= NULL
;
609 mgr
->setStatistics(!mgr
->getStatistics());
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
);
640 glutReshapeFunc(NULL
);
641 glutDisplayFunc(NULL
);
643 glutMotionFunc(NULL
);
644 glutKeyboardFunc(NULL
);
650 std::cout
<< "Esc : quit example" << std::endl
;
654 // compute shader program.
656 std::string
get_cp_program()
661 ost
<< "#version 430 compatibility"
663 << endl
<< "layout (local_size_x = 128, local_size_y = 1, local_size_z = 1) in;"
665 << endl
<< "layout (std430, binding = 1) buffer Positions"
667 << endl
<< " vec4 positions[];"
670 << endl
<< "layout (std430, binding = 2) buffer Velocities"
672 << endl
<< " vec4 velocities[];"
675 << endl
<< "layout (std430, binding = 3) buffer Lifetimes"
677 << endl
<< " float lifetimes[];"
680 << endl
<< "struct Attractor"
682 << endl
<< " vec3 position;"
683 << endl
<< " float mass;"
686 << endl
<< "layout (std430, binding = 4) buffer Attractors"
688 << endl
<< " Attractor attractors[];"
691 << endl
<< "// Delta time"
692 << endl
<< "uniform float dt;"
695 << endl
<< "// See: http://byteblacksmith.com/improvements-to-the-canonical-one-liner-glsl-rand-for-opengl-es-2-0/"
697 << endl
<< "highp float rand(vec2 v)"
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);"
707 << endl
<< "vec3 calcForceFor(vec3 forcePoint, vec3 pos)"
709 << endl
<< " float gauss = 10000.0;"
710 << endl
<< " float e = 2.71828183;"
711 << endl
<< " float k_weak = 1.0;"
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;"
717 << endl
<< " return f;"
720 << endl
<< "void main(void)"
722 << endl
<< " uint index = gl_GlobalInvocationID.x;"
724 << endl
<< " vec3 forcePoint = vec3(0);"
726 << endl
<< " for (int i = 0; i < attractors.length(); i++)"
728 << endl
<< " forcePoint += attractors[i].position;"
731 << endl
<< " vec3 vel = velocities[index].xyz;"
732 << endl
<< " vec3 pos = positions[index].xyz;"
733 << endl
<< " float lifetime = lifetimes[index];"
735 << endl
<< " float k_v = 1.5;"
737 << endl
<< " vec3 f = calcForceFor(forcePoint, pos) + rand(pos.xz)/100.0;"
739 << endl
<< " vec3 v = normalize(vel + (f * dt)) * k_v;"
741 << endl
<< " v += (forcePoint-pos) * 0.00005;"
743 << endl
<< " vec3 s = pos + v * dt;"
745 << endl
<< " lifetime -= 0.0001 * dt;"
747 << endl
<< " if (lifetime <= 0)"
749 << endl
<< " s = -s + rand(s.xy)*20.0 -rand(s.yz)*20.0;"
750 << endl
<< " lifetime = 0.99;"
754 << endl
<< " lifetimes[index] = lifetime;"
755 << endl
<< " positions[index] = vec4(s, 1.0);"
756 << endl
<< " velocities[index] = vec4(v, 0.0);"
765 // vertex shader program.
767 std::string
get_vp_program()
772 ost
<< "#version 430 compatibility"
774 << endl
<< "layout (location = 0) in vec4 vertPos;"
775 << endl
<< "layout (location = 1) in float lifetime;"
777 << endl
<< "uniform mat4 OSGModelViewMatrix;"
778 << endl
<< "uniform mat4 OSGProjectionMatrix;"
780 << endl
<< "out float color;"
782 << endl
<< "void main()"
784 << endl
<< " color = lifetime;"
785 << endl
<< " gl_Position = OSGProjectionMatrix * OSGModelViewMatrix * vertPos;"
794 // fragment shader program for bump mapping in surface local coordinates
796 std::string
get_fp_program()
801 ost
<< "#version 430 compatibility"
803 << endl
<< "in float color;"
805 << endl
<< "layout(location = 0) out vec4 vFragColor;"
807 << endl
<< "void main()"
809 << endl
<< " if (color < 0.1)"
811 << endl
<< " vFragColor = mix(vec4(vec3(0.0),1.0), vec4(0.0,0.5,1.0,1.0), color*10.0);"
813 << endl
<< " else if (color > 0.9)"
815 << endl
<< " vFragColor = mix(vec4(0.6,0.05,0.0,1.0), vec4(vec3(0.0),1.0), (color-0.9)*10.0);"
819 << endl
<< " vFragColor = mix(vec4(0.0,0.5,1.0,1.0), vec4(0.6,0.05,0.0,1.0), color);"