From Marcus Hein, Added support for OpenGL SSBO and SSBB via osg::ShaderStorageBufferObject and osg::ShaderStorageBufferBinding to core OSG library, and added new osgSSBO example
git-svn-id: http://svn.openscenegraph.org/osg/OpenSceneGraph/trunk@14599 16af8721-9629-0410-8352-f15c8da7e697
This commit is contained in:
parent
92e2d849ed
commit
1b6e50a2dd
@ -97,6 +97,7 @@ IF(DYNAMIC_OPENSCENEGRAPH)
|
||||
ADD_SUBDIRECTORY(osgpresentation)
|
||||
ADD_SUBDIRECTORY(osgreflect)
|
||||
ADD_SUBDIRECTORY(osgrobot)
|
||||
ADD_SUBDIRECTORY(osgSSBO)
|
||||
ADD_SUBDIRECTORY(osgscalarbar)
|
||||
ADD_SUBDIRECTORY(osgscribe)
|
||||
ADD_SUBDIRECTORY(osgsequence)
|
||||
|
4
examples/osgSSBO/CMakeLists.txt
Normal file
4
examples/osgSSBO/CMakeLists.txt
Normal file
@ -0,0 +1,4 @@
|
||||
|
||||
SET(TARGET_SRC osgSSBO.cpp )
|
||||
|
||||
SETUP_EXAMPLE(osgSSBO)
|
945
examples/osgSSBO/osgSSBO.cpp
Normal file
945
examples/osgSSBO/osgSSBO.cpp
Normal file
@ -0,0 +1,945 @@
|
||||
//info : osgSSBO example,testing ShaderStorageBufferObjects ,Markus Hein, 2014, osg-3.2.1
|
||||
//required hardware and driver must support GL >= GL 4.3 or GL ES 3.1 (GL ES not tested, would be nice if someone will test it on a small device)
|
||||
|
||||
//testing osg support for Shader Storage Buffer Objects
|
||||
|
||||
//version: "first take" from last night session..
|
||||
|
||||
|
||||
|
||||
#include <osg/StateAttributeCallback>
|
||||
#include <osg/Texture2D>
|
||||
#include <osg/Geometry>
|
||||
#include <osg/Geode>
|
||||
#include <osgDB/ReadFile>
|
||||
#include <osgGA/StateSetManipulator>
|
||||
#include <osgViewer/Viewer>
|
||||
#include <osgViewer/ViewerEventHandlers>
|
||||
|
||||
#include <osg/Node>
|
||||
#include <osg/PositionAttitudeTransform>
|
||||
#include <osg/Geometry>
|
||||
#include <osg/Notify>
|
||||
#include <osg/MatrixTransform>
|
||||
#include <osg/Texture2D>
|
||||
#include <osg/TextureRectangle>
|
||||
#include <osg/Stencil>
|
||||
#include <osg/Depth>
|
||||
#include <osg/Billboard>
|
||||
#include <osg/Material>
|
||||
#include <osg/AnimationPath>
|
||||
|
||||
#include <osgGA/TrackballManipulator>
|
||||
#include <osgGA/FlightManipulator>
|
||||
#include <osgGA/DriveManipulator>
|
||||
|
||||
#include <osgUtil/SmoothingVisitor>
|
||||
|
||||
#include <osgDB/Registry>
|
||||
#include <osgDB/ReadFile>
|
||||
#include <osgDB/WriteFile>
|
||||
|
||||
#include <osgViewer/Viewer>
|
||||
#include <osgViewer/ViewerEventHandlers>
|
||||
#include <osgViewer/Renderer>
|
||||
|
||||
|
||||
#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 <osg/Drawable>
|
||||
#include <osg/CopyOp>
|
||||
#include <osg/State>
|
||||
#include <osg/Matrix>
|
||||
#include <osg/ShapeDrawable>
|
||||
#include <osg/GL>
|
||||
#include <osg/StateSet>
|
||||
#include <osg/Texture2D>
|
||||
#include <osg/BlendFunc>
|
||||
#include <osg/TexEnv>
|
||||
#include <osg/Material>
|
||||
#include <osg/PointSprite>
|
||||
#include <osg/Program>
|
||||
#include <osg/Notify>
|
||||
#include <osg/Point>
|
||||
#include <osg/io_utils>
|
||||
#include <osg/VertexProgram>
|
||||
|
||||
#include <osgText/Font>
|
||||
#include <osgText/Text>
|
||||
|
||||
|
||||
#include <osgDB/ReadFile>
|
||||
#include <osgDB/WriteFile>
|
||||
#include <osgDB/FileNameUtils>
|
||||
#include <osgUtil/Optimizer>
|
||||
#include <iostream>
|
||||
#include <typeinfo>
|
||||
|
||||
|
||||
using namespace osg;
|
||||
|
||||
|
||||
//todo .. #define COMPUTATION_IN_SEPARATE_THREAD
|
||||
|
||||
#define WORK_GROUP_SIZE 16
|
||||
|
||||
|
||||
#define PRERENDER_ANTIALIASINGMULTISAMPLES 16
|
||||
#define PRERENDER_HIGH_QUALITY_ANTIALIASING
|
||||
#define PRERENDER_WIDTH 1920
|
||||
#define PRERENDER_HEIGHT 1080
|
||||
|
||||
|
||||
#define SUB_PLACEMENT_OFFSET_HORIZONTAL 0.5
|
||||
#define SUB_PLACEMENT_OFFSET_VERTICAL 0.5
|
||||
|
||||
enum BufferOffset
|
||||
{
|
||||
POSITION_NOW_OFFSET,
|
||||
POSITION_OLD_OFFSET,
|
||||
POSITION_INIT_OFFSET,
|
||||
|
||||
VELOCITY_NOW_OFFSET,
|
||||
VELOCITY_OLD_OFFSET,
|
||||
VELOCITY_INIT_OFFSET,
|
||||
|
||||
ACCELERATION_OFFSET,
|
||||
PROPERTIES_OFFSET,
|
||||
|
||||
OFFSET_END
|
||||
};
|
||||
|
||||
|
||||
const int __numDataValuesPerChannel = OFFSET_END;
|
||||
const int __numChannels = 4;
|
||||
const float __particleRenderScaleMultiplier = 0.3;
|
||||
|
||||
//512x512x4x7 = 7.340.032 floats in SSBO on GPU
|
||||
const int NUM_ELEMENTS_X = 512;
|
||||
const int NUM_ELEMENTS_Y = 512;
|
||||
|
||||
float random(float min, float max) { return min + (max - min)*(float)rand() / (float)RAND_MAX; }
|
||||
|
||||
|
||||
enum Channel
|
||||
{
|
||||
RED_CHANNEL,
|
||||
GREEN_CHANNEL,
|
||||
BLUE_CHANNEL,
|
||||
ALPHA_CHANNEL,
|
||||
RGB_CHANNEL,
|
||||
RGBA_CHANNEL
|
||||
};
|
||||
|
||||
|
||||
|
||||
class ShaderStorageBufferCallback : public osg::StateAttributeCallback
|
||||
{
|
||||
public:
|
||||
void operator() (osg::StateAttribute* attr, osg::NodeVisitor* nv)
|
||||
{
|
||||
//if you need to process the data in your app-code , better leaving it on GPU and processing there, uploading per frame will make it slow
|
||||
#if 0
|
||||
osg::ShaderStorageBufferBinding* ssbb = static_cast<osg::ShaderStorageBufferBinding*>(attr);
|
||||
osg::ShaderStorageBufferObject* ssbo
|
||||
= static_cast<osg::ShaderStorageBufferObject*>(ssbb->getBufferObject());
|
||||
|
||||
osg::FloatArray* array = static_cast<osg::FloatArray*>(ssbo->getBufferData(0));
|
||||
|
||||
float someValue = array->at(0);
|
||||
//std::cout << "someValue now: " << someValue << std::endl;
|
||||
//data transfer performance test
|
||||
// array->dirty();
|
||||
#endif
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
//do not forget to set OSG_FILE_PATH to default OSG-Data and make sure the new shaders are copied there under"shaders"
|
||||
class ComputeNode : public osg::PositionAttitudeTransform
|
||||
{
|
||||
|
||||
public:
|
||||
|
||||
osg::ref_ptr<osg::Program> _computeProgram;
|
||||
osg::ref_ptr<osg::Shader> _computeShader; //compute and write position data in SSBO
|
||||
|
||||
osg::ref_ptr<osg::Shader> _vertexShader; //reading position data from SSBO (OBS!: make sure glMemoryBuffer() is syncing this)
|
||||
osg::ref_ptr<osg::Shader> _geometryShader; //building a quad looking to the camera
|
||||
osg::ref_ptr<osg::Shader> _fragmentShader; //use false-colors etc. for making your data visible
|
||||
|
||||
osg::ref_ptr<osg::Node> _helperNode; // coordinate system node
|
||||
|
||||
ref_ptr<osg::ShaderStorageBufferObject> _ssbo;
|
||||
ref_ptr<osg::ShaderStorageBufferBinding> _ssbb;
|
||||
|
||||
GLfloat* _data; // some data we upload to GPU, initialised with random values
|
||||
osg::ref_ptr<FloatArray> _dataArray; //
|
||||
|
||||
osg::ref_ptr<osg::Group> _computationResultsRenderGroup;
|
||||
osg::ref_ptr<osg::Program> _computationResultsRenderProgram;
|
||||
osg::ref_ptr<osg::StateSet> _computationResultsRenderStateSet;
|
||||
|
||||
|
||||
std::string _computeShaderSourcePath;
|
||||
std::string _vertexShaderSourcePath;
|
||||
std::string _geometryShaderSourcePath;
|
||||
std::string _fragmentShaderSourcePath;
|
||||
|
||||
|
||||
void addHelperGeometry();
|
||||
void addDataMonitor(osg::Vec3 placement, osg::Vec3 relativePlacement, float scale, Channel channel, BufferOffset shaderBufferOffset, std::string labelcaption, float minDataRange, float maxDataRange);
|
||||
void addComputationResultsRenderTree();
|
||||
void initComputingSetup();
|
||||
|
||||
ComputeNode()
|
||||
{
|
||||
const char* envOsgFilePath = getenv("OSG_FILE_PATH");
|
||||
std::stringstream computeshaderpath; computeshaderpath << envOsgFilePath << "/shaders/osgssboComputeShader.cs";
|
||||
_computeShaderSourcePath = computeshaderpath.str();
|
||||
std::stringstream vertexshaderpath; vertexshaderpath << envOsgFilePath << "/shaders/osgssboVertexShader.vs";
|
||||
_vertexShaderSourcePath = vertexshaderpath.str();
|
||||
std::stringstream geometryshaderpath; geometryshaderpath << envOsgFilePath << "/shaders/osgssboGeometryShader.gs";
|
||||
_geometryShaderSourcePath = geometryshaderpath.str();
|
||||
std::stringstream fragmentshaderpath; fragmentshaderpath << envOsgFilePath << "/shaders/osgssboFragmentShader.fs";
|
||||
_fragmentShaderSourcePath = fragmentshaderpath.str();
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
|
||||
class ComputeNodeUpdateCallback : public osg::NodeCallback
|
||||
{
|
||||
public:
|
||||
|
||||
ComputeNode* _computeNode;
|
||||
osg::Timer_t _prevShaderUpdateTime;
|
||||
osg::Timer _timer;
|
||||
|
||||
ComputeNodeUpdateCallback(){}
|
||||
|
||||
ComputeNodeUpdateCallback(ComputeNode* computeNode)
|
||||
{
|
||||
_computeNode = computeNode;
|
||||
_prevShaderUpdateTime = 0;
|
||||
}
|
||||
|
||||
virtual void operator()(osg::Node* node, osg::NodeVisitor* nv)
|
||||
{
|
||||
osg::Timer_t currTime = _timer.tick();
|
||||
|
||||
if (_timer.delta_s(_prevShaderUpdateTime, currTime) > 1.0) //one second interval for shader-changed-do-reload check
|
||||
{
|
||||
osg::ref_ptr<osg::Shader> reloadedshader;
|
||||
std::string runningSource;
|
||||
std::string reloadedstring;
|
||||
|
||||
if (_computeNode->_computeShader.valid())
|
||||
{
|
||||
runningSource = _computeNode->_computeShader->getShaderSource();
|
||||
reloadedshader = osg::Shader::readShaderFile(osg::Shader::COMPUTE, _computeNode->_computeShaderSourcePath);
|
||||
|
||||
reloadedstring = reloadedshader->getShaderSource();
|
||||
if (!osgDB::equalCaseInsensitive(runningSource.c_str(), reloadedstring.c_str()))
|
||||
{
|
||||
_computeNode->_computeProgram->removeShader(_computeNode->_computeShader.get());
|
||||
_computeNode->_computeShader = reloadedshader.get();
|
||||
_computeNode->_computeProgram->addShader(_computeNode->_computeShader.get());
|
||||
}
|
||||
}
|
||||
|
||||
if (_computeNode->_vertexShader.valid())
|
||||
{
|
||||
|
||||
runningSource = _computeNode->_vertexShader->getShaderSource();
|
||||
reloadedshader = osg::Shader::readShaderFile(osg::Shader::VERTEX, _computeNode->_vertexShaderSourcePath);
|
||||
|
||||
reloadedstring = reloadedshader->getShaderSource();
|
||||
if (!osgDB::equalCaseInsensitive(runningSource.c_str(), reloadedstring.c_str()))
|
||||
{
|
||||
_computeNode->_computationResultsRenderProgram->removeShader(_computeNode->_vertexShader.get());
|
||||
_computeNode->_vertexShader = reloadedshader.get();
|
||||
_computeNode->_computationResultsRenderProgram->addShader(_computeNode->_vertexShader.get());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
if (_computeNode->_geometryShader.valid())
|
||||
{
|
||||
runningSource = _computeNode->_geometryShader->getShaderSource();
|
||||
reloadedshader = osg::Shader::readShaderFile(osg::Shader::GEOMETRY, _computeNode->_geometryShaderSourcePath);
|
||||
|
||||
reloadedstring = reloadedshader->getShaderSource();
|
||||
if (!osgDB::equalCaseInsensitive(runningSource.c_str(), reloadedstring.c_str()))
|
||||
{
|
||||
_computeNode->_computationResultsRenderProgram->removeShader(_computeNode->_geometryShader.get());
|
||||
_computeNode->_geometryShader = reloadedshader.get();
|
||||
_computeNode->_computationResultsRenderProgram->addShader(_computeNode->_geometryShader.get());
|
||||
}
|
||||
}
|
||||
|
||||
if (_computeNode->_fragmentShader.valid())
|
||||
{
|
||||
runningSource = _computeNode->_fragmentShader->getShaderSource();
|
||||
reloadedshader = osg::Shader::readShaderFile(osg::Shader::FRAGMENT, _computeNode->_fragmentShaderSourcePath);
|
||||
|
||||
reloadedstring = reloadedshader->getShaderSource();
|
||||
if (!osgDB::equalCaseInsensitive(runningSource.c_str(), reloadedstring.c_str()))
|
||||
{
|
||||
_computeNode->_computationResultsRenderProgram->removeShader(_computeNode->_fragmentShader.get());
|
||||
_computeNode->_fragmentShader = reloadedshader.get();
|
||||
_computeNode->_computationResultsRenderProgram->addShader(_computeNode->_fragmentShader.get());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
_prevShaderUpdateTime = _timer.tick();
|
||||
}
|
||||
|
||||
traverse(node, nv);
|
||||
|
||||
}
|
||||
};
|
||||
|
||||
//set OSG_FILE_PATH for loading axes.osgt
|
||||
void ComputeNode::addHelperGeometry()
|
||||
{
|
||||
_helperNode = osgDB::readNodeFile("axes.osgt");
|
||||
|
||||
if (_helperNode.valid())
|
||||
{
|
||||
addChild(_helperNode.get());
|
||||
}
|
||||
|
||||
//osg::PositionAttitudeTransform* pat = new osg::PositionAttitudeTransform;
|
||||
//pat->setPosition(osg::Vec3(0.5, 0, 0.5));
|
||||
//osg::Geode *sphereGeode = new osg::Geode;
|
||||
//float radius = 0.5f;
|
||||
//osg::TessellationHints* hints = new osg::TessellationHints;
|
||||
//hints->setDetailRatio(0.9f);
|
||||
//osg::ShapeDrawable* sphere = new osg::ShapeDrawable(new osg::Sphere(osg::Vec3(0.0f, 0.0f, 0.0f), radius), hints);
|
||||
//sphereGeode->addDrawable(sphere);
|
||||
//sphere->setColor(osg::Vec4(0, 1, 0, 0.1));
|
||||
//osg::StateSet* stateset = sphereGeode->getOrCreateStateSet();
|
||||
//osg::BlendFunc *blend = new osg::BlendFunc;
|
||||
//blend->setFunction(osg::BlendFunc::SRC_ALPHA, osg::BlendFunc::ONE_MINUS_SRC_ALPHA);
|
||||
//stateset->setAttributeAndModes(blend, osg::StateAttribute::ON);
|
||||
//pat->addChild(sphereGeode);
|
||||
//addChild(pat);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
void ComputeNode::addDataMonitor(osg::Vec3 placement, osg::Vec3 relativePlacement, float scale, Channel colorchannel, BufferOffset shaderStorageBufferOffset, std::string labelCaption, float minDataRange, float maxDataRange)
|
||||
{
|
||||
osg::PositionAttitudeTransform* pat = new osg::PositionAttitudeTransform;
|
||||
pat->setPosition(relativePlacement);
|
||||
addChild(pat);
|
||||
osg::Geometry* geom;
|
||||
|
||||
if (NUM_ELEMENTS_X >= NUM_ELEMENTS_Y)
|
||||
{
|
||||
float ratio = (float)((float)NUM_ELEMENTS_Y / (float)NUM_ELEMENTS_X);
|
||||
geom = osg::createTexturedQuadGeometry(placement, osg::Vec3(1.0f*scale, 0.0f, 0.0f), osg::Vec3(0.0f, 0.0f, ratio*1.0f*scale));
|
||||
}
|
||||
else
|
||||
{
|
||||
float ratio = (float)((float)NUM_ELEMENTS_X / (float)NUM_ELEMENTS_Y);
|
||||
geom = osg::createTexturedQuadGeometry(placement, osg::Vec3(ratio*1.0f*scale, 0.0f, 0.0f), osg::Vec3(0.0f, 0.0f, 1.0f*scale));
|
||||
|
||||
}
|
||||
|
||||
geom->setVertexAttribArray(1, geom->getTexCoordArray(0), osg::Array::BIND_PER_VERTEX);
|
||||
|
||||
osg::ref_ptr<osg::Geode> quad = new osg::Geode;
|
||||
quad->addDrawable(geom);
|
||||
quad->setStateSet(getOrCreateStateSet());
|
||||
pat->addChild(quad.get());
|
||||
|
||||
static const char* vertexShaderSrcChannelMonitor = {
|
||||
|
||||
"#version 430 \n"
|
||||
|
||||
"uniform int numRows;\n"
|
||||
"uniform int numCols;\n"
|
||||
"uniform float osg_FrameTime;\n"
|
||||
"uniform mat4 osg_ProjectionMatrix;\n"
|
||||
"uniform mat4 osg_ModelViewMatrix;\n"
|
||||
"out vec2 texCoordFromVertexShader;\n"
|
||||
"struct particle{ float x; float y; float z; float w;};"
|
||||
"layout (location = 0) in vec3 vertexpos;\n"
|
||||
"attribute vec2 tex_coords;\n"
|
||||
"void main() {\n"
|
||||
"texCoordFromVertexShader.xy = tex_coords.xy; gl_Position = ( osg_ProjectionMatrix * osg_ModelViewMatrix * vec4(vertexpos.x,vertexpos.y,vertexpos.z,1) ); \n"
|
||||
"}\n"
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
std::stringstream fragmentshaderstringstreamChannelMonitor;
|
||||
fragmentshaderstringstreamChannelMonitor << "#version 430\n";
|
||||
fragmentshaderstringstreamChannelMonitor << "uniform int numRows;\n";
|
||||
fragmentshaderstringstreamChannelMonitor << "uniform int numCols;\n";
|
||||
fragmentshaderstringstreamChannelMonitor << "uniform float dataRangeMin;\n";
|
||||
fragmentshaderstringstreamChannelMonitor << "uniform float dataRangeMax;\n";
|
||||
fragmentshaderstringstreamChannelMonitor << "in vec2 texCoordFromVertexShader;\n";
|
||||
fragmentshaderstringstreamChannelMonitor << "struct particle{ float x; float y; float z; float w;};";
|
||||
fragmentshaderstringstreamChannelMonitor << "layout(std140, binding=0) coherent buffer particles{particle p[];}; ";
|
||||
fragmentshaderstringstreamChannelMonitor << "\n";
|
||||
fragmentshaderstringstreamChannelMonitor << "void main(void)\n";
|
||||
fragmentshaderstringstreamChannelMonitor << "{\n";
|
||||
fragmentshaderstringstreamChannelMonitor << "ivec2 storePos = ivec2(numRows*texCoordFromVertexShader.x, numCols*texCoordFromVertexShader.y); particle particleData = p[" << shaderStorageBufferOffset * NUM_ELEMENTS_X*NUM_ELEMENTS_Y << " + (storePos.x*numRows + storePos.y)]; ";
|
||||
|
||||
//fragmentshaderstringstreamChannelMonitor << " memoryBarrierBuffer(); \n";
|
||||
fragmentshaderstringstreamChannelMonitor << " float dataRangeMultiplier = 1.0 / abs(dataRangeMax - dataRangeMin); \n";
|
||||
|
||||
switch (colorchannel)
|
||||
{
|
||||
case RED_CHANNEL:
|
||||
{
|
||||
fragmentshaderstringstreamChannelMonitor << " vec4 color; color.x = 0.5+dataRangeMultiplier*particleData.x; color.y =0.0; color.z = 0.0; color.w = 1.0; gl_FragColor = color;\n";
|
||||
|
||||
break;
|
||||
}
|
||||
case GREEN_CHANNEL:
|
||||
{
|
||||
fragmentshaderstringstreamChannelMonitor << " vec4 color; color.x = 0.0; color.y = 0.5+dataRangeMultiplier*particleData.y; color.z = 0.0; color.w = 1.0; gl_FragColor = color;\n";
|
||||
break;
|
||||
}
|
||||
case BLUE_CHANNEL:
|
||||
{
|
||||
fragmentshaderstringstreamChannelMonitor << " vec4 color; color.x = 0.0; color.y = 0.0; color.z = 0.5+dataRangeMultiplier*particleData.z; color.w = 0.0 ; gl_FragColor = color;\n";
|
||||
break;
|
||||
}
|
||||
case ALPHA_CHANNEL:
|
||||
{
|
||||
fragmentshaderstringstreamChannelMonitor << " vec4 color; color.x = 0.5+dataRangeMultiplier*particleData.w; color.y = 0.5+dataRangeMultiplier*particleData.w; color.z = 0.5+dataRangeMultiplier*particleData.w; color.w = 0.5+0.5*particleData.w; gl_FragColor = color;\n";
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
case RGB_CHANNEL:
|
||||
{
|
||||
fragmentshaderstringstreamChannelMonitor << " vec4 color; color.x = 0.5+dataRangeMultiplier*particleData.x; color.y = 0.5+dataRangeMultiplier*particleData.y; color.z = 0.5+dataRangeMultiplier*particleData.z; color.w = 1.0; gl_FragColor = color;\n";
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
fragmentshaderstringstreamChannelMonitor << "}\n";
|
||||
|
||||
|
||||
|
||||
|
||||
osg::Program * program = new osg::Program;
|
||||
program->addShader(new osg::Shader(osg::Shader::VERTEX, vertexShaderSrcChannelMonitor));
|
||||
program->addShader(new osg::Shader(osg::Shader::FRAGMENT, fragmentshaderstringstreamChannelMonitor.str().c_str()));
|
||||
program->addBindAttribLocation("tex_coords", 1);
|
||||
|
||||
osg::StateSet* ss = geom->getOrCreateStateSet();
|
||||
ss->setAttributeAndModes(program, osg::StateAttribute::ON);
|
||||
ss->addUniform(new osg::Uniform("numRows", (int)NUM_ELEMENTS_X));
|
||||
ss->addUniform(new osg::Uniform("numCols", (int)NUM_ELEMENTS_Y));
|
||||
|
||||
ss->addUniform(new osg::Uniform("dataRangeMin", (float)minDataRange));
|
||||
ss->addUniform(new osg::Uniform("dataRangeMax", (float)maxDataRange));
|
||||
|
||||
|
||||
ss->setMode(GL_LIGHTING, osg::StateAttribute::OFF);
|
||||
|
||||
//add a label
|
||||
osgText::Text* text = new osgText::Text;
|
||||
osgText::Font* font = osgText::readFontFile("fonts/arial.ttf");
|
||||
text->setFont(font);
|
||||
text->setColor(osg::Vec4(1, 1, 1, 1));
|
||||
text->setCharacterSize(0.1*scale);
|
||||
text->setPosition(placement + osg::Vec3(0.05, 0.05, 0));
|
||||
pat->setName(labelCaption);
|
||||
text->setText(pat->getName());
|
||||
text->setBackdropType(osgText::Text::OUTLINE);
|
||||
text->setBackdropImplementation(osgText::Text::POLYGON_OFFSET);
|
||||
text->setBackdropOffset(0.05f);
|
||||
text->setBackdropColor(osg::Vec4(0.0f, 0.0f, 0.0f, 1.0f));
|
||||
|
||||
quad->addDrawable(text);
|
||||
|
||||
pat->addChild(quad.get());
|
||||
|
||||
}
|
||||
|
||||
//compute texture image , taken from osgspotlight
|
||||
osg::Image* createSpotLightImage(const osg::Vec4& centerColour, const osg::Vec4& backgroudColour, unsigned int size, float power)
|
||||
{
|
||||
osg::Image* image = new osg::Image;
|
||||
image->allocateImage(size, size, 1,
|
||||
GL_RGBA, GL_UNSIGNED_BYTE);
|
||||
|
||||
|
||||
float mid = (float(size) - 1)*0.5f;
|
||||
float div = 2.0f / float(size);
|
||||
for (unsigned int r = 0; r < size; ++r)
|
||||
{
|
||||
unsigned char* ptr = image->data(0, r, 0);
|
||||
for (unsigned int c = 0; c < size; ++c)
|
||||
{
|
||||
float dx = (float(c) - mid)*div;
|
||||
float dy = (float(r) - mid)*div;
|
||||
float r = powf(1.0f - sqrtf(dx*dx + dy*dy), power);
|
||||
if (r < 0.0f) r = 0.0f;
|
||||
osg::Vec4 color = centerColour*r + backgroudColour*(1.0f - r);
|
||||
*ptr++ = (unsigned char)((color[0])*255.0f);
|
||||
*ptr++ = (unsigned char)((color[1])*255.0f);
|
||||
*ptr++ = (unsigned char)((color[2])*255.0f);
|
||||
*ptr++ = (unsigned char)((color[3])*255.0f);
|
||||
}
|
||||
}
|
||||
return image;
|
||||
}
|
||||
|
||||
|
||||
void ComputeNode::addComputationResultsRenderTree()
|
||||
{
|
||||
|
||||
_computationResultsRenderProgram = new osg::Program;
|
||||
|
||||
_vertexShader = osg::Shader::readShaderFile(osg::Shader::VERTEX, _vertexShaderSourcePath);
|
||||
_computationResultsRenderProgram->addShader(_vertexShader.get());
|
||||
|
||||
_geometryShader = osg::Shader::readShaderFile(osg::Shader::GEOMETRY, _geometryShaderSourcePath);
|
||||
_computationResultsRenderProgram->addShader(_geometryShader.get());
|
||||
|
||||
_fragmentShader = osg::Shader::readShaderFile(osg::Shader::FRAGMENT, _fragmentShaderSourcePath);
|
||||
_computationResultsRenderProgram->addShader(_fragmentShader.get());
|
||||
|
||||
|
||||
_computationResultsRenderProgram->addBindAttribLocation("tex_coords", 1);
|
||||
|
||||
_computationResultsRenderGroup = new osg::Group;
|
||||
_computationResultsRenderGroup->setDataVariance(osg::Object::DYNAMIC);
|
||||
_computationResultsRenderStateSet = _computationResultsRenderGroup->getOrCreateStateSet();
|
||||
_computationResultsRenderStateSet->setRenderingHint(osg::StateSet::TRANSPARENT_BIN);
|
||||
|
||||
osg::PointSprite *sprite = new osg::PointSprite;
|
||||
int texture_unit = 0;
|
||||
_computationResultsRenderStateSet->setTextureAttributeAndModes(texture_unit, sprite, osg::StateAttribute::ON);
|
||||
_computationResultsRenderStateSet->setAttributeAndModes(_computationResultsRenderProgram, osg::StateAttribute::ON);
|
||||
_computationResultsRenderStateSet->addUniform(new osg::Uniform("particleTexture", texture_unit));
|
||||
_computationResultsRenderStateSet->addUniform(new osg::Uniform("numRows", (int)NUM_ELEMENTS_X));
|
||||
_computationResultsRenderStateSet->addUniform(new osg::Uniform("numCols", (int)NUM_ELEMENTS_Y));
|
||||
|
||||
|
||||
_computationResultsRenderStateSet->setMode(GL_POINT_SMOOTH, osg::StateAttribute::ON);
|
||||
_computationResultsRenderStateSet->setMode(GL_VERTEX_PROGRAM_POINT_SIZE_ARB, osg::StateAttribute::ON);
|
||||
_computationResultsRenderStateSet->setMode(GL_ALPHA_TEST, osg::StateAttribute::ON);
|
||||
_computationResultsRenderStateSet->setMode(GL_LIGHTING, osg::StateAttribute::OFF);
|
||||
|
||||
osg::Texture2D *tex = new osg::Texture2D();
|
||||
|
||||
osg::Image* particleImage = createSpotLightImage(osg::Vec4(1, 0, 0, 1), osg::Vec4(0.5, 0, 0, 0.0), 32, 0.7);
|
||||
if (particleImage)
|
||||
{
|
||||
tex->setImage(particleImage);
|
||||
}
|
||||
_computationResultsRenderStateSet->setTextureAttributeAndModes(texture_unit, tex, osg::StateAttribute::ON);
|
||||
|
||||
|
||||
osg::BlendFunc *blend = new osg::BlendFunc;
|
||||
if (false) //emissive particles
|
||||
{
|
||||
blend->setFunction(osg::BlendFunc::SRC_ALPHA, osg::BlendFunc::ONE);
|
||||
}
|
||||
else
|
||||
{
|
||||
blend->setFunction(osg::BlendFunc::SRC_ALPHA, osg::BlendFunc::ONE_MINUS_SRC_ALPHA);
|
||||
}
|
||||
|
||||
_computationResultsRenderStateSet->setAttributeAndModes(blend, osg::StateAttribute::ON);
|
||||
|
||||
|
||||
osg::Depth* depth = new osg::Depth;
|
||||
depth->setRange(0.0f, 0.0f);
|
||||
depth->setFunction(osg::Depth::ALWAYS);
|
||||
depth->setWriteMask(false);
|
||||
depth->setFunction(osg::Depth::ALWAYS);
|
||||
|
||||
_computationResultsRenderStateSet->setAttributeAndModes(depth, osg::StateAttribute::OFF);
|
||||
|
||||
|
||||
osg::Geode* particleGeode = new osg::Geode;
|
||||
unsigned int numVertices = NUM_ELEMENTS_X*NUM_ELEMENTS_Y;
|
||||
|
||||
osg::Geometry* particleGeometry = new osg::Geometry;
|
||||
particleGeometry->setUseDisplayList(false);
|
||||
particleGeometry->setUseVertexBufferObjects(true);
|
||||
|
||||
osg::Vec3Array* vertexarray = new osg::Vec3Array;
|
||||
osg::Vec2Array* tcoords = new osg::Vec2Array;
|
||||
|
||||
osg::Vec2 bottom_texcoord(0.0f, 0.0f);
|
||||
|
||||
osg::Vec2 dx_texcoord(1.0f / (float)(NUM_ELEMENTS_X), 0.0f);
|
||||
osg::Vec2 dy_texcoord(0.0f, 1.0f / (float)(NUM_ELEMENTS_Y));
|
||||
|
||||
|
||||
|
||||
for (int i = 0; i < NUM_ELEMENTS_X; i++)
|
||||
{
|
||||
osg::Vec2 texcoord = bottom_texcoord + dy_texcoord*(float)i;
|
||||
|
||||
for (int j = 0; j < NUM_ELEMENTS_Y; j++)
|
||||
{
|
||||
vertexarray->push_back(osg::Vec3(texcoord.x(), texcoord.y(), 0.0));
|
||||
tcoords->push_back(osg::Vec2(texcoord.x(), texcoord.y()));
|
||||
texcoord += dx_texcoord;
|
||||
}
|
||||
}
|
||||
|
||||
particleGeometry->setVertexArray(vertexarray);
|
||||
particleGeometry->addPrimitiveSet(new osg::DrawArrays(GL_POINTS, 0, numVertices));
|
||||
particleGeometry->setTexCoordArray(0, tcoords);
|
||||
//this glMemoryBarrier thing... not sure if we could better do instanced drawing? all the data is in Shader Storage Buffer..
|
||||
particleGeometry->setVertexAttribArray(1, particleGeometry->getTexCoordArray(0), osg::Array::BIND_PER_VERTEX);
|
||||
|
||||
_computationResultsRenderGroup->addChild(particleGeode);
|
||||
particleGeode->addDrawable(particleGeometry);
|
||||
|
||||
addChild(_computationResultsRenderGroup);
|
||||
|
||||
}
|
||||
|
||||
|
||||
void ComputeNode::initComputingSetup()
|
||||
{
|
||||
|
||||
_computeProgram = new osg::Program;
|
||||
_computeProgram->setComputeGroups((NUM_ELEMENTS_X / WORK_GROUP_SIZE) <= 1 ? 1 : (NUM_ELEMENTS_X / WORK_GROUP_SIZE), (NUM_ELEMENTS_Y / WORK_GROUP_SIZE) <= 1 ? 1 : (NUM_ELEMENTS_Y / WORK_GROUP_SIZE), 1);
|
||||
_computeShader = osg::Shader::readShaderFile(osg::Shader::COMPUTE, _computeShaderSourcePath);
|
||||
_computeProgram->addShader(_computeShader.get());
|
||||
|
||||
setDataVariance(osg::Object::DYNAMIC);
|
||||
osg::StateSet* statesetComputation = getOrCreateStateSet();
|
||||
statesetComputation->setAttributeAndModes(_computeProgram.get());
|
||||
statesetComputation->addUniform(new osg::Uniform("numCols", (int)NUM_ELEMENTS_X));
|
||||
statesetComputation->addUniform(new osg::Uniform("numRows", (int)NUM_ELEMENTS_Y));
|
||||
statesetComputation->setMode(GL_LIGHTING, osg::StateAttribute::OFF);
|
||||
|
||||
//blocksize
|
||||
int numParticles = NUM_ELEMENTS_X * NUM_ELEMENTS_Y;
|
||||
const unsigned blockSize = numParticles * __numChannels * __numDataValuesPerChannel* sizeof(GLfloat);
|
||||
|
||||
//init all the particle data array
|
||||
int idx = 0;
|
||||
_data = new GLfloat[NUM_ELEMENTS_X * NUM_ELEMENTS_Y * __numChannels * __numDataValuesPerChannel];
|
||||
_dataArray = new FloatArray;
|
||||
|
||||
//init the data array somehow, this way all is stored in one BufferObject. maybe better using multiple buffers instead? not sure what is faster and better for threading
|
||||
for (int d = 0; d < __numDataValuesPerChannel; ++d)
|
||||
{
|
||||
for (int i = 0; i < NUM_ELEMENTS_X; ++i)
|
||||
{
|
||||
|
||||
for (int j = 0; j < NUM_ELEMENTS_Y; ++j)
|
||||
{
|
||||
|
||||
for (int k = 0; k < __numChannels; ++k)
|
||||
{
|
||||
switch (k)
|
||||
{
|
||||
|
||||
case (RED_CHANNEL) :
|
||||
{
|
||||
if ((d == POSITION_NOW_OFFSET) || (d == POSITION_OLD_OFFSET) || (d == POSITION_INIT_OFFSET))//position
|
||||
{
|
||||
*_data = random(0.25, 0.75);
|
||||
}
|
||||
if ((d == VELOCITY_NOW_OFFSET) || (d == VELOCITY_OLD_OFFSET) || (d == VELOCITY_INIT_OFFSET))//velocity
|
||||
{
|
||||
*_data = random(-2.4, 2.4);
|
||||
}
|
||||
if (d == ACCELERATION_OFFSET) //acceleration
|
||||
{
|
||||
*_data = random(-3.0, 3.0);
|
||||
}
|
||||
|
||||
if (d == PROPERTIES_OFFSET) //property particle mass (compute shader is computing sphere mass from radius instead)
|
||||
{
|
||||
*_data = random(0.2, 15.0);
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case (GREEN_CHANNEL) :
|
||||
{
|
||||
if ((d == POSITION_NOW_OFFSET) || (d == POSITION_OLD_OFFSET) || (d == POSITION_INIT_OFFSET))//position
|
||||
{
|
||||
*_data = random(0.25, 0.75);
|
||||
}
|
||||
if ((d == VELOCITY_NOW_OFFSET) || (d == VELOCITY_OLD_OFFSET) || (d == VELOCITY_INIT_OFFSET))//velocity
|
||||
{
|
||||
*_data = random(-2.4, 2.4);
|
||||
}
|
||||
|
||||
if (d == ACCELERATION_OFFSET)//acceleration
|
||||
{
|
||||
*_data = random(-3.0, 3.0);
|
||||
}
|
||||
if (d == PROPERTIES_OFFSET) //property particle radius
|
||||
{
|
||||
*_data = random(0.07, 0.219);
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case (BLUE_CHANNEL) :
|
||||
{
|
||||
if ((d == POSITION_NOW_OFFSET) || (d == POSITION_OLD_OFFSET) || (d == POSITION_INIT_OFFSET))//position
|
||||
{
|
||||
*_data = random(0.25, 0.75);
|
||||
}
|
||||
if ((d == VELOCITY_NOW_OFFSET) || (d == VELOCITY_OLD_OFFSET) || (d == VELOCITY_INIT_OFFSET))//velocity
|
||||
{
|
||||
*_data = random(-2.4, 2.4);
|
||||
}
|
||||
|
||||
if (d == ACCELERATION_OFFSET)//acceleration
|
||||
{
|
||||
*_data = random(-3.0, 3.0);
|
||||
}
|
||||
|
||||
|
||||
if (d == PROPERTIES_OFFSET) //place for some other property
|
||||
{
|
||||
*_data = random(0.0, 0.0);
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case (ALPHA_CHANNEL) :
|
||||
{
|
||||
if ((d == POSITION_NOW_OFFSET) || (d == POSITION_OLD_OFFSET) || (d == POSITION_INIT_OFFSET))//position
|
||||
{
|
||||
*_data = random(1.0, 1.0);
|
||||
}
|
||||
if ((d == VELOCITY_NOW_OFFSET) || (d == VELOCITY_OLD_OFFSET) || (d == VELOCITY_INIT_OFFSET))//velocity
|
||||
{
|
||||
*_data = random(-2.4, 2.4);
|
||||
}
|
||||
|
||||
if (d == ACCELERATION_OFFSET) //acceleration
|
||||
{
|
||||
//*_data = random(1.0, 1.0);
|
||||
*_data = random(0.0, 0.0);
|
||||
}
|
||||
|
||||
if (d == PROPERTIES_OFFSET) //place for some other property
|
||||
{
|
||||
*_data = random(0.3, 0.3);
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
_dataArray->push_back(*_data);
|
||||
_data++;
|
||||
idx++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
_ssbo = new osg::ShaderStorageBufferObject;
|
||||
_dataArray->setBufferObject(_ssbo.get());
|
||||
|
||||
|
||||
_ssbb = new osg::ShaderStorageBufferBinding(0, _ssbo.get(), 0, blockSize);
|
||||
statesetComputation->setAttributeAndModes(_ssbb.get(), osg::StateAttribute::ON);
|
||||
|
||||
|
||||
//option, do something useful with data or test the transfer speed
|
||||
//_ssbb->setUpdateCallback(new ShaderStorageBufferCallback);
|
||||
|
||||
//adding a quad , visualizing data in buffer
|
||||
addDataMonitor(osg::Vec3(0, -1, 0), osg::Vec3(SUB_PLACEMENT_OFFSET_HORIZONTAL * 0, -SUB_PLACEMENT_OFFSET_VERTICAL * -2.0, SUB_PLACEMENT_OFFSET_HORIZONTAL * 0), 1.0, RGB_CHANNEL, POSITION_NOW_OFFSET, "X,Y,Z - PositionNow", -1.0, 1.0);
|
||||
|
||||
//the coord from default dataset
|
||||
addHelperGeometry();
|
||||
|
||||
|
||||
addComputationResultsRenderTree();
|
||||
|
||||
}
|
||||
|
||||
|
||||
//taken from osgdistorsion example for getting it nice on screen with antialiasing
|
||||
osg::Node* createPrerenderSubgraph(osg::Node* subgraph, const osg::Vec4& clearColour)
|
||||
{
|
||||
osg::Group* prerenderNode = new osg::Group;
|
||||
|
||||
unsigned int tex_width = PRERENDER_WIDTH;
|
||||
unsigned int tex_height = PRERENDER_HEIGHT;
|
||||
|
||||
osg::Texture2D* texture = new osg::Texture2D;
|
||||
texture->setTextureSize(tex_width, tex_height);
|
||||
texture->setInternalFormat(GL_RGBA);
|
||||
texture->setFilter(osg::Texture2D::MIN_FILTER, osg::Texture2D::LINEAR);
|
||||
texture->setFilter(osg::Texture2D::MAG_FILTER, osg::Texture2D::LINEAR);
|
||||
|
||||
{
|
||||
osg::Camera* prerenderCamera = new osg::Camera;
|
||||
prerenderCamera->setClearColor(clearColour);
|
||||
prerenderCamera->setClearMask(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
|
||||
prerenderCamera->setReferenceFrame(osg::Transform::RELATIVE_RF);
|
||||
prerenderCamera->setProjectionMatrix(osg::Matrixd::identity());
|
||||
prerenderCamera->setViewMatrix(osg::Matrixd::identity());
|
||||
prerenderCamera->setViewport(0, 0, tex_width, tex_height);
|
||||
prerenderCamera->setRenderOrder(osg::Camera::PRE_RENDER);
|
||||
prerenderCamera->setRenderTargetImplementation(osg::Camera::FRAME_BUFFER_OBJECT);
|
||||
prerenderCamera->attach(osg::Camera::COLOR_BUFFER0, texture, 0, 0, false, PRERENDER_ANTIALIASINGMULTISAMPLES, PRERENDER_ANTIALIASINGMULTISAMPLES);
|
||||
prerenderCamera->addChild(subgraph);
|
||||
prerenderNode->addChild(prerenderCamera);
|
||||
|
||||
}
|
||||
|
||||
{
|
||||
osg::Geometry* polyGeom = new osg::Geometry();
|
||||
|
||||
polyGeom->setSupportsDisplayList(false);
|
||||
|
||||
osg::Vec3 origin(0.0f, 0.0f, 0.0f);
|
||||
osg::Vec3 xAxis(1.0f, 0.0f, 0.0f);
|
||||
osg::Vec3 yAxis(0.0f, 1.0f, 0.0f);
|
||||
|
||||
float height = 1024.0f;
|
||||
float width = 1280.0f;
|
||||
int noSteps = 3;
|
||||
|
||||
osg::Vec3Array* vertices = new osg::Vec3Array;
|
||||
osg::Vec2Array* texcoords = new osg::Vec2Array;
|
||||
osg::Vec4Array* colors = new osg::Vec4Array;
|
||||
|
||||
osg::Vec3 bottom = origin;
|
||||
osg::Vec3 dx = xAxis*(width / ((float)(noSteps - 1)));
|
||||
osg::Vec3 dy = yAxis*(height / ((float)(noSteps - 1)));
|
||||
|
||||
osg::Vec2 bottom_texcoord(0.0f, 0.0f);
|
||||
osg::Vec2 dx_texcoord(1.0f / (float)(noSteps - 1), 0.0f);
|
||||
osg::Vec2 dy_texcoord(0.0f, 1.0f / (float)(noSteps - 1));
|
||||
|
||||
int i, j;
|
||||
for (i = 0; i < noSteps; ++i)
|
||||
{
|
||||
osg::Vec3 cursor = bottom + dy*(float)i;
|
||||
osg::Vec2 texcoord = bottom_texcoord + dy_texcoord*(float)i;
|
||||
for (j = 0; j < noSteps; ++j)
|
||||
{
|
||||
vertices->push_back(cursor);
|
||||
texcoords->push_back(osg::Vec2((sin(texcoord.x()*osg::PI - osg::PI*0.5) + 1.0f)*0.5f, (sin(texcoord.y()*osg::PI - osg::PI*0.5) + 1.0f)*0.5f));
|
||||
colors->push_back(osg::Vec4(1.0f, 1.0f, 1.0f, 1.0f));
|
||||
cursor += dx;
|
||||
texcoord += dx_texcoord;
|
||||
}
|
||||
}
|
||||
|
||||
polyGeom->setVertexArray(vertices);
|
||||
polyGeom->setColorArray(colors, osg::Array::BIND_PER_VERTEX);
|
||||
polyGeom->setTexCoordArray(0, texcoords);
|
||||
|
||||
for (i = 0; i < noSteps - 1; ++i)
|
||||
{
|
||||
osg::DrawElementsUShort* elements = new osg::DrawElementsUShort(osg::PrimitiveSet::QUAD_STRIP);
|
||||
for (j = 0; j < noSteps; ++j)
|
||||
{
|
||||
elements->push_back(j + (i + 1)*noSteps);
|
||||
elements->push_back(j + (i)*noSteps);
|
||||
}
|
||||
polyGeom->addPrimitiveSet(elements);
|
||||
}
|
||||
|
||||
osg::StateSet* stateset = polyGeom->getOrCreateStateSet();
|
||||
stateset->setTextureAttributeAndModes(0, texture, osg::StateAttribute::ON);
|
||||
stateset->setMode(GL_LIGHTING, osg::StateAttribute::OFF);
|
||||
|
||||
osg::Geode* geode = new osg::Geode();
|
||||
geode->addDrawable(polyGeom);
|
||||
|
||||
osg::Camera* nestedRenderCamera = new osg::Camera;
|
||||
nestedRenderCamera->setReferenceFrame(osg::Transform::ABSOLUTE_RF);
|
||||
nestedRenderCamera->setViewMatrix(osg::Matrix::identity());
|
||||
nestedRenderCamera->setProjectionMatrixAsOrtho2D(0, 1280, 0, 1024);
|
||||
nestedRenderCamera->setRenderOrder(osg::Camera::NESTED_RENDER);
|
||||
nestedRenderCamera->addChild(geode);
|
||||
|
||||
prerenderNode->addChild(nestedRenderCamera);
|
||||
}
|
||||
|
||||
return prerenderNode;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
int main(int argc, char** argv)
|
||||
{
|
||||
osg::ArgumentParser arguments(&argc, argv);
|
||||
|
||||
osgViewer::Viewer viewer;
|
||||
|
||||
osg::ref_ptr<osg::Group> scene = new osg::Group;
|
||||
|
||||
|
||||
viewer.addEventHandler(new osgGA::StateSetManipulator(viewer.getCamera()->getOrCreateStateSet()));
|
||||
viewer.addEventHandler(new osgViewer::StatsHandler);
|
||||
viewer.addEventHandler(new osgViewer::WindowSizeHandler);
|
||||
viewer.addEventHandler(new osgViewer::ThreadingHandler);
|
||||
viewer.getCamera()->setProjectionMatrixAsPerspective(60.0f, 1.33333, 0.01, 100.0);
|
||||
viewer.setCameraManipulator(new osgGA::TrackballManipulator());
|
||||
|
||||
viewer.setUpViewInWindow(11, 11, 800 + 11, 600 + 11);
|
||||
//viewer.setUpViewOnSingleScreen(0); // !!
|
||||
|
||||
viewer.getCamera()->setClearColor(osg::Vec4(0.3, 0.3, 0.3, 1.0));
|
||||
viewer.setThreadingModel(osgViewer::Viewer::SingleThreaded);// we can play with threading models later
|
||||
|
||||
osg::ref_ptr<ComputeNode> computeNode = new ComputeNode();
|
||||
computeNode->setPosition(osg::Vec3(0, 0, 0));
|
||||
computeNode->setUpdateCallback(new ComputeNodeUpdateCallback(computeNode)); // on-the-fly reloading the shaders if shader source on disk is changed
|
||||
computeNode->initComputingSetup();
|
||||
|
||||
|
||||
|
||||
scene->addChild(computeNode.get());
|
||||
scene->addChild(computeNode->_computationResultsRenderGroup.get());
|
||||
|
||||
|
||||
#ifdef PRERENDER_HIGH_QUALITY_ANTIALIASING
|
||||
viewer.setSceneData(createPrerenderSubgraph(scene.get(), osg::Vec4(0.3, 0.4, 0.6, 1)));
|
||||
#else
|
||||
viewer.setSceneData(scene.get());
|
||||
#endif
|
||||
|
||||
viewer.realize();
|
||||
|
||||
viewer.getCamera()->getGraphicsContext()->getState()->setUseModelViewAndProjectionUniforms(true);
|
||||
|
||||
viewer.run();
|
||||
|
||||
return 1;
|
||||
}
|
@ -164,6 +164,35 @@ class OSG_EXPORT AtomicCounterBufferBinding : public BufferIndexBinding
|
||||
}
|
||||
};
|
||||
|
||||
class OSG_EXPORT ShaderStorageBufferBinding : public BufferIndexBinding
|
||||
{
|
||||
public:
|
||||
ShaderStorageBufferBinding(GLuint index=0);
|
||||
/** Create a binding for a shader storage buffer index target.
|
||||
* @param index the index target
|
||||
* @param bo associated buffer object
|
||||
* @param offset offset into buffer object
|
||||
* @param size size of data in buffer object
|
||||
*/
|
||||
ShaderStorageBufferBinding(GLuint index, BufferObject* bo, GLintptr offset, GLsizeiptr size);
|
||||
ShaderStorageBufferBinding(const ShaderStorageBufferBinding& rhs, const CopyOp& copyop=CopyOp::SHALLOW_COPY);
|
||||
META_StateAttribute(osg, ShaderStorageBufferBinding, SHADERSTORAGEBUFFERBINDING);
|
||||
|
||||
virtual int compare(const StateAttribute& bb) const
|
||||
{
|
||||
COMPARE_StateAttribute_Types(ShaderStorageBufferBinding, bb)
|
||||
COMPARE_StateAttribute_Parameter(_target)
|
||||
COMPARE_StateAttribute_Parameter(_index)
|
||||
COMPARE_StateAttribute_Parameter(_bufferObject)
|
||||
COMPARE_StateAttribute_Parameter(_offset)
|
||||
COMPARE_StateAttribute_Parameter(_size)
|
||||
return 0;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
} // namespace osg
|
||||
|
||||
#endif
|
||||
|
@ -732,6 +732,7 @@ class OSG_EXPORT PixelDataBufferObject : public BufferObject
|
||||
|
||||
};
|
||||
|
||||
|
||||
class OSG_EXPORT UniformBufferObject : public BufferObject
|
||||
{
|
||||
public:
|
||||
@ -759,6 +760,20 @@ inline void GLBufferObject::bindBuffer()
|
||||
if (_set) _set->moveToBack(this);
|
||||
}
|
||||
|
||||
|
||||
class OSG_EXPORT ShaderStorageBufferObject : public BufferObject
|
||||
{
|
||||
public:
|
||||
|
||||
ShaderStorageBufferObject();
|
||||
ShaderStorageBufferObject(const ShaderStorageBufferObject& ubo, const CopyOp& copyop=CopyOp::SHALLOW_COPY);
|
||||
META_Object(osg, ShaderStorageBufferObject);
|
||||
protected:
|
||||
virtual ~ShaderStorageBufferObject();
|
||||
};
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
|
@ -199,6 +199,8 @@ class OSG_EXPORT StateAttribute : public Object
|
||||
|
||||
VERTEX_ATTRIB_DIVISOR,
|
||||
|
||||
SHADERSTORAGEBUFFERBINDING,
|
||||
|
||||
CAPABILITY = 100
|
||||
};
|
||||
|
||||
|
@ -143,4 +143,26 @@ void AtomicCounterBufferBinding::readData(osg::State & state, osg::UIntArray & u
|
||||
bo->_extensions->glBindBuffer(GL_ATOMIC_COUNTER_BUFFER, static_cast<GLuint>(previousID));
|
||||
}
|
||||
|
||||
|
||||
ShaderStorageBufferBinding::ShaderStorageBufferBinding(GLuint index)
|
||||
: BufferIndexBinding(GL_SHADER_STORAGE_BUFFER, index)
|
||||
{
|
||||
}
|
||||
|
||||
ShaderStorageBufferBinding::ShaderStorageBufferBinding(GLuint index, BufferObject* bo, GLintptr offset, GLsizeiptr size)
|
||||
: BufferIndexBinding(GL_SHADER_STORAGE_BUFFER, index, bo, offset, size)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
ShaderStorageBufferBinding::ShaderStorageBufferBinding(const ShaderStorageBufferBinding& rhs, const CopyOp& copyop)
|
||||
: BufferIndexBinding(rhs, copyop)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
} // namespace osg
|
||||
|
@ -1560,3 +1560,25 @@ AtomicCounterBufferObject::AtomicCounterBufferObject(const AtomicCounterBufferOb
|
||||
AtomicCounterBufferObject::~AtomicCounterBufferObject()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// ShaderStorageBufferObject
|
||||
//
|
||||
ShaderStorageBufferObject::ShaderStorageBufferObject()
|
||||
{
|
||||
setTarget(GL_SHADER_STORAGE_BUFFER);
|
||||
setUsage(GL_STATIC_DRAW);
|
||||
}
|
||||
|
||||
ShaderStorageBufferObject::ShaderStorageBufferObject(const ShaderStorageBufferObject& ubo, const CopyOp& copyop)
|
||||
: BufferObject(ubo, copyop)
|
||||
{
|
||||
}
|
||||
|
||||
ShaderStorageBufferObject::~ShaderStorageBufferObject()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user