mirror of https://github.com/OpenMW/openmw.git
Merge branch 'hdr_quick' into 'master'
Fix auto exposure See merge request OpenMW/openmw!2174check_span
commit
26bd907b0b
@ -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
|
|
@ -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;
|
||||||
|
}
|
||||||
|
}
|
@ -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
|
@ -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;
|
|
||||||
}
|
|
@ -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));
|
||||||
|
}
|
Loading…
Reference in New Issue