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
[email protected]
http://lists.openscenegraph.org/listinfo.cgi/osg-users-openscenegraph.org