Add CompositeMapRenderer

Temporarily render all terrain using composite maps for testing purposes
pull/1225/head
scrawl 8 years ago
parent e323b2fa7b
commit b1d4bb5708

@ -114,7 +114,7 @@ add_component_dir (translation
)
add_component_dir (terrain
storage world buffercache defs terraingrid material terraindrawable texturemanager chunkmanager
storage world buffercache defs terraingrid material terraindrawable texturemanager chunkmanager compositemaprenderer
)
add_component_dir (loadinglistener

@ -368,10 +368,6 @@ namespace ESMTerrain
void Storage::getBlendmaps(float chunkSize, const osg::Vec2f &chunkCenter,
bool pack, ImageVector &blendmaps, std::vector<Terrain::LayerInfo> &layerList)
{
// TODO - blending isn't completely right yet; the blending radius appears to be
// different at a cell transition (2 vertices, not 4), so we may need to create a larger blendmap
// and interpolate the rest of the cell by hand? :/
osg::Vec2f origin = chunkCenter - osg::Vec2f(chunkSize/2.f, chunkSize/2.f);
int cellX = static_cast<int>(std::floor(origin.x()));
int cellY = static_cast<int>(std::floor(origin.y()));
@ -383,10 +379,6 @@ namespace ESMTerrain
int rowEnd = rowStart + chunkSize * (realTextureSize-1) + 1;
int colEnd = colStart + chunkSize * (realTextureSize-1) + 1;
assert (rowStart >= 0 && colStart >= 0);
assert (rowEnd <= realTextureSize);
assert (colEnd <= realTextureSize);
// Save the used texture indices so we know the total number of textures
// and number of required blend maps
std::set<UniqueTextureId> textureIndices;

@ -15,6 +15,7 @@
#include "material.hpp"
#include "storage.hpp"
#include "texturemanager.hpp"
#include "compositemaprenderer.hpp"
namespace
{
@ -39,11 +40,13 @@ namespace
namespace Terrain
{
ChunkManager::ChunkManager(Storage *storage, Resource::SceneManager *sceneMgr, TextureManager* textureManager)
ChunkManager::ChunkManager(Storage *storage, Resource::SceneManager *sceneMgr, TextureManager* textureManager, CompositeMapRenderer* renderer)
: ResourceManager(NULL)
, mStorage(storage)
, mSceneManager(sceneMgr)
, mTextureManager(textureManager)
, mCompositeMapRenderer(renderer)
, mCompositeMapSize(512)
{
}
@ -70,6 +73,33 @@ void ChunkManager::reportStats(unsigned int frameNumber, osg::Stats *stats) cons
stats->setAttribute(frameNumber, "Terrain Chunk", mCache->getCacheSize());
}
osg::ref_ptr<osg::Group> ChunkManager::createCompositeMapRTT(osg::ref_ptr<osg::Texture2D>& texture)
{
texture = new osg::Texture2D;
texture->setTextureWidth(mCompositeMapSize);
texture->setTextureHeight(mCompositeMapSize);
texture->setInternalFormat(GL_RGB);
texture->setFilter(osg::Texture::MIN_FILTER, osg::Texture::LINEAR);
texture->setFilter(osg::Texture::MAG_FILTER, osg::Texture::LINEAR);
texture->setWrap(osg::Texture::WRAP_S, osg::Texture::CLAMP_TO_EDGE);
texture->setWrap(osg::Texture::WRAP_T, osg::Texture::CLAMP_TO_EDGE);
osg::ref_ptr<osg::Camera> camera (new osg::Camera);
camera->setRenderTargetImplementation(osg::Camera::FRAME_BUFFER_OBJECT, osg::Camera::PIXEL_BUFFER_RTT);
camera->attach(osg::Camera::COLOR_BUFFER, texture);
camera->setReferenceFrame(osg::Camera::ABSOLUTE_RF);
camera->setViewMatrix(osg::Matrix::identity());
camera->setProjectionMatrix(osg::Matrix::identity());
camera->setProjectionResizePolicy(osg::Camera::FIXED);
camera->setClearColor(osg::Vec4(0.f, 0.f, 0.f, 1.f));
camera->setClearMask(GL_COLOR_BUFFER_BIT);
camera->setViewport(0, 0, mCompositeMapSize, mCompositeMapSize);
camera->setRenderOrder(osg::Camera::PRE_RENDER);
camera->setImplicitBufferAttachmentMask(osg::DisplaySettings::IMPLICIT_COLOR_BUFFER_ATTACHMENT); // no need for a depth buffer
return camera;
}
osg::ref_ptr<osg::Node> ChunkManager::createChunk(float chunkSize, const osg::Vec2f &chunkCenter)
{
float minH, maxH;
@ -161,8 +191,36 @@ osg::ref_ptr<osg::Node> ChunkManager::createChunk(float chunkSize, const osg::Ve
Shader::ShaderManager* shaderManager = &mSceneManager->getShaderManager();
geometry->setPasses(createPasses(useShaders, mSceneManager->getForcePerPixelLighting(),
mSceneManager->getClampLighting(), shaderManager, layers, blendmapTextures, blendmapScale, blendmapScale));
if (1) // useCompositeMap
{
osg::ref_ptr<osg::Texture2D> compositeMap;
osg::ref_ptr<osg::Group> compositeMapNode = createCompositeMapRTT(compositeMap);
osg::ref_ptr<osg::Geometry> 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<osg::ref_ptr<osg::StateSet> > passes = createPasses(useShaders, mSceneManager->getForcePerPixelLighting(),
mSceneManager->getClampLighting(), shaderManager, layers, blendmapTextures, blendmapScale, blendmapScale, true);
for (std::vector<osg::ref_ptr<osg::StateSet> >::iterator it = passes.begin(); it != passes.end(); ++it)
{
osg::ref_ptr<osg::Group> group = new osg::Group;
group->setStateSet(*it);
group->addChild(geom);
compositeMapNode->addChild(group);
}
compositeMapNode->getOrCreateStateSet()->setMode(GL_LIGHTING, osg::StateAttribute::OFF);
mCompositeMapRenderer->addCompositeMap(compositeMapNode, true);
std::vector<osg::ref_ptr<osg::StateSet> > passes2;
passes2.push_back(new osg::StateSet);
passes2[0]->setTextureAttributeAndModes(0, compositeMap, osg::StateAttribute::ON);
geometry->setPasses(passes2);
}
else
{
geometry->setPasses(createPasses(useShaders, mSceneManager->getForcePerPixelLighting(),
mSceneManager->getClampLighting(), shaderManager, layers, blendmapTextures, blendmapScale, blendmapScale));
}
transform->addChild(geometry);

@ -7,7 +7,8 @@
namespace osg
{
class Geometry;
class Group;
class Texture2D;
}
namespace SceneUtil
@ -24,13 +25,14 @@ namespace Terrain
{
class TextureManager;
class CompositeMapRenderer;
class Storage;
/// @brief Handles loading and caching of terrain chunks
class ChunkManager : public Resource::ResourceManager
{
public:
ChunkManager(Storage* storage, Resource::SceneManager* sceneMgr, TextureManager* textureManager);
ChunkManager(Storage* storage, Resource::SceneManager* sceneMgr, TextureManager* textureManager, CompositeMapRenderer* renderer);
osg::ref_ptr<osg::Node> getChunk(float size, const osg::Vec2f& center);
@ -39,10 +41,15 @@ namespace Terrain
private:
osg::ref_ptr<osg::Node> createChunk(float size, const osg::Vec2f& center);
osg::ref_ptr<osg::Group> createCompositeMapRTT(osg::ref_ptr<osg::Texture2D>& texture);
Terrain::Storage* mStorage;
Resource::SceneManager* mSceneManager;
TextureManager* mTextureManager;
CompositeMapRenderer* mCompositeMapRenderer;
BufferCache mBufferCache;
unsigned int mCompositeMapSize;
};
}

@ -0,0 +1,78 @@
#include "compositemaprenderer.hpp"
#include <OpenThreads/ScopedLock>
#include <osg/NodeVisitor>
namespace Terrain
{
CompositeMapRenderer::CompositeMapRenderer()
: mNumCompilePerFrame(1)
, mLastFrame(0)
{
setCullingActive(false);
}
void CompositeMapRenderer::traverse(osg::NodeVisitor &nv)
{
if (nv.getVisitorType() != osg::NodeVisitor::CULL_VISITOR)
return;
if (mLastFrame == nv.getTraversalNumber())
return;
mLastFrame = nv.getTraversalNumber();
mCompiled.clear();
unsigned int numCompiled = 0;
OpenThreads::ScopedLock<OpenThreads::Mutex> lock(mMutex);
while (!mImmediateCompileSet.empty())
{
osg::Node* node = *mImmediateCompileSet.begin();
mCompiled.insert(node);
node->accept(nv);
mImmediateCompileSet.erase(mImmediateCompileSet.begin());
++numCompiled;
}
while (!mCompileSet.empty() && numCompiled <= mNumCompilePerFrame)
{
osg::Node* node = *mCompileSet.begin();
mCompiled.insert(node);
node->accept(nv);
mCompileSet.erase(mCompileSet.begin());
++numCompiled;
}
}
void CompositeMapRenderer::setNumCompilePerFrame(int num)
{
mNumCompilePerFrame = num;
}
void CompositeMapRenderer::addCompositeMap(osg::Node *node, bool immediate)
{
OpenThreads::ScopedLock<OpenThreads::Mutex> lock(mMutex);
if (immediate)
mImmediateCompileSet.insert(node);
else
mCompileSet.insert(node);
}
void CompositeMapRenderer::setImmediate(osg::Node *node)
{
OpenThreads::ScopedLock<OpenThreads::Mutex> lock(mMutex);
mImmediateCompileSet.insert(node);
mCompileSet.erase(node);
}
}

@ -0,0 +1,48 @@
#ifndef OPENMW_COMPONENTS_TERRAIN_COMPOSITEMAPRENDERER_H
#define OPENMW_COMPONENTS_TERRAIN_COMPOSITEMAPRENDERER_H
#include <osg/Node>
#include <OpenThreads/Mutex>
#include <deque>
namespace Terrain
{
/**
* @brief The CompositeMapRenderer is responsible for updating composite map textures in a blocking or non-blocking way.
*/
class CompositeMapRenderer : public osg::Node
{
public:
CompositeMapRenderer();
virtual void traverse(osg::NodeVisitor& nv);
/// Set the maximum number of (non-immediate) composite maps to compile per frame
void setNumCompilePerFrame(int num);
/// Add a composite map to be rendered
void addCompositeMap(osg::Node* node, bool immediate=false);
/// Mark this composite map to be required for the current frame
void setImmediate(osg::Node* node);
private:
unsigned int mNumCompilePerFrame;
unsigned int mLastFrame;
typedef std::set<osg::ref_ptr<osg::Node> > CompileSet;
CompileSet mCompileSet;
CompileSet mImmediateCompileSet;
CompileSet mCompiled;
OpenThreads::Mutex mMutex;
};
}
#endif

@ -58,7 +58,8 @@ namespace Terrain
return depth;
}
std::vector<osg::ref_ptr<osg::StateSet> > createPasses(bool useShaders, bool forcePerPixelLighting, bool clampLighting, Shader::ShaderManager* shaderManager, const std::vector<TextureLayer> &layers, const std::vector<osg::ref_ptr<osg::Texture2D> > &blendmaps, int blendmapScale, float layerTileSize)
std::vector<osg::ref_ptr<osg::StateSet> > createPasses(bool useShaders, bool forcePerPixelLighting, bool clampLighting, Shader::ShaderManager* shaderManager, const std::vector<TextureLayer> &layers,
const std::vector<osg::ref_ptr<osg::Texture2D> > &blendmaps, int blendmapScale, float layerTileSize, bool renderCompositeMap)
{
std::vector<osg::ref_ptr<osg::StateSet> > passes;
@ -103,6 +104,8 @@ namespace Terrain
stateset->addUniform(new osg::Uniform("normalMap", texunit));
}
// TODO: fix shader for renderCompositeMap=True
Shader::ShaderManager::DefineMap defineMap;
defineMap["forcePPL"] = forcePerPixelLighting ? "1" : "0";
defineMap["clamp"] = clampLighting ? "1" : "0";

@ -28,7 +28,8 @@ namespace Terrain
std::vector<osg::ref_ptr<osg::StateSet> > createPasses(bool useShaders, bool forcePerPixelLighting, bool clampLighting, Shader::ShaderManager* shaderManager,
const std::vector<TextureLayer>& layers,
const std::vector<osg::ref_ptr<osg::Texture2D> >& blendmaps, int blendmapScale, float layerTileSize);
const std::vector<osg::ref_ptr<osg::Texture2D> >& blendmaps, int blendmapScale, float layerTileSize, bool renderCompositeMap=false);
}
#endif

@ -8,6 +8,7 @@
#include "storage.hpp"
#include "texturemanager.hpp"
#include "chunkmanager.hpp"
#include "compositemaprenderer.hpp"
namespace Terrain
{
@ -24,10 +25,13 @@ World::World(osg::Group* parent, Resource::ResourceSystem* resourceSystem, osgUt
mTerrainRoot->getOrCreateStateSet()->setRenderingHint(osg::StateSet::OPAQUE_BIN);
mTerrainRoot->setName("Terrain Root");
osg::ref_ptr<CompositeMapRenderer> renderer (new CompositeMapRenderer);
mTerrainRoot->addChild(renderer);
mParent->addChild(mTerrainRoot);
mTextureManager.reset(new TextureManager(mResourceSystem->getSceneManager()));
mChunkManager.reset(new ChunkManager(mStorage, mResourceSystem->getSceneManager(), mTextureManager.get()));
mChunkManager.reset(new ChunkManager(mStorage, mResourceSystem->getSceneManager(), mTextureManager.get(), renderer));
mResourceSystem->addResourceManager(mChunkManager.get());
mResourceSystem->addResourceManager(mTextureManager.get());

Loading…
Cancel
Save