1#version 450 2precision highp float; 3precision highp int; 4 5#ifdef TEXTURED 6#define FILTERS 7#endif 8 9#include "common.h" 10#include "primitive.h" 11 12layout(set = 0, binding = 4) uniform sampler2D uHighResTexture; 13layout(push_constant, std430) uniform Push 14{ 15 ivec4 hd_texture_vram_rect; // The area of vram this hd texture covers 16 ivec4 hd_texture_texel_rect; // The area of this hd texture's own texels that may currently be used 17} push; 18#ifdef TEXTURED 19#include "hdtextures.h" 20 21const int OPAQUE = 0; 22const int SEMI_TRANS = 1; 23const int SEMI_TRANS_OPAQUE = 2; 24layout(constant_id = 0) const int TRANSPARENCY_MODE = OPAQUE; 25 26const int FILTER_NEAREST = 0; 27const int FILTER_XBR = 1; 28const int FILTER_SABR = 2; 29const int FILTER_BILINEAR = 3; 30const int FILTER_3POINT = 4; 31const int FILTER_JINC2 = 5; 32layout(constant_id = 1) const int FILTER_TYPE = FILTER_NEAREST; 33#endif 34 35void main() 36{ 37 float opacity = 1.0; 38#ifdef TEXTURED 39 vec4 NNColor; 40 41 bool fastpath = (vParam.z & 0x100) != 0; 42 bool hd_enabled = !fastpath && (vParam.z & 0x200) == 0; 43 bool cache_hit = (vParam.z & 0x400) != 0; 44 45 vec4 hdColor; 46 if (fastpath) { 47 NNColor = sample_hd_fast(vUV); 48 } else if (hd_enabled && sample_hd_texture_nearest_hack(vUV, hdColor)) { 49 NNColor = hdColor; 50 } else { 51 NNColor = sample_vram_atlas(clamp_coord(vUV)); 52 } 53 54 // Even for opaque draw calls, this pixel is transparent. 55 // Sample in NN space since we need to do an exact test against 0.0. 56 // Doing it in a filtered domain is a bit awkward. 57 // In this pass, only accept opaque pixels. 58 if (TRANSPARENCY_MODE == SEMI_TRANS_OPAQUE) 59 if (all(equal(NNColor, vec4(0.0))) || NNColor.a > 0.5) 60 discard; 61 62 // To avoid opaque pixels from bleeding into the semi-transparent parts, 63 // sample nearest-neighbor only in semi-transparent parts of the image. 64 vec4 color = NNColor; 65 66 // texture filtering 67 if (FILTER_TYPE == FILTER_XBR) 68 color = sample_vram_xbr(opacity); 69 if (FILTER_TYPE == FILTER_BILINEAR) 70 color = sample_vram_bilinear(opacity); 71 if (FILTER_TYPE == FILTER_SABR) 72 color = sample_vram_sabr(opacity); 73 if (FILTER_TYPE == FILTER_JINC2) 74 color = sample_vram_jinc2(opacity); 75 if (FILTER_TYPE == FILTER_3POINT) 76 color = sample_vram_3point(opacity); 77 78 if (TRANSPARENCY_MODE == OPAQUE || TRANSPARENCY_MODE == SEMI_TRANS) 79 if (color.a == 0.0 && all(equal(vec4(NNColor), vec4(0.0)))) 80 discard; 81 82 // hd texture filtering 83 if (hd_enabled) { 84 bool valid = true; 85 vec4 hd_color = sample_hd_texture_trilinear(vUV, valid); 86 if (valid) { 87 color = hd_color; 88 opacity = hd_color.a; 89 } 90 } 91 92 if (opacity < 0.5) 93 discard; 94 95 vec3 shaded = color.rgb * vColor.rgb * (255.0 / 128.0); 96 FragColor = vec4(shaded, NNColor.a + vColor.a); 97#else 98 FragColor = vColor; 99#endif 100 101 // Get round down behavior instead of round-to-nearest. 102 // This is required for various "fade" out effects. 103 // However, don't accidentially round down if we are already rounded to avoid 104 // unintended feedback effects. 105 FragColor.rgb -= 0.49 / 255.0; 106 107#if 0 108#if defined(TEXTURED) 109 if ((vParam.z & 0x100) != 0) 110 FragColor.rgb += textureLod(uDitherLUT, gl_FragCoord.xy * 0.25, 0.0).xxx - 4.0 / 255.0; 111#endif 112 FragColor.rgb = quantize_bgr555(FragColor.rgb); 113#endif 114} 115