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):

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.

4xBR

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

ALovelyBloom

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.

Beam4

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).

Bicubic

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.

CRT.OpenGL

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.

CRT-simple.OpenGL

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.

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.

NTSC

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.

Phosphor21x

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.

Phosphorish

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 one's rather subtle, but is intended to do the minimum amount of work required to reproduce the pseudo-hires transparency.

Beam4+NTSC

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.

CRT+NTSC

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.

23 comments:

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 :)

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

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.

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:http://en.wikipedia.org/wiki/Shadow_mask

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:http://board.byuu.org/viewtopic.php?f=10&t=147

@AnonShaders 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 :)

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?

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?

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.

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.

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.

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.