CRT Scanline shader for SNES Classic Mini?


Sorry, I’ve only done this version for the the SNES Classic. It’s not nearly fast enough for curvature. I might look into adding it to my RetroPie version which is nicer than this shader already.


Do you have a rough estimate of how much faster the RPi’s GPU is than the SNES Classic’s?


It’s pretty close to being that if a RPI3 can do it at 1080p then the SNES Classic can do it at 720P. Give or take ~3 fps depending on exactly what your code does. And then if you use a fullscreen overlay, then that sucks up enough performance that a 60fps shader on the pi might not be at 720p on the SNES.

The reason this shader basically only works at 3x integer scaling isn’t for speed. It’s because the Mali 400 precision issues prevented me from using a polynomial/Gaussian function for the scanline profile (I’d get artifacts part way through the screen no matter what) and the low resolution forced me to use integer scaling for even looking scanlines.

When I get off work I can test your shader in “Another fast CRT shader” on the SNES Classic and let you know how it does. If that’s why your asking :slight_smile:. My experience with the SNES Classic thus far suggests that something ugly will happen though. Probably the mask won’t render correctly at the very least. But who knows? Your shader does look pretty nice!


heh, yeah, that’s what I was curious about :slight_smile:

And yeah, these mobile GPUs are always a crapshoot. Something that works on one breaks on another… Desktop GPUs are a little better, but not by much.


Here you go. These should be the defaults of ‘fakelottes’ with curvature off. By toggling options, I can tell you that the problems on the bottom section are precision issues in the scanline calculations and the problems on the rightmost section are precision issues in the the mask calculations. And turning off integer scaling so that it renders more pixels drops it from 37.4 to 32.8fps. But some of the masks are faster: option 2.0 runs at 49.9fps.

Also, the Mail 400 shader compiler says your fragment shader runs in 20 clock cycles. For reference mine takes 12cycles and will drop below 60fps with the SNES border overlays if I make it take 13 or 14 cycles. Which is kind of a bummer because I like the shadow mask effect from Lottes shader.


And just because I haven’t posted any new images of what’s included in my newest upload. This is what you’d get:


lol jesus, fakelottes looks terrible. That precision stuff is a dealbreaker. Thanks for testing, though!

yeesh, 12 cycles is pretty limiting. Yours looks quite nice, nevertheless! Good stuff :slight_smile:

[oh no, I just realized I’m older than Marge :confused: ]


Any update on this SoltanGris42?


Not really. I’m not sure really what to add from here. Everything I want to run looks about as good as I can manage.

I was kind of waiting around for a new hakchi release and/or retroarch hmod package. That way I could take a better shot at implementing the way the SNES UI triggers the shaders and associated settings since I have to overwrite some of their files. The UI works now, but the script mods should be written nicer/better. But hakchi and it’s packages haven’t really gone anywhere the way I thought they would as far as bug fixes and such.

However, if anybody has any problems with these shaders/packages that you’d like me to look at, I’d be happy to.


So any progress update on the RetroPie version?


Actually yes. I fixed several bugs and changed a few things around. I haven’t touched in a at least a month though because I was using my rpi3 on an actual CRT with a retrotink. I’ll double-check some stuff tomorrow and post a newer version.


I posted an update in the RetroPie forum here:

If you just want the files, go here:

I don’t want to post more off-topic (retropie stuff) in this thread. But I’ll try to get another post together for this board with links to my shaders for the pi3.


Thanx for the awesome shader. I have a noob question… How can I take the elements that i like out of one shader and use it in another? My go to shader has been crt-caligari because of the slight blur it gives the pixels. It is the closest to the magfilter 2, horizontal linear filter in canoe. But you cant set how dark the scanlines are like you can in this and other filters. I already tried to create variables in caligari that would change scanline strength but i failed. Id like to take the horizontal and vertical blending portion of caligari and add it to your shader. Any help would be appriciated.

CODE from crt-caligari

void main()
vec2 coords = ( vTexCoord * SourceSize.xy );
vec2 pixel_center = floor( coords ) + vec2(0.5, 0.5);
vec2 texture_coords = pixel_center *;

vec4 color = TEX2D( texture_coords );

float dx = coords.x - pixel_center.x;

float h_weight_00 = dx / SPOT_WIDTH;
WEIGHT( h_weight_00 );

color *= vec4( h_weight_00, h_weight_00, h_weight_00, h_weight_00  );

// get closest horizontal neighbour to blend
vec2 coords01;
if (dx>0.0) {
  coords01 = onex;
  dx = 1.0 - dx;
} else {
  coords01 = -onex;
  dx = 1.0 + dx;
vec4 colorNB = TEX2D( texture_coords + coords01 );

float h_weight_01 = dx / SPOT_WIDTH;
WEIGHT( h_weight_01 );

color = color + colorNB * vec4( h_weight_01 );

// Vertical Blending
float dy = coords.y - pixel_center.y;
float v_weight_00 = dy / SPOT_HEIGHT;
WEIGHT( v_weight_00 );
color *= vec4( v_weight_00 );

// get closest vertical neighbour to blend
vec2 coords10;
if (dy>0.0) {
  coords10 = oney;
  dy = 1.0 - dy;
} else {
  coords10 = -oney;
  dy = 1.0 + dy;
colorNB = TEX2D( texture_coords + coords10 );

float v_weight_10 = dy / SPOT_HEIGHT;
WEIGHT( v_weight_10 );

color = color + colorNB * vec4( v_weight_10 * h_weight_00, v_weight_10 * h_weight_00, v_weight_10 * h_weight_00, 
v_weight_10 * h_weight_00 );

colorNB = TEX2D(  texture_coords + coords01 + coords10 );

color = color + colorNB * vec4( v_weight_10 * h_weight_01, v_weight_10 * h_weight_01, v_weight_10 * h_weight_01, 
v_weight_10 * h_weight_01 );

color *= vec4( COLOR_BOOST );

FragColor = clamp( GAMMA_OUT(color), 0.0, 1.0 );


Love this shader. So far it seems like the best balance between picture quality and cost. I’m wondering if the following features could be added to make the shader even better:

-To be able to increase the scanline beam width variability. Check out CRT Hyllian’s beam width options for an example of what I’m talking about. I’d like to see thicker scanlines (black lines) over dark colors and thinner scanlines over brighter colors.

-To replace the aperture grille effect with a shadowmask / dotmask.


Please keep on working on ZFAST shader, and please continue to make other shaders for the SNES Classic. If you haven’t thought of it yet, you should start a post on r/snesclassicmods and r/miniSnesmods forums on Reddit. It would get more people in the SNES Classic scenes aware of your shader.


I used the following settings.

70, 60, 90, 0, 40, 40.

There’s still some degree of a “ruffles potato chip” effect, but it’s only really obvious on bright white colors and some greens.


I tested the shader on an old Android device with Mali 400 gpu and runs almost full speed (55-58 fps with threaded video disabled-display maximum is 58hz) at 1024x600 resolution. Surprising that worked a charm on non-integer scale too with even scanlines.