Minify and obfuscate GLSL or HLSL code


Shader Minifier

Build status

Shader Minifier is a tool that minifies and obfuscates shader code (GLSL and HLSL). Its original use-case is for the demoscene, for optimizing 4k and 64k intros. It is also suitable for reducing the size of the shaders in other applications (e.g. webgl, games).

In the context of 4kB intros, Shader Minifier help developers maintain and iterate on human-readable files, while shipping optimized code. Even when a shader is minified by hand by experienced demosceners, Shader Minifier is often able to optimize it further. See this 2010 report.

If your application uses multiple shaders, use the --preserve-externals option. Values such as the uniforms won't be renamed, which makes it easier to use in your application (at the expense of a slightly bigger shader).


  • Parse and print the GLSL or HLSL code.
  • Generate a file (such as a C header) that can be embedded in an application.
  • Strip spaces, remove comments.
  • Remove useless parens.
  • Simplify constant expressions: 3.14159 * 2. becomes 6.28318.
  • Remove curly braces whenever possible: if(test){v.x=4; return b++;} is replaced with if(test)return v.x=4,b++;.
  • Squeeze definitions: float a=2.;float b; becomes float a=2.,b;.
  • Consistently rename vector fields (e.g. use foo.xy instead of foo.rg) to help the compression.
  • Rename variables, typically to one character.
  • Reuse the variable names as much as possible: a local variable may have the same name as a global variable not used in the function; two functions may have the same name using function overloading.
  • Analyze the context and make statistics to compute the variable name that will be the most compression-friendly.
  • Inline variables.
  • Remove unused local variables.

Example output

/* File generated with Shader Minifier 1.1.6
# define VAR_MOUSE "f"
# define VAR_RESOLUTION "y"
# define VAR_TIME "v"

const char *heart_frag =
 "uniform float v;"
 "uniform vec2 y;"
 "uniform vec4 f;"
 "void main()"
   "vec2 f=(2.*gl_FragCoord.xy-y)/y.y;"
   "float r=mod(v,2.)/2.,a=pow(r,.2)*.5+.5;"
   "float m=atan(f.x,f.y)/3.14159,x=length(f),e=abs(m),o=(13.*e-22.*e*e+10.*e*e*e)/(6.-5.*e),l=step(x,o)*pow(1.-x/o,.25);"



Download Shader Minifier here:

It is a command-line tool. Without argument, it will show the usage. If you are not on Windows, you will need mono:

$ shader_minifier.exe  # Windows
$ mono shader_minifier.exe  # Linux, Mac...
USAGE: shader_minifier.exe [--help] [-o <string>] [-v] [--hlsl] [--format <text|indented|c-variables|c-array|js|nasm>]
                           [--field-names <rgba|xyzw|stpq>] [--preserve-externals] [--preserve-all-globals]
                           [--no-inlining] [--no-renaming] [--no-renaming-list <string>] [--no-sequence] [--smoothstep]


    <filename>...         List of files to minify


    -o <string>           Set the output filename (default is shader_code.h)
    -v                    Verbose, display additional information
    --hlsl                Use HLSL (default is GLSL)
    --format <text|indented|c-variables|c-array|js|nasm>
                          Choose to format the output (use none if you want just the shader)
    --field-names <rgba|xyzw|stpq>
                          Choose the field names for vectors: 'rgba', 'xyzw', or 'stpq'
    --preserve-externals  Do not rename external values (e.g. uniform)
                          Do not rename functions and global variables
    --no-inlining         Do not automatically inline variables
    --no-renaming         Do not rename anything
    --no-renaming-list <string>
                          Comma-separated list of functions to preserve
    --no-sequence         Do not use the comma operator trick
    --smoothstep          Use IQ's smoothstep trick
    --help                display this list of options.

In short:

  • List the shaders you want to minify on the command-line.

  • Use -o to choose the output file (by default, it will use shader_code.h). If you pass - for the output, it will be printed on stdout.

  • Use --format to control the output format. By default, it will create a C header. There are other options to get only the shader, or have it in a .js or nasm file.


4kB intros

4kB intros typically use a single shader file. The default flags should work well:

shader_minifier.exe -o shader_code.h fragment.glsl

We recommend that you frequently check the output of Shader Minifier to make sure there are no obvious problems. Use inlining where possible.

If you desperately need to save a few bytes, try another value of --field-names. It can affect the size after compression.

64kB intros

The recommandation is to use:

shader_minifier.exe --format c-array --preserve-externals *.frag -o shaders.h

Then, in your C or C++ code, include the file:

const char* shaderSources[] = {
#include shaders.h

Since the uniforms are not renamed, prefer shorter names when possible. Hopefully a future version of Shader Minifier will improve this.


Use --format js. It will define a variable for each shader, the variable name being derived from the input file. We expect you to run a Javascript minifier on the output file.

Other applications

The simplest solution is to minify each file separately:

shader_minifier.exe --format text --preserve-externals file.glsl -o file_opt.glsl

The output may be used as a drop-in replacement for your original shaders.


Shader Minifier will preserve the preprocessor directives (the lines starting with #), except that it strips the spaces.

If you define a macro, Shader Minifier will notice the name of the macro and won't rename the occurrences of the macro. It also doesn't rename variables used inside the macro. Clever macros are discouraged and can break the shader.


If you want to temporary turn off the minifier, use the //[ and //] comments. This can be useful as a workaround if you get a parser error.

Variables inside the region won't be renamed. Spaces will be stripped.

void GSScene( triangleadj GSSceneIn input[6], inout TriangleStream<PSSceneIn> OutputStream )
    PSSceneIn output = (PSSceneIn)0;


Automatic inlining

Shader Minifier will try to automatically inline some variables. This happens when:

  • the variable is used only once in the current block,
  • and the variable is not used in a sub-block (e.g. inside a loop),
  • and the init value is trivial (doesn't depend on a variable).

If inlining causes a bug in your code, you can disable it with --no-inlining and please report a bug.

Explicit Inlining

Shader Minifier will always inline variables that starts with i_. Inlining can allow the Minifier to simplify the code further.

For example, this input:

bool i_debug = false;
int i_level = 5;

int foo(int x, int y) {
  if (i_debug) {

  return 2 * i_level * x;

will be simplified into:

int foo(int x,int y)
  return 10*x;

If you want to aggressively reduce the size of your shader, try inlining more variables. Inlining can have performance implications though (if the variable stored the result of a computation), so be careful with it.

Inlining can lead to repetition in the shader code, which may make the shader longer (but the output may be more compression-friendly).


At this time, do not use overloaded functions (two functions with the same name but different arguments) in the input. The output probably won't compile.

On the other hand, Shader Minifier will aggressively use function overloading in the output. If two functions have a different number of arguments, they may have the same name in the output. This reduces the number of identifiers used by the shader and make it more compression friendly.

Bugs and limitations

  • The parser is not complete. Some constructs are not yet supported.
  • Don't use overloaded functions.
  • Avoid macros that contain references to other variables.

Please give feedback in the bugtracker. If something is blocking you, you can file a bug or update an existing bug. We rely on your feedback to prioritize the work.

Slightly outdated user manual:

Contributions are welcome.

Created by Laurent Le Brun (LLB / Ctrl-Alt-Test).

  • Add stdout as output option

    Add stdout as output option


    I was wondering if it'd be possible to add an output option to print the minified shader into stdout, which would allow piping with other tools and programs instead of handling files

    opened by Lutymane 5
  • support template string JS output

    support template string JS output

    For a while template literals have been supported in browsers, which allows us to define multiline strings without the need for escape characters like \n.

    So a minified shader output could simply be outputted multiline, just like --format none would do, but with backticks enclosing the text. So instead of, what gets now outputted with --format js:

    var var_U_RESOLUTION = "m"
    var var_U_TIME = "v"
    var shader_frag =
     "#version 300 es\n" +
     "uniform float v;" +
     "uniform vec2 m;" +
     "const float f=3.14159,s=50.,n=.01;struct Intersection{bool intersected;vec3 position;vec3 normal;};" +
     "float e(in vec2 v)" +
     "{" +
       "return fract(sin(dot(v.xy,vec2(12.9898,78.233)))*43758.5);" +
     "}" +
     "float x(in vec2 v)" +
     "{" +
       "vec2 f=floor(v),n=fract(v);" +
       "float m=e(f),s=e(f+vec2(1.,0.)),y=e(f+vec2(0.,1.)),I=e(f+vec2(1.,1.));" +
       "vec2 p=n*n*(3.-2.*n);" +
       "float i=mix(m,s,smoothstep(0.,1.,n.x)),x=mix(y,I,smoothstep(0.,1.,n.x)),l=mix(i,x,smoothstep(0.,1.,n.y));" +
       "return l;" +
     "}" +
    // snip

    the same thing could be written via template strings:

    var var_U_RESOLUTION = "m"
    var var_U_TIME = "v"
    var shader_frag = `
    #version 300 es
    uniform float v;uniform vec2 m;const float f=3.14159,s=50.,n=.01;struct Intersection{bool intersected;vec3 position;vec3 normal;};float e(in vec2 v){return fract(sin(dot(v.xy,vec2(12.9898,78.233)))*43758.5);}float x(in vec2 v){vec2 f=floor(v),n=fract(v);float m=e(f),s=e(f+vec2(1.,0.)),y=e(f+vec2(0.,1.)),I=e(f+vec2(1.,1.));vec2 p=n*n*(3.-2.*n);float i=mix(m,s,smoothstep(0.,1.,n.x)),x=mix(y,I,smoothstep(0.,1.,n.x)),l=mix(i,x,smoothstep(0.,1.,n.y));return l;} // snip

    Template literals are supported in all mayor browsers for quite some time now. see:

    opened by nylki 3
  • Optimize the use of 2-letter characters

    Optimize the use of 2-letter characters

    Instead of using "aa", "ab", "ac"... take into account the frequency of the characters and the context in which they are used.

    opened by laurentlb 2
  • Shader Minifier crashes and clears input file

    Shader Minifier crashes and clears input file

    This little snippet of code causes shader minifier to crash and clear the input file:

    const int TEST = 3;
    void main () {
      int[5] a = {1,2,3,4,5};
      gl_FragColor = a[TEST];

    I suspect it also took down the server(trying it in the online version) but I didn't confirm this yet due to obvious reasons.

    opened by LJ1102 2
  • References in #define are not renamed

    References in #define are not renamed



    uniform float a;
    const float b;
    #define c (a + b)


    uniform float f;const float o;
    #define c (a+b)

    which breaks the shader. Are #defines in your scope? I think it's easy to parse and replace variable names (regexp with word boundaries). Users may purposefully create complex macros, so a new CLI option would disable this replacement.

    opened by KoltesDigital 2
  • Array initialization error

    Array initialization error

    Parse error occurs in array initialization. eg:

    const int font[] = int[](
     0x69f99, 0x79797, 0xe111e, 0x79997, 0xf171f, 0xf1711, 0xe1d96, 0x99f99,

    error message:

    Parse error: Error in /tmp/user_shader_618879533.frag: Ln: 5 Col: 15 const int font[] = int[]( ^ Expecting: '('

    (ps: example taken from: [SH18] The Human Challenge )

    opened by pohar 2
  • Arrays not supported

    Arrays not supported

    This tool is really cool however the following throws an exception upon getting to the first bracket [:

    const vec2 samples[10] = vec2[](
    vec2(-0.5798373, -0.6431335),
    vec2(-0.905221, -0.124952),
    vec2(-0.2680226, 0.254136),
    vec2(-0.01519084, -0.5156112),
    vec2(-0.7712643, 0.4174358),
    vec2(0.4850016, 0.1596012),
    vec2(0.6443742, -0.5418636),
    vec2(-0.3830979, 0.8917095),
    vec2(0.4932076, 0.7231117),
    vec2(0.2750384, -0.9251713)

    The above code in particular is used to iterate over samples in a poisson disk which is a common way to smoothly filter shadow maps. Example:

    The only workaround I have found is to remove the array by manually unrolling the loop where those values are used which is non-ideal for performance and filesize especially for more than a few samples.

    opened by DomGries 2
  • "Parse error" with arrays

    Issue #16 seems to be still occurring in version 1.2:

    System.Exception: Parse error: Error in data\credits.glsl: Ln: 13 Col: 14
    const int msg[] = int[]('W', 'I', 'R', 'E', 'D', ' ', 'S', 'K', 'I', 'E', 'S');
    Expecting: '('
       at [email protected]433.Invoke(String message)
       at Main.minify(Tuple`2[] files)
       at[] files)

    I tried version 1.1.6 mentioned in issue #16 but that version also didn't work. The workaround suggested in #13 also did not work.

    opened by samizzo 1
  • Drop

    Drop "in" qualifier from function parameters

    This is the default and so doesn't need to be specified.

    The const qualifier is similarly redundant (any program valid with the qualifier is valid without it) -- actually true beyond just function parameters -- but I wasn't sure where the compiler might use it for optimisations so I stuck with what was safe.

    opened by jwatzman 1
  • Support switch statements

    Support switch statements

    See commit messages for details. Also incidentally fixes a bug around IndentedText to make my manual testing a bit less annoying. (I also added a test case which incidentally relies on this fix, though that can be easily changed if problematic.)

    I do not have a Windows build machine handy, so this was tested entirely on Linux. I was able to confirm that Checker --skip-glsl-compile works, but I didn't want to fight to get OpenTK to work. Apologies in advance if I've done anything silly!

    While I've done a lot of work with OCaml in the past, this is the first time I've touched FSharp -- once again, apologies in advance if I've done anything silly!

    opened by jwatzman 1
  • Unexpected behavior

    Unexpected behavior


    float N = 1.79284291400159;
    float N2 = 1.79284291400159;

    Output float N=1.79284291400159;float N=1.79284;

    You can quickly reproduce the example here

    opened by Andreslav 1
  • Shader Minifier as .NET tool

    Shader Minifier as .NET tool

    I'd like to include Shader Minifier as a local tool in my C# program. Please publish the project to NuGet.

    Some useful links:

    opened by randomC0der 0
  • Parse error from GLSL Geometry shader

    Parse error from GLSL Geometry shader

    Related: GLSL Compute shader throws same error

    Passthrough compute shade:

    #version 330
    layout(triangles) in;
    layout(triangle_strip, max_vertices = 3) out;
    void main() {
      for(int i = 0; i < 3; i++) { 
        gl_Position = gl_in[i].gl_Position;

    results in:

    Parse error: Error in triGeometry_g.geom: Ln: 3 Col: 21 layout(triangles) in; ^ Expecting: Type qualifier, identifier, 'layout' or 'struct'

    opened by wrightwriter 0
  • fail: multiple returns, ifdef preprocessor branching

    fail: multiple returns, ifdef preprocessor branching

    Related: #27


    vec3 func() {
    #ifdef CONDITION
      return vec3( 1.0 );
      return vec3( 0.0 );


    vec3 v(){
    #ifdef CONDITION
    return vec3(1.);}


    vec3 v(){
    #ifdef CONDITION
    return vec3(1.);
    return vec3(0.};
    opened by 0b5vr 3
  • fail: variables with a same name, ifdef preprocessor branching

    fail: variables with a same name, ifdef preprocessor branching

    Related: #28


    void main() {
    #ifdef CONDITION
      vec3 col = vec3( 1.0 );
      vec3 col = vec3( 0.0 );
      gl_FragColor = vec4( col, 1.0 );


    void main(){
    #ifdef CONDITION
    vec3 C=vec3(1.);
    vec3 r=vec3(0.);


    void main(){
    #ifdef CONDITION
    vec3 C=vec3(1.);
    vec3 C=vec3(0.);
    opened by 0b5vr 2
  • Flag that disables removal of forward declarations by reordering

    Flag that disables removal of forward declarations by reordering

    Shader_Minifier by default reorders functions to be able to remove forward declarations.

    While dealing with a single shader file containing all functions, or when combining shader sources before compilation, this technique is very useful to reduce shader source size in the executable.

    In my use-case (32k intros) however, I compile shaders containing single functions, to avoid inlining and reduce compile time. The technique requires forward declarations to be present, but those will be optimized by Shader_Minifier.

    I suggest

    • either adding a command line switch to disable forward declaration removal by reordering
    • or verifying that the forward declaration in question has a definition inside the minified sources before reordering and dropping it, keeping the forward declaration and not reordering if none is present.

    to enable the use of Shader_Minifier when compiling functions separately.

    I would be willing to submit a PR, should you decide you like the suggestion - just let me know if you like the idea (and which approach you prefer).

    opened by LeStahL 1
  • Parse error from GLSL compute shader

    Parse error from GLSL compute shader

    I got Parse error from following GLSL compute shader.


    #version 450
    layout(local_size_x = 32) in;
    void main(){


    Parse error: Error in test.cs: Ln: 3 Col: 29
    layout(local_size_x = 32) in;
    Expecting: Type qualifier, identifier, 'layout' or 'struct'
       場所 [email protected](String message)
       場所 [email protected][b,c,d](String fmt, Int32 len, FSharpFunc`2 outputChar, FSharpFunc`2 outa, b os
    FSharpFunc`2 finalize, FSharpList`1 args, Int32 i)
       場所 [email protected][b,c,d](FSharpFunc`2 initialize, String fmt, Int32 len, FSharpList`1 args)
       場所 <StartupCode$FSharp-Core>[email protected](T1 inp)
       場所 main.minify(String filename, String content)
       場所[] files)
    opened by demotomohiro 0
  • 1.2(Jan 13, 2022)

    What's Changed

    • Make Shader Minifier twice as fast by @laurentlb in
    • Migrate option parser to Argu by @laurentlb in
    • Use template string for JS output by @laurentlb in
    • Fix parentheses when the comma operator is in a function call by @laurentlb in
    • Rewriter: remove useless braces in a few more cases by @laurentlb in
    • Parser: better support for HLSL geometry shaders by @laurentlb in
    • README: Add proper documentation by @laurentlb in
    • Rewrite the full pi constant as acos(-1.) by @eldritchconundrum in
    • Fix -0.0 by @eldritchconundrum in
    • Allow shadowing of external values by @laurentlb in
    • Optimize the use of 2-letter characters by @laurentlb in
    • Properly rename exported values in a multifile context by @laurentlb in
    • New renaming strategy for when minifying multiple files by @laurentlb in
    • New formatting output: indented text by @laurentlb in
    • Inlining: automatically inline trivial values by @laurentlb in
    • Improve float precision by @laurentlb in
    • Add option to disable auto-inlining and document it by @laurentlb in
    • Automatically remove unused local variables by @laurentlb in
    • Even better formatting of floats by @laurentlb in

    Full Changelog:

    Source code(tar.gz)
    Source code(zip)
    shader_minifier.exe(2.20 MB)
Laurent Le Brun
Author of Starlark, ex-Bazel developer, I work on IDEs and I like the demoscene.
Laurent Le Brun
HLSL Parser and Translator for HLSL, GLSL, and MSL.

HLSLParser This is a fork of Unknownworld's hlslparser adapted to our needs in The Witness. We currently use it to translate pseudo-HLSL shaders (usin

null 310 May 28, 2022
glslcc: Cross-compiler for GLSL shader language (GLSL->HLSL,METAL,GLES,GLSLv3)

glslcc: Cross-compiler for GLSL shader language (GLSL->HLSL,METAL,GLES,GLSLv3) @septag glslcc is a command line tool that converts GLSL code to HLSL,

Sepehr Taghdisian 405 Jun 23, 2022
⚔️ A tool for cross compiling shaders. Convert between GLSL, HLSL, Metal Shader Language, or older versions of GLSL.

A cross compiler for shader languages. Convert between SPIR-V, GLSL / GLSL ES, HLSL, Metal Shader Language, or older versions of a given language. Cross Shader wraps glslang and SPIRV-Cross, exposing a simpler interface to transpile shaders.

Alain Galvan 157 Jun 23, 2022
Shader cross compiler to translate HLSL (Shader Model 4 and 5) to GLSL

XShaderCompiler ("Cross Shader Compiler") Features Cross compiles HLSL shader code (Shader Model 4 and 5) into GLSL Simple to integrate into other pro

Lukas Hermanns 342 Jun 20, 2022
Khronos-reference front end for GLSL/ESSL, partial front end for HLSL, and a SPIR-V generator.

News Visual Studio 2013 is no longer supported As scheduled, Microsoft Visual Studio 2013 is no longer officially supported. Please upgrade to at leas

The Khronos Group 2.2k Jun 25, 2022
LLVM IR and optimizer for shaders, including front-end adapters for GLSL and SPIR-V and back-end adapter for GLSL

Licensing LunarGLASS is available via a three clause BSD-style open source license. Goals The primary goals of the LunarGLASS project are: Reduce the

LunarG, Inc. 151 Jun 18, 2022
HLSL to GLSL language translator based on ATI's HLSL2GLSL. Used in Unity.

HLSL to GLSL shader language translator ⚠️ As of mid-2016, the project is unlikely to have any significant developments. At Unity we are moving to a d

Aras Pranckevičius 512 Jun 21, 2022
GLSL optimizer based on Mesa's GLSL compiler. Used to be used in Unity for mobile shader optimization.

GLSL optimizer ⚠️ As of mid-2016, the project is unlikely to have any significant developments. At Unity we are moving to a different shader compilati

Aras Pranckevičius 1.5k Jun 23, 2022
Obfuscate calls to imports by patching in stubs. ICO works on both X86 and X64 binaries.

ICO adds a new section into the image, then begins building stubs for each import that uses a extremely basic routine to decrypt an RVA and places them into the section.

null 34 Jun 4, 2022
Automatically de-obfuscate ollvm and generate binaries

AntiOllvm Automatically deobfuscate binaries and generate new binaries. Chinese Help 中文帮助点击 帮助 Decriptor Software obfuscation protection is very commo

sanfengAndroid 62 Jun 24, 2022
glsl code blocks for org-mode

GLSL code blocks for Emacs Org-mode This org-mode extension adds the capability to run GLSL code blocks directly from inside Emacs and immediately dis

null 27 Jun 14, 2022
『HLSL シェーダーの魔導書』(ISBN978-4-7981-6428-1)のサンプルファイル

# サンプルデータについて 本データは、『HLSL シェーダーの魔導書』(清原 隆行 著、翔泳社 刊)の付属データです。 なお、本データは以下のサイトから入手可能です。 - Github:

SEBook 翔泳社の本 81 Jun 26, 2022
A Visual Studio extension that provides enhanced support for editing High Level Shading Language (HLSL) files

HLSL Tools for Visual Studio This extension is for Visual Studio 2017 / 2019. Go here for the Visual Studio Code extension. HLSL Tools is a Visual Stu

Tim Jones 398 Jun 22, 2022
ShaderConductor is a tool designed for cross-compiling HLSL to other shading languages

ShaderConductor ShaderConductor is a tool designed for cross-compiling HLSL to other shading languages. Features Converts HLSL to readable, usable and

Microsoft 1.4k Jun 17, 2022
this is my simple voxel engine, appart from librairies like glad it is entierly written in C++ and GLSL

simple-voxel-raycaster this is my simple voxel engine, appart from librairies like glad it is entierly written in C++ and GLSL here is a gif: https://

null 1 Jun 4, 2022
VSIX Project that provides GLSL language integration.

GLSL language integration (for VS2017, 2019 and 2022) Download this extension from Visual Studio Marketplace version VS2017 & 2019 or VS 2022 preview

Daniel Scherzer 193 Jun 22, 2022
Simple printf functionality for GLSL.

Simple printf functionality for GLSL. This library is a simple proof of concept of using printf directly from a shader. The main point of being able

null 200 Jun 19, 2022
An efficient texture-free GLSL procedural noise library

Wombat An efficient texture-free GLSL procedural noise library Source: Derived from:

Brian Sharpe 192 Jun 21, 2022
Fast glsl deNoise spatial filter, with circular gaussian kernel, full configurable

glslSmartDeNoise Fast glsl spatial deNoise filter, with circular gaussian kernel and smart/flexible/adaptable -> full configurable: Standard Deviation

Michele Morrone 190 Jun 26, 2022