I’ve just released Shader Minifier 1.1. You can download the binary at the usual place.


  • New output options: use --format js to generate a Javascript file, and --format c-array to get a comma-separated list of strings (to be included in a C array).
  • Use the new option --no-renaming-list if there are identifiers you don’t want to get renamed (e.g. entry point functions in HLSL)
  • If you have #define macros, Shader Minifier will now avoid conflicts between macros and identifier renaming.
  • If your code has conditions with compile-time known values, they will get simplified (e.g. if (false), or int i_tag = 2; if (i_tag < 4) ...).
  • If there are many identifiers in your code (this probably won’t happen in a 4k intro), Minifier will now use 2-letter names if needed. This is not correctly optimized, but some people use this tool for obfuscation, instead of size-optimization.
  • The option --preserve-all-globals won’t rename any global variable or any function. This is useful if your shader is split between multiple files.
  • You can now tell the Minifier not to parse some block of code. Put your code between //[ and //] and it won’t be parsed, identifiers won’t be renamed, but spaces and comments will still be removed. This is very useful if you want to use features not yet supported in the tool (e.g. forward declarations, or layouts).
  • Other fixes in the parser (macros can be used in a function block, numbers can have suffixes, etc.)
  • Unix support. Use this zip file instead of the standard release, install a recent version of Mono (at least 2.10) and run mono shader_minifier.exe. This should work.
  • Online Minifier. You can use shader minifier online, but only one shader at a time.

Who is using it?

During the last year, many great intros have used it with great success.

  • Another Theory, by FRequency (#1 at Main 2010)
  • white one by Never (#1 at the Ultimate Meeting 2010)
  • anglerfish by Cubicle (#1 at Assembly 2011)
  • RED by BluFlame (#1 at Evoke 2011)
  • akiko by flopi (#2 at Riverwash 2011)
  • fr-071: sunr4y by farbrausch (#1 at Sunrise 2011)

Since last release, the number of users of GLSL Minifier has increased, while number of bug reports decreased. I think it’s a good reason to move to version 1.0. This obfuscator has been used in a few great intros, such as Another Theory (winner at Main) and White one (winner at tUM). Hopefully we will see many intros using it at Revision.

The main feature of this release is the support for HLSL obfuscation, so we’ll now call this tool “Shader Minifier”. I got pretty good results with it, and I’ve been able to reduce the size of some famous 4k intros. Renaming strategy has been improved a bit; Detailed statistics will come later.

Try it now, download Shader Minifier!

  • HLSL Support. Please use –hlsl flag.
  • in/out now behave like uniform on global values (requested by several people), you can choose to preserve them.
  • Information on console output is removed unless you use -v (verbose).
  • Spaces in macros are now stripped (thanks to @lx!).
  • New flag –no-renaming to prevent from doing renaming.
  • Various fixes and improvements.

The new version of our tool is released! Here is the changelog:

  • Allow forward declarations in the input code and remove them (functions are automatically reordered). Please use the syntax “int foo(int x)” and not “int foo(int)”.
  • More intelligent renaming based on the context the variable is used.
  • Allow structs in source code, fields are not renamed. Field names cannot look like vec fields (.rgb, .r…) because I haven’t written the typer yet.
  • Remove the –macro-threshold option. Will be fixed in a future version.
  • As usual, several bug fixes

The most important news is the improvement on the renaming strategy. In the 0.4 version, the Minifier tried to reuse the same variables again and again, and increased the frequency of a few characters. Now, it’s getting more complex: the name of a variable  depends on how it is used.

For instance, if you often call functions “max” and “mix”, you’ll often have the “x(” pattern. Thus, GLSL Minifier will probably name your function x to increase of the frequency of this pattern. The same goes for each two-char pattern the tool will find.

Here are some statistics I’ve just made, using shaders from 4k intros. I’ve taken a short C file, inserted the shader as a string, compiled, and compressed using Crinkler (/COMPMODE:SLOW /ORDERTRIES:3000). So, it’s all about making the shader compress better. Numbers are the filesize in bytes:

  • Retrospection
    • Original: 1462 (hand optimized)
    • Minifier 0.4: 1429
    • Minifier 0.5: 1421
  • Valleyball
    • Original: 2240 (using old BluFlame minifier)
    • Minifier 0.5: 2184
  • Another theory
    • Original: 1511 (hand optimized)
    • Minifier 0.4: 1475
    • Minifier 0.5: 1463
  • Lunaquatic
    • Minifier 0.4: 2635
    • Minifier 0.5: 2613
  • Sult
    • Minifier 0.4: 1411
    • Minifier 0.5: 1408
  • Slicesix
    • Minifier 0.4: 2493
    • Minifier 0.5: 2432

Conclusion: If you’re not using any tool to minify your GLSL shader, I bet you could save at least 20 bytes on your 4k intro. Try and see!

=> GLSL Minifier 0.5

I’ve just fixed a few bugs in GLSL Minifier. Here is the list of changes for the 0.4.2 version:

  • Smaller file to download (700kb instead of 1.8Mb), using MPress. Thanks eyebex!
  • Print -.5 instead of -0.5. Thanks to stan_1901!
  • Parse octal and hexadecimal numbers. Bug found in Valleyball source code, thanks BluFlame!
  • Can compress several shaders at once, but only if the –preserve-externals flag is set.
  • Reorder uniform/varying/attribute declarations. This reduces the size of some shaders.
  • Fix a bug where the order of instructions was messed-up. Thanks to XT95!
  • Fix the –macro-threshold option. Thanks to Řrřola!
  • Forbid the reusing variable names in the same function (which is rejected by ATI compiler). Thanks again to Řrřola!
  • Handle multiline macros in the parser. Bug found in The Wind under my wing code, thanks Navis!
  • Improve the way the C header file is generated, trying to avoid name clashing. Thanks again eyebex!

My testing scripts are not fully set up, so you might find some other bugs. Please report them! If you use the –preserve-externals option, you might get name clashes if you use one letter names. That will be fixed another time.

Download GLSL Minifier

We’ve just released GLSL Minifier 0.4! It fixes many problems, and add some new features. Tuesday update: version 0.4.1 improves a few things and adds an option to preserve external values, such as uniforms and varying. Here is the list of changes:

  • Command line is properly handled. Try the “-h” option to see the complete list of flags.
  • The -o option has been added, if you want to get the output in a particular file.
  • There is also a –shader-only, if you don’t want the C header and the formatted string.
  • Vectors accesses are made uniform, using (by default) only the “rgba” set. For instance, “foo.x” is renamed into “foo.r”.
  • Macros can be inserted to shorten external functions calls and types. This can greatly reduce the uncompressed output shader. However, the compressed file will most of the time be bigger (we’ve tested with Crinkler and kkrunchy). You can choose the threshold to control the number of macros that are inserted. This option is disabled by default.
  • The renaming algorithm has been changed. Previous versions of this tool were based on the GLSL 1.10 spec, which states that functions and variables use different namespaces. This is not true anymore since GLSL 1.20, so I had to remove a few tricks in the renamer & obfuscator.
  • The smoothstep function can be rewritten using IQ’s trick. It’s not done by default, because it’s not always a good thing to do.
  • Some information is now displayed on the console.
  • The –preserve-externals option has been added, so that you can use this compressor even if you have multiple shaders!

GLSL Minifier has been tested on the hand-optimized shader used in Retrospection, a great 4k intro (many thanks to FRequency and TITS who provided me the code). Here is the data:

Input file size is: 1727
File parsed. Shader size is: 1725
Rewrite tricks applied. Shader size is: 1723
Identifiers renamed. Shader size is: 1610
Macros added.
Minification finished. Shader size is: 1495

Note that this is the uncompressed size (size after macro injection is not useful). Once compiled with the C code and packed with Crinkler, it turns out we saved more than 30 bytes using this tool. If they had GLSL Minifier, FRequency and TITS could have improved even more their intro!

GLSL Minifier was also able to save a few bytes on To the Road of Ribbon, even if auld^titan spent time optimizing the intro to fit in 1k on Windows. Here is an example of output of the tool. See how it’s easy to include the file in your C/C++ project!

  1. #ifndef SHADER_CODE_H_
  2. #define SHADER_CODE_H_
  3. const char *shader_roadOfRibbon = ""
  4.  "float c=gl_Color.r*55;"
  5.  "float e(vec3 e)"
  6.  "{"
  7.    "return min(cos(e.r)+cos(e.g)+cos(e.b)+cos(e.g*20)*.02,length(max(abs(e-vec3(cos(e.b)*.2,cos(e.b)*.2-.5,0))-vec3(.2,.02,c+3),vec3(0))));"
  8.  "}"
  9.  "vec3 o(vec3 c)"
  10.  "{"
  11.    "return normalize(vec3(e(c+vec3(.02,0,0)),e(c+vec3(0,.02,0)),e(c+vec3(0,0,.02))));"
  12.  "}"
  13.  "void main()"
  14.  "{"
  15.    "vec3 v=vec3(cos(c),-cos(c*.5)*.5+.5,c),r=normalize(vec3(gl_FragCoord.rg*.002-1,1)),n=v;"
  16.    "for(int c=0;c<55;c++)"
  17.      "n+=r*e(n);"
  18.    "vec3 l=n+=r=reflect(r,o(n));"
  19.    "for(int c=0;c<55;c++)"
  20.      "n+=r*e(n);"
  21.    "gl_FragColor=abs(dot(o(n),vec3(.1)))+vec4(.2,cos(c*.5)*.5+.5,sin(c*.5)*.5+.5,1)*length(n-v)*.01+length(n-v)*.01+(1-min(l.g+2,1.))*vec4(1,.8,.7,1);"
  22.  "}";
  23. #endif // SHADER_CODE_H_

Today is the new release of our GLSL obfuscator & minifier.

Here is the change log:

  • Feature: Variables that start with “i_” are now inlined. That will help you keep a clear code, name your values, while still having a short shader code.
  • Feature: The shader in the C code is now split into many lines (using quotes on every line), and indented. That will help you maintain the obfuscated GLSL code.
  • Improvement: The useless space that sometimes appeared after “else”, “do” and “return” is removed.
  • Bug fix: Postfix operators are now handled.
  • Bug fix: Some parenthesis were missing +various other fixes

Edit: I’ve just updated this 0.3 release to include a few additional fixes (mainly parse errors), thanks to Ponce.


GLSL Minifier has just been released. This is the first public version, but it’s still a preview. It has not been much tested, and probably contains bugs. However, I believe it’s usable and it should help intro coders a lot.

Changes since 0.1 version:

  • Bug fix: problems with field accesses
  • Bug fix: macros are now accepted (but ignored) in the user code
  • Feature: multiple declarations with the same type are now squeezed.
  • Feature: better renaming for the functions, they now have a separated namespace.
  • Feature: use overloaded functions in the generated code: if two functions don’t have the same number of parameters, they can have the same name.