fixed: auto_ptr -> unique_ptr
[opensg.git] / Examples / Advanced / computeshader3.cpp
blob871d310004c7cc0716e84709e6695127b4846342
1 // OpenSG Example: ComputeShader3
2 //
3 // This example shows the basic usage of the compute shader.
4 // It is a variation of the ComplexSceneManager example
5 // found in Examples/CSM/NewShader/Compute/SimpleTex.
6 //
7 // In this example a material database in form of a shader storage
8 // buffer object is used in the shader in order to color the pixels
9 // of the image differently. The setup of the shader storage buffer
10 // object is shown and the example works with a variable work
11 // group size for illustration purpose. Additionally, the use of a
12 // memory barrier at the end of the comptuation is shown.
14 #include <boost/foreach.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 <OSGAlgorithmComputeElement.h>
29 #include <OSGChunkMaterial.h>
30 #include <OSGComputeShaderAlgorithm.h>
31 #include <OSGComputeShaderChunk.h>
32 #include <OSGContainerCollection.h>
33 #include <OSGFieldConnector.h>
34 #include <OSGFrameHandler.h>
35 #include <OSGGeometry.h>
36 #include <OSGImage.h>
37 #include <OSGImageFileHandler.h>
38 #include <OSGMaterialChunk.h>
39 #include <OSGMaterialGroup.h>
40 #include <OSGMultiPropertySSBOChunk.h>
41 #include <OSGShaderProgram.h>
42 #include <OSGShaderProgramVariables.h>
43 #include <OSGShaderVariableReal.h>
44 #include <OSGTextureObjChunk.h>
45 #include <OSGTextureEnvChunk.h>
46 #include <OSGTextureImageChunk.h>
47 #include <OSGTime.h>
48 #include <OSGTimeSensor.h>
49 #include <OSGTypedGeoIntegralProperty.h>
50 #include <OSGTypedGeoVectorProperty.h>
51 #include <OSGVRMLScalarInterpolator.h>
52 #else
53 // Headers
54 #include <OpenSG/OSGGLUT.h>
55 #include <OpenSG/OSGConfig.h>
56 #include <OpenSG/OSGSimpleGeometry.h>
57 #include <OpenSG/OSGGLUTWindow.h>
58 #include <OpenSG/OSGSimpleSceneManager.h>
59 #include <OpenSG/OSGBaseFunctions.h>
60 #include <OpenSG/OSGTransform.h>
61 #include <OpenSG/OSGGroup.h>
63 // new headers:
64 #include <OpenSG/OSGAlgorithmComputeElement.h>
65 #include <OpenSG/OSGChunkMaterial.h>
66 #include <OpenSG/OSGComputeShaderAlgorithm.h>
67 #include <OpenSG/OSGComputeShaderChunk.h>
68 #include <OpenSG/OSGContainerCollection.h>
69 #include <OpenSG/OSGFieldConnector.h>
70 #include <OpenSG/OSGFrameHandler.h>
71 #include <OpenSG/OSGGeometry.h>
72 #include <OpenSG/OSGImage.h>
73 #include <OpenSG/OSGImageFileHandler.h>
74 #include <OpenSG/OSGMaterialChunk.h>
75 #include <OpenSG/OSGMaterialGroup.h>
76 #include <OpenSG/OSGMultiPropertySSBOChunk.h>
77 #include <OpenSG/OSGShaderProgram.h>
78 #include <OpenSG/OSGShaderProgramVariables.h>
79 #include <OpenSG/OSGShaderVariableReal.h>
80 #include <OpenSG/OSGTextureObjChunk.h>
81 #include <OpenSG/OSGTextureEnvChunk.h>
82 #include <OpenSG/OSGTextureImageChunk.h>
83 #include <OpenSG/OSGTime.h>
84 #include <OpenSG/OSGTimeSensor.h>
85 #include <OpenSG/OSGTypedGeoIntegralProperty.h>
86 #include <OpenSG/OSGTypedGeoVectorProperty.h>
87 #include <OpenSG/OSGVRMLScalarInterpolator.h>
88 #endif
90 const OSG::Vec3i work_group_count(32,32,1);
91 const OSG::Vec3i work_group_size(16,16,1);
93 const std::size_t num_materials = (work_group_size.z()-1) * work_group_size.y() * work_group_size.x()
94 + (work_group_size.y()-1) * work_group_size.x()
95 + (work_group_size.x()-1)
96 + 1;
98 // Simple material data structure
100 struct Material
102 Material()
103 : ambient (0.f, 0.f, 0.f)
104 , diffuse (0.f, 0.f, 0.f)
105 , specular(0.f, 0.f, 0.f)
106 , emissive(0.f, 0.f, 0.f)
107 , opacity(1.f)
108 , shininess(100.f)
111 OSG::Color3f ambient;
112 OSG::Color3f diffuse;
113 OSG::Color3f specular;
114 OSG::Color3f emissive;
116 OSG::Real32 opacity;
117 OSG::Real32 shininess;
119 static OSG::UInt32 ambient_id;
120 static OSG::UInt32 diffuse_id;
121 static OSG::UInt32 specular_id;
122 static OSG::UInt32 emissive_id;
123 static OSG::UInt32 opacity_id;
124 static OSG::UInt32 shininess_id;
127 OSG::UInt32 Material:: ambient_id = 0;
128 OSG::UInt32 Material:: diffuse_id = 0;
129 OSG::UInt32 Material:: specular_id = 0;
130 OSG::UInt32 Material:: emissive_id = 0;
131 OSG::UInt32 Material:: opacity_id = 0;
132 OSG::UInt32 Material::shininess_id = 0;
134 typedef std::vector<Material> VecMaterialsT; // multiple materials
136 VecMaterialsT initialize_materials(std::size_t num) // helper to create materials
138 VecMaterialsT mat(num);
140 for (std::size_t i = 0; i < num; ++i)
142 mat[i].ambient = OSG::Color3f(0.001f, 0.001f, 0.001f);
143 mat[i].diffuse.setRandom();
144 mat[i].specular = OSG::Color3f(0.9f, 0.9f, 0.9f);
145 mat[i].emissive = OSG::Color3f(0.0f, 0.0f, 0.0f);
146 mat[i].opacity = 1.f;
147 mat[i].shininess = 100.f;
150 return mat;
153 VecMaterialsT materials = initialize_materials(num_materials); // the material database
155 OSG::MultiPropertySSBOChunkTransitPtr create_material_database_state(const VecMaterialsT& vMaterials)
157 OSG::MultiPropertySSBOChunkRefPtr materialChunk = OSG::MultiPropertySSBOChunk::create();
159 OSG::UInt32 vec3_id, float_id;
161 vec3_id = materialChunk->addMember(OSG::MultiPropertySSBOChunk:: VEC3_T, 4);
162 float_id = materialChunk->addMember(OSG::MultiPropertySSBOChunk::FLOAT_T, 2);
164 materialChunk->setUsage(GL_STATIC_DRAW);
166 Material:: ambient_id = vec3_id++;
167 Material:: diffuse_id = vec3_id++;
168 Material:: specular_id = vec3_id++;
169 Material:: emissive_id = vec3_id;
171 Material:: opacity_id = float_id++;
172 Material::shininess_id = float_id;
174 BOOST_FOREACH(const Material& mat, vMaterials)
176 OSG::UInt32 idx = materialChunk->addProperty();
178 materialChunk->setVec3Property (idx, Material:: ambient_id, mat.ambient);
179 materialChunk->setVec3Property (idx, Material:: diffuse_id, mat.diffuse);
180 materialChunk->setVec3Property (idx, Material:: specular_id, mat.specular);
181 materialChunk->setVec3Property (idx, Material:: emissive_id, mat.emissive);
183 materialChunk->setFloatProperty(idx, Material:: opacity_id, mat.opacity);
184 materialChunk->setFloatProperty(idx, Material::shininess_id, mat.shininess);
187 return OSG::MultiPropertySSBOChunkTransitPtr(materialChunk);
190 void update_material_database_state(OSG::MultiPropertySSBOChunk* materialChunk, const VecMaterialsT& vMaterials)
192 if (materialChunk)
194 if (materialChunk->getNumProperties() != vMaterials.size())
196 materialChunk->clearProperties();
198 BOOST_FOREACH(const Material& mat, vMaterials)
200 OSG::UInt32 idx = materialChunk->addProperty();
202 materialChunk->setVec3Property (idx, Material:: ambient_id, mat.ambient);
203 materialChunk->setVec3Property (idx, Material:: diffuse_id, mat.diffuse);
204 materialChunk->setVec3Property (idx, Material:: specular_id, mat.specular);
205 materialChunk->setVec3Property (idx, Material:: emissive_id, mat.emissive);
207 materialChunk->setFloatProperty(idx, Material:: opacity_id, mat.opacity);
208 materialChunk->setFloatProperty(idx, Material::shininess_id, mat.shininess);
211 else
213 for (OSG::UInt32 idx = 0; idx < vMaterials.size(); ++idx)
215 const Material& mat = vMaterials[idx];
217 materialChunk->setVec3Property (idx, Material:: ambient_id, mat.ambient);
218 materialChunk->setVec3Property (idx, Material:: diffuse_id, mat.diffuse);
219 materialChunk->setVec3Property (idx, Material:: specular_id, mat.specular);
220 materialChunk->setVec3Property (idx, Material:: emissive_id, mat.emissive);
222 materialChunk->setFloatProperty(idx, Material:: opacity_id, mat.opacity);
223 materialChunk->setFloatProperty(idx, Material::shininess_id, mat.shininess);
229 OSG::SimpleSceneManagerRefPtr mgr = NULL;
231 OSG::MultiPropertySSBOChunkRefPtr ssbo_data_state = NULL;
233 std::string get_cp_program();
235 OSG::NodeTransitPtr createPlane(OSG::TextureObjChunk* texObjChunk)
237 OSG::MaterialChunkRefPtr matChunk = OSG::MaterialChunk::create();
238 matChunk->setDiffuse(OSG::Color4f(0.f, 0.f, 0.f, 1.f));
240 OSG::TextureEnvChunkRefPtr texEnvChunk = OSG::TextureEnvChunk::create();
241 texEnvChunk->setEnvMode(GL_REPLACE);
243 OSG::ChunkMaterialRefPtr chunkMaterial = OSG::ChunkMaterial::create();
244 chunkMaterial->addChunk(texObjChunk, 0);
245 chunkMaterial->addChunk(texEnvChunk);
246 chunkMaterial->addChunk(matChunk);
249 OSG::MaterialGroupRefPtr matGroup = OSG::MaterialGroup::create();
250 matGroup->setMaterial(chunkMaterial);
252 OSG::NodeRefPtr plane = OSG::makeNodeFor(matGroup);
254 OSG::GeometryRefPtr geometry = OSG::Geometry::create();
255 geometry->setDlistCache(false);
256 geometry->setUseVAO(true);
257 geometry->setUseAttribCalls(true);
259 OSG::NodeRefPtr geomNode = OSG::makeNodeFor(geometry);
261 OSG::GeoUInt8PropertyRefPtr types = OSG::GeoUInt8Property ::create();
262 OSG::GeoUInt32PropertyRefPtr lengths = OSG::GeoUInt32Property::create();
263 OSG::GeoPnt3fPropertyRefPtr vertices = OSG::GeoPnt3fProperty ::create();
264 OSG::GeoVec3fPropertyRefPtr normals = OSG::GeoVec3fProperty ::create();
265 OSG::GeoColor3fPropertyRefPtr colors = OSG::GeoColor3fProperty::create();
266 OSG::GeoVec2fPropertyRefPtr textures = OSG::GeoVec2fProperty ::create();
267 OSG::GeoUInt32PropertyRefPtr indices = OSG::GeoUInt32Property::create();
269 types ->setUseVBO(true);
270 lengths ->setUseVBO(true);
271 indices ->setUseVBO(true);
272 vertices->setUseVBO(true);
273 normals ->setUseVBO(true);
274 colors ->setUseVBO(true);
275 textures->setUseVBO(true);
277 types ->setUsage(OSG::GeoProperty::UsageSystemSet);
278 lengths ->setUsage(OSG::GeoProperty::UsageSystemSet);
279 indices ->setUsage(OSG::GeoProperty::UsageSystemSet);
280 vertices->setUsage(OSG::GeoProperty::UsageSystemSet);
281 normals ->setUsage(OSG::GeoProperty::UsageSystemSet);
282 colors ->setUsage(OSG::GeoProperty::UsageSystemSet);
283 textures->setUsage(OSG::GeoProperty::UsageSystemSet);
285 types ->push_back(4);
286 lengths->push_back(6);
288 indices->push_back(0);
289 indices->push_back(1);
290 indices->push_back(2);
291 indices->push_back(0);
292 indices->push_back(2);
293 indices->push_back(3);
295 vertices->push_back(OSG::Pnt3f(-1.f,-1.f,-1.f));
296 vertices->push_back(OSG::Pnt3f( 1.f,-1.f,-1.f));
297 vertices->push_back(OSG::Pnt3f( 1.f, 1.f,-3.f));
298 vertices->push_back(OSG::Pnt3f(-1.f, 1.f,-3.f));
300 normals->push_back(OSG::Vec3f(0.f, 0.f, 1.f));
301 normals->push_back(OSG::Vec3f(0.f, 0.f, 1.f));
302 normals->push_back(OSG::Vec3f(0.f, 0.f, 1.f));
303 normals->push_back(OSG::Vec3f(0.f, 0.f, 1.f));
305 colors->push_back(OSG::Color3f(0.f, 1.f, 0.f));
307 textures->push_back(OSG::Vec2i(0,0));
308 textures->push_back(OSG::Vec2i(1,0));
309 textures->push_back(OSG::Vec2i(1,1));
310 textures->push_back(OSG::Vec2i(0,1));
312 geometry->setTypes (types);
313 geometry->setLengths (lengths);
314 geometry->setIndices (indices);
315 geometry->setPositions(vertices);
316 geometry->setNormals (normals);
317 geometry->setColors (colors);
318 geometry->setTexCoords(textures);
320 plane->addChild(geomNode);
322 return OSG::NodeTransitPtr(plane);
325 OSG::NodeTransitPtr createScene()
327 const OSG::UInt32 data_binding_point = 5;
329 ssbo_data_state = create_material_database_state(materials);
331 OSG::ChunkMaterialRefPtr data_state = OSG::ChunkMaterial::create();
332 data_state->addChunk(ssbo_data_state, data_binding_point);
334 OSG::ImageRefPtr image = OSG::ImageFileHandler::the()->read("Examples/CSM/Models/Textures/Earth512.png");
336 OSG::TextureObjChunkRefPtr texObjChunk = OSG::TextureObjChunk::create();
337 texObjChunk->setInternalFormat(GL_RGBA32F);
338 texObjChunk->setMinFilter(GL_LINEAR);
339 texObjChunk->setMagFilter(GL_LINEAR);
340 texObjChunk->setImage(image);
342 OSG::NodeRefPtr planeNode = createPlane(texObjChunk);
344 OSG::AlgorithmComputeElementRefPtr algoCompElement = OSG::AlgorithmComputeElement::create();
345 OSG::NodeRefPtr computeNode = OSG::makeNodeFor(algoCompElement);
346 computeNode->addChild(planeNode);
348 OSG::ComputeShaderAlgorithmRefPtr compShaderAlgo = OSG::ComputeShaderAlgorithm::create();
349 algoCompElement->setAlgorithm(compShaderAlgo);
351 OSG::TextureImageChunkRefPtr texImgChunk = OSG::TextureImageChunk::create();
352 texImgChunk->setTexture(texObjChunk);
353 texImgChunk->setAccess(GL_WRITE_ONLY);
354 texImgChunk->setFormat(GL_RGBA32F);
356 data_state->addChunk(texImgChunk, 0);
358 OSG::ShaderProgramRefPtr compShader = OSG::ShaderProgram::create();
359 compShader->setShaderType(GL_COMPUTE_SHADER);
360 compShader->setProgram(get_cp_program());
361 compShader->addUniformVariable("destTex", 0);
362 compShader->addUniformVariable("roll", 0.f);
363 compShader->addShaderStorageBlock("Materials", data_binding_point); // block binding point
365 OSG::ComputeShaderChunkRefPtr compShaderChunk = OSG::ComputeShaderChunk::create();
366 compShaderChunk->addComputeShader(compShader);
367 compShaderChunk->setVariables(compShader->getVariables());
369 compShaderAlgo->setUseMemoryBarrier(true);
370 compShaderAlgo->setUseVariableWorkGroupSize(true);
371 compShaderAlgo->setMemoryBarrier(GL_SHADER_STORAGE_BARRIER_BIT);
372 compShaderAlgo->setComputeShader(compShaderChunk);
373 compShaderAlgo->setDispatchConfig(work_group_count);
374 compShaderAlgo->setWorkGroupSize(work_group_size);
375 compShaderAlgo->setChunkMaterial(data_state);
377 OSG::NodeRefPtr scene = OSG::makeCoredNode<OSG::Group>();
378 scene->addChild(computeNode);
380 OSG::TimeSensorRefPtr sceneTimer = OSG::TimeSensor::create();
381 sceneTimer->setLoop(true);
382 sceneTimer->setCycleInterval(10);
384 OSG::VRMLScalarInterpolatorRefPtr rollInter = OSG::VRMLScalarInterpolator::create();
385 rollInter->editMFKeyValue()->push_back(0.f);
386 rollInter->editMFKeyValue()->push_back(10.24f);
388 rollInter->editMFKey()->push_back(0.f);
389 rollInter->editMFKey()->push_back(1.f);
391 const OSG::ShaderVariableReal* varRealRoll = dynamic_cast<const OSG::ShaderVariableReal*>(compShader->getVariables()->getVariable("roll"));
393 addConnection(sceneTimer, "fraction", rollInter, "inValue");
394 addConnection(rollInter, "outValue", const_cast<OSG::ShaderVariableReal*>(varRealRoll), "value");
396 OSG::ContainerCollectionRefPtr containerCollection = OSG::ContainerCollection::create();
398 containerCollection->addContainer(rollInter);
399 containerCollection->addContainer(sceneTimer);
401 scene->addAttachment(containerCollection);
403 return OSG::NodeTransitPtr(scene);
407 // forward declaration so we can have the interesting stuff upfront
409 int setupGLUT(int *argc, char *argv[]);
410 void releaseGLUT();
411 void print_help();
414 // Initialize GLUT & OpenSG and set up the scene
416 int main(int argc, char **argv)
418 OSG::preloadSharedObject("OSGImageFileIO");
420 // OSG init
421 OSG::osgInit(argc,argv);
423 // GLUT init
424 int winid = setupGLUT(&argc, argv);
426 print_help();
428 // open a new scope, because the pointers below should go out of scope
429 // before entering glutMainLoop.
430 // Otherwise OpenSG will complain about objects being alive after shutdown.
432 // the connection between GLUT and OpenSG
433 OSG::GLUTWindowRefPtr gwin = OSG::GLUTWindow::create();
434 gwin->setGlutId(winid);
435 gwin->init();
437 // create the SimpleSceneManager helper
438 mgr = OSG::SimpleSceneManager::create();
439 mgr->setWindow(gwin);
441 // The scene
442 OSG::NodeRefPtr scene = createScene();
444 mgr->setRoot(scene);
446 OSG::commitChanges();
448 // show the whole scene
449 mgr->showAll();
452 // GLUT main loop
453 glutMainLoop();
455 return 0;
459 // GLUT callback functions
463 // redraw the window
465 void display(void)
467 OSG::FrameHandler::the()->frame();
469 OSG::commitChanges();
471 mgr->redraw();
474 // react to size changes
476 void reshape(int w, int h)
478 mgr->resize(w, h);
479 glutPostRedisplay();
483 // react to mouse button presses
485 void mouse(int button, int state, int x, int y)
487 if (state)
488 mgr->mouseButtonRelease(button, x, y);
489 else
490 mgr->mouseButtonPress(button, x, y);
492 glutPostRedisplay();
496 // react to mouse motions with pressed buttons
498 void motion(int x, int y)
500 mgr->mouseMove(x, y);
501 glutPostRedisplay();
505 // react to keys
507 void keyboard(unsigned char k, int x, int y)
509 switch(k)
511 case 27: // ESC
513 // clean up global variables
514 mgr = NULL;
515 ssbo_data_state = NULL;
517 releaseGLUT();
519 OSG::osgExit();
520 exit(0);
522 break;
524 case 'm':
526 materials = initialize_materials(num_materials);
527 update_material_database_state(ssbo_data_state, materials);
528 glutPostRedisplay();
530 break;
535 // setup the GLUT library which handles the windows for us
537 int setupGLUT(int *argc, char *argv[])
539 glutInit(argc, argv);
540 glutInitDisplayMode(GLUT_RGB | GLUT_DEPTH | GLUT_DOUBLE);
541 glutInitWindowSize(1000, 800);
543 int winid = glutCreateWindow("OpenSG");
545 glutReshapeFunc(reshape);
546 glutDisplayFunc(display);
547 glutMouseFunc(mouse);
548 glutMotionFunc(motion);
549 glutKeyboardFunc(keyboard);
551 // call the redraw function whenever there's nothing else to do
552 glutIdleFunc(display);
554 return winid;
557 void releaseGLUT()
559 glutReshapeFunc(NULL);
560 glutDisplayFunc(NULL);
561 glutMouseFunc(NULL);
562 glutMotionFunc(NULL);
563 glutKeyboardFunc(NULL);
564 glutIdleFunc(NULL);
567 void print_help()
569 std::cout << "Esc : quit example" << std::endl;
570 std::cout << "m : reinitialize material database" << std::endl;
573 std::string get_cp_program()
575 using namespace std;
577 stringstream ost;
579 ost << "#version 450 compatibility"
580 << endl << ""
581 << endl << "#extension GL_ARB_compute_variable_group_size: enable"
582 << endl << ""
583 << endl << "uniform float roll;"
584 << endl << "uniform writeonly image2D destTex;"
585 << endl << ""
586 << endl << "struct Material"
587 << endl << "{"
588 << endl << " vec3 ambient;"
589 << endl << " vec3 diffuse;"
590 << endl << " vec3 specular;"
591 << endl << " vec3 emissive;"
592 << endl << ""
593 << endl << " float opacity;"
594 << endl << " float shininess;"
595 << endl << "};"
596 << endl << ""
597 << endl << "layout (std430) buffer Materials"
598 << endl << "{"
599 << endl << " Material material[];"
600 << endl << "} materials;"
601 << endl << ""
602 << endl << "layout (local_size_variable) in;"
603 << endl << ""
604 << endl << "void main()"
605 << endl << "{"
606 << endl << " //"
607 << endl << " // Due to driver issue at the time of writing this code: The build in variable"
608 << endl << " // gl_LocalInvocationIndex is not properly set in case of a variable work group"
609 << endl << " // size specification."
610 << endl << " //"
611 //<< endl << " uint localInvocationIndex = gl_LocalInvocationIndex;"
612 << endl << " uint localInvocationIndex = gl_LocalInvocationID.z * (gl_LocalGroupSizeARB.x * gl_LocalGroupSizeARB.y)"
613 << endl << " + gl_LocalInvocationID.y * gl_LocalGroupSizeARB.x"
614 << endl << " + gl_LocalInvocationID.x;"
615 << endl << ""
616 << endl << ""
617 << endl << " ivec2 storePos = ivec2( gl_GlobalInvocationID.xy );"
618 << endl << " float localCoef = length( vec2( ivec2(gl_LocalInvocationID.xy) - 8 ) / 8.0 );"
619 << endl << " float globalCoef = sin( float(gl_WorkGroupID.x + gl_WorkGroupID.y) * 0.1 + roll ) * 0.5;"
620 << endl << ""
621 << endl << " vec4 color = vec4(materials.material[localInvocationIndex].diffuse, 0.0);"
622 << endl << ""
623 << endl << " color.x -= globalCoef * localCoef;"
624 << endl << " color.y -= globalCoef * localCoef;"
625 << endl << " color.z -= globalCoef * localCoef;"
626 << endl << ""
627 << endl << " imageStore(destTex, storePos, color);"
628 << endl << "}"
629 << endl << ""
630 << endl;
632 return ost.str();