Automatic porting of libretro shaders to mpv #14246
Replies: 2 comments 1 reply
-
This is seriously amazing, mad props for going to all this effort. It's also a bit sad, though, as I really dislike the mpv shader system and want to kill it, but I haven't yet found the time to rework the shader system from scratch. One of the numerous things we could do to improve the situation is to integrate slang directly into mpv/libplacebo. I noticed you mentioned I think it would make much more sense to use
You can hook |
Beta Was this translation helpful? Give feedback.
-
I use MPV all the time, but I currently watch some old anime through Retroarch because i cant get CRT-Royale to look the same in MPV as i do in Retroarch (using the CRT-Royale port someone made). But Retroarch's video player broke support for soft-subs long ago and it never got fixed. I would LOVE to use this. Please let me know when this becomes something the average user can use. |
Beta Was this translation helpful? Give feedback.
-
Hello!
I would like to showcase
mpv-libretro
a project I made to convert libretro shaders (.slangp preset files & associated .slang source files) to the formatmpv --glsl-shader
expects.Here's a presentation of the problem as well as some difficulties i encountered along the way.
(disclaimer: i'm still learning about shaders, some things i say here might be wrong)
Motivation
I wanted to watch Tool-Assisted Speedruns of retro games. These speedruns are encoded in the resolution of the actual console (e.g. 256x224 pixels).
While using
--scale=nearest
is fine to a degree, libretro offers better upscaling filters for this type of content, e.g. emulating old CRT screens.However libretro shaders aren't compatible with mpv as-is, you need to transform them to use them in mpv, which is what
mpv-libretro
does.Screenshots
Here are some screenshots at 1440p of some speedruns:
On the left,
--scale=nearest
is used. On the right,--glsl-shader=crt-royale-fb-intel.glsl
is used (CRT Royale, fake bloom, intel preset), which has been ported from these sources: https://github.com/libretro/slang-shaders/blob/6cb93ce1be67b314a96f5e346befb2b58b63eb04/crt/crt-royale-fake-bloom-intel.slangp.--scale=nearest
--glsl-shader=crt-royale-fb-intel.glsl
Usage
The sources are there: https://github.com/hhirtz/mpv-libretro
I don't have CI setup so it needs to be built from source. It's a rust project and as far as i can tell, only requires (an up-to-date enough) Rust to build.
The tool must be called from the command line, with the shader preset file as first and only argument. It prints the mpv-compatible GLSL shader to standard output, so you need to call it like so:
cargo run -- crt-geom-ntsc-composite-sharp.slangp >crt-geom.glsl
The output shader uses
//!PARAM
directives as well aslinearize
/delinearize
, so you need--vo=gpu-next
to use it, e.g.:The video must be of correct size. If it's already been upscaled, you need to downscale (and possibly crop) it first. This can be done in different ways:
mpv --vf=...
, see https://github.com/hhirtz/mpv-retro-shaders/blob/073159d5465979f902cfe2147605e69de496dd05/README.md#usage-with-upscaled-videosThe correct size depends on the game and console.
How it's done and some difficulties
libretro shaders are organized this way: a shader preset file (
.slangp
extension) lists all the shader passes and external textures (PNG and JPEG files), as well as some metadata for each pass.Each shader pass is in its separate
.slang
file.For some reason libretro allows shader authors to define their own vertex shaders (this might be for 3D games?). The structure of each
.slang
file is thus as follows:The conversion is done in several steps:
.slangp
shader preset, to list all the passes, external textures and shader parameters. It also separates each .slang file into two (for the vertex and fragment shaders).//!PARAM
as per libplacebo shader format. Both mpv's and libretro's parameter spec closely match so it's been easy to convert them//!TEXTURE
, with a//!FORMAT rgba8
, as I found is compatible with most hardware? All texture metadata (exceptmipmap
, see limitations) are also added//!HOOK MAIN
pass. This has been by far the hardest step to do.MAIN
texture from sRGB to linear RGB. libretro shaders work with linear RGB, and I think mpv converts the different color types to sRGB only, there is no way to say a shader works in linear RGB only.The reason the vertex and the fragment shaders have to be merged is that it turns out a lot of libretro shaders do interesting stuff in the vertex stage (other than
gl_Position=MVP*Position
), so it cannot be just discarded. So we prefix all globals withvertex_
andfragment_
, merge the two Abstract Syntax Trees, and add the hook function:Some notes:
layout(set=..) in/out
) are made into simple global variables that are shared between the two stages.frame
count, and shader parameters). The list of dependencies to//!BIND
for each pass is built with this, as well as the samplers defined in the libretro shader.mat4(1.0)
, andPosition
is set asvec4(HOOKED_pos, 0.0, 1.0)
.Here is a list of libretro shaders ported to mpv:
https://github.com/hhirtz/mpv-retro-shaders
With the exception of
crt-guest-advanced-ntsc.glsl
,crt-lottes.glsl
andgba.glsl
, all of these shaders have been ported using this method.Limitations
Naming issues aside, the two shader systems are fairly similar. Doing the conversion between the two has been actually pretty straightforward. The mpv docs and libplacebo website helped a lot. However, some advanced features in libretro are not present in mpv and prevent the correct conversion of some shaders:
wrap_mode
, basically//!BORDER <CLAMP | REPEAT | MIRROR>
in mpv, but not limited to external texturese.g. https://github.com/libretro/slang-shaders/blob/6cb93ce1be67b314a96f5e346befb2b58b63eb04/crt/crt-royale.slangp#L203
filter_linear
, basically//!FILTER <LINEAR | NEAREST>
in mpv, but not limited to external texturese.g. https://github.com/libretro/slang-shaders/blob/6cb93ce1be67b314a96f5e346befb2b58b63eb04/crt/crt-royale.slangp#L160
mipmap_input
,float_framebuffer
andsrgb_framebuffer
, which i actually am not sure what they do. mpv does not offer such settings//!BUFFER
, but the size of the buffer has to be hardcoded). see Shader stage expansion for temporal shaders/algorithms? #8137Overall I'm very happy with mpv's shader system and the software in general, and wanted to contribute back a little. I will go back to enjoy some nice retro speedruns! Thank you to everyone involved in the project.
Beta Was this translation helpful? Give feedback.
All reactions