Omega Glory TV4X Scaling Filter

In a recent article about the Retrode on ArsTechnica there was a link to this blog regarding some attempt at a CRT filter.

http://omega-glory.net/projects/tv4x/

http://omega-glory.net/2012/2/12/CRT-TV-Screen-Emulation/ http://omega-glory.net/2012/8/18/Simulating-NTSC-Transport---Retro-Games/

I don’t know if it brings anything new to the table but I don’t recall seeing it anywhere here so I thought I’d mention it =)

The scanlines do not “bleed” making it less advanced than other CRT shaders.

Actually, in modern CRT filters, the pixel luminances bleed into the scanlines (the dark void), not the opposite.

Now, to be fair, I think what this filter is trying to do is get something of an approximation of a shadow mask. If you look at a shadow mask very closely, you may notice its scanlines tend to look a bit jagged due to how the phosphors are arranged, unlike an aperture grille, which for the most part look very straight. I believe that is what this is trying to achieve, though of course there’s only so much you can do at 4x scale, which is why all existing CRT filters/shaders make compromises in one way or another.

There are some problems with it, conceptually, in that it sounds like he’s approaching the signal as if it were a standard 480i instead of the nonstandard “240p” signal that consoles typically output. For example, the jittering shown in his Contra 3 gif should only happen on a handful of SNES games (R.P.M. Racing, one of the lavos cinematics on Chrono Trigger, a couple other things…; it’s much more common in PSX games). I’m also curious about the bit about scanlines moving down the screen. I’ve seen people mention this a few times and have no idea where it’s coming from (perhaps a misunderstanding about what scanlines actually are).

It’s also funny that he said:

The current state of CRT emulation is pretty pathetic. The only halfway decent CRT emulation filters I’ve come across, are the filters included in Richard Banister’s Emulator Enhancer, which is non-free. Most of the other filters do a very bad job of representing what a game actually looked like on a CRT.

since cgwg’s CRT shader existed long before that post was written. In fact, I’m pretty sure MAME had its HLSL CRT shader support before then, as well. Even in OS X-only applications, OpenEmulator (not to be confused with OpenEmu) has had really great NTSC and CRT emulation for a long time.

All that said, it’s always nice to see new ideas and implementations, so I wish him luck on the development. He would probably have been better off making it a shader, though, since it apparently doesn’t reach full-speed on a modern i7…

Yes, that’s what I meant. I worded it very poorly.

Hmm, that is a very bold thing for him to say regarding the state of CRT emulation, especially now that hunterk’s PhosphorLUT exists, which given a 10x scale delivers the most faithful CRT emulation I have ever seen. Of course, it also requires a monitor capable of displaying such a scale, which almost no one has at the moment, but them’s the breaks. 4x scale just isn’t enough for a truly accurate CRT look.

1 Like

Hey, someone sent me a message that a discussion was going on about some of my filter work (I’m the person who wrote TV2X / TV4X), so I thought it would be a good time to clear some things up.

First of all, I saw some people saying that there are problems with it treating signal as 480i. This is not the case. That post is actually very old, and at the time, I was looking into a way to emulate 480i signal, which is used on a few games (2 player mode in Sonic, for example). The idea was to treat 240p games as 240p, but also try and simulate the phosphor refresh / decay for 480i content. That idea has since been abandoned (maybe I’ll play around with it again later, but right now I don’t have much time for side projects).

Also, the 4X code is old and unmaintained at this point. While I was implementing it on SNES9X, I ran into issues with it running really slowly, despite the filter code running very fast. I tracked that down to the upscaling that goes on inside SNES9X. Basically, there’s problems scaling 4X to screen size, and that’s where the slow down was coming from.

My initial goal behind the 4X filter, was to basically be able to simulate the look of various major phosphor layouts (slot mask, dot mask, aperture grille, etc). At some point, the my goals became a bit too ambitious (also simulating what happens to signal when it gets sent over Composite, S-Video, and Component, trying to emulate 480i content, etc), and I had to scale it back… I’m doing all of this in my spare time, in addition to working full-time as a programmer, taking care of family stuff, training for gaming tournaments, etc.

So, after all of that, I started working on a 2X filter, and its actually looking pretty good. I have a build of SNES9X for Linux built, and running well on an old Athlon 64 3200+. I was working on a Mac port, but I found out that the Mac port of SNES9X is currently unmaintained, doesn’t compile, and needs to be completely rewritten because it heavily uses deprecated APIs. Right now, I’m working on getting my hands on a Windows system, and getting it up and running in SNES9X on that. There’s a couple other things I want to play around with, such as fixing the aspect ratio on SNES games (the resolution is typically 256x224, but when you have an actual console plugged into a TV, it gets horizontally stretched so that it’s at a 4:3 aspect ratio).

On most TVs, there is quite a bit of luminance that bleeds into the black space in between scanlines. The amount of “bleed” various a lot between TVs. High quality production monitors (ie : Sony PVM and BVM) have little to no bleed, so you can see the black lines in between scanlines very clearly on them. This is actually adjustable in my 2X filter. There’s a lot of things not taken into account, though, which I would have really liked to include. I’ve actually done extensive research about how TVs and the NTSC standard work for this project, so I know there are definitely some weaknesses. 100% emulation really isn’t possible at this point. There is just too much that has to be taken into account, and you’d have to render it at something like 10-20 times the original resolution. So the best I can do is compare against my Sony Trinitron TV, which is how I’ve been checking my work thus far.

Here’s some recent screenshots of my 2X filter, from my Twitter:

And I also have all of the 2X code in the TV4X project on GitHub:

At some point, I want to make a 3X filter, and possibly play around with some shader stuff, but I only have so much spare time.

That does look very good truth be told.

With libretro you wouldn’t have to bother with all these platform ports - we have bsnes/SNES9x/SNES9x Next cores on all three big OSes (OSX/Linux/Windows) so you could just focus on the shader instead.

It would be the only way to attain fullspeed anyways on most devices - doing a CPU filter in this day and age is totally backwards.

@turbinater Hey man, welcome :slight_smile:

That 2x version is looking quite nice.

What format was the shader going to be in? You said Snes9x, which implies either .cg format, or it’s built right into the program. .cg format would give it more flexibility. And you don’t have to worry about porting it to various systems. It just works if the program supports it.

Also, would those same slowdowns from upscaling occur in RetroArch as well? I’d imagine that RA handles upscaling differently than snes9x. Perhaps those issues wouldn’t occur in RA?

According to that, .cg works in Open Emu, Snes9x and RetroArch.

You can read more about the format here:

I’m well aware that everything has pretty much moved to shader based filters, and it’s on my list of things to learn. My main system is OS X, and a huge issue I was running into last time I attempted a shader, was that support can be very spotty on OS X. Apple seems dead set on putting the burden of driver development on themselves, but they don’t seem to have the manpower to keep pace with everyone else. Last time I tested my laptop, it didn’t even have full OpenGL 3.2 support (that may have been fixed by updates, but it still doesn’t support 3.3) :-/ … It’s difficult to go through a tutorial, and have none of the examples compile or work.

I’m sure if I was native to 3D programming I wouldn’t have much of a problem getting something to work, but I mostly do computer vision stuff in C and Python, so shaders still seem a bit foreign to me. If anyone knows of some good resources, I’m definitely interested.

@turbinater The shaders we use are quite different from the shaders you would typically encounter on a 3D game, for instance, so most of the tutorials you’ll find will be less than helpful, unfortunately. I think the best way to learn is really just to look at a few existing shaders that do the sorts of things you’re trying to do and see how they work.

maister’s NTSC shader is complicated, but likely contains some functions you’ll find familiar:

Likewise, cgwg’s CRT shader covers a lot of ground, including a standard 2-pass gaussian blur: https://github.com/libretro/common-shaders/tree/master/crt/crt-interlaced-halation

The biggest thing to watch out for in writing your own shader code is to avoid branching as much as possible, since that murders performance. If you have any questions, feel free to ask and I’ll answer them if I can. If I can’t, hopefully someone else can chime in :slight_smile:

Thanks! I’ll definitely play around with this stuff when I get a chance.

Sounds like I’ll be right at home. I’ve done quite a few branchless filters on CPU :slight_smile: