mirror of
https://gitlab.com/OpenMW/openmw.git
synced 2025-01-07 12:54:00 +00:00
Merge branch '6013-fix' into 'master'
Retain draw callback Closes #6013 and #5967 See merge request OpenMW/openmw!875
This commit is contained in:
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…
Reference in New Issue
Block a user