Sunday, May 15, 2011

More Emulator Pixel Shaders (CRT updated and more)

I'm just going to dive right in with the pictures in this post. If you want/need some backstory, read my previous CRT shader post. These shaders are all available in Screwtape's bsnes git repo, except for Beam4, which can be downloaded here, and NTSC, which can be downloaded here (both mirrored in my mediafire in case the pastebins expire before Screwtape adds them to his repo).

Update (01/11/12): bsnes support is back! Plus, the Win32 and GTK+ ports of snes9x support these shaders, as well. :D

UPDATE (9/20/11): Themaister has written an awesome little WebGL applet that enables shader testing and combining (up to 2 separate shaders) quickly and easily. Check it out! (requires browser with support for WebGL, such as newer versions of Google Chrome and Mozilla Firefox; only supports single-pass shaders at the time of this writing)

Here's a good picture to test with (320x240 resolution with point filtering, mimics raw SNES output):

UPDATE (5/30/11): Added shots of caligari's phosphor21x shader (a.k.a. caligari's scanlines in Screwtape's repo). UPDATE (6/3/11): Added Themaister's Dot 'n' Bloom, available from Screwtape's repo. UPDATE (6/18/11): Added caligari's scanlines - rgb triad. UPDATE (9/29/11): Added Themaister's phosphorish. UPDATE (11/22/11): Added edge detection and ALovelyBloom.

All images are taken at 3x scale, followed by that same image blown up 400% with no further interpolation. As always, click the thumbnails to embiggen.


This one uses an algorithm similar to HQ4x and it shows.


Unfortunately, this one's just a big flare-out on Super Mario World, but it looks pretty good on darker games, if you're into bloom. You can stack it with some other shaders to soften up phosphor effects and so on.

This is a multipass scanline shader from cgwg that also simulates an electron beam that takes longer to rise than to fall. It is perfect for producing the pseudo-hires transparency used in Kirby's Dreamland 3 and Jurassic Park. Sadly, it only works in emulators that support shader spec 1.1 (at the time of this writing, Themaister's SSNES and PS3 homebrew emus written by Dante Ali).


This one's pretty straightforward, using an algorithm similar to that of bilinear filtering (aka, 'smooth video'). It's a little sharper and preserves edges a little better.


This is the latest and greatest version of the collaborative CRT shader. The screen curvature is user-definable, based on changing a single value in the helpfully commented shader code. As you can see, it looks totally amazing. It also runs a lot faster than it used to, so give it a shot even if your machine couldn't handle it before.


This one is very closely related to the aforementioned CRT shader, only this one is optimized for weaker cards while only sacrificing a tiny bit of accuracy. If your machine can't run the full-fledged CRT shader, this one is your last good chance.

Dot 'n' Bloom

Another cool one from Themaister, Dot 'n' Bloom treats each pixel like a single, distinct dot and then adjusts its size based on brightness, such that brighter dots appear larger than darker ones, similar to a CRT electron beam (though this shader is not attempting to reproduce a CRT, it resembles one). He then added a bit of bloom to blend things together some. The results look really nice in motion (especially on Super Metroid :D) and the shader runs extremely fast.

Edge Detection

This one is more stylized than most of the others I've covered. As you might have guessed by the title, it finds the edges of colors and presents them as an outline. On SMW's cartoony, hard outlines, it makes a crazy quadruple outline.

Lanczos 4-tap

Another fairly straightforward interpolation filter, this one runs quite fast even on weaker hardware. You can learn more about the Lanczos algorithm and its use in resampling at the Wikipedia.

Lanczos 6-tap

As you might have guessed, this one is very similar to the 4-tap Lanczos, but it is further sharpened, which leads to the ringing/halo effect around sprites.


This multipass shader is the result of cgwg and Themaister porting blargg's awesome NTSC filter to GLSL. It looks quite nice and doesn't bog down the CPU like the regular filter version. Unfortunately, it only works on shader spec 1.1-compatible emus.

This is caligari's implementation of an algorithm originally written by xythen in Matlab, which served as the inspiration for the work that later became CRT.OpenGL. This shader builds on xythen's work to be essentially scale factor-independent, except it looks a little weird at 2x in my experience; everything larger looks great. An interesting note: the scanlines that appear with this shader are not simply added in. Instead, they are naturally occurring as a result of the phosphor simulation. Pretty cool stuff :D

By uncommenting some lines in caligari's code, you can enable one of three phosphor/shadow mask arrangements, of which the RGB triad option is the nicest (I recommend clicking these thumbnails to see in full size):

As you can see, this option causes some serious dimming of the picture brightness, which was also a technological obstacle for actual CRT engineers when shadow masks were first being designed and implemented. In bsnes, you should be able to just increase the gamma in the picture settings to compensate. You can download this shader variation from my mediafire account.


A simple, single-pass shader that makes a nice phosphor effect. This shader runs fast and works with both bsnes and SSNES. It is available here or in my mediafire.


This fast, crisp interpolation filter is totally new to the emulation scene. It's based on some fancy math demonstrated by Inigo Quilez and represents a good compromise between the pixelate2x and bicubic shaders.

Simple TV Blur

This one's rather subtle, but is intended to do the minimum amount of work required to reproduce the pseudo-hires transparency.

Just for fun, I used SSNES' shader stacking support to combine the new NTSC shader with the Beam4 shader. It's almost indistinguishable from Beam4 alone (except for some really slight changes to the color palette), so I wouldn't bother trying it yourself.


As above, I tried stacking the NTSC shader with the new CRT shader and this was the result. It's kinda cool in a way, like newsprint. :P According to cgwg, this is happening because it's only picking up the first pass of the NTSC shader, which has no color values.

CRT-Flat+Caligari's Scanlines - RGB Triad
When the regular CRT shader (edited to have 0.0 for the distortion value) is paired with caligari's scanlines - RGB triad variant, you end up with a pretty neat result:

The colors are off by a good bit (I think because of the double gamma correction) and it's very dark, but the phosphor triads from caligari's are still clearly discernible over the CRT shader's already-awesome result. Still not perfect, obviously, but getting close in a lot of ways.


Anonymous said...

I have been trying the CRT.OpenGL filter on Bsnes and it's absolutely wonderful. Great work!
I don't usually like to aks for these kind of things but could you make something similar for other emulators like Kega?
It's just too awesome to have it only on Snes emulators :)

Hunter K. said...

I didn't actually write these (though I did do some early work on the CRT shader), but they will work on any emulator that supports GLSL pixel shaders with a minimal amount of additional work (they would need to be separated into vertex and fragment files, and the uniforms would have to be changed away from bsnes' 'ruby' nomenclature). Rather than rewriting every shader to work on each separate emulator, though, we should just ask authors (like Kega's Steve Snake) to support the Shader Spec 1.1 that Screwtape and Themaister have been finalizing. Then shaders can be written once and work everywhere :D

Anonymous said...

That's great.
I might ask SteveSnake if it's still around.:)
Hope we got to see implemented in some other advanced systems like Playstation and Saturn emulators.

Anonymous said...

I'm sorry but none of my CRT ever looked like this :-(

1) scanlines are not meant to darken the picture like that, the surrounding pixels from the surrounding line actually keep their intensity and this intensity will make those blanked lines more or less visible depending on the pixel color, it's not so "regular".

2) phosphor does not look like that, here it looks like you put a grid filter on the image, everything is MUCH more blended on a real TV, also you don't see the pixels (or the R,G,B beam) separated like that, this is non-sense and uglier than the crappiest TV set

I agree that this looks better than pixelatized or blurry filtered picture when rendering lowres image to highres screens, but calling this wonderful or accurate is a little premature imo.

Hunter K. said...

Hi Anon,
As I mentioned in a comment on my other CRT shader post, if you look at cgwg/DOLLS' code, you'll see that their shader is based on some pretty heavy calculations derived from published whitepapers regarding CRT display technology, so the accuracy in that shader is pretty hard to argue with. caligari's phosphor/scanline code, on the other hand, is less accurate and more focused on producing a neat/pleasing effect.

As for #2, CRT TVs do literally have a grid drawn on them, known as the shadow mask, that significantly darkens the picture compared with the raw beam. Likewise, the phosphors are indeed separated into R,G, and B:

Reproducing the look/behavior of a CRT is still a burgeoning field, and these shaders represent the first baby steps in that direction. They will undoubtedly improve as more emulators implement support for multiple shader passes and LCD screen resolution increases to a point that shadow masks and CRT phosphors can be divided into LCD pixels without the interference/distortion of subpixel behavior.

If you'd like to contribute to the development of these shaders, check out the originating thread on the bsnes forums:

Hunter K. said...

@me not me
I'd love to help, but I don't really understand what you're asking.

Anonymous said...

please leave the post with my email I spamed apparently it is a bad "joke" from bad guys sorry and thanks for removing if possible.

Anonymous said...

Hi! Could you post a link to download the awesome CRT filter in the new BML format?
The link you posted takes me to a page with code, but I don't know how to compile that.

Thanks and keep the good work!

Hunter K. said...

Shaders are compiled on your video card at runtime, so just saving that code as CRT-BML.OpenGL.shader is all you have to do. Nevertheless, I went ahead and did that for you and updated the post with the new link :)

Anonymous said...

Thanks a lot! You're great :)

It's a shame this new release of Bsnes doesn't detect shaders anymore. I suppose you have to put them in the shaders directory, do you? I only have an option to blur in the shader options. Even after downloading your converted shader.

Also this new Bsnes crashes a lot when playing around with filters. Mmmm maybe I'll have to wait for the nex one?

Hunter K. said...

Yeah, you'll have to drop it into ~/.config/bsnes/shaders (on *nix systems) or %AppData%\bsnes\shaders (on Windows) to make it show up.

I've also noticed a lot of crashes when messing with filters/shaders on v083, but I haven't had time to look into it and find out why...

Anonymous said...

I have downloaded the BML version (CRT-BML.OpenGL.shader), but, contrary to other GLSL shaders, it seems to be doing nothing over here. No effects whatsoever on v084. Is it working for somebody else on this version?

Hunter K. said...

Hmm. I could have sworn it worked at some point, but I'm getting nothing here, either (Win32 compatibility build). I'll see if I can come up with anything...

Hunter K. said...

oh, duh: the BML version only worked with v083, apparently. It broke when byuu made the color changes in v084.

Anonymous said...

First nes-ntsc and snes-ntsc, then the crt-bml... I wonder if everybody likes both stacked on top of one another, though. Personally, I do, but perhaps other people would use just one or the other in the "golden quest" of recreating the ultimate nes- or snes experience.


Anonymous said...


I saw something over at the ngemu-forums today using BumpMap shaders with SNES Emulators. It's to bad I don't see more BumpMap shaders like the one, SimoneT made. I,ve tryed shaders with heavily blocky looking games that don't look all that great, but when I use a BumpMap shader it improves the sprites quite a bit.

I do hope there's going to be more, bumpmap shaders for SNES emulators in the future.

Anonymous said...

I doubt there is real practical use of this except for enjoying writing that Open GL whatever stuff itself. First the CRT's nanoseconds response times can never be matched by slow LCD technology so you never ever get smoothness of the CRT. Second to perfectly emulate various CRT artefacts, I am sure you need thousands and thousands of pixels. If you think yours 1600x1200 etc are enough, you are kinda out of reality.

Hunter K. said...

Hi Anon,
One practical use is to reproduce the pseudo-hires transparency used in several SNES games with byuu's bsnes accurate PPU emulation. You're 100% correct that these shaders can't impart any of the technical advantages of a CRT; they're purely aesthetic. As for the resolution requirements, you would probably need something like 10x scale (~2400p) to be able to draw the phosphors and shadow mask with individual LCD pixels, but cgwg (the main author for the CRT shader) already exploits subpixel behavior to get pretty close. I recommend reading over the CRT and Beam4 source code (the comments are extensive and informative) to see what's currently covered and what's still lacking.

Daninthemix said...

Have you seen the 4xSai plugin available for Kega Fusion? Combine that with Fusion's 25% scanline option and you have perfection.

Is there anyway someone could port this to the SNES emulators?

Unknown said...

How to port CRT shader to ePSXe shader? i tried but didnt work

Hunter K. said...

@Wojciech Olczyk,
There was some effort to port the CRT shader to Pete's OGL2 plugin in this thread:

You can read more about 'porting' them from Pete's format to XML here:

To go the other way, just do it all backward. :)

Unknown said...

[url=]Cred ca ai sa gasesti urmatoarele aplicatii foarte interesante.[/url]

[url=]I guess you'll find the following apps very interesting.[/url]

Hunter K. said...

Oh yeah, that's an awesome application! I wish it were open source, as they've done a lot of great work there.

Anonymous said...

Hello, can you please make one version of your shadder with the Curved TV view but without the NTSC/Scanlines? I really want this curved look, its awesome! thanks

Analytics Tracking Footer