mirror of
https://gitlab.com/OpenMW/openmw.git
synced 2025-02-03 17:54:06 +00:00
temporary fix for auto exposure
This commit is contained in:
parent
ea9f2761c3
commit
fd4966f77a
@ -149,7 +149,7 @@ bool Launcher::AdvancedPage::loadSettings()
|
||||
loadSettingBool(postprocessEnabledCheckBox, "enabled", "Post Processing");
|
||||
loadSettingBool(postprocessLiveReloadCheckBox, "live reload", "Post Processing");
|
||||
loadSettingBool(postprocessTransparentPostpassCheckBox, "transparent postpass", "Post Processing");
|
||||
postprocessHDRTimeComboBox->setValue(Settings::Manager::getDouble("hdr exposure time", "Post Processing"));
|
||||
postprocessHDRTimeComboBox->setValue(Settings::Manager::getDouble("auto exposure speed", "Post Processing"));
|
||||
|
||||
connect(skyBlendingCheckBox, SIGNAL(toggled(bool)), this, SLOT(slotSkyBlendingToggled(bool)));
|
||||
loadSettingBool(radialFogCheckBox, "radial fog", "Fog");
|
||||
@ -305,8 +305,8 @@ void Launcher::AdvancedPage::saveSettings()
|
||||
saveSettingBool(postprocessLiveReloadCheckBox, "live reload", "Post Processing");
|
||||
saveSettingBool(postprocessTransparentPostpassCheckBox, "transparent postpass", "Post Processing");
|
||||
double hdrExposureTime = postprocessHDRTimeComboBox->value();
|
||||
if (hdrExposureTime != Settings::Manager::getDouble("hdr exposure time", "Post Processing"))
|
||||
Settings::Manager::setDouble("hdr exposure time", "Post Processing", hdrExposureTime);
|
||||
if (hdrExposureTime != Settings::Manager::getDouble("auto exposure speed", "Post Processing"))
|
||||
Settings::Manager::setDouble("auto exposure speed", "Post Processing", hdrExposureTime);
|
||||
|
||||
saveSettingBool(radialFogCheckBox, "radial fog", "Fog");
|
||||
saveSettingBool(exponentialFogCheckBox, "exponential fog", "Fog");
|
||||
|
@ -23,7 +23,7 @@ add_openmw_dir (mwrender
|
||||
creatureanimation effectmanager util renderinginterface pathgrid rendermode weaponanimation screenshotmanager
|
||||
bulletdebugdraw globalmap characterpreview camera localmap water terrainstorage ripplesimulation
|
||||
renderbin actoranimation landmanager navmesh actorspaths recastmesh fogmanager objectpaging groundcover
|
||||
postprocessor pingpongcull hdr pingpongcanvas transparentpass navmeshmode
|
||||
postprocessor pingpongcull luminancecalculator pingpongcanvas transparentpass navmeshmode
|
||||
)
|
||||
|
||||
add_openmw_dir (mwinput
|
||||
|
@ -1,123 +0,0 @@
|
||||
#include "hdr.hpp"
|
||||
|
||||
#include <components/settings/settings.hpp>
|
||||
#include <components/shader/shadermanager.hpp>
|
||||
|
||||
#include "pingpongcanvas.hpp"
|
||||
|
||||
namespace MWRender
|
||||
{
|
||||
HDRDriver::HDRDriver(Shader::ShaderManager& shaderManager)
|
||||
: mCompiled(false)
|
||||
, mEnabled(false)
|
||||
, mWidth(1)
|
||||
, mHeight(1)
|
||||
{
|
||||
const float hdrExposureTime = std::clamp(Settings::Manager::getFloat("hdr exposure time", "Post Processing"), 0.f, 1.f);
|
||||
|
||||
constexpr float minLog = -9.0;
|
||||
constexpr float maxLog = 4.0;
|
||||
constexpr float logLumRange = (maxLog - minLog);
|
||||
constexpr float invLogLumRange = 1.0 / logLumRange;
|
||||
constexpr float epsilon = 0.004;
|
||||
|
||||
Shader::ShaderManager::DefineMap defines = {
|
||||
{"minLog", std::to_string(minLog)},
|
||||
{"maxLog", std::to_string(maxLog)},
|
||||
{"logLumRange", std::to_string(logLumRange)},
|
||||
{"invLogLumRange", std::to_string(invLogLumRange)},
|
||||
{"hdrExposureTime", std::to_string(hdrExposureTime)},
|
||||
{"epsilon", std::to_string(epsilon)},
|
||||
};
|
||||
|
||||
auto vertex = shaderManager.getShader("fullscreen_tri_vertex.glsl", {}, osg::Shader::VERTEX);
|
||||
auto hdrLuminance = shaderManager.getShader("hdr_luminance_fragment.glsl", defines, osg::Shader::FRAGMENT);
|
||||
auto hdr = shaderManager.getShader("hdr_fragment.glsl", defines, osg::Shader::FRAGMENT);
|
||||
|
||||
mProgram = shaderManager.getProgram(vertex, hdr);
|
||||
mLuminanceProgram = shaderManager.getProgram(vertex, hdrLuminance);
|
||||
}
|
||||
|
||||
void HDRDriver::compile()
|
||||
{
|
||||
int mipmapLevels = osg::Image::computeNumberOfMipmapLevels(mWidth, mHeight);
|
||||
|
||||
for (auto& buffer : mBuffers)
|
||||
{
|
||||
buffer.texture = new osg::Texture2D;
|
||||
buffer.texture->setInternalFormat(GL_R16F);
|
||||
buffer.texture->setSourceFormat(GL_RED);
|
||||
buffer.texture->setSourceType(GL_FLOAT);
|
||||
buffer.texture->setFilter(osg::Texture2D::MIN_FILTER, osg::Texture2D::LINEAR_MIPMAP_NEAREST);
|
||||
buffer.texture->setFilter(osg::Texture2D::MAG_FILTER, osg::Texture2D::LINEAR);
|
||||
buffer.texture->setTextureSize(mWidth, mHeight);
|
||||
buffer.texture->setNumMipmapLevels(mipmapLevels);
|
||||
|
||||
buffer.finalTexture = new osg::Texture2D;
|
||||
buffer.finalTexture->setInternalFormat(GL_R16F);
|
||||
buffer.finalTexture->setSourceFormat(GL_RED);
|
||||
buffer.finalTexture->setSourceType(GL_FLOAT);
|
||||
buffer.finalTexture->setFilter(osg::Texture2D::MIN_FILTER, osg::Texture2D::NEAREST);
|
||||
buffer.finalTexture->setFilter(osg::Texture2D::MAG_FILTER, osg::Texture2D::NEAREST);
|
||||
buffer.finalTexture->setTextureSize(1, 1);
|
||||
|
||||
buffer.finalFbo = new osg::FrameBufferObject;
|
||||
buffer.finalFbo->setAttachment(osg::FrameBufferObject::BufferComponent::COLOR_BUFFER0, osg::FrameBufferAttachment(buffer.finalTexture));
|
||||
|
||||
buffer.fullscreenFbo = new osg::FrameBufferObject;
|
||||
buffer.fullscreenFbo->setAttachment(osg::FrameBufferObject::BufferComponent::COLOR_BUFFER0, osg::FrameBufferAttachment(buffer.texture));
|
||||
|
||||
buffer.mipmapFbo = new osg::FrameBufferObject;
|
||||
buffer.mipmapFbo->setAttachment(osg::FrameBufferObject::BufferComponent::COLOR_BUFFER0, osg::FrameBufferAttachment(buffer.texture, mipmapLevels - 1));
|
||||
|
||||
buffer.fullscreenStateset = new osg::StateSet;
|
||||
buffer.fullscreenStateset->setAttributeAndModes(mLuminanceProgram);
|
||||
buffer.fullscreenStateset->addUniform(new osg::Uniform("sceneTex", 0));
|
||||
|
||||
buffer.mipmapStateset = new osg::StateSet;
|
||||
buffer.mipmapStateset->setAttributeAndModes(mProgram);
|
||||
buffer.mipmapStateset->setTextureAttributeAndModes(0, buffer.texture);
|
||||
buffer.mipmapStateset->addUniform(new osg::Uniform("luminanceSceneTex", 0));
|
||||
buffer.mipmapStateset->addUniform(new osg::Uniform("prevLuminanceSceneTex", 1));
|
||||
}
|
||||
|
||||
mBuffers[0].mipmapStateset->setTextureAttributeAndModes(1, mBuffers[1].finalTexture);
|
||||
mBuffers[1].mipmapStateset->setTextureAttributeAndModes(1, mBuffers[0].finalTexture);
|
||||
|
||||
mCompiled = true;
|
||||
}
|
||||
|
||||
void HDRDriver::draw(const PingPongCanvas& canvas, osg::RenderInfo& renderInfo, osg::State& state, osg::GLExtensions* ext, size_t frameId)
|
||||
{
|
||||
if (!mEnabled)
|
||||
return;
|
||||
|
||||
if (!mCompiled)
|
||||
compile();
|
||||
|
||||
auto& hdrBuffer = mBuffers[frameId];
|
||||
hdrBuffer.fullscreenFbo->apply(state, osg::FrameBufferObject::DRAW_FRAMEBUFFER);
|
||||
hdrBuffer.fullscreenStateset->setTextureAttributeAndModes(0, canvas.getSceneTexture(frameId));
|
||||
|
||||
state.apply(hdrBuffer.fullscreenStateset);
|
||||
canvas.drawGeometry(renderInfo);
|
||||
|
||||
state.applyTextureAttribute(0, hdrBuffer.texture);
|
||||
ext->glGenerateMipmap(GL_TEXTURE_2D);
|
||||
|
||||
hdrBuffer.mipmapFbo->apply(state, osg::FrameBufferObject::READ_FRAMEBUFFER);
|
||||
hdrBuffer.finalFbo->apply(state, osg::FrameBufferObject::DRAW_FRAMEBUFFER);
|
||||
|
||||
ext->glBlitFramebuffer(0, 0, 1, 1, 0, 0, 1, 1, GL_COLOR_BUFFER_BIT, GL_LINEAR);
|
||||
|
||||
state.apply(hdrBuffer.mipmapStateset);
|
||||
canvas.drawGeometry(renderInfo);
|
||||
|
||||
ext->glBindFramebuffer(GL_FRAMEBUFFER_EXT, state.getGraphicsContext() ? state.getGraphicsContext()->getDefaultFboId() : 0);
|
||||
}
|
||||
|
||||
osg::ref_ptr<osg::Texture2D> HDRDriver::getLuminanceTexture(size_t frameId) const
|
||||
{
|
||||
return mBuffers[frameId].finalTexture;
|
||||
}
|
||||
}
|
@ -1,71 +0,0 @@
|
||||
#ifndef OPENMW_MWRENDER_HDR_H
|
||||
#define OPENMW_MWRENDER_HDR_H
|
||||
|
||||
#include <array>
|
||||
|
||||
#include <osg/FrameBufferObject>
|
||||
#include <osg/Texture2D>
|
||||
#include <osg/Program>
|
||||
|
||||
namespace Shader
|
||||
{
|
||||
class ShaderManager;
|
||||
}
|
||||
|
||||
namespace MWRender
|
||||
{
|
||||
class PingPongCanvas;
|
||||
|
||||
class HDRDriver
|
||||
{
|
||||
|
||||
public:
|
||||
|
||||
HDRDriver() = default;
|
||||
|
||||
HDRDriver(Shader::ShaderManager& shaderManager);
|
||||
|
||||
void draw(const PingPongCanvas& canvas, osg::RenderInfo& renderInfo, osg::State& state, osg::GLExtensions* ext, size_t frameId);
|
||||
|
||||
bool isEnabled() const { return mEnabled; }
|
||||
|
||||
void enable() { mEnabled = true; }
|
||||
void disable() { mEnabled = false; }
|
||||
|
||||
void dirty(int w, int h)
|
||||
{
|
||||
mWidth = w;
|
||||
mHeight = h;
|
||||
mCompiled = false;
|
||||
}
|
||||
|
||||
osg::ref_ptr<osg::Texture2D> getLuminanceTexture(size_t frameId) const;
|
||||
|
||||
private:
|
||||
|
||||
void compile();
|
||||
|
||||
struct HDRContainer
|
||||
{
|
||||
osg::ref_ptr<osg::FrameBufferObject> fullscreenFbo;
|
||||
osg::ref_ptr<osg::FrameBufferObject> mipmapFbo;
|
||||
osg::ref_ptr<osg::FrameBufferObject> finalFbo;
|
||||
osg::ref_ptr<osg::Texture2D> texture;
|
||||
osg::ref_ptr<osg::Texture2D> finalTexture;
|
||||
osg::ref_ptr<osg::StateSet> fullscreenStateset;
|
||||
osg::ref_ptr<osg::StateSet> mipmapStateset;
|
||||
};
|
||||
|
||||
std::array<HDRContainer, 2> mBuffers;
|
||||
osg::ref_ptr<osg::Program> mLuminanceProgram;
|
||||
osg::ref_ptr<osg::Program> mProgram;
|
||||
|
||||
bool mCompiled;
|
||||
bool mEnabled;
|
||||
|
||||
int mWidth;
|
||||
int mHeight;
|
||||
};
|
||||
}
|
||||
|
||||
#endif
|
134
apps/openmw/mwrender/luminancecalculator.cpp
Normal file
134
apps/openmw/mwrender/luminancecalculator.cpp
Normal file
@ -0,0 +1,134 @@
|
||||
#include "luminancecalculator.hpp"
|
||||
|
||||
#include <components/settings/settings.hpp>
|
||||
#include <components/shader/shadermanager.hpp>
|
||||
|
||||
#include "pingpongcanvas.hpp"
|
||||
|
||||
namespace MWRender
|
||||
{
|
||||
LuminanceCalculator::LuminanceCalculator(Shader::ShaderManager& shaderManager)
|
||||
{
|
||||
const float hdrExposureTime = std::max(Settings::Manager::getFloat("auto exposure speed", "Post Processing"), 0.0001f);
|
||||
|
||||
constexpr float minLog = -9.0;
|
||||
constexpr float maxLog = 4.0;
|
||||
constexpr float logLumRange = (maxLog - minLog);
|
||||
constexpr float invLogLumRange = 1.0 / logLumRange;
|
||||
constexpr float epsilon = 0.004;
|
||||
|
||||
Shader::ShaderManager::DefineMap defines = {
|
||||
{"minLog", std::to_string(minLog)},
|
||||
{"maxLog", std::to_string(maxLog)},
|
||||
{"logLumRange", std::to_string(logLumRange)},
|
||||
{"invLogLumRange", std::to_string(invLogLumRange)},
|
||||
{"hdrExposureTime", std::to_string(hdrExposureTime)},
|
||||
{"epsilon", std::to_string(epsilon)},
|
||||
};
|
||||
|
||||
auto vertex = shaderManager.getShader("fullscreen_tri_vertex.glsl", {}, osg::Shader::VERTEX);
|
||||
auto luminanceFragment = shaderManager.getShader("hdr_luminance_fragment.glsl", defines, osg::Shader::FRAGMENT);
|
||||
auto resolveFragment = shaderManager.getShader("hdr_resolve_fragment.glsl", defines, osg::Shader::FRAGMENT);
|
||||
|
||||
mResolveProgram = shaderManager.getProgram(vertex, resolveFragment);
|
||||
mLuminanceProgram = shaderManager.getProgram(vertex, luminanceFragment);
|
||||
}
|
||||
|
||||
void LuminanceCalculator::compile()
|
||||
{
|
||||
int mipmapLevels = osg::Image::computeNumberOfMipmapLevels(mWidth, mHeight);
|
||||
|
||||
for (auto& buffer : mBuffers)
|
||||
{
|
||||
buffer.mipmappedSceneLuminanceTex = new osg::Texture2D;
|
||||
buffer.mipmappedSceneLuminanceTex->setInternalFormat(GL_R16F);
|
||||
buffer.mipmappedSceneLuminanceTex->setSourceFormat(GL_RED);
|
||||
buffer.mipmappedSceneLuminanceTex->setSourceType(GL_FLOAT);
|
||||
buffer.mipmappedSceneLuminanceTex->setFilter(osg::Texture2D::MIN_FILTER, osg::Texture2D::LINEAR_MIPMAP_NEAREST);
|
||||
buffer.mipmappedSceneLuminanceTex->setFilter(osg::Texture2D::MAG_FILTER, osg::Texture2D::LINEAR);
|
||||
buffer.mipmappedSceneLuminanceTex->setTextureSize(mWidth, mHeight);
|
||||
buffer.mipmappedSceneLuminanceTex->setNumMipmapLevels(mipmapLevels);
|
||||
|
||||
buffer.luminanceTex = new osg::Texture2D;
|
||||
buffer.luminanceTex->setInternalFormat(GL_R16F);
|
||||
buffer.luminanceTex->setSourceFormat(GL_RED);
|
||||
buffer.luminanceTex->setSourceType(GL_FLOAT);
|
||||
buffer.luminanceTex->setFilter(osg::Texture2D::MIN_FILTER, osg::Texture2D::NEAREST);
|
||||
buffer.luminanceTex->setFilter(osg::Texture2D::MAG_FILTER, osg::Texture2D::NEAREST);
|
||||
buffer.luminanceTex->setTextureSize(1, 1);
|
||||
|
||||
buffer.luminanceProxyTex = new osg::Texture2D(*buffer.luminanceTex);
|
||||
|
||||
buffer.resolveFbo = new osg::FrameBufferObject;
|
||||
buffer.resolveFbo->setAttachment(osg::FrameBufferObject::BufferComponent::COLOR_BUFFER0, osg::FrameBufferAttachment(buffer.luminanceTex));
|
||||
|
||||
buffer.luminanceProxyFbo = new osg::FrameBufferObject;
|
||||
buffer.luminanceProxyFbo->setAttachment(osg::FrameBufferObject::BufferComponent::COLOR_BUFFER0, osg::FrameBufferAttachment(buffer.luminanceProxyTex));
|
||||
|
||||
buffer.resolveSceneLumFbo = new osg::FrameBufferObject;
|
||||
buffer.resolveSceneLumFbo->setAttachment(osg::FrameBufferObject::BufferComponent::COLOR_BUFFER0, osg::FrameBufferAttachment(buffer.mipmappedSceneLuminanceTex, mipmapLevels - 1));
|
||||
|
||||
buffer.sceneLumFbo = new osg::FrameBufferObject;
|
||||
buffer.sceneLumFbo->setAttachment(osg::FrameBufferObject::BufferComponent::COLOR_BUFFER0, osg::FrameBufferAttachment(buffer.mipmappedSceneLuminanceTex));
|
||||
|
||||
buffer.sceneLumSS = new osg::StateSet;
|
||||
buffer.sceneLumSS->setAttributeAndModes(mLuminanceProgram);
|
||||
buffer.sceneLumSS->addUniform(new osg::Uniform("sceneTex", 0));
|
||||
|
||||
buffer.resolveSS = new osg::StateSet;
|
||||
buffer.resolveSS->setAttributeAndModes(mResolveProgram);
|
||||
buffer.resolveSS->setTextureAttributeAndModes(0, buffer.luminanceProxyTex);
|
||||
buffer.resolveSS->addUniform(new osg::Uniform("luminanceSceneTex", 0));
|
||||
buffer.resolveSS->addUniform(new osg::Uniform("prevLuminanceSceneTex", 1));
|
||||
}
|
||||
|
||||
mBuffers[0].resolveSS->setTextureAttributeAndModes(1, mBuffers[1].luminanceTex);
|
||||
mBuffers[1].resolveSS->setTextureAttributeAndModes(1, mBuffers[0].luminanceTex);
|
||||
|
||||
mCompiled = true;
|
||||
}
|
||||
|
||||
void LuminanceCalculator::draw(const PingPongCanvas& canvas, osg::RenderInfo& renderInfo, osg::State& state, osg::GLExtensions* ext, size_t frameId)
|
||||
{
|
||||
if (!mEnabled)
|
||||
return;
|
||||
|
||||
bool dirty = !mCompiled;
|
||||
|
||||
if (dirty)
|
||||
compile();
|
||||
|
||||
auto& buffer = mBuffers[frameId];
|
||||
buffer.sceneLumFbo->apply(state, osg::FrameBufferObject::DRAW_FRAMEBUFFER);
|
||||
buffer.sceneLumSS->setTextureAttributeAndModes(0, canvas.getSceneTexture(frameId));
|
||||
|
||||
state.apply(buffer.sceneLumSS);
|
||||
canvas.drawGeometry(renderInfo);
|
||||
|
||||
state.applyTextureAttribute(0, buffer.mipmappedSceneLuminanceTex);
|
||||
ext->glGenerateMipmap(GL_TEXTURE_2D);
|
||||
|
||||
buffer.resolveSceneLumFbo->apply(state, osg::FrameBufferObject::READ_FRAMEBUFFER);
|
||||
buffer.luminanceProxyFbo->apply(state, osg::FrameBufferObject::DRAW_FRAMEBUFFER);
|
||||
ext->glBlitFramebuffer(0, 0, 1, 1, 0, 0, 1, 1, GL_COLOR_BUFFER_BIT, GL_NEAREST);
|
||||
|
||||
if (dirty) {
|
||||
// Use current frame data for previous frame to warm up calculations and prevent popin
|
||||
mBuffers[(frameId + 1) % 2].resolveFbo->apply(state, osg::FrameBufferObject::DRAW_FRAMEBUFFER);
|
||||
ext->glBlitFramebuffer(0, 0, 1, 1, 0, 0, 1, 1, GL_COLOR_BUFFER_BIT, GL_NEAREST);
|
||||
|
||||
buffer.luminanceProxyFbo->apply(state, osg::FrameBufferObject::DRAW_FRAMEBUFFER);
|
||||
}
|
||||
|
||||
buffer.resolveFbo->apply(state, osg::FrameBufferObject::DRAW_FRAMEBUFFER);
|
||||
state.apply(buffer.resolveSS);
|
||||
canvas.drawGeometry(renderInfo);
|
||||
|
||||
ext->glBindFramebuffer(GL_FRAMEBUFFER_EXT, state.getGraphicsContext() ? state.getGraphicsContext()->getDefaultFboId() : 0);
|
||||
}
|
||||
|
||||
osg::ref_ptr<osg::Texture2D> LuminanceCalculator::getLuminanceTexture(size_t frameId) const
|
||||
{
|
||||
return mBuffers[frameId].luminanceTex;
|
||||
}
|
||||
}
|
74
apps/openmw/mwrender/luminancecalculator.hpp
Normal file
74
apps/openmw/mwrender/luminancecalculator.hpp
Normal file
@ -0,0 +1,74 @@
|
||||
#ifndef OPENMW_MWRENDER_LUMINANCECALCULATOR_H
|
||||
#define OPENMW_MWRENDER_LUMINANCECALCULATOR_H
|
||||
|
||||
#include <array>
|
||||
|
||||
#include <osg/FrameBufferObject>
|
||||
#include <osg/Texture2D>
|
||||
#include <osg/Program>
|
||||
|
||||
namespace Shader
|
||||
{
|
||||
class ShaderManager;
|
||||
}
|
||||
|
||||
namespace MWRender
|
||||
{
|
||||
class PingPongCanvas;
|
||||
|
||||
class LuminanceCalculator
|
||||
{
|
||||
|
||||
public:
|
||||
|
||||
LuminanceCalculator() = default;
|
||||
|
||||
LuminanceCalculator(Shader::ShaderManager& shaderManager);
|
||||
|
||||
void draw(const PingPongCanvas& canvas, osg::RenderInfo& renderInfo, osg::State& state, osg::GLExtensions* ext, size_t frameId);
|
||||
|
||||
bool isEnabled() const { return mEnabled; }
|
||||
|
||||
void enable() { mEnabled = true; }
|
||||
void disable() { mEnabled = false; }
|
||||
|
||||
void dirty(int w, int h)
|
||||
{
|
||||
constexpr float scale = 0.5;
|
||||
mWidth = w * scale;
|
||||
mHeight = h * scale;
|
||||
mCompiled = false;
|
||||
}
|
||||
|
||||
osg::ref_ptr<osg::Texture2D> getLuminanceTexture(size_t frameId) const;
|
||||
|
||||
private:
|
||||
|
||||
void compile();
|
||||
|
||||
struct Container
|
||||
{
|
||||
osg::ref_ptr<osg::FrameBufferObject> sceneLumFbo;
|
||||
osg::ref_ptr<osg::FrameBufferObject> resolveSceneLumFbo;
|
||||
osg::ref_ptr<osg::FrameBufferObject> resolveFbo;
|
||||
osg::ref_ptr<osg::FrameBufferObject> luminanceProxyFbo;
|
||||
osg::ref_ptr<osg::Texture2D> mipmappedSceneLuminanceTex;
|
||||
osg::ref_ptr<osg::Texture2D> luminanceTex;
|
||||
osg::ref_ptr<osg::Texture2D> luminanceProxyTex;
|
||||
osg::ref_ptr<osg::StateSet> sceneLumSS;
|
||||
osg::ref_ptr<osg::StateSet> resolveSS;
|
||||
};
|
||||
|
||||
std::array<Container, 2> mBuffers;
|
||||
osg::ref_ptr<osg::Program> mLuminanceProgram;
|
||||
osg::ref_ptr<osg::Program> mResolveProgram;
|
||||
|
||||
bool mCompiled = false;
|
||||
bool mEnabled = false;
|
||||
|
||||
int mWidth = 1;
|
||||
int mHeight = 1;
|
||||
};
|
||||
}
|
||||
|
||||
#endif
|
@ -27,8 +27,8 @@ namespace MWRender
|
||||
|
||||
addPrimitiveSet(new osg::DrawArrays(osg::PrimitiveSet::TRIANGLES, 0, 3));
|
||||
|
||||
mHDRDriver = HDRDriver(shaderManager);
|
||||
mHDRDriver.disable();
|
||||
mLuminanceCalculator = LuminanceCalculator(shaderManager);
|
||||
mLuminanceCalculator.disable();
|
||||
|
||||
Shader::ShaderManager::DefineMap defines;
|
||||
Stereo::Manager::instance().shaderStereoDefines(defines);
|
||||
@ -158,7 +158,7 @@ namespace MWRender
|
||||
mMultiviewResolveStateSet->setTextureAttribute(PostProcessor::Unit_LastShader, (osg::Texture*)mMultiviewResolveFramebuffer->getAttachment(osg::Camera::COLOR_BUFFER0).getTexture());
|
||||
}
|
||||
|
||||
mHDRDriver.dirty(bufferData.sceneTex->getTextureWidth(), bufferData.sceneTex->getTextureHeight());
|
||||
mLuminanceCalculator.dirty(bufferData.sceneTex->getTextureWidth(), bufferData.sceneTex->getTextureHeight());
|
||||
|
||||
if (Stereo::getStereo())
|
||||
mRenderViewport = new osg::Viewport(0, 0, bufferData.sceneTex->getTextureWidth(), bufferData.sceneTex->getTextureHeight());
|
||||
@ -174,10 +174,10 @@ namespace MWRender
|
||||
{GL_COLOR_ATTACHMENT0_EXT, GL_COLOR_ATTACHMENT1_EXT}
|
||||
}};
|
||||
|
||||
(bufferData.hdr) ? mHDRDriver.enable() : mHDRDriver.disable();
|
||||
(bufferData.hdr) ? mLuminanceCalculator.enable() : mLuminanceCalculator.disable();
|
||||
|
||||
// A histogram based approach is superior way to calculate scene luminance. Using mipmaps is more broadly supported, so that's what we use for now.
|
||||
mHDRDriver.draw(*this, renderInfo, state, ext, frameId);
|
||||
mLuminanceCalculator.draw(*this, renderInfo, state, ext, frameId);
|
||||
|
||||
auto buffer = buffers[0];
|
||||
|
||||
@ -217,7 +217,7 @@ namespace MWRender
|
||||
node.mRootStateSet->setTextureAttribute(PostProcessor::Unit_Depth, bufferData.depthTex);
|
||||
|
||||
if (bufferData.hdr)
|
||||
node.mRootStateSet->setTextureAttribute(PostProcessor::TextureUnits::Unit_EyeAdaptation, mHDRDriver.getLuminanceTexture(frameId));
|
||||
node.mRootStateSet->setTextureAttribute(PostProcessor::TextureUnits::Unit_EyeAdaptation, mLuminanceCalculator.getLuminanceTexture(frameId));
|
||||
|
||||
if (bufferData.normalsTex)
|
||||
node.mRootStateSet->setTextureAttribute(PostProcessor::TextureUnits::Unit_Normals, bufferData.normalsTex);
|
||||
|
@ -11,7 +11,7 @@
|
||||
#include <components/fx/technique.hpp>
|
||||
|
||||
#include "postprocessor.hpp"
|
||||
#include "hdr.hpp"
|
||||
#include "luminancecalculator.hpp"
|
||||
|
||||
namespace Shader
|
||||
{
|
||||
@ -55,7 +55,7 @@ namespace MWRender
|
||||
private:
|
||||
void copyNewFrameData(size_t frameId) const;
|
||||
|
||||
mutable HDRDriver mHDRDriver;
|
||||
mutable LuminanceCalculator mLuminanceCalculator;
|
||||
|
||||
osg::ref_ptr<osg::Program> mFallbackProgram;
|
||||
osg::ref_ptr<osg::Program> mMultiviewResolveProgram;
|
||||
|
@ -34,12 +34,12 @@ Automatically reloads a shader if the file has been changed. This is useful for
|
||||
.. warning::
|
||||
This should be disabled for normal gameplay
|
||||
|
||||
hdr exposure time
|
||||
-----------------
|
||||
auto exposure speed
|
||||
-------------------
|
||||
|
||||
:Type: float
|
||||
:Range: 0.0 to 1.0
|
||||
:Default: 0.05
|
||||
:Range: Any number > 0.0001
|
||||
:Default: 0.9
|
||||
|
||||
Use for eye adaptation to control speed at which average scene luminance can change from one frame to the next.
|
||||
Average scene luminance is used in some shader effects for features such as dynamic eye adaptation.
|
||||
|
@ -1204,7 +1204,7 @@ chain =
|
||||
live reload = false
|
||||
|
||||
# Used for eye adaptation to control speed at which scene luminance can change from one frame to the next. No effect when HDR is not being utilized.
|
||||
hdr exposure time = 0.05
|
||||
auto exposure speed = 0.9
|
||||
|
||||
# Transparent depth postpass. Re-renders transparent objects with alpha-clipping forced with a fixed threshold.
|
||||
transparent postpass = true
|
||||
|
@ -50,7 +50,7 @@ set(SHADER_FILES
|
||||
sky_fragment.glsl
|
||||
skypasses.glsl
|
||||
softparticles.glsl
|
||||
hdr_fragment.glsl
|
||||
hdr_resolve_fragment.glsl
|
||||
hdr_luminance_fragment.glsl
|
||||
fullscreen_tri_vertex.glsl
|
||||
fullscreen_tri_fragment.glsl
|
||||
|
@ -1,14 +0,0 @@
|
||||
#version 120
|
||||
|
||||
varying vec2 uv;
|
||||
uniform sampler2D luminanceSceneTex;
|
||||
uniform sampler2D prevLuminanceSceneTex;
|
||||
|
||||
void main()
|
||||
{
|
||||
float prevLum = texture2D(prevLuminanceSceneTex, vec2(0.5, 0.5)).r;
|
||||
|
||||
float l = texture2D(luminanceSceneTex, vec2(0.5, 0.5)).r;
|
||||
float weightedAvgLum = exp2((l * @logLumRange) + @minLog);
|
||||
gl_FragColor.r = prevLum + (weightedAvgLum - prevLum) * @hdrExposureTime;
|
||||
}
|
@ -6,12 +6,7 @@ uniform sampler2D sceneTex;
|
||||
void main()
|
||||
{
|
||||
float lum = dot(texture2D(sceneTex, uv).rgb, vec3(0.2126, 0.7152, 0.0722));
|
||||
|
||||
if (lum < @epsilon)
|
||||
{
|
||||
gl_FragColor.r = 0.0;
|
||||
return;
|
||||
}
|
||||
lum = max(lum, @epsilon);
|
||||
|
||||
gl_FragColor.r = clamp((log2(lum) - @minLog) * @invLogLumRange, 0.0, 1.0);
|
||||
}
|
||||
|
16
files/shaders/hdr_resolve_fragment.glsl
Normal file
16
files/shaders/hdr_resolve_fragment.glsl
Normal file
@ -0,0 +1,16 @@
|
||||
#version 120
|
||||
|
||||
varying vec2 uv;
|
||||
uniform sampler2D luminanceSceneTex;
|
||||
uniform sampler2D prevLuminanceSceneTex;
|
||||
|
||||
uniform float osg_DeltaFrameTime;
|
||||
|
||||
void main()
|
||||
{
|
||||
float prevLum = texture2D(prevLuminanceSceneTex, vec2(0.5, 0.5)).r;
|
||||
float currLum = texture2D(luminanceSceneTex, vec2(0.5, 0.5)).r;
|
||||
|
||||
float avgLum = exp2((currLum * @logLumRange) + @minLog);
|
||||
gl_FragColor.r = prevLum + (avgLum - prevLum) * (1.0 - exp(-osg_DeltaFrameTime * @hdrExposureTime));
|
||||
}
|
@ -695,7 +695,7 @@
|
||||
<string><html><head/><body><p>Controls how much eye adaptation can change from frame to frame. Smaller values makes for slower transitions.</p></body></html></string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>HDR exposure time</string>
|
||||
<string>Auto exposure speed</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
@ -708,10 +708,10 @@
|
||||
<number>3</number>
|
||||
</property>
|
||||
<property name="minimum">
|
||||
<double>0.000000000000000</double>
|
||||
<double>0.010000000000000</double>
|
||||
</property>
|
||||
<property name="maximum">
|
||||
<double>1.000000000000000</double>
|
||||
<double>10.000000000000000</double>
|
||||
</property>
|
||||
<property name="singleStep">
|
||||
<double>0.001000000000000</double>
|
||||
|
Loading…
x
Reference in New Issue
Block a user