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
}
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
2022-07-16 17:29:59 +00:00
#if HAS_CLIP_CONTROL
2015-09-08 09:19:07 +00:00
SV_Target1 = uint(exp2(32.0f) * sample_c().r);
2022-07-16 17:29:59 +00:00
#else
SV_Target1 = uint(exp2(24.0f) * sample_c().r);
#endif
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-07-16 17:29:59 +00:00
#if HAS_CLIP_CONTROL
2022-02-12 04:50:35 +00:00
uint d = uint(sample_c().r * exp2(32.0f));
2022-07-16 17:29:59 +00:00
#else
uint d = uint(sample_c().r * exp2(24.0f));
#endif
2022-02-12 04:50:35 +00:00
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-07-16 17:29:59 +00:00
#if HAS_CLIP_CONTROL
2022-02-12 04:50:35 +00:00
uint d = uint(sample_c().r * exp2(32.0f));
2022-07-16 17:29:59 +00:00
#else
uint d = uint(sample_c().r * exp2(24.0f));
#endif
2022-02-12 04:50:35 +00:00
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
2022-08-16 20:19:34 +00:00
float rgba8_to_depth32(vec4 unorm)
{
uvec4 c = uvec4(unorm * vec4(255.5f));
2022-07-16 17:29:59 +00:00
#if HAS_CLIP_CONTROL
2022-08-16 20:19:34 +00:00
return float(c.r | (c.g << 8) | (c.b << 16) | (c.a << 24)) * exp2(-32.0f);
2022-07-16 17:29:59 +00:00
#else
return float(c.r | (c.g << 8) | (c.b << 16) | (c.a << 24)) * exp2(-24.0f);
#endif
2022-08-16 20:19:34 +00:00
}
float rgba8_to_depth24(vec4 unorm)
{
uvec3 c = uvec3(unorm.rgb * vec3(255.5f));
2022-07-16 17:29:59 +00:00
#if HAS_CLIP_CONTROL
2022-08-16 20:19:34 +00:00
return float(c.r | (c.g << 8) | (c.b << 16)) * exp2(-32.0f);
2022-07-16 17:29:59 +00:00
#else
return float(c.r | (c.g << 8) | (c.b << 16)) * exp2(-24.0f);
#endif
2022-08-16 20:19:34 +00:00
}
float rgba8_to_depth16(vec4 unorm)
{
uvec2 c = uvec2(unorm.rg * vec2(255.5f));
2022-07-16 17:29:59 +00:00
#if HAS_CLIP_CONTROL
2022-08-16 20:19:34 +00:00
return float(c.r | (c.g << 8)) * exp2(-32.0f);
2022-07-16 17:29:59 +00:00
#else
return float(c.r | (c.g << 8)) * exp2(-24.0f);
#endif
2022-08-16 20:19:34 +00:00
}
float rgb5a1_to_depth16(vec4 unorm)
{
uvec4 c = uvec4(unorm * vec4(255.5f));
2022-07-16 17:29:59 +00:00
#if HAS_CLIP_CONTROL
2022-08-16 20:19:34 +00:00
return float(((c.r & 0xF8u) >> 3) | ((c.g & 0xF8u) << 2) | ((c.b & 0xF8u) << 7) | ((c.a & 0x80u) << 8)) * exp2(-32.0f);
2022-07-16 17:29:59 +00:00
#else
return float(((c.r & 0xF8u) >> 3) | ((c.g & 0xF8u) << 2) | ((c.b & 0xF8u) << 7) | ((c.a & 0x80u) << 8)) * exp2(-24.0f);
#endif
2022-08-16 20:19:34 +00:00
}
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
{
2022-08-16 20:19:34 +00:00
// Convert an RGBA texture into a float depth texture
gl_FragDepth = rgba8_to_depth32(sample_c());
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
2022-08-16 20:19:34 +00:00
// Convert an RGBA texture into a float depth texture
gl_FragDepth = rgba8_to_depth24(sample_c());
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)
2022-08-16 20:19:34 +00:00
// Convert an RGBA texture into a float depth texture
gl_FragDepth = rgba8_to_depth16(sample_c());
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
{
2022-08-16 20:19:34 +00:00
// Convert an RGB5A1 (saved as RGBA8) color to a 16 bit Z
gl_FragDepth = rgb5a1_to_depth16(sample_c());
}
#endif
#define SAMPLE_RGBA_DEPTH_BILN(CONVERT_FN) \
ivec2 dims = textureSize(TextureSampler, 0); \
vec2 top_left_f = PSin_t * vec2(dims) - 0.5f; \
ivec2 top_left = ivec2(floor(top_left_f)); \
ivec4 coords = clamp(ivec4(top_left, top_left + 1), ivec4(0), dims.xyxy - 1); \
vec2 mix_vals = fract(top_left_f); \
float depthTL = CONVERT_FN(texelFetch(TextureSampler, coords.xy, 0)); \
float depthTR = CONVERT_FN(texelFetch(TextureSampler, coords.zy, 0)); \
float depthBL = CONVERT_FN(texelFetch(TextureSampler, coords.xw, 0)); \
float depthBR = CONVERT_FN(texelFetch(TextureSampler, coords.zw, 0)); \
gl_FragDepth = mix(mix(depthTL, depthTR, mix_vals.x), mix(depthBL, depthBR, mix_vals.x), mix_vals.y);
#ifdef ps_convert_rgba8_float32_biln
void ps_convert_rgba8_float32_biln()
{
// Convert an RGBA texture into a float depth texture
SAMPLE_RGBA_DEPTH_BILN(rgba8_to_depth32);
}
#endif
#ifdef ps_convert_rgba8_float24_biln
void ps_convert_rgba8_float24_biln()
{
// Same as above but without the alpha channel (24 bits Z)
// Convert an RGBA texture into a float depth texture
SAMPLE_RGBA_DEPTH_BILN(rgba8_to_depth24);
}
#endif
#ifdef ps_convert_rgba8_float16_biln
void ps_convert_rgba8_float16_biln()
{
// Same as above but without the A/B channels (16 bits Z)
// Convert an RGBA texture into a float depth texture
SAMPLE_RGBA_DEPTH_BILN(rgba8_to_depth16);
}
#endif
#ifdef ps_convert_rgb5a1_float16_biln
void ps_convert_rgb5a1_float16_biln()
{
// Convert an RGB5A1 (saved as RGBA8) color to a 16 bit Z
SAMPLE_RGBA_DEPTH_BILN(rgb5a1_to_depth16);
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
{
// 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
2022-10-15 07:06:14 +00:00
uvec2 pos = uvec2(gl_FragCoord.xy);
2015-06-27 09:24:16 +00:00
2022-10-15 07:06:14 +00:00
// Collapse separate R G B A areas into their base pixel
uvec2 block = (pos & ~uvec2(15u, 3u)) >> 1;
uvec2 subblock = pos & uvec2(7u, 1u);
uvec2 coord = block | subblock;
2015-06-27 09:24:16 +00:00
2022-10-15 07:06:14 +00:00
// Apply offset to cols 1 and 2
uint is_col23 = pos.y & 4u;
uint is_col13 = pos.y & 2u;
uint is_col12 = is_col23 ^ (is_col13 << 1);
coord.x ^= is_col12; // If cols 1 or 2, flip bit 3 of x
2015-06-27 09:24:16 +00:00
2022-07-19 10:46:59 +00:00
if (floor(PS_SCALE_FACTOR) != PS_SCALE_FACTOR)
2022-10-15 07:06:14 +00:00
coord = uvec2(vec2(coord) * PS_SCALE_FACTOR);
2022-07-19 10:46:59 +00:00
else
2022-10-17 14:04:00 +00:00
coord *= uvec2(PS_SCALE_FACTOR);
2015-06-29 17:17:46 +00:00
2022-10-15 07:06:14 +00:00
vec4 pixel = texelFetch(TextureSampler, ivec2(coord), 0);
vec2 sel0 = (pos.y & 2u) == 0u ? pixel.rb : pixel.ga;
float sel1 = (pos.x & 8u) == 0u ? sel0.x : sel0.y;
SV_Target0 = vec4(sel1);
2015-06-27 09:24:16 +00:00
}
#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();
2022-12-10 08:33:03 +00:00
SV_Target0 = vec4(c.rgb, 1.0);
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
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
2022-10-04 03:01:18 +00:00
#ifdef ps_hdr_init
void ps_hdr_init()
2011-12-08 16:39:14 +00:00
{
2022-10-04 03:01:18 +00:00
vec4 value = sample_c();
2022-10-09 05:51:41 +00:00
SV_Target0 = vec4(round(value.rgb * 255.0f) / 65535.0f, value.a);
2022-10-04 03:01:18 +00:00
}
#endif
#ifdef ps_hdr_resolve
void ps_hdr_resolve()
{
vec4 value = sample_c();
2022-10-09 05:51:41 +00:00
SV_Target0 = vec4(vec3(uvec3(value.rgb * 65535.0f) & 255u) / 255.0f, value.a);
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
2023-01-02 13:14:10 +00:00
#ifdef ps_convert_clut_4
uniform uvec3 offset;
uniform vec2 scale;
void ps_convert_clut_4()
{
// CLUT4 is easy, just two rows of 8x8.
uint index = uint(gl_FragCoord.x) + offset.z;
uvec2 pos = uvec2(index % 8u, index / 8u);
ivec2 final = ivec2(floor(vec2(offset.xy + pos) * scale));
SV_Target0 = texelFetch(TextureSampler, final, 0);
}
#endif
#ifdef ps_convert_clut_8
uniform uvec3 offset;
uniform vec2 scale;
void ps_convert_clut_8()
{
2023-01-03 12:31:03 +00:00
uint index = min(uint(gl_FragCoord.x) + offset.z, 255u);
2023-01-02 13:14:10 +00:00
// CLUT is arranged into 8 groups of 16x2, with the top-right and bottom-left quadrants swapped.
// This can probably be done better..
uint subgroup = (index / 8u) % 4u;
uvec2 pos;
pos.x = (index % 8u) + ((subgroup >= 2u) ? 8u : 0u);
pos.y = ((index / 32u) * 2u) + (subgroup % 2u);
ivec2 final = ivec2(floor(vec2(offset.xy + pos) * scale));
SV_Target0 = texelFetch(TextureSampler, final, 0);
}
#endif
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
2022-08-31 20:16:31 +00:00
#if defined(ps_stencil_image_init_0) || defined(ps_stencil_image_init_1)
void main()
{
SV_Target0 = vec4(0x7FFFFFFF);
#ifdef ps_stencil_image_init_0
if((127.5f / 255.0f) < sample_c().a) // < 0x80 pass (== 0x80 should not pass)
SV_Target0 = vec4(-1);
#endif
#ifdef ps_stencil_image_init_1
if(sample_c().a < (127.5f / 255.0f)) // >= 0x80 pass
SV_Target0 = vec4(-1);
#endif
}
#endif
2011-11-21 22:36:03 +00:00
#endif