Ok, here's what I did to solve it. First, I rebuilt my binaries and retested. Strangely, I had different results, though it may be that I didn't do something the first time that I did the second. I can't imagine rebuilding OSG would help, but it appears as though it did.
Second, I retested the 120 shader version, and transitioned from gl_ to osg_ builtins one at a time. Here the secret divulged itself: osg_ModelViewProjectionMatrix and osg_Vertex must *not* be declared, but everything else must. That is, declaring the first two generated "duplicate declaration" errors, but omitting any other built-ins generated "undeclared idnetifier" errors. Note that I only tested osg_Normal, osg_ModelViewMatrix, and osg_NormalMatrix in addition to the first two. I still enabled the built-ins using: Code: (*itr)->getState()->setUseModelViewAndProjectionUniforms(true); (*itr)->getState()->setUseVertexAttributeAliasing(true); For posterity's sake, I've included the source I used to test. ------------------ Read this topic online here: http://forum.openscenegraph.org/viewtopic.php?p=46756#46756
/* OpenSceneGraph example, osgvertexattributes. * * 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 <osgUtil/ShaderGen> #include <osgDB/ReadFile> #include <osgDB/WriteFile> #include <osgViewer/Viewer> #include <osgViewer/ViewerEventHandlers> #include <osgGA/TrackballManipulator> class ConvertToVertexAttibArrays : public osg::NodeVisitor { public: typedef std::pair<unsigned int, std::string> AttributeAlias; ConvertToVertexAttibArrays(): osg::NodeVisitor(osg::NodeVisitor::TRAVERSE_ALL_CHILDREN) { _manualVertexAliasing = false; // mappings taken from http://www.opengl.org/registry/specs/NV/vertex_program.txt _vertexAlias = AttributeAlias(0, "osg_Vertex"); _normalAlias = AttributeAlias(2, "osg_Normal"); _colorAlias = AttributeAlias(3, "osg_Color"); _secondaryColorAlias = AttributeAlias(4, "osg_SecondaryColor"); _fogCoordAlias = AttributeAlias(5, "osg_FogCoord"); _texCoordAlias[0] = AttributeAlias(8, "osg_MultiTexCoord0"); _texCoordAlias[1] = AttributeAlias(9, "osg_MultiTexCoord1"); _texCoordAlias[2] = AttributeAlias(10, "osg_MultiTexCoord2"); _texCoordAlias[3] = AttributeAlias(11, "osg_MultiTexCoord3"); _texCoordAlias[4] = AttributeAlias(12, "osg_MultiTexCoord4"); _texCoordAlias[5] = AttributeAlias(13, "osg_MultiTexCoord5"); _texCoordAlias[6] = AttributeAlias(14, "osg_MultiTexCoord6"); _texCoordAlias[7] = AttributeAlias(15, "osg_MultiTexCoord7"); } void bindAttribute(osg::Program& program, const AttributeAlias& alias) { program.addBindAttribLocation(alias.second, alias.first); } void replaceAndBindAttrib(osg::Program& program, std::string& source, const std::string& originalStr, const AttributeAlias& alias, const std::string& declarationPrefix) { if (replace(source, originalStr, alias.second)) { source.insert(0, declarationPrefix + alias.second + std::string(";\n")); if (_manualVertexAliasing) bindAttribute(program, alias); } } void replaceBuiltInUniform(std::string& source, const std::string& originalStr, const std::string& newStr, const std::string& declarationPrefix) { if (replace(source, originalStr, newStr)) { source.insert(0, declarationPrefix + newStr + std::string(";\n")); } } void convertVertexShader(osg::Program& program, osg::Shader& shader) {/* std::string source = shader.getShaderSource(); // replace ftransform as it only works with built-ins replace(source, "ftransform()", "gl_ModelViewProjectionMatrix * gl_Vertex"); #if 1 replaceAndBindAttrib(program, source, "gl_Normal", _normalAlias, "attribute vec3 "); replaceAndBindAttrib(program, source, "gl_Vertex", _vertexAlias, "attribute vec4 "); replaceAndBindAttrib(program, source, "gl_Color", _colorAlias, "attribute vec4 "); replaceAndBindAttrib(program, source, "gl_SecondaryColor", _secondaryColorAlias, "attribute vec4 "); replaceAndBindAttrib(program, source, "gl_FogCoord", _fogCoordAlias, "attribute float "); replaceAndBindAttrib(program, source, "gl_MultiTexCoord0", _texCoordAlias[0], "attribute vec4 "); replaceAndBindAttrib(program, source, "gl_MultiTexCoord1", _texCoordAlias[1], "attribute vec4 "); replaceAndBindAttrib(program, source, "gl_MultiTexCoord2", _texCoordAlias[2], "attribute vec4 "); replaceAndBindAttrib(program, source, "gl_MultiTexCoord3", _texCoordAlias[3], "attribute vec4 "); replaceAndBindAttrib(program, source, "gl_MultiTexCoord4", _texCoordAlias[4], "attribute vec4 "); replaceAndBindAttrib(program, source, "gl_MultiTexCoord5", _texCoordAlias[5], "attribute vec4 "); replaceAndBindAttrib(program, source, "gl_MultiTexCoord6", _texCoordAlias[6], "attribute vec4 "); replaceAndBindAttrib(program, source, "gl_MultiTexCoord7", _texCoordAlias[7], "attribute vec4 "); #endif #if 1 // replace built in uniform replaceBuiltInUniform(source, "gl_ModelViewMatrix", "osg_ModeViewMatrix", "uniform mat4 "); replaceBuiltInUniform(source, "gl_ModelViewProjectionMatrix", "osg_ModelViewProjectionMatrix", "uniform mat4 "); replaceBuiltInUniform(source, "gl_ProjectionMatrix", "osg_ProjectionMatrix", "uniform mat4 "); #endif shader.setShaderSource(source);*/ } void convertFragmentShader(osg::Program& program, osg::Shader& shader) { } virtual void reset() { _visited.clear(); } void apply(osg::Node& node) { if (_visited.count(&node)!=0) return; _visited.insert(&node); // if (node.getStateSet()) apply(*(node.getStateSet())); traverse(node); } void apply(osg::Geode& geode) { if (_visited.count(&geode)!=0) return; _visited.insert(&geode); //if (geode.getStateSet()) apply(*(geode.getStateSet())); for(unsigned int i=0; i<geode.getNumDrawables(); ++i) { // if (geode.getDrawable(i)->getStateSet()) apply(*(geode.getDrawable(i)->getStateSet())); osg::Geometry* geom = geode.getDrawable(i)->asGeometry(); if (geom) apply(*geom); } } bool replace(std::string& str, const std::string& original_phrase, const std::string& new_phrase) { bool replacedStr = false; std::string::size_type pos = 0; while((pos=str.find(original_phrase, pos))!=std::string::npos) { std::string::size_type endOfPhrasePos = pos+original_phrase.size(); if (endOfPhrasePos<str.size()) { char c = str[endOfPhrasePos]; if ((c>='0' && c<='9') || (c>='a' && c<='z') || (c>='A' && c<='Z')) { pos = endOfPhrasePos; continue; } } replacedStr = true; str.replace(pos, original_phrase.size(), new_phrase); } return replacedStr; } void apply(osg::Program& program, osg::Shader& shader) { /* if (_visited.count(&shader)!=0) return; _visited.insert(&shader); osg::notify(osg::NOTICE)<<"Shader "<<shader.getTypename()<<" ----before-----------"<<std::endl; osg::notify(osg::NOTICE)<<shader.getShaderSource()<<std::endl; if (shader.getType()==osg::Shader::VERTEX) convertVertexShader(program, shader); else if (shader.getType()==osg::Shader::FRAGMENT) convertFragmentShader(program, shader); osg::notify(osg::NOTICE)<<"--after-----------"<<std::endl; osg::notify(osg::NOTICE)<<shader.getShaderSource()<<std::endl; osg::notify(osg::NOTICE)<<"---------------------"<<std::endl; */ } void apply(osg::StateSet& stateset) { /* if (_visited.count(&stateset)!=0) return; _visited.insert(&stateset); return; osg::notify(osg::NOTICE)<<"Found stateset "<<&stateset<<std::endl; osg::Program* program = dynamic_cast<osg::Program*>(stateset.getAttribute(osg::StateAttribute::PROGRAM)); if (program) { osg::notify(osg::NOTICE)<<" Found Program "<<program<<std::endl; for(unsigned int i=0; i<program->getNumShaders(); ++i) { apply(*program, *(program->getShader(i))); } } */ } void apply(osg::Geometry& geom) { geom.setUseDisplayList(false); if (!_manualVertexAliasing) return; osg::notify(osg::NOTICE)<<"Found geometry "<<&geom<<std::endl; if (geom.getVertexArray()) { setVertexAttrib(geom, _vertexAlias, geom.getVertexArray(), false, osg::Geometry::BIND_PER_VERTEX); geom.setVertexArray(0); } if (geom.getNormalArray()) { setVertexAttrib(geom, _normalAlias, geom.getNormalArray(), true, geom.getNormalBinding()); geom.setNormalArray(0); } if (geom.getColorArray()) { setVertexAttrib(geom, _colorAlias, geom.getColorArray(), false, geom.getColorBinding()); geom.setColorArray(0); } if (geom.getSecondaryColorArray()) { setVertexAttrib(geom, _secondaryColorAlias, geom.getSecondaryColorArray(), false, geom.getSecondaryColorBinding()); geom.setSecondaryColorArray(0); } if (geom.getFogCoordArray()) { // should we normalize the FogCoord array? Don't think so... setVertexAttrib(geom, _fogCoordAlias, geom.getFogCoordArray(), false, geom.getFogCoordBinding()); geom.setFogCoordArray(0); } unsigned int maxNumTexCoords = geom.getNumTexCoordArrays(); if (maxNumTexCoords>8) { osg::notify(osg::NOTICE)<<"Warning: Ignoring "<<maxNumTexCoords-8<<" texture coordinate arrays, only 8 are currently supported in vertex attribute conversion code."<<std::endl; maxNumTexCoords = 8; } for(unsigned int i=0; i<maxNumTexCoords; ++i) { if (geom.getTexCoordArray(i)) { setVertexAttrib(geom, _texCoordAlias[i], geom.getTexCoordArray(i), false, osg::Geometry::BIND_PER_VERTEX); geom.setTexCoordArray(i,0); } else { osg::notify(osg::NOTICE)<<"Found empty TexCoordArray("<<i<<")"<<std::endl; } } } void setVertexAttrib(osg::Geometry& geom, const AttributeAlias& alias, osg::Array* array, bool normalize, osg::Geometry::AttributeBinding binding) { unsigned int index = alias.first; const std::string& name = alias.second; array->setName(name); geom.setVertexAttribArray(index, array); geom.setVertexAttribNormalize(index, normalize); geom.setVertexAttribBinding(index, binding); osg::notify(osg::NOTICE)<<" vertex attrib("<<name<<", index="<<index<<", normalize="<<normalize<<" binding="<<binding<<")"<<std::endl; } typedef std::set<osg::Object*> Visited; Visited _visited; bool _manualVertexAliasing; AttributeAlias _vertexAlias; AttributeAlias _normalAlias; AttributeAlias _colorAlias; AttributeAlias _secondaryColorAlias; AttributeAlias _fogCoordAlias; AttributeAlias _texCoordAlias[8]; }; // // // void createShaders( osg::Node* node ) { // "uniform mat4 osg_ModelViewProjectionMatrix;\n" //"in vec4 osg_Vertex;\n" //"uniform mat3 osg_NormalMatrix;\n" //"in vec3 osg_Normal;\n" char vertexShaderSource[] = "#version 150\n" "uniform mat4 osg_ModelViewMatrix;\n" "uniform mat3 osg_NormalMatrix;\n" "out vec3 normal;\n" "in vec3 osg_Normal;\n" "out vec4 light0;\n" "void main()\n" "{\n" "light0 = vec4(0.0, 0.0, 1.0, 0.0 ); \n;" "//light0 = osg_ModelViewMatrix * vec4( 0.0, -1.0, 0.0, 0.0 );\n" "normal = normalize(osg_NormalMatrix * osg_Normal);\n" "gl_Position = osg_ModelViewProjectionMatrix * osg_Vertex; //ftransform();\n" "}\n"; char fragmentShaderSource[] = "#version 150\n" "vec4 color1;\n" "vec4 color2;\n" "vec4 color3;\n" "vec4 color4;\n" "uniform mat4 osg_ModelViewMatrix;\n" "out vec4 fragColor;\n" "in vec3 normal;\n" "in vec4 light0;\n" "void main()\n" "{\n" "color1 = vec4( 1.0, 0.5, 0.5, 1.0 );\n" "color2 = vec4( 0.5, 0.2, 0.2, 1.0 );\n" "color3 = vec4( 0.2, 0.1, 0.1, 1.0 );\n" "color4 = vec4( 0.1, 0.05, 0.05, 1.0 );\n" "//vec4 light0 = vec4(0.0, 0.0, 50.0, 0.0);\n" "//float intensity = dot(vec3(gl_LightSource[0].position), normal);\n" "float intensity = dot( vec3( light0 ), normal );\n" "if (intensity > 0.95) fragColor = color1;\n" "else if (intensity > 0.5) fragColor = color2;\n" "else if (intensity > 0.25) fragColor = color3;\n" "else fragColor = color4;\n" "}\n"; osg::Program* program = new osg::Program; program->addShader(new osg::Shader(osg::Shader::VERTEX, vertexShaderSource)); program->addShader(new osg::Shader(osg::Shader::FRAGMENT, fragmentShaderSource)); node->getOrCreateStateSet()->setAttribute(program); } osg::Node* createSimpleTestModel() { osg::Group* group = new osg::Group; osg::Geode* geode = new osg::Geode; group->addChild(geode); osg::Geometry* geometry = new osg::Geometry; geode->addDrawable(geometry); osg::Vec3Array* vertices = new osg::Vec3Array; vertices->push_back(osg::Vec3(0.0,0.0,0.0)); vertices->push_back(osg::Vec3(0.0,0.0,1.0)); vertices->push_back(osg::Vec3(1.0,0.0,0.0)); vertices->push_back(osg::Vec3(1.0,0.0,1.0)); geometry->setVertexArray(vertices); geometry->addPrimitiveSet(new osg::DrawArrays(GL_TRIANGLE_STRIP, 0, 4)); char vertexShaderSource[] = "void main(void)\n" "{\n" " gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex;\n" "}\n"; char fragmentShaderSource[] = "void main(void)\n" "{\n" " gl_FragColor = vec4(1.0,1.0,0.0,1.0); \n" "}\n"; osg::Program* program = new osg::Program; program->addShader(new osg::Shader(osg::Shader::VERTEX, vertexShaderSource)); program->addShader(new osg::Shader(osg::Shader::FRAGMENT, fragmentShaderSource)); geometry->getOrCreateStateSet()->setAttribute(program); return group; } osg::Node* createSimpleTextureTestModel() { osg::Group* group = new osg::Group; osg::Geode* geode = new osg::Geode; group->addChild(geode); osg::Geometry* geometry = new osg::Geometry; geode->addDrawable(geometry); osg::Vec3Array* vertices = new osg::Vec3Array; vertices->push_back(osg::Vec3(0.0,0.0,0.0)); vertices->push_back(osg::Vec3(0.0,0.0,1.0)); vertices->push_back(osg::Vec3(1.0,0.0,0.0)); vertices->push_back(osg::Vec3(1.0,0.0,1.0)); geometry->setVertexArray(vertices); osg::Vec2Array* texcoords = new osg::Vec2Array; texcoords->push_back(osg::Vec2(0.0,0.0)); texcoords->push_back(osg::Vec2(0.0,1.0)); texcoords->push_back(osg::Vec2(1.0,0.0)); texcoords->push_back(osg::Vec2(1.0,1.0)); geometry->setTexCoordArray(0, texcoords); geometry->addPrimitiveSet(new osg::DrawArrays(GL_TRIANGLE_STRIP, 0, 4)); char vertexShaderSource[] = "varying vec2 texCoord;\n" "void main(void)\n" "{\n" " gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex;\n" " texCoord = gl_MultiTexCoord0.xy;\n" "}\n"; char fragmentShaderSource[] = "varying vec2 texCoord;\n" "uniform sampler2D baseTexture;\n" "void main(void)\n" "{\n" " gl_FragColor = texture2D(baseTexture, texCoord); \n" "}\n"; osg::Program* program = new osg::Program; program->addShader(new osg::Shader(osg::Shader::VERTEX, vertexShaderSource)); program->addShader(new osg::Shader(osg::Shader::FRAGMENT, fragmentShaderSource)); osg::StateSet* stateset = geometry->getOrCreateStateSet(); stateset->setAttribute(program); osg::Image* image = osgDB::readImageFile("Images/lz.rgb"); osg::Texture2D* texture = new osg::Texture2D(image); texture->setFilter(osg::Texture::MIN_FILTER, osg::Texture::LINEAR); texture->setFilter(osg::Texture::MAG_FILTER, osg::Texture::LINEAR); stateset->setTextureAttribute(0, texture); osg::Uniform* baseTextureSampler = new osg::Uniform("baseTexture",0); stateset->addUniform(baseTextureSampler); return group; } int main() { // use an ArgumentParser object to manage the program arguments. //osg::ArgumentParser arguments(&argc,argv); // construct the viewer. osgViewer::Viewer viewer; //(arguments); //std::string outputFileName; // while (arguments.read("-o",outputFileName)) {} osg::ref_ptr<osg::Node> loadedModel = osgDB::readNodeFile( "cow.osg" ); bool runConvertToVertexAttributes = true; /* if (arguments.read("--simple") || arguments.read("--s")) { loadedModel = createSimpleTestModel(); } else if (arguments.read("--texture") || arguments.read("-t")) { loadedModel = createSimpleTextureTestModel(); } else { bool runShaderGen = true; while (arguments.read("--shader-gen")) { runShaderGen = true; } while (arguments.read("--no-shader-gen")) { runShaderGen = false; } while (arguments.read("--vertex-attrib")) { runConvertToVertexAttributes = true; } while (arguments.read("--no-vertex-attrib")) { runConvertToVertexAttributes = false; } loadedModel = osgDB::readNodeFiles(arguments); if (!loadedModel.get()) { osg::notify(osg::NOTICE)<<"No model loaded, please specify a model filename."<<std::endl; return 1; } if (runShaderGen) { // convert fixed function pipeline to shaders osgUtil::ShaderGenVisitor sgv; loadedModel->accept(sgv); } } */ createShaders( loadedModel ); if (runConvertToVertexAttributes) { // find any conventional vertex, colour, normal and tex coords arrays and convert to vertex attributes ConvertToVertexAttibArrays ctvaa; loadedModel->accept(ctvaa); } if (!loadedModel) return 1; /* if (!outputFileName.empty()) { osgDB::writeNodeFile(*loadedModel, outputFileName); return 0; } */ // add a viewport to the viewer and attach the scene graph. viewer.setSceneData(loadedModel.get()); viewer.setCameraManipulator(new osgGA::TrackballManipulator()); // add the stats handler viewer.addEventHandler(new osgViewer::StatsHandler); viewer.realize(); if (runConvertToVertexAttributes) { // switch on the uniforms that track the modelview and projection matrices osgViewer::Viewer::Windows windows; viewer.getWindows(windows); for(osgViewer::Viewer::Windows::iterator itr = windows.begin(); itr != windows.end(); ++itr) { (*itr)->getState()->setUseModelViewAndProjectionUniforms(true); (*itr)->getState()->setUseVertexAttributeAliasing(true); } } return viewer.run(); }
_______________________________________________ osg-users mailing list osg-users@lists.openscenegraph.org http://lists.openscenegraph.org/listinfo.cgi/osg-users-openscenegraph.org