mirror of
https://github.com/TES3MP/openmw-tes3mp.git
synced 2025-01-21 13:23:52 +00:00
fixes shadows on savegame screenshot
This commit is contained in:
parent
e1a5435531
commit
1cd4b9ee68
3 changed files with 58 additions and 9 deletions
|
@ -744,17 +744,19 @@ namespace MWRender
|
|||
class NotifyDrawCompletedCallback : public osg::Camera::DrawCallback
|
||||
{
|
||||
public:
|
||||
NotifyDrawCompletedCallback()
|
||||
: mDone(false)
|
||||
NotifyDrawCompletedCallback(unsigned int frame)
|
||||
: mDone(false), mFrame(frame)
|
||||
{
|
||||
}
|
||||
|
||||
virtual void operator () (osg::RenderInfo& renderInfo) const
|
||||
{
|
||||
mMutex.lock();
|
||||
mDone = true;
|
||||
mMutex.unlock();
|
||||
mCondition.signal();
|
||||
OpenThreads::ScopedLock<OpenThreads::Mutex> lock(mMutex);
|
||||
if (renderInfo.getState()->getFrameStamp()->getFrameNumber() >= mFrame)
|
||||
{
|
||||
mDone = true;
|
||||
mCondition.signal();
|
||||
}
|
||||
}
|
||||
|
||||
void waitTillDone()
|
||||
|
@ -769,6 +771,7 @@ namespace MWRender
|
|||
mutable OpenThreads::Condition mCondition;
|
||||
mutable OpenThreads::Mutex mMutex;
|
||||
mutable bool mDone;
|
||||
unsigned int mFrame;
|
||||
};
|
||||
|
||||
bool RenderingManager::screenshot360(osg::Image* image, std::string settingStr)
|
||||
|
@ -948,7 +951,7 @@ namespace MWRender
|
|||
mRootNode->addChild(camera);
|
||||
|
||||
// The draw needs to complete before we can copy back our image.
|
||||
osg::ref_ptr<NotifyDrawCompletedCallback> callback (new NotifyDrawCompletedCallback);
|
||||
osg::ref_ptr<NotifyDrawCompletedCallback> callback (new NotifyDrawCompletedCallback(0));
|
||||
camera->setFinalDrawCallback(callback);
|
||||
|
||||
MWBase::Environment::get().getWindowManager()->getLoadingScreen()->loadingOn(false);
|
||||
|
@ -967,6 +970,51 @@ namespace MWRender
|
|||
mRootNode->removeChild(camera);
|
||||
}
|
||||
|
||||
class ReadImageFromFramebufferCallback : public osg::Drawable::DrawCallback
|
||||
{
|
||||
public:
|
||||
ReadImageFromFramebufferCallback(osg::Image* image, int width, int height)
|
||||
: mWidth(width), mHeight(height), mImage(image)
|
||||
{
|
||||
}
|
||||
virtual void drawImplementation(osg::RenderInfo& renderInfo,const osg::Drawable* /*drawable*/) const
|
||||
{
|
||||
int screenW = renderInfo.getCurrentCamera()->getViewport()->width();
|
||||
int screenH = renderInfo.getCurrentCamera()->getViewport()->height();
|
||||
double imageaspect = (double)mWidth/(double)mHeight;
|
||||
int leftPadding = std::max(0, static_cast<int>(screenW - screenH * imageaspect) / 2);
|
||||
int topPadding = std::max(0, static_cast<int>(screenH - screenW / imageaspect) / 2);
|
||||
int width = screenW - leftPadding*2;
|
||||
int height = screenH - topPadding*2;
|
||||
mImage->readPixels(leftPadding, topPadding, width, height, GL_RGB, GL_UNSIGNED_BYTE);
|
||||
mImage->scaleImage(mWidth, mHeight, 1);
|
||||
}
|
||||
private:
|
||||
int mWidth;
|
||||
int mHeight;
|
||||
osg::ref_ptr<osg::Image> mImage;
|
||||
};
|
||||
|
||||
void RenderingManager::screenshotScreen(osg::Image* image, int w, int h)
|
||||
{
|
||||
osg::Camera* camera = mViewer->getCamera();
|
||||
osg::ref_ptr<osg::Drawable> tempDrw = new osg::Drawable;
|
||||
tempDrw->setDrawCallback(new ReadImageFromFramebufferCallback(image, w, h));
|
||||
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();
|
||||
// now that we've "used up" the current frame, get a fresh framenumber for the next frame() following after the screenshot is completed
|
||||
mViewer->advance(mViewer->getFrameStamp()->getSimulationTime());
|
||||
camera->removeChild(tempDrw);
|
||||
camera->setFinalDrawCallback(nullptr);
|
||||
}
|
||||
|
||||
void RenderingManager::screenshot(osg::Image *image, int w, int h, osg::Matrixd cameraTransform)
|
||||
{
|
||||
osg::ref_ptr<osg::Camera> rttCamera (new osg::Camera);
|
||||
|
|
|
@ -144,7 +144,8 @@ namespace MWRender
|
|||
void setWaterHeight(float level);
|
||||
|
||||
/// Take a screenshot of w*h onto the given image, not including the GUI.
|
||||
void screenshot(osg::Image* image, int w, int h, osg::Matrixd cameraTransform=osg::Matrixd());
|
||||
void screenshotScreen(osg::Image* image, int w, int h); // copie directly from framebuffer and scale to given size
|
||||
void screenshot(osg::Image* image, int w, int h, osg::Matrixd cameraTransform=osg::Matrixd()); // make a new render at given size
|
||||
bool screenshot360(osg::Image* image, std::string settingStr);
|
||||
|
||||
struct RayResult
|
||||
|
|
|
@ -2554,7 +2554,7 @@ namespace MWWorld
|
|||
|
||||
void World::screenshot(osg::Image* image, int w, int h)
|
||||
{
|
||||
mRendering->screenshot(image, w, h);
|
||||
mRendering->screenshotScreen(image, w, h);
|
||||
}
|
||||
|
||||
bool World::screenshot360(osg::Image* image, std::string settingStr)
|
||||
|
|
Loading…
Reference in a new issue