add modular image adjustment shader

This commit is contained in:
hunterk 2020-04-28 22:37:24 -05:00
parent 5fd80ad7ea
commit 239b6f01be
33 changed files with 1159 additions and 0 deletions

12
include/img/black_lvl.h Normal file
View file

@ -0,0 +1,12 @@
#ifndef BLACK_LVL
#define BLACK_LVL
#pragma parameter ia_black_level "Black Level" 0.00 -0.50 0.50 0.01
vec3 black_level(vec3 in_col){
vec3 out_col = in_col - vec3(ia_black_level);
out_col *= (vec3(1.0) / vec3(1.0 - ia_black_level));
return out_col;
}
#endif

View file

@ -0,0 +1,12 @@
#ifndef BLACK_LVL
#define BLACK_LVL
#pragma parameter ia_black_level "Black Level" 0.00 -0.50 0.50 0.01
vec3 black_level(vec3 in_col){
vec3 out_col = in_col;
out_col += (ia_black_level / 20.0) * (1.0 - out_col);
return out_col;
}
#endif

17
include/img/border_mask.h Normal file
View file

@ -0,0 +1,17 @@
#ifndef BORDER_MASK
#define BORDER_MASK
#pragma parameter ia_TOPMASK "Overscan Mask Top" 0.0 0.0 1.0 0.0025
#pragma parameter ia_BOTMASK "Overscan Mask Bottom" 0.0 0.0 1.0 0.0025
#pragma parameter ia_LMASK "Overscan Mask Left" 0.0 0.0 1.0 0.0025
#pragma parameter ia_RMASK "Overscan Mask Right" 0.0 0.0 1.0 0.0025
vec3 border_mask(vec3 in_col, vec2 coord){
vec3 out_col = (coord.y > ia_TOPMASK && coord.y < (1.0 - ia_BOTMASK)) ?
in_col : vec3(0.0);
out_col = (coord.x > ia_LMASK && coord.x < (1.0 - ia_RMASK)) ?
out_col : vec3(0.0);
return out_col;
}
#endif

16
include/img/bright_con.h Normal file
View file

@ -0,0 +1,16 @@
#ifndef BRIGHT_CON
#define BRIGHT_CON
#pragma parameter ia_contrast "Contrast" 1.0 0.0 10.0 0.05
#pragma parameter ia_bright_boost "Brightness Boost" 0.0 -1.0 1.0 0.05
vec3 cntrst(vec3 in_col){
vec3 out_col = in_col - 0.5;
out_col *= ia_contrast;
out_col += 0.5;
out_col += ia_bright_boost;
out_col = clamp(out_col, 0.0, 1.0);
return out_col;
}
#endif

78
include/img/cgwg_warp.h Normal file
View file

@ -0,0 +1,78 @@
#ifndef CURV
#define CURV
#pragma parameter Radius "cgwg Curvature Radius" 2.0 0.1 10.0 0.1
#pragma parameter Distance "cgwg Viewing Distance" 1.5 0.1 3.0 0.1
#pragma parameter x_tilt "Horizontal Tilt" 0.0 -0.5 0.5 0.05
#pragma parameter y_tilt "Vertical Tilt" 0.0 -0.5 0.5 0.05
// cgwg's geom
// license: GPLv2
vec2 sinangle = sin(vec2(x_tilt, y_tilt));
vec2 cosangle = cos(vec2(x_tilt, y_tilt));
const vec2 aspect = vec2(1.0, 0.75);
#define FIX(c) max(abs(c), 1e-5);
float intersect(vec2 xy)
{
float A = dot(xy,xy) + Distance*Distance;
float B = 2.0*(Radius*(dot(xy,sinangle) - Distance*cosangle.x*cosangle.y) - Distance*Distance);
float C = Distance*Distance + 2.0*Radius*Distance*cosangle.x*cosangle.y;
return (-B-sqrt(B*B - 4.0*A*C))/(2.0*A);
}
vec2 fwtrans(vec2 uv)
{
float r = FIX(sqrt(dot(uv,uv)));
uv *= sin(r/Radius)/r;
float x = 1.0-cos(r/Radius);
float D = Distance/Radius + x*cosangle.x*cosangle.y+dot(uv,sinangle);
return Distance*(uv*cosangle-x*sinangle)/D;
}
vec2 bkwtrans(vec2 xy)
{
float c = intersect(xy);
vec2 point = (vec2(c, c)*xy - vec2(-Radius, -Radius)*sinangle) / vec2(Radius, Radius);
vec2 poc = point/cosangle;
vec2 tang = sinangle/cosangle;
float A = dot(tang, tang) + 1.0;
float B = -2.0*dot(poc, tang);
float C = dot(poc, poc) - 1.0;
float a = (-B + sqrt(B*B - 4.0*A*C)) / (2.0*A);
vec2 uv = (point - a*sinangle) / cosangle;
float r = Radius*acos(a);
r = FIX(r);
return uv*r/sin(r/Radius);
}
vec3 maxscale()
{
vec2 c = bkwtrans(-Radius * sinangle / (1.0 + Radius/Distance*cosangle.x*cosangle.y));
vec2 a = vec2(0.5,0.5)*aspect;
vec2 lo = vec2(fwtrans(vec2(-a.x, c.y)).x,
fwtrans(vec2( c.x, -a.y)).y)/aspect;
vec2 hi = vec2(fwtrans(vec2(+a.x, c.y)).x,
fwtrans(vec2( c.x, +a.y)).y)/aspect;
return vec3((hi+lo)*aspect*0.5,max(hi.x-lo.x,hi.y-lo.y));
}
vec2 warp(vec2 coord)
{
vec3 stretch = maxscale();
coord = (coord - vec2(0.5, 0.5))*aspect*stretch.z + stretch.xy;
return (bkwtrans(coord) /
vec2(1.0, 1.0)/aspect + vec2(0.5, 0.5));
}
#endif

13
include/img/channel_mix.h Normal file
View file

@ -0,0 +1,13 @@
#ifndef CHANNEL_MIX
#define CHANNEL_MIX
#pragma parameter ia_rr "Red Channel" 1.0 0.0 2.0 0.01
#pragma parameter ia_gg "Green Channel" 1.0 0.0 2.0 0.01
#pragma parameter ia_bb "Blue Channel" 1.0 0.0 2.0 0.01
vec3 channel_mix(vec3 in_col){
vec3 out_col = in_col * vec3(ia_rr, ia_gg, ia_bb);
return out_col;
}
#endif

23
include/img/col_mangler.h Normal file
View file

@ -0,0 +1,23 @@
#ifndef CHANNEL_MIX
#define CHANNEL_MIX
#pragma parameter ia_rr "Red Channel" 1.0 0.0 2.0 0.01
#pragma parameter ia_gg "Green Channel" 1.0 0.0 2.0 0.01
#pragma parameter ia_bb "Blue Channel" 1.0 0.0 2.0 0.01
#pragma parameter ia_rg "Red-Green Tint" 0.0 0.0 1.0 0.005
#pragma parameter ia_rb "Red-Blue Tint" 0.0 0.0 1.0 0.005
#pragma parameter ia_gr "Green-Red Tint" 0.0 0.0 1.0 0.005
#pragma parameter ia_gb "Green-Blue Tint" 0.0 0.0 1.0 0.005
#pragma parameter ia_br "Blue-Red Tint" 0.0 0.0 1.0 0.005
#pragma parameter ia_bg "Blue-Green Tint" 0.0 0.0 1.0 0.005
mat3 mangler = mat3( ia_rr, ia_rg, ia_rb, //red channel
ia_gr, ia_gg, ia_gb, //green channel
ia_br, ia_bg, ia_bb); //blue channel
vec3 channel_mix(vec3 in_col){
vec3 out_col = in_col * mangler;
return out_col;
}
#endif

6
include/img/col_tools.h Normal file
View file

@ -0,0 +1,6 @@
#ifndef COL_TOOLS
#define COL_TOOLS
#include "../../misc/colorspace-tools.h"
#endif

20
include/img/corner.h Normal file
View file

@ -0,0 +1,20 @@
#ifndef CORNER
#define CORNER
#pragma parameter cornersize "Corner Size" 0.03 0.001 1.0 0.005
#pragma parameter cornersmooth "Corner Smoothness" 1000.0 80.0 2000.0 100.0
const vec2 corner_aspect = vec2(1.0, 0.75);
float corner(vec2 coord)
{
coord = (coord - vec2(0.5)) + vec2(0.5, 0.5);
coord = min(coord, vec2(1.0) - coord) * corner_aspect;
vec2 cdist = vec2(cornersize);
coord = (cdist - min(coord, cdist));
float dist = sqrt(dot(coord, coord));
return clamp((cdist.x - dist)*cornersmooth, 0.0, 1.0);
}
#endif

113
include/img/curvature.h Normal file
View file

@ -0,0 +1,113 @@
#ifndef CURV
#define CURV
// A collection of 2D curvature/warp functions
// torridgristle
vec2 tg_warp(vec2 texCoord){
vec2 Distortion = vec2(warpX, warpY) * 15.;
vec2 curvedCoords = texCoord * 2.0 - 1.0;
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+Distortion*0.2))));
curvedCoords = curvedCoords / (1.0-pow(vec2(0.29289321881345247559915563789515),(1.0/(vec2(1.0)+Distortion*0.2))));
curvedCoords = curvedCoords * 0.5 + 0.5;
return curvedCoords;
}
// lottes
// Distortion of scanlines, and end of screen alpha.
vec2 tl_warp(vec2 pos)
{
pos = pos*2.0-1.0;
pos *= vec2(1.0 + (pos.y*pos.y)*warpX, 1.0 + (pos.x*pos.x)*warpY);
return pos*0.5 + 0.5;
}
// cgwg's geom
// license: GPLv2
const float d = 1.5;
const vec2 sinangle = vec2(1.0);
const vec2 cosangle = vec2(1.0);
const vec2 aspect = vec2(1.0, 0.75);
float R = max(warpX, warpY);
#define FIX(c) max(abs(c), 1e-5);
float intersect(vec2 xy)
{
float A = dot(xy,xy) + d*d;
float B = 2.0*(R*(dot(xy,sinangle) - d*cosangle.x*cosangle.y) - d*d);
float C = d*d + 2.0*R*d*cosangle.x*cosangle.y;
return (-B-sqrt(B*B - 4.0*A*C))/(2.0*A);
}
vec2 fwtrans(vec2 uv)
{
float r = FIX(sqrt(dot(uv,uv)));
uv *= sin(r/R)/r;
float x = 1.0-cos(r/R);
float D = d/R + x*cosangle.x*cosangle.y+dot(uv,sinangle);
return d*(uv*cosangle-x*sinangle)/D;
}
vec3 maxscale()
{
vec2 c = bkwtrans(-R * sinangle / (1.0 + R/d*cosangle.x*cosangle.y));
vec2 a = vec2(0.5,0.5)*aspect;
vec2 lo = vec2(fwtrans(vec2(-a.x, c.y)).x,
fwtrans(vec2( c.x, -a.y)).y)/aspect;
vec2 hi = vec2(fwtrans(vec2(+a.x, c.y)).x,
fwtrans(vec2( c.x, +a.y)).y)/aspect;
return vec3((hi+lo)*aspect*0.5,max(hi.x-lo.x,hi.y-lo.y));
}
vec2 bkwtrans(vec2 xy)
{
float c = intersect(xy);
vec2 point = (vec2(c, c)*xy - vec2(-R, -R)*sinangle) / vec2(R, R);
vec2 poc = point/cosangle;
vec2 tang = sinangle/cosangle;
float A = dot(tang, tang) + 1.0;
float B = -2.0*dot(poc, tang);
float C = dot(poc, poc) - 1.0;
float a = (-B + sqrt(B*B - 4.0*A*C)) / (2.0*A);
vec2 uv = (point - a*sinangle) / cosangle;
float r = FIX(R*acos(a));
return uv*r/sin(r/R);
}
vec2 cgwg_warp(vec2 coord)
{
vec3 stretch = max_scale();
coord = (coord - vec2(0.5, 0.5))*aspect*stretch.z + stretch.xy;
return (bkwtrans(coord) /
vec2(1.0, 1.0)/aspect + vec2(0.5, 0.5));
}
float corner(vec2 coord)
{
coord = (coord - vec2(0.5)) + vec2(0.5, 0.5);
coord = min(coord, vec2(1.0) - coord) * aspect;
vec2 cdist = vec2(cornersize);
coord = (cdist - min(coord, cdist));
float dist = sqrt(dot(coord, coord));
return clamp((cdist.x - dist)*cornersmooth, 0.0, 1.0);
}
#endif

19
include/img/exp_gamma.h Normal file
View file

@ -0,0 +1,19 @@
#ifndef GAMMA
#define GAMMA
#pragma parameter ia_monitor_gamma "Physical Monitor Gamma" 2.2 0.1 5.0 0.05
#pragma parameter ia_target_gamma_r "Simulated Gamma R Channel" 2.2 0.1 5.0 0.05
#pragma parameter ia_target_gamma_g "Simulated Gamma G Channel" 2.2 0.1 5.0 0.05
#pragma parameter ia_target_gamma_b "Simulated Gamma B Channel" 2.2 0.1 5.0 0.05
vec3 gamma_in(vec3 in_col){
vec3 out_col = pow(in_col, vec3(ia_target_gamma_r, ia_target_gamma_g, ia_target_gamma_b));
return out_col;
}
vec3 gamma_out(vec3 in_col){
vec3 out_col= pow(in_col, 1./vec3(ia_monitor_gamma));
return out_col;
}
#endif

27
include/img/film_grain.h Normal file
View file

@ -0,0 +1,27 @@
#ifndef FILM_GRAIN
#define FILM_GRAIN
#pragma parameter ia_GRAIN_STR "Grain Strength" 0.0 0.0 72.0 3.0
#include "col_tools.h"
//https://www.shadertoy.com/view/4sXSWs strength= 16.0
vec3 rgb_grain(vec2 uv, float strength, uint counter){
float x = ((uv.x + 4.0 ) * (uv.y + 5.0 ) * ((mod(vec2(counter, counter).x, 800.0) + 10.0) * 8.0));
float y = ((uv.x + 5.0 ) * (uv.y + 6.0 ) * ((mod(vec2(counter, counter).x, 678.0) + 8.0) * 6.0));
float z = ((uv.x + 6.0 ) * (uv.y + 4.0 ) * ((mod(vec2(counter, counter).x, 498.0) + 6.0) * 10.0));
float r = (mod((mod(x, 13.0) + 1.0) * (mod(x, 123.0) + 1.0), 0.01)-0.005);
float g = (mod((mod(y, 13.0) + 1.0) * (mod(y, 123.0) + 1.0), 0.01)-0.005);
float b = (mod((mod(z, 13.0) + 1.0) * (mod(z, 123.0) + 1.0), 0.01)-0.005);
return vec3(r, g, b) * strength;
}
vec3 luma_grain(vec3 in_col, vec2 uv, float strength, uint counter){
float x = (uv.x + 4.0 ) * (uv.y + 4.0 ) * ((mod(vec2(counter, counter).x, 800.0) + 10.0) * 10.0);
x = (mod((mod(x, 13.0) + 1.0) * (mod(x, 123.0) + 1.0), 0.01)-0.005) * strength;
vec3 out_col = RGBtoYIQ(in_col);
out_col.r += x;
return YIQtoRGB(out_col);
}
#endif

19
include/img/gamma_srgb.h Normal file
View file

@ -0,0 +1,19 @@
#ifndef GAMMA
#define GAMMA
#pragma parameter gamma_in_lvl "CRT Gamma" 2.4 0.0 3.0 0.05
#pragma parameter gamma_out_lvl "LCD Gamma" 2.2 0.0 3.0 0.05
#include "moncurve.h"
vec3 gamma_in(vec3 in_col){
vec3 out_col = moncurve_f_f3(in_col, gamma_in_lvl + 0.15, 0.055);
return out_col;
}
vec3 gamma_out(vec3 in_col){
vec3 out_col = moncurve_r_f3(in_col, gamma_out_lvl + 0.20, 0.055);
return out_col;
}
#endif

View file

@ -0,0 +1,23 @@
#ifndef CURV
#define CURV
#pragma parameter warpX "Warp X" 0.031 0.0 0.125 0.01
#pragma parameter warpY "Warp Y" 0.041 0.0 0.125 0.01
vec2 Distortion = vec2(warpX, warpY) * 15.;
vec2 warp(vec2 texCoord){
vec2 Distortion = vec2(warpX, warpY) * 15.;
vec2 curvedCoords = texCoord * 2.0 - 1.0;
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+Distortion*0.2))));
curvedCoords = curvedCoords / (1.0-pow(vec2(0.29289321881345247559915563789515),(1.0/(vec2(1.0)+Distortion*0.2))));
curvedCoords = curvedCoords * 0.5 + 0.5;
return curvedCoords;
}
#endif

View file

@ -0,0 +1,71 @@
#ifndef HELPER_MACROS
#define HELPER_MACROS
// All of the parameter macros in one place
// replace 'global' with whichever struct you use for parameters
#define ia_FLIP_HORZ global.ia_FLIP_HORZ
#define ia_FLIP_VERT global.ia_FLIP_VERT
#define ia_overscan_percent_x global.ia_overscan_percent_x
#define ia_overscan_percent_y global.ia_overscan_percent_y
#define ia_ZOOM global.ia_ZOOM
#define ia_XPOS global.ia_XPOS
#define ia_YPOS global.ia_YPOS
#define ia_GRAIN_STR global.ia_GRAIN_STR
#define ia_SHARPEN global.ia_SHARPEN
#define ia_saturation global.ia_saturation
#define ia_luminance global.ia_luminance
#define ia_contrast global.ia_contrast
#define ia_bright_boost global.ia_bright_boost
#define ia_black_level global.ia_black_level
#define ia_target_gamma_r global.ia_target_gamma_r
#define ia_target_gamma_g global.ia_target_gamma_g
#define ia_target_gamma_b global.ia_target_gamma_b
#define ia_monitor_gamma global.ia_monitor_gamma
#define ia_R global.ia_R
#define ia_G global.ia_G
#define ia_B global.ia_B
#define ia_TOPMASK global.ia_TOPMASK
#define ia_BOTMASK global.ia_BOTMASK
#define ia_LMASK global.ia_LMASK
#define ia_RMASK global.ia_RMASK
#define ia_rr global.ia_rr
#define ia_gg global.ia_gg
#define ia_bb global.ia_bb
#define ia_rg global.ia_rg
#define ia_rb global.ia_rb
#define ia_gr global.ia_gr
#define ia_gb global.ia_gb
#define ia_br global.ia_br
#define ia_bg global.ia_bg
#define temperature global.temperature
#define luma_preserve global.luma_preserve
#define wp_red global.wp_red
#define wp_green global.wp_green
#define wp_blue global.wp_blue
#define integer_scale global.integer_scale
#define overscale global.overscale
#define ar_num global.ar_num
#define ar_den global.ar_den
#define g_hpfix global.g_hpfix
#define g_cntrst global.g_cntrst
#define g_mid global.g_mid
#define mask_strength global.mask_strength
#define mask_picker global.mask_picker
#define LUT_Size1 global.LUT_Size1
#define LUT_Size2 global.LUT_Size2
#define g_vignette global.g_vignette
#define g_vstr global.g_vstr
#define g_vpower global.g_vpower
#define gamma_in_lvl global.gamma_in_lvl
#define gamma_out_lvl global.gamma_out_lvl
#define warpX global.warpX
#define warpY global.warpY
#define cornersize global.cornersize
#define cornersmooth global.cornersmooth
#define Radius global.Radius
#define Distance global.Distance
#define x_tilt global.x_tilt
#define y_tilt global.y_tilt
#endif

16
include/img/image_flip.h Normal file
View file

@ -0,0 +1,16 @@
#ifndef IMAGE_FLIP
#define IMAGE_FLIP
// wraps the Position in gl_Position calculation
#pragma parameter ia_FLIP_HORZ "Flip Horiz Axis" 0.0 0.0 1.0 1.0
#pragma parameter ia_FLIP_VERT "Flip Vert Axis" 0.0 0.0 1.0 1.0
vec4 flip_pos(vec4 in_pos){
vec4 out_pos = in_pos;
out_pos.x = (ia_FLIP_HORZ < 0.5) ? out_pos.x : 1.0 - out_pos.x;
out_pos.y = (ia_FLIP_VERT < 0.5) ? out_pos.y : 1.0 - out_pos.y;
return out_pos;
}
#endif

28
include/img/int_ar.h Normal file
View file

@ -0,0 +1,28 @@
#ifndef INT_AR
#define INT_AR
// Forces integer scaling and arbitrary aspect ratio
// by hunterk
// license: public domain
// Apply in the vertex to the texCoord
#pragma parameter ar_num "Aspect Ratio Numerator" 64.0 1.0 256. 1.0
#pragma parameter ar_den "Aspect Ratio Denominator" 49.0 1.0 256. 1.0
#pragma parameter integer_scale "Force Integer Scaling" 0.0 0.0 1.0 1.0
#pragma parameter overscale "Integer Overscale" 0.0 0.0 1.0 1.0
const vec2 middle = vec2(0.4999999, 0.4999999);
vec2 int_ar(vec2 coord, vec4 tex_size, vec4 out_size){
vec2 corrected_size = tex_size.xy * vec2(ar_num / ar_den, 1.0)
* vec2(tex_size.y / tex_size.x, 1.0);
float full_scale = (integer_scale > 0.5) ? floor(out_size.y /
tex_size.y) + overscale : out_size.y / tex_size.y;
vec2 scale = (out_size.xy / corrected_size) / full_scale;
vec2 diff = coord.xy - middle;
vec2 ar_coord = middle + diff * scale;
return ar_coord;
}
#endif

16
include/img/lottes_warp.h Normal file
View file

@ -0,0 +1,16 @@
#ifndef CURV
#define CURV
#pragma parameter warpX "Warp X" 0.031 0.0 0.125 0.01
#pragma parameter warpY "Warp Y" 0.041 0.0 0.125 0.01
// Distortion of scanlines, and end of screen alpha.
vec2 warp(vec2 pos)
{
pos = pos*2.0-1.0;
pos *= vec2(1.0 + (pos.y*pos.y)*warpX, 1.0 + (pos.x*pos.x)*warpY);
return pos*0.5 + 0.5;
}
#endif

18
include/img/lum_chrom.h Normal file
View file

@ -0,0 +1,18 @@
#ifndef SAT_LUM
#define SAT_LUM
#pragma parameter ia_saturation "Chrominance" 1.0 0.01 2.0 0.01
#pragma parameter ia_luminance "Luminance" 1.0 0.0 2.0 0.01
#include "col_tools.h"
// Note: This saturation should be similar to broadcast television.
// 0% chrome == pure luma.
vec3 sat_lum(vec3 in_col){
vec3 out_col = RGBtoYIQ(in_col);
out_col *= vec3(ia_luminance, ia_saturation, ia_saturation);
return YIQtoRGB(out_col);
}
#endif

29
include/img/lut1.h Normal file
View file

@ -0,0 +1,29 @@
#ifndef LUT
#define LUT
// only #include in the fragment stage
#pragma parameter LUT_Size1 "LUT Size 1" 16.0 1.0 64.0 1.0
layout(set = 0, binding = 3) uniform sampler2D SamplerLUT1;
// This shouldn't be necessary but it seems some undefined values can
// creep in and each GPU vendor handles that differently. This keeps
// all values within a safe range
vec3 mixfix(vec3 a, vec3 b, float c)
{
return (a.z < 1.0) ? mix(a, b, c) : a;
}
vec3 lut1(vec3 in_col)
{
float red = ( in_col.r * (LUT_Size1 - 1.0) + 0.4999 ) / (LUT_Size1 * LUT_Size1);
float green = ( in_col.g * (LUT_Size1 - 1.0) + 0.4999 ) / LUT_Size1;
float blue1 = (floor( in_col.b * (LUT_Size1 - 1.0) ) / LUT_Size1) + red;
float blue2 = (ceil( in_col.b * (LUT_Size1 - 1.0) ) / LUT_Size1) + red;
float mixer = clamp(max((in_col.b - blue1) / (blue2 - blue1), 0.0), 0.0, 32.0);
vec3 color1 = texture( SamplerLUT1, vec2( blue1, green )).rgb;
vec3 color2 = texture( SamplerLUT1, vec2( blue2, green )).rgb;
return mixfix(color1, color2, mixer);
}
#endif

43
include/img/lut2.h Normal file
View file

@ -0,0 +1,43 @@
#ifndef LUT
#define LUT
// only #include in the fragment stage
#pragma parameter LUT_Size1 "LUT Size 1" 16.0 1.0 64.0 1.0
#pragma parameter LUT_Size2 "LUT Size 2" 16.0 1.0 64.0 1.0
layout(set = 0, binding = 3) uniform sampler2D SamplerLUT1;
layout(set = 0, binding = 4) uniform sampler2D SamplerLUT2;
// This shouldn't be necessary but it seems some undefined values can
// creep in and each GPU vendor handles that differently. This keeps
// all values within a safe range
vec3 mixfix(vec3 a, vec3 b, float c)
{
return (a.z < 1.0) ? mix(a, b, c) : a;
}
vec3 lut1(vec3 in_col)
{
float red = ( in_col.r * (LUT_Size1 - 1.0) + 0.4999 ) / (LUT_Size1 * LUT_Size1);
float green = ( in_col.g * (LUT_Size1 - 1.0) + 0.4999 ) / LUT_Size1;
float blue1 = (floor( in_col.b * (LUT_Size1 - 1.0) ) / LUT_Size1) + red;
float blue2 = (ceil( in_col.b * (LUT_Size1 - 1.0) ) / LUT_Size1) + red;
float mixer = clamp(max((in_col.b - blue1) / (blue2 - blue1), 0.0), 0.0, 32.0);
vec3 color1 = texture( SamplerLUT1, vec2( blue1, green )).rgb;
vec3 color2 = texture( SamplerLUT1, vec2( blue2, green )).rgb;
return mixfix(color1, color2, mixer);
}
vec3 lut2(vec3 in_col)
{
float red = ( in_col.r * (LUT_Size2 - 1.0) + 0.4999 ) / (LUT_Size2 * LUT_Size2);
float green = ( in_col.g * (LUT_Size2 - 1.0) + 0.4999 ) / LUT_Size2;
float blue1 = (floor( in_col.b * (LUT_Size2 - 1.0) ) / LUT_Size2) + red;
float blue2 = (ceil( in_col.b * (LUT_Size2 - 1.0) ) / LUT_Size2) + red;
float mixer = clamp(max((in_col.b - blue1) / (blue2 - blue1), 0.0), 0.0, 32.0);
vec3 color1 = texture( SamplerLUT2, vec2( blue1, green )).rgb;
vec3 color2 = texture( SamplerLUT2, vec2( blue2, green )).rgb;
return mixfix(color1, color2, mixer);
}
#endif

45
include/img/moncurve.h Normal file
View file

@ -0,0 +1,45 @@
#ifndef MONCURVE
#define MONCURVE
float moncurve_f( float color, float gamma, float offs)
{
// Forward monitor curve
color = clamp(color, 0.0, 1.0);
float fs = (( gamma - 1.0) / offs) * pow( offs * gamma / ( ( gamma - 1.0) * ( 1.0 + offs)), gamma);
float xb = offs / ( gamma - 1.0);
color = ( color > xb) ? pow( ( color + offs) / ( 1.0 + offs), gamma) : color * fs;
return color;
}
vec3 moncurve_f_f3( vec3 color, float gamma, float offs)
{
color.r = moncurve_f( color.r, gamma, offs);
color.g = moncurve_f( color.g, gamma, offs);
color.b = moncurve_f( color.b, gamma, offs);
return color.rgb;
}
float moncurve_r( float color, float gamma, float offs)
{
// Reverse monitor curve
color = clamp(color, 0.0, 1.0);
float yb = pow( offs * gamma / ( ( gamma - 1.0) * ( 1.0 + offs)), gamma);
float rs = pow( ( gamma - 1.0) / offs, gamma - 1.0) * pow( ( 1.0 + offs) / gamma, gamma);
color = ( color > yb) ? ( 1.0 + offs) * pow( color, 1.0 / gamma) - offs : color * rs;
return color;
}
vec3 moncurve_r_f3( vec3 color, float gamma, float offs)
{
color.r = moncurve_r( color.r, gamma, offs);
color.g = moncurve_r( color.g, gamma, offs);
color.b = moncurve_r( color.b, gamma, offs);
return color.rgb;
}
#endif

View file

@ -0,0 +1,67 @@
#ifndef PARAM_FLOATS
#define PARAM_FLOATS
// The parameters that go into your struct
// Collected here for tidiness
float ia_FLIP_HORZ;
float ia_FLIP_VERT;
float ia_overscan_percent_x;
float ia_overscan_percent_y;
float ia_ZOOM;
float ia_XPOS;
float ia_YPOS;
float ia_GRAIN_STR;
float ia_SHARPEN;
float ia_saturation;
float ia_luminance;
float ia_contrast;
float ia_bright_boost;
float ia_black_level;
float ia_target_gamma_r;
float ia_target_gamma_g;
float ia_target_gamma_b;
float ia_monitor_gamma;
float ia_TOPMASK;
float ia_BOTMASK;
float ia_LMASK;
float ia_RMASK;
float ia_rr;
float ia_gg;
float ia_bb;
float ia_rg;
float ia_rb;
float ia_gr;
float ia_gb;
float ia_br;
float ia_bg;
float temperature;
float luma_preserve;
float wp_red;
float wp_green;
float wp_blue;
float ar_num;
float ar_den;
float integer_scale;
float overscale;
float g_hpfix;
float g_cntrst;
float g_mid;
float mask_strength;
float mask_picker;
float LUT_Size1;
float LUT_Size2;
float g_vignette;
float g_vstr;
float g_vpower;
float gamma_in_lvl;
float gamma_out_lvl;
float warpX;
float warpY;
float cornersize;
float cornersmooth;
float Radius;
float Distance;
float x_tilt;
float y_tilt;
#endif

21
include/img/sat_lum.h Normal file
View file

@ -0,0 +1,21 @@
#ifndef SAT_LUM
#define SAT_LUM
#pragma parameter ia_saturation "Saturation" 1.0 0.0 5.0 0.1
#pragma parameter ia_luminance "Value" 1.0 0.0 2.0 0.1
#include "col_tools.h"
// Note: saturation 0 does not mean grayscale in this case.
// It's purely a measure of the saturation of the colors.
// That is, pure r, g and b each look white.
vec3 sat_lum(vec3 in_color){
vec3 out_color = RGBtoHSV(in_color);
out_color *= vec3(1.0, ia_saturation, ia_luminance);
out_color = HSVtoRGB(out_color);
out_color = clamp(out_color, 0.0, 1.0);
return out_color;
}
#endif

24
include/img/sharpening.h Normal file
View file

@ -0,0 +1,24 @@
#ifndef SHARP_COORD
#define SHARP_COORD
// wrap texture coordinate when sampling
#pragma parameter ia_SHARPEN "Sharpen" 0.0 0.0 1.0 0.05
const vec2 offset = vec2(0.5, 0.5);
// based on "Improved texture interpolation" by Iñigo Quílez
// Original description: http://www.iquilezles.org/www/articles/texture/texture.htm
vec2 sharp(vec2 in_coord, vec4 tex_size){
vec2 p = in_coord.xy;
p = p * tex_size.xy + offset;
vec2 i = floor(p);
vec2 f = p - i;
f = f * f * f * (f * (f * 6.0 - vec2(15.0, 15.0)) + vec2(10.0, 10.0));
p = i + f;
p = (p - offset) * tex_size.zw;
p = mix(in_coord, p, ia_SHARPEN);
return p;
}
#endif

View file

@ -0,0 +1,54 @@
#ifndef SIG_CON
#define SIG_CON
// borrowed from dogway's grade shader
#pragma parameter g_cntrst "Contrast" 0.0 -1.0 1.0 0.05
#pragma parameter g_mid "Contrast Pivot" 0.5 0.0 1.0 0.01
#pragma parameter g_hpfix "Contrast Hotspot Fix" 0.0 0.0 1.0 1.00
#include "col_tools.h"
#include "moncurve.h"
// Performs better in gamma encoded space
float contrast_sigmoid(float color, float cont, float pivot){
cont = pow(cont + 1., 3.);
float knee = 1. / (1. + exp(cont * pivot));
float shldr = 1. / (1. + exp(cont * (pivot - 1.)));
color = (1. / (1. + exp(cont * (pivot - color))) - knee) / (shldr - knee);
return color;
}
// Performs better in gamma encoded space
float contrast_sigmoid_inv(float color, float cont, float pivot){
cont = pow(cont - 1., 3.);
float knee = 1. / (1. + exp (cont * pivot));
float shldr = 1. / (1. + exp (cont * (pivot - 1.)));
color = pivot - log(1. / (color * (shldr - knee) + knee) - 1.) / cont;
return color;
}
// Saturation agnostic sigmoidal contrast
vec3 cntrst(vec3 in_col){
vec3 Yxy = XYZtoYxy(sRGB_to_XYZ(in_col));
float toGamma = clamp(moncurve_r(Yxy.r, 2.40, 0.055), 0.0, 1.0);
toGamma = (g_hpfix == 0.0) ? toGamma : ((Yxy.r > 0.5) ?
contrast_sigmoid_inv(toGamma, 2.3, 0.5) : toGamma);
float sigmoid = (g_cntrst > 0.0) ? contrast_sigmoid(toGamma, g_cntrst, g_mid) : contrast_sigmoid_inv(toGamma, g_cntrst, g_mid);
vec3 out_col = vec3(moncurve_f(sigmoid, 2.40, 0.055), Yxy.g, Yxy.b);
vec3 XYZsrgb = clamp(XYZ_to_sRGB(YxytoXYZ(out_col)), 0.0, 1.0);
out_col = (g_cntrst == 0.0) && (g_hpfix == 0.0) ? in_col :
((g_cntrst != 0.0) || (g_hpfix != 0.0) ? XYZsrgb : in_col);
return out_col;
}
#endif

View file

@ -0,0 +1,23 @@
#ifndef CROP_ZOOM_PAN
#define CROP_ZOOM_PAN
// wraps the standard TexCoord
#pragma parameter ia_overscan_percent_x "Stretch Width" 0.0 -25.0 25.0 1.0
#pragma parameter ia_overscan_percent_y "Stretch Height" 0.0 -25.0 25.0 1.0
#pragma parameter ia_ZOOM "Zoom In/Out" 1.0 0.0 4.0 0.01
#pragma parameter ia_XPOS "Pan X" 0.0 -2.0 2.0 0.005
#pragma parameter ia_YPOS "Pan Y" 0.0 -2.0 2.0 0.005
const vec2 shift = vec2(0.5);
vec2 crop_zoom_pan(vec2 in_coord){
vec2 out_coord = in_coord - shift;
out_coord /= ia_ZOOM;
out_coord *= vec2(1.0 - ia_overscan_percent_x / 100.0, 1.0 - ia_overscan_percent_y / 100.0);
out_coord += shift;
out_coord += vec2(ia_XPOS, ia_YPOS);
return out_coord;
}
#endif

11
include/img/subpx_masks.h Normal file
View file

@ -0,0 +1,11 @@
#ifndef SUBPX_MASKS
#define SUBPX_MASKS
#pragma parameter mask_strength "Phosphor Mask Strength" 0.5 0.0 1.0 0.01
#pragma parameter mask_picker "Phosphor Mask Layout" 0.0 0.0 19.0 1.0
int mask = int(mask_picker);
#include "../subpixel_masks.h"
#endif

17
include/img/vignette.h Normal file
View file

@ -0,0 +1,17 @@
#ifndef VIG
#define VIG
#pragma parameter g_vignette "Vignette Toggle" 1.0 0.0 1.0 1.0
#pragma parameter g_vstr "Vignette Strength" 40.0 0.0 50.0 1.0
#pragma parameter g_vpower "Vignette Power" 0.20 0.0 0.5 0.01
vec3 vignette(vec3 in_col, vec2 in_coord){
vec2 coord = in_coord * (1.0 - in_coord.xy);
float vig = coord.x * coord.y * g_vstr;
vig = min(pow(vig, g_vpower), 1.0);
vec3 out_col = in_col;
out_col *= (g_vignette == 1.0) ? vig : 1.0;
return out_col;
}
#endif

60
include/img/white_point.h Normal file
View file

@ -0,0 +1,60 @@
#ifndef WHITE_POINT
#define WHITE_POINT
// White Point Mapping
// ported by Dogway
//
// From the first comment post (sRGB primaries and linear light compensated)
// http://www.zombieprototypes.com/?p=210#comment-4695029660
// Based on the Neil Bartlett's blog update
// http://www.zombieprototypes.com/?p=210
// Inspired itself by Tanner Helland's work
// http://www.tannerhelland.com/4435/convert-temperature-rgb-algorithm-code
#include "col_tools.h"
#pragma parameter temperature "White Point" 6500.0 1031.0 12047.0 72.0
#pragma parameter luma_preserve "Preserve Luminance" 1.0 0.0 1.0 1.0
#pragma parameter wp_red "Red Shift" 0.0 -1.0 1.0 0.01
#pragma parameter wp_green "Green Shift" 0.0 -1.0 1.0 0.01
#pragma parameter wp_blue "Blue Shift" 0.0 -1.0 1.0 0.01
vec3 wp_adjust(vec3 color){
float temp = temperature / 100.;
float k = temperature / 10000.;
float lk = log(k);
vec3 wp = vec3(1.);
// calculate RED
wp.r = (temp <= 65.) ? 1. : 0.32068362618584273 + (0.19668730877673762 * pow(k - 0.21298613432655075, - 1.5139012907556737)) + (- 0.013883432789258415 * lk);
// calculate GREEN
float mg = 1.226916242502167 + (- 1.3109482654223614 * pow(k - 0.44267061967913873, 3.) * exp(- 5.089297600846147 * (k - 0.44267061967913873))) + (0.6453936305542096 * lk);
float pg = 0.4860175851734596 + (0.1802139719519286 * pow(k - 0.14573069517701578, - 1.397716496795082)) + (- 0.00803698899233844 * lk);
wp.g = (temp <= 65.5) ? ((temp <= 8.) ? 0. : mg) : pg;
// calculate BLUE
wp.b = (temp <= 19.) ? 0. : (temp >= 66.) ? 1. : 1.677499032830161 + (- 0.02313594016938082 * pow(k - 1.1367244820333684, 3.) * exp(- 4.221279555918655 * (k - 1.1367244820333684))) + (1.6550275798913296 * lk);
// clamp
wp.rgb = clamp(wp.rgb, vec3(0.), vec3(1.));
// R/G/B independent manual White Point adjustment
wp.rgb += vec3(wp_red, wp_green, wp_blue);
// Linear color input
return color * wp;
}
vec3 white_point(vec3 in_col){
vec3 original = sRGB_to_linear(in_col, 2.20);
vec3 adjusted = wp_adjust(original);
vec3 base_luma = XYZtoYxy(sRGB_to_XYZ(original));
vec3 adjusted_luma = XYZtoYxy(sRGB_to_XYZ(adjusted));
adjusted = (luma_preserve > 0.5) ? adjusted_luma + (vec3(base_luma.r,0.,0.) - vec3(adjusted_luma.r,0.,0.)) : adjusted_luma;
return linear_to_sRGB(XYZ_to_sRGB(YxytoXYZ(adjusted)), 2.20);
}
#endif

View file

@ -64,6 +64,32 @@ vec3 srgb_linear(vec3 x) {
#endif
}
vec3 linear_to_sRGB(vec3 color, float gamma){
color = clamp(color, 0.0, 1.0);
color.r = (color.r <= 0.00313066844250063) ?
color.r * 12.92 : 1.055 * pow(color.r, 1.0 / gamma) - 0.055;
color.g = (color.g <= 0.00313066844250063) ?
color.g * 12.92 : 1.055 * pow(color.g, 1.0 / gamma) - 0.055;
color.b = (color.b <= 0.00313066844250063) ?
color.b * 12.92 : 1.055 * pow(color.b, 1.0 / gamma) - 0.055;
return color.rgb;
}
vec3 sRGB_to_linear(vec3 color, float gamma){
color = clamp(color, 0.0, 1.0);
color.r = (color.r <= 0.04045) ?
color.r / 12.92 : pow((color.r + 0.055) / (1.055), gamma);
color.g = (color.g <= 0.04045) ?
color.g / 12.92 : pow((color.g + 0.055) / (1.055), gamma);
color.b = (color.b <= 0.04045) ?
color.b / 12.92 : pow((color.b + 0.055) / (1.055), gamma);
return color.rgb;
}
//Conversion matrices
vec3 RGBtoXYZ(vec3 RGB)
{

185
misc/img_mod.slang Normal file
View file

@ -0,0 +1,185 @@
#version 450
// Modular Image Adjustment
// Author: hunterk
// License: Public domain
layout(push_constant) uniform Push
{
vec4 SourceSize;
uint FrameCount;
vec4 OutputSize;
} registers;
layout(std140, set = 0, binding = 0) uniform UBO
{
mat4 MVP;
#include "../include/img/param_floats.h"
} global;
#include "../include/img/helper_macros.h"
/////////////////////////////// INCLUDES ////////////////////////////////
// comment the #include and corresponding line to remove functionality //
/////////////////////////////////////////////////////////////////////////
// Flip image vertically or horizontally
#include "../include/img/image_flip.h"
// Stretching, Zooming, Panning
#include "../include/img/stretch_zoom_pan.h"
// Film grain effect
#include "../include/img/film_grain.h"
// Sharp, antialiased pixels; use with linear filtering
#include "../include/img/sharpening.h"
// Saturation and Luminance
//#include "../include/img/sat_lum.h"
#include "../include/img/lum_chrom.h"
// Gamma correction
// exp_gamma is basic pow function
//#include "../include/img/exp_gamma.h"
#include "../include/img/gamma_srgb.h"
// Mask edges to hide unsightly garbage
#include "../include/img/border_mask.h"
// Change the whitepoint to warmer/cooler
#include "../include/img/white_point.h"
// Add a phosphor mask effect onto the image
#include "../include/img/subpx_masks.h"
// Force integer scaling and custom aspect ratio
//#include "../include/img/int_ar.h"
// Vignette; Darkens image around edges
//#include "../include/img/vignette.h"
// Black level
// uncomment only one of the next 2 lines to set black level method
//#include "../include/img/black_lvl.h"
#include "../include/img/black_lvl_dogway.h"
// Brightness and Contrast control
// uncomment only one of the next 2 lines to set contract complexity;
// sigmoidal_con is advanced, bright_con is basic
#include "../include/img/sigmoidal_con.h"
//#include "../include/img/bright_con.h"
// Adjust color balance and tint
// uncomment only one of the next 2 lines to set color channel complexity;
// color mangler is advanced, channel mixer is basic
//#include "../include/img/col_mangler.h"
#include "../include/img/channel_mix.h"
// 2D screen curvature
//#include "../include/img/gristle_warp.h"
//#include "../include/img/lottes_warp.h"
#include "../include/img/cgwg_warp.h"
// Rounded corners
#include "../include/img/corner.h"
////////////////////////////// END INCLUDES //////////////////////////////
#pragma stage vertex
layout(location = 0) in vec4 Position;
layout(location = 1) in vec2 TexCoord;
layout(location = 0) out vec2 vTexCoord;
void main()
{
vec4 pos = Position;
// apply axis flip
pos = flip_pos(pos);
gl_Position = global.MVP * pos;
vec2 coord = TexCoord.st;
// apply crop/zoom/pan
coord = crop_zoom_pan(TexCoord);
// apply integer scaling and aspect ratio
// coord = int_ar(coord, registers.SourceSize, registers.OutputSize);
vTexCoord = coord;
}
#pragma stage fragment
layout(location = 0) in vec2 vTexCoord;
layout(location = 0) out vec4 FragColor;
layout(set = 0, binding = 2) uniform sampler2D Source;
//////////////////////////////// LUTS ///////////////////////////////////
// Use either 1 or 2 color-grading LUTs
// uncomment only one of the next 2 lines
//#include "../include/img/lut1.h"
//#include "../include/img/lut2.h"
////////////////////////////// END LUTS /////////////////////////////////
void main()
{
// declare texture coordinates
vec2 coord = vTexCoord.xy;
// apply sharpening to coords
coord = sharp(vTexCoord, registers.SourceSize);
// apply screen curvature
coord = warp(coord);
// sample the texture
vec3 res = texture(Source, coord).rgb;
// apply grain (expects to run in gamma space)
res = luma_grain(res, vTexCoord.xy, ia_GRAIN_STR, registers.FrameCount);
// saturation and luminance (expects to run in gamma space)
res = sat_lum(res);
// contrast
res = cntrst(res);
// apply first gamma transform (linearize)
// (whether LUT or gamma should come first depends on LUT)
res = gamma_in(res);
// apply LUT1
// res = lut1(res);
// apply white point adjustment
res = white_point(res);
// black level
res = black_level(res);
// channel mix
res = channel_mix(res);
// overscan mask
res = border_mask(res, coord.xy);
// apply LUT2 (whether LUT or gamma should come first depends on LUT)
// res = lut2(res);
// apply gamma curve
res = gamma_out(res);
// apply mask effect
res *= mask_weights(gl_FragCoord.xy, mask_strength, mask);
// apply vignette effect
// res = vignette(res, vTexCoord.xy);
// apply rounded corners
res *= corner(coord);
FragColor = vec4(res, 1.0);
}

7
misc/img_mod.slangp Normal file
View file

@ -0,0 +1,7 @@
shaders = 1
shader0 = img_mod.slang
textures = "SamplerLUT1;SamplerLUT2"
SamplerLUT1 = ../reshade/shaders/LUT/16.png
SamplerLUT2 = ../reshade/shaders/LUT/16.png