Various Changes; Updated and Added Mods
This commit is contained in:
@@ -0,0 +1,32 @@
|
||||
<?xml version="1.0" encoding="windows-1251"?>
|
||||
<string_table>
|
||||
<string id="ui_mcm_menu_fps_based_mblur">
|
||||
<text>FPS Based MBlur</text>
|
||||
</string>
|
||||
|
||||
<string id="ui_mcm_fps_based_mblur_title">
|
||||
<text>FPS Based Motion Blur</text>
|
||||
</string>
|
||||
|
||||
<string id="ui_mcm_fps_based_mblur_ENABLED">
|
||||
<text>Enabled</text>
|
||||
</string>
|
||||
|
||||
<string id="ui_mcm_fps_based_mblur_BASE_MBLUR">
|
||||
<text>Motion Blur Amount</text>
|
||||
</string>
|
||||
|
||||
<string id="ui_mcm_fps_based_mblur_BASE_MBLUR_desc">
|
||||
<text>
|
||||
The Motion Blur in the Settings are useless, so edit Motion Blur amount here.\nWarning! r2_mblur is multiplicated by 10 in the shader, so still edit Motion Blur amount here even if you disabled mod by option.
|
||||
</text>
|
||||
</string>
|
||||
|
||||
<string id="ui_mcm_fps_based_mblur_DEBUG">
|
||||
<text>Debug</text>
|
||||
</string>
|
||||
|
||||
<string id="ui_mcm_fps_based_mblur_DEBUG_desc">
|
||||
<text>Enable some debug info that makes logs very big, so don't touch it unless you have to.</text>
|
||||
</string>
|
||||
</string_table>
|
||||
@@ -0,0 +1,32 @@
|
||||
<?xml version="1.0" encoding="windows-1251"?>
|
||||
<string_table>
|
||||
<string id="ui_mcm_menu_fps_based_mblur">
|
||||
<text>FPS Based MBlur</text>
|
||||
</string>
|
||||
|
||||
<string id="ui_mcm_fps_based_mblur_title">
|
||||
<text>FPS Based Motion Blur</text>
|
||||
</string>
|
||||
|
||||
<string id="ui_mcm_fps_based_mblur_ENABLED">
|
||||
<text>Âêëþ÷¸í</text>
|
||||
</string>
|
||||
|
||||
<string id="ui_mcm_fps_based_mblur_BASE_MBLUR">
|
||||
<text>Êîëè÷åñòâî ðàçìûòèÿ â äâèæåíèè</text>
|
||||
</string>
|
||||
|
||||
<string id="ui_mcm_fps_based_mblur_BASE_MBLUR_desc">
|
||||
<text>
|
||||
Íàñòðàèâàòü ðàçìûòèå â äâèæåíèè â íàñòðîéêàõ íå èìååò ñìûëñëà, òàê êàê ìîä äèíàìè÷åñêè èçìåíÿåò r2_mblur, òàê ÷òî ðåãóëèðóé åãî çäåñü.\nÂíèìàíèå! Äàæå åñëè ìîä âûêëþ÷åí îïöèåé, ñòîèò ïðîäîëæàòü íàñòðàèâàòü çäåñü, ïîòîìó ÷òî r2_mblur óìíîæàåòñÿ íà 10 â ùåéäåðå (0.1 -> 1).
|
||||
</text>
|
||||
</string>
|
||||
|
||||
<string id="ui_mcm_fps_based_mblur_DEBUG">
|
||||
<text>Ðåæèì îòëàäêè</text>
|
||||
</string>
|
||||
|
||||
<string id="ui_mcm_fps_based_mblur_DEBUG_desc">
|
||||
<text>Âêëþ÷àåò âûâîä èíôîðìàöèè äëÿ îòëàäêè â ëîãè, èç-çà ÷åãî îíè ñòàíîâÿòñÿ î÷åíü áîëüøèìè, à òàêæå ìîæåò ïîíèçèòñÿ ïðîèçâîäèòåëüíîñòü.  îáùåì íå òðîãàé ýòó îïöèþ åñëè íå íàäî.</text>
|
||||
</string>
|
||||
</string_table>
|
||||
@@ -0,0 +1,40 @@
|
||||
local BASE_MBLUR_MAX = 10
|
||||
local CALLBACK_REGISTERED = true
|
||||
|
||||
local ENABLED
|
||||
local BASE_MBLUR
|
||||
local CACHE
|
||||
|
||||
local print_dbg = fps_based_mblur_mcm.print_dbg
|
||||
local get_config = fps_based_mblur_mcm.get_config
|
||||
|
||||
function load_settings()
|
||||
ENABLED = get_config("ENABLED")
|
||||
BASE_MBLUR = get_config("BASE_MBLUR")
|
||||
CACHE = 1 / 50 * BASE_MBLUR / BASE_MBLUR_MAX
|
||||
|
||||
if ENABLED and not CALLBACK_REGISTERED then
|
||||
RegisterScriptCallback("actor_on_update", actor_on_update)
|
||||
CALLBACK_REGISTERED = true
|
||||
elseif not ENABLED and CALLBACK_REGISTERED then
|
||||
UnregisterScriptCallback("actor_on_update", actor_on_update)
|
||||
CALLBACK_REGISTERED = false
|
||||
|
||||
get_console():execute("r2_mblur " .. BASE_MBLUR / BASE_MBLUR_MAX)
|
||||
end
|
||||
end
|
||||
|
||||
function actor_on_update()
|
||||
local delta = device().f_time_delta
|
||||
|
||||
print_dbg("delta: %s", delta)
|
||||
print_dbg("not clamped amount: %s", CACHE / delta)
|
||||
|
||||
get_console():execute("r2_mblur " .. clamp(CACHE / delta, 0, 1))
|
||||
end
|
||||
|
||||
function on_game_start()
|
||||
RegisterScriptCallback("on_option_change", load_settings)
|
||||
RegisterScriptCallback("actor_on_first_update", load_settings)
|
||||
RegisterScriptCallback("actor_on_update", actor_on_update)
|
||||
end
|
||||
@@ -0,0 +1,49 @@
|
||||
-- If you don't use MCM, change your defaults from here.
|
||||
local defaults = {
|
||||
["ENABLED"] = true,
|
||||
["BASE_MBLUR"] = 1.0,
|
||||
["DEBUG"] = false,
|
||||
}
|
||||
|
||||
function get_config(key)
|
||||
if ui_mcm then
|
||||
return ui_mcm.get("fps_based_mblur/" .. key)
|
||||
else
|
||||
return defaults[key]
|
||||
end
|
||||
end
|
||||
|
||||
local dbg_log
|
||||
function print_dbg(text, ...)
|
||||
if get_config("DEBUG") or false then
|
||||
dbg_log = dbg_log or mcm_log and mcm_log.new("DBG")
|
||||
if dbg_log then
|
||||
dbg_log.enabled = true
|
||||
dbg_log:log(text, ...)
|
||||
else
|
||||
printf("fps based mblur: | %s | " .. text, time_global(), ...)
|
||||
end
|
||||
end
|
||||
return nil
|
||||
end
|
||||
|
||||
function on_mcm_load()
|
||||
op = {
|
||||
id = "fps_based_mblur",
|
||||
sh = true,
|
||||
gr = {
|
||||
{
|
||||
id = "title",
|
||||
type = "slide",
|
||||
link = "ui_options_slider_player",
|
||||
text = "ui_mcm_fps_based_mblur_title",
|
||||
size = { 512, 50 },
|
||||
spacing = 20,
|
||||
},
|
||||
{ id = "ENABLED", type = "check", val = 1, def = true },
|
||||
{ id = "BASE_MBLUR", type = "track", val = 2, def = 1.0, min = 0.0, max = 10.0, step = 0.025 },
|
||||
{ id = "DEBUG", type = "check", val = 1, def = false },
|
||||
},
|
||||
}
|
||||
return op
|
||||
end
|
||||
@@ -0,0 +1,86 @@
|
||||
#include "common.h"
|
||||
#include "lmodel.h"
|
||||
#include "shadow.h"
|
||||
|
||||
// Check Screen Space Shaders modules & addons
|
||||
#include "check_screenspace.h"
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////////////
|
||||
// This is the basic primitive used by convex, volumetric lights
|
||||
// for example spot-lights, one face of the omni lights, etc.
|
||||
//////////////////////////////////////////////////////////////////////////////////////////
|
||||
// following options are available to configure compilation:
|
||||
// USE_LMAP
|
||||
// USE_LMAPXFORM
|
||||
// USE_SHADOW
|
||||
//////////////////////////////////////////////////////////////////////////////////////////
|
||||
float4 m_lmap[2];
|
||||
|
||||
#ifdef MSAA_OPTIMIZATION
|
||||
float4 main(p_volume I, float4 pos2d : SV_Position, uint iSample : SV_SAMPLEINDEX ) : SV_Target
|
||||
#else
|
||||
float4 main(p_volume I, float4 pos2d : SV_Position ) : SV_Target
|
||||
#endif
|
||||
{
|
||||
float2 tcProj = I.tc.xy / I.tc.w;
|
||||
|
||||
gbuffer_data gbd = gbuffer_load_data(GLD_P(tcProj, pos2d, ISAMPLE) );
|
||||
|
||||
float4 _P = float4(gbd.P, gbd.mtl );
|
||||
float4 _N = float4(gbd.N, gbd.hemi );
|
||||
float4 _C = float4(gbd.C, gbd.gloss );
|
||||
|
||||
float m = xmaterial ;
|
||||
#ifndef USE_R2_STATIC_SUN
|
||||
m = _P.w;
|
||||
#endif
|
||||
|
||||
// FLORA FIXES & IMPROVEMENTS - SSS Update 14.2
|
||||
// Fix Flora ilumination ( Align normal to light )
|
||||
#ifdef SSFX_FLORAFIX
|
||||
if(abs(m - MAT_FLORA) <= 0.05)
|
||||
{
|
||||
_N.rgb = -normalize(_P - Ldynamic_pos.xyz);
|
||||
_C.w *= 0.3f;
|
||||
}
|
||||
#endif
|
||||
|
||||
// ----- light-model
|
||||
float rsqr;
|
||||
float4 light = plight_local(m, _P, _N, _C, Ldynamic_pos, Ldynamic_pos.w, rsqr );
|
||||
|
||||
// ----- shadow
|
||||
|
||||
float3 Offset = 0;
|
||||
#ifdef SSFX_SHADOWS
|
||||
// Biasing ( Use the nDotL from plight_local... )
|
||||
float bias_int = (1.0 - saturate(dot(_N, -normalize(_P - Ldynamic_pos.xyz)))) * rsqr * Ldynamic_pos.w;
|
||||
Offset = _N * (0.025f + bias_int * ssfx_shadow_bias.x) * (1536.0/float(SMAP_size));
|
||||
#endif
|
||||
|
||||
float4 P4 = float4(_P.xyz + Offset, 1);
|
||||
float4 PS = mul(m_shadow, P4 );
|
||||
|
||||
float s = 1.h;
|
||||
#ifdef USE_SHADOW
|
||||
s = shadow( PS, pos2d.xy );
|
||||
#endif
|
||||
|
||||
// ----- lightmap
|
||||
float4 lightmap= 1.h;
|
||||
#ifdef USE_LMAP
|
||||
#ifdef USE_LMAPXFORM
|
||||
PS.x = dot(P4, m_lmap[0] );
|
||||
PS.y = dot(P4, m_lmap[1] );
|
||||
#endif
|
||||
|
||||
// Can use linear with mip point
|
||||
lightmap = s_lmap.SampleLevel(smp_rtlinear, PS.xy / PS.w, 0 );
|
||||
#endif
|
||||
|
||||
#ifdef SSFX_ENHANCED_SHADERS
|
||||
return float4(SRGBToLinear(Ldynamic_color.rgb * lightmap.rgb * s.xxx),1) * light;
|
||||
#else
|
||||
return float4( Ldynamic_color * light * s * lightmap);
|
||||
#endif
|
||||
}
|
||||
@@ -0,0 +1,4 @@
|
||||
#define USE_SHADOW
|
||||
#define SLB_SHADOW_OMNI
|
||||
|
||||
#include "accum_base.ps"
|
||||
@@ -0,0 +1,5 @@
|
||||
#define USE_SHADOW
|
||||
#define USE_LMAP
|
||||
#define SLB_SHADOW_OMNI
|
||||
|
||||
#include "accum_base.ps"
|
||||
@@ -0,0 +1,5 @@
|
||||
#define USE_SHADOW
|
||||
#define USE_LMAP
|
||||
#define SLB_SHADOW_SPOT
|
||||
|
||||
#include "accum_base.ps"
|
||||
@@ -0,0 +1,6 @@
|
||||
#define USE_LMAP
|
||||
#define USE_LMAPXFORM
|
||||
#define USE_SHADOW
|
||||
#define SLB_SHADOW_SPOT
|
||||
|
||||
#include "accum_base.ps"
|
||||
@@ -0,0 +1,103 @@
|
||||
#include "common.h"
|
||||
#include "lmodel.h"
|
||||
|
||||
// Check Screen Space Shaders modules & addons
|
||||
#include "check_screenspace.h"
|
||||
|
||||
#ifdef SSFX_SSS
|
||||
#include "screenspace_shadows.h"
|
||||
#endif
|
||||
|
||||
#ifdef USE_MINMAX_SM
|
||||
#define SM_MINMAX
|
||||
#endif
|
||||
|
||||
#if SUN_QUALITY>2
|
||||
#define ULTRA_SHADOWS_ON
|
||||
#endif // SUN_QUALITY>2
|
||||
|
||||
#ifdef ULTRA_SHADOWS_ON
|
||||
#define USE_ULTRA_SHADOWS
|
||||
#endif
|
||||
|
||||
#define SLB_SHADOW_SUN_FAR
|
||||
#include "shadow.h"
|
||||
|
||||
uniform float3 view_shadow_proj; // Unused
|
||||
|
||||
#ifdef USE_SUNFILTER
|
||||
#ifdef MSAA_OPTIMIZATION
|
||||
float4 main ( v2p_volume I, uint iSample : SV_SAMPLEINDEX ) : SV_Target
|
||||
#else
|
||||
float4 main ( v2p_volume I ) : SV_Target
|
||||
#endif
|
||||
{
|
||||
gbuffer_data gbd = gbuffer_load_data( GLD_P(I.tc, I.hpos, ISAMPLE) );
|
||||
|
||||
float4 _P = float4( gbd.P, 1.0);
|
||||
|
||||
float4 PS = mul( m_shadow, _P );
|
||||
|
||||
float s = shadowtest_sun( PS, I.tcJ ) * sunmask( _P );
|
||||
|
||||
return s;
|
||||
}
|
||||
#else
|
||||
#ifdef MSAA_OPTIMIZATION
|
||||
float4 main ( v2p_volume I, uint iSample : SV_SAMPLEINDEX ) : SV_Target
|
||||
#else
|
||||
float4 main ( v2p_volume I ) : SV_Target
|
||||
#endif
|
||||
{
|
||||
gbuffer_data gbd = gbuffer_load_data( GLD_P(I.tc.xy/I.tc.w, I.hpos, ISAMPLE) );
|
||||
|
||||
float4 _P = float4( gbd.P, gbd.mtl );
|
||||
float4 _N = float4( gbd.N, gbd.hemi );
|
||||
float4 _C = float4( gbd.C, gbd.gloss );
|
||||
|
||||
// ----- light-model
|
||||
float m = xmaterial;
|
||||
#ifndef USE_R2_STATIC_SUN
|
||||
m = _P.w;
|
||||
#endif
|
||||
float4 light = plight_infinity ( m, _P, _N, _C, Ldynamic_dir );
|
||||
|
||||
// ----- shadow
|
||||
|
||||
// SHADOWS FIXES - SSS Update 19
|
||||
// Normal Offset for biasing
|
||||
float3 NormalOffset = 0;
|
||||
#ifdef SSFX_SHADOWS
|
||||
// NormalOffset = _N * ssfx_shadow_bias.y;
|
||||
#endif
|
||||
|
||||
float4 P4 = float4( _P.xyz + NormalOffset, 1.0);
|
||||
float4 PS = mul( m_shadow, P4 );
|
||||
|
||||
// SHADOWS FIXES - SSS Update 14.7
|
||||
// New far edge fading code
|
||||
float s = shadow( PS, I.hpos.xy ); // Far Shadows
|
||||
float shadows = sunmask( P4 ); // Clouds. Don't fade clouds.
|
||||
|
||||
// Fade UV
|
||||
float2 FadeUV = PS.xy / PS.w;
|
||||
|
||||
// Fade calc
|
||||
float4 fade = smoothstep(0.0f, 0.1f, float4(FadeUV.x, 1.0f - FadeUV.x, FadeUV.y, 1.0f - FadeUV.y));
|
||||
float f = fade.x * fade.y * fade.z * fade.w;
|
||||
s += ( 1.0f - s ) * ( 1.0f - f );
|
||||
|
||||
#ifdef SSFX_SSS
|
||||
s *= SSFX_ScreenSpaceShadows_Far(_P, I.hpos, ISAMPLE);
|
||||
#endif
|
||||
|
||||
// Add Shadows
|
||||
shadows *= s;
|
||||
|
||||
#ifdef SSFX_ENHANCED_SHADERS
|
||||
return blend( float4( SRGBToLinear( Ldynamic_color.rgb * shadows.xxx ), 1.0f ) * light, I.tc );
|
||||
#else
|
||||
return blend( Ldynamic_color * light * shadows, I.tc );
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
@@ -0,0 +1,88 @@
|
||||
#include "common.h"
|
||||
#include "lmodel.h"
|
||||
|
||||
#ifdef USE_MINMAX_SM
|
||||
#define SM_MINMAX
|
||||
#endif
|
||||
|
||||
#if SUN_QUALITY>2
|
||||
#define ULTRA_SHADOWS_ON
|
||||
#endif // SUN_QUALITY>2
|
||||
|
||||
#ifdef ULTRA_SHADOWS_ON
|
||||
#define USE_ULTRA_SHADOWS
|
||||
#endif
|
||||
|
||||
#define SLB_SHADOW_SUN_NEAR
|
||||
#include "shadow.h"
|
||||
|
||||
// Check Screen Space Shaders modules & addons
|
||||
#include "check_screenspace.h"
|
||||
|
||||
#ifdef SSFX_SSS
|
||||
#include "screenspace_shadows.h"
|
||||
#endif
|
||||
|
||||
#ifdef USE_SUNFILTER
|
||||
#ifdef MSAA_OPTIMIZATION
|
||||
float4 main ( v2p_volume I, uint iSample : SV_SAMPLEINDEX ) : SV_Target
|
||||
#else
|
||||
float4 main ( v2p_volume I ) : SV_Target
|
||||
#endif
|
||||
{
|
||||
gbuffer_data gbd = gbuffer_load_data( GLD_P(I.tc, I.hpos, ISAMPLE) );
|
||||
|
||||
|
||||
float4 _P = float4( gbd.P, 1.0);
|
||||
|
||||
float4 PS = mul( m_shadow, _P );
|
||||
|
||||
float s = shadowtest_sun( PS, I.tcJ ) * sunmask( _P );
|
||||
|
||||
return s;
|
||||
}
|
||||
#else
|
||||
#ifdef MSAA_OPTIMIZATION
|
||||
float4 main ( v2p_volume I, uint iSample : SV_SAMPLEINDEX ) : SV_Target
|
||||
#else
|
||||
float4 main ( v2p_volume I ) : SV_Target
|
||||
#endif
|
||||
{
|
||||
gbuffer_data gbd = gbuffer_load_data( GLD_P(I.tc.xy/I.tc.w, I.hpos, ISAMPLE) );
|
||||
|
||||
float4 _P = float4( gbd.P, gbd.mtl );
|
||||
float4 _N = float4( gbd.N, gbd.hemi );
|
||||
float4 _C = float4( gbd.C, gbd.gloss );
|
||||
|
||||
// ----- light-model
|
||||
float m = xmaterial;
|
||||
#ifndef USE_R2_STATIC_SUN
|
||||
m = _P.w;
|
||||
#endif
|
||||
float4 light = plight_infinity ( m, _P, _N, _C, Ldynamic_dir );
|
||||
|
||||
// ----- shadow
|
||||
// SHADOWS FIXES - SSS Update 19
|
||||
// Normal Offset for biasing
|
||||
float3 NormalOffset = 0;
|
||||
#ifdef SSFX_SHADOWS
|
||||
// NormalOffset = _N * ssfx_shadow_bias.y;
|
||||
#endif
|
||||
|
||||
float4 P4 = float4( _P.xyz + NormalOffset, 1.0);
|
||||
float4 PS = mul( m_shadow, P4 );
|
||||
float s = sunmask( P4 );
|
||||
s *= shadow( PS, I.hpos.xy );
|
||||
|
||||
#ifdef SSFX_SSS
|
||||
s *= SSFX_ScreenSpaceShadows(_P, I.hpos, ISAMPLE);
|
||||
#endif
|
||||
|
||||
#ifdef SSFX_ENHANCED_SHADERS // We have Enhanced Shaders installed
|
||||
return float4( SRGBToLinear(Ldynamic_color.rgb * s.xxx),1) * light;
|
||||
#else
|
||||
return float4( Ldynamic_color * light * s);
|
||||
#endif
|
||||
|
||||
}
|
||||
#endif
|
||||
@@ -0,0 +1,39 @@
|
||||
#ifndef MBLUR_H
|
||||
#define MBLUR_H
|
||||
|
||||
#ifndef USE_MBLUR
|
||||
float3 mblur (float2 UV, float3 pos, float3 c_original) { return c_original; }
|
||||
#else
|
||||
|
||||
#include "common.h"
|
||||
#include "slb_motion_blur.h"
|
||||
|
||||
////////////////////////////////////////
|
||||
float4x4 m_current; //Current projection matrix
|
||||
float4x4 m_previous; //Previous projection matrix
|
||||
float2 m_blur;
|
||||
////////////////////////////////////////
|
||||
|
||||
float3 mblur(float2 UV, float3 pos, float3 img)
|
||||
{
|
||||
//Fix sky ghosting caused by infinite depth value (KD)
|
||||
pos.z = is_sky(pos.z) > 0.5 ? 10000.0 : pos.z;
|
||||
|
||||
//Sample position buffer
|
||||
float4 pos4 = float4(pos, 1.0);
|
||||
|
||||
//Get current texture coordinates
|
||||
float4 p_current = mul(m_current, pos4);
|
||||
float2 current_tc = p_current.xy /= p_current.w;
|
||||
|
||||
//Get previous texture coordinates
|
||||
float4 p_previous = mul(m_previous, pos4);
|
||||
float2 previous_tc = p_previous.xy / p_previous.w;
|
||||
|
||||
//Get velocity (multiplied with motion blur intensity)
|
||||
float2 p_velocity = (current_tc - previous_tc) * m_blur;
|
||||
|
||||
return SLB_MBlur(UV, pos, img, p_velocity, 0);
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
@@ -0,0 +1,30 @@
|
||||
#include "common.h"
|
||||
#include "lmodel.h"
|
||||
#include "shadow.h"
|
||||
|
||||
|
||||
Texture2D s_water;
|
||||
|
||||
float4 main ( float2 tc : TEXCOORD0, float2 tcJ : TEXCOORD1, float4 pos2d : SV_Position ) : SV_Target
|
||||
{
|
||||
|
||||
gbuffer_data gbd = gbuffer_load_data( tc, pos2d );
|
||||
|
||||
float4 _P = float4( gbd.P, 1.0 );
|
||||
float4 PS = mul( m_shadow, _P );
|
||||
|
||||
float s = shadow(PS, pos2d.xy);
|
||||
|
||||
float2 tc1 = mul( m_sunmask, _P ); //
|
||||
|
||||
tc1 /= 2;
|
||||
tc1 = frac(tc1);
|
||||
|
||||
float4 water = s_water.SampleLevel( smp_linear, tc1, 0 );
|
||||
|
||||
water.xyz = (water.xzy-0.5)*2;
|
||||
water.xyz = mul( m_V, water.xyz );
|
||||
water *= s;
|
||||
|
||||
return float4(water.xyz,s);
|
||||
}
|
||||
@@ -0,0 +1,335 @@
|
||||
#ifndef SHADOW_H
|
||||
#define SHADOW_H
|
||||
|
||||
#include "common.h"
|
||||
|
||||
//uniform sampler s_smap : register(ps,s0); // 2D/cube shadowmap
|
||||
//Texture2D<float> s_smap; // 2D/cube shadowmap
|
||||
// Used for RGBA texture too ?!
|
||||
Texture2D s_smap : register(ps,t0); // 2D/cube shadowmap
|
||||
|
||||
Texture2D<float> s_smap_minmax; // 2D/cube shadowmap
|
||||
#include "gather.ps"
|
||||
|
||||
SamplerComparisonState smp_smap; // Special comare sampler
|
||||
sampler smp_jitter;
|
||||
|
||||
uniform float4 ssfx_shadow_bias;
|
||||
|
||||
Texture2D jitter0;
|
||||
Texture2D jitter1;
|
||||
Texture2D jitterMipped;
|
||||
|
||||
#ifndef USE_ULTRA_SHADOWS
|
||||
#define KERNEL 0.6f
|
||||
#else
|
||||
#define KERNEL 1.0f
|
||||
#endif
|
||||
|
||||
#define PCSS_PIXEL int(4)
|
||||
#define PCSS_STEP int(2)
|
||||
#define PCSS_PIXEL_MIN float(1.0)
|
||||
#define PCSS_SUN_WIDTH float(150.0)
|
||||
|
||||
float modify_light( float light )
|
||||
{
|
||||
return ( light > 0.7 ? 1.0 : lerp( 0.0, 1.0, saturate( light / 0.7 ) ) );
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////////////
|
||||
// hardware + PCF
|
||||
//////////////////////////////////////////////////////////////////////////////////////////
|
||||
float sample_hw_pcf (float4 tc,float4 shift)
|
||||
{
|
||||
static const float ts = KERNEL / float(SMAP_size);
|
||||
|
||||
tc.xyz /= tc.w;
|
||||
tc.xy += shift.xy * ts;
|
||||
|
||||
return s_smap.SampleCmpLevelZero( smp_smap, tc.xy, tc.z).x;
|
||||
}
|
||||
|
||||
float shadow_hw( float4 tc )
|
||||
{
|
||||
float s0 = sample_hw_pcf( tc, float4( -1, -1, 0, 0) );
|
||||
float s1 = sample_hw_pcf( tc, float4( +1, -1, 0, 0) );
|
||||
float s2 = sample_hw_pcf( tc, float4( -1, +1, 0, 0) );
|
||||
float s3 = sample_hw_pcf( tc, float4( +1, +1, 0, 0) );
|
||||
|
||||
return (s0+s1+s2+s3)/4.h;
|
||||
}
|
||||
|
||||
|
||||
#ifdef SM_MINMAX
|
||||
bool cheap_reject( float3 tc, inout bool full_light )
|
||||
{
|
||||
float4 plane0 = sm_minmax_gather( tc.xy, int2( -1,-1 ) );
|
||||
float4 plane1 = sm_minmax_gather( tc.xy, int2( 1,-1 ) );
|
||||
float4 plane2 = sm_minmax_gather( tc.xy, int2( -1, 1 ) );
|
||||
float4 plane3 = sm_minmax_gather( tc.xy, int2( 1, 1 ) );
|
||||
bool plane = all( ( plane0 >= (0).xxxx ) * ( plane1 >= (0).xxxx ) * ( plane2 >= (0).xxxx ) * ( plane3 >= (0).xxxx ) );
|
||||
|
||||
[flatten] if( !plane ) // if there are no proper plane equations in the support region
|
||||
{
|
||||
bool no_plane = all( ( plane0 < (0).xxxx ) * ( plane1 < (0).xxxx ) * ( plane2 < (0).xxxx ) * ( plane3 < (0).xxxx ) );
|
||||
float4 z = ( tc.z - 0.0005 ).xxxx;
|
||||
bool reject = all( ( z > -plane0 ) * ( z > -plane1 ) * ( z > -plane2 ) * ( z > -plane3 ) );
|
||||
[flatten] if( no_plane && reject )
|
||||
{
|
||||
full_light = false;
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else // plane equation detected
|
||||
{
|
||||
// compute corrected z for texel pos
|
||||
static const float scale = float( SMAP_size / 4 );
|
||||
float2 fc = frac( tc.xy * scale );
|
||||
float z = lerp( lerp( plane0.y, plane1.x, fc.x ), lerp( plane2.z, plane3.w, fc.x ), fc.y );
|
||||
|
||||
// do minmax test with new z
|
||||
full_light = ( ( tc.z - 0.0001 ) <= z );
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
//Sunshafts
|
||||
float shadow_dx10_1_sunshafts( float4 tc, float2 pos2d )
|
||||
{
|
||||
float3 t = tc.xyz / tc.w;
|
||||
float minmax = s_smap_minmax.SampleLevel( smp_nofilter, t, 0 ).x;
|
||||
bool umbra = ( ( minmax.x < 0 ) && ( t.z > -minmax.x ) );
|
||||
|
||||
[branch] if( umbra )
|
||||
{
|
||||
return 0.0;
|
||||
}
|
||||
else
|
||||
{
|
||||
return shadow_hw( tc );
|
||||
}
|
||||
}
|
||||
#endif // SM_MINMAX
|
||||
|
||||
|
||||
|
||||
//PCSS shadows
|
||||
static const float2 poissonDisk[32] = {
|
||||
float2(0.0617981, 0.07294159),
|
||||
float2(0.6470215, 0.7474022),
|
||||
float2(-0.5987766, -0.7512833),
|
||||
float2(-0.693034, 0.6913887),
|
||||
float2(0.6987045, -0.6843052),
|
||||
float2(-0.9402866, 0.04474335),
|
||||
float2(0.8934509, 0.07369385),
|
||||
float2(0.1592735, -0.9686295),
|
||||
float2(-0.05664673, 0.995282),
|
||||
float2(-0.1203411, -0.1301079),
|
||||
float2(0.1741608, -0.1682285),
|
||||
float2(-0.09369049, 0.3196758),
|
||||
float2(0.185363, 0.3213367),
|
||||
float2(-0.1493771, -0.3147511),
|
||||
float2(0.4452095, 0.2580113),
|
||||
float2(-0.1080467, -0.5329178),
|
||||
float2(0.1604507, 0.5460774),
|
||||
float2(-0.4037193, -0.2611179),
|
||||
float2(0.5947998, -0.2146744),
|
||||
float2(0.3276062, 0.9244621),
|
||||
float2(-0.6518704, -0.2503952),
|
||||
float2(-0.3580975, 0.2806469),
|
||||
float2(0.8587891, 0.4838005),
|
||||
float2(-0.1596546, -0.8791054),
|
||||
float2(-0.3096867, 0.5588146),
|
||||
float2(-0.5128918, 0.1448544),
|
||||
float2(0.8581337, -0.424046),
|
||||
float2(0.1562584, -0.5610626),
|
||||
float2(-0.7647934, 0.2709858),
|
||||
float2(-0.3090832, 0.9020988),
|
||||
float2(0.3935608, 0.4609676),
|
||||
float2(0.3929337, -0.5010948),
|
||||
};
|
||||
|
||||
//Quality tokens --Fine
|
||||
#if !defined(SUN_QUALITY)
|
||||
#define PCSS_NUM_SAMPLES int(1)
|
||||
#elif SUN_QUALITY==1
|
||||
#define PCSS_NUM_SAMPLES int(8)
|
||||
#elif SUN_QUALITY==2
|
||||
#define PCSS_NUM_SAMPLES int(12)
|
||||
#elif SUN_QUALITY==3
|
||||
#define PCSS_NUM_SAMPLES int(20)
|
||||
#elif (SUN_QUALITY==4 || SUN_QUALITY==5)
|
||||
#define PCSS_NUM_SAMPLES int(32)
|
||||
#endif
|
||||
|
||||
float shadow_pcss( float4 tc )
|
||||
{
|
||||
// - Small modification to fix flickering and black squares.
|
||||
// - Added a extra performance option with lower SUN_QUALITY settings.
|
||||
// - Extended the blocker search from 3x3 to 4x4 for better results.
|
||||
// https://www.moddb.com/mods/stalker-anomaly/addons/screen-space-shaders/
|
||||
|
||||
tc.xyz /= tc.w;
|
||||
|
||||
#if SUN_QUALITY > 3 // Blocker search ( Penumbra ) and filter
|
||||
|
||||
int3 uv = int3(tc.xy * float(SMAP_size), 0);
|
||||
float zBlock = tc.z - 0.0001;
|
||||
float avgBlockerDepth = 0.0;
|
||||
float blockerCount = 0.0;
|
||||
|
||||
[unroll]
|
||||
for( int row = -PCSS_PIXEL; row <= PCSS_PIXEL; row += PCSS_STEP )
|
||||
{
|
||||
[unroll]
|
||||
for( int col = -PCSS_PIXEL; col <= PCSS_PIXEL; col += PCSS_STEP )
|
||||
{
|
||||
float shadowMapDepth = s_smap.Load( uv, int2( col, row ) ).x;
|
||||
float b1 = ( shadowMapDepth < zBlock ) ? 1.0 : 0.0;
|
||||
blockerCount += b1;
|
||||
avgBlockerDepth += shadowMapDepth * b1;
|
||||
}
|
||||
}
|
||||
|
||||
if(blockerCount < 1)
|
||||
return 1.0;
|
||||
|
||||
avgBlockerDepth /= blockerCount;
|
||||
float fRatio = saturate( ( ( tc.z - avgBlockerDepth ) * PCSS_SUN_WIDTH ) / avgBlockerDepth );
|
||||
fRatio *= fRatio;
|
||||
fRatio = max(PCSS_PIXEL_MIN, fRatio * float(PCSS_PIXEL)) / float(SMAP_size);
|
||||
|
||||
float s = 0.0;
|
||||
[unroll]
|
||||
for( uint i = 0; i < PCSS_NUM_SAMPLES; ++i )
|
||||
{
|
||||
float2 offset = poissonDisk[i] * fRatio;
|
||||
s += s_smap.SampleCmpLevelZero( smp_smap, tc.xy + offset, tc.z ).x;
|
||||
}
|
||||
return s / PCSS_NUM_SAMPLES;
|
||||
|
||||
#else // No blocker search ( Penumbra ), just filter
|
||||
|
||||
|
||||
float fRatio = 4.0f / float(SMAP_size);
|
||||
|
||||
float s = 0.0;
|
||||
[unroll]
|
||||
for( uint i = 0; i < PCSS_NUM_SAMPLES; ++i )
|
||||
{
|
||||
float2 offset = poissonDisk[i] * fRatio;
|
||||
float test = s_smap.SampleCmpLevelZero( smp_smap, tc.xy + offset, tc.z ).x;
|
||||
s += test;
|
||||
}
|
||||
|
||||
return s / PCSS_NUM_SAMPLES;
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////////////
|
||||
// D24X8+PCF
|
||||
//////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
float4 test (float4 tc, float2 offset)
|
||||
{
|
||||
tc.xyz /= tc.w;
|
||||
tc.xy += offset;
|
||||
return s_smap.SampleCmpLevelZero( smp_smap, tc.xy, tc.z).x;
|
||||
}
|
||||
|
||||
half shadowtest_sun (float4 tc, float4 tcJ) // jittered sampling
|
||||
{
|
||||
half4 r;
|
||||
const float scale = (0.7/float(SMAP_size));
|
||||
|
||||
float2 tc_J = frac(tc.xy/tc.w*SMAP_size/4.0 )*0.5;
|
||||
float4 J0 = jitter0.Sample(smp_jitter,tc_J)*scale;
|
||||
|
||||
const float k = 0.5/float(SMAP_size);
|
||||
r.x = test (tc, J0.xy+half2(-k,-k)).x;
|
||||
r.y = test (tc, J0.wz+half2( k,-k)).y;
|
||||
r.z = test (tc,-J0.xy+half2(-k, k)).z;
|
||||
r.w = test (tc,-J0.wz+half2( k, k)).x;
|
||||
|
||||
return dot(r,1.0/4.0);
|
||||
}
|
||||
|
||||
float shadow_hw_hq( float4 tc )
|
||||
{
|
||||
#ifdef SM_MINMAX
|
||||
bool full_light = false;
|
||||
bool cheap_path = cheap_reject( tc.xyz / tc.w, full_light );
|
||||
|
||||
[branch] if( cheap_path )
|
||||
{
|
||||
[branch] if( full_light == true )
|
||||
return 1.0;
|
||||
else
|
||||
return sample_hw_pcf( tc, (0).xxxx );
|
||||
}
|
||||
else
|
||||
{
|
||||
return shadow_pcss(tc);
|
||||
}
|
||||
#else // SM_MINMAX
|
||||
return shadow_pcss(tc);
|
||||
#endif // SM_MINMAX
|
||||
}
|
||||
|
||||
uniform float4x4 m_shadow;
|
||||
#include "slb_shadow.h"
|
||||
float shadow( float4 tc, float2 pos2d )
|
||||
{
|
||||
return SLB_Shadow(tc, pos2d);
|
||||
#ifdef USE_ULTRA_SHADOWS
|
||||
#ifdef SM_MINMAX
|
||||
return modify_light( shadow_hw_hq( tc ) );
|
||||
#else
|
||||
return shadow_hw_hq( tc );
|
||||
#endif
|
||||
#else
|
||||
return shadow_pcss(tc);
|
||||
#endif
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////////////
|
||||
// testbed
|
||||
|
||||
float shadow_rain(float4 tc, float2 tcJ) // jittered sampling
|
||||
{
|
||||
float4 r;
|
||||
|
||||
const float scale = (4.0/float(SMAP_size));
|
||||
|
||||
float4 J0 = jitter0.Sample( smp_linear, tcJ )*scale;
|
||||
float4 J1 = jitter1.Sample( smp_linear, tcJ )*scale;
|
||||
|
||||
r.x = test (tc,J0.xy).x;
|
||||
r.y = test (tc,J0.wz).y;
|
||||
r.z = test (tc,J1.xy).z;
|
||||
r.w = test (tc,J1.wz).x;
|
||||
return dot(r,1.0/4.0);
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////////////
|
||||
#ifdef USE_SUNMASK
|
||||
float3x4 m_sunmask; // ortho-projection
|
||||
float sunmask( float4 P )
|
||||
{
|
||||
float2 tc = mul( m_sunmask, P ); //
|
||||
return s_lmap.SampleLevel( smp_linear, tc, 0 ).w; //Hemi map - ambient occlusion
|
||||
}
|
||||
#else
|
||||
float sunmask( float4 P ) { return 1.0; } //
|
||||
#endif
|
||||
//////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,49 @@
|
||||
#ifndef SLB_ALIASES_H
|
||||
#define SLB_ALIASES_H
|
||||
|
||||
#ifdef SLB_GLSL /// We are in glslViewer
|
||||
|
||||
#define SLB_SAMPLER_LOAD(sampler_name, texture_coord) texelFetch(sampler_name, texture_coord.xy, texture_coord.z)
|
||||
|
||||
#define SLB_BRANCH
|
||||
#define SLB_UNROLL(x)
|
||||
#define SLB_STATIC_CONST const
|
||||
|
||||
/// HLSL shit
|
||||
#define frac(x) fract(x)
|
||||
#define saturate(x) clamp(x, 0.0, 1.0)
|
||||
#define mul(a, b) (a * b)
|
||||
#define reversebits(x) bitfieldReverse(x)
|
||||
#define asuint(x) floatBitsToUint(x)
|
||||
#define lerp(a, b, x) mix(a, b, x)
|
||||
#define ddx(x) dFdx(x)
|
||||
#define ddy(x) dFdy(x)
|
||||
|
||||
#define float2 vec2
|
||||
#define float3 vec3
|
||||
#define float4 vec4
|
||||
|
||||
#define float2x2 mat2
|
||||
#define float3x3 mat3
|
||||
#define float4x4 mat4
|
||||
|
||||
#define int2 ivec2
|
||||
#define int3 ivec3
|
||||
#define int4 ivec4
|
||||
|
||||
#define uint2 uvec2
|
||||
#define uint3 uvec3
|
||||
#define uint4 uvec4
|
||||
|
||||
#else /// We are in stalker
|
||||
|
||||
#define SLB_SAMPLER_LOAD(sampler_name, texture_coord) sampler_name.Load(texture_coord)
|
||||
#define SLB_SAMPLER_LOAD_MSAA(sampler_name, texture_coord, iSample) sampler_name.Load(texture_coord, iSample)
|
||||
|
||||
#define SLB_BRANCH [branch]
|
||||
#define SLB_UNROLL(x) [unroll(x)]
|
||||
#define SLB_STATIC_CONST static const
|
||||
|
||||
#endif
|
||||
|
||||
#endif /// SLB_ALIASES_H
|
||||
@@ -0,0 +1,248 @@
|
||||
#ifndef SLB_COMMON_H
|
||||
#define SLB_COMMON_H
|
||||
|
||||
#include "slb_aliases.h"
|
||||
|
||||
#define SLB_PI 3.14159265358979323846
|
||||
#define SLB_TAU 6.28318530717958647693
|
||||
#define SLB_GoldenAngle 2.39996322972865332223
|
||||
#define SLB_GoldenRatio 0.61803398874989484820
|
||||
|
||||
/// Taken from https://gist.github.com/yiwenl/3f804e80d0930e34a0b33359259b556c
|
||||
float2x2 SLB_Rotate2Matrix(float a) {
|
||||
float s = sin(a);
|
||||
float c = cos(a);
|
||||
return float2x2(float2(c, s), float2(-s, c));
|
||||
}
|
||||
|
||||
float2 SLB_Rotate2(float2 v, float a) {
|
||||
float2x2 m = SLB_Rotate2Matrix(a);
|
||||
return mul(v, m);
|
||||
}
|
||||
|
||||
float SLB_ToFloat1(uint v) {
|
||||
return float(v) * (1.0/float(0xffffffffu));
|
||||
}
|
||||
|
||||
float2 SLB_ToFloat2(uint2 v) {
|
||||
return float2(v) * (1.0/float(0xffffffffu));
|
||||
}
|
||||
|
||||
float3 SLB_ToFloat3(uint3 v) {
|
||||
return float3(v) * (1.0/float(0xffffffffu));
|
||||
}
|
||||
|
||||
float4 SLB_ToFloat4(uint4 v) {
|
||||
return float4(v) * (1.0/float(0xffffffffu));
|
||||
}
|
||||
|
||||
float SLB_Min3(float3 v) {
|
||||
return min(v.x, min(v.y, v.z));
|
||||
}
|
||||
|
||||
float SLB_Max3(float3 v) {
|
||||
return max(v.x, max(v.y, v.z));
|
||||
}
|
||||
|
||||
/// Taken from https://web.archive.org/web/20200306054846/http://lolengine.net:80/blog/2013/07/27/rgb-to-hsv-in-glsl
|
||||
float3 SLB_RGB_To_HSV(float3 c) {
|
||||
float4 K = float4(0.0, -1.0 / 3.0, 2.0 / 3.0, -1.0);
|
||||
float4 p = c.g < c.b ? float4(c.bg, K.wz) : float4(c.gb, K.xy);
|
||||
float4 q = c.r < p.x ? float4(p.xyw, c.r) : float4(c.r, p.yzx);
|
||||
float d = q.x - min(q.w, q.y);
|
||||
const float e = 1.0e-10;
|
||||
return float3(abs(q.z + (q.w - q.y) / (6.0 * d + e)), d / (q.x + e), q.x);
|
||||
}
|
||||
|
||||
/// It took me long time to found this somewhere in vanilla shaders codebase;
|
||||
float2 SLB_Pos2DToCoord(float2 pos2d) {
|
||||
// return float2((pos2d.x * screen_res.z * 2.0 - 1.0), (pos2d.y * screen_res.w * 2.0 - 1.0))/2.0 * screen_res.xy;
|
||||
return (pos2d.xy * screen_res.zw - 0.5) * screen_res.xy;
|
||||
}
|
||||
|
||||
/// Taken from https://iquilezles.org/articles/smoothsteps
|
||||
float SLB_Cubic1D(float x) {
|
||||
return x*x*(3.0 - 2.0*x);
|
||||
}
|
||||
|
||||
/// Taken from https://iquilezles.org/articles/smoothsteps
|
||||
float SLB_Quartic1D(float x) {
|
||||
return x*x*(2.0 - x*x);
|
||||
}
|
||||
|
||||
/// Taken from https://iquilezles.org/articles/smoothsteps
|
||||
float SLB_Quintic1D(float x) {
|
||||
return x*x*x*(x*(6.0*x - 15.0) + 10.0);
|
||||
}
|
||||
|
||||
/// Taken from https://iquilezles.org/articles/smoothsteps
|
||||
float SLB_CubicRational1D(float x) {
|
||||
return x*x*x/(3.0*x*x - 3.0*x + 1.0);
|
||||
}
|
||||
|
||||
/// Taken from https://iquilezles.org/articles/smoothsteps
|
||||
float SLB_QuarticRational1D(float x) {
|
||||
return x*x*x*x/(2.0*x*x*x*x - 4.0*x*x*x + 6.0*x*x - 4.0*x + 1.0);
|
||||
}
|
||||
|
||||
/// Taken from somewhere
|
||||
float SLB_Gaussian1D(float x, float sigma) {
|
||||
return exp(-(x * x) / (2.0 * sigma * sigma));
|
||||
}
|
||||
|
||||
/// Taken from http://www.java-gaming.org/index.php?topic=35123.0
|
||||
/// Idk how to name it
|
||||
float4 SLB_Cubic_For_Bicubic(float v) {
|
||||
float4 n = float4(1.0, 2.0, 3.0, 4.0) - v;
|
||||
float4 s = n * n * n;
|
||||
float x = s.x;
|
||||
float y = s.y - 4.0 * s.x;
|
||||
float z = s.z - 4.0 * s.y + 6.0 * s.x;
|
||||
float w = 6.0 - x - y - z;
|
||||
return float4(x, y, z, w) * (1.0/6.0);
|
||||
}
|
||||
|
||||
float2 SLB_VogelDisk_Sample(const int sample_index, const int samples_count) {
|
||||
const float r = sqrt(float(sample_index) + 0.5) / sqrt(float(samples_count));
|
||||
const float theta = float(sample_index) * SLB_GoldenAngle;
|
||||
|
||||
const float sine = sin(theta), cosine = cos(theta);
|
||||
|
||||
return float2(r * cosine, r * sine);
|
||||
}
|
||||
|
||||
/// Taken from https://extremelearning.com.au/unreasonable-effectiveness-of-quasirandom-sequences
|
||||
float SLB_R1(float n) {
|
||||
const float g = 1.6180339887498948482;
|
||||
const float a1 = 1.0 - 1.0/g;
|
||||
float _n = floor(n);
|
||||
return frac(0.5 + a1*_n);
|
||||
}
|
||||
|
||||
/// Taken from https://fgiesen.wordpress.com/2009/12/13/decoding-morton-codes
|
||||
uint SLB_Part1By1(uint x) {
|
||||
x &= 0x0000ffffu;
|
||||
x = (x ^ (x << 8u)) & 0x00ff00ffu;
|
||||
x = (x ^ (x << 4u)) & 0x0f0f0f0fu;
|
||||
x = (x ^ (x << 2u)) & 0x33333333u;
|
||||
x = (x ^ (x << 1u)) & 0x55555555u;
|
||||
return x;
|
||||
}
|
||||
|
||||
/// Taken from https://fgiesen.wordpress.com/2009/12/13/decoding-morton-codes
|
||||
uint SLB_EncodeMorton2(uint x, uint y) {
|
||||
return (SLB_Part1By1(y) << 1u) + SLB_Part1By1(x);
|
||||
}
|
||||
|
||||
/// From https://psychopath.io post
|
||||
uint SLB_OwenHash4(uint n, uint seed) {
|
||||
n ^= n * 0x3d20adeau;
|
||||
n ^= (n >> 1u) & (n << 1u) & 0x55555555u;
|
||||
n += seed;
|
||||
n *= (seed >> 16u) | 1u;
|
||||
n ^= (n >> 1u) & (n << 1u) & 0x55555555u;
|
||||
n ^= n * 0x05526c56u;
|
||||
n ^= n * 0x53a22864u;
|
||||
return n;
|
||||
}
|
||||
|
||||
/// Inspired by https://www.shadertoy.com/view/ssBBW1 shader and https://psychopath.io posts
|
||||
uint SLB_Morton_OwenHash4_Bluenoise(uint2 coord) {
|
||||
uint m;
|
||||
m = SLB_EncodeMorton2(coord.x, coord.y);
|
||||
m = SLB_OwenHash4(reversebits(m), 0xe7843fbfu); // owen-scramble morton index
|
||||
m = SLB_OwenHash4(reversebits(m), 0x8d8fb1e0u); // map morton index to sobol sequence and owen-scramble
|
||||
return reversebits(m); // convert to float
|
||||
}
|
||||
|
||||
float SLB_Morton_OwenHash4_Bluenoise_float(uint2 coord) {
|
||||
return SLB_ToFloat1(SLB_Morton_OwenHash4_Bluenoise(coord));
|
||||
}
|
||||
|
||||
/// Taken from https://www.shadertoy.com/view/wltSDn
|
||||
uint SLB_PhiNoise(uint2 uv) {
|
||||
// flip every other tile to reduce anisotropy
|
||||
if(((uv.x ^ uv.y) & 4u) == 0u) uv = uv.yx;
|
||||
|
||||
// constants of 2d Roberts sequence rounded to nearest primes
|
||||
const uint r0 = 3242174893u;// prime[(2^32-1) / phi_2 ]
|
||||
const uint r1 = 2447445397u;// prime[(2^32-1) / phi_2^2]
|
||||
|
||||
// h = high-freq dither noise
|
||||
uint h = (uv.x * r0) + (uv.y * r1);
|
||||
|
||||
// l = low-freq white noise
|
||||
uv = uv >> 2u;// 3u works equally well (I think)
|
||||
uint l = ((uv.x * r0) ^ (uv.y * r1)) * r1;
|
||||
|
||||
// combine low and high
|
||||
return l + h;
|
||||
}
|
||||
|
||||
float SLB_PhiNoise_float(uint2 uv) {
|
||||
return SLB_ToFloat1(SLB_PhiNoise(uv));
|
||||
}
|
||||
|
||||
/// Taken from https://www.shadertoy.com/view/wltSDn
|
||||
uint SLB_PhiNoise2(uint2 uv) {
|
||||
uint2 uv0 = uv;
|
||||
// flip every other tile to reduce anisotropy
|
||||
if(((uv.x ^ uv.y) & 4u) == 0u) uv = uv.yx;
|
||||
if(((uv.x ) & 4u) == 0u) uv.x = -uv.x;// more iso but also more low-freq content
|
||||
|
||||
// constants of 2d Roberts sequence rounded to nearest primes
|
||||
const uint r0 = 3242174893u;// prime[(2^32-1) / phi_2 ]
|
||||
const uint r1 = 2447445397u;// prime[(2^32-1) / phi_2^2]
|
||||
|
||||
// h = high-freq dither noise
|
||||
uint h = (uv.x * r0) + (uv.y * r1);
|
||||
|
||||
uint l;
|
||||
{
|
||||
uv = uv0 >> 2u;
|
||||
|
||||
if(((uv.x ^ uv.y) & 4u) == 0u) uv = uv.yx;
|
||||
if(((uv.x ) & 4u) == 0u) uv.x = -uv.x;
|
||||
|
||||
uint h = (uv.x * r0) + (uv.y * r1);
|
||||
h = h ^ 0xE2E17FDCu;
|
||||
|
||||
l = h;
|
||||
|
||||
{
|
||||
uv = uv0 >> 4u;
|
||||
if(((uv.x ^ uv.y) & 4u) == 0u) uv = uv.yx;
|
||||
if(((uv.x ) & 4u) == 0u) uv.x = -uv.x;
|
||||
|
||||
uint h = (uv.x * r0) + (uv.y * r1);
|
||||
h = h ^ 0x1B98264Du;
|
||||
|
||||
l += h;
|
||||
}
|
||||
}
|
||||
|
||||
// combine low and high
|
||||
return l + h;
|
||||
}
|
||||
|
||||
float SLB_PhiNoise2_float(uint2 uv) {
|
||||
return SLB_ToFloat1(SLB_PhiNoise2(uv));
|
||||
}
|
||||
|
||||
/// Taken from paper named "Hash Functions for GPU Rendering"
|
||||
uint4 SLB_PCG4D(uint4 v) {
|
||||
v = v * 1664525u + 1013904223u;
|
||||
v.x += v.y*v.w; v.y += v.z*v.x; v.z += v.x*v.y; v.w += v.y*v.z;
|
||||
v ^= v >> 16u;
|
||||
v.x += v.y*v.w; v.y += v.z*v.x; v.z += v.x*v.y; v.w += v.y*v.z;
|
||||
return v;
|
||||
}
|
||||
|
||||
/// Taken from https://www.pcg-random.org
|
||||
uint SLB_PCG(uint v) {
|
||||
uint state = v * 747796405u + 2891336453u;
|
||||
uint word = ((state >> ((state >> 28u) + 4u)) ^ state) * 277803737u;
|
||||
return (word >> 22u) ^ word;
|
||||
}
|
||||
|
||||
#endif // SLB_COMMON_H
|
||||
@@ -0,0 +1,173 @@
|
||||
#ifndef SLB_MOTION_BLUR_H
|
||||
#define SLB_MOTION_BLUR_H
|
||||
|
||||
#include "slb_common.h"
|
||||
#include "slb_motion_blur_settings.h"
|
||||
|
||||
float3 SLB_Screen_GetImage(float2 tc, uint iSample) {
|
||||
return SLB_SAMPLER_LOAD(s_image, int3(tc * screen_res.xy - 0.25, 0)).rgb;
|
||||
}
|
||||
|
||||
float4 SLB_Screen_GetPosition(float2 tc, uint iSample) {
|
||||
#ifdef SLB_GLSL /// return dummy
|
||||
return float4(0.5, 0.5, float(abs(tc.x - 0.5) < 0.25)*10.0+0.01, 0.0);
|
||||
#else
|
||||
#ifdef USE_MSAA
|
||||
return SLB_SAMPLER_LOAD_MSAA(s_position, int3(tc * screen_res.xy - 0.25, 0), iSample);
|
||||
#else
|
||||
return SLB_SAMPLER_LOAD(s_position, int3(tc * screen_res.xy - 0.25, 0));
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
|
||||
// uniform float4 shader_param_6 = float4(0.9,0,9,0);
|
||||
|
||||
float SLB_MBlur_SightMask(float2 tc, float3 img, float2 aspect, uint iSample) {
|
||||
float len = saturate(SLB_MBLUR_SIGHT_MASK_SIZE - length((tc - 0.5)*aspect)*75.);
|
||||
|
||||
#ifdef SLB_MBLUR_SIGHT_MASK_COLOR
|
||||
#ifdef SLB_MBLUR_SIGHT_MASK_COLOR_SLOWER
|
||||
float threshold = SLB_MBLUR_SIGHT_MASK_COLOR_SLOWER_THRESHOLD;
|
||||
float mask = 0.0;
|
||||
|
||||
float2 dirs[9] = {
|
||||
float2( 0, 0),
|
||||
float2( 1, 0),
|
||||
float2( 0, 1),
|
||||
float2(-1, 0),
|
||||
float2( 0, -1),
|
||||
float2( 0.7071, 0.7071),
|
||||
float2( 0.7071, -0.7071),
|
||||
float2(-0.7071, -0.7071),
|
||||
float2(-0.7071, 0.7071)
|
||||
};
|
||||
|
||||
SLB_UNROLL(9)
|
||||
for(int i = 0; i < 9; i++) {
|
||||
float3 s;
|
||||
|
||||
if(i == 0) {
|
||||
s = img;
|
||||
} else {
|
||||
float2 offset = dirs[i]*1.5/1000.0/aspect;
|
||||
s = SLB_Screen_GetImage(tc + offset, iSample);
|
||||
}
|
||||
|
||||
float3 hsv = SLB_RGB_To_HSV(s);
|
||||
mask += float(hsv.y > threshold && hsv.z > threshold);
|
||||
mask += float(abs(hsv.x - 0.406) < 0.01 && hsv.y > 0.5 && hsv.z > 0.5);
|
||||
// mask += float(abs(hsv.x - 0.986) < 0.005 && hsv.y > 0.5 && hsv.z > 0.5);
|
||||
}
|
||||
|
||||
return 1.0 - len * saturate(mask);
|
||||
#else
|
||||
float threshold = SLB_MBLUR_SIGHT_MASK_COLOR_THRESHOLD;
|
||||
float mask = 0.0;
|
||||
|
||||
mask += step(threshold, img.r - (img.g + img.b));
|
||||
mask += step(threshold, img.g - (img.r + img.b));
|
||||
|
||||
return 1.0 - len * saturate(mask);
|
||||
#endif
|
||||
#else
|
||||
return 1.0 - len;
|
||||
#endif
|
||||
}
|
||||
|
||||
float SLB_MBlur_WeaponMask(float3 pos) {
|
||||
return saturate((length(pos) - SLB_MBLUR_WPN_RADIUS) / SLB_MBLUR_WPN_RADIUS_SMOOTHING);
|
||||
}
|
||||
|
||||
float3 SLB_MBlur(float2 uv, float3 pos, float3 img, float2 pixel_velocity, uint iSample) {
|
||||
float2 aspect = screen_res.x > screen_res.y ? float2(screen_res.x/screen_res.y, 1.) : float2(1., screen_res.y/screen_res.x);
|
||||
|
||||
#ifdef SLB_MBLUR_REVERSED
|
||||
pixel_velocity = -pixel_velocity;
|
||||
#endif
|
||||
|
||||
pixel_velocity *= SLB_MBLUR_LENGTH;
|
||||
float2 pixel_velocity_clamp = abs(normalize(pixel_velocity)) * SLB_MBLUR_CLAMP / aspect;
|
||||
pixel_velocity = clamp(pixel_velocity, -pixel_velocity_clamp, +pixel_velocity_clamp);
|
||||
|
||||
#ifdef SLB_MBLUR_WPN
|
||||
pixel_velocity *= SLB_MBlur_WeaponMask(pos);
|
||||
#endif
|
||||
|
||||
#ifdef SLB_MBLUR_SIGHT_MASK
|
||||
pixel_velocity *= SLB_MBlur_SightMask(uv, img, aspect, iSample);
|
||||
#endif
|
||||
|
||||
/// Accumulate motion blur samples
|
||||
float3 accum = img * 1e-2;
|
||||
float occ = 1e-2;
|
||||
|
||||
uint noise_offset = 0;
|
||||
|
||||
#ifdef SLB_MBLUR_ANIMATED_DITHER
|
||||
noise_offset = SLB_PCG(asuint(timers.y));
|
||||
#endif
|
||||
|
||||
float noise = SLB_PhiNoise2_float(uint2(uv*screen_res.xy) + uint2(noise_offset, noise_offset));
|
||||
#ifdef SLB_MBLUR_DUAL
|
||||
float dither = noise - 0.5;
|
||||
#else
|
||||
float dither = noise;
|
||||
#endif
|
||||
|
||||
float2 p_velocity_orig = pixel_velocity;
|
||||
|
||||
//gimme ze blur
|
||||
SLB_UNROLL(SLB_MBLUR_SAMPLES*2+1)
|
||||
#ifdef SLB_MBLUR_DUAL
|
||||
for (int i = -SLB_MBLUR_SAMPLES; i <= SLB_MBLUR_SAMPLES; i++) {
|
||||
#else
|
||||
for (int i = 0; i <= SLB_MBLUR_SAMPLES*2; i++) {
|
||||
#endif
|
||||
|
||||
if(abs(SLB_MBLUR_CONE_DITHER) > 0.001) {
|
||||
float dither_cone = SLB_R1(noise*1024.0 + float(i)) - 0.5;
|
||||
pixel_velocity = SLB_Rotate2(p_velocity_orig, dither_cone * SLB_MBLUR_CONE_DITHER * SLB_PI);
|
||||
}
|
||||
|
||||
float2 offset;
|
||||
|
||||
offset = pixel_velocity * float(i);
|
||||
offset /= float(SLB_MBLUR_SAMPLES*2+1);
|
||||
offset += pixel_velocity/float(SLB_MBLUR_SAMPLES*2+1) * dither;
|
||||
|
||||
float2 tc = uv + offset;
|
||||
float amount = float((0.0 < tc.x && tc.x < 1.0) && (0.0 < tc.y && tc.y < 1.0)); /// Fix black borders
|
||||
|
||||
if(SLB_MBLUR_SAMPLES == 0) {
|
||||
tc = clamp(tc, 0.0, 0.999);
|
||||
amount = 1.0;
|
||||
}
|
||||
|
||||
float3 simg = SLB_Screen_GetImage(tc, iSample).rgb;
|
||||
|
||||
if(i != 0) {
|
||||
#ifdef SLB_MBLUR_WPN
|
||||
float3 spos = SLB_Screen_GetPosition(tc, iSample).xyz;
|
||||
|
||||
/// Fix sky ghosting caused by infinite depth value (KD)
|
||||
spos.z = is_sky(spos.z) > 0.5 ? 10000.0 : spos.z;
|
||||
|
||||
amount *= SLB_MBlur_WeaponMask(spos);
|
||||
#endif
|
||||
|
||||
#ifdef SLB_MBLUR_SIGHT_MASK
|
||||
amount *= SLB_MBlur_SightMask(tc, simg, aspect, iSample);
|
||||
#endif
|
||||
}
|
||||
|
||||
accum += simg * amount;
|
||||
|
||||
occ += amount;
|
||||
}
|
||||
|
||||
accum /= occ + 1e-6; /// fix Nans
|
||||
|
||||
return accum;
|
||||
}
|
||||
|
||||
#endif // SLB_MOTION_BLUR_H
|
||||
@@ -0,0 +1,27 @@
|
||||
#ifndef SLB_MOTION_BLUR_SETTINGS_H
|
||||
#define SLB_MOTION_BLUR_SETTINGS_H
|
||||
|
||||
#define SLB_MBLUR_SAMPLES int(4) /// Blur samples /// default int(4) /// vanilla int(6)
|
||||
#define SLB_MBLUR_CLAMP float(0.1) /// Max blur length /// default float(0.1) /// vanilla float(0.012)
|
||||
#define SLB_MBLUR_LENGTH float(120) /// Blur length /// default float(120) /// vanilla float(12)
|
||||
|
||||
#define SLB_MBLUR_ANIMATED_DITHER /// Comment to disable
|
||||
#define SLB_MBLUR_CONE_DITHER float(0.0) /// Cone like dithering aka blurriness // default float(0.0)
|
||||
|
||||
#define SLB_MBLUR_DUAL /// Blur in both directions. Comment to disable
|
||||
#define SLB_MBLUR_REVERSED /// Reverse blur direction. Comment to disable
|
||||
|
||||
#define SLB_MBLUR_WPN /// Disabled motion blur for weapon and hud. Comment to disable
|
||||
#define SLB_MBLUR_WPN_RADIUS float(1.3) /// default float(1.3)
|
||||
#define SLB_MBLUR_WPN_RADIUS_SMOOTHING float(1.0) /// default float(1.0)
|
||||
|
||||
#define SLB_MBLUR_SIGHT_MASK /// Try its best to detect reticle but too many false positives
|
||||
#define SLB_MBLUR_SIGHT_MASK_SIZE float(5.0) /// Radius for searching /// default float(5.0)
|
||||
|
||||
#define SLB_MBLUR_SIGHT_MASK_COLOR /// Color based sight detection
|
||||
#define SLB_MBLUR_SIGHT_MASK_COLOR_THRESHOLD float(0.5) /// Threshold for masking /// default float(0.5)
|
||||
|
||||
// #define SLB_MBLUR_SIGHT_MASK_COLOR_SLOWER /// Slower and maybe better
|
||||
#define SLB_MBLUR_SIGHT_MASK_COLOR_SLOWER_THRESHOLD float(0.8) /// Threshold for masking /// default float(0.8)
|
||||
|
||||
#endif /// SLB_MOTION_BLUR_SETTINGS_H
|
||||
@@ -0,0 +1,487 @@
|
||||
#ifndef SLB_SHADOW_H
|
||||
#define SLB_SHADOW_H
|
||||
|
||||
#include "slb_common.h"
|
||||
#include "slb_shadow_settings.h"
|
||||
|
||||
#ifdef SLB_GLSL /// As always dummy
|
||||
float SLB_Shadow_Load(float2 uv) {
|
||||
return texelFetch(s_smap, int2(frac(uv)*float(SMAP_size)), 0).x;
|
||||
}
|
||||
|
||||
float SLB_Shadow_LoadOffset(float2 uv, int2 offset) {
|
||||
return texelFetch(s_smap, int2(frac(uv)*float(SMAP_size)) + offset, 0).x;
|
||||
}
|
||||
|
||||
float SLB_Shadow_SampleCmp(float2 uv, float z) {
|
||||
return textureLod(s_smap, uv, 0.0).x;
|
||||
}
|
||||
|
||||
float4 SLB_Shadow_Gather(float2 uv) {
|
||||
return textureGather(s_smap, uv);
|
||||
}
|
||||
|
||||
float4 SLB_Shadow_GatherOffset(float2 uv, int2 offset) {
|
||||
return textureGatherOffset(s_smap, uv, offset);
|
||||
}
|
||||
|
||||
float4 SLB_Shadow_GatherCmp(float2 uv, float z) {
|
||||
return textureGather(s_smap, uv);
|
||||
}
|
||||
#else
|
||||
float SLB_Shadow_Load(float2 uv) {
|
||||
return s_smap.Load(int3(uv*float(SMAP_size) - 0.25, 0));
|
||||
}
|
||||
|
||||
float SLB_Shadow_LoadOffset(float2 uv, int2 offset) {
|
||||
return s_smap.Load(int3(uv*float(SMAP_size) - 0.25, 0), offset);
|
||||
}
|
||||
|
||||
float SLB_Shadow_SampleCmp(float2 uv, float z) {
|
||||
return s_smap.SampleCmpLevelZero(smp_smap, uv, z).x;
|
||||
}
|
||||
|
||||
float4 SLB_Shadow_Gather(float2 uv) {
|
||||
return s_smap.Gather(smp_nofilter, uv);
|
||||
}
|
||||
|
||||
float4 SLB_Shadow_GatherOffset(float2 uv, int2 offset) {
|
||||
return s_smap.Gather(smp_nofilter, uv, offset);
|
||||
}
|
||||
|
||||
float4 SLB_Shadow_GatherCmp(float2 uv, float z) {
|
||||
return s_smap.GatherCmp(smp_smap, uv, z);
|
||||
}
|
||||
#endif
|
||||
|
||||
float SLB_Shadow_Linear(float4 tc) {
|
||||
return SLB_Shadow_SampleCmp(tc.xy, tc.z);
|
||||
}
|
||||
|
||||
/// Taken from https://www.shadertoy.com/view/XsfGDn
|
||||
float SLB_Shadow_Nice(float4 tc) {
|
||||
float2 uv = tc.xy;
|
||||
float2 textureResolution = float2(float(SMAP_size), float(SMAP_size));
|
||||
|
||||
uv = uv*textureResolution + 0.5;
|
||||
|
||||
float2 iuv = floor(uv);
|
||||
float2 fuv = frac(uv);
|
||||
|
||||
uv = iuv + fuv*fuv*(3.0-2.0*fuv);
|
||||
uv = (uv - 0.5)/textureResolution;
|
||||
|
||||
return SLB_Shadow_SampleCmp(uv, tc.z);
|
||||
}
|
||||
|
||||
/// Taken from http://www.java-gaming.org/index.php?topic=35123.0
|
||||
float SLB_Shadow_Bicubic(float4 tc) {
|
||||
float2 texCoords = tc.xy;
|
||||
|
||||
float2 texSize = float2(float(SMAP_size), float(SMAP_size));
|
||||
float2 invTexSize = 1.0 / texSize;
|
||||
|
||||
texCoords = texCoords * texSize - 0.5;
|
||||
|
||||
float2 fxy = frac(texCoords);
|
||||
texCoords -= fxy;
|
||||
|
||||
float4 xcubic = SLB_Cubic_For_Bicubic(fxy.x);
|
||||
float4 ycubic = SLB_Cubic_For_Bicubic(fxy.y);
|
||||
|
||||
float4 c = texCoords.xxyy + float2(-0.5, +1.5).xyxy;
|
||||
|
||||
float4 s = float4(xcubic.xz + xcubic.yw, ycubic.xz + ycubic.yw);
|
||||
float4 offset = c + float4(xcubic.yw, ycubic.yw) / s;
|
||||
|
||||
offset *= invTexSize.xxyy;
|
||||
|
||||
float sample0 = SLB_Shadow_SampleCmp(offset.xz, tc.z);
|
||||
float sample1 = SLB_Shadow_SampleCmp(offset.yz, tc.z);
|
||||
float sample2 = SLB_Shadow_SampleCmp(offset.xw, tc.z);
|
||||
float sample3 = SLB_Shadow_SampleCmp(offset.yw, tc.z);
|
||||
|
||||
float sx = s.x / (s.x + s.y);
|
||||
float sy = s.z / (s.z + s.w);
|
||||
|
||||
return lerp(lerp(sample3, sample2, sx), lerp(sample1, sample0, sx), sy);
|
||||
}
|
||||
|
||||
#if 0
|
||||
#include "slb_shadow_normal.h"
|
||||
#endif
|
||||
|
||||
#include "slb_shadow_optimized_pcf.h"
|
||||
|
||||
float SLB_Shadow_CHS(float4 tc, float noise) {
|
||||
float light_width = slb_shadow_settings_pcss_light_width;
|
||||
|
||||
float average_blocker_depth = 0.0;
|
||||
|
||||
{
|
||||
float average_blocker_div = 1e-6;
|
||||
|
||||
float blocker_count = 0.0;
|
||||
int blocker_count_max = 0;
|
||||
|
||||
for(int i = -3; i <= 3; i += 2) {
|
||||
for(int j = -3; j <= 3; j += 2) {
|
||||
float4 gather = SLB_Shadow_GatherOffset(tc.xy, int2(i, j));
|
||||
float4 weight = max(float4(0.0,0.0,0.0,0.0), tc.z - gather);
|
||||
weight /= weight + 0.025;
|
||||
#ifdef SLB_GLSL
|
||||
weight = 1.0 - gather;
|
||||
#endif
|
||||
average_blocker_depth += dot(gather, weight);
|
||||
average_blocker_div += dot(weight, float4(1.0, 1.0, 1.0, 1.0));
|
||||
blocker_count += float(weight.x > 1e-6) + float(weight.y > 1e-6)
|
||||
+ float(weight.z > 1e-6) + float(weight.w > 1e-6);
|
||||
blocker_count_max += 4;
|
||||
}
|
||||
}
|
||||
|
||||
SLB_BRANCH
|
||||
if(blocker_count < 0.5 || blocker_count > float(blocker_count_max) - 0.5) {
|
||||
#if 1 /// Toggles debug
|
||||
return 1.0 - blocker_count/float(blocker_count_max);
|
||||
#else
|
||||
return 0.0; } else { return 100.0;
|
||||
#endif
|
||||
}
|
||||
|
||||
average_blocker_depth /= average_blocker_div;
|
||||
}
|
||||
|
||||
float penumbra_size = light_width * (tc.z - average_blocker_depth)/average_blocker_depth;
|
||||
|
||||
float lightness = SLB_Shadow_OptimizedPCF(tc);
|
||||
|
||||
float scurve = clamp(3.0/float(SMAP_size)/penumbra_size, 1.0, 100.0);
|
||||
lightness = saturate((lightness*scurve + 0.5) - 0.5*scurve);
|
||||
|
||||
return lightness;
|
||||
}
|
||||
|
||||
float SLB_Shadow_VogelFilter(float4 tc, float noise, float filter_size, float filter_size_real, const int filter_samples, bool linear_sample, float radial_bias) {
|
||||
const float compare_window = 0.0001;
|
||||
|
||||
float lightness = 0.0;
|
||||
float div = 1e-6; /// Migitate division by zero
|
||||
|
||||
if(linear_sample) {
|
||||
float2x2 rot_mat = SLB_Rotate2Matrix(noise*SLB_TAU);
|
||||
|
||||
SLB_UNROLL(filter_samples)
|
||||
for(int i = 0; i < filter_samples; i++) {
|
||||
float2 offset = SLB_VogelDisk_Sample(i, filter_samples);
|
||||
float offset_length = length(offset);
|
||||
offset = mul(offset, rot_mat);
|
||||
offset *= filter_size;
|
||||
|
||||
float biased_z = tc.z - radial_bias*offset_length*filter_size_real;
|
||||
|
||||
float2 uv = tc.xy + offset;
|
||||
float notblocker;
|
||||
|
||||
{
|
||||
float4 depths = SLB_Shadow_Gather(uv);
|
||||
float4 notblockers = saturate((depths - biased_z + compare_window)/compare_window);
|
||||
#ifdef SLB_GLSL
|
||||
notblockers = depths;
|
||||
#endif
|
||||
|
||||
float s1 = notblockers.x;
|
||||
float s2 = notblockers.y;
|
||||
float s3 = notblockers.z;
|
||||
float s4 = notblockers.w;
|
||||
|
||||
float2 fract = frac(uv*float(SMAP_size)+0.5);
|
||||
notblocker = lerp(lerp(s4, s3, fract.x), lerp(s1, s2, fract.x), fract.y);
|
||||
|
||||
lightness += notblocker;
|
||||
div += 1.0;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
float2x2 rot_mat = SLB_Rotate2Matrix(noise*SLB_TAU);
|
||||
|
||||
SLB_UNROLL(filter_samples)
|
||||
for(int i = 0; i < filter_samples; i++) {
|
||||
float2 offset = SLB_VogelDisk_Sample(i, filter_samples);
|
||||
float offset_length = length(offset);
|
||||
offset = mul(offset, rot_mat);
|
||||
offset *= filter_size;
|
||||
|
||||
float biased_z = tc.z - radial_bias*offset_length*filter_size_real;
|
||||
|
||||
float2 uv = tc.xy + offset;
|
||||
|
||||
float depth = SLB_Shadow_Load(uv);
|
||||
float notblocker = saturate((depth - biased_z)/compare_window);
|
||||
float weight = float(depth > 1e-6);
|
||||
|
||||
#ifdef SLB_GLSL
|
||||
notblocker = depth;
|
||||
weight = 1.0;
|
||||
#endif
|
||||
|
||||
lightness += notblocker * weight;
|
||||
div += weight;
|
||||
}
|
||||
}
|
||||
|
||||
lightness /= div;
|
||||
return lightness;
|
||||
}
|
||||
|
||||
float SLB_Shadow_PCF(float4 tc, float noise) {
|
||||
SLB_STATIC_CONST int filter_samples = max(1, int(slb_shadow_settings_pcss_filter_samples*slb_shadow_pcss_filter_samples_multiplier));
|
||||
float pcss_size_min = slb_shadow_settings_pcss_size_min / float(SMAP_size) * slb_shadow_pcss_size_min_multiplier;
|
||||
float filter_size = pcss_size_min;
|
||||
|
||||
#if defined(SLB_SHADOW_SPOT)
|
||||
SLB_STATIC_CONST float radial_bias = 2.0;
|
||||
#elif defined(SLB_SHADOW_OMNI)
|
||||
SLB_STATIC_CONST float radial_bias = 1.0;
|
||||
#else
|
||||
SLB_STATIC_CONST float radial_bias = 0.3;
|
||||
#endif
|
||||
|
||||
float lightness = SLB_Shadow_VogelFilter(tc, noise, filter_size, filter_size/2.0, filter_samples, true, radial_bias);
|
||||
|
||||
lightness = SLB_QuarticRational1D(lightness);
|
||||
|
||||
return lightness;
|
||||
}
|
||||
|
||||
float SLB_Shadow_VogelCHS(float4 tc, float noise) {
|
||||
SLB_STATIC_CONST int filter_samples = max(1, int(slb_shadow_settings_pcss_filter_samples*slb_shadow_pcss_filter_samples_multiplier));
|
||||
SLB_STATIC_CONST float light_width = slb_shadow_settings_pcss_light_width;
|
||||
float pcss_size_min = slb_shadow_settings_pcss_size_min / float(SMAP_size) * slb_shadow_pcss_size_min_multiplier;
|
||||
float filter_size = pcss_size_min;
|
||||
|
||||
SLB_STATIC_CONST int biases = 4;
|
||||
const float compare_window = 0.0001;
|
||||
|
||||
const float filter_bias[biases] = {0.0, 0.1, 0.2, 0.3};
|
||||
|
||||
float average_blocker_depth = 0.0;
|
||||
float average_blocker_div = 1e-6; /// Migitate division by zero
|
||||
|
||||
float lightnesses[biases] = {0.0, 0.0, 0.0, 0.0};
|
||||
float lightnesses_div[biases] = {1e-6, 1e-6, 1e-6, 1e-6}; /// Migitate division by zero
|
||||
|
||||
float2x2 rot_mat = SLB_Rotate2Matrix(noise*SLB_TAU);
|
||||
|
||||
SLB_UNROLL(filter_samples)
|
||||
for(int i = 0; i < filter_samples; i++) {
|
||||
float2 offset = SLB_VogelDisk_Sample(i, filter_samples);
|
||||
float offset_length = length(offset);
|
||||
offset = mul(offset, rot_mat);
|
||||
offset *= filter_size;
|
||||
|
||||
float2 uv = tc.xy + offset;
|
||||
float4 depths = SLB_Shadow_Gather(uv);
|
||||
|
||||
SLB_UNROLL(biases)
|
||||
for(int j = 0; j < biases; j++) {
|
||||
float biased_z = tc.z - filter_bias[j]*offset_length*filter_size;
|
||||
{
|
||||
float4 notblockers = saturate((depths - biased_z + compare_window)/compare_window);
|
||||
#ifdef SLB_GLSL
|
||||
notblockers = depths;
|
||||
#endif
|
||||
|
||||
float s1 = notblockers.x;
|
||||
float s2 = notblockers.y;
|
||||
float s3 = notblockers.z;
|
||||
float s4 = notblockers.w;
|
||||
|
||||
float2 fract = frac(uv*float(SMAP_size)+0.5);
|
||||
float notblocker = lerp(lerp(s4, s3, fract.x), lerp(s1, s2, fract.x), fract.y);
|
||||
|
||||
lightnesses[j] += notblocker;
|
||||
lightnesses_div[j] += 1.0;
|
||||
}
|
||||
{
|
||||
float4 blockers = float4(float(biased_z - 0.0001*float(j-1) > depths.x),
|
||||
float(biased_z - 0.0001*float(j-1) > depths.y),
|
||||
float(biased_z - 0.0001*float(j-1) > depths.z),
|
||||
float(biased_z - 0.0001*float(j-1) > depths.w));
|
||||
|
||||
average_blocker_depth += dot(depths, blockers);
|
||||
average_blocker_div += dot(float4(1.0,1.0,1.0,1.0), blockers);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
SLB_UNROLL(biases)
|
||||
for(int i = 0; i < biases; i++) {
|
||||
lightnesses[i] /= lightnesses_div[i];
|
||||
}
|
||||
|
||||
average_blocker_depth /= average_blocker_div;
|
||||
|
||||
float penumbra_size = light_width * (tc.z - average_blocker_depth)/average_blocker_depth;
|
||||
|
||||
/// Choose bias
|
||||
float lightness = lightnesses[0];
|
||||
SLB_UNROLL(biases-1)
|
||||
for(int i = 1; i < biases; i++) {
|
||||
if(penumbra_size > float(i)/float(biases-1)*filter_size) {
|
||||
lightness = lightnesses[i];
|
||||
}
|
||||
}
|
||||
|
||||
float scurve = clamp(filter_size/penumbra_size, 1.0, 2.0*float(filter_samples)/(filter_size*float(SMAP_size)));
|
||||
lightness = saturate((lightness*scurve + 0.5) - 0.5*scurve);
|
||||
|
||||
return lightness;
|
||||
}
|
||||
|
||||
float SLB_Shadow_PCSS(float4 tc, float noise) {
|
||||
/// Settings
|
||||
SLB_STATIC_CONST int blocker_samples = max(1, int(slb_shadow_settings_pcss_blocker_samples * slb_shadow_pcss_blocker_samples_multiplier));
|
||||
SLB_STATIC_CONST int filter_samples = max(1, int(slb_shadow_settings_pcss_filter_samples * slb_shadow_pcss_filter_samples_multiplier));
|
||||
SLB_STATIC_CONST int filter_small_samples = max(1, int(slb_shadow_settings_pcss_filter_small_samples * slb_shadow_pcss_filter_small_samples_multiplier));
|
||||
float pcss_size = slb_shadow_settings_pcss_size / float(2048) * slb_shadow_pcss_size_multiplier;
|
||||
float pcss_size_min = slb_shadow_settings_pcss_size_min / float(SMAP_size) * slb_shadow_pcss_size_min_multiplier;
|
||||
float light_width = slb_shadow_settings_pcss_light_width;
|
||||
|
||||
float filter_size_real;
|
||||
float filter_size;
|
||||
|
||||
#if defined(SLB_SHADOW_SPOT)
|
||||
SLB_STATIC_CONST float radial_bias = 2.0;
|
||||
#elif defined(SLB_SHADOW_OMNI)
|
||||
SLB_STATIC_CONST float radial_bias = 1.0;
|
||||
#else
|
||||
SLB_STATIC_CONST float radial_bias = 0.3;
|
||||
#endif
|
||||
|
||||
{
|
||||
/// Blocker search
|
||||
float blocker_size = pcss_size;
|
||||
|
||||
float average_blocker_depth = tc.z * 1e-6;
|
||||
float average_blocker_div = 1e-6; /// Migitate division by zero
|
||||
|
||||
float2x2 rot_mat = SLB_Rotate2Matrix(noise*SLB_TAU);
|
||||
|
||||
SLB_UNROLL(blocker_samples)
|
||||
for(int i = 0; i < blocker_samples; i++) {
|
||||
float2 offset = SLB_VogelDisk_Sample(i, blocker_samples);
|
||||
offset *= sqrt(length(offset));
|
||||
float offset_length = length(offset);
|
||||
offset = mul(offset, rot_mat);
|
||||
offset *= blocker_size;
|
||||
|
||||
float depth = SLB_Shadow_Load(tc.xy + offset);
|
||||
|
||||
float biased_z = tc.z - radial_bias*offset_length*blocker_size;
|
||||
|
||||
float blocker = float(biased_z > depth && depth > 1e-6);
|
||||
|
||||
blocker *= 1.0/(offset_length + 1e-9);
|
||||
|
||||
average_blocker_depth += depth * blocker;
|
||||
average_blocker_div += blocker;
|
||||
}
|
||||
|
||||
average_blocker_depth /= average_blocker_div;
|
||||
|
||||
/// Calculate penumbra size
|
||||
filter_size = light_width * (tc.z - average_blocker_depth)/average_blocker_depth;
|
||||
|
||||
#if defined(SLB_SHADOW_SPOT) || defined(SLB_SHADOW_OMNI)
|
||||
filter_size *= 2 - average_blocker_depth;
|
||||
#endif
|
||||
|
||||
#ifdef SLB_GLSL
|
||||
filter_size += 1;
|
||||
#endif
|
||||
|
||||
filter_size = min(pcss_size, filter_size);
|
||||
|
||||
#ifdef SLB_GLSL
|
||||
// filter_size *= frac(timers.y/10.0);
|
||||
// filter_size *= cos(timers.y/5.0)*0.5 + 0.5;
|
||||
// filter_size *= abs(frac(timers.y/2.0/8.0)*2.0 - 1.0)*1.0 + 0.0;
|
||||
// filter_size *= noise;
|
||||
// filter_size *= 0.0;
|
||||
// if(sin(tc.x*100.0) > 0.5) {
|
||||
// filter_size = 2.9/float(SMAP_size);
|
||||
// } else {
|
||||
// filter_size = 3.000/float(SMAP_size);
|
||||
// }
|
||||
#endif
|
||||
|
||||
filter_size_real = max(pcss_size_min/1000.0, filter_size);
|
||||
filter_size = max(pcss_size_min, filter_size);
|
||||
}
|
||||
|
||||
float lightness;
|
||||
|
||||
SLB_BRANCH
|
||||
if(filter_size_real < pcss_size_min) {
|
||||
if (slb_shadow_pcss_early_quit) {
|
||||
float lightness = SLB_Shadow_VogelFilter(tc, noise, filter_size*1.25, filter_size_real*1.25, 8, false, radial_bias);
|
||||
float scurve = clamp(filter_size/filter_size_real, 1.0, 2/(pcss_size_min*float(SMAP_size)));
|
||||
lightness = saturate((lightness*scurve + 0.5) - 0.5*scurve);
|
||||
|
||||
SLB_BRANCH
|
||||
if(abs(lightness - 0.5) > 0.45)
|
||||
#if 1
|
||||
{ return lightness; }
|
||||
#else
|
||||
{ return 0.0; } else { return 10.0; }
|
||||
#endif
|
||||
}
|
||||
|
||||
lightness = SLB_Shadow_VogelFilter(tc, noise, filter_size, filter_size_real, filter_small_samples, true, radial_bias);
|
||||
} else {
|
||||
lightness = SLB_Shadow_VogelFilter(tc, noise, filter_size, filter_size_real, filter_samples, false, radial_bias);
|
||||
}
|
||||
|
||||
float scurve = clamp(filter_size/filter_size_real, 1.0, 2.0*float(filter_small_samples)/(pcss_size_min*float(SMAP_size)));
|
||||
lightness = saturate((lightness*scurve + 0.5) - 0.5*scurve);
|
||||
|
||||
return lightness;
|
||||
}
|
||||
|
||||
float SLB_Shadow(float4 tc, float2 pos2d) {
|
||||
float noise;
|
||||
if(slb_shadow_animated_noise) {
|
||||
uint noise_offset = SLB_PCG(asuint(timers.y));
|
||||
uint2 noise_uv = uint2(pos2d+0.5) + uint2(noise_offset, noise_offset);
|
||||
noise = SLB_PhiNoise2_float(noise_uv);
|
||||
} else {
|
||||
noise = SLB_Morton_OwenHash4_Bluenoise_float(uint2(pos2d+0.5));
|
||||
}
|
||||
|
||||
tc.xyz /= tc.w;
|
||||
|
||||
float lightness = 1.0;
|
||||
|
||||
if(slb_shadow_settings_method == slb_shadow_method_linear) {
|
||||
lightness = SLB_Shadow_Linear(tc);
|
||||
} else if (slb_shadow_settings_method == slb_shadow_method_nice) {
|
||||
lightness = SLB_Shadow_Nice(tc);
|
||||
} else if (slb_shadow_settings_method == slb_shadow_method_bicubic) {
|
||||
lightness = SLB_Shadow_Bicubic(tc);
|
||||
} else if (slb_shadow_settings_method == slb_shadow_method_optimized_pcf) {
|
||||
lightness = SLB_CubicRational1D(SLB_Shadow_OptimizedPCF(tc));
|
||||
} else if (slb_shadow_settings_method == slb_shadow_method_chs) {
|
||||
lightness = SLB_Shadow_CHS(tc, noise);
|
||||
} else if (slb_shadow_settings_method == slb_shadow_method_pcf) {
|
||||
lightness = SLB_Shadow_PCF(tc, noise);
|
||||
} else if (slb_shadow_settings_method == slb_shadow_method_vogel_chs) {
|
||||
lightness = SLB_Shadow_VogelCHS(tc, noise);
|
||||
} else if (slb_shadow_settings_method == slb_shadow_method_pcss) {
|
||||
lightness = SLB_Shadow_PCSS(tc, noise);
|
||||
}
|
||||
|
||||
return lightness;
|
||||
}
|
||||
|
||||
#endif /// SLB_SHADOW_H
|
||||
@@ -0,0 +1,63 @@
|
||||
#ifndef SLB_SHADOW_NORMAL_H
|
||||
#define SLB_SHADOW_NORMAL_H
|
||||
|
||||
float3 SLB_Shadow_ViewSpacePosAtScreenUV(float2 pos) {
|
||||
return float3(pos.x, pos.y, SLB_Shadow_Sample(pos)); // * float2(float(SMAP_size), 1.0).xxy;
|
||||
}
|
||||
|
||||
float3 SLB_Shadow_Normal(float2 vpos) {
|
||||
float2 texelSize = float2(1.0, 1.0)/float2(float(SMAP_size), float(SMAP_size));
|
||||
// screen uv from vpos
|
||||
float2 uv = floor(vpos/texelSize)*texelSize;
|
||||
|
||||
// current pixel's depth
|
||||
float c = SLB_Shadow_Sample(uv);
|
||||
|
||||
// get current pixel's view space position
|
||||
float3 viewSpacePos_c = SLB_Shadow_ViewSpacePosAtScreenUV(uv);
|
||||
|
||||
// get view space position at 1 pixel offsets in each major direction
|
||||
float3 viewSpacePos_l = SLB_Shadow_ViewSpacePosAtScreenUV(uv + float2(-1.0, 0.0) * texelSize);
|
||||
float3 viewSpacePos_r = SLB_Shadow_ViewSpacePosAtScreenUV(uv + float2( 1.0, 0.0) * texelSize);
|
||||
float3 viewSpacePos_d = SLB_Shadow_ViewSpacePosAtScreenUV(uv + float2( 0.0,-1.0) * texelSize);
|
||||
float3 viewSpacePos_u = SLB_Shadow_ViewSpacePosAtScreenUV(uv + float2( 0.0, 1.0) * texelSize);
|
||||
|
||||
// get the difference between the current and each offset position
|
||||
float3 l = viewSpacePos_c - viewSpacePos_l;
|
||||
float3 r = viewSpacePos_r - viewSpacePos_c;
|
||||
float3 d = viewSpacePos_c - viewSpacePos_d;
|
||||
float3 u = viewSpacePos_u - viewSpacePos_c;
|
||||
|
||||
// get depth values at 1 & 2 pixels offsets from current along the horizontal axis
|
||||
float4 H = float4(
|
||||
SLB_Shadow_Sample(uv + float2(-1.0, 0.0) * texelSize),
|
||||
SLB_Shadow_Sample(uv + float2( 1.0, 0.0) * texelSize),
|
||||
SLB_Shadow_Sample(uv + float2(-2.0, 0.0) * texelSize),
|
||||
SLB_Shadow_Sample(uv + float2( 2.0, 0.0) * texelSize)
|
||||
);
|
||||
|
||||
// get depth values at 1 & 2 pixels offsets from current along the vertical axis
|
||||
float4 V = float4(
|
||||
SLB_Shadow_Sample(uv + float2(0.0,-1.0) * texelSize),
|
||||
SLB_Shadow_Sample(uv + float2(0.0, 1.0) * texelSize),
|
||||
SLB_Shadow_Sample(uv + float2(0.0,-2.0) * texelSize),
|
||||
SLB_Shadow_Sample(uv + float2(0.0, 2.0) * texelSize)
|
||||
);
|
||||
|
||||
// current pixel's depth difference from slope of offset depth samples
|
||||
// differs from original article because we're using non-linear depth values
|
||||
// see article's comments
|
||||
float2 he = abs((2 * H.xy - H.zw) - c);
|
||||
float2 ve = abs((2 * V.xy - V.zw) - c);
|
||||
|
||||
// pick horizontal and vertical diff with the smallest depth difference from slopes
|
||||
float3 hDeriv = he.x < he.y ? l : r;
|
||||
float3 vDeriv = ve.x < ve.y ? d : u;
|
||||
|
||||
// get view space normal from the cross product of the best derivatives
|
||||
float3 viewNormal = normalize(cross(hDeriv, vDeriv));
|
||||
|
||||
return viewNormal;
|
||||
}
|
||||
|
||||
#endif /// SLB_SHADOW_NORMAL_H
|
||||
@@ -0,0 +1,152 @@
|
||||
#ifndef SLB_SHADOW_OPTIMIZED_PCF_H
|
||||
#define SLB_SHADOW_OPTIMIZED_PCF_H
|
||||
|
||||
/// Source https://github.com/TheRealMJP/Shadows/blob/master/Shadows/Mesh.hlsl
|
||||
|
||||
float SLB_Shadow_OptimizedPCF_Sample(in float2 base_uv, in float u, in float v, in float depth) {
|
||||
float2 shadowMapSize = float2(int2(SMAP_size, SMAP_size));
|
||||
float2 shadowMapSizeInv = 1.0 / shadowMapSize;
|
||||
|
||||
float2 uv = base_uv + float2(u, v) * shadowMapSizeInv;
|
||||
|
||||
const float compare_window = 0.0001;
|
||||
{
|
||||
float4 depths = SLB_Shadow_Gather(uv);
|
||||
float4 notblockers = saturate((depths - depth + compare_window)/compare_window);
|
||||
#ifdef SLB_GLSL
|
||||
notblockers = depths;
|
||||
#endif
|
||||
|
||||
float s1 = notblockers.x;
|
||||
float s2 = notblockers.y;
|
||||
float s3 = notblockers.z;
|
||||
float s4 = notblockers.w;
|
||||
|
||||
float2 fract = frac(uv*float(SMAP_size)+0.5);
|
||||
float notblocker = lerp(lerp(s4, s3, fract.x), lerp(s1, s2, fract.x), fract.y);
|
||||
|
||||
return notblocker;
|
||||
}
|
||||
}
|
||||
|
||||
float SLB_Shadow_OptimizedPCF(float4 tc) {
|
||||
const int filter_size = 7;
|
||||
|
||||
float2 shadowMapSize = float2(int2(SMAP_size, SMAP_size));
|
||||
float2 shadowMapSizeInv = 1.0 / shadowMapSize;
|
||||
float2 shadowPos = tc.xy;
|
||||
float lightDepth = tc.z;
|
||||
|
||||
float2 uv = shadowPos.xy * shadowMapSize; // 1 unit - 1 texel
|
||||
|
||||
float2 base_uv;
|
||||
base_uv.x = floor(uv.x + 0.5);
|
||||
base_uv.y = floor(uv.y + 0.5);
|
||||
|
||||
float s = (uv.x + 0.5 - base_uv.x);
|
||||
float t = (uv.y + 0.5 - base_uv.y);
|
||||
|
||||
base_uv -= float2(0.5, 0.5);
|
||||
base_uv *= shadowMapSizeInv;
|
||||
|
||||
float sum = 0;
|
||||
|
||||
if(filter_size == 2) {
|
||||
return SLB_Shadow_SampleCmp(shadowPos.xy, lightDepth);
|
||||
} else if(filter_size == 3) {
|
||||
float uw0 = (3 - 2 * s);
|
||||
float uw1 = (1 + 2 * s);
|
||||
|
||||
float u0 = (2 - s) / uw0 - 1;
|
||||
float u1 = s / uw1 + 1;
|
||||
|
||||
float vw0 = (3 - 2 * t);
|
||||
float vw1 = (1 + 2 * t);
|
||||
|
||||
float v0 = (2 - t) / vw0 - 1;
|
||||
float v1 = t / vw1 + 1;
|
||||
|
||||
sum += uw0 * vw0 * SLB_Shadow_OptimizedPCF_Sample(base_uv, u0, v0, lightDepth);
|
||||
sum += uw1 * vw0 * SLB_Shadow_OptimizedPCF_Sample(base_uv, u1, v0, lightDepth);
|
||||
sum += uw0 * vw1 * SLB_Shadow_OptimizedPCF_Sample(base_uv, u0, v1, lightDepth);
|
||||
sum += uw1 * vw1 * SLB_Shadow_OptimizedPCF_Sample(base_uv, u1, v1, lightDepth);
|
||||
|
||||
return sum * 1.0f / 16;
|
||||
} else if(filter_size == 5) {
|
||||
float uw0 = (4 - 3 * s);
|
||||
float uw1 = 7;
|
||||
float uw2 = (1 + 3 * s);
|
||||
|
||||
float u0 = (3 - 2 * s) / uw0 - 2;
|
||||
float u1 = (3 + s) / uw1;
|
||||
float u2 = s / uw2 + 2;
|
||||
|
||||
float vw0 = (4 - 3 * t);
|
||||
float vw1 = 7;
|
||||
float vw2 = (1 + 3 * t);
|
||||
|
||||
float v0 = (3 - 2 * t) / vw0 - 2;
|
||||
float v1 = (3 + t) / vw1;
|
||||
float v2 = t / vw2 + 2;
|
||||
|
||||
sum += uw0 * vw0 * SLB_Shadow_OptimizedPCF_Sample(base_uv, u0, v0, lightDepth);
|
||||
sum += uw1 * vw0 * SLB_Shadow_OptimizedPCF_Sample(base_uv, u1, v0, lightDepth);
|
||||
sum += uw2 * vw0 * SLB_Shadow_OptimizedPCF_Sample(base_uv, u2, v0, lightDepth);
|
||||
|
||||
sum += uw0 * vw1 * SLB_Shadow_OptimizedPCF_Sample(base_uv, u0, v1, lightDepth);
|
||||
sum += uw1 * vw1 * SLB_Shadow_OptimizedPCF_Sample(base_uv, u1, v1, lightDepth);
|
||||
sum += uw2 * vw1 * SLB_Shadow_OptimizedPCF_Sample(base_uv, u2, v1, lightDepth);
|
||||
|
||||
sum += uw0 * vw2 * SLB_Shadow_OptimizedPCF_Sample(base_uv, u0, v2, lightDepth);
|
||||
sum += uw1 * vw2 * SLB_Shadow_OptimizedPCF_Sample(base_uv, u1, v2, lightDepth);
|
||||
sum += uw2 * vw2 * SLB_Shadow_OptimizedPCF_Sample(base_uv, u2, v2, lightDepth);
|
||||
|
||||
return sum * 1.0f / 144;
|
||||
} else if(filter_size == 7) {
|
||||
float uw0 = (5 * s - 6);
|
||||
float uw1 = (11 * s - 28);
|
||||
float uw2 = -(11 * s + 17);
|
||||
float uw3 = -(5 * s + 1);
|
||||
|
||||
float u0 = (4 * s - 5) / uw0 - 3;
|
||||
float u1 = (4 * s - 16) / uw1 - 1;
|
||||
float u2 = -(7 * s + 5) / uw2 + 1;
|
||||
float u3 = -s / uw3 + 3;
|
||||
|
||||
float vw0 = (5 * t - 6);
|
||||
float vw1 = (11 * t - 28);
|
||||
float vw2 = -(11 * t + 17);
|
||||
float vw3 = -(5 * t + 1);
|
||||
|
||||
float v0 = (4 * t - 5) / vw0 - 3;
|
||||
float v1 = (4 * t - 16) / vw1 - 1;
|
||||
float v2 = -(7 * t + 5) / vw2 + 1;
|
||||
float v3 = -t / vw3 + 3;
|
||||
|
||||
sum += uw0 * vw0 * SLB_Shadow_OptimizedPCF_Sample(base_uv, u0, v0, lightDepth);
|
||||
sum += uw1 * vw0 * SLB_Shadow_OptimizedPCF_Sample(base_uv, u1, v0, lightDepth);
|
||||
sum += uw2 * vw0 * SLB_Shadow_OptimizedPCF_Sample(base_uv, u2, v0, lightDepth);
|
||||
sum += uw3 * vw0 * SLB_Shadow_OptimizedPCF_Sample(base_uv, u3, v0, lightDepth);
|
||||
|
||||
sum += uw0 * vw1 * SLB_Shadow_OptimizedPCF_Sample(base_uv, u0, v1, lightDepth);
|
||||
sum += uw1 * vw1 * SLB_Shadow_OptimizedPCF_Sample(base_uv, u1, v1, lightDepth);
|
||||
sum += uw2 * vw1 * SLB_Shadow_OptimizedPCF_Sample(base_uv, u2, v1, lightDepth);
|
||||
sum += uw3 * vw1 * SLB_Shadow_OptimizedPCF_Sample(base_uv, u3, v1, lightDepth);
|
||||
|
||||
sum += uw0 * vw2 * SLB_Shadow_OptimizedPCF_Sample(base_uv, u0, v2, lightDepth);
|
||||
sum += uw1 * vw2 * SLB_Shadow_OptimizedPCF_Sample(base_uv, u1, v2, lightDepth);
|
||||
sum += uw2 * vw2 * SLB_Shadow_OptimizedPCF_Sample(base_uv, u2, v2, lightDepth);
|
||||
sum += uw3 * vw2 * SLB_Shadow_OptimizedPCF_Sample(base_uv, u3, v2, lightDepth);
|
||||
|
||||
sum += uw0 * vw3 * SLB_Shadow_OptimizedPCF_Sample(base_uv, u0, v3, lightDepth);
|
||||
sum += uw1 * vw3 * SLB_Shadow_OptimizedPCF_Sample(base_uv, u1, v3, lightDepth);
|
||||
sum += uw2 * vw3 * SLB_Shadow_OptimizedPCF_Sample(base_uv, u2, v3, lightDepth);
|
||||
sum += uw3 * vw3 * SLB_Shadow_OptimizedPCF_Sample(base_uv, u3, v3, lightDepth);
|
||||
|
||||
return sum * 1.0f / 2704;
|
||||
} else {
|
||||
return 1.0;
|
||||
}
|
||||
}
|
||||
|
||||
#endif /// SLB_SHADOW_OPTIMIZED_PCF_H
|
||||
@@ -0,0 +1,109 @@
|
||||
#ifndef SLB_SHADOW_SETTINGS_H
|
||||
#define SLB_SHADOW_SETTINGS_H
|
||||
|
||||
/// Macro mess
|
||||
#define SLB_SHADOW_SETTINGS_ADD_PRESET(preset, method, pcss_filter_samples, pcss_filter_small_samples, pcss_blocker_samples, pcss_size, pcss_size_min, pcss_light_width) \
|
||||
SLB_STATIC_CONST int slb_shadow_settings_ ## preset ## _method = method; \
|
||||
SLB_STATIC_CONST int slb_shadow_settings_ ## preset ## _pcss_filter_samples = pcss_filter_samples; \
|
||||
SLB_STATIC_CONST int slb_shadow_settings_ ## preset ## _pcss_filter_small_samples = pcss_filter_small_samples; \
|
||||
SLB_STATIC_CONST int slb_shadow_settings_ ## preset ## _pcss_blocker_samples = pcss_blocker_samples; \
|
||||
SLB_STATIC_CONST float slb_shadow_settings_ ## preset ## _pcss_size = pcss_size; \
|
||||
SLB_STATIC_CONST float slb_shadow_settings_ ## preset ## _pcss_size_min = pcss_size_min; \
|
||||
SLB_STATIC_CONST float slb_shadow_settings_ ## preset ## _pcss_light_width = pcss_light_width;
|
||||
|
||||
#define SLB_SHADOW_SETTINGS_APPLY_PRESET(preset) \
|
||||
SLB_STATIC_CONST int slb_shadow_settings_method = slb_shadow_settings_ ## preset ## _method; \
|
||||
SLB_STATIC_CONST int slb_shadow_settings_pcss_filter_samples = slb_shadow_settings_ ## preset ## _pcss_filter_samples; \
|
||||
SLB_STATIC_CONST int slb_shadow_settings_pcss_filter_small_samples = slb_shadow_settings_ ## preset ## _pcss_filter_small_samples; \
|
||||
SLB_STATIC_CONST int slb_shadow_settings_pcss_blocker_samples = slb_shadow_settings_ ## preset ## _pcss_blocker_samples; \
|
||||
SLB_STATIC_CONST float slb_shadow_settings_pcss_size = slb_shadow_settings_ ## preset ## _pcss_size; \
|
||||
SLB_STATIC_CONST float slb_shadow_settings_pcss_size_min = slb_shadow_settings_ ## preset ## _pcss_size_min; \
|
||||
SLB_STATIC_CONST float slb_shadow_settings_pcss_light_width = slb_shadow_settings_ ## preset ## _pcss_light_width;
|
||||
|
||||
/// Enums
|
||||
SLB_STATIC_CONST int slb_shadow_method_linear = 0x252827bd;
|
||||
SLB_STATIC_CONST int slb_shadow_method_nice = 0xeaa1fbca;
|
||||
SLB_STATIC_CONST int slb_shadow_method_bicubic = 0xcb35b7d8;
|
||||
SLB_STATIC_CONST int slb_shadow_method_optimized_pcf = 0xcf7d64d5;
|
||||
SLB_STATIC_CONST int slb_shadow_method_chs = 0x15e654ad;
|
||||
SLB_STATIC_CONST int slb_shadow_method_pcf = 0x92726cc9;
|
||||
SLB_STATIC_CONST int slb_shadow_method_vogel_chs = 0x6f241210;
|
||||
SLB_STATIC_CONST int slb_shadow_method_pcss = 0xa9fa8994;
|
||||
|
||||
SLB_STATIC_CONST float slb_shadow_pcss_filter_gaussian_sigma = 0.5;
|
||||
|
||||
/// Real settings starts here
|
||||
/// slb_shadow_animated_noise: change noise every frame
|
||||
/// slb_shadow_pcss_early_quit: improves performance a bit in synthetic test but idk.
|
||||
SLB_STATIC_CONST bool slb_shadow_animated_noise = false; /// default false
|
||||
SLB_STATIC_CONST bool slb_shadow_pcss_early_quit = false; /// default false
|
||||
SLB_STATIC_CONST float slb_shadow_pcss_filter_samples_multiplier = 1.0; /// default 1.0
|
||||
SLB_STATIC_CONST float slb_shadow_pcss_filter_small_samples_multiplier = 1.0; /// default 1.0
|
||||
SLB_STATIC_CONST float slb_shadow_pcss_blocker_samples_multiplier = 1.0; /// default 1.0
|
||||
SLB_STATIC_CONST float slb_shadow_pcss_size_multiplier = 1.0; /// default 1.0
|
||||
SLB_STATIC_CONST float slb_shadow_pcss_size_min_multiplier = 1.0; /// default 1.0
|
||||
|
||||
/// Explanation:
|
||||
/// sun_near - preset for sun near you
|
||||
/// sun_near - preset for sun far from you
|
||||
/// spot - preset for spot lights e.g. flashlights
|
||||
/// omni - preset for omni lights e.g. some lamps
|
||||
/// fallback - preset for ... rainlayer.ps IDK what it does
|
||||
|
||||
#ifndef SUN_QUALITY /// Low quality
|
||||
|
||||
SLB_SHADOW_SETTINGS_ADD_PRESET(sun_near, slb_shadow_method_bicubic, 16, 16, 16, 8.0, 2.0, 0.1)
|
||||
SLB_SHADOW_SETTINGS_ADD_PRESET(sun_far, slb_shadow_method_bicubic, 16, 16, 16, 8.0, 2.0, 0.1)
|
||||
SLB_SHADOW_SETTINGS_ADD_PRESET(spot, slb_shadow_method_bicubic, 16, 16, 16, 8.0, 2.0, 0.02)
|
||||
SLB_SHADOW_SETTINGS_ADD_PRESET(omni, slb_shadow_method_bicubic, 16, 16, 16, 8.0, 2.0, 0.02)
|
||||
SLB_SHADOW_SETTINGS_ADD_PRESET(fallback, slb_shadow_method_bicubic, 16, 16, 16, 8.0, 2.0, 0.1)
|
||||
|
||||
#elif SUN_QUALITY==1 /// medium quality
|
||||
|
||||
SLB_SHADOW_SETTINGS_ADD_PRESET(sun_near, slb_shadow_method_optimized_pcf, 16, 16, 16, 8.0, 2.0, 0.1)
|
||||
SLB_SHADOW_SETTINGS_ADD_PRESET(sun_far, slb_shadow_method_optimized_pcf, 16, 16, 16, 8.0, 2.0, 0.1)
|
||||
SLB_SHADOW_SETTINGS_ADD_PRESET(spot, slb_shadow_method_optimized_pcf, 16, 16, 16, 8.0, 2.0, 0.02)
|
||||
SLB_SHADOW_SETTINGS_ADD_PRESET(omni, slb_shadow_method_optimized_pcf, 16, 16, 16, 8.0, 2.0, 0.02)
|
||||
SLB_SHADOW_SETTINGS_ADD_PRESET(fallback, slb_shadow_method_bicubic, 16, 16, 16, 8.0, 2.0, 0.1)
|
||||
|
||||
#elif SUN_QUALITY==2 /// high quality
|
||||
|
||||
SLB_SHADOW_SETTINGS_ADD_PRESET(sun_near, slb_shadow_method_vogel_chs, 16, 16, 16, 8.0, 3.0, 0.1)
|
||||
SLB_SHADOW_SETTINGS_ADD_PRESET(sun_far, slb_shadow_method_vogel_chs, 16, 16, 16, 8.0, 3.0, 0.1)
|
||||
SLB_SHADOW_SETTINGS_ADD_PRESET(spot, slb_shadow_method_vogel_chs, 16, 16, 16, 8.0, 3.0, 0.02)
|
||||
SLB_SHADOW_SETTINGS_ADD_PRESET(omni, slb_shadow_method_vogel_chs, 16, 16, 16, 8.0, 3.0, 0.02)
|
||||
SLB_SHADOW_SETTINGS_ADD_PRESET(fallback, slb_shadow_method_bicubic, 16, 16, 16, 8.0, 3.0, 0.1)
|
||||
|
||||
#elif SUN_QUALITY==3 /// ultra quality
|
||||
|
||||
SLB_SHADOW_SETTINGS_ADD_PRESET(sun_near, slb_shadow_method_pcss, 16, 16, 16, 8.0, 2.0, 0.1)
|
||||
SLB_SHADOW_SETTINGS_ADD_PRESET(sun_far, slb_shadow_method_pcss, 16, 16, 16, 2.0, 2.0, 0.1)
|
||||
SLB_SHADOW_SETTINGS_ADD_PRESET(spot, slb_shadow_method_pcss, 16, 16, 16, 8.0, 2.0, 0.02)
|
||||
SLB_SHADOW_SETTINGS_ADD_PRESET(omni, slb_shadow_method_pcss, 16, 16, 16, 8.0, 2.0, 0.02)
|
||||
SLB_SHADOW_SETTINGS_ADD_PRESET(fallback, slb_shadow_method_bicubic, 16, 16, 16, 8.0, 2.0, 0.1)
|
||||
|
||||
#elif SUN_QUALITY>=4 /// extreme quality
|
||||
|
||||
SLB_SHADOW_SETTINGS_ADD_PRESET(sun_near, slb_shadow_method_pcss, 32, 32, 32, 16.0, 2.0, 0.1)
|
||||
SLB_SHADOW_SETTINGS_ADD_PRESET(sun_far, slb_shadow_method_pcss, 32, 32, 32, 4.0, 2.0, 0.1)
|
||||
SLB_SHADOW_SETTINGS_ADD_PRESET(spot, slb_shadow_method_pcss, 32, 32, 32, 16.0, 2.0, 0.02)
|
||||
SLB_SHADOW_SETTINGS_ADD_PRESET(omni, slb_shadow_method_pcss, 32, 32, 32, 16.0, 2.0, 0.02)
|
||||
SLB_SHADOW_SETTINGS_ADD_PRESET(fallback, slb_shadow_method_bicubic, 32, 32, 32, 16.0, 2.0, 0.1)
|
||||
|
||||
#endif
|
||||
|
||||
/// Real settings ends here
|
||||
|
||||
#if defined(SLB_SHADOW_SUN_NEAR)
|
||||
SLB_SHADOW_SETTINGS_APPLY_PRESET(sun_near)
|
||||
#elif defined(SLB_SHADOW_SUN_FAR)
|
||||
SLB_SHADOW_SETTINGS_APPLY_PRESET(sun_far)
|
||||
#elif defined(SLB_SHADOW_SPOT)
|
||||
SLB_SHADOW_SETTINGS_APPLY_PRESET(spot)
|
||||
#elif defined(SLB_SHADOW_OMNI)
|
||||
SLB_SHADOW_SETTINGS_APPLY_PRESET(omni)
|
||||
#else
|
||||
SLB_SHADOW_SETTINGS_APPLY_PRESET(fallback)
|
||||
#endif
|
||||
|
||||
#endif /// SLB_SHADOW_SETTINGS_H
|
||||
@@ -0,0 +1,34 @@
|
||||
[General]
|
||||
gameName=stalkeranomaly
|
||||
modid=0
|
||||
version=d2024.3.26.0
|
||||
newestVersion=
|
||||
category="-1,"
|
||||
nexusFileStatus=1
|
||||
installationFile=Shaders_Look_Better_v1.1.0.7z
|
||||
repository=Nexus
|
||||
ignoredVersion=
|
||||
comments=
|
||||
notes=
|
||||
nexusDescription=
|
||||
url=
|
||||
hasCustomURL=true
|
||||
lastNexusQuery=
|
||||
lastNexusUpdate=
|
||||
nexusLastModified=2024-03-26T07:24:23Z
|
||||
nexusCategory=0
|
||||
converted=false
|
||||
validated=false
|
||||
color=@Variant(\0\0\0\x43\0\xff\xff\0\0\0\0\0\0\0\0)
|
||||
tracked=0
|
||||
|
||||
[installedFiles]
|
||||
1\modid=0
|
||||
size=1
|
||||
1\fileid=0
|
||||
|
||||
[Plugins]
|
||||
BAIN%20Installer\option0=00 Main
|
||||
BAIN%20Installer\option1=05 Motion Blur
|
||||
BAIN%20Installer\option2=10 Shadows
|
||||
BAIN%20Installer\option3=11 Shadows SSS
|
||||
Reference in New Issue
Block a user