1 #include "shaders_common.h" 2 3 static const char *output_fragment = GLSL( 4 // We're sampling from the internal framebuffer texture 5 uniform sampler2D fb; 6 // Framebuffer sampling: 0: Normal 16bpp mode, 1: Use 24bpp mode 7 uniform int depth_24bpp; 8 // Internal resolution upscaling factor. Necessary for proper 24bpp 9 // display since we need to know how the pixels are laid out in RAM. 10 uniform uint internal_upscaling; 11 // Coordinates of the top-left displayed pixel in VRAM (1x resolution) 12 uniform uvec2 offset; 13 // Normalized relative offset in the displayed area in VRAM. Absolute 14 // coordinates must take `offset` into account. 15 in vec2 frag_fb_coord; 16 17 out vec4 frag_color; 18 19 // Take a normalized color and convert it into a 16bit 1555 ABGR 20 // integer in the format used internally by the Playstation GPU. 21 uint rebuild_color(vec4 color) { 22 uint a = uint(floor(color.a + 0.5)); 23 uint r = uint(floor(color.r * 31. + 0.5)); 24 uint g = uint(floor(color.g * 31. + 0.5)); 25 uint b = uint(floor(color.b * 31. + 0.5)); 26 27 return (a << 15) | (b << 10) | (g << 5) | r; 28 } 29 30 void main() { 31 vec3 color; 32 33 if (depth_24bpp == 0) { 34 // Use the regular 16bpp mode, fetch directly from the framebuffer 35 // texture. The alpha/mask bit is ignored here. 36 vec2 off = vec2(offset) / vec2(1024., 512.); 37 38 color = texture(fb, frag_fb_coord + off).rgb; 39 } else { 40 // In this mode we have to interpret the framebuffer as containing 41 // 24bit RGB values instead of the usual 16bits 1555. 42 ivec2 fb_size = textureSize(fb, 0); 43 44 uint x_24 = uint(frag_fb_coord.x * float(fb_size.x)); 45 uint y = uint(frag_fb_coord.y * float(fb_size.y)); 46 47 uint x_native = x_24 / internal_upscaling; 48 49 x_24 = x_native * internal_upscaling; 50 51 // The 24bit color is stored over two 16bit pixels, convert the 52 // coordinates 53 uint x0_16 = (x_24 * 3U) / 2U; 54 55 // Add the offsets 56 x0_16 += offset.x * internal_upscaling; 57 y += offset.y * internal_upscaling; 58 59 // Move on to the next pixel at native resolution 60 uint x1_16 = x0_16 + internal_upscaling; 61 62 uint col0 = rebuild_color(texelFetch(fb, ivec2(x0_16, y), 0)); 63 uint col1 = rebuild_color(texelFetch(fb, ivec2(x1_16, y), 0)); 64 65 uint col = (col1 << 16) | col0; 66 67 // If we're drawing an odd 24 bit pixel we're starting in the 68 // middle of a 16bit cell so we need to adjust accordingly. 69 col >>= 8U * (x_native & 1U); 70 71 // Finally we can extract and normalize the 24bit pixel 72 float b = float((col >> 16U) & 0xffU) / 255.; 73 float g = float((col >> 8U) & 0xffU) / 255.; 74 float r = float(col & 0xffU) / 255.; 75 76 color = vec3(r, g, b); 77 } 78 79 frag_color = vec4(color, 1.0); 80 } 81 ); 82