2011-11-30 21:42:41 +00:00
//#version 420 // Keep it for editor detection
2012-01-02 20:08:11 +00:00
struct vertex_basic
{
vec4 p;
vec2 t;
};
2011-11-30 21:42:41 +00:00
#ifdef VERTEX_SHADER
2011-12-07 22:05:46 +00:00
out gl_PerVertex {
vec4 gl_Position;
float gl_PointSize;
2014-09-30 19:56:36 +00:00
#if !pGL_ES
2011-12-07 22:05:46 +00:00
float gl_ClipDistance[];
2013-05-25 14:28:16 +00:00
#endif
2014-09-30 19:56:36 +00:00
};
2011-12-07 22:05:46 +00:00
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;
// 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.
2013-07-11 17:08:42 +00:00
out SHADER
{
vec4 p;
vec2 t;
} VSout;
2013-05-26 13:05:03 +00:00
#define VSout_p (VSout.p)
#define VSout_t (VSout.t)
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
{
2014-04-05 19:43:23 +00:00
VSout_p = vec4(POSITION, 0.5f, 1.0f);
2013-05-26 13:05:03 +00:00
VSout_t = TEXCOORD0;
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
2013-07-11 17:08:42 +00:00
in SHADER
{
vec4 p;
vec2 t;
} PSin;
2013-05-26 13:05:03 +00:00
#define PSin_p (PSin.p)
#define PSin_t (PSin.t)
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!
2015-05-19 16:56:32 +00:00
#if defined(ps_main1) || defined(ps_main10)
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-11-30 21:42:41 +00:00
layout(binding = 0) uniform sampler2D TextureSampler;
2011-11-21 22:36:03 +00:00
2015-06-29 17:17:46 +00:00
layout(std140, binding = 15) uniform cb15
{
ivec4 ScalingFactor;
};
2011-12-11 19:09:08 +00:00
vec4 sample_c()
2011-11-21 22:36:03 +00:00
{
2015-07-24 19:56:15 +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)
);
2011-12-11 19:09:08 +00:00
return sample_c() * clamp((mask[i] + 0.5f), 0.0f, 1.0f);
2011-11-21 22:36:03 +00:00
}
2014-01-18 14:46:13 +00:00
vec4 ps_scanlines(uint i)
2014-01-12 11:38:50 +00:00
{
2014-01-18 14:46:13 +00:00
vec4 mask[2] =
2014-01-12 11:38:50 +00:00
{
2014-01-18 14:46:13 +00:00
vec4(1, 1, 1, 0),
vec4(0, 0, 0, 0)
2014-01-12 11:38:50 +00:00
};
return sample_c() * clamp((mask[i] + 0.5f), 0.0f, 1.0f);
}
2013-07-12 21:12:34 +00:00
#ifdef ps_main0
2011-11-30 21:42:41 +00:00
void ps_main0()
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
2013-07-12 21:12:34 +00:00
#ifdef ps_main1
2011-12-29 14:24:26 +00:00
void ps_main1()
{
2015-05-19 11:09:51 +00:00
// Input Color is RGBA8
// We want to output a pixel on the PSMCT16* format
// A1-BGR5
#if 0
2015-05-24 11:10:12 +00:00
// Note: dot is a good idea from pseudo. However we must be careful about float accuraccy.
// Here a global idea example:
//
// SV_Target1 = dot(round(sample_c() * vec4(31.f, 31.f, 31.f, 1.f)), vec4(1.f, 32.f, 1024.f, 32768.f));
//
2015-05-19 11:09:51 +00:00
// For me this code is more accurate but it will require some tests
2015-05-24 11:10:12 +00:00
vec4 c = sample_c() * 255.0f + 0.5f; // Denormalize value to avoid float precision issue
2015-05-19 11:09:51 +00:00
2015-05-24 11:10:12 +00:00
// shift Red: -3
// shift Green: -3 + 5
// shift Blue: -3 + 10
// shift Alpha: -7 + 15
highp uvec4 i = uvec4(c * vec4(1/8.0f, 4.0f, 128.0f, 256.0f)); // Shift value
2015-05-19 11:09:51 +00:00
2015-07-18 09:22:08 +00:00
// bit field operation requires GL4 HW. Could be nice to merge it with step/mix below
2015-05-24 11:10:12 +00:00
SV_Target1 = (i.r & uint(0x001f)) | (i.g & uint(0x03e0)) | (i.b & uint(0x7c00)) | (i.a & uint(0x8000));
2015-05-19 11:09:51 +00:00
#else
// Old code which is likely wrong.
2011-12-29 14:24:26 +00:00
vec4 c = sample_c();
c.a *= 256.0f / 127.0f; // hm, 0.5 won't give us 1.0 if we just multiply with 2
2012-05-26 09:58:37 +00:00
highp uvec4 i = uvec4(c * vec4(uint(0x001f), uint(0x03e0), uint(0x7c00), uint(0x8000)));
2011-12-29 14:24:26 +00:00
2015-07-18 09:22:08 +00:00
// bit field operation requires GL4 HW. Could be nice to merge it with step/mix below
2012-01-04 11:14:57 +00:00
SV_Target1 = (i.x & uint(0x001f)) | (i.y & uint(0x03e0)) | (i.z & uint(0x7c00)) | (i.w & uint(0x8000));
2015-05-19 11:09:51 +00:00
#endif
2015-05-24 11:10:12 +00:00
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
2015-05-19 16:56:32 +00:00
#ifdef ps_main10
void ps_main10()
{
2015-05-29 16:58:26 +00:00
// Convert a GL_FLOAT32 depth texture into a 32 bits UINT texture
2015-05-19 16:56:32 +00:00
vec4 c = sample_c();
const float exp2_32 = exp2(32.0f);
SV_Target1 = uint(exp2_32 * c.r);
}
#endif
2015-05-29 16:58:26 +00:00
#ifdef ps_main11
void ps_main11()
{
const float exp2_32 = exp2(32.0f);
const vec4 bitSh = vec4(256.0*256.0*256.0, 256.0*256.0, 256.0, 1.0);
const vec4 bitMsk = vec4(0.0, 1.0/256.0, 1.0/256.0, 1.0/256.0);
// Convert a GL_FLOAT32 depth texture into a RGBA texture
vec4 res = fract(vec4(sample_c().r) * bitSh);
SV_Target0 = (res - res.xxyz * bitMsk) * 256.0f/255.0f;
}
#endif
#ifdef ps_main12
2015-07-05 16:12:36 +00:00
//out float gl_FragDepth;
2015-05-29 16:58:26 +00:00
void ps_main12()
{
// Convert a RRGBA texture into a float depth texture
// FIXME: I'm afraid of the accuracy
const vec4 bitSh = vec4(1.0/(256.0*256.0*256.0), 1.0/(256.0*256.0), 1.0/256.0, 1.0) * vec4(255.0/256.0);
gl_FragDepth = dot(sample_c(), bitSh);
}
#endif
2015-06-13 08:05:33 +00:00
#ifdef ps_main13
2015-07-05 16:12:36 +00:00
//out float gl_FragDepth;
2015-06-13 08:05:33 +00:00
void ps_main13()
{
2015-07-31 21:23:17 +00:00
// Same as above but without the alpha channel (24 bits Z)
2015-06-13 08:05:33 +00:00
// Convert a RRGBA texture into a float depth texture
// FIXME: I'm afraid of the accuracy
2015-07-31 21:23:17 +00:00
const vec3 bitSh = vec3(1.0/(256.0*256.0*256.0), 1.0/(256.0*256.0), 1.0/256.0) * vec3(255.0/256.0);
gl_FragDepth = dot(sample_c().rgb, bitSh);
2015-06-13 08:05:33 +00:00
}
#endif
2015-06-27 09:24:16 +00:00
#ifdef ps_main14
2015-07-31 21:23:17 +00:00
//out float gl_FragDepth;
2015-06-27 09:24:16 +00:00
void ps_main14()
2015-07-31 21:23:17 +00:00
{
// Same as above but without the A/B channels (16 bits Z)
// Convert a RRGBA texture into a float depth texture
// FIXME: I'm afraid of the accuracy
const vec2 bitSh = vec2(1.0/(256.0*256.0*256.0), 1.0/(256.0*256.0)) * vec2(255.0/256.0);
gl_FragDepth = dot(sample_c().rg, bitSh);
}
#endif
#ifdef ps_main15
void ps_main15()
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 !
//#define ONLY_BLUE;
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);
ivec2 tb = ((ivec2(gl_FragCoord.xy) & ~ivec2(15, 3)) >> 1u);
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);
2015-06-29 17:17:46 +00:00
txN *= ScalingFactor.x;
txH *= ScalingFactor.x;
ty *= ScalingFactor.y;
// 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
2013-07-12 21:12:34 +00:00
#ifdef ps_main7
2011-11-30 21:42:41 +00:00
void ps_main7()
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
2011-11-30 21:42:41 +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
2013-07-12 21:12:34 +00:00
#ifdef ps_main5
2014-01-12 11:38:50 +00:00
void ps_main5() // scanlines
2011-11-21 22:36:03 +00:00
{
2013-05-26 13:05:03 +00:00
highp uvec4 p = uvec4(PSin_p);
2011-11-21 22:36:03 +00:00
2014-01-12 11:38:50 +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
2013-07-12 21:12:34 +00:00
#ifdef ps_main6
2011-11-30 21:42:41 +00:00
void ps_main6() // diagonal
2011-11-21 22:36:03 +00:00
{
2014-01-18 14:46:13 +00:00
highp uvec4 p = uvec4(PSin_p);
2011-11-21 22:36:03 +00:00
2012-01-04 11:14:57 +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
2014-01-12 11:38:50 +00:00
#ifdef ps_main8
void ps_main8() // triangular
{
2014-01-18 14:46:13 +00:00
highp uvec4 p = uvec4(PSin_p);
2014-01-12 11:38:50 +00:00
vec4 c = ps_crt(((p.x + ((p.y >> 1u) & 1u) * 3u) >> 1u) % 3u);
SV_Target0 = c;
}
#endif
2014-01-18 14:46:13 +00:00
#ifdef ps_main9
void ps_main9()
{
const float PI = 3.14159265359f;
vec2 texdim = vec2(textureSize(TextureSampler, 0));
vec4 c;
if (dFdy(PSin_t.y) * PSin_t.y > 0.5f) {
c = sample_c();
} else {
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));
}
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
2013-07-12 21:12:34 +00:00
#ifdef ps_main2
2011-12-08 16:39:14 +00:00
void ps_main2()
{
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
2013-07-12 21:12:34 +00:00
#ifdef ps_main3
2011-12-08 16:39:14 +00:00
void ps_main3()
{
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
2013-07-12 21:12:34 +00:00
#ifdef ps_main4
2011-12-08 16:39:14 +00:00
void ps_main4()
{
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
2011-11-21 22:36:03 +00:00
#endif