2011-11-30 21:42:41 +00:00
//#version 420 // Keep it for editor detection
2012-01-02 20:08:11 +00:00
2011-11-30 21:42:41 +00:00
#ifdef VERTEX_SHADER
2014-04-05 19:43:23 +00:00
layout(location = 0) in vec2 POSITION;
2011-11-30 21:42:41 +00:00
layout(location = 1) in vec2 TEXCOORD0;
2016-09-18 20:32:44 +00:00
layout(location = 7) in vec4 COLOR;
2011-11-30 21:42:41 +00:00
// FIXME set the interpolation (don't know what dx do)
// flat means that there is no interpolation. The value given to the fragment shader is based on the provoking vertex conventions.
//
// noperspective means that there will be linear interpolation in window-space. This is usually not what you want, but it can have its uses.
//
// smooth, the default, means to do perspective-correct interpolation.
//
// The centroid qualifier only matters when multisampling. If this qualifier is not present, then the value is interpolated to the pixel's center, anywhere in the pixel, or to one of the pixel's samples. This sample may lie outside of the actual primitive being rendered, since a primitive can cover only part of a pixel's area. The centroid qualifier is used to prevent this; the interpolation point must fall within both the pixel's area and the primitive's area.
2021-11-30 10:35:45 +00:00
out vec4 PSin_p;
out vec2 PSin_t;
out vec4 PSin_c;
2013-07-11 17:08:42 +00:00
2011-11-30 21:42:41 +00:00
void vs_main()
2011-11-21 22:36:03 +00:00
{
2021-11-30 10:35:45 +00:00
PSin_p = vec4(POSITION, 0.5f, 1.0f);
PSin_t = TEXCOORD0;
PSin_c = COLOR;
2014-04-05 19:43:23 +00:00
gl_Position = vec4(POSITION, 0.5f, 1.0f); // NOTE I don't know if it is possible to merge POSITION_OUT and gl_Position
2011-11-21 22:36:03 +00:00
}
2011-11-30 21:42:41 +00:00
#endif
2011-11-21 22:36:03 +00:00
2011-11-30 21:42:41 +00:00
#ifdef FRAGMENT_SHADER
2011-11-21 22:36:03 +00:00
2021-11-30 10:35:45 +00:00
in vec4 PSin_p;
in vec2 PSin_t;
in vec4 PSin_c;
2013-07-11 17:08:42 +00:00
2013-07-12 21:12:34 +00:00
// Give a different name so I remember there is a special case!
2020-09-26 08:59:18 +00:00
#if defined(ps_convert_rgba8_16bits) || defined(ps_convert_float32_32bits)
2013-07-12 21:12:34 +00:00
layout(location = 0) out uint SV_Target1;
#else
2011-12-07 22:05:46 +00:00
layout(location = 0) out vec4 SV_Target0;
2013-07-12 21:12:34 +00:00
#endif
2011-11-21 22:36:03 +00:00
2011-12-11 19:09:08 +00:00
vec4 sample_c()
2011-11-21 22:36:03 +00:00
{
2021-11-30 10:35:45 +00:00
return texture(TextureSampler, PSin_t);
2011-11-21 22:36:03 +00:00
}
2013-05-25 14:28:16 +00:00
vec4 ps_crt(uint i)
{
2013-07-11 17:08:42 +00:00
vec4 mask[4] = vec4[4]
(
vec4(1, 0, 0, 0),
vec4(0, 1, 0, 0),
vec4(0, 0, 1, 0),
vec4(1, 1, 1, 0)
);
2015-09-08 09:19:07 +00:00
return sample_c() * clamp((mask[i] + 0.5f), 0.0f, 1.0f);
2014-01-12 11:38:50 +00:00
}
2020-09-26 08:59:18 +00:00
#ifdef ps_copy
void ps_copy()
2011-11-21 22:36:03 +00:00
{
2011-12-11 19:09:08 +00:00
SV_Target0 = sample_c();
2011-11-21 22:36:03 +00:00
}
2013-07-12 21:12:34 +00:00
#endif
2011-11-21 22:36:03 +00:00
2022-02-03 11:40:03 +00:00
#ifdef ps_depth_copy
void ps_depth_copy()
{
gl_FragDepth = sample_c().r;
}
#endif
2020-09-26 08:59:18 +00:00
#ifdef ps_convert_rgba8_16bits
2022-02-11 21:01:27 +00:00
// Need to be careful with precision here, it can break games like Spider-Man 3 and Dogs Life
2020-09-26 08:59:18 +00:00
void ps_convert_rgba8_16bits()
2011-12-29 14:24:26 +00:00
{
2022-02-11 21:01:27 +00:00
highp uvec4 i = uvec4(sample_c() * vec4(255.5f, 255.5f, 255.5f, 255.5f));
2015-05-24 11:10:12 +00:00
2022-02-11 21:01:27 +00:00
SV_Target1 = ((i.x & 0x00F8u) >> 3) | ((i.y & 0x00F8u) << 2) | ((i.z & 0x00f8u) << 7) | ((i.w & 0x80u) << 8);
2011-12-29 14:24:26 +00:00
}
2013-07-12 21:12:34 +00:00
#endif
2011-12-29 14:24:26 +00:00
2020-09-26 08:59:18 +00:00
#ifdef ps_convert_float32_32bits
void ps_convert_float32_32bits()
2015-05-19 16:56:32 +00:00
{
2015-09-08 09:19:07 +00:00
// Convert a GL_FLOAT32 depth texture into a 32 bits UINT texture
SV_Target1 = uint(exp2(32.0f) * sample_c().r);
2015-05-19 16:56:32 +00:00
}
#endif
2020-09-26 08:59:18 +00:00
#ifdef ps_convert_float32_rgba8
void ps_convert_float32_rgba8()
2015-05-29 16:58:26 +00:00
{
2015-09-08 09:19:07 +00:00
// Convert a GL_FLOAT32 depth texture into a RGBA color texture
2022-02-12 04:50:35 +00:00
uint d = uint(sample_c().r * exp2(32.0f));
SV_Target0 = vec4(uvec4((d & 0xFFu), ((d >> 8) & 0xFFu), ((d >> 16) & 0xFFu), (d >> 24))) / vec4(255.0);
2015-05-29 16:58:26 +00:00
}
#endif
2020-09-26 08:59:18 +00:00
#ifdef ps_convert_float16_rgb5a1
void ps_convert_float16_rgb5a1()
2015-05-29 16:58:26 +00:00
{
2015-09-08 09:19:07 +00:00
// Convert a GL_FLOAT32 (only 16 lsb) depth into a RGB5A1 color texture
2022-02-12 04:50:35 +00:00
uint d = uint(sample_c().r * exp2(32.0f));
SV_Target0 = vec4(uvec4((d & 0x1Fu), ((d >> 5) & 0x1Fu), ((d >> 10) & 0x1Fu), (d >> 15) & 0x01u)) / vec4(32.0f, 32.0f, 32.0f, 1.0f);
2015-05-29 16:58:26 +00:00
}
#endif
2020-09-26 08:59:18 +00:00
#ifdef ps_convert_rgba8_float32
void ps_convert_rgba8_float32()
2015-06-13 08:05:33 +00:00
{
2015-09-08 09:19:07 +00:00
// Convert a RRGBA texture into a float depth texture
2022-02-12 04:50:35 +00:00
uvec4 c = uvec4(sample_c() * vec4(255.0f) + vec4(0.5f));
gl_FragDepth = float(c.r | (c.g << 8) | (c.b << 16) | (c.a << 24)) * exp2(-32.0f);
2015-06-13 08:05:33 +00:00
}
#endif
2020-09-26 08:59:18 +00:00
#ifdef ps_convert_rgba8_float24
void ps_convert_rgba8_float24()
2015-07-31 21:23:17 +00:00
{
2015-09-08 09:19:07 +00:00
// Same as above but without the alpha channel (24 bits Z)
2015-07-31 21:23:17 +00:00
2015-09-08 09:19:07 +00:00
// Convert a RRGBA texture into a float depth texture
2022-02-12 04:50:35 +00:00
uvec3 c = uvec3(sample_c().rgb * vec3(255.0f) + vec3(0.5f));
gl_FragDepth = float(c.r | (c.g << 8) | (c.b << 16)) * exp2(-32.0f);
2015-07-31 21:23:17 +00:00
}
#endif
2020-09-26 08:59:18 +00:00
#ifdef ps_convert_rgba8_float16
void ps_convert_rgba8_float16()
2015-09-08 09:19:07 +00:00
{
// Same as above but without the A/B channels (16 bits Z)
// Convert a RRGBA texture into a float depth texture
2022-02-12 04:50:35 +00:00
uvec2 c = uvec2(sample_c().rg * vec2(255.0f) + vec2(0.5f));
gl_FragDepth = float(c.r | (c.g << 8)) * exp2(-32.0f);
2015-09-08 09:19:07 +00:00
}
#endif
2020-09-26 08:59:18 +00:00
#ifdef ps_convert_rgb5a1_float16
void ps_convert_rgb5a1_float16()
2015-09-08 09:19:07 +00:00
{
// Convert a RGB5A1 (saved as RGBA8) color to a 16 bit Z
2022-02-12 04:50:35 +00:00
uvec4 c = uvec4(sample_c() * vec4(255.0f) + vec4(0.5f));
gl_FragDepth = float(((c.r & 0xF8u) >> 3) | ((c.g & 0xF8u) << 2) | ((c.b & 0xF8u) << 7) | ((c.a & 0x80u) << 8)) * exp2(-32.0f);
2015-09-08 09:19:07 +00:00
}
#endif
2020-09-26 08:59:18 +00:00
#ifdef ps_convert_rgba_8i
void ps_convert_rgba_8i()
2015-06-27 09:24:16 +00:00
{
2015-06-29 17:17:46 +00:00
// Potential speed optimization. There is a high probability that
// game only want to extract a single channel (blue). It will allow
// to remove most of the conditional operation and yield a +2/3 fps
// boost on MGS3
//
// Hypothesis wrong in Prince of Persia ... Seriously WTF !
2015-09-08 09:19:07 +00:00
//#define ONLY_BLUE;
2015-06-29 17:17:46 +00:00
2015-06-27 09:24:16 +00:00
// Convert a RGBA texture into a 8 bits packed texture
// Input column: 8x2 RGBA pixels
// 0: 8 RGBA
// 1: 8 RGBA
// Output column: 16x4 Index pixels
// 0: 8 R | 8 B
// 1: 8 R | 8 B
// 2: 8 G | 8 A
// 3: 8 G | 8 A
float c;
uvec2 sel = uvec2(gl_FragCoord.xy) % uvec2(16u, 16u);
2015-09-08 09:19:07 +00:00
ivec2 tb = ((ivec2(gl_FragCoord.xy) & ~ivec2(15, 3)) >> 1);
2015-06-27 09:24:16 +00:00
int ty = tb.y | (int(gl_FragCoord.y) & 1);
int txN = tb.x | (int(gl_FragCoord.x) & 7);
int txH = tb.x | ((int(gl_FragCoord.x) + 4) & 7);
2021-12-21 11:00:24 +00:00
txN *= PS_SCALE_FACTOR;
txH *= PS_SCALE_FACTOR;
ty *= PS_SCALE_FACTOR;
2015-06-29 17:17:46 +00:00
// TODO investigate texture gather
2015-06-27 09:24:16 +00:00
vec4 cN = texelFetch(TextureSampler, ivec2(txN, ty), 0);
vec4 cH = texelFetch(TextureSampler, ivec2(txH, ty), 0);
if ((sel.y & 4u) == 0u) {
// Column 0 and 2
2015-06-29 17:17:46 +00:00
#ifdef ONLY_BLUE
c = cN.b;
#else
2015-06-27 09:24:16 +00:00
if ((sel.y & 3u) < 2u) {
// first 2 lines of the col
if (sel.x < 8u)
c = cN.r;
else
c = cN.b;
} else {
if (sel.x < 8u)
c = cH.g;
else
c = cH.a;
}
2015-06-29 17:17:46 +00:00
#endif
2015-06-27 09:24:16 +00:00
} else {
2015-06-29 17:17:46 +00:00
#ifdef ONLY_BLUE
c = cH.b;
#else
2015-06-27 09:24:16 +00:00
// Column 1 and 3
if ((sel.y & 3u) < 2u) {
// first 2 lines of the col
if (sel.x < 8u)
c = cH.r;
else
c = cH.b;
} else {
if (sel.x < 8u)
c = cN.g;
else
c = cN.a;
}
2015-06-29 17:17:46 +00:00
#endif
2015-06-27 09:24:16 +00:00
}
SV_Target0 = vec4(c);
}
#endif
2020-09-26 08:59:18 +00:00
#ifdef ps_filter_transparency
void ps_filter_transparency()
2011-11-21 22:36:03 +00:00
{
2011-12-11 19:09:08 +00:00
vec4 c = sample_c();
2011-11-21 22:36:03 +00:00
2015-09-08 09:19:07 +00:00
c.a = dot(c.rgb, vec3(0.299, 0.587, 0.114));
2011-11-21 22:36:03 +00:00
2011-11-30 21:42:41 +00:00
SV_Target0 = c;
2011-11-21 22:36:03 +00:00
}
2013-07-12 21:12:34 +00:00
#endif
2011-11-21 22:36:03 +00:00
2020-09-26 08:59:18 +00:00
#ifdef ps_filter_scanlines
2015-09-08 09:19:07 +00:00
vec4 ps_scanlines(uint i)
{
vec4 mask[2] =
{
vec4(1, 1, 1, 0),
vec4(0, 0, 0, 0)
};
return sample_c() * clamp((mask[i] + 0.5f), 0.0f, 1.0f);
}
2020-09-26 08:59:18 +00:00
void ps_filter_scanlines() // scanlines
2011-11-21 22:36:03 +00:00
{
2015-10-25 14:02:16 +00:00
highp uvec4 p = uvec4(gl_FragCoord);
2011-11-21 22:36:03 +00:00
2015-09-08 09:19:07 +00:00
vec4 c = ps_scanlines(p.y % 2u);
2011-11-21 22:36:03 +00:00
2011-11-30 21:42:41 +00:00
SV_Target0 = c;
2011-11-21 22:36:03 +00:00
}
2013-07-12 21:12:34 +00:00
#endif
2011-11-21 22:36:03 +00:00
2020-09-26 08:59:18 +00:00
#ifdef ps_filter_diagonal
void ps_filter_diagonal() // diagonal
2011-11-21 22:36:03 +00:00
{
2015-10-25 14:02:16 +00:00
highp uvec4 p = uvec4(gl_FragCoord);
2011-11-21 22:36:03 +00:00
2015-09-08 09:19:07 +00:00
vec4 c = ps_crt((p.x + (p.y % 3u)) % 3u);
2011-11-21 22:36:03 +00:00
2011-11-30 21:42:41 +00:00
SV_Target0 = c;
2011-11-21 22:36:03 +00:00
}
2013-07-12 21:12:34 +00:00
#endif
2011-11-30 21:42:41 +00:00
2020-09-26 08:59:18 +00:00
#ifdef ps_filter_triangular
void ps_filter_triangular() // triangular
2014-01-12 11:38:50 +00:00
{
2015-10-25 14:02:16 +00:00
highp uvec4 p = uvec4(gl_FragCoord);
2014-01-12 11:38:50 +00:00
2015-09-08 09:19:07 +00:00
vec4 c = ps_crt(((p.x + ((p.y >> 1u) & 1u) * 3u) >> 1u) % 3u);
2014-01-12 11:38:50 +00:00
SV_Target0 = c;
}
#endif
2020-09-26 08:59:18 +00:00
#ifdef ps_filter_complex
void ps_filter_complex()
2014-01-18 14:46:13 +00:00
{
const float PI = 3.14159265359f;
2015-09-08 09:19:07 +00:00
vec2 texdim = vec2(textureSize(TextureSampler, 0));
2014-01-18 14:46:13 +00:00
vec4 c;
2021-11-30 10:35:45 +00:00
if (dFdy(PSin_t.y) * PSin_t.y > 0.5f) {
2015-09-08 09:19:07 +00:00
c = sample_c();
2014-01-18 14:46:13 +00:00
} else {
2021-11-30 10:35:45 +00:00
float factor = (0.9f - 0.4f * cos(2.0f * PI * PSin_t.y * texdim.y));
c = factor * texture(TextureSampler, vec2(PSin_t.x, (floor(PSin_t.y * texdim.y) + 0.5f) / texdim.y));
2014-01-18 14:46:13 +00:00
}
SV_Target0 = c;
}
#endif
2013-06-14 11:34:44 +00:00
// Used for DATE (stencil)
2013-07-28 14:40:43 +00:00
// DATM == 1
2020-09-26 08:59:18 +00:00
#ifdef ps_datm1
void ps_datm1()
2011-12-08 16:39:14 +00:00
{
2014-02-07 19:53:01 +00:00
if(sample_c().a < (127.5f / 255.0f)) // >= 0x80 pass
2012-01-31 17:08:05 +00:00
discard;
2011-12-08 16:39:14 +00:00
}
2013-07-12 21:12:34 +00:00
#endif
2013-06-14 11:34:44 +00:00
// Used for DATE (stencil)
2013-07-28 14:40:43 +00:00
// DATM == 0
2020-09-26 08:59:18 +00:00
#ifdef ps_datm0
void ps_datm0()
2011-12-08 16:39:14 +00:00
{
2014-02-07 19:53:01 +00:00
if((127.5f / 255.0f) < sample_c().a) // < 0x80 pass (== 0x80 should not pass)
2012-01-31 17:08:05 +00:00
discard;
2011-12-08 16:39:14 +00:00
}
2013-07-12 21:12:34 +00:00
#endif
2013-06-14 11:34:44 +00:00
2020-09-26 08:59:18 +00:00
#ifdef ps_mod256
void ps_mod256()
2011-12-08 16:39:14 +00:00
{
2015-07-24 19:56:15 +00:00
SV_Target0 = mod(round(sample_c() * 255.0f), 256.0f) / 255.0f;
2012-01-31 17:08:05 +00:00
}
2013-07-12 21:12:34 +00:00
#endif
2011-11-30 21:42:41 +00:00
2020-09-26 08:59:18 +00:00
#ifdef ps_yuv
2021-10-20 07:52:05 +00:00
uniform ivec2 EMOD;
2020-09-26 08:59:18 +00:00
void ps_yuv()
2016-10-09 12:28:49 +00:00
{
vec4 i = sample_c();
vec4 o;
mat3 rgb2yuv; // Value from GS manual
rgb2yuv[0] = vec3(0.587, -0.311, -0.419);
rgb2yuv[1] = vec3(0.114, 0.500, -0.081);
rgb2yuv[2] = vec3(0.299, -0.169, 0.500);
vec3 yuv = rgb2yuv * i.gbr;
float Y = float(0xDB)/255.0f * yuv.x + float(0x10)/255.0f;
float Cr = float(0xE0)/255.0f * yuv.y + float(0x80)/255.0f;
float Cb = float(0xE0)/255.0f * yuv.z + float(0x80)/255.0f;
2021-10-20 07:52:05 +00:00
switch(EMOD.x) {
2016-10-09 12:28:49 +00:00
case 0:
o.a = i.a;
break;
case 1:
o.a = Y;
break;
case 2:
o.a = Y/2.0f;
break;
case 3:
o.a = 0.0f;
break;
}
2021-10-20 07:52:05 +00:00
switch(EMOD.y) {
2016-10-09 12:28:49 +00:00
case 0:
o.rgb = i.rgb;
break;
case 1:
o.rgb = vec3(Y);
break;
case 2:
o.rgb = vec3(Y, Cb, Cr);
break;
case 3:
o.rgb = vec3(i.a);
break;
}
SV_Target0 = o;
}
#endif
2011-11-21 22:36:03 +00:00
#endif