Divergent/mods/Shaders Look Better/gamedata/shaders/r3/slb_motion_blur.h

174 lines
5.3 KiB
C
Raw Normal View History

#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