Merge branch '6013-fix' into 'master'

Retain draw callback

Closes #6013 and #5967

See merge request OpenMW/openmw!875
pull/593/head
AnyOldName3 4 years ago
commit c2e4eda825

@ -36,15 +36,15 @@ namespace MWRender
class NotifyDrawCompletedCallback : public osg::Camera::DrawCallback
{
public:
NotifyDrawCompletedCallback(unsigned int frame)
: mDone(false), mFrame(frame)
NotifyDrawCompletedCallback()
: mDone(false), mFrame(0)
{
}
void operator () (osg::RenderInfo& renderInfo) const override
{
std::lock_guard<std::mutex> lock(mMutex);
if (renderInfo.getState()->getFrameStamp()->getFrameNumber() >= mFrame)
if (renderInfo.getState()->getFrameStamp()->getFrameNumber() >= mFrame && !mDone)
{
mDone = true;
mCondition.notify_one();
@ -59,6 +59,12 @@ namespace MWRender
mCondition.wait(lock);
}
void reset(unsigned int frame)
{
mDone = false;
mFrame = frame;
}
mutable std::condition_variable mCondition;
mutable std::mutex mMutex;
mutable bool mDone;
@ -94,8 +100,18 @@ namespace MWRender
: mViewer(viewer)
, mRootNode(rootNode)
, mSceneRoot(sceneRoot)
, mDrawCompleteCallback(new NotifyDrawCompletedCallback)
, mResourceSystem(resourceSystem)
, mWater(water)
{
// Note: This assumes no other final draw callbacks are set anywhere and that this callback will remain set until the application exits.
// This works around *DrawCallback manipulation being unsafe in OSG >= 3.5.10 for release 0.47
// If you need to set other final draw callbacks, read the comments of issue 6013 for a suggestion
// Ref https://gitlab.com/OpenMW/openmw/-/issues/6013
mViewer->getCamera()->setFinalDrawCallback(mDrawCompleteCallback);
}
ScreenshotManager::~ScreenshotManager()
{
}
@ -107,16 +123,10 @@ namespace MWRender
tempDrw->setCullingActive(false);
tempDrw->getOrCreateStateSet()->setRenderBinDetails(100, "RenderBin", osg::StateSet::USE_RENDERBIN_DETAILS); // so its after all scene bins but before POST_RENDER gui camera
camera->addChild(tempDrw);
osg::ref_ptr<NotifyDrawCompletedCallback> callback (new NotifyDrawCompletedCallback(mViewer->getFrameStamp()->getFrameNumber()));
camera->setFinalDrawCallback(callback);
mViewer->eventTraversal();
mViewer->updateTraversal();
mViewer->renderingTraversals();
callback->waitTillDone();
traversalsAndWait(mViewer->getFrameStamp()->getFrameNumber());
// now that we've "used up" the current frame, get a fresh frame number for the next frame() following after the screenshot is completed
mViewer->advance(mViewer->getFrameStamp()->getSimulationTime());
camera->removeChild(tempDrw);
camera->setFinalDrawCallback(nullptr);
}
bool ScreenshotManager::screenshot360(osg::Image* image)
@ -257,6 +267,15 @@ namespace MWRender
return true;
}
void ScreenshotManager::traversalsAndWait(unsigned int frame)
{
mDrawCompleteCallback->reset(frame);
mViewer->eventTraversal();
mViewer->updateTraversal();
mViewer->renderingTraversals();
mDrawCompleteCallback->waitTillDone();
}
void ScreenshotManager::renderCameraToImage(osg::Camera *camera, osg::Image *image, int w, int h)
{
camera->setNodeMask(Mask_RenderToTexture);
@ -280,16 +299,10 @@ namespace MWRender
mRootNode->addChild(camera);
// The draw needs to complete before we can copy back our image.
osg::ref_ptr<NotifyDrawCompletedCallback> callback (new NotifyDrawCompletedCallback(0));
camera->setFinalDrawCallback(callback);
MWBase::Environment::get().getWindowManager()->getLoadingScreen()->loadingOn(false);
mViewer->eventTraversal();
mViewer->updateTraversal();
mViewer->renderingTraversals();
callback->waitTillDone();
// The draw needs to complete before we can copy back our image.
traversalsAndWait(0);
MWBase::Environment::get().getWindowManager()->getLoadingScreen()->loadingOff();

@ -16,11 +16,13 @@ namespace Resource
namespace MWRender
{
class Water;
class NotifyDrawCompletedCallback;
class ScreenshotManager
{
public:
ScreenshotManager(osgViewer::Viewer* viewer, osg::ref_ptr<osg::Group> rootNode, osg::ref_ptr<osg::Group> sceneRoot, Resource::ResourceSystem* resourceSystem, Water* water);
~ScreenshotManager();
void screenshot(osg::Image* image, int w, int h);
bool screenshot360(osg::Image* image);
@ -29,9 +31,11 @@ namespace MWRender
osg::ref_ptr<osgViewer::Viewer> mViewer;
osg::ref_ptr<osg::Group> mRootNode;
osg::ref_ptr<osg::Group> mSceneRoot;
osg::ref_ptr<NotifyDrawCompletedCallback> mDrawCompleteCallback;
Resource::ResourceSystem* mResourceSystem;
Water* mWater;
void traversalsAndWait(unsigned int frame);
void renderCameraToImage(osg::Camera *camera, osg::Image *image, int w, int h);
void makeCubemapScreenshot(osg::Image* image, int w, int h, osg::Matrixd cameraTransform=osg::Matrixd());
};

Loading…
Cancel
Save