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\
dw\
flt\
gdal\
lib3ds\
logo\
lwo\

View File

@ -11,7 +11,7 @@
*/
/* 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
* OpenGL Shading Language shader applied to each.
@ -23,49 +23,159 @@
#include <osg/ShapeDrawable>
#include <osg/PositionAttitudeTransform>
#include <osg/Geode>
#include <osg/Node>
#include <osg/Material>
#include <osg/Notify>
#include <osg/Vec3>
#include <osg/Texture1D>
#include <osg/Texture2D>
#include <osg/Texture3D>
#include <osgDB/ReadFile>
#include <osgDB/FileUtils>
#include <osgUtil/Optimizer>
#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 = {
"varying vec3 color;"
"varying vec4 color;"
"void main(void)"
"{"
"color = gl_Vertex;"
"gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex;"
"color = gl_Vertex.zyx * 1.0;"
"}"
};
static const char *microshaderFragSource = {
"varying vec3 color;"
"varying vec4 color;"
"void main(void)"
"{"
"gl_FragColor = vec4(color, 1.0);"
"gl_FragColor = color;"
"}"
};
///////////////////////////////////////////////////////////////////////////
static 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();
}
static osg::ref_ptr<osg::Group> rootNode;
// Create some geometry upon which to render GL2 shaders.
static osg::Geode*
@ -78,96 +188,231 @@ CreateModel()
return geode;
}
// read vert & frag shader source code from a pair of files.
static void
LoadShaderSource( osgGL2::ProgramObject* progObj, std::string baseFileName )
// Add a reference to the masterModel at the specified translation, and
// return its StateSet so we can easily attach StateAttributes.
static osg::StateSet*
ModelInstance()
{
std::string vertFileName = osgDB::findDataFile(baseFileName + ".vert");
if( vertFileName.length() != 0 )
{
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;
}
static float zvalue = 0.0f;
static osg::Node* masterModel = CreateModel();
std::string fragFileName = osgDB::findDataFile(baseFileName + ".frag");
if( fragFileName.length() != 0 )
osg::PositionAttitudeTransform* xform = new osg::PositionAttitudeTransform();
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 );
fragObj->loadShaderSourceFromFile( fragFileName.c_str() );
progObj->addShader( fragObj );
obj->loadShaderSourceFromFile( fqFileName.c_str() );
}
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
#define ZGRID 2.2
osg::Node*
GL2Scene()
osg::ref_ptr<osg::Group>
GL2Scene::buildScene()
{
osg::StateSet* ss;
osgGL2::ProgramObject* progObj;
osg::Texture3D* noiseTexture = make3DNoiseTexture( 32 /*128*/ );
osg::Texture1D* sineTexture = make1DSineTexture( 32 /*1024*/ );
// the rootNode of our created graph.
rootNode = new osg::Group;
ss = rootNode->getOrCreateStateSet();
// 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
// the root of our scenegraph.
// attach an "empty" ProgramObject to the rootNode, which will act as
// the 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.
progObj = new osgGL2::ProgramObject;
ss->setAttributeAndModes(progObj, osg::StateAttribute::ON);
rootNode = new osg::Group;
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.
masterModel = CreateModel();
rootNode->addChild(masterModel);
// the simple Microshader (its source appears earlier in this file)
{
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
//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);
// rootNode->addChild( osgDB::readNodeFile( "3dl_ogl.logo" ) );
return rootNode;
}
///////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////
void
GL2Update()
GL2Scene::GL2Scene()
{
/* 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*/

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 =\
GL2Scene.cpp \
Noise.cpp \
osgshaders.cpp
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
* author: Mike Weiblen 2003-07-14
* author: Mike Weiblen 2003-09-18
*
* A simple app skeleton for viewing OpenGL Shading Language shaders;
* derived from osgviewer.cpp from OSG 0.9.4-2
* A demo of the OpenGL Shading Language shaders using osgGL2.
*
* See http://www.3dlabs.com/opengl2/ for more information regarding
* the OpenGL Shading Language.
*/
#include <osg/Notify>
#include <osgGA/GUIEventAdapter>
#include <osgGA/GUIActionAdapter>
#include <osgDB/ReadFile>
#include <osgUtil/Optimizer>
#include <osgProducer/Viewer>
#include <osgGL2/Version>
#define GL2SCENE
osg::Node* GL2Scene();
void GL2Update();
#include "GL2Scene.h"
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 )
{
// 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.
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.
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"))
if( args.read("-h") || args.read("--help") )
{
arguments.getApplicationUsage()->write(std::cout);
args.getApplicationUsage()->write(std::cout);
return 1;
}
// any option left unread are converted into errors to write out later.
arguments.reportRemainingOptionsAsUnrecognized();
// report any errors if they have occured when parsing the program aguments.
if (arguments.errors())
args.reportRemainingOptionsAsUnrecognized();
if( args.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;
}
// create the scene
notify(NOTICE) << "osgGL2 version " << osgGL2GetVersion() << std::endl;
GL2ScenePtr gl2Scene = new GL2Scene;
// read the scene from the list of file specified commandline args.
osg::ref_ptr<osg::Node> loadedModel = osgDB::readNodeFiles(arguments);
// if no model has been successfully loaded report failure.
if (!loadedModel)
{
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.setSceneData( gl2Scene->getRootNode().get() );
viewer.getEventHandlerList().push_front( new KeyHandler(gl2Scene) );
viewer.realize();
while( !viewer.done() )
{
// wait for all cull and draw threads to complete.
viewer.sync();
// update the scene by traversing it with the the update visitor which will
// call all node update callbacks and animations.
viewer.update();
#ifdef GL2SCENE //(
GL2Update();
#endif //)
// fire off the cull and draw traversals of the scene.
viewer.frame();
}
// wait for all cull and draw threads to complete before exit.
viewer.sync();
return 0;
}
/*EOF*/

View File

@ -11,7 +11,7 @@
*/
/* 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
* 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 glUniform3i(GLint location, GLint v0, GLint v1, GLint v2) const;
void glUniform4i(GLint location, GLint v0, GLint v1, GLint v2, GLint v3) const;
void glUniform1fv(GLint location, GLsizei count, GLfloat *value) const;
void glUniform2fv(GLint location, GLsizei count, GLfloat *value) const;
void glUniform3fv(GLint location, GLsizei count, GLfloat *value) const;
void glUniform4fv(GLint location, GLsizei count, GLfloat *value) const;
void glUniform1iv(GLint location, GLsizei count, GLint *value) const;
void glUniform2iv(GLint location, GLsizei count, GLint *value) const;
void glUniform3iv(GLint location, GLsizei count, GLint *value) const;
void glUniform4iv(GLint location, GLsizei count, GLint *value) const;
void glUniformMatrix2fv(GLint location, GLsizei count, GLboolean transpose, GLfloat *value) const;
void glUniformMatrix3fv(GLint location, GLsizei count, GLboolean transpose, GLfloat *value) const;
void glUniformMatrix4fv(GLint location, GLsizei count, GLboolean transpose, GLfloat *value) const;
void glUniform1fv(GLint location, GLsizei count, const GLfloat *value) const;
void glUniform2fv(GLint location, GLsizei count, const GLfloat *value) const;
void glUniform3fv(GLint location, GLsizei count, const GLfloat *value) const;
void glUniform4fv(GLint location, GLsizei count, const GLfloat *value) const;
void glUniform1iv(GLint location, GLsizei count, const GLint *value) const;
void glUniform2iv(GLint location, GLsizei count, const GLint *value) const;
void glUniform3iv(GLint location, GLsizei count, const GLint *value) const;
void glUniform4iv(GLint location, GLsizei count, const GLint *value) const;
void glUniformMatrix2fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value) const;
void glUniformMatrix3fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value) const;
void glUniformMatrix4fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value) const;
GLint glGetUniformLocation(GLhandleARB programObject, 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;

View File

@ -11,7 +11,7 @@
*/
/* 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
* the OpenGL Shading Language.
@ -25,26 +25,32 @@
#include <osg/StateAttribute>
#include <osg/buffered_value>
#include <osg/ref_ptr>
#include <osg/Vec2>
#include <osg/Vec3>
#include <osg/Vec4>
#include <osgGL2/Export>
#include <osgGL2/Extensions>
#include <osgGL2/UniformValue>
#include <string>
#include <vector>
namespace osgGL2 {
///////////////////////////////////////////////////////////////////////////
class ProgramObject;
typedef osg::ref_ptr<ProgramObject> ProgramObjectPtr;
class ShaderObject;
typedef osg::ref_ptr<ShaderObject> ShaderObjectPtr;
///////////////////////////////////////////////////////////////////////////
/** Encapsulates the OpenGL Shading Language ProgramObject */
class OSGGL2_EXPORT ProgramObject : public osg::StateAttribute
{
public:
ProgramObject();
/** Copy constructor using CopyOp to manage deep vs shallow copy.*/
@ -74,10 +80,29 @@ class OSGGL2_EXPORT ProgramObject : public osg::StateAttribute
// data access methods.
/** Force a relink on next apply() of associated glProgramObject. */
void dirtyProgramObject();
/** Force a relink on next apply() of associated glProgramObject. */
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
* 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.*/
static void flushDeletedGL2Objects(unsigned int contextID,double currentTime, double& availableTime);
protected:
virtual ~ProgramObject();
typedef std::vector< osg::ref_ptr<ShaderObject> > ShaderObjectList;
ShaderObjectList _shaderObjectList;
class OSGGL2_EXPORT PerContextProgObj : public osg::Referenced
class PerContextProgObj : public osg::Referenced
{
public:
PerContextProgObj(const ProgramObject* parent, Extensions* extensions);
PerContextProgObj(const ProgramObject* progObj, unsigned int contextID);
PerContextProgObj(const PerContextProgObj& rhs);
GLhandleARB& getHandle() {return _handle;}
GLhandleARB& getHandle() {return _glProgObjHandle;}
bool isDirty() const {return _dirty;}
void markAsDirty() {_dirty = true; }
void markAsClean() {_dirty = false;}
bool build() const;
void build();
void use() const;
void markAsAttached() {_unattached = false;}
bool isUnattached() const {return _unattached;}
void updateUniforms( const UniformValueList& univalList );
void applyUniformValues();
protected:
PerContextProgObj() {};
void printInfoLog(osg::NotifySeverity severity) const;
protected: /*methods*/
PerContextProgObj();
~PerContextProgObj();
const ProgramObject* _parent;
protected: /*data*/
const ProgramObject* _progObj;
osg::ref_ptr<Extensions> _extensions;
GLhandleARB _handle;
GLhandleARB _glProgObjHandle;
bool _dirty;
bool _unattached;
UniformValueList _univalList;
const unsigned int _contextID;
};
typedef osg::buffered_value< osg::ref_ptr<PerContextProgObj> > PCPOList;
mutable PCPOList _pcpoList;
protected: /*methods*/
virtual ~ProgramObject();
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 */
@ -159,51 +186,57 @@ class OSGGL2_EXPORT ShaderObject : public osg::Object
void setShaderSource( const char* sourceText );
inline const std::string& getShaderSource() const {return _shaderSource; }
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. */
void dirtyShaderObject();
bool build(unsigned int contextID) const;
void build(unsigned int contextID) const;
void attach(unsigned int contextID, GLhandleARB progObj) const;
protected:
virtual ~ShaderObject();
std::string _shaderSource;
Type _type;
class OSGGL2_EXPORT PerContextShaderObj : public osg::Referenced
class PerContextShaderObj : public osg::Referenced
{
public:
PerContextShaderObj(const ShaderObject* parent, Extensions* extensions);
PerContextShaderObj(const ShaderObject* shadObj, unsigned int contextID);
PerContextShaderObj(const PerContextShaderObj& rhs);
GLhandleARB& getHandle() {return _handle;}
GLhandleARB& getHandle() {return _glShaderObjHandle;}
bool isDirty() const {return _dirty;}
void markAsDirty() {_dirty = true; }
void markAsClean() {_dirty = false;}
bool build();
void build();
void attach(GLhandleARB progObj);
void attach(GLhandleARB progObj) const;
protected:
PerContextShaderObj() {};
void printInfoLog(osg::NotifySeverity severity) const;
protected: /*methods*/
PerContextShaderObj();
~PerContextShaderObj();
const ShaderObject* _parent;
protected: /*data*/
const ShaderObject* _shadObj;
osg::ref_ptr<Extensions> _extensions;
GLhandleARB _handle;
GLhandleARB _glShaderObjHandle;
bool _dirty;
const unsigned int _contextID;
};
typedef osg::buffered_value< osg::ref_ptr<PerContextShaderObj> > PCSOList;
mutable PCSOList _pcsoList;
protected: /*methods*/
virtual ~ShaderObject();
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
* author: Mike Weiblen 2003-07-14
* author: Mike Weiblen 2003-09-12
*
* See http://www.3dlabs.com/opengl2/ for more information regarding
* 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)
{
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);
}
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)
{
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);
}
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)
{
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);
}
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)
{
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);
}
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)
{
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);
}
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)
{
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);
}
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)
{
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);
}
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)
{
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);
}
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)
{
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);
}
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)
{
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);
}
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)
{
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);
}
else

View File

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

View File

@ -12,7 +12,7 @@
*/
/* 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
* the OpenGL Shading Language.
@ -22,16 +22,18 @@
#include <osg/Notify>
#include <osg/State>
#include <osg/ref_ptr>
#include <osg/Timer>
#include <osg/FrameStamp>
#include <osgGL2/ProgramObject>
#include <osgGL2/UniformValue>
#include <osgGL2/Extensions>
#include <list>
using namespace osgGL2;
///////////////////////////////////////////////////////////////////////////
// static cache of deleted GL2 objects which may only
// 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);
if (!extensions->isShaderObjectsSupported())
return;
if (!extensions->isShaderObjectsSupported())
{
// can we really get here?
osg::notify(osg::WARN) << "flushDeletedGL2Objects not supported by OpenGL driver" << std::endl;
return;
}
GL2ObjectList& vpObjectList = citr->second;
@ -81,25 +87,33 @@ void ProgramObject::flushDeletedGL2Objects(unsigned int contextID,double /*curre
availableTime -= elapsedTime;
}
///////////////////////////////////////////////////////////////////////////
// osgGL2::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):
osg::StateAttribute(rhs, copyop)
{
osg::notify(osg::FATAL) << "how got here?" << std::endl;
}
// virtual
ProgramObject::~ProgramObject()
{
for( unsigned int cxt=0; cxt<_pcpoList.size(); ++cxt )
for( unsigned int cxt=0; cxt < _pcpoList.size(); ++cxt )
{
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()
{
for( unsigned int cxt=0; cxt<_pcpoList.size(); ++cxt )
for( unsigned int cxt=0; cxt < _pcpoList.size(); ++cxt )
{
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();
}
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
{
const unsigned int contextID = state.getContextID();
const Extensions* extensions = Extensions::Get(contextID,true);
if (!extensions->isShaderObjectsSupported())
return;
// if there are no ShaderObjects attached (ie it is "empty"),
// indicates to use GL 1.x "fixed functionality" rendering.
if( _shaderObjectList.size() == 0 )
// if there are no ShaderObjects on this ProgramObject,
// use GL 1.x "fixed functionality" rendering.
if( !_enabled || _shaderObjectList.empty() )
{
// glProgramObject handle 0 == GL 1.x fixed functionality
extensions->glUseProgramObject( 0 );
if( extensions->isShaderObjectsSupported() )
{
extensions->glUseProgramObject( 0 );
}
return;
}
PerContextProgObj* pcpo = getPCPO( contextID );
// if the first apply(), attach glShaderObjects to the glProgramObject
if( pcpo->isUnattached() )
if( ! extensions->isShaderObjectsSupported() )
{
for( unsigned int i=0; i < _shaderObjectList.size() ; ++i )
{
if( ! _shaderObjectList[i] ) continue;
_shaderObjectList[i]->attach( contextID, pcpo->getHandle() );
}
pcpo->markAsAttached();
osg::notify(osg::WARN) << "ARB_shader_objects not supported by OpenGL driver" << std::endl;
return;
}
// 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() )
{
for( unsigned int i=0; i < _shaderObjectList.size() ; ++i )
{
if( ! _shaderObjectList[i] ) continue;
_shaderObjectList[i]->build( contextID );
}
if( pcpo->build() )
pcpo->markAsClean();
pcpo->build();
}
// make this glProgramObject part of current GL state
pcpo->use();
// consume any pending setUniform messages
pcpo->applyUniformValues();
}
@ -183,49 +234,121 @@ ProgramObject::PerContextProgObj* ProgramObject::getPCPO(unsigned int contextID)
{
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();
}
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
ProgramObject::PerContextProgObj::PerContextProgObj(const ProgramObject* parent, Extensions* extensions) :
osg::Referenced()
ProgramObject::PerContextProgObj::PerContextProgObj(const ProgramObject* progObj, unsigned int contextID ) :
osg::Referenced(),
_contextID( contextID )
{
_parent = parent;
_extensions = extensions;
_handle= _extensions->glCreateProgramObject();
_progObj = progObj;
_extensions = Extensions::Get( _contextID, true );
_glProgObjHandle = _extensions->glCreateProgramObject();
markAsDirty();
_unattached = true;
}
ProgramObject::PerContextProgObj::PerContextProgObj(const PerContextProgObj& rhs) :
osg::Referenced()
osg::Referenced(),
_contextID( rhs._contextID )
{
_parent = rhs._parent;
_progObj = rhs._progObj;
_extensions = rhs._extensions;
_handle= rhs._handle;
_glProgObjHandle = rhs._glProgObjHandle ;
_dirty = rhs._dirty;
_unattached = rhs._unattached;
}
ProgramObject::PerContextProgObj::~PerContextProgObj()
{
}
bool ProgramObject::PerContextProgObj::build() const
void ProgramObject::PerContextProgObj::build()
{
_extensions->glLinkProgram(_handle);
return true;
int linked;
_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
{
_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
///////////////////////////////////////////////////////////////////////////
@ -260,13 +383,19 @@ ShaderObject::~ShaderObject()
// mark each PCSO (per-context Shader Object) as needing a recompile
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;
PerContextShaderObj* pcso = _pcsoList[cxt].get();
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 )
@ -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 );
if( pcso->isDirty() )
{
if( pcso->build() )
pcso->markAsClean();
pcso->build();
}
return true; /*TODO*/
}
@ -320,34 +457,44 @@ ShaderObject::PerContextShaderObj* ShaderObject::getPCSO(unsigned int contextID)
{
if( ! _pcsoList[contextID].valid() )
{
_pcsoList[contextID] = new PerContextShaderObj( this, Extensions::Get(contextID,true) );
_pcsoList[contextID] = new PerContextShaderObj( this, contextID );
}
return _pcsoList[contextID].get();
}
void ShaderObject::attach(unsigned int contextID, GLhandleARB progObj) const
{
getPCSO( contextID )->attach( progObj );
}
void ShaderObject::addProgObjRef( ProgramObject* progObj )
{
_programObjectList.push_back( progObj );
}
///////////////////////////////////////////////////////////////////////////
// PCSO : OSG abstraction of the per-context Shader Object
ShaderObject::PerContextShaderObj::PerContextShaderObj(const ShaderObject* parent, Extensions* extensions) :
osg::Referenced()
ShaderObject::PerContextShaderObj::PerContextShaderObj(const ShaderObject* shadObj, unsigned int contextID) :
osg::Referenced(),
_contextID( contextID )
{
_parent = parent;
_extensions = extensions;
_handle = _extensions->glCreateShaderObject( parent->getType() );
_shadObj = shadObj;
_extensions = Extensions::Get( _contextID, true );
_glShaderObjHandle = _extensions->glCreateShaderObject( shadObj->getType() );
markAsDirty();
}
ShaderObject::PerContextShaderObj::PerContextShaderObj(const PerContextShaderObj& rhs) :
osg::Referenced()
osg::Referenced(),
_contextID( rhs._contextID )
{
_parent = rhs._parent;
_shadObj = rhs._shadObj;
_extensions = rhs._extensions;
_handle = rhs._handle;
_glShaderObjHandle = rhs._glShaderObjHandle;
_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->glCompileShader( _handle );
_extensions->glShaderSource( _glShaderObjHandle, 1, &sourceText, NULL );
_extensions->glCompileShader( _glShaderObjHandle );
_extensions->glGetObjectParameteriv(_glShaderObjHandle,
GL_OBJECT_COMPILE_STATUS_ARB, &compiled);
// _extensions->glAttachObject( _handle, vertShaderObject );
return true;
_dirty = (compiled == 0);
if( _dirty )
{
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*/

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()
{
return "0.1.0";
return "0.2.3";
}

View File

@ -582,9 +582,11 @@ osg::Drawable* ReaderWriterOBJ::makeDrawable_useSeperateIndices(GLMmodel* obj, G
}
osgUtil::SmoothingVisitor tsv;
tsv.smooth(*geom);
if (obj->numnormals==0)
{
osgUtil::SmoothingVisitor tsv;
tsv.smooth(*geom);
}
return geom;
}