1 /* OpenSceneGraph example, osgminimalglsl.
2 *
3 *  Permission is hereby granted, free of charge, to any person obtaining a copy
4 *  of this software and associated documentation files (the "Software"), to deal
5 *  in the Software without restriction, including without limitation the rights
6 *  to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7 *  copies of the Software, and to permit persons to whom the Software is
8 *  furnished to do so, subject to the following conditions:
9 *
10 *  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
11 *  IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
12 *  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
13 *  AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
14 *  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
15 *  OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
16 *  THE SOFTWARE.
17 */
18 
19 /* file:        examples/osgminimalglsl.cpp
20  *
21  * A minimal demo of the OpenGL Shading Language shaders using core OSG.
22  *
23  * blocky shader taken from osgshaders sample (Author: Mike Weiblein)
24 */
25 
26 #include <osgViewer/Viewer>
27 
28 #include <osg/ShapeDrawable>
29 #include <osg/Geode>
30 #include <osg/Vec3>
31 
32 #include <osg/Program>
33 #include <osg/Shader>
34 #include <osg/Uniform>
35 
36 using namespace osg;
37 
38 ///////////////////////////////////////////////////////////////////////////
39 // in-line GLSL source code
40 
41 static const char *blockyVertSource = {
42     "// blocky.vert - an GLSL vertex shader with animation\n"
43     "// the App updates uniforms \"slowly\" (eg once per frame) for animation.\n"
44     "uniform float Sine;\n"
45     "const vec3 LightPosition = vec3(0.0, 0.0, 4.0);\n"
46     "const float BlockScale = 0.30;\n"
47     "// varyings are written by vert shader, interpolated, and read by frag shader.\n"
48     "varying float LightIntensity;\n"
49     "varying vec2  BlockPosition;\n"
50     "void main(void)\n"
51     "{\n"
52     "    // per-vertex diffuse lighting\n"
53     "    vec4 ecPosition    = gl_ModelViewMatrix * gl_Vertex;\n"
54     "    vec3 tnorm         = normalize(gl_NormalMatrix * gl_Normal);\n"
55     "    vec3 lightVec      = normalize(LightPosition - vec3 (ecPosition));\n"
56     "    LightIntensity     = max(dot(lightVec, tnorm), 0.0);\n"
57     "    // blocks will be determined by fragment's position on the XZ plane.\n"
58     "    BlockPosition  = gl_Vertex.xz / BlockScale;\n"
59     "    // scale the geometry based on an animation variable.\n"
60     "    vec4 vertex    = gl_Vertex;\n"
61     "    vertex.w       = 1.0 + 0.4 * (Sine + 1.0);\n"
62     "    gl_Position    = gl_ModelViewProjectionMatrix * vertex;\n"
63     "}\n"
64 };
65 
66 static const char *blockyFragSource = {
67     "// blocky.frag - an GLSL fragment shader with animation\n"
68     "// the App updates uniforms \"slowly\" (eg once per frame) for animation.\n"
69     "uniform float Sine;\n"
70     "const vec3 Color1 = vec3(1.0, 1.0, 1.0);\n"
71     "const vec3 Color2 = vec3(0.0, 0.0, 0.0);\n"
72     "// varyings are written by vert shader, interpolated, and read by frag shader.\n"
73     "varying vec2  BlockPosition;\n"
74     "varying float LightIntensity;\n"
75     "void main(void)\n"
76     "{\n"
77     "    vec3 color;\n"
78     "    float ss, tt, w, h;\n"
79     "    ss = BlockPosition.x;\n"
80     "    tt = BlockPosition.y;\n"
81     "    if (fract(tt * 0.5) > 0.5)\n"
82     "        ss += 0.5;\n"
83     "    ss = fract(ss);\n"
84     "    tt = fract(tt);\n"
85     "    // animate the proportion of block to mortar\n"
86     "    float blockFract = (Sine + 1.1) * 0.4;\n"
87     "    w = step(ss, blockFract);\n"
88     "    h = step(tt, blockFract);\n"
89     "    color = mix(Color2, Color1, w * h) * LightIntensity;\n"
90     "    gl_FragColor = vec4 (color, 1.0);\n"
91     "}\n"
92 };
93 
94 ///////////////////////////////////////////////////////////////////////////
95 // callback for animating various Uniforms (currently only the SIN uniform)
96 
97 class AnimateCallback: public osg::UniformCallback
98 {
99     public:
100         enum Operation { SIN };
AnimateCallback(Operation op)101         AnimateCallback(Operation op) : _operation(op) {}
operator ()(osg::Uniform * uniform,osg::NodeVisitor * nv)102         virtual void operator() ( osg::Uniform* uniform, osg::NodeVisitor* nv )
103         {
104             float angle = 2.0 * nv->getFrameStamp()->getSimulationTime();
105             float sine = sinf( angle );            // -1 -> 1
106             switch(_operation) {
107                 case SIN : uniform->set( sine ); break;
108             }
109         }
110     private:
111         Operation _operation;
112 };
113 
main(int,char **)114 int main(int, char **)
115 {
116     // construct the viewer.
117     osgViewer::Viewer viewer;
118 
119     // use a geode with a Box ShapeDrawable
120     osg::Geode* basicModel = new osg::Geode();
121     basicModel->addDrawable(new osg::ShapeDrawable(new osg::Box(osg::Vec3(0.0f,0.0f,0.0f),1.0f)));
122 
123     // create the "blocky" shader, a simple animation test
124     osg::StateSet *ss = basicModel->getOrCreateStateSet();
125     osg::Program* program = new osg::Program;
126     program->setName( "blocky" );
127     program->addShader( new osg::Shader( osg::Shader::VERTEX, blockyVertSource ) );
128     program->addShader( new osg::Shader( osg::Shader::FRAGMENT, blockyFragSource ) );
129     ss->setAttributeAndModes(program, osg::StateAttribute::ON);
130 
131     // attach some animated Uniform variable to the state set
132     osg::Uniform* SineUniform   = new osg::Uniform( "Sine", 0.0f );
133     ss->addUniform( SineUniform );
134     SineUniform->setUpdateCallback(new AnimateCallback(AnimateCallback::SIN));
135 
136     // run the osg::Viewer using our model
137     viewer.setSceneData( basicModel );
138     return viewer.run();
139 }
140 
141 /*EOF*/
142