1
0
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:
glassmancody.info 2022-07-22 20:41:08 -07:00
parent ea9f2761c3
commit fd4966f77a
15 changed files with 246 additions and 235 deletions

View File

@ -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");

View File

@ -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

View File

@ -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;
}
}

View File

@ -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

View 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;
}
}

View 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

View File

@ -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);

View File

@ -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;

View File

@ -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.

View File

@ -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

View File

@ -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

View File

@ -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;
}

View File

@ -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);
}

View 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));
}

View File

@ -695,7 +695,7 @@
<string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Controls how much eye adaptation can change from frame to frame. Smaller values makes for slower transitions.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</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>