A while ago, based on TheMaister’s work, I made a collection of shaders to display old-school 2D graphics with sharp pixels, no distortion, and minimal blurring.
In particular, the sharp-bilinear-simple shader was included. I recommend this shader with all games that display low-resolution 2D pixel graphics to achieve optimum image quality.
Sharp-bilinear-simple does an automatic integer pre-scale (2x, 3x, 4x, etc.), depending on the game and screen resolution. The pre-scale is done using point filtering with no blurring. Only the final scaling, if any is necessary after the pre-scale has already been applied, is then done using linear filtering. This produces sharp pixels with zero pixel wobble and minimal blurring in all 2D games regardless of output resolution.
Compared to a simple linear filtering that smoothes the pixels (“video smoothing=ON”), pixels are much less blurry with this shader. Compared to point filtering without smoothing (“video smoothing=OFF”), the pixels do not change shape or wobble as they move across the screen.
Here is an example image with the sharp-bilinear-simple shader switched on:
Here is an example with shaders off and smoothing on (too much blur):
Here is an example with shaders off and smoothing off (it looks sharp at first):
On first glance, the above seems to look sharp and good. You might think a shader is not necessary. But looking at the picture in detail, we can see the pixel wobble that happens when no shader is used. The pixels on the black diagonal (circled) should all be the same square shape. Instead, some of them appear rectangular and quite distorted:
Compare the above detail to the result with the shader on:
Now all pixels have the same shape, at the cost of a slight reduction in sharpness.
The calculations done by sharp-bilinear-simple are trivial. Using it with RetroPie on a Raspberry Pi 3 in 1080p full HD resolution, Street Fighter 3 Third Strike (libretro-fba) runs at a steady 60 fps. Since this is a pretty taxing game to emulate, I don’t think enabling the shader can cause slow-down in any games, at least not on Raspberry Pi 3.
Improvements to TheMaister’s Original “retro/sharp-bilinear”
- There’s a small improvement that makes sharp-bilinear-simple work better with vertical games (shmups etc.). The autoscale is calculated separately for both the horizontal and vertical dimension, e.g. the integer prescale could be 4 for the horizontal, and 2 for the vertical. The original sharp-bilinear only used the vertical dimension to calculate the auto-prescale, and then used the same integer for both x and y.
- The autoscaling factors are pre-calculated in the vertex shader, instead of re-calculating for every pixel.
- The sharp-bilinear-2x-prescale shader configuration, only included in the package for RetroPie and Retroarch, is even less computationally intensive than the sharp-bilinear-simple shader. It is just a shader config that applies two passes of the stock.glsl “Null shader,” with different filtering settings. It contains almost no calculations and should be extremely fast.
The shader is available on Github. It was recently included in Retroarch and Retropie where it can be enabled in the configuration menus. It was also added to FrangarCJ’s vita-shader-collection for the PS Vita, and can be enabled in several emulators such as UAE4all2 for Vita, ScummVM for Vita, and Cpasjuste’s excellent arcade emulator PFBA for Vita. The shader is also automatically enabled in the Vita games SDLPoP-Vita, SDLPal, and Bermuda.
Sharp-bilinear-simple relies on hardware filtering. In ScummVM for Vita “video smoothing” has to be on and in PFBA for Vita “filter: linear” has to be set for the shader to work correctly. In addition, the shader has to be selected. It is sometimes called “sharp,” or “sharp-simple” in the shader selection menu.
Until next time,