root/OpenSceneGraph/trunk/examples/osgshaderterrain/osgshaderterrain.cpp @ 5863

Revision 5863, 11.9 kB (checked in by robert, 7 years ago)

Various work on osgViewer library, including warp point and graphics window resize support

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
Line 
1#include <osg/AlphaFunc>
2#include <osg/Billboard>
3#include <osg/BlendFunc>
4#include <osg/Depth>
5#include <osg/Geode>
6#include <osg/Geometry>
7#include <osg/GL2Extensions>
8#include <osg/Material>
9#include <osg/Math>
10#include <osg/MatrixTransform>
11#include <osg/PolygonOffset>
12#include <osg/Program>
13#include <osg/Projection>
14#include <osg/Shader>
15#include <osg/ShapeDrawable>
16#include <osg/StateSet>
17#include <osg/Switch>
18#include <osg/Texture2D>
19#include <osg/Uniform>
20
21#include <osgDB/ReadFile>
22#include <osgDB/FileUtils>
23
24#include <osgUtil/IntersectVisitor>
25#include <osgUtil/SmoothingVisitor>
26
27#include <osgText/Text>
28
29#include <osgProducer/Viewer>
30
31// for the grid data..
32#include "../osghangglide/terrain_coords.h"
33
34osg::Node* createScene()
35{
36    osg::Group* scene = new osg::Group;
37   
38    unsigned int numColumns = 38;
39    unsigned int numRows = 39;
40    unsigned int r;
41    unsigned int c;
42
43    osg::Vec3 origin(0.0f,0.0f,0.0f);
44    osg::Vec3 size(1000.0f,1000.0f,250.0f);
45    osg::Vec3 scaleDown(1.0f/size.x(),1.0f/size.y(),1.0f/size.z());
46
47    // ---------------------------------------
48    // Set up a StateSet to texture the objects
49    // ---------------------------------------
50    osg::StateSet* stateset = new osg::StateSet();
51
52
53    osg::Uniform* originUniform = new osg::Uniform("terrainOrigin",origin);
54    stateset->addUniform(originUniform);
55
56    osg::Uniform* sizeUniform = new osg::Uniform("terrainSize",size);
57    stateset->addUniform(sizeUniform);
58
59    osg::Uniform* scaleDownUniform = new osg::Uniform("terrainScaleDown",scaleDown);
60    stateset->addUniform(scaleDownUniform);
61
62    osg::Uniform* terrainTextureSampler = new osg::Uniform("terrainTexture",0);
63    stateset->addUniform(terrainTextureSampler);
64
65    osg::Uniform* baseTextureSampler = new osg::Uniform("baseTexture",1);
66    stateset->addUniform(baseTextureSampler);
67
68    osg::Uniform* treeTextureSampler = new osg::Uniform("treeTexture",1);
69    stateset->addUniform(treeTextureSampler);
70
71
72    // compute z range of z values of grid data so we can scale it.
73    float min_z = FLT_MAX;
74    float max_z = -FLT_MAX;
75    for(r=0;r<numRows;++r)
76    {
77        for(c=0;c<numColumns;++c)
78        {
79            min_z = osg::minimum(min_z,vertex[r+c*numRows][2]);
80            max_z = osg::maximum(max_z,vertex[r+c*numRows][2]);
81        }
82    }
83       
84    float scale_z = size.z()/(max_z-min_z);
85
86    osg::Image* terrainImage = new osg::Image;
87    terrainImage->allocateImage(numColumns,numRows,1,GL_LUMINANCE, GL_FLOAT);
88    terrainImage->setInternalTextureFormat(GL_LUMINANCE_FLOAT32_ATI);
89    for(r=0;r<numRows;++r)
90    {
91        for(c=0;c<numColumns;++c)
92        {
93            *((float*)(terrainImage->data(c,r))) = (vertex[r+c*numRows][2]-min_z)*scale_z;
94        }
95    }
96   
97    osg::Texture2D* terrainTexture = new osg::Texture2D;
98    terrainTexture->setImage(terrainImage);
99    terrainTexture->setFilter(osg::Texture2D::MIN_FILTER, osg::Texture2D::NEAREST);
100    terrainTexture->setFilter(osg::Texture2D::MAG_FILTER, osg::Texture2D::NEAREST);
101    terrainTexture->setResizeNonPowerOfTwoHint(false);
102    stateset->setTextureAttributeAndModes(0,terrainTexture,osg::StateAttribute::ON);
103
104
105    osg::Image* image = osgDB::readImageFile("Images/lz.rgb");
106    if (image)
107    {
108        osg::Texture2D* texture = new osg::Texture2D;
109       
110        texture->setImage(image);
111        stateset->setTextureAttributeAndModes(1,texture,osg::StateAttribute::ON);
112    }
113
114    {   
115        std::cout<<"Creating terrain...";
116
117        osg::Geode* geode = new osg::Geode();
118        geode->setStateSet( stateset );
119
120
121        {
122            osg::Program* program = new osg::Program;
123            stateset->setAttribute(program);
124
125#if 0
126            // use inline shaders
127           
128            ///////////////////////////////////////////////////////////////////
129            // vertex shader using just Vec4 coefficients
130            char vertexShaderSource[] =
131               "uniform float osg_FrameTime;\n"
132               "uniform sampler2D terrainTexture;\n"
133               "uniform vec3 terrainOrigin;\n"
134               "uniform vec3 terrainScaleDown;\n"
135               "\n"
136               "varying vec2 texcoord;\n"
137               "\n"
138               "void main(void)\n"
139               "{\n"
140               "    texcoord = gl_Vertex.xy - terrainOrigin.xy;\n"
141               "    texcoord.x *= terrainScaleDown.x;\n"
142               "    texcoord.y *= terrainScaleDown.y;\n"
143               "\n"
144               "    vec4 position;\n"ttm->
145               "    position.x = gl_Vertex.x;\n"
146               "    position.y = gl_Vertex.y;\n"
147               "    position.z = texture2D(terrainTexture, texcoord).r;\n"
148               "    position.w = 1.0;\n"
149               " \n"
150               "    gl_Position     = gl_ModelViewProjectionMatrix * position;\n"
151                "   gl_FrontColor = vec4(1.0,1.0,1.0,1.0);\n"
152               "}\n";
153
154            //////////////////////////////////////////////////////////////////
155            // fragment shader
156            //
157            char fragmentShaderSource[] =
158                "uniform sampler2D baseTexture; \n"
159                "varying vec2 texcoord;\n"
160                "\n"
161                "void main(void) \n"
162                "{\n"
163                "    gl_FragColor = texture2D( baseTexture, texcoord); \n"
164                "}\n";
165
166            program->addShader(new osg::Shader(osg::Shader::VERTEX, vertexShaderSource));
167            program->addShader(new osg::Shader(osg::Shader::FRAGMENT, fragmentShaderSource));
168           
169#else
170
171            // get shaders from source
172            program->addShader(osg::Shader::readShaderFile(osg::Shader::VERTEX, osgDB::findDataFile("shaders/terrain.vert")));
173            program->addShader(osg::Shader::readShaderFile(osg::Shader::FRAGMENT, osgDB::findDataFile("shaders/terrain.frag")));
174
175#endif
176
177            // get shaders from source
178        }
179
180
181        {
182            osg::Geometry* geometry = new osg::Geometry;
183
184            osg::Vec3Array& v = *(new osg::Vec3Array(numColumns*numRows));
185            osg::Vec4ubArray& color = *(new osg::Vec4ubArray(1));
186
187            color[0].set(255,255,255,255);
188
189            float rowCoordDelta = size.y()/(float)(numRows-1);
190            float columnCoordDelta = size.x()/(float)(numColumns-1);
191
192            float rowTexDelta = 1.0f/(float)(numRows-1);
193            float columnTexDelta = 1.0f/(float)(numColumns-1);
194
195            osg::Vec3 pos = origin;
196            osg::Vec2 tex(0.0f,0.0f);
197            int vi=0;
198            for(r=0;r<numRows;++r)
199            {
200                pos.x() = origin.x();
201                tex.x() = 0.0f;
202                for(c=0;c<numColumns;++c)
203                {
204                    v[vi].set(pos.x(),pos.y(),pos.z());
205                    pos.x()+=columnCoordDelta;
206                    tex.x()+=columnTexDelta;
207                    ++vi;
208                }
209                pos.y() += rowCoordDelta;
210                tex.y() += rowTexDelta;
211            }
212
213            geometry->setVertexArray(&v);
214            geometry->setColorArray(&color);
215            geometry->setColorBinding(osg::Geometry::BIND_OVERALL);
216
217            for(r=0;r<numRows-1;++r)
218            {
219                osg::DrawElementsUShort& drawElements = *(new osg::DrawElementsUShort(GL_QUAD_STRIP,2*numColumns));
220                geometry->addPrimitiveSet(&drawElements);
221                int ei=0;
222                for(c=0;c<numColumns;++c)
223                {
224                    drawElements[ei++] = (r+1)*numColumns+c;
225                    drawElements[ei++] = (r)*numColumns+c;
226                }
227            }
228           
229            geometry->setInitialBound(osg::BoundingBox(origin, origin+size));
230
231            geode->addDrawable(geometry);
232
233            scene->addChild(geode);
234        }
235    }
236       
237    std::cout<<"done."<<std::endl;
238   
239    return scene;
240}
241
242class TestSupportCallback : public osgProducer::OsgCameraGroup::RealizeCallback
243{
244    public:
245        TestSupportCallback():_supported(true),_errorMessage() {}
246       
247        virtual void operator()( osgProducer::OsgCameraGroup&, osgProducer::OsgSceneHandler& sh, const Producer::RenderSurface& )
248        {
249            {
250                OpenThreads::ScopedLock<OpenThreads::Mutex> lock(_mutex);
251
252                unsigned int contextID = sh.getSceneView()->getState()->getContextID();
253                osg::GL2Extensions* gl2ext = osg::GL2Extensions::Get(contextID,true);
254                if( gl2ext )
255                {
256                    if( !gl2ext->isGlslSupported() )
257                    {
258                        _supported = false;
259                        _errorMessage = "ERROR: GLSL not supported by OpenGL driver.";
260                    }
261
262                    GLint numVertexTexUnits = 0;
263                    glGetIntegerv( GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS, &numVertexTexUnits );
264                    if( numVertexTexUnits <= 0 )
265                    {
266                        _supported = false;
267                        _errorMessage = "ERROR: vertex texturing not supported by OpenGL driver.";
268                    }
269                }
270            }
271                       
272            sh.init();
273        }
274       
275        OpenThreads::Mutex  _mutex;
276        bool                _supported;
277        std::string         _errorMessage;
278       
279};
280
281int main( int argc, char **argv )
282{
283
284    // use an ArgumentParser object to manage the program arguments.
285    osg::ArgumentParser arguments(&argc,argv);
286
287    // set up the usage document, in case we need to print out how to use this program.
288    arguments.getApplicationUsage()->setDescription(arguments.getApplicationName()+" is the example which demonstrates the osg::Shape classes.");
289    arguments.getApplicationUsage()->setCommandLineUsage(arguments.getApplicationName()+" [options] filename ...");
290    arguments.getApplicationUsage()->addCommandLineOption("-h or --help","Display this information");
291    arguments.getApplicationUsage()->addCommandLineOption("--trees <number>","Set the number of trees to create");
292   
293    // construct the viewer.
294    osgProducer::Viewer viewer(arguments);
295
296    // set up the value with sensible default event handlers.
297    viewer.setUpViewer(osgProducer::Viewer::STANDARD_SETTINGS);
298   
299    // get details on keyboard and mouse bindings used by the viewer.
300    viewer.getUsage(*arguments.getApplicationUsage());
301
302    // if user request help write it out to cout.
303    if (arguments.read("-h") || arguments.read("--help"))
304    {
305        arguments.getApplicationUsage()->write(std::cout);
306        return 1;
307    }
308
309    // any option left unread are converted into errors to write out later.
310    arguments.reportRemainingOptionsAsUnrecognized();
311
312    // report any errors if they have occured when parsing the program aguments.
313    if (arguments.errors())
314    {
315        arguments.writeErrorMessages(std::cout);
316        return 1;
317    }
318   
319    osg::Node* node = createScene();
320
321    // add model to viewer.
322    viewer.setSceneData( node );
323
324    // register a test extension callback to be called when app realizes and gets a valid graphics context
325    osg::ref_ptr<TestSupportCallback> testSupportCallback = new TestSupportCallback();
326    viewer.setRealizeCallback(testSupportCallback.get());
327
328    // create the windows and run the threads.
329    viewer.realize();
330
331    // exit if we don't have the extensions this example needs.
332    if (!testSupportCallback->_supported)
333    {
334        osg::notify(osg::WARN)<<testSupportCallback->_errorMessage<<std::endl;
335
336        exit(1);
337    }
338
339    while( !viewer.done() )
340    {
341        // wait for all cull and draw threads to complete.
342        viewer.sync();
343
344        // update the scene by traversing it with the the update visitor which will
345        // call all node update callbacks and animations.
346        viewer.update();
347         
348        // fire off the cull and draw traversals of the scene.
349        viewer.frame();
350       
351    }
352   
353    // wait for all cull and draw threads to complete.
354    viewer.sync();
355
356    // run a clean up frame to delete all OpenGL objects.
357    viewer.cleanup_frame();
358
359    // wait for all the clean up frame to complete.
360    viewer.sync();
361
362    return 0;
363}
Note: See TracBrowser for help on using the browser.