root/branches/Dirk_CPtr/Tutorials/22Shader.cpp

Revision 637, 9.0 kB (checked in by vossg, 2 years ago)

fixed : added statistics key (s)

  • Property svn:eol-style set to native
Line 
1 // OpenSG Tutorial Example: Shader
2 //
3 // This example shows how to use GLSL shaders.
4 // It creates a bouncing ball animation (completely calculated on the GPU).
5 // You need a graphics card supporting the GL_ARB_shading_language_100 extension
6 // to run this tutorial.
7
8 // Headers
9 #include <OpenSG/OSGGLUT.h>
10 #include <OpenSG/OSGConfig.h>
11 #include <OpenSG/OSGSimpleGeometry.h>
12 #include <OpenSG/OSGGLUTWindow.h>
13 #include <OpenSG/OSGSimpleSceneManager.h>
14 #include <OpenSG/OSGBaseFunctions.h>
15 #include <OpenSG/OSGTransform.h>
16 #include <OpenSG/OSGGroup.h>
17 #include <OpenSG/OSGPointLight.h>
18 #include <OpenSG/OSGRenderAction.h>
19 #include <OpenSG/OSGSceneFileHandler.h>
20
21 #include <OpenSG/OSGSimpleMaterial.h>
22 #include <OpenSG/OSGImage.h>
23 #include <OpenSG/OSGTextureChunk.h>
24 #include <OpenSG/OSGGradientBackground.h>
25 #include <OpenSG/OSGSHLChunk.h>
26 //#include <OpenSG/OSGShadowMapViewport.h>
27
28 // Activate the OpenSG namespace
29 OSG_USING_NAMESPACE
30
31 // The SimpleSceneManager to manage simple applications
32 SimpleSceneManager *_mgr = NULL;
33 NodePtr _scene = NullFC;
34 SHLChunkPtr _shl = NullFC;
35
36 // vertex shader program.
37 static std::string _vp_program =
38 "uniform float groundHeight;\n"
39 "uniform float bounceMin;\n"
40 "uniform float bounceHeight;\n"
41 "uniform float bounceSpeed;\n"
42 "uniform float time;\n"
43 "uniform float squeezeHeight;\n"
44 "\n"
45 "// output variables to the fragment program.\n"
46 "varying vec3 vNormal;\n"
47 "varying vec3 vViewVec;\n"
48 "\n"
49 "void main(void)\n"
50 "{\n"
51 "   // Normalize and scale, just because the source\n"
52 "   // model is not a perfect sphere around origin\n"
53 "   vec3 pos = 5.0 * normalize(vec3(gl_Vertex));\n"
54 "\n"
55 "   // Basic Bounce\n"
56 "   float t = fract( time * bounceSpeed )  ;\n"
57 "   float center = bounceHeight * t * (1.0 - t);\n"
58 "\n"
59 "   pos.y += center + bounceMin;\n"
60 "\n"
61 "   // Squeeze\n"
62 "   if (pos.y < groundHeight)\n"
63 "   {\n"
64 "      // Squeeze in Z direction\n"
65 "      float squeeze = (1.0 - exp2(1.0 * (pos.y - groundHeight)));\n"
66 "      pos.y = groundHeight - squeeze * squeezeHeight;\n"
67 "\n"
68 "      // Flatten in XZ direcion\n"
69 "      vec2 xyNorm = vec2(normalize(vec3(gl_Normal.xy,1.0)));\n"
70 "      pos.xz += squeeze * xyNorm * squeezeHeight;\n"
71 "\n"
72 "   }\n"
73 "\n"
74 "   gl_Position = gl_ModelViewProjectionMatrix * vec4(pos, 1.0);\n"
75 "\n"
76 "   // gl_NormalMatrix the inverse of the upper 3x3 of the view matrix.\n"
77 "   vNormal   =  gl_NormalMatrix  * gl_Normal;\n"
78 "\n"
79 "   vViewVec   = -vec3((gl_ModelViewMatrix * vec4(pos, 1.0)));\n"
80 "}\n";
81
82 // fragment shader program for bump mapping in surface local coordinates
83 static std::string _fp_program =
84 "uniform vec3 ballColor;\n"
85 "const vec4 lightDir = vec4(0.43644,-0.43644,-0.87287,1.0);\n"
86 "\n"
87 "// input variables from the vertex program.\n"
88 "varying vec3 vNormal;\n"
89 "varying vec3 vViewVec;\n"
90 "\n"
91 "void main(void)\n"
92 "{\n"
93 "   vec3 nLightVec = normalize(vec3(lightDir.x, lightDir.y, -lightDir.z));\n"
94 "   // Simple diffuse and specular\n"
95 "   vec3 nNormal = normalize(vNormal);  // nNormal = normalized normal\n"
96 "\n"
97 "   float diffuse = clamp( (dot(vNormal, nLightVec)) ,0.0 ,1.0 );\n"
98 "   vec3  reflectVec = reflect(-normalize(vViewVec), nNormal);\n"
99 "\n"
100 "   float specular = pow(clamp( dot(reflectVec, vec3(nLightVec)) ,0.0 ,1.0 ),32.0);\n"
101 "\n"
102 "\n"
103 "   gl_FragColor = vec4(ballColor, 1.0) * diffuse + 0.8 * specular;\n"
104 "}\n";
105
106 // forward declaration so we can have the interesting stuff upfront
107 int setupGLUT(int *argc, char *argv[]);
108
109 // redraw the window
110 void display(void)
111 {
112     static Real32 t = glutGet(GLUT_ELAPSED_TIME);
113
114     Real32 td = (glutGet(GLUT_ELAPSED_TIME) - t) / 100.0f;
115     _shl->setUniformParameter("time", td);
116
117     _mgr->redraw();
118 }
119
120
121 // Initialize GLUT & OpenSG and set up the scene
122 int main(int argc, char **argv)
123 {
124     // OSG init
125     osgInit(argc,argv);
126
127     // GLUT init
128     int winid = setupGLUT(&argc, argv);
129
130     // create the scene
131     _scene = makeCoredNode<Group>();
132
133     // create light
134     TransformPtr point1_trans;
135     PointLightPtr point1_core;
136     NodePtr point1 = makeCoredNode<PointLight>(&point1_core);
137     NodePtr point1_beacon = makeCoredNode<Transform>(&point1_trans);
138     point1_trans->editMatrix().setTranslate(0.0, 100.0, 0.0);
139
140     point1_core->setAmbient(0.15,0.15,0.15,1);
141     point1_core->setDiffuse(0.8,0.8,0.8,1);
142     point1_core->setSpecular(0.0,0.0,0.0,1);
143     point1_core->setBeacon(point1_beacon);
144     point1_core->setOn(true);
145
146     // create bottom
147     NodePtr bottom = makePlane(50.0, 50.0, 128, 128);
148    
149     UChar8 imgdata[] =
150         {  255,0,0,  0,255,0,  0,0,255, 255,255,0 };
151     ImagePtr bottom_img = Image::create();
152     bottom_img->set(Image::OSG_RGB_PF, 2, 2, 1, 1, 1, 0, imgdata);
153
154     TextureChunkPtr bottom_tex = TextureChunk::create();
155     bottom_tex->setImage(bottom_img);
156     bottom_tex->setMinFilter(GL_LINEAR);
157     bottom_tex->setMagFilter(GL_LINEAR);
158     bottom_tex->setWrapS(GL_REPEAT);
159     bottom_tex->setWrapT(GL_REPEAT);
160     bottom_tex->setEnvMode(GL_MODULATE);
161
162     SimpleMaterialPtr bottom_mat = SimpleMaterial::create();
163     bottom_mat->setAmbient(Color3f(0.3,0.3,0.3));
164     bottom_mat->setDiffuse(Color3f(1.0,1.0,1.0));
165     bottom_mat->addChunk(bottom_tex);
166    
167     GeometryPtr bottom_geo = cast_dynamic<GeometryPtr>(bottom->getCore());
168     bottom_geo->setMaterial(bottom_mat);
169    
170     // rotate the bottom about 90 degree.
171     TransformPtr bottom_trans_core;
172     NodePtr bottom_trans = makeCoredNode<Transform>(&bottom_trans_core);
173     Quaternion q;
174     q.setValueAsAxisDeg(1, 0, 0, -90);
175     bottom_trans_core->editMatrix().setRotate(q);
176     bottom_trans->addChild(bottom);
177
178     // create a sphere.
179     NodePtr sphere = makeLatLongSphere(50, 50, 1.0);
180    
181     // create the shader material
182     ChunkMaterialPtr cmat = ChunkMaterial::create();
183     _shl = SHLChunk::create();
184     _shl->setVertexProgram(_vp_program);
185     _shl->setFragmentProgram(_fp_program);
186     _shl->setUniformParameter("groundHeight", 1.0f);
187     _shl->setUniformParameter("bounceMin", -0.1f);
188     _shl->setUniformParameter("bounceHeight", 75.0f);
189     _shl->setUniformParameter("bounceSpeed", 0.05f);
190     _shl->setUniformParameter("time", 0.0f);
191     _shl->setUniformParameter("squeezeHeight", 1.0f);
192     _shl->setUniformParameter("ballColor", Vec3f(1.0f, 0.0f, 0.0f));
193
194     cmat->addChunk(_shl);
195
196     GeometryPtr spheregeo = cast_dynamic<GeometryPtr>(sphere->getCore());
197     spheregeo->setMaterial(cmat);
198
199     point1->addChild(bottom_trans);
200     point1->addChild(sphere);
201
202     _scene->addChild(point1_beacon);
203     _scene->addChild(point1);
204
205     // create ShadowViewport with a gradient background.
206     //ShadowMapViewportPtr svp = ShadowMapViewport::create();
207     GradientBackgroundPtr gbg = GradientBackground::create();
208
209     gbg->addLine(Color3f(0.7, 0.7, 0.8), 0);
210     gbg->addLine(Color3f(0.0, 0.1, 0.3), 1);
211
212     // Shadow viewport
213     //svp->setBackground(gbg);
214     //svp->setRoot(_scene);
215     //svp->setSize(0,0,1,1);
216     //svp->setOffFactor(10.0);
217     //svp->setOffBias(4.0);
218     //svp->setShadowColor(Color4f(0.1, 0.1, 0.1, 1.0));
219     //svp->setMapSize(1024);
220     // you can add the light sources here, as default all light source in
221     // the scenegraph are used.
222     //svp->getLightNodes().push_back(point1);
223
224     // the connection between GLUT and OpenSG
225     GLUTWindowPtr gwin= GLUTWindow::create();
226     gwin->setId(winid);
227     //gwin->addPort(svp);
228     gwin->init();
229
230     commitChanges();
231
232     // create the SimpleSceneManager helper
233     _mgr = new SimpleSceneManager;
234
235     // tell the manager what to manage
236     _mgr->setWindow(gwin );
237     _mgr->setRoot  (_scene);
238
239     //svp->setCamera(_mgr->getCamera());
240
241     _mgr->turnHeadlightOff();
242
243     // show the whole scene
244     _mgr->showAll();
245     _mgr->getNavigator()->setFrom(Pnt3f(0.0, 31, 47));
246
247     // GLUT main loop
248     glutMainLoop();
249
250     return 0;
251 }
252
253 //
254 // GLUT callback functions
255 //
256
257 // react to size changes
258 void reshape(int w, int h)
259 {
260     _mgr->resize(w, h);
261     glutPostRedisplay();
262 }
263
264 // react to mouse button presses
265 void mouse(int button, int state, int x, int y)
266 {
267     if (state)
268         _mgr->mouseButtonRelease(button, x, y);
269     else
270         _mgr->mouseButtonPress(button, x, y);
271        
272     glutPostRedisplay();
273 }
274
275 // react to mouse motions with pressed buttons
276 void motion(int x, int y)
277 {
278     _mgr->mouseMove(x, y);
279     glutPostRedisplay();
280 }
281
282 // react to keys
283 void keyboard(unsigned char k, int x, int y)
284 {
285     switch(k)
286     {
287         case 27:
288             OSG::osgExit();
289             exit(0);
290         break;
291         case 'w':
292             SceneFileHandler::the()->write(_scene, "scene.osb.gz", true);
293             printf("wrote scene.\n");
294         break;
295
296         case 's':
297         {
298             _mgr->setStatistics(!_mgr->getStatistics());
299         }
300         break;
301     }
302 }
303
304 // setup the GLUT library which handles the windows for us
305 int setupGLUT(int *argc, char *argv[])
306 {
307     glutInit(argc, argv);
308     glutInitDisplayMode(GLUT_RGB | GLUT_DEPTH | GLUT_DOUBLE);
309    
310     int winid = glutCreateWindow("OpenSG");
311    
312     glutReshapeFunc(reshape);
313     glutDisplayFunc(display);
314     glutMouseFunc(mouse);
315     glutMotionFunc(motion);
316     glutKeyboardFunc(keyboard);
317
318     // call the redraw function whenever there's nothing else to do
319     glutIdleFunc(display);
320
321     return winid;
322 }
Note: See TracBrowser for help on using the browser.