mirror of
https://github.com/TES3MP/openmw-tes3mp.git
synced 2025-01-19 22:23:51 +00:00
Add CompositeMapRenderer
Temporarily render all terrain using composite maps for testing purposes
This commit is contained in:
parent
e323b2fa7b
commit
b1d4bb5708
9 changed files with 208 additions and 17 deletions
|
@ -114,7 +114,7 @@ add_component_dir (translation
|
||||||
)
|
)
|
||||||
|
|
||||||
add_component_dir (terrain
|
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
|
add_component_dir (loadinglistener
|
||||||
|
|
|
@ -368,10 +368,6 @@ namespace ESMTerrain
|
||||||
void Storage::getBlendmaps(float chunkSize, const osg::Vec2f &chunkCenter,
|
void Storage::getBlendmaps(float chunkSize, const osg::Vec2f &chunkCenter,
|
||||||
bool pack, ImageVector &blendmaps, std::vector<Terrain::LayerInfo> &layerList)
|
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);
|
osg::Vec2f origin = chunkCenter - osg::Vec2f(chunkSize/2.f, chunkSize/2.f);
|
||||||
int cellX = static_cast<int>(std::floor(origin.x()));
|
int cellX = static_cast<int>(std::floor(origin.x()));
|
||||||
int cellY = static_cast<int>(std::floor(origin.y()));
|
int cellY = static_cast<int>(std::floor(origin.y()));
|
||||||
|
@ -383,10 +379,6 @@ namespace ESMTerrain
|
||||||
int rowEnd = rowStart + chunkSize * (realTextureSize-1) + 1;
|
int rowEnd = rowStart + chunkSize * (realTextureSize-1) + 1;
|
||||||
int colEnd = colStart + 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
|
// Save the used texture indices so we know the total number of textures
|
||||||
// and number of required blend maps
|
// and number of required blend maps
|
||||||
std::set<UniqueTextureId> textureIndices;
|
std::set<UniqueTextureId> textureIndices;
|
||||||
|
|
|
@ -15,6 +15,7 @@
|
||||||
#include "material.hpp"
|
#include "material.hpp"
|
||||||
#include "storage.hpp"
|
#include "storage.hpp"
|
||||||
#include "texturemanager.hpp"
|
#include "texturemanager.hpp"
|
||||||
|
#include "compositemaprenderer.hpp"
|
||||||
|
|
||||||
namespace
|
namespace
|
||||||
{
|
{
|
||||||
|
@ -39,11 +40,13 @@ namespace
|
||||||
namespace Terrain
|
namespace Terrain
|
||||||
{
|
{
|
||||||
|
|
||||||
ChunkManager::ChunkManager(Storage *storage, Resource::SceneManager *sceneMgr, TextureManager* textureManager)
|
ChunkManager::ChunkManager(Storage *storage, Resource::SceneManager *sceneMgr, TextureManager* textureManager, CompositeMapRenderer* renderer)
|
||||||
: ResourceManager(NULL)
|
: ResourceManager(NULL)
|
||||||
, mStorage(storage)
|
, mStorage(storage)
|
||||||
, mSceneManager(sceneMgr)
|
, mSceneManager(sceneMgr)
|
||||||
, mTextureManager(textureManager)
|
, 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());
|
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)
|
osg::ref_ptr<osg::Node> ChunkManager::createChunk(float chunkSize, const osg::Vec2f &chunkCenter)
|
||||||
{
|
{
|
||||||
float minH, maxH;
|
float minH, maxH;
|
||||||
|
@ -161,8 +191,36 @@ osg::ref_ptr<osg::Node> ChunkManager::createChunk(float chunkSize, const osg::Ve
|
||||||
|
|
||||||
Shader::ShaderManager* shaderManager = &mSceneManager->getShaderManager();
|
Shader::ShaderManager* shaderManager = &mSceneManager->getShaderManager();
|
||||||
|
|
||||||
|
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(),
|
geometry->setPasses(createPasses(useShaders, mSceneManager->getForcePerPixelLighting(),
|
||||||
mSceneManager->getClampLighting(), shaderManager, layers, blendmapTextures, blendmapScale, blendmapScale));
|
mSceneManager->getClampLighting(), shaderManager, layers, blendmapTextures, blendmapScale, blendmapScale));
|
||||||
|
}
|
||||||
|
|
||||||
transform->addChild(geometry);
|
transform->addChild(geometry);
|
||||||
|
|
||||||
|
|
|
@ -7,7 +7,8 @@
|
||||||
|
|
||||||
namespace osg
|
namespace osg
|
||||||
{
|
{
|
||||||
class Geometry;
|
class Group;
|
||||||
|
class Texture2D;
|
||||||
}
|
}
|
||||||
|
|
||||||
namespace SceneUtil
|
namespace SceneUtil
|
||||||
|
@ -24,13 +25,14 @@ namespace Terrain
|
||||||
{
|
{
|
||||||
|
|
||||||
class TextureManager;
|
class TextureManager;
|
||||||
|
class CompositeMapRenderer;
|
||||||
class Storage;
|
class Storage;
|
||||||
|
|
||||||
/// @brief Handles loading and caching of terrain chunks
|
/// @brief Handles loading and caching of terrain chunks
|
||||||
class ChunkManager : public Resource::ResourceManager
|
class ChunkManager : public Resource::ResourceManager
|
||||||
{
|
{
|
||||||
public:
|
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);
|
osg::ref_ptr<osg::Node> getChunk(float size, const osg::Vec2f& center);
|
||||||
|
|
||||||
|
@ -39,10 +41,15 @@ namespace Terrain
|
||||||
private:
|
private:
|
||||||
osg::ref_ptr<osg::Node> createChunk(float size, const osg::Vec2f& center);
|
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;
|
Terrain::Storage* mStorage;
|
||||||
Resource::SceneManager* mSceneManager;
|
Resource::SceneManager* mSceneManager;
|
||||||
TextureManager* mTextureManager;
|
TextureManager* mTextureManager;
|
||||||
|
CompositeMapRenderer* mCompositeMapRenderer;
|
||||||
BufferCache mBufferCache;
|
BufferCache mBufferCache;
|
||||||
|
|
||||||
|
unsigned int mCompositeMapSize;
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
78
components/terrain/compositemaprenderer.cpp
Normal file
78
components/terrain/compositemaprenderer.cpp
Normal file
|
@ -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);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
}
|
48
components/terrain/compositemaprenderer.hpp
Normal file
48
components/terrain/compositemaprenderer.hpp
Normal file
|
@ -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;
|
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;
|
std::vector<osg::ref_ptr<osg::StateSet> > passes;
|
||||||
|
|
||||||
|
@ -103,6 +104,8 @@ namespace Terrain
|
||||||
stateset->addUniform(new osg::Uniform("normalMap", texunit));
|
stateset->addUniform(new osg::Uniform("normalMap", texunit));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TODO: fix shader for renderCompositeMap=True
|
||||||
|
|
||||||
Shader::ShaderManager::DefineMap defineMap;
|
Shader::ShaderManager::DefineMap defineMap;
|
||||||
defineMap["forcePPL"] = forcePerPixelLighting ? "1" : "0";
|
defineMap["forcePPL"] = forcePerPixelLighting ? "1" : "0";
|
||||||
defineMap["clamp"] = clampLighting ? "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,
|
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<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
|
#endif
|
||||||
|
|
|
@ -8,6 +8,7 @@
|
||||||
#include "storage.hpp"
|
#include "storage.hpp"
|
||||||
#include "texturemanager.hpp"
|
#include "texturemanager.hpp"
|
||||||
#include "chunkmanager.hpp"
|
#include "chunkmanager.hpp"
|
||||||
|
#include "compositemaprenderer.hpp"
|
||||||
|
|
||||||
namespace Terrain
|
namespace Terrain
|
||||||
{
|
{
|
||||||
|
@ -24,10 +25,13 @@ World::World(osg::Group* parent, Resource::ResourceSystem* resourceSystem, osgUt
|
||||||
mTerrainRoot->getOrCreateStateSet()->setRenderingHint(osg::StateSet::OPAQUE_BIN);
|
mTerrainRoot->getOrCreateStateSet()->setRenderingHint(osg::StateSet::OPAQUE_BIN);
|
||||||
mTerrainRoot->setName("Terrain Root");
|
mTerrainRoot->setName("Terrain Root");
|
||||||
|
|
||||||
|
osg::ref_ptr<CompositeMapRenderer> renderer (new CompositeMapRenderer);
|
||||||
|
mTerrainRoot->addChild(renderer);
|
||||||
|
|
||||||
mParent->addChild(mTerrainRoot);
|
mParent->addChild(mTerrainRoot);
|
||||||
|
|
||||||
mTextureManager.reset(new TextureManager(mResourceSystem->getSceneManager()));
|
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(mChunkManager.get());
|
||||||
mResourceSystem->addResourceManager(mTextureManager.get());
|
mResourceSystem->addResourceManager(mTextureManager.get());
|
||||||
|
|
Loading…
Reference in a new issue