2011-02-19 10:57:28 +00:00
|
|
|
#ifdef SHADER_MODEL // make safe to include in resource file to enforce dependency
|
|
|
|
|
2018-10-12 06:06:17 +00:00
|
|
|
#ifndef PS_SCALE_FACTOR
|
|
|
|
#define PS_SCALE_FACTOR 1
|
|
|
|
#endif
|
|
|
|
|
2011-02-19 10:57:28 +00:00
|
|
|
struct VS_INPUT
|
|
|
|
{
|
2018-09-10 20:05:48 +00:00
|
|
|
float4 p : POSITION;
|
2011-02-19 10:57:28 +00:00
|
|
|
float2 t : TEXCOORD0;
|
2018-12-14 11:59:00 +00:00
|
|
|
float4 c : COLOR;
|
2011-02-19 10:57:28 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
struct VS_OUTPUT
|
|
|
|
{
|
|
|
|
float4 p : SV_Position;
|
|
|
|
float2 t : TEXCOORD0;
|
2018-12-14 11:59:00 +00:00
|
|
|
float4 c : COLOR;
|
2011-02-19 10:57:28 +00:00
|
|
|
};
|
|
|
|
|
2022-03-19 12:19:16 +00:00
|
|
|
cbuffer cb0 : register(b0)
|
2022-01-09 06:32:18 +00:00
|
|
|
{
|
2022-04-18 03:08:51 +00:00
|
|
|
float4 BGColor;
|
2022-01-09 06:32:18 +00:00
|
|
|
int EMODA;
|
|
|
|
int EMODC;
|
2022-04-18 03:08:51 +00:00
|
|
|
int cb0_pad[2];
|
2022-01-09 06:32:18 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
static const float3x3 rgb2yuv =
|
|
|
|
{
|
|
|
|
{0.587, 0.114, 0.299},
|
|
|
|
{-0.311, 0.500, -0.169},
|
|
|
|
{-0.419, -0.081, 0.500}
|
|
|
|
};
|
|
|
|
|
2011-02-19 10:57:28 +00:00
|
|
|
Texture2D Texture;
|
|
|
|
SamplerState TextureSampler;
|
|
|
|
|
|
|
|
float4 sample_c(float2 uv)
|
|
|
|
{
|
|
|
|
return Texture.Sample(TextureSampler, uv);
|
|
|
|
}
|
|
|
|
|
|
|
|
struct PS_INPUT
|
|
|
|
{
|
|
|
|
float4 p : SV_Position;
|
|
|
|
float2 t : TEXCOORD0;
|
2018-12-14 11:59:00 +00:00
|
|
|
float4 c : COLOR;
|
2011-02-19 10:57:28 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
struct PS_OUTPUT
|
|
|
|
{
|
|
|
|
float4 c : SV_Target0;
|
|
|
|
};
|
|
|
|
|
|
|
|
VS_OUTPUT vs_main(VS_INPUT input)
|
|
|
|
{
|
|
|
|
VS_OUTPUT output;
|
|
|
|
|
|
|
|
output.p = input.p;
|
|
|
|
output.t = input.t;
|
2018-12-14 11:59:00 +00:00
|
|
|
output.c = input.c;
|
2011-02-19 10:57:28 +00:00
|
|
|
|
|
|
|
return output;
|
|
|
|
}
|
|
|
|
|
2021-11-25 04:58:04 +00:00
|
|
|
PS_OUTPUT ps_copy(PS_INPUT input)
|
2011-02-19 10:57:28 +00:00
|
|
|
{
|
|
|
|
PS_OUTPUT output;
|
|
|
|
|
|
|
|
output.c = sample_c(input.t);
|
|
|
|
|
|
|
|
return output;
|
|
|
|
}
|
|
|
|
|
2022-02-03 11:40:03 +00:00
|
|
|
float ps_depth_copy(PS_INPUT input) : SV_Depth
|
|
|
|
{
|
|
|
|
return sample_c(input.t).r;
|
|
|
|
}
|
|
|
|
|
2021-11-25 04:58:04 +00:00
|
|
|
PS_OUTPUT ps_filter_transparency(PS_INPUT input)
|
2011-07-25 11:16:01 +00:00
|
|
|
{
|
|
|
|
PS_OUTPUT output;
|
|
|
|
|
|
|
|
float4 c = sample_c(input.t);
|
|
|
|
|
|
|
|
c.a = dot(c.rgb, float3(0.299, 0.587, 0.114));
|
|
|
|
|
|
|
|
output.c = c;
|
|
|
|
|
|
|
|
return output;
|
|
|
|
}
|
|
|
|
|
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
|
2021-11-25 04:58:04 +00:00
|
|
|
uint ps_convert_rgba8_16bits(PS_INPUT input) : SV_Target0
|
2011-02-19 10:57:28 +00:00
|
|
|
{
|
2022-02-11 21:01:27 +00:00
|
|
|
uint4 i = sample_c(input.t) * float4(255.5f, 255.5f, 255.5f, 255.5f);
|
2011-02-19 10:57:28 +00:00
|
|
|
|
2022-02-11 21:01:27 +00:00
|
|
|
return ((i.x & 0x00F8u) >> 3) | ((i.y & 0x00F8u) << 2) | ((i.z & 0x00f8u) << 7) | ((i.w & 0x80u) << 8);
|
2011-02-19 10:57:28 +00:00
|
|
|
}
|
|
|
|
|
2021-11-25 04:58:04 +00:00
|
|
|
PS_OUTPUT ps_datm1(PS_INPUT input)
|
2011-02-19 10:57:28 +00:00
|
|
|
{
|
|
|
|
PS_OUTPUT output;
|
|
|
|
|
2012-08-06 17:38:28 +00:00
|
|
|
clip(sample_c(input.t).a - 127.5f / 255); // >= 0x80 pass
|
2011-02-19 10:57:28 +00:00
|
|
|
|
|
|
|
output.c = 0;
|
|
|
|
|
|
|
|
return output;
|
|
|
|
}
|
|
|
|
|
2021-11-25 04:58:04 +00:00
|
|
|
PS_OUTPUT ps_datm0(PS_INPUT input)
|
2011-02-19 10:57:28 +00:00
|
|
|
{
|
|
|
|
PS_OUTPUT output;
|
|
|
|
|
2012-08-06 17:38:28 +00:00
|
|
|
clip(127.5f / 255 - sample_c(input.t).a); // < 0x80 pass (== 0x80 should not pass)
|
2011-02-19 10:57:28 +00:00
|
|
|
|
|
|
|
output.c = 0;
|
|
|
|
|
|
|
|
return output;
|
|
|
|
}
|
|
|
|
|
2021-11-25 04:58:04 +00:00
|
|
|
PS_OUTPUT ps_mod256(PS_INPUT input)
|
2011-02-19 10:57:28 +00:00
|
|
|
{
|
|
|
|
PS_OUTPUT output;
|
2019-01-11 17:20:04 +00:00
|
|
|
|
|
|
|
float4 c = round(sample_c(input.t) * 255);
|
|
|
|
// We use 2 fmod to avoid negative value.
|
|
|
|
float4 fmod1 = fmod(c, 256) + 256;
|
|
|
|
float4 fmod2 = fmod(fmod1, 256);
|
|
|
|
|
|
|
|
output.c = fmod2 / 255.0f;
|
2011-02-19 10:57:28 +00:00
|
|
|
|
|
|
|
return output;
|
|
|
|
}
|
|
|
|
|
2021-11-25 04:58:04 +00:00
|
|
|
uint ps_convert_float32_32bits(PS_INPUT input) : SV_Target0
|
2018-09-10 20:05:48 +00:00
|
|
|
{
|
2018-12-03 17:02:24 +00:00
|
|
|
// Convert a FLOAT32 depth texture into a 32 bits UINT texture
|
|
|
|
return uint(exp2(32.0f) * sample_c(input.t).r);
|
2018-09-10 20:05:48 +00:00
|
|
|
}
|
|
|
|
|
2021-11-25 04:58:04 +00:00
|
|
|
PS_OUTPUT ps_convert_float32_rgba8(PS_INPUT input)
|
2018-09-10 20:05:48 +00:00
|
|
|
{
|
|
|
|
PS_OUTPUT output;
|
|
|
|
|
2018-12-03 17:02:24 +00:00
|
|
|
// Convert a FLOAT32 depth texture into a RGBA color texture
|
2022-02-12 04:50:35 +00:00
|
|
|
uint d = uint(sample_c(input.t).r * exp2(32.0f));
|
|
|
|
output.c = float4(uint4((d & 0xFFu), ((d >> 8) & 0xFFu), ((d >> 16) & 0xFFu), (d >> 24))) / 255.0f;
|
2018-09-10 20:05:48 +00:00
|
|
|
|
|
|
|
return output;
|
|
|
|
}
|
|
|
|
|
2021-11-25 04:58:04 +00:00
|
|
|
PS_OUTPUT ps_convert_float16_rgb5a1(PS_INPUT input)
|
2018-09-10 20:05:48 +00:00
|
|
|
{
|
|
|
|
PS_OUTPUT output;
|
|
|
|
|
2018-12-03 17:02:24 +00:00
|
|
|
// Convert a FLOAT32 (only 16 lsb) depth into a RGB5A1 color texture
|
2022-02-12 04:50:35 +00:00
|
|
|
uint d = uint(sample_c(input.t).r * exp2(32.0f));
|
|
|
|
output.c = float4(uint4((d & 0x1Fu), ((d >> 5) & 0x1Fu), ((d >> 10) & 0x1Fu), (d >> 15) & 0x01u)) / float4(32.0f, 32.0f, 32.0f, 1.0f);
|
2018-09-10 20:05:48 +00:00
|
|
|
|
|
|
|
return output;
|
|
|
|
}
|
2022-08-16 20:19:34 +00:00
|
|
|
|
|
|
|
float rgba8_to_depth32(float4 val)
|
2018-09-10 20:05:48 +00:00
|
|
|
{
|
2022-08-16 20:19:34 +00:00
|
|
|
uint4 c = uint4(val * 255.5f);
|
2022-02-12 04:50:35 +00:00
|
|
|
return float(c.r | (c.g << 8) | (c.b << 16) | (c.a << 24)) * exp2(-32.0f);
|
2018-09-10 20:05:48 +00:00
|
|
|
}
|
|
|
|
|
2022-08-16 20:19:34 +00:00
|
|
|
float rgba8_to_depth24(float4 val)
|
|
|
|
{
|
|
|
|
uint3 c = uint3(val.rgb * 255.5f);
|
|
|
|
return float(c.r | (c.g << 8) | (c.b << 16)) * exp2(-32.0f);
|
|
|
|
}
|
|
|
|
|
|
|
|
float rgba8_to_depth16(float4 val)
|
|
|
|
{
|
|
|
|
uint2 c = uint2(val.rg * 255.5f);
|
|
|
|
return float(c.r | (c.g << 8)) * exp2(-32.0f);
|
|
|
|
}
|
|
|
|
|
|
|
|
float rgb5a1_to_depth16(float4 val)
|
|
|
|
{
|
|
|
|
uint4 c = uint4(val * 255.5f);
|
|
|
|
return float(((c.r & 0xF8u) >> 3) | ((c.g & 0xF8u) << 2) | ((c.b & 0xF8u) << 7) | ((c.a & 0x80u) << 8)) * exp2(-32.0f);
|
|
|
|
}
|
|
|
|
|
|
|
|
float ps_convert_rgba8_float32(PS_INPUT input) : SV_Depth
|
|
|
|
{
|
|
|
|
// Convert an RGBA texture into a float depth texture
|
|
|
|
return rgba8_to_depth32(sample_c(input.t));
|
|
|
|
}
|
|
|
|
|
2021-11-25 04:58:04 +00:00
|
|
|
float ps_convert_rgba8_float24(PS_INPUT input) : SV_Depth
|
2018-09-10 20:05:48 +00:00
|
|
|
{
|
2018-12-03 17:02:24 +00:00
|
|
|
// Same as above but without the alpha channel (24 bits Z)
|
2018-09-10 20:05:48 +00:00
|
|
|
|
2022-08-16 20:19:34 +00:00
|
|
|
// Convert an RGBA texture into a float depth texture
|
|
|
|
return rgba8_to_depth24(sample_c(input.t));
|
2018-09-10 20:05:48 +00:00
|
|
|
}
|
|
|
|
|
2021-11-25 04:58:04 +00:00
|
|
|
float ps_convert_rgba8_float16(PS_INPUT input) : SV_Depth
|
2018-09-10 20:05:48 +00:00
|
|
|
{
|
2018-12-03 17:02:24 +00:00
|
|
|
// Same as above but without the A/B channels (16 bits Z)
|
2018-09-10 20:05:48 +00:00
|
|
|
|
2022-08-16 20:19:34 +00:00
|
|
|
// Convert an RGBA texture into a float depth texture
|
|
|
|
return rgba8_to_depth16(sample_c(input.t));
|
2018-09-10 20:05:48 +00:00
|
|
|
}
|
|
|
|
|
2021-11-25 04:58:04 +00:00
|
|
|
float ps_convert_rgb5a1_float16(PS_INPUT input) : SV_Depth
|
2018-09-10 20:05:48 +00:00
|
|
|
{
|
2022-08-16 20:19:34 +00:00
|
|
|
// Convert an RGB5A1 (saved as RGBA8) color to a 16 bit Z
|
|
|
|
return rgb5a1_to_depth16(sample_c(input.t));
|
|
|
|
}
|
|
|
|
|
|
|
|
#define SAMPLE_RGBA_DEPTH_BILN(CONVERT_FN) \
|
|
|
|
uint width, height; \
|
|
|
|
Texture.GetDimensions(width, height); \
|
|
|
|
float2 top_left_f = input.t * float2(width, height) - 0.5f; \
|
|
|
|
int2 top_left = int2(floor(top_left_f)); \
|
|
|
|
int4 coords = clamp(int4(top_left, top_left + 1), int4(0, 0, 0, 0), int2(width - 1, height - 1).xyxy); \
|
|
|
|
float2 mix_vals = frac(top_left_f); \
|
|
|
|
float depthTL = CONVERT_FN(Texture.Load(int3(coords.xy, 0))); \
|
|
|
|
float depthTR = CONVERT_FN(Texture.Load(int3(coords.zy, 0))); \
|
|
|
|
float depthBL = CONVERT_FN(Texture.Load(int3(coords.xw, 0))); \
|
|
|
|
float depthBR = CONVERT_FN(Texture.Load(int3(coords.zw, 0))); \
|
|
|
|
return lerp(lerp(depthTL, depthTR, mix_vals.x), lerp(depthBL, depthBR, mix_vals.x), mix_vals.y);
|
|
|
|
|
|
|
|
float ps_convert_rgba8_float32_biln(PS_INPUT input) : SV_Depth
|
|
|
|
{
|
|
|
|
// Convert an RGBA texture into a float depth texture
|
|
|
|
SAMPLE_RGBA_DEPTH_BILN(rgba8_to_depth32);
|
|
|
|
}
|
|
|
|
|
|
|
|
float ps_convert_rgba8_float24_biln(PS_INPUT input) : SV_Depth
|
|
|
|
{
|
|
|
|
// 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);
|
|
|
|
}
|
|
|
|
|
|
|
|
float ps_convert_rgba8_float16_biln(PS_INPUT input) : SV_Depth
|
|
|
|
{
|
|
|
|
// 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);
|
|
|
|
}
|
|
|
|
|
|
|
|
float ps_convert_rgb5a1_float16_biln(PS_INPUT input) : SV_Depth
|
|
|
|
{
|
|
|
|
// Convert an RGB5A1 (saved as RGBA8) color to a 16 bit Z
|
|
|
|
SAMPLE_RGBA_DEPTH_BILN(rgb5a1_to_depth16);
|
2018-09-10 20:05:48 +00:00
|
|
|
}
|
|
|
|
|
2021-11-25 04:58:04 +00:00
|
|
|
PS_OUTPUT ps_convert_rgba_8i(PS_INPUT input)
|
2018-09-10 20:05:48 +00:00
|
|
|
{
|
|
|
|
PS_OUTPUT output;
|
|
|
|
|
|
|
|
// 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;
|
|
|
|
|
|
|
|
// 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;
|
|
|
|
|
|
|
|
uint2 sel = uint2(input.p.xy) % uint2(16u, 16u);
|
|
|
|
int2 tb = ((int2(input.p.xy) & ~int2(15, 3)) >> 1);
|
|
|
|
|
|
|
|
int ty = tb.y | (int(input.p.y) & 1);
|
|
|
|
int txN = tb.x | (int(input.p.x) & 7);
|
|
|
|
int txH = tb.x | ((int(input.p.x) + 4) & 7);
|
|
|
|
|
2018-10-12 06:06:17 +00:00
|
|
|
txN *= PS_SCALE_FACTOR;
|
|
|
|
txH *= PS_SCALE_FACTOR;
|
|
|
|
ty *= PS_SCALE_FACTOR;
|
2018-09-10 20:05:48 +00:00
|
|
|
|
|
|
|
// TODO investigate texture gather
|
|
|
|
float4 cN = Texture.Load(int3(txN, ty, 0));
|
|
|
|
float4 cH = Texture.Load(int3(txH, ty, 0));
|
|
|
|
|
|
|
|
|
|
|
|
if ((sel.y & 4u) == 0u)
|
|
|
|
{
|
|
|
|
#ifdef ONLY_BLUE
|
|
|
|
c = cN.b;
|
|
|
|
#else
|
|
|
|
// Column 0 and 2
|
|
|
|
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;
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
#ifdef ONLY_BLUE
|
|
|
|
c = cH.b;
|
|
|
|
#else
|
|
|
|
// 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;
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
|
|
|
output.c = (float4)(c); // Divide by something here?
|
|
|
|
|
|
|
|
return output;
|
|
|
|
}
|
|
|
|
|
2021-11-25 04:58:04 +00:00
|
|
|
PS_OUTPUT ps_yuv(PS_INPUT input)
|
2018-12-14 15:37:05 +00:00
|
|
|
{
|
|
|
|
PS_OUTPUT output;
|
|
|
|
|
2022-01-09 06:32:18 +00:00
|
|
|
float4 i = sample_c(input.t);
|
|
|
|
float3 yuv = mul(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;
|
|
|
|
|
|
|
|
switch (EMODA)
|
|
|
|
{
|
|
|
|
case 0:
|
|
|
|
output.c.a = i.a;
|
|
|
|
break;
|
|
|
|
case 1:
|
|
|
|
output.c.a = Y;
|
|
|
|
break;
|
|
|
|
case 2:
|
|
|
|
output.c.a = Y / 2.0f;
|
|
|
|
break;
|
|
|
|
case 3:
|
|
|
|
default:
|
|
|
|
output.c.a = 0.0f;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
switch (EMODC)
|
|
|
|
{
|
|
|
|
case 0:
|
|
|
|
output.c.rgb = i.rgb;
|
|
|
|
break;
|
|
|
|
case 1:
|
|
|
|
output.c.rgb = float3(Y, Y, Y);
|
|
|
|
break;
|
|
|
|
case 2:
|
|
|
|
output.c.rgb = float3(Y, Cb, Cr);
|
|
|
|
break;
|
|
|
|
case 3:
|
|
|
|
default:
|
|
|
|
output.c.rgb = float3(i.a, i.a, i.a);
|
|
|
|
break;
|
|
|
|
}
|
2018-12-14 15:37:05 +00:00
|
|
|
|
|
|
|
return output;
|
|
|
|
}
|
|
|
|
|
2022-03-19 12:19:16 +00:00
|
|
|
float ps_stencil_image_init_0(PS_INPUT input) : SV_Target
|
|
|
|
{
|
|
|
|
float c;
|
|
|
|
if ((127.5f / 255.0f) < sample_c(input.t).a) // < 0x80 pass (== 0x80 should not pass)
|
|
|
|
c = float(-1);
|
|
|
|
else
|
|
|
|
c = float(0x7FFFFFFF);
|
|
|
|
return c;
|
|
|
|
}
|
|
|
|
|
|
|
|
float ps_stencil_image_init_1(PS_INPUT input) : SV_Target
|
|
|
|
{
|
|
|
|
float c;
|
|
|
|
if (sample_c(input.t).a < (127.5f / 255.0f)) // >= 0x80 pass
|
|
|
|
c = float(-1);
|
|
|
|
else
|
|
|
|
c = float(0x7FFFFFFF);
|
|
|
|
return c;
|
|
|
|
}
|
|
|
|
|
2011-02-19 10:57:28 +00:00
|
|
|
#endif
|