2008-01-08 22:29:44 +08:00
|
|
|
/* OpenSceneGraph example, osgshaders2
|
|
|
|
*
|
|
|
|
* 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/osgshaders2/osgshaders2.cpp
|
|
|
|
* author: Mike Weiblen 2008-01-03
|
|
|
|
* copyright: (C) 2008 Zebra Imaging
|
|
|
|
* license: OpenSceneGraph Public License (OSGPL)
|
|
|
|
*
|
|
|
|
* A demo of GLSL geometry shaders using OSG
|
|
|
|
* Tested on Dell Precision M4300 w/ NVIDIA Quadro FX 360M
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
|
|
#include <osg/Notify>
|
|
|
|
#include <osg/ref_ptr>
|
|
|
|
#include <osg/Geode>
|
|
|
|
#include <osg/Geometry>
|
|
|
|
#include <osg/Point>
|
|
|
|
#include <osg/Vec3>
|
|
|
|
#include <osg/Vec4>
|
|
|
|
#include <osg/Program>
|
|
|
|
#include <osg/Shader>
|
|
|
|
#include <osg/Uniform>
|
|
|
|
#include <osgViewer/Viewer>
|
|
|
|
|
|
|
|
// play with these #defines to see their effect
|
|
|
|
#define ENABLE_GLSL
|
|
|
|
#define ENABLE_GEOMETRY_SHADER
|
|
|
|
|
|
|
|
///////////////////////////////////////////////////////////////////////////
|
|
|
|
|
|
|
|
#ifdef ENABLE_GLSL
|
|
|
|
|
|
|
|
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* vertSource = {
|
|
|
|
"#version 120\n"
|
|
|
|
"#extension GL_EXT_geometry_shader4 : enable\n"
|
|
|
|
"uniform float u_anim1;\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* geomSource = {
|
|
|
|
"#version 120\n"
|
|
|
|
"#extension GL_EXT_geometry_shader4 : enable\n"
|
|
|
|
"uniform float u_anim1;\n"
|
From Christophe Loustaunau,"
I have found some errors on the example osgGeometryShaders. It's about the varying in the geometry shader.
take a look at the varying vec4 v_color.
In the vertex shader, v_color is initialized to gl_vertex
then in the geometry shader v_color is initialized to gl_PositionIn[0]
and in the fragment shader v_color is used as the fragment color.
Try to initialized v_color to vec4(1.0, 0.0, 0.0, 1.0) in the vertex shader and comment the line :
" v_color = v;\n" in the geometry shader, and you will see the lines as black !
It's because you have to use keywords in and out.
extract from : http://www.opengl.org/registry/specs/EXT/geometry_shader4.txt :
in - for function parameters passed into a function or for input varying
variables (geometry only)
out - for function parameters passed back out of a function, but not
initialized for use when passed in. Also for output varying variables
(geometry only).
Then for a geometry shader, a varying must be an array :
extract from : http://www.opengl.org/registry/specs/EXT/geometry_shader4.txt :
Since a geometry shader operates on primitives, each input varying variable needs to be
declared as an array. Each element of such an array corresponds to a
vertex of the primitive being processed. If the varying variable is
declared as a scalar or matrix in the vertex shader, it will be a
one-dimensional array in the geometry shader. Each array can optionally
have a size declared. If a size is not specified, it inferred by the
linker and depends on the value of the input primitive type.
Here is a patch based on the svn version of osg that correct that.
"
2008-09-18 01:25:39 +08:00
|
|
|
"varying in vec4 v_color[];\n"
|
|
|
|
"varying out vec4 v_color_out;\n"
|
2008-01-08 22:29:44 +08:00
|
|
|
"void main(void)\n"
|
|
|
|
"{\n"
|
|
|
|
" vec4 v = gl_PositionIn[0];\n"
|
From Christophe Loustaunau,"
I have found some errors on the example osgGeometryShaders. It's about the varying in the geometry shader.
take a look at the varying vec4 v_color.
In the vertex shader, v_color is initialized to gl_vertex
then in the geometry shader v_color is initialized to gl_PositionIn[0]
and in the fragment shader v_color is used as the fragment color.
Try to initialized v_color to vec4(1.0, 0.0, 0.0, 1.0) in the vertex shader and comment the line :
" v_color = v;\n" in the geometry shader, and you will see the lines as black !
It's because you have to use keywords in and out.
extract from : http://www.opengl.org/registry/specs/EXT/geometry_shader4.txt :
in - for function parameters passed into a function or for input varying
variables (geometry only)
out - for function parameters passed back out of a function, but not
initialized for use when passed in. Also for output varying variables
(geometry only).
Then for a geometry shader, a varying must be an array :
extract from : http://www.opengl.org/registry/specs/EXT/geometry_shader4.txt :
Since a geometry shader operates on primitives, each input varying variable needs to be
declared as an array. Each element of such an array corresponds to a
vertex of the primitive being processed. If the varying variable is
declared as a scalar or matrix in the vertex shader, it will be a
one-dimensional array in the geometry shader. Each array can optionally
have a size declared. If a size is not specified, it inferred by the
linker and depends on the value of the input primitive type.
Here is a patch based on the svn version of osg that correct that.
"
2008-09-18 01:25:39 +08:00
|
|
|
" v_color_out = v + v_color[0];\n"
|
2008-01-08 22:29:44 +08:00
|
|
|
"\n"
|
|
|
|
" gl_Position = v + vec4(u_anim1,0.,0.,0.); EmitVertex();\n"
|
|
|
|
" gl_Position = v - vec4(u_anim1,0.,0.,0.); EmitVertex();\n"
|
|
|
|
" EndPrimitive();\n"
|
|
|
|
"\n"
|
|
|
|
" gl_Position = v + vec4(0.,1.0-u_anim1,0.,0.); EmitVertex();\n"
|
|
|
|
" gl_Position = v - vec4(0.,1.0-u_anim1,0.,0.); EmitVertex();\n"
|
|
|
|
" EndPrimitive();\n"
|
|
|
|
"}\n"
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
static const char* fragSource = {
|
|
|
|
"#version 120\n"
|
|
|
|
"#extension GL_EXT_geometry_shader4 : enable\n"
|
|
|
|
"uniform float u_anim1;\n"
|
From Christophe Loustaunau,"
I have found some errors on the example osgGeometryShaders. It's about the varying in the geometry shader.
take a look at the varying vec4 v_color.
In the vertex shader, v_color is initialized to gl_vertex
then in the geometry shader v_color is initialized to gl_PositionIn[0]
and in the fragment shader v_color is used as the fragment color.
Try to initialized v_color to vec4(1.0, 0.0, 0.0, 1.0) in the vertex shader and comment the line :
" v_color = v;\n" in the geometry shader, and you will see the lines as black !
It's because you have to use keywords in and out.
extract from : http://www.opengl.org/registry/specs/EXT/geometry_shader4.txt :
in - for function parameters passed into a function or for input varying
variables (geometry only)
out - for function parameters passed back out of a function, but not
initialized for use when passed in. Also for output varying variables
(geometry only).
Then for a geometry shader, a varying must be an array :
extract from : http://www.opengl.org/registry/specs/EXT/geometry_shader4.txt :
Since a geometry shader operates on primitives, each input varying variable needs to be
declared as an array. Each element of such an array corresponds to a
vertex of the primitive being processed. If the varying variable is
declared as a scalar or matrix in the vertex shader, it will be a
one-dimensional array in the geometry shader. Each array can optionally
have a size declared. If a size is not specified, it inferred by the
linker and depends on the value of the input primitive type.
Here is a patch based on the svn version of osg that correct that.
"
2008-09-18 01:25:39 +08:00
|
|
|
"varying vec4 v_color_out;\n"
|
2008-01-08 22:29:44 +08:00
|
|
|
"void main(void)\n"
|
|
|
|
"{\n"
|
From Christophe Loustaunau,"
I have found some errors on the example osgGeometryShaders. It's about the varying in the geometry shader.
take a look at the varying vec4 v_color.
In the vertex shader, v_color is initialized to gl_vertex
then in the geometry shader v_color is initialized to gl_PositionIn[0]
and in the fragment shader v_color is used as the fragment color.
Try to initialized v_color to vec4(1.0, 0.0, 0.0, 1.0) in the vertex shader and comment the line :
" v_color = v;\n" in the geometry shader, and you will see the lines as black !
It's because you have to use keywords in and out.
extract from : http://www.opengl.org/registry/specs/EXT/geometry_shader4.txt :
in - for function parameters passed into a function or for input varying
variables (geometry only)
out - for function parameters passed back out of a function, but not
initialized for use when passed in. Also for output varying variables
(geometry only).
Then for a geometry shader, a varying must be an array :
extract from : http://www.opengl.org/registry/specs/EXT/geometry_shader4.txt :
Since a geometry shader operates on primitives, each input varying variable needs to be
declared as an array. Each element of such an array corresponds to a
vertex of the primitive being processed. If the varying variable is
declared as a scalar or matrix in the vertex shader, it will be a
one-dimensional array in the geometry shader. Each array can optionally
have a size declared. If a size is not specified, it inferred by the
linker and depends on the value of the input primitive type.
Here is a patch based on the svn version of osg that correct that.
"
2008-09-18 01:25:39 +08:00
|
|
|
" gl_FragColor = v_color_out;\n"
|
2008-01-08 22:29:44 +08:00
|
|
|
"}\n"
|
|
|
|
};
|
|
|
|
|
|
|
|
osg::Program* createShader()
|
|
|
|
{
|
|
|
|
osg::Program* pgm = new osg::Program;
|
|
|
|
pgm->setName( "osgshader2 demo" );
|
|
|
|
|
|
|
|
pgm->addShader( new osg::Shader( osg::Shader::VERTEX, vertSource ) );
|
|
|
|
pgm->addShader( new osg::Shader( osg::Shader::FRAGMENT, fragSource ) );
|
|
|
|
|
|
|
|
#ifdef ENABLE_GEOMETRY_SHADER
|
|
|
|
pgm->addShader( new osg::Shader( osg::Shader::GEOMETRY, geomSource ) );
|
|
|
|
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_LINE_STRIP );
|
|
|
|
#endif
|
|
|
|
|
|
|
|
return pgm;
|
|
|
|
}
|
|
|
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
///////////////////////////////////////////////////////////////////////////
|
|
|
|
|
|
|
|
class SomePoints : public osg::Geometry
|
|
|
|
{
|
|
|
|
public:
|
|
|
|
SomePoints()
|
|
|
|
{
|
|
|
|
osg::Vec4Array* cAry = new osg::Vec4Array;
|
|
|
|
setColorArray( cAry );
|
|
|
|
setColorBinding( osg::Geometry::BIND_OVERALL );
|
|
|
|
cAry->push_back( osg::Vec4(1,1,1,1) );
|
|
|
|
|
|
|
|
osg::Vec3Array* vAry = new osg::Vec3Array;
|
|
|
|
setVertexArray( vAry );
|
|
|
|
vAry->push_back( osg::Vec3(0,0,0) );
|
|
|
|
vAry->push_back( osg::Vec3(0,1,0) );
|
|
|
|
vAry->push_back( osg::Vec3(1,0,0) );
|
|
|
|
vAry->push_back( osg::Vec3(1,1,0) );
|
|
|
|
vAry->push_back( osg::Vec3(0,0,1) );
|
|
|
|
vAry->push_back( osg::Vec3(0,1,1) );
|
|
|
|
vAry->push_back( osg::Vec3(1,0,1) );
|
|
|
|
vAry->push_back( osg::Vec3(1,1,1) );
|
|
|
|
|
|
|
|
addPrimitiveSet( new osg::DrawArrays( GL_POINTS, 0, vAry->size() ) );
|
|
|
|
|
|
|
|
osg::StateSet* sset = getOrCreateStateSet();
|
|
|
|
sset->setMode( GL_LIGHTING, osg::StateAttribute::OFF );
|
|
|
|
|
|
|
|
// if things go wrong, fall back to big points
|
|
|
|
osg::Point* p = new osg::Point;
|
|
|
|
p->setSize(6);
|
|
|
|
sset->setAttribute( p );
|
|
|
|
|
|
|
|
#ifdef ENABLE_GLSL
|
|
|
|
sset->setAttribute( createShader() );
|
|
|
|
|
|
|
|
// a generic cyclic animation value
|
|
|
|
osg::Uniform* u_anim1( new osg::Uniform( "u_anim1", 0.0f ) );
|
|
|
|
u_anim1->setUpdateCallback( new SineAnimation( 4, 0.5, 0.5 ) );
|
|
|
|
sset->addUniform( u_anim1 );
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
///////////////////////////////////////////////////////////////////////////
|
|
|
|
|
|
|
|
int main( int argc, char *argv[] )
|
|
|
|
{
|
|
|
|
osg::Geode* root( new osg::Geode );
|
|
|
|
root->addDrawable( new SomePoints );
|
|
|
|
|
|
|
|
osgViewer::Viewer viewer;
|
|
|
|
viewer.setSceneData( root );
|
|
|
|
return viewer.run();
|
|
|
|
}
|
|
|
|
|
|
|
|
// vim: set sw=4 ts=8 et ic ai:
|