Files
2025-05-24 18:09:39 -03:00

152 lines
6.1 KiB
GLSL

/**
*
* Copyright (c) 2018-2020, Kitty Barnett
*
* The source code in this file is provided to you under the terms of the
* GNU Lesser General Public License, version 2.1, but WITHOUT ANY WARRANTY;
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
* PARTICULAR PURPOSE. Terms of the LGPL can be found in doc/LGPL-licence.txt
* in this distribution, or online at http://www.gnu.org/licenses/lgpl-2.1.txt
*
* By copying, modifying or distributing this software, you acknowledge that
* you have read and understood your obligations described above, and agree to
* abide by those obligations.
*
*/
/*[EXTRA_CODE_HERE]*/
out vec4 frag_color;
in vec2 vary_fragcoord;
uniform sampler2D diffuseRect;
uniform vec2 screen_res;
uniform int rlvEffectMode; // ESphereMode
uniform vec4 rlvEffectParam1; // Sphere origin (in local coordinates)
uniform vec4 rlvEffectParam2; // Min/max dist + min/max value
uniform bvec2 rlvEffectParam3; // Min/max dist extend
uniform vec4 rlvEffectParam4; // Sphere params (=color when using blend)
uniform vec2 rlvEffectParam5; // Blur direction (not used for blend)
#define SPHERE_ORIGIN rlvEffectParam1.xyz
#define SPHERE_DISTMIN rlvEffectParam2.y
#define SPHERE_DISTMAX rlvEffectParam2.w
#define SPHERE_DISTEXTEND rlvEffectParam3
#define SPHERE_VALUEMIN rlvEffectParam2.x
#define SPHERE_VALUEMAX rlvEffectParam2.z
#define SPHERE_PARAMS rlvEffectParam4
#define BLUR_DIRECTION rlvEffectParam5.xy
vec4 getPositionWithDepth(vec2 pos_screen, float depth);
float getDepth(vec2 pos_screen);
vec3 blur13(sampler2D source, vec2 tc, vec2 direction)
{
vec4 color = vec4(0.0);
vec2 off1 = vec2(1.411764705882353) * direction;
vec2 off2 = vec2(3.2941176470588234) * direction;
vec2 off3 = vec2(5.176470588235294) * direction;
color += texture(source, tc) * 0.1964825501511404;
color += texture(source, tc + off1 / screen_res) * 0.2969069646728344;
color += texture(source, tc - off1 / screen_res) * 0.2969069646728344;
color += texture(source, tc + off2 / screen_res) * 0.09447039785044732;
color += texture(source, tc - off2 / screen_res) * 0.09447039785044732;
color += texture(source, tc + off3 / screen_res) * 0.010381362401148057;
color += texture(source, tc - off3 / screen_res) * 0.010381362401148057;
return color.xyz;
}
const float pi = 3.14159265;
// http://callumhay.blogspot.com/2010/09/gaussian-blur-shader-glsl.html
vec3 blurVariable(sampler2D source, vec2 tc, float kernelSize, vec2 direction, float strength) {
float numBlurPixelsPerSide = float(kernelSize / 2);
// Incremental Gaussian Coefficent Calculation (See GPU Gems 3 pp. 877 - 889)
vec3 incrementalGaussian;
incrementalGaussian.x = 1.0 / (sqrt(2.0 * pi) * strength);
incrementalGaussian.y = exp(-0.5 / (strength * strength));
incrementalGaussian.z = incrementalGaussian.y * incrementalGaussian.y;
vec4 avgValue = vec4(0.0, 0.0, 0.0, 0.0);
float coefficientSum = 0.0;
// Take the central sample first...
avgValue += texture(source, tc) * incrementalGaussian.x;
coefficientSum += incrementalGaussian.x;
incrementalGaussian.xy *= incrementalGaussian.yz;
// Go through the remaining 8 vertical samples (4 on each side of the center)
for (float i = 1.0; i <= numBlurPixelsPerSide; i++) {
avgValue += texture(source, tc - i * direction / screen_res) * incrementalGaussian.x;
avgValue += texture(source, tc + i * direction / screen_res) * incrementalGaussian.x;
coefficientSum += 2.0 * incrementalGaussian.x;
incrementalGaussian.xy *= incrementalGaussian.yz;
}
return (avgValue / coefficientSum).rgb;
}
vec3 chromaticAberration(sampler2D source, vec2 tc, vec2 redDrift, vec2 blueDrift, float strength)
{
vec3 sourceColor = texture(source, tc).rgb;
// Sample the color components
vec3 driftColor;
driftColor.r = texture(source, tc + redDrift / screen_res).r;
driftColor.g = sourceColor.g;
driftColor.b = texture(source, tc + blueDrift / screen_res).b;
// Adjust the strength of the effect
return mix(sourceColor, driftColor, strength);
}
void main()
{
vec2 fragTC = vary_fragcoord.xy;
vec3 fragPosLocal = getPositionWithDepth(fragTC, getDepth(fragTC)).xyz;
float distance = length(fragPosLocal.xyz - SPHERE_ORIGIN);
// Linear non-branching interpolation of the strength of the sphere effect (replaces if/elseif/else for x < min, min <= x <= max and x > max)
float effectStrength = SPHERE_VALUEMIN + mix(0, SPHERE_VALUEMAX - SPHERE_VALUEMIN, (distance - SPHERE_DISTMIN) / (SPHERE_DISTMAX - SPHERE_DISTMIN));
effectStrength = mix(effectStrength, mix(0, SPHERE_VALUEMIN, SPHERE_DISTEXTEND.x), distance < SPHERE_DISTMIN);
effectStrength = mix(effectStrength, mix(0, SPHERE_VALUEMAX, SPHERE_DISTEXTEND.y), distance > SPHERE_DISTMAX);
vec3 fragColor ;
switch (rlvEffectMode)
{
case 0: // Blend
fragColor = texture(diffuseRect, fragTC).rgb;
fragColor = mix(fragColor, SPHERE_PARAMS.rgb, effectStrength);
break;
case 1: // Blur (fixed)
fragColor = blur13(diffuseRect, fragTC, BLUR_DIRECTION * vec2(effectStrength));
break;
case 2: // Blur (variable)
fragColor = texture(diffuseRect, fragTC).rgb;
fragColor = mix(fragColor, blurVariable(diffuseRect, fragTC, SPHERE_PARAMS.x, BLUR_DIRECTION, effectStrength), bvec3(effectStrength > 0));
break;
case 3: // ChromaticAberration
fragColor = chromaticAberration(diffuseRect, fragTC, SPHERE_PARAMS.xy, SPHERE_PARAMS.zw, effectStrength);
break;
case 4: // Pixelate
{
effectStrength = sign(effectStrength);
float pixelWidth = max(1, round(SPHERE_PARAMS.x * effectStrength)) / screen_res.x;
float pixelHeight = max(1, round(SPHERE_PARAMS.y * effectStrength)) / screen_res.y;
fragTC = vec2(pixelWidth * floor(fragTC.x / pixelWidth), pixelHeight * floor(fragTC.y / pixelHeight));
fragColor = texture(diffuseRect, fragTC).rgb;
}
break;
}
frag_color.rgb = fragColor;
frag_color.a = 0.0;
}