mirror of
https://github.com/joncampbell123/dosbox-x.git
synced 2025-10-14 02:17:36 +08:00
include GLshaders
This commit is contained in:
@@ -7,7 +7,9 @@
|
||||
section) can be used to specify a GLSL shader file
|
||||
or a built-in shader when the output is set to
|
||||
"opengl" or "openglnb". For example, you can use
|
||||
"glshader=sharp" for pixel-perfect mode. (Wengier)
|
||||
the setting "glshader=sharp" (built-in shader) or
|
||||
"glshader=pixel_perfect" (with GLSL shader file)
|
||||
for the pixel-perfect scaling mode. (Wengier)
|
||||
- Support for FluidSynth MIDI Synthesizer is now
|
||||
included in the Windows Visual Studio builds by
|
||||
default. Set "mididevice=fluidsynth" and a sound
|
||||
|
93
contrib/glshaders/ScanLine.glsl
Normal file
93
contrib/glshaders/ScanLine.glsl
Normal file
@@ -0,0 +1,93 @@
|
||||
#version 120
|
||||
/*
|
||||
|
||||
dugan_CRT-EasyMode_tweaked.glsl
|
||||
dugan's ScanLine shader
|
||||
adapted by liPillON for usage with DosBox SVN r4319 and later
|
||||
no tweaks
|
||||
|
||||
source shader files:
|
||||
https://github.com/duganchen/dosbox_shaders/blob/master/scanline.frag
|
||||
https://github.com/duganchen/dosbox_shaders/blob/master/scanline.vert
|
||||
|
||||
first posted here:
|
||||
https://www.vogons.org/viewtopic.php?f=32&t=72697
|
||||
|
||||
*/
|
||||
|
||||
#if defined(VERTEX)
|
||||
|
||||
#if __VERSION__ >= 130
|
||||
#define COMPAT_VARYING out
|
||||
#define COMPAT_ATTRIBUTE in
|
||||
#define COMPAT_TEXTURE texture
|
||||
#else
|
||||
#define COMPAT_VARYING varying
|
||||
#define COMPAT_ATTRIBUTE attribute
|
||||
#define COMPAT_TEXTURE texture2D
|
||||
#endif
|
||||
|
||||
#ifdef GL_ES
|
||||
#define COMPAT_PRECISION mediump
|
||||
#else
|
||||
#define COMPAT_PRECISION
|
||||
#endif
|
||||
|
||||
uniform vec2 rubyTextureSize;
|
||||
uniform vec2 rubyInputSize;
|
||||
uniform vec2 rubyOutputSize;
|
||||
|
||||
COMPAT_ATTRIBUTE vec4 a_position;
|
||||
COMPAT_VARYING vec2 v_texCoord;
|
||||
|
||||
COMPAT_VARYING vec2 omega;
|
||||
|
||||
void main()
|
||||
{
|
||||
gl_Position = a_position;
|
||||
v_texCoord = vec2(a_position.x+1.0,1.0-a_position.y)/2.0*rubyInputSize/rubyTextureSize;
|
||||
|
||||
omega = vec2(3.1415 * rubyOutputSize.x * rubyTextureSize.x / rubyInputSize.x, 2.0 * 3.1415 * rubyTextureSize.y);
|
||||
}
|
||||
|
||||
#elif defined(FRAGMENT)
|
||||
|
||||
#if __VERSION__ >= 130
|
||||
#define COMPAT_VARYING in
|
||||
#define COMPAT_TEXTURE texture
|
||||
out vec4 FragColor;
|
||||
#else
|
||||
#define COMPAT_VARYING varying
|
||||
#define FragColor gl_FragColor
|
||||
#define COMPAT_TEXTURE texture2D
|
||||
#endif
|
||||
|
||||
#ifdef GL_ES
|
||||
#ifdef GL_FRAGMENT_PRECISION_HIGH
|
||||
precision highp float;
|
||||
#else
|
||||
precision mediump float;
|
||||
#endif
|
||||
#define COMPAT_PRECISION highp
|
||||
#else
|
||||
#define COMPAT_PRECISION
|
||||
#endif
|
||||
|
||||
const float SCANLINE_BASE_BRIGHTNESS = 0.95;
|
||||
const float SCANLINE_SINE_COMP_A = 0.05;
|
||||
const float SCANLINE_SINE_COMP_B = 0.15;
|
||||
|
||||
COMPAT_VARYING vec2 v_texCoord;
|
||||
uniform sampler2D rubyTexture;
|
||||
|
||||
COMPAT_VARYING vec2 omega;
|
||||
|
||||
void main()
|
||||
{
|
||||
vec2 sine_comp = vec2(SCANLINE_SINE_COMP_A, SCANLINE_SINE_COMP_B);
|
||||
vec3 res = COMPAT_TEXTURE(rubyTexture, v_texCoord).xyz;
|
||||
vec3 scanline = res * (SCANLINE_BASE_BRIGHTNESS + dot(sine_comp * sin(v_texCoord * omega), vec2(1.0, 1.0)));
|
||||
FragColor = vec4(scanline.x, scanline.y, scanline.z, 1.0);
|
||||
}
|
||||
|
||||
#endif
|
286
contrib/glshaders/crt-aperture.glsl
Normal file
286
contrib/glshaders/crt-aperture.glsl
Normal file
@@ -0,0 +1,286 @@
|
||||
#version 120
|
||||
|
||||
/*
|
||||
CRT Shader by EasyMode
|
||||
License: GPL
|
||||
*/
|
||||
|
||||
#pragma parameter SHARPNESS_IMAGE "Sharpness Image" 1.0 1.0 5.0 1.0
|
||||
#pragma parameter SHARPNESS_EDGES "Sharpness Edges" 3.0 1.0 5.0 1.0
|
||||
#pragma parameter GLOW_WIDTH "Glow Width" 0.5 0.05 0.65 0.05
|
||||
#pragma parameter GLOW_HEIGHT "Glow Height" 0.5 0.05 0.65 0.05
|
||||
#pragma parameter GLOW_HALATION "Glow Halation" 0.1 0.0 1.0 0.01
|
||||
#pragma parameter GLOW_DIFFUSION "Glow Diffusion" 0.05 0.0 1.0 0.01
|
||||
#pragma parameter MASK_COLORS "Mask Colors" 2.0 2.0 3.0 1.0
|
||||
#pragma parameter MASK_STRENGTH "Mask Strength" 0.3 0.0 1.0 0.05
|
||||
#pragma parameter MASK_SIZE "Mask Size" 1.0 1.0 9.0 1.0
|
||||
#pragma parameter SCANLINE_SIZE_MIN "Scanline Size Min." 0.5 0.5 1.5 0.05
|
||||
#pragma parameter SCANLINE_SIZE_MAX "Scanline Size Max." 1.5 0.5 1.5 0.05
|
||||
#pragma parameter SCANLINE_SHAPE "Scanline Shape" 2.5 1.0 100.0 0.1
|
||||
#pragma parameter SCANLINE_OFFSET "Scanline Offset" 1.0 0.0 1.0 1.0
|
||||
#pragma parameter GAMMA_INPUT "Gamma Input" 2.4 1.0 5.0 0.1
|
||||
#pragma parameter GAMMA_OUTPUT "Gamma Output" 2.4 1.0 5.0 0.1
|
||||
#pragma parameter BRIGHTNESS "Brightness" 1.5 0.0 2.0 0.05
|
||||
|
||||
#define Coord v_texCoord
|
||||
|
||||
#if defined(VERTEX)
|
||||
|
||||
#if __VERSION__ >= 130
|
||||
#define OUT out
|
||||
#define IN in
|
||||
#define tex2D texture
|
||||
#else
|
||||
#define OUT varying
|
||||
#define IN attribute
|
||||
#define tex2D texture2D
|
||||
#endif
|
||||
|
||||
#ifdef GL_ES
|
||||
#define PRECISION mediump
|
||||
#else
|
||||
#define PRECISION
|
||||
#endif
|
||||
|
||||
IN vec4 a_position;
|
||||
IN vec4 Color;
|
||||
IN vec2 TexCoord;
|
||||
OUT vec4 color;
|
||||
OUT vec2 Coord;
|
||||
|
||||
uniform PRECISION vec2 rubyTextureSize;
|
||||
uniform PRECISION vec2 rubyInputSize;
|
||||
|
||||
void main()
|
||||
{
|
||||
gl_Position = a_position;
|
||||
v_texCoord = vec2(a_position.x + 1.0, 1.0 - a_position.y) / 2.0 * rubyInputSize / rubyTextureSize;
|
||||
|
||||
color = Color;
|
||||
Coord = v_texCoord * 1.0001;
|
||||
}
|
||||
|
||||
#elif defined(FRAGMENT)
|
||||
|
||||
#if __VERSION__ >= 130
|
||||
#define IN in
|
||||
#define tex2D texture
|
||||
out vec4 FragColor;
|
||||
#else
|
||||
#define IN varying
|
||||
#define FragColor gl_FragColor
|
||||
#define tex2D texture2D
|
||||
#endif
|
||||
|
||||
#ifdef GL_ES
|
||||
#ifdef GL_FRAGMENT_PRECISION_HIGH
|
||||
precision highp float;
|
||||
#else
|
||||
precision mediump float;
|
||||
#endif
|
||||
#define PRECISION mediump
|
||||
#else
|
||||
#define PRECISION
|
||||
#endif
|
||||
|
||||
uniform PRECISION vec2 rubyOutputSize;
|
||||
uniform PRECISION vec2 rubyTextureSize;
|
||||
uniform PRECISION vec2 rubyInputSize;
|
||||
uniform sampler2D rubyTexture;
|
||||
IN vec2 Coord;
|
||||
|
||||
#ifdef PARAMETER_UNIFORM
|
||||
uniform PRECISION float SHARPNESS_IMAGE;
|
||||
uniform PRECISION float SHARPNESS_EDGES;
|
||||
uniform PRECISION float GLOW_WIDTH;
|
||||
uniform PRECISION float GLOW_HEIGHT;
|
||||
uniform PRECISION float GLOW_HALATION;
|
||||
uniform PRECISION float GLOW_DIFFUSION;
|
||||
uniform PRECISION float MASK_COLORS;
|
||||
uniform PRECISION float MASK_STRENGTH;
|
||||
uniform PRECISION float MASK_SIZE;
|
||||
uniform PRECISION float SCANLINE_SIZE_MIN;
|
||||
uniform PRECISION float SCANLINE_SIZE_MAX;
|
||||
uniform PRECISION float SCANLINE_SHAPE;
|
||||
uniform PRECISION float SCANLINE_OFFSET;
|
||||
uniform PRECISION float GAMMA_INPUT;
|
||||
uniform PRECISION float GAMMA_OUTPUT;
|
||||
uniform PRECISION float BRIGHTNESS;
|
||||
#else
|
||||
#define SHARPNESS_IMAGE 1.0
|
||||
#define SHARPNESS_EDGES 3.0
|
||||
#define GLOW_WIDTH 0.5
|
||||
#define GLOW_HEIGHT 0.5
|
||||
#define GLOW_HALATION 0.1
|
||||
#define GLOW_DIFFUSION 0.05
|
||||
#define MASK_COLORS 2.0
|
||||
#define MASK_STRENGTH 0.3
|
||||
#define MASK_SIZE 1.0
|
||||
#define SCANLINE_SIZE_MIN 0.5
|
||||
#define SCANLINE_SIZE_MAX 1.5
|
||||
#define SCANLINE_SHAPE 1.5
|
||||
#define SCANLINE_OFFSET 1.0
|
||||
#define GAMMA_INPUT 2.4
|
||||
#define GAMMA_OUTPUT 2.4
|
||||
#define BRIGHTNESS 1.5
|
||||
#endif
|
||||
|
||||
/*
|
||||
The following code allows the shader to override any texture filtering
|
||||
configured in DOSBox. if 'output' is set to 'opengl', bilinear filtering
|
||||
will be enabled and OPENGLNB will not be defined, if 'output' is set to
|
||||
'openglnb', nearest neighbour filtering will be enabled and OPENGLNB will
|
||||
be defined.
|
||||
|
||||
If you wish to use the default filtering method that is currently enabled
|
||||
in DOSBox, use COMPAT_TEXTURE to lookup a texel from the input texture.
|
||||
|
||||
If you wish to force nearest-neighbor interpolation use NN_TEXTURE.
|
||||
|
||||
If you wish to force bilinear interpolation use BL_TEXTURE.
|
||||
|
||||
If DOSBox is configured to use the filtering method that is being forced,
|
||||
the default hardware implementation will be used, otherwise the custom
|
||||
implementations below will be used instead.
|
||||
|
||||
These custom implemenations rely on the `rubyTextureSize` uniform variable.
|
||||
The code could calculate the texture size from the sampler using the
|
||||
textureSize() GLSL function, but this would require a minimum of GLSL
|
||||
version 130, which may prevent the shader from working on older systems.
|
||||
*/
|
||||
|
||||
#if defined(OPENGLNB)
|
||||
#define NN_TEXTURE tex2D
|
||||
#define BL_TEXTURE blTexture
|
||||
vec4 blTexture(in sampler2D sampler, in vec2 uv)
|
||||
{
|
||||
// subtract 0.5 here and add it again after the floor to centre the texel
|
||||
vec2 texCoord = uv * rubyTextureSize - vec2(0.5);
|
||||
vec2 s0t0 = floor(texCoord) + vec2(0.5);
|
||||
vec2 s0t1 = s0t0 + vec2(0.0, 1.0);
|
||||
vec2 s1t0 = s0t0 + vec2(1.0, 0.0);
|
||||
vec2 s1t1 = s0t0 + vec2(1.0);
|
||||
|
||||
vec2 invTexSize = 1.0 / rubyTextureSize;
|
||||
vec4 c_s0t0 = tex2D(sampler, s0t0 * invTexSize);
|
||||
vec4 c_s0t1 = tex2D(sampler, s0t1 * invTexSize);
|
||||
vec4 c_s1t0 = tex2D(sampler, s1t0 * invTexSize);
|
||||
vec4 c_s1t1 = tex2D(sampler, s1t1 * invTexSize);
|
||||
|
||||
vec2 weight = fract(texCoord);
|
||||
|
||||
vec4 c0 = c_s0t0 + (c_s1t0 - c_s0t0) * weight.x;
|
||||
vec4 c1 = c_s0t1 + (c_s1t1 - c_s0t1) * weight.x;
|
||||
|
||||
return (c0 + (c1 - c0) * weight.y);
|
||||
}
|
||||
#else
|
||||
#define BL_TEXTURE tex2D
|
||||
#define NN_TEXTURE nnTexture
|
||||
vec4 nnTexture(in sampler2D sampler, in vec2 uv)
|
||||
{
|
||||
vec2 texCoord = floor(uv * rubyTextureSize) + vec2(0.5);
|
||||
vec2 invTexSize = 1.0 / rubyTextureSize;
|
||||
return tex2D(sampler, texCoord * invTexSize);
|
||||
}
|
||||
#endif
|
||||
|
||||
#define FIX(c) max(abs(c), 1e-5)
|
||||
#define PI 3.141592653589
|
||||
#define saturate(c) clamp(c, 0.0, 1.0)
|
||||
#define TEX2D(c) pow(NN_TEXTURE(tex, c).rgb, vec3(GAMMA_INPUT))
|
||||
|
||||
mat3 get_color_matrix(sampler2D tex, vec2 co, vec2 dx)
|
||||
{
|
||||
return mat3(TEX2D(co - dx), TEX2D(co), TEX2D(co + dx));
|
||||
}
|
||||
|
||||
vec3 blur(mat3 m, float dist, float rad)
|
||||
{
|
||||
vec3 x = vec3(dist - 1.0, dist, dist + 1.0) / rad;
|
||||
vec3 w = exp2(x * x * -1.0);
|
||||
|
||||
return (m[0] * w.x + m[1] * w.y + m[2] * w.z) / (w.x + w.y + w.z);
|
||||
}
|
||||
|
||||
vec3 filter_gaussian(sampler2D tex, vec2 co, vec2 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 = co * tex_size;
|
||||
vec2 tex_co = (floor(pix_co) + 0.5) / tex_size;
|
||||
vec2 dist = (fract(pix_co) - 0.5) * -1.0;
|
||||
|
||||
mat3 line0 = get_color_matrix(tex, tex_co - dy, dx);
|
||||
mat3 line1 = get_color_matrix(tex, tex_co, dx);
|
||||
mat3 line2 = get_color_matrix(tex, tex_co + dy, dx);
|
||||
mat3 column = mat3(blur(line0, dist.x, GLOW_WIDTH),
|
||||
blur(line1, dist.x, GLOW_WIDTH),
|
||||
blur(line2, dist.x, GLOW_WIDTH));
|
||||
|
||||
return blur(column, dist.y, GLOW_HEIGHT);
|
||||
}
|
||||
|
||||
vec3 filter_lanczos(sampler2D tex, vec2 co, vec2 tex_size, float sharp)
|
||||
{
|
||||
tex_size.x *= sharp;
|
||||
|
||||
vec2 dx = vec2(1.0 / tex_size.x, 0.0);
|
||||
vec2 pix_co = co * tex_size - vec2(0.5, 0.0);
|
||||
vec2 tex_co = (floor(pix_co) + vec2(0.5, 0.0)) / tex_size;
|
||||
vec2 dist = fract(pix_co);
|
||||
vec4 coef = PI * vec4(dist.x + 1.0, dist.x, dist.x - 1.0, dist.x - 2.0);
|
||||
|
||||
coef = FIX(coef);
|
||||
coef = 2.0 * sin(coef) * sin(coef / 2.0) / (coef * coef);
|
||||
coef /= dot(coef, vec4(1.0));
|
||||
|
||||
vec4 col1 = vec4(TEX2D(tex_co), 1.0);
|
||||
vec4 col2 = vec4(TEX2D(tex_co + dx), 1.0);
|
||||
|
||||
return (mat4(col1, col1, col2, col2) * coef).rgb;
|
||||
}
|
||||
|
||||
vec3 get_scanline_weight(float x, vec3 col)
|
||||
{
|
||||
vec3 beam = mix(vec3(SCANLINE_SIZE_MIN), vec3(SCANLINE_SIZE_MAX), pow(col, vec3(1.0 / SCANLINE_SHAPE)));
|
||||
vec3 x_mul = 2.0 / beam;
|
||||
vec3 x_offset = x_mul * 0.5;
|
||||
|
||||
return smoothstep(0.0, 1.0, 1.0 - abs(x * x_mul - x_offset)) * x_offset;
|
||||
}
|
||||
|
||||
vec3 get_mask_weight(float x)
|
||||
{
|
||||
float i = mod(floor(x * rubyOutputSize.x * rubyTextureSize.x / (rubyInputSize.x * MASK_SIZE)), MASK_COLORS);
|
||||
|
||||
if (i == 0.0) return mix(vec3(1.0, 0.0, 1.0), vec3(1.0, 0.0, 0.0), MASK_COLORS - 2.0);
|
||||
else if (i == 1.0) return vec3(0.0, 1.0, 0.0);
|
||||
else return vec3(0.0, 0.0, 1.0);
|
||||
}
|
||||
|
||||
void main()
|
||||
{
|
||||
float scale = floor((rubyOutputSize.y / rubyInputSize.y) + 0.001);
|
||||
float offset = 1.0 / scale * 0.5;
|
||||
|
||||
if (bool(mod(scale, 2.0))) offset = 0.0;
|
||||
|
||||
vec2 co = (Coord * rubyTextureSize - vec2(0.0, offset * SCANLINE_OFFSET)) / rubyTextureSize;
|
||||
|
||||
vec3 col_glow = filter_gaussian(rubyTexture, co, rubyTextureSize);
|
||||
vec3 col_soft = filter_lanczos(rubyTexture, co, rubyTextureSize, SHARPNESS_IMAGE);
|
||||
vec3 col_sharp = filter_lanczos(rubyTexture, co, rubyTextureSize, SHARPNESS_EDGES);
|
||||
vec3 col = sqrt(col_sharp * col_soft);
|
||||
|
||||
col *= get_scanline_weight(fract(co.y * rubyTextureSize.y), col_soft);
|
||||
col_glow = saturate(col_glow - col);
|
||||
col += col_glow * col_glow * GLOW_HALATION;
|
||||
col = mix(col, col * get_mask_weight(co.x) * MASK_COLORS, MASK_STRENGTH);
|
||||
col += col_glow * GLOW_DIFFUSION;
|
||||
col = pow(col * BRIGHTNESS, vec3(1.0 / GAMMA_OUTPUT));
|
||||
|
||||
FragColor = vec4(col, 1.0);
|
||||
}
|
||||
|
||||
#endif
|
206
contrib/glshaders/crt-caligari.glsl
Normal file
206
contrib/glshaders/crt-caligari.glsl
Normal file
@@ -0,0 +1,206 @@
|
||||
#version 120
|
||||
|
||||
/*
|
||||
Phosphor shader - Copyright (C) 2011 caligari.
|
||||
|
||||
Ported by Hyllian.
|
||||
|
||||
This program is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU General Public License
|
||||
as published by the Free Software Foundation; either version 2
|
||||
of the License, or (at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
|
||||
*/
|
||||
|
||||
// Parameter lines go here:
|
||||
// 0.5 = the spot stays inside the original pixel
|
||||
// 1.0 = the spot bleeds up to the center of next pixel
|
||||
#pragma parameter SPOT_WIDTH "CRTCaligari Spot Width" 0.9 0.1 1.5 0.05
|
||||
#pragma parameter SPOT_HEIGHT "CRTCaligari Spot Height" 0.65 0.1 1.5 0.05
|
||||
// Used to counteract the desaturation effect of weighting.
|
||||
#pragma parameter COLOR_BOOST "CRTCaligari Color Boost" 1.45 1.0 2.0 0.05
|
||||
// Constants used with gamma correction.
|
||||
#pragma parameter InputGamma "CRTCaligari Input Gamma" 2.4 0.0 5.0 0.1
|
||||
#pragma parameter OutputGamma "CRTCaligari Output Gamma" 2.2 0.0 5.0 0.1
|
||||
|
||||
#if defined(VERTEX)
|
||||
|
||||
#if __VERSION__ >= 130
|
||||
#define COMPAT_VARYING out
|
||||
#define COMPAT_ATTRIBUTE in
|
||||
#define COMPAT_TEXTURE texture
|
||||
#else
|
||||
#define COMPAT_VARYING varying
|
||||
#define COMPAT_ATTRIBUTE attribute
|
||||
#define COMPAT_TEXTURE texture2D
|
||||
#endif
|
||||
|
||||
#ifdef GL_ES
|
||||
#define COMPAT_PRECISION mediump
|
||||
#else
|
||||
#define COMPAT_PRECISION
|
||||
#endif
|
||||
|
||||
COMPAT_ATTRIBUTE vec4 a_position;
|
||||
COMPAT_ATTRIBUTE vec4 TexCoord;
|
||||
COMPAT_VARYING vec2 v_texCoord;
|
||||
COMPAT_VARYING vec2 onex;
|
||||
COMPAT_VARYING vec2 oney;
|
||||
|
||||
vec4 _oPosition1;
|
||||
uniform mat4 MVPMatrix;
|
||||
uniform COMPAT_PRECISION int FrameDirection;
|
||||
uniform COMPAT_PRECISION int rubyFrameCount;
|
||||
uniform COMPAT_PRECISION vec2 rubyOutputSize;
|
||||
uniform COMPAT_PRECISION vec2 rubyTextureSize;
|
||||
uniform COMPAT_PRECISION vec2 rubyInputSize;
|
||||
|
||||
#define SourceSize vec4(rubyTextureSize, 1.0 / rubyTextureSize) //either rubyTextureSize or rubyInputSize
|
||||
|
||||
void main()
|
||||
{
|
||||
gl_Position = a_position;
|
||||
v_texCoord = vec2(a_position.x + 1.0, 1.0 - a_position.y) / 2.0 * rubyInputSize / rubyTextureSize;
|
||||
|
||||
onex = vec2(SourceSize.z, 0.0);
|
||||
oney = vec2(0.0, SourceSize.w);
|
||||
}
|
||||
|
||||
#elif defined(FRAGMENT)
|
||||
|
||||
#if __VERSION__ >= 130
|
||||
#define COMPAT_VARYING in
|
||||
#define COMPAT_TEXTURE texture
|
||||
out vec4 FragColor;
|
||||
#else
|
||||
#define COMPAT_VARYING varying
|
||||
#define FragColor gl_FragColor
|
||||
#define COMPAT_TEXTURE texture2D
|
||||
#endif
|
||||
|
||||
#ifdef GL_ES
|
||||
#ifdef GL_FRAGMENT_PRECISION_HIGH
|
||||
precision highp float;
|
||||
#else
|
||||
precision mediump float;
|
||||
#endif
|
||||
#define COMPAT_PRECISION mediump
|
||||
#else
|
||||
#define COMPAT_PRECISION
|
||||
#endif
|
||||
|
||||
uniform COMPAT_PRECISION int FrameDirection;
|
||||
uniform COMPAT_PRECISION int rubyFrameCount;
|
||||
uniform COMPAT_PRECISION vec2 rubyOutputSize;
|
||||
uniform COMPAT_PRECISION vec2 rubyTextureSize;
|
||||
uniform COMPAT_PRECISION vec2 rubyInputSize;
|
||||
uniform sampler2D rubyTexture;
|
||||
COMPAT_VARYING vec2 v_texCoord;
|
||||
COMPAT_VARYING vec2 onex;
|
||||
COMPAT_VARYING vec2 oney;
|
||||
|
||||
// compatibility #defines
|
||||
#define Source rubyTexture
|
||||
#define vTexCoord v_texCoord.xy
|
||||
|
||||
#define SourceSize vec4(rubyTextureSize, 1.0 / rubyTextureSize) //either rubyTextureSize or rubyInputSize
|
||||
#define rubyOutputSize vec4(rubyOutputSize, 1.0 / rubyOutputSize)
|
||||
|
||||
#ifdef PARAMETER_UNIFORM
|
||||
// All parameter floats need to have COMPAT_PRECISION in front of them
|
||||
uniform COMPAT_PRECISION float SPOT_WIDTH;
|
||||
uniform COMPAT_PRECISION float SPOT_HEIGHT;
|
||||
uniform COMPAT_PRECISION float COLOR_BOOST;
|
||||
uniform COMPAT_PRECISION float InputGamma;
|
||||
uniform COMPAT_PRECISION float OutputGamma;
|
||||
#else
|
||||
#define SPOT_WIDTH 0.9
|
||||
#define SPOT_HEIGHT 0.65
|
||||
#define COLOR_BOOST 1.45
|
||||
#define InputGamma 2.4
|
||||
#define OutputGamma 2.2
|
||||
#endif
|
||||
|
||||
#define GAMMA_IN(color) pow(color,vec4(InputGamma))
|
||||
#define GAMMA_OUT(color) pow(color, vec4(1.0 / OutputGamma))
|
||||
|
||||
#define TEX2D(coords) GAMMA_IN( COMPAT_TEXTURE(Source, coords) )
|
||||
|
||||
// Macro for weights computing
|
||||
#define WEIGHT(w) \
|
||||
if(w>1.0) w=1.0; \
|
||||
w = 1.0 - w * w; \
|
||||
w = w * w;
|
||||
|
||||
void main()
|
||||
{
|
||||
vec2 coords = ( vTexCoord * SourceSize.xy );
|
||||
vec2 pixel_center = floor( coords ) + vec2(0.5, 0.5);
|
||||
vec2 texture_coords = pixel_center * SourceSize.zw;
|
||||
|
||||
vec4 color = TEX2D( texture_coords );
|
||||
|
||||
float dx = coords.x - pixel_center.x;
|
||||
|
||||
float h_weight_00 = dx / SPOT_WIDTH;
|
||||
WEIGHT( h_weight_00 );
|
||||
|
||||
color *= vec4( h_weight_00, h_weight_00, h_weight_00, h_weight_00 );
|
||||
|
||||
// get closest horizontal neighbour to blend
|
||||
vec2 coords01;
|
||||
if (dx>0.0) {
|
||||
coords01 = onex;
|
||||
dx = 1.0 - dx;
|
||||
} else {
|
||||
coords01 = -onex;
|
||||
dx = 1.0 + dx;
|
||||
}
|
||||
vec4 colorNB = TEX2D( texture_coords + coords01 );
|
||||
|
||||
float h_weight_01 = dx / SPOT_WIDTH;
|
||||
WEIGHT( h_weight_01 );
|
||||
|
||||
color = color + colorNB * vec4( h_weight_01 );
|
||||
|
||||
//////////////////////////////////////////////////////
|
||||
// Vertical Blending
|
||||
float dy = coords.y - pixel_center.y;
|
||||
float v_weight_00 = dy / SPOT_HEIGHT;
|
||||
WEIGHT( v_weight_00 );
|
||||
color *= vec4( v_weight_00 );
|
||||
|
||||
// get closest vertical neighbour to blend
|
||||
vec2 coords10;
|
||||
if (dy>0.0) {
|
||||
coords10 = oney;
|
||||
dy = 1.0 - dy;
|
||||
} else {
|
||||
coords10 = -oney;
|
||||
dy = 1.0 + dy;
|
||||
}
|
||||
colorNB = TEX2D( texture_coords + coords10 );
|
||||
|
||||
float v_weight_10 = dy / SPOT_HEIGHT;
|
||||
WEIGHT( v_weight_10 );
|
||||
|
||||
color = color + colorNB * vec4( v_weight_10 * h_weight_00, v_weight_10 * h_weight_00, v_weight_10 * h_weight_00, v_weight_10 * h_weight_00 );
|
||||
|
||||
colorNB = TEX2D( texture_coords + coords01 + coords10 );
|
||||
|
||||
color = color + colorNB * vec4( v_weight_10 * h_weight_01, v_weight_10 * h_weight_01, v_weight_10 * h_weight_01, v_weight_10 * h_weight_01 );
|
||||
|
||||
color *= vec4( COLOR_BOOST );
|
||||
|
||||
FragColor = clamp( GAMMA_OUT(color), 0.0, 1.0 );
|
||||
}
|
||||
#endif
|
264
contrib/glshaders/crt-easymode.glsl
Normal file
264
contrib/glshaders/crt-easymode.glsl
Normal file
@@ -0,0 +1,264 @@
|
||||
#version 120
|
||||
|
||||
/*
|
||||
CRT Shader by EasyMode
|
||||
License: GPL
|
||||
|
||||
A flat CRT shader ideally for 1080p or higher displays.
|
||||
|
||||
Recommended Settings:
|
||||
|
||||
Video
|
||||
- Aspect Ratio: 4:3
|
||||
- Integer Scale: Off
|
||||
|
||||
Shader
|
||||
- Filter: Nearest
|
||||
- Scale: Don't Care
|
||||
|
||||
Example RGB Mask Parameter Settings:
|
||||
|
||||
Aperture Grille (Default)
|
||||
- Dot Width: 1
|
||||
- Dot Height: 1
|
||||
- Stagger: 0
|
||||
|
||||
Lottes' Shadow Mask
|
||||
- Dot Width: 2
|
||||
- Dot Height: 1
|
||||
- Stagger: 3
|
||||
*/
|
||||
|
||||
// Parameter lines go here:
|
||||
#pragma parameter SHARPNESS_H "Sharpness Horizontal" 0.5 0.0 1.0 0.05
|
||||
#pragma parameter SHARPNESS_V "Sharpness Vertical" 1.0 0.0 1.0 0.05
|
||||
#pragma parameter MASK_STRENGTH "Mask Strength" 0.3 0.0 1.0 0.01
|
||||
#pragma parameter MASK_DOT_WIDTH "Mask Dot Width" 1.0 1.0 100.0 1.0
|
||||
#pragma parameter MASK_DOT_HEIGHT "Mask Dot Height" 1.0 1.0 100.0 1.0
|
||||
#pragma parameter MASK_STAGGER "Mask Stagger" 0.0 0.0 100.0 1.0
|
||||
#pragma parameter MASK_SIZE "Mask Size" 1.0 1.0 100.0 1.0
|
||||
#pragma parameter SCANLINE_STRENGTH "Scanline Strength" 1.0 0.0 1.0 0.05
|
||||
#pragma parameter SCANLINE_BEAM_WIDTH_MIN "Scanline Beam Width Min." 1.5 0.5 5.0 0.5
|
||||
#pragma parameter SCANLINE_BEAM_WIDTH_MAX "Scanline Beam Width Max." 1.5 0.5 5.0 0.5
|
||||
#pragma parameter SCANLINE_BRIGHT_MIN "Scanline Brightness Min." 0.35 0.0 1.0 0.05
|
||||
#pragma parameter SCANLINE_BRIGHT_MAX "Scanline Brightness Max." 0.65 0.0 1.0 0.05
|
||||
#pragma parameter SCANLINE_CUTOFF "Scanline Cutoff" 400.0 1.0 1000.0 1.0
|
||||
#pragma parameter GAMMA_INPUT "Gamma Input" 2.0 0.1 5.0 0.1
|
||||
#pragma parameter GAMMA_OUTPUT "Gamma Output" 1.8 0.1 5.0 0.1
|
||||
#pragma parameter BRIGHT_BOOST "Brightness Boost" 1.2 1.0 2.0 0.01
|
||||
#pragma parameter DILATION "Dilation" 1.0 0.0 1.0 1.0
|
||||
|
||||
#if defined(VERTEX)
|
||||
|
||||
#if __VERSION__ >= 130
|
||||
#define COMPAT_VARYING out
|
||||
#define COMPAT_ATTRIBUTE in
|
||||
#define COMPAT_TEXTURE texture
|
||||
#else
|
||||
#define COMPAT_VARYING varying
|
||||
#define COMPAT_ATTRIBUTE attribute
|
||||
#define COMPAT_TEXTURE texture2D
|
||||
#endif
|
||||
|
||||
#ifdef GL_ES
|
||||
#define COMPAT_PRECISION mediump
|
||||
#else
|
||||
#define COMPAT_PRECISION
|
||||
#endif
|
||||
|
||||
COMPAT_ATTRIBUTE vec4 a_position;
|
||||
COMPAT_ATTRIBUTE vec4 COLOR;
|
||||
COMPAT_ATTRIBUTE vec4 TexCoord;
|
||||
COMPAT_VARYING vec4 COL0;
|
||||
COMPAT_VARYING vec2 v_texCoord;
|
||||
|
||||
uniform COMPAT_PRECISION vec2 rubyOutputSize;
|
||||
uniform COMPAT_PRECISION vec2 rubyTextureSize;
|
||||
uniform COMPAT_PRECISION vec2 rubyInputSize;
|
||||
|
||||
void main()
|
||||
{
|
||||
gl_Position = a_position;
|
||||
v_texCoord = vec2(a_position.x + 1.0, 1.0 - a_position.y) / 2.0 * rubyInputSize / rubyTextureSize;
|
||||
}
|
||||
|
||||
#elif defined(FRAGMENT)
|
||||
|
||||
#if __VERSION__ >= 130
|
||||
#define COMPAT_VARYING in
|
||||
#define COMPAT_TEXTURE texture
|
||||
out vec4 FragColor;
|
||||
#else
|
||||
#define COMPAT_VARYING varying
|
||||
#define FragColor gl_FragColor
|
||||
#define COMPAT_TEXTURE texture2D
|
||||
#endif
|
||||
|
||||
#ifdef GL_ES
|
||||
#ifdef GL_FRAGMENT_PRECISION_HIGH
|
||||
precision highp float;
|
||||
#else
|
||||
precision mediump float;
|
||||
precision mediump int;
|
||||
#endif
|
||||
#define COMPAT_PRECISION mediump
|
||||
#else
|
||||
#define COMPAT_PRECISION
|
||||
#endif
|
||||
|
||||
uniform COMPAT_PRECISION vec2 rubyOutputSize;
|
||||
uniform COMPAT_PRECISION vec2 rubyTextureSize;
|
||||
uniform COMPAT_PRECISION vec2 rubyInputSize;
|
||||
uniform sampler2D rubyTexture;
|
||||
COMPAT_VARYING vec2 v_texCoord;
|
||||
|
||||
#define FIX(c) max(abs(c), 1e-5)
|
||||
#define PI 3.141592653589
|
||||
|
||||
#define TEX2D(c) dilate(COMPAT_TEXTURE(rubyTexture, c))
|
||||
|
||||
// compatibility #defines
|
||||
#define Source rubyTexture
|
||||
#define vTexCoord v_texCoord.xy
|
||||
|
||||
#define SourceSize vec4(rubyTextureSize, 1.0 / rubyTextureSize) //either rubyTextureSize or rubyInputSize
|
||||
#define outsize vec4(rubyOutputSize, 1.0 / rubyOutputSize)
|
||||
|
||||
#ifdef PARAMETER_UNIFORM
|
||||
// All parameter floats need to have COMPAT_PRECISION in front of them
|
||||
uniform COMPAT_PRECISION float SHARPNESS_H;
|
||||
uniform COMPAT_PRECISION float SHARPNESS_V;
|
||||
uniform COMPAT_PRECISION float MASK_STRENGTH;
|
||||
uniform COMPAT_PRECISION float MASK_DOT_WIDTH;
|
||||
uniform COMPAT_PRECISION float MASK_DOT_HEIGHT;
|
||||
uniform COMPAT_PRECISION float MASK_STAGGER;
|
||||
uniform COMPAT_PRECISION float MASK_SIZE;
|
||||
uniform COMPAT_PRECISION float SCANLINE_STRENGTH;
|
||||
uniform COMPAT_PRECISION float SCANLINE_BEAM_WIDTH_MIN;
|
||||
uniform COMPAT_PRECISION float SCANLINE_BEAM_WIDTH_MAX;
|
||||
uniform COMPAT_PRECISION float SCANLINE_BRIGHT_MIN;
|
||||
uniform COMPAT_PRECISION float SCANLINE_BRIGHT_MAX;
|
||||
uniform COMPAT_PRECISION float SCANLINE_CUTOFF;
|
||||
uniform COMPAT_PRECISION float GAMMA_INPUT;
|
||||
uniform COMPAT_PRECISION float GAMMA_OUTPUT;
|
||||
uniform COMPAT_PRECISION float BRIGHT_BOOST;
|
||||
uniform COMPAT_PRECISION float DILATION;
|
||||
#else
|
||||
#define SHARPNESS_H 0.5
|
||||
#define SHARPNESS_V 1.0
|
||||
#define MASK_STRENGTH 0.3
|
||||
#define MASK_DOT_WIDTH 1.0
|
||||
#define MASK_DOT_HEIGHT 1.0
|
||||
#define MASK_STAGGER 0.0
|
||||
#define MASK_SIZE 1.0
|
||||
#define SCANLINE_STRENGTH 1.0
|
||||
#define SCANLINE_BEAM_WIDTH_MIN 1.5
|
||||
#define SCANLINE_BEAM_WIDTH_MAX 1.5
|
||||
#define SCANLINE_BRIGHT_MIN 0.35
|
||||
#define SCANLINE_BRIGHT_MAX 0.65
|
||||
#define SCANLINE_CUTOFF 400.0
|
||||
#define GAMMA_INPUT 2.0
|
||||
#define GAMMA_OUTPUT 1.8
|
||||
#define BRIGHT_BOOST 1.2
|
||||
#define DILATION 1.0
|
||||
#endif
|
||||
|
||||
// Set to 0 to use linear filter and gain speed
|
||||
#define ENABLE_LANCZOS 1
|
||||
|
||||
vec4 dilate(vec4 col)
|
||||
{
|
||||
vec4 x = mix(vec4(1.0), col, DILATION);
|
||||
|
||||
return col * x;
|
||||
}
|
||||
|
||||
float curve_distance(float x, float sharp)
|
||||
{
|
||||
|
||||
/*
|
||||
apply half-circle s-curve to distance for sharper (more pixelated) interpolation
|
||||
single line formula for Graph Toy:
|
||||
0.5 - sqrt(0.25 - (x - step(0.5, x)) * (x - step(0.5, x))) * sign(0.5 - x)
|
||||
*/
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
mat4 get_color_matrix(vec2 co, vec2 dx)
|
||||
{
|
||||
return mat4(TEX2D(co - dx), TEX2D(co), TEX2D(co + dx), TEX2D(co + 2.0 * dx));
|
||||
}
|
||||
|
||||
vec3 filter_lanczos(vec4 coeffs, mat4 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.rgb;
|
||||
}
|
||||
|
||||
void main()
|
||||
{
|
||||
vec2 dx = vec2(SourceSize.z, 0.0);
|
||||
vec2 dy = vec2(0.0, SourceSize.w);
|
||||
vec2 pix_co = vTexCoord * SourceSize.xy - vec2(0.5, 0.5);
|
||||
vec2 tex_co = (floor(pix_co) + vec2(0.5, 0.5)) * SourceSize.zw;
|
||||
vec2 dist = fract(pix_co);
|
||||
float curve_x;
|
||||
vec3 col, col2;
|
||||
|
||||
#if ENABLE_LANCZOS
|
||||
curve_x = curve_distance(dist.x, SHARPNESS_H * SHARPNESS_H);
|
||||
|
||||
vec4 coeffs = PI * vec4(1.0 + curve_x, curve_x, 1.0 - curve_x, 2.0 - curve_x);
|
||||
|
||||
coeffs = FIX(coeffs);
|
||||
coeffs = 2.0 * sin(coeffs) * sin(coeffs * 0.5) / (coeffs * coeffs);
|
||||
coeffs /= dot(coeffs, vec4(1.0));
|
||||
|
||||
col = filter_lanczos(coeffs, get_color_matrix(tex_co, dx));
|
||||
col2 = filter_lanczos(coeffs, get_color_matrix(tex_co + dy, dx));
|
||||
#else
|
||||
curve_x = curve_distance(dist.x, SHARPNESS_H);
|
||||
|
||||
col = mix(TEX2D(tex_co).rgb, TEX2D(tex_co + dx).rgb, curve_x);
|
||||
col2 = mix(TEX2D(tex_co + dy).rgb, TEX2D(tex_co + dx + dy).rgb, curve_x);
|
||||
#endif
|
||||
|
||||
col = mix(col, col2, curve_distance(dist.y, SHARPNESS_V));
|
||||
col = pow(col, vec3(GAMMA_INPUT / (DILATION + 1.0)));
|
||||
|
||||
float luma = dot(vec3(0.2126, 0.7152, 0.0722), col);
|
||||
float bright = (max(col.r, max(col.g, col.b)) + luma) * 0.5;
|
||||
float scan_bright = clamp(bright, SCANLINE_BRIGHT_MIN, SCANLINE_BRIGHT_MAX);
|
||||
float scan_beam = clamp(bright * SCANLINE_BEAM_WIDTH_MAX, SCANLINE_BEAM_WIDTH_MIN, SCANLINE_BEAM_WIDTH_MAX);
|
||||
float scan_weight = 1.0 - pow(cos(vTexCoord.y * 2.0 * PI * SourceSize.y) * 0.5 + 0.5, scan_beam) * SCANLINE_STRENGTH;
|
||||
|
||||
float mask = 1.0 - MASK_STRENGTH;
|
||||
vec2 mod_fac = floor(vTexCoord * outsize.xy * SourceSize.xy / (rubyInputSize.xy * vec2(MASK_SIZE, MASK_DOT_HEIGHT * MASK_SIZE)));
|
||||
int dot_no = int(mod((mod_fac.x + mod(mod_fac.y, 2.0) * MASK_STAGGER) / MASK_DOT_WIDTH, 3.0));
|
||||
vec3 mask_weight;
|
||||
|
||||
if (dot_no == 0) mask_weight = vec3(1.0, mask, mask);
|
||||
else if (dot_no == 1) mask_weight = vec3(mask, 1.0, mask);
|
||||
else mask_weight = vec3(mask, mask, 1.0);
|
||||
|
||||
if (rubyInputSize.y >= SCANLINE_CUTOFF)
|
||||
scan_weight = 1.0;
|
||||
|
||||
col2 = col.rgb;
|
||||
col *= vec3(scan_weight);
|
||||
col = mix(col, col2, scan_bright);
|
||||
col *= mask_weight;
|
||||
col = pow(col, vec3(1.0 / GAMMA_OUTPUT));
|
||||
|
||||
FragColor = vec4(col * BRIGHT_BOOST, 1.0);
|
||||
}
|
||||
#endif
|
264
contrib/glshaders/crt-easymode.tweaked.glsl
Normal file
264
contrib/glshaders/crt-easymode.tweaked.glsl
Normal file
@@ -0,0 +1,264 @@
|
||||
#version 120
|
||||
|
||||
/*
|
||||
CRT Shader by EasyMode
|
||||
License: GPL
|
||||
|
||||
A flat CRT shader ideally for 1080p or higher displays.
|
||||
|
||||
Recommended Settings:
|
||||
|
||||
Video
|
||||
- Aspect Ratio: 4:3
|
||||
- Integer Scale: Off
|
||||
|
||||
Shader
|
||||
- Filter: Nearest
|
||||
- Scale: Don't Care
|
||||
|
||||
Example RGB Mask Parameter Settings:
|
||||
|
||||
Aperture Grille (Default)
|
||||
- Dot Width: 1
|
||||
- Dot Height: 1
|
||||
- Stagger: 0
|
||||
|
||||
Lottes' Shadow Mask
|
||||
- Dot Width: 2
|
||||
- Dot Height: 1
|
||||
- Stagger: 3
|
||||
*/
|
||||
|
||||
// Parameter lines go here:
|
||||
#pragma parameter SHARPNESS_H "Sharpness Horizontal" 0.5 0.0 1.0 0.05
|
||||
#pragma parameter SHARPNESS_V "Sharpness Vertical" 1.0 0.0 1.0 0.05
|
||||
#pragma parameter MASK_STRENGTH "Mask Strength" 0.3 0.0 1.0 0.01
|
||||
#pragma parameter MASK_DOT_WIDTH "Mask Dot Width" 1.0 1.0 100.0 1.0
|
||||
#pragma parameter MASK_DOT_HEIGHT "Mask Dot Height" 1.0 1.0 100.0 1.0
|
||||
#pragma parameter MASK_STAGGER "Mask Stagger" 0.0 0.0 100.0 1.0
|
||||
#pragma parameter MASK_SIZE "Mask Size" 1.0 1.0 100.0 1.0
|
||||
#pragma parameter SCANLINE_STRENGTH "Scanline Strength" 1.0 0.0 1.0 0.05
|
||||
#pragma parameter SCANLINE_BEAM_WIDTH_MIN "Scanline Beam Width Min." 1.5 0.5 5.0 0.5
|
||||
#pragma parameter SCANLINE_BEAM_WIDTH_MAX "Scanline Beam Width Max." 1.5 0.5 5.0 0.5
|
||||
#pragma parameter SCANLINE_BRIGHT_MIN "Scanline Brightness Min." 0.35 0.0 1.0 0.05
|
||||
#pragma parameter SCANLINE_BRIGHT_MAX "Scanline Brightness Max." 0.65 0.0 1.0 0.05
|
||||
#pragma parameter SCANLINE_CUTOFF "Scanline Cutoff" 400.0 1.0 1000.0 1.0
|
||||
#pragma parameter GAMMA_INPUT "Gamma Input" 2.0 0.1 5.0 0.1
|
||||
#pragma parameter GAMMA_OUTPUT "Gamma Output" 1.8 0.1 5.0 0.1
|
||||
#pragma parameter BRIGHT_BOOST "Brightness Boost" 1.2 1.0 2.0 0.01
|
||||
#pragma parameter DILATION "Dilation" 1.0 0.0 1.0 1.0
|
||||
|
||||
#if defined(VERTEX)
|
||||
|
||||
#if __VERSION__ >= 130
|
||||
#define COMPAT_VARYING out
|
||||
#define COMPAT_ATTRIBUTE in
|
||||
#define COMPAT_TEXTURE texture
|
||||
#else
|
||||
#define COMPAT_VARYING varying
|
||||
#define COMPAT_ATTRIBUTE attribute
|
||||
#define COMPAT_TEXTURE texture2D
|
||||
#endif
|
||||
|
||||
#ifdef GL_ES
|
||||
#define COMPAT_PRECISION mediump
|
||||
#else
|
||||
#define COMPAT_PRECISION
|
||||
#endif
|
||||
|
||||
COMPAT_ATTRIBUTE vec4 a_position;
|
||||
COMPAT_ATTRIBUTE vec4 COLOR;
|
||||
COMPAT_ATTRIBUTE vec4 TexCoord;
|
||||
COMPAT_VARYING vec4 COL0;
|
||||
COMPAT_VARYING vec2 v_texCoord;
|
||||
|
||||
uniform COMPAT_PRECISION vec2 rubyOutputSize;
|
||||
uniform COMPAT_PRECISION vec2 rubyTextureSize;
|
||||
uniform COMPAT_PRECISION vec2 rubyInputSize;
|
||||
|
||||
void main()
|
||||
{
|
||||
gl_Position = a_position;
|
||||
v_texCoord = vec2(a_position.x + 1.0, 1.0 - a_position.y) / 2.0 * rubyInputSize / rubyTextureSize;
|
||||
}
|
||||
|
||||
#elif defined(FRAGMENT)
|
||||
|
||||
#if __VERSION__ >= 130
|
||||
#define COMPAT_VARYING in
|
||||
#define COMPAT_TEXTURE texture
|
||||
out vec4 FragColor;
|
||||
#else
|
||||
#define COMPAT_VARYING varying
|
||||
#define FragColor gl_FragColor
|
||||
#define COMPAT_TEXTURE texture2D
|
||||
#endif
|
||||
|
||||
#ifdef GL_ES
|
||||
#ifdef GL_FRAGMENT_PRECISION_HIGH
|
||||
precision highp float;
|
||||
#else
|
||||
precision mediump float;
|
||||
precision mediump int;
|
||||
#endif
|
||||
#define COMPAT_PRECISION mediump
|
||||
#else
|
||||
#define COMPAT_PRECISION
|
||||
#endif
|
||||
|
||||
uniform COMPAT_PRECISION vec2 rubyOutputSize;
|
||||
uniform COMPAT_PRECISION vec2 rubyTextureSize;
|
||||
uniform COMPAT_PRECISION vec2 rubyInputSize;
|
||||
uniform sampler2D rubyTexture;
|
||||
COMPAT_VARYING vec2 v_texCoord;
|
||||
|
||||
#define FIX(c) max(abs(c), 1e-5)
|
||||
#define PI 3.141592653589
|
||||
|
||||
#define TEX2D(c) dilate(COMPAT_TEXTURE(rubyTexture, c))
|
||||
|
||||
// compatibility #defines
|
||||
#define Source rubyTexture
|
||||
#define vTexCoord v_texCoord.xy
|
||||
|
||||
#define SourceSize vec4(rubyTextureSize, 1.0 / rubyTextureSize) //either rubyTextureSize or rubyInputSize
|
||||
#define outsize vec4(rubyOutputSize, 1.0 / rubyOutputSize)
|
||||
|
||||
#ifdef PARAMETER_UNIFORM
|
||||
// All parameter floats need to have COMPAT_PRECISION in front of them
|
||||
uniform COMPAT_PRECISION float SHARPNESS_H;
|
||||
uniform COMPAT_PRECISION float SHARPNESS_V;
|
||||
uniform COMPAT_PRECISION float MASK_STRENGTH;
|
||||
uniform COMPAT_PRECISION float MASK_DOT_WIDTH;
|
||||
uniform COMPAT_PRECISION float MASK_DOT_HEIGHT;
|
||||
uniform COMPAT_PRECISION float MASK_STAGGER;
|
||||
uniform COMPAT_PRECISION float MASK_SIZE;
|
||||
uniform COMPAT_PRECISION float SCANLINE_STRENGTH;
|
||||
uniform COMPAT_PRECISION float SCANLINE_BEAM_WIDTH_MIN;
|
||||
uniform COMPAT_PRECISION float SCANLINE_BEAM_WIDTH_MAX;
|
||||
uniform COMPAT_PRECISION float SCANLINE_BRIGHT_MIN;
|
||||
uniform COMPAT_PRECISION float SCANLINE_BRIGHT_MAX;
|
||||
uniform COMPAT_PRECISION float SCANLINE_CUTOFF;
|
||||
uniform COMPAT_PRECISION float GAMMA_INPUT;
|
||||
uniform COMPAT_PRECISION float GAMMA_OUTPUT;
|
||||
uniform COMPAT_PRECISION float BRIGHT_BOOST;
|
||||
uniform COMPAT_PRECISION float DILATION;
|
||||
#else
|
||||
#define SHARPNESS_H 0.55 //tweaked
|
||||
#define SHARPNESS_V 0.55 //tweaked
|
||||
#define MASK_STRENGTH 0.45 //tweaked
|
||||
#define MASK_DOT_WIDTH 1.0
|
||||
#define MASK_DOT_HEIGHT 1.0
|
||||
#define MASK_STAGGER 0.0
|
||||
#define MASK_SIZE 1.0
|
||||
#define SCANLINE_STRENGTH 1.0
|
||||
#define SCANLINE_BEAM_WIDTH_MIN 1.5
|
||||
#define SCANLINE_BEAM_WIDTH_MAX 1.5
|
||||
#define SCANLINE_BRIGHT_MIN 0.35
|
||||
#define SCANLINE_BRIGHT_MAX 0.65
|
||||
#define SCANLINE_CUTOFF 400.0
|
||||
#define GAMMA_INPUT 2.0
|
||||
#define GAMMA_OUTPUT 1.8
|
||||
#define BRIGHT_BOOST 1.225 //tweaked
|
||||
#define DILATION 1.0
|
||||
#endif
|
||||
|
||||
// Set to 0 to use linear filter and gain speed
|
||||
#define ENABLE_LANCZOS 1
|
||||
|
||||
vec4 dilate(vec4 col)
|
||||
{
|
||||
vec4 x = mix(vec4(1.0), col, DILATION);
|
||||
|
||||
return col * x;
|
||||
}
|
||||
|
||||
float curve_distance(float x, float sharp)
|
||||
{
|
||||
|
||||
/*
|
||||
apply half-circle s-curve to distance for sharper (more pixelated) interpolation
|
||||
single line formula for Graph Toy:
|
||||
0.5 - sqrt(0.25 - (x - step(0.5, x)) * (x - step(0.5, x))) * sign(0.5 - x)
|
||||
*/
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
mat4 get_color_matrix(vec2 co, vec2 dx)
|
||||
{
|
||||
return mat4(TEX2D(co - dx), TEX2D(co), TEX2D(co + dx), TEX2D(co + 2.0 * dx));
|
||||
}
|
||||
|
||||
vec3 filter_lanczos(vec4 coeffs, mat4 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.rgb;
|
||||
}
|
||||
|
||||
void main()
|
||||
{
|
||||
vec2 dx = vec2(SourceSize.z, 0.0);
|
||||
vec2 dy = vec2(0.0, SourceSize.w);
|
||||
vec2 pix_co = vTexCoord * SourceSize.xy - vec2(0.5, 0.5);
|
||||
vec2 tex_co = (floor(pix_co) + vec2(0.5, 0.5)) * SourceSize.zw;
|
||||
vec2 dist = fract(pix_co);
|
||||
float curve_x;
|
||||
vec3 col, col2;
|
||||
|
||||
#if ENABLE_LANCZOS
|
||||
curve_x = curve_distance(dist.x, SHARPNESS_H * SHARPNESS_H);
|
||||
|
||||
vec4 coeffs = PI * vec4(1.0 + curve_x, curve_x, 1.0 - curve_x, 2.0 - curve_x);
|
||||
|
||||
coeffs = FIX(coeffs);
|
||||
coeffs = 2.0 * sin(coeffs) * sin(coeffs * 0.5) / (coeffs * coeffs);
|
||||
coeffs /= dot(coeffs, vec4(1.0));
|
||||
|
||||
col = filter_lanczos(coeffs, get_color_matrix(tex_co, dx));
|
||||
col2 = filter_lanczos(coeffs, get_color_matrix(tex_co + dy, dx));
|
||||
#else
|
||||
curve_x = curve_distance(dist.x, SHARPNESS_H);
|
||||
|
||||
col = mix(TEX2D(tex_co).rgb, TEX2D(tex_co + dx).rgb, curve_x);
|
||||
col2 = mix(TEX2D(tex_co + dy).rgb, TEX2D(tex_co + dx + dy).rgb, curve_x);
|
||||
#endif
|
||||
|
||||
col = mix(col, col2, curve_distance(dist.y, SHARPNESS_V));
|
||||
col = pow(col, vec3(GAMMA_INPUT / (DILATION + 1.0)));
|
||||
|
||||
float luma = dot(vec3(0.2126, 0.7152, 0.0722), col);
|
||||
float bright = (max(col.r, max(col.g, col.b)) + luma) * 0.5;
|
||||
float scan_bright = clamp(bright, SCANLINE_BRIGHT_MIN, SCANLINE_BRIGHT_MAX);
|
||||
float scan_beam = clamp(bright * SCANLINE_BEAM_WIDTH_MAX, SCANLINE_BEAM_WIDTH_MIN, SCANLINE_BEAM_WIDTH_MAX);
|
||||
float scan_weight = 1.0 - pow(cos(vTexCoord.y * 2.0 * PI * SourceSize.y) * 0.5 + 0.5, scan_beam) * SCANLINE_STRENGTH;
|
||||
|
||||
float mask = 1.0 - MASK_STRENGTH;
|
||||
vec2 mod_fac = floor(vTexCoord * outsize.xy * SourceSize.xy / (rubyInputSize.xy * vec2(MASK_SIZE, MASK_DOT_HEIGHT * MASK_SIZE)));
|
||||
int dot_no = int(mod((mod_fac.x + mod(mod_fac.y, 2.0) * MASK_STAGGER) / MASK_DOT_WIDTH, 3.0));
|
||||
vec3 mask_weight;
|
||||
|
||||
if (dot_no == 0) mask_weight = vec3(1.0, mask, mask);
|
||||
else if (dot_no == 1) mask_weight = vec3(mask, 1.0, mask);
|
||||
else mask_weight = vec3(mask, mask, 1.0);
|
||||
|
||||
if (rubyInputSize.y >= SCANLINE_CUTOFF)
|
||||
scan_weight = 1.0;
|
||||
|
||||
col2 = col.rgb;
|
||||
col *= vec3(scan_weight);
|
||||
col = mix(col, col2, scan_bright);
|
||||
col *= mask_weight;
|
||||
col = pow(col, vec3(1.0 / GAMMA_OUTPUT));
|
||||
|
||||
FragColor = vec4(col * BRIGHT_BOOST, 1.0);
|
||||
}
|
||||
#endif
|
475
contrib/glshaders/crt-geom.glsl
Normal file
475
contrib/glshaders/crt-geom.glsl
Normal file
@@ -0,0 +1,475 @@
|
||||
#version 120
|
||||
/*
|
||||
CRT-interlaced
|
||||
|
||||
Copyright (C) 2010-2012 cgwg, Themaister and DOLLS
|
||||
|
||||
This program is free software; you can redistribute it and/or modify it
|
||||
under the terms of the GNU General Public License as published by the Free
|
||||
Software Foundation; either version 2 of the License, or (at your option)
|
||||
any later version.
|
||||
|
||||
(cgwg gave their consent to have the original version of this shader
|
||||
distributed under the GPL in this message:
|
||||
|
||||
http://board.byuu.org/viewtopic.php?p=26075#p26075
|
||||
|
||||
"Feel free to distribute my shaders under the GPL. After all, the
|
||||
barrel distortion code was taken from the Curvature shader, which is
|
||||
under the GPL."
|
||||
)
|
||||
This shader variant is pre-configured with screen curvature
|
||||
*/
|
||||
|
||||
#pragma parameter CRTgamma "CRTGeom Target Gamma" 2.4 0.1 5.0 0.1
|
||||
#pragma parameter monitorgamma "CRTGeom Monitor Gamma" 2.2 0.1 5.0 0.1
|
||||
#pragma parameter d "CRTGeom Distance" 1.6 0.1 3.0 0.1
|
||||
#pragma parameter CURVATURE "CRTGeom Curvature Toggle" 1.0 0.0 1.0 1.0
|
||||
#pragma parameter R "CRTGeom Curvature Radius" 2.0 0.1 10.0 0.1
|
||||
#pragma parameter cornersize "CRTGeom Corner Size" 0.03 0.001 1.0 0.005
|
||||
#pragma parameter cornersmooth "CRTGeom Corner Smoothness" 1000.0 80.0 2000.0 100.0
|
||||
#pragma parameter x_tilt "CRTGeom Horizontal Tilt" 0.0 -0.5 0.5 0.05
|
||||
#pragma parameter y_tilt "CRTGeom Vertical Tilt" 0.0 -0.5 0.5 0.05
|
||||
#pragma parameter overscan_x "CRTGeom Horiz. Overscan %" 100.0 -125.0 125.0 1.0
|
||||
#pragma parameter overscan_y "CRTGeom Vert. Overscan %" 100.0 -125.0 125.0 1.0
|
||||
#pragma parameter DOTMASK "CRTGeom Dot Mask Toggle" 0.3 0.0 0.3 0.3
|
||||
#pragma parameter SHARPER "CRTGeom Sharpness" 1.0 1.0 3.0 1.0
|
||||
#pragma parameter scanline_weight "CRTGeom Scanline Weight" 0.3 0.1 0.5 0.05
|
||||
#pragma parameter lum "CRTGeom Luminance" 0.0 0.0 1.0 0.01
|
||||
#pragma parameter interlace_detect "CRTGeom Interlacing Simulation" 1.0 0.0 1.0 1.0
|
||||
|
||||
#ifndef PARAMETER_UNIFORM
|
||||
#define CRTgamma 2.4
|
||||
#define monitorgamma 2.2
|
||||
#define d 1.6
|
||||
#define CURVATURE 1.0
|
||||
#define R 2.0
|
||||
#define cornersize 0.03
|
||||
#define cornersmooth 1000.0
|
||||
#define x_tilt 0.0
|
||||
#define y_tilt 0.0
|
||||
#define overscan_x 100.0
|
||||
#define overscan_y 100.0
|
||||
#define DOTMASK 0.3
|
||||
#define SHARPER 1.0
|
||||
#define scanline_weight 0.3
|
||||
#define lum 0.0
|
||||
#define interlace_detect 1.0
|
||||
#endif
|
||||
|
||||
#if defined(VERTEX)
|
||||
|
||||
#if __VERSION__ >= 130
|
||||
#define COMPAT_VARYING out
|
||||
#define COMPAT_ATTRIBUTE in
|
||||
#define COMPAT_TEXTURE texture
|
||||
#else
|
||||
#define COMPAT_VARYING varying
|
||||
#define COMPAT_ATTRIBUTE attribute
|
||||
#define COMPAT_TEXTURE texture2D
|
||||
#endif
|
||||
|
||||
#ifdef GL_ES
|
||||
#define COMPAT_PRECISION mediump
|
||||
#else
|
||||
#define COMPAT_PRECISION
|
||||
#endif
|
||||
|
||||
COMPAT_ATTRIBUTE vec4 a_position;
|
||||
COMPAT_VARYING vec2 v_texCoord;
|
||||
|
||||
uniform COMPAT_PRECISION vec2 rubyOutputSize;
|
||||
uniform COMPAT_PRECISION vec2 rubyTextureSize;
|
||||
uniform COMPAT_PRECISION vec2 rubyInputSize;
|
||||
|
||||
COMPAT_VARYING vec2 overscan;
|
||||
COMPAT_VARYING vec2 aspect;
|
||||
COMPAT_VARYING vec3 stretch;
|
||||
COMPAT_VARYING vec2 sinangle;
|
||||
COMPAT_VARYING vec2 cosangle;
|
||||
COMPAT_VARYING vec2 one;
|
||||
COMPAT_VARYING float mod_factor;
|
||||
COMPAT_VARYING vec2 ilfac;
|
||||
|
||||
#ifdef PARAMETER_UNIFORM
|
||||
uniform COMPAT_PRECISION float CRTgamma;
|
||||
uniform COMPAT_PRECISION float monitorgamma;
|
||||
uniform COMPAT_PRECISION float d;
|
||||
uniform COMPAT_PRECISION float CURVATURE;
|
||||
uniform COMPAT_PRECISION float R;
|
||||
uniform COMPAT_PRECISION float cornersize;
|
||||
uniform COMPAT_PRECISION float cornersmooth;
|
||||
uniform COMPAT_PRECISION float x_tilt;
|
||||
uniform COMPAT_PRECISION float y_tilt;
|
||||
uniform COMPAT_PRECISION float overscan_x;
|
||||
uniform COMPAT_PRECISION float overscan_y;
|
||||
uniform COMPAT_PRECISION float DOTMASK;
|
||||
uniform COMPAT_PRECISION float SHARPER;
|
||||
uniform COMPAT_PRECISION float scanline_weight;
|
||||
uniform COMPAT_PRECISION float lum;
|
||||
uniform COMPAT_PRECISION float interlace_detect;
|
||||
#endif
|
||||
|
||||
#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 bkwtrans(vec2 xy)
|
||||
{
|
||||
float c = intersect(xy);
|
||||
vec2 point = vec2(c)*xy;
|
||||
point -= vec2(-R)*sinangle;
|
||||
point /= vec2(R);
|
||||
vec2 tang = sinangle/cosangle;
|
||||
vec2 poc = point/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 = R*acos(a);
|
||||
return uv*r/sin(r/R);
|
||||
}
|
||||
|
||||
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));
|
||||
}
|
||||
|
||||
void main()
|
||||
{
|
||||
// START of parameters
|
||||
|
||||
// gamma of simulated CRT
|
||||
// CRTgamma = 1.8;
|
||||
// gamma of display monitor (typically 2.2 is correct)
|
||||
// monitorgamma = 2.2;
|
||||
// overscan (e.g. 1.02 for 2% overscan)
|
||||
overscan = vec2(1.00,1.00);
|
||||
// aspect ratio
|
||||
aspect = vec2(1.0, 0.75);
|
||||
// lengths are measured in units of (approximately) the width
|
||||
// of the monitor simulated distance from viewer to monitor
|
||||
// d = 2.0;
|
||||
// radius of curvature
|
||||
// R = 1.5;
|
||||
// tilt angle in radians
|
||||
// (behavior might be a bit wrong if both components are
|
||||
// nonzero)
|
||||
const vec2 angle = vec2(0.0,0.0);
|
||||
// size of curved corners
|
||||
// cornersize = 0.03;
|
||||
// border smoothness parameter
|
||||
// decrease if borders are too aliased
|
||||
// cornersmooth = 1000.0;
|
||||
|
||||
// END of parameters
|
||||
|
||||
gl_Position = a_position;
|
||||
v_texCoord = vec2(a_position.x + 1.0, 1.0 - a_position.y) / 2.0 * rubyInputSize / rubyTextureSize;
|
||||
|
||||
// Precalculate a bunch of useful values we'll need in the fragment
|
||||
// shader.
|
||||
sinangle = sin(vec2(x_tilt, y_tilt)) + vec2(0.001);//sin(vec2(max(abs(x_tilt), 1e-3), max(abs(y_tilt), 1e-3)));
|
||||
cosangle = cos(vec2(x_tilt, y_tilt)) + vec2(0.001);//cos(vec2(max(abs(x_tilt), 1e-3), max(abs(y_tilt), 1e-3)));
|
||||
stretch = maxscale();
|
||||
|
||||
// Disable interlacing as per https://emulation-general.fandom.com/wiki/CRT_Geom
|
||||
// ilfac = vec2(1.0,clamp(floor(rubyInputSize.y/200.0), 1.0, 2.0));
|
||||
ilfac = vec2(1.0,1.0);
|
||||
|
||||
// The size of one texel, in texture-coordinates.
|
||||
vec2 sharpTextureSize = vec2(SHARPER * rubyTextureSize.x, rubyTextureSize.y);
|
||||
one = ilfac / sharpTextureSize;
|
||||
|
||||
// Resulting X pixel-coordinate of the pixel we're drawing.
|
||||
mod_factor = v_texCoord.x * rubyTextureSize.x * rubyOutputSize.x / rubyInputSize.x;
|
||||
|
||||
}
|
||||
|
||||
#elif defined(FRAGMENT)
|
||||
|
||||
#if __VERSION__ >= 130
|
||||
#define COMPAT_VARYING in
|
||||
#define COMPAT_TEXTURE texture
|
||||
out vec4 FragColor;
|
||||
#else
|
||||
#define COMPAT_VARYING varying
|
||||
#define FragColor gl_FragColor
|
||||
#define COMPAT_TEXTURE texture2D
|
||||
#endif
|
||||
|
||||
#ifdef GL_ES
|
||||
#ifdef GL_FRAGMENT_PRECISION_HIGH
|
||||
precision highp float;
|
||||
#else
|
||||
precision mediump float;
|
||||
#endif
|
||||
#define COMPAT_PRECISION mediump
|
||||
#else
|
||||
#define COMPAT_PRECISION
|
||||
#endif
|
||||
|
||||
struct output_dummy {
|
||||
vec4 _color;
|
||||
};
|
||||
|
||||
COMPAT_VARYING vec2 v_texCoord;
|
||||
|
||||
uniform COMPAT_PRECISION int rubyFrameCount;
|
||||
uniform COMPAT_PRECISION vec2 rubyOutputSize;
|
||||
uniform COMPAT_PRECISION vec2 rubyTextureSize;
|
||||
uniform COMPAT_PRECISION vec2 rubyInputSize;
|
||||
uniform sampler2D rubyTexture;
|
||||
|
||||
// Comment the next line to disable interpolation in linear gamma (and
|
||||
// gain speed).
|
||||
#define LINEAR_PROCESSING
|
||||
|
||||
// Enable screen curvature.
|
||||
//#define CURVATURE
|
||||
|
||||
// Enable 3x oversampling of the beam profile
|
||||
#define OVERSAMPLE
|
||||
|
||||
// Use the older, purely gaussian beam profile
|
||||
//#define USEGAUSSIAN
|
||||
|
||||
// Macros.
|
||||
#define FIX(c) max(abs(c), 1e-5);
|
||||
#define PI 3.141592653589
|
||||
|
||||
#ifdef LINEAR_PROCESSING
|
||||
#define TEX2D(c) pow(COMPAT_TEXTURE(rubyTexture, (c)), vec4(CRTgamma))
|
||||
#else
|
||||
#define TEX2D(c) COMPAT_TEXTURE(rubyTexture, (c))
|
||||
#endif
|
||||
|
||||
COMPAT_VARYING vec2 one;
|
||||
COMPAT_VARYING float mod_factor;
|
||||
COMPAT_VARYING vec2 ilfac;
|
||||
COMPAT_VARYING vec2 overscan;
|
||||
COMPAT_VARYING vec2 aspect;
|
||||
COMPAT_VARYING vec3 stretch;
|
||||
COMPAT_VARYING vec2 sinangle;
|
||||
COMPAT_VARYING vec2 cosangle;
|
||||
|
||||
#ifdef PARAMETER_UNIFORM
|
||||
uniform COMPAT_PRECISION float CRTgamma;
|
||||
uniform COMPAT_PRECISION float monitorgamma;
|
||||
uniform COMPAT_PRECISION float d;
|
||||
uniform COMPAT_PRECISION float CURVATURE;
|
||||
uniform COMPAT_PRECISION float R;
|
||||
uniform COMPAT_PRECISION float cornersize;
|
||||
uniform COMPAT_PRECISION float cornersmooth;
|
||||
uniform COMPAT_PRECISION float x_tilt;
|
||||
uniform COMPAT_PRECISION float y_tilt;
|
||||
uniform COMPAT_PRECISION float overscan_x;
|
||||
uniform COMPAT_PRECISION float overscan_y;
|
||||
uniform COMPAT_PRECISION float DOTMASK;
|
||||
uniform COMPAT_PRECISION float SHARPER;
|
||||
uniform COMPAT_PRECISION float scanline_weight;
|
||||
uniform COMPAT_PRECISION float lum;
|
||||
uniform COMPAT_PRECISION float interlace_detect;
|
||||
#endif
|
||||
|
||||
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 bkwtrans(vec2 xy)
|
||||
{
|
||||
float c = intersect(xy);
|
||||
vec2 point = vec2(c)*xy;
|
||||
point -= vec2(-R)*sinangle;
|
||||
point /= vec2(R);
|
||||
vec2 tang = sinangle/cosangle;
|
||||
vec2 poc = point/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 transform(vec2 coord)
|
||||
{
|
||||
coord *= rubyTextureSize / rubyInputSize;
|
||||
coord = (coord-vec2(0.5))*aspect*stretch.z+stretch.xy;
|
||||
return (bkwtrans(coord)/vec2(overscan_x / 100.0, overscan_y / 100.0)/aspect+vec2(0.5)) * rubyInputSize / rubyTextureSize;
|
||||
}
|
||||
|
||||
float corner(vec2 coord)
|
||||
{
|
||||
coord *= rubyTextureSize / rubyInputSize;
|
||||
coord = (coord - vec2(0.5)) * vec2(overscan_x / 100.0, overscan_y / 100.0) + vec2(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);
|
||||
}
|
||||
|
||||
// Calculate the influence of a scanline on the current pixel.
|
||||
//
|
||||
// 'distance' is the distance in texture coordinates from the current
|
||||
// pixel to the scanline in question.
|
||||
// 'color' is the colour of the scanline at the horizontal location of
|
||||
// the current pixel.
|
||||
vec4 scanlineWeights(float distance, vec4 color)
|
||||
{
|
||||
// "wid" controls the width of the scanline beam, for each RGB
|
||||
// channel The "weights" lines basically specify the formula
|
||||
// that gives you the profile of the beam, i.e. the intensity as
|
||||
// a function of distance from the vertical center of the
|
||||
// scanline. In this case, it is gaussian if width=2, and
|
||||
// becomes nongaussian for larger widths. Ideally this should
|
||||
// be normalized so that the integral across the beam is
|
||||
// independent of its width. That is, for a narrower beam
|
||||
// "weights" should have a higher peak at the center of the
|
||||
// scanline than for a wider beam.
|
||||
#ifdef USEGAUSSIAN
|
||||
vec4 wid = 0.3 + 0.1 * pow(color, vec4(3.0));
|
||||
vec4 weights = vec4(distance / wid);
|
||||
return (lum + 0.4) * exp(-weights * weights) / wid;
|
||||
#else
|
||||
vec4 wid = 2.0 + 2.0 * pow(color, vec4(4.0));
|
||||
vec4 weights = vec4(distance / scanline_weight);
|
||||
return (lum + 1.4) * exp(-pow(weights * inversesqrt(0.5 * wid), wid)) / (0.6 + 0.2 * wid);
|
||||
#endif
|
||||
}
|
||||
|
||||
void main()
|
||||
{
|
||||
// Here's a helpful diagram to keep in mind while trying to
|
||||
// understand the code:
|
||||
//
|
||||
// | | | | |
|
||||
// -------------------------------
|
||||
// | | | | |
|
||||
// | 01 | 11 | 21 | 31 | <-- current scanline
|
||||
// | | @ | | |
|
||||
// -------------------------------
|
||||
// | | | | |
|
||||
// | 02 | 12 | 22 | 32 | <-- next scanline
|
||||
// | | | | |
|
||||
// -------------------------------
|
||||
// | | | | |
|
||||
//
|
||||
// Each character-cell represents a pixel on the output
|
||||
// surface, "@" represents the current pixel (always somewhere
|
||||
// in the bottom half of the current scan-line, or the top-half
|
||||
// of the next scanline). The grid of lines represents the
|
||||
// edges of the texels of the underlying texture.
|
||||
|
||||
// Texture coordinates of the texel containing the active pixel.
|
||||
vec2 xy = (CURVATURE > 0.5) ? transform(v_texCoord.xy) : v_texCoord.xy;
|
||||
|
||||
float cval = corner(xy);
|
||||
|
||||
// Of all the pixels that are mapped onto the texel we are
|
||||
// currently rendering, which pixel are we currently rendering?
|
||||
vec2 ilvec = vec2(0.0,ilfac.y * interlace_detect > 1.5 ? mod(float(rubyFrameCount),2.0) : 0.0);
|
||||
vec2 ratio_scale = (xy * rubyTextureSize - vec2(0.5) + ilvec)/ilfac;
|
||||
#ifdef OVERSAMPLE
|
||||
float filter_ = rubyInputSize.y/rubyOutputSize.y;//fwidth(ratio_scale.y);
|
||||
#endif
|
||||
vec2 uv_ratio = fract(ratio_scale);
|
||||
|
||||
// Snap to the center of the underlying texel.
|
||||
xy = (floor(ratio_scale)*ilfac + vec2(0.5) - ilvec) / rubyTextureSize;
|
||||
|
||||
// Calculate Lanczos scaling coefficients describing the effect
|
||||
// of various neighbour texels in a scanline on the current
|
||||
// pixel.
|
||||
vec4 coeffs = PI * vec4(1.0 + uv_ratio.x, uv_ratio.x, 1.0 - uv_ratio.x, 2.0 - uv_ratio.x);
|
||||
|
||||
// Prevent division by zero.
|
||||
coeffs = FIX(coeffs);
|
||||
|
||||
// Lanczos2 kernel.
|
||||
coeffs = 2.0 * sin(coeffs) * sin(coeffs / 2.0) / (coeffs * coeffs);
|
||||
|
||||
// Normalize.
|
||||
coeffs /= dot(coeffs, vec4(1.0));
|
||||
|
||||
// Calculate the effective colour of the current and next
|
||||
// scanlines at the horizontal location of the current pixel,
|
||||
// using the Lanczos coefficients above.
|
||||
vec4 col = clamp(mat4(
|
||||
TEX2D(xy + vec2(-one.x, 0.0)),
|
||||
TEX2D(xy),
|
||||
TEX2D(xy + vec2(one.x, 0.0)),
|
||||
TEX2D(xy + vec2(2.0 * one.x, 0.0))) * coeffs,
|
||||
0.0, 1.0);
|
||||
vec4 col2 = clamp(mat4(
|
||||
TEX2D(xy + vec2(-one.x, one.y)),
|
||||
TEX2D(xy + vec2(0.0, one.y)),
|
||||
TEX2D(xy + one),
|
||||
TEX2D(xy + vec2(2.0 * one.x, one.y))) * coeffs,
|
||||
0.0, 1.0);
|
||||
|
||||
#ifndef LINEAR_PROCESSING
|
||||
col = pow(col , vec4(CRTgamma));
|
||||
col2 = pow(col2, vec4(CRTgamma));
|
||||
#endif
|
||||
|
||||
// Calculate the influence of the current and next scanlines on
|
||||
// the current pixel.
|
||||
vec4 weights = scanlineWeights(uv_ratio.y, col);
|
||||
vec4 weights2 = scanlineWeights(1.0 - uv_ratio.y, col2);
|
||||
#ifdef OVERSAMPLE
|
||||
uv_ratio.y =uv_ratio.y+1.0/3.0*filter_;
|
||||
weights = (weights+scanlineWeights(uv_ratio.y, col))/3.0;
|
||||
weights2=(weights2+scanlineWeights(abs(1.0-uv_ratio.y), col2))/3.0;
|
||||
uv_ratio.y =uv_ratio.y-2.0/3.0*filter_;
|
||||
weights=weights+scanlineWeights(abs(uv_ratio.y), col)/3.0;
|
||||
weights2=weights2+scanlineWeights(abs(1.0-uv_ratio.y), col2)/3.0;
|
||||
#endif
|
||||
|
||||
vec3 mul_res = (col * weights + col2 * weights2).rgb * vec3(cval);
|
||||
|
||||
// dot-mask emulation:
|
||||
// Output pixels are alternately tinted green and magenta.
|
||||
vec3 dotMaskWeights = mix(
|
||||
vec3(1.0, 1.0 - DOTMASK, 1.0),
|
||||
vec3(1.0 - DOTMASK, 1.0, 1.0 - DOTMASK),
|
||||
floor(mod(mod_factor, 2.0))
|
||||
);
|
||||
|
||||
mul_res *= dotMaskWeights;
|
||||
|
||||
// Convert the image gamma for display on our output device.
|
||||
mul_res = pow(mul_res, vec3(1.0 / monitorgamma));
|
||||
|
||||
// Color the texel.
|
||||
output_dummy _OUT;
|
||||
FragColor = vec4(mul_res, 1.0);
|
||||
return;
|
||||
}
|
||||
#endif
|
475
contrib/glshaders/crt-geom.tweaked.glsl
Normal file
475
contrib/glshaders/crt-geom.tweaked.glsl
Normal file
@@ -0,0 +1,475 @@
|
||||
#version 120
|
||||
/*
|
||||
CRT-interlaced
|
||||
|
||||
Copyright (C) 2010-2012 cgwg, Themaister and DOLLS
|
||||
|
||||
This program is free software; you can redistribute it and/or modify it
|
||||
under the terms of the GNU General Public License as published by the Free
|
||||
Software Foundation; either version 2 of the License, or (at your option)
|
||||
any later version.
|
||||
|
||||
(cgwg gave their consent to have the original version of this shader
|
||||
distributed under the GPL in this message:
|
||||
|
||||
http://board.byuu.org/viewtopic.php?p=26075#p26075
|
||||
|
||||
"Feel free to distribute my shaders under the GPL. After all, the
|
||||
barrel distortion code was taken from the Curvature shader, which is
|
||||
under the GPL."
|
||||
)
|
||||
This shader variant is pre-configured with screen curvature
|
||||
*/
|
||||
|
||||
#pragma parameter CRTgamma "CRTGeom Target Gamma" 2.4 0.1 5.0 0.1
|
||||
#pragma parameter monitorgamma "CRTGeom Monitor Gamma" 2.2 0.1 5.0 0.1
|
||||
#pragma parameter d "CRTGeom Distance" 1.6 0.1 3.0 0.1
|
||||
#pragma parameter CURVATURE "CRTGeom Curvature Toggle" 1.0 0.0 1.0 1.0
|
||||
#pragma parameter R "CRTGeom Curvature Radius" 2.0 0.1 10.0 0.1
|
||||
#pragma parameter cornersize "CRTGeom Corner Size" 0.03 0.001 1.0 0.005
|
||||
#pragma parameter cornersmooth "CRTGeom Corner Smoothness" 1000.0 80.0 2000.0 100.0
|
||||
#pragma parameter x_tilt "CRTGeom Horizontal Tilt" 0.0 -0.5 0.5 0.05
|
||||
#pragma parameter y_tilt "CRTGeom Vertical Tilt" 0.0 -0.5 0.5 0.05
|
||||
#pragma parameter overscan_x "CRTGeom Horiz. Overscan %" 100.0 -125.0 125.0 1.0
|
||||
#pragma parameter overscan_y "CRTGeom Vert. Overscan %" 100.0 -125.0 125.0 1.0
|
||||
#pragma parameter DOTMASK "CRTGeom Dot Mask Toggle" 0.3 0.0 0.3 0.3
|
||||
#pragma parameter SHARPER "CRTGeom Sharpness" 1.0 1.0 3.0 1.0
|
||||
#pragma parameter scanline_weight "CRTGeom Scanline Weight" 0.3 0.1 0.5 0.05
|
||||
#pragma parameter lum "CRTGeom Luminance" 0.0 0.0 1.0 0.01
|
||||
#pragma parameter interlace_detect "CRTGeom Interlacing Simulation" 1.0 0.0 1.0 1.0
|
||||
|
||||
#ifndef PARAMETER_UNIFORM
|
||||
#define CRTgamma 1.9 //tweaked
|
||||
#define monitorgamma 2.2
|
||||
#define d 2.6 //tweaked
|
||||
#define CURVATURE 1.0
|
||||
#define R 3.0 //tweaked
|
||||
#define cornersize 0.01 //tweaked
|
||||
#define cornersmooth 1000.0
|
||||
#define x_tilt 0.0
|
||||
#define y_tilt 0.0
|
||||
#define overscan_x 100.0
|
||||
#define overscan_y 100.0
|
||||
#define DOTMASK 0.3
|
||||
#define SHARPER 1.0
|
||||
#define scanline_weight 0.3
|
||||
#define lum 0.125 //tweaked
|
||||
#define interlace_detect 1.0
|
||||
#endif
|
||||
|
||||
#if defined(VERTEX)
|
||||
|
||||
#if __VERSION__ >= 130
|
||||
#define COMPAT_VARYING out
|
||||
#define COMPAT_ATTRIBUTE in
|
||||
#define COMPAT_TEXTURE texture
|
||||
#else
|
||||
#define COMPAT_VARYING varying
|
||||
#define COMPAT_ATTRIBUTE attribute
|
||||
#define COMPAT_TEXTURE texture2D
|
||||
#endif
|
||||
|
||||
#ifdef GL_ES
|
||||
#define COMPAT_PRECISION mediump
|
||||
#else
|
||||
#define COMPAT_PRECISION
|
||||
#endif
|
||||
|
||||
COMPAT_ATTRIBUTE vec4 a_position;
|
||||
COMPAT_VARYING vec2 v_texCoord;
|
||||
|
||||
uniform COMPAT_PRECISION vec2 rubyOutputSize;
|
||||
uniform COMPAT_PRECISION vec2 rubyTextureSize;
|
||||
uniform COMPAT_PRECISION vec2 rubyInputSize;
|
||||
|
||||
COMPAT_VARYING vec2 overscan;
|
||||
COMPAT_VARYING vec2 aspect;
|
||||
COMPAT_VARYING vec3 stretch;
|
||||
COMPAT_VARYING vec2 sinangle;
|
||||
COMPAT_VARYING vec2 cosangle;
|
||||
COMPAT_VARYING vec2 one;
|
||||
COMPAT_VARYING float mod_factor;
|
||||
COMPAT_VARYING vec2 ilfac;
|
||||
|
||||
#ifdef PARAMETER_UNIFORM
|
||||
uniform COMPAT_PRECISION float CRTgamma;
|
||||
uniform COMPAT_PRECISION float monitorgamma;
|
||||
uniform COMPAT_PRECISION float d;
|
||||
uniform COMPAT_PRECISION float CURVATURE;
|
||||
uniform COMPAT_PRECISION float R;
|
||||
uniform COMPAT_PRECISION float cornersize;
|
||||
uniform COMPAT_PRECISION float cornersmooth;
|
||||
uniform COMPAT_PRECISION float x_tilt;
|
||||
uniform COMPAT_PRECISION float y_tilt;
|
||||
uniform COMPAT_PRECISION float overscan_x;
|
||||
uniform COMPAT_PRECISION float overscan_y;
|
||||
uniform COMPAT_PRECISION float DOTMASK;
|
||||
uniform COMPAT_PRECISION float SHARPER;
|
||||
uniform COMPAT_PRECISION float scanline_weight;
|
||||
uniform COMPAT_PRECISION float lum;
|
||||
uniform COMPAT_PRECISION float interlace_detect;
|
||||
#endif
|
||||
|
||||
#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 bkwtrans(vec2 xy)
|
||||
{
|
||||
float c = intersect(xy);
|
||||
vec2 point = vec2(c)*xy;
|
||||
point -= vec2(-R)*sinangle;
|
||||
point /= vec2(R);
|
||||
vec2 tang = sinangle/cosangle;
|
||||
vec2 poc = point/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 = R*acos(a);
|
||||
return uv*r/sin(r/R);
|
||||
}
|
||||
|
||||
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));
|
||||
}
|
||||
|
||||
void main()
|
||||
{
|
||||
// START of parameters
|
||||
|
||||
// gamma of simulated CRT
|
||||
// CRTgamma = 1.8;
|
||||
// gamma of display monitor (typically 2.2 is correct)
|
||||
// monitorgamma = 2.2;
|
||||
// overscan (e.g. 1.02 for 2% overscan)
|
||||
overscan = vec2(1.00,1.00);
|
||||
// aspect ratio
|
||||
aspect = vec2(1.0, 0.75);
|
||||
// lengths are measured in units of (approximately) the width
|
||||
// of the monitor simulated distance from viewer to monitor
|
||||
// d = 2.0;
|
||||
// radius of curvature
|
||||
// R = 1.5;
|
||||
// tilt angle in radians
|
||||
// (behavior might be a bit wrong if both components are
|
||||
// nonzero)
|
||||
const vec2 angle = vec2(0.0,0.0);
|
||||
// size of curved corners
|
||||
// cornersize = 0.03;
|
||||
// border smoothness parameter
|
||||
// decrease if borders are too aliased
|
||||
// cornersmooth = 1000.0;
|
||||
|
||||
// END of parameters
|
||||
|
||||
gl_Position = a_position;
|
||||
v_texCoord = vec2(a_position.x + 1.0, 1.0 - a_position.y) / 2.0 * rubyInputSize / rubyTextureSize;
|
||||
|
||||
// Precalculate a bunch of useful values we'll need in the fragment
|
||||
// shader.
|
||||
sinangle = sin(vec2(x_tilt, y_tilt)) + vec2(0.001);//sin(vec2(max(abs(x_tilt), 1e-3), max(abs(y_tilt), 1e-3)));
|
||||
cosangle = cos(vec2(x_tilt, y_tilt)) + vec2(0.001);//cos(vec2(max(abs(x_tilt), 1e-3), max(abs(y_tilt), 1e-3)));
|
||||
stretch = maxscale();
|
||||
|
||||
// Disable interlacing as per https://emulation-general.fandom.com/wiki/CRT_Geom
|
||||
// ilfac = vec2(1.0,clamp(floor(rubyInputSize.y/200.0), 1.0, 2.0));
|
||||
ilfac = vec2(1.0,1.0);
|
||||
|
||||
// The size of one texel, in texture-coordinates.
|
||||
vec2 sharpTextureSize = vec2(SHARPER * rubyTextureSize.x, rubyTextureSize.y);
|
||||
one = ilfac / sharpTextureSize;
|
||||
|
||||
// Resulting X pixel-coordinate of the pixel we're drawing.
|
||||
mod_factor = v_texCoord.x * rubyTextureSize.x * rubyOutputSize.x / rubyInputSize.x;
|
||||
|
||||
}
|
||||
|
||||
#elif defined(FRAGMENT)
|
||||
|
||||
#if __VERSION__ >= 130
|
||||
#define COMPAT_VARYING in
|
||||
#define COMPAT_TEXTURE texture
|
||||
out vec4 FragColor;
|
||||
#else
|
||||
#define COMPAT_VARYING varying
|
||||
#define FragColor gl_FragColor
|
||||
#define COMPAT_TEXTURE texture2D
|
||||
#endif
|
||||
|
||||
#ifdef GL_ES
|
||||
#ifdef GL_FRAGMENT_PRECISION_HIGH
|
||||
precision highp float;
|
||||
#else
|
||||
precision mediump float;
|
||||
#endif
|
||||
#define COMPAT_PRECISION mediump
|
||||
#else
|
||||
#define COMPAT_PRECISION
|
||||
#endif
|
||||
|
||||
struct output_dummy {
|
||||
vec4 _color;
|
||||
};
|
||||
|
||||
COMPAT_VARYING vec2 v_texCoord;
|
||||
|
||||
uniform COMPAT_PRECISION int rubyFrameCount;
|
||||
uniform COMPAT_PRECISION vec2 rubyOutputSize;
|
||||
uniform COMPAT_PRECISION vec2 rubyTextureSize;
|
||||
uniform COMPAT_PRECISION vec2 rubyInputSize;
|
||||
uniform sampler2D rubyTexture;
|
||||
|
||||
// Comment the next line to disable interpolation in linear gamma (and
|
||||
// gain speed).
|
||||
#define LINEAR_PROCESSING
|
||||
|
||||
// Enable screen curvature.
|
||||
//#define CURVATURE
|
||||
|
||||
// Enable 3x oversampling of the beam profile
|
||||
#define OVERSAMPLE
|
||||
|
||||
// Use the older, purely gaussian beam profile
|
||||
//#define USEGAUSSIAN
|
||||
|
||||
// Macros.
|
||||
#define FIX(c) max(abs(c), 1e-5);
|
||||
#define PI 3.141592653589
|
||||
|
||||
#ifdef LINEAR_PROCESSING
|
||||
#define TEX2D(c) pow(COMPAT_TEXTURE(rubyTexture, (c)), vec4(CRTgamma))
|
||||
#else
|
||||
#define TEX2D(c) COMPAT_TEXTURE(rubyTexture, (c))
|
||||
#endif
|
||||
|
||||
COMPAT_VARYING vec2 one;
|
||||
COMPAT_VARYING float mod_factor;
|
||||
COMPAT_VARYING vec2 ilfac;
|
||||
COMPAT_VARYING vec2 overscan;
|
||||
COMPAT_VARYING vec2 aspect;
|
||||
COMPAT_VARYING vec3 stretch;
|
||||
COMPAT_VARYING vec2 sinangle;
|
||||
COMPAT_VARYING vec2 cosangle;
|
||||
|
||||
#ifdef PARAMETER_UNIFORM
|
||||
uniform COMPAT_PRECISION float CRTgamma;
|
||||
uniform COMPAT_PRECISION float monitorgamma;
|
||||
uniform COMPAT_PRECISION float d;
|
||||
uniform COMPAT_PRECISION float CURVATURE;
|
||||
uniform COMPAT_PRECISION float R;
|
||||
uniform COMPAT_PRECISION float cornersize;
|
||||
uniform COMPAT_PRECISION float cornersmooth;
|
||||
uniform COMPAT_PRECISION float x_tilt;
|
||||
uniform COMPAT_PRECISION float y_tilt;
|
||||
uniform COMPAT_PRECISION float overscan_x;
|
||||
uniform COMPAT_PRECISION float overscan_y;
|
||||
uniform COMPAT_PRECISION float DOTMASK;
|
||||
uniform COMPAT_PRECISION float SHARPER;
|
||||
uniform COMPAT_PRECISION float scanline_weight;
|
||||
uniform COMPAT_PRECISION float lum;
|
||||
uniform COMPAT_PRECISION float interlace_detect;
|
||||
#endif
|
||||
|
||||
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 bkwtrans(vec2 xy)
|
||||
{
|
||||
float c = intersect(xy);
|
||||
vec2 point = vec2(c)*xy;
|
||||
point -= vec2(-R)*sinangle;
|
||||
point /= vec2(R);
|
||||
vec2 tang = sinangle/cosangle;
|
||||
vec2 poc = point/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 transform(vec2 coord)
|
||||
{
|
||||
coord *= rubyTextureSize / rubyInputSize;
|
||||
coord = (coord-vec2(0.5))*aspect*stretch.z+stretch.xy;
|
||||
return (bkwtrans(coord)/vec2(overscan_x / 100.0, overscan_y / 100.0)/aspect+vec2(0.5)) * rubyInputSize / rubyTextureSize;
|
||||
}
|
||||
|
||||
float corner(vec2 coord)
|
||||
{
|
||||
coord *= rubyTextureSize / rubyInputSize;
|
||||
coord = (coord - vec2(0.5)) * vec2(overscan_x / 100.0, overscan_y / 100.0) + vec2(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);
|
||||
}
|
||||
|
||||
// Calculate the influence of a scanline on the current pixel.
|
||||
//
|
||||
// 'distance' is the distance in texture coordinates from the current
|
||||
// pixel to the scanline in question.
|
||||
// 'color' is the colour of the scanline at the horizontal location of
|
||||
// the current pixel.
|
||||
vec4 scanlineWeights(float distance, vec4 color)
|
||||
{
|
||||
// "wid" controls the width of the scanline beam, for each RGB
|
||||
// channel The "weights" lines basically specify the formula
|
||||
// that gives you the profile of the beam, i.e. the intensity as
|
||||
// a function of distance from the vertical center of the
|
||||
// scanline. In this case, it is gaussian if width=2, and
|
||||
// becomes nongaussian for larger widths. Ideally this should
|
||||
// be normalized so that the integral across the beam is
|
||||
// independent of its width. That is, for a narrower beam
|
||||
// "weights" should have a higher peak at the center of the
|
||||
// scanline than for a wider beam.
|
||||
#ifdef USEGAUSSIAN
|
||||
vec4 wid = 0.3 + 0.1 * pow(color, vec4(3.0));
|
||||
vec4 weights = vec4(distance / wid);
|
||||
return (lum + 0.4) * exp(-weights * weights) / wid;
|
||||
#else
|
||||
vec4 wid = 2.0 + 2.0 * pow(color, vec4(4.0));
|
||||
vec4 weights = vec4(distance / scanline_weight);
|
||||
return (lum + 1.4) * exp(-pow(weights * inversesqrt(0.5 * wid), wid)) / (0.6 + 0.2 * wid);
|
||||
#endif
|
||||
}
|
||||
|
||||
void main()
|
||||
{
|
||||
// Here's a helpful diagram to keep in mind while trying to
|
||||
// understand the code:
|
||||
//
|
||||
// | | | | |
|
||||
// -------------------------------
|
||||
// | | | | |
|
||||
// | 01 | 11 | 21 | 31 | <-- current scanline
|
||||
// | | @ | | |
|
||||
// -------------------------------
|
||||
// | | | | |
|
||||
// | 02 | 12 | 22 | 32 | <-- next scanline
|
||||
// | | | | |
|
||||
// -------------------------------
|
||||
// | | | | |
|
||||
//
|
||||
// Each character-cell represents a pixel on the output
|
||||
// surface, "@" represents the current pixel (always somewhere
|
||||
// in the bottom half of the current scan-line, or the top-half
|
||||
// of the next scanline). The grid of lines represents the
|
||||
// edges of the texels of the underlying texture.
|
||||
|
||||
// Texture coordinates of the texel containing the active pixel.
|
||||
vec2 xy = (CURVATURE > 0.5) ? transform(v_texCoord.xy) : v_texCoord.xy;
|
||||
|
||||
float cval = corner(xy);
|
||||
|
||||
// Of all the pixels that are mapped onto the texel we are
|
||||
// currently rendering, which pixel are we currently rendering?
|
||||
vec2 ilvec = vec2(0.0,ilfac.y * interlace_detect > 1.5 ? mod(float(rubyFrameCount),2.0) : 0.0);
|
||||
vec2 ratio_scale = (xy * rubyTextureSize - vec2(0.5) + ilvec)/ilfac;
|
||||
#ifdef OVERSAMPLE
|
||||
float filter_ = rubyInputSize.y/rubyOutputSize.y;//fwidth(ratio_scale.y);
|
||||
#endif
|
||||
vec2 uv_ratio = fract(ratio_scale);
|
||||
|
||||
// Snap to the center of the underlying texel.
|
||||
xy = (floor(ratio_scale)*ilfac + vec2(0.5) - ilvec) / rubyTextureSize;
|
||||
|
||||
// Calculate Lanczos scaling coefficients describing the effect
|
||||
// of various neighbour texels in a scanline on the current
|
||||
// pixel.
|
||||
vec4 coeffs = PI * vec4(1.0 + uv_ratio.x, uv_ratio.x, 1.0 - uv_ratio.x, 2.0 - uv_ratio.x);
|
||||
|
||||
// Prevent division by zero.
|
||||
coeffs = FIX(coeffs);
|
||||
|
||||
// Lanczos2 kernel.
|
||||
coeffs = 2.0 * sin(coeffs) * sin(coeffs / 2.0) / (coeffs * coeffs);
|
||||
|
||||
// Normalize.
|
||||
coeffs /= dot(coeffs, vec4(1.0));
|
||||
|
||||
// Calculate the effective colour of the current and next
|
||||
// scanlines at the horizontal location of the current pixel,
|
||||
// using the Lanczos coefficients above.
|
||||
vec4 col = clamp(mat4(
|
||||
TEX2D(xy + vec2(-one.x, 0.0)),
|
||||
TEX2D(xy),
|
||||
TEX2D(xy + vec2(one.x, 0.0)),
|
||||
TEX2D(xy + vec2(2.0 * one.x, 0.0))) * coeffs,
|
||||
0.0, 1.0);
|
||||
vec4 col2 = clamp(mat4(
|
||||
TEX2D(xy + vec2(-one.x, one.y)),
|
||||
TEX2D(xy + vec2(0.0, one.y)),
|
||||
TEX2D(xy + one),
|
||||
TEX2D(xy + vec2(2.0 * one.x, one.y))) * coeffs,
|
||||
0.0, 1.0);
|
||||
|
||||
#ifndef LINEAR_PROCESSING
|
||||
col = pow(col , vec4(CRTgamma));
|
||||
col2 = pow(col2, vec4(CRTgamma));
|
||||
#endif
|
||||
|
||||
// Calculate the influence of the current and next scanlines on
|
||||
// the current pixel.
|
||||
vec4 weights = scanlineWeights(uv_ratio.y, col);
|
||||
vec4 weights2 = scanlineWeights(1.0 - uv_ratio.y, col2);
|
||||
#ifdef OVERSAMPLE
|
||||
uv_ratio.y =uv_ratio.y+1.0/3.0*filter_;
|
||||
weights = (weights+scanlineWeights(uv_ratio.y, col))/3.0;
|
||||
weights2=(weights2+scanlineWeights(abs(1.0-uv_ratio.y), col2))/3.0;
|
||||
uv_ratio.y =uv_ratio.y-2.0/3.0*filter_;
|
||||
weights=weights+scanlineWeights(abs(uv_ratio.y), col)/3.0;
|
||||
weights2=weights2+scanlineWeights(abs(1.0-uv_ratio.y), col2)/3.0;
|
||||
#endif
|
||||
|
||||
vec3 mul_res = (col * weights + col2 * weights2).rgb * vec3(cval);
|
||||
|
||||
// dot-mask emulation:
|
||||
// Output pixels are alternately tinted green and magenta.
|
||||
vec3 dotMaskWeights = mix(
|
||||
vec3(1.0, 1.0 - DOTMASK, 1.0),
|
||||
vec3(1.0 - DOTMASK, 1.0, 1.0 - DOTMASK),
|
||||
floor(mod(mod_factor, 2.0))
|
||||
);
|
||||
|
||||
mul_res *= dotMaskWeights;
|
||||
|
||||
// Convert the image gamma for display on our output device.
|
||||
mul_res = pow(mul_res, vec3(1.0 / monitorgamma));
|
||||
|
||||
// Color the texel.
|
||||
output_dummy _OUT;
|
||||
FragColor = vec4(mul_res, 1.0);
|
||||
return;
|
||||
}
|
||||
#endif
|
239
contrib/glshaders/crt-hyllian.glsl
Normal file
239
contrib/glshaders/crt-hyllian.glsl
Normal file
@@ -0,0 +1,239 @@
|
||||
#version 120
|
||||
|
||||
/*
|
||||
Hyllian's CRT Shader
|
||||
|
||||
Copyright (C) 2011-2016 Hyllian - sergiogdb@gmail.com
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
|
||||
*/
|
||||
|
||||
#pragma parameter PHOSPHOR "CRT - Phosphor ON/OFF" 1.0 0.0 1.0 1.0
|
||||
#pragma parameter VSCANLINES "CRT - Scanlines Direction" 0.0 0.0 1.0 1.0
|
||||
#pragma parameter InputGamma "CRT - Input gamma" 2.4 0.0 5.0 0.1
|
||||
#pragma parameter OutputGamma "CRT - Output Gamma" 2.2 0.0 5.0 0.1
|
||||
#pragma parameter SHARPNESS "CRT - Sharpness Hack" 1.0 1.0 5.0 1.0
|
||||
#pragma parameter COLOR_BOOST "CRT - Color Boost" 1.5 1.0 2.0 0.05
|
||||
#pragma parameter RED_BOOST "CRT - Red Boost" 1.0 1.0 2.0 0.01
|
||||
#pragma parameter GREEN_BOOST "CRT - Green Boost" 1.0 1.0 2.0 0.01
|
||||
#pragma parameter BLUE_BOOST "CRT - Blue Boost" 1.0 1.0 2.0 0.01
|
||||
#pragma parameter SCANLINES_STRENGTH "CRT - Scanline Strength" 0.72 0.0 1.0 0.02
|
||||
#pragma parameter BEAM_MIN_WIDTH "CRT - Min Beam Width" 0.86 0.0 1.0 0.02
|
||||
#pragma parameter BEAM_MAX_WIDTH "CRT - Max Beam Width" 1.0 0.0 1.0 0.02
|
||||
#pragma parameter CRT_ANTI_RINGING "CRT - Anti-Ringing" 0.8 0.0 1.0 0.1
|
||||
|
||||
#define GAMMA_IN(color) pow(color, vec4(InputGamma, InputGamma, InputGamma, InputGamma))
|
||||
#define GAMMA_OUT(color) pow(color, vec4(1.0 / OutputGamma, 1.0 / OutputGamma, 1.0 / OutputGamma, 1.0 / OutputGamma))
|
||||
|
||||
// Horizontal cubic filter.
|
||||
|
||||
// Some known filters use these values:
|
||||
|
||||
// B = 0.0, C = 0.0 => Hermite cubic filter.
|
||||
// B = 1.0, C = 0.0 => Cubic B-Spline filter.
|
||||
// B = 0.0, C = 0.5 => Catmull-Rom Spline filter. This is the default used in this shader.
|
||||
// B = C = 1.0/3.0 => Mitchell-Netravali cubic filter.
|
||||
// B = 0.3782, C = 0.3109 => Robidoux filter.
|
||||
// B = 0.2620, C = 0.3690 => Robidoux Sharp filter.
|
||||
// B = 0.36, C = 0.28 => My best config for ringing elimination in pixel art (Hyllian).
|
||||
|
||||
// For more info, see: http://www.imagemagick.org/Usage/img_diagrams/cubic_survey.gif
|
||||
|
||||
#define texCoord v_texCoord
|
||||
|
||||
#if defined(VERTEX)
|
||||
|
||||
#if __VERSION__ >= 130
|
||||
#define OUT out
|
||||
#define IN in
|
||||
#define tex2D texture
|
||||
#else
|
||||
#define OUT varying
|
||||
#define IN attribute
|
||||
#define tex2D texture2D
|
||||
#endif
|
||||
|
||||
#ifdef GL_ES
|
||||
#define PRECISION mediump
|
||||
#else
|
||||
#define PRECISION
|
||||
#endif
|
||||
|
||||
IN vec4 a_position;
|
||||
IN vec4 Color;
|
||||
IN vec2 TexCoord;
|
||||
OUT vec4 color;
|
||||
OUT vec2 texCoord;
|
||||
|
||||
uniform PRECISION vec2 rubyOutputSize;
|
||||
uniform PRECISION vec2 rubyTextureSize;
|
||||
uniform PRECISION vec2 rubyInputSize;
|
||||
|
||||
void main()
|
||||
{
|
||||
gl_Position = a_position;
|
||||
v_texCoord = vec2(a_position.x + 1.0, 1.0 - a_position.y) / 2.0 * rubyInputSize / rubyTextureSize;
|
||||
}
|
||||
|
||||
|
||||
#elif defined(FRAGMENT)
|
||||
|
||||
#if __VERSION__ >= 130
|
||||
#define IN in
|
||||
#define tex2D texture
|
||||
out vec4 FragColor;
|
||||
#else
|
||||
#define IN varying
|
||||
#define FragColor gl_FragColor
|
||||
#define tex2D texture2D
|
||||
#endif
|
||||
|
||||
#ifdef GL_ES
|
||||
#ifdef GL_FRAGMENT_PRECISION_HIGH
|
||||
precision highp float;
|
||||
#else
|
||||
precision mediump float;
|
||||
#endif
|
||||
#define PRECISION mediump
|
||||
#else
|
||||
#define PRECISION
|
||||
#endif
|
||||
|
||||
uniform PRECISION vec2 rubyOutputSize;
|
||||
uniform PRECISION vec2 rubyTextureSize;
|
||||
uniform PRECISION vec2 rubyInputSize;
|
||||
uniform sampler2D s_p;
|
||||
IN vec2 texCoord;
|
||||
|
||||
#ifdef PARAMETER_UNIFORM
|
||||
uniform PRECISION float PHOSPHOR;
|
||||
uniform PRECISION float VSCANLINES;
|
||||
uniform PRECISION float InputGamma;
|
||||
uniform PRECISION float OutputGamma;
|
||||
uniform PRECISION float SHARPNESS;
|
||||
uniform PRECISION float COLOR_BOOST;
|
||||
uniform PRECISION float RED_BOOST;
|
||||
uniform PRECISION float GREEN_BOOST;
|
||||
uniform PRECISION float BLUE_BOOST;
|
||||
uniform PRECISION float SCANLINES_STRENGTH;
|
||||
uniform PRECISION float BEAM_MIN_WIDTH;
|
||||
uniform PRECISION float BEAM_MAX_WIDTH;
|
||||
uniform PRECISION float CRT_ANTI_RINGING;
|
||||
#else
|
||||
#define PHOSPHOR 1.0
|
||||
#define VSCANLINES 0.0
|
||||
#define InputGamma 2.4
|
||||
#define OutputGamma 2.2
|
||||
#define SHARPNESS 1.0
|
||||
#define COLOR_BOOST 1.5
|
||||
#define RED_BOOST 1.0
|
||||
#define GREEN_BOOST 1.0
|
||||
#define BLUE_BOOST 1.0
|
||||
#define SCANLINES_STRENGTH 0.72
|
||||
#define BEAM_MIN_WIDTH 0.86
|
||||
#define BEAM_MAX_WIDTH 1.0
|
||||
#define CRT_ANTI_RINGING 0.8
|
||||
#endif
|
||||
// END PARAMETERS //
|
||||
|
||||
// Change these params to configure the horizontal filter.
|
||||
const float B = 0.0;
|
||||
const float C = 0.5;
|
||||
|
||||
const mat4 invX = mat4((-B - 6.0*C)/6.0, (12.0 - 9.0*B - 6.0*C)/6.0, -(12.0 - 9.0*B - 6.0*C)/6.0, (B + 6.0*C)/6.0,
|
||||
(3.0*B + 12.0*C)/6.0, (-18.0 + 12.0*B + 6.0*C)/6.0, (18.0 - 15.0*B - 12.0*C)/6.0, -C,
|
||||
(-3.0*B - 6.0*C)/6.0, 0.0, (3.0*B + 6.0*C)/6.0, 0.0,
|
||||
B/6.0, (6.0 - 2.0*B)/6.0, B/6.0, 0.0);
|
||||
|
||||
void main()
|
||||
{
|
||||
vec2 texture_size = vec2(SHARPNESS*rubyTextureSize.x, rubyTextureSize.y);
|
||||
|
||||
vec4 color;
|
||||
vec2 dx = mix(vec2(1.0/texture_size.x, 0.0), vec2(0.0, 1.0/texture_size.y), VSCANLINES);
|
||||
vec2 dy = mix(vec2(0.0, 1.0/texture_size.y), vec2(1.0/texture_size.x, 0.0), VSCANLINES);
|
||||
|
||||
vec2 pix_coord = texCoord*texture_size+vec2(-0.5,0.5);
|
||||
|
||||
vec2 tc = mix((floor(pix_coord) + vec2(0.5, 0.5))/texture_size, (floor(pix_coord) + vec2(1.0, -0.5))/texture_size, VSCANLINES);
|
||||
|
||||
vec2 fp = mix(fract(pix_coord), fract(pix_coord.yx), VSCANLINES);
|
||||
|
||||
vec4 c00 = GAMMA_IN(tex2D(s_p, tc - dx - dy).xyzw);
|
||||
vec4 c01 = GAMMA_IN(tex2D(s_p, tc - dy).xyzw);
|
||||
vec4 c02 = GAMMA_IN(tex2D(s_p, tc + dx - dy).xyzw);
|
||||
vec4 c03 = GAMMA_IN(tex2D(s_p, tc + 2.0*dx - dy).xyzw);
|
||||
vec4 c10 = GAMMA_IN(tex2D(s_p, tc - dx).xyzw);
|
||||
vec4 c11 = GAMMA_IN(tex2D(s_p, tc ).xyzw);
|
||||
vec4 c12 = GAMMA_IN(tex2D(s_p, tc + dx).xyzw);
|
||||
vec4 c13 = GAMMA_IN(tex2D(s_p, tc + 2.0*dx).xyzw);
|
||||
|
||||
// Get min/max samples
|
||||
vec4 min_sample = min(min(c01,c11), min(c02,c12));
|
||||
vec4 max_sample = max(max(c01,c11), max(c02,c12));
|
||||
|
||||
mat4 color_matrix0 = mat4(c00, c01, c02, c03);
|
||||
mat4 color_matrix1 = mat4(c10, c11, c12, c13);
|
||||
|
||||
vec4 lobes = vec4(fp.x*fp.x*fp.x, fp.x*fp.x, fp.x, 1.0);
|
||||
|
||||
vec4 invX_Px = invX * lobes;
|
||||
vec4 color0 = color_matrix0 * invX_Px;
|
||||
vec4 color1 = color_matrix1 * invX_Px;
|
||||
|
||||
// Anti-ringing
|
||||
vec4 aux = color0;
|
||||
color0 = clamp(color0, min_sample, max_sample);
|
||||
color0 = mix(aux, color0, CRT_ANTI_RINGING);
|
||||
aux = color1;
|
||||
color1 = clamp(color1, min_sample, max_sample);
|
||||
color1 = mix(aux, color1, CRT_ANTI_RINGING);
|
||||
|
||||
float pos0 = fp.y;
|
||||
float pos1 = 1.0 - fp.y;
|
||||
|
||||
vec4 lum0 = mix(vec4(BEAM_MIN_WIDTH), vec4(BEAM_MAX_WIDTH), color0);
|
||||
vec4 lum1 = mix(vec4(BEAM_MIN_WIDTH), vec4(BEAM_MAX_WIDTH), color1);
|
||||
|
||||
vec4 d0 = clamp(pos0/(lum0+0.0000001), 0.0, 1.0);
|
||||
vec4 d1 = clamp(pos1/(lum1+0.0000001), 0.0, 1.0);
|
||||
|
||||
d0 = exp(-10.0*SCANLINES_STRENGTH*d0*d0);
|
||||
d1 = exp(-10.0*SCANLINES_STRENGTH*d1*d1);
|
||||
|
||||
color = clamp(color0*d0+color1*d1, 0.0, 1.0);
|
||||
|
||||
color *= COLOR_BOOST*vec4(RED_BOOST, GREEN_BOOST, BLUE_BOOST, 1.0);
|
||||
|
||||
float mod_factor = texCoord.x * rubyOutputSize.x * rubyTextureSize.x / rubyInputSize.x;
|
||||
|
||||
vec4 dotMaskWeights = mix(
|
||||
vec4(1.0, 0.7, 1.0, 1.),
|
||||
vec4(0.7, 1.0, 0.7, 1.),
|
||||
floor(mod(mod_factor, 2.0))
|
||||
);
|
||||
|
||||
color.rgba *= mix(vec4(1.0,1.0,1.0,1.0), dotMaskWeights, PHOSPHOR);
|
||||
|
||||
color = GAMMA_OUT(color);
|
||||
|
||||
FragColor = vec4(color);
|
||||
}
|
||||
#endif
|
697
contrib/glshaders/crt-lottes-fast.glsl
Normal file
697
contrib/glshaders/crt-lottes-fast.glsl
Normal file
@@ -0,0 +1,697 @@
|
||||
#version 120
|
||||
|
||||
//_____________________________/\_______________________________
|
||||
//==============================================================
|
||||
//
|
||||
//
|
||||
// [CRTS] PUBLIC DOMAIN CRT-STYLED SCALAR - 20180120b
|
||||
//
|
||||
// by Timothy Lottes
|
||||
// https://www.shadertoy.com/view/MtSfRK
|
||||
// adapted for RetroArch by hunterk
|
||||
//
|
||||
//
|
||||
//==============================================================
|
||||
////////////////////////////////////////////////////////////////
|
||||
////////////////////////////////////////////////////////////////
|
||||
////////////////////////////////////////////////////////////////
|
||||
//_____________________________/\_______________________________
|
||||
//==============================================================
|
||||
//
|
||||
// WHAT'S NEW
|
||||
//
|
||||
//--------------------------------------------------------------
|
||||
// Evolution of prior shadertoy example
|
||||
//--------------------------------------------------------------
|
||||
// This one is semi-optimized
|
||||
// - Less texture fetches
|
||||
// - Didn't get to instruction level optimization
|
||||
// - Could likely use texture fetch to generate phosphor mask
|
||||
//--------------------------------------------------------------
|
||||
// Added options to disable unused features
|
||||
//--------------------------------------------------------------
|
||||
// Added in exposure matching
|
||||
// - Given scan-line effect and mask always darkens image
|
||||
// - Uses generalized tonemapper to boost mid-level
|
||||
// - Note this can compress highlights
|
||||
// - And won't get back peak brightness
|
||||
// - But best option if one doesn't want as much darkening
|
||||
//--------------------------------------------------------------
|
||||
// Includes option saturation and contrast controls
|
||||
//--------------------------------------------------------------
|
||||
// Added in subtractive aperture grille
|
||||
// - This is a bit brighter than prior
|
||||
//--------------------------------------------------------------
|
||||
// Make sure input to this filter is already low-resolution
|
||||
// - This is not designed to work on titles doing the following
|
||||
// - Rendering to hi-res with nearest sampling
|
||||
//--------------------------------------------------------------
|
||||
// Added a fast and more pixely option for 2 tap/pixel
|
||||
//--------------------------------------------------------------
|
||||
// Improved the vignette when WARP is enabled
|
||||
//--------------------------------------------------------------
|
||||
// Didn't test HLSL or CPU options
|
||||
// - Will incorportate patches if they are broken
|
||||
// - But out of time to try them myself
|
||||
//==============================================================
|
||||
////////////////////////////////////////////////////////////////
|
||||
////////////////////////////////////////////////////////////////
|
||||
////////////////////////////////////////////////////////////////
|
||||
//_____________________________/\_______________________________
|
||||
//==============================================================
|
||||
//
|
||||
// LICENSE = UNLICENSE (aka PUBLIC DOMAIN)
|
||||
//
|
||||
//--------------------------------------------------------------
|
||||
// This is free and unencumbered software released into the
|
||||
// public domain.
|
||||
//--------------------------------------------------------------
|
||||
// Anyone is free to copy, modify, publish, use, compile, sell,
|
||||
// or distribute this software, either in source code form or as
|
||||
// a compiled binary, for any purpose, commercial or
|
||||
// non-commercial, and by any means.
|
||||
//--------------------------------------------------------------
|
||||
// In jurisdictions that recognize copyright laws, the author or
|
||||
// authors of this software dedicate any and all copyright
|
||||
// interest in the software to the public domain. We make this
|
||||
// dedication for the benefit of the public at large and to the
|
||||
// detriment of our heirs and successors. We intend this
|
||||
// dedication to be an overt act of relinquishment in perpetuity
|
||||
// of all present and future rights to this software under
|
||||
// copyright law.
|
||||
//--------------------------------------------------------------
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
|
||||
// KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
|
||||
// WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
|
||||
// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS BE
|
||||
// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
|
||||
// AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT
|
||||
// OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
// DEALINGS IN THE SOFTWARE.
|
||||
//--------------------------------------------------------------
|
||||
// For more information, please refer to
|
||||
// <http://unlicense.org/>
|
||||
//==============================================================
|
||||
////////////////////////////////////////////////////////////////
|
||||
////////////////////////////////////////////////////////////////
|
||||
////////////////////////////////////////////////////////////////
|
||||
|
||||
#pragma parameter MASK "Mask Type" 1.0 0.0 3.0 1.0
|
||||
#pragma parameter MASK_INTENSITY "Mask Intensity" 0.5 0.0 1.0 0.05
|
||||
#pragma parameter SCANLINE_THINNESS "Scanline Intensity" 0.5 0.0 1.0 0.1
|
||||
#pragma parameter SCAN_BLUR "Sharpness" 2.5 1.0 3.0 0.1
|
||||
#pragma parameter CURVATURE "Curvature" 0.02 0.0 0.25 0.01
|
||||
#pragma parameter TRINITRON_CURVE "Trinitron-style Curve" 0.0 0.0 1.0 1.0
|
||||
#pragma parameter CORNER "Corner Round" 3.0 0.0 11.0 1.0
|
||||
#pragma parameter CRT_GAMMA "CRT Gamma" 2.4 0.0 51.0 0.1
|
||||
|
||||
#if defined(VERTEX)
|
||||
|
||||
#if __VERSION__ >= 130
|
||||
#define COMPAT_VARYING out
|
||||
#define COMPAT_ATTRIBUTE in
|
||||
#define COMPAT_TEXTURE texture
|
||||
#else
|
||||
#define COMPAT_VARYING varying
|
||||
#define COMPAT_ATTRIBUTE attribute
|
||||
#define COMPAT_TEXTURE texture2D
|
||||
#endif
|
||||
|
||||
#ifdef GL_ES
|
||||
#define COMPAT_PRECISION mediump
|
||||
#else
|
||||
#define COMPAT_PRECISION
|
||||
#endif
|
||||
|
||||
COMPAT_ATTRIBUTE vec4 a_position;
|
||||
COMPAT_ATTRIBUTE vec4 COLOR;
|
||||
COMPAT_ATTRIBUTE vec4 TexCoord;
|
||||
COMPAT_VARYING vec4 COL0;
|
||||
COMPAT_VARYING vec2 v_texCoord;
|
||||
|
||||
uniform COMPAT_PRECISION vec2 rubyOutputSize;
|
||||
uniform COMPAT_PRECISION vec2 rubyTextureSize;
|
||||
uniform COMPAT_PRECISION vec2 rubyInputSize;
|
||||
|
||||
// compatibility #defines
|
||||
#define vTexCoord v_texCoord.xy
|
||||
#define SourceSize vec4(rubyTextureSize, 1.0 / rubyTextureSize) //either rubyTextureSize or rubyInputSize
|
||||
#define OutSize vec4(rubyOutputSize, 1.0 / rubyOutputSize)
|
||||
|
||||
void main()
|
||||
{
|
||||
gl_Position = a_position;
|
||||
v_texCoord = vec2(a_position.x + 1.0, 1.0 - a_position.y) / 2.0 * rubyInputSize / rubyTextureSize;
|
||||
}
|
||||
|
||||
#elif defined(FRAGMENT)
|
||||
|
||||
#ifdef GL_ES
|
||||
#ifdef GL_FRAGMENT_PRECISION_HIGH
|
||||
precision highp float;
|
||||
#else
|
||||
precision mediump float;
|
||||
#endif
|
||||
#define COMPAT_PRECISION mediump
|
||||
#else
|
||||
#define COMPAT_PRECISION
|
||||
#endif
|
||||
|
||||
#if __VERSION__ >= 130
|
||||
#define COMPAT_VARYING in
|
||||
#define COMPAT_TEXTURE texture
|
||||
out COMPAT_PRECISION vec4 FragColor;
|
||||
#else
|
||||
#define COMPAT_VARYING varying
|
||||
#define FragColor gl_FragColor
|
||||
#define COMPAT_TEXTURE texture2D
|
||||
#endif
|
||||
|
||||
uniform COMPAT_PRECISION vec2 rubyOutputSize;
|
||||
uniform COMPAT_PRECISION vec2 rubyTextureSize;
|
||||
uniform COMPAT_PRECISION vec2 rubyInputSize;
|
||||
uniform sampler2D rubyTexture;
|
||||
COMPAT_VARYING vec2 v_texCoord;
|
||||
|
||||
// compatibility #defines
|
||||
#define Source rubyTexture
|
||||
#define vTexCoord v_texCoord.xy
|
||||
|
||||
#define SourceSize vec4(rubyTextureSize, 1.0 / rubyTextureSize) //either rubyTextureSize or rubyInputSize
|
||||
#define OutSize vec4(rubyOutputSize, 1.0 / rubyOutputSize)
|
||||
|
||||
#ifdef PARAMETER_UNIFORM
|
||||
uniform COMPAT_PRECISION float CRT_GAMMA;
|
||||
uniform COMPAT_PRECISION float SCANLINE_THINNESS;
|
||||
uniform COMPAT_PRECISION float SCAN_BLUR;
|
||||
uniform COMPAT_PRECISION float MASK_INTENSITY;
|
||||
uniform COMPAT_PRECISION float CURVATURE;
|
||||
uniform COMPAT_PRECISION float CORNER;
|
||||
uniform COMPAT_PRECISION float MASK;
|
||||
uniform COMPAT_PRECISION float TRINITRON_CURVE;
|
||||
#else
|
||||
#define CRT_GAMMA 2.4
|
||||
#define SCANLINE_THINNESS 0.5
|
||||
#define SCAN_BLUR 2.5
|
||||
#define MASK_INTENSITY 0.54
|
||||
#define CURVATURE 0.02
|
||||
#define CORNER 3.0
|
||||
#define MASK 1.0
|
||||
#define TRINITRON_CURVE 0.0
|
||||
#endif
|
||||
|
||||
//_____________________________/\_______________________________
|
||||
//==============================================================
|
||||
//
|
||||
// GAMMA FUNCTIONS
|
||||
//
|
||||
//--------------------------------------------------------------
|
||||
//--------------------------------------------------------------
|
||||
// Since shadertoy doesn't have sRGB textures
|
||||
// And we need linear input into shader
|
||||
// Don't do this in your code
|
||||
float FromSrgb1(float c){
|
||||
return (c<=0.04045)?c*(1.0/12.92):
|
||||
pow(c*(1.0/1.055)+(0.055/1.055),CRT_GAMMA);}
|
||||
//--------------------------------------------------------------
|
||||
vec3 FromSrgb(vec3 c){return vec3(
|
||||
FromSrgb1(c.r),FromSrgb1(c.g),FromSrgb1(c.b));}
|
||||
|
||||
// Convert from linear to sRGB
|
||||
// Since shader toy output is not linear
|
||||
float ToSrgb1(float c){
|
||||
return(c<0.0031308?c*12.92:1.055*pow(c,0.41666)-0.055);}
|
||||
//--------------------------------------------------------------
|
||||
vec3 ToSrgb(vec3 c){return vec3(
|
||||
ToSrgb1(c.r),ToSrgb1(c.g),ToSrgb1(c.b));}
|
||||
//--------------------------------------------------------------
|
||||
|
||||
//_____________________________/\_______________________________
|
||||
//==============================================================
|
||||
//
|
||||
// DEFINES
|
||||
//
|
||||
//--------------------------------------------------------------
|
||||
// CRTS_CPU - CPU code
|
||||
// CRTS_GPU - GPU code
|
||||
//--------------------------------------------------------------
|
||||
// CRTS_GLSL - GLSL
|
||||
// CRTS_HLSL - HLSL (not tested yet)
|
||||
//--------------------------------------------------------------
|
||||
// CRTS_DEBUG - Define to see on/off split screen
|
||||
//--------------------------------------------------------------
|
||||
// CRTS_WARP - Apply screen warp
|
||||
//--------------------------------------------------------------
|
||||
// CRTS_2_TAP - Faster very pixely 2-tap filter (off is 8)
|
||||
//--------------------------------------------------------------
|
||||
// CRTS_MASK_GRILLE - Aperture grille (aka Trinitron)
|
||||
// CRTS_MASK_GRILLE_LITE - Brighter (subtractive channels)
|
||||
// CRTS_MASK_NONE - No mask
|
||||
// CRTS_MASK_SHADOW - Horizontally stretched shadow mask
|
||||
//--------------------------------------------------------------
|
||||
// CRTS_TONE - Normalize mid-level and process color
|
||||
// CRTS_CONTRAST - Process color - enable contrast control
|
||||
// CRTS_SATURATION - Process color - enable saturation control
|
||||
//--------------------------------------------------------------
|
||||
#define CRTS_STATIC
|
||||
#define CrtsPow
|
||||
#define CRTS_RESTRICT
|
||||
//==============================================================
|
||||
////////////////////////////////////////////////////////////////
|
||||
////////////////////////////////////////////////////////////////
|
||||
////////////////////////////////////////////////////////////////
|
||||
|
||||
//==============================================================
|
||||
// SETUP FOR CRTS
|
||||
//--------------------------------------------------------------
|
||||
//==============================================================
|
||||
//#define CRTS_DEBUG 1
|
||||
#define CRTS_GPU 1
|
||||
#define CRTS_GLSL 1
|
||||
//--------------------------------------------------------------
|
||||
//#define CRTS_2_TAP 1
|
||||
//--------------------------------------------------------------
|
||||
#define CRTS_TONE 1
|
||||
#define CRTS_CONTRAST 0
|
||||
#define CRTS_SATURATION 0
|
||||
//--------------------------------------------------------------
|
||||
#define CRTS_WARP 1
|
||||
//--------------------------------------------------------------
|
||||
// Try different masks -> moved to runtime parameters
|
||||
//#define CRTS_MASK_GRILLE 1
|
||||
//#define CRTS_MASK_GRILLE_LITE 1
|
||||
//#define CRTS_MASK_NONE 1
|
||||
//#define CRTS_MASK_SHADOW 1
|
||||
//--------------------------------------------------------------
|
||||
// Scanline thinness
|
||||
// 0.50 = fused scanlines
|
||||
// 0.70 = recommended default
|
||||
// 1.00 = thinner scanlines (too thin)
|
||||
#define INPUT_THIN 0.5 + (0.5 * SCANLINE_THINNESS)
|
||||
//--------------------------------------------------------------
|
||||
// Horizonal scan blur
|
||||
// -3.0 = pixely
|
||||
// -2.5 = default
|
||||
// -2.0 = smooth
|
||||
// -1.0 = too blurry
|
||||
#define INPUT_BLUR -1.0 * SCAN_BLUR
|
||||
//--------------------------------------------------------------
|
||||
// Shadow mask effect, ranges from,
|
||||
// 0.25 = large amount of mask (not recommended, too dark)
|
||||
// 0.50 = recommended default
|
||||
// 1.00 = no shadow mask
|
||||
#define INPUT_MASK 1.0 - MASK_INTENSITY
|
||||
//--------------------------------------------------------------
|
||||
#define INPUT_X rubyInputSize.x
|
||||
#define INPUT_Y rubyInputSize.y
|
||||
//--------------------------------------------------------------
|
||||
// Setup the function which returns input image color
|
||||
vec3 CrtsFetch(vec2 uv){
|
||||
// For shadertoy, scale to get native texels in the image
|
||||
uv*=vec2(INPUT_X,INPUT_Y)/rubyTextureSize.xy;
|
||||
// Move towards intersting parts
|
||||
// uv+=vec2(0.5,0.5);
|
||||
// Non-shadertoy case would not have the color conversion
|
||||
return FromSrgb(COMPAT_TEXTURE(rubyTexture,uv.xy,-16.0).rgb);}
|
||||
#endif
|
||||
|
||||
////////////////////////////////////////////////////////////////
|
||||
////////////////////////////////////////////////////////////////
|
||||
////////////////////////////////////////////////////////////////
|
||||
//_____________________________/\_______________________________
|
||||
//==============================================================
|
||||
//
|
||||
// GPU CODE
|
||||
//
|
||||
//==============================================================
|
||||
#ifdef CRTS_GPU
|
||||
//_____________________________/\_______________________________
|
||||
//==============================================================
|
||||
// PORTABILITY
|
||||
//==============================================================
|
||||
#ifdef CRTS_GLSL
|
||||
#define CrtsF1 float
|
||||
#define CrtsF2 vec2
|
||||
#define CrtsF3 vec3
|
||||
#define CrtsF4 vec4
|
||||
#define CrtsFractF1 fract
|
||||
#define CrtsRcpF1(x) (1.0/(x))
|
||||
#define CrtsSatF1(x) clamp((x),0.0,1.0)
|
||||
//--------------------------------------------------------------
|
||||
CrtsF1 CrtsMax3F1(CrtsF1 a,CrtsF1 b,CrtsF1 c){
|
||||
return max(a,max(b,c));}
|
||||
#endif
|
||||
//==============================================================
|
||||
#ifdef CRTS_HLSL
|
||||
#define CrtsF1 float
|
||||
#define CrtsF2 float2
|
||||
#define CrtsF3 float3
|
||||
#define CrtsF4 float4
|
||||
#define CrtsFractF1 frac
|
||||
#define CrtsRcpF1(x) (1.0/(x))
|
||||
#define CrtsSatF1(x) saturate(x)
|
||||
//--------------------------------------------------------------
|
||||
CrtsF1 CrtsMax3F1(CrtsF1 a,CrtsF1 b,CrtsF1 c){
|
||||
return max(a,max(b,c));}
|
||||
#endif
|
||||
//_____________________________/\_______________________________
|
||||
//==============================================================
|
||||
// TONAL CONTROL CONSTANT GENERATION
|
||||
//--------------------------------------------------------------
|
||||
// This is in here for rapid prototyping
|
||||
// Please use the CPU code and pass in as constants
|
||||
//==============================================================
|
||||
CrtsF4 CrtsTone(
|
||||
CrtsF1 contrast,
|
||||
CrtsF1 saturation,
|
||||
CrtsF1 thin,
|
||||
CrtsF1 mask){
|
||||
//--------------------------------------------------------------
|
||||
if(MASK == 0.0) mask=1.0;
|
||||
//--------------------------------------------------------------
|
||||
if(MASK == 1.0){
|
||||
// Normal R mask is {1.0,mask,mask}
|
||||
// LITE R mask is {mask,1.0,1.0}
|
||||
mask=0.5+mask*0.5;
|
||||
}
|
||||
//--------------------------------------------------------------
|
||||
CrtsF4 ret;
|
||||
CrtsF1 midOut=0.18/((1.5-thin)*(0.5*mask+0.5));
|
||||
CrtsF1 pMidIn=pow(0.18,contrast);
|
||||
ret.x=contrast;
|
||||
ret.y=((-pMidIn)+midOut)/((1.0-pMidIn)*midOut);
|
||||
ret.z=((-pMidIn)*midOut+pMidIn)/(midOut*(-pMidIn)+midOut);
|
||||
ret.w=contrast+saturation;
|
||||
return ret;}
|
||||
//_____________________________/\_______________________________
|
||||
//==============================================================
|
||||
// MASK
|
||||
//--------------------------------------------------------------
|
||||
// Letting LCD/OLED pixel elements function like CRT phosphors
|
||||
// So "phosphor" resolution scales with display resolution
|
||||
//--------------------------------------------------------------
|
||||
// Not applying any warp to the mask (want high frequency)
|
||||
// Real aperture grille has a mask which gets wider on ends
|
||||
// Not attempting to be "real" but instead look the best
|
||||
//--------------------------------------------------------------
|
||||
// Shadow mask is stretched horizontally
|
||||
// RRGGBB
|
||||
// GBBRRG
|
||||
// RRGGBB
|
||||
// This tends to look better on LCDs than vertical
|
||||
// Also 2 pixel width is required to get triad centered
|
||||
//--------------------------------------------------------------
|
||||
// The LITE version of the Aperture Grille is brighter
|
||||
// Uses {dark,1.0,1.0} for R channel
|
||||
// Non LITE version uses {1.0,dark,dark}
|
||||
//--------------------------------------------------------------
|
||||
// 'pos' - This is 'fragCoord.xy'
|
||||
// Pixel {0,0} should be {0.5,0.5}
|
||||
// Pixel {1,1} should be {1.5,1.5}
|
||||
//--------------------------------------------------------------
|
||||
// 'dark' - Exposure of of masked channel
|
||||
// 0.0=fully off, 1.0=no effect
|
||||
//==============================================================
|
||||
CrtsF3 CrtsMask(CrtsF2 pos,CrtsF1 dark){
|
||||
if(MASK == 2.0){
|
||||
CrtsF3 m=CrtsF3(dark,dark,dark);
|
||||
CrtsF1 x=CrtsFractF1(pos.x*(1.0/3.0));
|
||||
if(x<(1.0/3.0))m.r=1.0;
|
||||
else if(x<(2.0/3.0))m.g=1.0;
|
||||
else m.b=1.0;
|
||||
return m;
|
||||
}
|
||||
//--------------------------------------------------------------
|
||||
if(MASK == 1.0){
|
||||
CrtsF3 m=CrtsF3(1.0,1.0,1.0);
|
||||
CrtsF1 x=CrtsFractF1(pos.x*(1.0/3.0));
|
||||
if(x<(1.0/3.0))m.r=dark;
|
||||
else if(x<(2.0/3.0))m.g=dark;
|
||||
else m.b=dark;
|
||||
return m;
|
||||
}
|
||||
//--------------------------------------------------------------
|
||||
if(MASK == 0.0){
|
||||
return CrtsF3(1.0,1.0,1.0);
|
||||
}
|
||||
//--------------------------------------------------------------
|
||||
if(MASK == 3.0){
|
||||
pos.x+=pos.y*2.9999;
|
||||
CrtsF3 m=CrtsF3(dark,dark,dark);
|
||||
CrtsF1 x=CrtsFractF1(pos.x*(1.0/6.0));
|
||||
if(x<(1.0/3.0))m.r=1.0;
|
||||
else if(x<(2.0/3.0))m.g=1.0;
|
||||
else m.b=1.0;
|
||||
return m;
|
||||
}
|
||||
}
|
||||
//_____________________________/\_______________________________
|
||||
//==============================================================
|
||||
// FILTER ENTRY
|
||||
//--------------------------------------------------------------
|
||||
// Input must be linear
|
||||
// Output color is linear
|
||||
//--------------------------------------------------------------
|
||||
// Must have fetch function setup: CrtsF3 CrtsFetch(CrtsF2 uv)
|
||||
// - The 'uv' range is {0.0 to 1.0} for input texture
|
||||
// - Output of this must be linear color
|
||||
//--------------------------------------------------------------
|
||||
// SCANLINE MATH & AUTO-EXPOSURE NOTES
|
||||
// ===================================
|
||||
// Each output line has contribution from at most 2 scanlines
|
||||
// Scanlines are shaped by a windowed cosine function
|
||||
// This shape blends together well with only 2 lines of overlap
|
||||
//--------------------------------------------------------------
|
||||
// Base scanline intensity is as follows
|
||||
// which leaves output intensity range from {0 to 1.0}
|
||||
// --------
|
||||
// thin := range {thick 0.5 to thin 1.0}
|
||||
// off := range {0.0 to <1.0},
|
||||
// sub-pixel offset between two scanlines
|
||||
// --------
|
||||
// a0=cos(min(0.5, off *thin)*2pi)*0.5+0.5;
|
||||
// a1=cos(min(0.5,(1.0-off)*thin)*2pi)*0.5+0.5;
|
||||
//--------------------------------------------------------------
|
||||
// This leads to a image darkening factor of roughly:
|
||||
// {(1.5-thin)/1.0}
|
||||
// This is further reduced by the mask:
|
||||
// {1.0/2.0+mask*1.0/2.0}
|
||||
// Reciprocal of combined effect is used for auto-exposure
|
||||
// to scale up the mid-level in the tonemapper
|
||||
//==============================================================
|
||||
CrtsF3 CrtsFilter(
|
||||
//--------------------------------------------------------------
|
||||
// SV_POSITION, fragCoord.xy
|
||||
CrtsF2 ipos,
|
||||
//--------------------------------------------------------------
|
||||
// rubyInputSize / rubyOutputSize (in pixels)
|
||||
CrtsF2 inputSizeDivOutputSize,
|
||||
//--------------------------------------------------------------
|
||||
// 0.5 * rubyInputSize (in pixels)
|
||||
CrtsF2 halfInputSize,
|
||||
//--------------------------------------------------------------
|
||||
// 1.0 / rubyInputSize (in pixels)
|
||||
CrtsF2 rcpInputSize,
|
||||
//--------------------------------------------------------------
|
||||
// 1.0 / rubyOutputSize (in pixels)
|
||||
CrtsF2 rcpOutputSize,
|
||||
//--------------------------------------------------------------
|
||||
// 2.0 / rubyOutputSize (in pixels)
|
||||
CrtsF2 twoDivOutputSize,
|
||||
//--------------------------------------------------------------
|
||||
// rubyInputSize.y
|
||||
CrtsF1 inputHeight,
|
||||
//--------------------------------------------------------------
|
||||
// Warp scanlines but not phosphor mask
|
||||
// 0.0 = no warp
|
||||
// 1.0/64.0 = light warping
|
||||
// 1.0/32.0 = more warping
|
||||
// Want x and y warping to be different (based on aspect)
|
||||
CrtsF2 warp,
|
||||
//--------------------------------------------------------------
|
||||
// Scanline thinness
|
||||
// 0.50 = fused scanlines
|
||||
// 0.70 = recommended default
|
||||
// 1.00 = thinner scanlines (too thin)
|
||||
// Shared with CrtsTone() function
|
||||
CrtsF1 thin,
|
||||
//--------------------------------------------------------------
|
||||
// Horizonal scan blur
|
||||
// -3.0 = pixely
|
||||
// -2.5 = default
|
||||
// -2.0 = smooth
|
||||
// -1.0 = too blurry
|
||||
CrtsF1 blur,
|
||||
//--------------------------------------------------------------
|
||||
// Shadow mask effect, ranges from,
|
||||
// 0.25 = large amount of mask (not recommended, too dark)
|
||||
// 0.50 = recommended default
|
||||
// 1.00 = no shadow mask
|
||||
// Shared with CrtsTone() function
|
||||
CrtsF1 mask,
|
||||
//--------------------------------------------------------------
|
||||
// Tonal curve parameters generated by CrtsTone()
|
||||
CrtsF4 tone
|
||||
//--------------------------------------------------------------
|
||||
){
|
||||
//--------------------------------------------------------------
|
||||
#ifdef CRTS_DEBUG
|
||||
CrtsF2 uv=ipos*rcpOutputSize;
|
||||
// Show second half processed, and first half un-processed
|
||||
if(uv.x<0.5){
|
||||
// Force nearest to get squares
|
||||
uv*=1.0/rcpInputSize;
|
||||
uv=floor(uv)+CrtsF2(0.5,0.5);
|
||||
uv*=rcpInputSize;
|
||||
CrtsF3 color=CrtsFetch(uv);
|
||||
return color;}
|
||||
#endif
|
||||
//--------------------------------------------------------------
|
||||
// Optional apply warp
|
||||
CrtsF2 pos;
|
||||
#ifdef CRTS_WARP
|
||||
// Convert to {-1 to 1} range
|
||||
pos=ipos*twoDivOutputSize-CrtsF2(1.0,1.0);
|
||||
// Distort pushes image outside {-1 to 1} range
|
||||
pos*=CrtsF2(
|
||||
1.0+(pos.y*pos.y)*warp.x,
|
||||
1.0+(pos.x*pos.x)*warp.y);
|
||||
// TODO: Vignette needs optimization
|
||||
CrtsF1 vin=(1.0-(
|
||||
(1.0-CrtsSatF1(pos.x*pos.x))*(1.0-CrtsSatF1(pos.y*pos.y)))) * (0.998 + (0.001 * CORNER));
|
||||
vin=CrtsSatF1((-vin)*inputHeight+inputHeight);
|
||||
// Leave in {0 to rubyInputSize}
|
||||
pos=pos*halfInputSize+halfInputSize;
|
||||
#else
|
||||
pos=ipos*inputSizeDivOutputSize;
|
||||
#endif
|
||||
//--------------------------------------------------------------
|
||||
// Snap to center of first scanline
|
||||
CrtsF1 y0=floor(pos.y-0.5)+0.5;
|
||||
#ifdef CRTS_2_TAP
|
||||
// Using Inigo's "Improved texture Interpolation"
|
||||
// http://iquilezles.org/www/articles/texture/texture.htm
|
||||
pos.x+=0.5;
|
||||
CrtsF1 xi=floor(pos.x);
|
||||
CrtsF1 xf=pos.x-xi;
|
||||
xf=xf*xf*xf*(xf*(xf*6.0-15.0)+10.0);
|
||||
CrtsF1 x0=xi+xf-0.5;
|
||||
CrtsF2 p=CrtsF2(x0*rcpInputSize.x,y0*rcpInputSize.y);
|
||||
// Coordinate adjusted bilinear fetch from 2 nearest scanlines
|
||||
CrtsF3 colA=CrtsFetch(p);
|
||||
p.y+=rcpInputSize.y;
|
||||
CrtsF3 colB=CrtsFetch(p);
|
||||
#else
|
||||
// Snap to center of one of four pixels
|
||||
CrtsF1 x0=floor(pos.x-1.5)+0.5;
|
||||
// Inital UV position
|
||||
CrtsF2 p=CrtsF2(x0*rcpInputSize.x,y0*rcpInputSize.y);
|
||||
// Fetch 4 nearest texels from 2 nearest scanlines
|
||||
CrtsF3 colA0=CrtsFetch(p);
|
||||
p.x+=rcpInputSize.x;
|
||||
CrtsF3 colA1=CrtsFetch(p);
|
||||
p.x+=rcpInputSize.x;
|
||||
CrtsF3 colA2=CrtsFetch(p);
|
||||
p.x+=rcpInputSize.x;
|
||||
CrtsF3 colA3=CrtsFetch(p);
|
||||
p.y+=rcpInputSize.y;
|
||||
CrtsF3 colB3=CrtsFetch(p);
|
||||
p.x-=rcpInputSize.x;
|
||||
CrtsF3 colB2=CrtsFetch(p);
|
||||
p.x-=rcpInputSize.x;
|
||||
CrtsF3 colB1=CrtsFetch(p);
|
||||
p.x-=rcpInputSize.x;
|
||||
CrtsF3 colB0=CrtsFetch(p);
|
||||
#endif
|
||||
//--------------------------------------------------------------
|
||||
// Vertical filter
|
||||
// Scanline intensity is using sine wave
|
||||
// Easy filter window and integral used later in exposure
|
||||
CrtsF1 off=pos.y-y0;
|
||||
CrtsF1 pi2=6.28318530717958;
|
||||
CrtsF1 hlf=0.5;
|
||||
CrtsF1 scanA=cos(min(0.5, off *thin )*pi2)*hlf+hlf;
|
||||
CrtsF1 scanB=cos(min(0.5,(-off)*thin+thin)*pi2)*hlf+hlf;
|
||||
//--------------------------------------------------------------
|
||||
#ifdef CRTS_2_TAP
|
||||
#ifdef CRTS_WARP
|
||||
// Get rid of wrong pixels on edge
|
||||
scanA*=vin;
|
||||
scanB*=vin;
|
||||
#endif
|
||||
// Apply vertical filter
|
||||
CrtsF3 color=(colA*scanA)+(colB*scanB);
|
||||
#else
|
||||
// Horizontal kernel is simple gaussian filter
|
||||
CrtsF1 off0=pos.x-x0;
|
||||
CrtsF1 off1=off0-1.0;
|
||||
CrtsF1 off2=off0-2.0;
|
||||
CrtsF1 off3=off0-3.0;
|
||||
CrtsF1 pix0=exp2(blur*off0*off0);
|
||||
CrtsF1 pix1=exp2(blur*off1*off1);
|
||||
CrtsF1 pix2=exp2(blur*off2*off2);
|
||||
CrtsF1 pix3=exp2(blur*off3*off3);
|
||||
CrtsF1 pixT=CrtsRcpF1(pix0+pix1+pix2+pix3);
|
||||
#ifdef CRTS_WARP
|
||||
// Get rid of wrong pixels on edge
|
||||
pixT*=vin;
|
||||
#endif
|
||||
scanA*=pixT;
|
||||
scanB*=pixT;
|
||||
// Apply horizontal and vertical filters
|
||||
CrtsF3 color=
|
||||
(colA0*pix0+colA1*pix1+colA2*pix2+colA3*pix3)*scanA +
|
||||
(colB0*pix0+colB1*pix1+colB2*pix2+colB3*pix3)*scanB;
|
||||
#endif
|
||||
//--------------------------------------------------------------
|
||||
// Apply phosphor mask
|
||||
color*=CrtsMask(ipos,mask);
|
||||
//--------------------------------------------------------------
|
||||
// Optional color processing
|
||||
#ifdef CRTS_TONE
|
||||
// Tonal control, start by protecting from /0
|
||||
CrtsF1 peak=max(1.0/(256.0*65536.0),
|
||||
CrtsMax3F1(color.r,color.g,color.b));
|
||||
// Compute the ratios of {R,G,B}
|
||||
CrtsF3 ratio=color*CrtsRcpF1(peak);
|
||||
// Apply tonal curve to peak value
|
||||
#ifdef CRTS_CONTRAST
|
||||
peak=pow(peak,tone.x);
|
||||
#endif
|
||||
peak=peak*CrtsRcpF1(peak*tone.y+tone.z);
|
||||
// Apply saturation
|
||||
#ifdef CRTS_SATURATION
|
||||
ratio=pow(ratio,CrtsF3(tone.w,tone.w,tone.w));
|
||||
#endif
|
||||
// Reconstruct color
|
||||
return ratio*peak;
|
||||
#else
|
||||
return color;
|
||||
#endif
|
||||
//--------------------------------------------------------------
|
||||
}
|
||||
|
||||
|
||||
void main()
|
||||
{
|
||||
vec2 warp_factor;
|
||||
warp_factor.x = CURVATURE;
|
||||
warp_factor.y = (3.0 / 4.0) * warp_factor.x; // assume 4:3 aspect
|
||||
warp_factor.x *= (1.0 - TRINITRON_CURVE);
|
||||
FragColor.rgb = CrtsFilter(vTexCoord.xy * rubyOutputSize.xy*(rubyTextureSize.xy / rubyInputSize.xy),
|
||||
rubyInputSize.xy / rubyOutputSize.xy,
|
||||
rubyInputSize.xy * vec2(0.5,0.5),
|
||||
1.0/rubyInputSize.xy,
|
||||
1.0/rubyOutputSize.xy,
|
||||
2.0/rubyOutputSize.xy,
|
||||
rubyInputSize.y,
|
||||
warp_factor,
|
||||
INPUT_THIN,
|
||||
INPUT_BLUR,
|
||||
INPUT_MASK,
|
||||
CrtsTone(1.0,0.0,INPUT_THIN,INPUT_MASK));
|
||||
|
||||
// Shadertoy outputs non-linear color
|
||||
FragColor.rgb=ToSrgb(FragColor.rgb);
|
||||
}
|
||||
#endif
|
738
contrib/glshaders/crt-lottes-fast.subtle+gain.glsl
Normal file
738
contrib/glshaders/crt-lottes-fast.subtle+gain.glsl
Normal file
@@ -0,0 +1,738 @@
|
||||
#version 120
|
||||
|
||||
//_____________________________/\_______________________________
|
||||
//==============================================================
|
||||
//
|
||||
//
|
||||
// [CRTS] PUBLIC DOMAIN CRT-STYLED SCALAR - 20180120b
|
||||
//
|
||||
// by Timothy Lottes
|
||||
// https://www.shadertoy.com/view/MtSfRK
|
||||
// adapted for RetroArch by hunterk
|
||||
//
|
||||
//
|
||||
//==============================================================
|
||||
////////////////////////////////////////////////////////////////
|
||||
////////////////////////////////////////////////////////////////
|
||||
////////////////////////////////////////////////////////////////
|
||||
//_____________________________/\_______________________________
|
||||
//==============================================================
|
||||
//
|
||||
// WHAT'S NEW
|
||||
//
|
||||
//--------------------------------------------------------------
|
||||
// Evolution of prior shadertoy example
|
||||
//--------------------------------------------------------------
|
||||
// This one is semi-optimized
|
||||
// - Less texture fetches
|
||||
// - Didn't get to instruction level optimization
|
||||
// - Could likely use texture fetch to generate phosphor mask
|
||||
//--------------------------------------------------------------
|
||||
// Added options to disable unused features
|
||||
//--------------------------------------------------------------
|
||||
// Added in exposure matching
|
||||
// - Given scan-line effect and mask always darkens image
|
||||
// - Uses generalized tonemapper to boost mid-level
|
||||
// - Note this can compress highlights
|
||||
// - And won't get back peak brightness
|
||||
// - But best option if one doesn't want as much darkening
|
||||
//--------------------------------------------------------------
|
||||
// Includes option saturation and contrast controls
|
||||
//--------------------------------------------------------------
|
||||
// Added in subtractive aperture grille
|
||||
// - This is a bit brighter than prior
|
||||
//--------------------------------------------------------------
|
||||
// Make sure input to this filter is already low-resolution
|
||||
// - This is not designed to work on titles doing the following
|
||||
// - Rendering to hi-res with nearest sampling
|
||||
//--------------------------------------------------------------
|
||||
// Added a fast and more pixely option for 2 tap/pixel
|
||||
//--------------------------------------------------------------
|
||||
// Improved the vignette when WARP is enabled
|
||||
//--------------------------------------------------------------
|
||||
// Didn't test HLSL or CPU options
|
||||
// - Will incorportate patches if they are broken
|
||||
// - But out of time to try them myself
|
||||
//==============================================================
|
||||
////////////////////////////////////////////////////////////////
|
||||
////////////////////////////////////////////////////////////////
|
||||
////////////////////////////////////////////////////////////////
|
||||
//_____________________________/\_______________________________
|
||||
//==============================================================
|
||||
//
|
||||
// LICENSE = UNLICENSE (aka PUBLIC DOMAIN)
|
||||
//
|
||||
//--------------------------------------------------------------
|
||||
// This is free and unencumbered software released into the
|
||||
// public domain.
|
||||
//--------------------------------------------------------------
|
||||
// Anyone is free to copy, modify, publish, use, compile, sell,
|
||||
// or distribute this software, either in source code form or as
|
||||
// a compiled binary, for any purpose, commercial or
|
||||
// non-commercial, and by any means.
|
||||
//--------------------------------------------------------------
|
||||
// In jurisdictions that recognize copyright laws, the author or
|
||||
// authors of this software dedicate any and all copyright
|
||||
// interest in the software to the public domain. We make this
|
||||
// dedication for the benefit of the public at large and to the
|
||||
// detriment of our heirs and successors. We intend this
|
||||
// dedication to be an overt act of relinquishment in perpetuity
|
||||
// of all present and future rights to this software under
|
||||
// copyright law.
|
||||
//--------------------------------------------------------------
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
|
||||
// KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
|
||||
// WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
|
||||
// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS BE
|
||||
// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
|
||||
// AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT
|
||||
// OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
// DEALINGS IN THE SOFTWARE.
|
||||
//--------------------------------------------------------------
|
||||
// For more information, please refer to
|
||||
// <http://unlicense.org/>
|
||||
//==============================================================
|
||||
////////////////////////////////////////////////////////////////
|
||||
////////////////////////////////////////////////////////////////
|
||||
////////////////////////////////////////////////////////////////
|
||||
|
||||
#pragma parameter MASK "Mask Type" 1.0 0.0 3.0 1.0
|
||||
#pragma parameter MASK_INTENSITY "Mask Intensity" 0.5 0.0 1.0 0.05
|
||||
#pragma parameter SCANLINE_THINNESS "Scanline Intensity" 0.5 0.0 1.0 0.1
|
||||
#pragma parameter SCAN_BLUR "Sharpness" 2.5 1.0 3.0 0.1
|
||||
#pragma parameter CURVATURE "Curvature" 0.02 0.0 0.25 0.01
|
||||
#pragma parameter TRINITRON_CURVE "Trinitron-style Curve" 0.0 0.0 1.0 1.0
|
||||
#pragma parameter CORNER "Corner Round" 3.0 0.0 11.0 1.0
|
||||
#pragma parameter CRT_GAMMA "CRT Gamma" 2.4 0.0 51.0 0.1
|
||||
|
||||
#if defined(VERTEX)
|
||||
|
||||
#if __VERSION__ >= 130
|
||||
#define COMPAT_VARYING out
|
||||
#define COMPAT_ATTRIBUTE in
|
||||
#define COMPAT_TEXTURE texture
|
||||
#else
|
||||
#define COMPAT_VARYING varying
|
||||
#define COMPAT_ATTRIBUTE attribute
|
||||
#define COMPAT_TEXTURE texture2D
|
||||
#endif
|
||||
|
||||
#ifdef GL_ES
|
||||
#define COMPAT_PRECISION mediump
|
||||
#else
|
||||
#define COMPAT_PRECISION
|
||||
#endif
|
||||
|
||||
COMPAT_ATTRIBUTE vec4 a_position;
|
||||
COMPAT_ATTRIBUTE vec4 COLOR;
|
||||
COMPAT_ATTRIBUTE vec4 TexCoord;
|
||||
COMPAT_VARYING vec4 COL0;
|
||||
COMPAT_VARYING vec2 v_texCoord;
|
||||
|
||||
uniform COMPAT_PRECISION vec2 rubyOutputSize;
|
||||
uniform COMPAT_PRECISION vec2 rubyTextureSize;
|
||||
uniform COMPAT_PRECISION vec2 rubyInputSize;
|
||||
|
||||
// compatibility #defines
|
||||
#define vTexCoord v_texCoord.xy
|
||||
#define SourceSize vec4(rubyTextureSize, 1.0 / rubyTextureSize) //either rubyTextureSize or rubyInputSize
|
||||
#define OutSize vec4(rubyOutputSize, 1.0 / rubyOutputSize)
|
||||
|
||||
void main()
|
||||
{
|
||||
gl_Position = a_position;
|
||||
v_texCoord = vec2(a_position.x + 1.0, 1.0 - a_position.y) / 2.0 * rubyInputSize / rubyTextureSize;
|
||||
}
|
||||
|
||||
#elif defined(FRAGMENT)
|
||||
|
||||
#ifdef GL_ES
|
||||
#ifdef GL_FRAGMENT_PRECISION_HIGH
|
||||
precision highp float;
|
||||
#else
|
||||
precision mediump float;
|
||||
#endif
|
||||
#define COMPAT_PRECISION mediump
|
||||
#else
|
||||
#define COMPAT_PRECISION
|
||||
#endif
|
||||
|
||||
#if __VERSION__ >= 130
|
||||
#define COMPAT_VARYING in
|
||||
#define COMPAT_TEXTURE texture
|
||||
out COMPAT_PRECISION vec4 FragColor;
|
||||
#else
|
||||
#define COMPAT_VARYING varying
|
||||
#define FragColor gl_FragColor
|
||||
#define COMPAT_TEXTURE texture2D
|
||||
#endif
|
||||
|
||||
uniform COMPAT_PRECISION vec2 rubyOutputSize;
|
||||
uniform COMPAT_PRECISION vec2 rubyTextureSize;
|
||||
uniform COMPAT_PRECISION vec2 rubyInputSize;
|
||||
uniform sampler2D rubyTexture;
|
||||
COMPAT_VARYING vec2 v_texCoord;
|
||||
|
||||
// compatibility #defines
|
||||
#define Source rubyTexture
|
||||
#define vTexCoord v_texCoord.xy
|
||||
|
||||
#define SourceSize vec4(rubyTextureSize, 1.0 / rubyTextureSize) //either rubyTextureSize or rubyInputSize
|
||||
#define OutSize vec4(rubyOutputSize, 1.0 / rubyOutputSize)
|
||||
|
||||
#ifdef PARAMETER_UNIFORM
|
||||
uniform COMPAT_PRECISION float CRT_GAMMA;
|
||||
uniform COMPAT_PRECISION float SCANLINE_THINNESS;
|
||||
uniform COMPAT_PRECISION float SCAN_BLUR;
|
||||
uniform COMPAT_PRECISION float MASK_INTENSITY;
|
||||
uniform COMPAT_PRECISION float CURVATURE;
|
||||
uniform COMPAT_PRECISION float CORNER;
|
||||
uniform COMPAT_PRECISION float MASK;
|
||||
uniform COMPAT_PRECISION float TRINITRON_CURVE;
|
||||
#else
|
||||
#define CRT_GAMMA 2.4
|
||||
#define SCANLINE_THINNESS 0.00
|
||||
#define SCAN_BLUR 8.8
|
||||
#define MASK_INTENSITY 0.44
|
||||
#define CURVATURE 0.02
|
||||
#define CORNER 2.5
|
||||
#define MASK 3.0
|
||||
#define TRINITRON_CURVE 0.0
|
||||
#endif
|
||||
|
||||
//_____________________________/\_______________________________
|
||||
//==============================================================
|
||||
//
|
||||
// ADDITIONAL FUNCTIONS AND DEFS
|
||||
//
|
||||
//--------------------------------------------------------------
|
||||
//--------------------------------------------------------------
|
||||
|
||||
// Constants ---------------------------------------------------
|
||||
|
||||
#define LUM_WEIGHTS vec3(0.299, 0.587, 0.114)
|
||||
|
||||
// Params ------------------------------------------------------
|
||||
|
||||
//#define SHOW_DRY 0.3 // if defined unprocessed image is shown at u > SHOW_DRY
|
||||
#define SHOW_DRY_MODE 1 // 0: unprocessed, 1: shader without final gain
|
||||
|
||||
#define FINAL_GAIN_MULT 2.6
|
||||
#define FINAL_GAIN_POW 2.8
|
||||
#define FINAL_GAIN_MIX 0.6
|
||||
|
||||
// Functions ----------------------------------------------------
|
||||
|
||||
// Applied in main()
|
||||
vec3 finalGain(vec3 col)
|
||||
{
|
||||
float lum = dot(col, LUM_WEIGHTS);
|
||||
vec3 lum_mult = vec3(1.0) + pow(lum, FINAL_GAIN_POW) * FINAL_GAIN_MULT;
|
||||
vec3 col_mult = vec3(1.0) + pow(col, vec3(FINAL_GAIN_POW)) * FINAL_GAIN_MULT;
|
||||
return col * mix(lum_mult, col_mult, vec3(FINAL_GAIN_MIX));
|
||||
}
|
||||
|
||||
//_____________________________/\_______________________________
|
||||
//==============================================================
|
||||
//
|
||||
// GAMMA FUNCTIONS
|
||||
//
|
||||
//--------------------------------------------------------------
|
||||
//--------------------------------------------------------------
|
||||
// Since shadertoy doesn't have sRGB textures
|
||||
// And we need linear input into shader
|
||||
// Don't do this in your code
|
||||
float FromSrgb1(float c){
|
||||
return (c<=0.04045)?c*(1.0/12.92):
|
||||
pow(c*(1.0/1.055)+(0.055/1.055),CRT_GAMMA);}
|
||||
//--------------------------------------------------------------
|
||||
vec3 FromSrgb(vec3 c){return vec3(
|
||||
FromSrgb1(c.r),FromSrgb1(c.g),FromSrgb1(c.b));}
|
||||
|
||||
// Convert from linear to sRGB
|
||||
// Since shader toy output is not linear
|
||||
float ToSrgb1(float c){
|
||||
return(c<0.0031308?c*12.92:1.055*pow(c,0.41666)-0.055);}
|
||||
//--------------------------------------------------------------
|
||||
vec3 ToSrgb(vec3 c){return vec3(
|
||||
ToSrgb1(c.r),ToSrgb1(c.g),ToSrgb1(c.b));}
|
||||
//--------------------------------------------------------------
|
||||
|
||||
//_____________________________/\_______________________________
|
||||
//==============================================================
|
||||
//
|
||||
// DEFINES
|
||||
//
|
||||
//--------------------------------------------------------------
|
||||
// CRTS_CPU - CPU code
|
||||
// CRTS_GPU - GPU code
|
||||
//--------------------------------------------------------------
|
||||
// CRTS_GLSL - GLSL
|
||||
// CRTS_HLSL - HLSL (not tested yet)
|
||||
//--------------------------------------------------------------
|
||||
// CRTS_DEBUG - Define to see on/off split screen
|
||||
//--------------------------------------------------------------
|
||||
// CRTS_WARP - Apply screen warp
|
||||
//--------------------------------------------------------------
|
||||
// CRTS_2_TAP - Faster very pixely 2-tap filter (off is 8)
|
||||
//--------------------------------------------------------------
|
||||
// CRTS_MASK_GRILLE - Aperture grille (aka Trinitron)
|
||||
// CRTS_MASK_GRILLE_LITE - Brighter (subtractive channels)
|
||||
// CRTS_MASK_NONE - No mask
|
||||
// CRTS_MASK_SHADOW - Horizontally stretched shadow mask
|
||||
//--------------------------------------------------------------
|
||||
// CRTS_TONE - Normalize mid-level and process color
|
||||
// CRTS_CONTRAST - Process color - enable contrast control
|
||||
// CRTS_SATURATION - Process color - enable saturation control
|
||||
//--------------------------------------------------------------
|
||||
#define CRTS_STATIC
|
||||
#define CrtsPow
|
||||
#define CRTS_RESTRICT
|
||||
//==============================================================
|
||||
////////////////////////////////////////////////////////////////
|
||||
////////////////////////////////////////////////////////////////
|
||||
////////////////////////////////////////////////////////////////
|
||||
|
||||
//==============================================================
|
||||
// SETUP FOR CRTS
|
||||
//--------------------------------------------------------------
|
||||
//==============================================================
|
||||
//#define CRTS_DEBUG 1
|
||||
#define CRTS_GPU 1
|
||||
#define CRTS_GLSL 1
|
||||
//--------------------------------------------------------------
|
||||
//#define CRTS_2_TAP 1
|
||||
//--------------------------------------------------------------
|
||||
#define CRTS_TONE 1
|
||||
#define CRTS_CONTRAST 0
|
||||
#define CRTS_SATURATION 0
|
||||
//--------------------------------------------------------------
|
||||
#define CRTS_WARP 1
|
||||
//--------------------------------------------------------------
|
||||
// Try different masks -> moved to runtime parameters
|
||||
//#define CRTS_MASK_GRILLE 1
|
||||
//#define CRTS_MASK_GRILLE_LITE 1
|
||||
//#define CRTS_MASK_NONE 1
|
||||
//#define CRTS_MASK_SHADOW 1
|
||||
//--------------------------------------------------------------
|
||||
// Scanline thinness
|
||||
// 0.50 = fused scanlines
|
||||
// 0.70 = recommended default
|
||||
// 1.00 = thinner scanlines (too thin)
|
||||
#define INPUT_THIN 0.5 + (0.5 * SCANLINE_THINNESS)
|
||||
//--------------------------------------------------------------
|
||||
// Horizonal scan blur
|
||||
// -3.0 = pixely
|
||||
// -2.5 = default
|
||||
// -2.0 = smooth
|
||||
// -1.0 = too blurry
|
||||
#define INPUT_BLUR -1.0 * SCAN_BLUR
|
||||
//--------------------------------------------------------------
|
||||
// Shadow mask effect, ranges from,
|
||||
// 0.25 = large amount of mask (not recommended, too dark)
|
||||
// 0.50 = recommended default
|
||||
// 1.00 = no shadow mask
|
||||
#define INPUT_MASK 1.0 - MASK_INTENSITY
|
||||
//--------------------------------------------------------------
|
||||
#define INPUT_X rubyInputSize.x
|
||||
#define INPUT_Y rubyInputSize.y
|
||||
//--------------------------------------------------------------
|
||||
// Setup the function which returns input image color
|
||||
vec3 CrtsFetch(vec2 uv){
|
||||
// For shadertoy, scale to get native texels in the image
|
||||
uv*=vec2(INPUT_X,INPUT_Y)/rubyTextureSize.xy;
|
||||
// Move towards intersting parts
|
||||
// uv+=vec2(0.5,0.5);
|
||||
// Non-shadertoy case would not have the color conversion
|
||||
return FromSrgb(COMPAT_TEXTURE(rubyTexture,uv.xy,-16.0).rgb);}
|
||||
#endif
|
||||
|
||||
////////////////////////////////////////////////////////////////
|
||||
////////////////////////////////////////////////////////////////
|
||||
////////////////////////////////////////////////////////////////
|
||||
//_____________________________/\_______________________________
|
||||
//==============================================================
|
||||
//
|
||||
// GPU CODE
|
||||
//
|
||||
//==============================================================
|
||||
#ifdef CRTS_GPU
|
||||
//_____________________________/\_______________________________
|
||||
//==============================================================
|
||||
// PORTABILITY
|
||||
//==============================================================
|
||||
#ifdef CRTS_GLSL
|
||||
#define CrtsF1 float
|
||||
#define CrtsF2 vec2
|
||||
#define CrtsF3 vec3
|
||||
#define CrtsF4 vec4
|
||||
#define CrtsFractF1 fract
|
||||
#define CrtsRcpF1(x) (1.0/(x))
|
||||
#define CrtsSatF1(x) clamp((x),0.0,1.0)
|
||||
//--------------------------------------------------------------
|
||||
CrtsF1 CrtsMax3F1(CrtsF1 a,CrtsF1 b,CrtsF1 c){
|
||||
return max(a,max(b,c));}
|
||||
#endif
|
||||
//==============================================================
|
||||
#ifdef CRTS_HLSL
|
||||
#define CrtsF1 float
|
||||
#define CrtsF2 float2
|
||||
#define CrtsF3 float3
|
||||
#define CrtsF4 float4
|
||||
#define CrtsFractF1 frac
|
||||
#define CrtsRcpF1(x) (1.0/(x))
|
||||
#define CrtsSatF1(x) saturate(x)
|
||||
//--------------------------------------------------------------
|
||||
CrtsF1 CrtsMax3F1(CrtsF1 a,CrtsF1 b,CrtsF1 c){
|
||||
return max(a,max(b,c));}
|
||||
#endif
|
||||
//_____________________________/\_______________________________
|
||||
//==============================================================
|
||||
// TONAL CONTROL CONSTANT GENERATION
|
||||
//--------------------------------------------------------------
|
||||
// This is in here for rapid prototyping
|
||||
// Please use the CPU code and pass in as constants
|
||||
//==============================================================
|
||||
CrtsF4 CrtsTone(
|
||||
CrtsF1 contrast,
|
||||
CrtsF1 saturation,
|
||||
CrtsF1 thin,
|
||||
CrtsF1 mask){
|
||||
//--------------------------------------------------------------
|
||||
if(MASK == 0.0) mask=1.0;
|
||||
//--------------------------------------------------------------
|
||||
if(MASK == 1.0){
|
||||
// Normal R mask is {1.0,mask,mask}
|
||||
// LITE R mask is {mask,1.0,1.0}
|
||||
mask=0.5+mask*0.5;
|
||||
}
|
||||
//--------------------------------------------------------------
|
||||
CrtsF4 ret;
|
||||
CrtsF1 midOut=0.18/((1.5-thin)*(0.5*mask+0.5));
|
||||
CrtsF1 pMidIn=pow(0.18,contrast);
|
||||
ret.x=contrast;
|
||||
ret.y=((-pMidIn)+midOut)/((1.0-pMidIn)*midOut);
|
||||
ret.z=((-pMidIn)*midOut+pMidIn)/(midOut*(-pMidIn)+midOut);
|
||||
ret.w=contrast+saturation;
|
||||
return ret;}
|
||||
//_____________________________/\_______________________________
|
||||
//==============================================================
|
||||
// MASK
|
||||
//--------------------------------------------------------------
|
||||
// Letting LCD/OLED pixel elements function like CRT phosphors
|
||||
// So "phosphor" resolution scales with display resolution
|
||||
//--------------------------------------------------------------
|
||||
// Not applying any warp to the mask (want high frequency)
|
||||
// Real aperture grille has a mask which gets wider on ends
|
||||
// Not attempting to be "real" but instead look the best
|
||||
//--------------------------------------------------------------
|
||||
// Shadow mask is stretched horizontally
|
||||
// RRGGBB
|
||||
// GBBRRG
|
||||
// RRGGBB
|
||||
// This tends to look better on LCDs than vertical
|
||||
// Also 2 pixel width is required to get triad centered
|
||||
//--------------------------------------------------------------
|
||||
// The LITE version of the Aperture Grille is brighter
|
||||
// Uses {dark,1.0,1.0} for R channel
|
||||
// Non LITE version uses {1.0,dark,dark}
|
||||
//--------------------------------------------------------------
|
||||
// 'pos' - This is 'fragCoord.xy'
|
||||
// Pixel {0,0} should be {0.5,0.5}
|
||||
// Pixel {1,1} should be {1.5,1.5}
|
||||
//--------------------------------------------------------------
|
||||
// 'dark' - Exposure of of masked channel
|
||||
// 0.0=fully off, 1.0=no effect
|
||||
//==============================================================
|
||||
CrtsF3 CrtsMask(CrtsF2 pos,CrtsF1 dark){
|
||||
if(MASK == 2.0){
|
||||
CrtsF3 m=CrtsF3(dark,dark,dark);
|
||||
CrtsF1 x=CrtsFractF1(pos.x*(1.0/3.0));
|
||||
if(x<(1.0/3.0))m.r=1.0;
|
||||
else if(x<(2.0/3.0))m.g=1.0;
|
||||
else m.b=1.0;
|
||||
return m;
|
||||
}
|
||||
//--------------------------------------------------------------
|
||||
if(MASK == 1.0){
|
||||
CrtsF3 m=CrtsF3(1.0,1.0,1.0);
|
||||
CrtsF1 x=CrtsFractF1(pos.x*(1.0/3.0));
|
||||
if(x<(1.0/3.0))m.r=dark;
|
||||
else if(x<(2.0/3.0))m.g=dark;
|
||||
else m.b=dark;
|
||||
return m;
|
||||
}
|
||||
//--------------------------------------------------------------
|
||||
if(MASK == 0.0){
|
||||
return CrtsF3(1.0,1.0,1.0);
|
||||
}
|
||||
//--------------------------------------------------------------
|
||||
if(MASK == 3.0){
|
||||
pos.x+=pos.y*2.9999;
|
||||
CrtsF3 m=CrtsF3(dark,dark,dark);
|
||||
CrtsF1 x=CrtsFractF1(pos.x*(1.0/6.0));
|
||||
if(x<(1.0/3.0))m.r=1.0;
|
||||
else if(x<(2.0/3.0))m.g=1.0;
|
||||
else m.b=1.0;
|
||||
return m;
|
||||
}
|
||||
}
|
||||
//_____________________________/\_______________________________
|
||||
//==============================================================
|
||||
// FILTER ENTRY
|
||||
//--------------------------------------------------------------
|
||||
// Input must be linear
|
||||
// Output color is linear
|
||||
//--------------------------------------------------------------
|
||||
// Must have fetch function setup: CrtsF3 CrtsFetch(CrtsF2 uv)
|
||||
// - The 'uv' range is {0.0 to 1.0} for input texture
|
||||
// - Output of this must be linear color
|
||||
//--------------------------------------------------------------
|
||||
// SCANLINE MATH & AUTO-EXPOSURE NOTES
|
||||
// ===================================
|
||||
// Each output line has contribution from at most 2 scanlines
|
||||
// Scanlines are shaped by a windowed cosine function
|
||||
// This shape blends together well with only 2 lines of overlap
|
||||
//--------------------------------------------------------------
|
||||
// Base scanline intensity is as follows
|
||||
// which leaves output intensity range from {0 to 1.0}
|
||||
// --------
|
||||
// thin := range {thick 0.5 to thin 1.0}
|
||||
// off := range {0.0 to <1.0},
|
||||
// sub-pixel offset between two scanlines
|
||||
// --------
|
||||
// a0=cos(min(0.5, off *thin)*2pi)*0.5+0.5;
|
||||
// a1=cos(min(0.5,(1.0-off)*thin)*2pi)*0.5+0.5;
|
||||
//--------------------------------------------------------------
|
||||
// This leads to a image darkening factor of roughly:
|
||||
// {(1.5-thin)/1.0}
|
||||
// This is further reduced by the mask:
|
||||
// {1.0/2.0+mask*1.0/2.0}
|
||||
// Reciprocal of combined effect is used for auto-exposure
|
||||
// to scale up the mid-level in the tonemapper
|
||||
//==============================================================
|
||||
CrtsF3 CrtsFilter(
|
||||
//--------------------------------------------------------------
|
||||
// SV_POSITION, fragCoord.xy
|
||||
CrtsF2 ipos,
|
||||
//--------------------------------------------------------------
|
||||
// rubyInputSize / rubyOutputSize (in pixels)
|
||||
CrtsF2 inputSizeDivOutputSize,
|
||||
//--------------------------------------------------------------
|
||||
// 0.5 * rubyInputSize (in pixels)
|
||||
CrtsF2 halfInputSize,
|
||||
//--------------------------------------------------------------
|
||||
// 1.0 / rubyInputSize (in pixels)
|
||||
CrtsF2 rcpInputSize,
|
||||
//--------------------------------------------------------------
|
||||
// 1.0 / rubyOutputSize (in pixels)
|
||||
CrtsF2 rcpOutputSize,
|
||||
//--------------------------------------------------------------
|
||||
// 2.0 / rubyOutputSize (in pixels)
|
||||
CrtsF2 twoDivOutputSize,
|
||||
//--------------------------------------------------------------
|
||||
// rubyInputSize.y
|
||||
CrtsF1 inputHeight,
|
||||
//--------------------------------------------------------------
|
||||
// Warp scanlines but not phosphor mask
|
||||
// 0.0 = no warp
|
||||
// 1.0/64.0 = light warping
|
||||
// 1.0/32.0 = more warping
|
||||
// Want x and y warping to be different (based on aspect)
|
||||
CrtsF2 warp,
|
||||
//--------------------------------------------------------------
|
||||
// Scanline thinness
|
||||
// 0.50 = fused scanlines
|
||||
// 0.70 = recommended default
|
||||
// 1.00 = thinner scanlines (too thin)
|
||||
// Shared with CrtsTone() function
|
||||
CrtsF1 thin,
|
||||
//--------------------------------------------------------------
|
||||
// Horizonal scan blur
|
||||
// -3.0 = pixely
|
||||
// -2.5 = default
|
||||
// -2.0 = smooth
|
||||
// -1.0 = too blurry
|
||||
CrtsF1 blur,
|
||||
//--------------------------------------------------------------
|
||||
// Shadow mask effect, ranges from,
|
||||
// 0.25 = large amount of mask (not recommended, too dark)
|
||||
// 0.50 = recommended default
|
||||
// 1.00 = no shadow mask
|
||||
// Shared with CrtsTone() function
|
||||
CrtsF1 mask,
|
||||
//--------------------------------------------------------------
|
||||
// Tonal curve parameters generated by CrtsTone()
|
||||
CrtsF4 tone
|
||||
//--------------------------------------------------------------
|
||||
){
|
||||
//--------------------------------------------------------------
|
||||
#ifdef CRTS_DEBUG
|
||||
CrtsF2 uv=ipos*rcpOutputSize;
|
||||
// Show second half processed, and first half un-processed
|
||||
if(uv.x<0.5){
|
||||
// Force nearest to get squares
|
||||
uv*=1.0/rcpInputSize;
|
||||
uv=floor(uv)+CrtsF2(0.5,0.5);
|
||||
uv*=rcpInputSize;
|
||||
CrtsF3 color=CrtsFetch(uv);
|
||||
return color;}
|
||||
#endif
|
||||
//--------------------------------------------------------------
|
||||
// Optional apply warp
|
||||
CrtsF2 pos;
|
||||
#ifdef CRTS_WARP
|
||||
// Convert to {-1 to 1} range
|
||||
pos=ipos*twoDivOutputSize-CrtsF2(1.0,1.0);
|
||||
// Distort pushes image outside {-1 to 1} range
|
||||
pos*=CrtsF2(
|
||||
1.0+(pos.y*pos.y)*warp.x,
|
||||
1.0+(pos.x*pos.x)*warp.y);
|
||||
// TODO: Vignette needs optimization
|
||||
CrtsF1 vin=(1.0-(
|
||||
(1.0-CrtsSatF1(pos.x*pos.x))*(1.0-CrtsSatF1(pos.y*pos.y)))) * (0.998 + (0.001 * CORNER));
|
||||
vin=CrtsSatF1((-vin)*inputHeight+inputHeight);
|
||||
// Leave in {0 to rubyInputSize}
|
||||
pos=pos*halfInputSize+halfInputSize;
|
||||
#else
|
||||
pos=ipos*inputSizeDivOutputSize;
|
||||
#endif
|
||||
//--------------------------------------------------------------
|
||||
// Snap to center of first scanline
|
||||
CrtsF1 y0=floor(pos.y-0.5)+0.5;
|
||||
#ifdef CRTS_2_TAP
|
||||
// Using Inigo's "Improved texture Interpolation"
|
||||
// http://iquilezles.org/www/articles/texture/texture.htm
|
||||
pos.x+=0.5;
|
||||
CrtsF1 xi=floor(pos.x);
|
||||
CrtsF1 xf=pos.x-xi;
|
||||
xf=xf*xf*xf*(xf*(xf*6.0-15.0)+10.0);
|
||||
CrtsF1 x0=xi+xf-0.5;
|
||||
CrtsF2 p=CrtsF2(x0*rcpInputSize.x,y0*rcpInputSize.y);
|
||||
// Coordinate adjusted bilinear fetch from 2 nearest scanlines
|
||||
CrtsF3 colA=CrtsFetch(p);
|
||||
p.y+=rcpInputSize.y;
|
||||
CrtsF3 colB=CrtsFetch(p);
|
||||
#else
|
||||
// Snap to center of one of four pixels
|
||||
CrtsF1 x0=floor(pos.x-1.5)+0.5;
|
||||
// Inital UV position
|
||||
CrtsF2 p=CrtsF2(x0*rcpInputSize.x,y0*rcpInputSize.y);
|
||||
// Fetch 4 nearest texels from 2 nearest scanlines
|
||||
CrtsF3 colA0=CrtsFetch(p);
|
||||
p.x+=rcpInputSize.x;
|
||||
CrtsF3 colA1=CrtsFetch(p);
|
||||
p.x+=rcpInputSize.x;
|
||||
CrtsF3 colA2=CrtsFetch(p);
|
||||
p.x+=rcpInputSize.x;
|
||||
CrtsF3 colA3=CrtsFetch(p);
|
||||
p.y+=rcpInputSize.y;
|
||||
CrtsF3 colB3=CrtsFetch(p);
|
||||
p.x-=rcpInputSize.x;
|
||||
CrtsF3 colB2=CrtsFetch(p);
|
||||
p.x-=rcpInputSize.x;
|
||||
CrtsF3 colB1=CrtsFetch(p);
|
||||
p.x-=rcpInputSize.x;
|
||||
CrtsF3 colB0=CrtsFetch(p);
|
||||
#endif
|
||||
//--------------------------------------------------------------
|
||||
// Vertical filter
|
||||
// Scanline intensity is using sine wave
|
||||
// Easy filter window and integral used later in exposure
|
||||
CrtsF1 off=pos.y-y0;
|
||||
CrtsF1 pi2=6.28318530717958;
|
||||
CrtsF1 hlf=0.5;
|
||||
CrtsF1 scanA=cos(min(0.5, off *thin )*pi2)*hlf+hlf;
|
||||
CrtsF1 scanB=cos(min(0.5,(-off)*thin+thin)*pi2)*hlf+hlf;
|
||||
//--------------------------------------------------------------
|
||||
#ifdef CRTS_2_TAP
|
||||
#ifdef CRTS_WARP
|
||||
// Get rid of wrong pixels on edge
|
||||
scanA*=vin;
|
||||
scanB*=vin;
|
||||
#endif
|
||||
// Apply vertical filter
|
||||
CrtsF3 color=(colA*scanA)+(colB*scanB);
|
||||
#else
|
||||
// Horizontal kernel is simple gaussian filter
|
||||
CrtsF1 off0=pos.x-x0;
|
||||
CrtsF1 off1=off0-1.0;
|
||||
CrtsF1 off2=off0-2.0;
|
||||
CrtsF1 off3=off0-3.0;
|
||||
CrtsF1 pix0=exp2(blur*off0*off0);
|
||||
CrtsF1 pix1=exp2(blur*off1*off1);
|
||||
CrtsF1 pix2=exp2(blur*off2*off2);
|
||||
CrtsF1 pix3=exp2(blur*off3*off3);
|
||||
CrtsF1 pixT=CrtsRcpF1(pix0+pix1+pix2+pix3);
|
||||
#ifdef CRTS_WARP
|
||||
// Get rid of wrong pixels on edge
|
||||
pixT*=vin;
|
||||
#endif
|
||||
scanA*=pixT;
|
||||
scanB*=pixT;
|
||||
// Apply horizontal and vertical filters
|
||||
CrtsF3 color=
|
||||
(colA0*pix0+colA1*pix1+colA2*pix2+colA3*pix3)*scanA +
|
||||
(colB0*pix0+colB1*pix1+colB2*pix2+colB3*pix3)*scanB;
|
||||
#endif
|
||||
//--------------------------------------------------------------
|
||||
// Apply phosphor mask
|
||||
color*=CrtsMask(ipos,mask);
|
||||
//--------------------------------------------------------------
|
||||
// Optional color processing
|
||||
#ifdef CRTS_TONE
|
||||
// Tonal control, start by protecting from /0
|
||||
CrtsF1 peak=max(1.0/(256.0*65536.0),
|
||||
CrtsMax3F1(color.r,color.g,color.b));
|
||||
// Compute the ratios of {R,G,B}
|
||||
CrtsF3 ratio=color*CrtsRcpF1(peak);
|
||||
// Apply tonal curve to peak value
|
||||
#ifdef CRTS_CONTRAST
|
||||
peak=pow(peak,tone.x);
|
||||
#endif
|
||||
peak=peak*CrtsRcpF1(peak*tone.y+tone.z);
|
||||
// Apply saturation
|
||||
#ifdef CRTS_SATURATION
|
||||
ratio=pow(ratio,CrtsF3(tone.w,tone.w,tone.w));
|
||||
#endif
|
||||
// Reconstruct color
|
||||
return ratio*peak;
|
||||
#else
|
||||
return color;
|
||||
#endif
|
||||
//--------------------------------------------------------------
|
||||
}
|
||||
|
||||
void main()
|
||||
{
|
||||
vec2 warp_factor;
|
||||
warp_factor.x = CURVATURE;
|
||||
warp_factor.y = (3.0 / 4.0) * warp_factor.x; // assume 4:3 aspect
|
||||
warp_factor.x *= (1.0 - TRINITRON_CURVE);
|
||||
FragColor.rgb = CrtsFilter(vTexCoord.xy * rubyOutputSize.xy*(rubyTextureSize.xy / rubyInputSize.xy),
|
||||
rubyInputSize.xy / rubyOutputSize.xy,
|
||||
rubyInputSize.xy * vec2(0.5,0.5),
|
||||
1.0/rubyInputSize.xy,
|
||||
1.0/rubyOutputSize.xy,
|
||||
2.0/rubyOutputSize.xy,
|
||||
rubyInputSize.y,
|
||||
warp_factor,
|
||||
INPUT_THIN,
|
||||
INPUT_BLUR,
|
||||
INPUT_MASK,
|
||||
CrtsTone(1.0,0.0,INPUT_THIN,INPUT_MASK));
|
||||
|
||||
// Shadertoy outputs non-linear color
|
||||
|
||||
#ifdef SHOW_DRY
|
||||
if (vTexCoord.x > SHOW_DRY)
|
||||
if (SHOW_DRY_MODE == 0)
|
||||
FragColor.rgb = texture2D(rubyTexture, vTexCoord.xy).rgb;
|
||||
else
|
||||
FragColor.rgb = ToSrgb(FragColor.rgb);
|
||||
else
|
||||
#endif
|
||||
FragColor.rgb = ToSrgb(finalGain(FragColor.rgb));
|
||||
|
||||
}
|
||||
#endif
|
418
contrib/glshaders/crt-lottes.glsl
Normal file
418
contrib/glshaders/crt-lottes.glsl
Normal file
@@ -0,0 +1,418 @@
|
||||
// PUBLIC DOMAIN CRT STYLED SCAN-LINE SHADER
|
||||
//
|
||||
// by Timothy Lottes
|
||||
//
|
||||
// This is more along the style of a really good CGA arcade monitor.
|
||||
// With RGB inputs instead of NTSC.
|
||||
// The shadow mask example has the mask rotated 90 degrees for less chromatic aberration.
|
||||
//
|
||||
// Left it unoptimized to show the theory behind the algorithm.
|
||||
//
|
||||
// It is an example what I personally would want as a display option for pixel art games.
|
||||
// Please take and use, change, or whatever.
|
||||
|
||||
// Parameter lines go here:
|
||||
#pragma parameter hardScan "hardScan" -8.0 -20.0 0.0 1.0
|
||||
#pragma parameter hardPix "hardPix" -3.0 -20.0 0.0 1.0
|
||||
#pragma parameter warpX "warpX" 0.031 0.0 0.125 0.01
|
||||
#pragma parameter warpY "warpY" 0.041 0.0 0.125 0.01
|
||||
#pragma parameter maskDark "maskDark" 0.5 0.0 2.0 0.1
|
||||
#pragma parameter maskLight "maskLight" 1.5 0.0 2.0 0.1
|
||||
#pragma parameter scaleInLinearGamma "scaleInLinearGamma" 1.0 0.0 1.0 1.0
|
||||
#pragma parameter shadowMask "shadowMask" 3.0 0.0 4.0 1.0
|
||||
#pragma parameter brightBoost "brightness boost" 1.0 0.0 2.0 0.05
|
||||
#pragma parameter hardBloomPix "bloom-x soft" -1.5 -2.0 -0.5 0.1
|
||||
#pragma parameter hardBloomScan "bloom-y soft" -2.0 -4.0 -1.0 0.1
|
||||
#pragma parameter bloomAmount "bloom ammount" 0.15 0.0 1.0 0.05
|
||||
#pragma parameter shape "filter kernel shape" 2.0 0.0 10.0 0.05
|
||||
|
||||
#if defined(VERTEX)
|
||||
|
||||
#if __VERSION__ >= 130
|
||||
#define COMPAT_VARYING out
|
||||
#define COMPAT_ATTRIBUTE in
|
||||
#define COMPAT_TEXTURE texture
|
||||
#else
|
||||
#define COMPAT_VARYING varying
|
||||
#define COMPAT_ATTRIBUTE attribute
|
||||
#define COMPAT_TEXTURE texture2D
|
||||
#endif
|
||||
|
||||
#ifdef GL_ES
|
||||
#define COMPAT_PRECISION mediump
|
||||
#else
|
||||
#define COMPAT_PRECISION
|
||||
#endif
|
||||
|
||||
COMPAT_ATTRIBUTE vec4 VertexCoord;
|
||||
COMPAT_ATTRIBUTE vec4 COLOR;
|
||||
COMPAT_ATTRIBUTE vec4 TexCoord;
|
||||
COMPAT_VARYING vec4 COL0;
|
||||
COMPAT_VARYING vec4 TEX0;
|
||||
|
||||
uniform COMPAT_PRECISION vec2 rubyTextureSize;
|
||||
uniform COMPAT_PRECISION vec2 rubyInputSize;
|
||||
|
||||
COMPAT_ATTRIBUTE vec4 a_position;
|
||||
COMPAT_VARYING vec2 v_texCoord;
|
||||
|
||||
void main()
|
||||
{
|
||||
gl_Position = a_position;
|
||||
v_texCoord = vec2(a_position.x+1.0,1.0-a_position.y)/2.0*rubyInputSize/rubyTextureSize;
|
||||
}
|
||||
|
||||
#elif defined(FRAGMENT)
|
||||
|
||||
#if __VERSION__ >= 130
|
||||
#define COMPAT_VARYING in
|
||||
#define COMPAT_TEXTURE texture
|
||||
out vec4 FragColor;
|
||||
#else
|
||||
#define COMPAT_VARYING varying
|
||||
#define FragColor gl_FragColor
|
||||
#define COMPAT_TEXTURE texture2D
|
||||
#endif
|
||||
|
||||
#ifdef GL_ES
|
||||
#ifdef GL_FRAGMENT_PRECISION_HIGH
|
||||
precision highp float;
|
||||
#else
|
||||
precision mediump float;
|
||||
#endif
|
||||
#define COMPAT_PRECISION mediump
|
||||
#else
|
||||
#define COMPAT_PRECISION
|
||||
#endif
|
||||
|
||||
uniform COMPAT_PRECISION vec2 rubyTextureSize;
|
||||
uniform COMPAT_PRECISION vec2 rubyInputSize;
|
||||
uniform COMPAT_PRECISION vec2 rubyOutputSize;
|
||||
|
||||
uniform COMPAT_PRECISION sampler2D rubyTexture;
|
||||
COMPAT_VARYING vec2 v_texCoord;
|
||||
|
||||
// fragment compatibility #defines
|
||||
#define Source rubyTexture
|
||||
#define vTexCoord v_texCoord.xy
|
||||
|
||||
#define SourceSize vec4(rubyTextureSize, 1.0 / rubyTextureSize) //either TextureSize or InputSize
|
||||
#define outsize vec4(rubyOutputSize, 1.0 / rubyOutputSize)
|
||||
|
||||
#ifdef PARAMETER_UNIFORM
|
||||
// All parameter floats need to have COMPAT_PRECISION in front of them
|
||||
uniform COMPAT_PRECISION float hardScan;
|
||||
uniform COMPAT_PRECISION float hardPix;
|
||||
uniform COMPAT_PRECISION float warpX;
|
||||
uniform COMPAT_PRECISION float warpY;
|
||||
uniform COMPAT_PRECISION float maskDark;
|
||||
uniform COMPAT_PRECISION float maskLight;
|
||||
uniform COMPAT_PRECISION float scaleInLinearGamma;
|
||||
uniform COMPAT_PRECISION float shadowMask;
|
||||
uniform COMPAT_PRECISION float brightBoost;
|
||||
uniform COMPAT_PRECISION float hardBloomPix;
|
||||
uniform COMPAT_PRECISION float hardBloomScan;
|
||||
uniform COMPAT_PRECISION float bloomAmount;
|
||||
uniform COMPAT_PRECISION float shape;
|
||||
#else
|
||||
#define hardScan -8.0
|
||||
#define hardPix -3.0
|
||||
#define warpX 0.031
|
||||
#define warpY 0.041
|
||||
#define maskDark 0.5
|
||||
#define maskLight 1.5
|
||||
#define scaleInLinearGamma 1.0
|
||||
#define shadowMask 3.0
|
||||
#define brightBoost 1.0
|
||||
#define hardBloomPix -1.5
|
||||
#define hardBloomScan -2.0
|
||||
#define bloomAmount 0.15
|
||||
#define shape 2.0
|
||||
#endif
|
||||
|
||||
//Uncomment to reduce instructions with simpler linearization
|
||||
//(fixes HD3000 Sandy Bridge IGP)
|
||||
//#define SIMPLE_LINEAR_GAMMA
|
||||
#define DO_BLOOM
|
||||
|
||||
// ------------- //
|
||||
|
||||
// sRGB to Linear.
|
||||
// Assuming using sRGB typed textures this should not be needed.
|
||||
#ifdef SIMPLE_LINEAR_GAMMA
|
||||
float ToLinear1(float c)
|
||||
{
|
||||
return c;
|
||||
}
|
||||
vec3 ToLinear(vec3 c)
|
||||
{
|
||||
return c;
|
||||
}
|
||||
vec3 ToSrgb(vec3 c)
|
||||
{
|
||||
return pow(c, vec3(1.0 / 2.2));
|
||||
}
|
||||
#else
|
||||
float ToLinear1(float c)
|
||||
{
|
||||
if (scaleInLinearGamma == 0.)
|
||||
return c;
|
||||
|
||||
return(c<=0.04045) ? c/12.92 : pow((c + 0.055)/1.055, 2.4);
|
||||
}
|
||||
|
||||
vec3 ToLinear(vec3 c)
|
||||
{
|
||||
if (scaleInLinearGamma==0.)
|
||||
return c;
|
||||
|
||||
return vec3(ToLinear1(c.r), ToLinear1(c.g), ToLinear1(c.b));
|
||||
}
|
||||
|
||||
// Linear to sRGB.
|
||||
// Assuming using sRGB typed textures this should not be needed.
|
||||
float ToSrgb1(float c)
|
||||
{
|
||||
if (scaleInLinearGamma == 0.)
|
||||
return c;
|
||||
|
||||
return(c<0.0031308 ? c*12.92 : 1.055*pow(c, 0.41666) - 0.055);
|
||||
}
|
||||
|
||||
vec3 ToSrgb(vec3 c)
|
||||
{
|
||||
if (scaleInLinearGamma == 0.)
|
||||
return c;
|
||||
|
||||
return vec3(ToSrgb1(c.r), ToSrgb1(c.g), ToSrgb1(c.b));
|
||||
}
|
||||
#endif
|
||||
|
||||
// Nearest emulated sample given floating point position and texel offset.
|
||||
// Also zero's off screen.
|
||||
vec3 Fetch(vec2 pos,vec2 off){
|
||||
pos=(floor(pos*SourceSize.xy+off)+vec2(0.5,0.5))/SourceSize.xy;
|
||||
#ifdef SIMPLE_LINEAR_GAMMA
|
||||
return ToLinear(brightBoost * pow(COMPAT_TEXTURE(Source,pos.xy).rgb, vec3(2.2)));
|
||||
#else
|
||||
return ToLinear(brightBoost * COMPAT_TEXTURE(Source,pos.xy).rgb);
|
||||
#endif
|
||||
}
|
||||
|
||||
// Distance in emulated pixels to nearest texel.
|
||||
vec2 Dist(vec2 pos)
|
||||
{
|
||||
pos = pos*SourceSize.xy;
|
||||
|
||||
return -((pos - floor(pos)) - vec2(0.5));
|
||||
}
|
||||
|
||||
// 1D Gaussian.
|
||||
float Gaus(float pos, float scale)
|
||||
{
|
||||
return exp2(scale*pow(abs(pos), shape));
|
||||
}
|
||||
|
||||
// 3-tap Gaussian filter along horz line.
|
||||
vec3 Horz3(vec2 pos, float off)
|
||||
{
|
||||
vec3 b = Fetch(pos, vec2(-1.0, off));
|
||||
vec3 c = Fetch(pos, vec2( 0.0, off));
|
||||
vec3 d = Fetch(pos, vec2( 1.0, off));
|
||||
float dst = Dist(pos).x;
|
||||
|
||||
// Convert distance to weight.
|
||||
float scale = hardPix;
|
||||
float wb = Gaus(dst-1.0,scale);
|
||||
float wc = Gaus(dst+0.0,scale);
|
||||
float wd = Gaus(dst+1.0,scale);
|
||||
|
||||
// Return filtered sample.
|
||||
return (b*wb+c*wc+d*wd)/(wb+wc+wd);
|
||||
}
|
||||
|
||||
// 5-tap Gaussian filter along horz line.
|
||||
vec3 Horz5(vec2 pos,float off){
|
||||
vec3 a = Fetch(pos,vec2(-2.0, off));
|
||||
vec3 b = Fetch(pos,vec2(-1.0, off));
|
||||
vec3 c = Fetch(pos,vec2( 0.0, off));
|
||||
vec3 d = Fetch(pos,vec2( 1.0, off));
|
||||
vec3 e = Fetch(pos,vec2( 2.0, off));
|
||||
|
||||
float dst = Dist(pos).x;
|
||||
// Convert distance to weight.
|
||||
float scale = hardPix;
|
||||
float wa = Gaus(dst - 2.0, scale);
|
||||
float wb = Gaus(dst - 1.0, scale);
|
||||
float wc = Gaus(dst + 0.0, scale);
|
||||
float wd = Gaus(dst + 1.0, scale);
|
||||
float we = Gaus(dst + 2.0, scale);
|
||||
|
||||
// Return filtered sample.
|
||||
return (a*wa+b*wb+c*wc+d*wd+e*we)/(wa+wb+wc+wd+we);
|
||||
}
|
||||
|
||||
// 7-tap Gaussian filter along horz line.
|
||||
vec3 Horz7(vec2 pos,float off)
|
||||
{
|
||||
vec3 a = Fetch(pos, vec2(-3.0, off));
|
||||
vec3 b = Fetch(pos, vec2(-2.0, off));
|
||||
vec3 c = Fetch(pos, vec2(-1.0, off));
|
||||
vec3 d = Fetch(pos, vec2( 0.0, off));
|
||||
vec3 e = Fetch(pos, vec2( 1.0, off));
|
||||
vec3 f = Fetch(pos, vec2( 2.0, off));
|
||||
vec3 g = Fetch(pos, vec2( 3.0, off));
|
||||
|
||||
float dst = Dist(pos).x;
|
||||
// Convert distance to weight.
|
||||
float scale = hardBloomPix;
|
||||
float wa = Gaus(dst - 3.0, scale);
|
||||
float wb = Gaus(dst - 2.0, scale);
|
||||
float wc = Gaus(dst - 1.0, scale);
|
||||
float wd = Gaus(dst + 0.0, scale);
|
||||
float we = Gaus(dst + 1.0, scale);
|
||||
float wf = Gaus(dst + 2.0, scale);
|
||||
float wg = Gaus(dst + 3.0, scale);
|
||||
|
||||
// Return filtered sample.
|
||||
return (a*wa+b*wb+c*wc+d*wd+e*we+f*wf+g*wg)/(wa+wb+wc+wd+we+wf+wg);
|
||||
}
|
||||
|
||||
// Return scanline weight.
|
||||
float Scan(vec2 pos, float off)
|
||||
{
|
||||
float dst = Dist(pos).y;
|
||||
|
||||
return Gaus(dst + off, hardScan);
|
||||
}
|
||||
|
||||
// Return scanline weight for bloom.
|
||||
float BloomScan(vec2 pos, float off)
|
||||
{
|
||||
float dst = Dist(pos).y;
|
||||
|
||||
return Gaus(dst + off, hardBloomScan);
|
||||
}
|
||||
|
||||
// Allow nearest three lines to effect pixel.
|
||||
vec3 Tri(vec2 pos)
|
||||
{
|
||||
vec3 a = Horz3(pos,-1.0);
|
||||
vec3 b = Horz5(pos, 0.0);
|
||||
vec3 c = Horz3(pos, 1.0);
|
||||
|
||||
float wa = Scan(pos,-1.0);
|
||||
float wb = Scan(pos, 0.0);
|
||||
float wc = Scan(pos, 1.0);
|
||||
|
||||
return a*wa + b*wb + c*wc;
|
||||
}
|
||||
|
||||
// Small bloom.
|
||||
vec3 Bloom(vec2 pos)
|
||||
{
|
||||
vec3 a = Horz5(pos,-2.0);
|
||||
vec3 b = Horz7(pos,-1.0);
|
||||
vec3 c = Horz7(pos, 0.0);
|
||||
vec3 d = Horz7(pos, 1.0);
|
||||
vec3 e = Horz5(pos, 2.0);
|
||||
|
||||
float wa = BloomScan(pos,-2.0);
|
||||
float wb = BloomScan(pos,-1.0);
|
||||
float wc = BloomScan(pos, 0.0);
|
||||
float wd = BloomScan(pos, 1.0);
|
||||
float we = BloomScan(pos, 2.0);
|
||||
|
||||
return a*wa+b*wb+c*wc+d*wd+e*we;
|
||||
}
|
||||
|
||||
// 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;
|
||||
}
|
||||
|
||||
// Shadow mask.
|
||||
vec3 Mask(vec2 pos)
|
||||
{
|
||||
vec3 mask = vec3(maskDark, maskDark, maskDark);
|
||||
|
||||
// Very compressed TV style shadow mask.
|
||||
if (shadowMask == 1.0)
|
||||
{
|
||||
float line = maskLight;
|
||||
float odd = 0.0;
|
||||
|
||||
if (fract(pos.x*0.166666666) < 0.5) odd = 1.0;
|
||||
if (fract((pos.y + odd) * 0.5) < 0.5) line = maskDark;
|
||||
|
||||
pos.x = fract(pos.x*0.333333333);
|
||||
|
||||
if (pos.x < 0.333) mask.r = maskLight;
|
||||
else if (pos.x < 0.666) mask.g = maskLight;
|
||||
else mask.b = maskLight;
|
||||
mask*=line;
|
||||
}
|
||||
|
||||
// Aperture-grille.
|
||||
else if (shadowMask == 2.0)
|
||||
{
|
||||
pos.x = fract(pos.x*0.333333333);
|
||||
|
||||
if (pos.x < 0.333) mask.r = maskLight;
|
||||
else if (pos.x < 0.666) mask.g = maskLight;
|
||||
else mask.b = maskLight;
|
||||
}
|
||||
|
||||
// Stretched VGA style shadow mask (same as prior shaders).
|
||||
else if (shadowMask == 3.0)
|
||||
{
|
||||
pos.x += pos.y*3.0;
|
||||
pos.x = fract(pos.x*0.166666666);
|
||||
|
||||
if (pos.x < 0.333) mask.r = maskLight;
|
||||
else if (pos.x < 0.666) mask.g = maskLight;
|
||||
else mask.b = maskLight;
|
||||
}
|
||||
|
||||
// VGA style shadow mask.
|
||||
else if (shadowMask == 4.0)
|
||||
{
|
||||
pos.xy = floor(pos.xy*vec2(1.0, 0.5));
|
||||
pos.x += pos.y*3.0;
|
||||
pos.x = fract(pos.x*0.166666666);
|
||||
|
||||
if (pos.x < 0.333) mask.r = maskLight;
|
||||
else if (pos.x < 0.666) mask.g = maskLight;
|
||||
else mask.b = maskLight;
|
||||
}
|
||||
|
||||
return mask;
|
||||
}
|
||||
|
||||
void main()
|
||||
{
|
||||
vec2 pos = Warp(v_texCoord.xy*(rubyTextureSize.xy/rubyInputSize.xy))*(rubyInputSize.xy/rubyTextureSize.xy);
|
||||
vec3 outColor = Tri(pos);
|
||||
|
||||
#ifdef DO_BLOOM
|
||||
//Add Bloom
|
||||
outColor.rgb += Bloom(pos)*bloomAmount;
|
||||
#endif
|
||||
|
||||
if (shadowMask > 0.0)
|
||||
outColor.rgb *= Mask(gl_FragCoord.xy * 1.000001);
|
||||
|
||||
#ifdef GL_ES /* TODO/FIXME - hacky clamp fix */
|
||||
vec2 bordertest = (pos);
|
||||
if ( bordertest.x > 0.0001 && bordertest.x < 0.9999 && bordertest.y > 0.0001 && bordertest.y < 0.9999)
|
||||
outColor.rgb = outColor.rgb;
|
||||
else
|
||||
outColor.rgb = vec3(0.0);
|
||||
#endif
|
||||
FragColor = vec4(ToSrgb(outColor.rgb), 1.0);
|
||||
}
|
||||
#endif
|
292
contrib/glshaders/crt-lottes.tweaked.glsl
Normal file
292
contrib/glshaders/crt-lottes.tweaked.glsl
Normal file
@@ -0,0 +1,292 @@
|
||||
#version 120
|
||||
/*
|
||||
|
||||
marty_CRT-Lottes_tweaked.glsl
|
||||
marty's adaptation of dugan's CRT-Lottes port
|
||||
adapted again by liPillON for usage with DosBox SVN r4319 and later
|
||||
slightly tweaked the parameters in order to:
|
||||
- reduce the blurring,
|
||||
- bump up the brightness a bit,
|
||||
- soften the crt mask,
|
||||
- tone down the display curvature
|
||||
|
||||
source shader files:
|
||||
https://github.com/duganchen/dosbox_shaders/blob/master/crt-lottes.frag
|
||||
https://github.com/duganchen/dosbox_shaders/blob/master/crt-lottes.vert
|
||||
|
||||
marty's source is available only within the release package of its port:
|
||||
https://github.com/MartyShepard/DOSBox-Optionals
|
||||
|
||||
first posted here:
|
||||
https://www.vogons.org/viewtopic.php?f=32&t=72697
|
||||
|
||||
*/
|
||||
|
||||
uniform vec2 rubyTextureSize;
|
||||
uniform vec2 rubyInputSize;
|
||||
|
||||
#if defined(VERTEX)
|
||||
|
||||
#if __VERSION__ >= 130
|
||||
#define COMPAT_VARYING out
|
||||
#define COMPAT_ATTRIBUTE in
|
||||
#define COMPAT_TEXTURE texture
|
||||
#else
|
||||
#define COMPAT_VARYING varying
|
||||
#define COMPAT_ATTRIBUTE attribute
|
||||
#define COMPAT_TEXTURE texture2D
|
||||
#endif
|
||||
|
||||
#ifdef GL_ES
|
||||
#define COMPAT_PRECISION mediump
|
||||
#else
|
||||
#define COMPAT_PRECISION
|
||||
#endif
|
||||
|
||||
COMPAT_ATTRIBUTE vec4 a_position;
|
||||
COMPAT_VARYING vec2 v_texCoord;
|
||||
|
||||
void main()
|
||||
{
|
||||
gl_Position = a_position;
|
||||
v_texCoord = vec2(a_position.x+1.0,1.0-a_position.y)/2.0*rubyInputSize/rubyTextureSize;
|
||||
}
|
||||
|
||||
#elif defined(FRAGMENT)
|
||||
|
||||
#if __VERSION__ >= 130
|
||||
#define COMPAT_VARYING in
|
||||
#define COMPAT_TEXTURE texture
|
||||
out vec4 FragColor;
|
||||
#else
|
||||
#define COMPAT_VARYING varying
|
||||
#define FragColor gl_FragColor
|
||||
#define COMPAT_TEXTURE texture2D
|
||||
#endif
|
||||
|
||||
#ifdef GL_ES
|
||||
#ifdef GL_FRAGMENT_PRECISION_HIGH
|
||||
precision highp float;
|
||||
#else
|
||||
precision mediump float;
|
||||
#endif
|
||||
#define COMPAT_PRECISION highp
|
||||
#else
|
||||
#define COMPAT_PRECISION
|
||||
#endif
|
||||
|
||||
COMPAT_VARYING vec2 v_texCoord;
|
||||
|
||||
uniform vec2 rubyOutputSize;
|
||||
uniform sampler2D rubyTexture;
|
||||
|
||||
const float hardScan = -7.0; //tweaked
|
||||
const float hardPix = -3.5; //tweaked
|
||||
const float warpX = 0.0075; //tweaked
|
||||
const float warpY = 0.0075; //tweaked
|
||||
const float maskDark = 0.5;
|
||||
const float maskLight = 1.5;
|
||||
const float scaleInLinearGamma = 1;
|
||||
const float shadowMask = 1;
|
||||
const float brightBoost = 1.4; //tweaked
|
||||
|
||||
#define Blackmask 1
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
|
||||
// sRGB to Linear.
|
||||
// Assuing using sRGB typed textures this should not be needed.
|
||||
float ToLinear1(float c)
|
||||
{
|
||||
if (scaleInLinearGamma == 0)
|
||||
{
|
||||
return c;
|
||||
}
|
||||
return (c <= 0.04045) ? c / 12.92 : pow((c + 0.055) / 1.055, 2.4);
|
||||
}
|
||||
|
||||
vec3 ToLinear(vec3 c)
|
||||
{
|
||||
if (scaleInLinearGamma == 0)
|
||||
{
|
||||
return c;
|
||||
}
|
||||
return vec3(ToLinear1(c.r), ToLinear1(c.g), ToLinear1(c.b));
|
||||
}
|
||||
|
||||
// Linear to sRGB.
|
||||
// Assuing using sRGB typed textures this should not be needed.
|
||||
float ToSrgb1(float c)
|
||||
{
|
||||
if (scaleInLinearGamma == 0)
|
||||
{
|
||||
return c;
|
||||
}
|
||||
return(c < 0.0031308 ? c *12.92 : 1.055 * pow(c, 0.41666) - 0.055);
|
||||
}
|
||||
|
||||
vec3 ToSrgb(vec3 c)
|
||||
{
|
||||
if (scaleInLinearGamma == 0)
|
||||
{
|
||||
return c;
|
||||
}
|
||||
return vec3(ToSrgb1(c.r), ToSrgb1(c.g), ToSrgb1(c.b));
|
||||
}
|
||||
|
||||
// Nearest emulated sample given floating point position and texel offset.
|
||||
// Also zero's off screen.
|
||||
vec3 Fetch(vec2 pos,vec2 off)
|
||||
{
|
||||
pos = (floor(pos * rubyTextureSize.xy + off) + vec2(0.5, 0.5)) / rubyTextureSize.xy;
|
||||
return ToLinear(brightBoost * COMPAT_TEXTURE(rubyTexture, pos.xy).rgb);
|
||||
}
|
||||
|
||||
// Distance in emulated pixels to nearest texel.
|
||||
vec2 Dist(vec2 pos)
|
||||
{
|
||||
pos = pos * rubyTextureSize.xy;
|
||||
return -((pos - floor(pos)) - vec2(0.5));
|
||||
}
|
||||
|
||||
// 1D Gaussian.
|
||||
float Gaus(float pos, float scale)
|
||||
{
|
||||
return exp2(scale * pos * pos);
|
||||
}
|
||||
|
||||
// 3-tap Gaussian filter along horz line.
|
||||
vec3 Horz3(vec2 pos, float off)
|
||||
{
|
||||
vec3 b = Fetch(pos, vec2(-1.0, off));
|
||||
vec3 c = Fetch(pos, vec2(0.0, off));
|
||||
vec3 d = Fetch(pos, vec2(1.0, off));
|
||||
float dst = Dist(pos).x;
|
||||
// Convert distance to weight.
|
||||
float scale = hardPix;
|
||||
float wb = Gaus(dst - 1.0, scale);
|
||||
float wc = Gaus(dst + 0.0, scale);
|
||||
float wd = Gaus(dst + 1.0, scale);
|
||||
// Return filtered sample.
|
||||
return (b * wb + c * wc + d * wd) / (wb + wc + wd);
|
||||
}
|
||||
|
||||
// 5-tap Gaussian filter along horz line.
|
||||
vec3 Horz5(vec2 pos, float off)
|
||||
{
|
||||
vec3 a = Fetch(pos, vec2(-2.0, off));
|
||||
vec3 b = Fetch(pos, vec2(-1.0, off));
|
||||
vec3 c = Fetch(pos, vec2(0.0, off));
|
||||
vec3 d = Fetch(pos, vec2(1.0, off));
|
||||
vec3 e = Fetch(pos, vec2(2.0, off));
|
||||
float dst = Dist(pos).x;
|
||||
// Convert distance to weight.
|
||||
float scale = hardPix;
|
||||
float wa = Gaus(dst - 2.0, scale);
|
||||
float wb = Gaus(dst - 1.0, scale);
|
||||
float wc = Gaus(dst + 0.0, scale);
|
||||
float wd = Gaus(dst + 1.0, scale);
|
||||
float we = Gaus(dst + 2.0, scale);
|
||||
// Return filtered sample.
|
||||
return (a * wa + b * wb + c * wc + d * wd + e * we) / (wa + wb + wc + wd + we);
|
||||
}
|
||||
|
||||
// Return scanline weight.
|
||||
float Scan(vec2 pos, float off)
|
||||
{
|
||||
float dst = Dist(pos).y;
|
||||
return Gaus(dst + off, hardScan);
|
||||
}
|
||||
|
||||
// Allow nearest three lines to effect pixel.
|
||||
vec3 Tri(vec2 pos)
|
||||
{
|
||||
vec3 a = Horz3(pos, -1.0);
|
||||
vec3 b = Horz5(pos, 0.0);
|
||||
vec3 c = Horz3(pos, 1.0);
|
||||
float wa = Scan(pos, -1.0);
|
||||
float wb = Scan(pos, 0.0);
|
||||
float wc = Scan(pos, 1.0);
|
||||
return a * wa + b * wb + c * wc;
|
||||
}
|
||||
|
||||
// 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;
|
||||
}
|
||||
|
||||
// Shadow mask.
|
||||
vec3 Mask(vec2 pos)
|
||||
{
|
||||
pos.x += pos.y * 3.0;
|
||||
vec3 mask = vec3(maskDark, maskDark, maskDark);
|
||||
pos.x = fract(pos.x / 6.0);
|
||||
if (pos.x < 0.333)
|
||||
{
|
||||
mask.r = maskLight;
|
||||
}
|
||||
else if (pos.x < 0.666)
|
||||
{
|
||||
mask.g = maskLight;
|
||||
}
|
||||
else
|
||||
{
|
||||
mask.b = maskLight;
|
||||
}
|
||||
return mask;
|
||||
}
|
||||
|
||||
uniform vec2 resolution;
|
||||
uniform vec2 mouse;
|
||||
uniform float time;
|
||||
|
||||
float box(vec2 _st, vec2 _size, float _smoothEdges) {
|
||||
_size = vec2(.1) - _size*.2;
|
||||
vec2 aa = vec2(_smoothEdges * 0.1);
|
||||
vec2 uv = smoothstep(_size, _size+aa, _st);
|
||||
uv *= smoothstep(_size, _size+aa, vec2(1.0)-_st);
|
||||
return uv.x * uv.y;
|
||||
}
|
||||
|
||||
vec3 drawRectangle(in vec2 st) {
|
||||
// Each result will return 1.0 (white) or 0.0 (
|
||||
vec3 color = vec3(0.0);
|
||||
vec2 borders = step(vec2(0.0),st);
|
||||
float pct = borders.x * borders.y;
|
||||
|
||||
// top-right
|
||||
vec2 tr = step(vec2(0.1),1.0-st);
|
||||
pct *= tr.x * tr.y;
|
||||
|
||||
// The multiplication of left*bottom will be similar to the logical AND.
|
||||
color = vec3(pct);
|
||||
return color;
|
||||
}
|
||||
|
||||
void main()
|
||||
{
|
||||
vec2 pos = Warp(v_texCoord.xy * (rubyTextureSize.xy / rubyInputSize.xy)) * (rubyInputSize.xy / rubyTextureSize.xy);
|
||||
|
||||
|
||||
#ifdef Blackmask
|
||||
vec3 outColor = vec3(1.0);
|
||||
outColor *= Tri(pos);
|
||||
outColor *= drawRectangle(pos);
|
||||
outColor *= vec3(box(pos, vec2(0.5), 0.01));
|
||||
#else
|
||||
vec3 outColor = Tri(pos);
|
||||
#endif
|
||||
|
||||
|
||||
if (shadowMask != 0)
|
||||
{
|
||||
outColor.rgb *= Mask(floor(v_texCoord.xy * (rubyTextureSize.xy / rubyInputSize.xy) * rubyOutputSize.xy) + vec2(0.5, 0.5));
|
||||
}
|
||||
|
||||
FragColor = vec4(ToSrgb(outColor.rgb), 1.0);
|
||||
}
|
||||
|
||||
#endif
|
107
contrib/glshaders/crt-nes-mini.glsl
Normal file
107
contrib/glshaders/crt-nes-mini.glsl
Normal file
@@ -0,0 +1,107 @@
|
||||
#version 120
|
||||
|
||||
// Parameter lines go here:
|
||||
#pragma parameter SCANTHICK "Scanline Thickness" 2.0 2.0 4.0 2.0
|
||||
#pragma parameter INTENSITY "Scanline Intensity" 0.15 0.0 1.0 0.01
|
||||
#pragma parameter BRIGHTBOOST "Luminance Boost" 0.15 0.0 1.0 0.01
|
||||
|
||||
#if defined(VERTEX)
|
||||
|
||||
#if __VERSION__ >= 130
|
||||
#define COMPAT_VARYING out
|
||||
#define COMPAT_ATTRIBUTE in
|
||||
#define COMPAT_TEXTURE texture
|
||||
#else
|
||||
#define COMPAT_VARYING varying
|
||||
#define COMPAT_ATTRIBUTE attribute
|
||||
#define COMPAT_TEXTURE texture2D
|
||||
#endif
|
||||
|
||||
#ifdef GL_ES
|
||||
#define COMPAT_PRECISION mediump
|
||||
#else
|
||||
#define COMPAT_PRECISION
|
||||
#endif
|
||||
|
||||
COMPAT_ATTRIBUTE vec4 a_position;
|
||||
COMPAT_ATTRIBUTE vec4 COLOR;
|
||||
COMPAT_ATTRIBUTE vec4 TexCoord;
|
||||
COMPAT_VARYING vec4 COL0;
|
||||
COMPAT_VARYING vec2 v_texCoord;
|
||||
|
||||
vec4 _oPosition1;
|
||||
uniform mat4 MVPMatrix;
|
||||
uniform COMPAT_PRECISION int FrameDirection;
|
||||
uniform COMPAT_PRECISION int rubyFrameCount;
|
||||
uniform COMPAT_PRECISION vec2 rubyOutputSize;
|
||||
uniform COMPAT_PRECISION vec2 rubyTextureSize;
|
||||
uniform COMPAT_PRECISION vec2 rubyInputSize;
|
||||
|
||||
void main()
|
||||
{
|
||||
gl_Position = a_position;
|
||||
v_texCoord = vec2(a_position.x + 1.0, 1.0 - a_position.y) / 2.0 * rubyInputSize / rubyTextureSize;
|
||||
}
|
||||
|
||||
#elif defined(FRAGMENT)
|
||||
|
||||
#if __VERSION__ >= 130
|
||||
#define COMPAT_VARYING in
|
||||
#define COMPAT_TEXTURE texture
|
||||
out vec4 FragColor;
|
||||
#else
|
||||
#define COMPAT_VARYING varying
|
||||
#define FragColor gl_FragColor
|
||||
#define COMPAT_TEXTURE texture2D
|
||||
#endif
|
||||
|
||||
#ifdef GL_ES
|
||||
#ifdef GL_FRAGMENT_PRECISION_HIGH
|
||||
precision highp float;
|
||||
#else
|
||||
precision mediump float;
|
||||
#endif
|
||||
#define COMPAT_PRECISION mediump
|
||||
#else
|
||||
#define COMPAT_PRECISION
|
||||
#endif
|
||||
|
||||
uniform COMPAT_PRECISION int FrameDirection;
|
||||
uniform COMPAT_PRECISION int rubyFrameCount;
|
||||
uniform COMPAT_PRECISION vec2 rubyOutputSize;
|
||||
uniform COMPAT_PRECISION vec2 rubyTextureSize;
|
||||
uniform COMPAT_PRECISION vec2 rubyInputSize;
|
||||
uniform sampler2D rubyTexture;
|
||||
COMPAT_VARYING vec2 v_texCoord;
|
||||
|
||||
// compatibility #defines
|
||||
#define Source rubyTexture
|
||||
#define vTexCoord v_texCoord.xy
|
||||
|
||||
#define SourceSize vec4(rubyTextureSize, 1.0 / rubyTextureSize) //either rubyTextureSize or rubyInputSize
|
||||
#define rubyOutputSize vec4(rubyOutputSize, 1.0 / rubyOutputSize)
|
||||
|
||||
#ifdef PARAMETER_UNIFORM
|
||||
// All parameter floats need to have COMPAT_PRECISION in front of them
|
||||
uniform COMPAT_PRECISION float SCANTHICK;
|
||||
uniform COMPAT_PRECISION float INTENSITY;
|
||||
uniform COMPAT_PRECISION float BRIGHTBOOST;
|
||||
#else
|
||||
#define SCANTHICK 2.0
|
||||
#define INTENSITY 0.15
|
||||
#define BRIGHTBOOST 0.15
|
||||
#endif
|
||||
|
||||
void main()
|
||||
{
|
||||
vec3 texel = COMPAT_TEXTURE(rubyTexture, v_texCoord.xy).rgb;
|
||||
vec3 pixelHigh = ((1.0 + BRIGHTBOOST) - (0.2 * texel)) * texel;
|
||||
vec3 pixelLow = ((1.0 - INTENSITY) + (0.1 * texel)) * texel;
|
||||
float selectY = mod(v_texCoord.y * SCANTHICK * rubyTextureSize.y, 2.0);
|
||||
float selectHigh = step(1.0, selectY);
|
||||
float selectLow = 1.0 - selectHigh;
|
||||
vec3 pixelColor = (selectLow * pixelLow) + (selectHigh * pixelHigh);
|
||||
|
||||
FragColor = vec4(pixelColor, 1.0);
|
||||
}
|
||||
#endif
|
294
contrib/glshaders/crt-pi.glsl
Normal file
294
contrib/glshaders/crt-pi.glsl
Normal file
@@ -0,0 +1,294 @@
|
||||
#version 120
|
||||
|
||||
/*
|
||||
crt-pi - A Raspberry Pi friendly CRT shader.
|
||||
|
||||
Copyright (C) 2015-2016 davej
|
||||
|
||||
This program is free software; you can redistribute it and/or modify it
|
||||
under the terms of the GNU General Public License as published by the Free
|
||||
Software Foundation; either version 2 of the License, or (at your option)
|
||||
any later version.
|
||||
|
||||
|
||||
Notes:
|
||||
|
||||
This shader is designed to work well on Raspberry Pi GPUs (i.e. 1080P @ 60Hz on a game with a 4:3 aspect ratio). It pushes the Pi's GPU hard and enabling some features will slow it down so that it is no longer able to match 1080P @ 60Hz. You will need to overclock your Pi to the fastest setting in raspi-config to get the best results from this shader: 'Pi2' for Pi2 and 'Turbo' for original Pi and Pi Zero. Note: Pi2s are slower at running the shader than other Pis, this seems to be down to Pi2s lower maximum memory speed. Pi2s don't quite manage 1080P @ 60Hz - they drop about 1 in 1000 frames. You probably won't notice this, but if you do, try enabling FAKE_GAMMA.
|
||||
|
||||
SCANLINES enables scanlines. You'll almost certainly want to use it with MULTISAMPLE to reduce moire effects. SCANLINE_WEIGHT defines how wide scanlines are (it is an inverse value so a higher number = thinner lines). SCANLINE_GAP_BRIGHTNESS defines how dark the gaps between the scan lines are. Darker gaps between scan lines make moire effects more likely.
|
||||
|
||||
GAMMA enables gamma correction using the values in INPUT_GAMMA and OUTPUT_GAMMA. FAKE_GAMMA causes it to ignore the values in INPUT_GAMMA and OUTPUT_GAMMA and approximate gamma correction in a way which is faster than true gamma whilst still looking better than having none. You must have GAMMA defined to enable FAKE_GAMMA.
|
||||
|
||||
CURVATURE distorts the screen by CURVATURE_X and CURVATURE_Y. Curvature slows things down a lot.
|
||||
|
||||
By default the shader uses linear blending horizontally. If you find this too blury, enable SHARPER.
|
||||
|
||||
BLOOM_FACTOR controls the increase in width for bright scanlines.
|
||||
|
||||
MASK_TYPE defines what, if any, shadow mask to use. MASK_BRIGHTNESS defines how much the mask type darkens the screen.
|
||||
|
||||
*/
|
||||
|
||||
#pragma parameter CURVATURE_X "Screen curvature - horizontal" 0.10 0.0 1.0 0.01
|
||||
#pragma parameter CURVATURE_Y "Screen curvature - vertical" 0.15 0.0 1.0 0.01
|
||||
#pragma parameter MASK_BRIGHTNESS "Mask brightness" 0.70 0.0 1.0 0.01
|
||||
#pragma parameter SCANLINE_WEIGHT "Scanline weight" 6.0 0.0 15.0 0.1
|
||||
#pragma parameter SCANLINE_GAP_BRIGHTNESS "Scanline gap brightness" 0.12 0.0 1.0 0.01
|
||||
#pragma parameter BLOOM_FACTOR "Bloom factor" 1.5 0.0 5.0 0.01
|
||||
#pragma parameter INPUT_GAMMA "Input gamma" 2.4 0.0 5.0 0.01
|
||||
#pragma parameter OUTPUT_GAMMA "Output gamma" 2.2 0.0 5.0 0.01
|
||||
|
||||
// Haven't put these as parameters as it would slow the code down.
|
||||
#define SCANLINES
|
||||
#define MULTISAMPLE
|
||||
#define GAMMA
|
||||
//#define FAKE_GAMMA
|
||||
//#define CURVATURE
|
||||
//#define SHARPER
|
||||
// MASK_TYPE: 0 = none, 1 = green/magenta, 2 = trinitron(ish)
|
||||
#define MASK_TYPE 1
|
||||
|
||||
|
||||
#ifdef GL_ES
|
||||
#define COMPAT_PRECISION mediump
|
||||
precision mediump float;
|
||||
#else
|
||||
#define COMPAT_PRECISION
|
||||
#endif
|
||||
|
||||
#ifdef PARAMETER_UNIFORM
|
||||
uniform COMPAT_PRECISION float CURVATURE_X;
|
||||
uniform COMPAT_PRECISION float CURVATURE_Y;
|
||||
uniform COMPAT_PRECISION float MASK_BRIGHTNESS;
|
||||
uniform COMPAT_PRECISION float SCANLINE_WEIGHT;
|
||||
uniform COMPAT_PRECISION float SCANLINE_GAP_BRIGHTNESS;
|
||||
uniform COMPAT_PRECISION float BLOOM_FACTOR;
|
||||
uniform COMPAT_PRECISION float INPUT_GAMMA;
|
||||
uniform COMPAT_PRECISION float OUTPUT_GAMMA;
|
||||
#else
|
||||
#define CURVATURE_X 0.10
|
||||
#define CURVATURE_Y 0.25
|
||||
#define MASK_BRIGHTNESS 0.70
|
||||
#define SCANLINE_WEIGHT 6.0
|
||||
#define SCANLINE_GAP_BRIGHTNESS 0.12
|
||||
#define BLOOM_FACTOR 1.5
|
||||
#define INPUT_GAMMA 2.4
|
||||
#define OUTPUT_GAMMA 2.2
|
||||
#endif
|
||||
|
||||
/* COMPATIBILITY
|
||||
- GLSL compilers
|
||||
*/
|
||||
|
||||
uniform vec2 rubyTextureSize;
|
||||
#if defined(CURVATURE)
|
||||
varying vec2 screenScale;
|
||||
#endif
|
||||
varying vec2 v_texCoord;
|
||||
varying float filterWidth;
|
||||
|
||||
#if defined(VERTEX)
|
||||
attribute vec4 a_position;
|
||||
attribute vec2 TexCoord;
|
||||
uniform vec2 rubyInputSize;
|
||||
uniform vec2 rubyOutputSize;
|
||||
|
||||
void main()
|
||||
{
|
||||
#if defined(CURVATURE)
|
||||
screenScale = rubyTextureSize / rubyInputSize;
|
||||
#endif
|
||||
filterWidth = (rubyInputSize.y / rubyOutputSize.y) / 3.0;
|
||||
gl_Position = a_position;
|
||||
v_texCoord = vec2(a_position.x + 1.0, 1.0 - a_position.y) / 2.0 * rubyInputSize / rubyTextureSize;
|
||||
}
|
||||
#elif defined(FRAGMENT)
|
||||
|
||||
/*
|
||||
The following code allows the shader to override any texture filtering
|
||||
configured in DOSBox. if 'output' is set to 'opengl', bilinear filtering
|
||||
will be enabled and OPENGLNB will not be defined, if 'output' is set to
|
||||
'openglnb', nearest neighbour filtering will be enabled and OPENGLNB will
|
||||
be defined.
|
||||
|
||||
If you wish to use the default filtering method that is currently enabled
|
||||
in DOSBox, use COMPAT_TEXTURE to lookup a texel from the input texture.
|
||||
|
||||
If you wish to force nearest-neighbor interpolation use NN_TEXTURE.
|
||||
|
||||
If you wish to force bilinear interpolation use BL_TEXTURE.
|
||||
|
||||
If DOSBox is configured to use the filtering method that is being forced,
|
||||
the default hardware implementation will be used, otherwise the custom
|
||||
implementations below will be used instead.
|
||||
|
||||
These custom implemenations rely on the `rubyTextureSize` uniform variable.
|
||||
The code could calculate the texture size from the sampler using the
|
||||
textureSize() GLSL function, but this would require a minimum of GLSL
|
||||
version 130, which may prevent the shader from working on older systems.
|
||||
*/
|
||||
|
||||
#if defined(OPENGLNB)
|
||||
#define NN_TEXTURE texture2D
|
||||
#define BL_TEXTURE blTexture
|
||||
vec4 blTexture(in sampler2D sampler, in vec2 uv)
|
||||
{
|
||||
// subtract 0.5 here and add it again after the floor to centre the texel
|
||||
vec2 texCoord = uv * rubyTextureSize - vec2(0.5);
|
||||
vec2 s0t0 = floor(texCoord) + vec2(0.5);
|
||||
vec2 s0t1 = s0t0 + vec2(0.0, 1.0);
|
||||
vec2 s1t0 = s0t0 + vec2(1.0, 0.0);
|
||||
vec2 s1t1 = s0t0 + vec2(1.0);
|
||||
|
||||
vec2 invTexSize = 1.0 / rubyTextureSize;
|
||||
vec4 c_s0t0 = texture2D(sampler, s0t0 * invTexSize);
|
||||
vec4 c_s0t1 = texture2D(sampler, s0t1 * invTexSize);
|
||||
vec4 c_s1t0 = texture2D(sampler, s1t0 * invTexSize);
|
||||
vec4 c_s1t1 = texture2D(sampler, s1t1 * invTexSize);
|
||||
|
||||
vec2 weight = fract(texCoord);
|
||||
|
||||
vec4 c0 = c_s0t0 + (c_s1t0 - c_s0t0) * weight.x;
|
||||
vec4 c1 = c_s0t1 + (c_s1t1 - c_s0t1) * weight.x;
|
||||
|
||||
return (c0 + (c1 - c0) * weight.y);
|
||||
}
|
||||
#else
|
||||
#define BL_TEXTURE texture2D
|
||||
#define NN_TEXTURE nnTexture
|
||||
vec4 nnTexture(in sampler2D sampler, in vec2 uv)
|
||||
{
|
||||
vec2 texCoord = floor(uv * rubyTextureSize) + vec2(0.5);
|
||||
vec2 invTexSize = 1.0 / rubyTextureSize;
|
||||
return texture2D(sampler, texCoord * invTexSize);
|
||||
}
|
||||
#endif
|
||||
|
||||
uniform sampler2D rubyTexture;
|
||||
|
||||
#if defined(CURVATURE)
|
||||
vec2 Distort(vec2 coord)
|
||||
{
|
||||
vec2 CURVATURE_DISTORTION = vec2(CURVATURE_X, CURVATURE_Y);
|
||||
// Barrel distortion shrinks the display area a bit, this will allow us to counteract that.
|
||||
vec2 barrelScale = 1.0 - (0.23 * CURVATURE_DISTORTION);
|
||||
coord *= screenScale;
|
||||
coord -= vec2(0.5);
|
||||
float rsq = coord.x * coord.x + coord.y * coord.y;
|
||||
coord += coord * (CURVATURE_DISTORTION * rsq);
|
||||
coord *= barrelScale;
|
||||
if (abs(coord.x) >= 0.5 || abs(coord.y) >= 0.5)
|
||||
coord = vec2(-1.0); // If out of bounds, return an invalid value.
|
||||
else
|
||||
{
|
||||
coord += vec2(0.5);
|
||||
coord /= screenScale;
|
||||
}
|
||||
|
||||
return coord;
|
||||
}
|
||||
#endif
|
||||
|
||||
float CalcScanLineWeight(float dist)
|
||||
{
|
||||
return max(1.0-dist*dist*SCANLINE_WEIGHT, SCANLINE_GAP_BRIGHTNESS);
|
||||
}
|
||||
|
||||
float CalcScanLine(float dy)
|
||||
{
|
||||
float scanLineWeight = CalcScanLineWeight(dy);
|
||||
#if defined(MULTISAMPLE)
|
||||
scanLineWeight += CalcScanLineWeight(dy-filterWidth);
|
||||
scanLineWeight += CalcScanLineWeight(dy+filterWidth);
|
||||
scanLineWeight *= 0.3333333;
|
||||
#endif
|
||||
return scanLineWeight;
|
||||
}
|
||||
|
||||
void main()
|
||||
{
|
||||
#if defined(CURVATURE)
|
||||
vec2 texcoord = Distort(v_texCoord);
|
||||
if (texcoord.x < 0.0)
|
||||
gl_FragColor = vec4(0.0);
|
||||
else
|
||||
#else
|
||||
vec2 texcoord = v_texCoord;
|
||||
#endif
|
||||
{
|
||||
vec2 texcoordInPixels = texcoord * rubyTextureSize;
|
||||
#if defined(SHARPER)
|
||||
vec2 tempCoord = floor(texcoordInPixels) + 0.5;
|
||||
vec2 coord = tempCoord / rubyTextureSize;
|
||||
vec2 deltas = texcoordInPixels - tempCoord;
|
||||
float scanLineWeight = CalcScanLine(deltas.y);
|
||||
vec2 signs = sign(deltas);
|
||||
deltas.x *= 2.0;
|
||||
deltas = deltas * deltas;
|
||||
deltas.y = deltas.y * deltas.y;
|
||||
deltas.x *= 0.5;
|
||||
deltas.y *= 8.0;
|
||||
deltas /= rubyTextureSize;
|
||||
deltas *= signs;
|
||||
vec2 tc = coord + deltas;
|
||||
#else
|
||||
float tempY = floor(texcoordInPixels.y) + 0.5;
|
||||
float yCoord = tempY / rubyTextureSize.y;
|
||||
float dy = texcoordInPixels.y - tempY;
|
||||
float scanLineWeight = CalcScanLine(dy);
|
||||
float signY = sign(dy);
|
||||
dy = dy * dy;
|
||||
dy = dy * dy;
|
||||
dy *= 8.0;
|
||||
dy /= rubyTextureSize.y;
|
||||
dy *= signY;
|
||||
vec2 tc = vec2(texcoord.x, yCoord + dy);
|
||||
#endif
|
||||
|
||||
vec3 colour = BL_TEXTURE(rubyTexture, tc).rgb;
|
||||
|
||||
#if defined(SCANLINES)
|
||||
#if defined(GAMMA)
|
||||
#if defined(FAKE_GAMMA)
|
||||
colour = colour * colour;
|
||||
#else
|
||||
colour = pow(colour, vec3(INPUT_GAMMA));
|
||||
#endif
|
||||
#endif
|
||||
scanLineWeight *= BLOOM_FACTOR;
|
||||
colour *= scanLineWeight;
|
||||
|
||||
#if defined(GAMMA)
|
||||
#if defined(FAKE_GAMMA)
|
||||
colour = sqrt(colour);
|
||||
#else
|
||||
colour = pow(colour, vec3(1.0/OUTPUT_GAMMA));
|
||||
#endif
|
||||
#endif
|
||||
#endif
|
||||
#if MASK_TYPE == 0
|
||||
gl_FragColor = vec4(colour, 1.0);
|
||||
#else
|
||||
#if MASK_TYPE == 1
|
||||
float whichMask = fract(gl_FragCoord.x * 0.5);
|
||||
vec3 mask;
|
||||
if (whichMask < 0.5)
|
||||
mask = vec3(MASK_BRIGHTNESS, 1.0, MASK_BRIGHTNESS);
|
||||
else
|
||||
mask = vec3(1.0, MASK_BRIGHTNESS, 1.0);
|
||||
#elif MASK_TYPE == 2
|
||||
float whichMask = fract(gl_FragCoord.x * 0.3333333);
|
||||
vec3 mask = vec3(MASK_BRIGHTNESS, MASK_BRIGHTNESS, MASK_BRIGHTNESS);
|
||||
if (whichMask < 0.3333333)
|
||||
mask.x = 1.0;
|
||||
else if (whichMask < 0.6666666)
|
||||
mask.y = 1.0;
|
||||
else
|
||||
mask.z = 1.0;
|
||||
#endif
|
||||
|
||||
gl_FragColor = vec4(colour * mask, 1.0);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
#endif
|
342
contrib/glshaders/fakelottes.glsl
Normal file
342
contrib/glshaders/fakelottes.glsl
Normal file
@@ -0,0 +1,342 @@
|
||||
#version 120
|
||||
|
||||
// Simple scanlines with curvature and mask effects lifted from crt-lottes
|
||||
// by hunterk
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
//////////////////////////// SETTINGS ////////////////////////////
|
||||
///// comment these lines to disable effects and gain speed //////
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
||||
#define MASK // fancy, expensive phosphor mask effect
|
||||
#define CURVATURE // applies barrel distortion to the screen
|
||||
#define SCANLINES // applies horizontal scanline effect
|
||||
//#define ROTATE_SCANLINES // for TATE games; also disables the mask effects, which look bad with it
|
||||
#define EXTRA_MASKS // disable these if you need extra registers freed up
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
////////////////////////// END SETTINGS //////////////////////////
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
||||
/////////////////////// Runtime Parameters ///////////////////////
|
||||
#pragma parameter shadowMask "shadowMask" 1.0 0.0 4.0 1.0
|
||||
#pragma parameter SCANLINE_SINE_COMP_B "Scanline Intensity" 0.40 0.0 1.0 0.05
|
||||
#pragma parameter warpX "warpX" 0.031 0.0 0.125 0.01
|
||||
#pragma parameter warpY "warpY" 0.041 0.0 0.125 0.01
|
||||
#pragma parameter maskDark "maskDark" 0.5 0.0 2.0 0.1
|
||||
#pragma parameter maskLight "maskLight" 1.5 0.0 2.0 0.1
|
||||
#pragma parameter crt_gamma "CRT Gamma" 2.5 1.0 4.0 0.05
|
||||
#pragma parameter monitor_gamma "Monitor Gamma" 2.2 1.0 4.0 0.05
|
||||
#pragma parameter SCANLINE_SINE_COMP_A "Scanline Sine Comp A" 0.0 0.0 0.10 0.01
|
||||
#pragma parameter SCANLINE_BASE_BRIGHTNESS "Scanline Base Brightness" 0.95 0.0 1.0 0.01
|
||||
|
||||
// prevent stupid behavior
|
||||
#if defined ROTATE_SCANLINES && !defined SCANLINES
|
||||
#define SCANLINES
|
||||
#endif
|
||||
|
||||
#if defined(VERTEX)
|
||||
|
||||
#if __VERSION__ >= 130
|
||||
#define COMPAT_VARYING out
|
||||
#define COMPAT_ATTRIBUTE in
|
||||
#define COMPAT_TEXTURE texture
|
||||
#else
|
||||
#define COMPAT_VARYING varying
|
||||
#define COMPAT_ATTRIBUTE attribute
|
||||
#define COMPAT_TEXTURE texture2D
|
||||
#endif
|
||||
|
||||
#ifdef GL_ES
|
||||
#define COMPAT_PRECISION mediump
|
||||
#else
|
||||
#define COMPAT_PRECISION
|
||||
#endif
|
||||
|
||||
COMPAT_ATTRIBUTE vec4 a_position;
|
||||
COMPAT_ATTRIBUTE vec4 COLOR;
|
||||
COMPAT_ATTRIBUTE vec4 TexCoord;
|
||||
COMPAT_VARYING vec4 COL0;
|
||||
COMPAT_VARYING vec2 v_texCoord;
|
||||
|
||||
vec4 _oPosition1;
|
||||
uniform mat4 MVPMatrix;
|
||||
uniform COMPAT_PRECISION int FrameDirection;
|
||||
uniform COMPAT_PRECISION int rubyFrameCount;
|
||||
uniform COMPAT_PRECISION vec2 rubyOutputSize;
|
||||
uniform COMPAT_PRECISION vec2 rubyTextureSize;
|
||||
uniform COMPAT_PRECISION vec2 rubyInputSize;
|
||||
|
||||
// compatibility #defines
|
||||
#define vTexCoord v_texCoord.xy
|
||||
#define SourceSize vec4(rubyTextureSize, 1.0 / rubyTextureSize) //either rubyTextureSize or rubyInputSize
|
||||
#define OutSize vec4(rubyOutputSize, 1.0 / rubyOutputSize)
|
||||
|
||||
#ifdef PARAMETER_UNIFORM
|
||||
uniform COMPAT_PRECISION float WHATEVER;
|
||||
#else
|
||||
#define WHATEVER 0.0
|
||||
#endif
|
||||
|
||||
void main()
|
||||
{
|
||||
gl_Position = a_position;
|
||||
v_texCoord = vec2(a_position.x + 1.0, 1.0 - a_position.y) / 2.0 * rubyInputSize / rubyTextureSize;
|
||||
}
|
||||
|
||||
#elif defined(FRAGMENT)
|
||||
|
||||
#if __VERSION__ >= 130
|
||||
#define COMPAT_VARYING in
|
||||
#define COMPAT_TEXTURE texture
|
||||
out vec4 FragColor;
|
||||
#else
|
||||
#define COMPAT_VARYING varying
|
||||
#define FragColor gl_FragColor
|
||||
#define COMPAT_TEXTURE texture2D
|
||||
#endif
|
||||
|
||||
#ifdef GL_ES
|
||||
#ifdef GL_FRAGMENT_PRECISION_HIGH
|
||||
precision highp float;
|
||||
#else
|
||||
precision mediump float;
|
||||
#endif
|
||||
#define COMPAT_PRECISION mediump
|
||||
#else
|
||||
#define COMPAT_PRECISION
|
||||
#endif
|
||||
|
||||
uniform COMPAT_PRECISION int FrameDirection;
|
||||
uniform COMPAT_PRECISION int rubyFrameCount;
|
||||
uniform COMPAT_PRECISION vec2 rubyOutputSize;
|
||||
uniform COMPAT_PRECISION vec2 rubyTextureSize;
|
||||
uniform COMPAT_PRECISION vec2 rubyInputSize;
|
||||
uniform sampler2D rubyTexture;
|
||||
COMPAT_VARYING vec2 v_texCoord;
|
||||
|
||||
// compatibility #defines
|
||||
#define Source rubyTexture
|
||||
#define vTexCoord v_texCoord.xy
|
||||
|
||||
#define SourceSize vec4(rubyTextureSize, 1.0 / rubyTextureSize) //either rubyTextureSize or rubyInputSize
|
||||
#define OutSize vec4(rubyOutputSize, 1.0 / rubyOutputSize)
|
||||
|
||||
#ifdef PARAMETER_UNIFORM
|
||||
uniform COMPAT_PRECISION float SCANLINE_BASE_BRIGHTNESS;
|
||||
uniform COMPAT_PRECISION float SCANLINE_SINE_COMP_A;
|
||||
uniform COMPAT_PRECISION float SCANLINE_SINE_COMP_B;
|
||||
uniform COMPAT_PRECISION float warpX;
|
||||
uniform COMPAT_PRECISION float warpY;
|
||||
uniform COMPAT_PRECISION float maskDark;
|
||||
uniform COMPAT_PRECISION float maskLight;
|
||||
uniform COMPAT_PRECISION float shadowMask;
|
||||
uniform COMPAT_PRECISION float crt_gamma;
|
||||
uniform COMPAT_PRECISION float monitor_gamma;
|
||||
#else
|
||||
#define SCANLINE_BASE_BRIGHTNESS 0.95
|
||||
#define SCANLINE_SINE_COMP_A 0.0
|
||||
#define SCANLINE_SINE_COMP_B 0.40
|
||||
#define warpX 0.031
|
||||
#define warpY 0.041
|
||||
#define maskDark 0.5
|
||||
#define maskLight 1.5
|
||||
#define shadowMask 1.0
|
||||
#define crt_gamma 2.5
|
||||
#define monitor_gamma 2.2
|
||||
#endif
|
||||
|
||||
/*
|
||||
The following code allows the shader to override any texture filtering
|
||||
configured in DOSBox. if 'output' is set to 'opengl', bilinear filtering
|
||||
will be enabled and OPENGLNB will not be defined, if 'output' is set to
|
||||
'openglnb', nearest neighbour filtering will be enabled and OPENGLNB will
|
||||
be defined.
|
||||
|
||||
If you wish to use the default filtering method that is currently enabled
|
||||
in DOSBox, use COMPAT_TEXTURE to lookup a texel from the input texture.
|
||||
|
||||
If you wish to force nearest-neighbor interpolation use NN_TEXTURE.
|
||||
|
||||
If you wish to force bilinear interpolation use BL_TEXTURE.
|
||||
|
||||
If DOSBox is configured to use the filtering method that is being forced,
|
||||
the default hardware implementation will be used, otherwise the custom
|
||||
implementations below will be used instead.
|
||||
|
||||
These custom implemenations rely on the `rubyTextureSize` uniform variable.
|
||||
The code could calculate the texture size from the sampler using the
|
||||
textureSize() GLSL function, but this would require a minimum of GLSL
|
||||
version 130, which may prevent the shader from working on older systems.
|
||||
*/
|
||||
|
||||
#if defined(OPENGLNB)
|
||||
#define NN_TEXTURE COMPAT_TEXTURE
|
||||
#define BL_TEXTURE blTexture
|
||||
vec4 blTexture(in sampler2D sampler, in vec2 uv)
|
||||
{
|
||||
// subtract 0.5 here and add it again after the floor to centre the texel
|
||||
vec2 texCoord = uv * rubyTextureSize - vec2(0.5);
|
||||
vec2 s0t0 = floor(texCoord) + vec2(0.5);
|
||||
vec2 s0t1 = s0t0 + vec2(0.0, 1.0);
|
||||
vec2 s1t0 = s0t0 + vec2(1.0, 0.0);
|
||||
vec2 s1t1 = s0t0 + vec2(1.0);
|
||||
|
||||
vec2 invTexSize = 1.0 / rubyTextureSize;
|
||||
vec4 c_s0t0 = COMPAT_TEXTURE(sampler, s0t0 * invTexSize);
|
||||
vec4 c_s0t1 = COMPAT_TEXTURE(sampler, s0t1 * invTexSize);
|
||||
vec4 c_s1t0 = COMPAT_TEXTURE(sampler, s1t0 * invTexSize);
|
||||
vec4 c_s1t1 = COMPAT_TEXTURE(sampler, s1t1 * invTexSize);
|
||||
|
||||
vec2 weight = fract(texCoord);
|
||||
|
||||
vec4 c0 = c_s0t0 + (c_s1t0 - c_s0t0) * weight.x;
|
||||
vec4 c1 = c_s0t1 + (c_s1t1 - c_s0t1) * weight.x;
|
||||
|
||||
return (c0 + (c1 - c0) * weight.y);
|
||||
}
|
||||
#else
|
||||
#define BL_TEXTURE COMPAT_TEXTURE
|
||||
#define NN_TEXTURE nnTexture
|
||||
vec4 nnTexture(in sampler2D sampler, in vec2 uv)
|
||||
{
|
||||
vec2 texCoord = floor(uv * rubyTextureSize) + vec2(0.5);
|
||||
vec2 invTexSize = 1.0 / rubyTextureSize;
|
||||
return COMPAT_TEXTURE(sampler, texCoord * invTexSize);
|
||||
}
|
||||
#endif
|
||||
|
||||
vec4 scanline(vec2 coord, vec4 frame)
|
||||
{
|
||||
#if defined SCANLINES
|
||||
vec2 omega = vec2(3.1415 * rubyOutputSize.x, 2.0 * 3.1415 * rubyTextureSize.y);
|
||||
vec2 sine_comp = vec2(SCANLINE_SINE_COMP_A, SCANLINE_SINE_COMP_B);
|
||||
vec3 res = frame.xyz;
|
||||
#ifdef ROTATE_SCANLINES
|
||||
sine_comp = sine_comp.yx;
|
||||
omega = omega.yx;
|
||||
#endif
|
||||
vec3 scanline = res * (SCANLINE_BASE_BRIGHTNESS + dot(sine_comp * sin(coord * omega), vec2(1.0, 1.0)));
|
||||
|
||||
return vec4(scanline.x, scanline.y, scanline.z, 1.0);
|
||||
#else
|
||||
return frame;
|
||||
#endif
|
||||
}
|
||||
|
||||
#ifdef CURVATURE
|
||||
// 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
|
||||
|
||||
#if defined MASK && !defined ROTATE_SCANLINES
|
||||
// Shadow mask.
|
||||
vec4 Mask(vec2 pos)
|
||||
{
|
||||
vec3 mask = vec3(maskDark, maskDark, maskDark);
|
||||
|
||||
// Very compressed TV style shadow mask.
|
||||
if (shadowMask == 1.0)
|
||||
{
|
||||
float line = maskLight;
|
||||
float odd = 0.0;
|
||||
|
||||
if (fract(pos.x*0.166666666) < 0.5) odd = 1.0;
|
||||
if (fract((pos.y + odd) * 0.5) < 0.5) line = maskDark;
|
||||
|
||||
pos.x = fract(pos.x*0.333333333);
|
||||
|
||||
if (pos.x < 0.333) mask.r = maskLight;
|
||||
else if (pos.x < 0.666) mask.g = maskLight;
|
||||
else mask.b = maskLight;
|
||||
mask*=line;
|
||||
}
|
||||
|
||||
// Aperture-grille.
|
||||
else if (shadowMask == 2.0)
|
||||
{
|
||||
pos.x = fract(pos.x*0.333333333);
|
||||
|
||||
if (pos.x < 0.333) mask.r = maskLight;
|
||||
else if (pos.x < 0.666) mask.g = maskLight;
|
||||
else mask.b = maskLight;
|
||||
}
|
||||
#ifdef EXTRA_MASKS
|
||||
// These can cause moire with curvature and scanlines
|
||||
// so they're an easy target for freeing up registers
|
||||
|
||||
// Stretched VGA style shadow mask (same as prior shaders).
|
||||
else if (shadowMask == 3.0)
|
||||
{
|
||||
pos.x += pos.y*3.0;
|
||||
pos.x = fract(pos.x*0.166666666);
|
||||
|
||||
if (pos.x < 0.333) mask.r = maskLight;
|
||||
else if (pos.x < 0.666) mask.g = maskLight;
|
||||
else mask.b = maskLight;
|
||||
}
|
||||
|
||||
// VGA style shadow mask.
|
||||
else if (shadowMask == 4.0)
|
||||
{
|
||||
pos.xy = floor(pos.xy*vec2(1.0, 0.5));
|
||||
pos.x += pos.y*3.0;
|
||||
pos.x = fract(pos.x*0.166666666);
|
||||
|
||||
if (pos.x < 0.333) mask.r = maskLight;
|
||||
else if (pos.x < 0.666) mask.g = maskLight;
|
||||
else mask.b = maskLight;
|
||||
}
|
||||
#endif
|
||||
|
||||
else mask = vec3(1.,1.,1.);
|
||||
|
||||
return vec4(mask, 1.0);
|
||||
}
|
||||
#endif
|
||||
|
||||
void main()
|
||||
{
|
||||
#ifdef CURVATURE
|
||||
vec2 pos = Warp(v_texCoord.xy*(rubyTextureSize.xy/rubyInputSize.xy))*(rubyInputSize.xy/rubyTextureSize.xy);
|
||||
#else
|
||||
vec2 pos = v_texCoord.xy;
|
||||
#endif
|
||||
|
||||
#if defined MASK && !defined ROTATE_SCANLINES
|
||||
// mask effects look bad unless applied in linear gamma space
|
||||
vec4 in_gamma = vec4(monitor_gamma, monitor_gamma, monitor_gamma, 1.0);
|
||||
vec4 out_gamma = vec4(1.0 / crt_gamma, 1.0 / crt_gamma, 1.0 / crt_gamma, 1.0);
|
||||
vec4 res = pow(BL_TEXTURE(Source, pos), in_gamma);
|
||||
#else
|
||||
vec4 res = BL_TEXTURE(Source, pos);
|
||||
#endif
|
||||
|
||||
#if defined MASK && !defined ROTATE_SCANLINES
|
||||
// apply the mask; looks bad with vert scanlines so make them mutually exclusive
|
||||
res *= Mask(gl_FragCoord.xy * 1.0001);
|
||||
#endif
|
||||
|
||||
#if defined CURVATURE && defined GL_ES
|
||||
// hacky clamp fix for GLES
|
||||
vec2 bordertest = (pos);
|
||||
if ( bordertest.x > 0.0001 && bordertest.x < 0.9999 && bordertest.y > 0.0001 && bordertest.y < 0.9999)
|
||||
res = res;
|
||||
else
|
||||
res = vec4(0.,0.,0.,0.);
|
||||
#endif
|
||||
|
||||
#if defined MASK && !defined ROTATE_SCANLINES
|
||||
// re-apply the gamma curve for the mask path
|
||||
FragColor = pow(scanline(pos, res), out_gamma);
|
||||
#else
|
||||
FragColor = scanline(pos, res);
|
||||
#endif
|
||||
}
|
||||
#endif
|
342
contrib/glshaders/fakelottes.tweaked.glsl
Normal file
342
contrib/glshaders/fakelottes.tweaked.glsl
Normal file
@@ -0,0 +1,342 @@
|
||||
#version 120
|
||||
|
||||
// Simple scanlines with curvature and mask effects lifted from crt-lottes
|
||||
// by hunterk
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
//////////////////////////// SETTINGS ////////////////////////////
|
||||
///// comment these lines to disable effects and gain speed //////
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
||||
#define MASK // fancy, expensive phosphor mask effect
|
||||
//#define CURVATURE // applies barrel distortion to the screen
|
||||
#define SCANLINES // applies horizontal scanline effect
|
||||
//#define ROTATE_SCANLINES // for TATE games; also disables the mask effects, which look bad with it
|
||||
#define EXTRA_MASKS // disable these if you need extra registers freed up
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
////////////////////////// END SETTINGS //////////////////////////
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
||||
/////////////////////// Runtime Parameters ///////////////////////
|
||||
#pragma parameter shadowMask "shadowMask" 1.0 0.0 4.0 1.0
|
||||
#pragma parameter SCANLINE_SINE_COMP_B "Scanline Intensity" 0.40 0.0 1.0 0.05
|
||||
#pragma parameter warpX "warpX" 0.031 0.0 0.125 0.01
|
||||
#pragma parameter warpY "warpY" 0.041 0.0 0.125 0.01
|
||||
#pragma parameter maskDark "maskDark" 0.5 0.0 2.0 0.1
|
||||
#pragma parameter maskLight "maskLight" 1.5 0.0 2.0 0.1
|
||||
#pragma parameter crt_gamma "CRT Gamma" 2.5 1.0 4.0 0.05
|
||||
#pragma parameter monitor_gamma "Monitor Gamma" 2.2 1.0 4.0 0.05
|
||||
#pragma parameter SCANLINE_SINE_COMP_A "Scanline Sine Comp A" 0.0 0.0 0.10 0.01
|
||||
#pragma parameter SCANLINE_BASE_BRIGHTNESS "Scanline Base Brightness" 0.95 0.0 1.0 0.01
|
||||
|
||||
// prevent stupid behavior
|
||||
#if defined ROTATE_SCANLINES && !defined SCANLINES
|
||||
#define SCANLINES
|
||||
#endif
|
||||
|
||||
#if defined(VERTEX)
|
||||
|
||||
#if __VERSION__ >= 130
|
||||
#define COMPAT_VARYING out
|
||||
#define COMPAT_ATTRIBUTE in
|
||||
#define COMPAT_TEXTURE texture
|
||||
#else
|
||||
#define COMPAT_VARYING varying
|
||||
#define COMPAT_ATTRIBUTE attribute
|
||||
#define COMPAT_TEXTURE texture2D
|
||||
#endif
|
||||
|
||||
#ifdef GL_ES
|
||||
#define COMPAT_PRECISION mediump
|
||||
#else
|
||||
#define COMPAT_PRECISION
|
||||
#endif
|
||||
|
||||
COMPAT_ATTRIBUTE vec4 a_position;
|
||||
COMPAT_ATTRIBUTE vec4 COLOR;
|
||||
COMPAT_ATTRIBUTE vec4 TexCoord;
|
||||
COMPAT_VARYING vec4 COL0;
|
||||
COMPAT_VARYING vec2 v_texCoord;
|
||||
|
||||
vec4 _oPosition1;
|
||||
uniform mat4 MVPMatrix;
|
||||
uniform COMPAT_PRECISION int FrameDirection;
|
||||
uniform COMPAT_PRECISION int rubyFrameCount;
|
||||
uniform COMPAT_PRECISION vec2 rubyOutputSize;
|
||||
uniform COMPAT_PRECISION vec2 rubyTextureSize;
|
||||
uniform COMPAT_PRECISION vec2 rubyInputSize;
|
||||
|
||||
// compatibility #defines
|
||||
#define vTexCoord v_texCoord.xy
|
||||
#define SourceSize vec4(rubyTextureSize, 1.0 / rubyTextureSize) //either rubyTextureSize or rubyInputSize
|
||||
#define OutSize vec4(rubyOutputSize, 1.0 / rubyOutputSize)
|
||||
|
||||
#ifdef PARAMETER_UNIFORM
|
||||
uniform COMPAT_PRECISION float WHATEVER;
|
||||
#else
|
||||
#define WHATEVER 0.0
|
||||
#endif
|
||||
|
||||
void main()
|
||||
{
|
||||
gl_Position = a_position;
|
||||
v_texCoord = vec2(a_position.x + 1.0, 1.0 - a_position.y) / 2.0 * rubyInputSize / rubyTextureSize;
|
||||
}
|
||||
|
||||
#elif defined(FRAGMENT)
|
||||
|
||||
#if __VERSION__ >= 130
|
||||
#define COMPAT_VARYING in
|
||||
#define COMPAT_TEXTURE texture
|
||||
out vec4 FragColor;
|
||||
#else
|
||||
#define COMPAT_VARYING varying
|
||||
#define FragColor gl_FragColor
|
||||
#define COMPAT_TEXTURE texture2D
|
||||
#endif
|
||||
|
||||
#ifdef GL_ES
|
||||
#ifdef GL_FRAGMENT_PRECISION_HIGH
|
||||
precision highp float;
|
||||
#else
|
||||
precision mediump float;
|
||||
#endif
|
||||
#define COMPAT_PRECISION mediump
|
||||
#else
|
||||
#define COMPAT_PRECISION
|
||||
#endif
|
||||
|
||||
uniform COMPAT_PRECISION int FrameDirection;
|
||||
uniform COMPAT_PRECISION int rubyFrameCount;
|
||||
uniform COMPAT_PRECISION vec2 rubyOutputSize;
|
||||
uniform COMPAT_PRECISION vec2 rubyTextureSize;
|
||||
uniform COMPAT_PRECISION vec2 rubyInputSize;
|
||||
uniform sampler2D rubyTexture;
|
||||
COMPAT_VARYING vec2 v_texCoord;
|
||||
|
||||
// compatibility #defines
|
||||
#define Source rubyTexture
|
||||
#define vTexCoord v_texCoord.xy
|
||||
|
||||
#define SourceSize vec4(rubyTextureSize, 1.0 / rubyTextureSize) //either rubyTextureSize or rubyInputSize
|
||||
#define OutSize vec4(rubyOutputSize, 1.0 / rubyOutputSize)
|
||||
|
||||
#ifdef PARAMETER_UNIFORM
|
||||
uniform COMPAT_PRECISION float SCANLINE_BASE_BRIGHTNESS;
|
||||
uniform COMPAT_PRECISION float SCANLINE_SINE_COMP_A;
|
||||
uniform COMPAT_PRECISION float SCANLINE_SINE_COMP_B;
|
||||
uniform COMPAT_PRECISION float warpX;
|
||||
uniform COMPAT_PRECISION float warpY;
|
||||
uniform COMPAT_PRECISION float maskDark;
|
||||
uniform COMPAT_PRECISION float maskLight;
|
||||
uniform COMPAT_PRECISION float shadowMask;
|
||||
uniform COMPAT_PRECISION float crt_gamma;
|
||||
uniform COMPAT_PRECISION float monitor_gamma;
|
||||
#else
|
||||
#define SCANLINE_BASE_BRIGHTNESS 0.95
|
||||
#define SCANLINE_SINE_COMP_A 0.0
|
||||
#define SCANLINE_SINE_COMP_B 0.40
|
||||
#define warpX 0.031
|
||||
#define warpY 0.041
|
||||
#define maskDark 0.5
|
||||
#define maskLight 1.5
|
||||
#define shadowMask 1.0
|
||||
#define crt_gamma 2.5
|
||||
#define monitor_gamma 2.2
|
||||
#endif
|
||||
|
||||
/*
|
||||
The following code allows the shader to override any texture filtering
|
||||
configured in DOSBox. if 'output' is set to 'opengl', bilinear filtering
|
||||
will be enabled and OPENGLNB will not be defined, if 'output' is set to
|
||||
'openglnb', nearest neighbour filtering will be enabled and OPENGLNB will
|
||||
be defined.
|
||||
|
||||
If you wish to use the default filtering method that is currently enabled
|
||||
in DOSBox, use COMPAT_TEXTURE to lookup a texel from the input texture.
|
||||
|
||||
If you wish to force nearest-neighbor interpolation use NN_TEXTURE.
|
||||
|
||||
If you wish to force bilinear interpolation use BL_TEXTURE.
|
||||
|
||||
If DOSBox is configured to use the filtering method that is being forced,
|
||||
the default hardware implementation will be used, otherwise the custom
|
||||
implementations below will be used instead.
|
||||
|
||||
These custom implemenations rely on the `rubyTextureSize` uniform variable.
|
||||
The code could calculate the texture size from the sampler using the
|
||||
textureSize() GLSL function, but this would require a minimum of GLSL
|
||||
version 130, which may prevent the shader from working on older systems.
|
||||
*/
|
||||
|
||||
#if defined(OPENGLNB)
|
||||
#define NN_TEXTURE COMPAT_TEXTURE
|
||||
#define BL_TEXTURE blTexture
|
||||
vec4 blTexture(in sampler2D sampler, in vec2 uv)
|
||||
{
|
||||
// subtract 0.5 here and add it again after the floor to centre the texel
|
||||
vec2 texCoord = uv * rubyTextureSize - vec2(0.5);
|
||||
vec2 s0t0 = floor(texCoord) + vec2(0.5);
|
||||
vec2 s0t1 = s0t0 + vec2(0.0, 1.0);
|
||||
vec2 s1t0 = s0t0 + vec2(1.0, 0.0);
|
||||
vec2 s1t1 = s0t0 + vec2(1.0);
|
||||
|
||||
vec2 invTexSize = 1.0 / rubyTextureSize;
|
||||
vec4 c_s0t0 = COMPAT_TEXTURE(sampler, s0t0 * invTexSize);
|
||||
vec4 c_s0t1 = COMPAT_TEXTURE(sampler, s0t1 * invTexSize);
|
||||
vec4 c_s1t0 = COMPAT_TEXTURE(sampler, s1t0 * invTexSize);
|
||||
vec4 c_s1t1 = COMPAT_TEXTURE(sampler, s1t1 * invTexSize);
|
||||
|
||||
vec2 weight = fract(texCoord);
|
||||
|
||||
vec4 c0 = c_s0t0 + (c_s1t0 - c_s0t0) * weight.x;
|
||||
vec4 c1 = c_s0t1 + (c_s1t1 - c_s0t1) * weight.x;
|
||||
|
||||
return (c0 + (c1 - c0) * weight.y);
|
||||
}
|
||||
#else
|
||||
#define BL_TEXTURE COMPAT_TEXTURE
|
||||
#define NN_TEXTURE nnTexture
|
||||
vec4 nnTexture(in sampler2D sampler, in vec2 uv)
|
||||
{
|
||||
vec2 texCoord = floor(uv * rubyTextureSize) + vec2(0.5);
|
||||
vec2 invTexSize = 1.0 / rubyTextureSize;
|
||||
return COMPAT_TEXTURE(sampler, texCoord * invTexSize);
|
||||
}
|
||||
#endif
|
||||
|
||||
vec4 scanline(vec2 coord, vec4 frame)
|
||||
{
|
||||
#if defined SCANLINES
|
||||
vec2 omega = vec2(3.1415 * rubyOutputSize.x, 2.0 * 3.1415 * rubyTextureSize.y);
|
||||
vec2 sine_comp = vec2(SCANLINE_SINE_COMP_A, SCANLINE_SINE_COMP_B);
|
||||
vec3 res = frame.xyz;
|
||||
#ifdef ROTATE_SCANLINES
|
||||
sine_comp = sine_comp.yx;
|
||||
omega = omega.yx;
|
||||
#endif
|
||||
vec3 scanline = res * (SCANLINE_BASE_BRIGHTNESS + dot(sine_comp * sin(coord * omega), vec2(1.0, 1.0)));
|
||||
|
||||
return vec4(scanline.x, scanline.y, scanline.z, 1.0);
|
||||
#else
|
||||
return frame;
|
||||
#endif
|
||||
}
|
||||
|
||||
#ifdef CURVATURE
|
||||
// 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
|
||||
|
||||
#if defined MASK && !defined ROTATE_SCANLINES
|
||||
// Shadow mask.
|
||||
vec4 Mask(vec2 pos)
|
||||
{
|
||||
vec3 mask = vec3(maskDark, maskDark, maskDark);
|
||||
|
||||
// Very compressed TV style shadow mask.
|
||||
if (shadowMask == 1.0)
|
||||
{
|
||||
float line = maskLight;
|
||||
float odd = 0.0;
|
||||
|
||||
if (fract(pos.x*0.166666666) < 0.5) odd = 1.0;
|
||||
if (fract((pos.y + odd) * 0.5) < 0.5) line = maskDark;
|
||||
|
||||
pos.x = fract(pos.x*0.333333333);
|
||||
|
||||
if (pos.x < 0.333) mask.r = maskLight;
|
||||
else if (pos.x < 0.666) mask.g = maskLight;
|
||||
else mask.b = maskLight;
|
||||
mask*=line;
|
||||
}
|
||||
|
||||
// Aperture-grille.
|
||||
else if (shadowMask == 2.0)
|
||||
{
|
||||
pos.x = fract(pos.x*0.333333333);
|
||||
|
||||
if (pos.x < 0.333) mask.r = maskLight;
|
||||
else if (pos.x < 0.666) mask.g = maskLight;
|
||||
else mask.b = maskLight;
|
||||
}
|
||||
#ifdef EXTRA_MASKS
|
||||
// These can cause moire with curvature and scanlines
|
||||
// so they're an easy target for freeing up registers
|
||||
|
||||
// Stretched VGA style shadow mask (same as prior shaders).
|
||||
else if (shadowMask == 3.0)
|
||||
{
|
||||
pos.x += pos.y*3.0;
|
||||
pos.x = fract(pos.x*0.166666666);
|
||||
|
||||
if (pos.x < 0.333) mask.r = maskLight;
|
||||
else if (pos.x < 0.666) mask.g = maskLight;
|
||||
else mask.b = maskLight;
|
||||
}
|
||||
|
||||
// VGA style shadow mask.
|
||||
else if (shadowMask == 4.0)
|
||||
{
|
||||
pos.xy = floor(pos.xy*vec2(1.0, 0.5));
|
||||
pos.x += pos.y*3.0;
|
||||
pos.x = fract(pos.x*0.166666666);
|
||||
|
||||
if (pos.x < 0.333) mask.r = maskLight;
|
||||
else if (pos.x < 0.666) mask.g = maskLight;
|
||||
else mask.b = maskLight;
|
||||
}
|
||||
#endif
|
||||
|
||||
else mask = vec3(1.,1.,1.);
|
||||
|
||||
return vec4(mask, 1.0);
|
||||
}
|
||||
#endif
|
||||
|
||||
void main()
|
||||
{
|
||||
#ifdef CURVATURE
|
||||
vec2 pos = Warp(v_texCoord.xy*(rubyTextureSize.xy/rubyInputSize.xy))*(rubyInputSize.xy/rubyTextureSize.xy);
|
||||
#else
|
||||
vec2 pos = v_texCoord.xy;
|
||||
#endif
|
||||
|
||||
#if defined MASK && !defined ROTATE_SCANLINES
|
||||
// mask effects look bad unless applied in linear gamma space
|
||||
vec4 in_gamma = vec4(monitor_gamma, monitor_gamma, monitor_gamma, 1.0);
|
||||
vec4 out_gamma = vec4(1.0 / crt_gamma, 1.0 / crt_gamma, 1.0 / crt_gamma, 1.0);
|
||||
vec4 res = pow(BL_TEXTURE(Source, pos), in_gamma);
|
||||
#else
|
||||
vec4 res = BL_TEXTURE(Source, pos);
|
||||
#endif
|
||||
|
||||
#if defined MASK && !defined ROTATE_SCANLINES
|
||||
// apply the mask; looks bad with vert scanlines so make them mutually exclusive
|
||||
res *= Mask(gl_FragCoord.xy * 1.0001);
|
||||
#endif
|
||||
|
||||
#if defined CURVATURE && defined GL_ES
|
||||
// hacky clamp fix for GLES
|
||||
vec2 bordertest = (pos);
|
||||
if ( bordertest.x > 0.0001 && bordertest.x < 0.9999 && bordertest.y > 0.0001 && bordertest.y < 0.9999)
|
||||
res = res;
|
||||
else
|
||||
res = vec4(0.,0.,0.,0.);
|
||||
#endif
|
||||
|
||||
#if defined MASK && !defined ROTATE_SCANLINES
|
||||
// re-apply the gamma curve for the mask path
|
||||
FragColor = pow(scanline(pos, res), out_gamma);
|
||||
#else
|
||||
FragColor = scanline(pos, res);
|
||||
#endif
|
||||
}
|
||||
#endif
|
51
contrib/glshaders/glshaders.txt
Normal file
51
contrib/glshaders/glshaders.txt
Normal file
@@ -0,0 +1,51 @@
|
||||
# A few GLSL shaders for DOSBox-X
|
||||
|
||||
DOSBox-X supports OpenGL (GLSL) shaders. In order to get these shaders working, you will need to make the following changes to the configuration file (dosbox-x.conf by default):
|
||||
|
||||
[sdl]
|
||||
fullresolution = desktop
|
||||
output = opengl / openglnb
|
||||
|
||||
[render]
|
||||
scaler = none
|
||||
glshader = [name of .glsl file]
|
||||
|
||||
DOSBox-X currently includes two OpenGL outputs (`opengl` and `openglnb`).`opengl` enables bilinear filtering of the input source, while `openglnb` disables bilinear filtering and uses nearest neighbour scaling instead. Both built-in GLSL shaders (including advinterp2x, advinterp3x, advmame2x, advmame3x, rgb2x, rgb3x, scan2x, scan3x, tv2x, tv3x, sharp) and GLSL shader files can be used.
|
||||
|
||||
The table below provides a summary of which `output` setting to use for each shader:
|
||||
|
||||
|shader name|output setting to use|
|
||||
|-----------|---------------------|
|
||||
|crt-aperture.glsl|openglnb|
|
||||
|crt-caligari.glsl|openglnb|
|
||||
|crt-easymode.glsl|openglnb|
|
||||
|crt-easymode.tweaked.glsl|openglnb|
|
||||
|crt-geom.glsl|openglnb|
|
||||
|crt-geom.tweaked.glsl|openglnb|
|
||||
|crt-hyllian.glsl|openglnb|
|
||||
|crt-lottes-fast.glsl|opengl|
|
||||
|crt-lottes.glsl|openglnb|
|
||||
|crt-lottes.tweaked.glsl|openglnb|
|
||||
|crt-nes-mini.glsl|either|
|
||||
|crt-pi.glsl|opengl|
|
||||
|fakelottes.glsl|opengl|
|
||||
|fakelottes.tweaked.glsl|opengl|
|
||||
|ScanLine.glsl|openglnb|
|
||||
|yee64.glsl|either|
|
||||
|yeetron.glsl|openglnb|
|
||||
|zfast_crt.glsl|opengl|
|
||||
|pixellate.glsl|openglnb|
|
||||
|pixel_perfect.glsl|openglnb|
|
||||
|
||||
Several of the included shaders have been modified to produce consistent results, regardless of the output which is used however by setting the correct output settings as shown above, the built-in filtering will be used, which could improve the performance of the shader.
|
||||
|
||||
The window size will not increase automatically, so you will need to manually set the window resolution or switch to full screen. If the full screen resolution option is not set to `desktop`, the image will be stretched and filtered.
|
||||
|
||||
Shaders can be copied to the DOSBox-X root directory, or alternatively to the `glshaders` subdirectory in the DOSBox-X configuration directory. The shader can be referenced by the filename, without the .glsl extension. If the shader fails to load, or does not compile correctly, an error/warning message can be seen in the DOSBox-X output window.
|
||||
|
||||
Thanks to [Delfino Furioso](https://www.vogons.org/viewtopic.php?f=32&t=72697) for porting/tweaking many of the CRT shaders. He has the following recommendations:
|
||||
- fakelottes for game resolutions up to 640x480
|
||||
- easymode for game resolutions over 640x480
|
||||
- geom as a 'jack of all trades' for all resolutions
|
||||
|
||||
The tweaked versions mainly reduce the curvature effect and brighten the image.
|
257
contrib/glshaders/pixel_perfect-scanlines.glsl
Normal file
257
contrib/glshaders/pixel_perfect-scanlines.glsl
Normal file
@@ -0,0 +1,257 @@
|
||||
#version 120
|
||||
|
||||
// Developed by tyrells
|
||||
// Based on Marat Tanalin's algorithm: https://tanalin.com/en/articles/integer-scaling/
|
||||
|
||||
// includes scanline code from https://github.com/libretro/glsl-shaders/blob/master/scanlines/shaders/scanline.glsl
|
||||
|
||||
uniform vec2 rubyInputSize;
|
||||
|
||||
#if defined(VERTEX)
|
||||
|
||||
#if __VERSION__ >= 130
|
||||
#define COMPAT_VARYING out
|
||||
#define COMPAT_ATTRIBUTE in
|
||||
#define COMPAT_TEXTURE texture
|
||||
#else
|
||||
#define COMPAT_VARYING varying
|
||||
#define COMPAT_ATTRIBUTE attribute
|
||||
#define COMPAT_TEXTURE texture2D
|
||||
#endif
|
||||
|
||||
#ifdef GL_ES
|
||||
#define COMPAT_PRECISION mediump
|
||||
#else
|
||||
#define COMPAT_PRECISION
|
||||
#endif
|
||||
|
||||
const vec2 targetAspectRatio = vec2(4.0, 3.0);
|
||||
|
||||
uniform vec2 rubyOutputSize;
|
||||
uniform vec2 rubyTextureSize;
|
||||
|
||||
COMPAT_ATTRIBUTE vec4 a_position;
|
||||
COMPAT_VARYING vec2 outCoord;
|
||||
|
||||
vec2 calculateScalingRatio(vec2 screenSize, vec2 imageSize, vec2 targetAspectRatio)
|
||||
{
|
||||
float _TargetAspectRatio = targetAspectRatio.x / targetAspectRatio.y;
|
||||
float imageAspectRatio = imageSize.x / imageSize.y;
|
||||
|
||||
vec2 maxIntRatio = floor(screenSize / imageSize);
|
||||
|
||||
if (imageAspectRatio == _TargetAspectRatio)
|
||||
{
|
||||
float ratio = max(min(maxIntRatio.x, maxIntRatio.y), 1.0f);
|
||||
return vec2(ratio);
|
||||
}
|
||||
|
||||
vec2 maxOutputSize = imageSize * maxIntRatio;
|
||||
float maxAspectRatio = maxOutputSize.x / maxOutputSize.y;
|
||||
vec2 scalingRatio = vec2(0.0, 0.0);
|
||||
// If the ratio MA is lower than the target aspect ratio TA
|
||||
if (maxAspectRatio < _TargetAspectRatio)
|
||||
{
|
||||
scalingRatio.x = maxIntRatio.x;
|
||||
float AUH = maxOutputSize.x / _TargetAspectRatio;
|
||||
|
||||
float yUpperScaleFactor = ceil(AUH / imageSize.y);
|
||||
float yLowerScaleFactor = floor(AUH / imageSize.y);
|
||||
|
||||
float upperAspectRatio = maxOutputSize.x / (yUpperScaleFactor * imageSize.y);
|
||||
float lowerAspectRatio = maxOutputSize.x / (yLowerScaleFactor * imageSize.y);
|
||||
|
||||
float upperTargetError = abs(_TargetAspectRatio - upperAspectRatio);
|
||||
float lowerTargetError = abs(_TargetAspectRatio - lowerAspectRatio);
|
||||
|
||||
if (abs(upperTargetError - lowerTargetError) < 0.001)
|
||||
{
|
||||
float upperImageError = abs(imageAspectRatio - upperAspectRatio);
|
||||
float lowerImageError = abs(imageAspectRatio - lowerAspectRatio);
|
||||
if (upperImageError < lowerImageError)
|
||||
scalingRatio.y = yUpperScaleFactor;
|
||||
else
|
||||
scalingRatio.y = yLowerScaleFactor;
|
||||
}
|
||||
// Added an extra check in here to prefer an aspect ratio above 1.0.
|
||||
// TODO: This will need to be looked at again for aspect ratios other than 4:3
|
||||
else if (lowerTargetError < upperTargetError || upperAspectRatio < 1.0)
|
||||
scalingRatio.y = yLowerScaleFactor;
|
||||
else
|
||||
scalingRatio.y = yUpperScaleFactor;
|
||||
}
|
||||
// If the ratio MA is greater than the target aspect ratio TA
|
||||
else if (maxAspectRatio > _TargetAspectRatio)
|
||||
{
|
||||
scalingRatio.y = maxIntRatio.y;
|
||||
float AUW = maxOutputSize.y * _TargetAspectRatio;
|
||||
|
||||
float xUpperScaleFactor = ceil(AUW / imageSize.x);
|
||||
float xLowerScaleFactor = floor(AUW / imageSize.x);
|
||||
|
||||
float upperAspectRatio = (xUpperScaleFactor * imageSize.x) / maxOutputSize.y;
|
||||
float lowerAspectRatio = (xLowerScaleFactor * imageSize.x) / maxOutputSize.y;
|
||||
|
||||
float upperTargetError = abs(_TargetAspectRatio - upperAspectRatio);
|
||||
float lowerTargetError = abs(_TargetAspectRatio - lowerAspectRatio);
|
||||
|
||||
if (abs(upperTargetError - lowerTargetError) < 0.001)
|
||||
{
|
||||
float upperImageError = abs(imageAspectRatio - upperAspectRatio);
|
||||
float lowerImageError = abs(imageAspectRatio - lowerAspectRatio);
|
||||
if (upperImageError < lowerImageError)
|
||||
scalingRatio.x = xUpperScaleFactor;
|
||||
else
|
||||
scalingRatio.x = xLowerScaleFactor;
|
||||
}
|
||||
// Added an extra check in here to prefer an aspect ratio above 1.0.
|
||||
// TODO: This will need to be looked at again for aspect ratios other than 4:3
|
||||
else if (upperTargetError < lowerTargetError || lowerAspectRatio < 1.0)
|
||||
scalingRatio.x = xUpperScaleFactor;
|
||||
else
|
||||
scalingRatio.x = xLowerScaleFactor;
|
||||
}
|
||||
// If the ratio MA is equal to the target aspect ratio TA
|
||||
else
|
||||
scalingRatio = maxIntRatio;
|
||||
|
||||
if (scalingRatio.x < 1.0)
|
||||
scalingRatio.x = 1.0;
|
||||
if (scalingRatio.y < 1.0)
|
||||
scalingRatio.y = 1.0;
|
||||
|
||||
return scalingRatio;
|
||||
}
|
||||
|
||||
COMPAT_VARYING vec2 omega;
|
||||
COMPAT_VARYING vec2 v_texCoord;
|
||||
|
||||
void main()
|
||||
{
|
||||
gl_Position = a_position;
|
||||
|
||||
//vec2 box_scale = vec2(5.0, 6.0);
|
||||
vec2 box_scale = calculateScalingRatio(rubyOutputSize, rubyInputSize, targetAspectRatio);
|
||||
vec2 scale = (rubyOutputSize / rubyInputSize) / box_scale;
|
||||
vec2 middle = vec2(0.5);
|
||||
vec2 TexCoord = vec2(a_position.x + 1.0, 1.0 - a_position.y) / 2.0;
|
||||
vec2 diff = (TexCoord - middle) * scale;
|
||||
|
||||
outCoord = middle + diff;
|
||||
|
||||
#define pi 3.141592654
|
||||
|
||||
omega = vec2(pi * rubyOutputSize.x * rubyTextureSize.x / rubyInputSize.x, 2.0 * pi * rubyTextureSize.y);
|
||||
|
||||
v_texCoord = outCoord * rubyInputSize / rubyTextureSize;
|
||||
}
|
||||
|
||||
#elif defined(FRAGMENT)
|
||||
|
||||
#if __VERSION__ >= 130
|
||||
#define COMPAT_VARYING in
|
||||
#define COMPAT_TEXTURE texture
|
||||
out vec4 FragColor;
|
||||
#else
|
||||
#define COMPAT_VARYING varying
|
||||
#define FragColor gl_FragColor
|
||||
#define COMPAT_TEXTURE texture2D
|
||||
#endif
|
||||
|
||||
#ifdef GL_ES
|
||||
#ifdef GL_FRAGMENT_PRECISION_HIGH
|
||||
precision highp float;
|
||||
#else
|
||||
precision mediump float;
|
||||
#endif
|
||||
#define COMPAT_PRECISION highp
|
||||
#else
|
||||
#define COMPAT_PRECISION
|
||||
#endif
|
||||
|
||||
uniform sampler2D rubyTexture;
|
||||
uniform vec2 rubyTextureSize;
|
||||
|
||||
/*
|
||||
The following code allows the shader to override any texture filtering
|
||||
configured in DOSBox. if 'output' is set to 'opengl', bilinear filtering
|
||||
will be enabled and OPENGLNB will not be defined, if 'output' is set to
|
||||
'openglnb', nearest neighbour filtering will be enabled and OPENGLNB will
|
||||
be defined.
|
||||
|
||||
If you wish to use the default filtering method that is currently enabled
|
||||
in DOSBox, use COMPAT_TEXTURE to lookup a texel from the input texture.
|
||||
|
||||
If you wish to force nearest-neighbor interpolation use NN_TEXTURE.
|
||||
|
||||
If you wish to force bilinear interpolation use BL_TEXTURE.
|
||||
|
||||
If DOSBox is configured to use the filtering method that is being forced,
|
||||
the default hardware implementation will be used, otherwise the custom
|
||||
implementations below will be used instead.
|
||||
|
||||
These custom implemenations rely on the `rubyTextureSize` uniform variable.
|
||||
The code could calculate the texture size from the sampler using the
|
||||
textureSize() GLSL function, but this would require a minimum of GLSL
|
||||
version 130, which may prevent the shader from working on older systems.
|
||||
*/
|
||||
|
||||
#if defined(OPENGLNB)
|
||||
#define NN_TEXTURE COMPAT_TEXTURE
|
||||
#define BL_TEXTURE blTexture
|
||||
vec4 blTexture(in sampler2D sampler, in vec2 uv)
|
||||
{
|
||||
// subtract 0.5 here and add it again after the floor to centre the texel
|
||||
vec2 texCoord = uv * rubyTextureSize - vec2(0.5);
|
||||
vec2 s0t0 = floor(texCoord) + vec2(0.5);
|
||||
vec2 s0t1 = s0t0 + vec2(0.0, 1.0);
|
||||
vec2 s1t0 = s0t0 + vec2(1.0, 0.0);
|
||||
vec2 s1t1 = s0t0 + vec2(1.0);
|
||||
|
||||
vec2 invTexSize = 1.0 / rubyTextureSize;
|
||||
vec4 c_s0t0 = COMPAT_TEXTURE(sampler, s0t0 * invTexSize);
|
||||
vec4 c_s0t1 = COMPAT_TEXTURE(sampler, s0t1 * invTexSize);
|
||||
vec4 c_s1t0 = COMPAT_TEXTURE(sampler, s1t0 * invTexSize);
|
||||
vec4 c_s1t1 = COMPAT_TEXTURE(sampler, s1t1 * invTexSize);
|
||||
|
||||
vec2 weight = fract(texCoord);
|
||||
|
||||
vec4 c0 = c_s0t0 + (c_s1t0 - c_s0t0) * weight.x;
|
||||
vec4 c1 = c_s0t1 + (c_s1t1 - c_s0t1) * weight.x;
|
||||
|
||||
return (c0 + (c1 - c0) * weight.y);
|
||||
}
|
||||
#else
|
||||
#define BL_TEXTURE COMPAT_TEXTURE
|
||||
#define NN_TEXTURE nnTexture
|
||||
vec4 nnTexture(in sampler2D sampler, in vec2 uv)
|
||||
{
|
||||
vec2 texCoord = floor(uv * rubyTextureSize) + vec2(0.5);
|
||||
vec2 invTexSize = 1.0 / rubyTextureSize;
|
||||
return COMPAT_TEXTURE(sampler, texCoord * invTexSize);
|
||||
}
|
||||
#endif
|
||||
|
||||
COMPAT_VARYING vec2 outCoord;
|
||||
|
||||
const float SCANLINE_BASE_BRIGHTNESS = 0.95;
|
||||
const float SCANLINE_SINE_COMP_A = 0.05;
|
||||
const float SCANLINE_SINE_COMP_B = 0.15;
|
||||
|
||||
COMPAT_VARYING vec2 omega;
|
||||
COMPAT_VARYING vec2 v_texCoord;
|
||||
|
||||
void main()
|
||||
{
|
||||
vec2 sine_comp = vec2(SCANLINE_SINE_COMP_A, SCANLINE_SINE_COMP_B);
|
||||
vec3 res = NN_TEXTURE(rubyTexture, v_texCoord).xyz;
|
||||
vec3 scanline = res * (SCANLINE_BASE_BRIGHTNESS + dot(sine_comp * sin(v_texCoord * omega), vec2(1.0, 1.0)));
|
||||
|
||||
if ( outCoord.x >= 0.0 && outCoord.x <= 1.0 && outCoord.y >= 0.0 && outCoord.y <= 1.0)
|
||||
FragColor = vec4(scanline.x, scanline.y, scanline.z, 1.0);
|
||||
else
|
||||
// Can change the background filler colour below
|
||||
FragColor = vec4(0.0, 0.0, 0.0, 1.0);
|
||||
}
|
||||
|
||||
#endif
|
235
contrib/glshaders/pixel_perfect.glsl
Normal file
235
contrib/glshaders/pixel_perfect.glsl
Normal file
@@ -0,0 +1,235 @@
|
||||
#version 120
|
||||
|
||||
// Developed by tyrells
|
||||
// Based on Marat Tanalin's algorithm: https://tanalin.com/en/articles/integer-scaling/
|
||||
|
||||
uniform vec2 rubyInputSize;
|
||||
|
||||
#if defined(VERTEX)
|
||||
|
||||
#if __VERSION__ >= 130
|
||||
#define COMPAT_VARYING out
|
||||
#define COMPAT_ATTRIBUTE in
|
||||
#define COMPAT_TEXTURE texture
|
||||
#else
|
||||
#define COMPAT_VARYING varying
|
||||
#define COMPAT_ATTRIBUTE attribute
|
||||
#define COMPAT_TEXTURE texture2D
|
||||
#endif
|
||||
|
||||
#ifdef GL_ES
|
||||
#define COMPAT_PRECISION mediump
|
||||
#else
|
||||
#define COMPAT_PRECISION
|
||||
#endif
|
||||
|
||||
const vec2 targetAspectRatio = vec2(4.0, 3.0);
|
||||
|
||||
uniform vec2 rubyOutputSize;
|
||||
|
||||
COMPAT_ATTRIBUTE vec4 a_position;
|
||||
COMPAT_VARYING vec2 outCoord;
|
||||
|
||||
vec2 calculateScalingRatio(vec2 screenSize, vec2 imageSize, vec2 targetAspectRatio)
|
||||
{
|
||||
float _TargetAspectRatio = targetAspectRatio.x / targetAspectRatio.y;
|
||||
float imageAspectRatio = imageSize.x / imageSize.y;
|
||||
|
||||
vec2 maxIntRatio = floor(screenSize / imageSize);
|
||||
|
||||
if (imageAspectRatio == _TargetAspectRatio)
|
||||
{
|
||||
float ratio = max(min(maxIntRatio.x, maxIntRatio.y), 1.0f);
|
||||
return vec2(ratio);
|
||||
}
|
||||
|
||||
vec2 maxOutputSize = imageSize * maxIntRatio;
|
||||
float maxAspectRatio = maxOutputSize.x / maxOutputSize.y;
|
||||
vec2 scalingRatio = vec2(0.0, 0.0);
|
||||
// If the ratio MA is lower than the target aspect ratio TA
|
||||
if (maxAspectRatio < _TargetAspectRatio)
|
||||
{
|
||||
scalingRatio.x = maxIntRatio.x;
|
||||
float AUH = maxOutputSize.x / _TargetAspectRatio;
|
||||
|
||||
float yUpperScaleFactor = ceil(AUH / imageSize.y);
|
||||
float yLowerScaleFactor = floor(AUH / imageSize.y);
|
||||
|
||||
float upperAspectRatio = maxOutputSize.x / (yUpperScaleFactor * imageSize.y);
|
||||
float lowerAspectRatio = maxOutputSize.x / (yLowerScaleFactor * imageSize.y);
|
||||
|
||||
float upperTargetError = abs(_TargetAspectRatio - upperAspectRatio);
|
||||
float lowerTargetError = abs(_TargetAspectRatio - lowerAspectRatio);
|
||||
|
||||
if (abs(upperTargetError - lowerTargetError) < 0.001)
|
||||
{
|
||||
float upperImageError = abs(imageAspectRatio - upperAspectRatio);
|
||||
float lowerImageError = abs(imageAspectRatio - lowerAspectRatio);
|
||||
if (upperImageError < lowerImageError)
|
||||
scalingRatio.y = yUpperScaleFactor;
|
||||
else
|
||||
scalingRatio.y = yLowerScaleFactor;
|
||||
}
|
||||
// Added an extra check in here to prefer an aspect ratio above 1.0.
|
||||
// TODO: This will need to be looked at again for aspect ratios other than 4:3
|
||||
else if (lowerTargetError < upperTargetError || upperAspectRatio < 1.0)
|
||||
scalingRatio.y = yLowerScaleFactor;
|
||||
else
|
||||
scalingRatio.y = yUpperScaleFactor;
|
||||
}
|
||||
// If the ratio MA is greater than the target aspect ratio TA
|
||||
else if (maxAspectRatio > _TargetAspectRatio)
|
||||
{
|
||||
scalingRatio.y = maxIntRatio.y;
|
||||
float AUW = maxOutputSize.y * _TargetAspectRatio;
|
||||
|
||||
float xUpperScaleFactor = ceil(AUW / imageSize.x);
|
||||
float xLowerScaleFactor = floor(AUW / imageSize.x);
|
||||
|
||||
float upperAspectRatio = (xUpperScaleFactor * imageSize.x) / maxOutputSize.y;
|
||||
float lowerAspectRatio = (xLowerScaleFactor * imageSize.x) / maxOutputSize.y;
|
||||
|
||||
float upperTargetError = abs(_TargetAspectRatio - upperAspectRatio);
|
||||
float lowerTargetError = abs(_TargetAspectRatio - lowerAspectRatio);
|
||||
|
||||
if (abs(upperTargetError - lowerTargetError) < 0.001)
|
||||
{
|
||||
float upperImageError = abs(imageAspectRatio - upperAspectRatio);
|
||||
float lowerImageError = abs(imageAspectRatio - lowerAspectRatio);
|
||||
if (upperImageError < lowerImageError)
|
||||
scalingRatio.x = xUpperScaleFactor;
|
||||
else
|
||||
scalingRatio.x = xLowerScaleFactor;
|
||||
}
|
||||
// Added an extra check in here to prefer an aspect ratio above 1.0.
|
||||
// TODO: This will need to be looked at again for aspect ratios other than 4:3
|
||||
else if (upperTargetError < lowerTargetError || lowerAspectRatio < 1.0)
|
||||
scalingRatio.x = xUpperScaleFactor;
|
||||
else
|
||||
scalingRatio.x = xLowerScaleFactor;
|
||||
}
|
||||
// If the ratio MA is equal to the target aspect ratio TA
|
||||
else
|
||||
scalingRatio = maxIntRatio;
|
||||
|
||||
if (scalingRatio.x < 1.0)
|
||||
scalingRatio.x = 1.0;
|
||||
if (scalingRatio.y < 1.0)
|
||||
scalingRatio.y = 1.0;
|
||||
|
||||
return scalingRatio;
|
||||
}
|
||||
|
||||
void main()
|
||||
{
|
||||
gl_Position = a_position;
|
||||
|
||||
//vec2 box_scale = vec2(5.0, 6.0);
|
||||
vec2 box_scale = calculateScalingRatio(rubyOutputSize, rubyInputSize, targetAspectRatio);
|
||||
vec2 scale = (rubyOutputSize / rubyInputSize) / box_scale;
|
||||
vec2 middle = vec2(0.5);
|
||||
vec2 TexCoord = vec2(a_position.x + 1.0, 1.0 - a_position.y) / 2.0;
|
||||
vec2 diff = (TexCoord - middle) * scale;
|
||||
|
||||
outCoord = middle + diff;
|
||||
}
|
||||
|
||||
#elif defined(FRAGMENT)
|
||||
|
||||
#if __VERSION__ >= 130
|
||||
#define COMPAT_VARYING in
|
||||
#define COMPAT_TEXTURE texture
|
||||
out vec4 FragColor;
|
||||
#else
|
||||
#define COMPAT_VARYING varying
|
||||
#define FragColor gl_FragColor
|
||||
#define COMPAT_TEXTURE texture2D
|
||||
#endif
|
||||
|
||||
#ifdef GL_ES
|
||||
#ifdef GL_FRAGMENT_PRECISION_HIGH
|
||||
precision highp float;
|
||||
#else
|
||||
precision mediump float;
|
||||
#endif
|
||||
#define COMPAT_PRECISION highp
|
||||
#else
|
||||
#define COMPAT_PRECISION
|
||||
#endif
|
||||
|
||||
uniform sampler2D rubyTexture;
|
||||
uniform vec2 rubyTextureSize;
|
||||
|
||||
/*
|
||||
The following code allows the shader to override any texture filtering
|
||||
configured in DOSBox. if 'output' is set to 'opengl', bilinear filtering
|
||||
will be enabled and OPENGLNB will not be defined, if 'output' is set to
|
||||
'openglnb', nearest neighbour filtering will be enabled and OPENGLNB will
|
||||
be defined.
|
||||
|
||||
If you wish to use the default filtering method that is currently enabled
|
||||
in DOSBox, use COMPAT_TEXTURE to lookup a texel from the input texture.
|
||||
|
||||
If you wish to force nearest-neighbor interpolation use NN_TEXTURE.
|
||||
|
||||
If you wish to force bilinear interpolation use BL_TEXTURE.
|
||||
|
||||
If DOSBox is configured to use the filtering method that is being forced,
|
||||
the default hardware implementation will be used, otherwise the custom
|
||||
implementations below will be used instead.
|
||||
|
||||
These custom implemenations rely on the `rubyTextureSize` uniform variable.
|
||||
The code could calculate the texture size from the sampler using the
|
||||
textureSize() GLSL function, but this would require a minimum of GLSL
|
||||
version 130, which may prevent the shader from working on older systems.
|
||||
*/
|
||||
|
||||
#if defined(OPENGLNB)
|
||||
#define NN_TEXTURE COMPAT_TEXTURE
|
||||
#define BL_TEXTURE blTexture
|
||||
vec4 blTexture(in sampler2D sampler, in vec2 uv)
|
||||
{
|
||||
// subtract 0.5 here and add it again after the floor to centre the texel
|
||||
vec2 texCoord = uv * rubyTextureSize - vec2(0.5);
|
||||
vec2 s0t0 = floor(texCoord) + vec2(0.5);
|
||||
vec2 s0t1 = s0t0 + vec2(0.0, 1.0);
|
||||
vec2 s1t0 = s0t0 + vec2(1.0, 0.0);
|
||||
vec2 s1t1 = s0t0 + vec2(1.0);
|
||||
|
||||
vec2 invTexSize = 1.0 / rubyTextureSize;
|
||||
vec4 c_s0t0 = COMPAT_TEXTURE(sampler, s0t0 * invTexSize);
|
||||
vec4 c_s0t1 = COMPAT_TEXTURE(sampler, s0t1 * invTexSize);
|
||||
vec4 c_s1t0 = COMPAT_TEXTURE(sampler, s1t0 * invTexSize);
|
||||
vec4 c_s1t1 = COMPAT_TEXTURE(sampler, s1t1 * invTexSize);
|
||||
|
||||
vec2 weight = fract(texCoord);
|
||||
|
||||
vec4 c0 = c_s0t0 + (c_s1t0 - c_s0t0) * weight.x;
|
||||
vec4 c1 = c_s0t1 + (c_s1t1 - c_s0t1) * weight.x;
|
||||
|
||||
return (c0 + (c1 - c0) * weight.y);
|
||||
}
|
||||
#else
|
||||
#define BL_TEXTURE COMPAT_TEXTURE
|
||||
#define NN_TEXTURE nnTexture
|
||||
vec4 nnTexture(in sampler2D sampler, in vec2 uv)
|
||||
{
|
||||
vec2 texCoord = floor(uv * rubyTextureSize) + vec2(0.5);
|
||||
vec2 invTexSize = 1.0 / rubyTextureSize;
|
||||
return COMPAT_TEXTURE(sampler, texCoord * invTexSize);
|
||||
}
|
||||
#endif
|
||||
|
||||
COMPAT_VARYING vec2 outCoord;
|
||||
|
||||
void main()
|
||||
{
|
||||
vec4 outColor = NN_TEXTURE(rubyTexture, outCoord * rubyInputSize / rubyTextureSize);
|
||||
if ( outCoord.x >= 0.0 && outCoord.x <= 1.0 && outCoord.y >= 0.0 && outCoord.y <= 1.0)
|
||||
FragColor = outColor;
|
||||
else
|
||||
// Can change the background filler colour below
|
||||
FragColor = vec4(0.0, 0.0, 0.0, 1.0);
|
||||
}
|
||||
|
||||
#endif
|
128
contrib/glshaders/pixellate.glsl
Normal file
128
contrib/glshaders/pixellate.glsl
Normal file
@@ -0,0 +1,128 @@
|
||||
#version 120
|
||||
|
||||
// Pixellate Shader
|
||||
// Copyright (c) 2011, 2012 Fes
|
||||
// Permission to use, copy, modify, and/or distribute this software for any
|
||||
// purpose with or without fee is hereby granted, provided that the above
|
||||
// copyright notice and this permission notice appear in all copies.
|
||||
// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
// WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
// MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
|
||||
// SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
// WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
// ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR
|
||||
// IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
// (Fes gave their permission to have this shader distributed under this
|
||||
// licence in this forum post:
|
||||
// http://board.byuu.org/viewtopic.php?p=57295#p57295
|
||||
|
||||
#define INTERPOLATE_IN_LINEAR_GAMMA 1.0
|
||||
|
||||
uniform vec2 rubyTextureSize;
|
||||
uniform vec2 rubyInputSize;
|
||||
|
||||
#if defined(VERTEX)
|
||||
|
||||
#if __VERSION__ >= 130
|
||||
#define COMPAT_VARYING out
|
||||
#define COMPAT_ATTRIBUTE in
|
||||
#define COMPAT_TEXTURE texture
|
||||
#else
|
||||
#define COMPAT_VARYING varying
|
||||
#define COMPAT_ATTRIBUTE attribute
|
||||
#define COMPAT_TEXTURE texture2D
|
||||
#endif
|
||||
|
||||
#ifdef GL_ES
|
||||
#define COMPAT_PRECISION mediump
|
||||
#else
|
||||
#define COMPAT_PRECISION
|
||||
#endif
|
||||
|
||||
COMPAT_ATTRIBUTE vec4 a_position;
|
||||
COMPAT_VARYING vec2 v_texCoord;
|
||||
|
||||
void main()
|
||||
{
|
||||
gl_Position = a_position;
|
||||
v_texCoord = vec2(a_position.x + 1.0, 1.0 - a_position.y) / 2.0 * rubyInputSize / rubyTextureSize;
|
||||
}
|
||||
|
||||
#elif defined(FRAGMENT)
|
||||
|
||||
#if __VERSION__ >= 130
|
||||
#define COMPAT_VARYING in
|
||||
#define COMPAT_TEXTURE texture
|
||||
out vec4 FragColor;
|
||||
#else
|
||||
#define COMPAT_VARYING varying
|
||||
#define FragColor gl_FragColor
|
||||
#define COMPAT_TEXTURE texture2D
|
||||
#endif
|
||||
|
||||
#ifdef GL_ES
|
||||
#ifdef GL_FRAGMENT_PRECISION_HIGH
|
||||
precision highp float;
|
||||
#else
|
||||
precision mediump float;
|
||||
#endif
|
||||
#define COMPAT_PRECISION highp
|
||||
#else
|
||||
#define COMPAT_PRECISION
|
||||
#endif
|
||||
|
||||
COMPAT_VARYING vec2 v_texCoord;
|
||||
|
||||
uniform vec2 rubyOutputSize;
|
||||
uniform sampler2D rubyTexture;
|
||||
|
||||
#define OutputSize rubyOutputSize
|
||||
#define TextureSize rubyTextureSize
|
||||
#define InputSize rubyInputSize
|
||||
#define Texture rubyTexture
|
||||
#define TEX0 v_texCoord
|
||||
|
||||
// fragment compatibility #defines
|
||||
#define Source Texture
|
||||
#define vTexCoord TEX0.xy
|
||||
|
||||
#define SourceSize vec4(TextureSize, 1.0 / TextureSize) //either TextureSize or InputSize
|
||||
#define outsize vec4(OutputSize, 1.0 / OutputSize)
|
||||
|
||||
void main()
|
||||
{
|
||||
vec2 texelSize = SourceSize.zw;
|
||||
|
||||
vec2 range = vec2(abs(InputSize.x / (outsize.x * SourceSize.x)), abs(InputSize.y / (outsize.y * SourceSize.y)));
|
||||
range = range / 2.0 * 0.999;
|
||||
|
||||
float left = vTexCoord.x - range.x;
|
||||
float top = vTexCoord.y + range.y;
|
||||
float right = vTexCoord.x + range.x;
|
||||
float bottom = vTexCoord.y - range.y;
|
||||
|
||||
vec3 topLeftColor = COMPAT_TEXTURE(Source, (floor(vec2(left, top) / texelSize) + 0.5) * texelSize).rgb;
|
||||
vec3 bottomRightColor = COMPAT_TEXTURE(Source, (floor(vec2(right, bottom) / texelSize) + 0.5) * texelSize).rgb;
|
||||
vec3 bottomLeftColor = COMPAT_TEXTURE(Source, (floor(vec2(left, bottom) / texelSize) + 0.5) * texelSize).rgb;
|
||||
vec3 topRightColor = COMPAT_TEXTURE(Source, (floor(vec2(right, top) / texelSize) + 0.5) * texelSize).rgb;
|
||||
|
||||
if (INTERPOLATE_IN_LINEAR_GAMMA > 0.5){
|
||||
topLeftColor = pow(topLeftColor, vec3(2.2));
|
||||
bottomRightColor = pow(bottomRightColor, vec3(2.2));
|
||||
bottomLeftColor = pow(bottomLeftColor, vec3(2.2));
|
||||
topRightColor = pow(topRightColor, vec3(2.2));
|
||||
}
|
||||
|
||||
vec2 border = clamp(floor((vTexCoord / texelSize) + vec2(0.5)) * texelSize, vec2(left, bottom), vec2(right, top));
|
||||
|
||||
float totalArea = 4.0 * range.x * range.y;
|
||||
|
||||
vec3 averageColor;
|
||||
averageColor = ((border.x - left) * (top - border.y) / totalArea) * topLeftColor;
|
||||
averageColor += ((right - border.x) * (border.y - bottom) / totalArea) * bottomRightColor;
|
||||
averageColor += ((border.x - left) * (border.y - bottom) / totalArea) * bottomLeftColor;
|
||||
averageColor += ((right - border.x) * (top - border.y) / totalArea) * topRightColor;
|
||||
|
||||
FragColor = (INTERPOLATE_IN_LINEAR_GAMMA > 0.5) ? vec4(pow(averageColor, vec3(1.0 / 2.2)), 1.0) : vec4(averageColor, 1.0);
|
||||
}
|
||||
#endif
|
389
contrib/glshaders/xbr-lv2-3d.glsl
Normal file
389
contrib/glshaders/xbr-lv2-3d.glsl
Normal file
@@ -0,0 +1,389 @@
|
||||
#version 120
|
||||
|
||||
/*
|
||||
Hyllian's xBR-lv2 Shader
|
||||
|
||||
Copyright (C) 2011-2015 Hyllian - sergiogdb@gmail.com
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a
|
||||
copy of this software and associated documentation files (the
|
||||
"Software"), to deal in the Software without restriction, including
|
||||
without limitation the rights to use, copy, modify, merge, publish,
|
||||
distribute, sublicense, and/or sell copies of the Software, and to permit
|
||||
persons to whom the Software is furnished to do so, subject to the
|
||||
following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
DEALINGS IN THE SOFTWARE.
|
||||
|
||||
Incorporates some of the ideas from SABR shader. Thanks to Joshua Street.
|
||||
*/
|
||||
|
||||
#pragma parameter XBR_Y_WEIGHT "Y Weight" 48.0 0.0 100.0 1.0
|
||||
#pragma parameter XBR_EQ_THRESHOLD "Eq Threshold" 15.0 0.0 50.0 1.0
|
||||
#pragma parameter XBR_LV1_COEFFICIENT "Lv1 Coefficient" 0.5 0.0 30.0 0.5
|
||||
#pragma parameter XBR_LV2_COEFFICIENT "Lv2 Coefficient" 2.0 1.0 3.0 0.1
|
||||
#pragma parameter XBR_RES "Internal Res Multiplier" 2.0 1.0 8.0 1.0
|
||||
#pragma parameter XBR_SCALE "xBR Scale" 3.0 1.0 5.0 1.0
|
||||
|
||||
#define mul(a,b) (b*a)
|
||||
#define saturate(c) clamp(c, 0.0, 1.0)
|
||||
|
||||
#if defined(VERTEX)
|
||||
|
||||
#if __VERSION__ >= 130
|
||||
#define COMPAT_VARYING out
|
||||
#define COMPAT_ATTRIBUTE in
|
||||
#define COMPAT_TEXTURE texture
|
||||
#else
|
||||
#define COMPAT_VARYING varying
|
||||
#define COMPAT_ATTRIBUTE attribute
|
||||
#define COMPAT_TEXTURE texture2D
|
||||
#endif
|
||||
|
||||
#ifdef GL_ES
|
||||
#define COMPAT_PRECISION mediump
|
||||
#else
|
||||
#define COMPAT_PRECISION
|
||||
#endif
|
||||
|
||||
COMPAT_ATTRIBUTE vec4 VertexCoord;
|
||||
COMPAT_ATTRIBUTE vec4 TexCoord;
|
||||
|
||||
COMPAT_ATTRIBUTE vec4 a_position;
|
||||
COMPAT_VARYING vec2 v_texCoord;
|
||||
COMPAT_VARYING vec4 t1;
|
||||
|
||||
vec4 _oPosition1;
|
||||
uniform mat4 MVPMatrix;
|
||||
uniform COMPAT_PRECISION vec2 rubyOutputSize;
|
||||
uniform COMPAT_PRECISION vec2 rubyTextureSize;
|
||||
uniform COMPAT_PRECISION vec2 rubyInputSize;
|
||||
|
||||
// compatibility #defines
|
||||
#define vTexCoord v_texCoord
|
||||
#define SourceSize vec4(rubyTextureSize, 1.0 / rubyTextureSize) //either TextureSize or InputSize
|
||||
#define OutSize vec4(rubyOutputSize, 1.0 / rubyOutputSize)
|
||||
|
||||
#ifdef PARAMETER_UNIFORM
|
||||
uniform COMPAT_PRECISION float XBR_Y_WEIGHT;
|
||||
uniform COMPAT_PRECISION float XBR_EQ_THRESHOLD;
|
||||
uniform COMPAT_PRECISION float XBR_LV1_COEFFICIENT;
|
||||
uniform COMPAT_PRECISION float XBR_LV2_COEFFICIENT;
|
||||
uniform COMPAT_PRECISION float XBR_RES;
|
||||
uniform COMPAT_PRECISION float XBR_SCALE;
|
||||
#else
|
||||
#define XBR_Y_WEIGHT 48.0
|
||||
#define XBR_EQ_THRESHOLD 15.0
|
||||
#define XBR_LV1_COEFFICIENT 0.5
|
||||
#define XBR_LV2_COEFFICIENT 2.0
|
||||
#define XBR_RES 2.0
|
||||
#define XBR_SCALE 3.0
|
||||
#endif
|
||||
|
||||
void main()
|
||||
{
|
||||
gl_Position = a_position;
|
||||
v_texCoord.xy = vec2(a_position.x + 1.0, 1.0 - a_position.y) / 2.0 * rubyInputSize / rubyTextureSize;
|
||||
vec2 ps = XBR_RES/SourceSize.xy;
|
||||
float dx = ps.x;
|
||||
float dy = ps.y;
|
||||
|
||||
t1 = vec4( dx, 0, 0, dy); // F H
|
||||
}
|
||||
|
||||
#elif defined(FRAGMENT)
|
||||
|
||||
#if __VERSION__ >= 130
|
||||
#define COMPAT_VARYING in
|
||||
#define COMPAT_TEXTURE texture
|
||||
out vec4 FragColor;
|
||||
#else
|
||||
#define COMPAT_VARYING varying
|
||||
#define FragColor gl_FragColor
|
||||
#define COMPAT_TEXTURE texture2D
|
||||
#endif
|
||||
|
||||
#ifdef GL_ES
|
||||
#ifdef GL_FRAGMENT_PRECISION_HIGH
|
||||
precision highp float;
|
||||
#else
|
||||
precision mediump float;
|
||||
#endif
|
||||
#define COMPAT_PRECISION mediump
|
||||
#else
|
||||
#define COMPAT_PRECISION
|
||||
#endif
|
||||
|
||||
uniform COMPAT_PRECISION vec2 rubyOutputSize;
|
||||
uniform COMPAT_PRECISION vec2 rubyTextureSize;
|
||||
uniform COMPAT_PRECISION vec2 rubyInputSize;
|
||||
uniform sampler2D rubyTexture;
|
||||
COMPAT_VARYING vec2 v_texCoord;
|
||||
COMPAT_VARYING vec4 t1;
|
||||
|
||||
// compatibility #defines
|
||||
#define Source rubyTexture
|
||||
#define vTexCoord v_texCoord.xy
|
||||
|
||||
#define SourceSize vec4(rubyTextureSize, 1.0 / rubyTextureSize) //either TextureSize or InputSize
|
||||
#define OutSize vec4(rubyOutputSize, 1.0 / rubyOutputSize)
|
||||
|
||||
#ifdef PARAMETER_UNIFORM
|
||||
uniform COMPAT_PRECISION float XBR_Y_WEIGHT;
|
||||
uniform COMPAT_PRECISION float XBR_EQ_THRESHOLD;
|
||||
uniform COMPAT_PRECISION float XBR_LV1_COEFFICIENT;
|
||||
uniform COMPAT_PRECISION float XBR_LV2_COEFFICIENT;
|
||||
uniform COMPAT_PRECISION float XBR_RES;
|
||||
uniform COMPAT_PRECISION float XBR_SCALE;
|
||||
#else
|
||||
#define XBR_Y_WEIGHT 48.0
|
||||
#define XBR_EQ_THRESHOLD 15.0
|
||||
#define XBR_LV1_COEFFICIENT 0.5
|
||||
#define XBR_LV2_COEFFICIENT 2.0
|
||||
#define XBR_RES 2.0
|
||||
#define XBR_SCALE 3.0
|
||||
#endif
|
||||
|
||||
// Uncomment just one of the three params below to choose the corner detection
|
||||
//#define CORNER_A
|
||||
//#define CORNER_B
|
||||
#define CORNER_C
|
||||
//#define CORNER_D
|
||||
|
||||
#ifndef CORNER_A
|
||||
#define SMOOTH_TIPS
|
||||
#endif
|
||||
|
||||
#define lv2_cf XBR_LV2_COEFFICIENT
|
||||
|
||||
const float coef = 2.0;
|
||||
const vec3 rgbw = vec3(14.352, 28.176, 5.472);
|
||||
const vec4 eq_threshold = vec4(15.0, 15.0, 15.0, 15.0);
|
||||
|
||||
vec4 delta = vec4(1.0/XBR_SCALE, 1.0/XBR_SCALE, 1.0/XBR_SCALE, 1.0/XBR_SCALE);
|
||||
vec4 delta_l = vec4(0.5/XBR_SCALE, 1.0/XBR_SCALE, 0.5/XBR_SCALE, 1.0/XBR_SCALE);
|
||||
vec4 delta_u = delta_l.yxwz;
|
||||
|
||||
const vec4 Ao = vec4( 1.0, -1.0, -1.0, 1.0 );
|
||||
const vec4 Bo = vec4( 1.0, 1.0, -1.0,-1.0 );
|
||||
const vec4 Co = vec4( 1.5, 0.5, -0.5, 0.5 );
|
||||
const vec4 Ax = vec4( 1.0, -1.0, -1.0, 1.0 );
|
||||
const vec4 Bx = vec4( 0.5, 2.0, -0.5,-2.0 );
|
||||
const vec4 Cx = vec4( 1.0, 1.0, -0.5, 0.0 );
|
||||
const vec4 Ay = vec4( 1.0, -1.0, -1.0, 1.0 );
|
||||
const vec4 By = vec4( 2.0, 0.5, -2.0,-0.5 );
|
||||
const vec4 Cy = vec4( 2.0, 0.0, -1.0, 0.5 );
|
||||
const vec4 Ci = vec4(0.25, 0.25, 0.25, 0.25);
|
||||
|
||||
const vec3 Y = vec3(0.2126, 0.7152, 0.0722);
|
||||
|
||||
// Difference between vector components.
|
||||
vec4 df(vec4 A, vec4 B)
|
||||
{
|
||||
return vec4(abs(A-B));
|
||||
}
|
||||
|
||||
// Determine if two vector components are equal based on a threshold.
|
||||
bvec4 eq(vec4 A, vec4 B)
|
||||
{
|
||||
return (lessThan(df(A, B), vec4(XBR_EQ_THRESHOLD)));
|
||||
}
|
||||
|
||||
vec4 weighted_distance(vec4 a, vec4 b, vec4 c, vec4 d, vec4 e, vec4 f, vec4 g, vec4 h)
|
||||
{
|
||||
return (df(a,b) + df(a,c) + df(d,e) + df(d,f) + 4.0*df(g,h));
|
||||
}
|
||||
|
||||
float c_df(vec3 c1, vec3 c2)
|
||||
{
|
||||
vec3 df = abs(c1 - c2);
|
||||
return df.r + df.g + df.b;
|
||||
}
|
||||
|
||||
void main()
|
||||
{
|
||||
bvec4 edri, edr, edr_left, edr_up, px; // px = pixel, edr = edge detection rule
|
||||
bvec4 interp_restriction_lv0, interp_restriction_lv1, interp_restriction_lv2_left, interp_restriction_lv2_up, block_3d, block_3d_left, block_3d_up;
|
||||
vec4 fx, fx_left, fx_up; // inequations of straight lines.
|
||||
|
||||
vec4 delta = vec4(1.0/XBR_SCALE, 1.0/XBR_SCALE, 1.0/XBR_SCALE, 1.0/XBR_SCALE);
|
||||
vec4 deltaL = vec4(0.5/XBR_SCALE, 1.0/XBR_SCALE, 0.5/XBR_SCALE, 1.0/XBR_SCALE);
|
||||
vec4 deltaU = deltaL.yxwz;
|
||||
|
||||
vec2 fp = fract(vTexCoord*SourceSize.xy/XBR_RES);
|
||||
|
||||
vec2 tex = (floor(vTexCoord*SourceSize.xy/XBR_RES) + vec2(0.5, 0.5))*XBR_RES/SourceSize.xy;
|
||||
|
||||
vec2 dx = t1.xy;
|
||||
vec2 dy = t1.zw;
|
||||
|
||||
vec3 A = COMPAT_TEXTURE(Source, vTexCoord -dx -dy).xyz;
|
||||
vec3 B = COMPAT_TEXTURE(Source, vTexCoord -dy).xyz;
|
||||
vec3 C = COMPAT_TEXTURE(Source, vTexCoord +dx -dy).xyz;
|
||||
vec3 D = COMPAT_TEXTURE(Source, vTexCoord -dx ).xyz;
|
||||
vec3 E = COMPAT_TEXTURE(Source, vTexCoord ).xyz;
|
||||
vec3 F = COMPAT_TEXTURE(Source, vTexCoord +dx ).xyz;
|
||||
vec3 G = COMPAT_TEXTURE(Source, vTexCoord -dx +dy).xyz;
|
||||
vec3 H = COMPAT_TEXTURE(Source, vTexCoord +dy).xyz;
|
||||
vec3 I = COMPAT_TEXTURE(Source, vTexCoord +dx +dy).xyz;
|
||||
|
||||
vec3 A1 = COMPAT_TEXTURE(Source, vTexCoord -dx -2.0*dy).xyz;
|
||||
vec3 B1 = COMPAT_TEXTURE(Source, vTexCoord -2.0*dy).xyz;
|
||||
vec3 C1 = COMPAT_TEXTURE(Source, vTexCoord +dx -2.0*dy).xyz;
|
||||
vec3 G5 = COMPAT_TEXTURE(Source, vTexCoord -dx +2.0*dy).xyz;
|
||||
vec3 H5 = COMPAT_TEXTURE(Source, vTexCoord +2.0*dy).xyz;
|
||||
vec3 I5 = COMPAT_TEXTURE(Source, vTexCoord +dx +2.0*dy).xyz;
|
||||
vec3 A0 = COMPAT_TEXTURE(Source, vTexCoord -2.0*dx -dy).xyz;
|
||||
vec3 D0 = COMPAT_TEXTURE(Source, vTexCoord -2.0*dx ).xyz;
|
||||
vec3 G0 = COMPAT_TEXTURE(Source, vTexCoord -2.0*dx +dy).xyz;
|
||||
vec3 C4 = COMPAT_TEXTURE(Source, vTexCoord +2.0*dx -dy).xyz;
|
||||
vec3 F4 = COMPAT_TEXTURE(Source, vTexCoord +2.0*dx ).xyz;
|
||||
vec3 I4 = COMPAT_TEXTURE(Source, vTexCoord +2.0*dx +dy).xyz;
|
||||
|
||||
vec3 F6 = COMPAT_TEXTURE(Source, tex +dx+0.25*dx+0.25*dy).xyz;
|
||||
vec3 F7 = COMPAT_TEXTURE(Source, tex +dx+0.25*dx-0.25*dy).xyz;
|
||||
vec3 F8 = COMPAT_TEXTURE(Source, tex +dx-0.25*dx-0.25*dy).xyz;
|
||||
vec3 F9 = COMPAT_TEXTURE(Source, tex +dx-0.25*dx+0.25*dy).xyz;
|
||||
|
||||
vec3 B6 = COMPAT_TEXTURE(Source, tex +0.25*dx+0.25*dy-dy).xyz;
|
||||
vec3 B7 = COMPAT_TEXTURE(Source, tex +0.25*dx-0.25*dy-dy).xyz;
|
||||
vec3 B8 = COMPAT_TEXTURE(Source, tex -0.25*dx-0.25*dy-dy).xyz;
|
||||
vec3 B9 = COMPAT_TEXTURE(Source, tex -0.25*dx+0.25*dy-dy).xyz;
|
||||
|
||||
vec3 D6 = COMPAT_TEXTURE(Source, tex -dx+0.25*dx+0.25*dy).xyz;
|
||||
vec3 D7 = COMPAT_TEXTURE(Source, tex -dx+0.25*dx-0.25*dy).xyz;
|
||||
vec3 D8 = COMPAT_TEXTURE(Source, tex -dx-0.25*dx-0.25*dy).xyz;
|
||||
vec3 D9 = COMPAT_TEXTURE(Source, tex -dx-0.25*dx+0.25*dy).xyz;
|
||||
|
||||
vec3 H6 = COMPAT_TEXTURE(Source, tex +0.25*dx+0.25*dy+dy).xyz;
|
||||
vec3 H7 = COMPAT_TEXTURE(Source, tex +0.25*dx-0.25*dy+dy).xyz;
|
||||
vec3 H8 = COMPAT_TEXTURE(Source, tex -0.25*dx-0.25*dy+dy).xyz;
|
||||
vec3 H9 = COMPAT_TEXTURE(Source, tex -0.25*dx+0.25*dy+dy).xyz;
|
||||
|
||||
float y_weight = XBR_Y_WEIGHT;
|
||||
|
||||
vec4 b = mul( mat4x3(B, D, H, F), y_weight*Y );
|
||||
vec4 c = mul( mat4x3(C, A, G, I), y_weight*Y );
|
||||
vec4 e = mul( mat4x3(E, E, E, E), y_weight*Y );
|
||||
vec4 d = b.yzwx;
|
||||
vec4 f = b.wxyz;
|
||||
vec4 g = c.zwxy;
|
||||
vec4 h = b.zwxy;
|
||||
vec4 i = c.wxyz;
|
||||
|
||||
vec4 i4 = mul( mat4x3(I4, C1, A0, G5), y_weight*Y );
|
||||
vec4 i5 = mul( mat4x3(I5, C4, A1, G0), y_weight*Y );
|
||||
vec4 h5 = mul( mat4x3(H5, F4, B1, D0), y_weight*Y );
|
||||
vec4 f4 = h5.yzwx;
|
||||
|
||||
vec4 f0 = mul( mat4x3(F6, B6, D6, H6), y_weight*Y );
|
||||
vec4 f1 = mul( mat4x3(F7, B7, D7, H7), y_weight*Y );
|
||||
vec4 f2 = mul( mat4x3(F8, B8, D8, H8), y_weight*Y );
|
||||
vec4 f3 = mul( mat4x3(F9, B9, D9, H9), y_weight*Y );
|
||||
|
||||
vec4 h0 = f0.wxyz;
|
||||
vec4 h1 = f1.wxyz;
|
||||
vec4 h2 = f2.wxyz;
|
||||
vec4 h3 = f3.wxyz;
|
||||
|
||||
// These inequations define the line below which interpolation occurs.
|
||||
fx = (Ao*fp.y+Bo*fp.x);
|
||||
fx_left = (Ax*fp.y+Bx*fp.x);
|
||||
fx_up = (Ay*fp.y+By*fp.x);
|
||||
|
||||
block_3d.x = ((f0.x==f1.x && f1.x==f2.x && f2.x==f3.x) && (h0.x==h1.x && h1.x==h2.x && h2.x==h3.x));
|
||||
block_3d.y = ((f0.y==f1.y && f1.y==f2.y && f2.y==f3.y) && (h0.y==h1.y && h1.y==h2.y && h2.y==h3.y));
|
||||
block_3d.z = ((f0.z==f1.z && f1.z==f2.z && f2.z==f3.z) && (h0.z==h1.z && h1.z==h2.z && h2.z==h3.z));
|
||||
block_3d.w = ((f0.w==f1.w && f1.w==f2.w && f2.w==f3.w) && (h0.w==h1.w && h1.w==h2.w && h2.w==h3.w));
|
||||
interp_restriction_lv1.x = interp_restriction_lv0.x = ((e.x!=f.x) && (e.x!=h.x) && block_3d.x);
|
||||
interp_restriction_lv1.y = interp_restriction_lv0.y = ((e.y!=f.y) && (e.y!=h.y) && block_3d.y);
|
||||
interp_restriction_lv1.z = interp_restriction_lv0.z = ((e.z!=f.z) && (e.z!=h.z) && block_3d.z);
|
||||
interp_restriction_lv1.w = interp_restriction_lv0.w = ((e.w!=f.w) && (e.w!=h.w) && block_3d.w);
|
||||
|
||||
#ifdef CORNER_B
|
||||
interp_restriction_lv1 = (interp_restriction_lv0 && ( !eq(f,b) && !eq(h,d) || eq(e,i) && !eq(f,i4) && !eq(h,i5) || eq(e,g) || eq(e,c) ) );
|
||||
#endif
|
||||
#ifdef CORNER_D
|
||||
vec4 c1 = i4.yzwx;
|
||||
vec4 g0 = i5.wxyz;
|
||||
interp_restriction_lv1 = (interp_restriction_lv0 && ( !eq(f,b) && !eq(h,d) || eq(e,i) && !eq(f,i4) && !eq(h,i5) || eq(e,g) || eq(e,c) ) && (f!=f4 && f!=i || h!=h5 && h!=i || h!=g || f!=c || eq(b,c1) && eq(d,g0)));
|
||||
#endif
|
||||
#ifdef CORNER_C
|
||||
interp_restriction_lv1.x = (interp_restriction_lv0.x && ( !eq(f,b).x && !eq(f,c).x || !eq(h,d).x && !eq(h,g).x || eq(e,i).x && (!eq(f,f4).x && !eq(f,i4).x || !eq(h,h5).x && !eq(h,i5).x) || eq(e,g).x || eq(e,c).x) );
|
||||
interp_restriction_lv1.y = (interp_restriction_lv0.y && ( !eq(f,b).y && !eq(f,c).y || !eq(h,d).y && !eq(h,g).y || eq(e,i).y && (!eq(f,f4).y && !eq(f,i4).y || !eq(h,h5).y && !eq(h,i5).y) || eq(e,g).y || eq(e,c).y) );
|
||||
interp_restriction_lv1.z = (interp_restriction_lv0.z && ( !eq(f,b).z && !eq(f,c).z || !eq(h,d).z && !eq(h,g).z || eq(e,i).z && (!eq(f,f4).z && !eq(f,i4).z || !eq(h,h5).z && !eq(h,i5).z) || eq(e,g).z || eq(e,c).z) );
|
||||
interp_restriction_lv1.w = (interp_restriction_lv0.w && ( !eq(f,b).w && !eq(f,c).w || !eq(h,d).w && !eq(h,g).w || eq(e,i).w && (!eq(f,f4).w && !eq(f,i4).w || !eq(h,h5).w && !eq(h,i5).w) || eq(e,g).w || eq(e,c).w) );
|
||||
#endif
|
||||
|
||||
interp_restriction_lv2_left.x = ((e.x!=g.x) && (d.x!=g.x));
|
||||
interp_restriction_lv2_left.y = ((e.y!=g.y) && (d.y!=g.y));
|
||||
interp_restriction_lv2_left.z = ((e.z!=g.z) && (d.z!=g.z));
|
||||
interp_restriction_lv2_left.w = ((e.w!=g.w) && (d.w!=g.w));
|
||||
interp_restriction_lv2_up.x = ((e.x!=c.x) && (b.x!=c.x));
|
||||
interp_restriction_lv2_up.y = ((e.y!=c.y) && (b.y!=c.y));
|
||||
interp_restriction_lv2_up.z = ((e.z!=c.z) && (b.z!=c.z));
|
||||
interp_restriction_lv2_up.w = ((e.w!=c.w) && (b.w!=c.w));
|
||||
|
||||
vec4 fx45i = saturate((fx + delta -Co - Ci)/(2*delta ));
|
||||
vec4 fx45 = saturate((fx + delta -Co )/(2*delta ));
|
||||
vec4 fx30 = saturate((fx_left + deltaL -Cx )/(2*deltaL));
|
||||
vec4 fx60 = saturate((fx_up + deltaU -Cy )/(2*deltaU));
|
||||
|
||||
vec4 wd1 = weighted_distance( e, c, g, i, h5, f4, h, f);
|
||||
vec4 wd2 = weighted_distance( h, d, i5, f, i4, b, e, i);
|
||||
|
||||
edri.x = (wd1.x <= wd2.x) && interp_restriction_lv0.x;
|
||||
edri.y = (wd1.y <= wd2.y) && interp_restriction_lv0.y;
|
||||
edri.z = (wd1.z <= wd2.z) && interp_restriction_lv0.z;
|
||||
edri.w = (wd1.w <= wd2.w) && interp_restriction_lv0.w;
|
||||
edr.x = (wd1.x < wd2.x) && interp_restriction_lv1.x;
|
||||
edr.y = (wd1.y < wd2.y) && interp_restriction_lv1.y;
|
||||
edr.z = (wd1.z < wd2.z) && interp_restriction_lv1.z;
|
||||
edr.w = (wd1.w < wd2.w) && interp_restriction_lv1.w;
|
||||
edr_left.x = ((XBR_LV2_COEFFICIENT*df(f,g).x) <= df(h,c).x) && interp_restriction_lv2_left.x && edr.x;
|
||||
edr_left.y = ((XBR_LV2_COEFFICIENT*df(f,g).y) <= df(h,c).y) && interp_restriction_lv2_left.y && edr.y;
|
||||
edr_left.z = ((XBR_LV2_COEFFICIENT*df(f,g).z) <= df(h,c).z) && interp_restriction_lv2_left.z && edr.z;
|
||||
edr_left.w = ((XBR_LV2_COEFFICIENT*df(f,g).w) <= df(h,c).w) && interp_restriction_lv2_left.w && edr.w;
|
||||
edr_up.x = (df(f,g).x >= (XBR_LV2_COEFFICIENT*df(h,c).x)) && interp_restriction_lv2_up.x && edr.x;
|
||||
edr_up.y = (df(f,g).y >= (XBR_LV2_COEFFICIENT*df(h,c).y)) && interp_restriction_lv2_up.y && edr.y;
|
||||
edr_up.z = (df(f,g).z >= (XBR_LV2_COEFFICIENT*df(h,c).z)) && interp_restriction_lv2_up.z && edr.z;
|
||||
edr_up.w = (df(f,g).w >= (XBR_LV2_COEFFICIENT*df(h,c).w)) && interp_restriction_lv2_up.w && edr.w;
|
||||
|
||||
fx45 = vec4(edr)*fx45;
|
||||
fx30 = vec4(edr_left)*fx30;
|
||||
fx60 = vec4(edr_up)*fx60;
|
||||
fx45i = vec4(edri)*fx45i;
|
||||
|
||||
px.x = (df(e,f3).x <= df(e,h1).x);
|
||||
px.y = (df(e,f3).y <= df(e,h1).y);
|
||||
px.z = (df(e,f3).z <= df(e,h1).z);
|
||||
px.w = (df(e,f3).w <= df(e,h1).w);
|
||||
|
||||
#ifdef SMOOTH_TIPS
|
||||
vec4 maximos = max(max(fx30, fx60), max(fx45, fx45i));
|
||||
#else
|
||||
vec4 maximos = max(max(fx30, fx60), fx45);
|
||||
#endif
|
||||
|
||||
vec3 res1 = E;
|
||||
res1 = mix(res1, mix(H, F, float(px.x)), maximos.x);
|
||||
res1 = mix(res1, mix(B, D, float(px.z)), maximos.z);
|
||||
|
||||
vec3 res2 = E;
|
||||
res2 = mix(res2, mix(F, B, float(px.y)), maximos.y);
|
||||
res2 = mix(res2, mix(D, H, float(px.w)), maximos.w);
|
||||
|
||||
vec3 res = mix(res1, res2, step(c_df(E, res1), c_df(E, res2)));
|
||||
|
||||
FragColor = vec4(res, 1.0);
|
||||
}
|
||||
#endif
|
283
contrib/glshaders/xbr-lv2-noblend.glsl
Normal file
283
contrib/glshaders/xbr-lv2-noblend.glsl
Normal file
@@ -0,0 +1,283 @@
|
||||
#version 120
|
||||
|
||||
/*
|
||||
Hyllian's xBR-lv2-noblend Shader
|
||||
|
||||
Copyright (C) 2011-2016 Hyllian - sergiogdb@gmail.com
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
|
||||
Incorporates some of the ideas from SABR shader. Thanks to Joshua Street.
|
||||
*/
|
||||
|
||||
#pragma parameter XBR_EQ_THRESHOLD "Eq Threshold" 0.6 0.0 2.0 0.1
|
||||
#pragma parameter XBR_LV2_COEFFICIENT "Lv2 Coefficient" 2.0 1.0 3.0 0.1
|
||||
|
||||
#define mul(a,b) (b*a)
|
||||
|
||||
// Uncomment just one of the three params below to choose the corner detection
|
||||
#define CORNER_A
|
||||
//#define CORNER_B
|
||||
//#define CORNER_C
|
||||
//#define CORNER_D
|
||||
|
||||
#define lv2_cf XBR_LV2_COEFFICIENT
|
||||
|
||||
#if defined(VERTEX)
|
||||
|
||||
#if __VERSION__ >= 130
|
||||
#define OUT out
|
||||
#define IN in
|
||||
#define tex2D texture
|
||||
#else
|
||||
#define OUT varying
|
||||
#define IN attribute
|
||||
#define tex2D texture2D
|
||||
#endif
|
||||
|
||||
#ifdef GL_ES
|
||||
#define PRECISION mediump
|
||||
#else
|
||||
#define PRECISION
|
||||
#endif
|
||||
|
||||
|
||||
IN vec4 a_position;
|
||||
|
||||
OUT vec2 texCoord;
|
||||
OUT vec4 t1;
|
||||
OUT vec4 t2;
|
||||
OUT vec4 t3;
|
||||
OUT vec4 t4;
|
||||
OUT vec4 t5;
|
||||
OUT vec4 t6;
|
||||
OUT vec4 t7;
|
||||
|
||||
uniform PRECISION vec2 rubyOutputSize;
|
||||
uniform PRECISION vec2 rubyTextureSize;
|
||||
uniform PRECISION vec2 rubyInputSize;
|
||||
|
||||
void main()
|
||||
{
|
||||
gl_Position = a_position;
|
||||
|
||||
float dx = (1.0/rubyTextureSize.x);
|
||||
float dy = (1.0/rubyTextureSize.y);
|
||||
|
||||
vec2 TexCoord = vec2(a_position.x + 1.0, 1.0 - a_position.y) / 2.0 * rubyInputSize / rubyTextureSize;
|
||||
texCoord = TexCoord;
|
||||
texCoord.x *= 1.00000001;
|
||||
t1 = TexCoord.xxxy + vec4( -dx, 0, dx,-2.0*dy); // A1 B1 C1
|
||||
t2 = TexCoord.xxxy + vec4( -dx, 0, dx, -dy); // A B C
|
||||
t3 = TexCoord.xxxy + vec4( -dx, 0, dx, 0); // D E F
|
||||
t4 = TexCoord.xxxy + vec4( -dx, 0, dx, dy); // G H I
|
||||
t5 = TexCoord.xxxy + vec4( -dx, 0, dx, 2.0*dy); // G5 H5 I5
|
||||
t6 = TexCoord.xyyy + vec4(-2.0*dx,-dy, 0, dy); // A0 D0 G0
|
||||
t7 = TexCoord.xyyy + vec4( 2.0*dx,-dy, 0, dy); // C4 F4 I4
|
||||
}
|
||||
|
||||
|
||||
#elif defined(FRAGMENT)
|
||||
|
||||
#if __VERSION__ >= 130
|
||||
#define IN in
|
||||
#define tex2D texture
|
||||
out vec4 FragColor;
|
||||
#else
|
||||
#define IN varying
|
||||
#define FragColor gl_FragColor
|
||||
#define tex2D texture2D
|
||||
#endif
|
||||
|
||||
#ifdef GL_ES
|
||||
#ifdef GL_FRAGMENT_PRECISION_HIGH
|
||||
precision highp float;
|
||||
#else
|
||||
precision mediump float;
|
||||
#endif
|
||||
#define PRECISION mediump
|
||||
#else
|
||||
#define PRECISION
|
||||
#endif
|
||||
|
||||
uniform PRECISION vec2 rubyOutputSize;
|
||||
uniform PRECISION vec2 rubyTextureSize;
|
||||
uniform PRECISION vec2 rubyInputSize;
|
||||
uniform sampler2D rubyTexture;
|
||||
IN vec2 texCoord;
|
||||
IN vec4 t1;
|
||||
IN vec4 t2;
|
||||
IN vec4 t3;
|
||||
IN vec4 t4;
|
||||
IN vec4 t5;
|
||||
IN vec4 t6;
|
||||
IN vec4 t7;
|
||||
|
||||
#ifdef PARAMETER_UNIFORM
|
||||
uniform PRECISION float XBR_EQ_THRESHOLD;
|
||||
uniform PRECISION float XBR_LV2_COEFFICIENT;
|
||||
#else
|
||||
#define XBR_EQ_THRESHOLD 0.6
|
||||
#define XBR_LV2_COEFFICIENT 2.0
|
||||
#endif
|
||||
// END PARAMETERS //
|
||||
|
||||
const vec3 Y = vec3(0.2126, 0.7152, 0.0722);
|
||||
|
||||
// Difference between vector components.
|
||||
vec4 df(vec4 A, vec4 B)
|
||||
{
|
||||
return vec4(abs(A-B));
|
||||
}
|
||||
|
||||
// Compare two vectors and return their components are different.
|
||||
vec4 diff(vec4 A, vec4 B)
|
||||
{
|
||||
return vec4(notEqual(A, B));
|
||||
}
|
||||
|
||||
// Determine if two vector components are equal based on a threshold.
|
||||
vec4 eq(vec4 A, vec4 B)
|
||||
{
|
||||
return (step(df(A, B), vec4(XBR_EQ_THRESHOLD)));
|
||||
}
|
||||
|
||||
// Determine if two vector components are NOT equal based on a threshold.
|
||||
vec4 neq(vec4 A, vec4 B)
|
||||
{
|
||||
return (vec4(1.0, 1.0, 1.0, 1.0) - eq(A, B));
|
||||
}
|
||||
|
||||
// Weighted distance.
|
||||
vec4 wd(vec4 a, vec4 b, vec4 c, vec4 d, vec4 e, vec4 f, vec4 g, vec4 h)
|
||||
{
|
||||
return (df(a,b) + df(a,c) + df(d,e) + df(d,f) + 4.0*df(g,h));
|
||||
}
|
||||
|
||||
vec4 weighted_distance(vec4 a, vec4 b, vec4 c, vec4 d, vec4 e, vec4 f, vec4 g, vec4 h, vec4 i, vec4 j, vec4 k, vec4 l)
|
||||
{
|
||||
return (df(a,b) + df(a,c) + df(d,e) + df(d,f) + df(i,j) + df(k,l) + 2.0*df(g,h));
|
||||
}
|
||||
|
||||
float c_df(vec3 c1, vec3 c2)
|
||||
{
|
||||
vec3 df = abs(c1 - c2);
|
||||
return df.r + df.g + df.b;
|
||||
}
|
||||
|
||||
void main()
|
||||
{
|
||||
vec4 edri, edr, edr_l, edr_u; // px = pixel, edr = edge detection rule
|
||||
vec4 irlv1, irlv2l, irlv2u, block_3d;
|
||||
bvec4 nc, px;
|
||||
vec4 fx, fx_l, fx_u; // inequations of straight lines.
|
||||
|
||||
vec2 fp = fract(texCoord*rubyTextureSize);
|
||||
|
||||
vec3 A1 = tex2D(rubyTexture, t1.xw ).xyz;
|
||||
vec3 B1 = tex2D(rubyTexture, t1.yw ).xyz;
|
||||
vec3 C1 = tex2D(rubyTexture, t1.zw ).xyz;
|
||||
vec3 A = tex2D(rubyTexture, t2.xw ).xyz;
|
||||
vec3 B = tex2D(rubyTexture, t2.yw ).xyz;
|
||||
vec3 C = tex2D(rubyTexture, t2.zw ).xyz;
|
||||
vec3 D = tex2D(rubyTexture, t3.xw ).xyz;
|
||||
vec3 E = tex2D(rubyTexture, t3.yw ).xyz;
|
||||
vec3 F = tex2D(rubyTexture, t3.zw ).xyz;
|
||||
vec3 G = tex2D(rubyTexture, t4.xw ).xyz;
|
||||
vec3 H = tex2D(rubyTexture, t4.yw ).xyz;
|
||||
vec3 I = tex2D(rubyTexture, t4.zw ).xyz;
|
||||
vec3 G5 = tex2D(rubyTexture, t5.xw ).xyz;
|
||||
vec3 H5 = tex2D(rubyTexture, t5.yw ).xyz;
|
||||
vec3 I5 = tex2D(rubyTexture, t5.zw ).xyz;
|
||||
vec3 A0 = tex2D(rubyTexture, t6.xy ).xyz;
|
||||
vec3 D0 = tex2D(rubyTexture, t6.xz ).xyz;
|
||||
vec3 G0 = tex2D(rubyTexture, t6.xw ).xyz;
|
||||
vec3 C4 = tex2D(rubyTexture, t7.xy ).xyz;
|
||||
vec3 F4 = tex2D(rubyTexture, t7.xz ).xyz;
|
||||
vec3 I4 = tex2D(rubyTexture, t7.xw ).xyz;
|
||||
|
||||
vec4 b = mul( mat4x3(B, D, H, F), Y );
|
||||
vec4 c = mul( mat4x3(C, A, G, I), Y );
|
||||
vec4 e = mul( mat4x3(E, E, E, E), Y );
|
||||
vec4 d = b.yzwx;
|
||||
vec4 f = b.wxyz;
|
||||
vec4 g = c.zwxy;
|
||||
vec4 h = b.zwxy;
|
||||
vec4 i = c.wxyz;
|
||||
|
||||
vec4 i4 = mul( mat4x3(I4, C1, A0, G5), Y );
|
||||
vec4 i5 = mul( mat4x3(I5, C4, A1, G0), Y );
|
||||
vec4 h5 = mul( mat4x3(H5, F4, B1, D0), Y );
|
||||
vec4 f4 = h5.yzwx;
|
||||
|
||||
vec4 Ao = vec4( 1.0, -1.0, -1.0, 1.0 );
|
||||
vec4 Bo = vec4( 1.0, 1.0, -1.0,-1.0 );
|
||||
vec4 Co = vec4( 1.5, 0.5, -0.5, 0.5 );
|
||||
vec4 Ax = vec4( 1.0, -1.0, -1.0, 1.0 );
|
||||
vec4 Bx = vec4( 0.5, 2.0, -0.5,-2.0 );
|
||||
vec4 Cx = vec4( 1.0, 1.0, -0.5, 0.0 );
|
||||
vec4 Ay = vec4( 1.0, -1.0, -1.0, 1.0 );
|
||||
vec4 By = vec4( 2.0, 0.5, -2.0,-0.5 );
|
||||
vec4 Cy = vec4( 2.0, 0.0, -1.0, 0.5 );
|
||||
|
||||
// These inequations define the line below which interpolation occurs.
|
||||
fx = vec4(greaterThan(Ao*fp.y+Bo*fp.x, Co));
|
||||
fx_l = vec4(greaterThan(Ax*fp.y+Bx*fp.x, Cx));
|
||||
fx_u = vec4(greaterThan(Ay*fp.y+By*fp.x, Cy));
|
||||
|
||||
#ifdef CORNER_A
|
||||
irlv1 = diff(e,f) * diff(e,h);
|
||||
#endif
|
||||
#ifdef CORNER_B
|
||||
irlv1 = (neq(f,b) * neq(h,d) + eq(e,i) * neq(f,i4) * neq(h,i5) + eq(e,g) + eq(e,c));
|
||||
#endif
|
||||
#ifdef CORNER_D
|
||||
vec4 c1 = i4.yzwx;
|
||||
vec4 g0 = i5.wxyz;
|
||||
irlv1 = (neq(f,b) * neq(h,d) + eq(e,i) * neq(f,i4) * neq(h,i5) + eq(e,g) + eq(e,c) ) * (diff(f,f4) * diff(f,i) + diff(h,h5) * diff(h,i) + diff(h,g) + diff(f,c) + eq(b,c1) * eq(d,g0));
|
||||
#endif
|
||||
#ifdef CORNER_C
|
||||
irlv1 = (neq(f,b) * neq(f,c) + neq(h,d) * neq(h,g) + eq(e,i) * (neq(f,f4) * neq(f,i4) + neq(h,h5) * neq(h,i5)) + eq(e,g) + eq(e,c));
|
||||
#endif
|
||||
|
||||
irlv2l = diff(e,g) * diff(d,g);
|
||||
irlv2u = diff(e,c) * diff(b,c);
|
||||
|
||||
vec4 wd1 = wd( e, c, g, i, h5, f4, h, f);
|
||||
vec4 wd2 = wd( h, d, i5, f, i4, b, e, i);
|
||||
|
||||
edri = step(wd1, wd2) * irlv1;
|
||||
edr = step(wd1 + vec4(0.1, 0.1, 0.1, 0.1), wd2) * step(vec4(0.5, 0.5, 0.5, 0.5), irlv1);
|
||||
edr_l = step( lv2_cf*df(f,g), df(h,c) ) * irlv2l * edr;
|
||||
edr_u = step( lv2_cf*df(h,c), df(f,g) ) * irlv2u * edr;
|
||||
|
||||
nc = bvec4( edr * ( fx + edr_l * (fx_l)) + edr_u * fx_u);
|
||||
|
||||
px = lessThanEqual(df(e, f), df(e, h));
|
||||
|
||||
vec3 res1 = nc.x ? px.x ? F : H : nc.y ? px.y ? B : F : nc.z ? px.z ? D : B : E;
|
||||
vec3 res2 = nc.w ? px.w ? H : D : nc.z ? px.z ? D : B : nc.y ? px.y ? B : F : E;
|
||||
|
||||
vec2 df12 = abs( mul( mat2x3(res1, res2), Y ) - e.xy);
|
||||
|
||||
vec3 res = mix(res1, res2, step(df12.x, df12.y));
|
||||
|
||||
FragColor.xyz = res;
|
||||
}
|
||||
#endif
|
345
contrib/glshaders/xbr-lv2.glsl
Normal file
345
contrib/glshaders/xbr-lv2.glsl
Normal file
@@ -0,0 +1,345 @@
|
||||
#version 120
|
||||
|
||||
/*
|
||||
Hyllian's xBR-lv2 Shader
|
||||
|
||||
Copyright (C) 2011-2016 Hyllian - sergiogdb@gmail.com
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
|
||||
Incorporates some of the ideas from SABR shader. Thanks to Joshua Street.
|
||||
*/
|
||||
|
||||
//#pragma parameter XBR_SCALE "xBR Scale" 3.0 1.0 5.0 1.0
|
||||
#pragma parameter XBR_Y_WEIGHT "Y Weight" 48.0 0.0 100.0 1.0
|
||||
#pragma parameter XBR_EQ_THRESHOLD "Eq Threshold" 15.0 0.0 50.0 1.0
|
||||
#pragma parameter XBR_LV1_COEFFICIENT "Lv1 Coefficient" 0.5 0.0 30.0 0.5
|
||||
#pragma parameter XBR_LV2_COEFFICIENT "Lv2 Coefficient" 2.0 1.0 3.0 0.1
|
||||
#pragma parameter small_details "Preserve Small Details" 0.0 0.0 1.0 1.0
|
||||
|
||||
#define mul(a,b) (b*a)
|
||||
|
||||
// Uncomment just one of the three params below to choose the corner detection
|
||||
//#define CORNER_A
|
||||
//#define CORNER_B
|
||||
#define CORNER_C
|
||||
//#define CORNER_D
|
||||
|
||||
#ifndef CORNER_A
|
||||
#define SMOOTH_TIPS
|
||||
#endif
|
||||
|
||||
#define XBR_SCALE 3.0
|
||||
|
||||
#define lv2_cf XBR_LV2_COEFFICIENT
|
||||
|
||||
#if defined(VERTEX)
|
||||
|
||||
#if __VERSION__ >= 130
|
||||
#define OUT out
|
||||
#define IN in
|
||||
#define tex2D texture
|
||||
#else
|
||||
#define OUT varying
|
||||
#define IN attribute
|
||||
#define tex2D texture2D
|
||||
#endif
|
||||
|
||||
#ifdef GL_ES
|
||||
#define PRECISION mediump
|
||||
#else
|
||||
#define PRECISION
|
||||
#endif
|
||||
|
||||
|
||||
IN vec4 a_position;
|
||||
|
||||
OUT vec2 texCoord;
|
||||
OUT vec4 t1;
|
||||
OUT vec4 t2;
|
||||
OUT vec4 t3;
|
||||
OUT vec4 t4;
|
||||
OUT vec4 t5;
|
||||
OUT vec4 t6;
|
||||
OUT vec4 t7;
|
||||
|
||||
uniform PRECISION vec2 rubyOutputSize;
|
||||
uniform PRECISION vec2 rubyTextureSize;
|
||||
uniform PRECISION vec2 rubyInputSize;
|
||||
|
||||
void main()
|
||||
{
|
||||
gl_Position = a_position;
|
||||
|
||||
float dx = (1.0/rubyTextureSize.x);
|
||||
float dy = (1.0/rubyTextureSize.y);
|
||||
|
||||
vec2 TexCoord = vec2(a_position.x + 1.0, 1.0 - a_position.y) / 2.0 * rubyInputSize / rubyTextureSize;
|
||||
texCoord = TexCoord;
|
||||
texCoord.x *= 1.00000001;
|
||||
t1 = TexCoord.xxxy + vec4( -dx, 0, dx,-2.0*dy); // A1 B1 C1
|
||||
t2 = TexCoord.xxxy + vec4( -dx, 0, dx, -dy); // A B C
|
||||
t3 = TexCoord.xxxy + vec4( -dx, 0, dx, 0); // D E F
|
||||
t4 = TexCoord.xxxy + vec4( -dx, 0, dx, dy); // G H I
|
||||
t5 = TexCoord.xxxy + vec4( -dx, 0, dx, 2.0*dy); // G5 H5 I5
|
||||
t6 = TexCoord.xyyy + vec4(-2.0*dx,-dy, 0, dy); // A0 D0 G0
|
||||
t7 = TexCoord.xyyy + vec4( 2.0*dx,-dy, 0, dy); // C4 F4 I4
|
||||
}
|
||||
|
||||
|
||||
#elif defined(FRAGMENT)
|
||||
|
||||
#if __VERSION__ >= 130
|
||||
#define IN in
|
||||
#define tex2D texture
|
||||
out vec4 FragColor;
|
||||
#else
|
||||
#define IN varying
|
||||
#define FragColor gl_FragColor
|
||||
#define tex2D texture2D
|
||||
#endif
|
||||
|
||||
#ifdef GL_ES
|
||||
#ifdef GL_FRAGMENT_PRECISION_HIGH
|
||||
precision highp float;
|
||||
#else
|
||||
precision mediump float;
|
||||
#endif
|
||||
#define PRECISION mediump
|
||||
#else
|
||||
#define PRECISION
|
||||
#endif
|
||||
|
||||
uniform PRECISION vec2 rubyOutputSize;
|
||||
uniform PRECISION vec2 rubyTextureSize;
|
||||
uniform PRECISION vec2 rubyInputSize;
|
||||
uniform sampler2D rubyTexture;
|
||||
IN vec2 texCoord;
|
||||
IN vec4 t1;
|
||||
IN vec4 t2;
|
||||
IN vec4 t3;
|
||||
IN vec4 t4;
|
||||
IN vec4 t5;
|
||||
IN vec4 t6;
|
||||
IN vec4 t7;
|
||||
|
||||
#ifdef PARAMETER_UNIFORM
|
||||
uniform PRECISION float XBR_Y_WEIGHT;
|
||||
uniform PRECISION float XBR_EQ_THRESHOLD;
|
||||
uniform PRECISION float XBR_LV1_COEFFICIENT;
|
||||
uniform PRECISION float XBR_LV2_COEFFICIENT;
|
||||
uniform PRECISION float small_details;
|
||||
#else
|
||||
#define XBR_Y_WEIGHT 48.0
|
||||
#define XBR_EQ_THRESHOLD 15.0
|
||||
#define XBR_LV1_COEFFICIENT 0.5
|
||||
#define XBR_LV2_COEFFICIENT 2.0
|
||||
#define small_details 0.0
|
||||
#endif
|
||||
// END PARAMETERS //
|
||||
|
||||
const float coef = 2.0;
|
||||
const vec3 rgbw = vec3(14.352, 28.176, 5.472);
|
||||
const vec4 eq_threshold = vec4(15.0, 15.0, 15.0, 15.0);
|
||||
|
||||
vec4 delta = vec4(1.0/XBR_SCALE, 1.0/XBR_SCALE, 1.0/XBR_SCALE, 1.0/XBR_SCALE);
|
||||
vec4 delta_l = vec4(0.5/XBR_SCALE, 1.0/XBR_SCALE, 0.5/XBR_SCALE, 1.0/XBR_SCALE);
|
||||
vec4 delta_u = delta_l.yxwz;
|
||||
|
||||
const vec4 Ao = vec4( 1.0, -1.0, -1.0, 1.0 );
|
||||
const vec4 Bo = vec4( 1.0, 1.0, -1.0,-1.0 );
|
||||
const vec4 Co = vec4( 1.5, 0.5, -0.5, 0.5 );
|
||||
const vec4 Ax = vec4( 1.0, -1.0, -1.0, 1.0 );
|
||||
const vec4 Bx = vec4( 0.5, 2.0, -0.5,-2.0 );
|
||||
const vec4 Cx = vec4( 1.0, 1.0, -0.5, 0.0 );
|
||||
const vec4 Ay = vec4( 1.0, -1.0, -1.0, 1.0 );
|
||||
const vec4 By = vec4( 2.0, 0.5, -2.0,-0.5 );
|
||||
const vec4 Cy = vec4( 2.0, 0.0, -1.0, 0.5 );
|
||||
const vec4 Ci = vec4(0.25, 0.25, 0.25, 0.25);
|
||||
|
||||
const vec3 Y = vec3(0.2126, 0.7152, 0.0722);
|
||||
|
||||
// Difference between vector components.
|
||||
vec4 df(vec4 A, vec4 B)
|
||||
{
|
||||
return vec4(abs(A-B));
|
||||
}
|
||||
|
||||
// Compare two vectors and return their components are different.
|
||||
vec4 diff(vec4 A, vec4 B)
|
||||
{
|
||||
return vec4(notEqual(A, B));
|
||||
}
|
||||
|
||||
// Determine if two vector components are equal based on a threshold.
|
||||
vec4 eq(vec4 A, vec4 B)
|
||||
{
|
||||
return (step(df(A, B), vec4(XBR_EQ_THRESHOLD)));
|
||||
}
|
||||
|
||||
// Determine if two vector components are NOT equal based on a threshold.
|
||||
vec4 neq(vec4 A, vec4 B)
|
||||
{
|
||||
return (vec4(1.0, 1.0, 1.0, 1.0) - eq(A, B));
|
||||
}
|
||||
|
||||
// Weighted distance.
|
||||
vec4 wd(vec4 a, vec4 b, vec4 c, vec4 d, vec4 e, vec4 f, vec4 g, vec4 h)
|
||||
{
|
||||
return (df(a,b) + df(a,c) + df(d,e) + df(d,f) + 4.0*df(g,h));
|
||||
}
|
||||
|
||||
vec4 weighted_distance(vec4 a, vec4 b, vec4 c, vec4 d, vec4 e, vec4 f, vec4 g, vec4 h, vec4 i, vec4 j, vec4 k, vec4 l)
|
||||
{
|
||||
return (df(a,b) + df(a,c) + df(d,e) + df(d,f) + df(i,j) + df(k,l) + 2.0*df(g,h));
|
||||
}
|
||||
|
||||
float c_df(vec3 c1, vec3 c2)
|
||||
{
|
||||
vec3 df = abs(c1 - c2);
|
||||
return df.r + df.g + df.b;
|
||||
}
|
||||
|
||||
void main()
|
||||
{
|
||||
vec4 edri, edr, edr_l, edr_u, px; // px = pixel, edr = edge detection rule
|
||||
vec4 irlv0, irlv1, irlv2l, irlv2u, block_3d;
|
||||
vec4 fx, fx_l, fx_u; // inequations of straight lines.
|
||||
|
||||
vec2 fp = fract(texCoord*rubyTextureSize);
|
||||
|
||||
vec3 A1 = tex2D(rubyTexture, t1.xw ).xyz;
|
||||
vec3 B1 = tex2D(rubyTexture, t1.yw ).xyz;
|
||||
vec3 C1 = tex2D(rubyTexture, t1.zw ).xyz;
|
||||
vec3 A = tex2D(rubyTexture, t2.xw ).xyz;
|
||||
vec3 B = tex2D(rubyTexture, t2.yw ).xyz;
|
||||
vec3 C = tex2D(rubyTexture, t2.zw ).xyz;
|
||||
vec3 D = tex2D(rubyTexture, t3.xw ).xyz;
|
||||
vec3 E = tex2D(rubyTexture, t3.yw ).xyz;
|
||||
vec3 F = tex2D(rubyTexture, t3.zw ).xyz;
|
||||
vec3 G = tex2D(rubyTexture, t4.xw ).xyz;
|
||||
vec3 H = tex2D(rubyTexture, t4.yw ).xyz;
|
||||
vec3 I = tex2D(rubyTexture, t4.zw ).xyz;
|
||||
vec3 G5 = tex2D(rubyTexture, t5.xw ).xyz;
|
||||
vec3 H5 = tex2D(rubyTexture, t5.yw ).xyz;
|
||||
vec3 I5 = tex2D(rubyTexture, t5.zw ).xyz;
|
||||
vec3 A0 = tex2D(rubyTexture, t6.xy ).xyz;
|
||||
vec3 D0 = tex2D(rubyTexture, t6.xz ).xyz;
|
||||
vec3 G0 = tex2D(rubyTexture, t6.xw ).xyz;
|
||||
vec3 C4 = tex2D(rubyTexture, t7.xy ).xyz;
|
||||
vec3 F4 = tex2D(rubyTexture, t7.xz ).xyz;
|
||||
vec3 I4 = tex2D(rubyTexture, t7.xw ).xyz;
|
||||
|
||||
vec4 b = vec4(dot(B ,rgbw), dot(D ,rgbw), dot(H ,rgbw), dot(F ,rgbw));
|
||||
vec4 c = vec4(dot(C ,rgbw), dot(A ,rgbw), dot(G ,rgbw), dot(I ,rgbw));
|
||||
vec4 d = b.yzwx;
|
||||
vec4 e = vec4(dot(E,rgbw));
|
||||
vec4 f = b.wxyz;
|
||||
vec4 g = c.zwxy;
|
||||
vec4 h = b.zwxy;
|
||||
vec4 i = c.wxyz;
|
||||
|
||||
vec4 i4, i5, h5, f4;
|
||||
|
||||
float y_weight = XBR_Y_WEIGHT;
|
||||
|
||||
if (small_details < 0.5)
|
||||
{
|
||||
i4 = vec4(dot(I4,rgbw), dot(C1,rgbw), dot(A0,rgbw), dot(G5,rgbw));
|
||||
i5 = vec4(dot(I5,rgbw), dot(C4,rgbw), dot(A1,rgbw), dot(G0,rgbw));
|
||||
h5 = vec4(dot(H5,rgbw), dot(F4,rgbw), dot(B1,rgbw), dot(D0,rgbw));
|
||||
}
|
||||
else
|
||||
{
|
||||
i4 = mul( mat4x3(I4, C1, A0, G5), y_weight * Y );
|
||||
i5 = mul( mat4x3(I5, C4, A1, G0), y_weight * Y );
|
||||
h5 = mul( mat4x3(H5, F4, B1, D0), y_weight * Y );
|
||||
}
|
||||
|
||||
// These inequations define the line below which interpolation occurs.
|
||||
fx = (Ao*fp.y+Bo*fp.x);
|
||||
fx_l = (Ax*fp.y+Bx*fp.x);
|
||||
fx_u = (Ay*fp.y+By*fp.x);
|
||||
|
||||
irlv1 = irlv0 = diff(e,f) * diff(e,h);
|
||||
|
||||
#ifdef CORNER_B
|
||||
irlv1 = (irlv0 * ( neq(f,b) * neq(h,d) + eq(e,i) * neq(f,i4) * neq(h,i5) + eq(e,g) + eq(e,c) ) );
|
||||
#endif
|
||||
#ifdef CORNER_D
|
||||
vec4 c1 = i4.yzwx;
|
||||
vec4 g0 = i5.wxyz;
|
||||
irlv1 = (irlv0 * ( neq(f,b) * neq(h,d) + eq(e,i) * neq(f,i4) * neq(h,i5) + eq(e,g) + eq(e,c) ) * (diff(f,f4) * diff(f,i) + diff(h,h5) * diff(h,i) + diff(h,g) + diff(f,c) + eq(b,c1) * eq(d,g0)));
|
||||
#endif
|
||||
#ifdef CORNER_C
|
||||
irlv1 = (irlv0 * ( neq(f,b) * neq(f,c) + neq(h,d) * neq(h,g) + eq(e,i) * (neq(f,f4) * neq(f,i4) + neq(h,h5) * neq(h,i5)) + eq(e,g) + eq(e,c)) );
|
||||
#endif
|
||||
|
||||
irlv2l = diff(e,g) * diff(d,g);
|
||||
irlv2u = diff(e,c) * diff(b,c);
|
||||
|
||||
vec4 fx45i = clamp((fx + delta -Co - Ci)/(2.0*delta ), 0.0, 1.0);
|
||||
vec4 fx45 = clamp((fx + delta -Co )/(2.0*delta ), 0.0, 1.0);
|
||||
vec4 fx30 = clamp((fx_l + delta_l -Cx )/(2.0*delta_l), 0.0, 1.0);
|
||||
vec4 fx60 = clamp((fx_u + delta_u -Cy )/(2.0*delta_u), 0.0, 1.0);
|
||||
|
||||
vec4 wd1, wd2;
|
||||
if (small_details < 0.5)
|
||||
{
|
||||
wd1 = wd( e, c, g, i, h5, f4, h, f);
|
||||
wd2 = wd( h, d, i5, f, i4, b, e, i);
|
||||
}
|
||||
else
|
||||
{
|
||||
wd1 = weighted_distance( e, c, g, i, f4, h5, h, f, b, d, i4, i5);
|
||||
wd2 = weighted_distance( h, d, i5, f, b, i4, e, i, g, h5, c, f4);
|
||||
}
|
||||
|
||||
edri = step(wd1, wd2) * irlv0;
|
||||
edr = step(wd1 + vec4(0.1, 0.1, 0.1, 0.1), wd2) * step(vec4(0.5, 0.5, 0.5, 0.5), irlv1);
|
||||
edr_l = step( lv2_cf*df(f,g), df(h,c) ) * irlv2l * edr;
|
||||
edr_u = step( lv2_cf*df(h,c), df(f,g) ) * irlv2u * edr;
|
||||
|
||||
fx45 = edr * fx45;
|
||||
fx30 = edr_l * fx30;
|
||||
fx60 = edr_u * fx60;
|
||||
fx45i = edri * fx45i;
|
||||
|
||||
px = step(df(e,f), df(e,h));
|
||||
|
||||
#ifdef SMOOTH_TIPS
|
||||
vec4 maximos = max(max(fx30, fx60), max(fx45, fx45i));
|
||||
#endif
|
||||
#ifndef SMOOTH_TIPS
|
||||
vec4 maximos = max(max(fx30, fx60), fx45);
|
||||
#endif
|
||||
|
||||
vec3 res1 = E;
|
||||
res1 = mix(res1, mix(H, F, px.x), maximos.x);
|
||||
res1 = mix(res1, mix(B, D, px.z), maximos.z);
|
||||
|
||||
vec3 res2 = E;
|
||||
res2 = mix(res2, mix(F, B, px.y), maximos.y);
|
||||
res2 = mix(res2, mix(D, H, px.w), maximos.w);
|
||||
|
||||
vec3 res = mix(res1, res2, step(c_df(E, res1), c_df(E, res2)));
|
||||
|
||||
FragColor.xyz = res;
|
||||
}
|
||||
#endif
|
349
contrib/glshaders/xbr-lv3.glsl
Normal file
349
contrib/glshaders/xbr-lv3.glsl
Normal file
@@ -0,0 +1,349 @@
|
||||
#version 120
|
||||
|
||||
/*
|
||||
Hyllian's xBR-lv3 Shader
|
||||
|
||||
Copyright (C) 2011-2015 Hyllian - sergiogdb@gmail.com
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
|
||||
|
||||
Incorporates some of the ideas from SABR shader. Thanks to Joshua Street.
|
||||
*/
|
||||
|
||||
// Parameter lines go here:
|
||||
#pragma parameter XBR_Y_WEIGHT "Y Weight" 48.0 0.0 100.0 1.0
|
||||
#pragma parameter XBR_EQ_THRESHOLD "EQ Threshold" 10.0 0.0 50.0 1.0
|
||||
#pragma parameter XBR_EQ_THRESHOLD2 "EQ Threshold 2" 2.0 0.0 4.0 1.0
|
||||
#pragma parameter XBR_LV2_COEFFICIENT "Lv2 Coefficient" 2.0 1.0 3.0 1.0
|
||||
#pragma parameter corner_type "Corner Calculation" 3.0 1.0 3.0 1.0
|
||||
|
||||
#if defined(VERTEX)
|
||||
|
||||
#if __VERSION__ >= 130
|
||||
#define COMPAT_VARYING out
|
||||
#define COMPAT_ATTRIBUTE in
|
||||
#define COMPAT_TEXTURE texture
|
||||
#else
|
||||
#define COMPAT_VARYING varying
|
||||
#define COMPAT_ATTRIBUTE attribute
|
||||
#define COMPAT_TEXTURE texture2D
|
||||
#endif
|
||||
|
||||
#ifdef GL_ES
|
||||
#define COMPAT_PRECISION mediump
|
||||
#else
|
||||
#define COMPAT_PRECISION
|
||||
#endif
|
||||
|
||||
COMPAT_ATTRIBUTE vec4 VertexCoord;
|
||||
COMPAT_ATTRIBUTE vec4 TexCoord;
|
||||
|
||||
COMPAT_ATTRIBUTE vec4 a_position;
|
||||
COMPAT_VARYING vec2 v_texCoord;
|
||||
|
||||
COMPAT_VARYING vec4 t1;
|
||||
COMPAT_VARYING vec4 t2;
|
||||
COMPAT_VARYING vec4 t3;
|
||||
COMPAT_VARYING vec4 t4;
|
||||
COMPAT_VARYING vec4 t5;
|
||||
COMPAT_VARYING vec4 t6;
|
||||
COMPAT_VARYING vec4 t7;
|
||||
|
||||
vec4 _oPosition1;
|
||||
uniform COMPAT_PRECISION vec2 rubyOutputSize;
|
||||
uniform COMPAT_PRECISION vec2 rubyTextureSize;
|
||||
uniform COMPAT_PRECISION vec2 rubyInputSize;
|
||||
|
||||
void main()
|
||||
{
|
||||
gl_Position = a_position;
|
||||
v_texCoord = vec2(a_position.x + 1.0, 1.0 - a_position.y) / 2.0 * rubyInputSize / rubyTextureSize;
|
||||
vec2 ps = vec2(1.0) / rubyTextureSize.xy;
|
||||
float dx = ps.x;
|
||||
float dy = ps.y;
|
||||
|
||||
// A1 B1 C1
|
||||
// A0 A B C C4
|
||||
// D0 D E F F4
|
||||
// G0 G H I I4
|
||||
// G5 H5 I5
|
||||
|
||||
t1 = v_texCoord.xxxy + vec4( -dx, 0, dx,-2.0*dy); // A1 B1 C1
|
||||
t2 = v_texCoord.xxxy + vec4( -dx, 0, dx, -dy); // A B C
|
||||
t3 = v_texCoord.xxxy + vec4( -dx, 0, dx, 0); // D E F
|
||||
t4 = v_texCoord.xxxy + vec4( -dx, 0, dx, dy); // G H I
|
||||
t5 = v_texCoord.xxxy + vec4( -dx, 0, dx, 2.0*dy); // G5 H5 I5
|
||||
t6 = v_texCoord.xyyy + vec4(-2.0*dx,-dy, 0, dy); // A0 D0 G0
|
||||
t7 = v_texCoord.xyyy + vec4( 2.0*dx,-dy, 0, dy); // C4 F4 I4
|
||||
}
|
||||
|
||||
#elif defined(FRAGMENT)
|
||||
|
||||
#ifdef GL_ES
|
||||
#ifdef GL_FRAGMENT_PRECISION_HIGH
|
||||
precision highp float;
|
||||
#else
|
||||
precision mediump float;
|
||||
#endif
|
||||
#define COMPAT_PRECISION mediump
|
||||
#else
|
||||
#define COMPAT_PRECISION
|
||||
#endif
|
||||
|
||||
#if __VERSION__ >= 130
|
||||
#define COMPAT_VARYING in
|
||||
#define COMPAT_TEXTURE texture
|
||||
out COMPAT_PRECISION vec4 FragColor;
|
||||
#else
|
||||
#define COMPAT_VARYING varying
|
||||
#define FragColor gl_FragColor
|
||||
#define COMPAT_TEXTURE texture2D
|
||||
#endif
|
||||
|
||||
uniform COMPAT_PRECISION vec2 rubyOutputSize;
|
||||
uniform COMPAT_PRECISION vec2 rubyTextureSize;
|
||||
uniform COMPAT_PRECISION vec2 rubyInputSize;
|
||||
uniform sampler2D rubyTexture;
|
||||
COMPAT_VARYING vec2 v_texCoord;
|
||||
COMPAT_VARYING vec4 t1;
|
||||
COMPAT_VARYING vec4 t2;
|
||||
COMPAT_VARYING vec4 t3;
|
||||
COMPAT_VARYING vec4 t4;
|
||||
COMPAT_VARYING vec4 t5;
|
||||
COMPAT_VARYING vec4 t6;
|
||||
COMPAT_VARYING vec4 t7;
|
||||
|
||||
// compatibility #defines
|
||||
|
||||
#define Source rubyTexture
|
||||
#define vTexCoord v_texCoord.xy
|
||||
|
||||
#define SourceSize vec4(rubyTextureSize, 1.0 / rubyTextureSize) //either TextureSize or InputSize
|
||||
#define OutputSize vec4(rubyOutputSize, 1.0 / rubyOutputSize)
|
||||
|
||||
#ifdef PARAMETER_UNIFORM
|
||||
uniform COMPAT_PRECISION float XBR_Y_WEIGHT;
|
||||
uniform COMPAT_PRECISION float XBR_EQ_THRESHOLD;
|
||||
uniform COMPAT_PRECISION float XBR_EQ_THRESHOLD2;
|
||||
uniform COMPAT_PRECISION float XBR_LV2_COEFFICIENT;
|
||||
uniform COMPAT_PRECISION float corner_type;
|
||||
#else
|
||||
#define XBR_Y_WEIGHT 48.0
|
||||
#define XBR_EQ_THRESHOLD 10.0
|
||||
#define XBR_EQ_THRESHOLD2 2.0
|
||||
#define XBR_LV2_COEFFICIENT 2.0
|
||||
#define corner_type 3.0
|
||||
#endif
|
||||
|
||||
const mat3 yuv = mat3(0.299, 0.587, 0.114, -0.169, -0.331, 0.499, 0.499, -0.418, -0.0813);
|
||||
const vec4 delta = vec4(0.4, 0.4, 0.4, 0.4);
|
||||
|
||||
vec4 df(vec4 A, vec4 B)
|
||||
{
|
||||
return vec4(abs(A-B));
|
||||
}
|
||||
|
||||
float c_df(vec3 c1, vec3 c2) {
|
||||
vec3 df = abs(c1 - c2);
|
||||
return df.r + df.g + df.b;
|
||||
}
|
||||
|
||||
bvec4 eq(vec4 A, vec4 B)
|
||||
{
|
||||
return lessThan(df(A, B), vec4(XBR_EQ_THRESHOLD));
|
||||
}
|
||||
|
||||
bvec4 eq2(vec4 A, vec4 B)
|
||||
{
|
||||
return lessThan(df(A, B), vec4(XBR_EQ_THRESHOLD2));
|
||||
}
|
||||
|
||||
bvec4 and(bvec4 A, bvec4 B)
|
||||
{
|
||||
return bvec4(A.x && B.x, A.y && B.y, A.z && B.z, A.w && B.w);
|
||||
}
|
||||
|
||||
bvec4 or(bvec4 A, bvec4 B)
|
||||
{
|
||||
return bvec4(A.x || B.x, A.y || B.y, A.z || B.z, A.w || B.w);
|
||||
}
|
||||
|
||||
vec4 weighted_distance(vec4 a, vec4 b, vec4 c, vec4 d, vec4 e, vec4 f, vec4 g, vec4 h)
|
||||
{
|
||||
return (df(a,b) + df(a,c) + df(d,e) + df(d,f) + 4.0*df(g,h));
|
||||
}
|
||||
|
||||
void main()
|
||||
{
|
||||
bvec4 edr, edr_left, edr_up, edr3_left, edr3_up, px; // px = pixel, edr = edge detection rule
|
||||
bvec4 interp_restriction_lv1, interp_restriction_lv2_left, interp_restriction_lv2_up;
|
||||
bvec4 interp_restriction_lv3_left, interp_restriction_lv3_up;
|
||||
bvec4 nc, nc30, nc60, nc45, nc15, nc75; // new_color
|
||||
vec4 fx, fx_left, fx_up, finalfx, fx3_left, fx3_up; // inequations of straight lines.
|
||||
vec3 res1, res2, pix1, pix2;
|
||||
float blend1, blend2;
|
||||
|
||||
vec2 fp = fract(vTexCoord * SourceSize.xy);
|
||||
|
||||
vec3 A1 = COMPAT_TEXTURE(rubyTexture, t1.xw).rgb;
|
||||
vec3 B1 = COMPAT_TEXTURE(rubyTexture, t1.yw).rgb;
|
||||
vec3 C1 = COMPAT_TEXTURE(rubyTexture, t1.zw).rgb;
|
||||
|
||||
vec3 A = COMPAT_TEXTURE(rubyTexture, t2.xw).rgb;
|
||||
vec3 B = COMPAT_TEXTURE(rubyTexture, t2.yw).rgb;
|
||||
vec3 C = COMPAT_TEXTURE(rubyTexture, t2.zw).rgb;
|
||||
|
||||
vec3 D = COMPAT_TEXTURE(rubyTexture, t3.xw).rgb;
|
||||
vec3 E = COMPAT_TEXTURE(rubyTexture, t3.yw).rgb;
|
||||
vec3 F = COMPAT_TEXTURE(rubyTexture, t3.zw).rgb;
|
||||
|
||||
vec3 G = COMPAT_TEXTURE(rubyTexture, t4.xw).rgb;
|
||||
vec3 H = COMPAT_TEXTURE(rubyTexture, t4.yw).rgb;
|
||||
vec3 I = COMPAT_TEXTURE(rubyTexture, t4.zw).rgb;
|
||||
|
||||
vec3 G5 = COMPAT_TEXTURE(rubyTexture, t5.xw).rgb;
|
||||
vec3 H5 = COMPAT_TEXTURE(rubyTexture, t5.yw).rgb;
|
||||
vec3 I5 = COMPAT_TEXTURE(rubyTexture, t5.zw).rgb;
|
||||
|
||||
vec3 A0 = COMPAT_TEXTURE(rubyTexture, t6.xy).rgb;
|
||||
vec3 D0 = COMPAT_TEXTURE(rubyTexture, t6.xz).rgb;
|
||||
vec3 G0 = COMPAT_TEXTURE(rubyTexture, t6.xw).rgb;
|
||||
|
||||
vec3 C4 = COMPAT_TEXTURE(rubyTexture, t7.xy).rgb;
|
||||
vec3 F4 = COMPAT_TEXTURE(rubyTexture, t7.xz).rgb;
|
||||
vec3 I4 = COMPAT_TEXTURE(rubyTexture, t7.xw).rgb;
|
||||
|
||||
vec4 b = transpose(mat4x3(B, D, H, F)) * (XBR_Y_WEIGHT * yuv[0]);
|
||||
vec4 c = transpose(mat4x3(C, A, G, I)) * (XBR_Y_WEIGHT * yuv[0]);
|
||||
vec4 e = transpose(mat4x3(E, E, E, E)) * (XBR_Y_WEIGHT * yuv[0]);
|
||||
vec4 d = b.yzwx;
|
||||
vec4 f = b.wxyz;
|
||||
vec4 g = c.zwxy;
|
||||
vec4 h = b.zwxy;
|
||||
vec4 i = c.wxyz;
|
||||
|
||||
vec4 i4 = transpose(mat4x3(I4, C1, A0, G5)) * (XBR_Y_WEIGHT*yuv[0]);
|
||||
vec4 i5 = transpose(mat4x3(I5, C4, A1, G0)) * (XBR_Y_WEIGHT*yuv[0]);
|
||||
vec4 h5 = transpose(mat4x3(H5, F4, B1, D0)) * (XBR_Y_WEIGHT*yuv[0]);
|
||||
vec4 f4 = h5.yzwx;
|
||||
|
||||
vec4 c1 = i4.yzwx;
|
||||
vec4 g0 = i5.wxyz;
|
||||
vec4 b1 = h5.zwxy;
|
||||
vec4 d0 = h5.wxyz;
|
||||
|
||||
vec4 Ao = vec4( 1.0, -1.0, -1.0, 1.0 );
|
||||
vec4 Bo = vec4( 1.0, 1.0, -1.0,-1.0 );
|
||||
vec4 Co = vec4( 1.5, 0.5, -0.5, 0.5 );
|
||||
vec4 Ax = vec4( 1.0, -1.0, -1.0, 1.0 );
|
||||
vec4 Bx = vec4( 0.5, 2.0, -0.5,-2.0 );
|
||||
vec4 Cx = vec4( 1.0, 1.0, -0.5, 0.0 );
|
||||
vec4 Ay = vec4( 1.0, -1.0, -1.0, 1.0 );
|
||||
vec4 By = vec4( 2.0, 0.5, -2.0,-0.5 );
|
||||
vec4 Cy = vec4( 2.0, 0.0, -1.0, 0.5 );
|
||||
|
||||
vec4 Az = vec4( 6.0, -2.0, -6.0, 2.0 );
|
||||
vec4 Bz = vec4( 2.0, 6.0, -2.0, -6.0 );
|
||||
vec4 Cz = vec4( 5.0, 3.0, -3.0, -1.0 );
|
||||
vec4 Aw = vec4( 2.0, -6.0, -2.0, 6.0 );
|
||||
vec4 Bw = vec4( 6.0, 2.0, -6.0,-2.0 );
|
||||
vec4 Cw = vec4( 5.0, -1.0, -3.0, 3.0 );
|
||||
|
||||
fx = (Ao*fp.y+Bo*fp.x);
|
||||
fx_left = (Ax*fp.y+Bx*fp.x);
|
||||
fx_up = (Ay*fp.y+By*fp.x);
|
||||
fx3_left= (Az*fp.y+Bz*fp.x);
|
||||
fx3_up = (Aw*fp.y+Bw*fp.x);
|
||||
|
||||
// It uses CORNER_C if none of the others are defined.
|
||||
if(corner_type == 1.0)
|
||||
{interp_restriction_lv1 = and(notEqual(e, f), notEqual(e, h));}
|
||||
else if(corner_type == 2.0)
|
||||
{interp_restriction_lv1 = and(and(notEqual(e,f) , notEqual(e,h)) ,
|
||||
( or(or(and(and(or(and(not(eq(f,b)) , not(eq(h,d))) ,
|
||||
eq(e,i)) , not(eq(f,i4))) , not(eq(h,i5))) , eq(e,g)) , eq(e,c)) ) );}
|
||||
//commenting this one out because something got broken
|
||||
/*else if(corner_type == 6.0)
|
||||
{interp_restriction_lv1 = and(and(and(notEqual(e,f) , notEqual(e,h)) ,
|
||||
( or(or(and(and(or(and(not(eq(f,b)) , not(eq(h,d))) ,
|
||||
eq(e,i)) , not(eq(f,i4))) , not(eq(h,i5))) , eq(e,g)) ,
|
||||
eq(e,c)) )) , (and(or(or(or(or(and(notEqual(f,f4) , notEqual(f,i)) ,
|
||||
and(notEqual(h,h5) , notEqual(h,i))) , notEqual(h,g)) , notEqual(f,c)) ,
|
||||
eq(b,c1)) , eq(d,g0))));} */
|
||||
else
|
||||
{interp_restriction_lv1 = and(and(notEqual(e, f), notEqual(e, h)),
|
||||
or(or(and(not(eq(f,b)), not(eq(f,c))),
|
||||
and(not(eq(h,d)), not(eq(h,g)))),
|
||||
or(and(eq(e,i), or(and(not(eq(f,f4)), not(eq(f,i4))),
|
||||
and(not(eq(h,h5)), not(eq(h,i5))))),
|
||||
or(eq(e,g), eq(e,c)))));}
|
||||
|
||||
interp_restriction_lv2_left = and(notEqual(e, g), notEqual(d, g));
|
||||
interp_restriction_lv2_up = and(notEqual(e, c), notEqual(b, c));
|
||||
interp_restriction_lv3_left = and(eq2(g,g0), not(eq2(d0,g0)));
|
||||
interp_restriction_lv3_up = and(eq2(c,c1), not(eq2(b1,c1)));
|
||||
|
||||
vec4 fx45 = smoothstep(Co - delta, Co + delta, fx);
|
||||
vec4 fx30 = smoothstep(Cx - delta, Cx + delta, fx_left);
|
||||
vec4 fx60 = smoothstep(Cy - delta, Cy + delta, fx_up);
|
||||
vec4 fx15 = smoothstep(Cz - delta, Cz + delta, fx3_left);
|
||||
vec4 fx75 = smoothstep(Cw - delta, Cw + delta, fx3_up);
|
||||
|
||||
edr = and(lessThan(weighted_distance( e, c, g, i, h5, f4, h, f), weighted_distance( h, d, i5, f, i4, b, e, i)), interp_restriction_lv1);
|
||||
edr_left = and(lessThanEqual((XBR_LV2_COEFFICIENT*df(f,g)), df(h,c)), interp_restriction_lv2_left);
|
||||
edr_up = and(greaterThanEqual(df(f,g), (XBR_LV2_COEFFICIENT*df(h,c))), interp_restriction_lv2_up);
|
||||
edr3_left = interp_restriction_lv3_left;
|
||||
edr3_up = interp_restriction_lv3_up;
|
||||
|
||||
nc45 = and(edr, bvec4(fx45));
|
||||
nc30 = and(edr, and(edr_left, bvec4(fx30)));
|
||||
nc60 = and(edr, and(edr_up, bvec4(fx60)));
|
||||
nc15 = and(and(edr, edr_left), and(edr3_left, bvec4(fx15)));
|
||||
nc75 = and(and(edr, edr_up), and(edr3_up, bvec4(fx75)));
|
||||
|
||||
px = lessThanEqual(df(e, f), df(e, h));
|
||||
|
||||
nc = bvec4(nc75.x || nc15.x || nc30.x || nc60.x || nc45.x, nc75.y || nc15.y || nc30.y || nc60.y || nc45.y, nc75.z || nc15.z || nc30.z || nc60.z || nc45.z, nc75.w || nc15.w || nc30.w || nc60.w || nc45.w);
|
||||
|
||||
vec4 final45 = vec4(nc45) * fx45;
|
||||
vec4 final30 = vec4(nc30) * fx30;
|
||||
vec4 final60 = vec4(nc60) * fx60;
|
||||
vec4 final15 = vec4(nc15) * fx15;
|
||||
vec4 final75 = vec4(nc75) * fx75;
|
||||
|
||||
vec4 maximo = max(max(max(final15, final75),max(final30, final60)), final45);
|
||||
|
||||
if (nc.x) {pix1 = px.x ? F : H; blend1 = maximo.x;}
|
||||
else if (nc.y) {pix1 = px.y ? B : F; blend1 = maximo.y;}
|
||||
else if (nc.z) {pix1 = px.z ? D : B; blend1 = maximo.z;}
|
||||
else if (nc.w) {pix1 = px.w ? H : D; blend1 = maximo.w;}
|
||||
|
||||
if (nc.w) {pix2 = px.w ? H : D; blend2 = maximo.w;}
|
||||
else if (nc.z) {pix2 = px.z ? D : B; blend2 = maximo.z;}
|
||||
else if (nc.y) {pix2 = px.y ? B : F; blend2 = maximo.y;}
|
||||
else if (nc.x) {pix2 = px.x ? F : H; blend2 = maximo.x;}
|
||||
|
||||
res1 = mix(E, pix1, blend1);
|
||||
res2 = mix(E, pix2, blend2);
|
||||
vec3 res = mix(res1, res2, step(c_df(E, res1), c_df(E, res2)));
|
||||
|
||||
FragColor = vec4(res, 1.0);
|
||||
}
|
||||
#endif
|
224
contrib/glshaders/yee64.glsl
Normal file
224
contrib/glshaders/yee64.glsl
Normal file
@@ -0,0 +1,224 @@
|
||||
#version 120
|
||||
|
||||
// ported from ReShade
|
||||
|
||||
#if defined(VERTEX)
|
||||
|
||||
#if __VERSION__ >= 130
|
||||
#define COMPAT_VARYING out
|
||||
#define COMPAT_ATTRIBUTE in
|
||||
#define COMPAT_TEXTURE texture
|
||||
#else
|
||||
#define COMPAT_VARYING varying
|
||||
#define COMPAT_ATTRIBUTE attribute
|
||||
#define COMPAT_TEXTURE texture2D
|
||||
#endif
|
||||
|
||||
#ifdef GL_ES
|
||||
#define COMPAT_PRECISION mediump
|
||||
#else
|
||||
#define COMPAT_PRECISION
|
||||
#endif
|
||||
|
||||
COMPAT_ATTRIBUTE vec4 a_position;
|
||||
COMPAT_ATTRIBUTE vec4 COLOR;
|
||||
COMPAT_ATTRIBUTE vec4 TexCoord;
|
||||
COMPAT_VARYING vec4 COL0;
|
||||
COMPAT_VARYING vec2 v_texCoord;
|
||||
|
||||
vec4 _oPosition1;
|
||||
uniform mat4 MVPMatrix;
|
||||
uniform COMPAT_PRECISION int FrameDirection;
|
||||
uniform COMPAT_PRECISION int rubyFrameCount;
|
||||
uniform COMPAT_PRECISION vec2 rubyOutputSize;
|
||||
uniform COMPAT_PRECISION vec2 rubyTextureSize;
|
||||
uniform COMPAT_PRECISION vec2 rubyInputSize;
|
||||
|
||||
// compatibility #defines
|
||||
#define vTexCoord v_texCoord.xy
|
||||
#define SourceSize vec4(rubyTextureSize, 1.0 / rubyTextureSize) //either rubyTextureSize or rubyInputSize
|
||||
#define OutSize vec4(rubyOutputSize, 1.0 / rubyOutputSize)
|
||||
|
||||
void main()
|
||||
{
|
||||
gl_Position = a_position;
|
||||
v_texCoord = vec2(a_position.x + 1.0, 1.0 - a_position.y) / 2.0 * rubyInputSize / rubyTextureSize;
|
||||
}
|
||||
|
||||
#elif defined(FRAGMENT)
|
||||
|
||||
#ifdef GL_ES
|
||||
#ifdef GL_FRAGMENT_PRECISION_HIGH
|
||||
precision highp float;
|
||||
#else
|
||||
precision mediump float;
|
||||
#endif
|
||||
#define COMPAT_PRECISION mediump
|
||||
#else
|
||||
#define COMPAT_PRECISION
|
||||
#endif
|
||||
|
||||
#if __VERSION__ >= 130
|
||||
#define COMPAT_VARYING in
|
||||
#define COMPAT_TEXTURE texture
|
||||
out COMPAT_PRECISION vec4 FragColor;
|
||||
#else
|
||||
#define COMPAT_VARYING varying
|
||||
#define FragColor gl_FragColor
|
||||
#define COMPAT_TEXTURE texture2D
|
||||
#endif
|
||||
|
||||
uniform COMPAT_PRECISION int FrameDirection;
|
||||
uniform COMPAT_PRECISION int rubyFrameCount;
|
||||
uniform COMPAT_PRECISION vec2 rubyOutputSize;
|
||||
uniform COMPAT_PRECISION vec2 rubyTextureSize;
|
||||
uniform COMPAT_PRECISION vec2 rubyInputSize;
|
||||
uniform sampler2D rubyTexture;
|
||||
COMPAT_VARYING vec2 v_texCoord;
|
||||
|
||||
// compatibility #defines
|
||||
#define Source rubyTexture
|
||||
#define vTexCoord v_texCoord.xy
|
||||
|
||||
#define SourceSize vec4(rubyTextureSize, 1.0 / rubyTextureSize) //either rubyTextureSize or rubyInputSize
|
||||
#define OutSize vec4(rubyOutputSize, 1.0 / rubyOutputSize)
|
||||
|
||||
void main()
|
||||
{
|
||||
//Declare parameters
|
||||
//pixelSize
|
||||
vec4 c0 = rubyInputSize.xyyy;
|
||||
//textureSize
|
||||
vec4 c1 = SourceSize;
|
||||
//viewSize
|
||||
vec4 c2 = OutSize;
|
||||
//texDiffuse
|
||||
|
||||
const vec4 c3 = vec4(-1., 0.5, 1.25, 0.);
|
||||
const vec4 c4 = vec4(0.5, -0.5, 1.5, -3.);
|
||||
const vec4 c5 = vec4(-1., 1., -2., 2.);
|
||||
const vec4 c6 = vec4(-3., -8., 720., 0.166666672);
|
||||
const vec4 c7 = vec4(-0.333000004, -0.666000009, 0.899999976, 1.20000005);
|
||||
const vec4 c8 = vec4(1.5, 0.5, 2.5, 0.899999976);
|
||||
|
||||
//Declare registers
|
||||
vec4 r0, r1, r2, r3, r4, r5, r6, r7, r8, r9;
|
||||
|
||||
//Code starts here
|
||||
vec4 v0 = vTexCoord.xyyy;
|
||||
//dcl_2d s0
|
||||
r0.z = c3.w;
|
||||
r1.x = 1.0 / c0.x;
|
||||
r1.y = 1.0 / c0.y;
|
||||
r1.xy = (r1 * c1).xy;
|
||||
r1.xy = (r1 * v0).xy;
|
||||
r2.x = 1.0 / c1.x;
|
||||
r2.y = 1.0 / c1.y;
|
||||
r1.zw = (r2.xyxy * c0.xyxy).zw;
|
||||
r1.zw = (r1 * r1.xyxy).zw;
|
||||
r1.xy = (r1 * c2).xy;
|
||||
r2.zw = (r1 * c1.xyxy).zw;
|
||||
r2.zw = fract(r2).zw;
|
||||
r0.xy = (-r2.zwzw).xy;
|
||||
r3.xy = (r1.zwzw * c1 + r0.xzzw).xy;
|
||||
r4.yz = (r1.xzww * c1.xxyw + r0.xzyw).yz;
|
||||
r3.z = r0.y + r3.y;
|
||||
r5 = r3.xzxz + -c4.zyxy;
|
||||
r3 = r3.xzxz + c8.xyzy;
|
||||
r3 = r2.xyxy * r3;
|
||||
r5 = r2.xyxy * r5;
|
||||
r6 = COMPAT_TEXTURE(Source, r5.zw);
|
||||
r5 = COMPAT_TEXTURE(Source, r5.xy);
|
||||
r5.xyz = (r5 * c3.zzzz).xyz;
|
||||
r7 = r1.zwzw * c1.xyxy + r0.xyxy;
|
||||
r0.zw = (r1 * c1.xyxy + - r7).zw;
|
||||
r8.x = c3.x;
|
||||
r1.zw = (r1 * c1.xyxy + r8.xxxx).zw;
|
||||
r1.zw = (r0.xyxy + r1).zw;
|
||||
r4.x = r0.x + r4.y;
|
||||
r4 = r4.xzxz + c4.xyxz;
|
||||
r4 = r2.xyxy * r4;
|
||||
r0.xy = (r1.zwzw + c3.yyyy).xy;
|
||||
r0.xy = (r2 * r0).xy;
|
||||
r8 = COMPAT_TEXTURE(Source, r0.xy);
|
||||
r8.xyz = (r8 * c3.zzzz).xyz;
|
||||
r0.xy = (r0.zwzw + -c3.yyyy).xy;
|
||||
r9 = -r0.xxxx + c5;
|
||||
r9 = r9 * r9;
|
||||
r9 = r9 * c4.wwww;
|
||||
r0.z = pow(2, r9.x);
|
||||
r6.xyz = (r6 * r0.zzzz).xyz;
|
||||
r6.xyz = (r6 * c3.zzzz).xyz;
|
||||
r0.w = pow(2, r9.z);
|
||||
r5.xyz = (r5 * r0.wwww + r6).xyz;
|
||||
r0.w = r0.z + r0.w;
|
||||
r6 = r7.zwzw + c4.zyxx;
|
||||
r7 = r7 + c4.yzzz;
|
||||
r7 = r2.xyxy * r7;
|
||||
r2 = r2.xyxy * r6;
|
||||
r6 = COMPAT_TEXTURE(Source, r2.zw);
|
||||
r2 = COMPAT_TEXTURE(Source, r2.xy);
|
||||
r2.xyz = (r2 * c3.zzzz).xyz;
|
||||
r1.zw = (r0.xyxy * r0.xyxy).zw;
|
||||
r0.xy = (-r0.yyyy + c5).xy;
|
||||
r0.xy = (r0 * r0).xy;
|
||||
r0.xy = (r0 * c6.yyyy).xy;
|
||||
r1.zw = (r1 * c6.xyxy).zw;
|
||||
r1.z = pow(2, r1.z);
|
||||
r1.w = pow(2, r1.w);
|
||||
r6.xyz = (r6 * r1.zzzz).xyz;
|
||||
r5.xyz = (r6 * c3.zzzz + r5).xyz;
|
||||
r6 = COMPAT_TEXTURE(Source, r3.xy);
|
||||
r3 = COMPAT_TEXTURE(Source, r3.zw);
|
||||
r3.xyz = (r3 * c3.zzzz).xyz;
|
||||
r2.w = pow(2, r9.y);
|
||||
r3.w = pow(2, r9.w);
|
||||
r6.xyz = (r6 * r2.wwww).xyz;
|
||||
r5.xyz = (r6 * c3.zzzz + r5).xyz;
|
||||
r3.xyz = (r3 * r3.wwww + r5).xyz;
|
||||
r0.w = r0.w + r1.z;
|
||||
r0.w = r2.w + r0.w;
|
||||
r0.w = r3.w + r0.w;
|
||||
r0.w = 1.0 / r0.w;
|
||||
r3.xyz = (r0.wwww * r3).xyz;
|
||||
r3.xyz = (r1.wwww * r3).xyz;
|
||||
r5 = COMPAT_TEXTURE(Source, r4.xy);
|
||||
r4 = COMPAT_TEXTURE(Source, r4.zw);
|
||||
r4.xyz = (r1.zzzz * r4).xyz;
|
||||
r4.xyz = (r4 * c3.zzzz).xyz;
|
||||
r5.xyz = (r5 * c3.zzzz).xyz;
|
||||
r5.xyz = (r1.zzzz * r5).xyz;
|
||||
r0.w = r0.z + r1.z;
|
||||
r0.w = r2.w + r0.w;
|
||||
r0.w = 1.0 / r0.w;
|
||||
r5.xyz = (r8 * r0.zzzz + r5).xyz;
|
||||
r2.xyz = (r2 * r2.wwww + r5).xyz;
|
||||
r2.xyz = (r0.wwww * r2).xyz;
|
||||
r0.x = pow(2, r0.x);
|
||||
r0.y = pow(2, r0.y);
|
||||
r2.xyz = (r2 * r0.xxxx + r3).xyz;
|
||||
r3 = COMPAT_TEXTURE(Source, r7.xy);
|
||||
r5 = COMPAT_TEXTURE(Source, r7.zw);
|
||||
r5.xyz = (r2.wwww * r5).xyz;
|
||||
r3.xyz = (r0.zzzz * r3).xyz;
|
||||
r3.xyz = (r3 * c3.zzzz + r4).xyz;
|
||||
r3.xyz = (r5 * c3.zzzz + r3).xyz;
|
||||
r0.xzw = (r0.wwww * r3.xyyz).xzw;
|
||||
r0.xyz = (r0.xzww * r0.yyyy + r2).xyz;
|
||||
r1.zw = fract(r1.xyxy).zw;
|
||||
r1.xy = (-r1.zwzw + r1).xy;
|
||||
r1.xy = (r1 + c3.yyyy).xy;
|
||||
r0.w = (r1.y * -c4.w + r1.x);
|
||||
r0.w = r0.w * c6.w;
|
||||
r0.w = fract(r0.w);
|
||||
r1.xy = (r0.wwww + c7).xy;
|
||||
r2.yz = (r1.y >= 0 ? c7.xzww : c7.xwzw).yz;
|
||||
r2.x = c8.w;
|
||||
r1.xyz = (r1.x >= 0 ? r2 : c7.wzzw).xyz;
|
||||
r1.xyz = (r0 * r1).xyz;
|
||||
r2.z = c6.z;
|
||||
r0.w = r2.z + -c2.y;
|
||||
FragColor.xyz = (r0.w >= 0 ? r0 : r1).xyz;
|
||||
FragColor.w = -c3.x;
|
||||
}
|
||||
#endif
|
239
contrib/glshaders/yeetron.glsl
Normal file
239
contrib/glshaders/yeetron.glsl
Normal file
@@ -0,0 +1,239 @@
|
||||
#version 120
|
||||
|
||||
// ported from ReShade
|
||||
|
||||
#if defined(VERTEX)
|
||||
|
||||
#if __VERSION__ >= 130
|
||||
#define COMPAT_VARYING out
|
||||
#define COMPAT_ATTRIBUTE in
|
||||
#define COMPAT_TEXTURE texture
|
||||
#else
|
||||
#define COMPAT_VARYING varying
|
||||
#define COMPAT_ATTRIBUTE attribute
|
||||
#define COMPAT_TEXTURE texture2D
|
||||
#endif
|
||||
|
||||
#ifdef GL_ES
|
||||
#define COMPAT_PRECISION mediump
|
||||
#else
|
||||
#define COMPAT_PRECISION
|
||||
#endif
|
||||
|
||||
COMPAT_ATTRIBUTE vec4 a_position;
|
||||
COMPAT_ATTRIBUTE vec4 COLOR;
|
||||
COMPAT_ATTRIBUTE vec4 TexCoord;
|
||||
COMPAT_VARYING vec4 COL0;
|
||||
COMPAT_VARYING vec2 v_texCoord;
|
||||
|
||||
vec4 _oPosition1;
|
||||
uniform mat4 MVPMatrix;
|
||||
uniform COMPAT_PRECISION int FrameDirection;
|
||||
uniform COMPAT_PRECISION int rubyFrameCount;
|
||||
uniform COMPAT_PRECISION vec2 rubyOutputSize;
|
||||
uniform COMPAT_PRECISION vec2 rubyTextureSize;
|
||||
uniform COMPAT_PRECISION vec2 rubyInputSize;
|
||||
|
||||
// compatibility #defines
|
||||
#define vTexCoord v_texCoord.xy
|
||||
#define SourceSize vec4(rubyTextureSize, 1.0 / rubyTextureSize) //either rubyTextureSize or rubyInputSize
|
||||
#define OutSize vec4(rubyOutputSize, 1.0 / rubyOutputSize)
|
||||
|
||||
void main()
|
||||
{
|
||||
gl_Position = a_position;
|
||||
v_texCoord = vec2(a_position.x + 1.0, 1.0 - a_position.y) / 2.0 * rubyInputSize / rubyTextureSize;
|
||||
}
|
||||
|
||||
#elif defined(FRAGMENT)
|
||||
|
||||
#ifdef GL_ES
|
||||
#ifdef GL_FRAGMENT_PRECISION_HIGH
|
||||
precision highp float;
|
||||
#else
|
||||
precision mediump float;
|
||||
#endif
|
||||
#define COMPAT_PRECISION mediump
|
||||
#else
|
||||
#define COMPAT_PRECISION
|
||||
#endif
|
||||
|
||||
#if __VERSION__ >= 130
|
||||
#define COMPAT_VARYING in
|
||||
#define COMPAT_TEXTURE texture
|
||||
out COMPAT_PRECISION vec4 FragColor;
|
||||
#else
|
||||
#define COMPAT_VARYING varying
|
||||
#define FragColor gl_FragColor
|
||||
#define COMPAT_TEXTURE texture2D
|
||||
#endif
|
||||
|
||||
uniform COMPAT_PRECISION int FrameDirection;
|
||||
uniform COMPAT_PRECISION int rubyFrameCount;
|
||||
uniform COMPAT_PRECISION vec2 rubyOutputSize;
|
||||
uniform COMPAT_PRECISION vec2 rubyTextureSize;
|
||||
uniform COMPAT_PRECISION vec2 rubyInputSize;
|
||||
uniform sampler2D rubyTexture;
|
||||
COMPAT_VARYING vec2 v_texCoord;
|
||||
|
||||
// compatibility #defines
|
||||
#define Source rubyTexture
|
||||
#define vTexCoord v_texCoord.xy
|
||||
|
||||
#define SourceSize vec4(rubyTextureSize, 1.0 / rubyTextureSize) //either rubyTextureSize or rubyInputSize
|
||||
#define OutSize vec4(rubyOutputSize, 1.0 / rubyOutputSize)
|
||||
|
||||
/*
|
||||
The following code allows the shader to override any texture filtering
|
||||
configured in DOSBox. if 'output' is set to 'opengl', bilinear filtering
|
||||
will be enabled and OPENGLNB will not be defined, if 'output' is set to
|
||||
'openglnb', nearest neighbour filtering will be enabled and OPENGLNB will
|
||||
be defined.
|
||||
|
||||
If you wish to use the default filtering method that is currently enabled
|
||||
in DOSBox, use COMPAT_TEXTURE to lookup a texel from the input texture.
|
||||
|
||||
If you wish to force nearest-neighbor interpolation use NN_TEXTURE.
|
||||
|
||||
If you wish to force bilinear interpolation use BL_TEXTURE.
|
||||
|
||||
If DOSBox is configured to use the filtering method that is being forced,
|
||||
the default hardware implementation will be used, otherwise the custom
|
||||
implementations below will be used instead.
|
||||
|
||||
These custom implemenations rely on the `rubyTextureSize` uniform variable.
|
||||
The code could calculate the texture size from the sampler using the
|
||||
textureSize() GLSL function, but this would require a minimum of GLSL
|
||||
version 130, which may prevent the shader from working on older systems.
|
||||
*/
|
||||
|
||||
#if defined(OPENGLNB)
|
||||
#define NN_TEXTURE COMPAT_TEXTURE
|
||||
#define BL_TEXTURE blTexture
|
||||
vec4 blTexture(in sampler2D sampler, in vec2 uv)
|
||||
{
|
||||
// subtract 0.5 here and add it again after the floor to centre the texel
|
||||
vec2 texCoord = uv * rubyTextureSize - vec2(0.5);
|
||||
vec2 s0t0 = floor(texCoord) + vec2(0.5);
|
||||
vec2 s0t1 = s0t0 + vec2(0.0, 1.0);
|
||||
vec2 s1t0 = s0t0 + vec2(1.0, 0.0);
|
||||
vec2 s1t1 = s0t0 + vec2(1.0);
|
||||
|
||||
vec2 invTexSize = 1.0 / rubyTextureSize;
|
||||
vec4 c_s0t0 = COMPAT_TEXTURE(sampler, s0t0 * invTexSize);
|
||||
vec4 c_s0t1 = COMPAT_TEXTURE(sampler, s0t1 * invTexSize);
|
||||
vec4 c_s1t0 = COMPAT_TEXTURE(sampler, s1t0 * invTexSize);
|
||||
vec4 c_s1t1 = COMPAT_TEXTURE(sampler, s1t1 * invTexSize);
|
||||
|
||||
vec2 weight = fract(texCoord);
|
||||
|
||||
vec4 c0 = c_s0t0 + (c_s1t0 - c_s0t0) * weight.x;
|
||||
vec4 c1 = c_s0t1 + (c_s1t1 - c_s0t1) * weight.x;
|
||||
|
||||
return (c0 + (c1 - c0) * weight.y);
|
||||
}
|
||||
#else
|
||||
#define BL_TEXTURE COMPAT_TEXTURE
|
||||
#define NN_TEXTURE nnTexture
|
||||
vec4 nnTexture(in sampler2D sampler, in vec2 uv)
|
||||
{
|
||||
vec2 texCoord = floor(uv * rubyTextureSize) + vec2(0.5);
|
||||
vec2 invTexSize = 1.0 / rubyTextureSize;
|
||||
return COMPAT_TEXTURE(sampler, texCoord * invTexSize);
|
||||
}
|
||||
#endif
|
||||
|
||||
vec4 cmp(vec4 src0, vec4 src1, vec4 src2) {
|
||||
return vec4(
|
||||
src0.x >= 0 ? src1.x : src2.x,
|
||||
src0.y >= 0 ? src1.y : src2.y,
|
||||
src0.z >= 0 ? src1.z : src2.z,
|
||||
src0.w >= 0 ? src1.w : src2.w
|
||||
);
|
||||
}
|
||||
|
||||
#define saturate(c) clamp(c, 0.0, 1.0)
|
||||
|
||||
void main()
|
||||
{
|
||||
//Declare parameters
|
||||
//pixelSize
|
||||
vec4 c0 = rubyInputSize.xyyy;
|
||||
//textureSize
|
||||
vec4 c1 = SourceSize;
|
||||
//viewSize
|
||||
vec4 c2 = OutSize;
|
||||
|
||||
//Declare constants
|
||||
const vec4 c3 = vec4(1.5, 0.800000012, 1.25, 0.75);
|
||||
const vec4 c4 = vec4(6.28318548, -3.14159274, 0.25, -0.25);
|
||||
const vec4 c5 = vec4(1., 0.5, 720., 3.);
|
||||
const vec4 c6 = vec4(0.166666672, -0.333000004, -0.666000009, 0.899999976);
|
||||
const vec4 c7 = vec4(0.899999976, 1.10000002, 0., 0.);
|
||||
const vec4 c8 = vec4(-0.5, -0.25, 2., 0.5);
|
||||
|
||||
//Declare registers
|
||||
vec4 r0, r1, r2, r3, r4, r5, r6, r7, r8, r9;
|
||||
|
||||
//Code starts here
|
||||
vec4 v0 = vTexCoord.xyyy;
|
||||
//dcl_2d s0
|
||||
r0.x = 1.0 / c0.x;
|
||||
r0.y = 1.0 / c0.y;
|
||||
r0.xy = (r0 * c1).xy;
|
||||
r0.xy = (r0 * v0).xy;
|
||||
r0.xy = (r0 * c2).xy;
|
||||
r0.zw = fract(r0.xyxy).zw;
|
||||
r0.xy = (-r0.zwzw + r0).xy;
|
||||
r0.xy = (r0 + c8.wwww).xy;
|
||||
r0.x = r0.y * c5.w + r0.x;
|
||||
r0.x = r0.x * c6.x;
|
||||
r0.x = fract(r0.x);
|
||||
r0.xy = (r0.xxxx + c6.yzzw).xy;
|
||||
r1.yz = (r0.y >= 0 ? c7.xxyw : c7.xyxw).yz;
|
||||
r1.x = c6.w;
|
||||
r0.xyz = (r0.x >= 0 ? r1 : c7.yxxw).xyz;
|
||||
r1.xy = (c1 * v0).xy;
|
||||
r0.w = r1.y * c8.w + c8.w;
|
||||
r0.w = fract(r0.w);
|
||||
r0.w = r0.w * c4.x + c4.y;
|
||||
r2.y = sin(r0.w);
|
||||
r1.zw = (abs(r2).yyyy + c4).zw;
|
||||
r1.z = clamp(r1.z, 0.0, 1.0);
|
||||
r0.w = r1.w >= 0 ? r1.z : c8.w;
|
||||
r2 = fract(r1.xyxy);
|
||||
r1.xy = (r1 + -r2.zwzw).xy;
|
||||
r2 = r2 + c8.xxyy;
|
||||
r1.zw = (r1.xyxy + c8.wwww).zw;
|
||||
r1.zw = (v0.xyxy * -c1.xyxy + r1).zw;
|
||||
r1.w = r1.w + r1.w;
|
||||
r1.z = r1.z * c8.w;
|
||||
r1.z = -abs(r1).z + c3.x;
|
||||
r3.x = max(c3.y, r1.z);
|
||||
r4.x = min(r3.x, c3.z);
|
||||
r1.zw = (-abs(r1).wwww + c3).zw;
|
||||
r1.z = clamp(r1.z, 0.0, 1.0);
|
||||
r1.z = r1.w >= 0 ? r1.z : c8.w;
|
||||
r4.y = r0.w + r1.z;
|
||||
r0.w = r0.w * r4.x;
|
||||
r1.z = r1.z * r4.x;
|
||||
r3.xy = (r4 * c5).xy;
|
||||
r1.w = r3.y * r3.x;
|
||||
r2.z = cmp(r2, r2.xyxy, c8.yyyy).z;
|
||||
r3.xy = max(c8.yyyy, -r2.zwzw).xy;
|
||||
r2.xy = (r2 + r3).xy;
|
||||
r1.xy = (r2 * c8.zzzz + r1).xy;
|
||||
r1.xy = (r1 + c8.wwww).xy;
|
||||
r2.x = 1.0 / c1.x;
|
||||
r2.y = 1.0 / c1.y;
|
||||
r1.xy = (r1 * r2).xy;
|
||||
r2 = NN_TEXTURE(Source, r1.xy);
|
||||
r3.x = r0.w * r2.x;
|
||||
r3.yz = (r1.xzww * r2).yz;
|
||||
FragColor.w = r2.w;
|
||||
r0.xyz = (r0 * r3).xyz;
|
||||
r1.z = c5.z;
|
||||
r0.w = r1.z + -c2.y;
|
||||
FragColor.xyz = (r0.w >= 0 ? r3 : r0).xyz;
|
||||
}
|
||||
#endif
|
262
contrib/glshaders/zfast_crt.glsl
Normal file
262
contrib/glshaders/zfast_crt.glsl
Normal file
@@ -0,0 +1,262 @@
|
||||
#version 120
|
||||
|
||||
/*
|
||||
zfast_crt_standard - A simple, fast CRT shader.
|
||||
|
||||
Copyright (C) 2017 Greg Hogan (SoltanGris42)
|
||||
|
||||
This program is free software; you can redistribute it and/or modify it
|
||||
under the terms of the GNU General Public License as published by the Free
|
||||
Software Foundation; either version 2 of the License, or (at your option)
|
||||
any later version.
|
||||
|
||||
|
||||
Notes: This shader does scaling with a weighted linear filter for adjustable
|
||||
sharpness on the x and y axes based on the algorithm by Inigo Quilez here:
|
||||
http://http://www.iquilezles.org/www/articles/texture/texture.htm
|
||||
but modified to be somewhat sharper. Then a scanline effect that varies
|
||||
based on pixel brighness is applied along with a monochrome aperture mask.
|
||||
This shader runs at 60fps on the Raspberry Pi 3 hardware at 2mpix/s
|
||||
resolutions (1920x1080 or 1600x1200).
|
||||
*/
|
||||
|
||||
//For testing compilation
|
||||
//#define FRAGMENT
|
||||
//#define VERTEX
|
||||
|
||||
//This can't be an option without slowing the shader down
|
||||
//Comment this out for a coarser 3 pixel mask...which is currently broken
|
||||
//on SNES Classic Edition due to Mali 400 gpu precision
|
||||
#define FINEMASK
|
||||
|
||||
//Some drivers don't return black with texture coordinates out of bounds
|
||||
//SNES Classic is too slow to black these areas out when using fullscreen
|
||||
//overlays. But you can uncomment the below to black them out if necessary
|
||||
//#define BLACK_OUT_BORDER
|
||||
|
||||
// Parameter lines go here:
|
||||
#pragma parameter BLURSCALEX "Blur Amount X-Axis" 0.30 0.0 1.0 0.05
|
||||
#pragma parameter LOWLUMSCAN "Scanline Darkness - Low" 6.0 0.0 10.0 0.5
|
||||
#pragma parameter HILUMSCAN "Scanline Darkness - High" 8.0 0.0 50.0 1.0
|
||||
#pragma parameter BRIGHTBOOST "Dark Pixel Brightness Boost" 1.25 0.5 1.5 0.05
|
||||
#pragma parameter MASK_DARK "Mask Effect Amount" 0.25 0.0 1.0 0.05
|
||||
#pragma parameter MASK_FADE "Mask/Scanline Fade" 0.8 0.0 1.0 0.05
|
||||
|
||||
#if defined(VERTEX)
|
||||
|
||||
#if __VERSION__ >= 130
|
||||
#define COMPAT_VARYING out
|
||||
#define COMPAT_ATTRIBUTE in
|
||||
#define COMPAT_TEXTURE texture
|
||||
#else
|
||||
#define COMPAT_VARYING varying
|
||||
#define COMPAT_ATTRIBUTE attribute
|
||||
#define COMPAT_TEXTURE texture2D
|
||||
#endif
|
||||
|
||||
#ifdef GL_ES
|
||||
#define COMPAT_PRECISION mediump
|
||||
#else
|
||||
#define COMPAT_PRECISION
|
||||
#endif
|
||||
|
||||
COMPAT_ATTRIBUTE vec4 a_position;
|
||||
COMPAT_ATTRIBUTE vec4 COLOR;
|
||||
COMPAT_ATTRIBUTE vec4 TexCoord;
|
||||
COMPAT_VARYING vec4 COL0;
|
||||
COMPAT_VARYING vec2 v_texCoord;
|
||||
COMPAT_VARYING float maskFade;
|
||||
COMPAT_VARYING vec2 invDims;
|
||||
|
||||
vec4 _oPosition1;
|
||||
uniform mat4 MVPMatrix;
|
||||
uniform COMPAT_PRECISION int FrameDirection;
|
||||
uniform COMPAT_PRECISION int rubyFrameCount;
|
||||
uniform COMPAT_PRECISION vec2 rubyOutputSize;
|
||||
uniform COMPAT_PRECISION vec2 rubyTextureSize;
|
||||
uniform COMPAT_PRECISION vec2 rubyInputSize;
|
||||
|
||||
// compatibility #defines
|
||||
#define vTexCoord v_texCoord.xy
|
||||
#define SourceSize vec4(rubyTextureSize, 1.0 / rubyTextureSize) //either rubyTextureSize or rubyInputSize
|
||||
#define OutSize vec4(rubyOutputSize, 1.0 / rubyOutputSize)
|
||||
|
||||
#ifdef PARAMETER_UNIFORM
|
||||
// All parameter floats need to have COMPAT_PRECISION in front of them
|
||||
uniform COMPAT_PRECISION float BLURSCALEX;
|
||||
//uniform COMPAT_PRECISION float BLURSCALEY;
|
||||
uniform COMPAT_PRECISION float LOWLUMSCAN;
|
||||
uniform COMPAT_PRECISION float HILUMSCAN;
|
||||
uniform COMPAT_PRECISION float BRIGHTBOOST;
|
||||
uniform COMPAT_PRECISION float MASK_DARK;
|
||||
uniform COMPAT_PRECISION float MASK_FADE;
|
||||
#else
|
||||
#define BLURSCALEX 0.45
|
||||
//#define BLURSCALEY 0.20
|
||||
#define LOWLUMSCAN 5.0
|
||||
#define HILUMSCAN 10.0
|
||||
#define BRIGHTBOOST 1.25
|
||||
#define MASK_DARK 0.25
|
||||
#define MASK_FADE 0.8
|
||||
#endif
|
||||
|
||||
void main()
|
||||
{
|
||||
gl_Position = a_position;
|
||||
v_texCoord = vec2(a_position.x + 1.0, 1.0 - a_position.y) / 2.0 * rubyInputSize / rubyTextureSize;
|
||||
|
||||
maskFade = 0.3333*MASK_FADE;
|
||||
invDims = 1.0/rubyTextureSize.xy;
|
||||
}
|
||||
|
||||
#elif defined(FRAGMENT)
|
||||
|
||||
#ifdef GL_ES
|
||||
#ifdef GL_FRAGMENT_PRECISION_HIGH
|
||||
precision highp float;
|
||||
#else
|
||||
precision mediump float;
|
||||
#endif
|
||||
#define COMPAT_PRECISION mediump
|
||||
#else
|
||||
#define COMPAT_PRECISION
|
||||
#endif
|
||||
|
||||
#if __VERSION__ >= 130
|
||||
#define COMPAT_VARYING in
|
||||
#define COMPAT_TEXTURE texture
|
||||
out COMPAT_PRECISION vec4 FragColor;
|
||||
#else
|
||||
#define COMPAT_VARYING varying
|
||||
#define FragColor gl_FragColor
|
||||
#define COMPAT_TEXTURE texture2D
|
||||
#endif
|
||||
|
||||
uniform COMPAT_PRECISION int FrameDirection;
|
||||
uniform COMPAT_PRECISION int rubyFrameCount;
|
||||
uniform COMPAT_PRECISION vec2 rubyOutputSize;
|
||||
uniform COMPAT_PRECISION vec2 rubyTextureSize;
|
||||
uniform COMPAT_PRECISION vec2 rubyInputSize;
|
||||
uniform sampler2D rubyTexture;
|
||||
COMPAT_VARYING vec2 v_texCoord;
|
||||
COMPAT_VARYING float maskFade;
|
||||
COMPAT_VARYING vec2 invDims;
|
||||
|
||||
// compatibility #defines
|
||||
#define Source rubyTexture
|
||||
#define vTexCoord v_texCoord.xy
|
||||
#define texture(c, d) COMPAT_TEXTURE(c, d)
|
||||
#define SourceSize vec4(rubyTextureSize, 1.0 / rubyTextureSize) //either rubyTextureSize or rubyInputSize
|
||||
#define OutSize vec4(rubyOutputSize, 1.0 / rubyOutputSize)
|
||||
|
||||
#ifdef PARAMETER_UNIFORM
|
||||
// All parameter floats need to have COMPAT_PRECISION in front of them
|
||||
uniform COMPAT_PRECISION float BLURSCALEX;
|
||||
//uniform COMPAT_PRECISION float BLURSCALEY;
|
||||
uniform COMPAT_PRECISION float LOWLUMSCAN;
|
||||
uniform COMPAT_PRECISION float HILUMSCAN;
|
||||
uniform COMPAT_PRECISION float BRIGHTBOOST;
|
||||
uniform COMPAT_PRECISION float MASK_DARK;
|
||||
uniform COMPAT_PRECISION float MASK_FADE;
|
||||
#else
|
||||
#define BLURSCALEX 0.45
|
||||
//#define BLURSCALEY 0.20
|
||||
#define LOWLUMSCAN 5.0
|
||||
#define HILUMSCAN 10.0
|
||||
#define BRIGHTBOOST 1.25
|
||||
#define MASK_DARK 0.25
|
||||
#define MASK_FADE 0.8
|
||||
#endif
|
||||
|
||||
/*
|
||||
The following code allows the shader to override any texture filtering
|
||||
configured in DOSBox. if 'output' is set to 'opengl', bilinear filtering
|
||||
will be enabled and OPENGLNB will not be defined, if 'output' is set to
|
||||
'openglnb', nearest neighbour filtering will be enabled and OPENGLNB will
|
||||
be defined.
|
||||
|
||||
If you wish to use the default filtering method that is currently enabled
|
||||
in DOSBox, use COMPAT_TEXTURE to lookup a texel from the input texture.
|
||||
|
||||
If you wish to force nearest-neighbor interpolation use NN_TEXTURE.
|
||||
|
||||
If you wish to force bilinear interpolation use BL_TEXTURE.
|
||||
|
||||
If DOSBox is configured to use the filtering method that is being forced,
|
||||
the default hardware implementation will be used, otherwise the custom
|
||||
implementations below will be used instead.
|
||||
|
||||
These custom implemenations rely on the `rubyTextureSize` uniform variable.
|
||||
The code could calculate the texture size from the sampler using the
|
||||
textureSize() GLSL function, but this would require a minimum of GLSL
|
||||
version 130, which may prevent the shader from working on older systems.
|
||||
*/
|
||||
|
||||
#if defined(OPENGLNB)
|
||||
#define NN_TEXTURE COMPAT_TEXTURE
|
||||
#define BL_TEXTURE blTexture
|
||||
vec4 blTexture(in sampler2D sampler, in vec2 uv)
|
||||
{
|
||||
// subtract 0.5 here and add it again after the floor to centre the texel
|
||||
vec2 texCoord = uv * rubyTextureSize - vec2(0.5);
|
||||
vec2 s0t0 = floor(texCoord) + vec2(0.5);
|
||||
vec2 s0t1 = s0t0 + vec2(0.0, 1.0);
|
||||
vec2 s1t0 = s0t0 + vec2(1.0, 0.0);
|
||||
vec2 s1t1 = s0t0 + vec2(1.0);
|
||||
|
||||
vec2 invTexSize = 1.0 / rubyTextureSize;
|
||||
vec4 c_s0t0 = COMPAT_TEXTURE(sampler, s0t0 * invTexSize);
|
||||
vec4 c_s0t1 = COMPAT_TEXTURE(sampler, s0t1 * invTexSize);
|
||||
vec4 c_s1t0 = COMPAT_TEXTURE(sampler, s1t0 * invTexSize);
|
||||
vec4 c_s1t1 = COMPAT_TEXTURE(sampler, s1t1 * invTexSize);
|
||||
|
||||
vec2 weight = fract(texCoord);
|
||||
|
||||
vec4 c0 = c_s0t0 + (c_s1t0 - c_s0t0) * weight.x;
|
||||
vec4 c1 = c_s0t1 + (c_s1t1 - c_s0t1) * weight.x;
|
||||
|
||||
return (c0 + (c1 - c0) * weight.y);
|
||||
}
|
||||
#else
|
||||
#define BL_TEXTURE COMPAT_TEXTURE
|
||||
#define NN_TEXTURE nnTexture
|
||||
vec4 nnTexture(in sampler2D sampler, in vec2 uv)
|
||||
{
|
||||
vec2 texCoord = floor(uv * rubyTextureSize) + vec2(0.5);
|
||||
vec2 invTexSize = 1.0 / rubyTextureSize;
|
||||
return COMPAT_TEXTURE(sampler, texCoord * invTexSize);
|
||||
}
|
||||
#endif
|
||||
|
||||
void main()
|
||||
{
|
||||
|
||||
//This is just like "Quilez Scaling" but sharper
|
||||
COMPAT_PRECISION vec2 p = vTexCoord * rubyTextureSize;
|
||||
COMPAT_PRECISION vec2 i = floor(p) + 0.50;
|
||||
COMPAT_PRECISION vec2 f = p - i;
|
||||
p = (i + 4.0*f*f*f)*invDims;
|
||||
p.x = mix( p.x , vTexCoord.x, BLURSCALEX);
|
||||
COMPAT_PRECISION float Y = f.y*f.y;
|
||||
COMPAT_PRECISION float YY = Y*Y;
|
||||
|
||||
#if defined(FINEMASK)
|
||||
COMPAT_PRECISION float whichmask = fract( gl_FragCoord.x*-0.4999);
|
||||
COMPAT_PRECISION float mask = 1.0 + float(whichmask < 0.5) * -MASK_DARK;
|
||||
#else
|
||||
COMPAT_PRECISION float whichmask = fract(gl_FragCoord.x * -0.3333);
|
||||
COMPAT_PRECISION float mask = 1.0 + float(whichmask <= 0.33333) * -MASK_DARK;
|
||||
#endif
|
||||
COMPAT_PRECISION vec3 colour = BL_TEXTURE(Source, p).rgb;
|
||||
|
||||
COMPAT_PRECISION float scanLineWeight = (BRIGHTBOOST - LOWLUMSCAN*(Y - 2.05*YY));
|
||||
COMPAT_PRECISION float scanLineWeightB = 1.0 - HILUMSCAN*(YY-2.8*YY*Y);
|
||||
|
||||
#if defined(BLACK_OUT_BORDER)
|
||||
colour.rgb*=float(tc.x > 0.0)*float(tc.y > 0.0); //why doesn't the driver do the right thing?
|
||||
#endif
|
||||
|
||||
FragColor.rgb = colour.rgb*mix(scanLineWeight*mask, scanLineWeightB, dot(colour.rgb,vec3(maskFade)));
|
||||
|
||||
}
|
||||
#endif
|
@@ -67,7 +67,8 @@ Source: ".\dosbox-x.reference.conf"; DestDir: "{app}"; Flags: ignoreversion; Com
|
||||
Source: "..\..\..\CHANGELOG"; DestDir: "{app}"; DestName: "changelog.txt"; Flags: ignoreversion; Components: full compact
|
||||
Source: "..\..\..\COPYING"; DestDir: "{app}"; DestName: "COPYING.txt"; Flags: ignoreversion; Components: full compact
|
||||
Source: "..\..\fonts\FREECG98.BMP"; DestDir: "{app}"; Flags: ignoreversion; Components: full compact
|
||||
Source: "..\..\shaders\*"; DestDir: "{app}\shaders"; Flags: ignoreversion recursesubdirs createallsubdirs; Components: full compact
|
||||
Source: "..\..\glshaders\*"; DestDir: "{app}\glshaders"; Flags: ignoreversion recursesubdirs createallsubdirs; Components: full compact
|
||||
Source: "..\shaders\*"; DestDir: "{app}\shaders"; Flags: ignoreversion recursesubdirs createallsubdirs; Components: full compact
|
||||
Source: "Win32_builds\x86_Release\dosbox-x.exe"; DestDir: "{app}"; Flags: ignoreversion; Check: CheckDirName('Win32_builds\x86_Release'); Components: full compact
|
||||
Source: "Win32_builds\x86_Release_SDL2\dosbox-x.exe"; DestDir: "{app}"; Flags: ignoreversion; Check: CheckDirName('Win32_builds\x86_Release_SDL2'); Components: full compact
|
||||
Source: "Win32_builds\ARM_Release\dosbox-x.exe"; DestDir: "{app}"; Flags: ignoreversion; Check: CheckDirName('Win32_builds\ARM_Release'); Components: full compact
|
||||
|
@@ -1169,13 +1169,15 @@ void RENDER_Init() {
|
||||
render.shader_src = NULL;
|
||||
render.shader_def = f=="default";
|
||||
} else if (!RENDER_GetShader(sh->realpath,shader_src)) {
|
||||
std::string path;
|
||||
Cross::GetPlatformConfigDir(path);
|
||||
path = path + "glshaders" + CROSS_FILESPLIT + f;
|
||||
if (!RENDER_GetShader(path,shader_src) && (sh->realpath==f || !RENDER_GetShader(f,shader_src))) {
|
||||
sh->SetValue("none");
|
||||
LOG_MSG("Shader file \"%s\" not found", f.c_str());
|
||||
}
|
||||
std::string path = std::string("glshaders") + CROSS_FILESPLIT + f;
|
||||
if (!RENDER_GetShader(path,shader_src)) {
|
||||
Cross::GetPlatformConfigDir(path);
|
||||
path = path + "glshaders" + CROSS_FILESPLIT + f;
|
||||
if (!RENDER_GetShader(path,shader_src) && (sh->realpath==f || !RENDER_GetShader(f,shader_src))) {
|
||||
sh->SetValue("none");
|
||||
LOG_MSG("Shader file \"%s\" not found", f.c_str());
|
||||
}
|
||||
}
|
||||
} else
|
||||
LOG_MSG("Loaded GLSL shader: %s\n", f.c_str());
|
||||
if (shader_src!=render.shader_src) free(shader_src);
|
||||
|
@@ -350,8 +350,8 @@
|
||||
<Command>copy "$(SolutionDir)\..\contrib\fonts\FREECG98.BMP" "$(OutputPath)\FREECG98.BMP"
|
||||
copy "$(SolutionDir)\..\dosbox-x.reference.conf" "$(OutputPath)\dosbox-x.reference.conf"
|
||||
copy "$(SolutionDir)\..\CHANGELOG" "$(OutputPath)\changelog.txt"
|
||||
mkdir "$(OutputPath)\shaders"
|
||||
copy "$(SolutionDir)\..\contrib\shaders\*.*" "$(OutputPath)\shaders\"</Command>
|
||||
if not exist "$(OutputPath)\shaders\" mkdir "$(OutputPath)\shaders"
|
||||
copy "$(SolutionDir)\..\contrib\windows\shaders\*.*" "$(OutputPath)\shaders\"</Command>
|
||||
</PostBuildEvent>
|
||||
<PostBuildEvent>
|
||||
<Message>
|
||||
@@ -384,8 +384,8 @@ copy "$(SolutionDir)\..\contrib\shaders\*.*" "$(OutputPath)\shaders\"</Command>
|
||||
<Command>copy "$(SolutionDir)\..\contrib\fonts\FREECG98.BMP" "$(OutputPath)\FREECG98.BMP"
|
||||
copy "$(SolutionDir)\..\dosbox-x.reference.conf" "$(OutputPath)\dosbox-x.reference.conf"
|
||||
copy "$(SolutionDir)\..\CHANGELOG" "$(OutputPath)\changelog.txt"
|
||||
mkdir "$(OutputPath)\shaders"
|
||||
copy "$(SolutionDir)\..\contrib\shaders\*.*" "$(OutputPath)\shaders\"</Command>
|
||||
if not exist "$(OutputPath)\shaders\" mkdir "$(OutputPath)\shaders"
|
||||
copy "$(SolutionDir)\..\contrib\windows\shaders\*.*" "$(OutputPath)\shaders\"</Command>
|
||||
</PostBuildEvent>
|
||||
<PostBuildEvent>
|
||||
<Message>
|
||||
@@ -414,8 +414,8 @@ copy "$(SolutionDir)\..\contrib\shaders\*.*" "$(OutputPath)\shaders\"</Command>
|
||||
<Command>copy "$(SolutionDir)\..\contrib\fonts\FREECG98.BMP" "$(OutputPath)\FREECG98.BMP"
|
||||
copy "$(SolutionDir)\..\dosbox-x.reference.conf" "$(OutputPath)\dosbox-x.reference.conf"
|
||||
copy "$(SolutionDir)\..\CHANGELOG" "$(OutputPath)\changelog.txt"
|
||||
mkdir "$(OutputPath)\shaders"
|
||||
copy "$(SolutionDir)\..\contrib\shaders\*.*" "$(OutputPath)\shaders\"</Command>
|
||||
if not exist "$(OutputPath)\shaders\" mkdir "$(OutputPath)\shaders"
|
||||
copy "$(SolutionDir)\..\contrib\windows\shaders\*.*" "$(OutputPath)\shaders\"</Command>
|
||||
<Message>
|
||||
</Message>
|
||||
</PostBuildEvent>
|
||||
@@ -445,8 +445,8 @@ copy "$(SolutionDir)\..\contrib\shaders\*.*" "$(OutputPath)\shaders\"</Command>
|
||||
<Command>copy "$(SolutionDir)\..\contrib\fonts\FREECG98.BMP" "$(OutputPath)\FREECG98.BMP"
|
||||
copy "$(SolutionDir)\..\dosbox-x.reference.conf" "$(OutputPath)\dosbox-x.reference.conf"
|
||||
copy "$(SolutionDir)\..\CHANGELOG" "$(OutputPath)\changelog.txt"
|
||||
mkdir "$(OutputPath)\shaders"
|
||||
copy "$(SolutionDir)\..\contrib\shaders\*.*" "$(OutputPath)\shaders\"</Command>
|
||||
if not exist "$(OutputPath)\shaders\" mkdir "$(OutputPath)\shaders"
|
||||
copy "$(SolutionDir)\..\contrib\windows\shaders\*.*" "$(OutputPath)\shaders\"</Command>
|
||||
<Message>
|
||||
</Message>
|
||||
</PostBuildEvent>
|
||||
@@ -476,8 +476,8 @@ copy "$(SolutionDir)\..\contrib\shaders\*.*" "$(OutputPath)\shaders\"</Command>
|
||||
<Command>copy "$(SolutionDir)\..\contrib\fonts\FREECG98.BMP" "$(OutputPath)\FREECG98.BMP"
|
||||
copy "$(SolutionDir)\..\dosbox-x.reference.conf" "$(OutputPath)\dosbox-x.reference.conf"
|
||||
copy "$(SolutionDir)\..\CHANGELOG" "$(OutputPath)\changelog.txt"
|
||||
mkdir "$(OutputPath)\shaders"
|
||||
copy "$(SolutionDir)\..\contrib\shaders\*.*" "$(OutputPath)\shaders\"</Command>
|
||||
if not exist "$(OutputPath)\shaders\" mkdir "$(OutputPath)\shaders"
|
||||
copy "$(SolutionDir)\..\contrib\windows\shaders\*.*" "$(OutputPath)\shaders\"</Command>
|
||||
<Message>
|
||||
</Message>
|
||||
</PostBuildEvent>
|
||||
@@ -509,8 +509,8 @@ copy "$(SolutionDir)\..\contrib\shaders\*.*" "$(OutputPath)\shaders\"</Command>
|
||||
<Command>copy "$(SolutionDir)\..\contrib\fonts\FREECG98.BMP" "$(OutputPath)\FREECG98.BMP"
|
||||
copy "$(SolutionDir)\..\dosbox-x.reference.conf" "$(OutputPath)\dosbox-x.reference.conf"
|
||||
copy "$(SolutionDir)\..\CHANGELOG" "$(OutputPath)\changelog.txt"
|
||||
mkdir "$(OutputPath)\shaders"
|
||||
copy "$(SolutionDir)\..\contrib\shaders\*.*" "$(OutputPath)\shaders\"</Command>
|
||||
if not exist "$(OutputPath)\shaders\" mkdir "$(OutputPath)\shaders"
|
||||
copy "$(SolutionDir)\..\contrib\windows\shaders\*.*" "$(OutputPath)\shaders\"</Command>
|
||||
<Message>
|
||||
</Message>
|
||||
</PostBuildEvent>
|
||||
@@ -540,8 +540,8 @@ copy "$(SolutionDir)\..\contrib\shaders\*.*" "$(OutputPath)\shaders\"</Command>
|
||||
<Command>copy "$(SolutionDir)\..\contrib\fonts\FREECG98.BMP" "$(OutputPath)\FREECG98.BMP"
|
||||
copy "$(SolutionDir)\..\dosbox-x.reference.conf" "$(OutputPath)\dosbox-x.reference.conf"
|
||||
copy "$(SolutionDir)\..\CHANGELOG" "$(OutputPath)\changelog.txt"
|
||||
mkdir "$(OutputPath)\shaders"
|
||||
copy "$(SolutionDir)\..\contrib\shaders\*.*" "$(OutputPath)\shaders\"</Command>
|
||||
if not exist "$(OutputPath)\shaders\" mkdir "$(OutputPath)\shaders"
|
||||
copy "$(SolutionDir)\..\contrib\windows\shaders\*.*" "$(OutputPath)\shaders\"</Command>
|
||||
<Message>
|
||||
</Message>
|
||||
</PostBuildEvent>
|
||||
@@ -571,8 +571,8 @@ copy "$(SolutionDir)\..\contrib\shaders\*.*" "$(OutputPath)\shaders\"</Command>
|
||||
<Command>copy "$(SolutionDir)\..\contrib\fonts\FREECG98.BMP" "$(OutputPath)\FREECG98.BMP"
|
||||
copy "$(SolutionDir)\..\dosbox-x.reference.conf" "$(OutputPath)\dosbox-x.reference.conf"
|
||||
copy "$(SolutionDir)\..\CHANGELOG" "$(OutputPath)\changelog.txt"
|
||||
mkdir "$(OutputPath)\shaders"
|
||||
copy "$(SolutionDir)\..\contrib\shaders\*.*" "$(OutputPath)\shaders\"</Command>
|
||||
if not exist "$(OutputPath)\shaders\" mkdir "$(OutputPath)\shaders"
|
||||
copy "$(SolutionDir)\..\contrib\windows\shaders\*.*" "$(OutputPath)\shaders\"</Command>
|
||||
<Message>
|
||||
</Message>
|
||||
</PostBuildEvent>
|
||||
@@ -608,8 +608,8 @@ copy "$(SolutionDir)\..\contrib\shaders\*.*" "$(OutputPath)\shaders\"</Command>
|
||||
<Command>copy "$(SolutionDir)\..\contrib\fonts\FREECG98.BMP" "$(OutputPath)\FREECG98.BMP"
|
||||
copy "$(SolutionDir)\..\dosbox-x.reference.conf" "$(OutputPath)\dosbox-x.reference.conf"
|
||||
copy "$(SolutionDir)\..\CHANGELOG" "$(OutputPath)\changelog.txt"
|
||||
mkdir "$(OutputPath)\shaders"
|
||||
copy "$(SolutionDir)\..\contrib\shaders\*.*" "$(OutputPath)\shaders\"</Command>
|
||||
if not exist "$(OutputPath)\shaders\" mkdir "$(OutputPath)\shaders"
|
||||
copy "$(SolutionDir)\..\contrib\windows\shaders\*.*" "$(OutputPath)\shaders\"</Command>
|
||||
</PostBuildEvent>
|
||||
<PostBuildEvent>
|
||||
<Message>
|
||||
@@ -643,8 +643,8 @@ copy "$(SolutionDir)\..\contrib\shaders\*.*" "$(OutputPath)\shaders\"</Command>
|
||||
<Command>copy "$(SolutionDir)\..\contrib\fonts\FREECG98.BMP" "$(OutputPath)\FREECG98.BMP"
|
||||
copy "$(SolutionDir)\..\dosbox-x.reference.conf" "$(OutputPath)\dosbox-x.reference.conf"
|
||||
copy "$(SolutionDir)\..\CHANGELOG" "$(OutputPath)\changelog.txt"
|
||||
mkdir "$(OutputPath)\shaders"
|
||||
copy "$(SolutionDir)\..\contrib\shaders\*.*" "$(OutputPath)\shaders\"</Command>
|
||||
if not exist "$(OutputPath)\shaders\" mkdir "$(OutputPath)\shaders"
|
||||
copy "$(SolutionDir)\..\contrib\windows\shaders\*.*" "$(OutputPath)\shaders\"</Command>
|
||||
</PostBuildEvent>
|
||||
<PostBuildEvent>
|
||||
<Message>
|
||||
@@ -674,8 +674,8 @@ copy "$(SolutionDir)\..\contrib\shaders\*.*" "$(OutputPath)\shaders\"</Command>
|
||||
<Command>copy "$(SolutionDir)\..\contrib\fonts\FREECG98.BMP" "$(OutputPath)\FREECG98.BMP"
|
||||
copy "$(SolutionDir)\..\dosbox-x.reference.conf" "$(OutputPath)\dosbox-x.reference.conf"
|
||||
copy "$(SolutionDir)\..\CHANGELOG" "$(OutputPath)\changelog.txt"
|
||||
mkdir "$(OutputPath)\shaders"
|
||||
copy "$(SolutionDir)\..\contrib\shaders\*.*" "$(OutputPath)\shaders\"</Command>
|
||||
if not exist "$(OutputPath)\shaders\" mkdir "$(OutputPath)\shaders"
|
||||
copy "$(SolutionDir)\..\contrib\windows\shaders\*.*" "$(OutputPath)\shaders\"</Command>
|
||||
<Message>
|
||||
</Message>
|
||||
</PostBuildEvent>
|
||||
@@ -706,8 +706,8 @@ copy "$(SolutionDir)\..\contrib\shaders\*.*" "$(OutputPath)\shaders\"</Command>
|
||||
<Command>copy "$(SolutionDir)\..\contrib\fonts\FREECG98.BMP" "$(OutputPath)\FREECG98.BMP"
|
||||
copy "$(SolutionDir)\..\dosbox-x.reference.conf" "$(OutputPath)\dosbox-x.reference.conf"
|
||||
copy "$(SolutionDir)\..\CHANGELOG" "$(OutputPath)\changelog.txt"
|
||||
mkdir "$(OutputPath)\shaders"
|
||||
copy "$(SolutionDir)\..\contrib\shaders\*.*" "$(OutputPath)\shaders\"</Command>
|
||||
if not exist "$(OutputPath)\shaders\" mkdir "$(OutputPath)\shaders"
|
||||
copy "$(SolutionDir)\..\contrib\windows\shaders\*.*" "$(OutputPath)\shaders\"</Command>
|
||||
<Message>
|
||||
</Message>
|
||||
</PostBuildEvent>
|
||||
@@ -738,8 +738,8 @@ copy "$(SolutionDir)\..\contrib\shaders\*.*" "$(OutputPath)\shaders\"</Command>
|
||||
<Command>copy "$(SolutionDir)\..\contrib\fonts\FREECG98.BMP" "$(OutputPath)\FREECG98.BMP"
|
||||
copy "$(SolutionDir)\..\dosbox-x.reference.conf" "$(OutputPath)\dosbox-x.reference.conf"
|
||||
copy "$(SolutionDir)\..\CHANGELOG" "$(OutputPath)\changelog.txt"
|
||||
mkdir "$(OutputPath)\shaders"
|
||||
copy "$(SolutionDir)\..\contrib\shaders\*.*" "$(OutputPath)\shaders\"</Command>
|
||||
if not exist "$(OutputPath)\shaders\" mkdir "$(OutputPath)\shaders"
|
||||
copy "$(SolutionDir)\..\contrib\windows\shaders\*.*" "$(OutputPath)\shaders\"</Command>
|
||||
<Message>
|
||||
</Message>
|
||||
</PostBuildEvent>
|
||||
@@ -772,8 +772,8 @@ copy "$(SolutionDir)\..\contrib\shaders\*.*" "$(OutputPath)\shaders\"</Command>
|
||||
<Command>copy "$(SolutionDir)\..\contrib\fonts\FREECG98.BMP" "$(OutputPath)\FREECG98.BMP"
|
||||
copy "$(SolutionDir)\..\dosbox-x.reference.conf" "$(OutputPath)\dosbox-x.reference.conf"
|
||||
copy "$(SolutionDir)\..\CHANGELOG" "$(OutputPath)\changelog.txt"
|
||||
mkdir "$(OutputPath)\shaders"
|
||||
copy "$(SolutionDir)\..\contrib\shaders\*.*" "$(OutputPath)\shaders\"</Command>
|
||||
if not exist "$(OutputPath)\shaders\" mkdir "$(OutputPath)\shaders"
|
||||
copy "$(SolutionDir)\..\contrib\windows\shaders\*.*" "$(OutputPath)\shaders\"</Command>
|
||||
<Message>
|
||||
</Message>
|
||||
</PostBuildEvent>
|
||||
@@ -804,8 +804,8 @@ copy "$(SolutionDir)\..\contrib\shaders\*.*" "$(OutputPath)\shaders\"</Command>
|
||||
<Command>copy "$(SolutionDir)\..\contrib\fonts\FREECG98.BMP" "$(OutputPath)\FREECG98.BMP"
|
||||
copy "$(SolutionDir)\..\dosbox-x.reference.conf" "$(OutputPath)\dosbox-x.reference.conf"
|
||||
copy "$(SolutionDir)\..\CHANGELOG" "$(OutputPath)\changelog.txt"
|
||||
mkdir "$(OutputPath)\shaders"
|
||||
copy "$(SolutionDir)\..\contrib\shaders\*.*" "$(OutputPath)\shaders\"</Command>
|
||||
if not exist "$(OutputPath)\shaders\" mkdir "$(OutputPath)\shaders"
|
||||
copy "$(SolutionDir)\..\contrib\windows\shaders\*.*" "$(OutputPath)\shaders\"</Command>
|
||||
<Message>
|
||||
</Message>
|
||||
</PostBuildEvent>
|
||||
@@ -836,8 +836,8 @@ copy "$(SolutionDir)\..\contrib\shaders\*.*" "$(OutputPath)\shaders\"</Command>
|
||||
<Command>copy "$(SolutionDir)\..\contrib\fonts\FREECG98.BMP" "$(OutputPath)\FREECG98.BMP"
|
||||
copy "$(SolutionDir)\..\dosbox-x.reference.conf" "$(OutputPath)\dosbox-x.reference.conf"
|
||||
copy "$(SolutionDir)\..\CHANGELOG" "$(OutputPath)\changelog.txt"
|
||||
mkdir "$(OutputPath)\shaders"
|
||||
copy "$(SolutionDir)\..\contrib\shaders\*.*" "$(OutputPath)\shaders\"</Command>
|
||||
if not exist "$(OutputPath)\shaders\" mkdir "$(OutputPath)\shaders"
|
||||
copy "$(SolutionDir)\..\contrib\windows\shaders\*.*" "$(OutputPath)\shaders\"</Command>
|
||||
<Message>
|
||||
</Message>
|
||||
</PostBuildEvent>
|
||||
|
Reference in New Issue
Block a user