mirror of
https://github.com/libretro/rustation-libretro.git
synced 2026-11-07 12:37:51 -10:00
Revert to floating point texture format for fb_texture
Apparently integer textures won't work properly without GL_EXT_gpu_shader4 which is not supported everywhere (especially on non-Nvidia hardware).
This commit is contained in:
1 parent
5b4e33a708
commit
3e328e3967
3 files changed
+32
-52
No files matched your search
@@ -79,11 +79,11 @@ impl GlState {
|
||||
let native_width = VRAM_WIDTH_PIXELS as u32;
|
||||
let native_height = VRAM_HEIGHT as u32;
|
||||
|
||||
// Integer texture holding the raw VRAM texture contents. We
|
||||
// can't meaningfully upscale it since most games use paletted
|
||||
// Texture holding the raw VRAM texture contents. We can't
|
||||
// meaningfully upscale it since most games use paletted
|
||||
// textures.
|
||||
let fb_texture =
|
||||
try!(Texture::new(native_width, native_height, gl::R16UI));
|
||||
try!(Texture::new(native_width, native_height, gl::RGB5_A1));
|
||||
|
||||
if depth > 16 {
|
||||
// Dithering is superfluous when we increase the internal
|
||||
@@ -255,8 +255,8 @@ impl GlState {
|
||||
|
||||
try!(self.fb_texture.set_sub_image(top_left,
|
||||
dimensions,
|
||||
gl::RED_INTEGER,
|
||||
gl::UNSIGNED_SHORT,
|
||||
gl::RGBA,
|
||||
gl::UNSIGNED_SHORT_1_5_5_5_REV,
|
||||
pixel_buffer));
|
||||
|
||||
try!(self.image_load_buffer.clear());
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
#version 330 core
|
||||
|
||||
// Integer texture 16bit per pixel, stored in the red component
|
||||
uniform usampler2D fb_texture;
|
||||
uniform sampler2D fb_texture;
|
||||
|
||||
// Scaling to apply to the dither pattern
|
||||
uniform uint dither_scaling;
|
||||
@@ -26,31 +25,29 @@ const uint BLEND_MODE_NO_TEXTURE = 0U;
|
||||
const uint BLEND_MODE_RAW_TEXTURE = 1U;
|
||||
const uint BLEND_MODE_TEXTURE_BLEND = 2U;
|
||||
|
||||
// Read a 16bpp pixel in VRAM
|
||||
uint vram_get_pixel(int x, int y) {
|
||||
return texelFetch(fb_texture, ivec2(x, y), 0).r;
|
||||
// Read a pixel in VRAM
|
||||
vec4 vram_get_pixel(int x, int y) {
|
||||
return texelFetch(fb_texture, ivec2(x, y), 0);
|
||||
}
|
||||
|
||||
// Convert a 16bit RGBA 5551 color into a normalized float RGBA
|
||||
// vector.
|
||||
vec4 texel_to_color(uint texel) {
|
||||
uint a = texel >> 15U;
|
||||
uint b = (texel >> 10U) & 0x1fU;
|
||||
uint g = (texel >> 5U) & 0x1fU;
|
||||
uint r = texel & 0x1fU;
|
||||
// Take a normalized color and convert it into a 16bit 1555 ABGR
|
||||
// integer in the format used internally by the Playstation GPU.
|
||||
uint rebuild_psx_color(vec4 color) {
|
||||
uint a = uint(floor(color.a + 0.5));
|
||||
uint r = uint(floor(color.r * 31. + 0.5));
|
||||
uint g = uint(floor(color.g * 31. + 0.5));
|
||||
uint b = uint(floor(color.b * 31. + 0.5));
|
||||
|
||||
uvec4 color = uvec4(r, g, b, a);
|
||||
|
||||
return vec4(color) / vec4(31., 31., 31., 1.);
|
||||
return (a << 15) | (b << 10) | (g << 5) | r;
|
||||
}
|
||||
|
||||
// Texture color 0x0000 is special in the Playstation GPU, it denotes
|
||||
// a fully transparent texel (even for opaque draw commands). If you
|
||||
// want black you have to use an opaque draw command and use `0x8000`
|
||||
// instead.
|
||||
// bool is_transparent(vec4 texel) {
|
||||
// return rebuild_color(texel) == 0;
|
||||
// }
|
||||
bool is_transparent(vec4 texel) {
|
||||
return rebuild_psx_color(texel) == 0U;
|
||||
}
|
||||
|
||||
// PlayStation dithering pattern. The offset is selected based on the
|
||||
// pixel position in VRAM, by blocks of 4x4 pixels. The value is added
|
||||
@@ -84,12 +81,14 @@ void main() {
|
||||
tex_x += int(frag_texture_page.x);
|
||||
tex_y += int(frag_texture_page.y);
|
||||
|
||||
uint texel = vram_get_pixel(tex_x, tex_y);
|
||||
vec4 texel = vram_get_pixel(tex_x, tex_y);
|
||||
|
||||
if (frag_depth_shift > 0U) {
|
||||
// 8 and 4bpp textures are paletted so we need to lookup the
|
||||
// real color in the CLUT
|
||||
|
||||
uint icolor = rebuild_psx_color(texel);
|
||||
|
||||
// A little bitwise magic to get the index in the CLUT. 4bpp
|
||||
// textures have 4 texels per VRAM "pixel", 8bpp have 2. We need
|
||||
// to shift the current color to find the proper part of the
|
||||
@@ -108,7 +107,7 @@ void main() {
|
||||
uint shift = (align * bpp);
|
||||
|
||||
// Finally we have the index in the CLUT
|
||||
uint index = (texel >> shift) & mask;
|
||||
uint index = (icolor >> shift) & mask;
|
||||
|
||||
int clut_x = int(frag_clut.x + index);
|
||||
int clut_y = int(frag_clut.y);
|
||||
@@ -119,17 +118,13 @@ void main() {
|
||||
|
||||
// texel color 0x0000 is always fully transparent (even for opaque
|
||||
// draw commands)
|
||||
if (texel == 0U) {
|
||||
if (is_transparent(texel)) {
|
||||
// Fully transparent texel, discard
|
||||
discard;
|
||||
}
|
||||
|
||||
// We're done messing with integers, convert to the normalized
|
||||
// floating point representation OpenGL understands.
|
||||
vec4 tcolor = texel_to_color(texel);
|
||||
|
||||
if (frag_texture_blend_mode == BLEND_MODE_RAW_TEXTURE) {
|
||||
color = tcolor;
|
||||
color = texel;
|
||||
} else /* BLEND_MODE_TEXTURE_BLEND */ {
|
||||
// Blend the texel with the shading color. `frag_shading_color`
|
||||
// is multiplied by two so that it can be used to darken or
|
||||
@@ -138,7 +133,7 @@ void main() {
|
||||
// OpenGL will take care of that since the output buffer holds
|
||||
// integers. The alpha/mask bit bit is taken directly from the
|
||||
// texture however.
|
||||
color = vec4(frag_shading_color * 2. * tcolor.rgb, tcolor.a);
|
||||
color = vec4(frag_shading_color * 2. * texel.rgb, texel.a);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,31 +1,16 @@
|
||||
#version 330 core
|
||||
|
||||
uniform usampler2D fb_texture;
|
||||
uniform sampler2D fb_texture;
|
||||
|
||||
in vec2 frag_fb_coord;
|
||||
|
||||
out vec4 frag_color;
|
||||
|
||||
// Read a 16bpp pixel in VRAM
|
||||
uint vram_get_pixel(int x, int y) {
|
||||
return texelFetch(fb_texture, ivec2(x, y), 0).r;
|
||||
}
|
||||
|
||||
// Convert a 16bit RGBA 5551 color into a normalized float RGBA
|
||||
// vector.
|
||||
vec4 texel_to_color(uint texel) {
|
||||
uint a = texel >> 15U;
|
||||
uint b = (texel >> 10U) & 0x1fU;
|
||||
uint g = (texel >> 5U) & 0x1fU;
|
||||
uint r = texel & 0x1fU;
|
||||
|
||||
uvec4 color = uvec4(r, g, b, a);
|
||||
|
||||
return vec4(color) / vec4(31., 31., 31., 1.);
|
||||
// Read a pixel in VRAM
|
||||
vec4 vram_get_pixel(int x, int y) {
|
||||
return texelFetch(fb_texture, ivec2(x, y), 0);
|
||||
}
|
||||
|
||||
void main() {
|
||||
uint texel = vram_get_pixel(int(frag_fb_coord.x), int(frag_fb_coord.y));
|
||||
|
||||
frag_color = texel_to_color(texel);
|
||||
frag_color = vram_get_pixel(int(frag_fb_coord.x), int(frag_fb_coord.y));
|
||||
}
|
||||
Reference in new issue
Block a user