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

@@ -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);
// 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");
ArgumentParser args(&argc,argv);
// 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);
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);
args.writeErrorMessages(std::cout);
return 1;
}
// read the scene from the list of file specified commandline args.
osg::ref_ptr<osg::Node> loadedModel = osgDB::readNodeFiles(arguments);
// create the scene
notify(NOTICE) << "osgGL2 version " << osgGL2GetVersion() << std::endl;
GL2ScenePtr gl2Scene = new GL2Scene;
// 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*/