1
0
Fork 0
mirror of https://github.com/OpenMW/openmw.git synced 2025-01-20 06:53:54 +00:00
openmw/components/terrain/compositemaprenderer.cpp

182 lines
5.7 KiB
C++
Raw Normal View History

#include "compositemaprenderer.hpp"
#include <osg/FrameBufferObject>
#include <osg/RenderInfo>
2022-09-22 18:26:05 +00:00
#include <osg/Texture2D>
#include <algorithm>
namespace Terrain
{
2022-09-22 18:26:05 +00:00
CompositeMapRenderer::CompositeMapRenderer()
: mTargetFrameRate(120)
, mMinimumTimeAvailable(0.0025)
{
setSupportsDisplayList(false);
setCullingActive(false);
2022-09-22 18:26:05 +00:00
mFBO = new osg::FrameBufferObject;
2022-09-22 18:26:05 +00:00
getOrCreateStateSet()->setMode(GL_LIGHTING, osg::StateAttribute::OFF);
}
2022-09-22 18:26:05 +00:00
CompositeMapRenderer::~CompositeMapRenderer() {}
2022-09-22 18:26:05 +00:00
void CompositeMapRenderer::drawImplementation(osg::RenderInfo& renderInfo) const
{
2022-09-22 18:26:05 +00:00
double dt = mTimer.time_s();
dt = std::min(dt, 0.2);
mTimer.setStartTick();
double targetFrameTime = 1.0 / static_cast<double>(mTargetFrameRate);
double conservativeTimeRatio(0.75);
double availableTime = std::max((targetFrameTime - dt) * conservativeTimeRatio, mMinimumTimeAvailable);
2022-09-22 18:26:05 +00:00
std::lock_guard<std::mutex> lock(mMutex);
2022-09-22 18:26:05 +00:00
if (mImmediateCompileSet.empty() && mCompileSet.empty())
return;
2022-09-22 18:26:05 +00:00
while (!mImmediateCompileSet.empty())
{
osg::ref_ptr<CompositeMap> node = *mImmediateCompileSet.begin();
mImmediateCompileSet.erase(node);
mMutex.unlock();
2023-12-28 04:30:04 +00:00
compile(*node, renderInfo);
2022-09-22 18:26:05 +00:00
mMutex.lock();
}
2023-11-29 14:43:33 +00:00
const auto deadline = std::chrono::steady_clock::now() + std::chrono::duration<double>(availableTime);
while (!mCompileSet.empty() && std::chrono::steady_clock::now() < deadline)
{
2022-09-22 18:26:05 +00:00
osg::ref_ptr<CompositeMap> node = *mCompileSet.begin();
mCompileSet.erase(node);
mMutex.unlock();
2023-12-28 04:30:04 +00:00
compile(*node, renderInfo);
2022-09-22 18:26:05 +00:00
mMutex.lock();
if (node->mCompiled < node->mDrawables.size())
{
// We did not compile the map fully.
// Place it back to queue to continue work in the next time.
mCompileSet.insert(node);
}
}
2022-09-22 18:26:05 +00:00
mTimer.setStartTick();
}
2023-12-28 04:30:04 +00:00
void CompositeMapRenderer::compile(CompositeMap& compositeMap, osg::RenderInfo& renderInfo) const
{
2022-09-22 18:26:05 +00:00
// if there are no more external references we can assume the texture is no longer required
if (compositeMap.mTexture->referenceCount() <= 1)
{
compositeMap.mCompiled = compositeMap.mDrawables.size();
return;
}
2022-09-22 18:26:05 +00:00
osg::Timer timer;
osg::State& state = *renderInfo.getState();
osg::GLExtensions* ext = state.get<osg::GLExtensions>();
2022-09-22 18:26:05 +00:00
if (!mFBO)
return;
2022-09-22 18:26:05 +00:00
if (!ext->isFrameBufferObjectSupported)
return;
2022-09-22 18:26:05 +00:00
osg::FrameBufferAttachment attach(compositeMap.mTexture);
mFBO->setAttachment(osg::Camera::COLOR_BUFFER, attach);
mFBO->apply(state, osg::FrameBufferObject::DRAW_FRAMEBUFFER);
2022-09-22 18:26:05 +00:00
GLenum status = ext->glCheckFramebufferStatus(GL_FRAMEBUFFER_EXT);
2022-09-22 18:26:05 +00:00
if (status != GL_FRAMEBUFFER_COMPLETE_EXT)
{
GLuint fboId = state.getGraphicsContext() ? state.getGraphicsContext()->getDefaultFboId() : 0;
ext->glBindFramebuffer(GL_FRAMEBUFFER_EXT, fboId);
OSG_ALWAYS << "Error attaching FBO" << std::endl;
return;
}
2022-09-22 18:26:05 +00:00
// inform State that Texture attribute has changed due to compiling of FBO texture
// should OSG be doing this on its own?
state.haveAppliedTextureAttribute(state.getActiveTextureUnit(), osg::StateAttribute::TEXTURE);
2022-09-22 18:26:05 +00:00
for (unsigned int i = compositeMap.mCompiled; i < compositeMap.mDrawables.size(); ++i)
{
osg::Drawable* drw = compositeMap.mDrawables[i];
osg::StateSet* stateset = drw->getStateSet();
2022-09-22 18:26:05 +00:00
if (stateset)
renderInfo.getState()->pushStateSet(stateset);
2022-09-22 18:26:05 +00:00
renderInfo.getState()->apply();
2022-09-22 18:26:05 +00:00
glViewport(0, 0, compositeMap.mTexture->getTextureWidth(), compositeMap.mTexture->getTextureHeight());
drw->drawImplementation(renderInfo);
2022-09-22 18:26:05 +00:00
if (stateset)
renderInfo.getState()->popStateSet();
2022-09-22 18:26:05 +00:00
++compositeMap.mCompiled;
2022-09-22 18:26:05 +00:00
compositeMap.mDrawables[i] = nullptr;
}
2022-09-22 18:26:05 +00:00
if (compositeMap.mCompiled == compositeMap.mDrawables.size())
compositeMap.mDrawables = std::vector<osg::ref_ptr<osg::Drawable>>();
2022-09-22 18:26:05 +00:00
state.haveAppliedAttribute(osg::StateAttribute::VIEWPORT);
2022-09-22 18:26:05 +00:00
GLuint fboId = state.getGraphicsContext() ? state.getGraphicsContext()->getDefaultFboId() : 0;
ext->glBindFramebuffer(GL_FRAMEBUFFER_EXT, fboId);
}
2022-09-22 18:26:05 +00:00
void CompositeMapRenderer::setMinimumTimeAvailableForCompile(double time)
2017-03-09 18:28:02 +00:00
{
2022-09-22 18:26:05 +00:00
mMinimumTimeAvailable = time;
2017-03-09 18:28:02 +00:00
}
2022-09-22 18:26:05 +00:00
void CompositeMapRenderer::setTargetFrameRate(float framerate)
{
mTargetFrameRate = framerate;
}
2022-09-22 18:26:05 +00:00
void CompositeMapRenderer::addCompositeMap(CompositeMap* compositeMap, bool immediate)
{
std::lock_guard<std::mutex> lock(mMutex);
if (immediate)
mImmediateCompileSet.insert(compositeMap);
else
mCompileSet.insert(compositeMap);
}
2022-09-22 18:26:05 +00:00
void CompositeMapRenderer::setImmediate(CompositeMap* compositeMap)
{
std::lock_guard<std::mutex> lock(mMutex);
CompileSet::iterator found = mCompileSet.find(compositeMap);
if (found == mCompileSet.end())
return;
else
{
mImmediateCompileSet.insert(compositeMap);
mCompileSet.erase(found);
}
}
2022-09-22 18:26:05 +00:00
unsigned int CompositeMapRenderer::getCompileSetSize() const
{
std::lock_guard<std::mutex> lock(mMutex);
return mCompileSet.size();
}
2022-09-22 18:26:05 +00:00
CompositeMap::CompositeMap()
: mCompiled(0)
{
}
2022-09-22 18:26:05 +00:00
CompositeMap::~CompositeMap() {}
}