OpenWalnut  1.5.0dev
WMTemplateShaders.cpp
1 //---------------------------------------------------------------------------
2 //
3 // Project: OpenWalnut ( http://www.openwalnut.org )
4 //
5 // Copyright 2009 OpenWalnut Community, BSV@Uni-Leipzig and CNCF@MPI-CBS
6 // For more information see http://www.openwalnut.org/copying
7 //
8 // This file is part of OpenWalnut.
9 //
10 // OpenWalnut is free software: you can redistribute it and/or modify
11 // it under the terms of the GNU Lesser General Public License as published by
12 // the Free Software Foundation, either version 3 of the License, or
13 // (at your option) any later version.
14 //
15 // OpenWalnut is distributed in the hope that it will be useful,
16 // but WITHOUT ANY WARRANTY; without even the implied warranty of
17 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 // GNU Lesser General Public License for more details.
19 //
20 // You should have received a copy of the GNU Lesser General Public License
21 // along with OpenWalnut. If not, see <http://www.gnu.org/licenses/>.
22 //
23 //---------------------------------------------------------------------------
24 
25 /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
26 // This is a tutorial on how to use the WGEShader interface. This tutorial also includes some shader files in the shaders subdirectory. You will
27 // be referred to them later.
28 // You do not know what shaders are? No nothing about GLSL, OpenGL or the OpenSceneGraph? Then this tutorial is probably not for you. This
29 // tutorial demonstrates how to comfortably integrate GLSL shaders into your modules and how to interact with them (coupling with properties).
30 //
31 // You will need the knowledge of these tutorials before you can go on:
32 // * WMTemplate
33 //
34 /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
35 
36 #include <memory>
37 #include <string>
38 
39 #include <osg/Geode>
40 #include <osg/Group>
41 #include <osg/Material>
42 #include <osg/ShapeDrawable>
43 #include <osg/StateAttribute>
44 
45 #include "WDemoGeometry.h"
46 #include "WMTemplateShaders.h"
47 #include "core/graphicsEngine/WGEGeodeUtils.h"
48 #include "core/graphicsEngine/WGEImage.h"
49 #include "core/graphicsEngine/WGEManagedGroupNode.h"
50 #include "core/graphicsEngine/WGERequirement.h"
51 #include "core/graphicsEngine/WGETexture.h"
52 #include "core/graphicsEngine/WGETextureUtils.h"
53 #include "core/graphicsEngine/WGEUtils.h"
54 #include "core/graphicsEngine/callbacks/WGEShaderAnimationCallback.h"
55 #include "core/graphicsEngine/shaders/WGEPropertyUniform.h"
56 #include "core/graphicsEngine/shaders/WGEShader.h"
57 #include "core/graphicsEngine/shaders/WGEShaderDefineOptions.h"
58 #include "core/graphicsEngine/shaders/WGEShaderPropertyDefine.h"
59 #include "core/graphicsEngine/shaders/WGEShaderPropertyDefineOptions.h"
60 #include "core/kernel/WKernel.h"
61 
62 /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
63 // All the basic setup ... Refer to WMTemplate.cpp if you do not understand these commands.
64 /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
65 
67  : WModule()
68 {
69 }
70 
72 {
73 }
74 
75 std::shared_ptr< WModule > WMTemplateShaders::factory() const
76 {
77  // NOTE: Refer to WMTemplate.cpp if you do not understand these commands.
78  return std::shared_ptr< WModule >( new WMTemplateShaders() );
79 }
80 
81 const std::string WMTemplateShaders::getName() const
82 {
83  // NOTE: Refer to WMTemplate.cpp if you do not understand these commands.
84  return "Template Shaders";
85 }
86 
87 const std::string WMTemplateShaders::getDescription() const
88 {
89  // NOTE: Refer to WMTemplate.cpp if you do not understand these commands.
90  return "Show some shader programming examples.";
91 }
92 
94 {
95  // NOTE: Refer to WMTemplate.cpp if you do not understand these commands.
96 
97  // We do not need any connectors. Have a look at WMTemplate.cpp if you want to know what this means.
99 }
100 
102 {
103  // NOTE: Refer to WMTemplate.cpp if you do not understand these commands.
104 
105  m_propCondition = std::shared_ptr< WCondition >( new WCondition() );
106 
107  // We create some preferences here to use in our shader later:
108  m_sphereScaler = m_properties->addProperty( "Sphere Scale", "Scale the spheres.", 1.0 );
109  m_planeColor = m_properties->addProperty( "Plane Color", "Color of the plane", WColor( 90, 95, 100, 255 ) / 255.0 );
110  m_spheresColor = m_properties->addProperty( "Sphere Color", "Color of the plane", WColor( 230, 43, 48, 255 ) / 255.0 );
111 
112  m_aWeight = m_properties->addProperty( "Light Intensity", "The intensity of light on the spheres.", 1.0 );
113  m_aWeight->setMin( 0 );
114  m_aWeight->setMax( 10 );
115 
116  m_flicker = m_properties->addProperty( "Animation", "Turn the animation off or on.", true );
117 
118  // Define some options:
119  WItemSelection::SPtr m_possibleSelections( new WItemSelection() );
120  m_possibleSelections->addItem( "Bump Mapping", "Make the brain pop out." );
121  m_possibleSelections->addItem( "Transparent Plane", "Make the base plane transparent." );
122  m_possibleSelections->addItem( "LSD Mode", "Make it a bit more colorful." );
123 
124  m_modeSelection = m_properties->addProperty( "Plane Render Modes", "Choose what you like.", m_possibleSelections->getSelectorAll() );
125 
126  // avoid that a user selects nothing
128 
130 }
131 
133 {
134  // NOTE: Refer to WMTemplate.cpp if you do not understand these commands.
135 
136  // We need graphics to draw anything:
137  m_requirements.push_back( new WGERequirement() );
138 }
139 
140 /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
141 // ATTENTION: now it gets interesting ...
142 /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
143 
145 {
146  m_moduleState.setResetable( true, true );
148 
149  // Now, we can mark the module ready.
150  ready();
151 
152  ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
153  // 1. Setup some geometry.
154  ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
155 
156  // Lets start. We begin by defining some geometry. We use standard OSG functionality to create an awesome
157  // visualization of some spheres on a plane:
158  // -> create a group node in which we will place our demo geometry.
159  osg::ref_ptr< WGEGroupNode > rootNode = new WGEGroupNode();
160  // We add this to the global scene. If you are unfamiliar with this, please refer to WMTemplate.cpp
161  WKernel::getRunningKernel()->getGraphicsEngine()->getScene()->insert( rootNode );
162  // Show plane directly. By default, the user views along the Y axis -> the plane is on the XY plane -> rotate to make it visible by default:
163  rootNode->setMatrix( osg::Matrixd::rotate( 1.57, 1.0, 0.0, 0.0 ) ); // First parameter is the angle in radians.
164 
165  // Now we can add your demo geometry:
166  osg::ref_ptr< osg::Node > spheres = WDemoGeometry::createSphereGeometry();
167  osg::ref_ptr< osg::Node > plane = WDemoGeometry::createPlaneGeometry();
168 
169  // Allow blending here? Yes. We need it later.
170  plane->getOrCreateStateSet()->setMode( GL_BLEND, osg::StateAttribute::ON );
171  plane->getOrCreateStateSet()->setRenderingHint( osg::StateSet::TRANSPARENT_BIN );
172 
173  // To see our new geometry we need to add it to the group of ours:
174  rootNode->insert( spheres );
175  rootNode->insert( plane );
176 
177  // OK. Let us summarize the rather uninteresting part: We created a root node (a group) that will contain our demo geometry. We created the
178  // geometry and added it to the group.
179 
180  ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
181  // 2. Setup shaders
182  ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
183 
184  // TIP: you do not understand this GLSL-shader-OpenGL-geode-node-OSG-stuff? You should probably first learn the basics of OpenGL and its
185  // Shading system. A good point to start is http://www.lighthouse3d.com/opengl/glsl/
186 
187  // Now it gets really interesting. We load a shader:
188  osg::ref_ptr< WGEShader > sphereShader(
189  new WGEShader(
190  "WMTemplateShaders-Spheres", // shader name prefix
191  m_localPath // where to search?
192  )
193  );
194 
195  // This line creates a new shader object and loads the code from some GLSL files. But which files? The first parameter of the WGEShader
196  // constructor is a string denoting the name prefix for the shader files. The second parameter determines where to search. Luckily, the
197  // WModule::m_localPath variable is automatically set for each module and points to the binary directory of your module. You can use other
198  // directories heres, add subdirectories and similar. It is even allowed to skip this path. In this case, the OpenWalnut search path is used.
199  // This is practical for loading OpenWalnut's own shaders directly. Never the less, the WGEShader constructor now looks inside this directory
200  // for the shader files that start with our prefix string:
201  //
202  // * WMTemplateShaders-Spheres-vertex.glsl
203  // * WMTemplateShaders-Spheres-fragment.glsl
204  // * WMTemplateShaders-Spheres-geometry.glsl
205  //
206  // This makes clear, what the prefix means. WGEShader automatically adds the "-vertex.glsl", "-fragment.glsl", and "-geometry.glsl"
207  // extensions. WGEShader now tries to load them. According to the OpenGL standard, not all shaders are needed. Usually, you provide at least
208  // a vertex and a fragment shader.
209  //
210  // NOTE: a small note on shader paths. As mentioned above, when loading shaders, OpenWalnut searches inside a given set of Paths. This is
211  // similar to your C++ compiler, which searches certain header files in a given set of paths. Besides the system paths, you specify additional
212  // search paths for your local header files. This is conceptually the same in OpenWalnut's WGEShader. There is a system path of OpenWalnut.
213  // There, all OpenWalnut shaders reside. When you specify your own path, WGEShader tries to fiend the above filenames in the following order:
214  // 1) specified_path/WMTemplateShaders-Spheres-vertex.glsl
215  // 2) specified_path/shaders/WMTemplateShaders-Spheres-vertex.glsl
216  // 3) WPathHelper::getShaderPath()/WMTemplateShaders-Spheres-vertex.glsl <-- this is the global shader path
217  //
218  // NOTE on naming: The above lines tell you where to place your shaders. In OpenWalnut, we usually put them into a subdirectory called "shaders".
219  // We additionally name shaders as the module. This makes it easier for developers to identify the shaders of your specific module.
220  //
221  // After this line, the shader object exists but it has not yet loaded the code, nor is it bound to any part of the graphics pipeline. A
222  // shader is always bound to something which draws something ... somehow ... like osg::Geodes. Luckily, we have two geodes we would like to shade:
223  sphereShader->apply( spheres );
224  // This now applied the shader to our node. There are different ways to apply a shader. What we have shown you here is the more comfortable
225  // way OpenWalnut provides. Always use this. It is thread-safe and handles shader-reload properly.
226 
227  // Lets load another shader for the plane and apply it:
228  osg::ref_ptr< WGEShader > planeShader( new WGEShader( "WMTemplateShaders-Plane", m_localPath ) );
229  planeShader->apply( plane );
230 
231  // Some side-note: To de-activate a shader again, use
232  // planeShader->deactivate( plane );
233  // You might ask why you need to specify the node once again. This is because a shader might be applied to multiple nodes at the same time.
234 
235  // OK. Let us summarize. We made some geometry and loaded two different shaders. We applied it to the geometry. If we compile and start the
236  // module now, OpenWalnut will tell us that it could not load our shaders. Because we did not write them yet. BUT this is not the next step
237  // for now. At least in this tutorial :-).
238 
239  ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
240  // 2. Setup parameters for shaders
241  ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
242 
243  // Now that we have shaders, we want to define some uniforms and learn about compile-time definitions.
244 
245  // First start with uniforms. Uniforms can be seen as dynamic input variables that do not change during ONE drawing of ONE osg::Node. The
246  // value is globally set for the program, unlike attributes, whose value changes for primitives, vertex and so on. The vertex color is a nice
247  // example for attributes.
248  // This, of course, is a little bit too simplified, but in most cases, it is exactly that: an input variable of one GLSL program that can be
249  // changed per rendered frame.
250  //
251  // Uniforms can have different types. Floats, ints and so on. OSG already supports these possible types in its osg::Uniform class and the
252  // intended way to define and set an uniform is:
253  osg::Uniform* animationTime(
254  new osg::Uniform(
255  "u_animation", // a name. We always use "u_someName" to easily identify uniforms via the "u_".
256  0 // initial value, type of this parameter defines the uniform type in GLSL!
257  )
258  );
259  spheres->getOrCreateStateSet()->addUniform( animationTime ); // Add this uniform to the spheres as variable for the GLSL program.
260  plane->getOrCreateStateSet()->addUniform( animationTime ); // It is possible to add one uniform to multiple nodes.
261  // You now might ask how to modify these uniforms? Well, as we already have added the uniforms to a state set
262  // -> whose node is already added to a group -> which already is added to a scene -> which already is visible we cannot set the values
263  // directly. This might cause threading problems. As usual in OSG, always use update callbacks.
264 
265  // This looks nice but has some disadvantages:
266  // * The OSG doc is not that explicit in telling you how thread-safe it is to change a value from a thread that is not the rendering thread.
267  // * Coupling uniforms with properties can produce a lot of boiler-plate code (register update callback to each OSG node, query property in
268  // there (due to thread-safety), set, ... ).
269  //
270  // So this is the reason why we introduced WGEPropertyUniform. Properties are so damn similar to uniforms. Why not coupling them:
271  spheres->getOrCreateStateSet()->addUniform( // <-- adding a uniform is always done this way
272  new WGEPropertyUniform< WPropDouble >( // <-- define the type of property
273  "u_sphereScaler", // a name as above.
274  m_sphereScaler // the property whose value should be used for the uniform.
275  )
276  );
277  // If the property now updates its value, the uniform is updated too. This is can be very comfortable to allow the user several parameters of
278  // your shader-based visualization. You can do this for all property types as long as you can somehow cast them to a GLSL type. This means:
279  // * you cannot use WPropString as GLSL does not know strings
280  // * you can use WPropSelection as they get cast to ints for example
281  // For details, review core/graphicsEngine/shaders/WGEUniformTypeTraits.h. Internally, OpenWalnut uses template function wge::toUniformType
282  // to cast an input property type to an uniform type. This means, you can specialize this template for a specific type if you like.
283 
284  // Add a color for the plane.
285  plane->getOrCreateStateSet()->addUniform( new WGEPropertyUniform< WPropColor >( "u_planeColor", m_planeColor ) );
286  spheres->getOrCreateStateSet()->addUniform( new WGEPropertyUniform< WPropColor >( "u_spheresColor", m_spheresColor ) );
287 
288  // Thats it for uniforms. It is trivial and further example will not show any more cool features. Now we should get to shader-compile-time
289  // definitions. You all know this from C/C++ ... good old #define. This works in GLSL too and WGEShader provides a nice API for this. In
290  // OpenWalnut, the following classes are derived from WGEShaderPreprocessor and can all be add to multiple shaders, work thread-safe.
291  // Instantiation scheme is always the same, but for some of them, WGEShader already provides comfortable methods to create and add the
292  // preprocessors for you.
293 
294  // Add a define. They are shader specific. First we add a PI constant to the WMTemplateShaders-Spheres that we will use in its vertex shader:
295  WGEShaderDefine< double >::SPtr somewhatLikePI = sphereShader->setDefine( "PI", 3.14 );
296  // After creating them, you can set them as you like. This works from any thread (in contrast to pure osg::Uniforms)
297  somewhatLikePI->setValue( 3.1416 ); // more "exact" PI
298  // Thats it. Now you can simply use the value "PI" in the shader. No need for an extra definition or something similar. This works because
299  // WGEShader directly inserts the text "#define PI 3.1416" to the shader. But this also means that, when changing the value, the shader
300  // re-compiles. So you will have to make a trade-off between compile time definitions and uniforms. You now might ask why it might be useful
301  // to define changeable compile-time constants. Assume you have a for-loop in your GLSL code. GLSL (depending on the version) will unroll the
302  // loop during compilation, forcing the programmer to specify a number of iterations during compile-time. But you might want to change this
303  // depending on your input dataset for example.
304 
305  // Besides simple compile-time values, the GLSL preprocessor also supports #ifdef/#else/#endif blocks. This is very handy, when you want to
306  // switch between different types of rendering or want to en-/dis-able features without using large if-blocks (btw it is not recommended in
307  // GLSL in any way)
308 
309  // Let us begin with simple switches, which en- or dis-able a certain code block. This is very handy when it comes to visual features which
310  // are not necessary and thus, might be turned off. (or to save GPU load if needed for something else).
311  WGEShaderDefineSwitch::SPtr bwSwitch = sphereShader->setDefine( "BW_ENABLED" );
312  // This example forces the spheres to be black & white only. By default, such simple switches are set to true. As we want colorful spheres
313  // for now, we disable this again:
314  bwSwitch->setActive( false );
315  // It is important to note here, that switches are nothing more than WGEShaderDefine< bool >. You already have seen them above.
316  // WGEShaderDefineSwitch is just an abbreviation with a more telling name. BUT there is a usage-difference ... instead
317  // of using setValue( false ), you should use setActive( false ). This method is a WGEShaderPreprocessor method and completely disables this
318  // preprocessor. The #define statement will be removed then. This is important when using #ifdef blocks in your GLSL code. If you would use
319  // setValue( false ); you will end up with BW_ENABLED still defined (and set to 0)
320 
321  // Now, let us assume we want to switch not only one block on/off, but multiple at the same time? Exclusively? You can, of course, realize
322  // this with multiple WGEShaderDefineSwitch instances. But OpenWalnut provides a more comfortable option here:
323  WGEShaderDefineOptions::SPtr bwMode( // Create instance
324  new WGEShaderDefineOptions( "RED_ONLY", // And specify a list of options to switch
325  "BLUE_ONLY",
326  "GREEN_ONLY",
327  "COMBINE"
328  )
329  );
330  // Never forget to add your preprocessor to one or multiple shaders
331  sphereShader->addPreprocessor( bwMode );
332  // Ok. We want to enable "COMBINE" mode:
333  bwMode->activateOption( 3 );
334  // When using activateOption, you have to possibilities: 1) set an option exclusively (shown above)
335  // 2) set an option and keep previous options set:
336  bwMode->activateOption( 1 );
337  bwMode->activateOption( 3, true ); // the second parameter denotes that the new option is not exclusive.
338  // This means, you have both in your shader code:
339  // #define RED_ONLY
340  // #define COMBINE
341  // Of course non-exclusive options are not always useful. But you have the possibility to turn on a set of options and allow their
342  // combination.
343 
344  // Now, we have compile-time values and can define switches for blocks. As with uniforms, it is now possible to couple these to properties.
345  // This is what you will learn next:
346 
347  // Similar to the property-coupled uniforms, we provide property-coupled compile-time definitions. These compile-time definitions are
348  // implemented as code-preprocessors. Hence the call:
349  sphereShader->addPreprocessor(
350  WGEShaderPreprocessor::SPtr( // create a preprocessor which is coupled to a property
352  "LIGHT_INTENSITY", // The name of the compile-time definition
353  m_aWeight // The coupled property
354  )
355  )
356  );
357 
358  // The WGEShaderDefineOptions example above was just for demonstration. Now, lets add a practical example. First, we want the user to be able
359  // to switch of the "flicker" animation. For this, we already define a WPropBool and bind it to a define now:
360  sphereShader->addPreprocessor(
363  m_flicker, // The property that controls this.
364  // Now list all #defines for each possible value of the given property:
365  "FLICKER_DISABLED", // The #define (option) to set if m_flicker->get() == false
366  "FLICKER_ENABLED" // The #define (option) to set if m_flicker->get() == true
367  )
368  )
369  );
370  // This, at first might look stupid to define two #defines here, since you could use #ifndef FLICKER_ENABLED too. BUT assume you later switch
371  // to a selection property which handles both of your cases (bool == true and bool == false) with two separate items. Then you will be lucky
372  // to see that your GLSL code is structured and contains both blocks separately.
373 
374  // Talking about selection properties ... why not using multiple options (as above) in combination with a property? We defined a selection
375  // property above and now assign #defines to each of its possible values
376  planeShader->addPreprocessor( // Add
377  WGEShaderPreprocessor::SPtr( // it is a preprocessor of course
378  new WGEShaderPropertyDefineOptions< WPropSelection >( // options based on selection
379  m_modeSelection, // The property to use
380  // As above, mention all possible values and their respecting #define
381  "BUMPMAPPING_ENABLED",
382  "TRANSPARENTPLANE_ENABLED",
383  "LSD_ENABLED"
384  )
385  )
386  );
387 
388  // Thats it. You now coupled properties to uniforms, learned how to set compile-time values and how to set and unset #defines in GLSL
389  // comfortably. In the next step, we add some textures to work with.
390 
391  ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
392  // 4. Textures
393  ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
394 
395  // We need some textures. You could use the default OSG functionality via osg::Texture* but OpenWalnut has extended it to
396  // provide you a comfortable interface. WGETexture keeps track of texture sizes, updates shader uniforms automatically and more. It even
397  // has properties! This way, you can just bind a texture, and your shader knows about them, their sizes and so on via uniforms.
398  // In our demo, we use a 3d white noise texture generated by the WGE utilities:
399  const size_t size = 64;
400  WGETexture3D::SPtr randTex = wge::genWhiteNoiseTexture( size, size, size, // dimensions
401  1 // number if channels: 1 -> gray scale, 3 -> RGB, 4 -> RGBA
402  ); // quite self-explanatory
404  spheres, // Where to bind
405  randTex, // The texture to bind
406  0, // The texture unit
407  "u_noise" // Name-prefix for the texture specific uniforms. Optional. If not specified, it will be "u_textureX" where X is the unit
408  );
409  // This ensures you will have the following uniforms defined too:
410  // * - u_noiseUnit: the unit number (useful for accessing correct gl_TexCoord and so on)
411  // * - u_noiseSampler: the needed sampler
412  // * - u_noiseSizeX: width of the texture in pixels
413  // * - u_noiseSizeY: height of the texture in pixels
414  // * - u_noiseSizeZ: depth of the texture in pixels
415  // Besides these, you will also get the uniforms for the properties in WGETexture::getProperties(). Awesome isn't it? This is especially
416  // useful when loading textures from data:
417  // std::shared_ptr< WDataSetVector > gradients = ....;
418  // osg::ref_ptr< WDataTexture3D > gradTexture3D = gradients->getTexture();
419  // wge::bindTexture( cube, gradTexture3D, 2, "u_gradients" );
420  //
421  // Some of the property uniforms will then be:
422  /*
423  //!< For un-scaling the data: the minimum.
424  uniform float u_gradientsMin = 0;
425 
426  //!< For un-scaling the data: the scaling factor.
427  uniform float u_gradientsScale = 1;
428 
429  //!< The alpha value for this colormap. Is in [0,1].
430  uniform float u_gradientsAlpha;
431 
432  //!< Flag denoting whether to clip the zero value.
433  uniform bool u_gradientsClipZeroEnabled = false;
434 
435  //!< The threshold value for this colormap. Is in [Min,Scale+Min]
436  uniform float u_gradientsThresholdLower;
437 
438  //!< The threshold value for this colormap. Is in [Min,Scale+Min]
439  uniform float u_gradientsThresholdUpper;
440 
441  //!< Flag denoting whether to use the threshold value for clipping or not.
442  uniform bool u_gradientsThresholdEnabled = false;
443 
444  //!< Flag denoting whether to use the windowing values for scaling or not.
445  uniform bool u_gradientsWindowEnabled = false;
446 
447  //!< Contains the lower and upper window level.
448  uniform vec2 u_gradientsWindow = vec2( 0.0, 1.0 );
449 
450  //!< The index of the colormap to use
451  uniform int u_gradientsColormap;
452 
453  //!< True if the colormap is active.
454  uniform bool u_gradientsActive = false;
455  */
456 
457  // We can also utilize WGEImage and load textures from a file, whose path is stored in our META file. Refer to WMTemplate and WMTemplateUI
458  // for more details about this.
459  WGEImage::SPtr planeImage = WGEImage::createFromFile( m_localPath / getMetaInformation()->query< std::string >( "common/amazingTexture" ) );
460  // Create a texture out of this:
461  WGETexture2D::SPtr planeTexture( new WGETexture2D( planeImage ) );
463  plane, // Where to bind
464  planeTexture, // The texture to bind
465  0, // The texture unit
466  "u_texture" // Name-prefix for the texture specific uniforms. Optional. If not specified, it will be "u_textureX" where X is the unit
467  );
468 
469  ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
470  // 5. Utilities and helpers
471  ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
472 
473  // We want some nice animations. We already have an uniform which contains the animation time. But who increases it?
474  // OpenWalnut provides several useful callbacks for several purpose. Have a look at core/graphicsEngine/callbacks for more.
475  // Here, we use an animation callback:
476  animationTime->setUpdateCallback( new WGEShaderAnimationCallback() );
477 
478  ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
479  // 6. Write the shaders
480  ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
481 
482  // Now we can write the shader code. Please open the "WMTemplateShaders-Spheres-*" files in your shaders subdirectory (sub of the directory
483  // THIS file resides in). Start reading WMTemplateShaders-Spheres-vertex.glsl.
484 
485  // TIP: As a shader developer, you most probably want to re-compile and test your shader very often. OpenWalnut supports you in this. All
486  // loaded shaders can be reloaded using the dot-key. Simply focus your 3D view and press the dot-key. This reloads the bound shaders. Yours
487  // too.
488  //
489  // TIP: In addition, your CMake Build-setup allows you to set the option "OW_LINK_SHADERS". On systems supporting soft-links, this ensures
490  // that your shader is not copied to the build directory but linked. So you can change the code in your source directory and reload it
491  // directly while OpenWalnut is running.
492 
493  ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
494  // 7. ... do stuff.
495  ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
496 
497  // You already know this module loop code. You won't need to implement any further interaction between your properties and your shader.
498  // This happens automatically due to OpenWalnut's comfortable shader<->property interface we set up above. But of course the options are
499  // endless. Modify the geometry, change attributes and so on ...
500 
501  // Now the remaining module code. In our case, this is empty.
502  while( !m_shutdownFlag() )
503  {
505  if( m_shutdownFlag() )
506  {
507  break;
508  }
509  }
510 
511  // Never miss to clean up. Especially remove your OSG nodes. Everything else you add to these nodes will be removed automatically.
512  debugLog() << "Shutting down ...";
513  WKernel::getRunningKernel()->getGraphicsEngine()->getScene()->remove( rootNode );
514 }
515 
virtual void wait() const
Wait for the condition.
void setResetable(bool resetable=true, bool autoReset=true)
Sets the resetable flag.
virtual void add(std::shared_ptr< WCondition > condition)
Adds another condition to the set of conditions to wait for.
Class to encapsulate boost::condition_variable_any.
Definition: WCondition.h:42
Class to wrap around the osg Group node and providing a thread safe add/removal mechanism.
Definition: WGEGroupNode.h:48
static WGEImage::SPtr createFromFile(boost::filesystem::path file)
Load an image from a file.
Definition: WGEImage.cpp:80
std::shared_ptr< WGEImage > SPtr
Convenience typedef for a std::shared_ptr< WGEImage >.
Definition: WGEImage.h:48
Class implementing a uniform which can be controlled by a property instance.
This requirement ensures an up and running WGE.
This is a uniform callback setting the uniform to the current time in milliseconds,...
This GLSL preprocessor is able to set one define from a list of defines depending on the active optio...
std::shared_ptr< WGEShaderDefineOptions > SPtr
Shared pointer for this class.
void setValue(const ValueType &value)
Sets the new value for this define.
std::shared_ptr< WGEShaderDefine< ValueType > > SPtr
Shared pointer for this class.
std::shared_ptr< WGEShaderPreprocessor > SPtr
Shared pointer for this class.
This is a WGEShaderDefineOptions class which additionally uses a property to automatically control th...
This class is able to provide arbitrary values as define statements in GLSL code.
Class encapsulating the OSG Program class for a more convenient way of adding and modifying shader.
Definition: WGEShader.h:48
This calls serves a simple purpose: have a texture and its scaling information together which allows ...
Definition: WGETexture.h:53
osg::ref_ptr< WGETexture< TextureType > > SPtr
Convenience type for OSG reference pointer on WGETextures.
Definition: WGETexture.h:63
A class containing a list of named items.
std::shared_ptr< WItemSelection > SPtr
Convenience typedef for a std::shared_ptr< WItemSelection >
static WKernel * getRunningKernel()
Returns pointer to the currently running kernel.
Definition: WKernel.cpp:117
std::shared_ptr< WGraphicsEngine > getGraphicsEngine() const
Returns pointer to currently running instance of graphics engine.
Definition: WKernel.cpp:122
std::shared_ptr< WCondition > m_propCondition
A condition for property updates.
WPropColor m_planeColor
Color of the plane.
WPropBool m_flicker
Turn on/off animation.
virtual void properties()
Initialize the properties for this module.
WPropSelection m_modeSelection
Switch between several modes.
WPropDouble m_sphereScaler
Allow scaling the spheres.
virtual void moduleMain()
Entry point after loading the module.
WMTemplateShaders()
Constuctor.
virtual ~WMTemplateShaders()
Destructor.
virtual const std::string getName() const
Gives back the name of this module.
WPropColor m_spheresColor
Color of the spheres.
virtual void requirements()
Initialize requirements for this module.
virtual void connectors()
Initialize the connectors this module is using.
virtual const std::string getDescription() const
Gives back a description of this module.
WPropDouble m_aWeight
Some weight.
virtual std::shared_ptr< WModule > factory() const
Due to the prototype design pattern used to build modules, this method returns a new instance of this...
Class representing a single module of OpenWalnut.
Definition: WModule.h:72
boost::filesystem::path m_localPath
The path where the module binary resides in.
Definition: WModule.h:734
Requirements m_requirements
The list of requirements.
Definition: WModule.h:754
virtual void properties()
Initialize properties in this function.
Definition: WModule.cpp:212
wlog::WStreamedLogger debugLog() const
Logger instance for comfortable debug logging.
Definition: WModule.cpp:575
virtual WModuleMetaInformation::ConstSPtr getMetaInformation() const
The meta information of this module.
Definition: WModule.cpp:229
std::shared_ptr< WProperties > m_properties
The property object for the module.
Definition: WModule.h:640
void ready()
Call this whenever your module is ready and can react on property changes.
Definition: WModule.cpp:505
WConditionSet m_moduleState
The internal state of the module.
Definition: WModule.h:703
virtual void connectors()
Initialize connectors in this function.
Definition: WModule.cpp:208
WBoolFlag m_shutdownFlag
Condition getting fired whenever the thread should quit.
osg::ref_ptr< osg::Node > createSphereGeometry()
Create several spheres.
osg::ref_ptr< osg::Node > createPlaneGeometry()
Create a plane.
void addTo(WPropSelection prop)
Add the PC_NOTEMPTY constraint to the property.
osg::ref_ptr< WGETexture< osg::Texture1D > > genWhiteNoiseTexture(size_t sizeX, size_t channels)
This generates an 1D texture only containing white noise in its channels.
void bindTexture(osg::ref_ptr< osg::Node > node, osg::ref_ptr< WDataTexture3D > texture, size_t unit=0, std::string prefix="")
Binds the specified texture to the specified unit.