Hi all,

my goal is to evaluate the usefulness of tessellation shaders for us. We are using a framework around osg so I whould like to use tessellation shaders in osg.

I tried my best to introduce tessellation shaders to osg (see diff below) but when running the application the console is flooded with OpenGL 'invalid operation' errors. Since the error message is quite general, maybe one can point out some possibilities to look for are areas to investigate further?

You will find all relevant source code below.
Thanks for any help!

Best regards.
Waldemar

*<osg diff>
*

   Index: include/osg/Shader
   ===================================================================
   --- include/osg/Shader  (revision 11835)
   +++ include/osg/Shader  (working copy)
   @@ -27,6 +27,10 @@
    #include <set>
    #include <map>
// I know this is very dirty but it is the fastest way to test my
   point at the moment
   +#define GL_TESS_CONTROL_SHADER            0x8E88
   +#define GL_TESS_EVALUATION_SHADER_BIT     0x00000010
   +#define GL_TESS_EVALUATION_SHADER         0x8E87
   +
    namespace osg {
class Program;
   @@ -88,6 +92,8 @@
                VERTEX = GL_VERTEX_SHADER,
                FRAGMENT = GL_FRAGMENT_SHADER,
                GEOMETRY = GL_GEOMETRY_SHADER_EXT,
   +            TESS_CONTROL = GL_TESS_CONTROL_SHADER,
   +            TESS_EVALUATION = GL_TESS_EVALUATION_SHADER,
                UNDEFINED = -1
            };
Index: src/osg/Shader.cpp
   ===================================================================
   --- src/osg/Shader.cpp  (revision 11835)
   +++ src/osg/Shader.cpp  (working copy)
   @@ -323,6 +323,8 @@
            case VERTEX:    return "VERTEX";
            case FRAGMENT:  return "FRAGMENT";
            case GEOMETRY:  return "GEOMETRY";
   +        case TESS_CONTROL: return "TESS_CONTROL";
   +        case TESS_EVALUATION: return "TESS_EVALUATION";
            default:        return "UNDEFINED";
        }
    }
   @@ -333,6 +335,8 @@
        if( tname == "VERTEX" )     return VERTEX;
        if( tname == "FRAGMENT" )   return FRAGMENT;
        if( tname == "GEOMETRY" )   return GEOMETRY;
   +    if( tname == "TESS_CONTROL" )   return TESS_CONTROL;
   +    if( tname == "TESS_EVALUATION" )   return TESS_EVALUATION;
        return UNDEFINED;
    }
Index: src/osg/ShaderComposer.cpp
   ===================================================================
   --- src/osg/ShaderComposer.cpp  (revision 11835)
   +++ src/osg/ShaderComposer.cpp  (working copy)
   @@ -43,6 +43,8 @@
// strip out vertex shaders
        Shaders vertexShaders;
   +    Shaders tessellationControllShaders;
   +    Shaders tessellationEvaluationShaders;
        Shaders geometryShaders;
        Shaders fragmentShaders;
@@ -62,6 +64,12 @@
                    case(Shader::VERTEX):
                        vertexShaders.push_back(shader);
                        break;
   +                case(Shader::TESS_CONTROL):
+ tessellationControllShaders.push_back(shader);
   +                                       break;
   +                case(Shader::TESS_EVALUATION):
+ tessellationEvaluationShaders.push_back(shader);
   +                                       break;
                    case(Shader::GEOMETRY):
                        geometryShaders.push_back(shader);
                        break;
   @@ -82,6 +90,16 @@
            addShaderToProgram(program.get(), vertexShaders);
        }
+ if (!tessellationControllShaders.empty())
   +       {
   +               addShaderToProgram(program.get(),
   tessellationControllShaders);
   +       }
   +
   +    if (!tessellationEvaluationShaders.empty())
   +       {
   +               addShaderToProgram(program.get(),
   tessellationEvaluationShaders);
   +       }
   +
        if (!geometryShaders.empty())
        {
            addShaderToProgram(program.get(), geometryShaders);

*
*

*<application source>*

   #include <iostream>

   #include <osg/PolygonMode>
   #include <osg/Image>
   #include <osg/Node>
   #include <osg/Group>
   #include <osg/Geode>
   #include <osg/Geometry>
   #include <osg/Program>
   #include <osg/Shader>
   #include <osg/Texture2D>
   #include <osg/Texture2DArray>
   #include <osgDB/ReadFile>
   #include <osgViewer/Viewer>
   #include <osg/PositionAttitudeTransform>
   #include <osgGA/TrackballManipulator>

   #include "MyKeyboardEventHandler.h"

   osg::Program* createTestShaderProgramm()
   {
       osg::Program* prog = new osg::Program;
       prog->setName("Test");
// VERTEX SHADER
       osg::Shader* vertShader =
   
osgDB::readShaderFile("/localhome/wschwan/workspace/height_map_tessellation/src/shaders/test.vert");
       if (!vertShader){
           osg::notify(osg::INFO) << " can't read vertex shader!" <<
   std::endl;
           std::exit(-1);
       } else {
           vertShader->setType(osg::Shader::VERTEX);
           prog->addShader( vertShader );
       }
// TESSELLATION CONTROLL SHADER
       std::ifstream tess_controll_shader
   
("/localhome/wschwan/workspace/height_map_tessellation/src/shaders/test.tesscontroll");
       if (!tess_controll_shader.is_open()){
           osg::notify(osg::INFO) << " can't read tesselation controll
   shader!" << std::endl;
           std::exit(-1);
       }

       std::string src = "";
       std::string line;
       while (!tess_controll_shader.eof())
       {
           std::getline (tess_controll_shader, line);
           src.append(line);
           src.append("\n");
       }
       tess_controll_shader.close();

       osg::Shader* tesControllShader = new
   osg::Shader(osg::Shader::TESS_CONTROL, src.c_str());
       prog->addShader( tesControllShader );

       // FRAGMENT SHADER
       osg::Shader* fragShader =
   
osgDB::readShaderFile("/localhome/wschwan/workspace/height_map_tessellation/src/shaders/test.frag");
       if (!fragShader){
           osg::notify(osg::INFO) << " can't read fragment shader!" <<
   std::endl;
           std::exit(-1);
       } else {
           fragShader->setType(osg::Shader::FRAGMENT);
           prog->addShader( fragShader );
       }

       return prog;
   }

   osg::Geode* createHeightField(int width = 10)
   {
       osg::Geometry* heightFieldGeometry = new osg::Geometry();

       osg::Geode* heightFieldGeode = new osg::Geode();
       heightFieldGeode->addDrawable(heightFieldGeometry);

       //Create verticies from left to right and front to back.
       osg::Vec3Array* heightFieldVertices = new osg::Vec3Array;
       osg::Vec2Array* heightFieldTexCords = new osg::Vec2Array;
       osg::Vec4Array* heightFieldColors = new osg::Vec4Array;

       float xMax = width-1;
       float yMax = width-1;

       osg::VertexBufferObject* vbo =
   heightFieldGeometry->getOrCreateVertexBufferObject();
       std::cout << "VBO Name: " << vbo->getName() << std::endl;

       int index = 0;
          for (int y = 0; y < width; y++){
              float yCord = y / yMax;

              for (int x = 0; x< width; x ++){
               float xCord = x / xMax;

               heightFieldVertices->push_back( osg::Vec3( x, y, 0) );
               heightFieldColors->push_back( osg::Vec4(1.0f, 1.0f,
   1.0f, 1.0f) ); //opaque white

   //            osg::notify() << "heightFieldTexCords->push_back(" <<
   xCord << "," << yCord << ")" << std::endl;

               heightFieldTexCords->push_back( osg::Vec2f( xCord, yCord
   ) );
               index++;
           }
       }


       //Associate this set of vertices with the geometry associated
   with the
       //geode we added to the scene.

       heightFieldGeometry->setVertexArray( heightFieldVertices );

       heightFieldGeometry->setColorArray(heightFieldColors);
       heightFieldGeometry->setColorBinding(
   osg::Geometry::BIND_PER_VERTEX );
       int textureUnit = 0;
       heightFieldGeometry->setTexCoordArray(textureUnit,
   heightFieldTexCords);


       osg::DrawElementsUInt* hightField = new
   osg::DrawElementsUInt(osg::PrimitiveSet::QUADS, 0);
       // create height field grid from left to right and front to back.
       for (int y = 0; y < width-1; y++){
           for (int x = 0; x< width-1; x ++){
               int vertexIndex = (y*width) + x;
               hightField->push_back(vertexIndex); // ancer point
               hightField->push_back(vertexIndex+1); //right neighbor
               hightField->push_back(vertexIndex+width+1); //top neighbor
               hightField->push_back(vertexIndex+width); //top right
   neighbor
           }
       }

       heightFieldGeometry->addPrimitiveSet(hightField);
       heightFieldGeometry->getOrCreateStateSet()->addUniform(new
   osg::Uniform("vbo", vbo));

       return heightFieldGeode;
   }

   int main()
   {
       osg::setNotifyLevel(osg::INFO);

       osgViewer::Viewer viewer;
       viewer.setUpViewInWindow(1685,0,1600,1000,0);
       osg::Group* root = new osg::Group();

       osg::Geode * heightField = createHeightField(20);

       root->addChild(heightField);


       // Declare and initialize a transform node.
       osg::PositionAttitudeTransform* pyramidTwoXForm =
           new osg::PositionAttitudeTransform();

       root->addChild(pyramidTwoXForm);


       // Declare and initialize a Vec3 instance to change the
       // position of the model in the scene
       osg::Vec3 pyramidTwoPosition(15,0,0);
       pyramidTwoXForm->setPosition( pyramidTwoPosition );

       // switch off lighting as we haven't assigned any normals.
       root->getOrCreateStateSet()->setMode(GL_LIGHTING,
   osg::StateAttribute::OFF);


       viewer.setSceneData( root );
       //viewer.run();

       // input handling
       MyKeyboardEventHandler* kbeh = new MyKeyboardEventHandler();
       kbeh->setStateSetForWireframeing(root->getOrCreateStateSet());
       viewer.addEventHandler(kbeh);

       // adding texture
       osg::Image* image =
   
osgDB::readImageFile("/localhome/wschwan/workspace/height_map_tessellation/data/test.jpg");
       if (!image){
           osg::notify(osg::FATAL) << " cant load texture image." <<
   std::endl;
           return -1;
       }

       osg::Texture2D* tex = new osg::Texture2D();
       tex->setDataVariance( osg::Object::DYNAMIC );
       tex->setImage(image);

       int textureUnit = 0;
       osg::StateSet* state = heightField->getOrCreateStateSet();
       state->setTextureAttributeAndModes(textureUnit, tex,
   osg::StateAttribute::ON);
       state->addUniform(new osg::Uniform("texture", textureUnit));


       // adding height map texture
       osg::Image* height_image =
   
osgDB::readImageFile("/localhome/wschwan/workspace/height_map_tessellation/data/textures/horizon3000x1500_offset_2500_2000.png");
       if (!height_image){
           osg::notify(osg::FATAL) << " cant load height map image." <<
   std::endl;
           return -1;
       }

       osg::Texture2D* heightTex = new osg::Texture2D();
       heightTex->setDataVariance( osg::Object::DYNAMIC );
       heightTex->setImage(height_image);

       state->setTextureAttributeAndModes(1, heightTex,
   osg::StateAttribute::ON);
       state->addUniform(new osg::Uniform("height_map", 1));

       state->setAttributeAndModes(createTestShaderProgramm(),
   osg::StateAttribute::ON);


       viewer.setCameraManipulator(new osgGA::TrackballManipulator());
       viewer.realize();

       while( !viewer.done() )
       {
           viewer.frame();
       }

       return 0;
   }

*<vertex shader>*

   #version 400

   in vec4 Position;
   out vec3 vPosition;

   void main()
   {
       vPosition = Position.xyz;
   }

*<tessellation control shader>
*

   #version 400

   layout(vertices = 4) out;
   in vec3 vPosition[];
   out vec3 tcPosition[];

   #define ID gl_InvocationID

   void main()
   {
       tcPosition[ID] = vPosition[ID];
float TessLevelInner = 1;
       float TessLevelOuter = 1;

       if (ID == 0) {
           gl_TessLevelInner[0] = TessLevelInner;
           gl_TessLevelInner[1] = TessLevelInner;
           gl_TessLevelOuter[0] = TessLevelOuter;
           gl_TessLevelOuter[1] = TessLevelOuter;
           gl_TessLevelOuter[2] = TessLevelOuter;
           gl_TessLevelOuter[3] = TessLevelOuter;
       }
   }

*<tessellation evaluation>*

   #version 400 compatiblity

   layout(quads) in;
   in vec3 tcPosition[];
   out vec3 tePosition;
   uniform mat4 Projection;
   uniform mat4 Modelview;

   void main()
   {
       float u = gl_TessCoord.x, v = gl_TessCoord.y;
       vec3 a = mix(tcPosition[0], tcPosition[3], u);
       vec3 b = mix(tcPosition[12], tcPosition[15], u);
       tePosition = mix(a, b, v);
       gl_Position = Projection * Modelview * vec4(tePosition, 1);
   }

*<fragment>*

   #version 400

   out vec4 FragColor;

   void main(void)
   {
       FragColor = vec4(1,1,1,1);
   }

_______________________________________________
osg-users mailing list
osg-users@lists.openscenegraph.org
http://lists.openscenegraph.org/listinfo.cgi/osg-users-openscenegraph.org

Reply via email to