From Mike Weiblen, updates to osgGL2 to support Uniform values

This commit is contained in:
Robert Osfield 2003-10-05 11:30:54 +00:00
parent 9d6bf8d1b6
commit ce15c880b1
17 changed files with 1350 additions and 319 deletions

View File

@ -31,6 +31,7 @@ PLUGIN_DIRS = \
dds\ dds\
dw\ dw\
flt\ flt\
gdal\
lib3ds\ lib3ds\
logo\ logo\
lwo\ lwo\

View File

@ -11,7 +11,7 @@
*/ */
/* file: examples/osgshaders/GL2Scene.cpp /* file: examples/osgshaders/GL2Scene.cpp
* author: Mike Weiblen 2003-07-14 * author: Mike Weiblen 2003-09-30
* *
* Compose a scene of several instances of a model, with a different * Compose a scene of several instances of a model, with a different
* OpenGL Shading Language shader applied to each. * OpenGL Shading Language shader applied to each.
@ -23,49 +23,159 @@
#include <osg/ShapeDrawable> #include <osg/ShapeDrawable>
#include <osg/PositionAttitudeTransform> #include <osg/PositionAttitudeTransform>
#include <osg/Geode> #include <osg/Geode>
#include <osg/Node>
#include <osg/Material>
#include <osg/Notify> #include <osg/Notify>
#include <osg/Vec3>
#include <osg/Texture1D>
#include <osg/Texture2D>
#include <osg/Texture3D>
#include <osgDB/ReadFile> #include <osgDB/ReadFile>
#include <osgDB/FileUtils> #include <osgDB/FileUtils>
#include <osgUtil/Optimizer> #include <osgUtil/Optimizer>
#include <osgGL2/ProgramObject> #include <osgGL2/ProgramObject>
#include "GL2Scene.h"
#include "Noise.h"
/////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////
// OpenGL Shading Language source code for the "microshader" example. ///////////////////////////////////////////////////////////////////////////
static osg::Image*
make3DNoiseImage(int texSize)
{
osg::Image* image = new osg::Image;
image->setImage(texSize, texSize, texSize,
4, GL_RGBA, GL_UNSIGNED_BYTE,
new unsigned char[4 * texSize * texSize * texSize],
osg::Image::USE_NEW_DELETE);
const int startFrequency = 4;
const int numOctaves = 4;
int f, i, j, k, inc;
double ni[3];
double inci, incj, inck;
int frequency = startFrequency;
GLubyte *ptr;
double amp = 0.5;
osg::notify(osg::INFO) << "creating 3D noise texture... ";
for (f = 0, inc = 0; f < numOctaves; ++f, frequency *= 2, ++inc, amp *= 0.5)
{
SetNoiseFrequency(frequency);
ptr = image->data();
ni[0] = ni[1] = ni[2] = 0;
inci = 1.0 / (texSize / frequency);
for (i = 0; i < texSize; ++i, ni[0] += inci)
{
incj = 1.0 / (texSize / frequency);
for (j = 0; j < texSize; ++j, ni[1] += incj)
{
inck = 1.0 / (texSize / frequency);
for (k = 0; k < texSize; ++k, ni[2] += inck, ptr += 4)
{
*(ptr+inc) = (GLubyte) (((noise3(ni) + 1.0) * amp) * 128.0);
}
}
}
}
osg::notify(osg::INFO) << "DONE" << std::endl;
return image;
}
static osg::Texture3D*
make3DNoiseTexture(int texSize )
{
osg::Texture3D* noiseTexture = new osg::Texture3D;
noiseTexture->setFilter(osg::Texture3D::MIN_FILTER, osg::Texture3D::LINEAR);
noiseTexture->setFilter(osg::Texture3D::MAG_FILTER, osg::Texture3D::LINEAR);
noiseTexture->setWrap(osg::Texture3D::WRAP_S, osg::Texture3D::REPEAT);
noiseTexture->setWrap(osg::Texture3D::WRAP_T, osg::Texture3D::REPEAT);
noiseTexture->setWrap(osg::Texture3D::WRAP_R, osg::Texture3D::REPEAT);
noiseTexture->setImage( make3DNoiseImage(texSize) );
return noiseTexture;
}
///////////////////////////////////////////////////////////////////////////
static osg::Image*
make1DSineImage( int texSize )
{
const float PI = 3.1415927;
osg::Image* image = new osg::Image;
image->setImage(texSize, 1, 1,
4, GL_RGBA, GL_UNSIGNED_BYTE,
new unsigned char[4 * texSize],
osg::Image::USE_NEW_DELETE);
GLubyte* ptr = image->data();
float inc = 2. * PI / (float)texSize;
for(int i = 0; i < texSize; i++)
{
*ptr++ = (GLubyte)((sinf(i * inc) * 0.5 + 0.5) * 255.);
*ptr++ = 0;
*ptr++ = 0;
*ptr++ = 1;
}
return image;
}
static osg::Texture1D*
make1DSineTexture( int texSize )
{
osg::Texture1D* sineTexture = new osg::Texture1D;
sineTexture->setWrap(osg::Texture1D::WRAP_S, osg::Texture1D::REPEAT);
sineTexture->setFilter(osg::Texture1D::MIN_FILTER, osg::Texture1D::LINEAR);
sineTexture->setFilter(osg::Texture1D::MAG_FILTER, osg::Texture1D::LINEAR);
sineTexture->setImage( make1DSineImage(texSize) );
return sineTexture;
}
///////////////////////////////////////////////////////////////////////////
static osg::Node* createGlobe()
{
osg::Geode* geode = new osg::Geode();
osg::StateSet* stateset = geode->getOrCreateStateSet();
osg::Texture2D* texture = new osg::Texture2D;
texture->setImage( osgDB::readImageFile("Images/land_shallow_topo_2048.jpg") );
stateset->setTextureAttributeAndModes(0, texture, osg::StateAttribute::ON);
geode->addDrawable(new osg::ShapeDrawable(new osg::Sphere(osg::Vec3(0,0,0), 2.0f)));
return geode;
}
///////////////////////////////////////////////////////////////////////////
// OpenGL Shading Language source code for the "microshader" example,
// which simply colors a fragment based on its location.
static const char *microshaderVertSource = { static const char *microshaderVertSource = {
"varying vec3 color;" "varying vec4 color;"
"void main(void)" "void main(void)"
"{" "{"
"color = gl_Vertex;"
"gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex;" "gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex;"
"color = gl_Vertex.zyx * 1.0;"
"}" "}"
}; };
static const char *microshaderFragSource = { static const char *microshaderFragSource = {
"varying vec3 color;" "varying vec4 color;"
"void main(void)" "void main(void)"
"{" "{"
"gl_FragColor = vec4(color, 1.0);" "gl_FragColor = color;"
"}" "}"
}; };
/////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////
static osg::Group* rootNode; static osg::ref_ptr<osg::Group> rootNode;
static osg::Node* masterModel;
// Add a reference to the masterModel at the specified translation, and
// return its StateSet so we can easily attach StateAttributes.
static osg::StateSet*
CloneMaster(float x, float y, float z )
{
osg::PositionAttitudeTransform* xform = new osg::PositionAttitudeTransform();
xform->setPosition(osg::Vec3(x, y, z));
xform->addChild(masterModel);
rootNode->addChild(xform);
return xform->getOrCreateStateSet();
}
// Create some geometry upon which to render GL2 shaders. // Create some geometry upon which to render GL2 shaders.
static osg::Geode* static osg::Geode*
@ -78,96 +188,231 @@ CreateModel()
return geode; return geode;
} }
// read vert & frag shader source code from a pair of files. // Add a reference to the masterModel at the specified translation, and
static void // return its StateSet so we can easily attach StateAttributes.
LoadShaderSource( osgGL2::ProgramObject* progObj, std::string baseFileName ) static osg::StateSet*
ModelInstance()
{ {
std::string vertFileName = osgDB::findDataFile(baseFileName + ".vert"); static float zvalue = 0.0f;
if( vertFileName.length() != 0 ) static osg::Node* masterModel = CreateModel();
{
osgGL2::ShaderObject* vertObj = new osgGL2::ShaderObject( osgGL2::ShaderObject::VERTEX );
vertObj->loadShaderSourceFromFile( vertFileName.c_str() );
progObj->addShader( vertObj );
}
else
{
osg::notify(osg::WARN) << "Warning: file \"" << baseFileName+".vert" << "\" not found." << std::endl;
}
std::string fragFileName = osgDB::findDataFile(baseFileName + ".frag"); osg::PositionAttitudeTransform* xform = new osg::PositionAttitudeTransform();
if( fragFileName.length() != 0 ) xform->setPosition(osg::Vec3( 0.0f, -1.0f, zvalue ));
zvalue = zvalue + 2.2f;
xform->addChild(masterModel);
rootNode->addChild(xform);
return xform->getOrCreateStateSet();
}
// load source from a file.
static void
LoadShaderSource( osgGL2::ShaderObject* obj, const std::string& fileName )
{
std::string fqFileName = osgDB::findDataFile(fileName);
if( fqFileName.length() != 0 )
{ {
osgGL2::ShaderObject* fragObj = new osgGL2::ShaderObject( osgGL2::ShaderObject::FRAGMENT ); obj->loadShaderSourceFromFile( fqFileName.c_str() );
fragObj->loadShaderSourceFromFile( fragFileName.c_str() );
progObj->addShader( fragObj );
} }
else else
{ {
osg::notify(osg::WARN) << "Warning: file \"" << baseFileName+".frag" << "\" not found." << std::endl; osg::notify(osg::WARN) << "File \"" << fileName << "\" not found." << std::endl;
} }
} }
///////////////////////////////////////////////////////////////////////////
// rude but convenient globals
static osgGL2::ProgramObject* BlockyProgObj;
static osgGL2::ShaderObject* BlockyVertObj;
static osgGL2::ShaderObject* BlockyFragObj;
static osgGL2::ProgramObject* ErodedProgObj;
static osgGL2::ShaderObject* ErodedVertObj;
static osgGL2::ShaderObject* ErodedFragObj;
static osgGL2::ProgramObject* MarbleProgObj;
static osgGL2::ShaderObject* MarbleVertObj;
static osgGL2::ShaderObject* MarbleFragObj;
///////////////////////////////////////////////////////////////////////////
// TODO encapsulate inside an osgFX effect.
class AnimateCallback: public osg::NodeCallback
{
public:
AnimateCallback( osgGL2::ProgramObject* progObj ) :
osg::NodeCallback(),
_enabled(true)
{}
virtual void operator() ( osg::Node* node, osg::NodeVisitor* nv )
{
if( _enabled )
{
float angle = 2.0 * nv->getFrameStamp()->getReferenceTime();
float sine = sinf( angle ); // -1 -> 1
float v01 = 0.5f * sine + 0.5f; // 0 -> 1
float v10 = 1.0f - v01; // 1 -> 0
ErodedProgObj->setUniform( "Offset", osg::Vec3(0.505f, 0.8f*v01, 0.0f) );
MarbleProgObj->setUniform( "Offset", osg::Vec3(0.505f, 0.8f*v01, 0.0f) );
BlockyProgObj->setUniform( "Sine", sine );
BlockyProgObj->setUniform( "Color1", osg::Vec3(v10, 0.0f, 0.0f) );
BlockyProgObj->setUniform( "Color2", osg::Vec3(v01, v01, v10) );
}
traverse(node, nv);
}
private:
bool _enabled;
};
/////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////
// Compose a scenegraph with examples of GL2 shaders // Compose a scenegraph with examples of GL2 shaders
#define ZGRID 2.2 osg::ref_ptr<osg::Group>
GL2Scene::buildScene()
osg::Node*
GL2Scene()
{ {
osg::StateSet* ss; osg::Texture3D* noiseTexture = make3DNoiseTexture( 32 /*128*/ );
osgGL2::ProgramObject* progObj; osg::Texture1D* sineTexture = make1DSineTexture( 32 /*1024*/ );
// the rootNode of our created graph. // the root of our scenegraph.
rootNode = new osg::Group; // attach an "empty" ProgramObject to the rootNode, which will act as
ss = rootNode->getOrCreateStateSet(); // the default StateAttribute. An empty ProgramObject (ie without any
// attached ShaderObjects) is a special case, which means to use the
// attach an "empty" ProgramObject to the rootNode as a default
// StateAttribute. An empty ProgramObject (ie without any attached
// ShaderObjects) is a special case, which means to use the
// OpenGL 1.x "fixed functionality" rendering pipeline. // OpenGL 1.x "fixed functionality" rendering pipeline.
progObj = new osgGL2::ProgramObject; rootNode = new osg::Group;
ss->setAttributeAndModes(progObj, osg::StateAttribute::ON); rootNode->setUpdateCallback( new AnimateCallback(0) );
{
// TODO this definition of a "default ProgramObject state" will not
// be necessary when the OSG core has proper support for the unique
// requirements of ProgramObject.
osg::StateSet* ss = rootNode->getOrCreateStateSet();
osgGL2::ProgramObject* progObj = new osgGL2::ProgramObject;
_progObjList.push_back( progObj );
ss->setAttributeAndModes(progObj, osg::StateAttribute::ON);
}
// put the unadorned masterModel at the origin for comparison. // the simple Microshader (its source appears earlier in this file)
masterModel = CreateModel(); {
rootNode->addChild(masterModel); osg::StateSet* ss = ModelInstance();
osgGL2::ProgramObject* progObj = new osgGL2::ProgramObject;
_progObjList.push_back( progObj );
progObj->addShader( new osgGL2::ShaderObject(
osgGL2::ShaderObject::VERTEX, microshaderVertSource ) );
progObj->addShader( new osgGL2::ShaderObject(
osgGL2::ShaderObject::FRAGMENT, microshaderFragSource ) );
ss->setAttributeAndModes( progObj, osg::StateAttribute::ON );
}
// the "blocky" shader, a simple animation test
{
osg::StateSet* ss = ModelInstance();
BlockyProgObj = new osgGL2::ProgramObject;
_progObjList.push_back( BlockyProgObj );
BlockyVertObj = new osgGL2::ShaderObject( osgGL2::ShaderObject::VERTEX );
BlockyFragObj = new osgGL2::ShaderObject( osgGL2::ShaderObject::FRAGMENT );
BlockyProgObj->addShader( BlockyFragObj );
BlockyProgObj->addShader( BlockyVertObj );
ss->setAttributeAndModes(BlockyProgObj, osg::StateAttribute::ON);
}
// the "eroded" shader, uses a noise texture to discard fragments
{
osg::StateSet* ss = ModelInstance();
ss->setTextureAttributeAndModes(6, noiseTexture, osg::StateAttribute::ON);
ErodedProgObj = new osgGL2::ProgramObject;
_progObjList.push_back( ErodedProgObj );
ErodedVertObj = new osgGL2::ShaderObject( osgGL2::ShaderObject::VERTEX );
ErodedFragObj = new osgGL2::ShaderObject( osgGL2::ShaderObject::FRAGMENT );
ErodedProgObj->addShader( ErodedFragObj );
ErodedProgObj->addShader( ErodedVertObj );
ss->setAttributeAndModes(ErodedProgObj, osg::StateAttribute::ON);
}
// the "marble" shader, uses two textures
{
osg::StateSet* ss = ModelInstance();
ss->setTextureAttributeAndModes(1, noiseTexture, osg::StateAttribute::ON);
ss->setTextureAttributeAndModes(2, sineTexture, osg::StateAttribute::ON);
MarbleProgObj = new osgGL2::ProgramObject;
_progObjList.push_back( MarbleProgObj );
MarbleVertObj = new osgGL2::ShaderObject( osgGL2::ShaderObject::VERTEX );
MarbleFragObj = new osgGL2::ShaderObject( osgGL2::ShaderObject::FRAGMENT );
MarbleProgObj->addShader( MarbleFragObj );
MarbleProgObj->addShader( MarbleVertObj );
ss->setAttributeAndModes(MarbleProgObj, osg::StateAttribute::ON);
}
// regular GL 1.x texturing for comparison.
if( 0 ) {
osg::StateSet* ss = ModelInstance();
osg::Texture2D* tex0 = new osg::Texture2D;
tex0->setImage( osgDB::readImageFile( "images/3dl-ge100.png" ) );
ss->setTextureAttributeAndModes(0, tex0, osg::StateAttribute::ON);
}
reloadShaderSource();
// add logo overlays // add logo overlays
//rootNode->addChild( osgDB::readNodeFile( "3dl_ogl.logo" ) ); // rootNode->addChild( osgDB::readNodeFile( "3dl_ogl.logo" ) );
//
// create references to the masterModel and attach shaders
//
// apply the simple microshader example
// (the shader sources are hardcoded above in this .cpp file)
ss = CloneMaster(0,0,ZGRID*1);
progObj = new osgGL2::ProgramObject;
progObj->addShader( new osgGL2::ShaderObject( osgGL2::ShaderObject::VERTEX, microshaderVertSource ) );
progObj->addShader( new osgGL2::ShaderObject( osgGL2::ShaderObject::FRAGMENT, microshaderFragSource ) );
ss->setAttributeAndModes(progObj, osg::StateAttribute::ON);
// load the "specular brick" shader from a pair of source files.
ss = CloneMaster(0,0,ZGRID*2);
progObj = new osgGL2::ProgramObject;
LoadShaderSource( progObj, "shaders/brick" );
ss->setAttributeAndModes(progObj, osg::StateAttribute::ON);
// load the "gold screen" shader from a pair of source files.
ss = CloneMaster(0,0,ZGRID*3);
progObj = new osgGL2::ProgramObject;
LoadShaderSource( progObj, "shaders/screen" );
ss->setAttributeAndModes(progObj, osg::StateAttribute::ON);
return rootNode; return rootNode;
} }
///////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////
void GL2Scene::GL2Scene()
GL2Update()
{ {
/* TODO : update uniform values for shader animation */ _rootNode = buildScene();
_shadersEnabled = true;
}
GL2Scene::~GL2Scene()
{
}
// mew 2003-09-19 : This way of configuring the shaders is temporary,
// pending a move to an osgFX-based approach.
void
GL2Scene::reloadShaderSource()
{
osg::notify(osg::WARN) << "reloadShaderSource()" << std::endl;
LoadShaderSource( BlockyVertObj, "shaders/blocky.vert" );
LoadShaderSource( BlockyFragObj, "shaders/blocky.frag" );
LoadShaderSource( ErodedVertObj, "shaders/eroded.vert" );
LoadShaderSource( ErodedFragObj, "shaders/eroded.frag" );
ErodedProgObj->setUniform( "LightPosition", osg::Vec3(0.0f, 0.0f, 4.0f) );
ErodedProgObj->setUniform( "Scale", 1.0f );
ErodedProgObj->setUniform( "sampler3d", 6 );
LoadShaderSource( MarbleVertObj, "shaders/marble.vert" );
LoadShaderSource( MarbleFragObj, "shaders/marble.frag" );
MarbleProgObj->setUniform( "Noise", 1 );
MarbleProgObj->setUniform( "Sine", 2 );
}
// mew 2003-09-19 : TODO Need to revisit how to better control
// osgGL2::ProgramObject enable state in OSG core. glProgramObjects are
// different enough from other GL state that StateSet::setAttributeAndModes()
// doesn't fit well, so came up with a local implementation.
void
GL2Scene::toggleShaderEnable()
{
_shadersEnabled = ! _shadersEnabled;
osg::notify(osg::WARN) << "shader enable = " <<
((_shadersEnabled) ? "ON" : "OFF") << std::endl;
for( unsigned int i = 0; i < _progObjList.size(); i++ )
{
_progObjList[i]->enable( _shadersEnabled );
}
} }
/*EOF*/ /*EOF*/

View File

@ -0,0 +1,50 @@
/* -*-c++-*- OpenSceneGraph - Copyright (C) 1998-2003 Robert Osfield
* Copyright (C) 2003 3Dlabs Inc. Ltd.
*
* This application is open source and may be redistributed and/or modified
* freely and without restriction, both in commericial and non commericial applications,
* as long as this copyright notice is maintained.
*
* This application is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
*/
/* file: examples/osgshaders/GL2Scene.h
* author: Mike Weiblen 2003-09-18
*
* See http://www.3dlabs.com/opengl2/ for more information regarding
* the OpenGL Shading Language.
*/
#include <osg/Node>
#include <osg/Referenced>
#include <osg/ref_ptr>
#include <osgGL2/ProgramObject>
class GL2Scene : public osg::Referenced
{
public:
GL2Scene();
osg::ref_ptr<osg::Group> getRootNode() { return _rootNode; }
void reloadShaderSource();
void toggleShaderEnable();
protected:
~GL2Scene();
private: /*methods*/
osg::ref_ptr<osg::Group> buildScene();
private: /*data*/
osg::ref_ptr<osg::Group> _rootNode;
std::vector<osgGL2::ProgramObjectPtr> _progObjList;
bool _shadersEnabled;
};
typedef osg::ref_ptr<GL2Scene> GL2ScenePtr;
/*EOF*/

View File

@ -3,6 +3,7 @@ include $(TOPDIR)/Make/makedefs
CXXFILES =\ CXXFILES =\
GL2Scene.cpp \ GL2Scene.cpp \
Noise.cpp \
osgshaders.cpp osgshaders.cpp
LIBS += -losgProducer -lProducer -losgText -losgGL2 -losgGA -losgDB -losgUtil -losg $(GL_LIBS) $(X_LIBS) $(OTHER_LIBS) LIBS += -losgProducer -lProducer -losgText -losgGL2 -losgGA -losgDB -losgUtil -losg $(GL_LIBS) $(X_LIBS) $(OTHER_LIBS)

View File

@ -0,0 +1,269 @@
/************************************************************************
* *
* Copyright (C) 2002 3Dlabs Inc. Ltd. *
* *
/************************************************************************/
#include <math.h>
#include <stdlib.h>
/* Coherent noise function over 1, 2 or 3 dimensions */
/* (copyright Ken Perlin) */
#define MAXB 0x100
#define N 0x1000
#define NP 12 /* 2^N */
#define NM 0xfff
#define s_curve(t) ( t * t * (3. - 2. * t) )
#define lerp(t, a, b) ( a + t * (b - a) )
#define setup(i,b0,b1,r0,r1)\
t = vec[i] + N;\
b0 = ((int)t) & BM;\
b1 = (b0+1) & BM;\
r0 = t - (int)t;\
r1 = r0 - 1.;
#define at2(rx,ry) ( rx * q[0] + ry * q[1] )
#define at3(rx,ry,rz) ( rx * q[0] + ry * q[1] + rz * q[2] )
static void initNoise(void);
static int p[MAXB + MAXB + 2];
static double g3[MAXB + MAXB + 2][3];
static double g2[MAXB + MAXB + 2][2];
static double g1[MAXB + MAXB + 2];
int start;
int B;
int BM;
void SetNoiseFrequency(int frequency)
{
start = 1;
B = frequency;
BM = B-1;
}
double noise1(double arg)
{
int bx0, bx1;
double rx0, rx1, sx, t, u, v, vec[1];
vec[0] = arg;
if (start) {
start = 0;
initNoise();
}
setup(0,bx0,bx1,rx0,rx1);
sx = s_curve(rx0);
u = rx0 * g1[ p[ bx0 ] ];
v = rx1 * g1[ p[ bx1 ] ];
return(lerp(sx, u, v));
}
double noise2(double vec[2])
{
int bx0, bx1, by0, by1, b00, b10, b01, b11;
double rx0, rx1, ry0, ry1, *q, sx, sy, a, b, t, u, v;
int i, j;
if (start) {
start = 0;
initNoise();
}
setup(0, bx0,bx1, rx0,rx1);
setup(1, by0,by1, ry0,ry1);
i = p[ bx0 ];
j = p[ bx1 ];
b00 = p[ i + by0 ];
b10 = p[ j + by0 ];
b01 = p[ i + by1 ];
b11 = p[ j + by1 ];
sx = s_curve(rx0);
sy = s_curve(ry0);
q = g2[ b00 ] ; u = at2(rx0,ry0);
q = g2[ b10 ] ; v = at2(rx1,ry0);
a = lerp(sx, u, v);
q = g2[ b01 ] ; u = at2(rx0,ry1);
q = g2[ b11 ] ; v = at2(rx1,ry1);
b = lerp(sx, u, v);
return lerp(sy, a, b);
}
double noise3(double vec[3])
{
int bx0, bx1, by0, by1, bz0, bz1, b00, b10, b01, b11;
double rx0, rx1, ry0, ry1, rz0, rz1, *q, sy, sz, a, b, c, d, t, u, v;
int i, j;
if (start) {
start = 0;
initNoise();
}
setup(0, bx0,bx1, rx0,rx1);
setup(1, by0,by1, ry0,ry1);
setup(2, bz0,bz1, rz0,rz1);
i = p[ bx0 ];
j = p[ bx1 ];
b00 = p[ i + by0 ];
b10 = p[ j + by0 ];
b01 = p[ i + by1 ];
b11 = p[ j + by1 ];
t = s_curve(rx0);
sy = s_curve(ry0);
sz = s_curve(rz0);
q = g3[ b00 + bz0 ] ; u = at3(rx0,ry0,rz0);
q = g3[ b10 + bz0 ] ; v = at3(rx1,ry0,rz0);
a = lerp(t, u, v);
q = g3[ b01 + bz0 ] ; u = at3(rx0,ry1,rz0);
q = g3[ b11 + bz0 ] ; v = at3(rx1,ry1,rz0);
b = lerp(t, u, v);
c = lerp(sy, a, b);
q = g3[ b00 + bz1 ] ; u = at3(rx0,ry0,rz1);
q = g3[ b10 + bz1 ] ; v = at3(rx1,ry0,rz1);
a = lerp(t, u, v);
q = g3[ b01 + bz1 ] ; u = at3(rx0,ry1,rz1);
q = g3[ b11 + bz1 ] ; v = at3(rx1,ry1,rz1);
b = lerp(t, u, v);
d = lerp(sy, a, b);
//fprintf(stderr, "%f\n", lerp(sz, c, d));
return lerp(sz, c, d);
}
void normalize2(double v[2])
{
double s;
s = sqrt(v[0] * v[0] + v[1] * v[1]);
v[0] = v[0] / s;
v[1] = v[1] / s;
}
void normalize3(double v[3])
{
double s;
s = sqrt(v[0] * v[0] + v[1] * v[1] + v[2] * v[2]);
v[0] = v[0] / s;
v[1] = v[1] / s;
v[2] = v[2] / s;
}
void initNoise(void)
{
int i, j, k;
srand(30757);
for (i = 0 ; i < B ; i++) {
p[i] = i;
g1[i] = (double)((rand() % (B + B)) - B) / B;
for (j = 0 ; j < 2 ; j++)
g2[i][j] = (double)((rand() % (B + B)) - B) / B;
normalize2(g2[i]);
for (j = 0 ; j < 3 ; j++)
g3[i][j] = (double)((rand() % (B + B)) - B) / B;
normalize3(g3[i]);
}
while (--i) {
k = p[i];
p[i] = p[j = rand() % B];
p[j] = k;
}
for (i = 0 ; i < B + 2 ; i++) {
p[B + i] = p[i];
g1[B + i] = g1[i];
for (j = 0 ; j < 2 ; j++)
g2[B + i][j] = g2[i][j];
for (j = 0 ; j < 3 ; j++)
g3[B + i][j] = g3[i][j];
}
}
/* --- My harmonic summing functions - PDB --------------------------*/
/*
In what follows "alpha" is the weight when the sum is formed.
Typically it is 2, As this approaches 1 the function is noisier.
"beta" is the harmonic scaling/spacing, typically 2.
*/
double PerlinNoise1D(double x,double alpha,double beta,int n)
{
int i;
double val,sum = 0;
double p,scale = 1;
p = x;
for (i=0;i<n;i++) {
val = noise1(p);
sum += val / scale;
scale *= alpha;
p *= beta;
}
return(sum);
}
double PerlinNoise2D(double x,double y,double alpha,double beta,int n)
{
int i;
double val,sum = 0;
double p[2],scale = 1;
p[0] = x;
p[1] = y;
for (i=0;i<n;i++) {
val = noise2(p);
sum += val / scale;
scale *= alpha;
p[0] *= beta;
p[1] *= beta;
}
return(sum);
}
double PerlinNoise3D(double x,double y,double z,double alpha,double beta,int n)
{
int i;
double val,sum = 0;
double p[3],scale = 1;
p[0] = x;
p[1] = y;
p[2] = z;
for (i=0;i<n;i++) {
val = noise3(p);
sum += val / scale;
scale *= alpha;
p[0] *= beta;
p[1] *= beta;
p[2] *= beta;
}
return(sum);
}

View File

@ -0,0 +1,30 @@
/************************************************************************
* *
* Copyright (C) 2002 3Dlabs Inc. Ltd. *
* *
***********************************************************************/
#ifndef __ogl2_demo_h__
#define __ogl2_demo_h__
extern void SetNoiseFrequency(int frequency);
extern double noise1(double arg);
extern double noise2(double vec[2]);
extern double noise3(double vec[3]);
extern void normalize2(double vec[2]);
extern void normalize3(double vec[3]);
/*
In what follows "alpha" is the weight when the sum is formed.
Typically it is 2, As this approaches 1 the function is noisier.
"beta" is the harmonic scaling/spacing, typically 2.
*/
extern double PerlinNoise1D(double x,double alpha, double beta, int n);
extern double PerlinNoise2D(double x,double y,double alpha, double beta, int n);
extern double PerlinNoise3D(double x,double y,double z,double alpha, double beta, int n);
#endif // __ogl2_demo_h__

View File

@ -0,0 +1,50 @@
osgshaders/README.txt - mike.weiblen@3dlabs.com - 2003-09-30
Copyright 2003 3Dlabs Inc.
osgshaders is a simple demo of the OpenGL Shading Language, as supported in the
Open Scene Graph using the "osgGL2" library.
Demonstrated are:
- loading, compiling and linking OpenGL Shading Language (OGLSL) shaders.
- multicontext support (use different Producer configurations to create
multiple windows)
- "uniform" variable support: enables an application to set parameters for
shaders at runtime for animation, etc.
- multi-texture support: using textures both as applied imagery and as lookup
tables for controlling shader behavior.
The two screen grabs show the demo at the extremes of a periodic animation
parameter.
WHAT's ON THE SCREEN?
1st row: the Marble shader, consisting of white marble with green veins.
The veins are animated to slosh back and forth, and look somewhat like
bands of stormclouds on Jupiter.
2nd row: the Eroded shader, which demonstrates the OGLSL "discard" command.
The animation erodes the surface of the objects based on a noise texture,
for an effect similar to rusting.
3rd row: the Blocky shader, which demonstrates animated scaling in the vertex
shader, as well as color animation using uniform variables set by the app.
4th row: the Microshader, an extremely simple shader which colors fragments
based on their position. It's small codesize makes it convenient to hardcode
directly into the application source.
RUNTIME KEY COMMANDS
These key commands are included in the onscreen help (as displayed by pressing
the "h" key):
x - Reload and recompile shader source code from their files.
You may edit the shader source code file, and recompile the shaders
while the application runs.
y - toggle shader enable.
#EOF

View File

@ -11,113 +11,108 @@
*/ */
/* file: examples/osgshaders/osgshaders.cpp /* file: examples/osgshaders/osgshaders.cpp
* author: Mike Weiblen 2003-07-14 * author: Mike Weiblen 2003-09-18
* *
* A simple app skeleton for viewing OpenGL Shading Language shaders; * A demo of the OpenGL Shading Language shaders using osgGL2.
* derived from osgviewer.cpp from OSG 0.9.4-2
* *
* See http://www.3dlabs.com/opengl2/ for more information regarding * See http://www.3dlabs.com/opengl2/ for more information regarding
* the OpenGL Shading Language. * the OpenGL Shading Language.
*/ */
#include <osg/Notify>
#include <osgGA/GUIEventAdapter>
#include <osgGA/GUIActionAdapter>
#include <osgDB/ReadFile> #include <osgDB/ReadFile>
#include <osgUtil/Optimizer> #include <osgUtil/Optimizer>
#include <osgProducer/Viewer> #include <osgProducer/Viewer>
#include <osgGL2/Version>
#define GL2SCENE #include "GL2Scene.h"
osg::Node* GL2Scene();
void GL2Update(); using namespace osg;
///////////////////////////////////////////////////////////////////////////
class KeyHandler: public osgGA::GUIEventHandler
{
public:
KeyHandler( GL2ScenePtr gl2Scene ) :
_gl2Scene(gl2Scene)
{}
bool handle( const osgGA::GUIEventAdapter& ea, osgGA::GUIActionAdapter& )
{
if( ea.getEventType() != osgGA::GUIEventAdapter::KEYDOWN )
return false;
switch( ea.getKey() )
{
case 'x':
_gl2Scene->reloadShaderSource();
return true;
case 'y':
_gl2Scene->toggleShaderEnable();
return true;
}
return false;
}
private:
GL2ScenePtr _gl2Scene;
};
///////////////////////////////////////////////////////////////////////////
int main( int argc, char **argv ) int main( int argc, char **argv )
{ {
// use an ArgumentParser object to manage the program arguments. // use an ArgumentParser object to manage the program arguments.
osg::ArgumentParser arguments(&argc,argv); ArgumentParser args(&argc,argv);
// set up the usage document, in case we need to print out how to use this program.
arguments.getApplicationUsage()->setApplicationName(arguments.getApplicationName());
arguments.getApplicationUsage()->setDescription(arguments.getApplicationName()+" is the standard OpenSceneGraph example which loads and visualises 3d models.");
arguments.getApplicationUsage()->setCommandLineUsage(arguments.getApplicationName()+" [options] filename ...");
arguments.getApplicationUsage()->addCommandLineOption("-h or --help","Display this information");
// set up the usage document
args.getApplicationUsage()->setApplicationName(args.getApplicationName());
args.getApplicationUsage()->setDescription(args.getApplicationName() +
" demonstrates the OpenGL Shading Language using osgGL2");
args.getApplicationUsage()->setCommandLineUsage(args.getApplicationName());
args.getApplicationUsage()->addCommandLineOption("-h or --help","Display this information");
args.getApplicationUsage()->addKeyboardMouseBinding( "x", "Reload and recompile shader source files." );
args.getApplicationUsage()->addKeyboardMouseBinding( "y", "Toggle shader enable" );
// construct the viewer. // construct the viewer.
osgProducer::Viewer viewer(arguments); osgProducer::Viewer viewer(args);
viewer.setUpViewer( osgProducer::Viewer::STANDARD_SETTINGS );
viewer.getUsage( *args.getApplicationUsage() );
// set up the value with sensible default event handlers. if( args.read("-h") || args.read("--help") )
viewer.setUpViewer(osgProducer::Viewer::STANDARD_SETTINGS);
// get details on keyboard and mouse bindings used by the viewer.
viewer.getUsage(*arguments.getApplicationUsage());
// if user request help write it out to cout.
if (arguments.read("-h") || arguments.read("--help"))
{ {
arguments.getApplicationUsage()->write(std::cout); args.getApplicationUsage()->write(std::cout);
return 1; return 1;
} }
// any option left unread are converted into errors to write out later. // any option left unread are converted into errors to write out later.
arguments.reportRemainingOptionsAsUnrecognized(); args.reportRemainingOptionsAsUnrecognized();
if( args.errors() )
// report any errors if they have occured when parsing the program aguments.
if (arguments.errors())
{ {
arguments.writeErrorMessages(std::cout); args.writeErrorMessages(std::cout);
return 1;
}
#ifdef GL2SCENE //(
osg::ref_ptr<osg::Node> loadedModel = GL2Scene();
#else //)(
if (arguments.argc()<=1)
{
arguments.getApplicationUsage()->write(std::cout,osg::ApplicationUsage::COMMAND_LINE_OPTION);
return 1; return 1;
} }
// read the scene from the list of file specified commandline args. // create the scene
osg::ref_ptr<osg::Node> loadedModel = osgDB::readNodeFiles(arguments); notify(NOTICE) << "osgGL2 version " << osgGL2GetVersion() << std::endl;
GL2ScenePtr gl2Scene = new GL2Scene;
// if no model has been successfully loaded report failure. viewer.setSceneData( gl2Scene->getRootNode().get() );
if (!loadedModel) viewer.getEventHandlerList().push_front( new KeyHandler(gl2Scene) );
{
std::cout << arguments.getApplicationName() <<": No data loaded" << std::endl;
return 1;
}
// optimize the scene graph, remove rendundent nodes and state etc.
osgUtil::Optimizer optimizer;
optimizer.optimize(loadedModel.get());
#endif //)
// set the scene to render
viewer.setSceneData(loadedModel.get());
// create the windows and run the threads.
viewer.realize(); viewer.realize();
while( !viewer.done() ) while( !viewer.done() )
{ {
// wait for all cull and draw threads to complete.
viewer.sync(); viewer.sync();
// update the scene by traversing it with the the update visitor which will
// call all node update callbacks and animations.
viewer.update(); viewer.update();
#ifdef GL2SCENE //(
GL2Update();
#endif //)
// fire off the cull and draw traversals of the scene.
viewer.frame(); viewer.frame();
} }
// wait for all cull and draw threads to complete before exit.
viewer.sync(); viewer.sync();
return 0; return 0;
} }
/*EOF*/

View File

@ -11,7 +11,7 @@
*/ */
/* file: include/osgGL2/Extensions /* file: include/osgGL2/Extensions
* author: Mike Weiblen 2003-07-14 * author: Mike Weiblen 2003-09-12
* *
* See http://www.3dlabs.com/opengl2/ for more information regarding * See http://www.3dlabs.com/opengl2/ for more information regarding
* the OpenGL Shading Language. * the OpenGL Shading Language.
@ -152,17 +152,17 @@ class OSGGL2_EXPORT Extensions : public osg::Referenced
void glUniform2i(GLint location, GLint v0, GLint v1) const; void glUniform2i(GLint location, GLint v0, GLint v1) const;
void glUniform3i(GLint location, GLint v0, GLint v1, GLint v2) const; void glUniform3i(GLint location, GLint v0, GLint v1, GLint v2) const;
void glUniform4i(GLint location, GLint v0, GLint v1, GLint v2, GLint v3) const; void glUniform4i(GLint location, GLint v0, GLint v1, GLint v2, GLint v3) const;
void glUniform1fv(GLint location, GLsizei count, GLfloat *value) const; void glUniform1fv(GLint location, GLsizei count, const GLfloat *value) const;
void glUniform2fv(GLint location, GLsizei count, GLfloat *value) const; void glUniform2fv(GLint location, GLsizei count, const GLfloat *value) const;
void glUniform3fv(GLint location, GLsizei count, GLfloat *value) const; void glUniform3fv(GLint location, GLsizei count, const GLfloat *value) const;
void glUniform4fv(GLint location, GLsizei count, GLfloat *value) const; void glUniform4fv(GLint location, GLsizei count, const GLfloat *value) const;
void glUniform1iv(GLint location, GLsizei count, GLint *value) const; void glUniform1iv(GLint location, GLsizei count, const GLint *value) const;
void glUniform2iv(GLint location, GLsizei count, GLint *value) const; void glUniform2iv(GLint location, GLsizei count, const GLint *value) const;
void glUniform3iv(GLint location, GLsizei count, GLint *value) const; void glUniform3iv(GLint location, GLsizei count, const GLint *value) const;
void glUniform4iv(GLint location, GLsizei count, GLint *value) const; void glUniform4iv(GLint location, GLsizei count, const GLint *value) const;
void glUniformMatrix2fv(GLint location, GLsizei count, GLboolean transpose, GLfloat *value) const; void glUniformMatrix2fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value) const;
void glUniformMatrix3fv(GLint location, GLsizei count, GLboolean transpose, GLfloat *value) const; void glUniformMatrix3fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value) const;
void glUniformMatrix4fv(GLint location, GLsizei count, GLboolean transpose, GLfloat *value) const; void glUniformMatrix4fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value) const;
GLint glGetUniformLocation(GLhandleARB programObject, const GLcharARB *name) const; GLint glGetUniformLocation(GLhandleARB programObject, const GLcharARB *name) const;
GLint glGetAttribLocation(GLhandleARB programObj, const GLcharARB *name) const; GLint glGetAttribLocation(GLhandleARB programObj, const GLcharARB *name) const;
void glGetActiveUniform(GLhandleARB programObj, GLuint index, GLsizei maxLength, GLsizei *length, GLint *size, GLint *type, GLcharARB *name) const; void glGetActiveUniform(GLhandleARB programObj, GLuint index, GLsizei maxLength, GLsizei *length, GLint *size, GLint *type, GLcharARB *name) const;

View File

@ -11,7 +11,7 @@
*/ */
/* file: include/osgGL2/ProgramObject /* file: include/osgGL2/ProgramObject
* author: Mike Weiblen 2003-07-14 * author: Mike Weiblen 2003-09-18
* *
* See http://www.3dlabs.com/opengl2/ for more information regarding * See http://www.3dlabs.com/opengl2/ for more information regarding
* the OpenGL Shading Language. * the OpenGL Shading Language.
@ -25,26 +25,32 @@
#include <osg/StateAttribute> #include <osg/StateAttribute>
#include <osg/buffered_value> #include <osg/buffered_value>
#include <osg/ref_ptr> #include <osg/ref_ptr>
#include <osg/Vec2>
#include <osg/Vec3>
#include <osg/Vec4>
#include <osgGL2/Export> #include <osgGL2/Export>
#include <osgGL2/Extensions> #include <osgGL2/Extensions>
#include <osgGL2/UniformValue>
#include <string> #include <string>
#include <vector>
namespace osgGL2 { namespace osgGL2 {
class ProgramObject;
typedef osg::ref_ptr<ProgramObject> ProgramObjectPtr;
///////////////////////////////////////////////////////////////////////////
class ShaderObject; class ShaderObject;
typedef osg::ref_ptr<ShaderObject> ShaderObjectPtr;
///////////////////////////////////////////////////////////////////////////
/** Encapsulates the OpenGL Shading Language ProgramObject */ /** Encapsulates the OpenGL Shading Language ProgramObject */
class OSGGL2_EXPORT ProgramObject : public osg::StateAttribute class OSGGL2_EXPORT ProgramObject : public osg::StateAttribute
{ {
public: public:
ProgramObject(); ProgramObject();
/** Copy constructor using CopyOp to manage deep vs shallow copy.*/ /** Copy constructor using CopyOp to manage deep vs shallow copy.*/
@ -74,10 +80,29 @@ class OSGGL2_EXPORT ProgramObject : public osg::StateAttribute
// data access methods. // data access methods.
/** Force a relink on next apply() of associated glProgramObject. */ /** Force a relink on next apply() of associated glProgramObject. */
void dirtyProgramObject(); void dirtyProgramObject();
void addShader( ShaderObject* shader ); /** Force a recompile of all ShaderObjects on next apply(). */
void dirtyShaderObjects();
/** Set whether rendering of ProgramObject is enabled or disabled */
void enable( bool enabled ) { _enabled = enabled; }
/** Attach a ShaderObject to this ProgramObject */
void addShader( ShaderObject* shadObj );
void setUniform( const char* uniformName, int value );
void setUniform( const char* uniformName, float value );
void setUniform( const char* uniformName, osg::Vec2 value );
void setUniform( const char* uniformName, osg::Vec3 value );
void setUniform( const char* uniformName, osg::Vec4 value );
inline void setSampler( const char* uniformName, int value )
{
// emphatic alias for setUniform(int)
setUniform( uniformName, static_cast<int>(value) );
}
/** use deleteObject instead of glDeleteObject to allow /** use deleteObject instead of glDeleteObject to allow
* GL2 Objects to cached until they can be deleted * GL2 Objects to cached until they can be deleted
@ -89,50 +114,52 @@ class OSGGL2_EXPORT ProgramObject : public osg::StateAttribute
* in the OpenGL context related to contextID.*/ * in the OpenGL context related to contextID.*/
static void flushDeletedGL2Objects(unsigned int contextID,double currentTime, double& availableTime); static void flushDeletedGL2Objects(unsigned int contextID,double currentTime, double& availableTime);
protected: protected:
class PerContextProgObj : public osg::Referenced
virtual ~ProgramObject();
typedef std::vector< osg::ref_ptr<ShaderObject> > ShaderObjectList;
ShaderObjectList _shaderObjectList;
class OSGGL2_EXPORT PerContextProgObj : public osg::Referenced
{ {
public: public:
PerContextProgObj(const ProgramObject* parent, Extensions* extensions); PerContextProgObj(const ProgramObject* progObj, unsigned int contextID);
PerContextProgObj(const PerContextProgObj& rhs); PerContextProgObj(const PerContextProgObj& rhs);
GLhandleARB& getHandle() {return _handle;} GLhandleARB& getHandle() {return _glProgObjHandle;}
bool isDirty() const {return _dirty;} bool isDirty() const {return _dirty;}
void markAsDirty() {_dirty = true; } void markAsDirty() {_dirty = true; }
void markAsClean() {_dirty = false;} void build();
bool build() const;
void use() const; void use() const;
void markAsAttached() {_unattached = false;} void updateUniforms( const UniformValueList& univalList );
bool isUnattached() const {return _unattached;} void applyUniformValues();
protected: void printInfoLog(osg::NotifySeverity severity) const;
PerContextProgObj() {};
protected: /*methods*/
PerContextProgObj();
~PerContextProgObj(); ~PerContextProgObj();
const ProgramObject* _parent; protected: /*data*/
const ProgramObject* _progObj;
osg::ref_ptr<Extensions> _extensions; osg::ref_ptr<Extensions> _extensions;
GLhandleARB _handle; GLhandleARB _glProgObjHandle;
bool _dirty; bool _dirty;
bool _unattached; UniformValueList _univalList;
const unsigned int _contextID;
}; };
typedef osg::buffered_value< osg::ref_ptr<PerContextProgObj> > PCPOList; protected: /*methods*/
mutable PCPOList _pcpoList; virtual ~ProgramObject();
PerContextProgObj* getPCPO(unsigned int contextID) const; PerContextProgObj* getPCPO(unsigned int contextID) const;
void updateUniforms( int frameNumber ) const;
protected: /*data*/
bool _enabled;
std::vector< ShaderObjectPtr > _shaderObjectList;
mutable osg::buffered_value< osg::ref_ptr<PerContextProgObj> > _pcpoList;
mutable int _frameNumberOfLastPCPOUpdate;
mutable UniformValueList _univalList;
}; };
/////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////
/** Encapsulates the OpenGL Shading Language ShaderObject */ /** Encapsulates the OpenGL Shading Language ShaderObject */
@ -159,51 +186,57 @@ class OSGGL2_EXPORT ShaderObject : public osg::Object
void setShaderSource( const char* sourceText ); void setShaderSource( const char* sourceText );
inline const std::string& getShaderSource() const {return _shaderSource; } inline const std::string& getShaderSource() const {return _shaderSource; }
bool loadShaderSourceFromFile( const char* fileName ); bool loadShaderSourceFromFile( const char* fileName );
Type getType() const { return _type; } inline Type getType() const { return _type; }
const char* getTypename() const;
/** Force a recompile on next apply() of associated glShaderObject. */ /** Force a recompile on next apply() of associated glShaderObject. */
void dirtyShaderObject(); void dirtyShaderObject();
bool build(unsigned int contextID) const; void build(unsigned int contextID) const;
void attach(unsigned int contextID, GLhandleARB progObj) const; void attach(unsigned int contextID, GLhandleARB progObj) const;
protected: protected:
class PerContextShaderObj : public osg::Referenced
virtual ~ShaderObject();
std::string _shaderSource;
Type _type;
class OSGGL2_EXPORT PerContextShaderObj : public osg::Referenced
{ {
public: public:
PerContextShaderObj(const ShaderObject* parent, Extensions* extensions); PerContextShaderObj(const ShaderObject* shadObj, unsigned int contextID);
PerContextShaderObj(const PerContextShaderObj& rhs); PerContextShaderObj(const PerContextShaderObj& rhs);
GLhandleARB& getHandle() {return _handle;} GLhandleARB& getHandle() {return _glShaderObjHandle;}
bool isDirty() const {return _dirty;} bool isDirty() const {return _dirty;}
void markAsDirty() {_dirty = true; } void markAsDirty() {_dirty = true; }
void markAsClean() {_dirty = false;} void build();
bool build();
void attach(GLhandleARB progObj); void attach(GLhandleARB progObj) const;
protected: void printInfoLog(osg::NotifySeverity severity) const;
PerContextShaderObj() {};
protected: /*methods*/
PerContextShaderObj();
~PerContextShaderObj(); ~PerContextShaderObj();
const ShaderObject* _parent; protected: /*data*/
const ShaderObject* _shadObj;
osg::ref_ptr<Extensions> _extensions; osg::ref_ptr<Extensions> _extensions;
GLhandleARB _handle; GLhandleARB _glShaderObjHandle;
bool _dirty; bool _dirty;
const unsigned int _contextID;
}; };
typedef osg::buffered_value< osg::ref_ptr<PerContextShaderObj> > PCSOList; protected: /*methods*/
mutable PCSOList _pcsoList; virtual ~ShaderObject();
PerContextShaderObj* getPCSO(unsigned int contextID) const; PerContextShaderObj* getPCSO(unsigned int contextID) const;
friend void ProgramObject::addShader( ShaderObject* shadObj ); // to access addProgObjRef()
void addProgObjRef( ProgramObject* progObj );
protected: /*data*/
Type _type;
std::string _shaderSource;
std::vector< ProgramObjectPtr > _programObjectList;
mutable osg::buffered_value< osg::ref_ptr<PerContextShaderObj> > _pcsoList;
}; };
} }

View File

@ -0,0 +1,88 @@
/* -*-c++-*- OpenSceneGraph - Copyright (C) 1998-2003 Robert Osfield
* Copyright (C) 2003 3Dlabs Inc. Ltd.
*
* This application is open source and may be redistributed and/or modified
* freely and without restriction, both in commericial and non commericial
* applications, as long as this copyright notice is maintained.
*
* This application is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
*/
/* file: include/osgGL2/UniformValue
* author: Mike Weiblen 2003-09-18
*
* See http://www.3dlabs.com/opengl2/ for more information regarding
* the OpenGL Shading Language.
*/
#ifndef OSGGL2_UNIFORMVALUE
#define OSGGL2_UNIFORMVALUE 1
#include <osg/ref_ptr>
#include <osg/Vec2>
#include <osg/Vec3>
#include <osg/Vec4>
#include <osg/Referenced>
#include <osgGL2/Extensions>
#include <vector>
namespace osgGL2 {
///////////////////////////////////////////////////////////////////////////
/** An abstract class to encapsulate a new value for a glUniform.
* osgGL2::ProgramObject.setUniform() constructs and sends a UniformValue
* to all its PCPOs (per-context glProgramObjects) to set the value of a
* glUniform; that value is propogated to the glProgramObjects during the
* next osgGL2::ProgramObject.apply().
* This class is for internal use by osgGL2::ProgramObject.
*/
class UniformValue : public osg::Referenced
{
public:
virtual void apply( Extensions *ext, const GLhandleARB progObj ) const = 0;
protected:
UniformValue( const char* uniformName ) : _name( uniformName ) {};
virtual ~UniformValue() {};
int getLocation( Extensions *ext, const GLhandleARB progObj ) const;
std::string _name;
};
typedef std::vector< osg::ref_ptr<UniformValue> > UniformValueList;
///////////////////////////////////////////////////////////////////////////
#define META_UniformValue( typeName ) \
class UniformValue_##typeName : public UniformValue \
{ \
public: \
UniformValue_##typeName( const char* uniformName, typeName value ); \
virtual void apply( Extensions *ext, const GLhandleARB progObj ) const; \
protected: \
typeName _value; \
}
META_UniformValue( int );
META_UniformValue( float );
using namespace osg;
META_UniformValue( Vec2 );
META_UniformValue( Vec3 );
META_UniformValue( Vec4 );
}
#endif
/*EOF*/

View File

@ -11,7 +11,7 @@
*/ */
/* file: src/osgGL2/Extensions.cpp /* file: src/osgGL2/Extensions.cpp
* author: Mike Weiblen 2003-07-14 * author: Mike Weiblen 2003-09-12
* *
* See http://www.3dlabs.com/opengl2/ for more information regarding * See http://www.3dlabs.com/opengl2/ for more information regarding
* the OpenGL Shading Language. * the OpenGL Shading Language.
@ -477,11 +477,11 @@ void Extensions::glUniform4i(GLint location, GLint v0, GLint v1, GLint v2, GLint
} }
} }
void Extensions::glUniform1fv(GLint location, GLsizei count, GLfloat *value) const void Extensions::glUniform1fv(GLint location, GLsizei count, const GLfloat *value) const
{ {
if (_glUniform1fv) if (_glUniform1fv)
{ {
typedef void (APIENTRY * Uniform1fvProc) (GLint location, GLsizei count, GLfloat *value); typedef void (APIENTRY * Uniform1fvProc) (GLint location, GLsizei count, const GLfloat *value);
((Uniform1fvProc)_glUniform1fv)(location, count, value); ((Uniform1fvProc)_glUniform1fv)(location, count, value);
} }
else else
@ -490,11 +490,11 @@ void Extensions::glUniform1fv(GLint location, GLsizei count, GLfloat *value) con
} }
} }
void Extensions::glUniform2fv(GLint location, GLsizei count, GLfloat *value) const void Extensions::glUniform2fv(GLint location, GLsizei count, const GLfloat *value) const
{ {
if (_glUniform2fv) if (_glUniform2fv)
{ {
typedef void (APIENTRY * Uniform2fvProc) (GLint location, GLsizei count, GLfloat *value); typedef void (APIENTRY * Uniform2fvProc) (GLint location, GLsizei count, const GLfloat *value);
((Uniform2fvProc)_glUniform2fv)(location, count, value); ((Uniform2fvProc)_glUniform2fv)(location, count, value);
} }
else else
@ -503,11 +503,11 @@ void Extensions::glUniform2fv(GLint location, GLsizei count, GLfloat *value) con
} }
} }
void Extensions::glUniform3fv(GLint location, GLsizei count, GLfloat *value) const void Extensions::glUniform3fv(GLint location, GLsizei count, const GLfloat *value) const
{ {
if (_glUniform3fv) if (_glUniform3fv)
{ {
typedef void (APIENTRY * Uniform3fvProc) (GLint location, GLsizei count, GLfloat *value); typedef void (APIENTRY * Uniform3fvProc) (GLint location, GLsizei count, const GLfloat *value);
((Uniform3fvProc)_glUniform3fv)(location, count, value); ((Uniform3fvProc)_glUniform3fv)(location, count, value);
} }
else else
@ -516,11 +516,11 @@ void Extensions::glUniform3fv(GLint location, GLsizei count, GLfloat *value) con
} }
} }
void Extensions::glUniform4fv(GLint location, GLsizei count, GLfloat *value) const void Extensions::glUniform4fv(GLint location, GLsizei count, const GLfloat *value) const
{ {
if (_glUniform4fv) if (_glUniform4fv)
{ {
typedef void (APIENTRY * Uniform4fvProc) (GLint location, GLsizei count, GLfloat *value); typedef void (APIENTRY * Uniform4fvProc) (GLint location, GLsizei count, const GLfloat *value);
((Uniform4fvProc)_glUniform4fv)(location, count, value); ((Uniform4fvProc)_glUniform4fv)(location, count, value);
} }
else else
@ -529,11 +529,11 @@ void Extensions::glUniform4fv(GLint location, GLsizei count, GLfloat *value) con
} }
} }
void Extensions::glUniform1iv(GLint location, GLsizei count, GLint *value) const void Extensions::glUniform1iv(GLint location, GLsizei count, const GLint *value) const
{ {
if (_glUniform1iv) if (_glUniform1iv)
{ {
typedef void (APIENTRY * Uniform1ivProc) (GLint location, GLsizei count, GLint *value); typedef void (APIENTRY * Uniform1ivProc) (GLint location, GLsizei count, const GLint *value);
((Uniform1ivProc)_glUniform1iv)(location, count, value); ((Uniform1ivProc)_glUniform1iv)(location, count, value);
} }
else else
@ -542,11 +542,11 @@ void Extensions::glUniform1iv(GLint location, GLsizei count, GLint *value) const
} }
} }
void Extensions::glUniform2iv(GLint location, GLsizei count, GLint *value) const void Extensions::glUniform2iv(GLint location, GLsizei count, const GLint *value) const
{ {
if (_glUniform2iv) if (_glUniform2iv)
{ {
typedef void (APIENTRY * Uniform2ivProc) (GLint location, GLsizei count, GLint *value); typedef void (APIENTRY * Uniform2ivProc) (GLint location, GLsizei count, const GLint *value);
((Uniform2ivProc)_glUniform2iv)(location, count, value); ((Uniform2ivProc)_glUniform2iv)(location, count, value);
} }
else else
@ -555,11 +555,11 @@ void Extensions::glUniform2iv(GLint location, GLsizei count, GLint *value) const
} }
} }
void Extensions::glUniform3iv(GLint location, GLsizei count, GLint *value) const void Extensions::glUniform3iv(GLint location, GLsizei count, const GLint *value) const
{ {
if (_glUniform3iv) if (_glUniform3iv)
{ {
typedef void (APIENTRY * Uniform3ivProc) (GLint location, GLsizei count, GLint *value); typedef void (APIENTRY * Uniform3ivProc) (GLint location, GLsizei count, const GLint *value);
((Uniform3ivProc)_glUniform3iv)(location, count, value); ((Uniform3ivProc)_glUniform3iv)(location, count, value);
} }
else else
@ -568,11 +568,11 @@ void Extensions::glUniform3iv(GLint location, GLsizei count, GLint *value) const
} }
} }
void Extensions::glUniform4iv(GLint location, GLsizei count, GLint *value) const void Extensions::glUniform4iv(GLint location, GLsizei count, const GLint *value) const
{ {
if (_glUniform4iv) if (_glUniform4iv)
{ {
typedef void (APIENTRY * Uniform4ivProc) (GLint location, GLsizei count, GLint *value); typedef void (APIENTRY * Uniform4ivProc) (GLint location, GLsizei count, const GLint *value);
((Uniform4ivProc)_glUniform4iv)(location, count, value); ((Uniform4ivProc)_glUniform4iv)(location, count, value);
} }
else else
@ -581,11 +581,11 @@ void Extensions::glUniform4iv(GLint location, GLsizei count, GLint *value) const
} }
} }
void Extensions::glUniformMatrix2fv(GLint location, GLsizei count, GLboolean transpose, GLfloat *value) const void Extensions::glUniformMatrix2fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value) const
{ {
if (_glUniformMatrix2fv) if (_glUniformMatrix2fv)
{ {
typedef void (APIENTRY * UniformMatrix2fvProc) (GLint location, GLsizei count, GLboolean transpose, GLfloat *value); typedef void (APIENTRY * UniformMatrix2fvProc) (GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
((UniformMatrix2fvProc)_glUniformMatrix2fv)(location, count, transpose, value); ((UniformMatrix2fvProc)_glUniformMatrix2fv)(location, count, transpose, value);
} }
else else
@ -594,11 +594,11 @@ void Extensions::glUniformMatrix2fv(GLint location, GLsizei count, GLboolean tra
} }
} }
void Extensions::glUniformMatrix3fv(GLint location, GLsizei count, GLboolean transpose, GLfloat *value) const void Extensions::glUniformMatrix3fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value) const
{ {
if (_glUniformMatrix3fv) if (_glUniformMatrix3fv)
{ {
typedef void (APIENTRY * UniformMatrix3fvProc) (GLint location, GLsizei count, GLboolean transpose, GLfloat *value); typedef void (APIENTRY * UniformMatrix3fvProc) (GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
((UniformMatrix3fvProc)_glUniformMatrix3fv)(location, count, transpose, value); ((UniformMatrix3fvProc)_glUniformMatrix3fv)(location, count, transpose, value);
} }
else else
@ -607,11 +607,11 @@ void Extensions::glUniformMatrix3fv(GLint location, GLsizei count, GLboolean tra
} }
} }
void Extensions::glUniformMatrix4fv(GLint location, GLsizei count, GLboolean transpose, GLfloat *value) const void Extensions::glUniformMatrix4fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value) const
{ {
if (_glUniformMatrix4fv) if (_glUniformMatrix4fv)
{ {
typedef void (APIENTRY * UniformMatrix4fvProc) (GLint location, GLsizei count, GLboolean transpose, GLfloat *value); typedef void (APIENTRY * UniformMatrix4fvProc) (GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
((UniformMatrix4fvProc)_glUniformMatrix4fv)(location, count, transpose, value); ((UniformMatrix4fvProc)_glUniformMatrix4fv)(location, count, transpose, value);
} }
else else

View File

@ -5,7 +5,8 @@ include $(TOPDIR)/Make/makedefs
CXXFILES = \ CXXFILES = \
Extensions.cpp \ Extensions.cpp \
Version.cpp \ Version.cpp \
ProgramObject.cpp ProgramObject.cpp\
UniformValue.cpp
DEF += -DOSGGL2_LIBRARY DEF += -DOSGGL2_LIBRARY

View File

@ -12,7 +12,7 @@
*/ */
/* file: src/osgGL2/ProgramObject.cpp /* file: src/osgGL2/ProgramObject.cpp
* author: Mike Weiblen 2003-07-14 * author: Mike Weiblen 2003-09-18
* *
* See http://www.3dlabs.com/opengl2/ for more information regarding * See http://www.3dlabs.com/opengl2/ for more information regarding
* the OpenGL Shading Language. * the OpenGL Shading Language.
@ -22,16 +22,18 @@
#include <osg/Notify> #include <osg/Notify>
#include <osg/State> #include <osg/State>
#include <osg/ref_ptr>
#include <osg/Timer> #include <osg/Timer>
#include <osg/FrameStamp>
#include <osgGL2/ProgramObject> #include <osgGL2/ProgramObject>
#include <osgGL2/UniformValue>
#include <osgGL2/Extensions> #include <osgGL2/Extensions>
#include <list> #include <list>
using namespace osgGL2; using namespace osgGL2;
/////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////
// static cache of deleted GL2 objects which may only // static cache of deleted GL2 objects which may only
// by actually deleted in the correct GL context. // by actually deleted in the correct GL context.
@ -63,8 +65,12 @@ void ProgramObject::flushDeletedGL2Objects(unsigned int contextID,double /*curre
{ {
const Extensions* extensions = Extensions::Get(contextID,true); const Extensions* extensions = Extensions::Get(contextID,true);
if (!extensions->isShaderObjectsSupported()) if (!extensions->isShaderObjectsSupported())
return; {
// can we really get here?
osg::notify(osg::WARN) << "flushDeletedGL2Objects not supported by OpenGL driver" << std::endl;
return;
}
GL2ObjectList& vpObjectList = citr->second; GL2ObjectList& vpObjectList = citr->second;
@ -81,25 +87,33 @@ void ProgramObject::flushDeletedGL2Objects(unsigned int contextID,double /*curre
availableTime -= elapsedTime; availableTime -= elapsedTime;
} }
/////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////
// osgGL2::ProgramObject // osgGL2::ProgramObject
/////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////
ProgramObject::ProgramObject() ProgramObject::ProgramObject()
{ {
// To ensure all PCPOs consistently get the same values, we must
// postpone updates until all PCPOs have been created.
// They are created during ProgramObject::apply(), so let a frame
// go by before sending the updates.
_frameNumberOfLastPCPOUpdate = 1;
_enabled = true;
} }
ProgramObject::ProgramObject(const ProgramObject& rhs, const osg::CopyOp& copyop): ProgramObject::ProgramObject(const ProgramObject& rhs, const osg::CopyOp& copyop):
osg::StateAttribute(rhs, copyop) osg::StateAttribute(rhs, copyop)
{ {
osg::notify(osg::FATAL) << "how got here?" << std::endl;
} }
// virtual // virtual
ProgramObject::~ProgramObject() ProgramObject::~ProgramObject()
{ {
for( unsigned int cxt=0; cxt<_pcpoList.size(); ++cxt ) for( unsigned int cxt=0; cxt < _pcpoList.size(); ++cxt )
{ {
if( ! _pcpoList[cxt] ) continue; if( ! _pcpoList[cxt] ) continue;
@ -112,10 +126,10 @@ ProgramObject::~ProgramObject()
} }
// mark each PCPO (per-context ProgramObject) as needing a relink // mark all PCPOs as needing a relink
void ProgramObject::dirtyProgramObject() void ProgramObject::dirtyProgramObject()
{ {
for( unsigned int cxt=0; cxt<_pcpoList.size(); ++cxt ) for( unsigned int cxt=0; cxt < _pcpoList.size(); ++cxt )
{ {
if( ! _pcpoList[cxt] ) continue; if( ! _pcpoList[cxt] ) continue;
@ -124,58 +138,95 @@ void ProgramObject::dirtyProgramObject()
} }
} }
void ProgramObject::addShader( ShaderObject* shader )
// mark all attached ShaderObjects as needing a rebuild
void ProgramObject::dirtyShaderObjects()
{ {
_shaderObjectList.push_back(shader); for( unsigned int i=0; i < _shaderObjectList.size() ; ++i )
{
_shaderObjectList[i]->dirtyShaderObject();
}
}
void ProgramObject::addShader( ShaderObject* shadObj )
{
_shaderObjectList.push_back( shadObj );
shadObj->addProgObjRef( this );
dirtyProgramObject(); dirtyProgramObject();
} }
void ProgramObject::setUniform( const char* uniformName, int value )
{
_univalList.push_back( new UniformValue_int( uniformName, value ) );
}
void ProgramObject::setUniform( const char* uniformName, float value )
{
_univalList.push_back( new UniformValue_float( uniformName, value ) );
}
void ProgramObject::setUniform( const char* uniformName, osg::Vec2 value )
{
_univalList.push_back( new UniformValue_Vec2( uniformName, value ) );
}
void ProgramObject::setUniform( const char* uniformName, osg::Vec3 value )
{
_univalList.push_back( new UniformValue_Vec3( uniformName, value ) );
}
void ProgramObject::setUniform( const char* uniformName, osg::Vec4 value )
{
_univalList.push_back( new UniformValue_Vec4( uniformName, value ) );
}
void ProgramObject::apply(osg::State& state) const void ProgramObject::apply(osg::State& state) const
{ {
const unsigned int contextID = state.getContextID(); const unsigned int contextID = state.getContextID();
const Extensions* extensions = Extensions::Get(contextID,true); const Extensions* extensions = Extensions::Get(contextID,true);
if (!extensions->isShaderObjectsSupported()) // if there are no ShaderObjects on this ProgramObject,
return; // use GL 1.x "fixed functionality" rendering.
if( !_enabled || _shaderObjectList.empty() )
// if there are no ShaderObjects attached (ie it is "empty"),
// indicates to use GL 1.x "fixed functionality" rendering.
if( _shaderObjectList.size() == 0 )
{ {
// glProgramObject handle 0 == GL 1.x fixed functionality if( extensions->isShaderObjectsSupported() )
extensions->glUseProgramObject( 0 ); {
extensions->glUseProgramObject( 0 );
}
return; return;
} }
PerContextProgObj* pcpo = getPCPO( contextID ); if( ! extensions->isShaderObjectsSupported() )
// if the first apply(), attach glShaderObjects to the glProgramObject
if( pcpo->isUnattached() )
{ {
for( unsigned int i=0; i < _shaderObjectList.size() ; ++i ) osg::notify(osg::WARN) << "ARB_shader_objects not supported by OpenGL driver" << std::endl;
{ return;
if( ! _shaderObjectList[i] ) continue;
_shaderObjectList[i]->attach( contextID, pcpo->getHandle() );
}
pcpo->markAsAttached();
} }
// if we're dirty, build all attached objects, then build ourself const osg::FrameStamp* frameStamp = state.getFrameStamp();
const int frameNumber = (frameStamp) ? frameStamp->getFrameNumber() : -1;
updateUniforms( frameNumber );
PerContextProgObj* pcpo = getPCPO( contextID );
if( pcpo->isDirty() ) if( pcpo->isDirty() )
{ {
for( unsigned int i=0; i < _shaderObjectList.size() ; ++i ) for( unsigned int i=0; i < _shaderObjectList.size() ; ++i )
{ {
if( ! _shaderObjectList[i] ) continue;
_shaderObjectList[i]->build( contextID ); _shaderObjectList[i]->build( contextID );
} }
pcpo->build();
if( pcpo->build() )
pcpo->markAsClean();
} }
// make this glProgramObject part of current GL state // make this glProgramObject part of current GL state
pcpo->use(); pcpo->use();
// consume any pending setUniform messages
pcpo->applyUniformValues();
} }
@ -183,49 +234,121 @@ ProgramObject::PerContextProgObj* ProgramObject::getPCPO(unsigned int contextID)
{ {
if( ! _pcpoList[contextID].valid() ) if( ! _pcpoList[contextID].valid() )
{ {
_pcpoList[contextID] = new PerContextProgObj( this, Extensions::Get(contextID,true) ); _pcpoList[contextID] = new PerContextProgObj( this, contextID );
// attach all PCSOs to this new PCPO
for( unsigned int i=0; i < _shaderObjectList.size() ; ++i )
{
_shaderObjectList[i]->attach( contextID, _pcpoList[contextID]->getHandle() );
}
} }
return _pcpoList[contextID].get(); return _pcpoList[contextID].get();
} }
void ProgramObject::updateUniforms( int frameNumber ) const
{
if( frameNumber <= _frameNumberOfLastPCPOUpdate )
return;
_frameNumberOfLastPCPOUpdate = frameNumber;
if( _univalList.empty() )
return;
for( unsigned int cxt=0; cxt < _pcpoList.size(); ++cxt )
{
if( ! _pcpoList[cxt] ) continue;
PerContextProgObj* pcpo = _pcpoList[cxt].get();
pcpo->updateUniforms( _univalList );
}
_univalList.clear();
}
/////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////
// PCPO : OSG abstraction of the per-context Program Object // PCPO : OSG abstraction of the per-context Program Object
ProgramObject::PerContextProgObj::PerContextProgObj(const ProgramObject* parent, Extensions* extensions) : ProgramObject::PerContextProgObj::PerContextProgObj(const ProgramObject* progObj, unsigned int contextID ) :
osg::Referenced() osg::Referenced(),
_contextID( contextID )
{ {
_parent = parent; _progObj = progObj;
_extensions = extensions; _extensions = Extensions::Get( _contextID, true );
_handle= _extensions->glCreateProgramObject(); _glProgObjHandle = _extensions->glCreateProgramObject();
markAsDirty(); markAsDirty();
_unattached = true;
} }
ProgramObject::PerContextProgObj::PerContextProgObj(const PerContextProgObj& rhs) : ProgramObject::PerContextProgObj::PerContextProgObj(const PerContextProgObj& rhs) :
osg::Referenced() osg::Referenced(),
_contextID( rhs._contextID )
{ {
_parent = rhs._parent; _progObj = rhs._progObj;
_extensions = rhs._extensions; _extensions = rhs._extensions;
_handle= rhs._handle; _glProgObjHandle = rhs._glProgObjHandle ;
_dirty = rhs._dirty; _dirty = rhs._dirty;
_unattached = rhs._unattached;
} }
ProgramObject::PerContextProgObj::~PerContextProgObj() ProgramObject::PerContextProgObj::~PerContextProgObj()
{ {
} }
bool ProgramObject::PerContextProgObj::build() const void ProgramObject::PerContextProgObj::build()
{ {
_extensions->glLinkProgram(_handle); int linked;
return true;
_extensions->glLinkProgram( _glProgObjHandle );
_extensions->glGetObjectParameteriv(_glProgObjHandle,
GL_OBJECT_LINK_STATUS_ARB, &linked);
_dirty = (linked == 0);
if( _dirty )
{
osg::notify(osg::WARN) << "glLinkProgram FAILED:" << std::endl;
printInfoLog(osg::WARN);
}
} }
void ProgramObject::PerContextProgObj::use() const void ProgramObject::PerContextProgObj::use() const
{ {
_extensions->glUseProgramObject( _handle ); _extensions->glUseProgramObject( _glProgObjHandle );
} }
void ProgramObject::PerContextProgObj::updateUniforms( const UniformValueList& univalList )
{
// TODO: should the incoming list be appended rather than assigned?
_univalList = univalList;
}
void ProgramObject::PerContextProgObj::applyUniformValues()
{
Extensions *ext = _extensions.get();
for( unsigned int i=0; i < _univalList.size() ; ++i )
{
_univalList[i]->apply( ext, _glProgObjHandle );
}
_univalList.clear();
}
void ProgramObject::PerContextProgObj::printInfoLog(osg::NotifySeverity severity) const
{
int blen = 0; // length of buffer to allocate
int slen = 0; // strlen GL actually wrote to buffer
_extensions->glGetObjectParameteriv(_glProgObjHandle, GL_OBJECT_INFO_LOG_LENGTH_ARB , &blen);
if (blen > 1)
{
GLcharARB* infoLog = new GLcharARB[blen];
_extensions->glGetInfoLog(_glProgObjHandle, blen, &slen, infoLog);
osg::notify(severity) << infoLog << std::endl;
delete infoLog;
}
}
/////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////
// osgGL2::ShaderObject // osgGL2::ShaderObject
/////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////
@ -260,13 +383,19 @@ ShaderObject::~ShaderObject()
// mark each PCSO (per-context Shader Object) as needing a recompile // mark each PCSO (per-context Shader Object) as needing a recompile
void ShaderObject::dirtyShaderObject() void ShaderObject::dirtyShaderObject()
{ {
for( unsigned int cxt=0; cxt<_pcsoList.size(); ++cxt ) for( unsigned int cxt=0; cxt < _pcsoList.size(); ++cxt )
{ {
if( ! _pcsoList[cxt] ) continue; if( ! _pcsoList[cxt] ) continue;
PerContextShaderObj* pcso = _pcsoList[cxt].get(); PerContextShaderObj* pcso = _pcsoList[cxt].get();
pcso->markAsDirty(); pcso->markAsDirty();
} }
// mark attached ProgramObjects dirty as well
for( unsigned int i=0; i < _programObjectList.size(); ++i )
{
_programObjectList[i]->dirtyProgramObject();
}
} }
void ShaderObject::setShaderSource( const char* sourceText ) void ShaderObject::setShaderSource( const char* sourceText )
@ -302,17 +431,25 @@ bool ShaderObject::loadShaderSourceFromFile( const char* fileName )
} }
const char* ShaderObject::getTypename() const
{
switch( getType() )
{
case VERTEX: return "Vertex";
case FRAGMENT: return "Fragment";
default: return "UNKNOWN";
}
}
bool ShaderObject::build(unsigned int contextID ) const
void ShaderObject::build(unsigned int contextID ) const
{ {
PerContextShaderObj* pcso = getPCSO( contextID ); PerContextShaderObj* pcso = getPCSO( contextID );
if( pcso->isDirty() ) if( pcso->isDirty() )
{ {
if( pcso->build() ) pcso->build();
pcso->markAsClean();
} }
return true; /*TODO*/
} }
@ -320,34 +457,44 @@ ShaderObject::PerContextShaderObj* ShaderObject::getPCSO(unsigned int contextID)
{ {
if( ! _pcsoList[contextID].valid() ) if( ! _pcsoList[contextID].valid() )
{ {
_pcsoList[contextID] = new PerContextShaderObj( this, Extensions::Get(contextID,true) ); _pcsoList[contextID] = new PerContextShaderObj( this, contextID );
} }
return _pcsoList[contextID].get(); return _pcsoList[contextID].get();
} }
void ShaderObject::attach(unsigned int contextID, GLhandleARB progObj) const void ShaderObject::attach(unsigned int contextID, GLhandleARB progObj) const
{ {
getPCSO( contextID )->attach( progObj ); getPCSO( contextID )->attach( progObj );
} }
void ShaderObject::addProgObjRef( ProgramObject* progObj )
{
_programObjectList.push_back( progObj );
}
/////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////
// PCSO : OSG abstraction of the per-context Shader Object // PCSO : OSG abstraction of the per-context Shader Object
ShaderObject::PerContextShaderObj::PerContextShaderObj(const ShaderObject* parent, Extensions* extensions) : ShaderObject::PerContextShaderObj::PerContextShaderObj(const ShaderObject* shadObj, unsigned int contextID) :
osg::Referenced() osg::Referenced(),
_contextID( contextID )
{ {
_parent = parent; _shadObj = shadObj;
_extensions = extensions; _extensions = Extensions::Get( _contextID, true );
_handle = _extensions->glCreateShaderObject( parent->getType() ); _glShaderObjHandle = _extensions->glCreateShaderObject( shadObj->getType() );
markAsDirty(); markAsDirty();
} }
ShaderObject::PerContextShaderObj::PerContextShaderObj(const PerContextShaderObj& rhs) : ShaderObject::PerContextShaderObj::PerContextShaderObj(const PerContextShaderObj& rhs) :
osg::Referenced() osg::Referenced(),
_contextID( rhs._contextID )
{ {
_parent = rhs._parent; _shadObj = rhs._shadObj;
_extensions = rhs._extensions; _extensions = rhs._extensions;
_handle = rhs._handle; _glShaderObjHandle = rhs._glShaderObjHandle;
_dirty = rhs._dirty; _dirty = rhs._dirty;
} }
@ -355,21 +502,42 @@ ShaderObject::PerContextShaderObj::~PerContextShaderObj()
{ {
} }
bool ShaderObject::PerContextShaderObj::build() void ShaderObject::PerContextShaderObj::build()
{ {
const char* sourceText = _parent->getShaderSource().c_str(); int compiled;
const char* sourceText = _shadObj->getShaderSource().c_str();
_extensions->glShaderSource( _handle, 1, &sourceText, NULL ); _extensions->glShaderSource( _glShaderObjHandle, 1, &sourceText, NULL );
_extensions->glCompileShader( _handle ); _extensions->glCompileShader( _glShaderObjHandle );
_extensions->glGetObjectParameteriv(_glShaderObjHandle,
GL_OBJECT_COMPILE_STATUS_ARB, &compiled);
// _extensions->glAttachObject( _handle, vertShaderObject ); _dirty = (compiled == 0);
if( _dirty )
return true; {
osg::notify(osg::WARN) << _shadObj->getTypename() << " glCompileShader FAILED:" << std::endl;
printInfoLog(osg::WARN);
}
} }
void ShaderObject::PerContextShaderObj::attach(GLhandleARB progObj) void ShaderObject::PerContextShaderObj::attach(GLhandleARB progObj) const
{ {
_extensions->glAttachObject(progObj, _handle); _extensions->glAttachObject( progObj, _glShaderObjHandle );
}
void ShaderObject::PerContextShaderObj::printInfoLog(osg::NotifySeverity severity) const
{
int blen = 0; // length of buffer to allocate
int slen = 0; // strlen GL actually wrote to buffer
_extensions->glGetObjectParameteriv(_glShaderObjHandle, GL_OBJECT_INFO_LOG_LENGTH_ARB , &blen);
if (blen > 1)
{
GLcharARB* infoLog = new GLcharARB[blen];
_extensions->glGetInfoLog(_glShaderObjHandle, blen, &slen, infoLog);
osg::notify(severity) << infoLog << std::endl;
delete infoLog;
}
} }
/*EOF*/ /*EOF*/

View File

@ -0,0 +1,98 @@
/* -*-c++-*- OpenSceneGraph - Copyright (C) 1998-2003 Robert Osfield
* Copyright (C) 2003 3Dlabs Inc. Ltd.
*
* This application is open source and may be redistributed and/or modified
* freely and without restriction, both in commericial and non commericial
* applications, as long as this copyright notice is maintained.
*
* This application is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
*/
/* file: src/osgGL2/UniformValue
* author: Mike Weiblen 2003-09-12
*
* See http://www.3dlabs.com/opengl2/ for more information regarding
* the OpenGL Shading Language.
*/
#include <string>
#include <osg/Notify>
#include <osgGL2/UniformValue>
using namespace osgGL2;
using namespace osg;
int UniformValue::getLocation( Extensions *ext, const GLhandleARB progObj ) const
{
GLint loc = ext->glGetUniformLocation( progObj, _name.c_str() );
if( loc == -1 )
{
osg::notify(osg::INFO) << "Uniform \"" << _name <<
"\" not found in ProgramObject" << std::endl;
}
return loc;
}
///////////////////////////////////////////////////////////////////////////
#define META_UniformValueCtor( typeName ) \
UniformValue_##typeName::UniformValue_##typeName( const char* uniformName, typeName value ) : \
UniformValue( uniformName ) \
{ _value = value; } \
META_UniformValueCtor( int );
void UniformValue_int::apply( Extensions *ext, const GLhandleARB progObj ) const
{
int loc = getLocation( ext, progObj );
if( loc != -1 )
{
ext->glUniform1i( loc, _value );
}
}
META_UniformValueCtor( float );
void UniformValue_float::apply( Extensions *ext, const GLhandleARB progObj ) const
{
int loc = getLocation( ext, progObj );
if( loc != -1 )
{
ext->glUniform1f( loc, _value );
}
}
META_UniformValueCtor( Vec2 );
void UniformValue_Vec2::apply( Extensions *ext, const GLhandleARB progObj ) const
{
int loc = getLocation( ext, progObj );
if( loc != -1 )
{
ext->glUniform2fv( loc, 1, _value.ptr() );
}
}
META_UniformValueCtor( Vec3 );
void UniformValue_Vec3::apply( Extensions *ext, const GLhandleARB progObj ) const
{
int loc = getLocation( ext, progObj );
if( loc != -1 )
{
ext->glUniform3fv( loc, 1, _value.ptr() );
}
}
META_UniformValueCtor( Vec4 );
void UniformValue_Vec4::apply( Extensions *ext, const GLhandleARB progObj ) const
{
int loc = getLocation( ext, progObj );
if( loc != -1 )
{
ext->glUniform4fv( loc, 1, _value.ptr() );
}
}
/*EOF*/

View File

@ -2,7 +2,7 @@
const char* osgGL2GetVersion() const char* osgGL2GetVersion()
{ {
return "0.1.0"; return "0.2.3";
} }

View File

@ -581,10 +581,12 @@ osg::Drawable* ReaderWriterOBJ::makeDrawable_useSeperateIndices(GLMmodel* obj, G
geom->addPrimitiveSet(new osg::DrawArrays(osg::PrimitiveSet::TRIANGLES,0,ntris*3)); geom->addPrimitiveSet(new osg::DrawArrays(osg::PrimitiveSet::TRIANGLES,0,ntris*3));
} }
osgUtil::SmoothingVisitor tsv;
tsv.smooth(*geom);
if (obj->numnormals==0)
{
osgUtil::SmoothingVisitor tsv;
tsv.smooth(*geom);
}
return geom; return geom;
} }