From 0efc54c7491520730f7af3889cf99fd794ee8e1a Mon Sep 17 00:00:00 2001 From: scrawl Date: Wed, 8 Mar 2017 22:13:05 +0100 Subject: [PATCH] Subdivide the composite maps --- components/terrain/chunkmanager.cpp | 126 +++++++++++++++++----------- components/terrain/chunkmanager.hpp | 8 +- components/terrain/terraingrid.cpp | 2 +- 3 files changed, 82 insertions(+), 54 deletions(-) diff --git a/components/terrain/chunkmanager.cpp b/components/terrain/chunkmanager.cpp index 94c521d5b..5f6a83376 100644 --- a/components/terrain/chunkmanager.cpp +++ b/components/terrain/chunkmanager.cpp @@ -31,7 +31,7 @@ ChunkManager::ChunkManager(Storage *storage, Resource::SceneManager *sceneMgr, T } -osg::ref_ptr ChunkManager::getChunk(float size, const osg::Vec2f ¢er) +osg::ref_ptr ChunkManager::getChunk(float size, const osg::Vec2f ¢er, int lod) { std::ostringstream stream; stream << size << " " << center.x() << " " << center.y(); @@ -42,7 +42,7 @@ osg::ref_ptr ChunkManager::getChunk(float size, const osg::Vec2f &cen return obj->asNode(); else { - osg::ref_ptr node = createChunk(size, center); + osg::ref_ptr node = createChunk(size, center, lod); mCache->addEntryToObjectCache(id, node.get()); return node; } @@ -80,44 +80,44 @@ osg::ref_ptr ChunkManager::createCompositeMapRTT(osg::ref_ptr ChunkManager::createChunk(float chunkSize, const osg::Vec2f &chunkCenter) +void ChunkManager::createCompositeMapGeometry(float chunkSize, const osg::Vec2f& chunkCenter, const osg::Vec4f& texCoords, osg::Group* compositeMapNode) { - osg::Vec2f worldCenter = chunkCenter*mStorage->getCellWorldSize(); - osg::ref_ptr transform (new SceneUtil::PositionAttitudeTransform); - transform->setPosition(osg::Vec3f(worldCenter.x(), worldCenter.y(), 0.f)); - - osg::ref_ptr positions (new osg::Vec3Array); - osg::ref_ptr normals (new osg::Vec3Array); - osg::ref_ptr colors (new osg::Vec4Array); - - osg::ref_ptr vbo (new osg::VertexBufferObject); - positions->setVertexBufferObject(vbo); - normals->setVertexBufferObject(vbo); - colors->setVertexBufferObject(vbo); - - unsigned int lod = 0; - - mStorage->fillVertexBuffers(lod, chunkSize, chunkCenter, positions, normals, colors); - - osg::ref_ptr geometry (new TerrainDrawable); - geometry->setVertexArray(positions); - geometry->setNormalArray(normals, osg::Array::BIND_PER_VERTEX); - geometry->setColorArray(colors, osg::Array::BIND_PER_VERTEX); - geometry->setUseDisplayList(false); - geometry->setUseVertexBufferObjects(true); - - unsigned int numVerts = (mStorage->getCellVertices()-1) * chunkSize / (1 << lod) + 1; + if (chunkSize > 1.f) + { + createCompositeMapGeometry(chunkSize/2.f, chunkCenter + osg::Vec2f(chunkSize/4.f, chunkSize/4.f), osg::Vec4f(texCoords.x() + texCoords.z()/2.f, texCoords.y(), texCoords.z()/2.f, texCoords.w()/2.f), compositeMapNode); + createCompositeMapGeometry(chunkSize/2.f, chunkCenter + osg::Vec2f(-chunkSize/4.f, chunkSize/4.f), osg::Vec4f(texCoords.x(), texCoords.y(), texCoords.z()/2.f, texCoords.w()/2.f), compositeMapNode); + createCompositeMapGeometry(chunkSize/2.f, chunkCenter + osg::Vec2f(chunkSize/4.f, -chunkSize/4.f), osg::Vec4f(texCoords.x() + texCoords.z()/2.f, texCoords.y()+texCoords.w()/2.f, texCoords.z()/2.f, texCoords.w()/2.f), compositeMapNode); + createCompositeMapGeometry(chunkSize/2.f, chunkCenter + osg::Vec2f(-chunkSize/4.f, -chunkSize/4.f), osg::Vec4f(texCoords.x(), texCoords.y()+ texCoords.w()/2.f, texCoords.z()/2.f, texCoords.w()/2.f), compositeMapNode); + } + else + { + float left = texCoords.x()*2.f-1; + float top = texCoords.y()*2.f-1; + float width = texCoords.z()*2.f; + float height = texCoords.w()*2.f; - geometry->addPrimitiveSet(mBufferCache.getIndexBuffer(numVerts, 0)); + osg::ref_ptr geom = osg::createTexturedQuadGeometry(osg::Vec3(left,top,0), osg::Vec3(width,0,0), osg::Vec3(0,height,0)); + geom->setTexCoordArray(1, geom->getTexCoordArray(0), osg::Array::BIND_PER_VERTEX); - geometry->getBound(); + std::vector > passes = createPasses(chunkSize, chunkCenter, true); + for (std::vector >::iterator it = passes.begin(); it != passes.end(); ++it) + { + osg::ref_ptr group = new osg::Group; + group->setStateSet(*it); + group->addChild(geom); + compositeMapNode->addChild(group); + } + } +} +std::vector > ChunkManager::createPasses(float chunkSize, const osg::Vec2f &chunkCenter, bool forCompositeMap) +{ std::vector layerList; std::vector > blendmaps; mStorage->getBlendmaps(chunkSize, chunkCenter, false, blendmaps, layerList); bool useShaders = mSceneManager->getForceShaders(); - if (!mSceneManager->getClampLighting()) + if (!mSceneManager->getClampLighting() && !forCompositeMap) useShaders = true; // always use shaders when lighting is unclamped, this is to avoid lighting seams between a terrain chunk with normal maps and one without normal maps std::vector layers; { @@ -129,7 +129,7 @@ osg::ref_ptr ChunkManager::createChunk(float chunkSize, const osg::Ve textureLayer.mDiffuseMap = mTextureManager->getTexture(it->mDiffuseMap); - if (!it->mNormalMap.empty()) + if (!forCompositeMap && !it->mNormalMap.empty()) textureLayer.mNormalMap = mTextureManager->getTexture(it->mNormalMap); if (it->requiresShaders()) @@ -150,29 +150,54 @@ osg::ref_ptr ChunkManager::createChunk(float chunkSize, const osg::Ve blendmapTextures.push_back(texture); } - // use texture coordinates for both texture units, the layer texture and blend texture - for (unsigned int i=0; i<2; ++i) - geometry->setTexCoordArray(i, mBufferCache.getUVBuffer(numVerts)); - float blendmapScale = mStorage->getBlendmapScale(chunkSize); - Shader::ShaderManager* shaderManager = &mSceneManager->getShaderManager(); + return ::Terrain::createPasses(useShaders, mSceneManager->getForcePerPixelLighting(), + mSceneManager->getClampLighting(), &mSceneManager->getShaderManager(), layers, blendmapTextures, blendmapScale, blendmapScale); +} + +osg::ref_ptr ChunkManager::createChunk(float chunkSize, const osg::Vec2f &chunkCenter, int lod) +{ + osg::Vec2f worldCenter = chunkCenter*mStorage->getCellWorldSize(); + osg::ref_ptr transform (new SceneUtil::PositionAttitudeTransform); + transform->setPosition(osg::Vec3f(worldCenter.x(), worldCenter.y(), 0.f)); + + osg::ref_ptr positions (new osg::Vec3Array); + osg::ref_ptr normals (new osg::Vec3Array); + osg::ref_ptr colors (new osg::Vec4Array); + + osg::ref_ptr vbo (new osg::VertexBufferObject); + positions->setVertexBufferObject(vbo); + normals->setVertexBufferObject(vbo); + colors->setVertexBufferObject(vbo); + + mStorage->fillVertexBuffers(lod, chunkSize, chunkCenter, positions, normals, colors); + + osg::ref_ptr geometry (new TerrainDrawable); + geometry->setVertexArray(positions); + geometry->setNormalArray(normals, osg::Array::BIND_PER_VERTEX); + geometry->setColorArray(colors, osg::Array::BIND_PER_VERTEX); + geometry->setUseDisplayList(false); + geometry->setUseVertexBufferObjects(true); - if (1) // useCompositeMap + unsigned int numVerts = (mStorage->getCellVertices()-1) * chunkSize / (1 << lod) + 1; + + geometry->addPrimitiveSet(mBufferCache.getIndexBuffer(numVerts, 0)); + + geometry->getBound(); + + bool useCompositeMap = chunkSize >= 1.f; + unsigned int numUvSets = useCompositeMap ? 1 : 2; + + for (unsigned int i=0; isetTexCoordArray(i, mBufferCache.getUVBuffer(numVerts)); + + if (useCompositeMap) { osg::ref_ptr compositeMap; osg::ref_ptr compositeMapNode = createCompositeMapRTT(compositeMap); - osg::ref_ptr geom = osg::createTexturedQuadGeometry(osg::Vec3(-1,-1,0), osg::Vec3(2,0,0), osg::Vec3(0,2,0)); - geom->setTexCoordArray(1, geom->getTexCoordArray(0), osg::Array::BIND_PER_VERTEX); - std::vector > passes = createPasses(useShaders, mSceneManager->getForcePerPixelLighting(), - mSceneManager->getClampLighting(), shaderManager, layers, blendmapTextures, blendmapScale, blendmapScale, true); - for (std::vector >::iterator it = passes.begin(); it != passes.end(); ++it) - { - osg::ref_ptr group = new osg::Group; - group->setStateSet(*it); - group->addChild(geom); - compositeMapNode->addChild(group); - } + + createCompositeMapGeometry(chunkSize, chunkCenter, osg::Vec4f(0,0,1,1), compositeMapNode); compositeMapNode->getOrCreateStateSet()->setMode(GL_LIGHTING, osg::StateAttribute::OFF); @@ -185,8 +210,7 @@ osg::ref_ptr ChunkManager::createChunk(float chunkSize, const osg::Ve } else { - geometry->setPasses(createPasses(useShaders, mSceneManager->getForcePerPixelLighting(), - mSceneManager->getClampLighting(), shaderManager, layers, blendmapTextures, blendmapScale, blendmapScale)); + geometry->setPasses(createPasses(chunkSize, chunkCenter, false)); } transform->addChild(geometry); diff --git a/components/terrain/chunkmanager.hpp b/components/terrain/chunkmanager.hpp index 3941fc843..382e4a6b0 100644 --- a/components/terrain/chunkmanager.hpp +++ b/components/terrain/chunkmanager.hpp @@ -34,15 +34,19 @@ namespace Terrain public: ChunkManager(Storage* storage, Resource::SceneManager* sceneMgr, TextureManager* textureManager, CompositeMapRenderer* renderer); - osg::ref_ptr getChunk(float size, const osg::Vec2f& center); + osg::ref_ptr getChunk(float size, const osg::Vec2f& center, int lod); virtual void reportStats(unsigned int frameNumber, osg::Stats* stats) const; private: - osg::ref_ptr createChunk(float size, const osg::Vec2f& center); + osg::ref_ptr createChunk(float size, const osg::Vec2f& center, int lod); osg::ref_ptr createCompositeMapRTT(osg::ref_ptr& texture); + void createCompositeMapGeometry(float chunkSize, const osg::Vec2f& chunkCenter, const osg::Vec4f& texCoords, osg::Group* compositeMapNode); + + std::vector > createPasses(float chunkSize, const osg::Vec2f& chunkCenter, bool forCompositeMap); + Terrain::Storage* mStorage; Resource::SceneManager* mSceneManager; TextureManager* mTextureManager; diff --git a/components/terrain/terraingrid.cpp b/components/terrain/terraingrid.cpp index f7489fcde..bb6020dd8 100644 --- a/components/terrain/terraingrid.cpp +++ b/components/terrain/terraingrid.cpp @@ -47,7 +47,7 @@ osg::ref_ptr TerrainGrid::buildTerrain (osg::Group* parent, float chu } else { - osg::ref_ptr node = mChunkManager->getChunk(chunkSize, chunkCenter); + osg::ref_ptr node = mChunkManager->getChunk(chunkSize, chunkCenter, 0); if (!node) return NULL; if (parent)