From 77b8962bccb0f233651bada12d1c352727917fe2 Mon Sep 17 00:00:00 2001 From: Robert Osfield Date: Fri, 13 Feb 2015 10:56:59 +0000 Subject: [PATCH] Deprecated the old ShaderComposition example code so that it's now only invoked if you add a --old to the osgshadercomposition command line. Introduced a new shader composition example based on the new #pragama and #define based GLSL shader/osg::StateSet::setDefine() functionality now built into the core OSG. git-svn-id: http://svn.openscenegraph.org/osg/OpenSceneGraph/trunk@14692 16af8721-9629-0410-8352-f15c8da7e697 --- examples/osgshadercomposition/CMakeLists.txt | 1 + .../oldshadercomposition.cpp | 160 +++++++++++++ .../osgshadercomposition.cpp | 212 +++++++++--------- 3 files changed, 266 insertions(+), 107 deletions(-) create mode 100644 examples/osgshadercomposition/oldshadercomposition.cpp diff --git a/examples/osgshadercomposition/CMakeLists.txt b/examples/osgshadercomposition/CMakeLists.txt index e06bab83e..f80525e31 100644 --- a/examples/osgshadercomposition/CMakeLists.txt +++ b/examples/osgshadercomposition/CMakeLists.txt @@ -1,4 +1,5 @@ SET(TARGET_SRC + oldshadercomposition.cpp osgshadercomposition.cpp ) diff --git a/examples/osgshadercomposition/oldshadercomposition.cpp b/examples/osgshadercomposition/oldshadercomposition.cpp new file mode 100644 index 000000000..443fcefe8 --- /dev/null +++ b/examples/osgshadercomposition/oldshadercomposition.cpp @@ -0,0 +1,160 @@ +/* OpenSceneGraph example, osganimate. +* +* 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. +*/ + +#include +#include +#include + +osg::Node* createOldShaderCompositionScene(osg::ArgumentParser& arguments) +{ + osg::Node* node = osgDB::readNodeFiles(arguments); + if (!node) return 0; + + osg::Group* group = new osg::Group; + double spacing = node->getBound().radius() * 2.0; + + osg::Vec3d position(0.0,0.0,0.0); + + osg::ShaderAttribute* sa1 = NULL; + + { + osg::StateSet* stateset = group->getOrCreateStateSet(); + osg::ShaderAttribute* sa = new osg::ShaderAttribute; + sa->setType(osg::StateAttribute::Type(10000)); + sa1 = sa; + stateset->setAttribute(sa); + + { + osg::Shader* vertex_shader = new osg::Shader(osg::Shader::VERTEX); + vertex_shader->addCodeInjection(-1,"varying vec4 color;\n"); + vertex_shader->addCodeInjection(-1,"varying vec4 texcoord;\n"); + vertex_shader->addCodeInjection(0,"color = gl_Color;\n"); + vertex_shader->addCodeInjection(0,"texcoord = gl_MultiTexCoord0;\n"); + vertex_shader->addCodeInjection(0,"gl_Position = ftransform();\n"); + sa->addShader(vertex_shader); + } + + { + osg::Shader* fragment_shader = new osg::Shader(osg::Shader::FRAGMENT); + fragment_shader->addCodeInjection(-1,"varying vec4 color;\n"); + fragment_shader->addCodeInjection(-1,"varying vec4 texcoord;\n"); + fragment_shader->addCodeInjection(-1,"uniform sampler2D baseTexture; \n"); + fragment_shader->addCodeInjection(0,"gl_FragColor = color * texture2D( baseTexture, texcoord );\n"); + + sa->addShader(fragment_shader); + } + + sa->addUniform(new osg::Uniform("baseTexture",0)); + + } + + // inherit the ShaderComponents entirely from above + { + osg::PositionAttitudeTransform* pat = new osg::PositionAttitudeTransform; + pat->setPosition(position); + pat->addChild(node); + + position.x() += spacing; + + group->addChild(pat); + + } + + { + osg::PositionAttitudeTransform* pat = new osg::PositionAttitudeTransform; + pat->setPosition(position); + pat->addChild(node); + + position.x() += spacing; + + osg::StateSet* stateset = pat->getOrCreateStateSet(); + stateset->setMode(GL_BLEND, osg::StateAttribute::ON); + + osg::ShaderAttribute* sa = new osg::ShaderAttribute; + sa->setType(osg::StateAttribute::Type(10001)); + stateset->setAttribute(sa); + + { + osg::Shader* fragment_shader = new osg::Shader(osg::Shader::FRAGMENT); + fragment_shader->addCodeInjection(0.9f,"gl_FragColor.a = gl_FragColor.a*0.5;\n"); + + sa->addShader(fragment_shader); + } + + group->addChild(pat); + } + + // resuse the first ShaderAttribute's type and ShaderComponent, just use new uniform + { + osg::PositionAttitudeTransform* pat = new osg::PositionAttitudeTransform; + pat->setPosition(position); + pat->addChild(node); + + position.x() += spacing; + + osg::StateSet* stateset = pat->getOrCreateStateSet(); + osg::ShaderAttribute* sa = new osg::ShaderAttribute(*sa1); + stateset->setAttribute(sa); + + // reuse the same ShaderComponent as the first branch + sa->addUniform(new osg::Uniform("myColour",osg::Vec4(1.0f,1.0f,0.0f,1.0f))); + + group->addChild(pat); + + } + + + // resuse the first ShaderAttribute's type and ShaderComponent, just use new uniform + { + osg::PositionAttitudeTransform* pat = new osg::PositionAttitudeTransform; + pat->setPosition(position); + pat->addChild(node); + + position.x() += spacing; + + osg::StateSet* stateset = pat->getOrCreateStateSet(); + osg::ShaderAttribute* sa = new osg::ShaderAttribute; + sa->setType(osg::StateAttribute::Type(10000)); + stateset->setAttribute(sa); + stateset->setMode(GL_BLEND, osg::StateAttribute::ON); + stateset->setRenderingHint(osg::StateSet::TRANSPARENT_BIN); + + { + osg::Shader* vertex_shader = new osg::Shader(osg::Shader::VERTEX); + vertex_shader->addCodeInjection(0,"gl_Position = ftransform();\n"); + + sa->addShader(vertex_shader); + } + + { + osg::Shader* fragment_shader = new osg::Shader(osg::Shader::FRAGMENT); + fragment_shader->addCodeInjection(-1,"uniform vec4 newColour;\n"); + fragment_shader->addCodeInjection(-1,"uniform float osg_FrameTime;\n"); + fragment_shader->addCodeInjection(0,"gl_FragColor = vec4(newColour.r,newColour.g,newColour.b, 0.5+sin(osg_FrameTime*2.0)*0.5);\n"); + + sa->addShader(fragment_shader); + sa->addUniform(new osg::Uniform("newColour",osg::Vec4(1.0f,1.0f,1.0f,0.5f))); + } + + group->addChild(pat); + + } + + return group; +} + diff --git a/examples/osgshadercomposition/osgshadercomposition.cpp b/examples/osgshadercomposition/osgshadercomposition.cpp index 750129ec1..b14c32eda 100644 --- a/examples/osgshadercomposition/osgshadercomposition.cpp +++ b/examples/osgshadercomposition/osgshadercomposition.cpp @@ -1,4 +1,4 @@ -/* OpenSceneGraph example, osganimate. +/* O penSceneGraph example, osganimate. * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -18,145 +18,129 @@ #include #include -#include #include -osg::Node* createSceneGraph(osg::ArgumentParser& arguments) +// pull in the old shader composition implementation function +extern osg::Node* createOldShaderCompositionScene(osg::ArgumentParser& arguments); + +osg::Node* createNewShaderCompositionScene(osg::ArgumentParser& arguments) { - osg::Node* node = osgDB::readNodeFiles(arguments); + osg::ref_ptr node = osgDB::readNodeFiles(arguments); if (!node) return 0; - osg::Group* group = new osg::Group; + osg::ref_ptr group = new osg::Group; + + osg::ref_ptr stateset = group->getOrCreateStateSet(); + osg::ref_ptr program = new osg::Program; + stateset->setAttribute(program.get()); + + osg::ref_ptr lighting_shader = osgDB::readShaderFile("shaders/lighting.vert"); + if (lighting_shader.valid()) + { + program->addShader(lighting_shader.get()); + OSG_NOTICE<<"Adding lighting shader"< vertex_shader = osgDB::readShaderFile("shaders/osgshadercomposition.vert"); + if (vertex_shader.valid()) + { + program->addShader(vertex_shader.get()); + OSG_NOTICE<<"Adding vertex shader"< fragment_shader = osgDB::readShaderFile("shaders/osgshadercomposition.frag"); + if (fragment_shader.valid()) + { + program->addShader(fragment_shader.get()); + OSG_NOTICE<<"Adding fragment shader"<addUniform(new osg::Uniform("texture0", 0)); + + double spacing = node->getBound().radius() * 2.0; osg::Vec3d position(0.0,0.0,0.0); - osg::ShaderAttribute* sa1 = NULL; - - { - osg::StateSet* stateset = group->getOrCreateStateSet(); - osg::ShaderAttribute* sa = new osg::ShaderAttribute; - sa->setType(osg::StateAttribute::Type(10000)); - sa1 = sa; - stateset->setAttribute(sa); - - { - osg::Shader* vertex_shader = new osg::Shader(osg::Shader::VERTEX); - vertex_shader->addCodeInjection(-1,"varying vec4 color;\n"); - vertex_shader->addCodeInjection(-1,"varying vec4 texcoord;\n"); - vertex_shader->addCodeInjection(0,"color = gl_Color;\n"); - vertex_shader->addCodeInjection(0,"texcoord = gl_MultiTexCoord0;\n"); - vertex_shader->addCodeInjection(0,"gl_Position = ftransform();\n"); - sa->addShader(vertex_shader); - } - - { - osg::Shader* fragment_shader = new osg::Shader(osg::Shader::FRAGMENT); - fragment_shader->addCodeInjection(-1,"varying vec4 color;\n"); - fragment_shader->addCodeInjection(-1,"varying vec4 texcoord;\n"); - fragment_shader->addCodeInjection(-1,"uniform sampler2D baseTexture; \n"); - fragment_shader->addCodeInjection(0,"gl_FragColor = color * texture2DProj( baseTexture, texcoord );\n"); - - sa->addShader(fragment_shader); - } - - sa->addUniform(new osg::Uniform("baseTexture",0)); - - } - - // inherit the ShaderComponents entirely from above { + // first subgraph, one the left, just inherit all the defaults osg::PositionAttitudeTransform* pat = new osg::PositionAttitudeTransform; pat->setPosition(position); - pat->addChild(node); + pat->addChild(node.get()); position.x() += spacing; group->addChild(pat); - } { + // second subgraph, enable lighting by passing a GL_LIGHTING defines to the shaders + // As the lighting.vert shader has a #pragma requires(GL_LIGHTING) in the shader it + // instructs the osg::Prorgam to link in this shader only when the GL_LIGHTING define + // is provided. The osgshadercomposition.vert also has a #pragma import_defines(GL_LIGHTING ..) so + // when the GL_LIGHTING is provided it'll enable the lighting paths in the osgshadercomposition.vert + // shader calling the lighting function per vertex osg::PositionAttitudeTransform* pat = new osg::PositionAttitudeTransform; pat->setPosition(position); - pat->addChild(node); + pat->getOrCreateStateSet()->setDefine("GL_LIGHTING"); + + pat->addChild(node.get()); position.x() += spacing; - osg::StateSet* stateset = pat->getOrCreateStateSet(); - stateset->setMode(GL_BLEND, osg::StateAttribute::ON); - - osg::ShaderAttribute* sa = new osg::ShaderAttribute; - sa->setType(osg::StateAttribute::Type(10001)); - stateset->setAttribute(sa); - - { - osg::Shader* fragment_shader = new osg::Shader(osg::Shader::FRAGMENT); - fragment_shader->addCodeInjection(0.9f,"gl_FragColor.a = gl_FragColor.a*0.5;\n"); - - sa->addShader(fragment_shader); - } - group->addChild(pat); } - // resuse the first ShaderAttribute's type and ShaderComponent, just use new uniform { + // third subgraph, enable texturing by passing the GL_TEXTURE_2D define to the shaders. + // Both the osgshadercomposition.vert and osgshadercomposition.frag shaders have a + // #pragma import_defines(GL_TEXTURE_2D) so that can use this define to enable the + // passing of texture coordinates between the vertex and framgment shaders and for + // the fragment shader to read the texture of unit 0 (provided by the "texture0" uniform above. osg::PositionAttitudeTransform* pat = new osg::PositionAttitudeTransform; pat->setPosition(position); - pat->addChild(node); + pat->getOrCreateStateSet()->setDefine("GL_TEXTURE_2D"); + + pat->addChild(node.get()); position.x() += spacing; - osg::StateSet* stateset = pat->getOrCreateStateSet(); - osg::ShaderAttribute* sa = new osg::ShaderAttribute(*sa1); - stateset->setAttribute(sa); - - // reuse the same ShaderComponent as the first branch - sa->addUniform(new osg::Uniform("myColour",osg::Vec4(1.0f,1.0f,0.0f,1.0f))); - group->addChild(pat); - } - // resuse the first ShaderAttribute's type and ShaderComponent, just use new uniform { + // fourth subgraph, enable texturing and lighting osg::PositionAttitudeTransform* pat = new osg::PositionAttitudeTransform; pat->setPosition(position); - pat->addChild(node); + pat->getOrCreateStateSet()->setDefine("GL_LIGHTING"); + pat->getOrCreateStateSet()->setDefine("GL_TEXTURE_2D"); + + pat->addChild(node.get()); position.x() += spacing; - osg::StateSet* stateset = pat->getOrCreateStateSet(); - osg::ShaderAttribute* sa = new osg::ShaderAttribute; - sa->setType(osg::StateAttribute::Type(10000)); - stateset->setAttribute(sa); - stateset->setMode(GL_BLEND, osg::StateAttribute::ON); - stateset->setRenderingHint(osg::StateSet::TRANSPARENT_BIN); - - { - osg::Shader* vertex_shader = new osg::Shader(osg::Shader::VERTEX); - vertex_shader->addCodeInjection(0,"gl_Position = ftransform();\n"); - - sa->addShader(vertex_shader); - } - - { - osg::Shader* fragment_shader = new osg::Shader(osg::Shader::FRAGMENT); - fragment_shader->addCodeInjection(-1,"uniform vec4 newColour;\n"); - fragment_shader->addCodeInjection(-1,"uniform float osg_FrameTime;\n"); - fragment_shader->addCodeInjection(0,"gl_FragColor = vec4(newColour.r,newColour.g,newColour.b, 0.5+sin(osg_FrameTime*2.0)*0.5);\n"); - - sa->addShader(fragment_shader); - sa->addUniform(new osg::Uniform("newColour",osg::Vec4(1.0f,1.0f,1.0f,0.5f))); - } - group->addChild(pat); - } - return group; + { + // fourth subgraph, enable texturing and lighting + osg::PositionAttitudeTransform* pat = new osg::PositionAttitudeTransform; + pat->setPosition(position); + pat->getOrCreateStateSet()->setDefine("GL_LIGHTING"); + pat->getOrCreateStateSet()->setDefine("GL_TEXTURE_2D"); + pat->getOrCreateStateSet()->setDefine("VERTEX_FUNC(v)", "vec4(v.x, v.y, v.z * sin(osg_SimulationTime), v.w)"); + + pat->addChild(node.get()); + + position.x() += spacing; + + group->addChild(pat); + } + + group->addChild(node.get()); + + return group.release(); } int main( int argc, char **argv ) @@ -165,21 +149,35 @@ int main( int argc, char **argv ) osgViewer::Viewer viewer(arguments); - osg::ref_ptr scenegraph = createSceneGraph(arguments); - if (!scenegraph) return 1; + viewer.setThreadingModel(osgViewer::Viewer::SingleThreaded); - viewer.setSceneData(scenegraph.get()); - - viewer.realize(); - - // enable shader composition - osgViewer::Viewer::Windows windows; - viewer.getWindows(windows); - for(osgViewer::Viewer::Windows::iterator itr = windows.begin(); - itr != windows.end(); - ++itr) + if (arguments.read("--old")) { - (*itr)->getState()->setShaderCompositionEnabled(true); + // use deprecated shader composition infrastructure + osg::ref_ptr scenegraph = createOldShaderCompositionScene(arguments); + if (!scenegraph) return 1; + + viewer.setSceneData(scenegraph.get()); + + viewer.realize(); + + // enable shader composition + osgViewer::Viewer::Windows windows; + viewer.getWindows(windows); + for(osgViewer::Viewer::Windows::iterator itr = windows.begin(); + itr != windows.end(); + ++itr) + { + (*itr)->getState()->setShaderCompositionEnabled(true); + } + } + else + { + // use new #pragama(tic) shader composition. + osg::ref_ptr scenegraph = createNewShaderCompositionScene(arguments); + if (!scenegraph) return 1; + + viewer.setSceneData(scenegraph.get()); } return viewer.run();