174 lines
5.3 KiB
C
174 lines
5.3 KiB
C
|
#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
|