mirror of
https://git.davidovski.xyz/dot.git
synced 2026-09-14 00:35:24 +00:00
190 lines
6.1 KiB
GLSL
190 lines
6.1 KiB
GLSL
#version 430
|
|
#define PI 3.1415926538
|
|
uniform float opacity;
|
|
uniform float time;
|
|
|
|
// Works best with fullscreen windows
|
|
// Made this to play retro games the way god intended
|
|
|
|
uniform float sc_freq = 0.2; // Frequency for the scanlines
|
|
|
|
uniform float sc_intensity = 0.6; // Intensity of the scanline effect
|
|
|
|
uniform bool grid = false; // Whether to also apply scanlines to x axis or not
|
|
|
|
uniform int distortion_offset = 2; // Pixel offset for red/blue distortion
|
|
|
|
uniform int downscale_factor = 2; // How many pixels of the window
|
|
// make an actual "pixel" (or block)
|
|
|
|
uniform float sph_distance = 500; // Distance from the theoretical sphere
|
|
// we use for our curvature transform
|
|
|
|
uniform float curvature = 1.5; // How much the window should "curve"
|
|
|
|
uniform float shadow_cutoff = 1; // How "early" the shadow starts affecting
|
|
// pixels close to the edges
|
|
// I'd keep this value very close to 1
|
|
|
|
uniform int shadow_intensity = 1; // Intensity level of the shadow effect (from 1 to 5)
|
|
|
|
vec4 outside_color = vec4(0 ,0 ,0, opacity); // Color for the outside of the window
|
|
|
|
float flash_speed = 0; // Speed of flashing effect, set to 0 to deactivate
|
|
|
|
float flash_intensity = 0.8; // Intensity of flashing effect
|
|
|
|
|
|
// You can play with different values for all the variables above
|
|
|
|
in vec2 texcoord; // texture coordinate of the fragment
|
|
|
|
uniform sampler2D tex; // texture of the window
|
|
|
|
ivec2 window_size = textureSize(tex, 0);
|
|
ivec2 window_center = ivec2(window_size.x/2, window_size.y/2);
|
|
float radius = (window_size.x/curvature);
|
|
int flash = int(round(flash_speed*time/(10000/window_size.y))) % window_size.y;
|
|
|
|
// Default window post-processing:
|
|
// 1) invert color
|
|
// 2) opacity / transparency
|
|
// 3) max-brightness clamping
|
|
// 4) rounded corners
|
|
vec4 default_post_processing(vec4 c);
|
|
|
|
// Darkens a pixels near the edges
|
|
vec4 darken_color(vec4 color, vec2 coords)
|
|
{
|
|
// If shadow intensity is 0, change nothing
|
|
if (shadow_intensity == 0)
|
|
{
|
|
return color;
|
|
}
|
|
|
|
// Get how far the coords are from the center
|
|
vec2 distances_from_center = abs(window_center - coords);
|
|
|
|
// Darken pixels close to the edges of the screen in a polynomial fashion
|
|
float brightness = 1;
|
|
brightness *= -pow((distances_from_center.y/window_center.y)*shadow_cutoff,
|
|
(5/shadow_intensity)*2)+1;
|
|
brightness *= -pow((distances_from_center.x/window_center.x)*shadow_cutoff,
|
|
(5/shadow_intensity)*2)+1;
|
|
color.xyz *= brightness;
|
|
|
|
return color;
|
|
}
|
|
|
|
// Applies a transformation to our window pixels to simulate
|
|
// a curved screen
|
|
ivec2 curve_coords_spheric(vec2 coords)
|
|
{
|
|
// Offset coords
|
|
coords -= window_center;
|
|
vec2 curved_coords;
|
|
|
|
// For this transform imagine a sphere in a 3d space with the
|
|
// window as a 2d plane tangent to that sphere
|
|
// For simplicity, we center the sphere at 0,0,0
|
|
// The coordinates of the projection share x and y with our window pixel
|
|
// We find Z using the formula for a sphere
|
|
vec3 projection_coords3d = vec3(coords.x, coords.y,
|
|
sqrt(pow(radius+sph_distance,2)-
|
|
pow(coords.x,2)-
|
|
pow(coords.y,2)));
|
|
|
|
// That vector goes from the center of the sphere to the projection of a pixel
|
|
// of our window onto the sphere's surface
|
|
// Let's scale it until it hits our window plane
|
|
projection_coords3d *= ((radius+sph_distance)/projection_coords3d.z);
|
|
curved_coords = projection_coords3d.xy;
|
|
|
|
// Compensate for starting coords offset
|
|
curved_coords += window_center;
|
|
|
|
return ivec2(curved_coords);
|
|
}
|
|
|
|
|
|
// Gets a color for a pixel with all the coordinate and
|
|
// downscale changes
|
|
vec4 get_pixel(vec2 coords)
|
|
{
|
|
// If pixel is at the edge of the window, return a completely black color
|
|
if (coords.x >=window_size.x-1 || coords.y >=window_size.y-1 ||
|
|
coords.x <=0 || coords.y <=0)
|
|
{
|
|
return outside_color;
|
|
}
|
|
vec4 color = texelFetch(tex, ivec2(coords), 0);
|
|
return default_post_processing(color);
|
|
}
|
|
|
|
// Gets the color from a downscaled block
|
|
vec4 get_block_color(vec2 coords)
|
|
{
|
|
// If downscale is set to 1, just return a pixel
|
|
if (downscale_factor < 2)
|
|
{
|
|
return get_pixel(coords);
|
|
}
|
|
|
|
// Relative position of pixel inside the block
|
|
ivec2 relative_position;
|
|
relative_position.xy = ivec2(coords).xy % downscale_factor;
|
|
|
|
// Average all colors from pixels inside the block
|
|
vec4 average = vec4(0, 0 , 0, 0);
|
|
for (int i = 0; i < downscale_factor; i++)
|
|
{
|
|
for (int j = 0; j < downscale_factor; j++)
|
|
{
|
|
average.xyzw += get_pixel(vec2(coords.x + i - relative_position.x,
|
|
coords.y + j - relative_position.y));
|
|
}
|
|
}
|
|
average /= pow(downscale_factor, 2);
|
|
|
|
return average;
|
|
}
|
|
|
|
|
|
// Main shader function
|
|
vec4 window_shader() {
|
|
|
|
// Apply curvature transform to coords
|
|
vec2 curved_coords = curve_coords_spheric(texcoord);
|
|
|
|
// Fetch the color
|
|
vec4 c = get_block_color(curved_coords);
|
|
|
|
// Fetch colors from close pixels to apply color distortion
|
|
vec4 c_right = get_block_color(vec2(curved_coords.x+2, curved_coords.y));
|
|
vec4 c_left = get_block_color(vec2(curved_coords.x-2, curved_coords.y));
|
|
|
|
// Mix red and blue colors
|
|
c = vec4(c_left.x, c.y, c_right.z, c.w);
|
|
|
|
// Apply scanlines
|
|
c.xyz *= sin(2*PI*sc_freq*(texcoord).y)/(2/sc_intensity) +
|
|
1 - sc_intensity/2;
|
|
|
|
// Also apply scanlines to x axis if grid is enabled
|
|
if (grid == true)
|
|
{
|
|
c.xyz *= sin(2*PI*sc_freq*(texcoord).x)/(2/sc_intensity) +
|
|
1 - sc_intensity/2;
|
|
}
|
|
|
|
// Apply flash
|
|
if (curved_coords.y >=flash-(window_size.y/10) && curved_coords.y <=flash)
|
|
{
|
|
c.xyz *= flash_intensity*(pow(((flash-curved_coords.y)/(window_size.y/10))-1,2)
|
|
+ 1/flash_intensity);
|
|
}
|
|
|
|
// Darken pixel
|
|
c = darken_color(c, curved_coords);
|
|
return (c);
|
|
}
|