You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
217 lines
5.8 KiB
C++
217 lines
5.8 KiB
C++
#include "compositemaprenderer.hpp"
|
|
|
|
#include <osg/FrameBufferObject>
|
|
#include <osg/Texture2D>
|
|
#include <osg/RenderInfo>
|
|
|
|
#include <components/sceneutil/unrefqueue.hpp>
|
|
#include <components/sceneutil/workqueue.hpp>
|
|
|
|
#include <algorithm>
|
|
|
|
namespace Terrain
|
|
{
|
|
|
|
CompositeMapRenderer::CompositeMapRenderer()
|
|
: mTargetFrameRate(120)
|
|
, mMinimumTimeAvailable(0.0025)
|
|
{
|
|
setSupportsDisplayList(false);
|
|
setCullingActive(false);
|
|
|
|
mFBO = new osg::FrameBufferObject;
|
|
|
|
mUnrefQueue = new SceneUtil::UnrefQueue;
|
|
|
|
getOrCreateStateSet()->setMode(GL_LIGHTING, osg::StateAttribute::OFF);
|
|
}
|
|
|
|
CompositeMapRenderer::~CompositeMapRenderer()
|
|
{
|
|
}
|
|
|
|
void CompositeMapRenderer::setWorkQueue(SceneUtil::WorkQueue* workQueue)
|
|
{
|
|
mWorkQueue = workQueue;
|
|
}
|
|
|
|
void CompositeMapRenderer::drawImplementation(osg::RenderInfo &renderInfo) const
|
|
{
|
|
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);
|
|
|
|
if (mWorkQueue)
|
|
mUnrefQueue->flush(mWorkQueue.get());
|
|
|
|
std::lock_guard<std::mutex> lock(mMutex);
|
|
|
|
if (mImmediateCompileSet.empty() && mCompileSet.empty())
|
|
return;
|
|
|
|
while (!mImmediateCompileSet.empty())
|
|
{
|
|
osg::ref_ptr<CompositeMap> node = *mImmediateCompileSet.begin();
|
|
mImmediateCompileSet.erase(node);
|
|
|
|
mMutex.unlock();
|
|
compile(*node, renderInfo, nullptr);
|
|
mMutex.lock();
|
|
}
|
|
|
|
double timeLeft = availableTime;
|
|
|
|
while (!mCompileSet.empty() && timeLeft > 0)
|
|
{
|
|
osg::ref_ptr<CompositeMap> node = *mCompileSet.begin();
|
|
mCompileSet.erase(node);
|
|
|
|
mMutex.unlock();
|
|
compile(*node, renderInfo, &timeLeft);
|
|
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);
|
|
}
|
|
}
|
|
mTimer.setStartTick();
|
|
}
|
|
|
|
void CompositeMapRenderer::compile(CompositeMap &compositeMap, osg::RenderInfo &renderInfo, double* timeLeft) const
|
|
{
|
|
// 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;
|
|
}
|
|
|
|
osg::Timer timer;
|
|
osg::State& state = *renderInfo.getState();
|
|
osg::GLExtensions* ext = state.get<osg::GLExtensions>();
|
|
|
|
if (!mFBO)
|
|
return;
|
|
|
|
if (!ext->isFrameBufferObjectSupported)
|
|
return;
|
|
|
|
osg::FrameBufferAttachment attach (compositeMap.mTexture);
|
|
mFBO->setAttachment(osg::Camera::COLOR_BUFFER, attach);
|
|
mFBO->apply(state, osg::FrameBufferObject::DRAW_FRAMEBUFFER);
|
|
|
|
GLenum status = ext->glCheckFramebufferStatus(GL_FRAMEBUFFER_EXT);
|
|
|
|
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;
|
|
}
|
|
|
|
// 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);
|
|
|
|
for (unsigned int i=compositeMap.mCompiled; i<compositeMap.mDrawables.size(); ++i)
|
|
{
|
|
osg::Drawable* drw = compositeMap.mDrawables[i];
|
|
osg::StateSet* stateset = drw->getStateSet();
|
|
|
|
if (stateset)
|
|
renderInfo.getState()->pushStateSet(stateset);
|
|
|
|
renderInfo.getState()->apply();
|
|
|
|
glViewport(0,0,compositeMap.mTexture->getTextureWidth(), compositeMap.mTexture->getTextureHeight());
|
|
drw->drawImplementation(renderInfo);
|
|
|
|
if (stateset)
|
|
renderInfo.getState()->popStateSet();
|
|
|
|
++compositeMap.mCompiled;
|
|
|
|
if (mWorkQueue)
|
|
{
|
|
mUnrefQueue->push(compositeMap.mDrawables[i]);
|
|
}
|
|
compositeMap.mDrawables[i] = nullptr;
|
|
|
|
if (timeLeft)
|
|
{
|
|
*timeLeft -= timer.time_s();
|
|
timer.setStartTick();
|
|
|
|
if (*timeLeft <= 0)
|
|
break;
|
|
}
|
|
}
|
|
if (compositeMap.mCompiled == compositeMap.mDrawables.size())
|
|
compositeMap.mDrawables = std::vector<osg::ref_ptr<osg::Drawable>>();
|
|
|
|
state.haveAppliedAttribute(osg::StateAttribute::VIEWPORT);
|
|
|
|
GLuint fboId = state.getGraphicsContext() ? state.getGraphicsContext()->getDefaultFboId() : 0;
|
|
ext->glBindFramebuffer(GL_FRAMEBUFFER_EXT, fboId);
|
|
}
|
|
|
|
void CompositeMapRenderer::setMinimumTimeAvailableForCompile(double time)
|
|
{
|
|
mMinimumTimeAvailable = time;
|
|
}
|
|
|
|
void CompositeMapRenderer::setTargetFrameRate(float framerate)
|
|
{
|
|
mTargetFrameRate = framerate;
|
|
}
|
|
|
|
void CompositeMapRenderer::addCompositeMap(CompositeMap* compositeMap, bool immediate)
|
|
{
|
|
std::lock_guard<std::mutex> lock(mMutex);
|
|
if (immediate)
|
|
mImmediateCompileSet.insert(compositeMap);
|
|
else
|
|
mCompileSet.insert(compositeMap);
|
|
}
|
|
|
|
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);
|
|
}
|
|
}
|
|
|
|
unsigned int CompositeMapRenderer::getCompileSetSize() const
|
|
{
|
|
std::lock_guard<std::mutex> lock(mMutex);
|
|
return mCompileSet.size();
|
|
}
|
|
|
|
CompositeMap::CompositeMap()
|
|
: mCompiled(0)
|
|
{
|
|
}
|
|
|
|
CompositeMap::~CompositeMap()
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|