Chasing rays and shading pixels

Chasing the perfect picture for retro consoles on modern flat-screen displays is a complex topic and is largely the reason why this website came into existence in the first place. We’ve written several articles on video processors and upscaling original hardware, but that doesn’t mean we’re against emulation. While emulating an older platform will always be an approximation of the actual hardware rather than a truly authentic experience, that’s not necessarily a bad thing, especially considering that a PC has much better compatibility with modern displays than retro consoles do.

In this article, I want to look at the recent CRT emulation pixel shaders. Efforts to make emulation look more authentic have been going on for several years. Around 2010 several individuals started to develop pixel shaders for emulators. These new techniques made use of the powerful graphical processing units in modern PC graphics cards to produce effects that go way beyond the usual scaling and processing available in emulators or video processors. The shaders are slowly but surely making their way into mainstream emulation, although currently it helps if you have a little technical know-how in order to get them working. Rather than show you screenshots of each shader in action, this page will show you how to configure them instead. Before we get stuck in, I should stress that I’m not a mathematician although I do have some programming experience. I would be lying if I said I understood exactly what was happening in the shader code I’m modifying, fortunately it’s not necessary to understand everything just to make the changes we need. If this all sounds like a lot of hoops to jump through, you might want to scroll down and see the results I got from the shaders I configured. Overall the improvement was leaps and bounds ahead of other upscaling techniques on the PC.


For our first example, we’re going to use BSNES and the CRT-interlaced shader. This shader works with both interlace and progressive (240/288p) games. First of all you’ll need BSNES, which you can download here. I use the “accuracy” version but it’s up to you, both versions work with the shaders. Once you’ve downloaded the file, unpack it to a directory anywhere on your hard drive. If you can’t unpack it, you probably need 7-zip, which you can get here. There’s also a handy-dandy set of tutorials for 7-zip here.

Once you have everything extracted, open the BSNES directory. Inside the folder there should be a sub-folder called “Shaders”. You can see this folder circled in red on the picture to the left. This is where we’ll be putting the next file we need. It’s time now to download the CRT-interlaced shader. Visit this page to obtain the latest version. Click on the tab in the top right of the page labelled “Raw blob data”. Your browsers download manager should then open. You need to save the file into your BSNES Shaders sub-folder. Once the file is downloaded, before BSNES will recognise the file as a shader, you’ll need to do a little renaming. By default the file is called “shaders_OpenGL_v1.1_CRT-interlaced.shader”. Rename that to “v1.1_CRT-interlaced.OpenGL.shader”.

At this point, you can fire up BSNES and see if you like the shader or not. Start the emulator, choose a ROM (that you are legally entitled to play, of course). Now, from the Settings menu in BSNES, choose Video Shader->v1.1_CRT-interlaced. A screen shot of the resulting image is shown below, click the picture for a bigger version:-


Okay, so the image certainly looks pretty cool, but there are a few things that you might want to change. The simulated CRT is actually sloping away from us. This might be how a CRT was in an arcade cabinet but I think most of us played our NES’s with a regular CRT television. To change any of these parameters, we need to edit the shader file we just downloaded. You can use Notepad for this, although if the text formatting is garbled you might want to seek out another editor. Arachnophilia is a powerful and free editor written in Java, it can be downloaded here.

Once you’ve opened your file in your editor, don’t be bewildered by the contents. Most of the code is commented and so is easy to figure out. It’s a good idea to save a backup copy of your shader before you tinker around with it, that way you can quickly switch between the two shaders and compare how they look. Let’s take a look at a few things you might want to change:-

Curvature:- If the default curvature seems a little too severe, it can easily be changed. Find line 189 (approximately), where you will see a comment (a line of code preceded by two forward slashes “//” is a comment, comments are ignored by the computer, they’re just for the programmers benefit). The comment should read “radius of curvature”. Below that, there’s a line that reads “R = 1.5;”. Try changing this to “R = 2.0;”, you can go higher still if you like, but go up in small increments.

Tilt:- If you don’t want the simulated monitor to tilt away from you, locate the comments that read “tilt angle in radians (behavior might be a bit wrong if both components are nonzero)”. Under that there is a line of code “const vec2 angle = vec2(0.0,-0.15);”. To eliminate tilt altogether, simply change this to “const vec2 angle = vec2(0.0,-0.00);”

Scanlines:- The default scanlines are too dark for my liking. Changing them isn’t as straightforward as changing the tilt or curvature, but I managed to figure it out. Incidentally, if anyone more knowledgeable than me sees that I’m changing the wrong bit of code do let me know in the comments section. Anyway, to change the scanline density, locate the block of code that begins “// Calculate the influence of a scanline on the current pixel.”. Now, scroll a bit further, there’s a line that reads “vec4 weights = vec4(distance / 0.3);” Increase this value slightly to make the scanlines lighter. For instance, make the value 0.35, 0.4 at the very most. If you go much higher you will end up with no scanlines and a blurred image.

Here are the results of the tweaks discussed above. Click the picture for a bigger version:-

Mario Bros with the tweaked CRT emulation


For me, this is now the perfect image and much cheaper than trying to RGB mod a NES console. Now you have SNES and NES emulation configured, you can take what you learned and apply it to other emulators too. Your emulator simply has to support OpenGL or DirectX (HLSL) shaders. (We’ve recently added a guide for Retroarch and Gameboy Advance emulation, which you can read here). Enjoy your perfect looking NES and SNES games!

Back from OpenGL/DirectX Pixel Shaders to Home Page

One thought on “Chasing rays and shading pixels

Leave a Reply

Your email address will not be published.