forked from teamnwah/openmw-tes3coop
Refactor BufferCache to allow caching buffers of different sizes
This commit is contained in:
parent
9a3a64f0c4
commit
274690f790
3 changed files with 24 additions and 27 deletions
|
@ -178,56 +178,56 @@ osg::ref_ptr<IndexArrayType> createIndexBuffer(unsigned int flags, unsigned int
|
||||||
namespace Terrain
|
namespace Terrain
|
||||||
{
|
{
|
||||||
|
|
||||||
osg::ref_ptr<osg::Vec2Array> BufferCache::getUVBuffer()
|
osg::ref_ptr<osg::Vec2Array> BufferCache::getUVBuffer(unsigned int numVerts)
|
||||||
{
|
{
|
||||||
OpenThreads::ScopedLock<OpenThreads::Mutex> lock(mUvBufferMutex);
|
OpenThreads::ScopedLock<OpenThreads::Mutex> lock(mUvBufferMutex);
|
||||||
if (mUvBufferMap.find(mNumVerts) != mUvBufferMap.end())
|
if (mUvBufferMap.find(numVerts) != mUvBufferMap.end())
|
||||||
{
|
{
|
||||||
return mUvBufferMap[mNumVerts];
|
return mUvBufferMap[numVerts];
|
||||||
}
|
}
|
||||||
|
|
||||||
int vertexCount = mNumVerts * mNumVerts;
|
int vertexCount = numVerts * numVerts;
|
||||||
|
|
||||||
osg::ref_ptr<osg::Vec2Array> uvs (new osg::Vec2Array);
|
osg::ref_ptr<osg::Vec2Array> uvs (new osg::Vec2Array);
|
||||||
uvs->reserve(vertexCount);
|
uvs->reserve(vertexCount);
|
||||||
|
|
||||||
for (unsigned int col = 0; col < mNumVerts; ++col)
|
for (unsigned int col = 0; col < numVerts; ++col)
|
||||||
{
|
{
|
||||||
for (unsigned int row = 0; row < mNumVerts; ++row)
|
for (unsigned int row = 0; row < numVerts; ++row)
|
||||||
{
|
{
|
||||||
uvs->push_back(osg::Vec2f(col / static_cast<float>(mNumVerts-1),
|
uvs->push_back(osg::Vec2f(col / static_cast<float>(numVerts-1),
|
||||||
((mNumVerts-1) - row) / static_cast<float>(mNumVerts-1)));
|
((numVerts-1) - row) / static_cast<float>(numVerts-1)));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Assign a VBO here to enable state sharing between different Geometries.
|
// Assign a VBO here to enable state sharing between different Geometries.
|
||||||
uvs->setVertexBufferObject(new osg::VertexBufferObject);
|
uvs->setVertexBufferObject(new osg::VertexBufferObject);
|
||||||
|
|
||||||
mUvBufferMap[mNumVerts] = uvs;
|
mUvBufferMap[numVerts] = uvs;
|
||||||
return uvs;
|
return uvs;
|
||||||
}
|
}
|
||||||
|
|
||||||
osg::ref_ptr<osg::DrawElements> BufferCache::getIndexBuffer(unsigned int flags)
|
osg::ref_ptr<osg::DrawElements> BufferCache::getIndexBuffer(unsigned int numVerts, unsigned int flags)
|
||||||
{
|
{
|
||||||
|
std::pair<int, int> id = std::make_pair(numVerts, flags);
|
||||||
OpenThreads::ScopedLock<OpenThreads::Mutex> lock(mIndexBufferMutex);
|
OpenThreads::ScopedLock<OpenThreads::Mutex> lock(mIndexBufferMutex);
|
||||||
unsigned int verts = mNumVerts;
|
|
||||||
|
|
||||||
if (mIndexBufferMap.find(flags) != mIndexBufferMap.end())
|
if (mIndexBufferMap.find(id) != mIndexBufferMap.end())
|
||||||
{
|
{
|
||||||
return mIndexBufferMap[flags];
|
return mIndexBufferMap[id];
|
||||||
}
|
}
|
||||||
|
|
||||||
osg::ref_ptr<osg::DrawElements> buffer;
|
osg::ref_ptr<osg::DrawElements> buffer;
|
||||||
|
|
||||||
if (verts*verts <= (0xffffu))
|
if (numVerts*numVerts <= (0xffffu))
|
||||||
buffer = createIndexBuffer<osg::DrawElementsUShort>(flags, verts);
|
buffer = createIndexBuffer<osg::DrawElementsUShort>(flags, numVerts);
|
||||||
else
|
else
|
||||||
buffer = createIndexBuffer<osg::DrawElementsUInt>(flags, verts);
|
buffer = createIndexBuffer<osg::DrawElementsUInt>(flags, numVerts);
|
||||||
|
|
||||||
// Assign a EBO here to enable state sharing between different Geometries.
|
// Assign a EBO here to enable state sharing between different Geometries.
|
||||||
buffer->setElementBufferObject(new osg::ElementBufferObject);
|
buffer->setElementBufferObject(new osg::ElementBufferObject);
|
||||||
|
|
||||||
mIndexBufferMap[flags] = buffer;
|
mIndexBufferMap[id] = buffer;
|
||||||
return buffer;
|
return buffer;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -14,28 +14,24 @@ namespace Terrain
|
||||||
class BufferCache
|
class BufferCache
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
BufferCache(unsigned int numVerts) : mNumVerts(numVerts) {}
|
|
||||||
|
|
||||||
/// @param flags first 4*4 bits are LOD deltas on each edge, respectively (4 bits each)
|
/// @param flags first 4*4 bits are LOD deltas on each edge, respectively (4 bits each)
|
||||||
/// next 4 bits are LOD level of the index buffer (LOD 0 = don't omit any vertices)
|
/// next 4 bits are LOD level of the index buffer (LOD 0 = don't omit any vertices)
|
||||||
/// @note Thread safe.
|
/// @note Thread safe.
|
||||||
osg::ref_ptr<osg::DrawElements> getIndexBuffer (unsigned int flags);
|
osg::ref_ptr<osg::DrawElements> getIndexBuffer (unsigned int numVerts, unsigned int flags);
|
||||||
|
|
||||||
/// @note Thread safe.
|
/// @note Thread safe.
|
||||||
osg::ref_ptr<osg::Vec2Array> getUVBuffer();
|
osg::ref_ptr<osg::Vec2Array> getUVBuffer(unsigned int numVerts);
|
||||||
|
|
||||||
// TODO: add releaseGLObjects() for our vertex/element buffer objects
|
// TODO: add releaseGLObjects() for our vertex/element buffer objects
|
||||||
|
|
||||||
private:
|
private:
|
||||||
// Index buffers are shared across terrain batches where possible. There is one index buffer for each
|
// Index buffers are shared across terrain batches where possible. There is one index buffer for each
|
||||||
// combination of LOD deltas and index buffer LOD we may need.
|
// combination of LOD deltas and index buffer LOD we may need.
|
||||||
std::map<int, osg::ref_ptr<osg::DrawElements> > mIndexBufferMap;
|
std::map<std::pair<int, int>, osg::ref_ptr<osg::DrawElements> > mIndexBufferMap;
|
||||||
OpenThreads::Mutex mIndexBufferMutex;
|
OpenThreads::Mutex mIndexBufferMutex;
|
||||||
|
|
||||||
std::map<int, osg::ref_ptr<osg::Vec2Array> > mUvBufferMap;
|
std::map<int, osg::ref_ptr<osg::Vec2Array> > mUvBufferMap;
|
||||||
OpenThreads::Mutex mUvBufferMutex;
|
OpenThreads::Mutex mUvBufferMutex;
|
||||||
|
|
||||||
unsigned int mNumVerts;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -51,7 +51,6 @@ namespace Terrain
|
||||||
TerrainGrid::TerrainGrid(osg::Group* parent, Resource::ResourceSystem* resourceSystem, osgUtil::IncrementalCompileOperation* ico, Storage* storage, int nodeMask, Shader::ShaderManager* shaderManager, SceneUtil::UnrefQueue* unrefQueue)
|
TerrainGrid::TerrainGrid(osg::Group* parent, Resource::ResourceSystem* resourceSystem, osgUtil::IncrementalCompileOperation* ico, Storage* storage, int nodeMask, Shader::ShaderManager* shaderManager, SceneUtil::UnrefQueue* unrefQueue)
|
||||||
: Terrain::World(parent, resourceSystem, ico, storage, nodeMask)
|
: Terrain::World(parent, resourceSystem, ico, storage, nodeMask)
|
||||||
, mNumSplits(4)
|
, mNumSplits(4)
|
||||||
, mCache((storage->getCellVertices()-1)/static_cast<float>(mNumSplits) + 1)
|
|
||||||
, mUnrefQueue(unrefQueue)
|
, mUnrefQueue(unrefQueue)
|
||||||
, mShaderManager(shaderManager)
|
, mShaderManager(shaderManager)
|
||||||
{
|
{
|
||||||
|
@ -130,7 +129,9 @@ osg::ref_ptr<osg::Node> TerrainGrid::buildTerrain (osg::Group* parent, float chu
|
||||||
geometry->setUseDisplayList(false);
|
geometry->setUseDisplayList(false);
|
||||||
geometry->setUseVertexBufferObjects(true);
|
geometry->setUseVertexBufferObjects(true);
|
||||||
|
|
||||||
geometry->addPrimitiveSet(mCache.getIndexBuffer(0));
|
unsigned int numVerts = (mStorage->getCellVertices()-1) * chunkSize + 1;
|
||||||
|
|
||||||
|
geometry->addPrimitiveSet(mCache.getIndexBuffer(numVerts, 0));
|
||||||
|
|
||||||
// we already know the bounding box, so no need to let OSG compute it.
|
// we already know the bounding box, so no need to let OSG compute it.
|
||||||
osg::Vec3f min(-0.5f*mStorage->getCellWorldSize()*chunkSize,
|
osg::Vec3f min(-0.5f*mStorage->getCellWorldSize()*chunkSize,
|
||||||
|
@ -184,7 +185,7 @@ osg::ref_ptr<osg::Node> TerrainGrid::buildTerrain (osg::Group* parent, float chu
|
||||||
|
|
||||||
// use texture coordinates for both texture units, the layer texture and blend texture
|
// use texture coordinates for both texture units, the layer texture and blend texture
|
||||||
for (unsigned int i=0; i<2; ++i)
|
for (unsigned int i=0; i<2; ++i)
|
||||||
geometry->setTexCoordArray(i, mCache.getUVBuffer());
|
geometry->setTexCoordArray(i, mCache.getUVBuffer(numVerts));
|
||||||
|
|
||||||
float blendmapScale = ESM::Land::LAND_TEXTURE_SIZE*chunkSize;
|
float blendmapScale = ESM::Land::LAND_TEXTURE_SIZE*chunkSize;
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue