slang-shaders/bezel/koko-aio/shaders/reflection_blur_x.slang

232 lines
9.5 KiB
Plaintext
Raw Normal View History

#version 450
#include "config.inc"
#pragma stage vertex
layout(location = 0) in vec4 Position;
layout(location = 1) in vec2 TexCoord;
layout(location = 1) out vec2 vWarp_vexp;
layout(location = 2) out vec2 vWarp_arg2;
layout(location = 0) out vec2 vTexCoord;
#include "includes/functions.include.slang"
void main() {
gl_Position = global.MVP * Position;
vTexCoord = TexCoord;
//Precalc some Curvature/Warp values:
vWarp_vexp = 1.0/ (1 + (vec2(GEOM_WARP_X, GEOM_WARP_Y) * 0.2)) ;
vWarp_arg2 = 1.0 - pow(vec2(0.29289321881345247559915563789515), vWarp_vexp );
if (DO_BEZEL > 0.5)
vTexCoord = zoom(TexCoord, BEZEL_REFL_ZOOM);
}
#pragma stage fragment
layout(location = 0) in vec2 vTexCoord;
layout(location = 1) in vec2 vWarp_vexp;
layout(location = 2) in vec2 vWarp_arg2;
layout(location = 0) out vec4 FragColor;
layout(set = 0, binding = 1) uniform sampler2D first_pass;
layout(set = 0, binding = 2) uniform sampler2D avglum_pass;
#define SourceTexture first_pass
#define SourceTextureSize global.first_passSize
#include "includes/functions.include.slang"
#define c_tolerance 0.051
vec3 texture_clamp_to_border(sampler2D tex, vec2 coords, float lod) {
//This emulates clamp to border:
if (coords.x < 0.0 || coords.x > 1.0 || coords.y < 0.0 || coords.y > 1.0)
return vec3(0.0);
else
return textureLod( tex, coords, lod).rgb ;
}
vec3 blur_unroll_clamp_to_border(float Size, vec2 co, float lod, float coords_crop_point) {
//Blur the image along x axis and emulate a clamp_to_border when outside the [0..1] range
//FIXME: coords_crop_point are not taken into account? CHECKME if you ever use this.
Size = Size * NEW_SCALEMOD_X; //<- so that blur size doesn't depend on output resolution
vec3 color;
vec2 d = SourceTextureSize.zw * Size;
color = texture_clamp_to_border( SourceTexture, co + d * vec2(-1.0, 1.0 ) ,lod).rgb;
color += texture_clamp_to_border( SourceTexture, co + d * vec2( 1.0, 1.0 ) ,lod).rgb;
color += texture_clamp_to_border( SourceTexture, co + d * vec2(-1.0, -1.0 ) ,lod).rgb;
color += texture_clamp_to_border( SourceTexture, co + d * vec2( 1.0, -1.0 ) ,lod).rgb;
return color / 4.0;
}
vec3 blur_unroll(float Size, vec2 co, float lod) {
//Blurs the image along x axis
Size = Size * NEW_SCALEMOD_X; //<- so that blur size doesn't depend on output resolution
vec3 color;
vec2 d = SourceTextureSize.zw * Size;
color = textureLod( SourceTexture, co + d * vec2(-1.0, 1.0 ) ,lod).rgb;
color += textureLod( SourceTexture, co + d * vec2( 1.0, 1.0 ) ,lod).rgb;
color += textureLod( SourceTexture, co + d * vec2(-1.0, -1.0 ) ,lod).rgb;
color += textureLod( SourceTexture, co + d * vec2( 1.0, -1.0 ) ,lod).rgb;
return color / 4.0;
}
vec2 mirrored_repeat(vec2 co, float crop) {
//Do a coords mirrored repeat with the mirror axis
//shifted by a "crop" amount.
//Don't try to unbranch me, it is a matter of 1/1000.
float cmin = 0.0 + crop ;
float cmax = 1.0 - crop ;
if (co.x < cmin )
co.x = 2*cmin - co.x;
if (co.y < cmin)
co.y = 2*cmin - co.y;
if (co.x > cmax )
co.x = 2*cmax - co.x;
if (co.y > cmax )
co.y = 2*cmax - co.y;
return co;
}
float circle_smooth(vec2 coords, vec2 middle, float f_radius, float FALLOFF) {
//Draw a circle with smoothed borders:
float fdistance=distance(middle, vec2(coords.x, coords.y));
float circle = (1-smoothstep(f_radius-FALLOFF, f_radius+FALLOFF, fdistance));
return circle;
}
float square_smooth(vec2 co, vec2 corner, float size, float smoothshade) {
//Draws a square with smooth borders:
vec4 rect = vec4(corner.x, corner.y, corner.x+size, corner.y+size);
vec2 hv = smoothstep(rect.xy - smoothshade, rect.xy, co) * smoothstep(co - smoothshade, co, rect.zw);
return hv.x * hv.y;
}
float corners_shade(vec2 co, float size, float smoothsize){
//Draws 4 smooth squares or circles in the corners.
//They are intended to modulate the blur radius and the strength of the reflection.
/*
vec4 circles;
float circle_radius = size; //0.13?
float circle_falloff = smoothsize; //0.05?
float circle_power =2.0;
circles.x = circle_smooth(co, vec2(0.0,0.0), circle_radius, circle_falloff) * circle_power;
circles.y = circle_smooth(co, vec2(0.0,1.0), circle_radius, circle_falloff) * circle_power;
circles.z = circle_smooth(co, vec2(1.0,0.0), circle_radius, circle_falloff) * circle_power;
circles.w = circle_smooth(co, vec2(1.0,1.0), circle_radius, circle_falloff) * circle_power;
float circle = max(max(max(circles.x, circles.y), circles.z), circles.w);
circle = min(circle, 1.0);
circle = 1-circle;
return circle;
*/
vec4 squares;
float squaresize = size;
float squarefade = smoothsize;
//(vec2 co, vec2 corner, float size, float smoothshade) {
squares.x = square_smooth(co, vec2(0.0,0.0), squaresize, squarefade);
squares.y = square_smooth(co, vec2(1.0 - squaresize, 0.0), squaresize, squarefade);
squares.z = square_smooth(co, vec2(0.0, 1-squaresize), squaresize, squarefade);
squares.w = square_smooth(co, vec2(1-squaresize, 1-squaresize), squaresize, squarefade);
return max(max(max(squares.x, squares.y), squares.z), squares.w);
}
float borders_gradient(vec2 co, float foffset) {
// Create a b/w shade near the borders that will be used to
// Modulate from sharp reflections to blur reflections.
vec4 shades;
shades.x = abs( co.x - foffset );
shades.y = abs( 1 - co.x - foffset );
shades.z = abs( co.y - foffset );
shades.w = abs( 1 - co.y - foffset );
return min(min(min(shades.x, shades.y), shades.z), shades.w);
}
void main() {
if (DO_BEZEL == 0.0) return;
//Zoom out the image coordinates by the bezel border size to make room for reflections:
vec2 coords = zoomout_coords(vTexCoord, BEZEL_BORDER_SIZE, 1.0);
vec2 coords_zoomedout = coords;
//This skip condition will be used to spped-up processing by discarding unuseful pixels.
//the c_tolerance parameter is a safe measure /FIXME: for what?
bool skip_condition = (coords.x < 1.0 - c_tolerance && coords.x > c_tolerance &&
coords.y < 1.0 - c_tolerance && coords.y > c_tolerance ) ;
//Mark the pixel as not useful, so that the next pass will be aware of it and skip rendering too:
if (skip_condition) {
FragColor = mark_useless(vec3(0.0));
return;
}
//If coords needs to be curved, do it now:
if (DO_CURVATURE == 1.0 && ( GEOM_WARP_X > 0.0 || GEOM_WARP_Y > 0.0) ) {
coords = Warp_fast(coords, vWarp_vexp, vWarp_arg2); //coords_curved = Warp(coords_curved,GEOM_WARP_X,GEOM_WARP_Y);
}
//Since we will use a mirrored_repeat trick to simulate reflections, we need to know
//where the mirror axis is.
//The mirror axis position may depend on the dynamic zoom level
//(the feature that zooms the image in when it is bright)
float coords_crop_point = 0.0;
if (DO_DYNZOOM == 1.0) {
//Crop coordinates to move the mirror axes
float dyn_zoom = get_dyn_zoom(avglum_pass);
coords_crop_point = (dyn_zoom - 1.0) * 0.5;
//Zoom image coords to align it
coords = zoom(coords, dyn_zoom);
}
coords_crop_point += BEZEL_RFL_OFFSET; // <- Adding the user offset
//Mirror repeat the image by taking the crop point (mirror axis offset) into account:
coords = mirrored_repeat(coords, coords_crop_point);
//Create gradients in the corners to fadeout reflections and to blur more near them:
float fcorners_shade = corners_shade(vTexCoord, BEZEL_REFL_CORNER_BLANK_SIZE, BEZEL_REFL_CORNER_BLANK_SHADE);
//Create a gradient near borders to modulate between blurrend and sharp refection.
//This also goes into output alpha channel to make the next pass aware of it.
float shade_sharp_blur = borders_gradient(coords, coords_crop_point);
shade_sharp_blur = shade_sharp_blur * 1/(BEZEL_BORDER_SIZE * 0.3) ;
shade_sharp_blur = shade_sharp_blur - BEZEL_RFL_BLR_SHD; //Modulates between sharp and blur via user parameter
//Also modulate in the corners via fcorners_shade (fcorners_shade
shade_sharp_blur = max(fcorners_shade, shade_sharp_blur);
//Clamp to min 0.01 because anything lower will cause the next pass to think the pixel is useless.
shade_sharp_blur = max(shade_sharp_blur, 0.01);
//shade_sharp_blur = clamp(shade_sharp_blur, 0.01, 1.0);
//blur the reflection along x axis:
vec3 pixel_out = blur_unroll(BEZEL_REFL_BLUR_MAX * shade_sharp_blur, coords, 2.0);
// I tried, instead of simple blur_unroll() to take a black border into account ( blur_unroll_clamp_to_border() )
// to emulate the reflection of black border into the main content
// when it is smaller than the bezel, but due to the low resolution of this pass, the results are bad:
// vec3 pixel_out = blur_unroll_clamp_to_border(BEZEL_REFL_BLUR_MAX * shade_sharp_blur, coords, 2.0, coords_crop_point);
//multiply the blurred image by the corner shade so that reflections will not be visible in the corners.
pixel_out = pixel_out * (1 - fcorners_shade);
// Finally, output the blurred image and put the sharp to blurred gradient in the alpha channel
// to be used by the next blur-y pass too to modulate the blur radius.
FragColor = vec4(apply_fuzzy_main_pass(pixel_out), shade_sharp_blur);
}