mirror of
https://github.com/Abdess/retroarch_system.git
synced 2026-10-10 13:33:24 -05:00
feat: collect shaders, machine roms and the doom wad
This commit is contained in:
1 parent
4ffc11b4cf
commit
d2bc1288b5
39 files changed
+6914
-3
No files matched your search
@@ -0,0 +1,64 @@
|
||||
// Based on CAS_Shader.glsl
|
||||
// Copyright(c) 2019 Advanced Micro Devices, Inc.All rights reserved.
|
||||
// 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.
|
||||
|
||||
uniform uvec4 const0;
|
||||
uniform uvec4 const1;
|
||||
uniform ivec2 srcOffset;
|
||||
|
||||
layout(binding=0) uniform sampler2D imgSrc;
|
||||
layout(binding=0, rgba8) uniform writeonly image2D imgDst;
|
||||
|
||||
#define A_GPU 1
|
||||
#define A_GLSL 1
|
||||
|
||||
#include "ffx_a.h"
|
||||
|
||||
AF3 CasLoad(ASU2 p)
|
||||
{
|
||||
return texelFetch(imgSrc, srcOffset + ivec2(p), 0).rgb;
|
||||
}
|
||||
|
||||
// Lets you transform input from the load into a linear color space between 0 and 1. See ffx_cas.h
|
||||
// In this case, our input is already linear and between 0 and 1
|
||||
void CasInput(inout AF1 r, inout AF1 g, inout AF1 b) {}
|
||||
|
||||
#include "ffx_cas.h"
|
||||
|
||||
layout(local_size_x=64) in;
|
||||
void main()
|
||||
{
|
||||
// Do remapping of local xy in workgroup for a more PS-like swizzle pattern.
|
||||
AU2 gxy = ARmp8x8(gl_LocalInvocationID.x)+AU2(gl_WorkGroupID.x<<4u,gl_WorkGroupID.y<<4u);
|
||||
|
||||
// Filter.
|
||||
AF4 c = vec4(0.0f);
|
||||
CasFilter(c.r, c.g, c.b, gxy, const0, const1, CAS_SHARPEN_ONLY);
|
||||
imageStore(imgDst, ASU2(gxy), c);
|
||||
gxy.x += 8u;
|
||||
|
||||
CasFilter(c.r, c.g, c.b, gxy, const0, const1, CAS_SHARPEN_ONLY);
|
||||
imageStore(imgDst, ASU2(gxy), c);
|
||||
gxy.y += 8u;
|
||||
|
||||
CasFilter(c.r, c.g, c.b, gxy, const0, const1, CAS_SHARPEN_ONLY);
|
||||
imageStore(imgDst, ASU2(gxy), c);
|
||||
gxy.x -= 8u;
|
||||
|
||||
CasFilter(c.r, c.g, c.b, gxy, const0, const1, CAS_SHARPEN_ONLY);
|
||||
imageStore(imgDst, ASU2(gxy), c);
|
||||
}
|
||||
@@ -0,0 +1,667 @@
|
||||
// SPDX-FileCopyrightText: 2002-2026 PCSX2 Dev Team
|
||||
// SPDX-License-Identifier: GPL-3.0+
|
||||
|
||||
//#version 420 // Keep it for editor detection
|
||||
|
||||
#ifdef VERTEX_SHADER
|
||||
|
||||
layout(location = 0) in vec2 POSITION;
|
||||
layout(location = 1) in vec2 TEXCOORD0;
|
||||
layout(location = 7) in vec4 COLOR;
|
||||
|
||||
out vec4 PSin_p;
|
||||
out vec2 PSin_t;
|
||||
out vec4 PSin_c;
|
||||
|
||||
void vs_main()
|
||||
{
|
||||
PSin_p = vec4(POSITION, 0.5f, 1.0f);
|
||||
PSin_t = TEXCOORD0;
|
||||
PSin_c = COLOR;
|
||||
gl_Position = vec4(POSITION, 0.5f, 1.0f); // NOTE I don't know if it is possible to merge POSITION_OUT and gl_Position
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#ifdef FRAGMENT_SHADER
|
||||
|
||||
// Adreno's GLSL ES preprocessor errors on undefined identifiers in #if
|
||||
// expressions (desktop treats them as 0). The PrimID DATE-init programs are
|
||||
// compiled WITHOUT the per-ShaderConvert macro block (see GSDeviceOGL's
|
||||
// ps_primid_image_init loop), so every macro in the OUTPUT chain below needs
|
||||
// an explicit default.
|
||||
#ifndef HAS_INTEGER_OUTPUT
|
||||
#define HAS_INTEGER_OUTPUT 0
|
||||
#endif
|
||||
#ifndef HAS_DEPTH_OUTPUT
|
||||
#define HAS_DEPTH_OUTPUT 0
|
||||
#endif
|
||||
#ifndef HAS_FLOAT32_OUTPUT
|
||||
#define HAS_FLOAT32_OUTPUT 0
|
||||
#endif
|
||||
#ifndef HAS_STENCIL_OUTPUT
|
||||
#define HAS_STENCIL_OUTPUT 0
|
||||
#endif
|
||||
#ifndef HAS_FLOAT32_INPUT
|
||||
#define HAS_FLOAT32_INPUT 0
|
||||
#endif
|
||||
#ifndef HAS_BILN
|
||||
#define HAS_BILN 0
|
||||
#endif
|
||||
|
||||
in vec4 PSin_p;
|
||||
in vec2 PSin_t;
|
||||
in vec4 PSin_c;
|
||||
|
||||
layout(binding = 0) uniform sampler2D TextureSampler;
|
||||
|
||||
#if HAS_INTEGER_OUTPUT
|
||||
layout(location = 0) out uint o_col0;
|
||||
#define OUTPUT o_col0
|
||||
#elif HAS_DEPTH_OUTPUT
|
||||
// gl_FragDepth must not be redeclared on GLES ("reserved built-in name"
|
||||
// compile error on Adreno/Mali) — it's available as a built-in there.
|
||||
#ifndef GL_ES
|
||||
out float gl_FragDepth;
|
||||
#endif
|
||||
#define OUTPUT gl_FragDepth
|
||||
#elif HAS_FLOAT32_OUTPUT
|
||||
layout(location = 0) out float o_col0;
|
||||
#define OUTPUT o_col0
|
||||
#elif HAS_STENCIL_OUTPUT
|
||||
#else
|
||||
layout(location = 0) out vec4 o_col0;
|
||||
#define OUTPUT o_col0
|
||||
#endif
|
||||
|
||||
#if HAS_FLOAT32_INPUT
|
||||
|
||||
float sample_c()
|
||||
{
|
||||
return texture(TextureSampler, PSin_t).r;
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
vec4 sample_c()
|
||||
{
|
||||
return texture(TextureSampler, PSin_t);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
uint rgba8_to_uint(vec4 c)
|
||||
{
|
||||
uvec4 i = gpu_bitwise_and(uvec4(c * 255.5f), uvec4(0xFFu));
|
||||
return i.r | (i.g << 8) | (i.b << 16) | (i.a << 24);
|
||||
}
|
||||
|
||||
uint rgb5a1_to_uint(vec4 c)
|
||||
{
|
||||
uvec4 i = gpu_bitwise_and(uvec4(c * 255.5f), uvec4(0xF8u, 0xF8u, 0xF8u, 0x80u));
|
||||
return (i.r >> 3) | (i.g << 2) | (i.b << 7) | (i.a << 8);
|
||||
}
|
||||
|
||||
uint depth_to_uint(float d)
|
||||
{
|
||||
return uint(d * exp2(32.0f));
|
||||
}
|
||||
|
||||
vec4 uint_to_rgba8(uint i)
|
||||
{
|
||||
return vec4((i & 0xFFu), ((i >> 8) & 0xFFu), ((i >> 16) & 0xFFu), ((i >> 24) & 0xFFu)) / 255.0f;
|
||||
}
|
||||
|
||||
vec4 uint_to_rgb5a1(uint i)
|
||||
{
|
||||
return vec4(gpu_bitwise_and(uvec4(i << 3, i >> 2, i >> 7, i >> 8), uvec4(0xF8u, 0xF8u, 0xF8u, 0x80u))) / 255.0f;
|
||||
}
|
||||
|
||||
float uint_to_depth32(uint i)
|
||||
{
|
||||
return float(i) * exp2(-32.0f);
|
||||
}
|
||||
|
||||
float uint_to_depth24(uint i)
|
||||
{
|
||||
return float(i & 0xFFFFFFu) * exp2(-32.0f);
|
||||
}
|
||||
|
||||
float uint_to_depth16(uint i)
|
||||
{
|
||||
return float(i & 0xFFFFu) * exp2(-32.0f);
|
||||
}
|
||||
|
||||
float rgba8_to_depth32(vec4 val)
|
||||
{
|
||||
return uint_to_depth32(rgba8_to_uint(val));
|
||||
}
|
||||
|
||||
float rgba8_to_depth24(vec4 val)
|
||||
{
|
||||
return uint_to_depth24(rgba8_to_uint(val));
|
||||
}
|
||||
|
||||
float rgba8_to_depth16(vec4 val)
|
||||
{
|
||||
return uint_to_depth16(rgba8_to_uint(val));
|
||||
}
|
||||
|
||||
float rgb5a1_to_depth16(vec4 val)
|
||||
{
|
||||
return uint_to_depth16(rgb5a1_to_uint(val));
|
||||
}
|
||||
|
||||
vec4 depth32_to_rgba8(float d)
|
||||
{
|
||||
return uint_to_rgba8(depth_to_uint(d));
|
||||
}
|
||||
|
||||
vec4 depth16_to_rgb5a1(float d)
|
||||
{
|
||||
return uint_to_rgb5a1(depth_to_uint(d));
|
||||
}
|
||||
|
||||
float depth32_to_depth24(float d)
|
||||
{
|
||||
return uint_to_depth24(depth_to_uint(d));
|
||||
}
|
||||
|
||||
#ifdef ps_copy
|
||||
void ps_copy()
|
||||
{
|
||||
OUTPUT = sample_c();
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef ps_depth_copy
|
||||
void ps_depth_copy()
|
||||
{
|
||||
OUTPUT = sample_c();
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef ps_downsample_copy
|
||||
uniform ivec2 ClampMin;
|
||||
uniform int DownsampleFactor;
|
||||
uniform float Weight;
|
||||
uniform float StepMultiplier;
|
||||
|
||||
void ps_downsample_copy()
|
||||
{
|
||||
ivec2 coord = max(ivec2(gl_FragCoord.xy) * DownsampleFactor, ClampMin);
|
||||
vec4 result = vec4(0);
|
||||
for (int yoff = 0; yoff < DownsampleFactor; yoff++)
|
||||
{
|
||||
for (int xoff = 0; xoff < DownsampleFactor; xoff++)
|
||||
result += texelFetch(TextureSampler, coord + ivec2(float(xoff) * StepMultiplier, float(yoff) * StepMultiplier), 0);
|
||||
}
|
||||
o_col0 = result / Weight;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef ps_convert_rgb5a1_16bits
|
||||
void ps_convert_rgb5a1_16bits()
|
||||
{
|
||||
// Need to be careful with precision here, it can break games like Spider-Man 3 and Dogs Life
|
||||
OUTPUT = rgb5a1_to_uint(sample_c());
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef ps_convert_depth32_32bits
|
||||
void ps_convert_depth32_32bits()
|
||||
{
|
||||
// Convert a GL_FLOAT32 depth texture into a 32 bits UINT texture
|
||||
OUTPUT = depth_to_uint(sample_c());
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef ps_convert_depth32_rgba8
|
||||
void ps_convert_depth32_rgba8()
|
||||
{
|
||||
// Convert a GL_FLOAT32 depth texture into a RGBA color texture
|
||||
OUTPUT = depth32_to_rgba8(sample_c());
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef ps_convert_depth16_rgb5a1
|
||||
void ps_convert_depth16_rgb5a1()
|
||||
{
|
||||
// Convert a GL_FLOAT32 (only 16 lsb) depth into a RGB5A1 color texture
|
||||
OUTPUT = depth16_to_rgb5a1(sample_c());
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef ps_convert_depth32_depth24
|
||||
void ps_convert_depth32_depth24()
|
||||
{
|
||||
// Truncates depth value to 24bits
|
||||
OUTPUT = depth32_to_depth24(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)); \
|
||||
OUTPUT = mix(mix(depthTL, depthTR, mix_vals.x), mix(depthBL, depthBR, mix_vals.x), mix_vals.y);
|
||||
|
||||
#ifdef ps_convert_rgba8_depth32
|
||||
void ps_convert_rgba8_depth32()
|
||||
{
|
||||
// Convert an RGBA texture into a float depth texture
|
||||
#if HAS_BILN
|
||||
SAMPLE_RGBA_DEPTH_BILN(rgba8_to_depth32);
|
||||
#else
|
||||
OUTPUT = rgba8_to_depth32(sample_c());
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef ps_convert_rgba8_depth24
|
||||
void ps_convert_rgba8_depth24()
|
||||
{
|
||||
// Same as above but without the alpha channel (24 bits Z)
|
||||
// Convert an RGBA texture into a float depth texture
|
||||
#if HAS_BILN
|
||||
SAMPLE_RGBA_DEPTH_BILN(rgba8_to_depth24);
|
||||
#else
|
||||
OUTPUT = rgba8_to_depth24(sample_c());
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef ps_convert_rgba8_depth16
|
||||
void ps_convert_rgba8_depth16()
|
||||
{
|
||||
// Same as above but without the A/B channels (16 bits Z)
|
||||
// Convert an RGBA texture into a float depth texture
|
||||
#if HAS_BILN
|
||||
SAMPLE_RGBA_DEPTH_BILN(rgba8_to_depth16);
|
||||
#else
|
||||
OUTPUT = rgba8_to_depth16(sample_c());
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef ps_convert_rgb5a1_depth16
|
||||
void ps_convert_rgb5a1_depth16()
|
||||
{
|
||||
// Convert an RGB5A1 (saved as RGBA8) color to a 16 bit Z
|
||||
#if HAS_BILN
|
||||
SAMPLE_RGBA_DEPTH_BILN(rgb5a1_to_depth16);
|
||||
#else
|
||||
OUTPUT = rgb5a1_to_depth16(sample_c());
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef ps_convert_rgb5a1_8i
|
||||
uniform uint SBW;
|
||||
uniform uint DBW;
|
||||
uniform uint PSM;
|
||||
uniform float ScaleFactor;
|
||||
|
||||
void ps_convert_rgb5a1_8i()
|
||||
{
|
||||
// Convert a RGB5A1 texture into a 8 bits packed texture
|
||||
// Input column: 16x2 RGB5A1 pixels
|
||||
// 0: 16 RGBA
|
||||
// 1: 16 RGBA
|
||||
// Output column: 16x4 Index pixels
|
||||
// 0: 16 R5G2
|
||||
// 1: 16 R5G2
|
||||
// 2: 16 G2B5A1
|
||||
// 3: 16 G2B5A1
|
||||
|
||||
uvec2 pos = uvec2(gl_FragCoord.xy);
|
||||
|
||||
// Collapse separate R G B A areas into their base pixel
|
||||
uvec2 column = gpu_bitwise_and(pos, ~uvec2(0u, 3u)) / uvec2(1u, 2u);
|
||||
uvec2 subcolumn = gpu_bitwise_and(pos, uvec2(0u, 1u));
|
||||
column.x -= (column.x / 128u) * 64u;
|
||||
column.y += (column.y / 32u) * 32u;
|
||||
|
||||
// Deal with swizzling differences
|
||||
if ((PSM & 0x8u) != 0u) // PSMCT16S
|
||||
{
|
||||
if ((pos.x & 32u) != 0u)
|
||||
{
|
||||
column.y += 32u; // 4 columns high times 4 to get bottom 4 blocks
|
||||
column.x &= ~32u;
|
||||
}
|
||||
|
||||
if ((pos.x & 64u) != 0u)
|
||||
{
|
||||
column.x -= 32u;
|
||||
}
|
||||
|
||||
if (((pos.x & 16u) != 0u) != ((pos.y & 16u) != 0u))
|
||||
{
|
||||
column.x ^= 16u;
|
||||
column.y ^= 8u;
|
||||
}
|
||||
|
||||
if ((PSM & 0x30u) != 0u) // PSMZ16S - Untested but hopefully ok if anything uses it.
|
||||
{
|
||||
column.x ^= 32u;
|
||||
column.y ^= 16u;
|
||||
}
|
||||
}
|
||||
else // PSMCT16
|
||||
{
|
||||
if ((pos.y & 32u) != 0u)
|
||||
{
|
||||
column.y -= 16u;
|
||||
column.x += 32u;
|
||||
}
|
||||
|
||||
if ((pos.x & 96u) != 0u)
|
||||
{
|
||||
uint multi = (pos.x & 96u) / 32u;
|
||||
column.y += 16u * multi; // 4 columns high times 4 to get bottom 4 blocks
|
||||
column.x -= (pos.x & 96u);
|
||||
}
|
||||
|
||||
if (((pos.x & 16u) != 0u) != ((pos.y & 16u) != 0u))
|
||||
{
|
||||
column.x ^= 16u;
|
||||
column.y ^= 8u;
|
||||
}
|
||||
|
||||
if ((PSM & 0x30u) != 0u) // PSMZ16 - Untested but hopefully ok if anything uses it.
|
||||
{
|
||||
column.x ^= 32u;
|
||||
column.y ^= 32u;
|
||||
}
|
||||
}
|
||||
uvec2 coord = column | subcolumn;
|
||||
|
||||
// Compensate for potentially differing page pitch.
|
||||
uvec2 block_xy = coord / uvec2(64u, 64u);
|
||||
uint block_num = (block_xy.y * (DBW / 128u)) + block_xy.x;
|
||||
uvec2 block_offset = uvec2((block_num % (SBW / 64u)) * 64u, (block_num / (SBW / 64u)) * 64u);
|
||||
coord = (coord % uvec2(64u, 64u)) + block_offset;
|
||||
|
||||
// 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
|
||||
|
||||
if (floor(ScaleFactor) != ScaleFactor)
|
||||
coord = uvec2(vec2(coord) * ScaleFactor);
|
||||
else
|
||||
coord *= uvec2(ScaleFactor);
|
||||
|
||||
vec4 pixel = texelFetch(TextureSampler, ivec2(coord), 0);
|
||||
|
||||
uvec4 denorm_c = uvec4(pixel * 255.5f);
|
||||
if ((pos.y & 2u) == 0u)
|
||||
{
|
||||
uint red = (denorm_c.r >> 3) & 0x1Fu;
|
||||
uint green = (denorm_c.g >> 3) & 0x1Fu;
|
||||
|
||||
o_col0 = vec4(float(((green << 5) | red) & 0xFFu) / 255.0f);
|
||||
}
|
||||
else
|
||||
{
|
||||
uint green = (denorm_c.g >> 3) & 0x1Fu;
|
||||
uint blue = (denorm_c.b >> 3) & 0x1Fu;
|
||||
uint alpha = denorm_c.a & 0x80u;
|
||||
|
||||
o_col0 = vec4(float((alpha | (blue << 2) | (green >> 3)) & 0xFFu) / 255.0f);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef ps_convert_rgba_8i
|
||||
uniform uint SBW;
|
||||
uniform uint DBW;
|
||||
uniform uint PSM;
|
||||
uniform float ScaleFactor;
|
||||
|
||||
void ps_convert_rgba_8i()
|
||||
{
|
||||
// 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
|
||||
uvec2 pos = uvec2(gl_FragCoord.xy);
|
||||
|
||||
// Collapse separate R G B A areas into their base pixel
|
||||
uvec2 block = gpu_bitwise_and(pos, ~uvec2(15u, 3u)) >> 1;
|
||||
uvec2 subblock = gpu_bitwise_and(pos, uvec2(7u, 1u));
|
||||
uvec2 coord = block | subblock;
|
||||
|
||||
// Compensate for potentially differing page pitch.
|
||||
uvec2 block_xy = coord / uvec2(64u, 32u);
|
||||
uint block_num = (block_xy.y * (DBW / 128u)) + block_xy.x;
|
||||
uvec2 block_offset = uvec2((block_num % (SBW / 64u)) * 64u, (block_num / (SBW / 64u)) * 32u);
|
||||
coord = (coord % uvec2(64u, 32u)) + block_offset;
|
||||
|
||||
// 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
|
||||
|
||||
if (floor(ScaleFactor) != ScaleFactor)
|
||||
coord = uvec2(vec2(coord) * ScaleFactor);
|
||||
else
|
||||
coord *= uvec2(ScaleFactor);
|
||||
|
||||
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;
|
||||
o_col0 = vec4(sel1);
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef ps_filter_transparency
|
||||
void ps_filter_transparency()
|
||||
{
|
||||
vec4 c = sample_c();
|
||||
o_col0 = vec4(c.rgb, 1.0);
|
||||
}
|
||||
#endif
|
||||
|
||||
// Used for DATE (stencil)
|
||||
// DATM == 1
|
||||
#ifdef ps_datm1
|
||||
void ps_datm1()
|
||||
{
|
||||
if(sample_c().a < (127.5f / 255.0f)) // >= 0x80 pass
|
||||
discard;
|
||||
}
|
||||
#endif
|
||||
|
||||
// Used for DATE (stencil)
|
||||
// DATM == 0
|
||||
#ifdef ps_datm0
|
||||
void ps_datm0()
|
||||
{
|
||||
if((127.5f / 255.0f) < sample_c().a) // < 0x80 pass (== 0x80 should not pass)
|
||||
discard;
|
||||
}
|
||||
#endif
|
||||
|
||||
// Used for DATE (stencil)
|
||||
// DATM == 1
|
||||
#ifdef ps_datm1_rta_correction
|
||||
void ps_datm1_rta_correction()
|
||||
{
|
||||
if(sample_c().a < (254.5f / 255.0f)) // >= 0x80 pass
|
||||
discard;
|
||||
}
|
||||
#endif
|
||||
|
||||
// Used for DATE (stencil)
|
||||
// DATM == 0
|
||||
#ifdef ps_datm0_rta_correction
|
||||
void ps_datm0_rta_correction()
|
||||
{
|
||||
if((254.5f / 255.0f) < sample_c().a) // < 0x80 pass (== 0x80 should not pass)
|
||||
discard;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef ps_rta_correction
|
||||
void ps_rta_correction()
|
||||
{
|
||||
vec4 value = sample_c();
|
||||
o_col0 = vec4(value.rgb, value.a / (128.25f / 255.0f));
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef ps_rta_decorrection
|
||||
void ps_rta_decorrection()
|
||||
{
|
||||
vec4 value = sample_c();
|
||||
o_col0 = vec4(value.rgb, value.a * (128.25f / 255.0f));
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef ps_colclip_init
|
||||
void ps_colclip_init()
|
||||
{
|
||||
vec4 value = sample_c();
|
||||
o_col0 = vec4(round(value.rgb * 255.0f) / 65535.0f, value.a);
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef ps_colclip_resolve
|
||||
void ps_colclip_resolve()
|
||||
{
|
||||
vec4 value = sample_c();
|
||||
o_col0 = vec4(vec3(gpu_bitwise_and(uvec3(value.rgb * 65535.0f), uvec3(255u))) / 255.0f, value.a);
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef ps_convert_clut_4
|
||||
uniform uvec3 offset;
|
||||
uniform float 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) * vec2(scale)));
|
||||
o_col0 = texelFetch(TextureSampler, final, 0);
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef ps_convert_clut_8
|
||||
uniform uvec3 offset;
|
||||
uniform float scale;
|
||||
|
||||
void ps_convert_clut_8()
|
||||
{
|
||||
uint index = min(uint(gl_FragCoord.x) + offset.z, 255u);
|
||||
|
||||
// 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) * vec2(scale)));
|
||||
o_col0 = texelFetch(TextureSampler, final, 0);
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef ps_yuv
|
||||
uniform ivec2 EMOD;
|
||||
|
||||
void ps_yuv()
|
||||
{
|
||||
vec4 i = sample_c();
|
||||
vec4 o = vec4(0.0f);
|
||||
|
||||
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;
|
||||
|
||||
switch(EMOD.x)
|
||||
{
|
||||
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;
|
||||
}
|
||||
|
||||
switch(EMOD.y)
|
||||
{
|
||||
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;
|
||||
}
|
||||
|
||||
o_col0 = o;
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(ps_primid_image_init_0) || defined(ps_primid_image_init_1) || defined(ps_primid_image_init_2) || defined(ps_primid_image_init_3)
|
||||
|
||||
void main()
|
||||
{
|
||||
o_col0 = vec4(0x7FFFFFFF);
|
||||
|
||||
#ifdef ps_primid_image_init_0
|
||||
if((127.5f / 255.0f) < sample_c().a) // < 0x80 pass (== 0x80 should not pass)
|
||||
o_col0 = vec4(-1);
|
||||
#endif
|
||||
#ifdef ps_primid_image_init_1
|
||||
if(sample_c().a < (127.5f / 255.0f)) // >= 0x80 pass
|
||||
o_col0 = vec4(-1);
|
||||
#endif
|
||||
#ifdef ps_primid_image_init_2
|
||||
if((254.5f / 255.0f) < sample_c().a) // < 0x80 pass (== 0x80 should not pass)
|
||||
o_col0 = vec4(-1);
|
||||
#endif
|
||||
#ifdef ps_primid_image_init_3
|
||||
if(sample_c().a < (254.5f / 255.0f)) // >= 0x80 pass
|
||||
o_col0 = vec4(-1);
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,38 @@
|
||||
// SPDX-FileCopyrightText: 2002-2026 PCSX2 Dev Team
|
||||
// SPDX-License-Identifier: GPL-3.0+
|
||||
|
||||
#ifdef VERTEX_SHADER
|
||||
|
||||
layout(location = 0) in vec2 Position;
|
||||
layout(location = 1) in vec2 UV;
|
||||
layout(location = 2) in vec4 Color;
|
||||
|
||||
uniform mat4 ProjMtx;
|
||||
|
||||
out vec2 Frag_UV;
|
||||
out vec4 Frag_Color;
|
||||
|
||||
void vs_main()
|
||||
{
|
||||
Frag_UV = UV;
|
||||
Frag_Color = Color;
|
||||
gl_Position = ProjMtx * vec4(Position.xy, 0.0, 1.0);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#ifdef FRAGMENT_SHADER
|
||||
|
||||
layout(binding = 0) uniform sampler2D Texture;
|
||||
|
||||
in vec2 Frag_UV;
|
||||
in vec4 Frag_Color;
|
||||
|
||||
layout(location = 0) out vec4 Out_Color;
|
||||
|
||||
void ps_main()
|
||||
{
|
||||
Out_Color = Frag_Color * texture(Texture, Frag_UV.st);
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,205 @@
|
||||
// SPDX-FileCopyrightText: 2002-2026 PCSX2 Dev Team
|
||||
// SPDX-License-Identifier: GPL-3.0+
|
||||
|
||||
//#version 420 // Keep it for editor detection
|
||||
|
||||
#ifdef FRAGMENT_SHADER
|
||||
|
||||
in vec4 PSin_p;
|
||||
in vec2 PSin_t;
|
||||
in vec4 PSin_c;
|
||||
|
||||
uniform vec4 ZrH;
|
||||
|
||||
layout(binding = 0) uniform sampler2D TextureSampler;
|
||||
|
||||
layout(location = 0) out vec4 SV_Target0;
|
||||
|
||||
|
||||
// Weave shader
|
||||
void ps_main0()
|
||||
{
|
||||
int idx = int(ZrH.x); // buffer index passed from CPU
|
||||
int field = idx & 1; // current field
|
||||
int vpos = int(gl_FragCoord.y); // vertical position of destination texture
|
||||
|
||||
if ((vpos & 1) == field)
|
||||
SV_Target0 = textureLod(TextureSampler, PSin_t, 0.0);
|
||||
else
|
||||
discard;
|
||||
}
|
||||
|
||||
|
||||
// Bob shader
|
||||
void ps_main1()
|
||||
{
|
||||
SV_Target0 = textureLod(TextureSampler, PSin_t, 0.0);
|
||||
}
|
||||
|
||||
|
||||
// Blend shader
|
||||
void ps_main2()
|
||||
{
|
||||
vec2 vstep = vec2(0.0f, ZrH.y);
|
||||
vec4 c0 = textureLod(TextureSampler, PSin_t - vstep, 0.0);
|
||||
vec4 c1 = textureLod(TextureSampler, PSin_t, 0.0);
|
||||
vec4 c2 = textureLod(TextureSampler, PSin_t + vstep, 0.0);
|
||||
|
||||
SV_Target0 = (c0 + c1 * 2.0f + c2) / 4.0f;
|
||||
}
|
||||
|
||||
|
||||
// MAD shader - buffering
|
||||
void ps_main3()
|
||||
{
|
||||
// We take half the lines from the current frame and stores them in the MAD frame buffer.
|
||||
// the MAD frame buffer is split in 2 consecutive banks of 2 fields each, the fields in each bank
|
||||
// are interleaved (top field at even lines and bottom field at odd lines).
|
||||
// When the source texture has an odd vres, the first line of bank 1 would be an odd index
|
||||
// causing the wrong lines to be discarded, so a vertical offset (lofs) is added to the vertical
|
||||
// position of the destination texture to force the proper field alignment
|
||||
|
||||
int idx = int(ZrH.x); // buffer index passed from CPU
|
||||
int bank = idx >> 1; // current bank
|
||||
int field = idx & 1; // current field
|
||||
int vres = int(ZrH.z) >> 1; // vertical resolution of source texture
|
||||
int lofs = ((((vres + 1) >> 1) << 1) - vres) & bank; // line alignment offset for bank 1
|
||||
int vpos = int(gl_FragCoord.y) + lofs; // vertical position of destination texture
|
||||
|
||||
// if the index of current destination line belongs to the current fiels we update it, otherwise
|
||||
// we leave the old line in the destination buffer
|
||||
if ((vpos & 1) == field)
|
||||
SV_Target0 = textureLod(TextureSampler, PSin_t, 0.0);
|
||||
else
|
||||
discard;
|
||||
}
|
||||
|
||||
|
||||
// MAD shader - reconstruction
|
||||
void ps_main4()
|
||||
{
|
||||
// we use the contents of the MAD frame buffer to reconstruct the missing lines from the current field.
|
||||
|
||||
int idx = int(ZrH.x); // buffer index passed from CPU
|
||||
int field = idx & 1; // current field
|
||||
int vpos = int(gl_FragCoord.y); // vertical position of destination texture
|
||||
float sensitivity = ZrH.w; // passed from CPU, higher values mean more likely to use weave
|
||||
vec3 motion_thr = vec3(1.0, 1.0, 1.0) * sensitivity; //
|
||||
vec2 bofs = vec2(0.0f, 0.5f); // position of the bank 1 relative to source texture size
|
||||
vec2 vscale = vec2(1.0f, 0.5f); // scaling factor from source to destination texture
|
||||
vec2 lofs = vec2(0.0f, ZrH.y) * vscale; // distance between two adjacent lines relative to source texture size
|
||||
vec2 iptr = PSin_t * vscale; // pointer to the current pixel in the source texture
|
||||
|
||||
vec2 p_t0; // pointer to current pixel (missing or not) from most recent frame
|
||||
vec2 p_t1; // pointer to current pixel (missing or not) from one frame back
|
||||
vec2 p_t2; // pointer to current pixel (missing or not) from two frames back
|
||||
vec2 p_t3; // pointer to current pixel (missing or not) from three frames back
|
||||
|
||||
switch (idx)
|
||||
{
|
||||
case 1:
|
||||
p_t0 = iptr;
|
||||
p_t1 = iptr;
|
||||
p_t2 = iptr + bofs;
|
||||
p_t3 = iptr + bofs;
|
||||
break;
|
||||
case 2:
|
||||
p_t0 = iptr + bofs;
|
||||
p_t1 = iptr;
|
||||
p_t2 = iptr;
|
||||
p_t3 = iptr + bofs;
|
||||
break;
|
||||
case 3:
|
||||
p_t0 = iptr + bofs;
|
||||
p_t1 = iptr + bofs;
|
||||
p_t2 = iptr;
|
||||
p_t3 = iptr;
|
||||
break;
|
||||
default:
|
||||
p_t0 = iptr;
|
||||
p_t1 = iptr + bofs;
|
||||
p_t2 = iptr + bofs;
|
||||
p_t3 = iptr;
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
// calculating motion, only relevant for missing lines where the "center line" is pointed
|
||||
// by p_t1
|
||||
|
||||
vec4 hn = textureLod(TextureSampler, p_t0 - lofs, 0.0); // new high pixel
|
||||
vec4 cn = textureLod(TextureSampler, p_t1, 0.0); // new center pixel
|
||||
vec4 ln = textureLod(TextureSampler, p_t0 + lofs, 0.0); // new low pixel
|
||||
|
||||
vec4 ho = textureLod(TextureSampler, p_t2 - lofs, 0.0); // old high pixel
|
||||
vec4 co = textureLod(TextureSampler, p_t3, 0.0); // old center pixel
|
||||
vec4 lo = textureLod(TextureSampler, p_t2 + lofs, 0.0); // old low pixel
|
||||
|
||||
vec3 mh = hn.rgb - ho.rgb; // high pixel motion
|
||||
vec3 mc = cn.rgb - co.rgb; // center pixel motion
|
||||
vec3 ml = ln.rgb - lo.rgb; // low pixel motion
|
||||
|
||||
mh = max(mh, -mh) - motion_thr;
|
||||
mc = max(mc, -mc) - motion_thr;
|
||||
ml = max(ml, -ml) - motion_thr;
|
||||
|
||||
#if 1 // use this code to evaluate each color motion separately
|
||||
float mh_max = max(max(mh.x, mh.y), mh.z);
|
||||
float mc_max = max(max(mc.x, mc.y), mc.z);
|
||||
float ml_max = max(max(ml.x, ml.y), ml.z);
|
||||
#else // use this code to evaluate average color motion
|
||||
float mh_max = mh.x + mh.y + mh.z;
|
||||
float mc_max = mc.x + mc.y + mc.z;
|
||||
float ml_max = ml.x + ml.y + ml.z;
|
||||
#endif
|
||||
|
||||
|
||||
// selecting deinterlacing output
|
||||
|
||||
if ((vpos & 1) == field)
|
||||
{
|
||||
// output coordinate present on current field
|
||||
SV_Target0 = textureLod(TextureSampler, p_t0, 0.0);
|
||||
}
|
||||
else if ((iptr.y > 0.5f - lofs.y) || (iptr.y < 0.0 + lofs.y))
|
||||
{
|
||||
// top and bottom lines are always weaved
|
||||
SV_Target0 = cn;
|
||||
}
|
||||
else
|
||||
{
|
||||
// missing line needs to be reconstructed
|
||||
if(((mh_max > 0.0f) || (ml_max > 0.0f)) || (mc_max > 0.0f))
|
||||
// high motion -> interpolate pixels above and below
|
||||
SV_Target0 = (hn + ln) / 2.0f;
|
||||
else
|
||||
{
|
||||
// Check if it's completely static first, we don't need to mess with any of that.
|
||||
if((mh_max != -motion_thr.x) || (ml_max != -motion_thr.x) || (mc_max != -motion_thr.x))
|
||||
{
|
||||
// Check the diff with the above and below lines, if the difference is smaller between the new high and low lines
|
||||
// compared to the new centre line and the high line (with some threshold of about 25 color steps), then reconstruct.
|
||||
vec3 mhln = hn.rgb - ln.rgb;
|
||||
vec3 mchn = hn.rgb - cn.rgb;
|
||||
|
||||
mhln = max(mhln, -mhln) - motion_thr;
|
||||
mchn = max(mchn, -mchn) - motion_thr;
|
||||
|
||||
float mhln_max = max(max(mhln.x, mhln.y), mhln.z);
|
||||
float mchn_max = max(max(mchn.x, mchn.y), mchn.z);
|
||||
|
||||
// The new centre line is a fair chunk different from those surrounding it, so quite likely incorrect.
|
||||
if (mhln_max < 0.0f && mchn_max >= (mhln_max * 0.90f))
|
||||
SV_Target0 = (hn + ln) / 2.0f;
|
||||
else
|
||||
// low motion -> weave
|
||||
SV_Target0 = cn;
|
||||
}
|
||||
else
|
||||
// low motion -> weave
|
||||
SV_Target0 = cn;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,33 @@
|
||||
// SPDX-FileCopyrightText: 2002-2026 PCSX2 Dev Team
|
||||
// SPDX-License-Identifier: GPL-3.0+
|
||||
|
||||
//#version 420 // Keep it for editor detection
|
||||
|
||||
#ifdef FRAGMENT_SHADER
|
||||
|
||||
in vec4 PSin_p;
|
||||
in vec2 PSin_t;
|
||||
in vec4 PSin_c;
|
||||
|
||||
uniform vec4 BGColor;
|
||||
|
||||
layout(binding = 0) uniform sampler2D TextureSampler;
|
||||
|
||||
layout(location = 0) out vec4 SV_Target0;
|
||||
|
||||
void ps_main0()
|
||||
{
|
||||
vec4 c = texture(TextureSampler, PSin_t);
|
||||
// Note: clamping will be done by fixed unit
|
||||
c.a *= 2.0f;
|
||||
SV_Target0 = c;
|
||||
}
|
||||
|
||||
void ps_main1()
|
||||
{
|
||||
vec4 c = texture(TextureSampler, PSin_t);
|
||||
c.a = BGColor.a;
|
||||
SV_Target0 = c;
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,476 @@
|
||||
// SPDX-FileCopyrightText: 2002-2026 PCSX2 Dev Team
|
||||
// SPDX-License-Identifier: GPL-3.0+
|
||||
|
||||
//#version 420 // Keep it for editor detection
|
||||
|
||||
|
||||
#ifdef VERTEX_SHADER
|
||||
|
||||
layout(location = 0) in vec2 POSITION;
|
||||
layout(location = 1) in vec2 TEXCOORD0;
|
||||
layout(location = 7) in vec4 COLOR;
|
||||
|
||||
// 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.
|
||||
out vec4 PSin_p;
|
||||
out vec2 PSin_t;
|
||||
out vec4 PSin_c;
|
||||
|
||||
void vs_main()
|
||||
{
|
||||
PSin_p = vec4(POSITION, 0.5f, 1.0f);
|
||||
PSin_t = TEXCOORD0;
|
||||
PSin_c = COLOR;
|
||||
gl_Position = vec4(POSITION, 0.5f, 1.0f); // NOTE I don't know if it is possible to merge POSITION_OUT and gl_Position
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#ifdef FRAGMENT_SHADER
|
||||
|
||||
uniform vec4 u_source_rect;
|
||||
uniform vec4 u_target_rect;
|
||||
uniform vec2 u_source_size;
|
||||
uniform vec2 u_target_size;
|
||||
uniform vec2 u_target_resolution;
|
||||
uniform vec2 u_rcp_target_resolution; // 1 / u_target_resolution
|
||||
uniform vec2 u_source_resolution;
|
||||
uniform vec2 u_rcp_source_resolution; // 1 / u_source_resolution
|
||||
uniform float u_time;
|
||||
|
||||
in vec4 PSin_p;
|
||||
in vec2 PSin_t;
|
||||
in vec4 PSin_c;
|
||||
|
||||
layout(binding = 0) uniform sampler2D TextureSampler;
|
||||
|
||||
layout(location = 0) out vec4 SV_Target0;
|
||||
|
||||
vec4 sample_c()
|
||||
{
|
||||
return texture(TextureSampler, PSin_t);
|
||||
}
|
||||
|
||||
vec4 sample_c(vec2 uv)
|
||||
{
|
||||
return texture(TextureSampler, uv);
|
||||
}
|
||||
|
||||
vec4 ps_crt(uint i)
|
||||
{
|
||||
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));
|
||||
return sample_c() * clamp((mask[i] + 0.5f), 0.0f, 1.0f);
|
||||
}
|
||||
|
||||
#ifdef ps_copy
|
||||
void ps_copy()
|
||||
{
|
||||
SV_Target0 = sample_c();
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef ps_filter_scanlines
|
||||
vec4 ps_scanlines(uint i)
|
||||
{
|
||||
vec4 mask[2] = vec4[2]
|
||||
(
|
||||
vec4(1, 1, 1, 0),
|
||||
vec4(0, 0, 0, 0)
|
||||
);
|
||||
|
||||
return sample_c() * clamp((mask[i] + 0.5f), 0.0f, 1.0f);
|
||||
}
|
||||
|
||||
void ps_filter_scanlines() // scanlines
|
||||
{
|
||||
highp uvec4 p = uvec4(gl_FragCoord);
|
||||
|
||||
vec4 c = ps_scanlines(p.y % 2u);
|
||||
|
||||
SV_Target0 = c;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef ps_filter_diagonal
|
||||
void ps_filter_diagonal() // diagonal
|
||||
{
|
||||
highp uvec4 p = uvec4(gl_FragCoord);
|
||||
|
||||
vec4 c = ps_crt((p.x + (p.y % 3u)) % 3u);
|
||||
|
||||
SV_Target0 = c;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef ps_filter_triangular
|
||||
void ps_filter_triangular() // triangular
|
||||
{
|
||||
highp uvec4 p = uvec4(gl_FragCoord);
|
||||
|
||||
vec4 c = ps_crt(((p.x + ((p.y >> 1u) & 1u) * 3u) >> 1u) % 3u);
|
||||
|
||||
SV_Target0 = c;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef ps_filter_complex
|
||||
void ps_filter_complex()
|
||||
{
|
||||
const float PI = 3.14159265359f;
|
||||
vec2 texdim = vec2(textureSize(TextureSampler, 0));
|
||||
float factor = (0.9f - 0.4f * cos(2.0f * PI * PSin_t.y * texdim.y));
|
||||
vec4 c = factor * texture(TextureSampler, vec2(PSin_t.x, (floor(PSin_t.y * texdim.y) + 0.5f) / texdim.y));
|
||||
|
||||
SV_Target0 = c;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef ps_filter_lottes
|
||||
|
||||
#define MaskingType 4 //[1|2|3|4] The type of CRT shadow masking used. 1: compressed TV style, 2: Aperture-grille, 3: Stretched VGA style, 4: VGA style.
|
||||
#define ScanBrightness -8.00 //[-16.0 to 1.0] The overall brightness of the scanline effect. Lower for darker, higher for brighter.
|
||||
#define FilterCRTAmount -3.00 //[-4.0 to 1.0] The amount of filtering used, to replicate the TV CRT look. Lower for less, higher for more.
|
||||
#define HorizontalWarp 0.00 //[0.0 to 0.1] The distortion warping effect for the horizontal (x) axis of the screen. Use small increments.
|
||||
#define VerticalWarp 0.00 //[0.0 to 0.1] The distortion warping effect for the verticle (y) axis of the screen. Use small increments.
|
||||
#define MaskAmountDark 0.50 //[0.0 to 1.0] The value of the dark masking line effect used. Lower for darker lower end masking, higher for brighter.
|
||||
#define MaskAmountLight 1.50 //[0.0 to 2.0] The value of the light masking line effect used. Lower for darker higher end masking, higher for brighter.
|
||||
#define BloomPixel -1.50 //[-2.0 -0.5] Pixel bloom radius. Higher for increased softness of bloom.
|
||||
#define BloomScanLine -2.0 //[-4.0 -1.0] Scanline bloom radius. Higher for increased softness of bloom.
|
||||
#define BloomAmount 0.15 //[0.0 1.0] Bloom intensity. Higher for brighter.
|
||||
#define Shape 2.0 //[0.0 10.0] Kernal filter shape. Lower values will darken image and introduce moire patterns if used with curvature.
|
||||
#define UseShadowMask 1 //[0 or 1] Enables, or disables the use of the CRT shadow mask. 0 is disabled, 1 is enabled.
|
||||
|
||||
float ToLinear1(float c)
|
||||
{
|
||||
return c <= 0.04045 ? c / 12.92 : pow((c + 0.055) / 1.055, 2.4);
|
||||
}
|
||||
|
||||
vec3 ToLinear(vec3 c)
|
||||
{
|
||||
return vec3(ToLinear1(c.r), ToLinear1(c.g), ToLinear1(c.b));
|
||||
}
|
||||
|
||||
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));
|
||||
}
|
||||
|
||||
vec3 Fetch(vec2 pos, vec2 off)
|
||||
{
|
||||
pos = (floor(pos * u_target_size + off) + vec2(0.5, 0.5)) / u_target_size;
|
||||
if (max(abs(pos.x - 0.5), abs(pos.y - 0.5)) > 0.5)
|
||||
{
|
||||
return vec3(0.0, 0.0, 0.0);
|
||||
}
|
||||
else
|
||||
{
|
||||
return ToLinear(texture(TextureSampler, pos.xy).rgb);
|
||||
}
|
||||
}
|
||||
|
||||
vec2 Dist(vec2 pos)
|
||||
{
|
||||
pos = pos * vec2(640, 480);
|
||||
|
||||
return -((pos - floor(pos)) - vec2(0.5, 0.5));
|
||||
}
|
||||
|
||||
float Gaus(float pos, float scale)
|
||||
{
|
||||
return exp2(scale * pow(abs(pos), Shape));
|
||||
}
|
||||
|
||||
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 = FilterCRTAmount;
|
||||
float wb = Gaus(dst - 1.0, scale);
|
||||
float wc = Gaus(dst + 0.0, scale);
|
||||
float wd = Gaus(dst + 1.0, scale);
|
||||
|
||||
return (b * wb + c * wc + d * wd) / (wb + wc + wd);
|
||||
}
|
||||
|
||||
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 = FilterCRTAmount;
|
||||
|
||||
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 (a * wa + b * wb + c * wc + d * wd + e * we) / (wa + wb + wc + wd + we);
|
||||
}
|
||||
|
||||
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 = BloomPixel;
|
||||
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, ScanBrightness);
|
||||
}
|
||||
|
||||
float BloomScan(vec2 pos, float off)
|
||||
{
|
||||
float dst = Dist(pos).y;
|
||||
|
||||
return Gaus(dst + off, BloomScanLine);
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
vec2 Warp(vec2 pos)
|
||||
{
|
||||
pos = pos * 2.0 - 1.0;
|
||||
pos *= vec2(1.0 + (pos.y * pos.y) * HorizontalWarp, 1.0 + (pos.x * pos.x) * VerticalWarp);
|
||||
return pos * 0.5 + 0.5;
|
||||
}
|
||||
|
||||
vec3 Mask(vec2 pos)
|
||||
{
|
||||
#if MaskingType == 1
|
||||
// Very compressed TV style shadow mask.
|
||||
float lines = MaskAmountLight;
|
||||
float odd = 0.0;
|
||||
|
||||
if (fract(pos.x / 6.0) < 0.5)
|
||||
{
|
||||
odd = 1.0;
|
||||
}
|
||||
if (fract((pos.y + odd) / 2.0) < 0.5)
|
||||
{
|
||||
lines = MaskAmountDark;
|
||||
}
|
||||
pos.x = fract(pos.x / 3.0);
|
||||
vec3 mask = vec3(MaskAmountDark, MaskAmountDark, MaskAmountDark);
|
||||
|
||||
if (pos.x < 0.333)
|
||||
{
|
||||
mask.r = MaskAmountLight;
|
||||
}
|
||||
else if (pos.x < 0.666)
|
||||
{
|
||||
mask.g = MaskAmountLight;
|
||||
}
|
||||
else
|
||||
{
|
||||
mask.b = MaskAmountLight;
|
||||
}
|
||||
|
||||
mask *= lines;
|
||||
|
||||
return mask;
|
||||
|
||||
#elif MaskingType == 2
|
||||
// Aperture-grille.
|
||||
pos.x = fract(pos.x / 3.0);
|
||||
vec3 mask = vec3(MaskAmountDark, MaskAmountDark, MaskAmountDark);
|
||||
|
||||
if (pos.x < 0.333)
|
||||
{
|
||||
mask.r = MaskAmountLight;
|
||||
}
|
||||
else if (pos.x < 0.666)
|
||||
{
|
||||
mask.g = MaskAmountLight;
|
||||
}
|
||||
else
|
||||
{
|
||||
mask.b = MaskAmountLight;
|
||||
}
|
||||
|
||||
return mask;
|
||||
|
||||
#elif MaskingType == 3
|
||||
// Stretched VGA style shadow mask (same as prior shaders).
|
||||
pos.x += pos.y * 3.0;
|
||||
vec3 mask = vec3(MaskAmountDark, MaskAmountDark, MaskAmountDark);
|
||||
pos.x = fract(pos.x / 6.0);
|
||||
|
||||
if (pos.x < 0.333)
|
||||
{
|
||||
mask.r = MaskAmountLight;
|
||||
}
|
||||
else if (pos.x < 0.666)
|
||||
{
|
||||
mask.g = MaskAmountLight;
|
||||
}
|
||||
else
|
||||
{
|
||||
mask.b = MaskAmountLight;
|
||||
}
|
||||
|
||||
return mask;
|
||||
|
||||
#else
|
||||
// VGA style shadow mask.
|
||||
pos.xy = floor(pos.xy * vec2(1.0, 0.5));
|
||||
pos.x += pos.y * 3.0;
|
||||
|
||||
vec3 mask = vec3(MaskAmountDark, MaskAmountDark, MaskAmountDark);
|
||||
pos.x = fract(pos.x / 6.0);
|
||||
|
||||
if (pos.x < 0.333)
|
||||
{
|
||||
mask.r = MaskAmountLight;
|
||||
}
|
||||
else if (pos.x < 0.666)
|
||||
{
|
||||
mask.g = MaskAmountLight;
|
||||
}
|
||||
else
|
||||
{
|
||||
mask.b = MaskAmountLight;
|
||||
}
|
||||
return mask;
|
||||
#endif
|
||||
}
|
||||
|
||||
vec4 LottesCRTPass()
|
||||
{
|
||||
//flipped y axis in opengl
|
||||
vec2 fragcoord = vec2(gl_FragCoord.x, u_target_resolution.y - gl_FragCoord.y) - u_target_rect.xy;
|
||||
vec4 color;
|
||||
vec2 inSize = u_target_resolution - (2.0 * u_target_rect.xy);
|
||||
|
||||
vec2 pos = Warp(fragcoord.xy / inSize);
|
||||
color.rgb = Tri(pos);
|
||||
color.rgb += Bloom(pos) * BloomAmount;
|
||||
#if UseShadowMask
|
||||
color.rgb *= Mask(fragcoord.xy);
|
||||
#endif
|
||||
color.rgb = ToSrgb(color.rgb);
|
||||
|
||||
return color;
|
||||
}
|
||||
|
||||
void ps_filter_lottes()
|
||||
{
|
||||
SV_Target0 = LottesCRTPass();
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#ifdef ps_4x_rgss
|
||||
void ps_4x_rgss()
|
||||
{
|
||||
vec2 dxy = vec2(dFdx(PSin_t.x), dFdy(PSin_t.y));
|
||||
vec3 color = vec3(0);
|
||||
|
||||
float s = 1.0/8.0;
|
||||
float l = 3.0/8.0;
|
||||
|
||||
color += sample_c(PSin_t + vec2( s, l) * dxy).rgb;
|
||||
color += sample_c(PSin_t + vec2( l,-s) * dxy).rgb;
|
||||
color += sample_c(PSin_t + vec2(-s,-l) * dxy).rgb;
|
||||
color += sample_c(PSin_t + vec2(-l, s) * dxy).rgb;
|
||||
|
||||
SV_Target0 = vec4(color * 0.25,1);
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef ps_automagical_supersampling
|
||||
void ps_automagical_supersampling()
|
||||
{
|
||||
vec2 ratio = (u_source_size / u_target_size) * 0.5;
|
||||
vec2 steps = floor(ratio);
|
||||
vec3 col = sample_c(PSin_t).rgb;
|
||||
float div = 1.0;
|
||||
|
||||
for (float y = 0.0; y < steps.y; y++)
|
||||
{
|
||||
for (float x = 0.0; x < steps.x; x++)
|
||||
{
|
||||
vec2 offset = vec2(x,y) - ratio * 0.5;
|
||||
col += sample_c(PSin_t + offset * u_rcp_source_resolution * 2.0).rgb;
|
||||
div++;
|
||||
}
|
||||
}
|
||||
|
||||
SV_Target0 = vec4(col / div, 1.0);
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,64 @@
|
||||
// SPDX-FileCopyrightText: 2002-2026 PCSX2 Dev Team
|
||||
// SPDX-License-Identifier: GPL-3.0+
|
||||
|
||||
//#version 420 // Keep it for editor detection
|
||||
|
||||
/*
|
||||
** Contrast, saturation, brightness
|
||||
** Code of this function is from TGM's shader pack
|
||||
** http://irrlicht.sourceforge.net/phpBB2/viewtopic.php?t=21057
|
||||
** TGM's author comment about the license (included in the previous link)
|
||||
** "do with it, what you want! its total free!
|
||||
** (but would be nice, if you say that you used my shaders :wink: ) but not necessary"
|
||||
*/
|
||||
|
||||
#ifdef FRAGMENT_SHADER
|
||||
|
||||
uniform vec4 params;
|
||||
|
||||
in vec4 PSin_p;
|
||||
in vec2 PSin_t;
|
||||
in vec4 PSin_c;
|
||||
|
||||
layout(binding = 0) uniform sampler2D TextureSampler;
|
||||
|
||||
layout(location = 0) out vec4 SV_Target0;
|
||||
|
||||
// For all settings: 1.0 = 100% 0.5=50% 1.5 = 150%
|
||||
vec4 ContrastSaturationBrightness(vec4 color)
|
||||
{
|
||||
float brt = params.x;
|
||||
float con = params.y;
|
||||
float sat = params.z;
|
||||
float gam = params.w;
|
||||
|
||||
// Increase or decrease these values to adjust r, g and b color channels separately
|
||||
const float AvgLumR = 0.5;
|
||||
const float AvgLumG = 0.5;
|
||||
const float AvgLumB = 0.5;
|
||||
|
||||
const vec3 LumCoeff = vec3(0.2125, 0.7154, 0.0721);
|
||||
|
||||
vec3 AvgLumin = vec3(AvgLumR, AvgLumG, AvgLumB);
|
||||
vec3 brtColor = color.rgb * brt;
|
||||
float dot_intensity = dot(brtColor, LumCoeff);
|
||||
vec3 intensity = vec3(dot_intensity, dot_intensity, dot_intensity);
|
||||
vec3 satColor = mix(intensity, brtColor, sat);
|
||||
vec3 conColor = mix(AvgLumin, satColor, con);
|
||||
|
||||
vec3 csb = conColor;
|
||||
csb = pow(csb, vec3(1.0 / gam));
|
||||
color.rgb = csb;
|
||||
|
||||
return color;
|
||||
}
|
||||
|
||||
|
||||
void ps_main()
|
||||
{
|
||||
vec4 c = texture(TextureSampler, PSin_t);
|
||||
SV_Target0 = ContrastSaturationBrightness(c);
|
||||
}
|
||||
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,71 @@
|
||||
#version 460 core
|
||||
#extension GL_EXT_samplerless_texture_functions : require
|
||||
|
||||
// Based on CAS_Shader.glsl
|
||||
// Copyright(c) 2019 Advanced Micro Devices, Inc.All rights reserved.
|
||||
// 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.
|
||||
|
||||
layout(push_constant) uniform const_buffer
|
||||
{
|
||||
uvec4 const0;
|
||||
uvec4 const1;
|
||||
ivec2 srcOffset;
|
||||
};
|
||||
|
||||
layout(set=0, binding=0) uniform texture2D imgSrc;
|
||||
layout(set=0, binding=1, rgba8) uniform writeonly image2D imgDst;
|
||||
layout(constant_id=0) const int sharpenOnly = 0;
|
||||
|
||||
#define A_GPU 1
|
||||
#define A_GLSL 1
|
||||
|
||||
#include "ffx_a.h"
|
||||
|
||||
AF3 CasLoad(ASU2 p)
|
||||
{
|
||||
return texelFetch(imgSrc, srcOffset + ivec2(p), 0).rgb;
|
||||
}
|
||||
|
||||
// Lets you transform input from the load into a linear color space between 0 and 1. See ffx_cas.h
|
||||
// In this case, our input is already linear and between 0 and 1
|
||||
void CasInput(inout AF1 r, inout AF1 g, inout AF1 b) {}
|
||||
|
||||
#include "ffx_cas.h"
|
||||
|
||||
layout(local_size_x=64) in;
|
||||
void main()
|
||||
{
|
||||
// Do remapping of local xy in workgroup for a more PS-like swizzle pattern.
|
||||
AU2 gxy = ARmp8x8(gl_LocalInvocationID.x)+AU2(gl_WorkGroupID.x<<4u,gl_WorkGroupID.y<<4u);
|
||||
|
||||
// Filter.
|
||||
AF4 c = vec4(0.0f);
|
||||
CasFilter(c.r, c.g, c.b, gxy, const0, const1, sharpenOnly != 0);
|
||||
imageStore(imgDst, ASU2(gxy), c);
|
||||
gxy.x += 8u;
|
||||
|
||||
CasFilter(c.r, c.g, c.b, gxy, const0, const1, sharpenOnly != 0);
|
||||
imageStore(imgDst, ASU2(gxy), c);
|
||||
gxy.y += 8u;
|
||||
|
||||
CasFilter(c.r, c.g, c.b, gxy, const0, const1, sharpenOnly != 0);
|
||||
imageStore(imgDst, ASU2(gxy), c);
|
||||
gxy.x -= 8u;
|
||||
|
||||
CasFilter(c.r, c.g, c.b, gxy, const0, const1, sharpenOnly != 0);
|
||||
imageStore(imgDst, ASU2(gxy), c);
|
||||
}
|
||||
@@ -0,0 +1,652 @@
|
||||
// SPDX-FileCopyrightText: 2002-2026 PCSX2 Dev Team
|
||||
// SPDX-License-Identifier: GPL-3.0+
|
||||
|
||||
#ifdef VERTEX_SHADER
|
||||
|
||||
layout(location = 0) in vec4 a_pos;
|
||||
layout(location = 1) in vec2 a_tex;
|
||||
|
||||
layout(location = 0) out vec2 v_tex;
|
||||
|
||||
void main()
|
||||
{
|
||||
gl_Position = vec4(a_pos.x, -a_pos.y, a_pos.z, a_pos.w);
|
||||
v_tex = a_tex;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#ifdef FRAGMENT_SHADER
|
||||
|
||||
layout(location = 0) in vec2 v_tex;
|
||||
|
||||
#if HAS_INTEGER_OUTPUT
|
||||
layout(location = 0) out uint o_col0;
|
||||
#define OUTPUT o_col0
|
||||
#elif HAS_DEPTH_OUTPUT
|
||||
out float gl_FragDepth;
|
||||
#define OUTPUT gl_FragDepth
|
||||
#elif HAS_FLOAT32_OUTPUT
|
||||
layout(location = 0) out float o_col0;
|
||||
#define OUTPUT o_col0
|
||||
#elif HAS_STENCIL_OUTPUT
|
||||
#else
|
||||
layout(location = 0) out vec4 o_col0;
|
||||
#define OUTPUT o_col0
|
||||
#endif
|
||||
|
||||
layout(set = 0, binding = 0) uniform sampler2D samp0;
|
||||
|
||||
#if HAS_FLOAT32_INPUT
|
||||
|
||||
float sample_c(vec2 uv)
|
||||
{
|
||||
return texture(samp0, uv).r;
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
vec4 sample_c(vec2 uv)
|
||||
{
|
||||
return texture(samp0, uv);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
uint rgba8_to_uint(vec4 c)
|
||||
{
|
||||
uvec4 i = gpu_bitwise_and(uvec4(c * 255.5f), uvec4(0xFFu));
|
||||
return i.r | (i.g << 8) | (i.b << 16) | (i.a << 24);
|
||||
}
|
||||
|
||||
uint rgb5a1_to_uint(vec4 c)
|
||||
{
|
||||
uvec4 i = gpu_bitwise_and(uvec4(c * 255.5f), uvec4(0xF8u, 0xF8u, 0xF8u, 0x80u));
|
||||
return (i.r >> 3) | (i.g << 2) | (i.b << 7) | (i.a << 8);
|
||||
}
|
||||
|
||||
uint depth_to_uint(float d)
|
||||
{
|
||||
return uint(d * exp2(32.0f));
|
||||
}
|
||||
|
||||
vec4 uint_to_rgba8(uint i)
|
||||
{
|
||||
return vec4((i & 0xFFu), ((i >> 8) & 0xFFu), ((i >> 16) & 0xFFu), ((i >> 24) & 0xFFu)) / 255.0f;
|
||||
}
|
||||
|
||||
vec4 uint_to_rgb5a1(uint i)
|
||||
{
|
||||
return vec4(gpu_bitwise_and(uvec4(i << 3, i >> 2, i >> 7, i >> 8), uvec4(0xF8u, 0xF8u, 0xF8u, 0x80u))) / 255.0f;
|
||||
}
|
||||
|
||||
float uint_to_depth32(uint i)
|
||||
{
|
||||
return float(i) * exp2(-32.0f);
|
||||
}
|
||||
|
||||
float uint_to_depth24(uint i)
|
||||
{
|
||||
return float(i & 0xFFFFFFu) * exp2(-32.0f);
|
||||
}
|
||||
|
||||
float uint_to_depth16(uint i)
|
||||
{
|
||||
return float(i & 0xFFFFu) * exp2(-32.0f);
|
||||
}
|
||||
|
||||
float rgba8_to_depth32(vec4 val)
|
||||
{
|
||||
return uint_to_depth32(rgba8_to_uint(val));
|
||||
}
|
||||
|
||||
float rgba8_to_depth24(vec4 val)
|
||||
{
|
||||
return uint_to_depth24(rgba8_to_uint(val));
|
||||
}
|
||||
|
||||
float rgba8_to_depth16(vec4 val)
|
||||
{
|
||||
return uint_to_depth16(rgba8_to_uint(val));
|
||||
}
|
||||
|
||||
float rgb5a1_to_depth16(vec4 val)
|
||||
{
|
||||
return uint_to_depth16(rgb5a1_to_uint(val));
|
||||
}
|
||||
|
||||
vec4 depth32_to_rgba8(float d)
|
||||
{
|
||||
return uint_to_rgba8(depth_to_uint(d));
|
||||
}
|
||||
|
||||
vec4 depth16_to_rgb5a1(float d)
|
||||
{
|
||||
return uint_to_rgb5a1(depth_to_uint(d));
|
||||
}
|
||||
|
||||
float depth32_to_depth24(float d)
|
||||
{
|
||||
return uint_to_depth24(depth_to_uint(d));
|
||||
}
|
||||
|
||||
#ifdef ps_copy
|
||||
void ps_copy()
|
||||
{
|
||||
OUTPUT = sample_c(v_tex);
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef ps_depth_copy
|
||||
void ps_depth_copy()
|
||||
{
|
||||
OUTPUT = sample_c(v_tex);
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef ps_downsample_copy
|
||||
layout(push_constant) uniform cb10
|
||||
{
|
||||
ivec2 ClampMin;
|
||||
int DownsampleFactor;
|
||||
int pad0;
|
||||
float Weight;
|
||||
float step_multiplier;
|
||||
vec2 pad1;
|
||||
};
|
||||
void ps_downsample_copy()
|
||||
{
|
||||
ivec2 coord = max(ivec2(gl_FragCoord.xy) * DownsampleFactor, ClampMin);
|
||||
vec4 result = vec4(0);
|
||||
for (int yoff = 0; yoff < DownsampleFactor; yoff++)
|
||||
{
|
||||
for (int xoff = 0; xoff < DownsampleFactor; xoff++)
|
||||
{
|
||||
result += texelFetch(samp0, coord + ivec2(xoff * step_multiplier, yoff * step_multiplier), 0);
|
||||
}
|
||||
}
|
||||
OUTPUT = result / Weight;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef ps_filter_transparency
|
||||
void ps_filter_transparency()
|
||||
{
|
||||
vec4 c = sample_c(v_tex);
|
||||
OUTPUT = vec4(c.rgb, 1.0);
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef ps_convert_rgb5a1_16bits
|
||||
void ps_convert_rgb5a1_16bits()
|
||||
{
|
||||
// Need to be careful with precision here, it can break games like Spider-Man 3 and Dogs Life
|
||||
OUTPUT = rgb5a1_to_uint(sample_c(v_tex));
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef ps_datm1
|
||||
void ps_datm1()
|
||||
{
|
||||
if(sample_c(v_tex).a < (127.5f / 255.0f)) // >= 0x80 pass
|
||||
discard;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef ps_datm0
|
||||
void ps_datm0()
|
||||
{
|
||||
if((127.5f / 255.0f) < sample_c(v_tex).a) // < 0x80 pass (== 0x80 should not pass)
|
||||
discard;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef ps_datm1_rta_correction
|
||||
void ps_datm1_rta_correction()
|
||||
{
|
||||
if(sample_c(v_tex).a < (254.5f / 255.0f)) // >= 0x80 pass
|
||||
discard;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef ps_datm0_rta_correction
|
||||
void ps_datm0_rta_correction()
|
||||
{
|
||||
if((254.5f / 255.0f) < sample_c(v_tex).a) // < 0x80 pass (== 0x80 should not pass)
|
||||
discard;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef ps_rta_correction
|
||||
void ps_rta_correction()
|
||||
{
|
||||
vec4 value = sample_c(v_tex);
|
||||
OUTPUT = vec4(value.rgb, value.a / (128.25f / 255.0f));
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef ps_rta_decorrection
|
||||
void ps_rta_decorrection()
|
||||
{
|
||||
vec4 value = sample_c(v_tex);
|
||||
OUTPUT = vec4(value.rgb, value.a * (128.25f / 255.0f));
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef ps_colclip_init
|
||||
void ps_colclip_init()
|
||||
{
|
||||
vec4 value = sample_c(v_tex);
|
||||
OUTPUT = vec4(roundEven(value.rgb * 255.0f) / 65535.0f, value.a);
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef ps_colclip_resolve
|
||||
void ps_colclip_resolve()
|
||||
{
|
||||
vec4 value = sample_c(v_tex);
|
||||
OUTPUT = vec4(vec3(gpu_bitwise_and(uvec3(value.rgb * 65535.5f), uvec3(255u))) / 255.0f, value.a);
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef ps_convert_depth32_32bits
|
||||
void ps_convert_depth32_32bits()
|
||||
{
|
||||
// Convert a vec32 depth texture into a 32 bits UINT texture
|
||||
OUTPUT = depth_to_uint(sample_c(v_tex));
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef ps_convert_depth32_rgba8
|
||||
void ps_convert_depth32_rgba8()
|
||||
{
|
||||
// Convert a vec32 depth texture into a RGBA color texture
|
||||
OUTPUT = depth32_to_rgba8(sample_c(v_tex));
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef ps_convert_depth16_rgb5a1
|
||||
void ps_convert_depth16_rgb5a1()
|
||||
{
|
||||
// Convert a vec32 (only 16 lsb) depth into a RGB5A1 color texture
|
||||
OUTPUT = depth16_to_rgb5a1(sample_c(v_tex));
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef ps_convert_depth32_depth24
|
||||
void ps_convert_depth32_depth24()
|
||||
{
|
||||
// Truncates depth value to 24bits
|
||||
OUTPUT = depth32_to_depth24(sample_c(v_tex));
|
||||
}
|
||||
#endif
|
||||
|
||||
#define SAMPLE_RGBA_DEPTH_BILN(CONVERT_FN) \
|
||||
ivec2 dims = textureSize(samp0, 0); \
|
||||
vec2 top_left_f = v_tex * 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(samp0, coords.xy, 0)); \
|
||||
float depthTR = CONVERT_FN(texelFetch(samp0, coords.zy, 0)); \
|
||||
float depthBL = CONVERT_FN(texelFetch(samp0, coords.xw, 0)); \
|
||||
float depthBR = CONVERT_FN(texelFetch(samp0, coords.zw, 0)); \
|
||||
OUTPUT = mix(mix(depthTL, depthTR, mix_vals.x), mix(depthBL, depthBR, mix_vals.x), mix_vals.y);
|
||||
|
||||
#ifdef ps_convert_rgba8_depth32
|
||||
void ps_convert_rgba8_depth32()
|
||||
{
|
||||
// Convert an RGBA texture into a float depth texture
|
||||
#if HAS_BILN
|
||||
SAMPLE_RGBA_DEPTH_BILN(rgba8_to_depth32);
|
||||
#else
|
||||
OUTPUT = rgba8_to_depth32(sample_c(v_tex));
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef ps_convert_rgba8_depth24
|
||||
void ps_convert_rgba8_depth24()
|
||||
{
|
||||
// Same as above but without the alpha channel (24 bits Z)
|
||||
#if HAS_BILN
|
||||
SAMPLE_RGBA_DEPTH_BILN(rgba8_to_depth24);
|
||||
#else
|
||||
OUTPUT = rgba8_to_depth24(sample_c(v_tex));
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef ps_convert_rgba8_depth16
|
||||
void ps_convert_rgba8_depth16()
|
||||
{
|
||||
// Same as above but without the A/B channels (16 bits Z)
|
||||
#if HAS_BILN
|
||||
SAMPLE_RGBA_DEPTH_BILN(rgba8_to_depth16);
|
||||
#else
|
||||
OUTPUT = rgba8_to_depth16(sample_c(v_tex));
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef ps_convert_rgb5a1_depth16
|
||||
void ps_convert_rgb5a1_depth16()
|
||||
{
|
||||
// Convert an RGB5A1 (saved as RGBA8) color to a 16 bit Z
|
||||
#if HAS_BILN
|
||||
SAMPLE_RGBA_DEPTH_BILN(rgb5a1_to_depth16);
|
||||
#else
|
||||
OUTPUT = rgb5a1_to_depth16(sample_c(v_tex));
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef ps_convert_rgb5a1_8i
|
||||
layout(push_constant) uniform cb10
|
||||
{
|
||||
uint SBW;
|
||||
uint DBW;
|
||||
uint PSM;
|
||||
float cb_pad1;
|
||||
float ScaleFactor;
|
||||
vec3 cb_pad2;
|
||||
};
|
||||
|
||||
void ps_convert_rgb5a1_8i()
|
||||
{
|
||||
// Convert a RGB5A1 texture into a 8 bits packed texture
|
||||
// Input column: 16x2 RGB5A1 pixels
|
||||
// 0: 16 RGBA
|
||||
// 1: 16 RGBA
|
||||
// Output column: 16x4 Index pixels
|
||||
// 0: 16 R5G2
|
||||
// 1: 16 R5G2
|
||||
// 2: 16 G2B5A1
|
||||
// 3: 16 G2B5A1
|
||||
|
||||
uvec2 pos = uvec2(gl_FragCoord.xy);
|
||||
|
||||
// Collapse separate R G B A areas into their base pixel
|
||||
uvec2 column = gpu_bitwise_and(pos, ~uvec2(0u, 3u)) / uvec2(1u, 2u);
|
||||
uvec2 subcolumn = gpu_bitwise_and(pos, uvec2(0u, 1u));
|
||||
column.x -= (column.x / 128u) * 64u;
|
||||
column.y += (column.y / 32u) * 32u;
|
||||
|
||||
// Deal with swizzling differences
|
||||
if ((PSM & 0x8u) != 0u) // PSMCT16S
|
||||
{
|
||||
if ((pos.x & 32u) != 0u)
|
||||
{
|
||||
column.y += 32u; // 4 columns high times 4 to get bottom 4 blocks
|
||||
column.x &= ~32u;
|
||||
}
|
||||
|
||||
if ((pos.x & 64u) != 0u)
|
||||
{
|
||||
column.x -= 32u;
|
||||
}
|
||||
|
||||
if (((pos.x & 16u) != 0u) != ((pos.y & 16u) != 0u))
|
||||
{
|
||||
column.x ^= 16u;
|
||||
column.y ^= 8u;
|
||||
}
|
||||
|
||||
if ((PSM & 0x30u) != 0u) // PSMZ16S - Untested but hopefully ok if anything uses it.
|
||||
{
|
||||
column.x ^= 32u;
|
||||
column.y ^= 16u;
|
||||
}
|
||||
}
|
||||
else // PSMCT16
|
||||
{
|
||||
if ((pos.y & 32u) != 0u)
|
||||
{
|
||||
column.y -= 16u;
|
||||
column.x += 32u;
|
||||
}
|
||||
|
||||
if ((pos.x & 96u) != 0u)
|
||||
{
|
||||
uint multi = (pos.x & 96u) / 32u;
|
||||
column.y += 16u * multi; // 4 columns high times 4 to get bottom 4 blocks
|
||||
column.x -= (pos.x & 96u);
|
||||
}
|
||||
|
||||
if (((pos.x & 16u) != 0u) != ((pos.y & 16u) != 0u))
|
||||
{
|
||||
column.x ^= 16u;
|
||||
column.y ^= 8u;
|
||||
}
|
||||
|
||||
if ((PSM & 0x30u) != 0u) // PSMZ16 - Untested but hopefully ok if anything uses it.
|
||||
{
|
||||
column.x ^= 32u;
|
||||
column.y ^= 32u;
|
||||
}
|
||||
}
|
||||
uvec2 coord = column | subcolumn;
|
||||
|
||||
// Compensate for potentially differing page pitch.
|
||||
uvec2 block_xy = coord / uvec2(64u, 64u);
|
||||
uint block_num = (block_xy.y * (DBW / 128u)) + block_xy.x;
|
||||
uvec2 block_offset = uvec2((block_num % (SBW / 64u)) * 64u, (block_num / (SBW / 64u)) * 64u);
|
||||
coord = (coord % uvec2(64u, 64u)) + block_offset;
|
||||
|
||||
// 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
|
||||
|
||||
if (floor(ScaleFactor) != ScaleFactor)
|
||||
coord = uvec2(vec2(coord) * ScaleFactor);
|
||||
else
|
||||
coord *= uvec2(ScaleFactor);
|
||||
|
||||
vec4 pixel = texelFetch(samp0, ivec2(coord), 0);
|
||||
|
||||
uvec4 denorm_c = uvec4(pixel * 255.5f);
|
||||
if ((pos.y & 2u) == 0u)
|
||||
{
|
||||
uint red = (denorm_c.r >> 3) & 0x1Fu;
|
||||
uint green = (denorm_c.g >> 3) & 0x1Fu;
|
||||
|
||||
o_col0 = vec4(float(((green << 5) | red) & 0xFFu) / 255.0f);
|
||||
}
|
||||
else
|
||||
{
|
||||
uint green = (denorm_c.g >> 3) & 0x1Fu;
|
||||
uint blue = (denorm_c.b >> 3) & 0x1Fu;
|
||||
uint alpha = denorm_c.a & 0x80u;
|
||||
|
||||
o_col0 = vec4(float((alpha | (blue << 2) | (green >> 3)) & 0xFFu) / 255.0f);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef ps_convert_rgba_8i
|
||||
layout(push_constant) uniform cb10
|
||||
{
|
||||
uint SBW;
|
||||
uint DBW;
|
||||
uint PSM;
|
||||
float cb_pad1;
|
||||
float ScaleFactor;
|
||||
vec3 cb_pad2;
|
||||
};
|
||||
|
||||
void ps_convert_rgba_8i()
|
||||
{
|
||||
// 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
|
||||
uvec2 pos = uvec2(gl_FragCoord.xy);
|
||||
|
||||
// Collapse separate R G B A areas into their base pixel
|
||||
uvec2 block = gpu_bitwise_and(pos, ~uvec2(15u, 3u)) >> 1;
|
||||
uvec2 subblock = gpu_bitwise_and(pos, uvec2(7u, 1u));
|
||||
uvec2 coord = block | subblock;
|
||||
|
||||
// Compensate for potentially differing page pitch.
|
||||
uvec2 block_xy = coord / uvec2(64u, 32u);
|
||||
uint block_num = (block_xy.y * (DBW / 128u)) + block_xy.x;
|
||||
uvec2 block_offset = uvec2((block_num % (SBW / 64u)) * 64u, (block_num / (SBW / 64u)) * 32u);
|
||||
coord = (coord % uvec2(64u, 32u)) + block_offset;
|
||||
|
||||
// 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
|
||||
|
||||
if (floor(ScaleFactor) != ScaleFactor)
|
||||
coord = uvec2(vec2(coord) * ScaleFactor);
|
||||
else
|
||||
coord *= uvec2(ScaleFactor);
|
||||
|
||||
vec4 pixel = texelFetch(samp0, ivec2(coord), 0);
|
||||
vec2 sel0 = (pos.y & 2u) == 0u ? pixel.rb : pixel.ga;
|
||||
float sel1 = (pos.x & 8u) == 0u ? sel0.x : sel0.y;
|
||||
o_col0 = vec4(sel1); // Divide by something here?
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef ps_convert_clut_4
|
||||
layout(push_constant) uniform cb10
|
||||
{
|
||||
uvec2 offset;
|
||||
uint doffset;
|
||||
uint cb_pad1;
|
||||
float scale;
|
||||
vec3 cb_pad2;
|
||||
};
|
||||
|
||||
void ps_convert_clut_4()
|
||||
{
|
||||
// CLUT4 is easy, just two rows of 8x8.
|
||||
uint index = uint(gl_FragCoord.x) + doffset;
|
||||
uvec2 pos = uvec2(index % 8u, index / 8u);
|
||||
|
||||
ivec2 final = ivec2(floor(vec2(offset + pos) * vec2(scale)));
|
||||
o_col0 = texelFetch(samp0, final, 0);
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef ps_convert_clut_8
|
||||
layout(push_constant) uniform cb10
|
||||
{
|
||||
uvec2 offset;
|
||||
uint doffset;
|
||||
uint cb_pad1;
|
||||
float scale;
|
||||
vec3 cb_pad2;
|
||||
};
|
||||
|
||||
void ps_convert_clut_8()
|
||||
{
|
||||
uint index = min(uint(gl_FragCoord.x) + doffset, 255u);
|
||||
|
||||
// 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 + pos) * vec2(scale)));
|
||||
o_col0 = texelFetch(samp0, final, 0);
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef ps_yuv
|
||||
layout(push_constant) uniform cb10
|
||||
{
|
||||
int EMODA;
|
||||
int EMODC;
|
||||
};
|
||||
|
||||
void ps_yuv()
|
||||
{
|
||||
vec4 i = sample_c(v_tex);
|
||||
vec4 o = vec4(0.0f);
|
||||
|
||||
mat3 rgb2yuv;
|
||||
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;
|
||||
|
||||
switch(EMODA)
|
||||
{
|
||||
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;
|
||||
}
|
||||
|
||||
switch(EMODC)
|
||||
{
|
||||
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;
|
||||
}
|
||||
|
||||
o_col0 = o;
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(ps_primid_image_init_0) || defined(ps_primid_image_init_1) || defined(ps_primid_image_init_2) || defined(ps_primid_image_init_3)
|
||||
|
||||
void main()
|
||||
{
|
||||
o_col0 = vec4(0x7FFFFFFF);
|
||||
|
||||
#ifdef ps_primid_image_init_0
|
||||
if((127.5f / 255.0f) < sample_c(v_tex).a) // < 0x80 pass (== 0x80 should not pass)
|
||||
o_col0 = vec4(-1);
|
||||
#endif
|
||||
#ifdef ps_primid_image_init_1
|
||||
if(sample_c(v_tex).a < (127.5f / 255.0f)) // >= 0x80 pass
|
||||
o_col0 = vec4(-1);
|
||||
#endif
|
||||
#ifdef ps_primid_image_init_2
|
||||
if((254.5f / 255.0f) < sample_c(v_tex).a) // < 0x80 pass (== 0x80 should not pass)
|
||||
o_col0 = vec4(-1);
|
||||
#endif
|
||||
#ifdef ps_primid_image_init_3
|
||||
if(sample_c(v_tex).a < (254.5f / 255.0f)) // >= 0x80 pass
|
||||
o_col0 = vec4(-1);
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,42 @@
|
||||
// SPDX-FileCopyrightText: 2002-2026 PCSX2 Dev Team
|
||||
// SPDX-License-Identifier: GPL-3.0+
|
||||
|
||||
#ifdef VERTEX_SHADER
|
||||
|
||||
layout(location = 0) in vec2 Position;
|
||||
layout(location = 1) in vec2 UV;
|
||||
layout(location = 2) in vec4 Color;
|
||||
|
||||
layout(push_constant) uniform PushConstants
|
||||
{
|
||||
vec2 uScale;
|
||||
vec2 uTranslate;
|
||||
};
|
||||
|
||||
layout(location = 0) out vec2 Frag_UV;
|
||||
layout(location = 1) out vec4 Frag_Color;
|
||||
|
||||
void vs_main()
|
||||
{
|
||||
Frag_UV = UV;
|
||||
Frag_Color = Color;
|
||||
gl_Position = vec4(Position * uScale + uTranslate, 0.0f, 1.0f);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#ifdef FRAGMENT_SHADER
|
||||
|
||||
layout(binding = 0) uniform sampler2D Texture;
|
||||
|
||||
layout(location = 0) in vec2 Frag_UV;
|
||||
layout(location = 1) in vec4 Frag_Color;
|
||||
|
||||
layout(location = 0) out vec4 Out_Color;
|
||||
|
||||
void ps_main()
|
||||
{
|
||||
Out_Color = Frag_Color * texture(Texture, Frag_UV.st);
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,227 @@
|
||||
// SPDX-FileCopyrightText: 2002-2026 PCSX2 Dev Team
|
||||
// SPDX-License-Identifier: GPL-3.0+
|
||||
|
||||
#ifdef VERTEX_SHADER
|
||||
|
||||
layout(location = 0) in vec4 a_pos;
|
||||
layout(location = 1) in vec2 a_tex;
|
||||
|
||||
layout(location = 0) out vec2 v_tex;
|
||||
|
||||
void main()
|
||||
{
|
||||
gl_Position = vec4(a_pos.x, -a_pos.y, a_pos.z, a_pos.w);
|
||||
v_tex = a_tex;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#ifdef FRAGMENT_SHADER
|
||||
|
||||
layout(location = 0) in vec2 v_tex;
|
||||
layout(location = 0) out vec4 o_col0;
|
||||
|
||||
layout(push_constant) uniform cb0
|
||||
{
|
||||
vec4 ZrH;
|
||||
};
|
||||
|
||||
layout(set = 0, binding = 0) uniform sampler2D samp0;
|
||||
|
||||
|
||||
// Weave shader
|
||||
#ifdef ps_main0
|
||||
void ps_main0()
|
||||
{
|
||||
const int idx = int(ZrH.x); // buffer index passed from CPU
|
||||
const int field = idx & 1; // current field
|
||||
const int vpos = int(gl_FragCoord.y); // vertical position of destination texture
|
||||
|
||||
if ((vpos & 1) == field)
|
||||
o_col0 = textureLod(samp0, v_tex, 0);
|
||||
else
|
||||
discard;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
// Bob shader
|
||||
#ifdef ps_main1
|
||||
void ps_main1()
|
||||
{
|
||||
o_col0 = textureLod(samp0, v_tex, 0);
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
// Blend shader
|
||||
#ifdef ps_main2
|
||||
void ps_main2()
|
||||
{
|
||||
vec2 vstep = vec2(0.0f, ZrH.y);
|
||||
vec4 c0 = textureLod(samp0, v_tex - vstep, 0);
|
||||
vec4 c1 = textureLod(samp0, v_tex, 0);
|
||||
vec4 c2 = textureLod(samp0, v_tex + vstep, 0);
|
||||
|
||||
o_col0 = (c0 + c1 * 2.0f + c2) / 4.0f;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
// MAD shader - buffering
|
||||
#ifdef ps_main3
|
||||
void ps_main3()
|
||||
{
|
||||
// We take half the lines from the current frame and stores them in the MAD frame buffer.
|
||||
// the MAD frame buffer is split in 2 consecutive banks of 2 fields each, the fields in each bank
|
||||
// are interleaved (top field at even lines and bottom field at odd lines).
|
||||
// When the source texture has an odd vres, the first line of bank 1 would be an odd index
|
||||
// causing the wrong lines to be discarded, so a vertical offset (lofs) is added to the vertical
|
||||
// position of the destination texture to force the proper field alignment
|
||||
|
||||
const int idx = int(ZrH.x); // buffer index passed from CPU
|
||||
const int bank = idx >> 1; // current bank
|
||||
const int field = idx & 1; // current field
|
||||
const int vres = int(ZrH.z) >> 1; // vertical resolution of source texture
|
||||
const int lofs = ((((vres + 1) >> 1) << 1) - vres) & bank; // line alignment offset for bank 1
|
||||
const int vpos = int(gl_FragCoord.y) + lofs; // vertical position of destination texture
|
||||
|
||||
// if the index of current destination line belongs to the current fiels we update it, otherwise
|
||||
// we leave the old line in the destination buffer
|
||||
if ((vpos & 1) == field)
|
||||
o_col0 = textureLod(samp0, v_tex, 0);
|
||||
else
|
||||
discard;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
// MAD shader - reconstruction
|
||||
#ifdef ps_main4
|
||||
void ps_main4()
|
||||
{
|
||||
// we use the contents of the MAD frame buffer to reconstruct the missing lines from the current
|
||||
// field.
|
||||
|
||||
const int idx = int(ZrH.x); // buffer index passed from CPU
|
||||
const int bank = idx >> 1; // current bank
|
||||
const int field = idx & 1; // current field
|
||||
const int vpos = int(gl_FragCoord.y); // vertical position of destination texture
|
||||
const float sensitivity = ZrH.w; // passed from CPU, higher values mean more likely to use weave
|
||||
const vec3 motion_thr = vec3(1.0, 1.0, 1.0) * sensitivity; //
|
||||
const vec2 bofs = vec2(0.0f, 0.5f); // position of the bank 1 relative to source texture size
|
||||
const vec2 vscale = vec2(1.0f, 0.5f); // scaling factor from source to destination texture
|
||||
const vec2 lofs = vec2(0.0f, ZrH.y) * vscale; // distance between two adjacent lines relative to source texture size
|
||||
const vec2 iptr = v_tex * vscale; // pointer to the current pixel in the source texture
|
||||
|
||||
vec2 p_t0; // pointer to current pixel (missing or not) from most recent frame
|
||||
vec2 p_t1; // pointer to current pixel (missing or not) from one frame back
|
||||
vec2 p_t2; // pointer to current pixel (missing or not) from two frames back
|
||||
vec2 p_t3; // pointer to current pixel (missing or not) from three frames back
|
||||
|
||||
switch (idx)
|
||||
{
|
||||
case 1:
|
||||
p_t0 = iptr;
|
||||
p_t1 = iptr;
|
||||
p_t2 = iptr + bofs;
|
||||
p_t3 = iptr + bofs;
|
||||
break;
|
||||
case 2:
|
||||
p_t0 = iptr + bofs;
|
||||
p_t1 = iptr;
|
||||
p_t2 = iptr;
|
||||
p_t3 = iptr + bofs;
|
||||
break;
|
||||
case 3:
|
||||
p_t0 = iptr + bofs;
|
||||
p_t1 = iptr + bofs;
|
||||
p_t2 = iptr;
|
||||
p_t3 = iptr;
|
||||
break;
|
||||
default:
|
||||
p_t0 = iptr;
|
||||
p_t1 = iptr + bofs;
|
||||
p_t2 = iptr + bofs;
|
||||
p_t3 = iptr;
|
||||
break;
|
||||
}
|
||||
|
||||
// calculating motion, only relevant for missing lines where the "center line" is pointed by p_t1
|
||||
|
||||
vec4 hn = textureLod(samp0, p_t0 - lofs, 0); // new high pixel
|
||||
vec4 cn = textureLod(samp0, p_t1, 0); // new center pixel
|
||||
vec4 ln = textureLod(samp0, p_t0 + lofs, 0); // new low pixel
|
||||
|
||||
vec4 ho = textureLod(samp0, p_t2 - lofs, 0); // old high pixel
|
||||
vec4 co = textureLod(samp0, p_t3, 0); // old center pixel
|
||||
vec4 lo = textureLod(samp0, p_t2 + lofs, 0); // old low pixel
|
||||
|
||||
vec3 mh = hn.rgb - ho.rgb; // high pixel motion
|
||||
vec3 mc = cn.rgb - co.rgb; // center pixel motion
|
||||
vec3 ml = ln.rgb - lo.rgb; // low pixel motion
|
||||
|
||||
mh = max(mh, -mh) - motion_thr;
|
||||
mc = max(mc, -mc) - motion_thr;
|
||||
ml = max(ml, -ml) - motion_thr;
|
||||
|
||||
#if 1 // use this code to evaluate each color motion separately
|
||||
float mh_max = max(max(mh.x, mh.y), mh.z);
|
||||
float mc_max = max(max(mc.x, mc.y), mc.z);
|
||||
float ml_max = max(max(ml.x, ml.y), ml.z);
|
||||
#else // use this code to evaluate average color motion
|
||||
float mh_max = mh.x + mh.y + mh.z;
|
||||
float mc_max = mc.x + mc.y + mc.z;
|
||||
float ml_max = ml.x + ml.y + ml.z;
|
||||
#endif
|
||||
|
||||
// selecting deinterlacing output
|
||||
|
||||
if ((vpos & 1) == field) // output coordinate present on current field
|
||||
{
|
||||
// output coordinate present on current field
|
||||
o_col0 = textureLod(samp0, p_t0, 0);
|
||||
}
|
||||
else if ((iptr.y > 0.5f - lofs.y) || (iptr.y < 0.0 + lofs.y))
|
||||
{
|
||||
// top and bottom lines are always weaved
|
||||
o_col0 = cn;
|
||||
}
|
||||
else
|
||||
{
|
||||
// missing line needs to be reconstructed
|
||||
if(((mh_max > 0.0f) || (ml_max > 0.0f)) || (mc_max > 0.0f))
|
||||
// high motion -> interpolate pixels above and below
|
||||
o_col0 = (hn + ln) / 2.0f;
|
||||
else
|
||||
{
|
||||
// Check if it's completely static first, we don't need to mess with any of that.
|
||||
if((mh_max != -motion_thr.x) || (ml_max != -motion_thr.x) || (mc_max != -motion_thr.x))
|
||||
{
|
||||
// Check the diff with the above and below lines, if the difference is smaller between the new high and low lines
|
||||
// compared to the new centre line and the high line (with some threshold of about 25 color steps), then reconstruct.
|
||||
vec3 mhln = hn.rgb - ln.rgb;
|
||||
vec3 mchn = hn.rgb - cn.rgb;
|
||||
|
||||
mhln = max(mhln, -mhln) - motion_thr;
|
||||
mchn = max(mchn, -mchn) - motion_thr;
|
||||
|
||||
float mhln_max = max(max(mhln.x, mhln.y), mhln.z);
|
||||
float mchn_max = max(max(mchn.x, mchn.y), mchn.z);
|
||||
|
||||
// The new centre line is a fair chunk different from those surrounding it, so quite likely incorrect.
|
||||
if (mhln_max < 0.0f && mchn_max >= (mhln_max * 0.90f))
|
||||
o_col0 = (hn + ln) / 2.0f;
|
||||
else
|
||||
// low motion -> weave
|
||||
o_col0 = cn;
|
||||
}
|
||||
else
|
||||
// low motion -> weave
|
||||
o_col0 = cn;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,46 @@
|
||||
// SPDX-FileCopyrightText: 2002-2026 PCSX2 Dev Team
|
||||
// SPDX-License-Identifier: GPL-3.0+
|
||||
|
||||
#ifdef VERTEX_SHADER
|
||||
|
||||
layout(location = 0) in vec4 a_pos;
|
||||
layout(location = 1) in vec2 a_tex;
|
||||
|
||||
layout(location = 0) out vec2 v_tex;
|
||||
|
||||
void main()
|
||||
{
|
||||
gl_Position = vec4(a_pos.x, -a_pos.y, a_pos.z, a_pos.w);
|
||||
v_tex = a_tex;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#ifdef FRAGMENT_SHADER
|
||||
|
||||
layout(location = 0) in vec2 v_tex;
|
||||
layout(location = 0) out vec4 o_col0;
|
||||
|
||||
layout(push_constant) uniform cb10
|
||||
{
|
||||
vec4 BGColor;
|
||||
};
|
||||
|
||||
layout(set = 0, binding = 0) uniform sampler2D samp0;
|
||||
|
||||
void ps_main0()
|
||||
{
|
||||
vec4 c = texture(samp0, v_tex);
|
||||
// Note: clamping will be done by fixed unit
|
||||
c.a *= 2.0f;
|
||||
o_col0 = c;
|
||||
}
|
||||
|
||||
void ps_main1()
|
||||
{
|
||||
vec4 c = texture(samp0, v_tex);
|
||||
c.a = BGColor.a;
|
||||
o_col0 = c;
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,446 @@
|
||||
// SPDX-FileCopyrightText: 2002-2026 PCSX2 Dev Team
|
||||
// SPDX-License-Identifier: GPL-3.0+
|
||||
|
||||
#ifdef VERTEX_SHADER
|
||||
|
||||
layout(location = 0) in vec4 a_pos;
|
||||
layout(location = 1) in vec2 a_tex;
|
||||
|
||||
layout(location = 0) out vec2 v_tex;
|
||||
|
||||
void main()
|
||||
{
|
||||
gl_Position = vec4(a_pos.x, -a_pos.y, a_pos.z, a_pos.w);
|
||||
v_tex = a_tex;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#ifdef FRAGMENT_SHADER
|
||||
|
||||
layout(push_constant) uniform cb10
|
||||
{
|
||||
vec4 u_source_rect;
|
||||
vec4 u_target_rect;
|
||||
vec2 u_source_size;
|
||||
vec2 u_target_size;
|
||||
vec2 u_target_resolution;
|
||||
vec2 u_rcp_target_resolution; // 1 / u_target_resolution
|
||||
vec2 u_source_resolution;
|
||||
vec2 u_rcp_source_resolution; // 1 / u_source_resolution
|
||||
float u_time;
|
||||
};
|
||||
|
||||
layout(location = 0) in vec2 v_tex;
|
||||
|
||||
layout(location = 0) out vec4 o_col0;
|
||||
|
||||
layout(set = 0, binding = 0) uniform sampler2D samp0;
|
||||
|
||||
vec4 sample_c(vec2 uv)
|
||||
{
|
||||
return texture(samp0, uv);
|
||||
}
|
||||
|
||||
vec4 ps_crt(uint i)
|
||||
{
|
||||
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));
|
||||
return sample_c(v_tex) * clamp((mask[i] + 0.5f), 0.0f, 1.0f);
|
||||
}
|
||||
|
||||
vec4 ps_scanlines(uint i)
|
||||
{
|
||||
vec4 mask[2] =
|
||||
{
|
||||
vec4(1, 1, 1, 0),
|
||||
vec4(0, 0, 0, 0)};
|
||||
|
||||
return sample_c(v_tex) * clamp((mask[i] + 0.5f), 0.0f, 1.0f);
|
||||
}
|
||||
|
||||
#ifdef ps_copy
|
||||
void ps_copy()
|
||||
{
|
||||
o_col0 = sample_c(v_tex);
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef ps_filter_scanlines
|
||||
void ps_filter_scanlines() // scanlines
|
||||
{
|
||||
uvec4 p = uvec4(gl_FragCoord);
|
||||
|
||||
o_col0 = ps_scanlines(p.y % 2);
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef ps_filter_diagonal
|
||||
void ps_filter_diagonal() // diagonal
|
||||
{
|
||||
uvec4 p = uvec4(gl_FragCoord);
|
||||
o_col0 = ps_crt((p.x + (p.y % 3)) % 3);
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef ps_filter_triangular
|
||||
void ps_filter_triangular() // triangular
|
||||
{
|
||||
uvec4 p = uvec4(gl_FragCoord);
|
||||
|
||||
// output.c = ps_crt(input, ((p.x + (p.y & 1) * 3) >> 1) % 3);
|
||||
o_col0 = ps_crt(((p.x + ((p.y >> 1) & 1) * 3) >> 1) % 3);
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef ps_filter_complex
|
||||
void ps_filter_complex() // triangular
|
||||
{
|
||||
const float PI = 3.14159265359f;
|
||||
vec2 texdim = vec2(textureSize(samp0, 0));
|
||||
|
||||
o_col0 = (0.9 - 0.4 * cos(2 * PI * v_tex.y * texdim.y)) * sample_c(vec2(v_tex.x, (floor(v_tex.y * texdim.y) + 0.5) / texdim.y));
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef ps_filter_lottes
|
||||
|
||||
#define MaskingType 4 //[1|2|3|4] The type of CRT shadow masking used. 1: compressed TV style, 2: Aperture-grille, 3: Stretched VGA style, 4: VGA style.
|
||||
#define ScanBrightness -8.00 //[-16.0 to 1.0] The overall brightness of the scanline effect. Lower for darker, higher for brighter.
|
||||
#define FilterCRTAmount -3.00 //[-4.0 to 1.0] The amount of filtering used, to replicate the TV CRT look. Lower for less, higher for more.
|
||||
#define HorizontalWarp 0.00 //[0.0 to 0.1] The distortion warping effect for the horizontal (x) axis of the screen. Use small increments.
|
||||
#define VerticalWarp 0.00 //[0.0 to 0.1] The distortion warping effect for the verticle (y) axis of the screen. Use small increments.
|
||||
#define MaskAmountDark 0.50 //[0.0 to 1.0] The value of the dark masking line effect used. Lower for darker lower end masking, higher for brighter.
|
||||
#define MaskAmountLight 1.50 //[0.0 to 2.0] The value of the light masking line effect used. Lower for darker higher end masking, higher for brighter.
|
||||
#define BloomPixel -1.50 //[-2.0 -0.5] Pixel bloom radius. Higher for increased softness of bloom.
|
||||
#define BloomScanLine -2.0 //[-4.0 -1.0] Scanline bloom radius. Higher for increased softness of bloom.
|
||||
#define BloomAmount 0.15 //[0.0 1.0] Bloom intensity. Higher for brighter.
|
||||
#define Shape 2.0 //[0.0 10.0] Kernal filter shape. Lower values will darken image and introduce moire patterns if used with curvature.
|
||||
#define UseShadowMask 1 //[0 or 1] Enables, or disables the use of the CRT shadow mask. 0 is disabled, 1 is enabled.
|
||||
|
||||
float ToLinear1(float c)
|
||||
{
|
||||
return c <= 0.04045 ? c / 12.92 : pow((c + 0.055) / 1.055, 2.4);
|
||||
}
|
||||
|
||||
vec3 ToLinear(vec3 c)
|
||||
{
|
||||
return vec3(ToLinear1(c.r), ToLinear1(c.g), ToLinear1(c.b));
|
||||
}
|
||||
|
||||
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));
|
||||
}
|
||||
|
||||
vec3 Fetch(vec2 pos, vec2 off)
|
||||
{
|
||||
pos = (floor(pos * u_target_size + off) + vec2(0.5, 0.5)) / u_target_size;
|
||||
if (max(abs(pos.x - 0.5), abs(pos.y - 0.5)) > 0.5)
|
||||
{
|
||||
return vec3(0.0, 0.0, 0.0);
|
||||
}
|
||||
else
|
||||
{
|
||||
return ToLinear(texture(samp0, pos.xy).rgb);
|
||||
}
|
||||
}
|
||||
|
||||
vec2 Dist(vec2 pos)
|
||||
{
|
||||
pos = pos * vec2(640, 480);
|
||||
|
||||
return -((pos - floor(pos)) - vec2(0.5, 0.5));
|
||||
}
|
||||
|
||||
float Gaus(float pos, float scale)
|
||||
{
|
||||
return exp2(scale * pow(abs(pos), Shape));
|
||||
}
|
||||
|
||||
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 = FilterCRTAmount;
|
||||
float wb = Gaus(dst - 1.0, scale);
|
||||
float wc = Gaus(dst + 0.0, scale);
|
||||
float wd = Gaus(dst + 1.0, scale);
|
||||
|
||||
return (b * wb + c * wc + d * wd) / (wb + wc + wd);
|
||||
}
|
||||
|
||||
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 = FilterCRTAmount;
|
||||
|
||||
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 (a * wa + b * wb + c * wc + d * wd + e * we) / (wa + wb + wc + wd + we);
|
||||
}
|
||||
|
||||
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 = BloomPixel;
|
||||
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, ScanBrightness);
|
||||
}
|
||||
|
||||
float BloomScan(vec2 pos, float off)
|
||||
{
|
||||
float dst = Dist(pos).y;
|
||||
|
||||
return Gaus(dst + off, BloomScanLine);
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
vec2 Warp(vec2 pos)
|
||||
{
|
||||
pos = pos * 2.0 - 1.0;
|
||||
pos *= vec2(1.0 + (pos.y * pos.y) * HorizontalWarp, 1.0 + (pos.x * pos.x) * VerticalWarp);
|
||||
return pos * 0.5 + 0.5;
|
||||
}
|
||||
|
||||
vec3 Mask(vec2 pos)
|
||||
{
|
||||
#if MaskingType == 1
|
||||
// Very compressed TV style shadow mask.
|
||||
float lines = MaskAmountLight;
|
||||
float odd = 0.0;
|
||||
|
||||
if (fract(pos.x / 6.0) < 0.5)
|
||||
{
|
||||
odd = 1.0;
|
||||
}
|
||||
if (fract((pos.y + odd) / 2.0) < 0.5)
|
||||
{
|
||||
lines = MaskAmountDark;
|
||||
}
|
||||
pos.x = fract(pos.x / 3.0);
|
||||
vec3 mask = vec3(MaskAmountDark, MaskAmountDark, MaskAmountDark);
|
||||
|
||||
if (pos.x < 0.333)
|
||||
{
|
||||
mask.r = MaskAmountLight;
|
||||
}
|
||||
else if (pos.x < 0.666)
|
||||
{
|
||||
mask.g = MaskAmountLight;
|
||||
}
|
||||
else
|
||||
{
|
||||
mask.b = MaskAmountLight;
|
||||
}
|
||||
|
||||
mask *= lines;
|
||||
|
||||
return mask;
|
||||
|
||||
#elif MaskingType == 2
|
||||
// Aperture-grille.
|
||||
pos.x = fract(pos.x / 3.0);
|
||||
vec3 mask = vec3(MaskAmountDark, MaskAmountDark, MaskAmountDark);
|
||||
|
||||
if (pos.x < 0.333)
|
||||
{
|
||||
mask.r = MaskAmountLight;
|
||||
}
|
||||
else if (pos.x < 0.666)
|
||||
{
|
||||
mask.g = MaskAmountLight;
|
||||
}
|
||||
else
|
||||
{
|
||||
mask.b = MaskAmountLight;
|
||||
}
|
||||
|
||||
return mask;
|
||||
|
||||
#elif MaskingType == 3
|
||||
// Stretched VGA style shadow mask (same as prior shaders).
|
||||
pos.x += pos.y * 3.0;
|
||||
vec3 mask = vec3(MaskAmountDark, MaskAmountDark, MaskAmountDark);
|
||||
pos.x = fract(pos.x / 6.0);
|
||||
|
||||
if (pos.x < 0.333)
|
||||
{
|
||||
mask.r = MaskAmountLight;
|
||||
}
|
||||
else if (pos.x < 0.666)
|
||||
{
|
||||
mask.g = MaskAmountLight;
|
||||
}
|
||||
else
|
||||
{
|
||||
mask.b = MaskAmountLight;
|
||||
}
|
||||
|
||||
return mask;
|
||||
|
||||
#else
|
||||
// VGA style shadow mask.
|
||||
pos.xy = floor(pos.xy * vec2(1.0, 0.5));
|
||||
pos.x += pos.y * 3.0;
|
||||
|
||||
vec3 mask = vec3(MaskAmountDark, MaskAmountDark, MaskAmountDark);
|
||||
pos.x = fract(pos.x / 6.0);
|
||||
|
||||
if (pos.x < 0.333)
|
||||
{
|
||||
mask.r = MaskAmountLight;
|
||||
}
|
||||
else if (pos.x < 0.666)
|
||||
{
|
||||
mask.g = MaskAmountLight;
|
||||
}
|
||||
else
|
||||
{
|
||||
mask.b = MaskAmountLight;
|
||||
}
|
||||
return mask;
|
||||
#endif
|
||||
}
|
||||
|
||||
vec4 LottesCRTPass()
|
||||
{
|
||||
vec4 color;
|
||||
vec4 fragcoord = gl_FragCoord - u_target_rect;
|
||||
vec2 inSize = u_target_resolution - (2 * u_target_rect.xy);
|
||||
|
||||
vec2 pos = Warp(fragcoord.xy / inSize);
|
||||
color.rgb = Tri(pos);
|
||||
color.rgb += Bloom(pos) * BloomAmount;
|
||||
#if UseShadowMask
|
||||
color.rgb *= Mask(fragcoord.xy);
|
||||
#endif
|
||||
color.rgb = ToSrgb(color.rgb);
|
||||
|
||||
return color;
|
||||
}
|
||||
|
||||
void ps_filter_lottes()
|
||||
{
|
||||
o_col0 = LottesCRTPass();
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#ifdef ps_4x_rgss
|
||||
void ps_4x_rgss()
|
||||
{
|
||||
vec2 dxy = vec2(dFdx(v_tex.x), dFdy(v_tex.y));
|
||||
vec3 color = vec3(0);
|
||||
|
||||
float s = 1.0/8.0;
|
||||
float l = 3.0/8.0;
|
||||
|
||||
color += sample_c(v_tex + vec2( s, l) * dxy).rgb;
|
||||
color += sample_c(v_tex + vec2( l,-s) * dxy).rgb;
|
||||
color += sample_c(v_tex + vec2(-s,-l) * dxy).rgb;
|
||||
color += sample_c(v_tex + vec2(-l, s) * dxy).rgb;
|
||||
|
||||
o_col0 = vec4(color * 0.25, 1.0);
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef ps_automagical_supersampling
|
||||
void ps_automagical_supersampling()
|
||||
{
|
||||
vec2 ratio = (u_source_size / u_target_size) * 0.5;
|
||||
vec2 steps = floor(ratio);
|
||||
vec3 col = sample_c(v_tex).rgb;
|
||||
float div = 1.0;
|
||||
|
||||
for (float y = 0.0; y < steps.y; y++)
|
||||
{
|
||||
for (float x = 0.0; x < steps.x; x++)
|
||||
{
|
||||
vec2 offset = vec2(x,y) - ratio * 0.5;
|
||||
col += sample_c(v_tex + offset * u_rcp_source_resolution * 2.0).rgb;
|
||||
div++;
|
||||
}
|
||||
}
|
||||
|
||||
o_col0 = vec4(col / div, 1.0);
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,77 @@
|
||||
// SPDX-FileCopyrightText: 2002-2026 PCSX2 Dev Team
|
||||
// SPDX-License-Identifier: GPL-3.0+
|
||||
|
||||
//#version 420 // Keep it for editor detection
|
||||
|
||||
#ifdef VERTEX_SHADER
|
||||
|
||||
layout(location = 0) in vec4 a_pos;
|
||||
layout(location = 1) in vec2 a_tex;
|
||||
|
||||
layout(location = 0) out vec2 v_tex;
|
||||
|
||||
void main()
|
||||
{
|
||||
gl_Position = vec4(a_pos.x, -a_pos.y, a_pos.z, a_pos.w);
|
||||
v_tex = a_tex;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
/*
|
||||
** Contrast, saturation, brightness
|
||||
** Code of this function is from TGM's shader pack
|
||||
** http://irrlicht.sourceforge.net/phpBB2/viewtopic.php?t=21057
|
||||
** TGM's author comment about the license (included in the previous link)
|
||||
** "do with it, what you want! its total free!
|
||||
** (but would be nice, if you say that you used my shaders :wink: ) but not necessary"
|
||||
*/
|
||||
|
||||
#ifdef FRAGMENT_SHADER
|
||||
|
||||
layout(push_constant) uniform cb0
|
||||
{
|
||||
vec4 params;
|
||||
};
|
||||
|
||||
layout(set = 0, binding = 0) uniform sampler2D samp0;
|
||||
layout(location = 0) in vec2 v_tex;
|
||||
layout(location = 0) out vec4 o_col0;
|
||||
|
||||
// For all settings: 1.0 = 100% 0.5=50% 1.5 = 150%
|
||||
vec4 ContrastSaturationBrightness(vec4 color)
|
||||
{
|
||||
float brt = params.x;
|
||||
float con = params.y;
|
||||
float sat = params.z;
|
||||
float gam = params.w;
|
||||
|
||||
// Increase or decrease these values to adjust r, g and b color channels separately
|
||||
const float AvgLumR = 0.5;
|
||||
const float AvgLumG = 0.5;
|
||||
const float AvgLumB = 0.5;
|
||||
|
||||
const vec3 LumCoeff = vec3(0.2125, 0.7154, 0.0721);
|
||||
|
||||
vec3 AvgLumin = vec3(AvgLumR, AvgLumG, AvgLumB);
|
||||
vec3 brtColor = color.rgb * brt;
|
||||
float dot_intensity = dot(brtColor, LumCoeff);
|
||||
vec3 intensity = vec3(dot_intensity, dot_intensity, dot_intensity);
|
||||
vec3 satColor = mix(intensity, brtColor, sat);
|
||||
vec3 conColor = mix(AvgLumin, satColor, con);
|
||||
|
||||
vec3 csb = conColor;
|
||||
csb = pow(csb, vec3(1.0 / gam));
|
||||
color.rgb = csb;
|
||||
return color;
|
||||
}
|
||||
|
||||
|
||||
void main()
|
||||
{
|
||||
vec4 c = texture(samp0, v_tex);
|
||||
o_col0 = ContrastSaturationBrightness(c);
|
||||
}
|
||||
|
||||
|
||||
#endif
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -0,0 +1,65 @@
|
||||
// Based on CAS_Shader.glsl
|
||||
// Copyright(c) 2019 Advanced Micro Devices, Inc.All rights reserved.
|
||||
// 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.
|
||||
|
||||
uniform uvec4 const0;
|
||||
uniform uvec4 const1;
|
||||
uniform ivec2 srcOffset;
|
||||
|
||||
// Sampler binding defaults to 0 if not explicitly set; texture unit 0 is used in code.
|
||||
uniform sampler2D imgSrc;
|
||||
layout(binding=0, rgba8) uniform writeonly image2D imgDst;
|
||||
|
||||
#define A_GPU 1
|
||||
#define A_GLSL 1
|
||||
|
||||
#include "ffx_a.h"
|
||||
|
||||
AF3 CasLoad(ASU2 p)
|
||||
{
|
||||
return texelFetch(imgSrc, srcOffset + ivec2(p), 0).rgb;
|
||||
}
|
||||
|
||||
// Lets you transform input from the load into a linear color space between 0 and 1. See ffx_cas.h
|
||||
// In this case, our input is already linear and between 0 and 1
|
||||
void CasInput(inout AF1 r, inout AF1 g, inout AF1 b) {}
|
||||
|
||||
#include "ffx_cas.h"
|
||||
|
||||
layout(local_size_x=64) in;
|
||||
void main()
|
||||
{
|
||||
// Do remapping of local xy in workgroup for a more PS-like swizzle pattern.
|
||||
AU2 gxy = ARmp8x8(gl_LocalInvocationID.x)+AU2(gl_WorkGroupID.x<<4u,gl_WorkGroupID.y<<4u);
|
||||
|
||||
// Filter.
|
||||
AF4 c = vec4(0.0f);
|
||||
CasFilter(c.r, c.g, c.b, gxy, const0, const1, CAS_SHARPEN_ONLY);
|
||||
imageStore(imgDst, ASU2(gxy), c);
|
||||
gxy.x += 8u;
|
||||
|
||||
CasFilter(c.r, c.g, c.b, gxy, const0, const1, CAS_SHARPEN_ONLY);
|
||||
imageStore(imgDst, ASU2(gxy), c);
|
||||
gxy.y += 8u;
|
||||
|
||||
CasFilter(c.r, c.g, c.b, gxy, const0, const1, CAS_SHARPEN_ONLY);
|
||||
imageStore(imgDst, ASU2(gxy), c);
|
||||
gxy.x -= 8u;
|
||||
|
||||
CasFilter(c.r, c.g, c.b, gxy, const0, const1, CAS_SHARPEN_ONLY);
|
||||
imageStore(imgDst, ASU2(gxy), c);
|
||||
}
|
||||
@@ -0,0 +1,655 @@
|
||||
// SPDX-FileCopyrightText: 2002-2025 PCSX2 Dev Team
|
||||
// SPDX-License-Identifier: GPL-3.0+
|
||||
|
||||
//#version 420 // Keep it for editor detection
|
||||
|
||||
|
||||
#ifdef VERTEX_SHADER
|
||||
|
||||
layout(location = 0) in vec2 POSITION;
|
||||
layout(location = 1) in vec2 TEXCOORD0;
|
||||
layout(location = 7) in vec4 COLOR;
|
||||
|
||||
// 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.
|
||||
out vec4 PSin_p;
|
||||
out vec2 PSin_t;
|
||||
out vec4 PSin_c;
|
||||
|
||||
void vs_main()
|
||||
{
|
||||
PSin_p = vec4(POSITION, 0.5f, 1.0f);
|
||||
PSin_t = TEXCOORD0;
|
||||
PSin_c = COLOR;
|
||||
gl_Position = vec4(POSITION, 0.5f, 1.0f); // NOTE I don't know if it is possible to merge POSITION_OUT and gl_Position
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#ifdef FRAGMENT_SHADER
|
||||
|
||||
in vec4 PSin_p;
|
||||
in vec2 PSin_t;
|
||||
in vec4 PSin_c;
|
||||
|
||||
layout(binding = 0) uniform sampler2D TextureSampler;
|
||||
|
||||
// Give a different name so I remember there is a special case!
|
||||
#if defined(ps_convert_rgba8_16bits) || defined(ps_convert_float32_32bits)
|
||||
layout(location = 0) out uint SV_Target1;
|
||||
#elif defined(ps_convert_float32_depth_to_color)
|
||||
layout(location = 0) out float SV_Target0;
|
||||
#else
|
||||
layout(location = 0) out vec4 SV_Target0;
|
||||
#endif
|
||||
|
||||
vec4 sample_c()
|
||||
{
|
||||
return texture(TextureSampler, PSin_t);
|
||||
}
|
||||
|
||||
#ifdef ps_copy
|
||||
void ps_copy()
|
||||
{
|
||||
SV_Target0 = sample_c();
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef ps_depth_copy
|
||||
void ps_depth_copy()
|
||||
{
|
||||
gl_FragDepth = sample_c().r;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef ps_downsample_copy
|
||||
uniform ivec2 ClampMin;
|
||||
uniform int DownsampleFactor;
|
||||
uniform float Weight;
|
||||
uniform float StepMultiplier;
|
||||
|
||||
void ps_downsample_copy()
|
||||
{
|
||||
int step = int(StepMultiplier);
|
||||
ivec2 coord = max(ivec2(gl_FragCoord.xy) * DownsampleFactor, ClampMin);
|
||||
vec4 result = vec4(0);
|
||||
for (int yoff = 0; yoff < DownsampleFactor; yoff++)
|
||||
{
|
||||
for (int xoff = 0; xoff < DownsampleFactor; xoff++)
|
||||
result += texelFetch(TextureSampler, coord + ivec2(xoff * step, yoff * step), 0);
|
||||
}
|
||||
SV_Target0 = result / Weight;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef ps_convert_rgba8_16bits
|
||||
// Need to be careful with precision here, it can break games like Spider-Man 3 and Dogs Life
|
||||
void ps_convert_rgba8_16bits()
|
||||
{
|
||||
highp uvec4 i = uvec4(sample_c() * vec4(255.5f, 255.5f, 255.5f, 255.5f));
|
||||
|
||||
SV_Target1 = ((i.x & 0x00F8u) >> 3) | ((i.y & 0x00F8u) << 2) | ((i.z & 0x00f8u) << 7) | ((i.w & 0x80u) << 8);
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef ps_convert_float32_32bits
|
||||
void ps_convert_float32_32bits()
|
||||
{
|
||||
// Convert a GL_FLOAT32 depth texture into a 32 bits UINT texture
|
||||
#if HAS_CLIP_CONTROL
|
||||
SV_Target1 = uint(exp2(32.0f) * sample_c().r);
|
||||
#else
|
||||
SV_Target1 = uint(exp2(24.0f) * sample_c().r);
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef ps_convert_float32_rgba8
|
||||
void ps_convert_float32_rgba8()
|
||||
{
|
||||
// Convert a GL_FLOAT32 depth texture into a RGBA color texture
|
||||
#if HAS_CLIP_CONTROL
|
||||
uint d = uint(sample_c().r * exp2(32.0f));
|
||||
#else
|
||||
uint d = uint(sample_c().r * exp2(24.0f));
|
||||
#endif
|
||||
SV_Target0 = vec4(uvec4((d & 0xFFu), ((d >> 8) & 0xFFu), ((d >> 16) & 0xFFu), (d >> 24))) / vec4(255.0);
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef ps_convert_float16_rgb5a1
|
||||
void ps_convert_float16_rgb5a1()
|
||||
{
|
||||
// Convert a GL_FLOAT32 (only 16 lsb) depth into a RGB5A1 color texture
|
||||
#if HAS_CLIP_CONTROL
|
||||
uint d = uint(sample_c().r * exp2(32.0f));
|
||||
#else
|
||||
uint d = uint(sample_c().r * exp2(24.0f));
|
||||
#endif
|
||||
SV_Target0 = vec4(gpu_bitwise_and(uvec4(d << 3, d >> 2, d >> 7, d >> 8), uvec4(0xf8, 0xf8, 0xf8, 0x80))) / 255.0f;
|
||||
}
|
||||
#endif
|
||||
|
||||
float rgba8_to_depth32(vec4 unorm)
|
||||
{
|
||||
uvec4 c = uvec4(unorm * vec4(255.5f));
|
||||
#if HAS_CLIP_CONTROL
|
||||
return float(c.r | (c.g << 8) | (c.b << 16) | (c.a << 24)) * exp2(-32.0f);
|
||||
#else
|
||||
return float(c.r | (c.g << 8) | (c.b << 16) | (c.a << 24)) * exp2(-24.0f);
|
||||
#endif
|
||||
}
|
||||
|
||||
float rgba8_to_depth24(vec4 unorm)
|
||||
{
|
||||
uvec3 c = uvec3(unorm.rgb * vec3(255.5f));
|
||||
#if HAS_CLIP_CONTROL
|
||||
return float(c.r | (c.g << 8) | (c.b << 16)) * exp2(-32.0f);
|
||||
#else
|
||||
return float(c.r | (c.g << 8) | (c.b << 16)) * exp2(-24.0f);
|
||||
#endif
|
||||
}
|
||||
|
||||
float rgba8_to_depth16(vec4 unorm)
|
||||
{
|
||||
uvec2 c = uvec2(unorm.rg * vec2(255.5f));
|
||||
#if HAS_CLIP_CONTROL
|
||||
return float(c.r | (c.g << 8)) * exp2(-32.0f);
|
||||
#else
|
||||
return float(c.r | (c.g << 8)) * exp2(-24.0f);
|
||||
#endif
|
||||
}
|
||||
|
||||
float rgb5a1_to_depth16(vec4 unorm)
|
||||
{
|
||||
uvec4 c = uvec4(unorm * vec4(255.5f));
|
||||
#if HAS_CLIP_CONTROL
|
||||
return float(((c.r & 0xF8u) >> 3) | ((c.g & 0xF8u) << 2) | ((c.b & 0xF8u) << 7) | ((c.a & 0x80u) << 8)) * exp2(-32.0f);
|
||||
#else
|
||||
return float(((c.r & 0xF8u) >> 3) | ((c.g & 0xF8u) << 2) | ((c.b & 0xF8u) << 7) | ((c.a & 0x80u) << 8)) * exp2(-24.0f);
|
||||
#endif
|
||||
}
|
||||
|
||||
#ifdef ps_convert_float32_depth_to_color
|
||||
void ps_convert_float32_depth_to_color()
|
||||
{
|
||||
SV_Target0 = sample_c().r;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef ps_convert_float32_color_to_depth
|
||||
void ps_convert_float32_color_to_depth()
|
||||
{
|
||||
gl_FragDepth = sample_c().r;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef ps_convert_float32_float24
|
||||
void ps_convert_float32_float24()
|
||||
{
|
||||
// Truncates depth value to 24bits
|
||||
#if HAS_CLIP_CONTROL
|
||||
uint d = uint(sample_c().r * exp2(32.0f)) & 0xFFFFFFu;
|
||||
gl_FragDepth = float(d) * exp2(-32.0f);
|
||||
#else
|
||||
uint d = uint(sample_c().r * exp2(24.0f)) & 0xFFFFFFu;
|
||||
gl_FragDepth = float(d) * exp2(-24.0f);
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef ps_convert_rgba8_float32
|
||||
void ps_convert_rgba8_float32()
|
||||
{
|
||||
// Convert an RGBA texture into a float depth texture
|
||||
gl_FragDepth = rgba8_to_depth32(sample_c());
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef ps_convert_rgba8_float24
|
||||
void ps_convert_rgba8_float24()
|
||||
{
|
||||
// Same as above but without the alpha channel (24 bits Z)
|
||||
|
||||
// Convert an RGBA texture into a float depth texture
|
||||
gl_FragDepth = rgba8_to_depth24(sample_c());
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef ps_convert_rgba8_float16
|
||||
void ps_convert_rgba8_float16()
|
||||
{
|
||||
// Same as above but without the A/B channels (16 bits Z)
|
||||
|
||||
// Convert an RGBA texture into a float depth texture
|
||||
gl_FragDepth = rgba8_to_depth16(sample_c());
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef ps_convert_rgb5a1_float16
|
||||
void ps_convert_rgb5a1_float16()
|
||||
{
|
||||
// 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);
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef ps_convert_rgb5a1_8i
|
||||
uniform uint SBW;
|
||||
uniform uint DBW;
|
||||
uniform uint PSM;
|
||||
uniform float ScaleFactor;
|
||||
|
||||
void ps_convert_rgb5a1_8i()
|
||||
{
|
||||
// Convert a RGB5A1 texture into a 8 bits packed texture
|
||||
// Input column: 16x2 RGB5A1 pixels
|
||||
// 0: 16 RGBA
|
||||
// 1: 16 RGBA
|
||||
// Output column: 16x4 Index pixels
|
||||
// 0: 16 R5G2
|
||||
// 1: 16 R5G2
|
||||
// 2: 16 G2B5A1
|
||||
// 3: 16 G2B5A1
|
||||
|
||||
uvec2 pos = uvec2(gl_FragCoord.xy);
|
||||
|
||||
// Collapse separate R G B A areas into their base pixel
|
||||
uvec2 column = gpu_bitwise_and(pos, ~uvec2(0u, 3u)) / uvec2(1,2);
|
||||
uvec2 subcolumn = gpu_bitwise_and(pos, uvec2(0u, 1u));
|
||||
column.x -= (column.x / 128u) * 64u;
|
||||
column.y += (column.y / 32u) * 32u;
|
||||
|
||||
// Deal with swizzling differences
|
||||
if ((PSM & 0x8u) != 0u) // PSMCT16S
|
||||
{
|
||||
if ((pos.x & 32u) != 0u)
|
||||
{
|
||||
column.y += 32u; // 4 columns high times 4 to get bottom 4 blocks
|
||||
column.x &= ~32u;
|
||||
}
|
||||
|
||||
if ((pos.x & 64u) != 0u)
|
||||
{
|
||||
column.x -= 32u;
|
||||
}
|
||||
|
||||
if (((pos.x & 16u) != 0u) != ((pos.y & 16u) != 0u))
|
||||
{
|
||||
column.x ^= 16u;
|
||||
column.y ^= 8u;
|
||||
}
|
||||
|
||||
if ((PSM & 0x30u) != 0u) // PSMZ16S - Untested but hopefully ok if anything uses it.
|
||||
{
|
||||
column.x ^= 32u;
|
||||
column.y ^= 16u;
|
||||
}
|
||||
}
|
||||
else // PSMCT16
|
||||
{
|
||||
if ((pos.y & 32u) != 0u)
|
||||
{
|
||||
column.y -= 16u;
|
||||
column.x += 32u;
|
||||
}
|
||||
|
||||
if ((pos.x & 96u) != 0u)
|
||||
{
|
||||
uint multi = (pos.x & 96u) / 32u;
|
||||
column.y += 16u * multi; // 4 columns high times 4 to get bottom 4 blocks
|
||||
column.x -= (pos.x & 96u);
|
||||
}
|
||||
|
||||
if (((pos.x & 16u) != 0u) != ((pos.y & 16u) != 0u))
|
||||
{
|
||||
column.x ^= 16u;
|
||||
column.y ^= 8u;
|
||||
}
|
||||
|
||||
if ((PSM & 0x30u) != 0u) // PSMZ16 - Untested but hopefully ok if anything uses it.
|
||||
{
|
||||
column.x ^= 32u;
|
||||
column.y ^= 32u;
|
||||
}
|
||||
}
|
||||
uvec2 coord = column | subcolumn;
|
||||
|
||||
// Compensate for potentially differing page pitch.
|
||||
uvec2 block_xy = coord / uvec2(64u, 64u);
|
||||
uint block_num = (block_xy.y * (DBW / 128u)) + block_xy.x;
|
||||
uvec2 block_offset = uvec2((block_num % (SBW / 64u)) * 64u, (block_num / (SBW / 64u)) * 64u);
|
||||
coord = (coord % uvec2(64u, 64u)) + block_offset;
|
||||
|
||||
// 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
|
||||
|
||||
if (floor(ScaleFactor) != ScaleFactor)
|
||||
coord = uvec2(vec2(coord) * ScaleFactor);
|
||||
else
|
||||
coord *= uvec2(ScaleFactor);
|
||||
|
||||
vec4 pixel = texelFetch(TextureSampler, ivec2(coord), 0);
|
||||
|
||||
uvec4 denorm_c = uvec4(pixel * 255.5f);
|
||||
if ((pos.y & 2u) == 0u)
|
||||
{
|
||||
uint red = (denorm_c.r >> 3) & 0x1Fu;
|
||||
uint green = (denorm_c.g >> 3) & 0x1Fu;
|
||||
float sel0 = float(((green << 5) | red) & 0xFFu) / 255.0f;
|
||||
|
||||
SV_Target0 = vec4(sel0);
|
||||
}
|
||||
else
|
||||
{
|
||||
uint green = (denorm_c.g >> 3) & 0x1Fu;
|
||||
uint blue = (denorm_c.b >> 3) & 0x1Fu;
|
||||
uint alpha = denorm_c.a & 0x80u;
|
||||
float sel0 = float((alpha | (blue << 2) | (green >> 3)) & 0xFFu) / 255.0f;
|
||||
|
||||
SV_Target0 = vec4(sel0);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef ps_convert_rgba_8i
|
||||
uniform uint SBW;
|
||||
uniform uint DBW;
|
||||
uniform uint PSM;
|
||||
uniform float ScaleFactor;
|
||||
|
||||
void ps_convert_rgba_8i()
|
||||
{
|
||||
// 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
|
||||
uvec2 pos = uvec2(gl_FragCoord.xy);
|
||||
|
||||
// Collapse separate R G B A areas into their base pixel
|
||||
uvec2 block = gpu_bitwise_and(pos, ~uvec2(15u, 3u)) >> 1;
|
||||
uvec2 subblock = gpu_bitwise_and(pos, uvec2(7u, 1u));
|
||||
uvec2 coord = block | subblock;
|
||||
|
||||
// Compensate for potentially differing page pitch.
|
||||
uvec2 block_xy = coord / uvec2(64u, 32u);
|
||||
uint block_num = (block_xy.y * (DBW / 128u)) + block_xy.x;
|
||||
uvec2 block_offset = uvec2((block_num % (SBW / 64u)) * 64u, (block_num / (SBW / 64u)) * 32u);
|
||||
coord = (coord % uvec2(64u, 32u)) + block_offset;
|
||||
|
||||
// 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
|
||||
|
||||
if (floor(ScaleFactor) != ScaleFactor)
|
||||
coord = uvec2(vec2(coord) * ScaleFactor);
|
||||
else
|
||||
coord *= uvec2(ScaleFactor);
|
||||
|
||||
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);
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef ps_filter_transparency
|
||||
void ps_filter_transparency()
|
||||
{
|
||||
vec4 c = sample_c();
|
||||
SV_Target0 = vec4(c.rgb, 1.0);
|
||||
}
|
||||
#endif
|
||||
|
||||
// Used for DATE (stencil)
|
||||
// DATM == 1
|
||||
#ifdef ps_datm1
|
||||
void ps_datm1()
|
||||
{
|
||||
if(sample_c().a < (127.5f / 255.0f)) // >= 0x80 pass
|
||||
discard;
|
||||
}
|
||||
#endif
|
||||
|
||||
// Used for DATE (stencil)
|
||||
// DATM == 0
|
||||
#ifdef ps_datm0
|
||||
void ps_datm0()
|
||||
{
|
||||
if((127.5f / 255.0f) < sample_c().a) // < 0x80 pass (== 0x80 should not pass)
|
||||
discard;
|
||||
}
|
||||
#endif
|
||||
|
||||
// Used for DATE (stencil)
|
||||
// DATM == 1
|
||||
#ifdef ps_datm1_rta_correction
|
||||
void ps_datm1_rta_correction()
|
||||
{
|
||||
if(sample_c().a < (254.5f / 255.0f)) // >= 0x80 pass
|
||||
discard;
|
||||
}
|
||||
#endif
|
||||
|
||||
// Used for DATE (stencil)
|
||||
// DATM == 0
|
||||
#ifdef ps_datm0_rta_correction
|
||||
void ps_datm0_rta_correction()
|
||||
{
|
||||
if((254.5f / 255.0f) < sample_c().a) // < 0x80 pass (== 0x80 should not pass)
|
||||
discard;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef ps_rta_correction
|
||||
void ps_rta_correction()
|
||||
{
|
||||
vec4 value = sample_c();
|
||||
SV_Target0 = vec4(value.rgb, value.a / (128.25f / 255.0f));
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef ps_rta_decorrection
|
||||
void ps_rta_decorrection()
|
||||
{
|
||||
vec4 value = sample_c();
|
||||
SV_Target0 = vec4(value.rgb, value.a * (128.25f / 255.0f));
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef ps_colclip_init
|
||||
void ps_colclip_init()
|
||||
{
|
||||
vec4 value = sample_c();
|
||||
SV_Target0 = vec4(round(value.rgb * 255.0f) / 65535.0f, value.a);
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef ps_colclip_resolve
|
||||
void ps_colclip_resolve()
|
||||
{
|
||||
vec4 value = sample_c();
|
||||
SV_Target0 = vec4(vec3(gpu_bitwise_and(uvec3(value.rgb * 65535.0f), uvec3(255u))) / 255.0f, value.a);
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef ps_convert_clut_4
|
||||
uniform uvec3 offset;
|
||||
uniform float 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) * vec2(scale)));
|
||||
SV_Target0 = texelFetch(TextureSampler, final, 0);
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef ps_convert_clut_8
|
||||
uniform uvec3 offset;
|
||||
uniform float scale;
|
||||
|
||||
void ps_convert_clut_8()
|
||||
{
|
||||
uint index = min(uint(gl_FragCoord.x) + offset.z, 255u);
|
||||
|
||||
// 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) * vec2(scale)));
|
||||
SV_Target0 = texelFetch(TextureSampler, final, 0);
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef ps_yuv
|
||||
uniform ivec2 EMOD;
|
||||
|
||||
void ps_yuv()
|
||||
{
|
||||
vec4 i = sample_c();
|
||||
vec4 o = vec4(0.0f);
|
||||
|
||||
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;
|
||||
|
||||
switch(EMOD.x)
|
||||
{
|
||||
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;
|
||||
}
|
||||
|
||||
switch(EMOD.y)
|
||||
{
|
||||
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
|
||||
|
||||
#if defined(ps_stencil_image_init_0) || defined(ps_stencil_image_init_1) || defined(ps_stencil_image_init_2) || defined(ps_stencil_image_init_3)
|
||||
|
||||
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
|
||||
#ifdef ps_stencil_image_init_2
|
||||
if((254.5f / 255.0f) < sample_c().a) // < 0x80 pass (== 0x80 should not pass)
|
||||
SV_Target0 = vec4(-1);
|
||||
#endif
|
||||
#ifdef ps_stencil_image_init_3
|
||||
if(sample_c().a < (254.5f / 255.0f)) // >= 0x80 pass
|
||||
SV_Target0 = vec4(-1);
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,38 @@
|
||||
// SPDX-FileCopyrightText: 2002-2025 PCSX2 Dev Team
|
||||
// SPDX-License-Identifier: GPL-3.0+
|
||||
|
||||
#ifdef VERTEX_SHADER
|
||||
|
||||
layout(location = 0) in vec2 Position;
|
||||
layout(location = 1) in vec2 UV;
|
||||
layout(location = 2) in vec4 Color;
|
||||
|
||||
uniform mat4 ProjMtx;
|
||||
|
||||
out vec2 Frag_UV;
|
||||
out vec4 Frag_Color;
|
||||
|
||||
void vs_main()
|
||||
{
|
||||
Frag_UV = UV;
|
||||
Frag_Color = Color;
|
||||
gl_Position = ProjMtx * vec4(Position.xy, 0.0, 1.0);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#ifdef FRAGMENT_SHADER
|
||||
|
||||
layout(binding = 0) uniform sampler2D Texture;
|
||||
|
||||
in vec2 Frag_UV;
|
||||
in vec4 Frag_Color;
|
||||
|
||||
layout(location = 0) out vec4 Out_Color;
|
||||
|
||||
void ps_main()
|
||||
{
|
||||
Out_Color = Frag_Color * texture(Texture, Frag_UV.st);
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,181 @@
|
||||
// SPDX-FileCopyrightText: 2002-2025 PCSX2 Dev Team
|
||||
// SPDX-License-Identifier: GPL-3.0+
|
||||
|
||||
//#version 420 // Keep it for editor detection
|
||||
|
||||
#ifdef FRAGMENT_SHADER
|
||||
|
||||
in vec4 PSin_p;
|
||||
in vec2 PSin_t;
|
||||
in vec4 PSin_c;
|
||||
|
||||
uniform vec4 ZrH;
|
||||
|
||||
layout(binding = 0) uniform sampler2D TextureSampler;
|
||||
|
||||
layout(location = 0) out vec4 SV_Target0;
|
||||
|
||||
|
||||
// Weave shader
|
||||
void ps_main0()
|
||||
{
|
||||
int idx = int(ZrH.x); // buffer index passed from CPU
|
||||
int field = idx & 1; // current field
|
||||
int vpos = int(gl_FragCoord.y); // vertical position of destination texture
|
||||
|
||||
if ((vpos & 1) == field)
|
||||
SV_Target0 = textureLod(TextureSampler, PSin_t, 0.0f);
|
||||
else
|
||||
discard;
|
||||
}
|
||||
|
||||
|
||||
// Bob shader
|
||||
void ps_main1()
|
||||
{
|
||||
SV_Target0 = textureLod(TextureSampler, PSin_t, 0.0f);
|
||||
}
|
||||
|
||||
|
||||
// Blend shader
|
||||
void ps_main2()
|
||||
{
|
||||
vec2 vstep = vec2(0.0f, ZrH.y);
|
||||
vec4 c0 = textureLod(TextureSampler, PSin_t - vstep, 0.0f);
|
||||
vec4 c1 = textureLod(TextureSampler, PSin_t, 0.0f);
|
||||
vec4 c2 = textureLod(TextureSampler, PSin_t + vstep, 0.0f);
|
||||
|
||||
SV_Target0 = (c0 + c1 * 2.0f + c2) / 4.0f;
|
||||
}
|
||||
|
||||
|
||||
// MAD shader - buffering
|
||||
void ps_main3()
|
||||
{
|
||||
// We take half the lines from the current frame and stores them in the MAD frame buffer.
|
||||
// the MAD frame buffer is split in 2 consecutive banks of 2 fields each, the fields in each bank
|
||||
// are interleaved (top field at even lines and bottom field at odd lines).
|
||||
// When the source texture has an odd vres, the first line of bank 1 would be an odd index
|
||||
// causing the wrong lines to be discarded, so a vertical offset (lofs) is added to the vertical
|
||||
// position of the destination texture to force the proper field alignment
|
||||
|
||||
int idx = int(ZrH.x); // buffer index passed from CPU
|
||||
int bank = idx >> 1; // current bank
|
||||
int field = idx & 1; // current field
|
||||
int vres = int(ZrH.z) >> 1; // vertical resolution of source texture
|
||||
int lofs = ((((vres + 1) >> 1) << 1) - vres) & bank; // line alignment offset for bank 1
|
||||
int vpos = int(gl_FragCoord.y) + lofs; // vertical position of destination texture
|
||||
|
||||
// if the index of current destination line belongs to the current fiels we update it, otherwise
|
||||
// we leave the old line in the destination buffer
|
||||
if ((vpos & 1) == field)
|
||||
SV_Target0 = textureLod(TextureSampler, PSin_t, 0.0f);
|
||||
else
|
||||
discard;
|
||||
}
|
||||
|
||||
|
||||
// MAD shader - reconstruction
|
||||
void ps_main4()
|
||||
{
|
||||
// we use the contents of the MAD frame buffer to reconstruct the missing lines from the current field.
|
||||
|
||||
int idx = int(ZrH.x); // buffer index passed from CPU
|
||||
int field = idx & 1; // current field
|
||||
int vpos = int(gl_FragCoord.y); // vertical position of destination texture
|
||||
float sensitivity = ZrH.w; // passed from CPU, higher values mean more likely to use weave
|
||||
vec3 motion_thr = vec3(1.0, 1.0, 1.0) * sensitivity; //
|
||||
vec2 bofs = vec2(0.0f, 0.5f); // position of the bank 1 relative to source texture size
|
||||
vec2 vscale = vec2(1.0f, 0.5f); // scaling factor from source to destination texture
|
||||
vec2 lofs = vec2(0.0f, ZrH.y) * vscale; // distance between two adjacent lines relative to source texture size
|
||||
vec2 iptr = PSin_t * vscale; // pointer to the current pixel in the source texture
|
||||
|
||||
vec2 p_t0; // pointer to current pixel (missing or not) from most recent frame
|
||||
vec2 p_t1; // pointer to current pixel (missing or not) from one frame back
|
||||
vec2 p_t2; // pointer to current pixel (missing or not) from two frames back
|
||||
vec2 p_t3; // pointer to current pixel (missing or not) from three frames back
|
||||
|
||||
switch (idx)
|
||||
{
|
||||
case 1:
|
||||
p_t0 = iptr;
|
||||
p_t1 = iptr;
|
||||
p_t2 = iptr + bofs;
|
||||
p_t3 = iptr + bofs;
|
||||
break;
|
||||
case 2:
|
||||
p_t0 = iptr + bofs;
|
||||
p_t1 = iptr;
|
||||
p_t2 = iptr;
|
||||
p_t3 = iptr + bofs;
|
||||
break;
|
||||
case 3:
|
||||
p_t0 = iptr + bofs;
|
||||
p_t1 = iptr + bofs;
|
||||
p_t2 = iptr;
|
||||
p_t3 = iptr;
|
||||
break;
|
||||
default:
|
||||
p_t0 = iptr;
|
||||
p_t1 = iptr + bofs;
|
||||
p_t2 = iptr + bofs;
|
||||
p_t3 = iptr;
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
// calculating motion, only relevant for missing lines where the "center line" is pointed
|
||||
// by p_t1
|
||||
|
||||
vec4 hn = textureLod(TextureSampler, p_t0 - lofs, 0.0f); // new high pixel
|
||||
vec4 cn = textureLod(TextureSampler, p_t1, 0.0f); // new center pixel
|
||||
vec4 ln = textureLod(TextureSampler, p_t0 + lofs, 0.0f); // new low pixel
|
||||
|
||||
vec4 ho = textureLod(TextureSampler, p_t2 - lofs, 0.0f); // old high pixel
|
||||
vec4 co = textureLod(TextureSampler, p_t3, 0.0f); // old center pixel
|
||||
vec4 lo = textureLod(TextureSampler, p_t2 + lofs, 0.0f); // old low pixel
|
||||
|
||||
vec3 mh = hn.rgb - ho.rgb; // high pixel motion
|
||||
vec3 mc = cn.rgb - co.rgb; // center pixel motion
|
||||
vec3 ml = ln.rgb - lo.rgb; // low pixel motion
|
||||
|
||||
mh = max(mh, -mh) - motion_thr;
|
||||
mc = max(mc, -mc) - motion_thr;
|
||||
ml = max(ml, -ml) - motion_thr;
|
||||
|
||||
#if 1 // use this code to evaluate each color motion separately
|
||||
float mh_max = max(max(mh.x, mh.y), mh.z);
|
||||
float mc_max = max(max(mc.x, mc.y), mc.z);
|
||||
float ml_max = max(max(ml.x, ml.y), ml.z);
|
||||
#else // use this code to evaluate average color motion
|
||||
float mh_max = mh.x + mh.y + mh.z;
|
||||
float mc_max = mc.x + mc.y + mc.z;
|
||||
float ml_max = ml.x + ml.y + ml.z;
|
||||
#endif
|
||||
|
||||
|
||||
// selecting deinterlacing output
|
||||
|
||||
if ((vpos & 1) == field)
|
||||
{
|
||||
// output coordinate present on current field
|
||||
SV_Target0 = textureLod(TextureSampler, p_t0, 0.0f);
|
||||
}
|
||||
else if ((iptr.y > 0.5f - lofs.y) || (iptr.y < 0.0 + lofs.y))
|
||||
{
|
||||
// top and bottom lines are always weaved
|
||||
SV_Target0 = cn;
|
||||
}
|
||||
else
|
||||
{
|
||||
// missing line needs to be reconstructed
|
||||
if(((mh_max > 0.0f) || (ml_max > 0.0f)) || (mc_max > 0.0f))
|
||||
// high motion -> interpolate pixels above and below
|
||||
SV_Target0 = (hn + ln) / 2.0f;
|
||||
else
|
||||
// low motion -> weave
|
||||
SV_Target0 = cn;
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,33 @@
|
||||
// SPDX-FileCopyrightText: 2002-2025 PCSX2 Dev Team
|
||||
// SPDX-License-Identifier: GPL-3.0+
|
||||
|
||||
//#version 420 // Keep it for editor detection
|
||||
|
||||
#ifdef FRAGMENT_SHADER
|
||||
|
||||
in vec4 PSin_p;
|
||||
in vec2 PSin_t;
|
||||
in vec4 PSin_c;
|
||||
|
||||
uniform vec4 BGColor;
|
||||
|
||||
layout(binding = 0) uniform sampler2D TextureSampler;
|
||||
|
||||
layout(location = 0) out vec4 SV_Target0;
|
||||
|
||||
void ps_main0()
|
||||
{
|
||||
vec4 c = texture(TextureSampler, PSin_t);
|
||||
// Note: clamping will be done by fixed unit
|
||||
c.a *= 2.0f;
|
||||
SV_Target0 = c;
|
||||
}
|
||||
|
||||
void ps_main1()
|
||||
{
|
||||
vec4 c = texture(TextureSampler, PSin_t);
|
||||
c.a = BGColor.a;
|
||||
SV_Target0 = c;
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,553 @@
|
||||
// SPDX-FileCopyrightText: 2002-2025 PCSX2 Dev Team
|
||||
// SPDX-License-Identifier: GPL-3.0+
|
||||
|
||||
//#version 420 // Keep it for editor detection
|
||||
|
||||
|
||||
#ifdef VERTEX_SHADER
|
||||
|
||||
layout(location = 0) in vec2 POSITION;
|
||||
layout(location = 1) in vec2 TEXCOORD0;
|
||||
layout(location = 7) in vec4 COLOR;
|
||||
|
||||
// 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.
|
||||
out vec4 PSin_p;
|
||||
out vec2 PSin_t;
|
||||
out vec4 PSin_c;
|
||||
|
||||
void vs_main()
|
||||
{
|
||||
PSin_p = vec4(POSITION, 0.5f, 1.0f);
|
||||
PSin_t = TEXCOORD0;
|
||||
PSin_c = COLOR;
|
||||
gl_Position = vec4(POSITION, 0.5f, 1.0f); // NOTE I don't know if it is possible to merge POSITION_OUT and gl_Position
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#ifdef FRAGMENT_SHADER
|
||||
|
||||
uniform vec4 u_source_rect;
|
||||
uniform vec4 u_target_rect;
|
||||
uniform vec2 u_source_size;
|
||||
uniform vec2 u_target_size;
|
||||
uniform vec2 u_target_resolution;
|
||||
uniform vec2 u_rcp_target_resolution; // 1 / u_target_resolution
|
||||
uniform vec2 u_source_resolution;
|
||||
uniform vec2 u_rcp_source_resolution; // 1 / u_source_resolution
|
||||
uniform float u_time;
|
||||
|
||||
in vec4 PSin_p;
|
||||
in vec2 PSin_t;
|
||||
in vec4 PSin_c;
|
||||
|
||||
layout(binding = 0) uniform sampler2D TextureSampler;
|
||||
|
||||
layout(location = 0) out vec4 SV_Target0;
|
||||
|
||||
vec4 sample_c()
|
||||
{
|
||||
return texture(TextureSampler, PSin_t);
|
||||
}
|
||||
|
||||
vec4 sample_c(vec2 uv)
|
||||
{
|
||||
return texture(TextureSampler, uv);
|
||||
}
|
||||
|
||||
vec4 ps_crt(uint i)
|
||||
{
|
||||
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));
|
||||
return sample_c() * clamp((mask[i] + 0.5f), 0.0f, 1.0f);
|
||||
}
|
||||
|
||||
#ifdef ps_copy
|
||||
void ps_copy()
|
||||
{
|
||||
SV_Target0 = sample_c();
|
||||
}
|
||||
#endif
|
||||
#ifdef ps_sgsr
|
||||
// Snapdragon Game Super Resolution 1.
|
||||
// Copyright (c) 2025, Qualcomm Innovation Center, Inc.
|
||||
// SPDX-License-Identifier: BSD-3-Clause
|
||||
float sgsr_fast_lanczos2(float x)
|
||||
{
|
||||
float wa = x - 4.0;
|
||||
float wb = x * wa - wa;
|
||||
wa *= wa;
|
||||
return wb * wa;
|
||||
}
|
||||
|
||||
vec2 sgsr_weight_y(float dx, float dy, float c, float stddev)
|
||||
{
|
||||
float x = ((dx * dx) + (dy * dy)) * 0.55 + clamp(abs(c) * stddev, 0.0, 1.0);
|
||||
float w = sgsr_fast_lanczos2(x);
|
||||
return vec2(w, w * c);
|
||||
}
|
||||
|
||||
void ps_sgsr()
|
||||
{
|
||||
// u_time carries the selected SGSR mode for this presentation shader.
|
||||
// Quality covers subtle edges, Balanced is Qualcomm's reference tuning,
|
||||
// and Performance evaluates only stronger edges.
|
||||
float mode = clamp(floor(u_time + 0.5), 1.0, 3.0);
|
||||
float edge_threshold = (mode < 1.5) ? (4.0 / 255.0) : ((mode < 2.5) ? (8.0 / 255.0) : (16.0 / 255.0));
|
||||
float edge_sharpness = (mode < 1.5) ? 2.2 : ((mode < 2.5) ? 2.0 : 1.6);
|
||||
vec4 color = vec4(textureLod(TextureSampler, PSin_t, 0.0).rgb, 1.0);
|
||||
|
||||
vec2 img_coord = PSin_t * u_source_resolution + vec2(-0.5, 0.5);
|
||||
vec2 img_coord_pixel = floor(img_coord);
|
||||
vec2 coord = img_coord_pixel * u_rcp_source_resolution;
|
||||
vec2 pl = img_coord - img_coord_pixel;
|
||||
vec4 left = textureGather(TextureSampler, coord, 1);
|
||||
|
||||
float edge_vote = abs(left.z - left.y) + abs(color.g - left.y) + abs(color.g - left.z);
|
||||
if (edge_vote > edge_threshold)
|
||||
{
|
||||
coord.x += u_rcp_source_resolution.x;
|
||||
vec4 right = textureGather(TextureSampler, coord + vec2(u_rcp_source_resolution.x, 0.0), 1);
|
||||
vec4 up_down;
|
||||
up_down.xy = textureGather(TextureSampler, coord + vec2(0.0, -u_rcp_source_resolution.y), 1).wz;
|
||||
up_down.zw = textureGather(TextureSampler, coord + vec2(0.0, u_rcp_source_resolution.y), 1).yx;
|
||||
|
||||
float mean = (left.y + left.z + right.x + right.w) * 0.25;
|
||||
left -= vec4(mean);
|
||||
right -= vec4(mean);
|
||||
up_down -= vec4(mean);
|
||||
float center = color.g - mean;
|
||||
|
||||
float sum = dot(abs(left), vec4(1.0)) + dot(abs(right), vec4(1.0)) + dot(abs(up_down), vec4(1.0));
|
||||
float stddev = 2.181818 / max(sum, 1.0e-6);
|
||||
vec2 wy = sgsr_weight_y(pl.x, pl.y + 1.0, up_down.x, stddev);
|
||||
wy += sgsr_weight_y(pl.x - 1.0, pl.y + 1.0, up_down.y, stddev);
|
||||
wy += sgsr_weight_y(pl.x - 1.0, pl.y - 2.0, up_down.z, stddev);
|
||||
wy += sgsr_weight_y(pl.x, pl.y - 2.0, up_down.w, stddev);
|
||||
wy += sgsr_weight_y(pl.x + 1.0, pl.y - 1.0, left.x, stddev);
|
||||
wy += sgsr_weight_y(pl.x, pl.y - 1.0, left.y, stddev);
|
||||
wy += sgsr_weight_y(pl.x, pl.y, left.z, stddev);
|
||||
wy += sgsr_weight_y(pl.x + 1.0, pl.y, left.w, stddev);
|
||||
wy += sgsr_weight_y(pl.x - 1.0, pl.y - 1.0, right.x, stddev);
|
||||
wy += sgsr_weight_y(pl.x - 2.0, pl.y - 1.0, right.y, stddev);
|
||||
wy += sgsr_weight_y(pl.x - 2.0, pl.y, right.z, stddev);
|
||||
wy += sgsr_weight_y(pl.x - 1.0, pl.y, right.w, stddev);
|
||||
|
||||
float final_y = wy.y / max(wy.x, 1.0e-6);
|
||||
float max_y = max(max(left.y, left.z), max(right.x, right.w));
|
||||
float min_y = min(min(left.y, left.z), min(right.x, right.w));
|
||||
float delta_y = clamp(edge_sharpness * final_y, min_y, max_y) - center;
|
||||
delta_y = clamp(delta_y, -23.0 / 255.0, 23.0 / 255.0);
|
||||
color.rgb = clamp(color.rgb + vec3(delta_y), vec3(0.0), vec3(1.0));
|
||||
}
|
||||
|
||||
SV_Target0 = color;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
#ifdef ps_filter_scanlines
|
||||
vec4 ps_scanlines(uint i)
|
||||
{
|
||||
vec4 mask[2] = vec4[2]
|
||||
(
|
||||
vec4(1, 1, 1, 0),
|
||||
vec4(0, 0, 0, 0)
|
||||
);
|
||||
|
||||
return sample_c() * clamp((mask[i] + 0.5f), 0.0f, 1.0f);
|
||||
}
|
||||
|
||||
void ps_filter_scanlines() // scanlines
|
||||
{
|
||||
highp uvec4 p = uvec4(gl_FragCoord);
|
||||
|
||||
vec4 c = ps_scanlines(p.y % 2u);
|
||||
|
||||
SV_Target0 = c;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef ps_filter_diagonal
|
||||
void ps_filter_diagonal() // diagonal
|
||||
{
|
||||
highp uvec4 p = uvec4(gl_FragCoord);
|
||||
|
||||
vec4 c = ps_crt((p.x + (p.y % 3u)) % 3u);
|
||||
|
||||
SV_Target0 = c;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef ps_filter_triangular
|
||||
void ps_filter_triangular() // triangular
|
||||
{
|
||||
highp uvec4 p = uvec4(gl_FragCoord);
|
||||
|
||||
vec4 c = ps_crt(((p.x + ((p.y >> 1u) & 1u) * 3u) >> 1u) % 3u);
|
||||
|
||||
SV_Target0 = c;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef ps_filter_complex
|
||||
void ps_filter_complex()
|
||||
{
|
||||
const float PI = 3.14159265359f;
|
||||
vec2 texdim = vec2(textureSize(TextureSampler, 0));
|
||||
float factor = (0.9f - 0.4f * cos(2.0f * PI * PSin_t.y * texdim.y));
|
||||
vec4 c = factor * texture(TextureSampler, vec2(PSin_t.x, (floor(PSin_t.y * texdim.y) + 0.5f) / texdim.y));
|
||||
|
||||
SV_Target0 = c;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef ps_filter_lottes
|
||||
|
||||
#define MaskingType 4 //[1|2|3|4] The type of CRT shadow masking used. 1: compressed TV style, 2: Aperture-grille, 3: Stretched VGA style, 4: VGA style.
|
||||
#define ScanBrightness -8.00 //[-16.0 to 1.0] The overall brightness of the scanline effect. Lower for darker, higher for brighter.
|
||||
#define FilterCRTAmount -3.00 //[-4.0 to 1.0] The amount of filtering used, to replicate the TV CRT look. Lower for less, higher for more.
|
||||
#define HorizontalWarp 0.00 //[0.0 to 0.1] The distortion warping effect for the horizontal (x) axis of the screen. Use small increments.
|
||||
#define VerticalWarp 0.00 //[0.0 to 0.1] The distortion warping effect for the verticle (y) axis of the screen. Use small increments.
|
||||
#define MaskAmountDark 0.50 //[0.0 to 1.0] The value of the dark masking line effect used. Lower for darker lower end masking, higher for brighter.
|
||||
#define MaskAmountLight 1.50 //[0.0 to 2.0] The value of the light masking line effect used. Lower for darker higher end masking, higher for brighter.
|
||||
#define BloomPixel -1.50 //[-2.0 -0.5] Pixel bloom radius. Higher for increased softness of bloom.
|
||||
#define BloomScanLine -2.0 //[-4.0 -1.0] Scanline bloom radius. Higher for increased softness of bloom.
|
||||
#define BloomAmount 0.15 //[0.0 1.0] Bloom intensity. Higher for brighter.
|
||||
#define Shape 2.0 //[0.0 10.0] Kernal filter shape. Lower values will darken image and introduce moire patterns if used with curvature.
|
||||
#define UseShadowMask 1 //[0 or 1] Enables, or disables the use of the CRT shadow mask. 0 is disabled, 1 is enabled.
|
||||
|
||||
float ToLinear1(float c)
|
||||
{
|
||||
return c <= 0.04045 ? c / 12.92 : pow((c + 0.055) / 1.055, 2.4);
|
||||
}
|
||||
|
||||
vec3 ToLinear(vec3 c)
|
||||
{
|
||||
return vec3(ToLinear1(c.r), ToLinear1(c.g), ToLinear1(c.b));
|
||||
}
|
||||
|
||||
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));
|
||||
}
|
||||
|
||||
vec3 Fetch(vec2 pos, vec2 off)
|
||||
{
|
||||
pos = (floor(pos * u_target_size + off) + vec2(0.5, 0.5)) / u_target_size;
|
||||
if (max(abs(pos.x - 0.5), abs(pos.y - 0.5)) > 0.5)
|
||||
{
|
||||
return vec3(0.0, 0.0, 0.0);
|
||||
}
|
||||
else
|
||||
{
|
||||
return ToLinear(texture(TextureSampler, pos.xy).rgb);
|
||||
}
|
||||
}
|
||||
|
||||
vec2 Dist(vec2 pos)
|
||||
{
|
||||
pos = pos * vec2(640, 480);
|
||||
|
||||
return -((pos - floor(pos)) - vec2(0.5, 0.5));
|
||||
}
|
||||
|
||||
float Gaus(float pos, float scale)
|
||||
{
|
||||
return exp2(scale * pow(abs(pos), Shape));
|
||||
}
|
||||
|
||||
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 = FilterCRTAmount;
|
||||
float wb = Gaus(dst - 1.0, scale);
|
||||
float wc = Gaus(dst + 0.0, scale);
|
||||
float wd = Gaus(dst + 1.0, scale);
|
||||
|
||||
return (b * wb + c * wc + d * wd) / (wb + wc + wd);
|
||||
}
|
||||
|
||||
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 = FilterCRTAmount;
|
||||
|
||||
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 (a * wa + b * wb + c * wc + d * wd + e * we) / (wa + wb + wc + wd + we);
|
||||
}
|
||||
|
||||
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 = BloomPixel;
|
||||
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, ScanBrightness);
|
||||
}
|
||||
|
||||
float BloomScan(vec2 pos, float off)
|
||||
{
|
||||
float dst = Dist(pos).y;
|
||||
|
||||
return Gaus(dst + off, BloomScanLine);
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
vec2 Warp(vec2 pos)
|
||||
{
|
||||
pos = pos * 2.0 - 1.0;
|
||||
pos *= vec2(1.0 + (pos.y * pos.y) * HorizontalWarp, 1.0 + (pos.x * pos.x) * VerticalWarp);
|
||||
return pos * 0.5 + 0.5;
|
||||
}
|
||||
|
||||
vec3 Mask(vec2 pos)
|
||||
{
|
||||
#if MaskingType == 1
|
||||
// Very compressed TV style shadow mask.
|
||||
float lines = MaskAmountLight;
|
||||
float odd = 0.0;
|
||||
|
||||
if (fract(pos.x / 6.0) < 0.5)
|
||||
{
|
||||
odd = 1.0;
|
||||
}
|
||||
if (fract((pos.y + odd) / 2.0) < 0.5)
|
||||
{
|
||||
lines = MaskAmountDark;
|
||||
}
|
||||
pos.x = fract(pos.x / 3.0);
|
||||
vec3 mask = vec3(MaskAmountDark, MaskAmountDark, MaskAmountDark);
|
||||
|
||||
if (pos.x < 0.333)
|
||||
{
|
||||
mask.r = MaskAmountLight;
|
||||
}
|
||||
else if (pos.x < 0.666)
|
||||
{
|
||||
mask.g = MaskAmountLight;
|
||||
}
|
||||
else
|
||||
{
|
||||
mask.b = MaskAmountLight;
|
||||
}
|
||||
|
||||
mask *= lines;
|
||||
|
||||
return mask;
|
||||
|
||||
#elif MaskingType == 2
|
||||
// Aperture-grille.
|
||||
pos.x = fract(pos.x / 3.0);
|
||||
vec3 mask = vec3(MaskAmountDark, MaskAmountDark, MaskAmountDark);
|
||||
|
||||
if (pos.x < 0.333)
|
||||
{
|
||||
mask.r = MaskAmountLight;
|
||||
}
|
||||
else if (pos.x < 0.666)
|
||||
{
|
||||
mask.g = MaskAmountLight;
|
||||
}
|
||||
else
|
||||
{
|
||||
mask.b = MaskAmountLight;
|
||||
}
|
||||
|
||||
return mask;
|
||||
|
||||
#elif MaskingType == 3
|
||||
// Stretched VGA style shadow mask (same as prior shaders).
|
||||
pos.x += pos.y * 3.0;
|
||||
vec3 mask = vec3(MaskAmountDark, MaskAmountDark, MaskAmountDark);
|
||||
pos.x = fract(pos.x / 6.0);
|
||||
|
||||
if (pos.x < 0.333)
|
||||
{
|
||||
mask.r = MaskAmountLight;
|
||||
}
|
||||
else if (pos.x < 0.666)
|
||||
{
|
||||
mask.g = MaskAmountLight;
|
||||
}
|
||||
else
|
||||
{
|
||||
mask.b = MaskAmountLight;
|
||||
}
|
||||
|
||||
return mask;
|
||||
|
||||
#else
|
||||
// VGA style shadow mask.
|
||||
pos.xy = floor(pos.xy * vec2(1.0, 0.5));
|
||||
pos.x += pos.y * 3.0;
|
||||
|
||||
vec3 mask = vec3(MaskAmountDark, MaskAmountDark, MaskAmountDark);
|
||||
pos.x = fract(pos.x / 6.0);
|
||||
|
||||
if (pos.x < 0.333)
|
||||
{
|
||||
mask.r = MaskAmountLight;
|
||||
}
|
||||
else if (pos.x < 0.666)
|
||||
{
|
||||
mask.g = MaskAmountLight;
|
||||
}
|
||||
else
|
||||
{
|
||||
mask.b = MaskAmountLight;
|
||||
}
|
||||
return mask;
|
||||
#endif
|
||||
}
|
||||
|
||||
vec4 LottesCRTPass()
|
||||
{
|
||||
//flipped y axis in opengl
|
||||
vec2 fragcoord = vec2(gl_FragCoord.x, u_target_resolution.y - gl_FragCoord.y) - u_target_rect.xy;
|
||||
vec4 color;
|
||||
vec2 inSize = u_target_resolution - (2.0 * u_target_rect.xy);
|
||||
|
||||
vec2 pos = Warp(fragcoord.xy / inSize);
|
||||
color.rgb = Tri(pos);
|
||||
color.rgb += Bloom(pos) * BloomAmount;
|
||||
#if UseShadowMask
|
||||
color.rgb *= Mask(fragcoord.xy);
|
||||
#endif
|
||||
color.rgb = ToSrgb(color.rgb);
|
||||
|
||||
return color;
|
||||
}
|
||||
|
||||
void ps_filter_lottes()
|
||||
{
|
||||
SV_Target0 = LottesCRTPass();
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#ifdef ps_4x_rgss
|
||||
void ps_4x_rgss()
|
||||
{
|
||||
vec2 dxy = vec2(dFdx(PSin_t.x), dFdy(PSin_t.y));
|
||||
vec3 color = vec3(0);
|
||||
|
||||
float s = 1.0/8.0;
|
||||
float l = 3.0/8.0;
|
||||
|
||||
color += sample_c(PSin_t + vec2( s, l) * dxy).rgb;
|
||||
color += sample_c(PSin_t + vec2( l,-s) * dxy).rgb;
|
||||
color += sample_c(PSin_t + vec2(-s,-l) * dxy).rgb;
|
||||
color += sample_c(PSin_t + vec2(-l, s) * dxy).rgb;
|
||||
|
||||
SV_Target0 = vec4(color * 0.25,1);
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef ps_automagical_supersampling
|
||||
void ps_automagical_supersampling()
|
||||
{
|
||||
vec2 ratio = (u_source_size / u_target_size) * 0.5;
|
||||
vec2 steps = floor(ratio);
|
||||
vec3 col = sample_c(PSin_t).rgb;
|
||||
float div = 1.0;
|
||||
|
||||
for (float y = 0.0; y < steps.y; y++)
|
||||
{
|
||||
for (float x = 0.0; x < steps.x; x++)
|
||||
{
|
||||
vec2 offset = vec2(x,y) - ratio * 0.5;
|
||||
col += sample_c(PSin_t + offset * u_rcp_source_resolution * 2.0).rgb;
|
||||
div++;
|
||||
}
|
||||
}
|
||||
|
||||
SV_Target0 = vec4(col / div, 1);
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,60 @@
|
||||
// SPDX-FileCopyrightText: 2002-2025 PCSX2 Dev Team
|
||||
// SPDX-License-Identifier: GPL-3.0+
|
||||
|
||||
//#version 420 // Keep it for editor detection
|
||||
|
||||
/*
|
||||
** Contrast, saturation, brightness
|
||||
** Code of this function is from TGM's shader pack
|
||||
** http://irrlicht.sourceforge.net/phpBB2/viewtopic.php?t=21057
|
||||
** TGM's author comment about the license (included in the previous link)
|
||||
** "do with it, what you want! its total free!
|
||||
** (but would be nice, if you say that you used my shaders :wink: ) but not necessary"
|
||||
*/
|
||||
|
||||
#ifdef FRAGMENT_SHADER
|
||||
|
||||
uniform vec4 params;
|
||||
|
||||
in vec4 PSin_p;
|
||||
in vec2 PSin_t;
|
||||
in vec4 PSin_c;
|
||||
|
||||
layout(binding = 0) uniform sampler2D TextureSampler;
|
||||
|
||||
layout(location = 0) out vec4 SV_Target0;
|
||||
|
||||
// For all settings: 1.0 = 100% 0.5=50% 1.5 = 150%
|
||||
vec4 ContrastSaturationBrightness(vec4 color)
|
||||
{
|
||||
float brt = params.x;
|
||||
float con = params.y;
|
||||
float sat = params.z;
|
||||
|
||||
// Increase or decrease these values to adjust r, g and b color channels separately
|
||||
const float AvgLumR = 0.5;
|
||||
const float AvgLumG = 0.5;
|
||||
const float AvgLumB = 0.5;
|
||||
|
||||
const vec3 LumCoeff = vec3(0.2125, 0.7154, 0.0721);
|
||||
|
||||
vec3 AvgLumin = vec3(AvgLumR, AvgLumG, AvgLumB);
|
||||
vec3 brtColor = color.rgb * brt;
|
||||
float dot_intensity = dot(brtColor, LumCoeff);
|
||||
vec3 intensity = vec3(dot_intensity, dot_intensity, dot_intensity);
|
||||
vec3 satColor = mix(intensity, brtColor, sat);
|
||||
vec3 conColor = mix(AvgLumin, satColor, con);
|
||||
|
||||
color.rgb = conColor;
|
||||
return color;
|
||||
}
|
||||
|
||||
|
||||
void ps_main()
|
||||
{
|
||||
vec4 c = texture(TextureSampler, PSin_t);
|
||||
SV_Target0 = ContrastSaturationBrightness(c);
|
||||
}
|
||||
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,71 @@
|
||||
#version 460 core
|
||||
#extension GL_EXT_samplerless_texture_functions : require
|
||||
|
||||
// Based on CAS_Shader.glsl
|
||||
// Copyright(c) 2019 Advanced Micro Devices, Inc.All rights reserved.
|
||||
// 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.
|
||||
|
||||
layout(push_constant) uniform const_buffer
|
||||
{
|
||||
uvec4 const0;
|
||||
uvec4 const1;
|
||||
ivec2 srcOffset;
|
||||
};
|
||||
|
||||
layout(set=0, binding=0) uniform texture2D imgSrc;
|
||||
layout(set=0, binding=1, rgba8) uniform writeonly image2D imgDst;
|
||||
layout(constant_id=0) const int sharpenOnly = 0;
|
||||
|
||||
#define A_GPU 1
|
||||
#define A_GLSL 1
|
||||
|
||||
#include "ffx_a.h"
|
||||
|
||||
AF3 CasLoad(ASU2 p)
|
||||
{
|
||||
return texelFetch(imgSrc, srcOffset + ivec2(p), 0).rgb;
|
||||
}
|
||||
|
||||
// Lets you transform input from the load into a linear color space between 0 and 1. See ffx_cas.h
|
||||
// In this case, our input is already linear and between 0 and 1
|
||||
void CasInput(inout AF1 r, inout AF1 g, inout AF1 b) {}
|
||||
|
||||
#include "ffx_cas.h"
|
||||
|
||||
layout(local_size_x=64) in;
|
||||
void main()
|
||||
{
|
||||
// Do remapping of local xy in workgroup for a more PS-like swizzle pattern.
|
||||
AU2 gxy = ARmp8x8(gl_LocalInvocationID.x)+AU2(gl_WorkGroupID.x<<4u,gl_WorkGroupID.y<<4u);
|
||||
|
||||
// Filter.
|
||||
AF4 c = vec4(0.0f);
|
||||
CasFilter(c.r, c.g, c.b, gxy, const0, const1, sharpenOnly != 0);
|
||||
imageStore(imgDst, ASU2(gxy), c);
|
||||
gxy.x += 8u;
|
||||
|
||||
CasFilter(c.r, c.g, c.b, gxy, const0, const1, sharpenOnly != 0);
|
||||
imageStore(imgDst, ASU2(gxy), c);
|
||||
gxy.y += 8u;
|
||||
|
||||
CasFilter(c.r, c.g, c.b, gxy, const0, const1, sharpenOnly != 0);
|
||||
imageStore(imgDst, ASU2(gxy), c);
|
||||
gxy.x -= 8u;
|
||||
|
||||
CasFilter(c.r, c.g, c.b, gxy, const0, const1, sharpenOnly != 0);
|
||||
imageStore(imgDst, ASU2(gxy), c);
|
||||
}
|
||||
@@ -0,0 +1,636 @@
|
||||
// SPDX-FileCopyrightText: 2002-2025 PCSX2 Dev Team
|
||||
// SPDX-License-Identifier: GPL-3.0+
|
||||
|
||||
#ifdef VERTEX_SHADER
|
||||
|
||||
layout(location = 0) in vec4 a_pos;
|
||||
layout(location = 1) in vec2 a_tex;
|
||||
|
||||
layout(location = 0) out vec2 v_tex;
|
||||
|
||||
void main()
|
||||
{
|
||||
gl_Position = vec4(a_pos.x, -a_pos.y, a_pos.z, a_pos.w);
|
||||
v_tex = a_tex;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#ifdef FRAGMENT_SHADER
|
||||
|
||||
layout(location = 0) in vec2 v_tex;
|
||||
|
||||
#if defined(ps_convert_rgba8_16bits) || defined(ps_convert_float32_32bits)
|
||||
layout(location = 0) out uint o_col0;
|
||||
#elif defined(ps_convert_float32_depth_to_color)
|
||||
layout(location = 0) out float o_col0;
|
||||
#elif !defined(ps_datm1) && \
|
||||
!defined(ps_datm0) && \
|
||||
!defined(ps_datm1_rta_correction) && \
|
||||
!defined(ps_datm0_rta_correction) && \
|
||||
!defined(ps_convert_rgba8_float32) && \
|
||||
!defined(ps_convert_rgba8_float24) && \
|
||||
!defined(ps_convert_rgba8_float16) && \
|
||||
!defined(ps_convert_rgb5a1_float16) && \
|
||||
!defined(ps_convert_rgba8_float32_biln) && \
|
||||
!defined(ps_convert_rgba8_float24_biln) && \
|
||||
!defined(ps_convert_rgba8_float16_biln) && \
|
||||
!defined(ps_convert_rgb5a1_float16_biln) && \
|
||||
!defined(ps_depth_copy)
|
||||
layout(location = 0) out vec4 o_col0;
|
||||
#endif
|
||||
|
||||
layout(set = 0, binding = 0) uniform sampler2D samp0;
|
||||
|
||||
vec4 sample_c(vec2 uv)
|
||||
{
|
||||
return texture(samp0, uv);
|
||||
}
|
||||
|
||||
#ifdef ps_copy
|
||||
void ps_copy()
|
||||
{
|
||||
o_col0 = sample_c(v_tex);
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef ps_depth_copy
|
||||
void ps_depth_copy()
|
||||
{
|
||||
gl_FragDepth = sample_c(v_tex).r;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef ps_downsample_copy
|
||||
layout(push_constant) uniform cb10
|
||||
{
|
||||
ivec2 ClampMin;
|
||||
int DownsampleFactor;
|
||||
int pad0;
|
||||
float Weight;
|
||||
float step_multiplier;
|
||||
vec2 pad1;
|
||||
};
|
||||
void ps_downsample_copy()
|
||||
{
|
||||
int step = int(step_multiplier);
|
||||
ivec2 coord = max(ivec2(gl_FragCoord.xy) * DownsampleFactor, ClampMin);
|
||||
vec4 result = vec4(0);
|
||||
for (int yoff = 0; yoff < DownsampleFactor; yoff++)
|
||||
{
|
||||
for (int xoff = 0; xoff < DownsampleFactor; xoff++)
|
||||
result += texelFetch(samp0, coord + ivec2(xoff * step, yoff * step), 0);
|
||||
}
|
||||
o_col0 = result / Weight;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef ps_filter_transparency
|
||||
void ps_filter_transparency()
|
||||
{
|
||||
vec4 c = sample_c(v_tex);
|
||||
o_col0 = vec4(c.rgb, 1.0);
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef ps_convert_rgba8_16bits
|
||||
// Need to be careful with precision here, it can break games like Spider-Man 3 and Dogs Life
|
||||
void ps_convert_rgba8_16bits()
|
||||
{
|
||||
uvec4 i = uvec4(sample_c(v_tex) * vec4(255.5f, 255.5f, 255.5f, 255.5f));
|
||||
|
||||
o_col0 = ((i.x & 0x00F8u) >> 3) | ((i.y & 0x00F8u) << 2) | ((i.z & 0x00f8u) << 7) | ((i.w & 0x80u) << 8);
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef ps_datm1
|
||||
void ps_datm1()
|
||||
{
|
||||
if(sample_c(v_tex).a < (127.5f / 255.0f)) // >= 0x80 pass
|
||||
discard;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef ps_datm0
|
||||
void ps_datm0()
|
||||
{
|
||||
if((127.5f / 255.0f) < sample_c(v_tex).a) // < 0x80 pass (== 0x80 should not pass)
|
||||
discard;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef ps_datm1_rta_correction
|
||||
void ps_datm1_rta_correction()
|
||||
{
|
||||
if(sample_c(v_tex).a < (254.5f / 255.0f)) // >= 0x80 pass
|
||||
discard;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef ps_datm0_rta_correction
|
||||
void ps_datm0_rta_correction()
|
||||
{
|
||||
if((254.5f / 255.0f) < sample_c(v_tex).a) // < 0x80 pass (== 0x80 should not pass)
|
||||
discard;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef ps_rta_correction
|
||||
void ps_rta_correction()
|
||||
{
|
||||
vec4 value = sample_c(v_tex);
|
||||
o_col0 = vec4(value.rgb, value.a / (128.25f / 255.0f));
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef ps_rta_decorrection
|
||||
void ps_rta_decorrection()
|
||||
{
|
||||
vec4 value = sample_c(v_tex);
|
||||
o_col0 = vec4(value.rgb, value.a * (128.25f / 255.0f));
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef ps_colclip_init
|
||||
void ps_colclip_init()
|
||||
{
|
||||
vec4 value = sample_c(v_tex);
|
||||
o_col0 = vec4(roundEven(value.rgb * 255.0f) / 65535.0f, value.a);
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef ps_colclip_resolve
|
||||
void ps_colclip_resolve()
|
||||
{
|
||||
vec4 value = sample_c(v_tex);
|
||||
o_col0 = vec4(vec3(gpu_bitwise_and(uvec3(value.rgb * 65535.5f), uvec3(255u))) / 255.0f, value.a);
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef ps_convert_float32_depth_to_color
|
||||
void ps_convert_float32_depth_to_color()
|
||||
{
|
||||
o_col0 = sample_c(v_tex).r;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef ps_convert_float32_color_to_depth
|
||||
void ps_convert_float32_color_to_depth()
|
||||
{
|
||||
gl_FragDepth = sample_c(v_tex).r;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef ps_convert_float32_32bits
|
||||
void ps_convert_float32_32bits()
|
||||
{
|
||||
// Convert a vec32 depth texture into a 32 bits UINT texture
|
||||
o_col0 = uint(exp2(32.0f) * sample_c(v_tex).r);
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef ps_convert_float32_rgba8
|
||||
void ps_convert_float32_rgba8()
|
||||
{
|
||||
// Convert a vec32 depth texture into a RGBA color texture
|
||||
uint d = uint(sample_c(v_tex).r * exp2(32.0f));
|
||||
o_col0 = vec4(uvec4((d & 0xFFu), ((d >> 8) & 0xFFu), ((d >> 16) & 0xFFu), (d >> 24))) / vec4(255.0);
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef ps_convert_float16_rgb5a1
|
||||
void ps_convert_float16_rgb5a1()
|
||||
{
|
||||
// Convert a vec32 (only 16 lsb) depth into a RGB5A1 color texture
|
||||
uint d = uint(sample_c(v_tex).r * exp2(32.0f));
|
||||
o_col0 = vec4(gpu_bitwise_and(uvec4(d << 3, d >> 2, d >> 7, d >> 8), uvec4(0xf8, 0xf8, 0xf8, 0x80))) / 255.0f;
|
||||
}
|
||||
#endif
|
||||
|
||||
float rgba8_to_depth32(vec4 unorm)
|
||||
{
|
||||
uvec4 c = uvec4(unorm * vec4(255.5f));
|
||||
return float(c.r | (c.g << 8) | (c.b << 16) | (c.a << 24)) * exp2(-32.0f);
|
||||
}
|
||||
|
||||
float rgba8_to_depth24(vec4 unorm)
|
||||
{
|
||||
uvec3 c = uvec3(unorm.rgb * vec3(255.5f));
|
||||
return float(c.r | (c.g << 8) | (c.b << 16)) * exp2(-32.0f);
|
||||
}
|
||||
|
||||
float rgba8_to_depth16(vec4 unorm)
|
||||
{
|
||||
uvec2 c = uvec2(unorm.rg * vec2(255.5f));
|
||||
return float(c.r | (c.g << 8)) * exp2(-32.0f);
|
||||
}
|
||||
|
||||
float rgb5a1_to_depth16(vec4 unorm)
|
||||
{
|
||||
uvec4 c = uvec4(unorm * vec4(255.5f));
|
||||
return float(((c.r & 0xF8u) >> 3) | ((c.g & 0xF8u) << 2) | ((c.b & 0xF8u) << 7) | ((c.a & 0x80u) << 8)) * exp2(-32.0f);
|
||||
}
|
||||
|
||||
#ifdef ps_convert_float32_float24
|
||||
void ps_convert_float32_float24()
|
||||
{
|
||||
// Truncates depth value to 24bits
|
||||
uint d = uint(sample_c(v_tex).r * exp2(32.0f)) & 0xFFFFFFu;
|
||||
gl_FragDepth = float(d) * exp2(-32.0f);
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef ps_convert_rgba8_float32
|
||||
void ps_convert_rgba8_float32()
|
||||
{
|
||||
// Convert an RGBA texture into a float depth texture
|
||||
gl_FragDepth = rgba8_to_depth32(sample_c(v_tex));
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef ps_convert_rgba8_float24
|
||||
void ps_convert_rgba8_float24()
|
||||
{
|
||||
// Same as above but without the alpha channel (24 bits Z)
|
||||
|
||||
// Convert an RGBA texture into a float depth texture
|
||||
gl_FragDepth = rgba8_to_depth24(sample_c(v_tex));
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef ps_convert_rgba8_float16
|
||||
void ps_convert_rgba8_float16()
|
||||
{
|
||||
// Same as above but without the A/B channels (16 bits Z)
|
||||
|
||||
// Convert an RGBA texture into a float depth texture
|
||||
gl_FragDepth = rgba8_to_depth16(sample_c(v_tex));
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef ps_convert_rgb5a1_float16
|
||||
void ps_convert_rgb5a1_float16()
|
||||
{
|
||||
// Convert an RGB5A1 (saved as RGBA8) color to a 16 bit Z
|
||||
gl_FragDepth = rgb5a1_to_depth16(sample_c(v_tex));
|
||||
}
|
||||
#endif
|
||||
|
||||
#define SAMPLE_RGBA_DEPTH_BILN(CONVERT_FN) \
|
||||
ivec2 dims = textureSize(samp0, 0); \
|
||||
vec2 top_left_f = v_tex * 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(samp0, coords.xy, 0)); \
|
||||
float depthTR = CONVERT_FN(texelFetch(samp0, coords.zy, 0)); \
|
||||
float depthBL = CONVERT_FN(texelFetch(samp0, coords.xw, 0)); \
|
||||
float depthBR = CONVERT_FN(texelFetch(samp0, 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);
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef ps_convert_rgb5a1_8i
|
||||
layout(push_constant) uniform cb10
|
||||
{
|
||||
uint SBW;
|
||||
uint DBW;
|
||||
uint PSM;
|
||||
float cb_pad1;
|
||||
float ScaleFactor;
|
||||
vec3 cb_pad2;
|
||||
};
|
||||
|
||||
void ps_convert_rgb5a1_8i()
|
||||
{
|
||||
// Convert a RGB5A1 texture into a 8 bits packed texture
|
||||
// Input column: 16x2 RGB5A1 pixels
|
||||
// 0: 16 RGBA
|
||||
// 1: 16 RGBA
|
||||
// Output column: 16x4 Index pixels
|
||||
// 0: 16 R5G2
|
||||
// 1: 16 R5G2
|
||||
// 2: 16 G2B5A1
|
||||
// 3: 16 G2B5A1
|
||||
|
||||
uvec2 pos = uvec2(gl_FragCoord.xy);
|
||||
|
||||
// Collapse separate R G B A areas into their base pixel
|
||||
uvec2 column = gpu_bitwise_and(pos, ~uvec2(0u, 3u)) / uvec2(1,2);
|
||||
uvec2 subcolumn = gpu_bitwise_and(pos, uvec2(0u, 1u));
|
||||
column.x -= (column.x / 128) * 64;
|
||||
column.y += (column.y / 32) * 32;
|
||||
|
||||
// Deal with swizzling differences
|
||||
if ((PSM & 0x8) != 0) // PSMCT16S
|
||||
{
|
||||
if ((pos.x & 32) != 0)
|
||||
{
|
||||
column.y += 32; // 4 columns high times 4 to get bottom 4 blocks
|
||||
column.x &= ~32;
|
||||
}
|
||||
|
||||
if ((pos.x & 64) != 0)
|
||||
{
|
||||
column.x -= 32;
|
||||
}
|
||||
|
||||
if (((pos.x & 16) != 0) != ((pos.y & 16) != 0))
|
||||
{
|
||||
column.x ^= 16;
|
||||
column.y ^= 8;
|
||||
}
|
||||
|
||||
if ((PSM & 0x30) != 0) // PSMZ16S - Untested but hopefully ok if anything uses it.
|
||||
{
|
||||
column.x ^= 32;
|
||||
column.y ^= 16;
|
||||
}
|
||||
}
|
||||
else // PSMCT16
|
||||
{
|
||||
if ((pos.y & 32) != 0)
|
||||
{
|
||||
column.y -= 16;
|
||||
column.x += 32;
|
||||
}
|
||||
|
||||
if ((pos.x & 96) != 0)
|
||||
{
|
||||
uint multi = (pos.x & 96) / 32;
|
||||
column.y += 16 * multi; // 4 columns high times 4 to get bottom 4 blocks
|
||||
column.x -= (pos.x & 96);
|
||||
}
|
||||
|
||||
if (((pos.x & 16) != 0) != ((pos.y & 16) != 0))
|
||||
{
|
||||
column.x ^= 16;
|
||||
column.y ^= 8;
|
||||
}
|
||||
|
||||
if ((PSM & 0x30) != 0) // PSMZ16 - Untested but hopefully ok if anything uses it.
|
||||
{
|
||||
column.x ^= 32;
|
||||
column.y ^= 32;
|
||||
}
|
||||
}
|
||||
uvec2 coord = column | subcolumn;
|
||||
|
||||
// Compensate for potentially differing page pitch.
|
||||
uvec2 block_xy = coord / uvec2(64u, 64u);
|
||||
uint block_num = (block_xy.y * (DBW / 128u)) + block_xy.x;
|
||||
uvec2 block_offset = uvec2((block_num % (SBW / 64u)) * 64u, (block_num / (SBW / 64u)) * 64u);
|
||||
coord = (coord % uvec2(64u, 64u)) + block_offset;
|
||||
|
||||
// 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
|
||||
|
||||
if (floor(ScaleFactor) != ScaleFactor)
|
||||
coord = uvec2(vec2(coord) * ScaleFactor);
|
||||
else
|
||||
coord *= uvec2(ScaleFactor);
|
||||
|
||||
vec4 pixel = texelFetch(samp0, ivec2(coord), 0);
|
||||
uvec4 denorm_c = uvec4(pixel * 255.5f);
|
||||
if ((pos.y & 2u) == 0u)
|
||||
{
|
||||
uint red = (denorm_c.r >> 3) & 0x1Fu;
|
||||
uint green = (denorm_c.g >> 3) & 0x1Fu;
|
||||
float sel0 = float(((green << 5) | red) & 0xFF) / 255.0f;
|
||||
|
||||
o_col0 = vec4(sel0);
|
||||
}
|
||||
else
|
||||
{
|
||||
uint green = (denorm_c.g >> 3) & 0x1Fu;
|
||||
uint blue = (denorm_c.b >> 3) & 0x1Fu;
|
||||
uint alpha = denorm_c.a & 0x80u;
|
||||
float sel0 = float((alpha | (blue << 2) | (green >> 3)) & 0xFF) / 255.0f;
|
||||
|
||||
o_col0 = vec4(sel0);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef ps_convert_rgba_8i
|
||||
layout(push_constant) uniform cb10
|
||||
{
|
||||
uint SBW;
|
||||
uint DBW;
|
||||
uint PSM;
|
||||
float cb_pad1;
|
||||
float ScaleFactor;
|
||||
vec3 cb_pad2;
|
||||
};
|
||||
|
||||
void ps_convert_rgba_8i()
|
||||
{
|
||||
// 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
|
||||
uvec2 pos = uvec2(gl_FragCoord.xy);
|
||||
|
||||
// Collapse separate R G B A areas into their base pixel
|
||||
uvec2 block = gpu_bitwise_and(pos, ~uvec2(15u, 3u)) >> 1;
|
||||
uvec2 subblock = gpu_bitwise_and(pos, uvec2(7u, 1u));
|
||||
uvec2 coord = block | subblock;
|
||||
|
||||
// Compensate for potentially differing page pitch.
|
||||
uvec2 block_xy = coord / uvec2(64u, 32u);
|
||||
uint block_num = (block_xy.y * (DBW / 128u)) + block_xy.x;
|
||||
uvec2 block_offset = uvec2((block_num % (SBW / 64u)) * 64u, (block_num / (SBW / 64u)) * 32u);
|
||||
coord = (coord % uvec2(64u, 32u)) + block_offset;
|
||||
|
||||
// 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
|
||||
|
||||
if (floor(ScaleFactor) != ScaleFactor)
|
||||
coord = uvec2(vec2(coord) * ScaleFactor);
|
||||
else
|
||||
coord *= uvec2(ScaleFactor);
|
||||
|
||||
vec4 pixel = texelFetch(samp0, ivec2(coord), 0);
|
||||
vec2 sel0 = (pos.y & 2u) == 0u ? pixel.rb : pixel.ga;
|
||||
float sel1 = (pos.x & 8u) == 0u ? sel0.x : sel0.y;
|
||||
o_col0 = vec4(sel1); // Divide by something here?
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef ps_convert_clut_4
|
||||
layout(push_constant) uniform cb10
|
||||
{
|
||||
uvec2 offset;
|
||||
uint doffset;
|
||||
uint cb_pad1;
|
||||
float scale;
|
||||
vec3 cb_pad2;
|
||||
};
|
||||
|
||||
void ps_convert_clut_4()
|
||||
{
|
||||
// CLUT4 is easy, just two rows of 8x8.
|
||||
uint index = uint(gl_FragCoord.x) + doffset;
|
||||
uvec2 pos = uvec2(index % 8u, index / 8u);
|
||||
|
||||
ivec2 final = ivec2(floor(vec2(offset + pos) * vec2(scale)));
|
||||
o_col0 = texelFetch(samp0, final, 0);
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef ps_convert_clut_8
|
||||
layout(push_constant) uniform cb10
|
||||
{
|
||||
uvec2 offset;
|
||||
uint doffset;
|
||||
uint cb_pad1;
|
||||
float scale;
|
||||
vec3 cb_pad2;
|
||||
};
|
||||
|
||||
void ps_convert_clut_8()
|
||||
{
|
||||
uint index = min(uint(gl_FragCoord.x) + doffset, 255u);
|
||||
|
||||
// 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 + pos) * vec2(scale)));
|
||||
o_col0 = texelFetch(samp0, final, 0);
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef ps_yuv
|
||||
layout(push_constant) uniform cb10
|
||||
{
|
||||
int EMODA;
|
||||
int EMODC;
|
||||
};
|
||||
|
||||
void ps_yuv()
|
||||
{
|
||||
vec4 i = sample_c(v_tex);
|
||||
vec4 o = vec4(0.0f);
|
||||
|
||||
mat3 rgb2yuv;
|
||||
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;
|
||||
|
||||
switch(EMODA)
|
||||
{
|
||||
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;
|
||||
}
|
||||
|
||||
switch(EMODC)
|
||||
{
|
||||
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;
|
||||
}
|
||||
|
||||
o_col0 = o;
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(ps_stencil_image_init_0) || defined(ps_stencil_image_init_1) || defined(ps_stencil_image_init_2) || defined(ps_stencil_image_init_3)
|
||||
|
||||
void main()
|
||||
{
|
||||
o_col0 = vec4(0x7FFFFFFF);
|
||||
|
||||
#ifdef ps_stencil_image_init_0
|
||||
if((127.5f / 255.0f) < sample_c(v_tex).a) // < 0x80 pass (== 0x80 should not pass)
|
||||
o_col0 = vec4(-1);
|
||||
#endif
|
||||
#ifdef ps_stencil_image_init_1
|
||||
if(sample_c(v_tex).a < (127.5f / 255.0f)) // >= 0x80 pass
|
||||
o_col0 = vec4(-1);
|
||||
#endif
|
||||
#ifdef ps_stencil_image_init_2
|
||||
if((254.5f / 255.0f) < sample_c(v_tex).a) // < 0x80 pass (== 0x80 should not pass)
|
||||
o_col0 = vec4(-1);
|
||||
#endif
|
||||
#ifdef ps_stencil_image_init_3
|
||||
if(sample_c(v_tex).a < (254.5f / 255.0f)) // >= 0x80 pass
|
||||
o_col0 = vec4(-1);
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,42 @@
|
||||
// SPDX-FileCopyrightText: 2002-2025 PCSX2 Dev Team
|
||||
// SPDX-License-Identifier: GPL-3.0+
|
||||
|
||||
#ifdef VERTEX_SHADER
|
||||
|
||||
layout(location = 0) in vec2 Position;
|
||||
layout(location = 1) in vec2 UV;
|
||||
layout(location = 2) in vec4 Color;
|
||||
|
||||
layout(push_constant) uniform PushConstants
|
||||
{
|
||||
vec2 uScale;
|
||||
vec2 uTranslate;
|
||||
};
|
||||
|
||||
layout(location = 0) out vec2 Frag_UV;
|
||||
layout(location = 1) out vec4 Frag_Color;
|
||||
|
||||
void vs_main()
|
||||
{
|
||||
Frag_UV = UV;
|
||||
Frag_Color = Color;
|
||||
gl_Position = vec4(Position * uScale + uTranslate, 0.0f, 1.0f);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#ifdef FRAGMENT_SHADER
|
||||
|
||||
layout(binding = 0) uniform sampler2D Texture;
|
||||
|
||||
layout(location = 0) in vec2 Frag_UV;
|
||||
layout(location = 1) in vec4 Frag_Color;
|
||||
|
||||
layout(location = 0) out vec4 Out_Color;
|
||||
|
||||
void ps_main()
|
||||
{
|
||||
Out_Color = Frag_Color * texture(Texture, Frag_UV.st);
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,203 @@
|
||||
// SPDX-FileCopyrightText: 2002-2025 PCSX2 Dev Team
|
||||
// SPDX-License-Identifier: GPL-3.0+
|
||||
|
||||
#ifdef VERTEX_SHADER
|
||||
|
||||
layout(location = 0) in vec4 a_pos;
|
||||
layout(location = 1) in vec2 a_tex;
|
||||
|
||||
layout(location = 0) out vec2 v_tex;
|
||||
|
||||
void main()
|
||||
{
|
||||
gl_Position = vec4(a_pos.x, -a_pos.y, a_pos.z, a_pos.w);
|
||||
v_tex = a_tex;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#ifdef FRAGMENT_SHADER
|
||||
|
||||
layout(location = 0) in vec2 v_tex;
|
||||
layout(location = 0) out vec4 o_col0;
|
||||
|
||||
layout(push_constant) uniform cb0
|
||||
{
|
||||
vec4 ZrH;
|
||||
};
|
||||
|
||||
layout(set = 0, binding = 0) uniform sampler2D samp0;
|
||||
|
||||
|
||||
// Weave shader
|
||||
#ifdef ps_main0
|
||||
void ps_main0()
|
||||
{
|
||||
const int idx = int(ZrH.x); // buffer index passed from CPU
|
||||
const int field = idx & 1; // current field
|
||||
const int vpos = int(gl_FragCoord.y); // vertical position of destination texture
|
||||
|
||||
if ((vpos & 1) == field)
|
||||
o_col0 = textureLod(samp0, v_tex, 0);
|
||||
else
|
||||
discard;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
// Bob shader
|
||||
#ifdef ps_main1
|
||||
void ps_main1()
|
||||
{
|
||||
o_col0 = textureLod(samp0, v_tex, 0);
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
// Blend shader
|
||||
#ifdef ps_main2
|
||||
void ps_main2()
|
||||
{
|
||||
vec2 vstep = vec2(0.0f, ZrH.y);
|
||||
vec4 c0 = textureLod(samp0, v_tex - vstep, 0);
|
||||
vec4 c1 = textureLod(samp0, v_tex, 0);
|
||||
vec4 c2 = textureLod(samp0, v_tex + vstep, 0);
|
||||
|
||||
o_col0 = (c0 + c1 * 2.0f + c2) / 4.0f;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
// MAD shader - buffering
|
||||
#ifdef ps_main3
|
||||
void ps_main3()
|
||||
{
|
||||
// We take half the lines from the current frame and stores them in the MAD frame buffer.
|
||||
// the MAD frame buffer is split in 2 consecutive banks of 2 fields each, the fields in each bank
|
||||
// are interleaved (top field at even lines and bottom field at odd lines).
|
||||
// When the source texture has an odd vres, the first line of bank 1 would be an odd index
|
||||
// causing the wrong lines to be discarded, so a vertical offset (lofs) is added to the vertical
|
||||
// position of the destination texture to force the proper field alignment
|
||||
|
||||
const int idx = int(ZrH.x); // buffer index passed from CPU
|
||||
const int bank = idx >> 1; // current bank
|
||||
const int field = idx & 1; // current field
|
||||
const int vres = int(ZrH.z) >> 1; // vertical resolution of source texture
|
||||
const int lofs = ((((vres + 1) >> 1) << 1) - vres) & bank; // line alignment offset for bank 1
|
||||
const int vpos = int(gl_FragCoord.y) + lofs; // vertical position of destination texture
|
||||
|
||||
// if the index of current destination line belongs to the current fiels we update it, otherwise
|
||||
// we leave the old line in the destination buffer
|
||||
if ((vpos & 1) == field)
|
||||
o_col0 = textureLod(samp0, v_tex, 0);
|
||||
else
|
||||
discard;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
// MAD shader - reconstruction
|
||||
#ifdef ps_main4
|
||||
void ps_main4()
|
||||
{
|
||||
// we use the contents of the MAD frame buffer to reconstruct the missing lines from the current
|
||||
// field.
|
||||
|
||||
const int idx = int(ZrH.x); // buffer index passed from CPU
|
||||
const int bank = idx >> 1; // current bank
|
||||
const int field = idx & 1; // current field
|
||||
const int vpos = int(gl_FragCoord.y); // vertical position of destination texture
|
||||
const float sensitivity = ZrH.w; // passed from CPU, higher values mean more likely to use weave
|
||||
const vec3 motion_thr = vec3(1.0, 1.0, 1.0) * sensitivity; //
|
||||
const vec2 bofs = vec2(0.0f, 0.5f); // position of the bank 1 relative to source texture size
|
||||
const vec2 vscale = vec2(1.0f, 0.5f); // scaling factor from source to destination texture
|
||||
const vec2 lofs = vec2(0.0f, ZrH.y) * vscale; // distance between two adjacent lines relative to source texture size
|
||||
const vec2 iptr = v_tex * vscale; // pointer to the current pixel in the source texture
|
||||
|
||||
vec2 p_t0; // pointer to current pixel (missing or not) from most recent frame
|
||||
vec2 p_t1; // pointer to current pixel (missing or not) from one frame back
|
||||
vec2 p_t2; // pointer to current pixel (missing or not) from two frames back
|
||||
vec2 p_t3; // pointer to current pixel (missing or not) from three frames back
|
||||
|
||||
switch (idx)
|
||||
{
|
||||
case 1:
|
||||
p_t0 = iptr;
|
||||
p_t1 = iptr;
|
||||
p_t2 = iptr + bofs;
|
||||
p_t3 = iptr + bofs;
|
||||
break;
|
||||
case 2:
|
||||
p_t0 = iptr + bofs;
|
||||
p_t1 = iptr;
|
||||
p_t2 = iptr;
|
||||
p_t3 = iptr + bofs;
|
||||
break;
|
||||
case 3:
|
||||
p_t0 = iptr + bofs;
|
||||
p_t1 = iptr + bofs;
|
||||
p_t2 = iptr;
|
||||
p_t3 = iptr;
|
||||
break;
|
||||
default:
|
||||
p_t0 = iptr;
|
||||
p_t1 = iptr + bofs;
|
||||
p_t2 = iptr + bofs;
|
||||
p_t3 = iptr;
|
||||
break;
|
||||
}
|
||||
|
||||
// calculating motion, only relevant for missing lines where the "center line" is pointed by p_t1
|
||||
|
||||
vec4 hn = textureLod(samp0, p_t0 - lofs, 0); // new high pixel
|
||||
vec4 cn = textureLod(samp0, p_t1, 0); // new center pixel
|
||||
vec4 ln = textureLod(samp0, p_t0 + lofs, 0); // new low pixel
|
||||
|
||||
vec4 ho = textureLod(samp0, p_t2 - lofs, 0); // old high pixel
|
||||
vec4 co = textureLod(samp0, p_t3, 0); // old center pixel
|
||||
vec4 lo = textureLod(samp0, p_t2 + lofs, 0); // old low pixel
|
||||
|
||||
vec3 mh = hn.rgb - ho.rgb; // high pixel motion
|
||||
vec3 mc = cn.rgb - co.rgb; // center pixel motion
|
||||
vec3 ml = ln.rgb - lo.rgb; // low pixel motion
|
||||
|
||||
mh = max(mh, -mh) - motion_thr;
|
||||
mc = max(mc, -mc) - motion_thr;
|
||||
ml = max(ml, -ml) - motion_thr;
|
||||
|
||||
#if 1 // use this code to evaluate each color motion separately
|
||||
float mh_max = max(max(mh.x, mh.y), mh.z);
|
||||
float mc_max = max(max(mc.x, mc.y), mc.z);
|
||||
float ml_max = max(max(ml.x, ml.y), ml.z);
|
||||
#else // use this code to evaluate average color motion
|
||||
float mh_max = mh.x + mh.y + mh.z;
|
||||
float mc_max = mc.x + mc.y + mc.z;
|
||||
float ml_max = ml.x + ml.y + ml.z;
|
||||
#endif
|
||||
|
||||
// selecting deinterlacing output
|
||||
|
||||
if ((vpos & 1) == field) // output coordinate present on current field
|
||||
{
|
||||
// output coordinate present on current field
|
||||
o_col0 = textureLod(samp0, p_t0, 0);
|
||||
}
|
||||
else if ((iptr.y > 0.5f - lofs.y) || (iptr.y < 0.0 + lofs.y))
|
||||
{
|
||||
// top and bottom lines are always weaved
|
||||
o_col0 = cn;
|
||||
}
|
||||
else
|
||||
{
|
||||
// missing line needs to be reconstructed
|
||||
if(((mh_max > 0.0f) || (ml_max > 0.0f)) || (mc_max > 0.0f))
|
||||
// high motion -> interpolate pixels above and below
|
||||
o_col0 = (hn + ln) / 2.0f;
|
||||
else
|
||||
// low motion -> weave
|
||||
o_col0 = cn;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,46 @@
|
||||
// SPDX-FileCopyrightText: 2002-2025 PCSX2 Dev Team
|
||||
// SPDX-License-Identifier: GPL-3.0+
|
||||
|
||||
#ifdef VERTEX_SHADER
|
||||
|
||||
layout(location = 0) in vec4 a_pos;
|
||||
layout(location = 1) in vec2 a_tex;
|
||||
|
||||
layout(location = 0) out vec2 v_tex;
|
||||
|
||||
void main()
|
||||
{
|
||||
gl_Position = vec4(a_pos.x, -a_pos.y, a_pos.z, a_pos.w);
|
||||
v_tex = a_tex;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#ifdef FRAGMENT_SHADER
|
||||
|
||||
layout(location = 0) in vec2 v_tex;
|
||||
layout(location = 0) out vec4 o_col0;
|
||||
|
||||
layout(push_constant) uniform cb10
|
||||
{
|
||||
vec4 BGColor;
|
||||
};
|
||||
|
||||
layout(set = 0, binding = 0) uniform sampler2D samp0;
|
||||
|
||||
void ps_main0()
|
||||
{
|
||||
vec4 c = texture(samp0, v_tex);
|
||||
// Note: clamping will be done by fixed unit
|
||||
c.a *= 2.0f;
|
||||
o_col0 = c;
|
||||
}
|
||||
|
||||
void ps_main1()
|
||||
{
|
||||
vec4 c = texture(samp0, v_tex);
|
||||
c.a = BGColor.a;
|
||||
o_col0 = c;
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,523 @@
|
||||
// SPDX-FileCopyrightText: 2002-2025 PCSX2 Dev Team
|
||||
// SPDX-License-Identifier: GPL-3.0+
|
||||
|
||||
#ifdef VERTEX_SHADER
|
||||
|
||||
layout(location = 0) in vec4 a_pos;
|
||||
layout(location = 1) in vec2 a_tex;
|
||||
|
||||
layout(location = 0) out vec2 v_tex;
|
||||
|
||||
void main()
|
||||
{
|
||||
gl_Position = vec4(a_pos.x, -a_pos.y, a_pos.z, a_pos.w);
|
||||
v_tex = a_tex;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#ifdef FRAGMENT_SHADER
|
||||
|
||||
layout(push_constant) uniform cb10
|
||||
{
|
||||
vec4 u_source_rect;
|
||||
vec4 u_target_rect;
|
||||
vec2 u_source_size;
|
||||
vec2 u_target_size;
|
||||
vec2 u_target_resolution;
|
||||
vec2 u_rcp_target_resolution; // 1 / u_target_resolution
|
||||
vec2 u_source_resolution;
|
||||
vec2 u_rcp_source_resolution; // 1 / u_source_resolution
|
||||
float u_time;
|
||||
};
|
||||
|
||||
layout(location = 0) in vec2 v_tex;
|
||||
|
||||
layout(location = 0) out vec4 o_col0;
|
||||
|
||||
layout(set = 0, binding = 0) uniform sampler2D samp0;
|
||||
|
||||
vec4 sample_c(vec2 uv)
|
||||
{
|
||||
return texture(samp0, uv);
|
||||
}
|
||||
|
||||
vec4 ps_crt(uint i)
|
||||
{
|
||||
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));
|
||||
return sample_c(v_tex) * clamp((mask[i] + 0.5f), 0.0f, 1.0f);
|
||||
}
|
||||
|
||||
vec4 ps_scanlines(uint i)
|
||||
{
|
||||
vec4 mask[2] =
|
||||
{
|
||||
vec4(1, 1, 1, 0),
|
||||
vec4(0, 0, 0, 0)};
|
||||
|
||||
return sample_c(v_tex) * clamp((mask[i] + 0.5f), 0.0f, 1.0f);
|
||||
}
|
||||
|
||||
#ifdef ps_copy
|
||||
void ps_copy()
|
||||
{
|
||||
o_col0 = sample_c(v_tex);
|
||||
}
|
||||
#endif
|
||||
#ifdef ps_sgsr
|
||||
// Snapdragon Game Super Resolution 1.
|
||||
// Copyright (c) 2025, Qualcomm Innovation Center, Inc.
|
||||
// SPDX-License-Identifier: BSD-3-Clause
|
||||
float sgsr_fast_lanczos2(float x)
|
||||
{
|
||||
float wa = x - 4.0;
|
||||
float wb = x * wa - wa;
|
||||
wa *= wa;
|
||||
return wb * wa;
|
||||
}
|
||||
|
||||
vec2 sgsr_weight_y(float dx, float dy, float c, float stddev)
|
||||
{
|
||||
float x = ((dx * dx) + (dy * dy)) * 0.55 + clamp(abs(c) * stddev, 0.0, 1.0);
|
||||
float w = sgsr_fast_lanczos2(x);
|
||||
return vec2(w, w * c);
|
||||
}
|
||||
|
||||
void ps_sgsr()
|
||||
{
|
||||
// u_time carries the selected SGSR mode for this presentation shader.
|
||||
// Quality covers subtle edges, Balanced is Qualcomm's reference tuning,
|
||||
// and Performance evaluates only stronger edges.
|
||||
float mode = clamp(floor(u_time + 0.5), 1.0, 3.0);
|
||||
float edge_threshold = (mode < 1.5) ? (4.0 / 255.0) : ((mode < 2.5) ? (8.0 / 255.0) : (16.0 / 255.0));
|
||||
float edge_sharpness = (mode < 1.5) ? 2.2 : ((mode < 2.5) ? 2.0 : 1.6);
|
||||
vec4 color = vec4(textureLod(samp0, v_tex, 0.0).rgb, 1.0);
|
||||
|
||||
vec2 img_coord = v_tex * u_source_resolution + vec2(-0.5, 0.5);
|
||||
vec2 img_coord_pixel = floor(img_coord);
|
||||
vec2 coord = img_coord_pixel * u_rcp_source_resolution;
|
||||
vec2 pl = img_coord - img_coord_pixel;
|
||||
vec4 left = textureGather(samp0, coord, 1);
|
||||
|
||||
float edge_vote = abs(left.z - left.y) + abs(color.g - left.y) + abs(color.g - left.z);
|
||||
if (edge_vote > edge_threshold)
|
||||
{
|
||||
coord.x += u_rcp_source_resolution.x;
|
||||
vec4 right = textureGather(samp0, coord + vec2(u_rcp_source_resolution.x, 0.0), 1);
|
||||
vec4 up_down;
|
||||
up_down.xy = textureGather(samp0, coord + vec2(0.0, -u_rcp_source_resolution.y), 1).wz;
|
||||
up_down.zw = textureGather(samp0, coord + vec2(0.0, u_rcp_source_resolution.y), 1).yx;
|
||||
|
||||
float mean = (left.y + left.z + right.x + right.w) * 0.25;
|
||||
left -= vec4(mean);
|
||||
right -= vec4(mean);
|
||||
up_down -= vec4(mean);
|
||||
float center = color.g - mean;
|
||||
|
||||
float sum = dot(abs(left), vec4(1.0)) + dot(abs(right), vec4(1.0)) + dot(abs(up_down), vec4(1.0));
|
||||
float stddev = 2.181818 / max(sum, 1.0e-6);
|
||||
vec2 wy = sgsr_weight_y(pl.x, pl.y + 1.0, up_down.x, stddev);
|
||||
wy += sgsr_weight_y(pl.x - 1.0, pl.y + 1.0, up_down.y, stddev);
|
||||
wy += sgsr_weight_y(pl.x - 1.0, pl.y - 2.0, up_down.z, stddev);
|
||||
wy += sgsr_weight_y(pl.x, pl.y - 2.0, up_down.w, stddev);
|
||||
wy += sgsr_weight_y(pl.x + 1.0, pl.y - 1.0, left.x, stddev);
|
||||
wy += sgsr_weight_y(pl.x, pl.y - 1.0, left.y, stddev);
|
||||
wy += sgsr_weight_y(pl.x, pl.y, left.z, stddev);
|
||||
wy += sgsr_weight_y(pl.x + 1.0, pl.y, left.w, stddev);
|
||||
wy += sgsr_weight_y(pl.x - 1.0, pl.y - 1.0, right.x, stddev);
|
||||
wy += sgsr_weight_y(pl.x - 2.0, pl.y - 1.0, right.y, stddev);
|
||||
wy += sgsr_weight_y(pl.x - 2.0, pl.y, right.z, stddev);
|
||||
wy += sgsr_weight_y(pl.x - 1.0, pl.y, right.w, stddev);
|
||||
|
||||
float final_y = wy.y / max(wy.x, 1.0e-6);
|
||||
float max_y = max(max(left.y, left.z), max(right.x, right.w));
|
||||
float min_y = min(min(left.y, left.z), min(right.x, right.w));
|
||||
float delta_y = clamp(edge_sharpness * final_y, min_y, max_y) - center;
|
||||
delta_y = clamp(delta_y, -23.0 / 255.0, 23.0 / 255.0);
|
||||
color.rgb = clamp(color.rgb + vec3(delta_y), vec3(0.0), vec3(1.0));
|
||||
}
|
||||
|
||||
o_col0 = color;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
#ifdef ps_filter_scanlines
|
||||
void ps_filter_scanlines() // scanlines
|
||||
{
|
||||
uvec4 p = uvec4(gl_FragCoord);
|
||||
|
||||
o_col0 = ps_scanlines(p.y % 2);
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef ps_filter_diagonal
|
||||
void ps_filter_diagonal() // diagonal
|
||||
{
|
||||
uvec4 p = uvec4(gl_FragCoord);
|
||||
o_col0 = ps_crt((p.x + (p.y % 3)) % 3);
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef ps_filter_triangular
|
||||
void ps_filter_triangular() // triangular
|
||||
{
|
||||
uvec4 p = uvec4(gl_FragCoord);
|
||||
|
||||
// output.c = ps_crt(input, ((p.x + (p.y & 1) * 3) >> 1) % 3);
|
||||
o_col0 = ps_crt(((p.x + ((p.y >> 1) & 1) * 3) >> 1) % 3);
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef ps_filter_complex
|
||||
void ps_filter_complex() // triangular
|
||||
{
|
||||
const float PI = 3.14159265359f;
|
||||
vec2 texdim = vec2(textureSize(samp0, 0));
|
||||
|
||||
o_col0 = (0.9 - 0.4 * cos(2 * PI * v_tex.y * texdim.y)) * sample_c(vec2(v_tex.x, (floor(v_tex.y * texdim.y) + 0.5) / texdim.y));
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef ps_filter_lottes
|
||||
|
||||
#define MaskingType 4 //[1|2|3|4] The type of CRT shadow masking used. 1: compressed TV style, 2: Aperture-grille, 3: Stretched VGA style, 4: VGA style.
|
||||
#define ScanBrightness -8.00 //[-16.0 to 1.0] The overall brightness of the scanline effect. Lower for darker, higher for brighter.
|
||||
#define FilterCRTAmount -3.00 //[-4.0 to 1.0] The amount of filtering used, to replicate the TV CRT look. Lower for less, higher for more.
|
||||
#define HorizontalWarp 0.00 //[0.0 to 0.1] The distortion warping effect for the horizontal (x) axis of the screen. Use small increments.
|
||||
#define VerticalWarp 0.00 //[0.0 to 0.1] The distortion warping effect for the verticle (y) axis of the screen. Use small increments.
|
||||
#define MaskAmountDark 0.50 //[0.0 to 1.0] The value of the dark masking line effect used. Lower for darker lower end masking, higher for brighter.
|
||||
#define MaskAmountLight 1.50 //[0.0 to 2.0] The value of the light masking line effect used. Lower for darker higher end masking, higher for brighter.
|
||||
#define BloomPixel -1.50 //[-2.0 -0.5] Pixel bloom radius. Higher for increased softness of bloom.
|
||||
#define BloomScanLine -2.0 //[-4.0 -1.0] Scanline bloom radius. Higher for increased softness of bloom.
|
||||
#define BloomAmount 0.15 //[0.0 1.0] Bloom intensity. Higher for brighter.
|
||||
#define Shape 2.0 //[0.0 10.0] Kernal filter shape. Lower values will darken image and introduce moire patterns if used with curvature.
|
||||
#define UseShadowMask 1 //[0 or 1] Enables, or disables the use of the CRT shadow mask. 0 is disabled, 1 is enabled.
|
||||
|
||||
float ToLinear1(float c)
|
||||
{
|
||||
return c <= 0.04045 ? c / 12.92 : pow((c + 0.055) / 1.055, 2.4);
|
||||
}
|
||||
|
||||
vec3 ToLinear(vec3 c)
|
||||
{
|
||||
return vec3(ToLinear1(c.r), ToLinear1(c.g), ToLinear1(c.b));
|
||||
}
|
||||
|
||||
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));
|
||||
}
|
||||
|
||||
vec3 Fetch(vec2 pos, vec2 off)
|
||||
{
|
||||
pos = (floor(pos * u_target_size + off) + vec2(0.5, 0.5)) / u_target_size;
|
||||
if (max(abs(pos.x - 0.5), abs(pos.y - 0.5)) > 0.5)
|
||||
{
|
||||
return vec3(0.0, 0.0, 0.0);
|
||||
}
|
||||
else
|
||||
{
|
||||
return ToLinear(texture(samp0, pos.xy).rgb);
|
||||
}
|
||||
}
|
||||
|
||||
vec2 Dist(vec2 pos)
|
||||
{
|
||||
pos = pos * vec2(640, 480);
|
||||
|
||||
return -((pos - floor(pos)) - vec2(0.5, 0.5));
|
||||
}
|
||||
|
||||
float Gaus(float pos, float scale)
|
||||
{
|
||||
return exp2(scale * pow(abs(pos), Shape));
|
||||
}
|
||||
|
||||
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 = FilterCRTAmount;
|
||||
float wb = Gaus(dst - 1.0, scale);
|
||||
float wc = Gaus(dst + 0.0, scale);
|
||||
float wd = Gaus(dst + 1.0, scale);
|
||||
|
||||
return (b * wb + c * wc + d * wd) / (wb + wc + wd);
|
||||
}
|
||||
|
||||
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 = FilterCRTAmount;
|
||||
|
||||
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 (a * wa + b * wb + c * wc + d * wd + e * we) / (wa + wb + wc + wd + we);
|
||||
}
|
||||
|
||||
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 = BloomPixel;
|
||||
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, ScanBrightness);
|
||||
}
|
||||
|
||||
float BloomScan(vec2 pos, float off)
|
||||
{
|
||||
float dst = Dist(pos).y;
|
||||
|
||||
return Gaus(dst + off, BloomScanLine);
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
vec2 Warp(vec2 pos)
|
||||
{
|
||||
pos = pos * 2.0 - 1.0;
|
||||
pos *= vec2(1.0 + (pos.y * pos.y) * HorizontalWarp, 1.0 + (pos.x * pos.x) * VerticalWarp);
|
||||
return pos * 0.5 + 0.5;
|
||||
}
|
||||
|
||||
vec3 Mask(vec2 pos)
|
||||
{
|
||||
#if MaskingType == 1
|
||||
// Very compressed TV style shadow mask.
|
||||
float lines = MaskAmountLight;
|
||||
float odd = 0.0;
|
||||
|
||||
if (fract(pos.x / 6.0) < 0.5)
|
||||
{
|
||||
odd = 1.0;
|
||||
}
|
||||
if (fract((pos.y + odd) / 2.0) < 0.5)
|
||||
{
|
||||
lines = MaskAmountDark;
|
||||
}
|
||||
pos.x = fract(pos.x / 3.0);
|
||||
vec3 mask = vec3(MaskAmountDark, MaskAmountDark, MaskAmountDark);
|
||||
|
||||
if (pos.x < 0.333)
|
||||
{
|
||||
mask.r = MaskAmountLight;
|
||||
}
|
||||
else if (pos.x < 0.666)
|
||||
{
|
||||
mask.g = MaskAmountLight;
|
||||
}
|
||||
else
|
||||
{
|
||||
mask.b = MaskAmountLight;
|
||||
}
|
||||
|
||||
mask *= lines;
|
||||
|
||||
return mask;
|
||||
|
||||
#elif MaskingType == 2
|
||||
// Aperture-grille.
|
||||
pos.x = fract(pos.x / 3.0);
|
||||
vec3 mask = vec3(MaskAmountDark, MaskAmountDark, MaskAmountDark);
|
||||
|
||||
if (pos.x < 0.333)
|
||||
{
|
||||
mask.r = MaskAmountLight;
|
||||
}
|
||||
else if (pos.x < 0.666)
|
||||
{
|
||||
mask.g = MaskAmountLight;
|
||||
}
|
||||
else
|
||||
{
|
||||
mask.b = MaskAmountLight;
|
||||
}
|
||||
|
||||
return mask;
|
||||
|
||||
#elif MaskingType == 3
|
||||
// Stretched VGA style shadow mask (same as prior shaders).
|
||||
pos.x += pos.y * 3.0;
|
||||
vec3 mask = vec3(MaskAmountDark, MaskAmountDark, MaskAmountDark);
|
||||
pos.x = fract(pos.x / 6.0);
|
||||
|
||||
if (pos.x < 0.333)
|
||||
{
|
||||
mask.r = MaskAmountLight;
|
||||
}
|
||||
else if (pos.x < 0.666)
|
||||
{
|
||||
mask.g = MaskAmountLight;
|
||||
}
|
||||
else
|
||||
{
|
||||
mask.b = MaskAmountLight;
|
||||
}
|
||||
|
||||
return mask;
|
||||
|
||||
#else
|
||||
// VGA style shadow mask.
|
||||
pos.xy = floor(pos.xy * vec2(1.0, 0.5));
|
||||
pos.x += pos.y * 3.0;
|
||||
|
||||
vec3 mask = vec3(MaskAmountDark, MaskAmountDark, MaskAmountDark);
|
||||
pos.x = fract(pos.x / 6.0);
|
||||
|
||||
if (pos.x < 0.333)
|
||||
{
|
||||
mask.r = MaskAmountLight;
|
||||
}
|
||||
else if (pos.x < 0.666)
|
||||
{
|
||||
mask.g = MaskAmountLight;
|
||||
}
|
||||
else
|
||||
{
|
||||
mask.b = MaskAmountLight;
|
||||
}
|
||||
return mask;
|
||||
#endif
|
||||
}
|
||||
|
||||
vec4 LottesCRTPass()
|
||||
{
|
||||
vec4 color;
|
||||
vec4 fragcoord = gl_FragCoord - u_target_rect;
|
||||
vec2 inSize = u_target_resolution - (2 * u_target_rect.xy);
|
||||
|
||||
vec2 pos = Warp(fragcoord.xy / inSize);
|
||||
color.rgb = Tri(pos);
|
||||
color.rgb += Bloom(pos) * BloomAmount;
|
||||
#if UseShadowMask
|
||||
color.rgb *= Mask(fragcoord.xy);
|
||||
#endif
|
||||
color.rgb = ToSrgb(color.rgb);
|
||||
|
||||
return color;
|
||||
}
|
||||
|
||||
void ps_filter_lottes()
|
||||
{
|
||||
o_col0 = LottesCRTPass();
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#ifdef ps_4x_rgss
|
||||
void ps_4x_rgss()
|
||||
{
|
||||
vec2 dxy = vec2(dFdx(v_tex.x), dFdy(v_tex.y));
|
||||
vec3 color = vec3(0);
|
||||
|
||||
float s = 1.0/8.0;
|
||||
float l = 3.0/8.0;
|
||||
|
||||
color += sample_c(v_tex + vec2( s, l) * dxy).rgb;
|
||||
color += sample_c(v_tex + vec2( l,-s) * dxy).rgb;
|
||||
color += sample_c(v_tex + vec2(-s,-l) * dxy).rgb;
|
||||
color += sample_c(v_tex + vec2(-l, s) * dxy).rgb;
|
||||
|
||||
o_col0 = vec4(color * 0.25,1);
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef ps_automagical_supersampling
|
||||
void ps_automagical_supersampling()
|
||||
{
|
||||
vec2 ratio = (u_source_size / u_target_size) * 0.5;
|
||||
vec2 steps = floor(ratio);
|
||||
vec3 col = sample_c(v_tex).rgb;
|
||||
float div = 1;
|
||||
|
||||
for (float y = 0; y < steps.y; y++)
|
||||
{
|
||||
for (float x = 0; x < steps.x; x++)
|
||||
{
|
||||
vec2 offset = vec2(x,y) - ratio * 0.5;
|
||||
col += sample_c(v_tex + offset * u_rcp_source_resolution * 2.0).rgb;
|
||||
div++;
|
||||
}
|
||||
}
|
||||
|
||||
o_col0 = vec4(col / div, 1);
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,74 @@
|
||||
// SPDX-FileCopyrightText: 2002-2025 PCSX2 Dev Team
|
||||
// SPDX-License-Identifier: GPL-3.0+
|
||||
|
||||
//#version 420 // Keep it for editor detection
|
||||
|
||||
#ifdef VERTEX_SHADER
|
||||
|
||||
layout(location = 0) in vec4 a_pos;
|
||||
layout(location = 1) in vec2 a_tex;
|
||||
|
||||
layout(location = 0) out vec2 v_tex;
|
||||
|
||||
void main()
|
||||
{
|
||||
gl_Position = vec4(a_pos.x, -a_pos.y, a_pos.z, a_pos.w);
|
||||
v_tex = a_tex;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
/*
|
||||
** Contrast, saturation, brightness
|
||||
** Code of this function is from TGM's shader pack
|
||||
** http://irrlicht.sourceforge.net/phpBB2/viewtopic.php?t=21057
|
||||
** TGM's author comment about the license (included in the previous link)
|
||||
** "do with it, what you want! its total free!
|
||||
** (but would be nice, if you say that you used my shaders :wink: ) but not necessary"
|
||||
*/
|
||||
|
||||
#ifdef FRAGMENT_SHADER
|
||||
|
||||
layout(push_constant) uniform cb0
|
||||
{
|
||||
vec4 params;
|
||||
};
|
||||
|
||||
layout(set = 0, binding = 0) uniform sampler2D samp0;
|
||||
layout(location = 0) in vec2 v_tex;
|
||||
layout(location = 0) out vec4 o_col0;
|
||||
|
||||
// For all settings: 1.0 = 100% 0.5=50% 1.5 = 150%
|
||||
vec4 ContrastSaturationBrightness(vec4 color)
|
||||
{
|
||||
float brt = params.x;
|
||||
float con = params.y;
|
||||
float sat = params.z;
|
||||
|
||||
// Increase or decrease these values to adjust r, g and b color channels separately
|
||||
const float AvgLumR = 0.5;
|
||||
const float AvgLumG = 0.5;
|
||||
const float AvgLumB = 0.5;
|
||||
|
||||
const vec3 LumCoeff = vec3(0.2125, 0.7154, 0.0721);
|
||||
|
||||
vec3 AvgLumin = vec3(AvgLumR, AvgLumG, AvgLumB);
|
||||
vec3 brtColor = color.rgb * brt;
|
||||
float dot_intensity = dot(brtColor, LumCoeff);
|
||||
vec3 intensity = vec3(dot_intensity, dot_intensity, dot_intensity);
|
||||
vec3 satColor = mix(intensity, brtColor, sat);
|
||||
vec3 conColor = mix(AvgLumin, satColor, con);
|
||||
|
||||
color.rgb = conColor;
|
||||
return color;
|
||||
}
|
||||
|
||||
|
||||
void main()
|
||||
{
|
||||
vec4 c = texture(samp0, v_tex);
|
||||
o_col0 = ContrastSaturationBrightness(c);
|
||||
}
|
||||
|
||||
|
||||
#endif
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
+626
-3
@@ -1,8 +1,8 @@
|
||||
{
|
||||
"schema_version": 1,
|
||||
"generated_at": "2026-08-11T07:40:19Z",
|
||||
"total_files": 8321,
|
||||
"total_size": 10455720343,
|
||||
"generated_at": "2026-08-11T07:56:05Z",
|
||||
"total_files": 8357,
|
||||
"total_size": 10466186980,
|
||||
"files": {
|
||||
"520d3d1b5897800af47f92efd2444a26b7a7dead": {
|
||||
"path": "bios/3DO Company/3DO/3do_arcade_saot.bin",
|
||||
@@ -48247,6 +48247,146 @@
|
||||
"crc32": "6e8b2b47",
|
||||
"adler32": "f5bc538e"
|
||||
},
|
||||
"b478ce9d1343b8dd201c045f010bd1b64ba158ae": {
|
||||
"path": "bios/Other/armsx2/pcsx2/resources/shaders/opengl/cas.glsl",
|
||||
"name": "cas.glsl",
|
||||
"size": 2413,
|
||||
"sha1": "b478ce9d1343b8dd201c045f010bd1b64ba158ae",
|
||||
"md5": "2c928cbd0410a7e7edae6b2808a1f566",
|
||||
"sha256": "3d5b9cef750ea8bedceef43c4c52215e8280abb81b5b8fa002007bb3f97f0506",
|
||||
"crc32": "ce9e57e4",
|
||||
"adler32": "6031f981"
|
||||
},
|
||||
"32777e258030ad9559864d9f4273d515d65f728f": {
|
||||
"path": "bios/Other/armsx2/pcsx2/resources/shaders/opengl/convert.glsl",
|
||||
"name": "convert.glsl",
|
||||
"size": 15093,
|
||||
"sha1": "32777e258030ad9559864d9f4273d515d65f728f",
|
||||
"md5": "4791fe606bfd87d5afe710c5b4c7bbfb",
|
||||
"sha256": "4ac385f0e38ee2c3a3f7014db86bd59927a5d4e4f76f24df9b8f8b3d97142390",
|
||||
"crc32": "38998f1a",
|
||||
"adler32": "1c0d032f"
|
||||
},
|
||||
"04bfcabf518320593dcda8198475c7f39295ef1f": {
|
||||
"path": "bios/Other/armsx2/pcsx2/resources/shaders/opengl/imgui.glsl",
|
||||
"name": "imgui.glsl",
|
||||
"size": 637,
|
||||
"sha1": "04bfcabf518320593dcda8198475c7f39295ef1f",
|
||||
"md5": "fff1d8c84afbf21c47baaa919e1eef95",
|
||||
"sha256": "25978439553bbd959fe4eb5d03b739a3d697348458a7bac3df48556148f48027",
|
||||
"crc32": "b9848dc2",
|
||||
"adler32": "a7d8c97b"
|
||||
},
|
||||
"d6209a8b3c4681823b1f0b7d0648c819ec72e2ad": {
|
||||
"path": "bios/Other/armsx2/pcsx2/resources/shaders/opengl/interlace.glsl",
|
||||
"name": "interlace.glsl",
|
||||
"size": 6946,
|
||||
"sha1": "d6209a8b3c4681823b1f0b7d0648c819ec72e2ad",
|
||||
"md5": "bd4ca766cc7abf55f37336234248a6fb",
|
||||
"sha256": "ff7e27fa41f33ec5d4a86b2a48a622dbcd8dd0ae37f8afe306fdd182a7aa8ec1",
|
||||
"crc32": "43dd2e9e",
|
||||
"adler32": "e2a83de3"
|
||||
},
|
||||
"7f476bffdc19d7ba2806eef40c2e8e40bdf0896c": {
|
||||
"path": "bios/Other/armsx2/pcsx2/resources/shaders/opengl/merge.glsl",
|
||||
"name": "merge.glsl",
|
||||
"size": 579,
|
||||
"sha1": "7f476bffdc19d7ba2806eef40c2e8e40bdf0896c",
|
||||
"md5": "8ffd758adde9783ba80625a25b06ef7a",
|
||||
"sha256": "6cd2bc21890426b5430d44b28a89289bcc6fc9ecd632bb3a8eafb6c8b818499c",
|
||||
"crc32": "f1b5eedb",
|
||||
"adler32": "a37cb550"
|
||||
},
|
||||
"ca7a974714111895bbf03360078ea1008694c52e": {
|
||||
"path": "bios/Other/armsx2/pcsx2/resources/shaders/opengl/present.glsl",
|
||||
"name": "present.glsl",
|
||||
"size": 11730,
|
||||
"sha1": "ca7a974714111895bbf03360078ea1008694c52e",
|
||||
"md5": "ddb9dab93906986ec0bb63c5aad0401e",
|
||||
"sha256": "27ffa5fdf1634f7be2734d2eff2d9dce0cca71c2832685e0a682388731dc5c60",
|
||||
"crc32": "7f2bb4e3",
|
||||
"adler32": "28b5f85e"
|
||||
},
|
||||
"511dc6bb2f81d0ad61fe46c6e91dce8b344fd934": {
|
||||
"path": "bios/Other/armsx2/pcsx2/resources/shaders/opengl/shadeboost.glsl",
|
||||
"name": "shadeboost.glsl",
|
||||
"size": 1623,
|
||||
"sha1": "511dc6bb2f81d0ad61fe46c6e91dce8b344fd934",
|
||||
"md5": "8e8ebd0758705f947ca6f8eba4baf8e6",
|
||||
"sha256": "e7297a2e333bb1882bcf82d2a109a2ab033715cce1bba4934f42ec68370f0077",
|
||||
"crc32": "30ec9e5f",
|
||||
"adler32": "52b30c3f"
|
||||
},
|
||||
"005cecf1a5e20b05407d55d0aad22cf81ad66c31": {
|
||||
"path": "bios/Other/armsx2/pcsx2/resources/shaders/vulkan/cas.glsl",
|
||||
"name": "cas.glsl",
|
||||
"size": 2637,
|
||||
"sha1": "005cecf1a5e20b05407d55d0aad22cf81ad66c31",
|
||||
"md5": "deb7394a31184990c78c9753a293ff60",
|
||||
"sha256": "ea3f65c6d1b18abe23b42a3d9ddf48d787df287feef6cfac52ca6109d8852d97",
|
||||
"crc32": "e00e7479",
|
||||
"adler32": "59323e74"
|
||||
},
|
||||
"53ff273e335432fdbbff9da2762e229ec2bd5078": {
|
||||
"path": "bios/Other/armsx2/pcsx2/resources/shaders/vulkan/convert.glsl",
|
||||
"name": "convert.glsl",
|
||||
"size": 14024,
|
||||
"sha1": "53ff273e335432fdbbff9da2762e229ec2bd5078",
|
||||
"md5": "383ccce840167fd0264e3e382a411694",
|
||||
"sha256": "e8213fa871bebc8fc883be3bbccf111c8aec1f84063e05a24850efc735312e08",
|
||||
"crc32": "df5810f9",
|
||||
"adler32": "a26ab337"
|
||||
},
|
||||
"b8d20aa6884878ba72c080d3f2107e09606963d3": {
|
||||
"path": "bios/Other/armsx2/pcsx2/resources/shaders/vulkan/imgui.glsl",
|
||||
"name": "imgui.glsl",
|
||||
"size": 791,
|
||||
"sha1": "b8d20aa6884878ba72c080d3f2107e09606963d3",
|
||||
"md5": "23b4ac68a9c4f01ce319d1bfd7ba6627",
|
||||
"sha256": "372e33cccb520a987983dd897c51c6b7e609f16badd67d056a95799a7f768566",
|
||||
"crc32": "1b5ae2e5",
|
||||
"adler32": "638efe68"
|
||||
},
|
||||
"d5ba24ba836c418f7f2d9d8b44bd337baa9e45a3": {
|
||||
"path": "bios/Other/armsx2/pcsx2/resources/shaders/vulkan/interlace.glsl",
|
||||
"name": "interlace.glsl",
|
||||
"size": 7289,
|
||||
"sha1": "d5ba24ba836c418f7f2d9d8b44bd337baa9e45a3",
|
||||
"md5": "6888a8e85b9c0a357580d4464ddd7d0d",
|
||||
"sha256": "af535e4b871b188957a7169ed883f6f8a209f0908e5b7aff17755605c8d07857",
|
||||
"crc32": "21dc5ffb",
|
||||
"adler32": "43e8a7f9"
|
||||
},
|
||||
"e84aa516874350f414e95d3891ce480fe2958aae": {
|
||||
"path": "bios/Other/armsx2/pcsx2/resources/shaders/vulkan/merge.glsl",
|
||||
"name": "merge.glsl",
|
||||
"size": 759,
|
||||
"sha1": "e84aa516874350f414e95d3891ce480fe2958aae",
|
||||
"md5": "d4933454a5637402889209af223d59fe",
|
||||
"sha256": "3c0eb665db06c289841829a6aa4716e46ce5ae8e08005a82ad4f3020bd8406e7",
|
||||
"crc32": "4d559151",
|
||||
"adler32": "b899ea33"
|
||||
},
|
||||
"0e22e330e10f31d7e7d7db00966cd48d1c5c6dce": {
|
||||
"path": "bios/Other/armsx2/pcsx2/resources/shaders/vulkan/present.glsl",
|
||||
"name": "present.glsl",
|
||||
"size": 10336,
|
||||
"sha1": "0e22e330e10f31d7e7d7db00966cd48d1c5c6dce",
|
||||
"md5": "dee17db223f997696ecd59fc2bac56cb",
|
||||
"sha256": "88d9f9b08f3a62cfd77fdf366c2a1ecca7924c407a3eabb1c1df68cfca2ee2d1",
|
||||
"crc32": "980f007e",
|
||||
"adler32": "31fc126f"
|
||||
},
|
||||
"bef69d202c6e21f2ec0d6930e439a9498642ba6b": {
|
||||
"path": "bios/Other/armsx2/pcsx2/resources/shaders/vulkan/shadeboost.glsl",
|
||||
"name": "shadeboost.glsl",
|
||||
"size": 1914,
|
||||
"sha1": "bef69d202c6e21f2ec0d6930e439a9498642ba6b",
|
||||
"md5": "8d55f559c3f1a35c3b8c66f1a57ca25b",
|
||||
"sha256": "31ab20c5617e0bdd3e1afaf9cac2212586f94433f176ca30810a1fecf3f338e8",
|
||||
"crc32": "e5a3fed2",
|
||||
"adler32": "2af75de2"
|
||||
},
|
||||
"25e41433147face77af96fecac4519ed11ae8072": {
|
||||
"path": "bios/Other/armsx2/placeholder.png",
|
||||
"name": "placeholder.png",
|
||||
@@ -49017,6 +49157,26 @@
|
||||
"crc32": "bb56de24",
|
||||
"adler32": "28b01f1d"
|
||||
},
|
||||
"28c7616cd02e4286f9b4c1c4a8b8850832b49fcb": {
|
||||
"path": "bios/Other/colem/EOS.ROM",
|
||||
"name": "EOS.ROM",
|
||||
"size": 16384,
|
||||
"sha1": "28c7616cd02e4286f9b4c1c4a8b8850832b49fcb",
|
||||
"md5": "cf10b154f2e006a9740d7653cfc47cab",
|
||||
"sha256": "a49928fbac56380917134b54961ece2e90073022f3e04a6023d26cdbbd9c3356",
|
||||
"crc32": "ef6403c5",
|
||||
"adler32": "2d380b09"
|
||||
},
|
||||
"d4aec4efe1431e56fe52d83baf9118542c525255": {
|
||||
"path": "bios/Other/colem/WRITER.ROM",
|
||||
"name": "WRITER.ROM",
|
||||
"size": 32768,
|
||||
"sha1": "d4aec4efe1431e56fe52d83baf9118542c525255",
|
||||
"md5": "4fe4f6800076ea3d897d4285653447bd",
|
||||
"sha256": "3b17255d2679d11f79e6cacda86de5f6bc9bb5cddf78cbddc651af03b237317d",
|
||||
"crc32": "58d86a2a",
|
||||
"adler32": "ba97647e"
|
||||
},
|
||||
"15d52de01320d9b954e03b4c2e71ec75fd301bbb": {
|
||||
"path": "bios/Other/cpcemu/ROM/COPYMATE.ROM",
|
||||
"name": "COPYMATE.ROM",
|
||||
@@ -49097,6 +49257,26 @@
|
||||
"crc32": "588b5540",
|
||||
"adler32": "b1254be6"
|
||||
},
|
||||
"72ecfde5f58c5993765a6ef5b8866c4777cc4ade": {
|
||||
"path": "bios/Other/cspect/enNextZX.rom",
|
||||
"name": "enNextZX.rom",
|
||||
"size": 65536,
|
||||
"sha1": "72ecfde5f58c5993765a6ef5b8866c4777cc4ade",
|
||||
"md5": "8535c40c6cce978623a3e06a38e3a0fd",
|
||||
"sha256": "dd901acd306794ad34f3131ad1df54b6f4de5527ad1b2aa42f82e417f93f17a5",
|
||||
"crc32": "6d9951f0",
|
||||
"adler32": "d3b66ba9"
|
||||
},
|
||||
"4f05efec7af0829f43aa3cac18a30ae2a33ded88": {
|
||||
"path": "bios/Other/cspect/enNxtmmc.rom",
|
||||
"name": "enNxtmmc.rom",
|
||||
"size": 8192,
|
||||
"sha1": "4f05efec7af0829f43aa3cac18a30ae2a33ded88",
|
||||
"md5": "907a03706a196b0da832ddab204264f2",
|
||||
"sha256": "ded2038d78f57b4fd7e05df0330064f661c221f7b06d8cd2bddee1ff6062f019",
|
||||
"crc32": "5a443736",
|
||||
"adler32": "865d3c5e"
|
||||
},
|
||||
"e6c0050b3c67ee26198488fbbe4a5d019c15b628": {
|
||||
"path": "bios/Other/dolphin/codehandler.bin",
|
||||
"name": "codehandler.bin",
|
||||
@@ -49277,6 +49457,156 @@
|
||||
"crc32": "35ee85c3",
|
||||
"adler32": "fa9adec5"
|
||||
},
|
||||
"3c6b523e5432a892a0c284d9ba2593919b0173b7": {
|
||||
"path": "bios/Other/emucorev/psvita_games.db",
|
||||
"name": "psvita_games.db",
|
||||
"size": 3801088,
|
||||
"sha1": "3c6b523e5432a892a0c284d9ba2593919b0173b7",
|
||||
"md5": "229cf38617d6669286b5d1a48906aa53",
|
||||
"sha256": "ca56a424e87cf4c257dcd3810567e62cb10767096b6a2378e69b07040c5fbc13",
|
||||
"crc32": "69787db6",
|
||||
"adler32": "53e718d5"
|
||||
},
|
||||
"0e2ee74d1f9ebc3a6faf9dbaebbacc2ff053f4df": {
|
||||
"path": "bios/Other/emucorex/games.db",
|
||||
"name": "games.db",
|
||||
"size": 6025216,
|
||||
"sha1": "0e2ee74d1f9ebc3a6faf9dbaebbacc2ff053f4df",
|
||||
"md5": "4b945ee2b52c49c397d368dc21fa42dc",
|
||||
"sha256": "86883a0199a129b900f4a5c7ade6245b7e9d1399ec3c08d1fbf1838c01722e8e",
|
||||
"crc32": "c9a52a37",
|
||||
"adler32": "6ce8f9bd"
|
||||
},
|
||||
"cb0d4276f9947762af0841a8af75efa6cbe9109c": {
|
||||
"path": "bios/Other/emucorex/resources/shaders/opengl/cas.glsl",
|
||||
"name": "cas.glsl",
|
||||
"size": 2483,
|
||||
"sha1": "cb0d4276f9947762af0841a8af75efa6cbe9109c",
|
||||
"md5": "b56eb507fac5ac64a7079514c02b8ca7",
|
||||
"sha256": "53e5ddc6825ecde7b502acb5fae3a173ba6696ec5b8bb7445f378f7b0ad1beb8",
|
||||
"crc32": "13eed5a5",
|
||||
"adler32": "552611d7"
|
||||
},
|
||||
"35910b67070342cdd6ec4d68eb2e56b39d350543": {
|
||||
"path": "bios/Other/emucorex/resources/shaders/opengl/convert.glsl",
|
||||
"name": "convert.glsl",
|
||||
"size": 16416,
|
||||
"sha1": "35910b67070342cdd6ec4d68eb2e56b39d350543",
|
||||
"md5": "b8f058ec01942f596c890a060a32f08b",
|
||||
"sha256": "fcb651c2ff39102a33ece3716579e3aee7d8b92d4700e52b56b6cf14baa8b8d1",
|
||||
"crc32": "bb25c312",
|
||||
"adler32": "afe8a197"
|
||||
},
|
||||
"ca149058af89d8f612aaa529661e8267d9569875": {
|
||||
"path": "bios/Other/emucorex/resources/shaders/opengl/imgui.glsl",
|
||||
"name": "imgui.glsl",
|
||||
"size": 637,
|
||||
"sha1": "ca149058af89d8f612aaa529661e8267d9569875",
|
||||
"md5": "9338b9a25372178b4ecbf0215697e9be",
|
||||
"sha256": "ea82ce9731de4a0b5af3e66e47e048af569e0e98c5739b32f268fb54caa7603a",
|
||||
"crc32": "342d0e13",
|
||||
"adler32": "a57ec97a"
|
||||
},
|
||||
"be39a049af0b8ab0c2168ad6d8cf636e15ae0dd2": {
|
||||
"path": "bios/Other/emucorex/resources/shaders/opengl/interlace.glsl",
|
||||
"name": "interlace.glsl",
|
||||
"size": 5983,
|
||||
"sha1": "be39a049af0b8ab0c2168ad6d8cf636e15ae0dd2",
|
||||
"md5": "9f46187238e838a602b358705a9b813b",
|
||||
"sha256": "15a58d9f7442f24e86484f4a7f0c10570b434ef68e8fb2d5c38513c0016d1e64",
|
||||
"crc32": "3198c556",
|
||||
"adler32": "facf1933"
|
||||
},
|
||||
"c8eb9c1926baad8bbba25f97be54abae233fe715": {
|
||||
"path": "bios/Other/emucorex/resources/shaders/opengl/merge.glsl",
|
||||
"name": "merge.glsl",
|
||||
"size": 579,
|
||||
"sha1": "c8eb9c1926baad8bbba25f97be54abae233fe715",
|
||||
"md5": "1cbf28d65b0d6fe727b571d3e46871b8",
|
||||
"sha256": "654281fb002aa1a086ee979d694e9d6443864bdc8740d20188baf8e125e386fa",
|
||||
"crc32": "ae991348",
|
||||
"adler32": "a15cb54f"
|
||||
},
|
||||
"4abe45e59dc9286321a115c76c31cc7fe85e58d5": {
|
||||
"path": "bios/Other/emucorex/resources/shaders/opengl/present.glsl",
|
||||
"name": "present.glsl",
|
||||
"size": 14894,
|
||||
"sha1": "4abe45e59dc9286321a115c76c31cc7fe85e58d5",
|
||||
"md5": "480b029f6c357fb683a6720e2b78d990",
|
||||
"sha256": "e31c519e6b22683cebefc5c2358b2b7ddad10964a1e478fa3eba01f3ab5adb17",
|
||||
"crc32": "67a7b03b",
|
||||
"adler32": "c5f5ce78"
|
||||
},
|
||||
"03c8b0d3ebeb0ecdc7f594ba6f7242a6f6e4d564": {
|
||||
"path": "bios/Other/emucorex/resources/shaders/opengl/shadeboost.glsl",
|
||||
"name": "shadeboost.glsl",
|
||||
"size": 1548,
|
||||
"sha1": "03c8b0d3ebeb0ecdc7f594ba6f7242a6f6e4d564",
|
||||
"md5": "23a5e91beb2072f48e1011e7a9b6e901",
|
||||
"sha256": "15ff418a0fc877886015cc781c9c3b0810a870bee5803d76741bbcbcc540b9e5",
|
||||
"crc32": "54c435f2",
|
||||
"adler32": "c42ff6d7"
|
||||
},
|
||||
"705d20d39a910d58a070fb86780ac58c8007591c": {
|
||||
"path": "bios/Other/emucorex/resources/shaders/vulkan/convert.glsl",
|
||||
"name": "convert.glsl",
|
||||
"size": 14941,
|
||||
"sha1": "705d20d39a910d58a070fb86780ac58c8007591c",
|
||||
"md5": "669f55ffa59d7b754ab11f96c42f206f",
|
||||
"sha256": "ac3d88c299e304faf76cda2b305510d5a6c19c06319e53ee54fdc18b028a860f",
|
||||
"crc32": "fd02bb00",
|
||||
"adler32": "70d4d2c4"
|
||||
},
|
||||
"276d984150c2fd2fb5ba287f2e5ceb7262dc5a95": {
|
||||
"path": "bios/Other/emucorex/resources/shaders/vulkan/imgui.glsl",
|
||||
"name": "imgui.glsl",
|
||||
"size": 791,
|
||||
"sha1": "276d984150c2fd2fb5ba287f2e5ceb7262dc5a95",
|
||||
"md5": "b79725bff4fecb48d68ad575e13950d1",
|
||||
"sha256": "2d765ffb2bef04082138e29e8ba7f7cc1c788c6415226d1aab1b7eb5bbd0431f",
|
||||
"crc32": "c9511683",
|
||||
"adler32": "609afe67"
|
||||
},
|
||||
"268f43cd946eea999c62f63a24eb00cb2fdc342c": {
|
||||
"path": "bios/Other/emucorex/resources/shaders/vulkan/interlace.glsl",
|
||||
"name": "interlace.glsl",
|
||||
"size": 6329,
|
||||
"sha1": "268f43cd946eea999c62f63a24eb00cb2fdc342c",
|
||||
"md5": "b3e6aa12e24e59cad71d1b7d851a2572",
|
||||
"sha256": "710e9e43ba7115e80b3e34c18072d838ef59f08f096204a7c5c9bf8704047b7f",
|
||||
"crc32": "3317d2fb",
|
||||
"adler32": "80778129"
|
||||
},
|
||||
"808b7b46bfb033c7fe4d94d0dbf5a271de30dedc": {
|
||||
"path": "bios/Other/emucorex/resources/shaders/vulkan/merge.glsl",
|
||||
"name": "merge.glsl",
|
||||
"size": 759,
|
||||
"sha1": "808b7b46bfb033c7fe4d94d0dbf5a271de30dedc",
|
||||
"md5": "8fbeeb5c09477bcaf614087003df61a4",
|
||||
"sha256": "2e6883d4304c5de25c464a9fd97fcd2f642d8d2af2db9c2b13882e67f0f35b93",
|
||||
"crc32": "51cef730",
|
||||
"adler32": "b5c5ea32"
|
||||
},
|
||||
"a848aad1840c7d85bfcdd552521a7181b00331cc": {
|
||||
"path": "bios/Other/emucorex/resources/shaders/vulkan/present.glsl",
|
||||
"name": "present.glsl",
|
||||
"size": 13440,
|
||||
"sha1": "a848aad1840c7d85bfcdd552521a7181b00331cc",
|
||||
"md5": "b0bdec53b1c50873ba45539565f1327c",
|
||||
"sha256": "2db47ffca9510468e37717266838576f96dccd9ed6b7f00c0a721c9868338b19",
|
||||
"crc32": "50fb46e4",
|
||||
"adler32": "8296d1bd"
|
||||
},
|
||||
"9b2704655a893ff1675d28df4bd9ffc9e15d3dd5": {
|
||||
"path": "bios/Other/emucorex/resources/shaders/vulkan/shadeboost.glsl",
|
||||
"name": "shadeboost.glsl",
|
||||
"size": 1831,
|
||||
"sha1": "9b2704655a893ff1675d28df4bd9ffc9e15d3dd5",
|
||||
"md5": "ec6b58f723279afe732b7f9660acf27d",
|
||||
"sha256": "27ab08e76e08fa8a1023b076f3e6c23bc6841732658942f30cea634394f40729",
|
||||
"crc32": "69dc25d7",
|
||||
"adler32": "9f4b472e"
|
||||
},
|
||||
"84d422b53547271e3a07342704a05ef481db3f99": {
|
||||
"path": "bios/Other/fbneo/136032.101.e3",
|
||||
"name": "136032.101.e3",
|
||||
@@ -49297,6 +49627,16 @@
|
||||
"crc32": "ebf1e0ae",
|
||||
"adler32": "2e4808ff"
|
||||
},
|
||||
"0a42a4816c89447b16e1f3245409591efea98a4a": {
|
||||
"path": "bios/Other/fbneo/136032.103.f7",
|
||||
"name": "136032.103.f7",
|
||||
"size": 235,
|
||||
"sha1": "0a42a4816c89447b16e1f3245409591efea98a4a",
|
||||
"md5": "c4abdbe2a64c2ef06b6b659f32ea883f",
|
||||
"sha256": "c770a3ae305c3420292516dbd86373f67798983c74754d2cc988de6ddf6ec51f",
|
||||
"crc32": "92d6a0b4",
|
||||
"adler32": "cc91d423"
|
||||
},
|
||||
"72ba464da01bd6d3a91b8d9997d5ac14b6f47aad": {
|
||||
"path": "bios/Other/fbneo/136032.104.f5",
|
||||
"name": "136032.104.f5",
|
||||
@@ -49407,6 +49747,16 @@
|
||||
"crc32": "18c0ff3e",
|
||||
"adler32": "7e6df93f"
|
||||
},
|
||||
"8e14e85c645187504ec9d162b3ea614a0c421d32": {
|
||||
"path": "bios/Other/mednafen/apple2e-enh-kb.rom",
|
||||
"name": "apple2e-enh-kb.rom",
|
||||
"size": 2048,
|
||||
"sha1": "8e14e85c645187504ec9d162b3ea614a0c421d32",
|
||||
"md5": "b956c537e7b6b85ffa5c3493b1490d8a",
|
||||
"sha256": "a1989da84ea4381d309e7e08783771f884e913236b9bcc71c3d649aacf76537a",
|
||||
"crc32": "c506efb9",
|
||||
"adler32": "87aaa299"
|
||||
},
|
||||
"58807f32c413a0c9db6deb0365f2fac9518e7c86": {
|
||||
"path": "bios/Other/opentyrian/cubetxt1.dat",
|
||||
"name": "cubetxt1.dat",
|
||||
@@ -50147,6 +50497,16 @@
|
||||
"crc32": "c6bebfc6",
|
||||
"adler32": "04deae73"
|
||||
},
|
||||
"8a799c6615702aac72016b784e30ea1abd3e197b": {
|
||||
"path": "bios/Other/prboom-plus/prboom-plus.wad",
|
||||
"name": "prboom-plus.wad",
|
||||
"size": 357768,
|
||||
"sha1": "8a799c6615702aac72016b784e30ea1abd3e197b",
|
||||
"md5": "1164ae723c9181698cc41dde6a341132",
|
||||
"sha256": "29e6e18023cf39319f9984107f5f0f796b2593b1c3a55fc79adf3ae12498a6ce",
|
||||
"crc32": "a4626dfa",
|
||||
"adler32": "e0b1fb08"
|
||||
},
|
||||
"0f25848f73705328ca03b02905e95e3a5d087d8c": {
|
||||
"path": "bios/Other/punes/dip.cfg",
|
||||
"name": "dip.cfg",
|
||||
@@ -92788,6 +93148,20 @@
|
||||
"95f294d24b5e97ceab96282f1284190f": "8dba66121f3bbc4b2bdf67722ef4c2b6b6b23ee6",
|
||||
"d66b0bccd743bd11eaca55bcaec925da": "c54f04b63ac6f04e0a0944ef260b5497e4494dbd",
|
||||
"6f47c5daf33a759df3395db8ebe62ed1": "7b0bb79d38c573648de218645c6fb16449e156e0",
|
||||
"2c928cbd0410a7e7edae6b2808a1f566": "b478ce9d1343b8dd201c045f010bd1b64ba158ae",
|
||||
"4791fe606bfd87d5afe710c5b4c7bbfb": "32777e258030ad9559864d9f4273d515d65f728f",
|
||||
"fff1d8c84afbf21c47baaa919e1eef95": "04bfcabf518320593dcda8198475c7f39295ef1f",
|
||||
"bd4ca766cc7abf55f37336234248a6fb": "d6209a8b3c4681823b1f0b7d0648c819ec72e2ad",
|
||||
"8ffd758adde9783ba80625a25b06ef7a": "7f476bffdc19d7ba2806eef40c2e8e40bdf0896c",
|
||||
"ddb9dab93906986ec0bb63c5aad0401e": "ca7a974714111895bbf03360078ea1008694c52e",
|
||||
"8e8ebd0758705f947ca6f8eba4baf8e6": "511dc6bb2f81d0ad61fe46c6e91dce8b344fd934",
|
||||
"deb7394a31184990c78c9753a293ff60": "005cecf1a5e20b05407d55d0aad22cf81ad66c31",
|
||||
"383ccce840167fd0264e3e382a411694": "53ff273e335432fdbbff9da2762e229ec2bd5078",
|
||||
"23b4ac68a9c4f01ce319d1bfd7ba6627": "b8d20aa6884878ba72c080d3f2107e09606963d3",
|
||||
"6888a8e85b9c0a357580d4464ddd7d0d": "d5ba24ba836c418f7f2d9d8b44bd337baa9e45a3",
|
||||
"d4933454a5637402889209af223d59fe": "e84aa516874350f414e95d3891ce480fe2958aae",
|
||||
"dee17db223f997696ecd59fc2bac56cb": "0e22e330e10f31d7e7d7db00966cd48d1c5c6dce",
|
||||
"8d55f559c3f1a35c3b8c66f1a57ca25b": "bef69d202c6e21f2ec0d6930e439a9498642ba6b",
|
||||
"ba3669cafd8b5036f15b1e682ef8c94a": "25e41433147face77af96fecac4519ed11ae8072",
|
||||
"99a84ce95581f49e5f38075648884ede": "84b000485929698392676e8e7915bfcce15291ee",
|
||||
"628d6b1c531d208721e104343dfbc607": "374ee91aeabee48013d2f090571752ec5081356f",
|
||||
@@ -92865,6 +93239,8 @@
|
||||
"8b85ec04bbc2ecb403e2bca380dbbb08": "c6578caffb1a57f6c18979dc596f3fb9cb986706",
|
||||
"acb87b8d453644b45c7fc8c8247744f5": "1fbd073bbd6cb906a0c0678767fab81feb552173",
|
||||
"b15266f06fa290f3f444302a74890d9b": "62a877bfffb3e690044520f52120c5cd48b97545",
|
||||
"cf10b154f2e006a9740d7653cfc47cab": "28c7616cd02e4286f9b4c1c4a8b8850832b49fcb",
|
||||
"4fe4f6800076ea3d897d4285653447bd": "d4aec4efe1431e56fe52d83baf9118542c525255",
|
||||
"e9c4288eab8885a1e6ae7504a4736115": "15d52de01320d9b954e03b4c2e71ec75fd301bbb",
|
||||
"aa2fb251814bd971b2b9874ab0971b3f": "0e247123b9d3204784eeadb4629b9d35b9dfd984",
|
||||
"ffcbcbce32223a152753d30766ad6215": "582dd1706391f6f0161ad3486ae75a04fb0f7d5b",
|
||||
@@ -92873,6 +93249,8 @@
|
||||
"0246740371010333385665dfeb7cd0ec": "1acd01c2c03424a78b32c9440f4d890fb1104815",
|
||||
"5ee871d5600eb9b5a22989c295f902a5": "200d59076dfef36db061d6d7d21d80021cab1237",
|
||||
"8ca256a832e83c875f5432b3dee8a36f": "6765a91a42fed68a807325bf62a728e5ac5d622f",
|
||||
"8535c40c6cce978623a3e06a38e3a0fd": "72ecfde5f58c5993765a6ef5b8866c4777cc4ade",
|
||||
"907a03706a196b0da832ddab204264f2": "4f05efec7af0829f43aa3cac18a30ae2a33ded88",
|
||||
"1f118b8735fcf40c20b38c3184eebfd9": "e6c0050b3c67ee26198488fbbe4a5d019c15b628",
|
||||
"a1d3c0e5a40f163f4fb00a5e0774c63c": "7fbbedcc7a1ae00414a4e9e967109cc78be1fe3b",
|
||||
"9bef639b7426ef6948602a12b33522a8": "483a17ff25b68a8f18cae691da99f16beefbe370",
|
||||
@@ -92891,8 +93269,24 @@
|
||||
"5b5dd2bc68764c7204dc4fe69118f2a4": "2a15dfa682df1ff841e2092348aa6a2460e40810",
|
||||
"4e10a27e6b3ceac0b3e2df4fadc48bb4": "723b0c61428321b0aca4c43fcd91406807d4f815",
|
||||
"77b5b2d0c1c3a4200a9cda047f74f957": "fefcb49cb13ea191d2c87b406c141a957020432c",
|
||||
"229cf38617d6669286b5d1a48906aa53": "3c6b523e5432a892a0c284d9ba2593919b0173b7",
|
||||
"4b945ee2b52c49c397d368dc21fa42dc": "0e2ee74d1f9ebc3a6faf9dbaebbacc2ff053f4df",
|
||||
"b56eb507fac5ac64a7079514c02b8ca7": "cb0d4276f9947762af0841a8af75efa6cbe9109c",
|
||||
"b8f058ec01942f596c890a060a32f08b": "35910b67070342cdd6ec4d68eb2e56b39d350543",
|
||||
"9338b9a25372178b4ecbf0215697e9be": "ca149058af89d8f612aaa529661e8267d9569875",
|
||||
"9f46187238e838a602b358705a9b813b": "be39a049af0b8ab0c2168ad6d8cf636e15ae0dd2",
|
||||
"1cbf28d65b0d6fe727b571d3e46871b8": "c8eb9c1926baad8bbba25f97be54abae233fe715",
|
||||
"480b029f6c357fb683a6720e2b78d990": "4abe45e59dc9286321a115c76c31cc7fe85e58d5",
|
||||
"23a5e91beb2072f48e1011e7a9b6e901": "03c8b0d3ebeb0ecdc7f594ba6f7242a6f6e4d564",
|
||||
"669f55ffa59d7b754ab11f96c42f206f": "705d20d39a910d58a070fb86780ac58c8007591c",
|
||||
"b79725bff4fecb48d68ad575e13950d1": "276d984150c2fd2fb5ba287f2e5ceb7262dc5a95",
|
||||
"b3e6aa12e24e59cad71d1b7d851a2572": "268f43cd946eea999c62f63a24eb00cb2fdc342c",
|
||||
"8fbeeb5c09477bcaf614087003df61a4": "808b7b46bfb033c7fe4d94d0dbf5a271de30dedc",
|
||||
"b0bdec53b1c50873ba45539565f1327c": "a848aad1840c7d85bfcdd552521a7181b00331cc",
|
||||
"ec6b58f723279afe732b7f9660acf27d": "9b2704655a893ff1675d28df4bd9ffc9e15d3dd5",
|
||||
"dc1aa189468255e644e44b99ad7da49c": "84d422b53547271e3a07342704a05ef481db3f99",
|
||||
"fc90330915e7c494898615eb58689d68": "2d327e78832edd67ca3909c25b8c8c839637a1ed",
|
||||
"c4abdbe2a64c2ef06b6b659f32ea883f": "0a42a4816c89447b16e1f3245409591efea98a4a",
|
||||
"366fba6185c7abb4431ae7e8a1041a08": "72ba464da01bd6d3a91b8d9997d5ac14b6f47aad",
|
||||
"cf01b762bcc96591dbd27c236cc3b1bd": "85febd34bcb166fc3326b5e5e4e80e157b660a08",
|
||||
"befc5553a0a88cb989668b42d83418d7": "cbcd424510435a04e9041967a13781fd19b0f2c4",
|
||||
@@ -92904,6 +93298,7 @@
|
||||
"cd43b9f8ec8c742fca150f9666da47a0": "f72ebcb3ad771321e36cacb49779dca6f2b4db9e",
|
||||
"034527d42a96d0f39977cb85c6a8f2d8": "fcfbbb25e06f58d13e762b02bfd468c834d98fc8",
|
||||
"ee44560f34033efa3bb47b3e0aac1772": "7b03befac4fbcef8c649048fa3ff5d095fd48dd3",
|
||||
"b956c537e7b6b85ffa5c3493b1490d8a": "8e14e85c645187504ec9d162b3ea614a0c421d32",
|
||||
"3f2476d9ff29a06cf9fb85d52302222a": "58807f32c413a0c9db6deb0365f2fac9518e7c86",
|
||||
"2b199deeccab1042fb02b46c47c2a8d0": "ee7dc2eb87e5a75564382efcd95d13554d3835ba",
|
||||
"4229d5532a206aabe7e1fa11a7d8447e": "1ee93623406dc61b50ccb41a97bae769ea15cef2",
|
||||
@@ -92978,6 +93373,7 @@
|
||||
"7844c637dc246ec5f0e760ea33475073": "2f5ac8921b7cba56b02122ef772f5f11bbf6d8a2",
|
||||
"37ce488ec574ba351c2dcf90a13d8fed": "b624812e3aa0ef2f75847f47907296e1f370cecd",
|
||||
"03336a2165522a9493190e3873beebbd": "f99a13464a4dae347628f0ebb320e767e48e3a96",
|
||||
"1164ae723c9181698cc41dde6a341132": "8a799c6615702aac72016b784e30ea1abd3e197b",
|
||||
"05e1d1a0c8ecd45537a1d52ab925d110": "0f25848f73705328ca03b02905e95e3a5d087d8c",
|
||||
"18207ca5b15ba7d05742dca8399d30c6": "8ed9fb83d8e4d73217d347e3b7965cb640cb8395",
|
||||
"df976d4c51ac403796e2f51643617f92": "5109af30336443dd3107190b08dfbe8de623445b",
|
||||
@@ -109507,6 +109903,47 @@
|
||||
"no-save.png": [
|
||||
"7b0bb79d38c573648de218645c6fb16449e156e0"
|
||||
],
|
||||
"cas.glsl": [
|
||||
"b478ce9d1343b8dd201c045f010bd1b64ba158ae",
|
||||
"005cecf1a5e20b05407d55d0aad22cf81ad66c31",
|
||||
"cb0d4276f9947762af0841a8af75efa6cbe9109c"
|
||||
],
|
||||
"convert.glsl": [
|
||||
"32777e258030ad9559864d9f4273d515d65f728f",
|
||||
"53ff273e335432fdbbff9da2762e229ec2bd5078",
|
||||
"35910b67070342cdd6ec4d68eb2e56b39d350543",
|
||||
"705d20d39a910d58a070fb86780ac58c8007591c"
|
||||
],
|
||||
"imgui.glsl": [
|
||||
"04bfcabf518320593dcda8198475c7f39295ef1f",
|
||||
"b8d20aa6884878ba72c080d3f2107e09606963d3",
|
||||
"ca149058af89d8f612aaa529661e8267d9569875",
|
||||
"276d984150c2fd2fb5ba287f2e5ceb7262dc5a95"
|
||||
],
|
||||
"interlace.glsl": [
|
||||
"d6209a8b3c4681823b1f0b7d0648c819ec72e2ad",
|
||||
"d5ba24ba836c418f7f2d9d8b44bd337baa9e45a3",
|
||||
"be39a049af0b8ab0c2168ad6d8cf636e15ae0dd2",
|
||||
"268f43cd946eea999c62f63a24eb00cb2fdc342c"
|
||||
],
|
||||
"merge.glsl": [
|
||||
"7f476bffdc19d7ba2806eef40c2e8e40bdf0896c",
|
||||
"e84aa516874350f414e95d3891ce480fe2958aae",
|
||||
"c8eb9c1926baad8bbba25f97be54abae233fe715",
|
||||
"808b7b46bfb033c7fe4d94d0dbf5a271de30dedc"
|
||||
],
|
||||
"present.glsl": [
|
||||
"ca7a974714111895bbf03360078ea1008694c52e",
|
||||
"0e22e330e10f31d7e7d7db00966cd48d1c5c6dce",
|
||||
"4abe45e59dc9286321a115c76c31cc7fe85e58d5",
|
||||
"a848aad1840c7d85bfcdd552521a7181b00331cc"
|
||||
],
|
||||
"shadeboost.glsl": [
|
||||
"511dc6bb2f81d0ad61fe46c6e91dce8b344fd934",
|
||||
"bef69d202c6e21f2ec0d6930e439a9498642ba6b",
|
||||
"03c8b0d3ebeb0ecdc7f594ba6f7242a6f6e4d564",
|
||||
"9b2704655a893ff1675d28df4bd9ffc9e15d3dd5"
|
||||
],
|
||||
"placeholder.png": [
|
||||
"25e41433147face77af96fecac4519ed11ae8072"
|
||||
],
|
||||
@@ -109722,6 +110159,12 @@
|
||||
"cbf_zh-Hant-TW.bcfnt": [
|
||||
"62a877bfffb3e690044520f52120c5cd48b97545"
|
||||
],
|
||||
"EOS.ROM": [
|
||||
"28c7616cd02e4286f9b4c1c4a8b8850832b49fcb"
|
||||
],
|
||||
"WRITER.ROM": [
|
||||
"d4aec4efe1431e56fe52d83baf9118542c525255"
|
||||
],
|
||||
"COPYMATE.ROM": [
|
||||
"15d52de01320d9b954e03b4c2e71ec75fd301bbb"
|
||||
],
|
||||
@@ -109746,6 +110189,12 @@
|
||||
"CPC6128.ROM.SE": [
|
||||
"6765a91a42fed68a807325bf62a728e5ac5d622f"
|
||||
],
|
||||
"enNextZX.rom": [
|
||||
"72ecfde5f58c5993765a6ef5b8866c4777cc4ade"
|
||||
],
|
||||
"enNxtmmc.rom": [
|
||||
"4f05efec7af0829f43aa3cac18a30ae2a33ded88"
|
||||
],
|
||||
"codehandler.bin": [
|
||||
"e6c0050b3c67ee26198488fbbe4a5d019c15b628",
|
||||
"63e0d5b58d41fccf0853e46e7ab2f25262d2db5d",
|
||||
@@ -109799,12 +110248,21 @@
|
||||
"wqy_12pt.bdf": [
|
||||
"fefcb49cb13ea191d2c87b406c141a957020432c"
|
||||
],
|
||||
"psvita_games.db": [
|
||||
"3c6b523e5432a892a0c284d9ba2593919b0173b7"
|
||||
],
|
||||
"games.db": [
|
||||
"0e2ee74d1f9ebc3a6faf9dbaebbacc2ff053f4df"
|
||||
],
|
||||
"136032.101.e3": [
|
||||
"84d422b53547271e3a07342704a05ef481db3f99"
|
||||
],
|
||||
"136032.102.e5": [
|
||||
"2d327e78832edd67ca3909c25b8c8c839637a1ed"
|
||||
],
|
||||
"136032.103.f7": [
|
||||
"0a42a4816c89447b16e1f3245409591efea98a4a"
|
||||
],
|
||||
"136032.104.f5": [
|
||||
"72ba464da01bd6d3a91b8d9997d5ac14b6f47aad"
|
||||
],
|
||||
@@ -109835,6 +110293,9 @@
|
||||
"Master.dsk": [
|
||||
"7b03befac4fbcef8c649048fa3ff5d095fd48dd3"
|
||||
],
|
||||
"apple2e-enh-kb.rom": [
|
||||
"8e14e85c645187504ec9d162b3ea614a0c421d32"
|
||||
],
|
||||
"cubetxt1.dat": [
|
||||
"58807f32c413a0c9db6deb0365f2fac9518e7c86"
|
||||
],
|
||||
@@ -110028,6 +110489,9 @@
|
||||
"ppge_atlas.meta": [
|
||||
"f99a13464a4dae347628f0ebb320e767e48e3a96"
|
||||
],
|
||||
"prboom-plus.wad": [
|
||||
"8a799c6615702aac72016b784e30ea1abd3e197b"
|
||||
],
|
||||
"dip.cfg": [
|
||||
"0f25848f73705328ca03b02905e95e3a5d087d8c"
|
||||
],
|
||||
@@ -120282,6 +120746,9 @@
|
||||
"136032.107.b2": [
|
||||
"72ba464da01bd6d3a91b8d9997d5ac14b6f47aad"
|
||||
],
|
||||
"apple2e-video.rom": [
|
||||
"7060de104046736529c1e8a687a0dd7b84f8c51b"
|
||||
],
|
||||
"prism_failsafe.rom": [
|
||||
"d020440638aff4d39467128413ef795677be9c23"
|
||||
],
|
||||
@@ -127946,6 +128413,20 @@
|
||||
"2c7a1b2a": "8dba66121f3bbc4b2bdf67722ef4c2b6b6b23ee6",
|
||||
"d766f908": "c54f04b63ac6f04e0a0944ef260b5497e4494dbd",
|
||||
"6e8b2b47": "7b0bb79d38c573648de218645c6fb16449e156e0",
|
||||
"ce9e57e4": "b478ce9d1343b8dd201c045f010bd1b64ba158ae",
|
||||
"38998f1a": "32777e258030ad9559864d9f4273d515d65f728f",
|
||||
"b9848dc2": "04bfcabf518320593dcda8198475c7f39295ef1f",
|
||||
"43dd2e9e": "d6209a8b3c4681823b1f0b7d0648c819ec72e2ad",
|
||||
"f1b5eedb": "7f476bffdc19d7ba2806eef40c2e8e40bdf0896c",
|
||||
"7f2bb4e3": "ca7a974714111895bbf03360078ea1008694c52e",
|
||||
"30ec9e5f": "511dc6bb2f81d0ad61fe46c6e91dce8b344fd934",
|
||||
"e00e7479": "005cecf1a5e20b05407d55d0aad22cf81ad66c31",
|
||||
"df5810f9": "53ff273e335432fdbbff9da2762e229ec2bd5078",
|
||||
"1b5ae2e5": "b8d20aa6884878ba72c080d3f2107e09606963d3",
|
||||
"21dc5ffb": "d5ba24ba836c418f7f2d9d8b44bd337baa9e45a3",
|
||||
"4d559151": "e84aa516874350f414e95d3891ce480fe2958aae",
|
||||
"980f007e": "0e22e330e10f31d7e7d7db00966cd48d1c5c6dce",
|
||||
"e5a3fed2": "bef69d202c6e21f2ec0d6930e439a9498642ba6b",
|
||||
"9e4fd72a": "25e41433147face77af96fecac4519ed11ae8072",
|
||||
"15304b4e": "84b000485929698392676e8e7915bfcce15291ee",
|
||||
"156472ad": "374ee91aeabee48013d2f090571752ec5081356f",
|
||||
@@ -128023,6 +128504,8 @@
|
||||
"d60e70f2": "c6578caffb1a57f6c18979dc596f3fb9cb986706",
|
||||
"90386ab3": "1fbd073bbd6cb906a0c0678767fab81feb552173",
|
||||
"bb56de24": "62a877bfffb3e690044520f52120c5cd48b97545",
|
||||
"ef6403c5": "28c7616cd02e4286f9b4c1c4a8b8850832b49fcb",
|
||||
"58d86a2a": "d4aec4efe1431e56fe52d83baf9118542c525255",
|
||||
"fc7f544e": "15d52de01320d9b954e03b4c2e71ec75fd301bbb",
|
||||
"37f1bb31": "0e247123b9d3204784eeadb4629b9d35b9dfd984",
|
||||
"6e28fa67": "582dd1706391f6f0161ad3486ae75a04fb0f7d5b",
|
||||
@@ -128031,6 +128514,8 @@
|
||||
"2fa2e7d6": "1acd01c2c03424a78b32c9440f4d890fb1104815",
|
||||
"1574923b": "200d59076dfef36db061d6d7d21d80021cab1237",
|
||||
"588b5540": "6765a91a42fed68a807325bf62a728e5ac5d622f",
|
||||
"6d9951f0": "72ecfde5f58c5993765a6ef5b8866c4777cc4ade",
|
||||
"5a443736": "4f05efec7af0829f43aa3cac18a30ae2a33ded88",
|
||||
"ba8dfa56": "e6c0050b3c67ee26198488fbbe4a5d019c15b628",
|
||||
"9ac7f0c7": "7fbbedcc7a1ae00414a4e9e967109cc78be1fe3b",
|
||||
"6fe1f772": "483a17ff25b68a8f18cae691da99f16beefbe370",
|
||||
@@ -128049,8 +128534,24 @@
|
||||
"b7b59533": "2a15dfa682df1ff841e2092348aa6a2460e40810",
|
||||
"0a6dccec": "723b0c61428321b0aca4c43fcd91406807d4f815",
|
||||
"35ee85c3": "fefcb49cb13ea191d2c87b406c141a957020432c",
|
||||
"69787db6": "3c6b523e5432a892a0c284d9ba2593919b0173b7",
|
||||
"c9a52a37": "0e2ee74d1f9ebc3a6faf9dbaebbacc2ff053f4df",
|
||||
"13eed5a5": "cb0d4276f9947762af0841a8af75efa6cbe9109c",
|
||||
"bb25c312": "35910b67070342cdd6ec4d68eb2e56b39d350543",
|
||||
"342d0e13": "ca149058af89d8f612aaa529661e8267d9569875",
|
||||
"3198c556": "be39a049af0b8ab0c2168ad6d8cf636e15ae0dd2",
|
||||
"ae991348": "c8eb9c1926baad8bbba25f97be54abae233fe715",
|
||||
"67a7b03b": "4abe45e59dc9286321a115c76c31cc7fe85e58d5",
|
||||
"54c435f2": "03c8b0d3ebeb0ecdc7f594ba6f7242a6f6e4d564",
|
||||
"fd02bb00": "705d20d39a910d58a070fb86780ac58c8007591c",
|
||||
"c9511683": "276d984150c2fd2fb5ba287f2e5ceb7262dc5a95",
|
||||
"3317d2fb": "268f43cd946eea999c62f63a24eb00cb2fdc342c",
|
||||
"51cef730": "808b7b46bfb033c7fe4d94d0dbf5a271de30dedc",
|
||||
"50fb46e4": "a848aad1840c7d85bfcdd552521a7181b00331cc",
|
||||
"69dc25d7": "9b2704655a893ff1675d28df4bd9ffc9e15d3dd5",
|
||||
"7e84972a": "84d422b53547271e3a07342704a05ef481db3f99",
|
||||
"ebf1e0ae": "2d327e78832edd67ca3909c25b8c8c839637a1ed",
|
||||
"92d6a0b4": "0a42a4816c89447b16e1f3245409591efea98a4a",
|
||||
"7a29dc07": "72ba464da01bd6d3a91b8d9997d5ac14b6f47aad",
|
||||
"79021d3c": "85febd34bcb166fc3326b5e5e4e80e157b660a08",
|
||||
"76ee86c4": "cbcd424510435a04e9041967a13781fd19b0f2c4",
|
||||
@@ -128062,6 +128563,7 @@
|
||||
"066d1348": "f72ebcb3ad771321e36cacb49779dca6f2b4db9e",
|
||||
"8031ff02": "fcfbbb25e06f58d13e762b02bfd468c834d98fc8",
|
||||
"18c0ff3e": "7b03befac4fbcef8c649048fa3ff5d095fd48dd3",
|
||||
"c506efb9": "8e14e85c645187504ec9d162b3ea614a0c421d32",
|
||||
"84e948df": "58807f32c413a0c9db6deb0365f2fac9518e7c86",
|
||||
"bf8e13c9": "ee7dc2eb87e5a75564382efcd95d13554d3835ba",
|
||||
"7b91c5d2": "1ee93623406dc61b50ccb41a97bae769ea15cef2",
|
||||
@@ -128136,6 +128638,7 @@
|
||||
"0e016ecf": "2f5ac8921b7cba56b02122ef772f5f11bbf6d8a2",
|
||||
"eef26072": "b624812e3aa0ef2f75847f47907296e1f370cecd",
|
||||
"c6bebfc6": "f99a13464a4dae347628f0ebb320e767e48e3a96",
|
||||
"a4626dfa": "8a799c6615702aac72016b784e30ea1abd3e197b",
|
||||
"84f47dc9": "0f25848f73705328ca03b02905e95e3a5d087d8c",
|
||||
"79b7fdc4": "8ed9fb83d8e4d73217d347e3b7965cb640cb8395",
|
||||
"be691779": "5109af30336443dd3107190b08dfbe8de623445b",
|
||||
@@ -136269,6 +136772,20 @@
|
||||
"c749cd9513bd345b9f12ff46eac0ffbf4e54c0b0884921df97ca8297396e3fea": "8dba66121f3bbc4b2bdf67722ef4c2b6b6b23ee6",
|
||||
"dfd8035387a463722ad07af3c91934e0a685f2afa57e31d305f0602656d1edb1": "c54f04b63ac6f04e0a0944ef260b5497e4494dbd",
|
||||
"ab829598e15b771112130cbafbd982736400690c11e3d7c81e3fc8c582c24f47": "7b0bb79d38c573648de218645c6fb16449e156e0",
|
||||
"3d5b9cef750ea8bedceef43c4c52215e8280abb81b5b8fa002007bb3f97f0506": "b478ce9d1343b8dd201c045f010bd1b64ba158ae",
|
||||
"4ac385f0e38ee2c3a3f7014db86bd59927a5d4e4f76f24df9b8f8b3d97142390": "32777e258030ad9559864d9f4273d515d65f728f",
|
||||
"25978439553bbd959fe4eb5d03b739a3d697348458a7bac3df48556148f48027": "04bfcabf518320593dcda8198475c7f39295ef1f",
|
||||
"ff7e27fa41f33ec5d4a86b2a48a622dbcd8dd0ae37f8afe306fdd182a7aa8ec1": "d6209a8b3c4681823b1f0b7d0648c819ec72e2ad",
|
||||
"6cd2bc21890426b5430d44b28a89289bcc6fc9ecd632bb3a8eafb6c8b818499c": "7f476bffdc19d7ba2806eef40c2e8e40bdf0896c",
|
||||
"27ffa5fdf1634f7be2734d2eff2d9dce0cca71c2832685e0a682388731dc5c60": "ca7a974714111895bbf03360078ea1008694c52e",
|
||||
"e7297a2e333bb1882bcf82d2a109a2ab033715cce1bba4934f42ec68370f0077": "511dc6bb2f81d0ad61fe46c6e91dce8b344fd934",
|
||||
"ea3f65c6d1b18abe23b42a3d9ddf48d787df287feef6cfac52ca6109d8852d97": "005cecf1a5e20b05407d55d0aad22cf81ad66c31",
|
||||
"e8213fa871bebc8fc883be3bbccf111c8aec1f84063e05a24850efc735312e08": "53ff273e335432fdbbff9da2762e229ec2bd5078",
|
||||
"372e33cccb520a987983dd897c51c6b7e609f16badd67d056a95799a7f768566": "b8d20aa6884878ba72c080d3f2107e09606963d3",
|
||||
"af535e4b871b188957a7169ed883f6f8a209f0908e5b7aff17755605c8d07857": "d5ba24ba836c418f7f2d9d8b44bd337baa9e45a3",
|
||||
"3c0eb665db06c289841829a6aa4716e46ce5ae8e08005a82ad4f3020bd8406e7": "e84aa516874350f414e95d3891ce480fe2958aae",
|
||||
"88d9f9b08f3a62cfd77fdf366c2a1ecca7924c407a3eabb1c1df68cfca2ee2d1": "0e22e330e10f31d7e7d7db00966cd48d1c5c6dce",
|
||||
"31ab20c5617e0bdd3e1afaf9cac2212586f94433f176ca30810a1fecf3f338e8": "bef69d202c6e21f2ec0d6930e439a9498642ba6b",
|
||||
"0a42ffa04c5895647026f4cbbd30cae3e1455bd6e36d069ae83142e0c229c74b": "25e41433147face77af96fecac4519ed11ae8072",
|
||||
"e740b08eb0f7bd074a0a7e6033f5ab9292fb601157e64aacbd9fec6174020d42": "84b000485929698392676e8e7915bfcce15291ee",
|
||||
"92848f15d5eeea9fdfe87e272e4c9ea32f876b3665f5b27ef059711b7c757502": "374ee91aeabee48013d2f090571752ec5081356f",
|
||||
@@ -136346,6 +136863,8 @@
|
||||
"5e39d040be8e40554009b4ff29194f7d70c468a7c9c445c0be06320539851125": "c6578caffb1a57f6c18979dc596f3fb9cb986706",
|
||||
"5d786f4ef7e59e4ee20c73803753e455ebf812046a930f5ad1437839329e8aca": "1fbd073bbd6cb906a0c0678767fab81feb552173",
|
||||
"dbefcc65df7e7e301af3fead2282626574b67bc7d838f45a6c618b74793ac7bc": "62a877bfffb3e690044520f52120c5cd48b97545",
|
||||
"a49928fbac56380917134b54961ece2e90073022f3e04a6023d26cdbbd9c3356": "28c7616cd02e4286f9b4c1c4a8b8850832b49fcb",
|
||||
"3b17255d2679d11f79e6cacda86de5f6bc9bb5cddf78cbddc651af03b237317d": "d4aec4efe1431e56fe52d83baf9118542c525255",
|
||||
"f68b6a88c51d63e77893d102453df550da96227eb192dd1b970ca3c3abc23b0c": "15d52de01320d9b954e03b4c2e71ec75fd301bbb",
|
||||
"7d2c4d6e2421991742c1dc9d75afd22b7d450b9ca4852462610df5af85f6ab1c": "0e247123b9d3204784eeadb4629b9d35b9dfd984",
|
||||
"3053eef5f6132188facb0c27cc67e0be2eeaebc1f9c8c10b3859731550dec5c3": "582dd1706391f6f0161ad3486ae75a04fb0f7d5b",
|
||||
@@ -136354,6 +136873,8 @@
|
||||
"49c5b2da99bf3230dec3e4bfbb136609ae5f8d250d8920be0ebda1e5a256f88a": "1acd01c2c03424a78b32c9440f4d890fb1104815",
|
||||
"8ec2639be145d242d18c02f5ed9eaa52c7d4c40b49dc672755200c3be701abf7": "200d59076dfef36db061d6d7d21d80021cab1237",
|
||||
"456ced147bf5a3a11fe70971f56c1a215e85808fa86dd7d8610a73b3e9b6148e": "6765a91a42fed68a807325bf62a728e5ac5d622f",
|
||||
"dd901acd306794ad34f3131ad1df54b6f4de5527ad1b2aa42f82e417f93f17a5": "72ecfde5f58c5993765a6ef5b8866c4777cc4ade",
|
||||
"ded2038d78f57b4fd7e05df0330064f661c221f7b06d8cd2bddee1ff6062f019": "4f05efec7af0829f43aa3cac18a30ae2a33ded88",
|
||||
"2b2ff0716aeb9b806cc61181e559041312957f25f04c435bd7da80a78917b33b": "e6c0050b3c67ee26198488fbbe4a5d019c15b628",
|
||||
"38f9f59d505bc4e2d86b0196706195f33ad72b7fe9d029cf263072cde19d044f": "7fbbedcc7a1ae00414a4e9e967109cc78be1fe3b",
|
||||
"4ad991be2b0aa305f09b90a79fc50f57833b30b008890b5ef1336cc3d9d0bae0": "483a17ff25b68a8f18cae691da99f16beefbe370",
|
||||
@@ -136372,8 +136893,24 @@
|
||||
"890991d60c3aeea43058d0c29dc72fcc428d2670e38c1d94d5d1bfae03437a8f": "2a15dfa682df1ff841e2092348aa6a2460e40810",
|
||||
"af64766bf3df3336c76b04f2d07749812373790b9f20ed59c0faf7cc8a5241ad": "723b0c61428321b0aca4c43fcd91406807d4f815",
|
||||
"ead9acd03c8d749ddde899afed49ba4b50e6ca14585a3091bc23a7074902cfe0": "fefcb49cb13ea191d2c87b406c141a957020432c",
|
||||
"ca56a424e87cf4c257dcd3810567e62cb10767096b6a2378e69b07040c5fbc13": "3c6b523e5432a892a0c284d9ba2593919b0173b7",
|
||||
"86883a0199a129b900f4a5c7ade6245b7e9d1399ec3c08d1fbf1838c01722e8e": "0e2ee74d1f9ebc3a6faf9dbaebbacc2ff053f4df",
|
||||
"53e5ddc6825ecde7b502acb5fae3a173ba6696ec5b8bb7445f378f7b0ad1beb8": "cb0d4276f9947762af0841a8af75efa6cbe9109c",
|
||||
"fcb651c2ff39102a33ece3716579e3aee7d8b92d4700e52b56b6cf14baa8b8d1": "35910b67070342cdd6ec4d68eb2e56b39d350543",
|
||||
"ea82ce9731de4a0b5af3e66e47e048af569e0e98c5739b32f268fb54caa7603a": "ca149058af89d8f612aaa529661e8267d9569875",
|
||||
"15a58d9f7442f24e86484f4a7f0c10570b434ef68e8fb2d5c38513c0016d1e64": "be39a049af0b8ab0c2168ad6d8cf636e15ae0dd2",
|
||||
"654281fb002aa1a086ee979d694e9d6443864bdc8740d20188baf8e125e386fa": "c8eb9c1926baad8bbba25f97be54abae233fe715",
|
||||
"e31c519e6b22683cebefc5c2358b2b7ddad10964a1e478fa3eba01f3ab5adb17": "4abe45e59dc9286321a115c76c31cc7fe85e58d5",
|
||||
"15ff418a0fc877886015cc781c9c3b0810a870bee5803d76741bbcbcc540b9e5": "03c8b0d3ebeb0ecdc7f594ba6f7242a6f6e4d564",
|
||||
"ac3d88c299e304faf76cda2b305510d5a6c19c06319e53ee54fdc18b028a860f": "705d20d39a910d58a070fb86780ac58c8007591c",
|
||||
"2d765ffb2bef04082138e29e8ba7f7cc1c788c6415226d1aab1b7eb5bbd0431f": "276d984150c2fd2fb5ba287f2e5ceb7262dc5a95",
|
||||
"710e9e43ba7115e80b3e34c18072d838ef59f08f096204a7c5c9bf8704047b7f": "268f43cd946eea999c62f63a24eb00cb2fdc342c",
|
||||
"2e6883d4304c5de25c464a9fd97fcd2f642d8d2af2db9c2b13882e67f0f35b93": "808b7b46bfb033c7fe4d94d0dbf5a271de30dedc",
|
||||
"2db47ffca9510468e37717266838576f96dccd9ed6b7f00c0a721c9868338b19": "a848aad1840c7d85bfcdd552521a7181b00331cc",
|
||||
"27ab08e76e08fa8a1023b076f3e6c23bc6841732658942f30cea634394f40729": "9b2704655a893ff1675d28df4bd9ffc9e15d3dd5",
|
||||
"d7626affff7dfc0a8782e0894770258ea572d0f2d9859690efbc8ce018cb36bc": "84d422b53547271e3a07342704a05ef481db3f99",
|
||||
"81fb611f7dc9d531720836f31e5aff1cc5466013d0afb7ab7f947cb5b7520504": "2d327e78832edd67ca3909c25b8c8c839637a1ed",
|
||||
"c770a3ae305c3420292516dbd86373f67798983c74754d2cc988de6ddf6ec51f": "0a42a4816c89447b16e1f3245409591efea98a4a",
|
||||
"e9c94dc577b050e856e1c7de90c4d034fa3f7eca7c4b887adb7b47115c466cfa": "72ba464da01bd6d3a91b8d9997d5ac14b6f47aad",
|
||||
"3d5bd91c33ee983e795c81ab7683d7591e73ed2d9947c7e8cec3bded31b6b686": "85febd34bcb166fc3326b5e5e4e80e157b660a08",
|
||||
"0a417e3f3bdd879ddddd22e93d0093b5d4810ce0e040b45447709ad98d0a6029": "cbcd424510435a04e9041967a13781fd19b0f2c4",
|
||||
@@ -136385,6 +136922,7 @@
|
||||
"c72a36bbd471daf5d12df9f7b85773771583ec960ff9ca17e66d2f7b22e5c8c3": "f72ebcb3ad771321e36cacb49779dca6f2b4db9e",
|
||||
"fcf442b26c492253dfb8d2146e215b7b84b3ba87443face9c94a1e9474aa3ca4": "fcfbbb25e06f58d13e762b02bfd468c834d98fc8",
|
||||
"0add32bcbd0e5b350437fa9d138b3c232368e36d8009852479fdb09d9db31113": "7b03befac4fbcef8c649048fa3ff5d095fd48dd3",
|
||||
"a1989da84ea4381d309e7e08783771f884e913236b9bcc71c3d649aacf76537a": "8e14e85c645187504ec9d162b3ea614a0c421d32",
|
||||
"2a0bc26ac4a8cdcbe7a145c9b1868a87ecb4335e9787f2f1e5713c965372df2b": "58807f32c413a0c9db6deb0365f2fac9518e7c86",
|
||||
"6604a1dcc264e8b8e98f036a8bc35579e9b90b92eccbc4d7c1effee9785d1580": "ee7dc2eb87e5a75564382efcd95d13554d3835ba",
|
||||
"fcfc9762cd4cfad42feb12d975929de86851b216d4491252c701527e22b55539": "1ee93623406dc61b50ccb41a97bae769ea15cef2",
|
||||
@@ -136459,6 +136997,7 @@
|
||||
"f68a569f71fc090cec61bc5f699d0553dca7c5d012166709e74fc6c72568fdc2": "2f5ac8921b7cba56b02122ef772f5f11bbf6d8a2",
|
||||
"49f94f7bc9fc605cbf60457937429e3c8499e515d8164b7dd7cd0345844fc86a": "b624812e3aa0ef2f75847f47907296e1f370cecd",
|
||||
"e3e8ab044b973137c9864f473f345849ecb4c0a9a3234eaba399dfa16c5f06f0": "f99a13464a4dae347628f0ebb320e767e48e3a96",
|
||||
"29e6e18023cf39319f9984107f5f0f796b2593b1c3a55fc79adf3ae12498a6ce": "8a799c6615702aac72016b784e30ea1abd3e197b",
|
||||
"0406c436e54064b938ffe855e1ad0abb362d67f009781a5dce79b044bcd68115": "0f25848f73705328ca03b02905e95e3a5d087d8c",
|
||||
"a60757b92f2f3df9447aa50e004aabe9f4cb0845bb037afca118ff89b5913ae3": "8ed9fb83d8e4d73217d347e3b7965cb640cb8395",
|
||||
"3aa539a472b4a7ffbf4329356d0e3c0b17893cedc6044408ca22988d7930ecc4": "5109af30336443dd3107190b08dfbe8de623445b",
|
||||
@@ -145883,6 +146422,48 @@
|
||||
"nxengine/tilekey.dat": [
|
||||
"74c14b15dbc2f36c81d2ad9cb65e2893298415da"
|
||||
],
|
||||
"pcsx2/resources/shaders/opengl/cas.glsl": [
|
||||
"b478ce9d1343b8dd201c045f010bd1b64ba158ae"
|
||||
],
|
||||
"pcsx2/resources/shaders/opengl/convert.glsl": [
|
||||
"32777e258030ad9559864d9f4273d515d65f728f"
|
||||
],
|
||||
"pcsx2/resources/shaders/opengl/imgui.glsl": [
|
||||
"04bfcabf518320593dcda8198475c7f39295ef1f"
|
||||
],
|
||||
"pcsx2/resources/shaders/opengl/interlace.glsl": [
|
||||
"d6209a8b3c4681823b1f0b7d0648c819ec72e2ad"
|
||||
],
|
||||
"pcsx2/resources/shaders/opengl/merge.glsl": [
|
||||
"7f476bffdc19d7ba2806eef40c2e8e40bdf0896c"
|
||||
],
|
||||
"pcsx2/resources/shaders/opengl/present.glsl": [
|
||||
"ca7a974714111895bbf03360078ea1008694c52e"
|
||||
],
|
||||
"pcsx2/resources/shaders/opengl/shadeboost.glsl": [
|
||||
"511dc6bb2f81d0ad61fe46c6e91dce8b344fd934"
|
||||
],
|
||||
"pcsx2/resources/shaders/vulkan/cas.glsl": [
|
||||
"005cecf1a5e20b05407d55d0aad22cf81ad66c31"
|
||||
],
|
||||
"pcsx2/resources/shaders/vulkan/convert.glsl": [
|
||||
"53ff273e335432fdbbff9da2762e229ec2bd5078"
|
||||
],
|
||||
"pcsx2/resources/shaders/vulkan/imgui.glsl": [
|
||||
"b8d20aa6884878ba72c080d3f2107e09606963d3"
|
||||
],
|
||||
"pcsx2/resources/shaders/vulkan/interlace.glsl": [
|
||||
"d5ba24ba836c418f7f2d9d8b44bd337baa9e45a3"
|
||||
],
|
||||
"pcsx2/resources/shaders/vulkan/merge.glsl": [
|
||||
"e84aa516874350f414e95d3891ce480fe2958aae"
|
||||
],
|
||||
"pcsx2/resources/shaders/vulkan/present.glsl": [
|
||||
"0e22e330e10f31d7e7d7db00966cd48d1c5c6dce"
|
||||
],
|
||||
"pcsx2/resources/shaders/vulkan/shadeboost.glsl": [
|
||||
"bef69d202c6e21f2ec0d6930e439a9498642ba6b"
|
||||
],
|
||||
"BeebFile/6502Tube.rom": [
|
||||
"05980c296e1a7800c4aa21d6bed16323b6d859d5"
|
||||
],
|
||||
@@ -146030,6 +146611,45 @@
|
||||
"ROM/National/CPC6128.ROM.SE": [
|
||||
"6765a91a42fed68a807325bf62a728e5ac5d622f"
|
||||
],
|
||||
"resources/shaders/opengl/cas.glsl": [
|
||||
"cb0d4276f9947762af0841a8af75efa6cbe9109c"
|
||||
],
|
||||
"resources/shaders/opengl/convert.glsl": [
|
||||
"35910b67070342cdd6ec4d68eb2e56b39d350543"
|
||||
],
|
||||
"resources/shaders/opengl/imgui.glsl": [
|
||||
"ca149058af89d8f612aaa529661e8267d9569875"
|
||||
],
|
||||
"resources/shaders/opengl/interlace.glsl": [
|
||||
"be39a049af0b8ab0c2168ad6d8cf636e15ae0dd2"
|
||||
],
|
||||
"resources/shaders/opengl/merge.glsl": [
|
||||
"c8eb9c1926baad8bbba25f97be54abae233fe715"
|
||||
],
|
||||
"resources/shaders/opengl/present.glsl": [
|
||||
"4abe45e59dc9286321a115c76c31cc7fe85e58d5"
|
||||
],
|
||||
"resources/shaders/opengl/shadeboost.glsl": [
|
||||
"03c8b0d3ebeb0ecdc7f594ba6f7242a6f6e4d564"
|
||||
],
|
||||
"resources/shaders/vulkan/convert.glsl": [
|
||||
"705d20d39a910d58a070fb86780ac58c8007591c"
|
||||
],
|
||||
"resources/shaders/vulkan/imgui.glsl": [
|
||||
"276d984150c2fd2fb5ba287f2e5ceb7262dc5a95"
|
||||
],
|
||||
"resources/shaders/vulkan/interlace.glsl": [
|
||||
"268f43cd946eea999c62f63a24eb00cb2fdc342c"
|
||||
],
|
||||
"resources/shaders/vulkan/merge.glsl": [
|
||||
"808b7b46bfb033c7fe4d94d0dbf5a271de30dedc"
|
||||
],
|
||||
"resources/shaders/vulkan/present.glsl": [
|
||||
"a848aad1840c7d85bfcdd552521a7181b00331cc"
|
||||
],
|
||||
"resources/shaders/vulkan/shadeboost.glsl": [
|
||||
"9b2704655a893ff1675d28df4bd9ffc9e15d3dd5"
|
||||
],
|
||||
"roms/108281-001.bin": [
|
||||
"d108bb99cb1a05d808e6e25cc720da24faee9e7c"
|
||||
],
|
||||
@@ -154942,6 +155562,9 @@
|
||||
"SCPU64/pepto-pal.vpl": [
|
||||
"88a2209694f64f7167f239646aedcd0d09dc51bb"
|
||||
],
|
||||
"resources/shaders/vulkan/cas.glsl": [
|
||||
"005cecf1a5e20b05407d55d0aad22cf81ad66c31"
|
||||
],
|
||||
"roms/5429.vbi": [
|
||||
"8060cd4b49052572bb5ec929f8ad21e2addce237"
|
||||
],
|
||||
|
||||
Reference in new issue
Block a user