from yeaf - HDR revamp

gl side is wipwork
This commit is contained in:
AzaezelX 2022-08-28 22:24:23 -05:00
parent 05a6b80224
commit 7efc7281db
27 changed files with 670 additions and 326 deletions

View file

@ -29,49 +29,48 @@ $PostFX::HDRPostFX::enableToneMapping = 0.5;
///
/// 0.18 is fairly common value.
///
$PostFX::HDRPostFX::keyValue = 0.18;
$PostFX::HDRPostFX::keyValue = 0.115;
$PostFX::HDRPostFX::exposureValue = 1.0;
//Explicit HDR Params
$PostFX::HDRPostFX::exposureValue = 1.5;
$PostFX::HDRPostFX::whitePoint = 2.5;
//HDR Color Corrections Vars
$PostFX::HDRPostFX::logContrast = 1.0;
$PostFX::HDRPostFX::saturationValue = 1.0;
$PostFX::HDRPostFX::colorFilter = "1.0 1.0 1.0";
/// The minimum luninace value to allow when tone mapping
/// the scene. Is particularly useful if your scene very
/// dark or has a black ambient color in places.
$PostFX::HDRPostFX::minLuminace = 0.001;
/// The lowest luminance value which is mapped to white. This
/// is usually set to the highest visible luminance in your
/// scene. By setting this to smaller values you get a contrast
/// enhancement.
$PostFX::HDRPostFX::whiteCutoff = 1.0;
/// The rate of adaptation from the previous and new
/// average scene luminance.
$PostFX::HDRPostFX::adaptRate = 2.0;
/// Blends between the scene and the blue shifted version
/// of the scene for a cinematic desaturated night effect.
$PostFX::HDRPostFX::enableBlueShift = 0.0;
/// The blue shift color value.
$PostFX::HDRPostFX::blueShiftColor = "1.05 0.97 1.27";
$PostFX::HDRPostFX::adaptRate = 0.85;
/// Blends between the scene and the bloomed scene.
$PostFX::HDRPostFX::enableBloom = 1.0;
/// The threshold luminace value for pixels which are
/// considered "bright" and need to be bloomed.
$PostFX::HDRPostFX::brightPassThreshold = 0.2;
$PostFX::HDRPostFX::brightPassThreshold = 0.08;
/// These are used in the gaussian blur of the
/// bright pass for the bloom effect.
$PostFX::HDRPostFX::gaussMultiplier = 0.145;
$PostFX::HDRPostFX::gaussMultiplier = 0.4;
$PostFX::HDRPostFX::gaussMean = 0;
$PostFX::HDRPostFX::gaussStdDev = 0.5;
// The tonemapping algo to use
$PostFX::HDRPostFX::tonemapMode = "Filmic";
$PostFX::HDRPostFX::tonemapMode = "ACES";
$PostFX::HDRPostFX::enableAutoExposure = true;
@ -79,9 +78,9 @@ $PostFX::HDRPostFX::enableAutoExposure = true;
singleton ShaderData( HDR_BrightPassShader )
{
DXVertexShaderFile = $Core::CommonShaderPath @ "/postFX/postFxV.hlsl";
DXPixelShaderFile = "./brightPassFilterP.hlsl";
DXPixelShaderFile = "./HDR_utils/brightPassFilterP.hlsl";
OGLVertexShaderFile = $Core::CommonShaderPath @ "/postFX/gl/postFxV.glsl";
OGLPixelShaderFile = "./brightPassFilterP.glsl";
OGLPixelShaderFile = "./HDR_utils/brightPassFilterP.glsl";
samplerNames[0] = "$inputTex";
samplerNames[1] = "$luminanceTex";
@ -91,10 +90,10 @@ singleton ShaderData( HDR_BrightPassShader )
singleton ShaderData( HDR_DownScale4x4Shader )
{
DXVertexShaderFile = "./downScale4x4V.hlsl";
DXPixelShaderFile = "./downScale4x4P.hlsl";
OGLVertexShaderFile = "./downScale4x4V.glsl";
OGLPixelShaderFile = "./downScale4x4P.glsl";
DXVertexShaderFile = "./HDR_Bloom/downScale4x4V.hlsl";
DXPixelShaderFile = "./HDR_Bloom/downScale4x4P.hlsl";
OGLVertexShaderFile = "./HDR_Bloom/downScale4x4V.glsl";
OGLPixelShaderFile = "./HDR_Bloom/downScale4x4P.glsl";
samplerNames[0] = "$inputTex";
@ -104,9 +103,9 @@ singleton ShaderData( HDR_DownScale4x4Shader )
singleton ShaderData( HDR_BloomGaussBlurHShader )
{
DXVertexShaderFile = $Core::CommonShaderPath @ "/postFX/postFxV.hlsl";
DXPixelShaderFile = "./bloomGaussBlurHP.hlsl";
DXPixelShaderFile = "./HDR_Bloom/bloomGaussBlurHP.hlsl";
OGLVertexShaderFile = $Core::CommonShaderPath @ "/postFX/gl/postFxV.glsl";
OGLPixelShaderFile = "./bloomGaussBlurHP.glsl";
OGLPixelShaderFile = "./HDR_Bloom/bloomGaussBlurHP.glsl";
samplerNames[0] = "$inputTex";
@ -116,9 +115,9 @@ singleton ShaderData( HDR_BloomGaussBlurHShader )
singleton ShaderData( HDR_BloomGaussBlurVShader )
{
DXVertexShaderFile = $Core::CommonShaderPath @ "/postFX/postFxV.hlsl";
DXPixelShaderFile = "./bloomGaussBlurVP.hlsl";
DXPixelShaderFile = "./HDR_Bloom/bloomGaussBlurVP.hlsl";
OGLVertexShaderFile = $Core::CommonShaderPath @ "/postFX/gl/postFxV.glsl";
OGLPixelShaderFile = "./bloomGaussBlurVP.glsl";
OGLPixelShaderFile = "./HDR_Bloom/bloomGaussBlurVP.glsl";
samplerNames[0] = "$inputTex";
@ -128,9 +127,9 @@ singleton ShaderData( HDR_BloomGaussBlurVShader )
singleton ShaderData( HDR_SampleLumShader )
{
DXVertexShaderFile = $Core::CommonShaderPath @ "/postFX/postFxV.hlsl";
DXPixelShaderFile = "./sampleLumInitialP.hlsl";
DXPixelShaderFile = "./HDR_utils/sampleLumInitialP.hlsl";
OGLVertexShaderFile = $Core::CommonShaderPath @ "/postFX/gl/postFxV.glsl";
OGLPixelShaderFile = "./sampleLumInitialP.glsl";
OGLPixelShaderFile = "./HDR_utils/sampleLumInitialP.glsl";
samplerNames[0] = "$inputTex";
@ -140,9 +139,9 @@ singleton ShaderData( HDR_SampleLumShader )
singleton ShaderData( HDR_DownSampleLumShader )
{
DXVertexShaderFile = $Core::CommonShaderPath @ "/postFX/postFxV.hlsl";
DXPixelShaderFile = "./sampleLumIterativeP.hlsl";
DXPixelShaderFile = "./HDR_utils/sampleLumIterativeP.hlsl";
OGLVertexShaderFile = $Core::CommonShaderPath @ "/postFX/gl/postFxV.glsl";
OGLPixelShaderFile = "./sampleLumIterativeP.glsl";
OGLPixelShaderFile = "./HDR_utils/sampleLumIterativeP.glsl";
samplerNames[0] = "$inputTex";
@ -152,9 +151,9 @@ singleton ShaderData( HDR_DownSampleLumShader )
singleton ShaderData( HDR_CalcAdaptedLumShader )
{
DXVertexShaderFile = $Core::CommonShaderPath @ "/postFX/postFxV.hlsl";
DXPixelShaderFile = "./calculateAdaptedLumP.hlsl";
DXPixelShaderFile = "./HDR_utils/calculateAdaptedLumP.hlsl";
OGLVertexShaderFile = $Core::CommonShaderPath @ "/postFX/gl/postFxV.glsl";
OGLPixelShaderFile = "./calculateAdaptedLumP.glsl";
OGLPixelShaderFile = "./HDR_utils/calculateAdaptedLumP.glsl";
samplerNames[0] = "$currLum";
samplerNames[1] = "$lastAdaptedLum";
@ -165,9 +164,9 @@ singleton ShaderData( HDR_CalcAdaptedLumShader )
singleton ShaderData( HDR_CombineShader )
{
DXVertexShaderFile = $Core::CommonShaderPath @ "/postFX/postFxV.hlsl";
DXPixelShaderFile = "./finalPassCombineP.hlsl";
DXPixelShaderFile = "./HDR_finalPass.hlsl";
OGLVertexShaderFile = $Core::CommonShaderPath @ "/postFX/gl/postFxV.glsl";
OGLPixelShaderFile = "./finalPassCombineP.glsl";
OGLPixelShaderFile = "./HDR_finalPass.glsl";
samplerNames[0] = "$sceneTex";
samplerNames[1] = "$luminanceTex";
@ -225,8 +224,12 @@ singleton GFXStateBlockData( HDRStateBlock )
function HDRPostFX::setShaderConsts( %this )
{
%this.setShaderConst( "$brightPassThreshold", $PostFX::HDRPostFX::brightPassThreshold );
%this.setShaderConst( "$g_fMiddleGray", $PostFX::HDRPostFX::keyValue );
%this.setShaderConst( "$ExposureValue", $PostFX::HDRPostFX::exposureValue );
%this.setShaderConst( "$g_fMiddleGray", $PostFX::HDRPostFX::keyValue );
%this.setShaderConst( "$exposureValue", $PostFX::HDRPostFX::exposureValue );
%this.setShaderConst( "$whitePoint", $PostFX::HDRPostFX::whitePoint );
%this.setShaderConst( "$logContrast", $PostFX::HDRPostFX::logContrast );
%this.setShaderConst( "$saturationValue", $PostFX::HDRPostFX::saturationValue );
%bloomH = %this-->bloomH;
%bloomH.setShaderConst( "$gaussMultiplier", $PostFX::HDRPostFX::gaussMultiplier );
@ -249,25 +252,31 @@ function HDRPostFX::setShaderConsts( %this )
%this-->finalLum.setShaderConst( "$adaptRate", $PostFX::HDRPostFX::adaptRate );
%combinePass = %this-->combinePass;
%combinePass.setShaderConst( "$g_fEnableToneMapping", $PostFX::HDRPostFX::enableToneMapping );
%combinePass.setShaderConst( "$g_fMiddleGray", $PostFX::HDRPostFX::keyValue );
%combinePass.setShaderConst( "$ExposureValue", $PostFX::HDRPostFX::exposureValue );
%combinePass.setShaderConst( "$g_fBloomScale", $PostFX::HDRPostFX::enableBloom );
%combinePass.setShaderConst( "$g_fEnableBlueShift", $PostFX::HDRPostFX::enableBlueShift );
%combinePass.setShaderConst( "$g_fBlueShiftColor", $PostFX::HDRPostFX::blueShiftColor );
%combinePass.setShaderConst( "$whitePoint", $PostFX::HDRPostFX::whitePoint );
%combinePass.setShaderConst( "$exposureValue", $PostFX::HDRPostFX::exposureValue );
%combinePass.setShaderConst( "$colorFilter", $PostFX::HDRPostFX::colorFilter );
%combinePass.setShaderConst( "$saturationValue", $PostFX::HDRPostFX::saturationValue );
%combinePass.setShaderConst( "$logContrast", $PostFX::HDRPostFX::logContrast );
%combinePass.setShaderConst( "$g_fBloomScale", $PostFX::HDRPostFX::enableBloom );
%combinePass.setShaderConst( "$g_fEnableAutoExposure", $PostFX::HDRPostFX::enableAutoExposure );
%tonemapMode = 1;
if($PostFX::HDRPostFX::tonemapMode $= "ACES")
%tonemapMode = 1;
else if($PostFX::HDRPostFX::tonemapMode $= "Uncharted 2")
else if($PostFX::HDRPostFX::tonemapMode $= "Filmic Helji")
%tonemapMode = 2;
else if($PostFX::HDRPostFX::tonemapMode $= "Filmic")
else if($PostFX::HDRPostFX::tonemapMode $= "Hable U2")
%tonemapMode = 3;
else if($PostFX::HDRPostFX::tonemapMode $= "Reinhard")
%tonemapMode = 4;
else if($PostFX::HDRPostFX::tonemapMode $= "Reinhard")
%tonemapMode = 4;
else if($PostFX::HDRPostFX::tonemapMode $= "Linear")
%tonemapMode = 5;
%combinePass.setShaderConst( "$g_fTonemapMode", %tonemapMode );
@ -276,10 +285,7 @@ function HDRPostFX::setShaderConsts( %this )
%combinePass.setShaderConst( "$g_fOneOverGamma", 1 / %clampedGamma );
%combinePass.setShaderConst( "$Brightness", $pref::Video::Brightness );
%combinePass.setShaderConst( "$Contrast", $pref::Video::Contrast );
%whiteCutoff = ( $PostFX::HDRPostFX::whiteCutoff * $PostFX::HDRPostFX::whiteCutoff ) *
( $PostFX::HDRPostFX::whiteCutoff * $PostFX::HDRPostFX::whiteCutoff );
%combinePass.setShaderConst( "$g_fWhiteCutoff", %whiteCutoff );
}
function HDRPostFX::preProcess( %this )
@ -352,6 +358,7 @@ function HDRPostFX::onAdd( %this )
PostFXManager.registerPostEffect(%this);
$PostFX::HDRPostFX::enableToneMapping = 1;
}
//This is used to populate the PostFXEditor's settings so the post FX can be edited
@ -361,29 +368,31 @@ function HDRPostFX::populatePostFXSettings(%this)
{
PostEffectEditorInspector.startGroup("HDR - General");
PostEffectEditorInspector.addCallbackField("$PostFX::HDRPostFX::Enabled", "Enabled", "bool", "", $PostFX::HDRPostFX::Enabled, "", "toggleHDRPostFX");
PostEffectEditorInspector.addField("$PostFX::HDRPostFX::minLuminace", "Minimum Luminance", "range", "", $PostFX::HDRPostFX::minLuminace, "0 1 100");
PostEffectEditorInspector.addField("$PostFX::HDRPostFX::whiteCutoff", "White Cutoff", "range", "", $PostFX::HDRPostFX::whiteCutoff, "0 10 20");
PostEffectEditorInspector.addField("$PostFX::HDRPostFX::exposureValue", "Exposure", "range", "", $PostFX::HDRPostFX::exposureValue, "0 5 50");
PostEffectEditorInspector.endGroup();
PostEffectEditorInspector.startGroup("HDR - Tonemapping");
PostEffectEditorInspector.addField("$PostFX::HDRPostFX::tonemapMode", "Tonemapping Mode", "list", "", $PostFX::HDRPostFX::tonemapMode, "ACES,Uncharted 2,Filmic,Reinhard");
PostEffectEditorInspector.addField("$PostFX::HDRPostFX::exposureValue", "Exposure", "float", "", $PostFX::HDRPostFX::exposureValue, " 1");
PostEffectEditorInspector.addField("$PostFX::HDRPostFX::tonemapMode", "Tonemapping Mode", "list", "", $PostFX::HDRPostFX::tonemapMode, "ACES,Filmic Helji,Hable U2,Reinhard,Linear");
PostEffectEditorInspector.addField("$PostFX::HDRPostFX::whitePoint", "White Point", "float", "", $PostFX::HDRPostFX::whitePoint, " 2");
PostEffectEditorInspector.endGroup();
PostEffectEditorInspector.startGroup("HDR - Color Correction");
PostEffectEditorInspector.addField("$PostFX::HDRPostFX::logContrast", "Contrast", "range", "", $PostFX::HDRPostFX::logContrast, "1 2 20");
PostEffectEditorInspector.addField("$PostFX::HDRPostFX::saturationValue", "Saturation", "range", "", $PostFX::HDRPostFX::saturationValue, "0 2 20");
PostEffectEditorInspector.addField("$PostFX::HDRPostFX::colorFilter", "Color Tint", "colorF", "", $PostFX::HDRPostFX::colorFilter, "0 0 0");
PostEffectEditorInspector.endGroup();
PostEffectEditorInspector.startGroup("HDR - Bloom");
PostEffectEditorInspector.addField("$PostFX::HDRPostFX::enableBloom", "Enable Bloom", "bool", "", $PostFX::HDRPostFX::enableBloom, "");
PostEffectEditorInspector.startGroup("HDR - HDR Bloom");
PostEffectEditorInspector.addField("$PostFX::HDRPostFX::enableBloom", "Enable HDR Bloom", "bool", "", $PostFX::HDRPostFX::enableBloom, "");
PostEffectEditorInspector.addField("$PostFX::HDRPostFX::gaussMultiplier", "Bloom Multiplier", "range", "", $PostFX::HDRPostFX::gaussMultiplier, "0.0 1.0 2.0");
PostEffectEditorInspector.addField("$PostFX::HDRPostFX::brightPassThreshold", "Bright Pass Threshold", "float", "", $PostFX::HDRPostFX::brightPassThreshold, "");
PostEffectEditorInspector.addField("$PostFX::HDRPostFX::gaussMultiplier", "Blur Multiplier", "range", "", $PostFX::HDRPostFX::gaussMultiplier, "0 1 10");
PostEffectEditorInspector.addField("$PostFX::HDRPostFX::gaussMean", "Blur Mean Value", "range", "", $PostFX::HDRPostFX::gaussMean, "0 1 10");
PostEffectEditorInspector.addField("$PostFX::HDRPostFX::gaussStdDev", "Blur Std. Dev Value", "range", "", $PostFX::HDRPostFX::gaussStdDev, "0 1 10");
PostEffectEditorInspector.endGroup();
PostEffectEditorInspector.endGroup();
PostEffectEditorInspector.startGroup("HDR - Adaptation");
PostEffectEditorInspector.addField("$PostFX::HDRPostFX::enableAutoExposure", "Enable Auto Exposure", "bool", "", $PostFX::HDRPostFX::enableAutoExposure, "");
PostEffectEditorInspector.addField("$PostFX::HDRPostFX::minLuminace", "Minimum Luminance", "range", "", $PostFX::HDRPostFX::minLuminace, "0 1 100");
PostEffectEditorInspector.addField("$PostFX::HDRPostFX::adaptRate", "Brightness Adapt Rate", "range", "", $PostFX::HDRPostFX::adaptRate, "0 1 10");
PostEffectEditorInspector.addField("$PostFX::HDRPostFX::keyValue", "Key Value", "range", "", $PostFX::HDRPostFX::keyValue, "0 1 10");
PostEffectEditorInspector.addField("$PostFX::HDRPostFX::enableBlueShift", "Enable Blue Shift", "bool", "", $PostFX::HDRPostFX::enableBlueShift, "");
PostEffectEditorInspector.addField("$PostFX::HDRPostFX::blueShiftColor", "Blue Shift Color", "colorF", "", $PostFX::HDRPostFX::blueShiftColor, "");
PostEffectEditorInspector.endGroup();
}
@ -403,10 +412,16 @@ function HDRPostFX::applyFromPreset(%this)
HDRPostFX.disable();
}
function HDRPostFX::savePresetSettings(%this)
{
PostFXManager::savePresetSetting("$PostFX::HDRPostFX::Enabled");
PostFXManager::savePresetSetting("$PostFX::HDRPostFX::exposureValue");
PostFXManager::savePresetSetting("$PostFX::HDRPostFX::whitePoint");
PostFXManager::savePresetSetting("$PostFX::HDRPostFX::logContrast");
PostFXManager::savePresetSetting("$PostFX::HDRPostFX::saturationValue");
PostFXManager::savePresetSetting("$PostFX::HDRPostFX::colorFilter");
PostFXManager::savePresetSetting("$PostFX::HDRPostFX::minLuminace");
PostFXManager::savePresetSetting("$PostFX::HDRPostFX::whiteCutoff");
PostFXManager::savePresetSetting("$PostFX::HDRPostFX::adaptRate");
@ -414,12 +429,8 @@ function HDRPostFX::savePresetSettings(%this)
PostFXManager::savePresetSetting("$PostFX::HDRPostFX::enableBloom");
PostFXManager::savePresetSetting("$PostFX::HDRPostFX::brightPassThreshold");
PostFXManager::savePresetSetting("$PostFX::HDRPostFX::gaussMultiplier");
PostFXManager::savePresetSetting("$PostFX::HDRPostFX::gaussMean");
PostFXManager::savePresetSetting("$PostFX::HDRPostFX::gaussStdDev");
PostFXManager::savePresetSetting("$PostFX::HDRPostFX::enableAutoExposure");
PostFXManager::savePresetSetting("$PostFX::HDRPostFX::keyValue");
PostFXManager::savePresetSetting("$PostFX::HDRPostFX::enableBlueShift");
PostFXManager::savePresetSetting("$PostFX::HDRPostFX::blueShiftColor");
}
singleton PostEffect( HDRPostFX )
@ -570,9 +581,9 @@ singleton PostEffect( HDRPostFX )
singleton ShaderData( LuminanceVisShader )
{
DXVertexShaderFile = $Core::CommonShaderPath @ "/postFX/postFxV.hlsl";
DXPixelShaderFile = $Core::CommonShaderPath @ "/postFX/hdr/luminanceVisP.hlsl";
DXPixelShaderFile = $Core::CommonShaderPath @ "/postFX/hdr/HDR_utils/luminanceVisP.hlsl";
OGLVertexShaderFile = $Core::CommonShaderPath @ "/postFX/gl/postFxV.glsl";
OGLPixelShaderFile = $Core::CommonShaderPath @ "/postFX/hdr/gl/luminanceVisP.glsl";
OGLPixelShaderFile = $Core::CommonShaderPath @ "/postFX/hdr/HDR_utils/luminanceVisP.glsl";
samplerNames[0] = "$inputTex";

View file

@ -0,0 +1,40 @@
//-----------------------------------------------------------------------------
// Copyright (c) 2012 GarageGames, LLC
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to
// deal in the Software without restriction, including without limitation the
// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
// sell copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
// IN THE SOFTWARE.
//-----------------------------------------------------------------------------
vec3 TO_Exposure (vec3 x, float exposureValue, vec3 colorFilter)
{
x = exp2(vec3(exposureValue))/2 * colorFilter;
return x;
}
vec3 TO_Saturation (vec3 x, float saturation)
{
float L = hdrLuminance(x);
x = mix(vec3(L), x, saturation);
return x;
}
float TO_LogContrast (float x, float contrast)
{
float a = 0.15 + (log2(x + 0.0001f ) - 0.15)* contrast ;
return clamp(exp2(a)-0.0001f,0.0 , 2.5);
}

View file

@ -0,0 +1,43 @@
//-----------------------------------------------------------------------------
// Copyright (c) 2012 GarageGames, LLC
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to
// deal in the Software without restriction, including without limitation the
// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
// sell copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
// IN THE SOFTWARE.
//-----------------------------------------------------------------------------
#include "core/rendering/shaders/torque.hlsl"
float3 TO_Exposure (float3 x, float exposureValue, float3 colorFilter)
{
x = exp2(exposureValue)/2 * colorFilter;
return x;
}
float3 TO_Saturation (float3 x, float saturation)
{
float L = hdrLuminance(x);
x = lerp(L, x, saturation);
return x;
}
float TO_LogContrast (float x, float contrast)
{
float a = 0.15 + (log2(x + 0.0001f ) - 0.15)* contrast ;
return clamp(exp2(a)-0.0001f,0.0 , 2.5);
}

View file

@ -24,7 +24,9 @@
#include "core/rendering/shaders/gl/hlslCompat.glsl"
#include "core/rendering/shaders/postFX/gl/postFx.glsl"
#include "shadergen:/autogenConditioners.h"
#include "HDR_Tonemap.glsl"
#include "HDR_colorUtils.glsl"
#line 29
uniform sampler2D sceneTex;
uniform sampler2D luminanceTex;
uniform sampler2D bloomTex;
@ -39,59 +41,57 @@ uniform float g_fWhiteCutoff;
uniform float g_fEnableAutoExposure;
uniform float g_fTonemapMode;
uniform float g_fEnableBlueShift;
uniform vec3 g_fBlueShiftColor;
uniform float g_fBloomScale;
uniform float g_fOneOverGamma;
uniform float Brightness;
uniform float Contrast;
//Explicit HDR Params
uniform float exposureValue;
uniform float whitePoint;
uniform float logContrast;
uniform float brightnessValue;
uniform float saturationValue;
uniform float3 colorFilter;
out vec4 OUT_col;
// uncharted 2 tonemapper see: http://filmicgames.com/archives/75
vec3 Uncharted2Tonemap(vec3 x)
{
const float A = 0.15;
const float B = 0.50;
const float C = 0.10;
const float D = 0.20;
const float E = 0.02;
const float F = 0.30;
return ((x*(A*x + C*B) + D*E) / (x*(A*x + B) + D*F)) - E / F;
}
float3 ACESFilm( float3 x )
{
const float a = 2.51;
const float b = 0.03;
const float c = 2.43;
const float d = 0.59;
const float e = 0.14;
return saturate((x*(a*x+b))/(x*(c*x+d)+e));
}
vec3 tonemap(vec3 c)
{
vec3 colorOut = c;
if(g_fTonemapMode == 1.0)
{
const float W = 11.2;
float ExposureBias = 2.0f;
//float ExposureAdjust = 1.5f;
//c *= ExposureAdjust;
colorOut = Uncharted2Tonemap(ExposureBias*colorOut);
colorOut = colorOut * (1.0f / Uncharted2Tonemap(vec3(W,W,W)));
vec3 Tonemap(vec3 x)
{
//ACES
if(g_fTonemapMode == 1.0f)
{
x = ACESFitted(x, whitePoint);
}
//Filmic Helji
if(g_fTonemapMode == 2.0f)
{
x = TO_Hejl(x, whitePoint);
}
//Hable Uncharted 2
if (g_fTonemapMode == 3.0)
{
x = TO_HableU2(x, whitePoint);
}
//Reinhard
if (g_fTonemapMode == 4.0)
{
float L = hdrLuminance(x);
vec3 nL = TO_Reinhard(vec3(L), whitePoint);
x *= (nL / L);
}
//Linear Tonemap
else if (g_fTonemapMode == 5.0)
{
x = TO_Linear(x);
}
else if(g_fTonemapMode == 2.0)
{
colorOut = ACESFilm(colorOut);
}
return colorOut;
}
return x;
}
void main()
{
@ -99,45 +99,48 @@ void main()
float adaptedLum = texture( luminanceTex, vec2( 0.5f, 0.5f ) ).r;
vec4 bloom = texture( bloomTex, IN_uv0 );
// For very low light conditions, the rods will dominate the perception
// of light, and therefore color will be desaturated and shifted
// towards blue.
if ( g_fEnableBlueShift > 0.0f )
{
const vec3 LUMINANCE_VECTOR = vec3(0.2125f, 0.7154f, 0.0721f);
// Define a linear blending from -1.5 to 2.6 (log scale) which
// determines the mix amount for blue shift
float coef = 1.0f - ( adaptedLum + 1.5 ) / 4.1;
coef = saturate( coef * g_fEnableBlueShift );
// Lerp between current color and blue, desaturated copy
vec3 rodColor = dot( _sample.rgb, LUMINANCE_VECTOR ) * g_fBlueShiftColor;
_sample.rgb = mix( _sample.rgb, rodColor, coef );
rodColor = dot( bloom.rgb, LUMINANCE_VECTOR ) * g_fBlueShiftColor;
bloom.rgb = mix( bloom.rgb, rodColor, coef );
}
// Add the bloom effect.
_sample.rgb += clamp(vec3(g_fBloomScale,g_fBloomScale,g_fBloomScale) * bloom.rgb, vec3(0,0,0), vec3(1.0,1.0,1.0));
// Add the bloom effect.
_sample += (g_fBloomScale * bloom) / 10;
//Apply Exposure
_sample.rgb *= TO_Exposure(_sample.rgb, exposureValue, colorFilter);
//Apply Saturation
_sample.rgb = TO_Saturation(_sample.rgb, saturationValue);
// Apply contrast
_sample.rgb = ((_sample.rgb - 0.5f) * Contrast) + 0.5f;
// Apply brightness
//_sample.rgb += Brightness;
//Apply Color Contrast
_sample.r = TO_LogContrast(_sample.r, logContrast);
_sample.g = TO_LogContrast(_sample.g, logContrast);
_sample.b = TO_LogContrast(_sample.b, logContrast);
//tonemapping - TODO fix up eye adaptation
if ( g_fEnableToneMapping > 0.0f )
{
float adapation = 1;
if ( g_fEnableAutoExposure > 0.0f )
adapation = (g_fMiddleGray / (adaptedLum + 0.0001)) * hdrLuminance( _sample.rgb );
_sample.rgb = tonemap(_sample.rgb * adapation);
}
if ( g_fEnableToneMapping > 0.0f )
{
float adapation = 1.0;
if( g_fEnableAutoExposure > 0.0f )
{
adaptedLum = saturate(adaptedLum);
float linearExposure = (g_fMiddleGray / adaptedLum);
adapation = log2(max(linearExposure, 0.0001f));
_sample.rgb = Tonemap(exposureValue * _sample.rgb *exp2(adapation));
}
else {
_sample.rgb = Tonemap(_sample.rgb);
}
}
OUT_col = _sample;
}

View file

@ -0,0 +1,153 @@
//-----------------------------------------------------------------------------
// Copyright (c) 2012 GarageGames, LLC
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to
// deal in the Software without restriction, including without limitation the
// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
// sell copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
// IN THE SOFTWARE.
//-----------------------------------------------------------------------------
#include "core/rendering/shaders/torque.hlsl"
#include "core/rendering/shaders/postFX/postFx.hlsl"
#include "core/rendering/shaders/shaderModelAutoGen.hlsl"
#include "./HDR_Tonemap.hlsl"
#include "./HDR_colorUtils.hlsl"
TORQUE_UNIFORM_SAMPLER2D(sceneTex, 0);
TORQUE_UNIFORM_SAMPLER2D(luminanceTex, 1);
TORQUE_UNIFORM_SAMPLER2D(bloomTex, 2);
uniform float2 texSize0;
uniform float2 texSize2;
uniform float g_fEnableToneMapping;
uniform float g_fMiddleGray;
uniform float g_fEnableAutoExposure;
uniform float g_fTonemapMode;
uniform float g_fBloomScale;
uniform float g_fOneOverGamma;
uniform float Brightness;
uniform float Contrast;
//Explicit HDR Params
uniform float exposureValue;
uniform float whitePoint;
uniform float logContrast;
uniform float brightnessValue;
uniform float saturationValue;
uniform float3 colorFilter;
vec3 ACESFitted(vec3 x, float w)
{
x = tMul(ACESInputMat, x);
// Apply RRT and ODT
x = RRTAndODTFit(x, w);
x = tMul(ACESOutputMat, x);
// Clamp to [0, 1]
return saturate(x);
}
float3 Tonemap(float3 x)
{
//ACES
if(g_fTonemapMode == 1.0f)
{
x = ACESFitted(x, whitePoint);
}
//Filmic Helji
if(g_fTonemapMode == 2.0f)
{
x = TO_Hejl(x, whitePoint);
}
//Hable Uncharted 2
if (g_fTonemapMode == 3.0)
{
x = TO_HableU2(x, whitePoint);
}
//Reinhard
if (g_fTonemapMode == 4.0)
{
float L = hdrLuminance(x);
float3 nL = TO_Reinhard(L, whitePoint);
x *= (nL / L);
}
//Linear Tonemap
else if (g_fTonemapMode == 5.0)
{
x = TO_Linear(x);
}
return x;
}
float4 main( PFXVertToPix IN ) : TORQUE_TARGET0
{
float4 sample = hdrDecode( TORQUE_TEX2D( sceneTex, IN.uv0 ) );
float adaptedLum = TORQUE_TEX2D( luminanceTex, float2( 0.5f, 0.5f ) ).r;
float4 bloom = TORQUE_TEX2D( bloomTex, IN.uv0 );
// Add the bloom effect.
sample += (g_fBloomScale * bloom) / 10;
//Apply Exposure
sample.rgb *= TO_Exposure(sample.rgb, exposureValue, colorFilter);
//Apply Saturation
sample.rgb = TO_Saturation(sample.rgb, saturationValue);
// Apply Screen contrast
sample.rgb = ((sample.rgb - 0.5f) * Contrast) + 0.5f;
// Apply Screen brightness
//sample.rgb += Brightness;
//Apply Color Contrast
sample.r = TO_LogContrast(sample.r, logContrast);
sample.g = TO_LogContrast(sample.g, logContrast);
sample.b = TO_LogContrast(sample.b, logContrast);
//tonemapping - TODO fix up eye adaptation
if ( g_fEnableToneMapping > 0.0f )
{
float adapation = 1.0;
if( g_fEnableAutoExposure > 0.0f )
{
adaptedLum = saturate(adaptedLum);
float linearExposure = (g_fMiddleGray * rcp(adaptedLum));
adapation = log2(max(linearExposure, 0.0001f));
sample.rgb = Tonemap(exposureValue * sample.rgb *exp2(adapation));
}
else {
sample.rgb = Tonemap(sample.rgb);
}
}
return sample;
}

View file

@ -0,0 +1,124 @@
//-----------------------------------------------------------------------------
// Copyright (c) 2012 GarageGames, LLC
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to
// deal in the Software without restriction, including without limitation the
// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
// sell copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
// IN THE SOFTWARE.
//-----------------------------------------------------------------------------
// Stephen Hill's ACES Fit
// Source: https://github.com/TheRealMJP/BakingLab/blob/master/BakingLab/ACES.hlsl
#line 24
// sRGB => XYZ => D65_2_D60 => AP1 => RRT_SAT
const mat3 ACESInputMat = mat3
(
0.59719, 0.35458, 0.04823,
0.07600, 0.90834, 0.01566,
0.02840, 0.13383, 0.83777
);
// ODT_SAT => XYZ => D60_2_D65 => sRGB
const mat3 ACESOutputMat = mat3
(
1.60475, -0.53108, -0.07367,
-0.10208, 1.10813, -0.00605,
-0.00327, -0.07276, 1.07602
);
vec3 RRTAndODTFit(vec3 x, float w)
{
vec3 a = vec3((x * (x + 0.0245786f) - 0.000090537f) / (x * (0.983729f * x + 0.4329510f) + 0.238081f));
vec3 b = vec3((w * (w + 0.0245786f) - 0.000090537f) / (w * (0.983729f * w + 0.4329510f) + 0.238081f));
return a/b;
}
vec3 ACESFitted(vec3 x, float w)
{
x = tMul(ACESInputMat, x);
// Apply RRT and ODT
x = RRTAndODTFit(x, w);
x = tMul(ACESOutputMat, x);
// Clamp to [0, 1]
return saturate(x);
}
// Luminance Reinhard Operator as explained in:
// Source: https://imdoingitwrong.wordpress.com/2010/08/19/why-reinhard-desaturates-my-blacks-3/
vec3 TO_Reinhard(vec3 x, float w)
{
vec3 n = x * (1.0f + (x / (w * w)));
return saturate(n / (1.0f + x));
}
// John Hable Uncharted 2 Operator
// We're actually using his filmic curve from: https://www.slideshare.net/naughty_dog/lighting-shading-by-john-hable
vec3 TO_HableU2(vec3 x, float w)
{
//x *= 1.5f; //Hardcoded Exposure
vec3 curr = vec3(((x* (0.22f * x + 0.10f * 0.30f) + 0.20f * 0.01f)/
(x* (0.22f * x + 0.30f) + 0.20f * 0.30f))-0.01f/0.30f);
vec3 white = vec3(((w* (0.22f * w + 0.10f * 0.30f) + 0.20f * 0.01f)/
(w* (0.22f * w + 0.30f) + 0.20f * 0.30f))-0.01f/0.30f);
return saturate(curr / white);
}
// Jim Hejl 2015 Filmic Curve
// Source: https://twitter.com/jimhejl/status/633777619998130176/
vec3 TO_Hejl (vec3 x, float w)
{
vec4 vh = vec4 (x, w);
vec4 va = (1.425 * vh) + 0.05f;
vec4 vf = ((vh * va + 0.004f) / ((vh * (va + 0.55f) + 0.0491f))) - 0.0821f;
return saturate(vf.rgb / vf.www);
}
vec3 TO_Linear (vec3 x)
{
return saturate((x * (1.8 * x + 1.4)) / (x * (1.8 * x + 0.5) + 1.5));
}
/* Narkowicz ACES Tonemap Curve
Source: https://knarkowicz.wordpress.com/2016/01/06/aces-filmic-tone-mapping-curve/
vec3 ACES_Narkowicz( vec3 x )
{
const float a = 2.51f;
const float b = 0.03f;
const float c = 2.43f;
const float d = 0.59f;
const float e = 0.14f;
return saturate((x*(a*x+b))/(x*(c*x+d)+e));
}
Filmic ALU Curve Jim Hejl and Richard Burgess-Dawson
Source: http://filmicworlds.com/blog/filmic-tonemapping-operators/
vec3 TO_Filmic(vec3 x)
{
x = max(0,x-0.004f);
return (x*(6.2f*x+.5f))/(x*(6.2f*x+1.7f)+0.06f);
}
*/

View file

@ -0,0 +1,126 @@
//-----------------------------------------------------------------------------
// Copyright (c) 2012 GarageGames, LLC
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to
// deal in the Software without restriction, including without limitation the
// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
// sell copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
// IN THE SOFTWARE.
//-----------------------------------------------------------------------------
// Stephen Hill's ACES Fit
// Source: https://github.com/TheRealMJP/BakingLab/blob/master/BakingLab/ACES.hlsl
// sRGB => XYZ => D65_2_D60 => AP1 => RRT_SAT
static const float3x3 ACESInputMat =
{
{0.59719, 0.35458, 0.04823},
{0.07600, 0.90834, 0.01566},
{0.02840, 0.13383, 0.83777}
};
// ODT_SAT => XYZ => D60_2_D65 => sRGB
static const float3x3 ACESOutputMat =
{
{ 1.60475, -0.53108, -0.07367},
{-0.10208, 1.10813, -0.00605},
{-0.00327, -0.07276, 1.07602}
};
float3 RRTAndODTFit(float3 x, float w)
{
float3 a = (x * (x + 0.0245786f) - 0.000090537f) / (x * (0.983729f * x + 0.4329510f) + 0.238081f);
float3 b = (w * (w + 0.0245786f) - 0.000090537f) / (w * (0.983729f * w + 0.4329510f) + 0.238081f);
return a/b;
}
float3 ACESFitted(float3 x, float w)
{
x = mul(ACESInputMat, x);
// Apply RRT and ODT
x = RRTAndODTFit(x, w);
x = mul(ACESOutputMat, x);
// Clamp to [0, 1]
return saturate(x);
}
// Luminance Reinhard Operator as explained in:
// Source: https://imdoingitwrong.wordpress.com/2010/08/19/why-reinhard-desaturates-my-blacks-3/
float3 TO_Reinhard(float3 x, float w)
{
float3 n = x * (1.0f + (x / (w * w)));
return saturate(n / (1.0f + x));
}
// John Hable Uncharted 2 Operator
// We're actually using his filmic curve from: https://www.slideshare.net/naughty_dog/lighting-shading-by-john-hable
float3 TO_HableU2(float3 x, float w)
{
//x *= 1.5f; //Hardcoded Exposure
float3 curr = ((x* (0.22f * x + 0.10f * 0.30f) + 0.20f * 0.01f)/
(x* (0.22f * x + 0.30f) + 0.20f * 0.30f))-0.01f/0.30f;
float3 white = ((w* (0.22f * w + 0.10f * 0.30f) + 0.20f * 0.01f)/
(w* (0.22f * w + 0.30f) + 0.20f * 0.30f))-0.01f/0.30f;
return saturate(curr / white);
}
// Jim Hejl 2015 Filmic Curve
// Source: https://twitter.com/jimhejl/status/633777619998130176/
float3 TO_Hejl (float3 x, float w)
{
float4 vh = float4 (x, w);
float4 va = (1.425 * vh) + 0.05f;
float4 vf = ((vh * va + 0.004f) / ((vh * (va + 0.55f) + 0.0491f))) - 0.0821f;
return saturate(vf.rgb / vf.www);
}
float3 TO_Linear (float3 x)
{
return saturate((x * (1.8 * x + 1.4)) / (x * (1.8 * x + 0.5) + 1.5));
}
/* Narkowicz ACES Tonemap Curve
Source: https://knarkowicz.wordpress.com/2016/01/06/aces-filmic-tone-mapping-curve/
float3 ACES_Narkowicz( float3 x )
{
const float a = 2.51f;
const float b = 0.03f;
const float c = 2.43f;
const float d = 0.59f;
const float e = 0.14f;
return saturate((x*(a*x+b))/(x*(c*x+d)+e));
}
Filmic ALU Curve Jim Hejl and Richard Burgess-Dawson
Source: http://filmicworlds.com/blog/filmic-tonemapping-operators/
float3 TO_Filmic(float3 x)
{
x = max(0,x-0.004f);
return (x*(6.2f*x+.5f))/(x*(6.2f*x+1.7f)+0.06f);
}
*/

View file

@ -1,167 +0,0 @@
//-----------------------------------------------------------------------------
// Copyright (c) 2012 GarageGames, LLC
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to
// deal in the Software without restriction, including without limitation the
// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
// sell copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
// IN THE SOFTWARE.
//-----------------------------------------------------------------------------
#include "core/rendering/shaders/torque.hlsl"
#include "core/rendering/shaders/postFX/postFx.hlsl"
#include "core/rendering/shaders/shaderModelAutoGen.hlsl"
TORQUE_UNIFORM_SAMPLER2D(sceneTex, 0);
TORQUE_UNIFORM_SAMPLER2D(luminanceTex, 1);
TORQUE_UNIFORM_SAMPLER2D(bloomTex, 2);
uniform float2 texSize0;
uniform float2 texSize2;
uniform float g_fEnableToneMapping;
uniform float g_fMiddleGray;
uniform float g_fWhiteCutoff;
uniform float g_fEnableBlueShift;
uniform float g_fEnableAutoExposure;
uniform float g_fTonemapMode;
uniform float3 g_fBlueShiftColor;
uniform float g_fBloomScale;
uniform float g_fOneOverGamma;
uniform float Brightness;
uniform float Contrast;
uniform float ExposureValue;
float3 Reinhard(float3 x)
{
x *= 2.0;
return x / (1.0 + x);
}
float3 Filmic(float3 x)
{
x *= 0.4;
x = max(0,x-0.004);
return (x*(6.2*x+.5))/(x*(6.2*x+1.7)+0.06);
}
// Uncharted 2 tonemapper see: http://filmicgames.com/archives/75
float3 Uncharted2Tonemap(const float3 x)
{
const float A = 0.15;
const float B = 0.50;
const float C = 0.10;
const float D = 0.20;
const float E = 0.02;
const float F = 0.30;
return ((x*(A*x + C*B) + D*E) / (x*(A*x + B) + D*F)) - E / F;
}
float3 ACESFilm( float3 x )
{
const float a = 2.51;
const float b = 0.03;
const float c = 2.43;
const float d = 0.59;
const float e = 0.14;
return saturate((x*(a*x+b))/(x*(c*x+d)+e));
}
float3 tonemap(float3 color)
{
if(g_fTonemapMode == 1.0)
{
color = ACESFilm(color);
}
if(g_fTonemapMode == 2.0)
{
color *= 2.5; // compensate exposure to final image
const float W = 11.2;
float ExposureBias = 2.0f;
color = Uncharted2Tonemap(ExposureBias*color);
color = color * (1.0f / Uncharted2Tonemap(W));
}
if (g_fTonemapMode == 3.0)
{
color = Filmic(color);
}
else if (g_fTonemapMode == 4.0)
{
color = Reinhard(color);
}
return color;
}
float4 main( PFXVertToPix IN ) : TORQUE_TARGET0
{
float4 sample = hdrDecode( TORQUE_TEX2D( sceneTex, IN.uv0 ) );
float adaptedLum = TORQUE_TEX2D( luminanceTex, float2( 0.5f, 0.5f ) ).r;
float4 bloom = TORQUE_TEX2D( bloomTex, IN.uv0 );
// For very low light conditions, the rods will dominate the perception
// of light, and therefore color will be desaturated and shifted
// towards blue.
if ( g_fEnableBlueShift > 0.0f )
{
const float3 LUMINANCE_VECTOR = float3(0.2125f, 0.7154f, 0.0721f);
// Define a linear blending from -1.5 to 2.6 (log scale) which
// determines the lerp amount for blue shift
float coef = 1.0f - ( adaptedLum + 1.5 ) / 4.1;
coef = saturate( coef * g_fEnableBlueShift );
// Lerp between current color and blue, desaturated copy
float3 rodColor = dot( sample.rgb, LUMINANCE_VECTOR ) * g_fBlueShiftColor;
sample.rgb = lerp( sample.rgb, rodColor, coef );
rodColor = dot( bloom.rgb, LUMINANCE_VECTOR ) * g_fBlueShiftColor;
bloom.rgb = lerp( bloom.rgb, rodColor, coef );
}
sample.rgb *= ExposureValue;
// Add the bloom effect.
sample += saturate(g_fBloomScale * bloom);
// Apply contrast
sample.rgb = ((sample.rgb - 0.5f) * Contrast) + 0.5f;
// Apply brightness
//sample.rgb += Brightness;
//tonemapping - TODO fix up eye adaptation
if ( g_fEnableToneMapping > 0.0f )
{
float adapation = 1;
if( g_fEnableAutoExposure > 0.0f )
adapation = (g_fMiddleGray / (adaptedLum + 0.0001)) * hdrLuminance( sample.rgb );
sample.rgb = tonemap(sample.rgb * adapation);
}
return sample;
}

View file

@ -1,21 +1,32 @@
$PostFX::HDRPostFX::Enabled = 1;
$PostFX::HDRPostFX::ExposureValue = "1";
$PostFX::HDRPostFX::exposureValue = "1.5";
$PostFX::HDRPostFX::whitePoint = "2";
$PostFX::HDRPostFX::logContrast = "1.25";
$PostFX::HDRPostFX::saturationValue = "1";
$PostFX::HDRPostFX::colorFilter = "1.0 1.0 1.0";
$PostFX::HDRPostFX::minLuminace = "0.001";
$PostFX::HDRPostFX::whiteCutoff = "1.0";
$PostFX::HDRPostFX::adaptRate = "1";
$PostFX::HDRPostFX::adaptRate = "0.85";
$PostFX::HDRPostFX::tonemapMode = "ACES";
$PostFX::HDRPostFX::enableBloom = "1";
$PostFX::HDRPostFX::brightPassThreshold = "0.2";
$PostFX::HDRPostFX::gaussMultiplier = "0.145";
$PostFX::HDRPostFX::gaussMean = "0";
$PostFX::HDRPostFX::gaussStdDev = "0.5";
$PostFX::HDRPostFX::enableAutoExposure = "0";
$PostFX::HDRPostFX::keyValue = "0.18";
$PostFX::HDRPostFX::enableBlueShift = "0";
$PostFX::HDRPostFX::blueShiftColor = "1.05 0.97 1.27";
$PostFX::SharpenPostFX::Enabled = "1";
$PostFX::SharpenPostFX::sharpness = "0.15";
$PostFX::HDRPostFX::brightPassThreshold = "0.02";
$PostFX::HDRPostFX::gaussMultiplier = "0.4";
$PostFX::HDRPostFX::enableAutoExposure = "1";
$PostFX::HDRPostFX::keyValue = "0.115";
$PostFX::SSAOPostFx::Enabled = 1;
$PostFX::SSAOPostFX::quality = "2";
$PostFX::SSAOPostFX::sRadius = 0.1;
$PostFX::SSAOPostFX::sStrength = 6;
$PostFX::SSAOPostFX::sDepthMin = 0.1;
$PostFX::SSAOPostFX::sDepthMax = 1;
$PostFX::SSAOPostFX::sNormalTol = 0;
$PostFX::SSAOPostFX::sNormalPow = 1;
$PostFX::SSAOPostFX::lRadius = 1;
$PostFX::SSAOPostFX::lStrength = 10;
$PostFX::SSAOPostFX::lDepthMin = 0.2;
$PostFX::SSAOPostFX::lDepthMax = 2;
$PostFX::SSAOPostFX::lNormalTol = -0.5;
$PostFX::SSAOPostFX::lNormalPow = 2;
$PostFX::VignettePostFX::Enabled = "1";
$PostFX::VignettePostFX::VMin = "0.25";
$PostFX::VignettePostFX::VMax = "0.9";
$PostFX::VignettePostFX::VMax = "0.8";
$PostFX::VignettePostFX::Color = "0 0 0 1";