#include "compositemaprenderer.hpp" #include #include #include #include namespace Terrain { CompositeMapRenderer::CompositeMapRenderer() : mTargetFrameRate(120) , mMinimumTimeAvailable(0.0025) { setSupportsDisplayList(false); setCullingActive(false); mFBO = new osg::FrameBufferObject; getOrCreateStateSet()->setMode(GL_LIGHTING, osg::StateAttribute::OFF); } CompositeMapRenderer::~CompositeMapRenderer() { } 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(mTargetFrameRate); double conservativeTimeRatio(0.75); double availableTime = std::max((targetFrameTime - dt)*conservativeTimeRatio, mMinimumTimeAvailable); std::lock_guard lock(mMutex); if (mImmediateCompileSet.empty() && mCompileSet.empty()) return; while (!mImmediateCompileSet.empty()) { osg::ref_ptr 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 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(); 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; igetStateSet(); 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; 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>(); 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 lock(mMutex); if (immediate) mImmediateCompileSet.insert(compositeMap); else mCompileSet.insert(compositeMap); } void CompositeMapRenderer::setImmediate(CompositeMap* compositeMap) { std::lock_guard 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 lock(mMutex); return mCompileSet.size(); } CompositeMap::CompositeMap() : mCompiled(0) { } CompositeMap::~CompositeMap() { } }