Thursday, May 3, 2018

Shaders for Low-Power Machines

This started out as one big post with a bunch of new and new-ish shaders, but I decided to bust it up and hopefully make this a little more useful and focused. Be sure to check out the next post for some more fun shaders.

While there's no shortage of heavy-weight, gorgeous shaders that will make even a modern gaming GPU howl, a lot of people use older machines, single-chip computers (such as Raspberry Pis) and machines with integrated graphics that simply don't have the grunt to take on those hefty shaders. It can be tedious digging through the hundreds of shaders available to try and find the few that might work on lower-powered GPUs, so I wanted to present a few of those here.

As always, click the thumbnails to to embiggen.

Lightweight CRT Shaders
bparker created these shaders with the goal of bringing some of the more popular CRT effects to even a "potato" of a computer. They work by tiling a tiny lookup-texture across the entire screen.
The 'cool' version has a bit of a blue tint to it, but this can be helpful in making purple stuff, like the sky in Super Mario Bros and the water in Secret of Mana, a little bluer:
The 'warm' version is patterned after the 'kurozumi' preset for CRT-Royale:
Written by SoltanGris42, this shader is intended to run full speed on and work around some of the GPU quirks of the SNES Mini/Classic and can also reach full speed on a RPi3 at resolutions of up to 1920x1080 or even 1600x1200:
CRT-Lottes is a great shader, but the bloom and scanline effects are a too much for many weaker machines, so I took the beautiful mask code and combined it with a basic scanline shader to produce something that's still reasonably handsome and should run full speed on a RPi3:
It's also worth noting that fakelottes' scanline code looks pretty decent even at non-integer scales.


I think I've covered this one--written by davej--before, but it's worth mentioning again because it looks great and is designed specifically around the constraints of the Raspberry Pi GPUs (RPi1, RPi2 and RPi-Zero need to be overclocked for 1080p/60):

LCD Grid
Another lightweight shader from SoltanGris42, this shader does nearest-neighbor scaling and then darkens the border pixels to mimic a low-res LCD pixel grid. The thickness and darkness of the grid are adjustable:
From jdgleaver, this shader is mostly intended for use with non-backlit systems, like the original Game Boy, Game Boy Color and Game Boy Advance, but it looks cool with pretty much anything. It uses the line-weighting equation from zfast-LCD but adds a lot of nice options and a cool background texture effect:

Basic Scanlines
RiskyJumps and I had similar inspiration for these shaders: what is the essence of a scanline effect?

Requring just a bare handful of GPU cycles to process, this shader just draws a vertical sine wave across the screen, which makes for a pleasant, rounded scanline effect that looks pretty decent even at non-integer scales:
In contrast, my scanline-fract shader looks just awful at non-integer scales. However, it scales up nicely to any integer and draws even black lines (or as dark as you please) across the screen with any thickness (in pixels) you choose. The default thickness is a half-pixel, but you can make them thinner or thicker:

I don't know if this shader will run on an RPi3 or not, but it's certainly very fast. By leaving out the pixel rasterization step, aliaspider was able to get sharp edges at any scale and without the computation burden of that process. On my crummy office workstation GPU (a Radeon 200-series), it gets well over 1,000 frames per second. Even so, it looks great and has the fantastic edge/corner detection of the xBRZ filter/shaders (look at that circle-c!):

Sharpest Pixels
While "Pixellate" is the perennial favorite for this task--that is, getting the absolute sharpest pixels without having the uneven pixel sizes associated with nearest-neighbor at non-integer scale factors--some GPUs are just too slow for the many texture samples required for it. I'm not going to show any images here because there's not much to see, but the sharp-bilinear shader prescales the image with nearest-neighbor to the largest integer and then uses bilinear scaling for the remaining fractional scaling. Since it uses the GPU's built-in scaling hardware, it's practically free. In fact, you can do the exact same thing manually by putting in a pass of the stock shader at the desired integer scale and then scaling the rest of the way with bilinear (if bilinear filtering is disabled, you can do this explicitly by setting another stock pass with "don't care" for the scale factor and "linear" for the filtering method).


Anonymous said...

Hello man. Are these glsl or cg? Where can we find them? Any chance to covert to cg also? Because some machines (old) work better with d3d.

Hunter K. said...

These are GLSL and slang, for the most part, but that's a good point. I'll try to get some converted to Cg/HLSL, as well.

Anonymous said...

Love Scanlines-Sine-Abs and zfast CRT/lcd.

Anonymous said...

The shaders are common for all versions of retroarch? If I update online the shaders_cg I will find if you updated if I use e.g. version 1.3?

Hunter K. said...

Yes, the shader spec has been unchanged for a very long time.

I finished porting the zfast shaders and will try to get them uploaded soon-ish.

Anonymous said...

The absolute lightest I have seen is the old / glsl. Runs 60 fps on shitty netbooks with gma3600! With setting brightness 0.95, sine a 0.05 sine b 0.25. A must be the mask, B the scanlines darkness and brightness the overall brightness of the image as I understand after tweaking. Its not crt-geom but is OK for such crap cards.

Analytics Tracking Footer