dd996a3289
forcing users to use osgDB::readRef*File() methods. The later is preferable as it closes a potential threading bug when using paging databases in conjunction with the osgDB::Registry Object Cache. This threading bug occurs when one thread gets an object from the Cache via an osgDB::read*File() call where only a pointer to the object is passed back, so taking a reference to the object is delayed till it gets reassigned to a ref_ptr<>, but at the same time another thread calls a flush of the Object Cache deleting this object as it's referenceCount is now zero. Using osgDB::readREf*File() makes sure the a ref_ptr<> is passed back and the referenceCount never goes to zero. To ensure the OSG builds when OSG_PROVIDE_READFILE is to OFF the many cases of osgDB::read*File() usage had to be replaced with a ref_ptr<> osgDB::readRef*File() usage. The avoid this change causing lots of other client code to be rewritten to handle the use of ref_ptr<> in place of C pointer I introduced a serious of templte methods in various class to adapt ref_ptr<> to the underly C pointer to be passed to old OSG API's, example of this is found in include/osg/Group: bool addChild(Node* child); // old method which can only be used with a Node* tempalte<class T> bool addChild(const osg::ref_ptr<T>& child) { return addChild(child.get()); } // adapter template method These changes together cover 149 modified files, so it's a large submission. This extent of changes are warrent to make use of the Object Cache and multi-threaded loaded more robust. git-svn-id: http://svn.openscenegraph.org/osg/OpenSceneGraph/trunk@15164 16af8721-9629-0410-8352-f15c8da7e697
207 lines
6.9 KiB
C++
207 lines
6.9 KiB
C++
#include <iostream>
|
|
|
|
#include <osg/Array>
|
|
#include <osg/BoundingSphere>
|
|
#include <osg/BufferIndexBinding>
|
|
#include <osg/BufferObject>
|
|
#include <osg/Group>
|
|
#include <osg/Math>
|
|
#include <osg/MatrixTransform>
|
|
#include <osg/Program>
|
|
#include <osg/Shader>
|
|
|
|
#include <osgDB/ReadFile>
|
|
#include <osgDB/WriteFile>
|
|
#include <osgUtil/Optimizer>
|
|
|
|
#include <osgViewer/Viewer>
|
|
#include <osgViewer/ViewerEventHandlers>
|
|
|
|
using namespace std;
|
|
using namespace osg;
|
|
|
|
// This example is based on the sample code in the
|
|
// ARB_uniform_buffer_object extension specification.
|
|
|
|
GLfloat colors1[] = {
|
|
// block
|
|
0.45,0.45,1,1,
|
|
0.45,0.45,1,1,
|
|
0.75,0.75,0.75,1,
|
|
0.0,0.0,1.0,1,
|
|
0.0,1.0,0.0,1
|
|
};
|
|
GLfloat colors2[] = {
|
|
// block
|
|
0.45,0.45,1,1,
|
|
0.45,0.45,1,1,
|
|
0.75,0.75,0.75,1,
|
|
1.0,0.0,0.0,1,
|
|
0.0,1.0,0.0,1,
|
|
};
|
|
|
|
char vertexShaderSource[] =
|
|
"// Vertex shader for Gooch shading\n"
|
|
"// Author: Randi Rost\n"
|
|
"// Copyright (c) 2002-2006 3Dlabs Inc. Ltd.\n"
|
|
"// See 3Dlabs-License.txt for license information\n"
|
|
|
|
"vec3 LightPosition = vec3(0.0, 10.0, 4.0); \n"
|
|
|
|
"varying float NdotL;\n"
|
|
"varying vec3 ReflectVec;\n"
|
|
"varying vec3 ViewVec;\n"
|
|
|
|
"void main(void)\n"
|
|
"{\n"
|
|
"vec3 ecPos = vec3 (gl_ModelViewMatrix * gl_Vertex);\n"
|
|
"vec3 tnorm = normalize(gl_NormalMatrix * gl_Normal);\n"
|
|
"vec3 lightVec = normalize(LightPosition - ecPos);\n"
|
|
"ReflectVec = normalize(reflect(-lightVec, tnorm));\n"
|
|
"ViewVec = normalize(-ecPos);\n"
|
|
"NdotL = (dot(lightVec, tnorm) + 1.0) * 0.5;\n"
|
|
"gl_Position = ftransform();\n"
|
|
"}\n";
|
|
|
|
char fragmentShaderSource[] =
|
|
"// Fragment shader for Gooch shading, adapted for ARB_uniform_buffer_object\n"
|
|
|
|
"#extension GL_ARB_uniform_buffer_object : enable\n"
|
|
|
|
"layout(std140) uniform colors0\n"
|
|
"{\n"
|
|
"float DiffuseCool;\n"
|
|
"float DiffuseWarm;\n"
|
|
"vec3 SurfaceColor;\n"
|
|
"vec3 WarmColor;\n"
|
|
"vec3 CoolColor;\n"
|
|
"};\n"
|
|
|
|
"varying float NdotL;\n"
|
|
"varying vec3 ReflectVec;\n"
|
|
"varying vec3 ViewVec;\n"
|
|
|
|
"void main (void)\n"
|
|
"{\n"
|
|
"vec3 kcool = min(CoolColor + DiffuseCool * SurfaceColor, 1.0);\n"
|
|
"vec3 kwarm = min(WarmColor + DiffuseWarm * SurfaceColor, 1.0); \n"
|
|
"vec3 kfinal = mix(kcool, kwarm, NdotL);\n"
|
|
|
|
"vec3 nreflect = normalize(ReflectVec);\n"
|
|
"vec3 nview = normalize(ViewVec);\n"
|
|
|
|
"float spec = max(dot(nreflect, nview), 0.0);\n"
|
|
"spec = pow(spec, 32.0);\n"
|
|
|
|
"gl_FragColor = vec4 (min(kfinal + spec, 1.0), 1.0);\n"
|
|
"}\n";
|
|
|
|
// Callback for animating the WarmColor
|
|
|
|
class UniformBufferCallback : public StateAttributeCallback
|
|
{
|
|
public:
|
|
void operator() (StateAttribute* attr, NodeVisitor* nv)
|
|
{
|
|
UniformBufferBinding* ubb = static_cast<UniformBufferBinding*>(attr);
|
|
UniformBufferObject* ubo
|
|
= static_cast<UniformBufferObject*>(ubb->getBufferObject());
|
|
FloatArray* array = static_cast<FloatArray*>(ubo->getBufferData(0));
|
|
double time = nv->getFrameStamp()->getSimulationTime();
|
|
double frac = fmod(time, 1.0);
|
|
Vec4f warmColor = (Vec4f(0.0, 0.0, 1.0 ,1) * frac
|
|
+ Vec4f(1.0, 0.0, 0.0, 1) * (1 - frac));
|
|
// Since we're using the std140 layout, we know where the
|
|
// warmColor variable is located in the buffer.
|
|
for (int i = 0; i < 4; ++i)
|
|
(*array)[12 + i] = warmColor[i];
|
|
array->dirty();
|
|
}
|
|
};
|
|
|
|
int main(int argc, char** argv)
|
|
{
|
|
osg::ArgumentParser arguments(&argc,argv);
|
|
osgViewer::Viewer viewer(arguments);
|
|
|
|
if (arguments.argc() <= 1) {
|
|
cerr << "Need a scene.\n";
|
|
return 1;
|
|
}
|
|
|
|
osg::ref_ptr<osg::Node> loadedModel = osgDB::readRefNodeFiles(arguments);
|
|
if (!loadedModel) {
|
|
cerr << "couldn't load " << argv[1] << "\n";
|
|
return 1;
|
|
}
|
|
osgUtil::Optimizer optimizer;
|
|
optimizer.optimize(loadedModel.get());
|
|
const BoundingSphere bound = loadedModel->getBound();
|
|
const float displacement = 2.25 * bound.radius();
|
|
Group* scene = new Group;
|
|
StateSet* rootSS = scene->getOrCreateStateSet();
|
|
|
|
Shader* vertexShader = new Shader(Shader::VERTEX);
|
|
vertexShader->setShaderSource(vertexShaderSource);
|
|
Shader* fragmentShader = new Shader(Shader::FRAGMENT);
|
|
fragmentShader->setShaderSource(fragmentShaderSource);
|
|
Program* prog = new Program;
|
|
prog->addShader(vertexShader);
|
|
prog->addShader(fragmentShader);
|
|
prog->addBindUniformBlock("colors0", 0);
|
|
rootSS->setAttributeAndModes(prog, StateAttribute::ON);
|
|
// Place 3 instances of the loaded model with different uniform
|
|
// blocks for each.
|
|
//
|
|
// The blocksize is known because of the std140 format.
|
|
const unsigned blockSize = 20 * sizeof(GLfloat);
|
|
ref_ptr<FloatArray> colorArray
|
|
= new FloatArray(&colors1[0],
|
|
&colors1[sizeof(colors1) / sizeof(GLfloat)]);
|
|
ref_ptr<UniformBufferObject> ubo = new UniformBufferObject;
|
|
colorArray->setBufferObject(ubo.get());
|
|
Group* group1 = new Group;
|
|
StateSet* ss1 = group1->getOrCreateStateSet();
|
|
group1->addChild(loadedModel.get());
|
|
scene->addChild(group1);
|
|
ref_ptr<UniformBufferBinding> ubb1
|
|
= new UniformBufferBinding(0, ubo.get(), 0, blockSize);
|
|
ss1->setAttributeAndModes(ubb1.get(), StateAttribute::ON);
|
|
|
|
ref_ptr<FloatArray> colorArray2
|
|
= new FloatArray(&colors2[0],
|
|
&colors2[sizeof(colors2) / sizeof(GLfloat)]);
|
|
ref_ptr<UniformBufferObject> ubo2 = new UniformBufferObject;
|
|
colorArray2->setBufferObject(ubo2.get());
|
|
MatrixTransform* group2 = new MatrixTransform;
|
|
Matrix mat2 = Matrix::translate(-displacement, 0.0, 0.0);
|
|
group2->setMatrix(mat2);
|
|
StateSet* ss2 = group2->getOrCreateStateSet();
|
|
group2->addChild(loadedModel.get());
|
|
scene->addChild(group2);
|
|
ref_ptr<UniformBufferBinding> ubb2
|
|
= new UniformBufferBinding(0, ubo2.get(), 0, blockSize);
|
|
ss2->setAttributeAndModes(ubb2.get(), StateAttribute::ON);
|
|
|
|
ref_ptr<FloatArray> colorArray3
|
|
= new FloatArray(&colors2[0],
|
|
&colors2[sizeof(colors2) / sizeof(GLfloat)]);
|
|
ref_ptr<UniformBufferObject> ubo3 = new UniformBufferObject;
|
|
colorArray3->setBufferObject(ubo3.get());
|
|
MatrixTransform* group3 = new MatrixTransform;
|
|
Matrix mat3 = Matrix::translate(displacement, 0.0, 0.0);
|
|
group3->setMatrix(mat3);
|
|
StateSet* ss3 = group3->getOrCreateStateSet();
|
|
group3->addChild(loadedModel.get());
|
|
scene->addChild(group3);
|
|
ref_ptr<UniformBufferBinding> ubb3
|
|
= new UniformBufferBinding(0, ubo3.get(), 0, blockSize);
|
|
ubb3->setUpdateCallback(new UniformBufferCallback);
|
|
ubb3->setDataVariance(Object::DYNAMIC);
|
|
ss3->setAttributeAndModes(ubb3.get(), StateAttribute::ON);
|
|
|
|
viewer.setSceneData(scene);
|
|
viewer.realize();
|
|
return viewer.run();
|
|
}
|