root/OpenSceneGraph/trunk/examples/osgvertexprogram/osgvertexprogram.cpp @ 1856

Revision 1856, 18.1 kB (checked in by robert, 11 years ago)

Added tests for presense of extensions to osgcubemap, osgvertexproram and
osgmultitexture examples.

Added osg::VertexProgram::Extensions class to better handle multiple graphics
context vertex program extensions.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
Line 
1#include <osg/Vec3>
2#include <osg/Vec4>
3#include <osg/Quat>
4#include <osg/Matrix>
5#include <osg/ShapeDrawable>
6#include <osg/Geometry>
7#include <osg/Geode>
8#include <osg/Transform>
9#include <osg/Material>
10#include <osg/NodeCallback>
11#include <osg/Depth>
12#include <osg/CullFace>
13#include <osg/TexMat>
14#include <osg/TexGen>
15#include <osg/TexEnvCombine>
16#include <osg/TextureCubeMap>
17#include <osg/VertexProgram>
18
19#include <osgDB/Registry>
20#include <osgDB/ReadFile>
21
22#include <osgUtil/SmoothingVisitor>
23#include <osgUtil/Optimizer>
24
25#include <osgProducer/Viewer>
26
27
28float refract = 1.01;          // ratio of indicies of refraction
29float fresnel = 1.1;           // Fresnel multiplier
30
31
32const char vpstr[] =
33    "!!ARBvp1.0 # Refraction                                    \n"
34    "                                                           \n"
35    "ATTRIB iPos         = vertex.position;                     \n"
36    "#ATTRIB iCol        = vertex.color.primary;                \n"
37    "ATTRIB iNormal      = vertex.normal;                       \n"
38    "PARAM  esEyePos     = { 0, 0, 0, 1 };                      \n"
39    "PARAM  const0123    = { 0, 1, 2, 3 };                      \n"
40    "PARAM  fresnel      = program.local[0];                    \n"
41    "PARAM  refract      = program.local[1];                    \n"
42    "PARAM  itMV[4]      = { state.matrix.modelview.invtrans }; \n"
43    "PARAM  MVP[4]       = { state.matrix.mvp };                \n"
44    "PARAM  MV[4]        = { state.matrix.modelview };          \n"
45    "PARAM  texmat[4]    = { state.matrix.texture[0] };         \n"
46    "TEMP   esPos;        # position in eye-space               \n"
47    "TEMP   esNormal;     # normal in eye-space                 \n"
48    "TEMP   tmp, IdotN, K;                                      \n"
49    "TEMP   esE;          # eye vector                          \n"
50    "TEMP   esI;          # incident vector (=-E)               \n"
51    "TEMP   esR;          # first refract- then reflect-vector  \n"
52    "OUTPUT oPos         = result.position;                     \n"
53    "OUTPUT oColor       = result.color;                        \n"
54    "OUTPUT oRefractMap  = result.texcoord[0];                  \n"
55    "OUTPUT oReflectMap  = result.texcoord[1];                  \n"
56    "                                                           \n"
57    "# transform vertex to clip space                           \n"
58    "DP4    oPos.x, MVP[0], iPos;                               \n"
59    "DP4    oPos.y, MVP[1], iPos;                               \n"
60    "DP4    oPos.z, MVP[2], iPos;                               \n"
61    "DP4    oPos.w, MVP[3], iPos;                               \n"
62    "                                                           \n"
63    "# Transform the normal to eye space.                       \n"
64    "DP3    esNormal.x, itMV[0], iNormal;                       \n"
65    "DP3    esNormal.y, itMV[1], iNormal;                       \n"
66    "DP3    esNormal.z, itMV[2], iNormal;                       \n"
67    "                                                           \n"
68    "# normalize normal                                         \n"
69    "DP3    esNormal.w, esNormal, esNormal;                     \n"
70    "RSQ    esNormal.w, esNormal.w;                             \n"
71    "MUL    esNormal, esNormal, esNormal.w;                     \n"
72    "                                                           \n"
73    "# transform vertex position to eye space                   \n"
74    "DP4    esPos.x, MV[0], iPos;                               \n"
75    "DP4    esPos.y, MV[1], iPos;                               \n"
76    "DP4    esPos.z, MV[2], iPos;                               \n"
77    "DP4    esPos.w, MV[3], iPos;                               \n"
78    "                                                           \n"
79    "# vertex to eye vector                                     \n"
80    "ADD    esE, -esPos, esEyePos;                              \n"
81    "#MOV   esE, -esPos;                                        \n"
82    "                                                           \n"
83    "# normalize eye vector                                     \n"
84    "DP3    esE.w, esE, esE;                                    \n"
85    "RSQ    esE.w, esE.w;                                       \n"
86    "MUL    esE, esE, esE.w;                                    \n"
87    "                                                           \n"
88    "# calculate some handy values                              \n"
89    "MOV    esI, -esE;                                          \n"
90    "DP3    IdotN, esNormal, esI;                               \n"
91    "                                                           \n"
92    "# calculate refraction vector, Renderman style             \n"
93    "                                                           \n"
94    "# k = 1-index*index*(1-(I dot N)^2)                        \n"
95    "MAD    tmp, -IdotN, IdotN, const0123.y;                    \n"
96    "MUL    tmp, tmp, refract.y;                                \n"
97    "ADD    K.x, const0123.y, -tmp;                             \n"
98    "                                                           \n"
99    "# k<0,  R = [0,0,0]                                        \n"
100    "# k>=0, R = index*I-(index*(I dot N) + sqrt(k))*N          \n"
101    "RSQ    K.y, K.x;                                           \n"
102    "RCP    K.y, K.y;                           # K.y = sqrt(k) \n"
103    "MAD    tmp.x, refract.x, IdotN, K.y;                       \n"
104    "MUL    tmp, esNormal, tmp.x;                               \n"
105    "MAD    esR, refract.x, esI, tmp;                           \n"
106    "                                                           \n"
107    "# transform refracted ray by cubemap transform             \n"
108    "DP3    oRefractMap.x, texmat[0], esR;                      \n"
109    "DP3    oRefractMap.y, texmat[1], esR;                      \n"
110    "DP3    oRefractMap.z, texmat[2], esR;                      \n"
111    "                                                           \n"
112    "# calculate reflection vector                              \n"
113    "# R = 2*N*(N dot E)-E                                      \n"
114    "MUL    tmp, esNormal, const0123.z;                         \n"
115    "DP3    esR.w, esNormal, esE;                               \n"
116    "MAD    esR, esR.w, tmp, -esE;                              \n"
117    "                                                           \n"
118    "# transform reflected ray by cubemap transform             \n"
119    "DP3    oReflectMap.x, texmat[0], esR;                      \n"
120    "DP3    oReflectMap.y, texmat[1], esR;                      \n"
121    "DP3    oReflectMap.z, texmat[2], esR;                      \n"
122    "                                                           \n"
123    "# Fresnel approximation = fresnel*(1-(N dot I))^2          \n"
124    "ADD    tmp.x, const0123.y, -IdotN;                         \n"
125    "MUL    tmp.x, tmp.x, tmp.x;                                \n"
126    "MUL    oColor, tmp.x, fresnel;                             \n"
127    "                                                           \n"
128    "END                                                        \n";
129
130
131osg::TextureCubeMap* readCubeMap()
132{
133    osg::TextureCubeMap* cubemap = new osg::TextureCubeMap;
134    //#define CUBEMAP_FILENAME(face) "nvlobby_" #face ".png"
135    //#define CUBEMAP_FILENAME(face) "Cubemap_axis/" #face ".png"
136    #define CUBEMAP_FILENAME(face) "Cubemap_snow/" #face ".jpg"
137
138    osg::Image* imagePosX = osgDB::readImageFile(CUBEMAP_FILENAME(posx));
139    osg::Image* imageNegX = osgDB::readImageFile(CUBEMAP_FILENAME(negx));
140    osg::Image* imagePosY = osgDB::readImageFile(CUBEMAP_FILENAME(posy));
141    osg::Image* imageNegY = osgDB::readImageFile(CUBEMAP_FILENAME(negy));
142    osg::Image* imagePosZ = osgDB::readImageFile(CUBEMAP_FILENAME(posz));
143    osg::Image* imageNegZ = osgDB::readImageFile(CUBEMAP_FILENAME(negz));
144
145    if (imagePosX && imageNegX && imagePosY && imageNegY && imagePosZ && imageNegZ)
146    {
147        cubemap->setImage(osg::TextureCubeMap::POSITIVE_X, imagePosX);
148        cubemap->setImage(osg::TextureCubeMap::NEGATIVE_X, imageNegX);
149        cubemap->setImage(osg::TextureCubeMap::POSITIVE_Y, imagePosY);
150        cubemap->setImage(osg::TextureCubeMap::NEGATIVE_Y, imageNegY);
151        cubemap->setImage(osg::TextureCubeMap::POSITIVE_Z, imagePosZ);
152        cubemap->setImage(osg::TextureCubeMap::NEGATIVE_Z, imageNegZ);
153
154        cubemap->setWrap(osg::Texture::WRAP_S, osg::Texture::CLAMP_TO_EDGE);
155        cubemap->setWrap(osg::Texture::WRAP_T, osg::Texture::CLAMP_TO_EDGE);
156        cubemap->setWrap(osg::Texture::WRAP_R, osg::Texture::CLAMP_TO_EDGE);
157
158        cubemap->setFilter(osg::Texture::MIN_FILTER, osg::Texture::LINEAR_MIPMAP_LINEAR);
159        cubemap->setFilter(osg::Texture::MAG_FILTER, osg::Texture::LINEAR);
160    }
161
162    return cubemap;
163}
164
165
166// Update texture matrix for cubemaps
167struct TexMatCallback : public osg::NodeCallback
168{
169public:
170
171    TexMatCallback(osg::TexMat& tm) :
172        _texMat(tm)
173    {
174    }
175
176    virtual void operator()(osg::Node* node, osg::NodeVisitor* nv)
177    {
178        osgUtil::CullVisitor* cv = dynamic_cast<osgUtil::CullVisitor*>(nv);
179        if (cv)
180        {
181            const osg::Matrix& MV = cv->getModelViewMatrix();
182            const osg::Matrix R = osg::Matrix::rotate( osg::DegreesToRadians(112.0f), 0.0f,0.0f,1.0f)*
183                                  osg::Matrix::rotate( osg::DegreesToRadians(90.0f), 1.0f,0.0f,0.0f);
184
185            osg::Quat q;
186            q.set(MV);
187            const osg::Matrix C = osg::Matrix::rotate( q.inverse() );
188
189            _texMat.setMatrix( C*R );
190        }
191
192        traverse(node,nv);
193    }
194
195    osg::TexMat& _texMat;
196};
197
198
199struct MoveEarthySkyWithEyePointCallback : public osg::Transform::ComputeTransformCallback
200{
201    /** Get the transformation matrix which moves from local coords to world coords.*/
202    virtual bool computeLocalToWorldMatrix(osg::Matrix& matrix,const osg::Transform*, osg::NodeVisitor* nv) const 
203    {
204        osgUtil::CullVisitor* cv = dynamic_cast<osgUtil::CullVisitor*>(nv);
205        if (cv)
206        {
207            osg::Vec3 eyePointLocal = cv->getEyeLocal();
208            matrix.preMult(osg::Matrix::translate(eyePointLocal));
209        }
210        return true;
211    }
212
213    /** Get the transformation matrix which moves from world coords to local coords.*/
214    virtual bool computeWorldToLocalMatrix(osg::Matrix& matrix,const osg::Transform*, osg::NodeVisitor* nv) const
215    {
216        osgUtil::CullVisitor* cv = dynamic_cast<osgUtil::CullVisitor*>(nv);
217        if (cv)
218        {
219            osg::Vec3 eyePointLocal = cv->getEyeLocal();
220            matrix.postMult(osg::Matrix::translate(-eyePointLocal));
221        }
222        return true;
223    }
224};
225
226
227osg::Node* createSkyBox()
228{
229
230    osg::StateSet* stateset = new osg::StateSet();
231
232    osg::TexEnv* te = new osg::TexEnv;
233    te->setMode(osg::TexEnv::REPLACE);
234    stateset->setTextureAttributeAndModes(0, te, osg::StateAttribute::ON);
235
236    osg::TexGen *tg = new osg::TexGen;
237    tg->setMode(osg::TexGen::NORMAL_MAP);
238    stateset->setTextureAttributeAndModes(0, tg, osg::StateAttribute::ON);
239
240    osg::TexMat *tm = new osg::TexMat;
241    stateset->setTextureAttribute(0, tm);
242
243    osg::TextureCubeMap* skymap = readCubeMap();
244    stateset->setTextureAttributeAndModes(0, skymap, osg::StateAttribute::ON);
245
246    stateset->setMode( GL_LIGHTING, osg::StateAttribute::OFF );
247    stateset->setMode( GL_CULL_FACE, osg::StateAttribute::OFF );
248
249    // clear the depth to the far plane.
250    osg::Depth* depth = new osg::Depth;
251    depth->setFunction(osg::Depth::ALWAYS);
252    depth->setRange(1.0,1.0);   
253    stateset->setAttributeAndModes(depth, osg::StateAttribute::ON );
254
255    stateset->setRenderBinDetails(-1,"RenderBin");
256
257    osg::Drawable* drawable = new osg::ShapeDrawable(new osg::Sphere(osg::Vec3(0.0f,0.0f,0.0f),1));
258
259    osg::Geode* geode = new osg::Geode;
260    geode->setCullingActive(false);
261    geode->setStateSet( stateset );
262    geode->addDrawable(drawable);
263
264
265    osg::Transform* transform = new osg::Transform;
266    transform->setCullingActive(false);
267    transform->setComputeTransformCallback(new MoveEarthySkyWithEyePointCallback);
268    transform->addChild(geode);
269
270    osg::ClearNode* clearNode = new osg::ClearNode;
271//  clearNode->setRequiresClear(false);
272    clearNode->setCullCallback(new TexMatCallback(*tm));
273    clearNode->addChild(transform);
274
275    return clearNode;
276}
277
278
279
280
281osg::Node* addRefractStateSet(osg::Node* node)
282{
283    osg::StateSet* stateset = new osg::StateSet();
284
285    osg::TextureCubeMap* reflectmap = readCubeMap();
286    stateset->setTextureAttributeAndModes( 0, reflectmap, osg::StateAttribute::ON | osg::StateAttribute::OVERRIDE );
287    stateset->setTextureAttributeAndModes( 1, reflectmap, osg::StateAttribute::ON | osg::StateAttribute::OVERRIDE );
288   
289    osg::TexMat* texMat = new osg::TexMat;
290    stateset->setTextureAttribute(0, texMat);
291
292    // ---------------------------------------------------
293    // Vertex Program
294    // ---------------------------------------------------
295    osg::VertexProgram* vp = new osg::VertexProgram();
296    vp->setVertexProgram( vpstr );
297    vp->setProgramLocalParameter( 0, osg::Vec4( fresnel, fresnel, fresnel, 1.0f ) );
298    vp->setProgramLocalParameter( 1, osg::Vec4( refract, refract*refract, 0.0f, 0.0f ) );
299    stateset->setAttributeAndModes( vp, osg::StateAttribute::ON | osg::StateAttribute::OVERRIDE );
300
301    // ---------------------------------------------------
302    // fragment = refraction*(1-fresnel) + reflection*fresnel
303    // T0 = texture unit 0, refraction map
304    // T1 = texture unit 1, reflection map
305    // C.rgb = primary color, water color
306    // C.a   = primary color, fresnel factor
307    // Cp    = result from previous texture environment
308    // ---------------------------------------------------
309
310    // REPLACE function: Arg0
311    // = T0
312    osg::TexEnvCombine *te0 = new osg::TexEnvCombine;   
313    te0->setCombine_RGB(osg::TexEnvCombine::REPLACE);
314    te0->setSource0_RGB(osg::TexEnvCombine::TEXTURE0);
315    te0->setOperand0_RGB(osg::TexEnvCombine::SRC_COLOR);
316   
317    // INTERPOLATE function: Arg0 * (Arg2) + Arg1 * (1-Arg2)
318    // = T1 * C0.a + Cp * (1-C0.a)
319    osg::TexEnvCombine *te1 = new osg::TexEnvCombine;   
320
321    // rgb = Cp + Ct
322    te1->setCombine_RGB(osg::TexEnvCombine::INTERPOLATE);
323    te1->setSource0_RGB(osg::TexEnvCombine::TEXTURE1);
324    te1->setOperand0_RGB(osg::TexEnvCombine::SRC_COLOR);
325    te1->setSource1_RGB(osg::TexEnvCombine::PREVIOUS);
326    te1->setOperand1_RGB(osg::TexEnvCombine::SRC_COLOR);
327    te1->setSource2_RGB(osg::TexEnvCombine::PRIMARY_COLOR);
328    te1->setOperand2_RGB(osg::TexEnvCombine::SRC_COLOR);
329
330    stateset->setTextureAttributeAndModes(0, te0, osg::StateAttribute::ON | osg::StateAttribute::OVERRIDE);
331    stateset->setTextureAttributeAndModes(1, te1, osg::StateAttribute::ON | osg::StateAttribute::OVERRIDE);
332
333    osg::Group* group = new osg::Group;
334    group->addChild(node);
335    group->setCullCallback(new TexMatCallback(*texMat));
336    group->setStateSet( stateset );
337   
338    return group;
339}
340
341
342int main(int argc, char *argv[])
343{
344    // use an ArgumentParser object to manage the program arguments.
345    osg::ArgumentParser arguments(&argc,argv);
346
347    // set up the usage document, in case we need to print out how to use this program.
348    arguments.getApplicationUsage()->setDescription(arguments.getApplicationName()+" is the example which demonstrate support for ARB_vertex_program.");
349    arguments.getApplicationUsage()->setCommandLineUsage(arguments.getApplicationName()+" [options] filename ...");
350    arguments.getApplicationUsage()->addCommandLineOption("-h or --help","Display this information");
351   
352    // construct the viewer.
353    osgProducer::Viewer viewer(arguments);
354
355    // set up the value with sensible default event handlers.
356    viewer.setUpViewer(osgProducer::Viewer::STANDARD_SETTINGS);
357
358    // get details on keyboard and mouse bindings used by the viewer.
359    viewer.getUsage(*arguments.getApplicationUsage());
360
361    // if user request help write it out to cout.
362    if (arguments.read("-h") || arguments.read("--help"))
363    {
364        arguments.getApplicationUsage()->write(std::cout);
365        return 1;
366    }
367
368    // any option left unread are converted into errors to write out later.
369    arguments.reportRemainingOptionsAsUnrecognized();
370
371    // report any errors if they have occured when parsing the program aguments.
372    if (arguments.errors())
373    {
374        arguments.writeErrorMessages(std::cout);
375        return 1;
376    }
377
378    osg::Group* rootnode = new osg::Group;
379
380    rootnode->addChild(createSkyBox());
381
382    // load the nodes from the commandline arguments.
383    osg::Node* model = osgDB::readNodeFiles(arguments);
384    if (!model)
385    {
386        const float radius = 1.0f;
387        osg::Geode* geode = new osg::Geode;
388        geode->addDrawable(new osg::ShapeDrawable(new osg::Sphere(osg::Vec3(0.0f,0.0f,0.0f),radius)));
389        model = geode;
390    }
391
392    // run optimization over the scene graph
393    osgUtil::Optimizer optimzer;
394    optimzer.optimize(model);
395
396    // create normals.   
397    osgUtil::SmoothingVisitor smoother;
398    model->accept(smoother);
399
400    rootnode->addChild( addRefractStateSet(model) );
401
402    // add a viewport to the viewer and attach the scene graph.
403    viewer.setSceneData(rootnode);
404   
405    // create the windows and run the threads.
406    viewer.realize();
407
408    // now check to see if vertex program is supported.
409    for(unsigned int contextID = 0;
410        contextID<viewer.getDisplaySettings()->getMaxNumberOfGraphicsContexts();
411        ++contextID)
412    {
413        osg::VertexProgram::Extensions* vpExt = osg::VertexProgram::getExtensions(contextID,false);
414        if (vpExt)
415        {
416            if (!vpExt->isVertexProgramSupported())
417            {
418                cout<<"Warning: ARB_vertex_program not supported by OpenGL drivers, unable to run application."<<std::endl;
419                return 1;
420            }
421        }
422    }
423
424    while( !viewer.done() )
425    {
426        // wait for all cull and draw threads to complete.
427        viewer.sync();
428
429        // update the scene by traversing it with the the update visitor which will
430        // call all node update callbacks and animations.
431        viewer.update();
432         
433        // fire off the cull and draw traversals of the scene.
434        viewer.frame();
435       
436    }
437   
438    // wait for all cull and draw threads to complete before exit.
439    viewer.sync();
440
441    return 0;
442}
Note: See TracBrowser for help on using the browser.