mirror of
https://github.com/italicsjenga/slang-shaders.git
synced 2024-11-25 17:01:31 +11:00
227 lines
6.7 KiB
Plaintext
227 lines
6.7 KiB
Plaintext
|
#version 450
|
||
|
#include "config.inc"
|
||
|
|
||
|
|
||
|
/*
|
||
|
CRT Shader by EasyMode
|
||
|
License: GPL
|
||
|
|
||
|
Modified by kokoko3k, stripped to keep just curvature related code.
|
||
|
*/
|
||
|
|
||
|
#define FIX(c) max(abs(c), 1e-5)
|
||
|
#define PI 3.141592653589
|
||
|
#define TEX2D(c) texture(tex, c)
|
||
|
#define in_texture final_pass
|
||
|
#define in_textureSize final_passSize
|
||
|
//#define in_textureSize SourceSize
|
||
|
|
||
|
#pragma stage vertex
|
||
|
layout(location = 0) in vec4 Position;
|
||
|
layout(location = 1) in vec2 TexCoord;
|
||
|
layout(location = 0) out vec2 vTexCoord;
|
||
|
layout(location = 1) out vec2 vOutputCoord;
|
||
|
|
||
|
#include "functions.include"
|
||
|
void main() {
|
||
|
gl_Position = global.MVP * Position;
|
||
|
vTexCoord = get_scaled_coords(TexCoord);
|
||
|
vOutputCoord = TexCoord;
|
||
|
}
|
||
|
|
||
|
#pragma stage fragment
|
||
|
layout(location = 0) in vec2 vTexCoord;
|
||
|
layout(location = 1) in vec2 vOutputCoord;
|
||
|
layout(location = 0) out vec4 FragColor;
|
||
|
layout(set = 0, binding = 2) uniform sampler2D in_texture;
|
||
|
|
||
|
float curve_distance(float x, float sharp)
|
||
|
{
|
||
|
float x_step = step(0.5, x);
|
||
|
float curve = 0.5 - sqrt(0.25 - (x - x_step) * (x - x_step)) * sign(0.5 - x);
|
||
|
|
||
|
return mix(x, curve, sharp);
|
||
|
}
|
||
|
|
||
|
mat4x4 get_color_matrix(sampler2D tex, vec2 co, vec2 dx)
|
||
|
{
|
||
|
return mat4x4(TEX2D(co - dx), TEX2D(co), TEX2D(co + dx), TEX2D(co + 2.0 * dx));
|
||
|
}
|
||
|
|
||
|
vec4 filter_lanczos(vec4 coeffs, mat4x4 color_matrix)
|
||
|
{
|
||
|
vec4 col = color_matrix * coeffs;
|
||
|
vec4 sample_min = min(color_matrix[1], color_matrix[2]);
|
||
|
vec4 sample_max = max(color_matrix[1], color_matrix[2]);
|
||
|
|
||
|
col = clamp(col, sample_min, sample_max);
|
||
|
|
||
|
return col;
|
||
|
}
|
||
|
|
||
|
vec2 curve_coordinate(vec2 co, float curvature_x, float curvature_y)
|
||
|
{
|
||
|
vec2 curve = vec2(curvature_x, curvature_y);
|
||
|
vec2 co2 = co + co * curve - curve / 2.0;
|
||
|
vec2 co_weight = vec2(co.y, co.x) * 2.0 - 1.0;
|
||
|
|
||
|
co = mix(co, co2, co_weight * co_weight);
|
||
|
|
||
|
return co;
|
||
|
}
|
||
|
|
||
|
float get_corner_weight(vec2 co, vec2 corner, float smoothfunc)
|
||
|
{
|
||
|
float corner_weight;
|
||
|
|
||
|
co = min(co, vec2(1.0) - co) * vec2(1.0, 0.75);
|
||
|
co = (corner - min(co, corner));
|
||
|
corner_weight = clamp((corner.x - sqrt(dot(co, co))) * smoothfunc, 0.0, 1.0);
|
||
|
corner_weight = mix(1.0, corner_weight, ceil(corner.x));
|
||
|
|
||
|
return corner_weight;
|
||
|
}
|
||
|
|
||
|
#define GEOM_ANTIALIAS 1.0
|
||
|
|
||
|
vec3 curve_antialias(vec2 xy,vec2 tex_size){
|
||
|
vec2 midpoint = vec2(0.5, 0.5);
|
||
|
|
||
|
vec2 co = vOutputCoord * tex_size * params.in_textureSize.zw;
|
||
|
vec2 co2 = vTexCoord * tex_size * params.in_textureSize.zw;
|
||
|
|
||
|
vec3 col;
|
||
|
float corner_weight = get_corner_weight(curve_coordinate(co2, GEOM_BORDER_WX, GEOM_BORDER_WY ), vec2(GEOM_CORNER_SIZE), GEOM_CORNER_SMOOTH);
|
||
|
|
||
|
if ( (GEOM_WARP_X > 0) || (GEOM_WARP_Y > 0) ) {
|
||
|
xy *= params.in_textureSize.xy / tex_size;
|
||
|
|
||
|
vec2 dx = vec2(1.0 / tex_size.x, 0.0);
|
||
|
vec2 dy = vec2(0.0, 1.0 / tex_size.y);
|
||
|
vec2 pix_co = xy * tex_size - midpoint;
|
||
|
vec2 tex_co = (floor(pix_co) + midpoint) / tex_size;
|
||
|
vec2 dist = fract(pix_co);
|
||
|
float curve_x, curve_y;
|
||
|
vec3 col2, diff;
|
||
|
|
||
|
curve_x = curve_distance(dist.x, SHARPNESS_H * SHARPNESS_H);
|
||
|
curve_y = curve_distance(dist.y, SHARPNESS_V * SHARPNESS_V);
|
||
|
|
||
|
vec4 coeffs_x = PI * vec4(1.0 + curve_x, curve_x, 1.0 - curve_x, 2.0 - curve_x);
|
||
|
vec4 coeffs_y = PI * vec4(1.0 + curve_y, curve_y, 1.0 - curve_y, 2.0 - curve_y);
|
||
|
|
||
|
coeffs_x = FIX(coeffs_x);
|
||
|
coeffs_x = 2.0 * sin(coeffs_x) * sin(coeffs_x / 2.0) / (coeffs_x * coeffs_x);
|
||
|
coeffs_x /= dot(coeffs_x, vec4(1.0));
|
||
|
|
||
|
coeffs_y = FIX(coeffs_y);
|
||
|
coeffs_y = 2.0 * sin(coeffs_y) * sin(coeffs_y / 2.0) / (coeffs_y * coeffs_y);
|
||
|
coeffs_y /= dot(coeffs_y, vec4(1.0));
|
||
|
|
||
|
mat4x4 color_matrix;
|
||
|
|
||
|
|
||
|
color_matrix[0] = filter_lanczos(coeffs_x, get_color_matrix(in_texture, tex_co - dy, dx));
|
||
|
color_matrix[1] = filter_lanczos(coeffs_x, get_color_matrix(in_texture, tex_co, dx));
|
||
|
color_matrix[2] = filter_lanczos(coeffs_x, get_color_matrix(in_texture, tex_co + dy, dx));
|
||
|
color_matrix[3] = filter_lanczos(coeffs_x, get_color_matrix(in_texture, tex_co + 2.0 * dy, dx));
|
||
|
|
||
|
col = filter_lanczos(coeffs_y, color_matrix).rgb;
|
||
|
} else {
|
||
|
col = texture(in_texture, vOutputCoord).rgb;
|
||
|
}
|
||
|
|
||
|
col *= vec3(corner_weight);
|
||
|
return col;
|
||
|
}
|
||
|
|
||
|
vec2 Warp2(vec2 texCoord){
|
||
|
|
||
|
vec2 curvedCoords = texCoord * 2.0 - 1.0;
|
||
|
vec2 CRT_Distortion = vec2(GEOM_WARP_X, GEOM_WARP_Y) * 15.;
|
||
|
float curvedCoordsDistance = sqrt(curvedCoords.x*curvedCoords.x+curvedCoords.y*curvedCoords.y);
|
||
|
|
||
|
curvedCoords = curvedCoords / curvedCoordsDistance;
|
||
|
|
||
|
curvedCoords = curvedCoords * (1.0-pow(vec2(1.0-(curvedCoordsDistance/1.4142135623730950488016887242097)),(1.0/(1.0+CRT_Distortion*0.2))));
|
||
|
|
||
|
curvedCoords = curvedCoords / (1.0-pow(vec2(0.29289321881345247559915563789515),(1.0/(vec2(1.0)+CRT_Distortion*0.2))));
|
||
|
|
||
|
curvedCoords = curvedCoords * 0.5 + 0.5;
|
||
|
return curvedCoords;
|
||
|
}
|
||
|
|
||
|
vec3 do_curvature_antialias(){
|
||
|
vec2 tex_size = params.in_textureSize.xy ;
|
||
|
|
||
|
vec2 co = vOutputCoord * tex_size * params.in_textureSize.zw;
|
||
|
vec2 co2 = vTexCoord * tex_size * params.in_textureSize.zw;
|
||
|
vec2 curved_xy = curve_coordinate(co, GEOM_WARP_X,GEOM_WARP_Y );
|
||
|
|
||
|
vec3 col;
|
||
|
//float corner_weight = get_corner_weight(curve_coordinate(co2, GEOM_BORDER_WX, GEOM_BORDER_WY ), vec2(GEOM_CORNER_SIZE), GEOM_CORNER_SMOOTH);
|
||
|
float corner_weight = get_corner_weight(Warp2(co), vec2(GEOM_CORNER_SIZE), GEOM_CORNER_SMOOTH);
|
||
|
|
||
|
|
||
|
if ( (GEOM_WARP_X > 0) || (GEOM_WARP_Y > 0) ) {
|
||
|
if (GEOM_ANTIALIAS == 1.0)
|
||
|
col = curve_antialias(curved_xy,tex_size);
|
||
|
else
|
||
|
col = texture(in_texture,curved_xy).rgb;
|
||
|
} else {
|
||
|
col = texture(in_texture, vOutputCoord).rgb;
|
||
|
}
|
||
|
|
||
|
col *= vec3(corner_weight) ;
|
||
|
|
||
|
|
||
|
|
||
|
return col;
|
||
|
}
|
||
|
|
||
|
const vec2 corner_aspect = vec2(1.0, 0.75);
|
||
|
|
||
|
float corner2(vec2 coord)
|
||
|
{
|
||
|
coord = (coord - vec2(0.5)) + vec2(0.5, 0.5);
|
||
|
coord = min(coord, vec2(1.0) - coord) * corner_aspect;
|
||
|
vec2 cdist = vec2(GEOM_CORNER_SIZE);
|
||
|
coord = (cdist - min(coord, cdist));
|
||
|
float dist = sqrt(dot(coord, coord));
|
||
|
|
||
|
return clamp((cdist.x - dist)*GEOM_CORNER_SMOOTH, 0.0, 1.0);
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
vec3 do_curvature_alias(){
|
||
|
vec2 curved_xy = Warp2(vOutputCoord);
|
||
|
return texture(in_texture,curved_xy ).rgb * corner2(curved_xy);
|
||
|
}
|
||
|
|
||
|
vec4 main_wrap()
|
||
|
{
|
||
|
if (DO_CURVATURE == 1.0) {
|
||
|
return vec4(do_curvature_antialias(), 1.0);
|
||
|
} else {
|
||
|
return texture(in_texture, vOutputCoord);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
#include "functions.include"
|
||
|
void main() {
|
||
|
vec4 psample = texture(in_texture, vOutputCoord);
|
||
|
if ( border_needed() ) {
|
||
|
if (is_outer_frame(psample))
|
||
|
FragColor = mark_outer_frame(vec3(0.0));
|
||
|
else
|
||
|
FragColor = main_wrap();
|
||
|
} else {
|
||
|
FragColor = main_wrap();
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|