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

Revision 6941, 17.4 kB (checked in by robert, 8 years ago)

From Martin Lavery and Robert Osfield, Updated examples to use a variation of the MIT License

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