From b38c6258bf48b7cd6c1537d707025b5095209ff2 Mon Sep 17 00:00:00 2001 From: Robert Osfield Date: Tue, 10 Feb 2015 17:20:26 +0000 Subject: [PATCH] Added support for new #pragam(atic) shader composition to new displacement mapping technique git-svn-id: http://svn.openscenegraph.org/osg/OpenSceneGraph/trunk@14683 16af8721-9629-0410-8352-f15c8da7e697 --- examples/osgterrain/osgterrain.cpp | 35 ++++ include/osgTerrain/GeometryPool | 49 +++++- src/osgTerrain/GeometryPool.cpp | 262 +++++++++++++++++++++++++---- 3 files changed, 308 insertions(+), 38 deletions(-) diff --git a/examples/osgterrain/osgterrain.cpp b/examples/osgterrain/osgterrain.cpp index bc160fba2..209609f58 100644 --- a/examples/osgterrain/osgterrain.cpp +++ b/examples/osgterrain/osgterrain.cpp @@ -135,6 +135,21 @@ public: assignedToAll(); return true; } + else if (ea.getKey()=='l') + { + toggleDefine("GL_LIGHTING"); + return true; + } + else if (ea.getKey()=='t') + { + toggleDefine("GL_TEXTURE_2D"); + return true; + } + else if (ea.getKey()=='d') + { + toggleDefine("COMPUTE_DIAGONALS"); + return true; + } return false; } @@ -143,6 +158,22 @@ public: } } + void toggleDefine(const std::string& defineName) + { + osg::StateSet::DefineList& defineList = _terrain->getOrCreateStateSet()->getDefineList(); + osg::StateSet::DefineList::iterator itr = defineList.find(defineName); + if (itr==defineList.end()) + { + defineList[defineName].second = (osg::StateAttribute::ON | osg::StateAttribute::OVERRIDE); + } + else + { + osg::StateSet::DefinePair& dp = itr->second; + if ( (dp.second & osg::StateAttribute::ON)==0) dp.second = (osg::StateAttribute::ON | osg::StateAttribute::OVERRIDE); + else dp.second = (osg::StateAttribute::OFF | osg::StateAttribute::OVERRIDE); + } + } + protected: ~TerrainHandler() {} @@ -351,6 +382,10 @@ int main(int argc, char** argv) } } + //terrain->getOrCreateStateSet()->setDefine("NUM_LIGHTS", "20.0"); + //terrain->getOrCreateStateSet()->setDefine("GL_LIGHTING"); // , osg::StateAttribute::OFF|osg::StateAttribute::OVERRIDE); + //terrain->getOrCreateStateSet()->setDefine("COMPUTE_DIAGONALS"); // , osg::StateAttribute::OFF|osg::StateAttribute::OVERRIDE); + // run the viewers main loop return viewer.run(); diff --git a/include/osgTerrain/GeometryPool b/include/osgTerrain/GeometryPool index ba5a836ac..feb849102 100644 --- a/include/osgTerrain/GeometryPool +++ b/include/osgTerrain/GeometryPool @@ -28,7 +28,7 @@ namespace osgTerrain { extern OSGTERRAIN_EXPORT const osgTerrain::Locator* computeMasterLocator(const osgTerrain::TerrainTile* tile); -class OSGTERRAIN_EXPORT SharedGeometry : public osg::Geometry +class OSGTERRAIN_EXPORT SharedGeometry : public osg::Drawable { public: SharedGeometry(); @@ -37,6 +37,27 @@ class OSGTERRAIN_EXPORT SharedGeometry : public osg::Geometry META_Node(osgTerrain, SharedGeometry); + void setVertexArray(osg::Array* array) { _vertexArray = array; } + osg::Array* getVertexArray() { return _vertexArray.get(); } + const osg::Array* getVertexArray() const { return _vertexArray.get(); } + + void setNormalArray(osg::Array* array) { _normalArray = array; } + osg::Array* getNormalArray() { return _normalArray.get(); } + const osg::Array* getNormalArray() const { return _normalArray.get(); } + + void setColorArray(osg::Array* array) { _colorArray = array; } + osg::Array* getColorArray() { return _colorArray.get(); } + const osg::Array* getColorArray() const { return _colorArray.get(); } + + void setTexCoordArray(osg::Array* array) { _texcoordArray = array; } + osg::Array* getTexCoordArray() { return _texcoordArray.get(); } + const osg::Array* getTexCoordArray() const { return _texcoordArray.get(); } + + void setDrawElements(osg::DrawElements* array) { _drawElements = array; } + osg::DrawElements* getDrawElements() { return _drawElements.get(); } + const osg::DrawElements* getDrawElements() const { return _drawElements.get(); } + + typedef std::vector VertexToHeightFieldMapping; void setVertexToHeightFieldMapping(const VertexToHeightFieldMapping& vthfm) { _vertexToHeightFieldMapping = vthfm; } @@ -44,13 +65,35 @@ class OSGTERRAIN_EXPORT SharedGeometry : public osg::Geometry VertexToHeightFieldMapping& getVertexToHeightFieldMapping() { return _vertexToHeightFieldMapping; } const VertexToHeightFieldMapping& getVertexToHeightFieldMapping() const { return _vertexToHeightFieldMapping; } - using osg::Geometry::supports; - using osg::Geometry::accept; + void compileGLObjects(osg::RenderInfo& renderInfo) const; + + void drawImplementation(osg::RenderInfo& renderInfo) const; + + void resizeGLObjectBuffers(unsigned int maxSize); + void releaseGLObjects(osg::State* state) const; + + virtual bool supports(const osg::Drawable::AttributeFunctor&) const { return true; } + virtual void accept(osg::Drawable::AttributeFunctor&); + + virtual bool supports(const osg::Drawable::ConstAttributeFunctor&) const { return true; } + virtual void accept(osg::Drawable::ConstAttributeFunctor&) const; + + virtual bool supports(const osg::PrimitiveFunctor&) const { return true; } + virtual void accept(osg::PrimitiveFunctor&) const; + + virtual bool supports(const osg::PrimitiveIndexFunctor&) const { return true; } + virtual void accept(osg::PrimitiveIndexFunctor&) const; protected: virtual ~SharedGeometry(); + osg::ref_ptr _vertexArray; + osg::ref_ptr _normalArray; + osg::ref_ptr _colorArray; + osg::ref_ptr _texcoordArray; + osg::ref_ptr _drawElements; + VertexToHeightFieldMapping _vertexToHeightFieldMapping; }; diff --git a/src/osgTerrain/GeometryPool.cpp b/src/osgTerrain/GeometryPool.cpp index b1b41662c..01e2b8c62 100644 --- a/src/osgTerrain/GeometryPool.cpp +++ b/src/osgTerrain/GeometryPool.cpp @@ -119,20 +119,27 @@ osg::ref_ptr GeometryPool::getOrCreateGeometry(osgTerrain::Terra geometry->setUseVertexBufferObjects(true); + osg::ref_ptr vbo = new osg::VertexBufferObject; + SharedGeometry::VertexToHeightFieldMapping& vthfm = geometry->getVertexToHeightFieldMapping(); - osg::ref_ptr vertices = new osg::Vec3Array; + osg::ref_ptr vertices = new osg::Vec3Array(osg::Array::BIND_PER_VERTEX); + vertices->setVertexBufferObject(vbo.get()); geometry->setVertexArray(vertices.get()); - osg::ref_ptr normals = new osg::Vec3Array; - geometry->setNormalArray(normals.get(), osg::Array::BIND_PER_VERTEX); + osg::ref_ptr normals = new osg::Vec3Array(osg::Array::BIND_PER_VERTEX); + normals->setVertexBufferObject(vbo.get()); + geometry->setNormalArray(normals.get()); - osg::ref_ptr colours = new osg::Vec4Array; - geometry->setColorArray(colours.get(), osg::Array::BIND_OVERALL); + osg::ref_ptr colours = new osg::Vec4Array(osg::Array::BIND_OVERALL); + geometry->setColorArray(colours.get()); colours->push_back(osg::Vec4(1.0f, 1.0f, 1.0f, 1.0f)); - osg::ref_ptr texcoords = new osg::Vec4Array; - geometry->setTexCoordArray(0, texcoords.get(), osg::Array::BIND_PER_VERTEX); + osg::ref_ptr texcoords = new osg::Vec4Array(osg::Array::BIND_PER_VERTEX); + texcoords->setVertexBufferObject(vbo.get()); + geometry->setTexCoordArray(texcoords.get()); + + int nx = key.nx; int ny = key.nx; @@ -314,13 +321,16 @@ osg::ref_ptr GeometryPool::getOrCreateGeometry(osgTerrain::Terra #else bool smallTile = numVertices <= 16384; + GLenum primitiveTypes = _useGeometryShader ? GL_LINES_ADJACENCY : GL_QUADS; + primitiveTypes = GL_QUADS; osg::ref_ptr elements = smallTile ? static_cast(new osg::DrawElementsUShort(primitiveTypes)) : static_cast(new osg::DrawElementsUInt(primitiveTypes)); elements->reserveElements( (nx-1) * (ny-1) * 4 + (nx-1)*2*4 + (ny-1)*2*4 ); - geometry->addPrimitiveSet(elements.get()); + elements->setElementBufferObject(new osg::ElementBufferObject()); + geometry->setDrawElements(elements.get()); // first row containing the skirt @@ -615,13 +625,13 @@ osg::ref_ptr GeometryPool::getOrCreateProgram(LayerTypes& layerTyp if (_useGeometryShader) { // prepend define to enable the compute shader style - shader->setShaderSource(std::string("#define COMPUTE_DIAGONALS\n")+shader->getShaderSource()); + //shader->setShaderSource(std::string("#define COMPUTE_DIAGONALS\n")+shader->getShaderSource()); } if (useLighting) { // prepend define to enable lighting - shader->setShaderSource(std::string("#define GL_LIGHTING\n")+shader->getShaderSource()); + // shader->setShaderSource(std::string("#define GL_LIGHTING\n")+shader->getShaderSource()); } program->addShader(shader.get()); @@ -633,15 +643,15 @@ osg::ref_ptr GeometryPool::getOrCreateProgram(LayerTypes& layerTyp } - if (_useGeometryShader) + //if (_useGeometryShader) { #include "shaders/terrain_displacement_mapping_geom.cpp" osg::ref_ptr shader = osgDB::readShaderFileWithFallback(osg::Shader::GEOMETRY, "shaders/terrain_displacement_mapping.geom", terrain_displacement_mapping_geom); program->addShader(shader.get()); - program->setParameter( GL_GEOMETRY_VERTICES_OUT_EXT, 4 ); - program->setParameter( GL_GEOMETRY_INPUT_TYPE_EXT, GL_LINES_ADJACENCY ); - program->setParameter( GL_GEOMETRY_OUTPUT_TYPE_EXT, GL_TRIANGLE_STRIP); + program->setParameter( GL_GEOMETRY_VERTICES_OUT, 4 ); + program->setParameter( GL_GEOMETRY_INPUT_TYPE, GL_LINES_ADJACENCY ); + program->setParameter( GL_GEOMETRY_OUTPUT_TYPE, GL_TRIANGLE_STRIP); } if (num_Contour>0) @@ -677,7 +687,7 @@ osg::ref_ptr GeometryPool::getOrCreateProgram(LayerTypes& layerTyp if (useTextures) { // prepend define to enable lighting - shader->setShaderSource(std::string("#define GL_TEXTURE_2D\n")+shader->getShaderSource()); + //shader->setShaderSource(std::string("#define GL_TEXTURE_2D\n")+shader->getShaderSource()); } program->addShader(shader.get()); } @@ -833,6 +843,8 @@ void GeometryPool::applyLayers(osgTerrain::TerrainTile* tile, osg::StateSet* sta { stateset->setAttribute(program.get()); } + + //stateset->setDefine("GL_LIGHTING", osg::StateAttribute::ON); } @@ -842,11 +854,17 @@ void GeometryPool::applyLayers(osgTerrain::TerrainTile* tile, osg::StateSet* sta // SharedGeometry::SharedGeometry() { -// setSupportsDisplayList(false); + setSupportsDisplayList(false); + _supportsVertexBufferObjects = true; } SharedGeometry::SharedGeometry(const SharedGeometry& rhs,const osg::CopyOp& copyop): - osg::Geometry(rhs, copyop), + osg::Drawable(rhs, copyop), + _vertexArray(rhs._vertexArray), + _normalArray(rhs._normalArray), + _colorArray(rhs._colorArray), + _texcoordArray(rhs._texcoordArray), + _drawElements(rhs._drawElements), _vertexToHeightFieldMapping(rhs._vertexToHeightFieldMapping) { // setSupportsDisplayList(false); @@ -856,6 +874,177 @@ SharedGeometry::~SharedGeometry() { } +void SharedGeometry::compileGLObjects(osg::RenderInfo& renderInfo) const +{ + if (!_vertexArray) return; + if (_vertexArray->getVertexBufferObject()) + { + osg::State& state = *renderInfo.getState(); + unsigned int contextID = state.getContextID(); + osg::GLExtensions* extensions = state.get(); + if (!extensions) return; + + { + osg::BufferObject* vbo = _vertexArray->getVertexBufferObject(); + osg::GLBufferObject* glBufferObject = vbo->getOrCreateGLBufferObject(contextID); + if (glBufferObject && glBufferObject->isDirty()) + { + // OSG_NOTICE<<"Compile buffer "<compileBuffer(); + } + } + + { + osg::BufferObject* ebo = _drawElements->getElementBufferObject(); + osg::GLBufferObject* glBufferObject = ebo->getOrCreateGLBufferObject(contextID); + if (glBufferObject && glBufferObject->isDirty()) + { + // OSG_NOTICE<<"Compile buffer "<compileBuffer(); + } + } + + // unbind the BufferObjects + extensions->glBindBuffer(GL_ARRAY_BUFFER_ARB,0); + extensions->glBindBuffer(GL_ELEMENT_ARRAY_BUFFER_ARB,0); + } + else + { + Drawable::compileGLObjects(renderInfo); + } +} + +void SharedGeometry::resizeGLObjectBuffers(unsigned int maxSize) +{ + Drawable::resizeGLObjectBuffers(maxSize); + + osg::BufferObject* vbo = _vertexArray->getVertexBufferObject(); + if (vbo) vbo->resizeGLObjectBuffers(maxSize); + + osg::BufferObject* ebo = _drawElements->getElementBufferObject(); + if (ebo) ebo->resizeGLObjectBuffers(maxSize); +} + +void SharedGeometry::releaseGLObjects(osg::State* state) const +{ + Drawable::releaseGLObjects(state); + + osg::BufferObject* vbo = _vertexArray->getVertexBufferObject(); + if (vbo) vbo->releaseGLObjects(state); + + osg::BufferObject* ebo = _drawElements->getElementBufferObject(); + if (ebo) ebo->releaseGLObjects(state); +} + +void SharedGeometry::drawImplementation(osg::RenderInfo& renderInfo) const +{ + bool computeDiagonals = renderInfo.getState()->supportsShaderRequirement("COMPUTE_DIAGONALS"); + //OSG_NOTICE<<"SharedGeometry "<getBinding()==osg::Array::BIND_PER_VERTEX) + state.setNormalPointer(_normalArray.get()); + + if (_colorArray.valid() && _colorArray->getBinding()==osg::Array::BIND_PER_VERTEX) + state.setColorPointer(_colorArray.get()); + + if (_texcoordArray.valid() && _texcoordArray->getBinding()==osg::Array::BIND_PER_VERTEX) + state.setTexCoordPointer(0, _texcoordArray.get()); + + state.applyDisablingOfVertexAttributes(); + + if (checkForGLErrors) state.checkGLErrors("Geometry::drawImplementation() after vertex arrays setup."); + + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + // + // draw the primitives themselves. + // + GLenum primitiveType = computeDiagonals ? GL_LINES_ADJACENCY : GL_QUADS; + + osg::GLBufferObject* ebo = _drawElements->getOrCreateGLBufferObject(state.getContextID()); + state.bindElementBufferObject(ebo); + + glDrawElements(primitiveType, _drawElements->getNumIndices(), _drawElements->getDataType(), (const GLvoid *)(ebo->getOffset(_drawElements->getBufferIndex()))); + + + // unbind the VBO's if any are used. + state.unbindVertexBufferObject(); + state.unbindElementBufferObject(); + +#if 0 + if (computeDiagonals) + { + if (state.checkGLErrors("End of SharedGeometry::drawImplementation. computeDiagonals=TRUE")) {} + else OSG_NOTICE<<"SharedGeometry::drawImplementation. OK computeDiagonals=TRUE"<getNumElements(),static_cast(_vertexArray->getDataPointer())); + + _drawElements->accept(pf); +} + +void SharedGeometry::accept(osg::PrimitiveIndexFunctor& pif) const +{ + pif.setVertexArray(_vertexArray->getNumElements(),static_cast(_vertexArray->getDataPointer())); + + _drawElements->accept(pif); +} ///////////////////////////////////////////////////////////////////////////////////////////////////////// @@ -919,22 +1108,17 @@ void HeightFieldDrawable::accept(osg::PrimitiveFunctor& pf) const { pf.setVertexArray(_vertices->size(), &((*_vertices)[0])); - for(osg::Geometry::PrimitiveSetList::const_iterator itr = _geometry->getPrimitiveSetList().begin(); - itr != _geometry->getPrimitiveSetList().end(); - ++itr) + const osg::DrawElementsUShort* deus = dynamic_cast(_geometry->getDrawElements()); + if (deus) { - const osg::DrawElementsUShort* deus = dynamic_cast(itr->get()); - if (deus) + pf.drawElements(GL_QUADS, deus->size(), &((*deus)[0])); + } + else + { + const osg::DrawElementsUInt* deui = dynamic_cast(_geometry->getDrawElements()); + if (deui) { - pf.drawElements(GL_QUADS, deus->size(), &((*deus)[0])); - } - else - { - const osg::DrawElementsUInt* deui = dynamic_cast(itr->get()); - if (deui) - { - pf.drawElements(GL_QUADS, deui->size(), &((*deui)[0])); - } + pf.drawElements(GL_QUADS, deui->size(), &((*deui)[0])); } } } @@ -949,11 +1133,19 @@ void HeightFieldDrawable::accept(osg::PrimitiveIndexFunctor& pif) const if (_vertices.valid()) { pif.setVertexArray(_vertices->size(), &((*_vertices)[0])); - for(osg::Geometry::PrimitiveSetList::const_iterator itr = _geometry->getPrimitiveSetList().begin(); - itr != _geometry->getPrimitiveSetList().end(); - ++itr) + + const osg::DrawElementsUShort* deus = dynamic_cast(_geometry->getDrawElements()); + if (deus) { - (*itr)->accept(pif); + pif.drawElements(GL_QUADS, deus->size(), &((*deus)[0])); + } + else + { + const osg::DrawElementsUInt* deui = dynamic_cast(_geometry->getDrawElements()); + if (deui) + { + pif.drawElements(GL_QUADS, deui->size(), &((*deui)[0])); + } } } else