1 // OpenSG Tutorial Example: Shader
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.
8 #ifdef OSG_BUILD_ACTIVE
11 #include <OSGConfig.h>
12 #include <OSGSimpleGeometry.h>
13 #include <OSGGLUTWindow.h>
14 #include <OSGSimpleSceneManager.h>
15 #include <OSGBaseFunctions.h>
16 #include <OSGTransform.h>
18 #include <OSGPointLight.h>
19 #include <OSGRenderAction.h>
20 #include <OSGSceneFileHandler.h>
22 #include <OSGSimpleMaterial.h>
24 #include <OSGTextureObjChunk.h>
25 #include <OSGTextureEnvChunk.h>
26 #include <OSGGradientBackground.h>
27 #include <OSGSimpleSHLChunk.h>
30 #include <OpenSG/OSGGLUT.h>
31 #include <OpenSG/OSGConfig.h>
32 #include <OpenSG/OSGSimpleGeometry.h>
33 #include <OpenSG/OSGGLUTWindow.h>
34 #include <OpenSG/OSGSimpleSceneManager.h>
35 #include <OpenSG/OSGBaseFunctions.h>
36 #include <OpenSG/OSGTransform.h>
37 #include <OpenSG/OSGGroup.h>
38 #include <OpenSG/OSGPointLight.h>
39 #include <OpenSG/OSGRenderAction.h>
40 #include <OpenSG/OSGSceneFileHandler.h>
42 #include <OpenSG/OSGSimpleMaterial.h>
43 #include <OpenSG/OSGImage.h>
44 #include <OpenSG/OSGTextureObjChunk.h>
45 #include <OpenSG/OSGTextureEnvChunk.h>
46 #include <OpenSG/OSGGradientBackground.h>
47 #include <OpenSG/OSGSimpleSHLChunk.h>
52 // The SimpleSceneManager to manage simple applications
53 SimpleSceneManagerRefPtr _mgr
= NULL
;
55 SimpleSHLChunkRefPtr _shl
;
57 // vertex shader program.
58 static std::string _vp_program
=
59 "uniform float groundHeight;\n"
60 "uniform float bounceMin;\n"
61 "uniform float bounceHeight;\n"
62 "uniform float bounceSpeed;\n"
63 "uniform float time;\n"
64 "uniform float squeezeHeight;\n"
66 "// output variables to the fragment program.\n"
67 "varying vec3 vNormal;\n"
68 "varying vec3 vViewVec;\n"
72 " // Normalize and scale, just because the source\n"
73 " // model is not a perfect sphere around origin\n"
74 " vec3 pos = 5.0 * normalize(vec3(gl_Vertex));\n"
77 " float t = fract( time * bounceSpeed ) ;\n"
78 " float center = bounceHeight * t * (1.0 - t);\n"
80 " pos.y += center + bounceMin;\n"
83 " if (pos.y < groundHeight)\n"
85 " // Squeeze in Z direction\n"
86 " float squeeze = (1.0 - exp2(1.0 * (pos.y - groundHeight)));\n"
87 " pos.y = groundHeight - squeeze * squeezeHeight;\n"
89 " // Flatten in XZ direcion\n"
90 " vec2 xyNorm = vec2(normalize(vec3(gl_Normal.xy,1.0)));\n"
91 " pos.xz += squeeze * xyNorm * squeezeHeight;\n"
95 " gl_Position = gl_ModelViewProjectionMatrix * vec4(pos, 1.0);\n"
97 " // gl_NormalMatrix the inverse of the upper 3x3 of the view matrix.\n"
98 " vNormal = gl_NormalMatrix * gl_Normal;\n"
100 " vViewVec = -vec3((gl_ModelViewMatrix * vec4(pos, 1.0)));\n"
103 // fragment shader program for bump mapping in surface local coordinates
104 static std::string _fp_program
=
105 "uniform vec3 ballColor;\n"
106 "const vec4 lightDir = vec4(0.43644,-0.43644,-0.87287,1.0);\n"
108 "// input variables from the vertex program.\n"
109 "varying vec3 vNormal;\n"
110 "varying vec3 vViewVec;\n"
114 " vec3 nLightVec = normalize(vec3(lightDir.x, lightDir.y, -lightDir.z));\n"
115 " // Simple diffuse and specular\n"
116 " vec3 nNormal = normalize(vNormal); // nNormal = normalized normal\n"
118 " float diffuse = clamp( (dot(vNormal, nLightVec)) ,0.0 ,1.0 );\n"
119 " vec3 reflectVec = reflect(-normalize(vViewVec), nNormal);\n"
121 " float specular = pow(clamp( dot(reflectVec, vec3(nLightVec)) ,0.0 ,1.0 ),32.0);\n"
124 " gl_FragColor = vec4(ballColor, 1.0) * diffuse + 0.8 * specular;\n"
127 // forward declaration so we can have the interesting stuff upfront
128 int setupGLUT(int *argc
, char *argv
[]);
133 static Real32 t
= glutGet(GLUT_ELAPSED_TIME
);
135 Real32 td
= (glutGet(GLUT_ELAPSED_TIME
) - t
) / 100.0f
;
136 _shl
->updateUniformVariable("time", td
);
142 // Initialize GLUT & OpenSG and set up the scene
143 int main(int argc
, char **argv
)
149 int winid
= setupGLUT(&argc
, argv
);
151 // open a new scope, because the pointers below should go out of scope
152 // before entering glutMainLoop.
153 // Otherwise OpenSG will complain about objects being alive after shutdown.
156 _scene
= makeCoredNode
<Group
>();
159 TransformRefPtr point1_trans
;
160 PointLightRefPtr point1_core
;
161 NodeRefPtr point1
= makeCoredNode
<PointLight
>(&point1_core
);
162 NodeRefPtr point1_beacon
= makeCoredNode
<Transform
>(&point1_trans
);
163 point1_trans
->editMatrix().setTranslate(0.0, 100.0, 0.0);
165 point1_core
->setAmbient (0.15f
,0.15f
,0.15f
,1.f
);
166 point1_core
->setDiffuse (0.8f
, 0.8f
, 0.8f
, 1.f
);
167 point1_core
->setSpecular(0.0f
, 0.0f
, 0.0f
, 1.f
);
168 point1_core
->setBeacon(point1_beacon
);
169 point1_core
->setOn(true);
172 NodeRefPtr bottom
= makePlane(50.0, 50.0, 128, 128);
175 { 255,0,0, 0,255,0, 0,0,255, 255,255,0 };
176 ImageRefPtr bottom_img
= Image::create();
177 bottom_img
->set(Image::OSG_RGB_PF
, 2, 2, 1, 1, 1, 0, imgdata
);
179 TextureObjChunkRefPtr bottom_tex
= TextureObjChunk::create();
180 TextureEnvChunkRefPtr bottom_tex_env
= TextureEnvChunk::create();
182 bottom_tex
->setImage(bottom_img
);
183 bottom_tex
->setMinFilter(GL_LINEAR
);
184 bottom_tex
->setMagFilter(GL_LINEAR
);
185 bottom_tex
->setWrapS(GL_REPEAT
);
186 bottom_tex
->setWrapT(GL_REPEAT
);
187 bottom_tex_env
->setEnvMode(GL_MODULATE
);
189 SimpleMaterialRefPtr bottom_mat
= SimpleMaterial::create();
190 bottom_mat
->setAmbient(Color3f(0.3f
,0.3f
,0.3f
));
191 bottom_mat
->setDiffuse(Color3f(1.0f
,1.0f
,1.0f
));
192 bottom_mat
->addChunk(bottom_tex
);
193 bottom_mat
->addChunk(bottom_tex_env
);
195 GeometryRefPtr bottom_geo
= dynamic_cast<Geometry
*>(bottom
->getCore());
196 bottom_geo
->setMaterial(bottom_mat
);
198 // rotate the bottom about 90 degree.
199 TransformRefPtr bottom_trans_core
;
200 NodeRefPtr bottom_trans
= makeCoredNode
<Transform
>(&bottom_trans_core
);
202 q
.setValueAsAxisDeg(1, 0, 0, -90);
203 bottom_trans_core
->editMatrix().setRotate(q
);
204 bottom_trans
->addChild(bottom
);
207 NodeRefPtr sphere
= makeLatLongSphere(50, 50, 1.0);
209 // create the shader material
210 ChunkMaterialRefPtr cmat
= ChunkMaterial::create();
211 _shl
= SimpleSHLChunk::create();
212 _shl
->setVertexProgram (_vp_program
);
213 _shl
->setFragmentProgram(_fp_program
);
214 _shl
->addUniformVariable("groundHeight", 1.0f
);
215 _shl
->addUniformVariable("bounceMin", -0.1f
);
216 _shl
->addUniformVariable("bounceHeight", 75.0f
);
217 _shl
->addUniformVariable("bounceSpeed", 0.05f
);
218 _shl
->addUniformVariable("time", 0.0f
);
219 _shl
->addUniformVariable("squeezeHeight", 1.0f
);
220 _shl
->addUniformVariable("ballColor", Vec3f(1.0f
, 0.0f
, 0.0f
));
222 cmat
->addChunk(_shl
);
224 GeometryRefPtr spheregeo
= dynamic_cast<Geometry
*>(sphere
->getCore());
225 spheregeo
->setMaterial(cmat
);
227 point1
->addChild(bottom_trans
);
228 point1
->addChild(sphere
);
230 _scene
->addChild(point1_beacon
);
231 _scene
->addChild(point1
);
233 // the connection between GLUT and OpenSG
234 GLUTWindowRefPtr gwin
= GLUTWindow::create();
235 gwin
->setGlutId(winid
);
240 // create the SimpleSceneManager helper
241 _mgr
= SimpleSceneManager::create();
243 // tell the manager what to manage
244 _mgr
->setWindow(gwin
);
245 _mgr
->setRoot (_scene
);
247 //svp->setCamera(_mgr->getCamera());
249 _mgr
->turnHeadlightOff();
251 // show the whole scene
253 _mgr
->getNavigator()->setFrom(Pnt3f(0.0, 31, 47));
263 // GLUT callback functions
266 // react to size changes
267 void reshape(int w
, int h
)
273 // react to mouse button presses
274 void mouse(int button
, int state
, int x
, int y
)
277 _mgr
->mouseButtonRelease(button
, x
, y
);
279 _mgr
->mouseButtonPress(button
, x
, y
);
284 // react to mouse motions with pressed buttons
285 void motion(int x
, int y
)
287 _mgr
->mouseMove(x
, y
);
292 void keyboard(unsigned char k
, int x
, int y
)
297 // clean up global variables
306 SceneFileHandler::the()->write(_scene
, "scene.osb.gz", true);
307 printf("wrote scene.\n");
312 _mgr
->setStatistics(!_mgr
->getStatistics());
318 // setup the GLUT library which handles the windows for us
319 int setupGLUT(int *argc
, char *argv
[])
321 glutInit(argc
, argv
);
322 glutInitDisplayMode(GLUT_RGB
| GLUT_DEPTH
| GLUT_DOUBLE
);
324 int winid
= glutCreateWindow("OpenSG");
326 glutReshapeFunc(reshape
);
327 glutDisplayFunc(display
);
328 glutMouseFunc(mouse
);
329 glutMotionFunc(motion
);
330 glutKeyboardFunc(keyboard
);
332 // call the redraw function whenever there's nothing else to do
333 glutIdleFunc(display
);