mirror of
https://github.com/italicsjenga/slang-shaders.git
synced 2024-11-26 01:11:32 +11:00
Add frame mixing shaders
This commit is contained in:
parent
c3e5725975
commit
31e16c5915
6
motionblur/mix_frames.slangp
Normal file
6
motionblur/mix_frames.slangp
Normal file
|
@ -0,0 +1,6 @@
|
||||||
|
shaders = "1"
|
||||||
|
|
||||||
|
shader0 = "shaders/mix_frames.slang"
|
||||||
|
|
||||||
|
filter_linear0 = "false"
|
||||||
|
scale_type_0 = "source"
|
6
motionblur/mix_frames_smart.slangp
Normal file
6
motionblur/mix_frames_smart.slangp
Normal file
|
@ -0,0 +1,6 @@
|
||||||
|
shaders = "1"
|
||||||
|
|
||||||
|
shader0 = "shaders/mix_frames_smart.slang"
|
||||||
|
|
||||||
|
filter_linear0 = "false"
|
||||||
|
scale_type_0 = "source"
|
57
motionblur/shaders/mix_frames.slang
Normal file
57
motionblur/shaders/mix_frames.slang
Normal file
|
@ -0,0 +1,57 @@
|
||||||
|
#version 450
|
||||||
|
|
||||||
|
/*
|
||||||
|
mix_frames - performs 50:50 blending between the current and previous
|
||||||
|
frames.
|
||||||
|
|
||||||
|
Author: jdgleaver
|
||||||
|
|
||||||
|
This program is free software; you can redistribute it and/or modify it
|
||||||
|
under the terms of the GNU General Public License as published by the Free
|
||||||
|
Software Foundation; either version 2 of the License, or (at your option)
|
||||||
|
any later version.
|
||||||
|
*/
|
||||||
|
|
||||||
|
layout(std140, set = 0, binding = 0) uniform UBO
|
||||||
|
{
|
||||||
|
mat4 MVP;
|
||||||
|
} global;
|
||||||
|
|
||||||
|
#pragma stage vertex
|
||||||
|
|
||||||
|
layout(location = 0) in vec4 Position;
|
||||||
|
layout(location = 1) in vec2 TexCoord;
|
||||||
|
layout(location = 0) out vec2 vTexCoord;
|
||||||
|
|
||||||
|
/*
|
||||||
|
VERTEX_SHADER
|
||||||
|
*/
|
||||||
|
void main()
|
||||||
|
{
|
||||||
|
gl_Position = global.MVP * Position;
|
||||||
|
vTexCoord = TexCoord;
|
||||||
|
}
|
||||||
|
|
||||||
|
#pragma stage fragment
|
||||||
|
|
||||||
|
layout(location = 0) in vec2 vTexCoord;
|
||||||
|
layout(location = 0) out vec4 FragColor;
|
||||||
|
layout(set = 0, binding = 2) uniform sampler2D Source;
|
||||||
|
layout(set = 0, binding = 3) uniform sampler2D OriginalHistory1;
|
||||||
|
|
||||||
|
/*
|
||||||
|
FRAGMENT SHADER
|
||||||
|
*/
|
||||||
|
void main()
|
||||||
|
{
|
||||||
|
// Get colour of current pixel
|
||||||
|
vec3 colour = texture(Source, vTexCoord.xy).rgb;
|
||||||
|
|
||||||
|
// Get colour of previous pixel
|
||||||
|
vec3 colourPrev = texture(OriginalHistory1, vTexCoord.xy).rgb;
|
||||||
|
|
||||||
|
// Mix colours
|
||||||
|
colour.rgb = mix(colour.rgb, colourPrev.rgb, 0.5);
|
||||||
|
|
||||||
|
FragColor = vec4(colour.rgb, 1.0);
|
||||||
|
}
|
111
motionblur/shaders/mix_frames_smart.slang
Normal file
111
motionblur/shaders/mix_frames_smart.slang
Normal file
|
@ -0,0 +1,111 @@
|
||||||
|
#version 450
|
||||||
|
|
||||||
|
/*
|
||||||
|
mix_frames_smart - performs 50:50 blending between the current and
|
||||||
|
previous frames, but only if pixels repeatedly switch state on alternate
|
||||||
|
frames (i.e. prevents flicker on games that use LCD ghosting for transparency,
|
||||||
|
without blurring the entire screen). This is not 100% effective, but 'good
|
||||||
|
enough' in many cases (e.g. it fixes map rendering issues in F-Zero GP on the GBA).
|
||||||
|
Works best when flickering objects are in a fixed location.
|
||||||
|
|
||||||
|
Author: jdgleaver
|
||||||
|
|
||||||
|
This program is free software; you can redistribute it and/or modify it
|
||||||
|
under the terms of the GNU General Public License as published by the Free
|
||||||
|
Software Foundation; either version 2 of the License, or (at your option)
|
||||||
|
any later version.
|
||||||
|
*/
|
||||||
|
|
||||||
|
// User-specified fudge factor. Increasing this value loosens up the
|
||||||
|
// detection of repeated 'flicker' frames. This is required for
|
||||||
|
// games like Boktai on the GBA, where the character shadow flickers
|
||||||
|
// on and off between frames, but is sometimes overlaid with a screen
|
||||||
|
// shading effect (so checking for pixel RGB equality fails - need to
|
||||||
|
// check whether pixels are 'almost' equal)
|
||||||
|
#pragma parameter DEFLICKER_EMPHASIS "Deflicker Emphasis" 0.0 0.0 1.0 0.01
|
||||||
|
|
||||||
|
layout(push_constant) uniform Push
|
||||||
|
{
|
||||||
|
float DEFLICKER_EMPHASIS;
|
||||||
|
} registers;
|
||||||
|
|
||||||
|
layout(std140, set = 0, binding = 0) uniform UBO
|
||||||
|
{
|
||||||
|
mat4 MVP;
|
||||||
|
} global;
|
||||||
|
|
||||||
|
#pragma stage vertex
|
||||||
|
|
||||||
|
layout(location = 0) in vec4 Position;
|
||||||
|
layout(location = 1) in vec2 TexCoord;
|
||||||
|
layout(location = 0) out vec2 vTexCoord;
|
||||||
|
|
||||||
|
/*
|
||||||
|
VERTEX_SHADER
|
||||||
|
*/
|
||||||
|
void main()
|
||||||
|
{
|
||||||
|
gl_Position = global.MVP * Position;
|
||||||
|
vTexCoord = TexCoord;
|
||||||
|
}
|
||||||
|
|
||||||
|
#pragma stage fragment
|
||||||
|
|
||||||
|
layout(location = 0) in vec2 vTexCoord;
|
||||||
|
layout(location = 0) out vec4 FragColor;
|
||||||
|
layout(set = 0, binding = 2) uniform sampler2D Source;
|
||||||
|
layout(set = 0, binding = 3) uniform sampler2D OriginalHistory1;
|
||||||
|
layout(set = 0, binding = 4) uniform sampler2D OriginalHistory2;
|
||||||
|
layout(set = 0, binding = 5) uniform sampler2D OriginalHistory3;
|
||||||
|
layout(set = 0, binding = 6) uniform sampler2D OriginalHistory4;
|
||||||
|
layout(set = 0, binding = 7) uniform sampler2D OriginalHistory5;
|
||||||
|
|
||||||
|
#define EPSILON 0.000001
|
||||||
|
|
||||||
|
float is_equal(vec3 x, vec3 y)
|
||||||
|
{
|
||||||
|
vec3 result = 1.0 - abs(sign(x - y));
|
||||||
|
return min(min(result.r, result.g), result.b);
|
||||||
|
}
|
||||||
|
|
||||||
|
float is_approx_equal(vec3 x, vec3 y)
|
||||||
|
{
|
||||||
|
vec3 result = 1.0 - step(EPSILON + registers.DEFLICKER_EMPHASIS, abs(x - y));
|
||||||
|
return min(min(result.r, result.g), result.b);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
FRAGMENT SHADER
|
||||||
|
*/
|
||||||
|
void main()
|
||||||
|
{
|
||||||
|
// Get pixel colours of current + last 5 frames
|
||||||
|
// NB: Using fewer frames results in too many false positives
|
||||||
|
vec3 colour0 = texture(Source, vTexCoord.xy).rgb;
|
||||||
|
vec3 colour1 = texture(OriginalHistory1, vTexCoord.xy).rgb;
|
||||||
|
vec3 colour2 = texture(OriginalHistory2, vTexCoord.xy).rgb;
|
||||||
|
vec3 colour3 = texture(OriginalHistory3, vTexCoord.xy).rgb;
|
||||||
|
vec3 colour4 = texture(OriginalHistory4, vTexCoord.xy).rgb;
|
||||||
|
vec3 colour5 = texture(OriginalHistory5, vTexCoord.xy).rgb;
|
||||||
|
|
||||||
|
// Determine whether mixing should occur
|
||||||
|
// i.e. whether alternate frames have the same pixel colour, but
|
||||||
|
// adjacent frames do not (don't need to check colour0 != colour1,
|
||||||
|
// since if this is true the mixing will do nothing)
|
||||||
|
float doMix = (1.0 - is_equal(colour0, colour3))
|
||||||
|
* (1.0 - is_equal(colour0, colour5))
|
||||||
|
* (1.0 - is_equal(colour1, colour2))
|
||||||
|
* (1.0 - is_equal(colour1, colour4))
|
||||||
|
* (1.0 - is_equal(colour2, colour3))
|
||||||
|
* (1.0 - is_equal(colour2, colour5))
|
||||||
|
* min(
|
||||||
|
(is_approx_equal(colour0, colour2) * is_approx_equal(colour2, colour4)) +
|
||||||
|
(is_approx_equal(colour1, colour3) * is_approx_equal(colour3, colour5)),
|
||||||
|
1.0
|
||||||
|
);
|
||||||
|
|
||||||
|
// Mix colours
|
||||||
|
colour0.rgb = mix(colour0.rgb, colour1.rgb, doMix * 0.5);
|
||||||
|
|
||||||
|
FragColor = vec4(colour0.rgb, 1.0);
|
||||||
|
}
|
Loading…
Reference in a new issue