I've ported the Sonic Mania CRT shaders to ReShade

Discussion in 'Engineering & Reverse Engineering' started by luluco, Sep 3, 2017.

  1. luluco

    luluco

    Member
    17
    0
    0
    Brazil
    EDIT: Here they are: CRT-Yee64, CRT-Yeetron.

    I'm a shader enthusiast, been programming shaders for a while now for fun, mostly in ReShade (a generic shader injector for almost any game).

    Recently by request of a friend I translated the DirectX 9 ASM instructions of CRT-Yeetron and CRT-Yee64 (called "Sharp" and "Smooth" in the video options) to ReShade's own "FX" language, which is almost identical to CG/DX9 HLSL with a few key differences.
    I was wondering about the legality of posting them here or my own GitHub repo, as the shaders have been ripped from the data file of Mania.

    Here's a few screenshots:
    Here's two crops, one of Mania and one of GTA:SA with the original Yee64 and my port respectively.
    [​IMG][​IMG]

    Here's screenshots of Yeetron and Yee64 respectively:
    [​IMG][​IMG]

    Here's a screenshot with Yee64 along with an NTSC effect, a Virtual Resolution effect and a "S contrast curve" effect, to simulate the look of an old PS2 game:
    [​IMG]

    The effect might not be 1x1 exactly as the original, but that's because of two factors:
    • Mania runs at a specific internal resolution, similar to an emulator. This can be partly addressed with my other Virtual Resolution effect.
    • The shaders have a set of parameters which I have no way to know how they are handled in the CPU code, so my friend has helped me achieve something similar based on RetroArch CRT shaders (which would be a nice thing to port these shaders to).

    So overall I don't claim these are perfect ports, I just translated the ASM instructions into high level code, I just felt someone else might be interested.
    Let me know if this isn't allowed here.
     
  2. Chimera

    Chimera

    I'm not a furry. Tech Member
    1,258
    1
    18
    Castlevania prettyness
    the only thing i can see being a problem is using the texture provided from Mania, as that's teeechnically copyrighted material. That said, we being a modding community use copyrighted content a la the sprites on the daily, so I'm assuming it's not the biggest deal if it's just the texture being used for hobbiest reasons / you're not selling anything with it.

    Worst comes to worst you can try finding an alternate version of the CRT pattern online and use that, I spose, unless the shader doesn't even use a texture filter, in which case I'd say this is probably 100% fine as the code's been changed past recognition (I could be completely wrong though since digital copyright laws are legitimately awful).
     
  3. luluco

    luluco

    Member
    17
    0
    0
    Brazil
    It doesn't use a texture, the overlay is generated by the shader.

    That's what I'm worried about too, software copyright is a mess overall.
     
  4. Cooljerk

    Cooljerk

    NotEqual Tech, Inc - VR & Game Dev Oldbie
    4,334
    75
    28
    Most CRT filters in the last several years have moved well beyond using simple texture filters. Good CRT filters these days should be simulating the actual luminosity variation per scanline depending on color value.

    Dunno what type of uniform or vertex buffer object variables you're needing, but simple things like fragment counting can be achieved using atomic operations. You can discern the width of the texture being operated on this way by iterating atomic counters until you detect a change in Y position of the incoming fragment.

    I have no idea how to work with atomic counters in HLSL, though, only GLSL.

    EDIT: Beaten

    EDIT AGAIN: Also, you can find lots of freely-licensed CRT shaders online if you look around, if anybody is really worried about legality.
     
  5. luluco

    luluco

    Member
    17
    0
    0
    Brazil
    Here's an example taken from the original code, and how I translated it:
    ASM:
    Code (Text):
    1.  
    2. mov r0.z, c3.w
    3. rcp r1.x, c0.x
    4. rcp r1.y, c0.y
    5. mul r1.xy, r1, c1
    6. mul r1.xy, r1, v0
    7. rcp r2.x, c1.x
    8. rcp r2.y, c1.y
    9. mul r1.zw, r2.xyxy, c0.xyxy
    10. mul r1.zw, r1, r1.xyxy
    11. mul r1.xy, r1, c2
    12. mul r2.zw, r1, c1.xyxy
    13. frc r2.zw, r2
    14.  
    FX/HLSL:
    Code (Text):
    1.  
    2. r0.z = c3.w;
    3. r1.x = 1.0 / c0.x;
    4. r1.y = 1.0 / c0.y;
    5. r1.xy = (r1 * c1).xy;
    6. r1.xy = (r1 * v0).xy;
    7. r2.x = 1.0 / c1.x;
    8. r2.y = 1.0 / c1.y;
    9. r1.zw = (r2.xyxy * c0.xyxy).zw;
    10. r1.zw = (r1 * r1.xyxy).zw;
    11. r1.xy = (r1 * c2).xy;
    12. r2.zw = (r1 * c1.xyxy).zw;
    13. r2.zw = frac(r2).zw;
    14.  

    It's not even a particularly hard task, just tedious, but it's pretty much the same code, hence it could be considered "stolen" by law.

    These are the parameters it uses:
    Code (Text):
    1.  
    2. // Parameters:
    3. //
    4. //   float2 pixelSize;
    5. //   sampler2D texDiffuse;
    6. //   float2 textureSize;
    7. //   float2 viewSize;
    8.  

    In my current implementation I've added a source resolution parameter and a "downscale" paramater, then I set textureSize to source_resolution / downscale

    I set the pixelSize to the screen resolution but with the x component multiplied by the screen aspect ratio and it gave me close results to the original.
    viewSize is just set to the screen resolution, as I believe it should be.
    texDiffuse is obviously the fullscreen texture the game renders to.
     
  6. Cooljerk

    Cooljerk

    NotEqual Tech, Inc - VR & Game Dev Oldbie
    4,334
    75
    28
    [strike]Ha, they actually do use a diffuse texture, I guess for the pattern. Or wait, is that texture supposed to be the input texture (i.e. the framebuffer) that the CRT filter is being applied to?[/strike] EDIT: haha, we're playing post tag it seems :P. PixelSize and viewSize I guess are related to the scaling the engine does to convert from the internal resolution to screen resolution. This makes sense, you wouldn't want to do the CRT filter on the original texture size, then blow it up, or else the CRT artifacts would look scaled and weird.

    I'm about go work at my parents place (they got hit by the hurricane) but I'll come back later tonight and see if we can figure out a way to discern the total output resolution using atomic counters.
     
  7. luluco

    luluco

    Member
    17
    0
    0
    Brazil
    Yeah before scaling the pixelSize to the aspect ratio the CRT artifacts looked too stretched (specially on my 21:9 screen).
    I'm not much of a CRT effects guy so most of this is still magic to me.

    Good luck there!
     
  8. Black Squirrel

    Black Squirrel

    staying alert on the beach Wiki Sysop
    5,677
    259
    63
    Northumberland, England
    quipu two metres apart
    CRT filters are weird.

    I mean sure, they do sort-of emulate a slightly wonky CRT television, and if that's your bag, more power to you. But every CRT is different and every filter, including the one in Mania, gets it wrong in unique and interesting ways. You'd have more luck emulating a CRT by playing a 15,734Hz tone over the top of everything - at least that bit was consistent across models.


    The way I'd do it, and is what I tend to recommend when using Kega Fusion (or one of its derivatives) as a Mega Drive emulator, is to go for the CBVS filter. That doesn't emulate a CRT display per se, it emulates a composite signal, which is naturally a bit blurry and usually crap. Faced with limited colours, Mega Drive artists drew their pixels in a certain way to take advantage of this - it's how the Mega Drive (and Saturn) does semi-transparency. It doesn't actually do semi-transparency, but if your screen isn't ultra-sharp, it totally does.


    This was something pulled up in the Sonic 1/2/CD remakes - Taxman uses real alpha transparency for the shields, but half the graphics use these tricks in subtle little ways and Sonic 3 is loaded with them (although not to the same extent as say, Earthworm Jim).


    to get out the old example again:

    [​IMG]

    As far as I could see, Mania doesn't really do this. Although it's a difficult one to judge because it actually has colours to spare so doesn't need to.



    As an aside, this is exactly the same for audio. If you turn on the "filter" in Kega Fusion, you can hear the tune in the Sonic Spinball options music. They never expected absolute clarity.
     
  9. Blue Spikeball

    Blue Spikeball

    Member
    757
    73
    28
    The half-assed transparencies were one of the things that annoyed me the most about the remakes. They had the opportunity to finally fix stuff such as the waterfalls and give them real transparency, but no, they opted to keep the original dithered effect that doesn't work on anything other than CRT screens for some reason. Sonic 1 was the worst in that aspect. They left the waterfalls untouched, made the shields truly transparent but kept the flickering for seemingly no reason, and I still don't get why they replaced the spring sprites with the extra dithered ones from CD. And it was just as baffling how Sonic 2 alternated between transparent waterfalls (EHZ) and dithered waterfalls (ARZ).

    Sorry for the rant. Anyways, what's the filter used by the bottom pic?
     
  10. luluco

    luluco

    Member
    17
    0
    0
    Brazil
    I'm aware the effect isn't really realistic compared to a real CRT TV.
    I did port a shader called "Artifact Colors" before for the same friend that does a more realistic approach: https://github.com/Matsilagi/reshade-retroarch-shaders/blob/master/Shaders/ArtifactColors.fx
    Original: https://www.shadertoy.com/view/llyGzR

    Also here are the CRT effects from Mania I ported:
    CRT-Yee64
    CRT-Yeetron

    It's ported to ReShade but can be easily ported over to CG, HLSL or GLSL, like to RetroArch.
     
  11. Matsilagi

    Matsilagi

    Member
    3
    0
    0
    It may be one of those RetroArch NTSC blurring filters.
    I've some ported on my github for ReShade aswell, funny enough, the OP from this thread helped me with lots of them.
    If you guys want, i can edit this post and place the link here.
    EDIT: ninja'd.
     
  12. Zenor

    Zenor

    flip the chessboard over Member
    274
    0
    16
    It's a simple filter that just averages each pixel with the one directly to its left, like so.
     
  13. luluco

    luluco

    Member
    17
    0
    0
    Brazil
    So just good ol' box blur?
     
  14. Blue Spikeball

    Blue Spikeball

    Member
    757
    73
    28
    I don't suppose anyone knows if a filter like that exists for Kega Fusion? I know it has TV Mode, but it makes everything look too blurry.

    Edit: Derp, it seems that the excessive blurriness in Kega was due to the upscaling. Running it on the native MD resolution with TV mode (CVBS) on makes it look like the screenshots posted here.

    I wonder if there would be a way around that, hypothetically speaking? Maybe if one rendered the graphics on 320x240 with the blending filter and then upscaled them using 2xSaI or a similar filter?
     
  15. luluco

    luluco

    Member
    17
    0
    0
    Brazil
    You can get Blargg's excellent "MD NTSC" filter for Kega Fusion together with various plugins here, I use that with 25% scanlines:
    No Filter:
    [​IMG]
    Only MD NTSC:
    [​IMG]
    MD NTSC + 25% Scanlines
    [​IMG]

    I also use the "Brighten" option, to compensate for the general darkness brought by scanlines and MD NTSC.
     
  16. luluco

    luluco

    Member
    17
    0
    0
    Brazil
    The difference is striking, checkout the waterfalls and clouds in the background:
    [​IMG]
     
  17. Blue Spikeball

    Blue Spikeball

    Member
    757
    73
    28
    Thank you for the advice and the sample pics. And yes, that filter makes the transparent waterfall and water in those pics look fantastic. Unfortunately, I've noticed a few issues with the dithering when using it. For instance, the colors of waterfalls, tubes and other stuff that uses vertical dithering for transparency get warped when the screen scrolls:
    [​IMG]

    And dithered colors tend to become horizontal lines:
    [​IMG]
    [​IMG]

    Anyway. Just to clarify, I'm not trying to make the graphics look as close to CRT as possible (though I can see the appeal in such filters). I was just interested in a filter that would blend pixels in order to "fix" the dithering and transparencies in games, without causing too much blurring.
     
  18. Cooljerk

    Cooljerk

    NotEqual Tech, Inc - VR & Game Dev Oldbie
    4,334
    75
    28
    You're looking for something more akin to a bilinear filter, one that samples from 2 directions. This is actually closer to how a real CRT would behave, because the bleed from the phosphor isn't only horizontal.