diff --git a/libretro.cpp b/libretro.cpp index 2e325fae..ad43ddd4 100644 --- a/libretro.cpp +++ b/libretro.cpp @@ -1711,10 +1711,10 @@ static int Load(const char *name, MDFNFILE *fp) static int LoadCD(std::vector *CDInterfaces) { InitCommon(CDInterfaces); - + if (psx_skipbios == 1) BIOSROM->WriteU32(0x6990, 0); - + MDFNGameInfo->GameType = GMT_CDROM; return(1); @@ -2567,7 +2567,7 @@ static void check_variables(bool startup) #endif var.key = option_cpu_overclock; - + if (environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &var) && var.value) { if (strcmp(var.value, "enabled") == 0) @@ -2577,7 +2577,7 @@ static void check_variables(bool startup) } else psx_cpu_overclock = false; - + var.key = option_skip_bios; if (environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &var) && var.value) @@ -2586,8 +2586,8 @@ static void check_variables(bool startup) psx_skipbios = 1; else psx_skipbios = 0; - } - + } + var.key = option_widescreen_hack; if (environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &var) && var.value) @@ -2858,7 +2858,7 @@ static void check_variables(bool startup) display_internal_framerate = false; var.key = option_crop_overscan; - + if (environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &var) && var.value) { if (strcmp(var.value, "enabled") == 0) @@ -3987,7 +3987,7 @@ void retro_set_environment(retro_environment_t cb) static const struct retro_variable vars[] = { #if defined(HAVE_OPENGL) || defined(HAVE_OPENGLES) || defined(HAVE_VULKAN) { option_renderer, "Renderer (restart); " FIRST_RENDERER EXT_RENDERER }, - { option_renderer_software_fb, "Software framebuffer; enabled|disabled" }, + { option_renderer_software_fb, "Software framebuffer; enabled|disabled" }, #endif #ifdef HAVE_VULKAN { option_adaptive_smoothing, "Adaptive smoothing; enabled|disabled" }, @@ -3995,7 +3995,7 @@ void retro_set_environment(retro_environment_t cb) { option_internal_resolution, "Internal GPU resolution; 1x(native)|2x|4x|8x" }, #if defined(HAVE_OPENGL) || defined(HAVE_OPENGLES) // Only used in GL renderer for now. - { option_filter, "Texture filtering; nearest|SABR" }, + { option_filter, "Texture filtering; nearest|SABR|xBR|bilinear|3-point" }, { option_depth, "Internal color depth; dithered 16bpp (native)|32bpp" }, { option_wireframe, "Wireframe mode; disabled|enabled" }, { option_display_vram, "Display full VRAM; disabled|enabled" }, @@ -4006,7 +4006,7 @@ void retro_set_environment(retro_environment_t cb) { option_pgxp_texture, "PGXP perspective correct texturing; disabled|enabled" }, #endif { option_dither_mode, "Dithering pattern; 1x(native)|internal resolution|disabled" }, - { option_scale_dither, "Scale dithering pattern with internal resolution; enabled|disabled" }, + { option_scale_dither, "Scale dithering pattern with internal resolution; enabled|disabled" }, { option_initial_scanline, "Initial scanline; 0|1|2|3|4|5|6|7|8|9|10|10|11|12|13|14|15|16|17|18|19|20|21|22|23|24|25|26|27|28|29|30|31|32|33|34|35|36|37|38|39|40" }, { option_last_scanline, "Last scanline; 239|238|237|236|235|234|232|231|230|229|228|227|226|225|224|223|222|221|220|219|218|217|216|215|214|213|212|211|210" }, { option_initial_scanline_pal, "Initial scanline PAL; 0|1|2|3|4|5|6|7|8|9|10|10|11|12|13|14|15|16|17|18|19|20|21|22|23|24|25|26|27|28|29|30|31|32|33|34|35|36|37|38|39|40" }, @@ -4182,7 +4182,7 @@ void retro_cheat_set(unsigned index, bool enabled, const char * code) const CheatFormatStruct* cf = CheatFormats; char name[256]; MemoryPatch patch; - + //Decode the cheat try { @@ -4192,10 +4192,10 @@ void retro_cheat_set(unsigned index, bool enabled, const char * code) { return; } - + //Generate a name sprintf(name,"cheat_%u",index); - + //Set parameters patch.name=std::string(name); patch.status=enabled; diff --git a/rsx/rsx_lib_gl.cpp b/rsx/rsx_lib_gl.cpp index 8b4cc3d1..5297a8f5 100644 --- a/rsx/rsx_lib_gl.cpp +++ b/rsx/rsx_lib_gl.cpp @@ -34,6 +34,15 @@ #define FILTER_SABR #include "../rustation-libretro/src/shaders/command_fragment.glsl.h" #undef FILTER_SABR +#define FILTER_XBR +#include "../rustation-libretro/src/shaders/command_fragment.glsl.h" +#undef FILTER_XBR +#define FILTER_BILINEAR +#include "../rustation-libretro/src/shaders/command_fragment.glsl.h" +#undef FILTER_BILINEAR +#define FILTER_3POINT +#include "../rustation-libretro/src/shaders/command_fragment.glsl.h" +#undef FILTER_3POINT #include "../rustation-libretro/src/shaders/output_vertex.glsl.h" #include "../rustation-libretro/src/shaders/output_fragment.glsl.h" #include "../rustation-libretro/src/shaders/image_load_vertex.glsl.h" @@ -59,7 +68,10 @@ enum VideoClock { enum FilterMode { FILTER_MODE_NEAREST, - FILTER_MODE_SABR + FILTER_MODE_SABR, + FILTER_MODE_XBR, + FILTER_MODE_BILINEAR, + FILTER_MODE_3POINT }; // Main GPU instance, used to access the VRAM @@ -275,6 +287,12 @@ GlRenderer::GlRenderer(DrawConfig* config) filter = FILTER_MODE_NEAREST; else if (!strcmp(var.value, "SABR")) filter = FILTER_MODE_SABR; + else if (!strcmp(var.value, "xBR")) + filter = FILTER_MODE_XBR; + else if (!strcmp(var.value, "bilinear")) + filter = FILTER_MODE_BILINEAR; + else if (!strcmp(var.value, "3-point")) + filter = FILTER_MODE_3POINT; this->filter_type = filter; } @@ -327,6 +345,24 @@ GlRenderer::GlRenderer(DrawConfig* config) command_fragment_sabr, VERTEX_BUFFER_LEN); break; + case FILTER_MODE_XBR: + command_buffer = GlRenderer::build_buffer( + command_vertex, + command_fragment_xbr, + VERTEX_BUFFER_LEN); + break; + case FILTER_MODE_BILINEAR: + command_buffer = GlRenderer::build_buffer( + command_vertex, + command_fragment_bilinear, + VERTEX_BUFFER_LEN); + break; + case FILTER_MODE_3POINT: + command_buffer = GlRenderer::build_buffer( + command_vertex, + command_fragment_3point, + VERTEX_BUFFER_LEN); + break; case FILTER_MODE_NEAREST: default: command_buffer = GlRenderer::build_buffer( @@ -1137,9 +1173,9 @@ private: public: static RetroGl* getInstance(VideoClock video_clock); static RetroGl* getInstance(); - /* + /* Rust's enums members can contain data. To emulate that, - I'll use a helper struct to save the data. + I'll use a helper struct to save the data. */ GlStateData state_data; GlState state; @@ -1456,7 +1492,7 @@ static bool shim_context_framebuffer_lock(void* data) return RetroGl::getInstance()->context_framebuffer_lock(data); } -static RetroGl* static_renderer = NULL; +static RetroGl* static_renderer = NULL; void rsx_gl_init(void) { @@ -1471,7 +1507,7 @@ bool rsx_gl_open(bool is_pal) void rsx_gl_close(void) { - static_renderer = NULL; + static_renderer = NULL; } void rsx_gl_refresh_variables(void) @@ -1800,14 +1836,14 @@ void rsx_gl_push_quad( exit(EXIT_FAILURE); } - CommandVertex v[4] = + CommandVertex v[4] = { { {p0x, p0y, 0.95, p0w}, /* position */ {(uint8_t) c0, (uint8_t) (c0 >> 8), (uint8_t) (c0 >> 16)}, /* color */ {t0x, t0y}, /* texture_coord */ - {texpage_x, texpage_y}, - {clut_x, clut_y}, + {texpage_x, texpage_y}, + {clut_x, clut_y}, texture_blend_mode, depth_shift, (uint8_t) dither, @@ -1817,8 +1853,8 @@ void rsx_gl_push_quad( {p1x, p1y, 0.95, p1w }, /* position */ {(uint8_t) c1, (uint8_t) (c1 >> 8), (uint8_t) (c1 >> 16)}, /* color */ {t1x, t1y}, /* texture_coord */ - {texpage_x, texpage_y}, - {clut_x, clut_y}, + {texpage_x, texpage_y}, + {clut_x, clut_y}, texture_blend_mode, depth_shift, (uint8_t) dither, @@ -1828,8 +1864,8 @@ void rsx_gl_push_quad( {p2x, p2y, 0.95, p2w }, /* position */ {(uint8_t) c2, (uint8_t) (c2 >> 8), (uint8_t) (c2 >> 16)}, /* color */ {t2x, t2y}, /* texture_coord */ - {texpage_x, texpage_y}, - {clut_x, clut_y}, + {texpage_x, texpage_y}, + {clut_x, clut_y}, texture_blend_mode, depth_shift, (uint8_t) dither, @@ -1839,8 +1875,8 @@ void rsx_gl_push_quad( {p3x, p3y, 0.95, p3w }, /* position */ {(uint8_t) c3, (uint8_t) (c3 >> 8), (uint8_t) (c3 >> 16)}, /* color */ {t3x, t3y}, /* texture_coord */ - {texpage_x, texpage_y}, - {clut_x, clut_y}, + {texpage_x, texpage_y}, + {clut_x, clut_y}, texture_blend_mode, depth_shift, (uint8_t) dither, @@ -1939,14 +1975,14 @@ void rsx_gl_push_triangle( exit(EXIT_FAILURE); } - CommandVertex v[3] = + CommandVertex v[3] = { { {p0x, p0y, 0.95, p0w}, /* position */ {(uint8_t) c0, (uint8_t) (c0 >> 8), (uint8_t) (c0 >> 16)}, /* color */ {t0x, t0y}, /* texture_coord */ - {texpage_x, texpage_y}, - {clut_x, clut_y}, + {texpage_x, texpage_y}, + {clut_x, clut_y}, texture_blend_mode, depth_shift, (uint8_t) dither, @@ -1956,8 +1992,8 @@ void rsx_gl_push_triangle( {p1x, p1y, 0.95, p1w }, /* position */ {(uint8_t) c1, (uint8_t) (c1 >> 8), (uint8_t) (c1 >> 16)}, /* color */ {t1x, t1y}, /* texture_coord */ - {texpage_x, texpage_y}, - {clut_x, clut_y}, + {texpage_x, texpage_y}, + {clut_x, clut_y}, texture_blend_mode, depth_shift, (uint8_t) dither, @@ -1967,8 +2003,8 @@ void rsx_gl_push_triangle( {p2x, p2y, 0.95, p2w }, /* position */ {(uint8_t) c2, (uint8_t) (c2 >> 8), (uint8_t) (c2 >> 16)}, /* color */ {t2x, t2y}, /* texture_coord */ - {texpage_x, texpage_y}, - {clut_x, clut_y}, + {texpage_x, texpage_y}, + {clut_x, clut_y}, texture_blend_mode, depth_shift, (uint8_t) dither, @@ -1990,7 +2026,7 @@ void rsx_gl_fill_rect(uint32_t color, uint16_t top_left[2] = {x, y}; uint16_t dimensions[2] = {w, h}; - uint8_t col[3] = {(uint8_t) color, (uint8_t) (color >> 8), (uint8_t) (color >> 16)}; + uint8_t col[3] = {(uint8_t) color, (uint8_t) (color >> 8), (uint8_t) (color >> 16)}; if (static_renderer->state == GlState_Valid) { @@ -2079,7 +2115,7 @@ void rsx_gl_copy_rect( // duplicate the diagonal but I believe it was incorrect because of // the OpenGL filling convention. At least it's what TinyTiger told // me... - + glBindFramebuffer(GL_READ_FRAMEBUFFER, copy_fb); glFramebufferTexture(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, @@ -2182,7 +2218,7 @@ void rsx_gl_load_image(uint16_t x, uint16_t y, uint16_t *vram) { - /* TODO FIXME - upload_vram_window expects a + /* TODO FIXME - upload_vram_window expects a uint16_t[VRAM_HEIGHT*VRAM_WIDTH_PIXELS] array arg instead of a ptr */ if (static_renderer->state == GlState_Valid) diff --git a/rustation-libretro/src/shaders/command_fragment.glsl.h b/rustation-libretro/src/shaders/command_fragment.glsl.h index 3d9ee97f..ed63f3be 100644 --- a/rustation-libretro/src/shaders/command_fragment.glsl.h +++ b/rustation-libretro/src/shaders/command_fragment.glsl.h @@ -2,6 +2,12 @@ #ifdef FILTER_SABR static const char * command_fragment_sabr = GLSL( +#elif defined(FILTER_XBR) +static const char * command_fragment_xbr = GLSL( +#elif defined(FILTER_BILINEAR) +static const char * command_fragment_bilinear = GLSL( +#elif defined(FILTER_3POINT) +static const char * command_fragment_3point = GLSL( #else static const char * command_fragment = GLSL( #endif @@ -86,8 +92,8 @@ vec4 sample_texel(vec2 coords) { uint pix_per_hw = 1U << frag_depth_shift; // Texture pages are limited to 256x256 pixels - uint tex_x = uint(coords.x) & 0xffU; - uint tex_y = uint(coords.y) & 0xffU; + uint tex_x = clamp(uint(coords.x), 0x0U, 0xffU); + uint tex_y = clamp(uint(coords.y), 0x0U, 0xffU); // Texture window adjustments tex_x = (tex_x & frag_texture_window[0]) | frag_texture_window[1]; @@ -139,6 +145,25 @@ vec4 sample_texel(vec2 coords) { } return texel; } + +#if defined(FILTER_SABR) || defined(FILTER_XBR) +in vec2 tc; +in vec4 xyp_1_2_3; +in vec4 xyp_6_7_8; +in vec4 xyp_11_12_13; +in vec4 xyp_16_17_18; +in vec4 xyp_21_22_23; +in vec4 xyp_5_10_15; +in vec4 xyp_9_14_9; + +float c_df(vec3 c1, vec3 c2) { + vec3 df = abs(c1 - c2); + return df.r + df.g + df.b; +} + +const float coef = 2.0; +#endif + #ifdef FILTER_SABR // constants and functions for sabr const vec4 Ai = vec4( 1.0, -1.0, -1.0, 1.0); @@ -154,8 +179,6 @@ const vec4 M30 = vec4(0.2, 0.4, 0.2, 0.4); const vec4 M60 = M30.yxwz; const vec4 Mshift = vec4(0.2, 0.2, 0.2, 0.2); -const float coef = 2.0; - const vec4 threshold = vec4(0.32, 0.32, 0.32, 0.32); const vec3 lum = vec3(0.21, 0.72, 0.07); @@ -176,20 +199,6 @@ vec4 lum_wd(vec4 a, vec4 b, vec4 c, vec4 d, vec4 e, vec4 f, vec4 g, vec4 h) { return lum_df(a, b) + lum_df(a, c) + lum_df(d, e) + lum_df(d, f) + 4.0 * lum_df(g, h); } -float c_df(vec3 c1, vec3 c2) { - vec3 df = abs(c1 - c2); - return df.r + df.g + df.b; -} - -in vec2 tc; -in vec4 xyp_1_2_3; -in vec4 xyp_6_7_8; -in vec4 xyp_11_12_13; -in vec4 xyp_16_17_18; -in vec4 xyp_21_22_23; -in vec4 xyp_5_10_15; -in vec4 xyp_9_14_9; - //sabr vec4 get_texel_sabr() { @@ -277,6 +286,233 @@ vec4 get_texel_sabr() return texel; } #endif + +#ifdef FILTER_XBR + +// constants and functions for xbr +const vec3 rgbw = vec3(14.352, 28.176, 5.472); +const vec4 eq_threshold = vec4(15.0, 15.0, 15.0, 15.0); + +const vec4 delta = vec4(1.0/4., 1.0/4., 1.0/4., 1.0/4.); +const vec4 delta_l = vec4(0.5/4., 1.0/4., 0.5/4., 1.0/4.); +const vec4 delta_u = delta_l.yxwz; + +const vec4 Ao = vec4( 1.0, -1.0, -1.0, 1.0 ); +const vec4 Bo = vec4( 1.0, 1.0, -1.0,-1.0 ); +const vec4 Co = vec4( 1.5, 0.5, -0.5, 0.5 ); +const vec4 Ax = vec4( 1.0, -1.0, -1.0, 1.0 ); +const vec4 Bx = vec4( 0.5, 2.0, -0.5,-2.0 ); +const vec4 Cx = vec4( 1.0, 1.0, -0.5, 0.0 ); +const vec4 Ay = vec4( 1.0, -1.0, -1.0, 1.0 ); +const vec4 By = vec4( 2.0, 0.5, -2.0,-0.5 ); +const vec4 Cy = vec4( 2.0, 0.0, -1.0, 0.5 ); +const vec4 Ci = vec4(0.25, 0.25, 0.25, 0.25); + +// Difference between vector components. +vec4 df(vec4 A, vec4 B) +{ + return vec4(abs(A-B)); +} + +// Compare two vectors and return their components are different. +vec4 diff(vec4 A, vec4 B) +{ + return vec4(notEqual(A, B)); +} + +// Determine if two vector components are equal based on a threshold. +vec4 eq(vec4 A, vec4 B) +{ + return (step(df(A, B), vec4(15.))); +} + +// Determine if two vector components are NOT equal based on a threshold. +vec4 neq(vec4 A, vec4 B) +{ + return (vec4(1.0, 1.0, 1.0, 1.0) - eq(A, B)); +} + +// Weighted distance. +vec4 wd(vec4 a, vec4 b, vec4 c, vec4 d, vec4 e, vec4 f, vec4 g, vec4 h) +{ + return (df(a,b) + df(a,c) + df(d,e) + df(d,f) + 4.0*df(g,h)); +} + +vec4 get_texel_xbr() +{ + vec4 edri; + vec4 edr; + vec4 edr_l; + vec4 edr_u; + vec4 px; // px = pixel, edr = edge detection rule + vec4 irlv0; + vec4 irlv1; + vec4 irlv2l; + vec4 irlv2u; + vec4 block_3d; + vec4 fx; + vec4 fx_l; + vec4 fx_u; // inequations of straight lines. + + vec2 fp = fract(tc); + + vec3 A1 = sample_texel(xyp_1_2_3.xw ).xyz; + vec3 B1 = sample_texel(xyp_1_2_3.yw ).xyz; + vec3 C1 = sample_texel(xyp_1_2_3.zw ).xyz; + vec3 A = sample_texel(xyp_6_7_8.xw ).xyz; + vec3 B = sample_texel(xyp_6_7_8.yw ).xyz; + vec3 C = sample_texel(xyp_6_7_8.zw ).xyz; + vec3 D = sample_texel(xyp_11_12_13.xw ).xyz; + vec3 E = sample_texel(xyp_11_12_13.yw ).xyz; + vec3 F = sample_texel(xyp_11_12_13.zw ).xyz; + vec3 G = sample_texel(xyp_16_17_18.xw ).xyz; + vec3 H = sample_texel(xyp_16_17_18.yw ).xyz; + vec3 I = sample_texel(xyp_16_17_18.zw ).xyz; + vec3 G5 = sample_texel(xyp_21_22_23.xw ).xyz; + vec3 H5 = sample_texel(xyp_21_22_23.yw ).xyz; + vec3 I5 = sample_texel(xyp_21_22_23.zw ).xyz; + vec3 A0 = sample_texel(xyp_5_10_15.xy ).xyz; + vec3 D0 = sample_texel(xyp_5_10_15.xz ).xyz; + vec3 G0 = sample_texel(xyp_5_10_15.xw ).xyz; + vec3 C4 = sample_texel(xyp_9_14_9.xy ).xyz; + vec3 F4 = sample_texel(xyp_9_14_9.xz ).xyz; + vec3 I4 = sample_texel(xyp_9_14_9.xw ).xyz; + + vec4 b = vec4(dot(B ,rgbw), dot(D ,rgbw), dot(H ,rgbw), dot(F ,rgbw)); + vec4 c = vec4(dot(C ,rgbw), dot(A ,rgbw), dot(G ,rgbw), dot(I ,rgbw)); + vec4 d = b.yzwx; + vec4 e = vec4(dot(E,rgbw)); + vec4 f = b.wxyz; + vec4 g = c.zwxy; + vec4 h = b.zwxy; + vec4 i = c.wxyz; + vec4 i4 = vec4(dot(I4,rgbw), dot(C1,rgbw), dot(A0,rgbw), dot(G5,rgbw)); + vec4 i5 = vec4(dot(I5,rgbw), dot(C4,rgbw), dot(A1,rgbw), dot(G0,rgbw)); + vec4 h5 = vec4(dot(H5,rgbw), dot(F4,rgbw), dot(B1,rgbw), dot(D0,rgbw)); + vec4 f4 = h5.yzwx; + + // These inequations define the line below which interpolation occurs. + fx = (Ao*fp.y+Bo*fp.x); + fx_l = (Ax*fp.y+Bx*fp.x); + fx_u = (Ay*fp.y+By*fp.x); + + irlv1 = irlv0 = diff(e,f) * diff(e,h); + +//#ifdef CORNER_B +// irlv1 = (irlv0 * ( neq(f,b) * neq(h,d) + eq(e,i) * neq(f,i4) * neq(h,i5) + eq(e,g) + eq(e,c) ) ); +//#endif +//#ifdef CORNER_D +// vec4 c1 = i4.yzwx; +// vec4 g0 = i5.wxyz; +// irlv1 = (irlv0 * ( neq(f,b) * neq(h,d) + eq(e,i) * neq(f,i4) * neq(h,i5) + eq(e,g) + eq(e,c) ) * (diff(f,f4) * diff(f,i) + diff(h,h5) * diff(h,i) + diff(h,g) + diff(f,c) + eq(b,c1) * eq(d,g0))); +//#endif +//#ifdef CORNER_C + irlv1 = (irlv0 * ( neq(f,b) * neq(f,c) + neq(h,d) * neq(h,g) + eq(e,i) * (neq(f,f4) * neq(f,i4) + neq(h,h5) * neq(h,i5)) + eq(e,g) + eq(e,c)) ); +//#endif + + irlv2l = diff(e,g) * diff(d,g); + irlv2u = diff(e,c) * diff(b,c); + + vec4 fx45i = clamp((fx + delta -Co - Ci)/(2.0*delta ), 0.0, 1.0); + vec4 fx45 = clamp((fx + delta -Co )/(2.0*delta ), 0.0, 1.0); + vec4 fx30 = clamp((fx_l + delta_l -Cx )/(2.0*delta_l), 0.0, 1.0); + vec4 fx60 = clamp((fx_u + delta_u -Cy )/(2.0*delta_u), 0.0, 1.0); + + vec4 wd1 = wd( e, c, g, i, h5, f4, h, f); + vec4 wd2 = wd( h, d, i5, f, i4, b, e, i); + + edri = step(wd1, wd2) * irlv0; + edr = step(wd1 + vec4(0.1, 0.1, 0.1, 0.1), wd2) * step(vec4(0.5, 0.5, 0.5, 0.5), irlv1); + edr_l = step( 2.*df(f,g), df(h,c) ) * irlv2l * edr; + edr_u = step( 2.*df(h,c), df(f,g) ) * irlv2u * edr; + + fx45 = edr * fx45; + fx30 = edr_l * fx30; + fx60 = edr_u * fx60; + fx45i = edri * fx45i; + + px = step(df(e,f), df(e,h)); + +//#ifdef SMOOTH_TIPS + vec4 maximos = max(max(fx30, fx60), max(fx45, fx45i)); +//#endif +//#ifndef SMOOTH_TIPS +// vec4 maximos = max(max(fx30, fx60), fx45); +//#endif + + vec3 res1 = E; + res1 = mix(res1, mix(H, F, px.x), maximos.x); + res1 = mix(res1, mix(B, D, px.z), maximos.z); + + vec3 res2 = E; + res2 = mix(res2, mix(F, B, px.y), maximos.y); + res2 = mix(res2, mix(D, H, px.w), maximos.w); + + vec3 res = mix(res1, res2, step(c_df(E, res1), c_df(E, res2))); + float texel_alpha = sample_texel(tc).a; + + return vec4(res, texel_alpha); +} +#endif + +#ifdef FILTER_3POINT +vec4 get_texel_3point() +{ + float x = frag_texture_coord.x; + float y = frag_texture_coord.y; + + float u_frac = fract(x); + float v_frac = fract(y); + + vec4 texel_00; + + if (u_frac + v_frac < 1.0) { + // Use bottom-left + texel_00 = sample_texel(vec2(x + 0, y + 0)); + } else { + // Use top-right + texel_00 = sample_texel(vec2(x + 1, y + 1)); + + float tmp = 1 - v_frac; + v_frac = 1 - u_frac; + u_frac = tmp; + } + + vec4 texel_10 = sample_texel(vec2(x + 1, y + 0)); + vec4 texel_01 = sample_texel(vec2(x + 0, y + 1)); + + vec4 texel = texel_00 + + u_frac * (texel_10 - texel_00) + + v_frac * (texel_01 - texel_00); + + return texel; +} +#endif + +#ifdef FILTER_BILINEAR +// Bilinear filtering +vec4 get_texel_bilinear() +{ + float x = frag_texture_coord.x; + float y = frag_texture_coord.y; + + float u_frac = fract(x); + float v_frac = fract(y); + + vec4 texel_00 = sample_texel(vec2(x + 0, y + 0)); + vec4 texel_10 = sample_texel(vec2(x + 1, y + 0)); + vec4 texel_01 = sample_texel(vec2(x + 0, y + 1)); + vec4 texel_11 = sample_texel(vec2(x + 1, y + 1)); + + vec4 texel = texel_00 * (1. - u_frac) * (1. - v_frac) + + texel_10 * u_frac * (1. - v_frac) + + texel_01 * (1. - u_frac) * v_frac + + texel_11 * u_frac * v_frac; + + return texel; +} +#endif + void main() { vec4 color; @@ -288,10 +524,25 @@ void main() { { vec4 texel0 = sample_texel(vec2(frag_texture_coord.x, frag_texture_coord.y)); + vec4 texel = vec4(0.0); #ifdef FILTER_SABR - vec4 texel = get_texel_sabr(); -#else - vec4 texel = texel0; + texel = get_texel_sabr(); +#endif + +#ifdef FILTER_XBR + texel = get_texel_xbr(); +#endif + +#ifdef FILTER_BILINEAR + texel = get_texel_bilinear(); +#endif + +#ifdef FILTER_3POINT + texel = get_texel_3point(); +#endif + +#if !defined(FILTER_SABR) && !defined(FILTER_XBR) && !defined(FILTER_BILINEAR) && !defined(FILTER_3POINT) + texel = texel0; //use nearest if nothing else is chosen #endif // texel color 0x0000 is always fully transparent (even for opaque diff --git a/rustation-libretro/src/shaders/command_vertex.glsl.h b/rustation-libretro/src/shaders/command_vertex.glsl.h index 629bbc0f..a0cf7cd9 100644 --- a/rustation-libretro/src/shaders/command_vertex.glsl.h +++ b/rustation-libretro/src/shaders/command_vertex.glsl.h @@ -66,11 +66,11 @@ void main() { frag_texture_window = texture_window; tc = frag_texture_coord.xy; - xyp_1_2_3 = tc.xxxy + vec4( -1., 0.0, 1., -2.0 * 1.); - xyp_6_7_8 = tc.xxxy + vec4( -1., 0.0, 1., -1.); - xyp_11_12_13 = tc.xxxy + vec4( -1., 0.0, 1., 0.0); - xyp_16_17_18 = tc.xxxy + vec4( -1., 0.0, 1., 1.); - xyp_21_22_23 = tc.xxxy + vec4( -1., 0.0, 1., 2.0 * 1.); - xyp_5_10_15 = tc.xyyy + vec4(-2.0 * 1., -1., 0.0, 1.); - xyp_9_14_9 = tc.xyyy + vec4( 2.0 * 1., -1., 0.0, 1.); + xyp_1_2_3 = tc.xxxy + vec4(-1., 0., 1., -2.); + xyp_6_7_8 = tc.xxxy + vec4(-1., 0., 1., -1.); + xyp_11_12_13 = tc.xxxy + vec4(-1., 0., 1., 0.); + xyp_16_17_18 = tc.xxxy + vec4(-1., 0., 1., 1.); + xyp_21_22_23 = tc.xxxy + vec4(-1., 0., 1., 2.); + xyp_5_10_15 = tc.xyyy + vec4(-2., -1., 0., 1.); + xyp_9_14_9 = tc.xyyy + vec4( 2., -1., 0., 1.); });