From af7bb82175e58f63bd9062c542b270cd67189264 Mon Sep 17 00:00:00 2001 From: Robert Osfield Date: Tue, 6 Jan 2009 15:11:54 +0000 Subject: [PATCH] From Paul Martz, example demonstating new draw instanced primitive funcitonality. --- examples/CMakeLists.txt | 1 + examples/osgdrawinstanced/CMakeLists.txt | 4 + .../osgdrawinstanced/osgdrawinstanced.cpp | 148 ++++++++++++++++++ 3 files changed, 153 insertions(+) create mode 100644 examples/osgdrawinstanced/CMakeLists.txt create mode 100644 examples/osgdrawinstanced/osgdrawinstanced.cpp diff --git a/examples/CMakeLists.txt b/examples/CMakeLists.txt index c2999f010..a417a1cd6 100644 --- a/examples/CMakeLists.txt +++ b/examples/CMakeLists.txt @@ -32,6 +32,7 @@ IF(DYNAMIC_OPENSCENEGRAPH) ADD_SUBDIRECTORY(osgdelaunay) ADD_SUBDIRECTORY(osgdepthpartition) ADD_SUBDIRECTORY(osgdepthpeeling) + ADD_SUBDIRECTORY(osgdrawinstanced) ADD_SUBDIRECTORY(osgdistortion) ADD_SUBDIRECTORY(osgfadetext) ADD_SUBDIRECTORY(osgfont) diff --git a/examples/osgdrawinstanced/CMakeLists.txt b/examples/osgdrawinstanced/CMakeLists.txt new file mode 100644 index 000000000..6f5c71865 --- /dev/null +++ b/examples/osgdrawinstanced/CMakeLists.txt @@ -0,0 +1,4 @@ +SET(TARGET_SRC osgdrawinstanced.cpp ) + +#### end var setup ### +SETUP_EXAMPLE(osgdrawinstanced) diff --git a/examples/osgdrawinstanced/osgdrawinstanced.cpp b/examples/osgdrawinstanced/osgdrawinstanced.cpp new file mode 100644 index 000000000..77062f3b9 --- /dev/null +++ b/examples/osgdrawinstanced/osgdrawinstanced.cpp @@ -0,0 +1,148 @@ +/* OpenSceneGraph example, osgdrawinstanced. +* +* Permission is hereby granted, free of charge, to any person obtaining a copy +* of this software and associated documentation files (the "Software"), to deal +* in the Software without restriction, including without limitation the rights +* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +* copies of the Software, and to permit persons to whom the Software is +* furnished to do so, subject to the following conditions: +* +* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +* THE SOFTWARE. +*/ +// +// This code is copyright (c) 2008 Skew Matrix Software LLC. You may use +// the code under the licensing terms described above. +// + +#include +#include +#include +#include + +#include + +#include + +void +createDAIGeometry( osg::Geometry& geom, int nInstances=1 ) +{ + const float halfDimX( .5 ); + const float halfDimZ( .5 ); + + osg::Vec3Array* v = new osg::Vec3Array; + v->resize( 4 ); + geom.setVertexArray( v ); + + // Geometry for a single quad. + (*v)[ 0 ] = osg::Vec3( -halfDimX, 0., -halfDimZ ); + (*v)[ 1 ] = osg::Vec3( halfDimX, 0., -halfDimZ ); + (*v)[ 2 ] = osg::Vec3( halfDimX, 0., halfDimZ ); + (*v)[ 3 ] = osg::Vec3( -halfDimX, 0., halfDimZ ); + + // Use the DrawArraysInstanced PrimitiveSet and tell it to draw 1024 instances. + geom.addPrimitiveSet( new osg::DrawArrays( GL_QUADS, 0, 4, nInstances ) ); +} + + +osg::StateSet* +createStateSet() +{ + osg::ref_ptr< osg::StateSet > ss = new osg::StateSet; + + // Create a vertex program that references the gl_InstanceID to + // render each instance uniquely. gl_InstanceID will be in the range + // 0 to numInstances-1 (1023 in our case). + std::string vertexSource = + "uniform sampler2D osgLogo; \n" + "uniform float osg_SimulationTime; \n" + + "void main() \n" + "{ \n" + // Using the instance ID, generate "texture coords" for this instance. + "vec2 tC; \n" + "const float r = gl_InstanceID / 32.; \n" + "tC.s = fract( r ); tC.t = floor( r ) / 32.; \n" + // Get the color from the OSG logo. + "gl_FrontColor = texture2D( osgLogo, tC ); \n" + + // Use the (scaled) tex coord to translate the position of the vertices. + "vec4 pos = vec4( tC.s * 48., 0., tC.t * 48., 1. ); \n" + + // Compute a rotation angle from the instanceID and elapsed time. + "float timeOffset = gl_InstanceID / (32. * 32.); \n" + "float angle = ( osg_SimulationTime - timeOffset ) * 6.283; \n" + "float sa = sin( angle ); \n" + "float ca = cos( angle ); \n" + // New orientation, rotate around z axis. + "vec4 newX = vec4( ca, sa, 0., 0. ); \n" + "vec4 newY = vec4( sa, ca, 0., 0. ); \n" + "vec4 newZ = vec4( 0., 0., 1., 0. ); \n" + "mat4 mV = mat4( newX, newY, newZ, pos ); \n" + "gl_Position = ( gl_ModelViewProjectionMatrix * mV * gl_Vertex ); \n" + "} \n"; + + osg::ref_ptr< osg::Shader > vertexShader = new osg::Shader(); + vertexShader->setType( osg::Shader::VERTEX ); + vertexShader->setShaderSource( vertexSource ); + + osg::ref_ptr< osg::Program > program = new osg::Program(); + program->addShader( vertexShader.get() ); + + ss->setAttribute( program.get(), + osg::StateAttribute::ON | osg::StateAttribute::PROTECTED ); + + osg::ref_ptr< osg::Image> iLogo = osgDB::readImageFile( "Images/osg128.png" ); + if( !iLogo.valid() ) + { + osg::notify( osg::ALWAYS ) << "Can't open image file osg128.png" << std::endl; + return( NULL ); + } + osg::Texture2D* texLogo = new osg::Texture2D( iLogo ); + texLogo->setFilter( osg::Texture2D::MIN_FILTER, osg::Texture2D::LINEAR ); + texLogo->setFilter( osg::Texture2D::MAG_FILTER, osg::Texture2D::LINEAR ); + + ss->setTextureAttribute( 0, texLogo ); + + osg::ref_ptr< osg::Uniform > texLogoUniform = + new osg::Uniform( "osgLogo", 0 ); + ss->addUniform( texLogoUniform.get() ); + + return( ss.release() ); +} + + +int main( int argc, char **argv ) +{ + // Make a scene graph consisting of a single Geode, containing + // a single Geometry, and a single PrimitiveSet. + osg::ref_ptr< osg::Geode > geode = new osg::Geode; + + osg::ref_ptr< osg::Geometry > geom = new osg::Geometry; + // Configure the Geometry for use with EXT_draw_arrays: + // DL off and buffer objects on. + geom->setUseDisplayList( false ); + geom->setUseVertexBufferObjects( true ); + // OSG has no clue where out vertex shader will place the geometric data, + // so specify an initial bound to allow proper culling and near/far computation. + osg::BoundingBox bb( -1., -.1, -1., 49., 1., 49. ); + geom->setInitialBound( bb ); + // Add geometric data and the PrimitiveSet. Specify numInstances as 32*32 or 1024. + createDAIGeometry( *geom, 32*32 ); + geode->addDrawable( geom ); + + // Create a StateSet to render the instanced Geometry. + osg::ref_ptr< osg::StateSet > ss = createStateSet(); + geode->setStateSet( ss.get() ); + + // osgDB::writeNodeFile(*geode, "instanced.osg"); + + osgViewer::Viewer viewer; + viewer.setSceneData( geode.get() ); + return viewer.run(); +}