common-shaders: the Cg filter pack every libretro emulator backend is expected to support
Collection of commonly used Cg shaders. These shaders are usable by either HLSL and/or Cg runtime compilers. The cg2glsl script will translate most of these into GLSL shaders.
At a glance
- What is it?
- The libretro common-shaders package is a collection of pixel shaders for old school emulators, written in Cg so the same source runs under OpenGL and D3D, and paired with a config-based meta-shader format for combining passes. RetroArch, the SNES9x Win32 port, and OpenEmu are named as implementations of the specification.
- Who is it for?
- common-shaders fits a team writing an emulator front end that wants the familiar CRT, scanline, upscaling, and anti-aliasing filters without writing shaders from scratch, and that is prepared to implement the uniform and texture conventions the spec requires. It is the wrong choice for a hardware-accelerated modern pipeline that would rather use GLSL directly, and the wrong choice if you need a single licence covering the whole collection.
- Can I use it commercially?
- Not without permission. GitHub finds no licence file in the repository, and without a licence all rights are reserved by default: you may read the code but not reuse it. Check the README, or ask the authors, before using it.
- Is it still maintained?
- Activity is slowing. The repository last received commits 6 months ago.
- What is it written in?
- Mainly C, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on October 23, 2026, and from our analysis. They are not legal advice.
Editorial analysis
A shader spec, not just a shader pile
This is a package of pixel shaders intended for old school emulators, with copyrights held by the respective authors. The shaders are coded in the Cg language, suitable for both OpenGL and D3D, and most of them are converted from other languages such as GLSL, FX, and HLSL.
The important framing is in the next line. The shaders all follow a convention which must be followed by the implementer of an OGL or D3D backend. That is a specification, and the repository is as much the definition of the contract as it is a set of files.
The known implementations of this spec are listed as RetroArch, the SNES9x Win32 port, and OpenEmu. Three implementations is a small but meaningful number. It means the convention has survived contact with more than one codebase, which is the only real test of a convention, and it means the shader collection is portable in a way that a single application's shader folder would not be.
The Cg choice is the enabling decision. Cg is a shading language that compiles to both OpenGL and Direct3D, so one source file covers both backends. That matters here because emulator front ends are exactly the kind of software that has to run on more than one graphics API, and writing every filter twice would double the maintenance for a collection this size.
The conversion history is worth noting as well. Most of these shaders are converted from other languages, so the collection is a porting effort layered on top of work done elsewhere, and the shaders that feel most native to one graphics API are the ones most likely to have lost something in the conversion.
The uniforms are the contract, and they are deliberately odd
The specification of the interface is where the difficulty lives, and it is worth reading the details because they are the reason a naive implementation produces a broken image.
The entry points are fixed: `main_vertex` for the vertex stage and `main_fragment` for the fragment stage. Every shader works on texture unit 0, the default, and 2D textures must be used. Power-of-two sized textures are recommended for optimal visual quality.
The texture coordinate origin is defined to be top-left oriented, so a texture coordinate of (0, 0) will always refer to the top-left pixel of the visible frame. The implementation must always ensure that this ordering is held for any texture that the shader has access to. The summary says plainly that this is opposite of what most graphical APIs expect, and it is the single most common source of a vertically flipped or mirrored emulator output.
The second rule is the border mode. Every texture bound for a shader must have black border mode set, meaning sampling a texel outside the given texture coordinates must always return a pixel with RGBA values of (0, 0, 0, 0). A shader that samples beyond the edge of the video area, which many of them do, gets garbage without this.
The uniform struct is named `input`, with members `video_size`, `texture_size`, `output_size`, `frame_count`, and `frame_direction`. The `IN.video_size` is the size of the actual video data in the texture, for instance (256, 224) for normal resolution SNES frames. `IN.texture_size` is the size of the texture itself, optimally power-of-two. `IN.output_size` is the size of the video output, the viewport shown on screen. `IN.frame_count` is a counter that increases by 1 every frame, and it is really an integer but needs to be a float because Cg lacks integer uniforms. `IN.frame_direction` should be 1.0 for regular playing and -1.0 while the game is rewinding. The vertex shader also needs `modelViewProj` set to the current MVP transform.
The generic fragment entry point signature in the spec is a float4 returning `COLOR`, with texture coordinates in TEXCOORD0 and a sampler in TEXUNIT0. The spec also warns that although COLOR0 is legal, no data of interest is passed there and you cannot assume anything about data in that stream.
Meta-shaders combine passes without editing the shaders
The.cg files themselves contain no metadata necessary to perform advanced filtering, and they cannot process an effect in multiple passes, which is necessary for some effects. The CgFX format does exist, but it would need current shaders to be rewritten to an HLSL-esque format, and it suffers a problem mentioned below.
The solution is a config file based format rather than putting everything into one file in an XML shader format. The stated advantages are concrete. There is no need to rearrange code in one big file, which greatly helps testing shader combinations. A large library of.cg files can be used to combine many shaders without needing to redundantly copy code over. And it is possible to unit-test every pass separately.
The format is key = value, with values containing spaces wrapped in quotes, no ini sections, and comments prefixed by the hash character, either on their own line or at the end of a key = value pair.
The meta-format has four purposes. It combines several standalone.cg shaders into a multipass shader. It defines scaling parameters for each pass, so an HQ2x shader might want to output with a scale of exactly 2x. It controls filtering of textures, since many shaders want nearest-neighbor filtering and some want linear. And it defines external lookup textures, since shaders can access external textures found in.tga files.
The parameters follow the same pattern. `shaders` is an integer defining how many.cg shaders will be loaded, at least one, with the paths in `shader0`, `shader1` and so on, relative to the directory the meta-shader was loaded from. `filter_linearN` is a boolean per pass controlling how the input to pass N is filtered, with N = 0 affecting how the initial pass samples the raw input frame and N = 1 controlling how pass 1 samples pass 0's output, and the filtering option is implementation defined if the value is not given. `float_framebufferN` decides whether shader N should render to a 32-bit floating point buffer, which only takes effect if shader N is actually rendered to an FBO and is useful for shaders storing values outside the [0, 1] range. `frame_count_modN` applies a modulo to `IN.frame_count`. And `scale_typeN` is a string, with the values including "source" for the output.
The `nearest.cgp` and `bilinear.cgp` files at the repository root are the simplest examples of the format, and the `cgp/` directory holds the meta-shaders.
Folders are the taxonomy, and there are a lot of them
The shader genres are sorted into folders, and the top level of the repository is effectively the index.
The categories are described in the spec. The 2x-classic folder holds the typical classic filters usually run on CPU, such as HQ2x, 2xSaI, and SuperEagle, converted into shaders. The Blur folder focuses on blurring the output image. The Enhance folder focuses on enhancing image quality through other means than blurring only. The TV folder focuses on replicating the visual image of a game running on a CRT screen. The Misc folder holds shaders that do not fit the above categories. And the Meta folder contains the meta-shaders in the.cgp format.
Looking at the actual directory listing, the collection is much larger than those five categories. There are `anti-aliasing/`, `auto-box/`, `bicubic/`, `blurs/`, `borders/`, `crt/`, `ddt/`, `denoisers/`, `dithering/`, `eagle/`, `gpu/`, `handheld/`, `hqx/`, `include/`, `interpolation/`, `misc/`, `motionblur/`, `mudlord/`, `nedi/`, `neon/`, `ntsc/`, `pal/`, `quad/`, `reshade/`, `sabr/`, `scalefx/`, `scalehq/`, `scalenx/`, `sharpen/`, `srgb-helpers/`, `warp/`, `waterpaint/`, `windowed/`, `xbr/`, `xbrz/`, `xsai/`, and `xsoft/`.
The named ones are recognisable to anyone who has touched emulator video. `crt/` is the curved-tube look. `ntsc/` is the composite video simulation. `ddt/` is the Directional Diffusion, a smoothing technique. `xbr/`, `xbrz/`, and `xsai/` are the well known upscaling families. `sabr/` is an alternative scaling filter. `reshade/` is for post-processing. `srgb-helpers/` and `include/` are support rather than effects.
The flat files at the root are the two base filters plus the stock shaders. There is `stock.cg`, `old-stock.cg`, `nearest.cgp`, and `bilinear.cgp`, which is the plain input path.
The practical consequence for a backend implementer is that the folder structure is a compatibility surface. A frontend that supports common-shaders has to support the whole convention, because a user will point it at any of these folders and expect it to work.
The install is a copy into a share directory
The build system is minimal, and the reason is that the package is data rather than code.
The Makefile has a `PREFIX` of `/usr` and an `INSTALLDIR` of `$(PREFIX)/share/libretro/shaders/shaders_cg`, which is the libretro shader directory on a Unix system. The `all` target does nothing but echo that there is nothing to make for common-shaders, which is an accurate description of a repository of shader files and a config script.
The `install` target creates the directory, copies everything with `cp -ar -t`, and then removes two files from the installed copy:
install:
mkdir -p $(DESTDIR)$(INSTALLDIR)
cp -ar -t $(DESTDIR)$(INSTALLDIR) *
rm -f $(DESTDIR)$(INSTALLDIR)/Makefile \
$(DESTDIR)$(INSTALLDIR)/configureThe Makefile and the `configure` script are removed because they are build-time artefacts, not shader content, and shipping them into a shader directory would be clutter. There is a `test-install` target that does the install into `/tmp/build` with a DESTDIR override, which is how the package is smoke tested without touching the real system.
The `configure` script at the repository root is the Cg compiler toolchain setup, and the `compat_includes.inc` file is there for compatibility with older shader sources. The `python/` directory and the `test/` directory are for the tooling and the test harness.
The `cg2glsl` script mentioned in the project description is the translator that converts most of these shaders into GLSL, which is the practical escape hatch for a backend that does not want to ship a Cg compiler. The `docs/` directory holds the documentation, and the `.gitlab-ci.yml` shows the project's CI runs on GitLab rather than GitHub.
Where common-shaders is the wrong tool
The limits are clear, and several of them are about the age of the approach.
First, Cg is a legacy choice. The Cg toolchain is no longer a first-class part of any modern graphics stack, and shipping a runtime that compiles Cg means shipping a compiler alongside your application. The cg2glsl translator exists precisely because that is a burden, and a modern project that has a shader build step would rather write GLSL directly and have one source of truth, rather than maintain Cg sources plus a conversion step plus the risk of the conversion losing something.
Second, the specification is demanding to implement. Top-left texture origin, black border mode on every bound texture, a fixed uniform struct, the frame count as a float, the frame direction for rewind support, and the two entry point names. Every one of those is a place where a partial implementation produces a subtly wrong image rather than an error. A team that has to implement the spec from scratch is doing real work before it gets any of the filters.
Third, and this is the licensing point to be careful about, the summary states that copyrights are held by the respective authors, and the repository listing gives the licence as unknown. A collection assembled from many sources by many authors does not have one blanket grant. If you are shipping these shaders inside a product, you need to establish per-shader provenance, and the summary tells you most were converted from GLSL, FX, and HLSL, which means the upstream terms travel with them. That is a real obligation and it is not something the folder structure helps with.
Fourth, the collection is presentation, not emulation. These shaders run after the emulator has produced a frame, and they are pixel filters operating on a texture. They cannot make an emulator faster, they cannot fix timing, and they cannot add features the emulator does not have. A team looking for better performance in the emulator core is looking in the wrong place.
Fifth, the collection is old in the sense that matters. The last push to the repository was on 2026-04-11, and the implementation list names three front ends, one of which is a Win32 port of SNES9x. The shaders still work, because they are small and the conventions are stable, but the project is not where new shader techniques are being developed, and a team starting fresh in 2026 would likely find newer GLSL-first collections to work from.
Editorial conclusion
common-shaders fits a team writing an emulator front end that wants the familiar CRT, scanline, upscaling, and anti-aliasing filters without writing shaders from scratch, and that is prepared to implement the uniform and texture conventions the spec requires. It is the wrong choice for a hardware-accelerated modern pipeline that would rather use GLSL directly, and the wrong choice if you need a single licence covering the whole collection. Check three things before you depend on it: that your backend can honour the black border mode and the top-left texture origin, since the spec requires both and a shader will look wrong without them, that you are using a runtime that still compiles Cg, and that you check the per-file authorship, because the summary states the copyrights are held by the respective authors rather than by one entity.
Frequently asked questions
What is the libretro common-shaders package?
It is a package of pixel shaders intended for old school emulators, written in the Cg language so the same source is suitable for both OpenGL and D3D. The shaders all follow a convention that must be followed by the implementer of an OGL or D3D backend, and RetroArch, the SNES9x Win32 port, and OpenEmu are listed as known implementations.
What conventions must a backend implement to support common-shaders?
The entry points are `main_vertex` and `main_fragment`, all shaders work on texture unit 0 with 2D textures, the texture coordinate origin is top-left oriented which is opposite to what most graphics APIs expect, and every bound texture must have black border mode set so sampling outside the coordinates returns RGBA (0, 0, 0, 0). The fixed uniform struct is named `input` with `video_size`, `texture_size`, `output_size`, `frame_count`, and `frame_direction`.
What is the Cg meta-shader format used for?
It combines several standalone .cg shaders into a multipass shader, defines scaling parameters for each pass, controls texture filtering, and defines external lookup textures in .tga files. The format is a config file of key = value pairs with no ini sections and hash-prefixed comments, with parameters such as `shaders`, `filter_linearN`, `float_framebufferN`, `frame_count_modN`, and `scale_typeN`.
How do I install the common-shaders package?
The Makefile installs into `$(PREFIX)/share/libretro/shaders/shaders_cg` with a PREFIX of `/usr`, copying the files and then removing the Makefile and configure script from the installed copy. The `all` target does nothing but report that there is nothing to make, since the package is shader data rather than compiled code.
Official sources
Add this badge to your README
If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.
[](https://hysenlabs.com/projects/libretro-common-shaders)Was this useful?