From 8b384baca936f273c0176f7f5cafdf812c4a35ed Mon Sep 17 00:00:00 2001 From: Robert Osfield Date: Tue, 6 Jan 2015 17:12:51 +0000 Subject: [PATCH] From Julien Valentin, "To sum up changes, I had: -some extensions in GLExtensions - GL_TEXTURE_BUFFER as target in osg::StateSet - a VBO based transform feed back example " git-svn-id: http://svn.openscenegraph.org/osg/OpenSceneGraph/trunk@14651 16af8721-9629-0410-8352-f15c8da7e697 --- examples/CMakeLists.txt | 1 + examples/osgtransformfeedback/CMakeLists.txt | 7 + .../osgtransformfeedback.cpp | 299 ++++++++++++++++++ include/osg/GLExtensions | 5 + include/osg/Program | 31 ++ src/osg/GLExtensions.cpp | 6 + src/osg/Program.cpp | 28 +- src/osg/StateSet.cpp | 1 + src/osgWrappers/serializers/osg/Program.cpp | 53 +++- 9 files changed, 428 insertions(+), 3 deletions(-) create mode 100644 examples/osgtransformfeedback/CMakeLists.txt create mode 100644 examples/osgtransformfeedback/osgtransformfeedback.cpp diff --git a/examples/CMakeLists.txt b/examples/CMakeLists.txt index b744338ee..d58e100e4 100644 --- a/examples/CMakeLists.txt +++ b/examples/CMakeLists.txt @@ -130,6 +130,7 @@ IF(DYNAMIC_OPENSCENEGRAPH) ADD_SUBDIRECTORY(osgtexturerectangle) ADD_SUBDIRECTORY(osgtexturecompression) ADD_SUBDIRECTORY(osgthirdpersonview) + ADD_SUBDIRECTORY(osgtransformfeedback) ADD_SUBDIRECTORY(osguniformbuffer) ADD_SUBDIRECTORY(osguserstats) ADD_SUBDIRECTORY(osgvertexprogram) diff --git a/examples/osgtransformfeedback/CMakeLists.txt b/examples/osgtransformfeedback/CMakeLists.txt new file mode 100644 index 000000000..46d44be28 --- /dev/null +++ b/examples/osgtransformfeedback/CMakeLists.txt @@ -0,0 +1,7 @@ +#this file is automatically generated + + +SET(TARGET_SRC osgtransformfeedback.cpp ) + +#### end var setup ### +SETUP_EXAMPLE(osgtransformfeedback) diff --git a/examples/osgtransformfeedback/osgtransformfeedback.cpp b/examples/osgtransformfeedback/osgtransformfeedback.cpp new file mode 100644 index 000000000..45f15092c --- /dev/null +++ b/examples/osgtransformfeedback/osgtransformfeedback.cpp @@ -0,0 +1,299 @@ +/* OpenSceneGraph example, osgtransformfeedback +* +* 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. +*/ + +/* file: examples/osgtransformfeedback/osgtransformfeedback.cpp +* author: Julien Valentin 2013-10-01 +* copyright: (C) 2013 +* license: OpenSceneGraph Public License (OSGPL) +* +* A demo of GLSL geometry shaders using OSG transform feedback +* +*/ + + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include + +#include + +/////////////////////////////////////////////////////////////////////////// + +class SineAnimation: public osg::Uniform::Callback +{ +public: + SineAnimation( float rate = 1.0f, float scale = 1.0f, float offset = 0.0f ) : + _rate(rate), _scale(scale), _offset(offset) + {} + + void operator()( osg::Uniform* uniform, osg::NodeVisitor* nv ) + { + float angle = _rate * nv->getFrameStamp()->getSimulationTime(); + float value = sinf( angle ) * _scale + _offset; + uniform->set( value ); + } + +private: + const float _rate; + const float _scale; + const float _offset; +}; + +/////////////////////////////////////////////////////////////////////////// +static const char* RendervertSource = +{ + "#version 120\n" + "uniform float u_anim1;\n" + "//in vec4 Vertex;\n" + "varying vec4 v_color;\n" + "void main(void)\n" + "{\n" + " v_color = gl_Vertex;\n" + " gl_Position = gl_ModelViewProjectionMatrix *(gl_Vertex);\n" + "}\n" +}; +static const char* vertSource = +{ + "#version 120\n" + "#extension GL_EXT_geometry_shader4 : enable\n" + "uniform float u_anim1;\n" + //"in vec4 Vertex;\n" + " varying out vec4 v_color;\n" + //"out vec4 v_vertex;\n" + "void main(void)\n" + "{\n" + //" v_color = Vertex;\n" + //" v_vertex = Vertex;;//gl_ModelViewProjectionMatrix * Vertex;\n" + " gl_Position = (gl_Vertex);\n" + " v_color = gl_Vertex;\n" + "}\n" +}; + + + +static const char* geomSource = +{ + "#version 120\n" + "#extension GL_EXT_geometry_shader4 : enable\n" + // "layout(points) in;\n"\ + // "layout(points, max_vertices = 4) out;\n" + "uniform float u_anim1;\n" + " varying in vec4 v_color[];\n" + //" varying in vec4 v_vertex[];\n" + " varying vec4 out1;\n" + "void main(void)\n" + "{\n" + " vec4 v =vec4( gl_PositionIn[0].xyz,1);\n" + " out1 = v + vec4(u_anim1,0.,0.,0.);// gl_Position = v + vec4(u_anim1,0.,0.,0.); \n" + " EmitVertex();\n" + " EndPrimitive();\n" + " out1 = v - vec4(u_anim1,0.,0.,0.); // gl_Position = v - vec4(u_anim1,0.,0.,0.); \n" + " EmitVertex();\n" + " EndPrimitive();\n" + "\n" + " out1= v + vec4(0.,1.0-u_anim1,0.,0.);// gl_Position = v + vec4(0.,1.0-u_anim1,0.,0.); \n" + " EmitVertex();\n" + " EndPrimitive();\n" + " out1 = v - vec4(0.,1.0-u_anim1,0.,0.); //gl_Position = v - vec4(0.,1.0-u_anim1,0.,0.); \n" + " EmitVertex();\n" + " EndPrimitive();\n" + "}\n" +}; + + +static const char* fragSource = +{ + "#version 120\n" + "#extension GL_EXT_geometry_shader4 : enable\n" + "uniform float u_anim1;\n" + "varying vec4 v_color_out;\n" + "void main(void)\n" + "{\n" + " gl_FragColor = vec4(1,0,0,1);//v_color_out;\n" + "}\n" +}; + +osg::Program* createGeneratorShader() +{ + osg::Program* pgm = new osg::Program; + pgm->setName( "osg transformfeedback demo" ); + pgm->addShader( new osg::Shader( osg::Shader::VERTEX, vertSource ) ); + pgm->setParameter( GL_GEOMETRY_VERTICES_OUT_EXT, 4 ); + pgm->setParameter( GL_GEOMETRY_INPUT_TYPE_EXT, GL_POINTS ); + pgm->setParameter( GL_GEOMETRY_OUTPUT_TYPE_EXT, GL_POINTS ); + pgm->addShader( new osg::Shader( osg::Shader::GEOMETRY, geomSource ) ); + pgm->addTransformFeedBackVarying(std::string("out1")); + pgm->setTransformFeedBackMode(GL_INTERLEAVED_ATTRIBS); + return pgm; +} + +osg::Program* createRenderShader() +{ + osg::Program* pgm = new osg::Program; + pgm->setName( "osg transformfeedback renderer demo" ); + pgm->addShader( new osg::Shader( osg::Shader::VERTEX, RendervertSource ) ); + pgm->addShader( new osg::Shader( osg::Shader::FRAGMENT, fragSource ) ); + return pgm; +} + +////////////////////////////////////////////////////////////////////////////////////// + + + +class SomePointsRenderer; +class SomePointsGenerator:public osg::Geometry +{ +public: + SomePointsGenerator(); + void setRenderer(osg::Geometry*renderer); + GLuint getNumPrimitivesGenerated()const; + +protected: + osg::Program * _program; + osg::ref_ptr genbuffer;//Renderer buffer + osg::Vec4Array* vAry; + + virtual void drawImplementation( osg::RenderInfo& renderInfo ) const; +}; +///////////////////////////////////////////////////////////////////////////////////// + +class SomePointsRenderer : public osg::Geometry +{ +public: + + SomePointsRenderer(SomePointsGenerator*_generator) + { + + setUseVertexBufferObjects(true); + + osg::Vec4Array* vAry2 = new osg::Vec4Array; + vAry2->resize(_generator->getNumPrimitivesGenerated()); + setVertexArray(vAry2); + addPrimitiveSet( new osg::DrawArrays( GL_LINES, 0,_generator->getNumPrimitivesGenerated())); + + osg::StateSet* sset = getOrCreateStateSet(); + ///hacking rendering order + /*osg::BlendFunc* bf = new + osg::BlendFunc(osg::BlendFunc::SRC_ALPHA, + osg::BlendFunc::ONE_MINUS_SRC_ALPHA ); + sset->setAttributeAndModes(bf);*/ + + sset->setMode( GL_LIGHTING, osg::StateAttribute::OFF ); + getOrCreateVertexBufferObject(); + sset->setAttribute( createRenderShader() ); + + } + + + +}; + +/////////////////////////////////////////////////////////////////////////// +GLuint SomePointsGenerator::getNumPrimitivesGenerated()const +{ + return vAry->size()*4; +} + +void SomePointsGenerator::drawImplementation( osg::RenderInfo& renderInfo ) const +{ + + //get output buffer + unsigned int contextID = renderInfo.getState()->getContextID(); + + GLuint ubuff= genbuffer->getOrCreateGLBufferObject(contextID)->getGLObjectID(); + + osg::GLExtensions* ext = renderInfo.getState()->get(); + + ext->glBindBufferBase(GL_TRANSFORM_FEEDBACK_BUFFER, 0,ubuff); + + glEnable(GL_RASTERIZER_DISCARD); + + ext->glBeginTransformFeedback(GL_POINTS); + + + osg::Geometry::drawImplementation( renderInfo ); + + + ext->glEndTransformFeedback(); + + glDisable(GL_RASTERIZER_DISCARD); + + ext->glBindBufferBase(GL_TRANSFORM_FEEDBACK_BUFFER, 0, 0); +} + + + +SomePointsGenerator::SomePointsGenerator():osg::Geometry() +{ + + setUseVertexBufferObjects(true); + + osg::StateSet* sset = getOrCreateStateSet(); + sset->setMode( GL_LIGHTING, osg::StateAttribute::OFF ); + vAry = new osg::Vec4Array;; + vAry->push_back( osg::Vec4(0,0,0,1) ); + vAry->push_back( osg::Vec4(0,1,0,1) ); + vAry->push_back( osg::Vec4(1,0,0,1) ); + vAry->push_back( osg::Vec4(1,1,0,1 )); + addPrimitiveSet( new osg::DrawArrays( GL_POINTS, 0, vAry->size() ) ); + setVertexArray( vAry ); + + _program=createGeneratorShader() ; + sset->setAttribute(_program ); + + // a generic cyclic animation value + osg::Uniform* u_anim1( new osg::Uniform( "u_anim1", 0.9f ) ); + u_anim1->setUpdateCallback( new SineAnimation( 4, 0.5, 0.5 ) ); + sset->addUniform( u_anim1 ); + +} + +void SomePointsGenerator::setRenderer(osg::Geometry* renderer) +{ + genbuffer = renderer->getOrCreateVertexBufferObject(); +} + + + +/////////////////////////////////////////////////////////////////////////// + +int main( int , char** ) +{ + osg::Geode* root( new osg::Geode ); + SomePointsGenerator * pate = new SomePointsGenerator(); + SomePointsRenderer* pate2 = new SomePointsRenderer(pate); + pate->setRenderer( pate2); + root->addDrawable( pate ); + root->addDrawable( pate2 ); + osgViewer::Viewer viewer; + viewer.setSceneData( root ); + return viewer.run(); +} diff --git a/include/osg/GLExtensions b/include/osg/GLExtensions index ec625651d..ee6d00b5f 100644 --- a/include/osg/GLExtensions +++ b/include/osg/GLExtensions @@ -599,6 +599,11 @@ class OSG_EXPORT GLExtensions : public osg::Referenced void (GL_APIENTRY * glGetTransformFeedbacki_v) (GLuint xfb, GLenum pname, GLuint index, GLint *param); void (GL_APIENTRY * glGetTransformFeedbacki64_v) (GLuint xfb, GLenum pname, GLuint index, GLint64 *param); + // Vertex Array Object + void (GL_APIENTRY * glDeleteVertexArrays) (GLsizei size,const GLuint *handles); + void (GL_APIENTRY * glGenVertexArrays) (GLsizei size, GLuint *handles); + GLboolean (GL_APIENTRY * glIsVertexArray) (GLuint handle); + void (GL_APIENTRY * glBindVertexArray) (GLuint handle); }; diff --git a/include/osg/Program b/include/osg/Program index 7116570a5..e1c669974 100644 --- a/include/osg/Program +++ b/include/osg/Program @@ -124,6 +124,33 @@ class OSG_EXPORT Program : public osg::StateAttribute /** Remove a uniform block binding. */ void removeBindUniformBlock(const std::string& name); + /** Remove a TransformFeedBackVarying. */ + void removeTransformFeedBackVarying(const std::string& name) + { + for(std::vector::iterator i=_feedbackout.begin(); i!=_feedbackout.end(); i++) + { + if (*i == name) {_feedbackout.erase(i);break; } + } + } + + /** Add a TransformFeedBack Varying Name. */ + void addTransformFeedBackVarying(const std::string& outname) + { + _feedbackout.push_back(outname); + } + + /** Get number of TransformFeedBack Varyings. */ + inline unsigned int getNumTransformFeedBackVaryings() const { return _feedbackout.size(); } + + /** Get const TransformFeedBack Varying at index i. */ + inline const std::string& getTransformFeedBackVarying(unsigned int i) const { return _feedbackout[i]; } + + /** Set TransformFeedBack Mode. */ + void setTransformFeedBackMode(GLenum e) {_feedbackmode=e;} + + /** Get TransformFeedBack Mode. */ + GLenum getTransformFeedBackMode() const {return _feedbackmode;} + /** Simple class for wrapping up the data used in glProgramBinary and glGetProgramBinary. * On the first run of your application Programs should be assigned an empty ProgramBinary. * Before your application exits it should retrieve the program binary via @@ -393,6 +420,10 @@ class OSG_EXPORT Program : public osg::StateAttribute GLint _numGroupsY; GLint _numGroupsZ; + /**TransformFeedBack**/ + GLenum _feedbackmode; + std::vector _feedbackout; + private: Program& operator=(const Program&); // disallowed diff --git a/src/osg/GLExtensions.cpp b/src/osg/GLExtensions.cpp index 4bf3a8771..d5bc9de44 100644 --- a/src/osg/GLExtensions.cpp +++ b/src/osg/GLExtensions.cpp @@ -1065,6 +1065,12 @@ GLExtensions::GLExtensions(unsigned int contextID) osg::setGLExtensionFuncPtr(glGetTransformFeedbacki_v, "glGetTransformFeedbacki_v"); osg::setGLExtensionFuncPtr(glGetTransformFeedbacki64_v, "glGetTransformFeedbacki64_v"); + //Vertex Array Object + osg::setGLExtensionFuncPtr(glGenVertexArrays,"glGenVertexArrays"); + osg::setGLExtensionFuncPtr(glBindVertexArray,"glBindVertexArray"); + osg::setGLExtensionFuncPtr(glDeleteVertexArrays,"glDeleteVertexArrays"); + osg::setGLExtensionFuncPtr(glIsVertexArray,"glIsVertexArray"); + } diff --git a/src/osg/Program.cpp b/src/osg/Program.cpp index 99a1703de..1e4d038a1 100644 --- a/src/osg/Program.cpp +++ b/src/osg/Program.cpp @@ -137,7 +137,7 @@ void Program::ProgramBinary::assign(unsigned int size, const unsigned char* data Program::Program() : _geometryVerticesOut(1), _geometryInputType(GL_TRIANGLES), _geometryOutputType(GL_TRIANGLE_STRIP), - _numGroupsX(0), _numGroupsY(0), _numGroupsZ(0) + _numGroupsX(0), _numGroupsY(0), _numGroupsZ(0), _feedbackmode(GL_SEPARATE_ATTRIBS) { } @@ -180,6 +180,9 @@ Program::Program(const Program& rhs, const osg::CopyOp& copyop): _numGroupsX = rhs._numGroupsX; _numGroupsY = rhs._numGroupsY; _numGroupsZ = rhs._numGroupsZ; + + _feedbackmode=rhs._feedbackmode; + _feedbackout=rhs._feedbackout; } @@ -223,6 +226,9 @@ int Program::compare(const osg::StateAttribute& sa) const if( _numGroupsZ < rhs._numGroupsZ ) return -1; if( rhs._numGroupsZ < _numGroupsZ ) return 1; + if(_feedbackoutcompileShader( state ); } + if(!_feedbackout.empty()) + { + const PerContextProgram* pcp = getPCP(contextID); + const GLExtensions* extensions = state.get(); + + unsigned int numfeedback = _feedbackout.size(); + const char**varyings = new const char*[numfeedback]; + const char **varyingsptr = varyings; + for(std::vector::const_iterator it=_feedbackout.begin(); + it!=_feedbackout.end(); + it++) + { + *varyingsptr++=(*it).c_str(); + } + + extensions->glTransformFeedbackVaryings( pcp->getHandle(), numfeedback, varyings, _feedbackmode); + delete [] varyings; + } getPCP( contextID )->linkProgram(state); } @@ -437,7 +461,7 @@ void Program::removeBindUniformBlock(const std::string& name) - +#include void Program::apply( osg::State& state ) const { const unsigned int contextID = state.getContextID(); diff --git a/src/osg/StateSet.cpp b/src/osg/StateSet.cpp index 08f942b6b..fce671172 100644 --- a/src/osg/StateSet.cpp +++ b/src/osg/StateSet.cpp @@ -50,6 +50,7 @@ class TextureGLModeSet _textureModeSet.insert(GL_TEXTURE_1D); _textureModeSet.insert(GL_TEXTURE_2D); _textureModeSet.insert(GL_TEXTURE_3D); + _textureModeSet.insert(GL_TEXTURE_BUFFER_ARB); _textureModeSet.insert(GL_TEXTURE_CUBE_MAP); _textureModeSet.insert(GL_TEXTURE_RECTANGLE_NV); diff --git a/src/osgWrappers/serializers/osg/Program.cpp b/src/osgWrappers/serializers/osg/Program.cpp index 9f0e7d639..d884bd98c 100644 --- a/src/osgWrappers/serializers/osg/Program.cpp +++ b/src/osgWrappers/serializers/osg/Program.cpp @@ -76,7 +76,51 @@ static bool writeShaders( osgDB::OutputStream& os, const osg::Program& attr ) os << os.END_BRACKET << std::endl; return true; } - +// feedBackVaryings +static bool checkFeedBackVaryingsName( const osg::Program& attr ) +{ + return true; +} +static bool readFeedBackVaryingsName( osgDB::InputStream& is, osg::Program& attr ) +{ + unsigned int size = is.readSize(); is >> is.BEGIN_BRACKET; + for ( unsigned int i=0; i> str; + attr.addTransformFeedBackVarying(str); + } + is >> is.END_BRACKET; + return true; +} +static bool writeFeedBackVaryingsName( osgDB::OutputStream& os, const osg::Program& attr ) +{ + unsigned int size = attr.getNumTransformFeedBackVaryings(); + os.writeSize(size); os << os.BEGIN_BRACKET << std::endl; + for ( unsigned int i=0; i>size; + attr.setTransformFeedBackMode(size); + return true; +} +static bool writeFeedBackMode( osgDB::OutputStream& os, const osg::Program& attr ) +{ + os << attr.getTransformFeedBackMode()<< std::endl; + return true; +} // _numGroupsX/Y/Z static bool checkComputeGroups( const osg::Program& attr ) { @@ -112,8 +156,15 @@ REGISTER_OBJECT_WRAPPER( Program, ADD_USER_SERIALIZER( GeometryVerticesOut ); // _geometryVerticesOut ADD_USER_SERIALIZER( GeometryInputType ); // _geometryInputType ADD_USER_SERIALIZER( GeometryOutputType ); // _geometryOutputType + { UPDATE_TO_VERSION_SCOPED( 95 ) ADD_USER_SERIALIZER( ComputeGroups ); // _numGroupsX/Y/Z } + + { + UPDATE_TO_VERSION_SCOPED( 116 ) + ADD_USER_SERIALIZER( FeedBackVaryingsName ); + ADD_USER_SERIALIZER( FeedBackMode ); + } }