1 // OpenSG Tutorial Example: ShaderStorageBufferObject
3 // This example shows how to create a shader storage block and binding it
4 // to a shader storage buffer object.
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.
17 #include <boost/random/mersenne_twister.hpp>
18 #include <boost/random/uniform_int_distribution.hpp>
20 #ifdef OSG_BUILD_ACTIVE
23 #include <OSGConfig.h>
24 #include <OSGSimpleGeometry.h>
25 #include <OSGGLUTWindow.h>
26 #include <OSGSimpleSceneManager.h>
27 #include <OSGBaseFunctions.h>
28 #include <OSGTransform.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>
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>
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>
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
91 directional_light
= 0,
98 : position(0.f
, 0.f
, 0.f
)
99 , spot_direction(0.f
, 1.f
, 0.f
)
103 , attenuation(1.f
, 0.f
, 0.f
)
104 , spot_cos_cutoff(cosf(45.f
))
109 static Light
create_light(Type e
)
115 case directional_light
: l
.spot_direction
= OSG::Vec3f(1.f
, 0.f
, 0.f
);
117 case point_light
: l
.position
= OSG::Pnt3f(0.f
, 0.2f
, 0.f
);
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
;
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
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
);
155 VecLightsT lights
= initialize_lights(); // the lights
159 // Simple material data structure
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
)
172 OSG::Color3f ambient
;
173 OSG::Color3f diffuse
;
174 OSG::Color3f specular
;
175 OSG::Color3f emissive
;
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
)
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
);
198 materials
.push_back(m
);
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
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)
228 OSG::Viewport
* pPort
= mgr
->getWindow()->getPort(0);
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
);
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)
251 OSG::Viewport
* pPort
= mgr
->getWindow()->getPort(0);
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
);
269 void update_light_state(OSG::ShaderStorageBufferObjChunk
* ssbo
, const VecLightsT
& vLights
)
272 for (std::size_t i
= 0; i
< vLights
.size(); ++i
) {
273 std::stringstream stream
;
274 stream
<< "Lights.light[" << i
<< "]." << std::flush
;
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
);
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
);
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
;
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
)
338 for (std::size_t i
= 0; i
< vMaterials
.size(); ++i
) {
339 std::stringstream stream
;
340 stream
<< "Materials.material[" << i
<< "]." << std::flush
;
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
);
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
);
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
;
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
)
392 #ifndef USE_TEST_FP_SHADER
393 ssbo
->setInt("GeomState.material_index", geom_state
.material_index
);
395 ssbo
->setInt("GeomState.material_index", 7);
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
[]);
452 // light spot direction and light position must be provided in eye space
453 update_light_state(ssbo_light_state
, lights
);
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();
476 // Initialize GLUT & OpenSG and set up the scene
478 int main(int argc
, char **argv
)
481 OSG::osgInit(argc
,argv
);
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
);
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.
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,
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();
612 // show the whole scene
623 // GLUT callback functions
627 // react to size changes
629 void reshape(int w
, int h
)
636 // react to mouse button presses
638 void mouse(int button
, int state
, int x
, int y
)
641 mgr
->mouseButtonRelease(button
, x
, y
);
643 mgr
->mouseButtonPress(button
, x
, y
);
649 // react to mouse motions with pressed buttons
651 void motion(int x
, int y
)
653 mgr
->mouseMove(x
, y
);
660 void keyboard(unsigned char k
, int x
, int y
)
666 // clean up global variables
671 ssbo_light_state
= NULL
;
672 ssbo_geom_state_1
= NULL
;
673 ssbo_geom_state_2
= NULL
;
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
);
694 mgr
->setStatistics(!mgr
->getStatistics());
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
);
723 // vertex shader program.
725 std::string
get_vp_program()
727 std::string vp_program
=
729 "#version 330 compatibility\n"
731 "#extension GL_ARB_separate_shader_objects: enable\n"
732 "#extension GL_ARB_shader_storage_buffer_object: enable\n"
734 "smooth out vec3 vNormalES; // eye space normal\n"
735 "smooth out vec3 vPositionES; // eye space position\n"
740 " // multiply the object space vertex position with the modelview matrix \n"
741 " // to get the eye space vertex position\n"
743 " vPositionES = (gl_ModelViewMatrix * gl_Vertex).xyz;\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"
749 " vNormalES = gl_NormalMatrix * gl_Normal;\n"
752 " // multiply the combiend modelview projection matrix with the object space vertex\n"
753 " // position to get the clip space position\n"
755 " gl_Position = ftransform();\n"
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
=
770 "#version 330 compatibility\n"
772 "#extension GL_ARB_separate_shader_objects: enable\n"
773 "#extension GL_ARB_shader_storage_buffer_object: enable\n"
775 "smooth in vec3 vNormalES; // eye space normal\n"
776 "smooth in vec3 vPositionES; // eye space position\n"
778 "const int num_lights = 2;\n"
779 "const int num_materials = 5000;\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"
788 " vec3 position; // in eye space\n"
789 " vec3 spot_direction; // in eye space\n"
791 " vec3 Ia; // ambient max. Intensity\n"
792 " vec3 Id; // diffuse max. Intensity\n"
793 " vec3 Is; // specular max. Intensity\n"
795 " vec3 attenuation; // (constant, linear, quadratic) with constant >= 1 and linear,quadratic >= 0\n"
797 " float spot_cos_cutoff; // cosine cut of angle\n"
799 " float spot_exponent; // [0-128]\n"
800 " int type; // directional_light, point_light, spot_light, no_light\n"
803 "layout (std430) buffer Lights\n"
805 " Light light[num_lights];\n"
816 " float shininess;\n"
819 "layout (std430) buffer Materials\n"
821 " Material material[num_materials];\n"
825 "layout (std430) buffer GeomState\n"
827 " int material_index;\n"
830 "const vec3 cCameraPositionES = vec3(0,0,0); // eye is at vec3(0,0,0) in eye space!\n"
832 "layout(location = 0) out vec4 vFragColor;\n"
835 "// directional light contribution\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"
843 " if (lights.light[i].type != directional_light)\n"
844 " return vec3(0.0, 0.0, 0.0);\n"
847 " // the light direction in eye space\n"
849 " vec3 l = -lights.light[i].spot_direction; // we carry the directional light direction in the spot_direction slot\n"
852 " // the half vector\n"
854 " vec3 h = normalize(l + v);\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"
859 " float m = materials.material[j].shininess;\n"
861 " float pf; // power factor\n"
863 " if (n_dot_l == 0.0)\n"
866 " pf = pow(n_dot_h, m);\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"
875 "// point light contribution\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"
884 " if (lights.light[i].type != point_light)\n"
885 " return vec3(0.0, 0.0, 0.0);\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"
892 " // the half vector\n"
894 " vec3 h = normalize(l + v);\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"
899 " float m = materials.material[j].shininess;\n"
901 " float pf; // power factor\n"
903 " if (n_dot_l == 0.0)\n"
906 " pf = pow(n_dot_h, m);\n"
909 " // Compute attenuation\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"
915 " attenuation = clamp(attenuation, 0.0, 1.0);\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"
924 "// spot light contribution\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"
933 " if (lights.light[i].type != spot_light)\n"
934 " return vec3(0.0, 0.0, 0.0);\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"
940 " vec3 s = lights.light[i].spot_direction; // spot direction\n"
943 " // the half vector\n"
945 " vec3 h = normalize(l + v);\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"
951 " float m = materials.material[j].shininess;\n"
953 " float pf; // power factor\n"
955 " if (n_dot_l == 0.0)\n"
958 " pf = pow(n_dot_h, m);\n"
961 " // Compute attenuation\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"
967 " attenuation = clamp(attenuation, 0.0, 1.0);\n"
969 " if (l_dot_s < lights.light[i].spot_cos_cutoff) \n"
970 " attenuation = 0.0;\n"
972 " attenuation *= pow(l_dot_s, lights.light[i].spot_exponent);\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"
983 " // normalize the eye space normal\n"
985 " vec3 N = normalize(vNormalES);\n"
988 " // get the view vector and normalize it\n"
990 " vec3 V = normalize(cCameraPositionES - vPositionES);\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"
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"
1002 " vFragColor = vec4(color, materials.material[geom_state.material_index ].opacity);\n"
1007 std::string fp_program
=
1009 "#version 330 compatibility\n"
1011 "#extension GL_ARB_separate_shader_objects: enable\n"
1012 "#extension GL_ARB_shader_storage_buffer_object: enable\n"
1014 "smooth in vec3 vNormalES; // eye space normal\n"
1015 "smooth in vec3 vPositionES; // eye space position\n"
1017 "const int num_lights = 2;\n"
1018 "const int num_materials = 5000;\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"
1027 " vec3 position; // in eye space\n"
1028 " vec3 spot_direction; // in eye space\n"
1030 " vec3 Ia; // ambient max. Intensity\n"
1031 " vec3 Id; // diffuse max. Intensity\n"
1032 " vec3 Is; // specular max. Intensity\n"
1034 " vec3 attenuation; // (constant, linear, quadratic) with constant >= 1 and linear,quadratic >= 0\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"
1041 "layout (std430) buffer Lights\n"
1043 " Light light[num_lights];\n"
1054 " float shininess;\n"
1057 "layout (std430) buffer Materials\n"
1059 " Material material[num_materials];\n"
1063 "layout (std430) buffer GeomState\n"
1065 " int material_index;\n"
1068 "layout(location = 0) out vec4 vFragColor;\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"
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"
1091 " int material_index = geom_state.material_index;\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"
1096 " if (type != point_light)\n"
1099 " if (position != vec3(1.1, 2.2, 3.3))\n"
1102 " if (spot_direction != vec3(4.4, 5.5, 6.6))\n"
1105 " if (Ia != vec3(0.2, 0.2, 0.2))\n"
1108 " if (Id != vec3(0.4, 0.4, 0.4))\n"
1111 " if (Is != vec3(0.6, 0.6, 0.6))\n"
1114 " if (attenuation != vec3(0.8, 0.8, 0.8))\n"
1117 " if (spot_cos_cutoff != 0.8)\n"
1120 " if (spot_exponent != 12.3)\n"
1123 " if (ambient != vec3(0.1, 0.2, 0.3))\n"
1126 " if (diffuse != vec3(0.2, 0.4, 0.6))\n"
1129 " if (specular != vec3(0.4, 0.6, 0.8))\n"
1132 " if (emissive != vec3(0.6, 0.8, 1.0))\n"
1135 " if (opacity != 0.7)\n"
1138 " if (shininess != 25.4)\n"
1141 " if (material_index != 7)\n"
1145 " vFragColor = color;\n"