mirror of
https://github.com/italicsjenga/slang-shaders.git
synced 2024-11-27 09:51:30 +11:00
232 lines
9.5 KiB
Plaintext
232 lines
9.5 KiB
Plaintext
|
#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);
|
||
|
|
||
|
}
|
||
|
|
||
|
|
||
|
|