First step of refactoring the osg::Program management in osgTerrain::GeometryPool for better performance by placing default osg::Program and shader defines on a single StateSet below the osgTerrain::Terrain

git-svn-id: http://svn.openscenegraph.org/osg/OpenSceneGraph/trunk@14704 16af8721-9629-0410-8352-f15c8da7e697
This commit is contained in:
Robert Osfield 2015-02-20 15:02:43 +00:00
parent 5c023d1f76
commit afbf20eba9
6 changed files with 106 additions and 78 deletions

View File

@ -140,11 +140,31 @@ public:
toggleDefine("LIGHTING");
return true;
}
else if (ea.getKey()=='h')
{
toggleDefine("HEIGHTFIELD_LAYER");
return true;
}
else if (ea.getKey()=='t')
{
toggleDefine("TEXTURE_2D");
return true;
}
else if (ea.getKey()=='y')
{
toggleDefine("COLOR_LAYER0");
return true;
}
else if (ea.getKey()=='u')
{
toggleDefine("COLOR_LAYER1");
return true;
}
else if (ea.getKey()=='i')
{
toggleDefine("COLOR_LAYER2");
return true;
}
else if (ea.getKey()=='d')
{
toggleDefine("COMPUTE_DIAGONALS");

View File

@ -327,7 +327,7 @@ class OSG_EXPORT StateSet : public Object
/** Set the list of defines to pass on to shaders.*/
void setDefineList(DefineList& dl) { _defineList = dl; }
void setDefineList(const DefineList& dl) { _defineList = dl; }
/** Get the list of defines to pass on to shaders.*/
DefineList& getDefineList() { return _defineList; }

View File

@ -145,6 +145,8 @@ class OSGTERRAIN_EXPORT GeometryPool : public osg::Referenced
typedef std::vector<LayerType> LayerTypes;
typedef std::map<LayerTypes, osg::ref_ptr<osg::Program> > ProgramMap;
osg::StateSet* getRootStateSetForTerrain(Terrain* terrain);
virtual osg::ref_ptr<osg::Program> getOrCreateProgram(LayerTypes& layerTypes);
virtual osg::ref_ptr<SharedGeometry> getOrCreateGeometry(osgTerrain::TerrainTile* tile);
@ -153,19 +155,17 @@ class OSGTERRAIN_EXPORT GeometryPool : public osg::Referenced
virtual void applyLayers(osgTerrain::TerrainTile* tile, osg::StateSet* stateset);
void setUseGeometryShader(bool flag) { _useGeometryShader = flag; }
bool getUseGeometryShader() const { return _useGeometryShader; }
protected:
virtual ~GeometryPool();
bool _useGeometryShader;
OpenThreads::Mutex _geometryMapMutex;
GeometryMap _geometryMap;
OpenThreads::Mutex _programMapMutex;
ProgramMap _programMap;
osg::ref_ptr<osg::StateSet> _rootStateSet;
bool _rootStateSetAssigned;
};

View File

@ -165,6 +165,7 @@ void MultiTextureControl::updateStateSet()
}
#endif
stateset->addUniform(uniform.get());
stateset->setDefine("TEXTURE_WEIGHTS");
}
setStateSet(stateset.get());

View File

@ -42,21 +42,10 @@ const osgTerrain::Locator* osgTerrain::computeMasterLocator(const osgTerrain::Te
// GeometryPool
//
GeometryPool::GeometryPool():
_useGeometryShader(false)
_rootStateSetAssigned(false)
{
const char* ptr = 0;
if ((ptr = getenv("OSG_TERRAIN_USE_GEOMETRY_SHADER")) != 0)
{
if (strcmp(ptr,"OFF")==0 || strcmp(ptr,"Off")==0 || strcmp(ptr,"off")==0 ||
strcmp(ptr,"FALSE")==0 || strcmp(ptr,"False")==0 || strcmp(ptr,"false")==0)
{
_useGeometryShader = false;
}
else
{
_useGeometryShader = true;
}
}
_rootStateSet = new osg::StateSet;
}
GeometryPool::~GeometryPool()
@ -322,8 +311,8 @@ osg::ref_ptr<SharedGeometry> GeometryPool::getOrCreateGeometry(osgTerrain::Terra
#else
bool smallTile = numVertices <= 16384;
GLenum primitiveTypes = _useGeometryShader ? GL_LINES_ADJACENCY : GL_QUADS;
primitiveTypes = GL_QUADS;
GLenum primitiveTypes = GL_QUADS;
osg::ref_ptr<osg::DrawElements> elements = smallTile ?
static_cast<osg::DrawElements*>(new osg::DrawElementsUShort(primitiveTypes)) :
static_cast<osg::DrawElements*>(new osg::DrawElementsUInt(primitiveTypes));
@ -577,11 +566,11 @@ osg::ref_ptr<osg::MatrixTransform> GeometryPool::getTileSubgraph(osgTerrain::Ter
osg::ref_ptr<osg::Program> GeometryPool::getOrCreateProgram(LayerTypes& layerTypes)
{
OpenThreads::ScopedLock<OpenThreads::Mutex> lock(_programMapMutex);
//OpenThreads::ScopedLock<OpenThreads::Mutex> lock(_programMapMutex);
ProgramMap::iterator itr = _programMap.find(layerTypes);
if (itr!=_programMap.end())
{
// OSG_NOTICE<<") returning exisitng Program "<<itr->second.get()<<std::endl;
// OSG_NOTICE<<") returning existing Program "<<itr->second.get()<<std::endl;
return itr->second.get();
}
@ -615,21 +604,14 @@ osg::ref_ptr<osg::Program> GeometryPool::getOrCreateProgram(LayerTypes& layerTyp
program->addShader(osgDB::readShaderFile("shaders/lighting.vert"));
// OSG_NOTICE<<") creating new Program "<<program.get()<<std::endl;
if (num_HeightField>0)
{
#include "shaders/terrain_displacement_mapping_vert.cpp"
osg::ref_ptr<osg::Shader> shader = osgDB::readShaderFileWithFallback(osg::Shader::VERTEX, "shaders/terrain_displacement_mapping.vert", terrain_displacement_mapping_vert);
program->addShader(shader.get());
}
else
{
#include "shaders/terrain_displacement_mapping_flat_vert.cpp"
program->addShader(osgDB::readShaderFileWithFallback(osg::Shader::VERTEX, "shaders/terrain_displacement_mapping.vert", terrain_displacement_mapping_flat_vert));
}
//if (_useGeometryShader)
{
#include "shaders/terrain_displacement_mapping_geom.cpp"
osg::ref_ptr<osg::Shader> shader = osgDB::readShaderFileWithFallback(osg::Shader::GEOMETRY, "shaders/terrain_displacement_mapping.geom", terrain_displacement_mapping_geom);
@ -646,27 +628,8 @@ osg::ref_ptr<osg::Program> GeometryPool::getOrCreateProgram(LayerTypes& layerTyp
}
{
osg::ref_ptr<osg::Shader> shader;
if (num_Color==0)
{
#include "shaders/terrain_displacement_mapping_frag.cpp"
shader = osgDB::readShaderFileWithFallback(osg::Shader::FRAGMENT, "shaders/terrain_displacement_mapping.frag", terrain_displacement_mapping_frag);
}
else if (num_Color==1)
{
#include "shaders/terrain_displacement_mapping_C_frag.cpp"
shader = osgDB::readShaderFileWithFallback(osg::Shader::FRAGMENT, "shaders/terrain_displacement_mapping_C.frag", terrain_displacement_mapping_C_frag);
}
else if (num_Color==2)
{
#include "shaders/terrain_displacement_mapping_CC_frag.cpp"
shader = osgDB::readShaderFileWithFallback(osg::Shader::FRAGMENT, "shaders/terrain_displacement_mapping_CC.frag", terrain_displacement_mapping_CC_frag);
}
else if (num_Color==3)
{
#include "shaders/terrain_displacement_mapping_CCC_frag.cpp"
shader = osgDB::readShaderFileWithFallback(osg::Shader::FRAGMENT, "shaders/terrain_displacement_mapping_CCC.frag", terrain_displacement_mapping_CCC_frag);
}
#include "shaders/terrain_displacement_mapping_frag.cpp"
osg::ref_ptr<osg::Shader> shader = osgDB::readShaderFileWithFallback(osg::Shader::FRAGMENT, "shaders/terrain_displacement_mapping.frag", terrain_displacement_mapping_frag);
if (shader.valid())
{
@ -723,6 +686,7 @@ void GeometryPool::applyLayers(osgTerrain::TerrainTile* tile, osg::StateSet* sta
layerTypes.push_back(HEIGHTFIELD_LAYER);
}
#if 1
int colorLayerNum = 0;
for(unsigned int layerNum=0; layerNum<tile->getNumColorLayers(); ++layerNum)
{
osgTerrain::Layer* colorLayer = tile->getColorLayer(layerNum);
@ -787,47 +751,77 @@ void GeometryPool::applyLayers(osgTerrain::TerrainTile* tile, osg::StateSet* sta
stateset->setTextureAttributeAndModes(textureUnit, texture2D, osg::StateAttribute::ON);
std::stringstream str;
str<<"colorTexture"<<textureUnit;
str<<"colorTexture"<<colorLayerNum;
stateset->addUniform(new osg::Uniform(str.str().c_str(),textureUnit));
layerTypes.push_back(COLOR_LAYER);
++colorLayerNum;
}
else if (contourLayer)
{
osg::Texture1D* texture1D = dynamic_cast<osg::Texture1D*>(layerToTextureMap[colorLayer]);
if (!texture1D)
{
texture1D = new osg::Texture1D;
texture1D->setImage(image);
texture1D->setResizeNonPowerOfTwoHint(false);
texture1D->setFilter(osg::Texture::MIN_FILTER, osg::Texture::NEAREST);
texture1D->setFilter(osg::Texture::MAG_FILTER, colorLayer->getMagFilter());
layerToTextureMap[colorLayer] = texture1D;
}
int textureUnit = layerTypes.size();
stateset->setTextureAttributeAndModes(textureUnit, texture1D, osg::StateAttribute::ON);
std::stringstream str;
str<<"contourTexture"<<textureUnit;
stateset->addUniform(new osg::Uniform(str.str().c_str(),textureUnit));
layerTypes.push_back(CONTOUR_LAYER);
OSG_NOTICE<<"Warning : GeometryPool does not presently support ContourLayers."<<std::endl;
}
}
#endif
osg::ref_ptr<osg::Program> program = getOrCreateProgram(layerTypes);
if (program.valid())
{
stateset->setAttribute(program.get());
}
// If we have a root StateSet assigned for Terrain?
// If tile_LayerTypes a subset of root_LayerTypes then toggle on/off locally
// If tile_LayerTypes a superset of root_LayerTypes then create local Program
// else no need to set anything
// else no root StateSet
// create new StateSet for Program required and assigned with layers required enabled
//
//stateset->setDefine("GL_LIGHTING", osg::StateAttribute::ON);
{
OpenThreads::ScopedLock<OpenThreads::Mutex> lock(_programMapMutex);
if (!_rootStateSetAssigned)
{
_rootStateSetAssigned = true;
_rootStateSet->setDefine("LIGHTING");
int num_Color = 0;
for(LayerTypes::iterator itr = layerTypes.begin();
itr != layerTypes.end();
++itr)
{
switch(*itr)
{
case(HEIGHTFIELD_LAYER): _rootStateSet->setDefine("HEIGHTFIELD_LAYER"); break;
case(COLOR_LAYER): ++num_Color; break;
case(CONTOUR_LAYER): break; // not supported right now
}
}
if (num_Color>=1)
{
_rootStateSet->setDefine("TEXTURE_2D");
_rootStateSet->setDefine("COLOR_LAYER0");
}
if (num_Color>=2) _rootStateSet->setDefine("COLOR_LAYER1");
if (num_Color>=3) _rootStateSet->setDefine("COLOR_LAYER2");
osg::ref_ptr<osg::Program> program = getOrCreateProgram(layerTypes);
if (program.valid())
{
_rootStateSet->setAttribute(program.get());
}
}
}
}
osg::StateSet* GeometryPool::getRootStateSetForTerrain(Terrain* terrain)
{
//OSG_NOTICE<<"getRootStateSetForTerrain("<<terrain<<")"<<std::endl;
return _rootStateSet.get();
}
/////////////////////////////////////////////////////////////////////////////////////////////////////////
//

View File

@ -123,6 +123,19 @@ void Terrain::traverse(osg::NodeVisitor& nv)
}
}
if (nv.getVisitorType()==osg::NodeVisitor::CULL_VISITOR)
{
osgUtil::CullVisitor* cv = dynamic_cast<osgUtil::CullVisitor*>(&nv);
osg::StateSet* ss = _geometryPool.valid() ? _geometryPool->getRootStateSetForTerrain(this) : 0;
if (cv && ss)
{
cv->pushStateSet(ss);
Group::traverse(nv);
cv->popStateSet();
return;
}
}
Group::traverse(nv);
}