mirror of
https://github.com/TES3MP/openmw-tes3mp.git
synced 2025-01-22 03:53:52 +00:00
Merge branch 'bzzt_6_fix_shadows_in_screenshot_with_octreeoclusion' into 'master'
fix shadows in save game screenshot See merge request OpenMW/openmw!183
This commit is contained in:
commit
728b92c4d8
3 changed files with 58 additions and 9 deletions
|
@ -744,18 +744,20 @@ namespace MWRender
|
||||||
class NotifyDrawCompletedCallback : public osg::Camera::DrawCallback
|
class NotifyDrawCompletedCallback : public osg::Camera::DrawCallback
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
NotifyDrawCompletedCallback()
|
NotifyDrawCompletedCallback(unsigned int frame)
|
||||||
: mDone(false)
|
: mDone(false), mFrame(frame)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual void operator () (osg::RenderInfo& renderInfo) const
|
virtual void operator () (osg::RenderInfo& renderInfo) const
|
||||||
{
|
{
|
||||||
mMutex.lock();
|
OpenThreads::ScopedLock<OpenThreads::Mutex> lock(mMutex);
|
||||||
|
if (renderInfo.getState()->getFrameStamp()->getFrameNumber() >= mFrame)
|
||||||
|
{
|
||||||
mDone = true;
|
mDone = true;
|
||||||
mMutex.unlock();
|
|
||||||
mCondition.signal();
|
mCondition.signal();
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void waitTillDone()
|
void waitTillDone()
|
||||||
{
|
{
|
||||||
|
@ -769,6 +771,7 @@ namespace MWRender
|
||||||
mutable OpenThreads::Condition mCondition;
|
mutable OpenThreads::Condition mCondition;
|
||||||
mutable OpenThreads::Mutex mMutex;
|
mutable OpenThreads::Mutex mMutex;
|
||||||
mutable bool mDone;
|
mutable bool mDone;
|
||||||
|
unsigned int mFrame;
|
||||||
};
|
};
|
||||||
|
|
||||||
bool RenderingManager::screenshot360(osg::Image* image, std::string settingStr)
|
bool RenderingManager::screenshot360(osg::Image* image, std::string settingStr)
|
||||||
|
@ -948,7 +951,7 @@ namespace MWRender
|
||||||
mRootNode->addChild(camera);
|
mRootNode->addChild(camera);
|
||||||
|
|
||||||
// The draw needs to complete before we can copy back our image.
|
// 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);
|
camera->setFinalDrawCallback(callback);
|
||||||
|
|
||||||
MWBase::Environment::get().getWindowManager()->getLoadingScreen()->loadingOn(false);
|
MWBase::Environment::get().getWindowManager()->getLoadingScreen()->loadingOn(false);
|
||||||
|
@ -967,6 +970,51 @@ namespace MWRender
|
||||||
mRootNode->removeChild(camera);
|
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::screenshotFramebuffer(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 frame number 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)
|
void RenderingManager::screenshot(osg::Image *image, int w, int h, osg::Matrixd cameraTransform)
|
||||||
{
|
{
|
||||||
osg::ref_ptr<osg::Camera> rttCamera (new osg::Camera);
|
osg::ref_ptr<osg::Camera> rttCamera (new osg::Camera);
|
||||||
|
|
|
@ -144,7 +144,8 @@ namespace MWRender
|
||||||
void setWaterHeight(float level);
|
void setWaterHeight(float level);
|
||||||
|
|
||||||
/// Take a screenshot of w*h onto the given image, not including the GUI.
|
/// 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 screenshot(osg::Image* image, int w, int h, osg::Matrixd cameraTransform=osg::Matrixd()); // make a new render at given size
|
||||||
|
void screenshotFramebuffer(osg::Image* image, int w, int h); // copy directly from framebuffer and scale to given size
|
||||||
bool screenshot360(osg::Image* image, std::string settingStr);
|
bool screenshot360(osg::Image* image, std::string settingStr);
|
||||||
|
|
||||||
struct RayResult
|
struct RayResult
|
||||||
|
|
|
@ -2554,7 +2554,7 @@ namespace MWWorld
|
||||||
|
|
||||||
void World::screenshot(osg::Image* image, int w, int h)
|
void World::screenshot(osg::Image* image, int w, int h)
|
||||||
{
|
{
|
||||||
mRendering->screenshot(image, w, h);
|
mRendering->screenshotFramebuffer(image, w, h);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool World::screenshot360(osg::Image* image, std::string settingStr)
|
bool World::screenshot360(osg::Image* image, std::string settingStr)
|
||||||
|
|
Loading…
Reference in a new issue