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

Revision 6941, 10.7 kB (checked in by robert, 7 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, osgshaderterrain.
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/AlphaFunc>
20#include <osg/Billboard>
21#include <osg/BlendFunc>
22#include <osg/Depth>
23#include <osg/Geode>
24#include <osg/Geometry>
25#include <osg/GL2Extensions>
26#include <osg/Material>
27#include <osg/Math>
28#include <osg/MatrixTransform>
29#include <osg/PolygonOffset>
30#include <osg/Program>
31#include <osg/Projection>
32#include <osg/Shader>
33#include <osg/ShapeDrawable>
34#include <osg/StateSet>
35#include <osg/Switch>
36#include <osg/Texture2D>
37#include <osg/Uniform>
38
39#include <osgDB/ReadFile>
40#include <osgDB/FileUtils>
41
42#include <osgUtil/IntersectVisitor>
43#include <osgUtil/SmoothingVisitor>
44
45#include <osgText/Text>
46
47#include <osgViewer/Viewer>
48
49#include <iostream>
50
51// for the grid data..
52#include "../osghangglide/terrain_coords.h"
53
54osg::Node* createScene()
55{
56    osg::Group* scene = new osg::Group;
57   
58    unsigned int numColumns = 38;
59    unsigned int numRows = 39;
60    unsigned int r;
61    unsigned int c;
62
63    osg::Vec3 origin(0.0f,0.0f,0.0f);
64    osg::Vec3 size(1000.0f,1000.0f,250.0f);
65    osg::Vec3 scaleDown(1.0f/size.x(),1.0f/size.y(),1.0f/size.z());
66
67    // ---------------------------------------
68    // Set up a StateSet to texture the objects
69    // ---------------------------------------
70    osg::StateSet* stateset = new osg::StateSet();
71
72
73    osg::Uniform* originUniform = new osg::Uniform("terrainOrigin",origin);
74    stateset->addUniform(originUniform);
75
76    osg::Uniform* sizeUniform = new osg::Uniform("terrainSize",size);
77    stateset->addUniform(sizeUniform);
78
79    osg::Uniform* scaleDownUniform = new osg::Uniform("terrainScaleDown",scaleDown);
80    stateset->addUniform(scaleDownUniform);
81
82    osg::Uniform* terrainTextureSampler = new osg::Uniform("terrainTexture",0);
83    stateset->addUniform(terrainTextureSampler);
84
85    osg::Uniform* baseTextureSampler = new osg::Uniform("baseTexture",1);
86    stateset->addUniform(baseTextureSampler);
87
88    osg::Uniform* treeTextureSampler = new osg::Uniform("treeTexture",1);
89    stateset->addUniform(treeTextureSampler);
90
91
92    // compute z range of z values of grid data so we can scale it.
93    float min_z = FLT_MAX;
94    float max_z = -FLT_MAX;
95    for(r=0;r<numRows;++r)
96    {
97        for(c=0;c<numColumns;++c)
98        {
99            min_z = osg::minimum(min_z,vertex[r+c*numRows][2]);
100            max_z = osg::maximum(max_z,vertex[r+c*numRows][2]);
101        }
102    }
103       
104    float scale_z = size.z()/(max_z-min_z);
105
106    osg::Image* terrainImage = new osg::Image;
107    terrainImage->allocateImage(numColumns,numRows,1,GL_LUMINANCE, GL_FLOAT);
108    terrainImage->setInternalTextureFormat(GL_LUMINANCE_FLOAT32_ATI);
109    for(r=0;r<numRows;++r)
110    {
111        for(c=0;c<numColumns;++c)
112        {
113            *((float*)(terrainImage->data(c,r))) = (vertex[r+c*numRows][2]-min_z)*scale_z;
114        }
115    }
116   
117    osg::Texture2D* terrainTexture = new osg::Texture2D;
118    terrainTexture->setImage(terrainImage);
119    terrainTexture->setFilter(osg::Texture2D::MIN_FILTER, osg::Texture2D::NEAREST);
120    terrainTexture->setFilter(osg::Texture2D::MAG_FILTER, osg::Texture2D::NEAREST);
121    terrainTexture->setResizeNonPowerOfTwoHint(false);
122    stateset->setTextureAttributeAndModes(0,terrainTexture,osg::StateAttribute::ON);
123
124
125    osg::Image* image = osgDB::readImageFile("Images/lz.rgb");
126    if (image)
127    {
128        osg::Texture2D* texture = new osg::Texture2D;
129       
130        texture->setImage(image);
131        stateset->setTextureAttributeAndModes(1,texture,osg::StateAttribute::ON);
132    }
133
134    {   
135        std::cout<<"Creating terrain...";
136
137        osg::Geode* geode = new osg::Geode();
138        geode->setStateSet( stateset );
139
140
141        {
142            osg::Program* program = new osg::Program;
143            stateset->setAttribute(program);
144
145#if 1
146            // use inline shaders
147           
148            ///////////////////////////////////////////////////////////////////
149            // vertex shader using just Vec4 coefficients
150            char vertexShaderSource[] =
151               "uniform sampler2D terrainTexture;\n"
152               "uniform vec3 terrainOrigin;\n"
153               "uniform vec3 terrainScaleDown;\n"
154               "\n"
155               "varying vec2 texcoord;\n"
156               "\n"
157               "void main(void)\n"
158               "{\n"
159               "    texcoord = gl_Vertex.xy - terrainOrigin.xy;\n"
160               "    texcoord.x *= terrainScaleDown.x;\n"
161               "    texcoord.y *= terrainScaleDown.y;\n"
162               "\n"
163               "    vec4 position;\n"
164               "    position.x = gl_Vertex.x;\n"
165               "    position.y = gl_Vertex.y;\n"
166               "    position.z = texture2D(terrainTexture, texcoord).r;\n"
167               "    position.w = 1.0;\n"
168               " \n"
169               "    gl_Position     = gl_ModelViewProjectionMatrix * position;\n"
170                "   gl_FrontColor = vec4(1.0,1.0,1.0,1.0);\n"
171               "}\n";
172
173            //////////////////////////////////////////////////////////////////
174            // fragment shader
175            //
176            char fragmentShaderSource[] =
177                "uniform sampler2D baseTexture; \n"
178                "varying vec2 texcoord;\n"
179                "\n"
180                "void main(void) \n"
181                "{\n"
182                "    gl_FragColor = texture2D( baseTexture, texcoord); \n"
183                "}\n";
184
185            program->addShader(new osg::Shader(osg::Shader::VERTEX, vertexShaderSource));
186            program->addShader(new osg::Shader(osg::Shader::FRAGMENT, fragmentShaderSource));
187           
188#else
189
190            // get shaders from source
191            program->addShader(osg::Shader::readShaderFile(osg::Shader::VERTEX, osgDB::findDataFile("shaders/terrain.vert")));
192            program->addShader(osg::Shader::readShaderFile(osg::Shader::FRAGMENT, osgDB::findDataFile("shaders/terrain.frag")));
193
194#endif
195
196            // get shaders from source
197        }
198
199
200        {
201            osg::Geometry* geometry = new osg::Geometry;
202
203            osg::Vec3Array& v = *(new osg::Vec3Array(numColumns*numRows));
204            osg::Vec4ubArray& color = *(new osg::Vec4ubArray(1));
205
206            color[0].set(255,255,255,255);
207
208            float rowCoordDelta = size.y()/(float)(numRows-1);
209            float columnCoordDelta = size.x()/(float)(numColumns-1);
210
211            float rowTexDelta = 1.0f/(float)(numRows-1);
212            float columnTexDelta = 1.0f/(float)(numColumns-1);
213
214            osg::Vec3 pos = origin;
215            osg::Vec2 tex(0.0f,0.0f);
216            int vi=0;
217            for(r=0;r<numRows;++r)
218            {
219                pos.x() = origin.x();
220                tex.x() = 0.0f;
221                for(c=0;c<numColumns;++c)
222                {
223                    v[vi].set(pos.x(),pos.y(),pos.z());
224                    pos.x()+=columnCoordDelta;
225                    tex.x()+=columnTexDelta;
226                    ++vi;
227                }
228                pos.y() += rowCoordDelta;
229                tex.y() += rowTexDelta;
230            }
231
232            geometry->setVertexArray(&v);
233            geometry->setColorArray(&color);
234            geometry->setColorBinding(osg::Geometry::BIND_OVERALL);
235
236            for(r=0;r<numRows-1;++r)
237            {
238                osg::DrawElementsUShort& drawElements = *(new osg::DrawElementsUShort(GL_QUAD_STRIP,2*numColumns));
239                geometry->addPrimitiveSet(&drawElements);
240                int ei=0;
241                for(c=0;c<numColumns;++c)
242                {
243                    drawElements[ei++] = (r+1)*numColumns+c;
244                    drawElements[ei++] = (r)*numColumns+c;
245                }
246            }
247           
248            geometry->setInitialBound(osg::BoundingBox(origin, origin+size));
249
250            geode->addDrawable(geometry);
251
252            scene->addChild(geode);
253        }
254    }
255       
256    std::cout<<"done."<<std::endl;
257   
258    return scene;
259}
260
261class TestSupportOperation: public osg::Operation
262{
263public:
264
265    TestSupportOperation():
266        osg::Operation("TestSupportOperation",false),
267        _supported(true),
268        _errorMessage() {}
269
270    virtual void operator () (osg::Object* object)
271    {
272        osg::GraphicsContext* gc = dynamic_cast<osg::GraphicsContext*>(object);
273        if (!gc) return;
274   
275        OpenThreads::ScopedLock<OpenThreads::Mutex> lock(_mutex);
276
277        unsigned int contextID = gc->getState()->getContextID();
278        osg::GL2Extensions* gl2ext = osg::GL2Extensions::Get(contextID,true);
279        if( gl2ext )
280        {
281            if( !gl2ext->isGlslSupported() )
282            {
283                _supported = false;
284                _errorMessage = "ERROR: GLSL not supported by OpenGL driver.";
285            }
286
287            GLint numVertexTexUnits = 0;
288            glGetIntegerv( GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS, &numVertexTexUnits );
289            if( numVertexTexUnits <= 0 )
290            {
291                _supported = false;
292                _errorMessage = "ERROR: vertex texturing not supported by OpenGL driver.";
293            }
294        }
295        else
296        {
297            _supported = false;
298            _errorMessage = "ERROR: GLSL not supported.";
299        }
300    }
301       
302    OpenThreads::Mutex  _mutex;
303    bool                _supported;
304    std::string         _errorMessage;
305};
306
307int main(int, char **)
308{
309    // construct the viewer.
310    osgViewer::Viewer viewer;
311
312    osg::Node* node = createScene();
313
314    // add model to viewer.
315    viewer.setSceneData( node );
316
317    viewer.setUpViewAcrossAllScreens();
318   
319    osg::ref_ptr<TestSupportOperation> testSupportOperation = new TestSupportOperation;
320#if 0
321    // temporily commenting out as its causing the viewer to crash... no clue yet to why   
322    viewer.setRealizeOperation(testSupportOperation.get());
323#endif
324    // create the windows and run the threads.
325    viewer.realize();
326   
327    if (!testSupportOperation->_supported)
328    {
329        osg::notify(osg::WARN)<<testSupportOperation->_errorMessage<<std::endl;
330
331        return 1;
332    }
333
334    return viewer.run();
335}
Note: See TracBrowser for help on using the browser.