Shader Minifier

This product will make you happy.

See https://github.com/laurentlb/shader_minifier for updated documentation and new releases.

Shader Minifier is a tool to pack HLSL or GLSL shader code. You can use it to make nice 4k PC-demos (such as this one) or to obfuscate your shader code in your next video game (don’t forget there are tools to intercept and display your shader code while your application is running). It generates a code as small as possible that is equivalent to the input code. The generated code is also designed to compress well, and has been optimized for use with Crinkler, but should perform well with any other compression tool. Shader Minifier generates a C header file you can include from your code. This file contains the shader code in a compact string and macros to retrieve the name of the uniforms (because they are renamed).

How well does this tool pack? Can’t I do it by hand?

Size-optimizing a shader code by hand is tedious and inefficient. No matter how good your are, this GLSL/HLSL packer will probably be able to improve your hand-optimized code. It doesn’t mean you can do stupid things and rely only on the tool. Basically, you should do the optimizations the tool cannot do. Keep all the spaces, comments and useful variables names you need to have a readable and maintainable piece of code. You should focus on clever optimizations.

Most intros, even among the best ones, would benefit from this tool. Hand-written shaders can often be reduced by dozens of bytes (after compression) by using Shader Minifier. See statistics.

Features

  • Code is parsed and pretty-printed in an automatic and uniform way.
  • A C header code is (optionally) generated. The shader is split in many lines (using quotes on every line) and indented, so that you can still maintain the shader.
  • Useless whitespaces and comments are removed.
  • Useless parenthesis are removed, by applying GLSL precedence rules.
  • Useless curly brackets are removed. eg. “if(test){a=4; return b++;}” is replaced by “if(test)return a=4,b++;”
  • Constant arithmetic expressions are simplified. This allows you to keep a more readable input file. 3.14159 * 2. will become 6.28318
  • Definitions are squeezed. eg. “float a=2.;float b;” becomes “float a=2.,b;”
  • User variables and functions are renamed, usually using a single letter. Names are reused as much as possible (this includes overloading functions, and variable shadowing). Agressive name reuse greatly improves compression, and delays the point where you need two-letters names.
  • Variables that start with “i_” are inlined. That will help you keep a clear code, name your values, while still having a short final code. The inlining is stupid, so avoid side-effects!
  • Vectors accesses are made uniform, using (by default) only the “xyzw” set. For instance, “foo.r” is renamed into “foo.x”.
  • 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.
  • If you use multiple shaders, you might use the –preserve-externals function, and your uniform/varying/attribute values won’t be renamed.

Example of (stupid) input file:

uniform int time;
float sum(vec3 v) {
  return v.x + v.y + v.z;
}
float foo(vec3 v, float k) {
  float tmp = 1.;
  int i_count = 4;
  for (int i = 0; i < 5 * i_count; ++i) {
    tmp /= k;
  }
  return tmp * v.sts;
}

Here is the generated output, ready to be included in a C/C++ project!

#ifndef SHADER_CODE_H_
#define SHADER_CODE_H_
#define U_TIME "r"

const char *shader_test = ""
  "uniform int r;"
  "float t(vec3 r)"
  "{"
    "return r.r+r.g+r.b;"
  "}"
  "float t(vec3 r,float t)"
  "{"
    "float o=1.;"
    "for(int r=0;r<20;++r)"
      "o/=t;"
    "return o*r.rgr;"
  "}";
#endif // SHADER_CODE_H_

Bugs, limitations

  • Macros are not modified (useless whitespace will be removed though). If you do tricky things in your macro (eg. if the replacement is needed to parse the code), the tool might fail. Also, you’re not allowed to use macros inside functions or expressions.
  • User-defined records are not renamed and cannot contain fields conflicting with vec4 (e.g. “r”, “rg”, “x”…).
  • If you have overloaded functions in your input, the tool might be confused.

Download

Download Shader Minifier from GitHub
This exe should work on Windows and Unix, but you’ll need Microsoft .NET or Mono.

Please report any issue on GitHub. Use Discord if you want to chat.