├── .gitattributes ├── .github └── FUNDING.yml ├── .gitignore ├── Checker ├── Checker.fsproj ├── compression_test.fs ├── glslang.exe └── main.fs ├── Directory.Build.props ├── Example ├── Example.csproj └── Program.cs ├── LICENSE ├── Minifier ├── Minifier.fsproj ├── analyzer.fs ├── api.fs ├── ast.fs ├── builtin.fs ├── formatter.fs ├── inlining.fs ├── options.fs ├── parse.fs ├── preprocessor.fs ├── printer.fs ├── renamer.fs └── rewriter.fs ├── README.md ├── SMBolero.Client ├── Main.fs ├── Properties │ └── launchSettings.json ├── SMBolero.Client.fsproj ├── Startup.fs └── wwwroot │ ├── css │ └── index.css │ ├── index.html │ ├── main.html │ └── minifier.js ├── SMBolero.Server ├── Index.fs ├── Properties │ └── launchSettings.json ├── SMBolero.Server.fsproj └── Startup.fs ├── Shader Minifier.sln ├── ShaderMinifier ├── ShaderMinifier.fsproj └── main.fs ├── TRANSFORMATIONS.md ├── appveyor.yml ├── check.bash ├── compile.bash ├── lib ├── Argu.dll ├── Compressor.dll ├── FParsec.dll ├── FParsecCS.dll ├── FSharp.Core.dll ├── OpenTK.dll └── System.ValueTuple.dll ├── run-from-source.bash └── tests ├── all-glsl.expected ├── commands.txt ├── compile.txt ├── compression_results.log ├── real ├── README.md ├── audio-flight-v2.frag ├── audio-flight-v2.frag.expected ├── buoy.frag ├── buoy.frag.expected ├── chocolux.expected ├── chocolux.frag ├── clod.expected ├── clod.frag ├── controllable-machinery.frag ├── controllable-machinery.frag.expected ├── deform.frag ├── disco.expected ├── disco.frag ├── ed-209.frag ├── ed-209.frag.expected ├── elevated.hlsl ├── elevated.hlsl.expected ├── endeavour.frag ├── endeavour.frag.expected ├── from-the-seas-to-the-stars.frag ├── from-the-seas-to-the-stars.frag.expected ├── frozen-wasteland.frag ├── frozen-wasteland.frag.expected ├── heart.expected ├── heart.frag ├── heart.frag.expected ├── heart2.expected ├── heart2.frag ├── julia.frag ├── kaleidoscope.frag ├── kinder_painter.expected ├── kinder_painter.frag ├── leizex.expected ├── leizex.frag ├── lunaquatic.frag ├── lunaquatic.frag.expected ├── mandel.frag ├── mandelbulb.expected ├── mandelbulb.frag ├── metatunnel.frag ├── monjori.frag ├── monjori.frag.expected ├── motion_blur.frag ├── mouton │ ├── fxaa.frag │ ├── mouton.expected │ ├── mouton.frag │ └── mouton.vert ├── ohanami.frag ├── ohanami.frag.expected ├── orchard.frag ├── orchard.frag.expected ├── oscars_chair.frag ├── oscars_chair.frag.expected ├── postprocessing.frag ├── quaternion.frag ├── radial_blur.frag ├── robin.frag ├── robin.frag.expected ├── slisesix.frag ├── slisesix.frag.expected ├── star.frag ├── sult.expected ├── sult.frag ├── terrarium.frag ├── terrarium.frag.expected ├── the_real_party_is_in_your_pocket.frag ├── the_real_party_is_in_your_pocket.frag.expected ├── to_the_road_of_ribbon.expected ├── to_the_road_of_ribbon.frag ├── valley_ball.glsl ├── valley_ball.glsl.expected ├── yx_long_way_from_home.frag ├── yx_long_way_from_home.frag.expected └── z_invert.frag.expected ├── shadertoy.h.glsl └── unit ├── 1.simple.frag ├── 2.simple.frag ├── 2.simple.opt.frag ├── arg-inlining.expected ├── arg-inlining.frag ├── array.frag ├── array.frag.expected ├── augmented.frag ├── augmented.frag.expected ├── blocks.expected ├── blocks.frag ├── bug.frag.expected ├── bug321.expected ├── bug321.frag ├── commas.frag ├── conditionals.frag ├── conditionals.frag.expected ├── deadcode.frag ├── deadcode.frag.expected ├── decimals.frag ├── decimals.frag.expected ├── empty_block.frag ├── externals.expected ├── externals.frag ├── externals.preserved.expected ├── file name with-weird caractères.frag ├── file name with-weird caractères.frag.c-variables.expected ├── file name with-weird caractères.frag.js.expected ├── file name with-weird caractères.frag.json.expected ├── file name with-weird caractères.frag.nasm.expected ├── file name with-weird caractères.frag.rust.expected ├── float.frag ├── float.frag.expected ├── forbidden.expected ├── forbidden.frag ├── forward_declaration.frag ├── forward_declaration.frag.expected ├── function_comma.expected ├── function_comma.frag ├── function_overload.expected ├── function_overload.frag ├── function_overload.no.expected ├── function_overload2.expected ├── functions.hlsl ├── geometry.hlsl ├── geometry.hlsl.expected ├── hexa.frag ├── inline-aggro.aggro.expected ├── inline-aggro.expected ├── inline-aggro.frag ├── inline-fn-multiple.expected ├── inline-fn-multiple.frag ├── inline-fn.aggro.expected ├── inline-fn.expected ├── inline-fn.frag ├── inline.aggro.expected ├── inline.expected ├── inline.frag ├── inline.no.expected ├── inout.expected ├── inout.frag ├── inout2.frag ├── interface-block-renaming.expected ├── interface-block-renaming1.frag ├── interface-block-renaming2.frag ├── interface_block.frag ├── interface_block.frag.expected ├── keyword_prefix.frag ├── keyword_prefix.frag.expected ├── layout.comp ├── layout.frag ├── layout.frag.expected ├── layout.geom ├── loop.frag ├── loop.frag.expected ├── macros.expected ├── macros.frag ├── many_variables.expected ├── many_variables.frag ├── minus-zero.expected ├── minus-zero.frag ├── nested_if.frag ├── nested_if.frag.expected ├── numbers.frag ├── numbers.frag.expected ├── operators.expected ├── operators.frag ├── overload.expected ├── overload.frag ├── pi.frag ├── pi.frag.expected ├── precedence.frag ├── precedence.frag.expected ├── precision.frag ├── precision.frag.expected ├── preprocess.frag ├── preprocess.frag.expected ├── preprocess_if.frag ├── preprocess_if.frag.expected ├── qualifiers.expected ├── qualifiers.frag ├── rename_conflict.frag ├── reuse-var.frag ├── reuse-var.frag.expected ├── shadowing.frag ├── shadowing.frag.expected ├── simple.frag ├── simplify.expected ├── simplify.frag ├── smoothstep.frag ├── struct.frag ├── struct.frag.expected ├── struct2.frag ├── struct2.frag.expected ├── struct_inheritance.hlsl ├── struct_inheritance.hlsl.expected ├── suffix.frag ├── switch.expected ├── switch.frag ├── symbols.frag ├── symbols.frag.expected ├── symbols.frag.sym ├── templates.hlsl ├── templates.hlsl.expected ├── ternary.frag ├── ternary.frag.expected ├── unused_assignments.frag ├── unused_assignments.frag.expected ├── unused_removal.frag ├── unused_removal.frag.expected ├── vectors.frag ├── vectors.frag.expected ├── verbatim.frag └── verbatim.frag.expected /.gitattributes: -------------------------------------------------------------------------------- 1 | # Auto detect text files and perform LF normalization 2 | * text=auto 3 | 4 | # Custom for Visual Studio 5 | *.cs diff=csharp 6 | *.sln merge=union 7 | *.csproj merge=union 8 | *.vbproj merge=union 9 | *.fsproj merge=union 10 | *.dbproj merge=union 11 | 12 | # Standard to msysgit 13 | *.doc diff=astextplain 14 | *.DOC diff=astextplain 15 | *.docx diff=astextplain 16 | *.DOCX diff=astextplain 17 | *.dot diff=astextplain 18 | *.DOT diff=astextplain 19 | *.pdf diff=astextplain 20 | *.PDF diff=astextplain 21 | *.rtf diff=astextplain 22 | *.RTF diff=astextplain 23 | -------------------------------------------------------------------------------- /.github/FUNDING.yml: -------------------------------------------------------------------------------- 1 | github: [laurentlb] 2 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | ################# 2 | ## Checker 3 | ################# 4 | 5 | Checker/.out.spv 6 | tests/out/ 7 | 8 | ################# 9 | ## Eclipse 10 | ################# 11 | 12 | *.pydevproject 13 | .project 14 | .metadata 15 | bin/ 16 | tmp/ 17 | *.tmp 18 | *.bak 19 | *.swp 20 | *~.nib 21 | local.properties 22 | .classpath 23 | .settings/ 24 | .loadpath 25 | 26 | # External tool builders 27 | .externalToolBuilders/ 28 | 29 | # Locally stored "Eclipse launch configurations" 30 | *.launch 31 | 32 | # CDT-specific 33 | .cproject 34 | 35 | # PDT-specific 36 | .buildpath 37 | 38 | 39 | ################# 40 | ## Visual Studio 41 | ################# 42 | 43 | .vs/ 44 | 45 | ## Ignore Visual Studio temporary files, build results, and 46 | ## files generated by popular Visual Studio add-ons. 47 | 48 | # User-specific files 49 | *.suo 50 | *.user 51 | *.sln.docstates 52 | 53 | # Build results 54 | [Dd]ebug/ 55 | [Rr]elease/ 56 | *_i.c 57 | *_p.c 58 | *.ilk 59 | *.meta 60 | *.obj 61 | *.pch 62 | *.pdb 63 | *.pgc 64 | *.pgd 65 | *.rsp 66 | *.sbr 67 | *.tlb 68 | *.tli 69 | *.tlh 70 | *.tmp 71 | *.vspscc 72 | .builds 73 | *.dotCover 74 | 75 | ## TODO: If you have NuGet Package Restore enabled, uncomment this 76 | #packages/ 77 | 78 | # Visual C++ cache files 79 | ipch/ 80 | *.aps 81 | *.ncb 82 | *.opensdf 83 | *.sdf 84 | 85 | # Visual Studio profiler 86 | *.psess 87 | *.vsp 88 | 89 | # ReSharper is a .NET coding add-in 90 | _ReSharper* 91 | 92 | # Installshield output folder 93 | [Ee]xpress 94 | 95 | # DocProject is a documentation generator add-in 96 | DocProject/buildhelp/ 97 | DocProject/Help/*.HxT 98 | DocProject/Help/*.HxC 99 | DocProject/Help/*.hhc 100 | DocProject/Help/*.hhk 101 | DocProject/Help/*.hhp 102 | DocProject/Help/Html2 103 | DocProject/Help/html 104 | 105 | # Click-Once directory 106 | publish 107 | 108 | # Others 109 | [Bb]in 110 | [Oo]bj 111 | sql 112 | TestResults 113 | *.Cache 114 | ClientBin 115 | stylecop.* 116 | ~$* 117 | *.dbmdl 118 | Generated_Code #added for RIA/Silverlight projects 119 | 120 | # Backup & report files from converting an old project file to a newer 121 | # Visual Studio version. Backup files are not needed, because we have git ;-) 122 | _UpgradeReport_Files/ 123 | Backup*/ 124 | UpgradeLog*.XML 125 | 126 | 127 | 128 | ############ 129 | ## Windows 130 | ############ 131 | 132 | # Windows image file caches 133 | Thumbs.db 134 | 135 | # Folder config file 136 | Desktop.ini 137 | 138 | 139 | ############# 140 | ## Python 141 | ############# 142 | 143 | *.py[co] 144 | 145 | # Packages 146 | *.egg 147 | *.egg-info 148 | dist 149 | build 150 | eggs 151 | parts 152 | bin 153 | var 154 | sdist 155 | develop-eggs 156 | .installed.cfg 157 | 158 | # Installer logs 159 | pip-log.txt 160 | 161 | # Unit test / coverage reports 162 | .coverage 163 | .tox 164 | 165 | #Translations 166 | *.mo 167 | 168 | #Mr Developer 169 | .mr.developer.cfg 170 | 171 | # Mac crap 172 | .DS_Store 173 | -------------------------------------------------------------------------------- /Checker/Checker.fsproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Exe 5 | net8.0 6 | .. 7 | --update-golden 8 | 9 | 10 | 11 | 12 | 13 | 14 | PreserveNewest 15 | 16 | 17 | 18 | 19 | 20 | ..\lib\Argu.dll 21 | 22 | 23 | ..\lib\FSharp.Core.dll 24 | 25 | 26 | ..\lib\OpenTK.dll 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | -------------------------------------------------------------------------------- /Checker/compression_test.fs: -------------------------------------------------------------------------------- 1 | module CompressionTests 2 | 3 | open ShaderMinifier 4 | open System.Runtime.InteropServices 5 | open System.IO 6 | open System.Text 7 | 8 | #nowarn "51" // use of native pointers 9 | 10 | module Crinkler = 11 | [] 12 | extern void InitCompressor() 13 | 14 | [] 15 | extern single ApproximateModels4k(char* data, int datasize) 16 | 17 | 18 | let testFiles = [ 19 | "audio-flight-v2.frag" 20 | "buoy.frag" 21 | "controllable-machinery.frag" 22 | "ed-209.frag" 23 | "elevated.hlsl" 24 | "endeavour.frag" 25 | "from-the-seas-to-the-stars.frag" 26 | "frozen-wasteland.frag" 27 | "kinder_painter.frag" 28 | "leizex.frag" 29 | "lunaquatic.frag" 30 | "mandelbulb.frag" 31 | "ohanami.frag" 32 | "orchard.frag" 33 | "oscars_chair.frag" 34 | "robin.frag" 35 | "slisesix.frag" 36 | "terrarium.frag" 37 | "the_real_party_is_in_your_pocket.frag" 38 | "valley_ball.glsl" 39 | "yx_long_way_from_home.frag" 40 | ] 41 | 42 | let writer = new StringWriter() 43 | 44 | let log fmt = 45 | let logger str = 46 | printf "%s" str 47 | writer.Write(str) 48 | 49 | Printf.ksprintf logger fmt 50 | 51 | let compressionTest args filenames = 52 | let options = Options.init(args) 53 | let minified = 54 | use out = new StringWriter() 55 | let files = [|for f in filenames -> f, File.ReadAllText("tests/real/" + f)|] 56 | let minifier = Minifier(options, files) 57 | minifier.Format(out) 58 | out.ToString().ToCharArray() 59 | 60 | let pointer = &&minified.[0] 61 | log "%-40s " (match filenames with [f] -> f | f::_ -> f + " (and others)" | [] -> "?") 62 | log "%5d " minified.Length 63 | let compressedSize = Crinkler.ApproximateModels4k(pointer, minified.Length) 64 | log "=> %8.3f\n" compressedSize 65 | minified.Length, float compressedSize 66 | 67 | let compressFile (file: string) = 68 | let langArg = if file.EndsWith("hlsl") then [|"--hlsl"|] else [||] 69 | let extraArgs = [|"--format"; "text"|] 70 | compressionTest (Array.append langArg extraArgs) [file] 71 | 72 | let run () = 73 | Crinkler.InitCompressor() // Platform must be set to x64 74 | 75 | writer.GetStringBuilder().Clear() |> ignore 76 | 77 | // Tests for minifying multiple files together. 78 | // We don't have good examples of files that fit together, but these files use the same uniforms (e.g. time, tex0). 79 | let multifileInputs1 = ["clod.frag"; "leizex.frag"; "slisesix.frag"; "motion_blur.frag"; "mandel.frag"; "kaleidoscope.frag"] 80 | let multifileOutput1 = compressionTest [|"--format"; "text"|] multifileInputs1 81 | 82 | let multifileInputs2 = ["mouton/mouton.vert"; "mouton/mouton.frag"; "mouton/fxaa.frag"] 83 | let multifileOutput2 = compressionTest [|"--format"; "text"|] multifileInputs2 84 | 85 | // Tests for individual files. 86 | let sizes = multifileOutput1 :: multifileOutput2 :: List.map compressFile testFiles 87 | let minifiedSum = List.sumBy fst sizes 88 | let compressedSum = List.sumBy snd sizes 89 | log "Total: %5d => %9.3f\n" minifiedSum compressedSum 90 | 91 | File.WriteAllText("tests/compression_results.log", writer.ToString()) 92 | -------------------------------------------------------------------------------- /Checker/glslang.exe: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/laurentlb/shader-minifier/686983819d150b5fd30bb6fbf6d1e60652f2e52d/Checker/glslang.exe -------------------------------------------------------------------------------- /Directory.Build.props: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | $(MSBuildThisFileDirectory)artifacts 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /Example/Example.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | Exe 5 | net8.0 6 | enable 7 | enable 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /Example/Program.cs: -------------------------------------------------------------------------------- 1 | /** 2 | * Example of use of the ShaderMinifier library from C#. 3 | */ 4 | 5 | using ShaderMinifier; 6 | 7 | var shader = """ 8 | out vec4 fragColor; 9 | void main() 10 | { 11 | fragColor = vec4(1., 1., 1., 1.); 12 | } 13 | """; 14 | 15 | var file = Tuple.Create("filename.frag", shader); 16 | var options = Minifier.ParseOptions(new[] { "--format", "text" }); 17 | var minifier = new Minifier(options, new[] { file }); 18 | minifier.Format(System.Console.Out); 19 | -------------------------------------------------------------------------------- /Minifier/Minifier.fsproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | net8.0 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | ..\lib\Argu.dll 25 | 26 | 27 | ..\lib\FParsec.dll 28 | 29 | 30 | ..\lib\FParsecCS.dll 31 | 32 | 33 | ..\lib\FSharp.Core.dll 34 | 35 | 36 | 37 | 38 | -------------------------------------------------------------------------------- /Minifier/api.fs: -------------------------------------------------------------------------------- 1 | namespace ShaderMinifier 2 | 3 | open System.IO 4 | 5 | type Minifier(options, files) = 6 | let getSize (shaders: Ast.Shader[]) = 7 | shaders |> Seq.sumBy (fun s -> Printer.print s.code |> String.length) 8 | 9 | let minify (options: Options.Options) (files: (string*string)[]) = 10 | // like printfn when verbose option is set 11 | let vprintf fmt = fprintf (if options.verbose then stdout else TextWriter.Null) fmt 12 | 13 | let printSize (shaders: Ast.Shader[]) = 14 | if options.verbose then 15 | let length = getSize shaders 16 | vprintf "Shader size is: %d\n" length 17 | 18 | let names = String.concat "," [for n, c in files -> $"'{n}' ({c.Length}b)"] 19 | options.trace $"----- minifying {names}" 20 | vprintf "Input file size is: %d\n" (files |> Array.sumBy (fun (_, s) -> s.Length)) 21 | 22 | let parseAndRewrite (filename, content) = 23 | let shader = Parse.runParser options filename content 24 | let code = 25 | if shader.reorderFunctions then 26 | Rewriter.reorderFunctions options shader.code 27 | else shader.code 28 | { shader with code = Rewriter.simplify options code } 29 | 30 | let shaders = Array.Parallel.map parseAndRewrite files 31 | vprintf "Rewrite tricks applied. "; printSize shaders 32 | 33 | if options.noRenaming then 34 | shaders, [||] 35 | else 36 | let exportedNames = Renamer.rename options (Seq.toArray shaders) |> List.toArray 37 | vprintf "Identifiers renamed. "; printSize shaders 38 | shaders, exportedNames 39 | 40 | let shaders, exportedNames = minify options files 41 | 42 | static member ParseOptions(flags) = Options.init flags 43 | static member ParseOptionsWithFiles(flags) = Options.initFiles flags 44 | 45 | member _.GetSize = getSize shaders 46 | member _.GetShaders = shaders 47 | 48 | member _.Format(writer) = Formatter.print options writer shaders exportedNames 49 | member _.Format(writer, options) = 50 | Formatter.print options writer shaders exportedNames 51 | member _.FormatWithLocations(writer) = Formatter.printWithLocations options writer shaders exportedNames 52 | -------------------------------------------------------------------------------- /Minifier/builtin.fs: -------------------------------------------------------------------------------- 1 | module internal Builtin 2 | 3 | // source: https://registry.khronos.org/OpenGL/specs/gl/GLSLangSpec.4.60.pdf 4 | 5 | let keywords = System.Collections.Generic.HashSet<_>([ 6 | "if"; "else"; "break"; "continue"; "do"; "for"; "while"; "switch"; "case"; "default"; 7 | "in"; "out"; "inout"; "discard"; "return"; "lowp"; "mediump"; "highp"; "precision"; 8 | "struct"; "layout"; "centroid"; "flat"; "smooth"; "noperspective"; "patch"; "sample"; "invariant"; 9 | "precise"; "subroutine"; "coherent"; "volatile"; "restrict"; "readonly"; "writeonly"; 10 | "const"; "uniform"; "buffer"; "shared"; "attribute"; "varying" 11 | "template" 12 | ]) 13 | 14 | let builtinScalarTypes = set [ 15 | "bool"; "int"; "uint"; "float"; "double" 16 | ] 17 | let builtinVectorTypes = set([ 18 | for p in [""; "d"; "b"; "i"; "u"] do 19 | for n in ["2"; "3"; "4"] do 20 | yield p+"vec"+n 21 | ]) 22 | let builtinMatrixTypes = set([ 23 | for p in [""; "d"] do 24 | for n in ["2"; "3"; "4"] do 25 | yield p+"mat"+n 26 | for c in ["2"; "3"; "4"] do 27 | for r in ["2"; "3"; "4"] do 28 | yield p+"mat"+c+"x"+r 29 | ]) 30 | 31 | let isSamplerType (name: string) = name.Contains("sampler") 32 | 33 | let builtinTypes = set [ "void" ] + builtinScalarTypes + builtinVectorTypes + builtinMatrixTypes; 34 | 35 | let implicitConversions = // (from, to) 36 | [ 37 | (["int"], "uint") 38 | (["int"; "uint"], "float") 39 | (["int"; "uint"; "float"], "double") 40 | (["ivec2"], "uvec2") 41 | (["ivec3"], "uvec3") 42 | (["ivec4"], "uvec4") 43 | (["ivec2"; "uvec2"], "vec2") 44 | (["ivec3"; "uvec3"], "vec3") 45 | (["ivec4"; "uvec4"], "vec4") 46 | (["ivec2"; "uvec2"; "vec2"], "dvec") 47 | (["ivec3"; "uvec3"; "vec3"], "dvec3") 48 | (["ivec4"; "uvec4"; "vec4"], "dvec4") 49 | (["mat2"], "dmat2") 50 | (["mat3"], "dmat3") 51 | (["mat4"], "dmat4") 52 | (["mat2x3"], "dmat2x3") 53 | (["mat2x4"], "dmat2x4") 54 | (["mat3x2"], "dmat3x2") 55 | (["mat3x4"], "dmat3x4") 56 | (["mat4x2"], "dmat4x2") 57 | (["mat4x3"], "dmat4x3") 58 | ] 59 | 60 | let assignOps = set [ 61 | "="; "+="; "-="; "*="; "/="; "%=" 62 | "<<="; ">>="; "&="; "^="; "|=" 63 | "++"; "--"; "$++"; "$--" 64 | ] 65 | let nonAssignOps = set [ 66 | "*"; "/"; "%" 67 | "+"; "-" 68 | "<<"; ">>" 69 | "<"; ">"; "<="; ">=" 70 | "=="; "!=" 71 | "&"; "^"; "|" 72 | "&&"; "^^"; "||" 73 | ] 74 | let augmentableOperators = set ["+"; "-"; "*"; "/"; "%"; "<<"; ">>"; "&"; "^"; "|"] 75 | 76 | let castFunctions = builtinTypes - set ["void"] 77 | let trigonometryFunctions = set([ 78 | "acos"; "acosh"; "asin"; "asinh"; "atan"; "atanh"; "cos"; "cosh"; "degrees"; 79 | "radians"; "sin"; "sinh"; "tan"; "tanh"]) 80 | let mathsFunctions = set([ 81 | "abs"; "ceil"; "clamp"; "dFdx"; "dFdy"; "exp"; "exp2"; "floor"; "floor"; "fma"; 82 | "fract"; "fwidth"; "inversesqrt"; "isinf"; "isnan"; "log"; "log2"; "max"; "min"; 83 | "mix"; "mod"; "modf"; "noise"; "pow"; "round"; "roundEven"; "sign"; "smoothstep"; 84 | "sqrt"; "step"; "trunc"]) 85 | let vectorFunctions = set([ 86 | "cross"; "distance"; "dot"; "equal"; "faceforward"; "length"; "normalize"; 87 | "notEqual"; "reflect"; "refract"]) 88 | let textureFunctions = set(["texture"; "textureLod"; "texture2D"]) 89 | 90 | let pureBuiltinFunctions = 91 | trigonometryFunctions + 92 | mathsFunctions + 93 | vectorFunctions + 94 | castFunctions + 95 | textureFunctions 96 | 97 | let impureBuiltinFunctions = set ["atomicCounterIncrement"] 98 | 99 | let builtinFunctions = pureBuiltinFunctions + impureBuiltinFunctions 100 | 101 | // Type qualifiers telling that a global variables is an 'external' name 102 | // (it may be referenced from other files). 103 | let externalQualifiers = set ["in"; "out"; "attribute"; "varying"; "uniform"] 104 | 105 | let isFieldSwizzle s = 106 | Seq.forall (fun c -> Seq.contains c "rgba") s || 107 | Seq.forall (fun c -> Seq.contains c "xyzw") s || 108 | Seq.forall (fun c -> Seq.contains c "stpq") s 109 | 110 | let swizzleIndex = function 111 | | 'r' | 'x' | 's' -> 0 112 | | 'g' | 'y' | 't' -> 1 113 | | 'b' | 'z' | 'p' -> 2 114 | | 'a' | 'w' | 'q' -> 3 115 | | c -> failwithf "not a swizzle (%c) " c 116 | -------------------------------------------------------------------------------- /SMBolero.Client/Properties/launchSettings.json: -------------------------------------------------------------------------------- 1 | { 2 | "profiles": { 3 | "SMBolero.Client": { 4 | "commandName": "Project", 5 | "launchBrowser": true, 6 | "environmentVariables": { 7 | "ASPNETCORE_ENVIRONMENT": "Development" 8 | }, 9 | "applicationUrl": "https://localhost:54027;http://localhost:54028" 10 | } 11 | } 12 | } -------------------------------------------------------------------------------- /SMBolero.Client/SMBolero.Client.fsproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | net8.0 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | PreserveNewest 22 | 23 | 24 | Never 25 | 26 | 27 | Never 28 | 29 | 30 | 31 | -------------------------------------------------------------------------------- /SMBolero.Client/Startup.fs: -------------------------------------------------------------------------------- 1 | namespace SMBolero.Client 2 | 3 | open Microsoft.AspNetCore.Components.WebAssembly.Hosting 4 | open Bolero.Remoting.Client 5 | 6 | module Program = 7 | 8 | [] 9 | let Main args = 10 | let builder = WebAssemblyHostBuilder.CreateDefault(args) 11 | builder.RootComponents.Add("#main") 12 | builder.Services.AddBoleroRemoting(builder.HostEnvironment) |> ignore 13 | builder.Build().RunAsync() |> ignore 14 | 0 15 | -------------------------------------------------------------------------------- /SMBolero.Client/wwwroot/index.html: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | Shader Minifier 7 | 8 | 9 | 10 |
Loading...
11 | 12 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /SMBolero.Client/wwwroot/minifier.js: -------------------------------------------------------------------------------- 1 | const highlights = []; 2 | const min2src = []; 3 | const src2min = []; 4 | 5 | function getHash(line, col, isMin) { 6 | return line * 1000 + col; 7 | } 8 | 9 | function extractAnnotations(str) { 10 | const lines = str.split('\n'); 11 | for (let i = 0; i < lines.length; i++) { 12 | var hasReplaced = true; 13 | while (hasReplaced) { 14 | hasReplaced = false; 15 | lines[i] = lines[i].replace(/(\w+)@(-?\d+),(-?\d+)@/, function (match, ident, line, col, offset) { 16 | hasReplaced = true; 17 | line--; 18 | col--; 19 | min2src[getHash(i, offset)] = { ident, line, col }; 20 | src2min[getHash(line, col)] = { ident, line: i, col: offset }; 21 | return ident; 22 | }); 23 | } 24 | } 25 | return lines.join('\n'); 26 | } 27 | 28 | function getPrefix(isMin) { 29 | return isMin ? 'min' : 'src'; 30 | } 31 | 32 | function addAnnotations(str, sourceMap, div, isMin) { 33 | const lines = str.split('\n'); 34 | for (let i = 0; i < lines.length; i++) { 35 | const line = lines[i]; 36 | const lineDiv = document.createElement('div'); 37 | lineDiv.classList.add('line'); 38 | var html = line.replace(/\w+/g, function (match, offset) { 39 | // console.log(match, i, offset); 40 | const hash1 = getHash(i, offset); 41 | if (sourceMap[hash1]) { 42 | const hash2 = getHash(sourceMap[hash1].line, sourceMap[hash1].col); 43 | return `${match}`; 44 | } 45 | return match; 46 | }); 47 | 48 | const comment = html.indexOf('//'); 49 | if (comment !== -1) { 50 | html = html.substring(0, comment) + '' + html.substring(comment) + ''; 51 | } 52 | 53 | lineDiv.innerHTML = html; 54 | div.appendChild(lineDiv); 55 | } 56 | } 57 | 58 | function show(x, hash) { 59 | const links = document.querySelectorAll("." + hash); 60 | removeHighlights(); 61 | for (const link of links) { 62 | addHighlight(link); 63 | } 64 | addHighlight(x); 65 | } 66 | function removeHighlights() { 67 | for (const hl of highlights) { 68 | hl.classList.remove('highlight'); 69 | } 70 | highlights.length = 0; 71 | } 72 | 73 | 74 | function addHighlight(item) { 75 | item.classList.add('highlight'); 76 | item.scrollIntoView({ block: "center" }); 77 | highlights.push(item); 78 | } 79 | 80 | function updateShader(shaderSource, shaderMinified) { 81 | const source = document.querySelector('.source'); 82 | const minified = document.querySelector('.minified'); 83 | 84 | removeHighlights(); 85 | source.innerHTML = ''; 86 | minified.innerHTML = ''; 87 | min2src.length = 0; 88 | src2min.length = 0; 89 | 90 | const shaderMinified2 = extractAnnotations(shaderMinified); 91 | addAnnotations(shaderMinified2, min2src, minified, true); 92 | addAnnotations(shaderSource, src2min, source, false); 93 | } 94 | 95 | function copyBtn() { 96 | const minified = document.querySelector('.minified'); 97 | console.log("Copy", minified.textContent); 98 | navigator.clipboard.writeText(minified.textContent); 99 | const icon = document.querySelector('.copy-icon'); 100 | 101 | // animation 102 | icon.classList.remove('animated-icon'); 103 | setTimeout(() => icon.classList.add('animated-icon'), 0); 104 | } 105 | -------------------------------------------------------------------------------- /SMBolero.Server/Index.fs: -------------------------------------------------------------------------------- 1 | module SMBolero.Server.Index 2 | 3 | open Bolero.Html 4 | open Bolero.Server.Html 5 | open SMBolero 6 | 7 | let page = doctypeHtml { 8 | head { 9 | meta { attr.charset "UTF-8" } 10 | meta { attr.name "viewport"; attr.content "width=device-width, initial-scale=1.0" } 11 | title { "Shader Minifier" } 12 | link { attr.rel "stylesheet"; attr.href "css/index.css" } 13 | } 14 | body { 15 | div { attr.id "main"; comp } 16 | boleroScript 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /SMBolero.Server/Properties/launchSettings.json: -------------------------------------------------------------------------------- 1 | { 2 | "profiles": { 3 | "SMBolero.Server": { 4 | "commandName": "Project", 5 | "launchBrowser": true, 6 | "environmentVariables": { 7 | "ASPNETCORE_ENVIRONMENT": "Development" 8 | }, 9 | "applicationUrl": "https://localhost:54039;http://localhost:54040" 10 | } 11 | } 12 | } -------------------------------------------------------------------------------- /SMBolero.Server/SMBolero.Server.fsproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | net8.0 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | -------------------------------------------------------------------------------- /SMBolero.Server/Startup.fs: -------------------------------------------------------------------------------- 1 | namespace SMBolero.Server 2 | 3 | open Microsoft.AspNetCore 4 | open Microsoft.AspNetCore.Authentication.Cookies 5 | open Microsoft.AspNetCore.Builder 6 | open Microsoft.AspNetCore.Hosting 7 | open Microsoft.Extensions.DependencyInjection 8 | open Bolero 9 | open Bolero.Remoting.Server 10 | open Bolero.Server 11 | open SMBolero 12 | open Bolero.Templating.Server 13 | 14 | type Startup() = 15 | 16 | // This method gets called by the runtime. Use this method to add services to the container. 17 | // For more information on how to configure your application, visit https://go.microsoft.com/fwlink/?LinkID=398940 18 | member this.ConfigureServices(services: IServiceCollection) = 19 | services.AddMvc() |> ignore 20 | services.AddServerSideBlazor() |> ignore 21 | services 22 | .AddAuthorization() 23 | .AddAuthentication(CookieAuthenticationDefaults.AuthenticationScheme) 24 | .AddCookie() 25 | .Services 26 | .AddBoleroHost() 27 | #if DEBUG 28 | .AddHotReload(templateDir = __SOURCE_DIRECTORY__ + "/../SMBolero.Client") 29 | #endif 30 | |> ignore 31 | 32 | // This method gets called by the runtime. Use this method to configure the HTTP request pipeline. 33 | member this.Configure(app: IApplicationBuilder, env: IWebHostEnvironment) = 34 | app 35 | .UseAuthentication() 36 | .UseRemoting() 37 | .UseStaticFiles() 38 | .UseRouting() 39 | .UseBlazorFrameworkFiles() 40 | .UseEndpoints(fun endpoints -> 41 | #if DEBUG 42 | endpoints.UseHotReload() 43 | #endif 44 | endpoints.MapBlazorHub() |> ignore 45 | endpoints.MapFallbackToBolero(Index.page) |> ignore) 46 | |> ignore 47 | 48 | module Program = 49 | 50 | [] 51 | let main args = 52 | WebHost 53 | .CreateDefaultBuilder(args) 54 | .UseStaticWebAssets() 55 | .UseStartup() 56 | .Build() 57 | .Run() 58 | 0 59 | -------------------------------------------------------------------------------- /Shader Minifier.sln: -------------------------------------------------------------------------------- 1 |  2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio Version 17 4 | VisualStudioVersion = 17.0.31903.59 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{F2A71F9B-5D33-465A-A702-920D77279786}") = "Minifier", "Minifier\Minifier.fsproj", "{325463FD-AC9D-40DC-B8F2-4ECE086DD840}" 7 | EndProject 8 | Project("{F2A71F9B-5D33-465A-A702-920D77279786}") = "Checker", "Checker\Checker.fsproj", "{193EC716-6B61-4A84-A955-6F5AA057B776}" 9 | EndProject 10 | Project("{F2A71F9B-5D33-465A-A702-920D77279786}") = "SMBolero.Client", "SMBolero.Client\SMBolero.Client.fsproj", "{F6A044CD-2AAA-4849-A4BC-B35AD681A2E2}" 11 | EndProject 12 | Project("{F2A71F9B-5D33-465A-A702-920D77279786}") = "SMBolero.Server", "SMBolero.Server\SMBolero.Server.fsproj", "{AD579A74-B3E4-46F1-B262-1F0E37B71BE3}" 13 | EndProject 14 | Project("{F2A71F9B-5D33-465A-A702-920D77279786}") = "ShaderMinifier", "ShaderMinifier\ShaderMinifier.fsproj", "{9D562C37-FE7F-4D40-B456-4036FA4FAA7E}" 15 | EndProject 16 | Global 17 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 18 | Debug|Any CPU = Debug|Any CPU 19 | Release|Any CPU = Release|Any CPU 20 | EndGlobalSection 21 | GlobalSection(SolutionProperties) = preSolution 22 | HideSolutionNode = FALSE 23 | EndGlobalSection 24 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 25 | {325463FD-AC9D-40DC-B8F2-4ECE086DD840}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 26 | {325463FD-AC9D-40DC-B8F2-4ECE086DD840}.Debug|Any CPU.Build.0 = Debug|Any CPU 27 | {325463FD-AC9D-40DC-B8F2-4ECE086DD840}.Release|Any CPU.ActiveCfg = Release|Any CPU 28 | {325463FD-AC9D-40DC-B8F2-4ECE086DD840}.Release|Any CPU.Build.0 = Release|Any CPU 29 | {193EC716-6B61-4A84-A955-6F5AA057B776}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 30 | {193EC716-6B61-4A84-A955-6F5AA057B776}.Debug|Any CPU.Build.0 = Debug|Any CPU 31 | {193EC716-6B61-4A84-A955-6F5AA057B776}.Release|Any CPU.ActiveCfg = Release|Any CPU 32 | {193EC716-6B61-4A84-A955-6F5AA057B776}.Release|Any CPU.Build.0 = Release|Any CPU 33 | {F6A044CD-2AAA-4849-A4BC-B35AD681A2E2}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 34 | {F6A044CD-2AAA-4849-A4BC-B35AD681A2E2}.Debug|Any CPU.Build.0 = Debug|Any CPU 35 | {F6A044CD-2AAA-4849-A4BC-B35AD681A2E2}.Release|Any CPU.ActiveCfg = Release|Any CPU 36 | {F6A044CD-2AAA-4849-A4BC-B35AD681A2E2}.Release|Any CPU.Build.0 = Release|Any CPU 37 | {AD579A74-B3E4-46F1-B262-1F0E37B71BE3}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 38 | {AD579A74-B3E4-46F1-B262-1F0E37B71BE3}.Debug|Any CPU.Build.0 = Debug|Any CPU 39 | {AD579A74-B3E4-46F1-B262-1F0E37B71BE3}.Release|Any CPU.ActiveCfg = Release|Any CPU 40 | {AD579A74-B3E4-46F1-B262-1F0E37B71BE3}.Release|Any CPU.Build.0 = Release|Any CPU 41 | {9D562C37-FE7F-4D40-B456-4036FA4FAA7E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 42 | {9D562C37-FE7F-4D40-B456-4036FA4FAA7E}.Debug|Any CPU.Build.0 = Debug|Any CPU 43 | {9D562C37-FE7F-4D40-B456-4036FA4FAA7E}.Release|Any CPU.ActiveCfg = Release|Any CPU 44 | {9D562C37-FE7F-4D40-B456-4036FA4FAA7E}.Release|Any CPU.Build.0 = Release|Any CPU 45 | EndGlobalSection 46 | EndGlobal 47 | -------------------------------------------------------------------------------- /ShaderMinifier/ShaderMinifier.fsproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | Exe 5 | net8.0 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | ..\lib\Argu.dll 15 | 16 | 17 | ..\lib\FParsec.dll 18 | 19 | 20 | ..\lib\FParsecCS.dll 21 | 22 | 23 | ..\lib\FSharp.Core.dll 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | -------------------------------------------------------------------------------- /ShaderMinifier/main.fs: -------------------------------------------------------------------------------- 1 | module Main 2 | 3 | open ShaderMinifier 4 | open System.IO 5 | 6 | let readFile file = 7 | use stream = 8 | if file = "" then new StreamReader(System.Console.OpenStandardInput()) 9 | else new StreamReader(file) 10 | stream.ReadToEnd() 11 | 12 | let minifyFiles (options: Options.Options) filenames out = 13 | let files = [| 14 | for f in filenames do 15 | let content = readFile f 16 | let filename = if f = "" then "stdin" else f 17 | yield filename, content |] 18 | let minifier = Minifier(options, files) 19 | minifier.Format(out) 20 | 21 | let run (options: Options.Options) filenames = 22 | use out = 23 | if Options.debugMode || options.outputName = "" || options.outputName = "-" then stdout 24 | else new StreamWriter(options.outputName) :> TextWriter 25 | try 26 | minifyFiles options filenames out 27 | 0 28 | with 29 | | :? IOException as ex -> 30 | printfn "Error: %s" ex.Message 31 | 1 32 | | exn -> 33 | printfn "%s" (exn.ToString()) 34 | 1 35 | 36 | [] 37 | let main argv = 38 | let err = 39 | try 40 | let options, files = Options.initFiles argv 41 | if options.verbose then 42 | printfn "Shader Minifier %s - https://github.com/laurentlb/Shader_Minifier" Options.version 43 | run options files 44 | with 45 | | :? Argu.ArguParseException as ex -> 46 | printfn "%s" ex.Message 47 | 1 48 | | Failure msg -> 49 | printfn "%s" msg 50 | 1 51 | if Options.debugMode then System.Console.ReadLine() |> ignore 52 | exit err 53 | -------------------------------------------------------------------------------- /appveyor.yml: -------------------------------------------------------------------------------- 1 | version: 1.0.{build} 2 | branches: 3 | only: 4 | - master 5 | image: Visual Studio 2022 6 | configuration: Debug 7 | platform: Any CPU 8 | before_build: 9 | - cmd: nuget restore 10 | build_script: 11 | - cmd: dotnet --version 12 | - cmd: dotnet build "Shader Minifier.sln" /l:"C:\Program Files\AppVeyor\BuildAgent\dotnetcore\Appveyor.MSBuildLogger.dll" 13 | test_script: 14 | - cmd: dotnet run --project Checker/ --compile-golden 15 | -------------------------------------------------------------------------------- /check.bash: -------------------------------------------------------------------------------- 1 | #! /bin/bash 2 | 3 | dotnet run --project Checker/ --skip-glslang-compile 4 | -------------------------------------------------------------------------------- /compile.bash: -------------------------------------------------------------------------------- 1 | #! /bin/bash 2 | 3 | dotnet build "Shader Minifier.sln" 4 | -------------------------------------------------------------------------------- /lib/Argu.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/laurentlb/shader-minifier/686983819d150b5fd30bb6fbf6d1e60652f2e52d/lib/Argu.dll -------------------------------------------------------------------------------- /lib/Compressor.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/laurentlb/shader-minifier/686983819d150b5fd30bb6fbf6d1e60652f2e52d/lib/Compressor.dll -------------------------------------------------------------------------------- /lib/FParsec.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/laurentlb/shader-minifier/686983819d150b5fd30bb6fbf6d1e60652f2e52d/lib/FParsec.dll -------------------------------------------------------------------------------- /lib/FParsecCS.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/laurentlb/shader-minifier/686983819d150b5fd30bb6fbf6d1e60652f2e52d/lib/FParsecCS.dll -------------------------------------------------------------------------------- /lib/FSharp.Core.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/laurentlb/shader-minifier/686983819d150b5fd30bb6fbf6d1e60652f2e52d/lib/FSharp.Core.dll -------------------------------------------------------------------------------- /lib/OpenTK.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/laurentlb/shader-minifier/686983819d150b5fd30bb6fbf6d1e60652f2e52d/lib/OpenTK.dll -------------------------------------------------------------------------------- /lib/System.ValueTuple.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/laurentlb/shader-minifier/686983819d150b5fd30bb6fbf6d1e60652f2e52d/lib/System.ValueTuple.dll -------------------------------------------------------------------------------- /run-from-source.bash: -------------------------------------------------------------------------------- 1 | #! /bin/bash 2 | 3 | dotnet run --project ShaderMinifier -- "$@" 4 | -------------------------------------------------------------------------------- /tests/compile.txt: -------------------------------------------------------------------------------- 1 | 330 frag tests/out/real/chocolux.minind.frag 2 | 330 frag tests/out/real/clod.minind.frag 3 | 110 frag tests/out/real/kinder_painter.minind.frag 4 | 330 frag tests/out/real/disco.minind.frag 5 | 330 frag tests/out/real/leizex.minind.frag 6 | 330 frag tests/out/real/heart.minind.frag 7 | 330 frag tests/out/real/mandelbulb.minind.frag 8 | # https://github.com/laurentlb/shader-minifier/issues/402 : 110 frag tests/out/real/to_the_road_of_ribbon.minind.frag 9 | 330 frag tests/out/real/sult.minind.frag 10 | 330 frag tests/out/real/monjori.minind.frag 11 | 330 frag tests/out/real/valley_ball.minind.glsl 12 | 330 frag tests/out/real/slisesix.minind.frag 13 | 330 frag tests/out/real/lunaquatic.minind.frag 14 | 15 | hlsl frag tests/out/real/elevated.minind.hlsl 16 | 17 | 110 frag tests/out/real/yx_long_way_from_home.minind.frag 18 | 110 frag tests/out/real/oscars_chair.minind.frag 19 | 110 frag tests/out/real/the_real_party_is_in_your_pocket.minind.frag 20 | # illegal input (bad preprocessing?) - 110 frag tests/out/real/ohanami.minind.frag 21 | 430 comp tests/out/real/terrarium.minind.frag 22 | 430 comp tests/out/real/from-the-seas-to-the-stars.minind.frag 23 | 24 | shadertoy frag tests/out/real/ed-209.minind.frag 25 | shadertoy frag tests/out/real/frozen-wasteland.minind.frag 26 | shadertoy frag tests/out/real/controllable-machinery.minind.frag 27 | shadertoy frag tests/out/real/endeavour.minind.frag 28 | shadertoy frag tests/out/real/audio-flight-v2.minind.frag 29 | shadertoy frag tests/out/real/buoy.minind.frag 30 | shadertoy frag tests/out/real/orchard.minind.frag 31 | shadertoy frag tests/out/real/robin.minind.frag 32 | -------------------------------------------------------------------------------- /tests/compression_results.log: -------------------------------------------------------------------------------- 1 | clod.frag (and others) 8694 => 1481.011 2 | mouton/mouton.vert (and others) 16573 => 2403.350 3 | audio-flight-v2.frag 4466 => 863.455 4 | buoy.frag 3975 => 594.340 5 | controllable-machinery.frag 7671 => 1212.215 6 | ed-209.frag 7389 => 1303.549 7 | elevated.hlsl 3405 => 602.340 8 | endeavour.frag 2567 => 522.812 9 | from-the-seas-to-the-stars.frag 14169 => 2272.104 10 | frozen-wasteland.frag 4455 => 772.630 11 | kinder_painter.frag 2832 => 446.282 12 | leizex.frag 2252 => 502.674 13 | lunaquatic.frag 5222 => 1040.171 14 | mandelbulb.frag 2309 => 530.410 15 | ohanami.frag 3179 => 699.259 16 | orchard.frag 5336 => 981.381 17 | oscars_chair.frag 4650 => 979.902 18 | robin.frag 6183 => 1030.289 19 | slisesix.frag 4431 => 882.862 20 | terrarium.frag 3565 => 743.327 21 | the_real_party_is_in_your_pocket.frag 11964 => 1744.283 22 | valley_ball.glsl 4306 => 877.540 23 | yx_long_way_from_home.frag 2885 => 581.527 24 | Total: 132478 => 23067.712 25 | -------------------------------------------------------------------------------- /tests/real/README.md: -------------------------------------------------------------------------------- 1 | This is a third-party directory. Files in this directory do not have the same 2 | license as the main repository. These files are used only for testing purposes. 3 | Do not use them in any other way without their author first. 4 | 5 | ## How we use the files 6 | 7 | 1. Parser coverage. We need to ensure that Shader Minifier can parse a variety 8 | of shader files. These files help us improve the coverage and be more 9 | confident when we make changes to the parser. 10 | 11 | 2. AST transformation coverage. When we implement AST transformations, we run 12 | them on the test shaders. We call a shader compiler to ensure the output 13 | still compiles. Additionally, we manually review the changes to the minified 14 | shaders to spot potential issues. 15 | 16 | 3. Compression tests. We use these tests to check that Shader Minifier output 17 | stays small and compresses well. We need a variety of test files that are 18 | "realistic" (synthetic files wouldn't have the same compression profile). 19 | 20 | 4. Performance tests. We check the performance of Shader Minifier on real 21 | shaders and make sure it remains fast enough. 22 | 23 | 24 | ## Updating the files 25 | 26 | - `.expected` files are generated by Shader Minifier. They are updated when we 27 | run the tests. 28 | - If you own any of these files, you can reach out to update the file, clarify 29 | the attribution, or have it deleted. 30 | - If you want to contribute new files, you can send a pull request. We prefer 31 | files that increase the code coverage or are representative of the modern 32 | demoscene. 33 | 34 | Note: When the project started, it was not open-source and shaders were 35 | collected from various sources. They are not always well attributed; sorry about 36 | that, we're more careful from now on. We add files that have a compatible 37 | license and add attribution in the file header. 38 | -------------------------------------------------------------------------------- /tests/real/chocolux.expected: -------------------------------------------------------------------------------- 1 | // Generated with (https://github.com/laurentlb/Shader_Minifier/) 2 | #ifndef CHOCOLUX_EXPECTED_ 3 | # define CHOCOLUX_EXPECTED_ 4 | # define VAR_resolution "k" 5 | # define VAR_time "v" 6 | 7 | const char *chocolux_frag = 8 | "uniform vec2 k;" 9 | "uniform float v;" 10 | "float s(vec3 d)" 11 | "{" 12 | "return length(d-vec3(cos(v)+sin(v*.2),.3,2.+cos(v*.5)*.5))*length(d-vec3(-cos(v*.7),.3,2.+sin(v*.5)))*length(d-vec3(-sin(v*.2)*.5,sin(v),2))*(cos(d.y)*cos(d.x)-.1-cos(d.z*7.+v*7.)*cos(d.x*3.)*cos(d.y*4.)*.1);" 13 | "}" 14 | "void main()" 15 | "{" 16 | "vec2 d=-1.+2.*gl_FragCoord.xy/k.xy;" 17 | "vec3 c=vec3(d.x,d.y*1.25-.3,0),y=vec3(d.x+cos(v)*.3,d.y,1)/64.;" 18 | "vec4 f=vec4(0);" 19 | "float x=0.;" 20 | "for(int v=0;v<75;v++)" 21 | "{" 22 | "if(s(c+y*x)<.4)" 23 | "{" 24 | "x-=5.;" 25 | "for(int f=0;f<5;f++)" 26 | "{" 27 | "if(s(c+y*x)<.4)" 28 | "break;" 29 | "x+=1.;" 30 | "}" 31 | "vec3 d=vec3(.01,0,0),v=vec3(0);" 32 | "v.x=s(c+y*x)-s(vec3(c+y*x+d.xyy));" 33 | "v.y=s(c+y*x)-s(vec3(c+y*x+d.yxy));" 34 | "v.z=s(c+y*x)-s(vec3(c+y*x+d.yyx));" 35 | "v=normalize(v);" 36 | "f+=max(dot(vec3(0,0,-.5),v),0.)+max(dot(vec3(0,-.5,.5),v),0.)*.5;" 37 | "break;" 38 | "}" 39 | "x+=5.;" 40 | "}" 41 | "gl_FragColor=f+x*.025*vec4(.1,.2,.5,1);" 42 | "}"; 43 | 44 | #endif // CHOCOLUX_EXPECTED_ 45 | -------------------------------------------------------------------------------- /tests/real/chocolux.frag: -------------------------------------------------------------------------------- 1 | uniform vec2 resolution; 2 | uniform float time; 3 | 4 | float h(vec3 q) 5 | { 6 | float f=1.*distance(q,vec3(cos(time)+sin(time*.2),.3,2.+cos(time*.5)*.5)); 7 | f*=distance(q,vec3(-cos(time*.7),.3,2.+sin(time*.5))); 8 | f*=distance(q,vec3(-sin(time*.2)*.5,sin(time),2.)); 9 | f*=cos(q.y)*cos(q.x)-.1-cos(q.z*7.+time*7.)*cos(q.x*3.)*cos(q.y*4.)*.1; 10 | return f; 11 | } 12 | 13 | void main() 14 | { 15 | vec2 p = -1.0 + 2.0 * gl_FragCoord.xy / resolution.xy; 16 | vec3 o=vec3(p.x,p.y*1.25-0.3,0.); 17 | vec3 d=vec3(p.x+cos(time)*0.3,p.y,1.)/64.; 18 | vec4 c=vec4(0.); 19 | float t=0.; 20 | for(int i=0;i<75;i++) 21 | { 22 | if(h(o+d*t)<.4) 23 | { 24 | t-=5.; 25 | for(int j=0;j<5;j++) 26 | { 27 | if(h(o+d*t)<.4) 28 | break; 29 | t+=1.; 30 | } 31 | vec3 e=vec3(.01,.0,.0); 32 | vec3 n=vec3(.0); 33 | n.x=h(o+d*t)-h(vec3(o+d*t+e.xyy)); 34 | n.y=h(o+d*t)-h(vec3(o+d*t+e.yxy)); 35 | n.z=h(o+d*t)-h(vec3(o+d*t+e.yyx)); 36 | n=normalize(n); 37 | c+=max(dot(vec3(.0,.0,-.5),n),.0)+max(dot(vec3(.0,-.5,.5),n),.0)*.5; 38 | break; 39 | } 40 | t+=5.; 41 | } 42 | gl_FragColor=c+vec4(.1,.2,.5,1.)*(t*.025); 43 | } 44 | -------------------------------------------------------------------------------- /tests/real/clod.expected: -------------------------------------------------------------------------------- 1 | uniform vec2 v;uniform float s;uniform sampler2D y,c,C,D;float n(vec3 v){float s=(sin(v.x)+v.y*.25)*.35;v=vec3(cos(s)*v.x-sin(s)*v.y,sin(s)*v.x+cos(s)*v.y,v.z);return dot(cos(v)*cos(v),vec3(1))-1.2;}vec3 m(vec3 v){vec3 m=vec3(sin(s*1.5)*.5,cos(s)*.5,s);float y=0.,c,f;for(int s=0;s<75;s++){if(n(m+v*y)<0.){c=y-.125;f=y;for(int s=0;s<10;s++){y=(c+f)*.5;if(n(m+v*y)<0.)f=y;else c=y;}vec3 s=vec3(.1,0,0),i=m+v*y;s=-normalize(vec3(n(i+s),n(i+s.yxy),n(i+s.yyx))+vec3(sin(i*75.))*.01);return vec3(mix((max(-dot(s,vec3(.577)),0.)+.125*max(-dot(s,vec3(-.707,-.707,0)),0.))*(mod(length(i.xy)*20.,2.)<1.?vec3(.71,.85,.25):vec3(.79,.93,.4)),vec3(.93,.94,.85),vec3(pow(y/9.,5.))));}y+=.125;}return vec3(.93,.94,.85);}void main(){vec2 s=-1.+2.*gl_FragCoord.xy/v.xy;gl_FragColor=vec4(m(normalize(vec3(s.xy,1))),1);} 2 | -------------------------------------------------------------------------------- /tests/real/clod.frag: -------------------------------------------------------------------------------- 1 | uniform vec2 resolution; 2 | uniform float time; 3 | uniform sampler2D tex0; 4 | uniform sampler2D tex1; 5 | uniform sampler2D tex2; 6 | uniform sampler2D tex3; 7 | 8 | float f(vec3 o) 9 | { 10 | float a=(sin(o.x)+o.y*.25)*.35; 11 | o=vec3(cos(a)*o.x-sin(a)*o.y,sin(a)*o.x+cos(a)*o.y,o.z); 12 | return dot(cos(o)*cos(o),vec3(1))-1.2; 13 | } 14 | vec3 s(vec3 o,vec3 d) 15 | { 16 | float t=0.,a,b; 17 | for(int i=0;i<75;i++) 18 | { 19 | if(f(o+d*t)<0.0) 20 | { 21 | a=t-.125;b=t; 22 | for(int i=0; i<10;i++) 23 | { 24 | t=(a+b)*.5; 25 | if(f(o+d*t)<0.0) 26 | b=t; 27 | else 28 | a=t; 29 | } 30 | vec3 e=vec3(.1,0.0,0.0); 31 | vec3 p=o+d*t; 32 | vec3 n=-normalize(vec3(f(p+e),f(p+e.yxy),f(p+e.yyx))+vec3((sin(p*75.)))*.01); 33 | 34 | return vec3( mix( ((max(-dot(n,vec3(.577)),0.) + 0.125*max(-dot(n,vec3(-.707,-.707,0)),0.)))*(mod(length(p.xy)*20.,2.)<1.0?vec3(.71,.85,.25):vec3(.79,.93,.4)) 35 | ,vec3(.93,.94,.85), vec3(pow(t/9.,5.)) ) ); 36 | } 37 | t+=.125; 38 | } 39 | return vec3(.93,.94,.85); 40 | } 41 | void main() 42 | { 43 | vec2 p = -1.0 + 2.0 * gl_FragCoord.xy / resolution.xy; 44 | gl_FragColor=vec4(s(vec3(sin(time*1.5)*.5,cos(time)*.5,time), normalize(vec3(p.xy,1.0))),1.0); 45 | } 46 | -------------------------------------------------------------------------------- /tests/real/deform.frag: -------------------------------------------------------------------------------- 1 | uniform float time; 2 | uniform vec2 resolution; 3 | uniform vec4 mouse; 4 | uniform sampler2D tex0; 5 | uniform sampler2D tex1; 6 | uniform sampler2D tex2; 7 | uniform sampler2D tex3; 8 | 9 | void main(void) 10 | { 11 | vec2 p = -1.0 + 2.0 * gl_FragCoord.xy / resolution.xy; 12 | vec2 m = -1.0 + 2.0 * mouse.xy / resolution.xy; 13 | 14 | float a1 = atan(p.y-m.y,p.x-m.x); 15 | float r1 = sqrt(dot(p-m,p-m)); 16 | float a2 = atan(p.y+m.y,p.x+m.x); 17 | float r2 = sqrt(dot(p+m,p+m)); 18 | 19 | vec2 uv; 20 | uv.x = 0.2*time + (r1-r2)*0.25; 21 | uv.y = sin(2.0*(a1-a2)); 22 | 23 | float w = r1*r2*0.8; 24 | vec3 col = texture2D(tex0,uv).xyz; 25 | 26 | gl_FragColor = vec4(col/(.1+w),1.0); 27 | } 28 | -------------------------------------------------------------------------------- /tests/real/disco.expected: -------------------------------------------------------------------------------- 1 | // Generated with (https://github.com/laurentlb/Shader_Minifier/) 2 | var var_RESOLUTION = "s" 3 | var var_TEX0 = "f" 4 | var var_TEX1 = "C" 5 | var var_TEX2 = "D" 6 | var var_TEX3 = "y" 7 | var var_TIME = "v" 8 | 9 | var disco_frag = `uniform vec2 s;uniform float v;uniform sampler2D f,C,D,y;vec4 n(vec2 s,float f){float c=v*sign(f),a=s.x*320.*.0065*f,i=s.y*240.*.006*f,y=sqrt(a*a+i*i);if(y>1.)return vec4(0);{float r=-.4*sign(f)+sin(c*.05),n=sqrt(1.-a*a-i*i),u=i*sin(r)-n*cos(r);i=i*cos(r)+n*sin(r);n=acos(i);r=acos(a/sin(n))/6.283*120.*sign(u)-c;n=n*60./3.1415;u=cos(floor(n/3.1415));y=pow(abs(cos(r)*sin(n)),.2)*.1/(u+sin(float(int((r+1.57075)/3.1415))+c*.6+cos(u*25.)))*pow(1.-y,.9);return y<0.?vec4(-y/2.*abs(cos(c*.1)),0,-y*2.*abs(sin(c*.04)),1):vec4(y,y*2.,y*2.,1);}}void main(){vec2 f=-1.+2.*gl_FragCoord.xy/s.xy;vec4 r=vec4(0);for(int i=80;i>0;i--)r+=n(f,1.-float(i)/80.)*(.008-float(i)*5e-5);vec4 i=n(f,1.);gl_FragColor=(i.w==0.?n(f,-.2)*.02:i)+sqrt(r);}` 10 | -------------------------------------------------------------------------------- /tests/real/disco.frag: -------------------------------------------------------------------------------- 1 | uniform vec2 resolution; 2 | uniform float time; 3 | uniform sampler2D tex0; 4 | uniform sampler2D tex1; 5 | uniform sampler2D tex2; 6 | uniform sampler2D tex3; 7 | 8 | vec4 s(vec2 px,float z) 9 | { 10 | float l=3.1415; 11 | float k=time*sign(z); 12 | float x = px.x*320.0*.0065*z; 13 | float y = px.y*240.0*.0060*z; 14 | float c=sqrt(x*x+y*y); 15 | if(c>1.0) 16 | { 17 | return vec4(0.0); 18 | } 19 | else 20 | { 21 | float u=-.4*sign(z)+sin(k*.05); 22 | float v=sqrt(1.0-x*x-y*y); 23 | float q=y*sin(u)-v*cos(u); 24 | y=y*cos(u)+v*sin(u); 25 | v=acos(y); 26 | u=acos(x/sin(v))/(2.0*l)*120.0*sign(q)-k; 27 | v=v*60.0/l; 28 | q=cos(floor(v/l)); 29 | c=pow(abs(cos(u)*sin(v)),.2)*.1/(q+sin(float(int((u+l/2.0)/l))+k*.6+cos(q*25.0)))*pow(1.0-c,.9); 30 | 31 | vec4 res; 32 | if(c<0.0) 33 | res = vec4(-c/2.0*abs(cos(k*.1)),0.0,-c*2.0*abs(sin(k*.04)),1.0); 34 | else 35 | res = vec4(c,c*2.0,c*2.0,1.0); 36 | return res; 37 | } 38 | } 39 | 40 | void main(void) 41 | { 42 | vec2 p = -1.0 + 2.0 * gl_FragCoord.xy / resolution.xy; 43 | vec4 c = vec4(0.0); 44 | for(int i=80;i>0;i--) 45 | c+=s(p,1.0-float(i)/80.0)*(.008-float(i)*.00005); 46 | vec4 d=s(p,1.0); 47 | gl_FragColor = (d.a==0.0?s(p,-.2)*.02:d)+sqrt(c); 48 | } 49 | -------------------------------------------------------------------------------- /tests/real/elevated.hlsl: -------------------------------------------------------------------------------- 1 | sampler t0,t1,t2;float4 q[16];float4x4 v:register(c16);float3 no(float2 p){float2 f=p-floor(p);float2 u=f*f*f*(f*(f*6-15)+10);float a=tex2Dlod(t0,float4((floor(p)+float2(0,0))/256,0,0));float b=tex2Dlod(t0,float4((floor(p)+float2(1,0))/256,0,0));float c=tex2Dlod(t0,float4((floor(p)+float2(0,1))/256,0,0));float d=tex2Dlod(t0,float4((floor(p)+float2(1,1))/256,0,0));return float3(a+(b-a)*u.x+(c-a)*u.y+(a-b-c+d)*u.x*u.y,30*f*f*(f*(f-2)+1)*(float2(b-a,c-a)+(a-b-c+d)*u.yx));}float f(float2 p,float o){float2 d=0;float a=0;float b=3;for(float i=0;i.5){float t=length(d.xyz-q[4].xyz);float w=q[1].w-d.y;if(w<0){float3 n=cn(d.xz,.001*t,12-log2(t));float h=f(3*d.xz,3);float r=no(666*d.xz);c=(.1+.75*q[2].x)*(.8+.2*r);c=lerp(c,lerp(float3(.8,.85,.9),float3(.45,.45,.2)*(.8+.2*r),q[2].x),smoothstep(.5-.8*n.y,1-1.1*n.y,h*.15));c=lerp(c,lerp(float3(.37,.23,.08),float3(.42,.4,.2),q[2].x)*(.5+.5*r),smoothstep(0,1,50*(n.y-1)+(h+q[2].x)/.4));c*=b(d,n,cn(d.xz,.001*t,5));}else{t=(q[1].w-q[4].y)/e.y;d=q[4]+e.xyzz*t;float3 n=normalize(cn(float2(512,32)*d.xz+saturate(w*60)*float2(q[3].w,0),.001*t,4)*float3(1,6,1));c=.12*(float3(.4,1,1)-float3(.2,.6,.4)*saturate(w*16));c*=.3+.7*q[2].x;c+=pow(1-mul(-e,n),4)*(pow(mul(q[3],reflect(-e,n)),32)*float3(.32,.31,.3)+.1);c=lerp(c,b(d,n,n),smoothstep(1,0,q[2].x+w*60-f(666*d.xz+saturate(w*60)*float2(q[3].w,0)*2,5))*.5);}c*=.7+.3*smoothstep(0,1,256*abs(w));c*=exp(-.042*t);c+=(1-exp(-.1*t))*(float3(.52,.59,.65)+pow(saturate(mul(e,q[3])),8)*float3(.6,.4,.1));}return float4(c,0);}float4 m4(float2 x:texcoord):color{float2 o=x+.5/1280;float4 d=tex2D(t1,o);float3 c=tex2D(t2,o);if(d.w>.5){d=mul(v,float4(d.xyz,1));d.y*=-1;c=0;for(float i=0;i<16;i++){c.x+=tex2D(t2,o+i*(.5+.5*d.xy/d.w-o)/16+float2(2,0)/1280).x;c.y+=tex2D(t2,o+i*(.5+.5*d.xy/d.w-o)/16+float2(0,0)/1280).y;c.z+=tex2D(t2,o+i*(.5+.5*d.xy/d.w-o)/16+float2(-2,0)/1280).z;}c/=16;}c=pow(c,.45)*q[2].z+q[2].y;c*=.4+9.6*o.x*o.y*(1-o.x)*(1-o.y);c.xz*=.98;float w=tex2D(t0,q[3].w*.1);o+=w;c-=.005*w;c.x+=.01*tex2D(t0,o+=.1);c.y+=.01*tex2D(t0,o+=.1);c.z+=.01*tex2D(t0,o+=.1);return float4(c,0);} 2 | -------------------------------------------------------------------------------- /tests/real/endeavour.frag.expected: -------------------------------------------------------------------------------- 1 | const float pi=acos(-1.); 2 | const vec3 c=vec3(1,0,-1); 3 | float a=1.; 4 | void rand(vec2 x,out float num) 5 | { 6 | x+=4e2; 7 | num=fract(sin(dot(sign(x)*abs(x),vec2(12.9898,78.233)))*43758.5453); 8 | } 9 | void lfnoise(vec2 t,out float num) 10 | { 11 | vec2 i=floor(t); 12 | t=smoothstep(c.yy,c.xx,fract(t)); 13 | vec2 v1,v2; 14 | rand(i,v1.x); 15 | rand(i+c.xy,v1.y); 16 | rand(i+c.yx,v2.x); 17 | rand(i+c.xx,v2.y); 18 | v1=c.zz+2.*mix(v1,v2,t.y); 19 | num=mix(v1.x,v1.y,t.x); 20 | } 21 | void mfnoise(vec2 x,float fmin,float fmax,float alpha,out float num) 22 | { 23 | num=0.; 24 | float a=1.,nf=0.,buf; 25 | for(float f=fmin;f-.05) 60 | { 61 | float n2; 62 | mfnoise(x.xy,30.,5e2,.47,n2); 63 | vec2 sda=vec2(x.z+.05+.01*n2,1); 64 | add(sdf,sda,sdf); 65 | } 66 | float R=.07+.1*sdf.x,dis; 67 | lfnoise(.5*x.y*c.xx,dis); 68 | vec2 sdb,ya=abs(x.xz-.4*dis*c.xy)+.045*c.yx-.065*c.xy; 69 | zextrude(x.y,-length(ya)+R,sdb.x); 70 | stroke(sdb.x,.003,R); 71 | sdb.y=2.; 72 | vec2 ind; 73 | dhexagonpattern(vec2(56,12)*vec2(x.y,atan(ya.y,ya.x)),dis,ind); 74 | stroke(dis,.2,dis); 75 | stroke(sdb.x,.003*step(dis,0.),sdb.x); 76 | sdf.x=max(sdf.x,-R); 77 | add(sdf,sdb,sdf); 78 | sdf.x=min(sdf.x,abs(-length(max(abs(mod(x,.1)-.05)-vec3(.05*c.xx,.6),0.)))+.01); 79 | } 80 | void normal(vec3 x,out vec3 n) 81 | { 82 | vec2 s,na; 83 | scene(x,s); 84 | scene(x+5e-4*c.xyy,na); 85 | n.x=na.x; 86 | scene(x+5e-4*c.yxy,na); 87 | n.y=na.x; 88 | scene(x+5e-4*c.yyx,na); 89 | n.z=na.x; 90 | n=normalize(n-s.x); 91 | } 92 | void planet_texture(vec2 x,out vec3 col) 93 | { 94 | float d; 95 | mfnoise(x,1.,4e2,.65,d); 96 | col=mix(vec3(.19,.02,0),vec3(.91,.45,.02),.5+.5*d); 97 | stroke(d,.01,d); 98 | col=mix(mix(mix(.8*vec3(.99,.49,.02),c.yyy,d*clamp(.2-.5*x.y/12.,0.,1.)),col,smoothstep(-.05,.05,d)),vec3(.15,.05,0),clamp(.2-.5*x.y/12.,0.,1.)); 99 | } 100 | void mainImage(out vec4 fragColor,vec2 fragCoord) 101 | { 102 | a=iResolution.x/iResolution.y; 103 | vec2 uv=fragCoord/iResolution.yy-.5*vec2(a,1),s; 104 | vec3 col=c.yyy,o=.5*c.yyx+.3*iTime*c.yxy,t=vec3(uv,0)+.3*iTime*c.yxy+c.yxy,dir=normalize(t-o); 105 | float d=(.04-o.z)/dir.z; 106 | int i; 107 | for(i=0;i<450;++i) 108 | { 109 | t=o+d*dir; 110 | scene(t,s); 111 | if(s.x<1e-4) 112 | break; 113 | d+=s.x; 114 | } 115 | if(i<450) 116 | { 117 | vec3 n,l=normalize(t+c.yyx); 118 | normal(t,n); 119 | vec3 c1=vec3(.99,.64,.02); 120 | if(s.y==1.) 121 | { 122 | planet_texture(t.xy,c1); 123 | col=.3*c1+.3*c1*abs(dot(l,n))+(1.3*c1+.1*c.xyy)*pow(abs(dot(reflect(-l,n),dir)),3.); 124 | if(t.z<0.) 125 | { 126 | float dis; 127 | lfnoise(.5*t.y*c.xx,dis); 128 | dis=abs(t.x-.4*dis)-.15; 129 | col=mix(col,.3*col,smoothstep(-.01,.01,-dis)); 130 | } 131 | } 132 | else if(s.y==2.) 133 | planet_texture(t.xy,c1),col=.3*c1+.3*c1*abs(dot(l,n))+(1.3*c1+.1*c.xyy)*pow(abs(dot(reflect(-l,n),dir)),3.),col=mix(col,.4*length(col)*c.xyy,.7); 134 | } 135 | col=clamp(col,0.,1.); 136 | fragColor=vec4(col,1); 137 | } 138 | -------------------------------------------------------------------------------- /tests/real/heart.expected: -------------------------------------------------------------------------------- 1 | // Generated with (https://github.com/laurentlb/Shader_Minifier/) 2 | pub const VAR_MOUSE: &'static [u8] = b"f\0"; 3 | pub const VAR_RESOLUTION: &'static [u8] = b"y\0"; 4 | pub const VAR_TIME: &'static [u8] = b"v\0"; 5 | 6 | pub const HEART_FRAG: &'static [u8] = b"\ 7 | uniform float v;\ 8 | uniform vec2 y;\ 9 | uniform vec4 f;\ 10 | void main()\ 11 | {\ 12 | vec2 f=(2.*gl_FragCoord.xy-y)/y.y;\ 13 | float g=mod(v,2.)/2.,a=pow(g,.2)*.5+.5;\ 14 | a-=a*.2*sin(g*6.2831*5.)*exp(-g*6.);\ 15 | f*=vec2(.5,1.5)+a*vec2(.5,-.5);\ 16 | g=atan(f.x,f.y)/3.141593;\ 17 | a=length(f);\ 18 | g=abs(g);\ 19 | g=(13.*g-22.*g*g+10.*g*g*g)/(6.-5.*g);\ 20 | gl_FragColor=vec4(step(a,g)*pow(1.-a/g,.25),0,0,1);\ 21 | }\0"; 22 | -------------------------------------------------------------------------------- /tests/real/heart.frag: -------------------------------------------------------------------------------- 1 | uniform float time; 2 | uniform vec2 resolution; 3 | uniform vec4 mouse; 4 | 5 | void main(void) 6 | { 7 | vec2 p = (2.0*gl_FragCoord.xy-resolution)/resolution.y; 8 | 9 | // animate 10 | float tt = mod(time,2.0)/2.0; 11 | float ss = pow(tt,.2)*0.5 + 0.5; 12 | ss -= ss*0.2*sin(tt*6.2831*5.0)*exp(-tt*6.0); 13 | p *= vec2(0.5,1.5) + ss*vec2(0.5,-0.5); 14 | 15 | 16 | float a = atan(p.x,p.y)/3.141593; 17 | float r = length(p); 18 | 19 | // shape 20 | float h = abs(a); 21 | float d = (13.0*h - 22.0*h*h + 10.0*h*h*h)/(6.0-5.0*h); 22 | 23 | // color 24 | float f = step(r,d)*pow(1.0-r/d,0.25); 25 | 26 | gl_FragColor = vec4(f,0.0,0.0,1.0); 27 | } 28 | -------------------------------------------------------------------------------- /tests/real/heart.frag.expected: -------------------------------------------------------------------------------- 1 | // Generated with (https://github.com/laurentlb/Shader_Minifier/) 2 | #ifndef HEART_FRAG_EXPECTED_ 3 | # define HEART_FRAG_EXPECTED_ 4 | # define VAR_mouse "f" 5 | # define VAR_resolution "y" 6 | # define VAR_time "v" 7 | 8 | const char *heart_frag = 9 | "uniform float v;" 10 | "uniform vec2 y;" 11 | "uniform vec4 f;" 12 | "void main()" 13 | "{" 14 | "vec2 f=(2.*gl_FragCoord.xy-y)/y.y;" 15 | "float g=mod(v,2.)/2.,a=pow(g,.2)*.5+.5;" 16 | "a-=a*.2*sin(g*6.2831*5.)*exp(-g*6.);" 17 | "f*=vec2(.5,1.5)+a*vec2(.5,-.5);" 18 | "g=atan(f.x,f.y)/3.141593;" 19 | "a=length(f);" 20 | "g=abs(g);" 21 | "g=(13.*g-22.*g*g+10.*g*g*g)/(6.-5.*g);" 22 | "gl_FragColor=vec4(step(a,g)*pow(1.-a/g,.25),0,0,1);" 23 | "}"; 24 | 25 | #endif // HEART_FRAG_EXPECTED_ 26 | -------------------------------------------------------------------------------- /tests/real/heart2.expected: -------------------------------------------------------------------------------- 1 | {"mappings":{"mouse":"f","resolution":"y","time":"v"},"shaders":{"tests/real/heart2.frag":"uniform float v;uniform vec2 y;uniform vec4 f;void main(){vec2 f=(2.*gl_FragCoord.xy-y)/y.y;float g=mod(v,2.)/2.,a=pow(g,.2)*.5+.5;a-=a*.2*sin(g*6.2831*5.)*exp(-g*6.);f*=vec2(.5,1.5)+a*vec2(.5,-.5);g=atan(f.x,f.y)/3.141593;a=length(f);g=abs(g);g=(13.*g-22.*g*g+10.*g*g*g)/(6.-5.*g);gl_FragColor=vec4(step(a,g)*pow(1.-a/g,.25),0,0,1);}"}} 2 | -------------------------------------------------------------------------------- /tests/real/heart2.frag: -------------------------------------------------------------------------------- 1 | uniform float time; 2 | uniform vec2 resolution; 3 | uniform vec4 mouse; 4 | 5 | void main(void) 6 | { 7 | vec2 p = (2.0*gl_FragCoord.xy-resolution)/resolution.y; 8 | 9 | // animate 10 | float tt = mod(time,2.0)/2.0; 11 | float ss = pow(tt,.2)*0.5 + 0.5; 12 | ss -= ss*0.2*sin(tt*6.2831*5.0)*exp(-tt*6.0); 13 | p *= vec2(0.5,1.5) + ss*vec2(0.5,-0.5); 14 | 15 | 16 | float a = atan(p.x,p.y)/3.141593; 17 | float r = length(p); 18 | 19 | // shape 20 | float h = abs(a); 21 | float d = (13.0*h - 22.0*h*h + 10.0*h*h*h)/(6.0-5.0*h); 22 | 23 | // color 24 | float f = step(r,d)*pow(1.0-r/d,0.25); 25 | 26 | gl_FragColor = vec4(f,0.0,0.0,1.0); 27 | } 28 | -------------------------------------------------------------------------------- /tests/real/julia.frag: -------------------------------------------------------------------------------- 1 | uniform vec2 resolution; 2 | uniform float time; 3 | uniform sampler2D tex0; 4 | uniform sampler2D tex1; 5 | uniform sampler2D tex2; 6 | uniform sampler2D tex3; 7 | 8 | void main(void) 9 | { 10 | vec2 p = -1.0 + 2.0 * gl_FragCoord.xy / resolution.xy; 11 | vec2 cc = vec2( cos(.25*time), sin(.25*time*1.423) ); 12 | 13 | float dmin = 1000.0; 14 | vec2 z = p*vec2(1.33,1.0); 15 | for( int i=0; i<64; i++ ) 16 | { 17 | z = cc + vec2( z.x*z.x - z.y*z.y, 2.0*z.x*z.y ); 18 | float m2 = dot(z,z); 19 | if( m2>100.0 ) break; 20 | dmin=min(dmin,m2); 21 | } 22 | 23 | float color = sqrt(sqrt(dmin))*0.7; 24 | gl_FragColor = vec4(color,color,color,1.0); 25 | } 26 | -------------------------------------------------------------------------------- /tests/real/kaleidoscope.frag: -------------------------------------------------------------------------------- 1 | uniform vec2 resolution; 2 | uniform float time; 3 | uniform sampler2D tex0; 4 | uniform sampler2D tex1; 5 | uniform sampler2D tex2; 6 | uniform sampler2D tex3; 7 | 8 | void main(void) 9 | { 10 | vec2 p = -1.0 + 2.0 * gl_FragCoord.xy / resolution.xy; 11 | vec2 uv; 12 | 13 | float a = atan(p.y,p.x); 14 | float r = sqrt(dot(p,p)); 15 | 16 | uv.x = 7.0*a/3.1416; 17 | uv.y = -time+ sin(7.0*r+time) + .7*cos(time+7.0*a); 18 | 19 | float w = .5+.5*(sin(time+7.0*r)+ .7*cos(time+7.0*a)); 20 | 21 | vec3 col = texture2D(tex0,uv*.5).xyz; 22 | 23 | gl_FragColor = vec4(col*w,1.0); 24 | } 25 | -------------------------------------------------------------------------------- /tests/real/leizex.expected: -------------------------------------------------------------------------------- 1 | ; Generated with (https://github.com/laurentlb/Shader_Minifier/) 2 | _var_RESOLUTION: db 'n', 0 3 | _var_TEX0: db 'f', 0 4 | _var_TEX1: db 'm', 0 5 | _var_TEX2: db 'o', 0 6 | _var_TEX3: db 'y', 0 7 | _var_TIME: db 'v', 0 8 | 9 | _leizex_frag: 10 | db '#extension GL_EXT_gpu_shader4:enable', 10, '' 11 | db 'uniform vec2 n;' 12 | db 'uniform float v;' 13 | db 'uniform sampler2D f,m,o,y;' 14 | db 'float t(int v)' 15 | db '{' 16 | db 'v^=v<<13;' 17 | db 'v=v*(v*v*15731+789221)+1376312589&2147483647;' 18 | db 'return float(v);' 19 | db '}' 20 | db 'float t(vec3 v,int f)' 21 | db '{' 22 | db 'ivec3 n=ivec3(floor(v));' 23 | db 'vec3 c=fract(v);' 24 | db 'c=c*c*(3.-2.*c);' 25 | db 'f+=n.x+n.y*57+113*n.z;' 26 | db 'float y=mix(mix(mix(t(f),t(f+1),c.x),mix(t(f+57),t(f+58),c.x),c.y),mix(mix(t(f+113),t(f+114),c.x),mix(t(f+170),t(f+171),c.x),c.y),c.z);' 27 | db 'return 1.-y*(1./1073741824.);' 28 | db '}' 29 | db 'vec2 t(vec3 v)' 30 | db '{' 31 | db 'ivec3 c=ivec3(floor(v));' 32 | db 'vec3 f=fract(v);' 33 | db 'vec2 n=vec2(1);' 34 | db 'for(int v=-1;v<=1;v++)' 35 | db 'for(int x=-1;x<=1;x++)' 36 | db 'for(int y=-1;y<=1;y++)' 37 | db '{' 38 | db 'int i=c.x+y+57*(c.y+x)+113*(c.z+v);' 39 | db 'vec3 m=vec3(float(y),float(x),float(v))-f+vec3(t(i),t(i+1217),t(i+2513))/2147483647.;' 40 | db 'float s=dot(m,m);' 41 | db 'if(s1024.0 ) break; 29 | co += 1.0; 30 | } 31 | co = co + 1.0 - log2(.5*log2(m2)); 32 | 33 | co = sqrt(co/256.0); 34 | gl_FragColor = vec4( .5+.5*cos(6.2831*co+0.0), 35 | .5+.5*cos(6.2831*co+0.4), 36 | .5+.5*cos(6.2831*co+0.7), 37 | 1.0 ); 38 | } 39 | -------------------------------------------------------------------------------- /tests/real/mandelbulb.expected: -------------------------------------------------------------------------------- 1 | // Generated with (https://github.com/laurentlb/Shader_Minifier/) 2 | #ifndef MANDELBULB_EXPECTED_ 3 | # define MANDELBULB_EXPECTED_ 4 | 5 | const char *mandelbulb_frag = 6 | "uniform vec2 resolution;" 7 | "uniform float time;" 8 | "bool f(vec3 v,vec3 f,out vec2 i)" 9 | "{" 10 | "vec4 t=vec4(0,0,0,1.25);" 11 | "vec3 y=v-t.xyz;" 12 | "float c=dot(y,f),e=c*c-dot(y,y)+t.w*t.w;" 13 | "if(e<0.)" 14 | "return false;" 15 | "e=sqrt(e);" 16 | "i.x=-c-e;" 17 | "i.y=-c+e;" 18 | "return true;" 19 | "}" 20 | "bool f(vec3 v,out float f,out vec4 y)" 21 | "{" 22 | "vec4 e=vec4(100);" 23 | "vec3 i=v;" 24 | "float t=dot(i,i);" 25 | "if(t>1e2)" 26 | "return f=.5*log(t)/pow(8.,0.),y=vec4(1),false;" 27 | "for(int x=1;x<7;x++)" 28 | "{" 29 | "\n#if 0\n" 30 | "float z=sqrt(dot(i,i)),o=acos(i.y/z),c=atan(i.x,i.z);" 31 | "z=pow(z,8.);" 32 | "o*=8.;" 33 | "c*=8.;" 34 | "i=v+z*vec3(sin(o)*sin(c),cos(o),sin(o)*cos(c));" 35 | "\n#else\n" 36 | "float n=i.x,s=n*n,d=s*s,a=i.y,l=a*a,m=i.z,w=m*m,g=w*w,p=s+w,r=inversesqrt(p*p*p*p*p*p*p),C=d+l*l+g-6.*l*w-6.*s*l+2.*w*s,F=s-l+w;" 37 | "i.x=v.x+64.*n*a*m*(s-w)*F*(d-6.*s*w+g)*C*r;" 38 | "i.y=v.y+-16.*l*p*F*F+C*C;" 39 | "i.z=v.z+-8.*a*F*(d*d-28.*d*s*w+70.*d*g-28.*s*w*g+g*g)*C*r;" 40 | "\n#endif\n" 41 | "t=dot(i,i);" 42 | "e=min(e,vec4(i.xyz*i.xyz,t));" 43 | "if(t>1e2)" 44 | "return y=e,f=.5*log(t)/pow(8.,float(x)),false;" 45 | "}" 46 | "y=e;" 47 | "f=0.;" 48 | "return true;" 49 | "}" 50 | "bool f(vec3 v,vec3 s,out float y,out vec3 i,out vec4 t)" 51 | "{" 52 | "vec2 e;" 53 | "if(!f(v,s,e))" 54 | "return false;" 55 | "if(e.y<.001)" 56 | "return false;" 57 | "if(e.x<.001)" 58 | "e.x=.001;" 59 | "if(e.y>1e20)" 60 | "e.y=1e20;" 61 | "float c;" 62 | "vec3 x;" 63 | "vec4 o;" 64 | "float w=1./sqrt(2.);" 65 | "for(float p=e.x;p.001)" 105 | "if(f(i,v,r,C,x))" 106 | "e=.1;" 107 | "s=mix(mix(mix(vec3(1),vec3(.8,.6,.2),sqrt(o.x)*1.25),vec3(.8,.3,.3),sqrt(o.y)*1.25),vec3(.7,.4,.3),sqrt(o.z)*1.25)*((.5+.5*t.y)*vec3(.14,.15,.16)*.8+e*vec3(1,.85,.4)+.5*w*vec3(.08,.1,.14))*vec3(pow(d,.8),d,pow(d,1.1));" 108 | "s=1.5*(s*.15+.85*sqrt(s));" 109 | "}" 110 | "else" 111 | " s=1.3*vec3(1,.98,.9)*(.7+.3*p.y);" 112 | "i=i*.5+.5;" 113 | "s=clamp(s*(.7+4.8*i.x*i.y*(1.-i.x)*(1.-i.y)),0.,1.);" 114 | "gl_FragColor=vec4(s,1);" 115 | "}"; 116 | 117 | #endif // MANDELBULB_EXPECTED_ 118 | -------------------------------------------------------------------------------- /tests/real/metatunnel.frag: -------------------------------------------------------------------------------- 1 | uniform vec2 resolution; 2 | uniform float time; 3 | 4 | float h(vec3 q) 5 | { 6 | float f=1.*distance(q,vec3(cos(time)+sin(time*.2),.3,2.+cos(time*.5)*.5)); 7 | f*=distance(q,vec3(-cos(time*.7),.3,2.+sin(time*.5))); 8 | f*=distance(q,vec3(-sin(time*.2)*.5,sin(time),2.)); 9 | f*=cos(q.y)*cos(q.x)-.1-cos(q.z*7.+time*7.)*cos(q.x*3.)*cos(q.y*4.)*.1; 10 | return f; 11 | } 12 | 13 | void main() 14 | { 15 | vec2 p = -1.0 + 2.0 * gl_FragCoord.xy / resolution.xy; 16 | vec3 o=vec3(p.x,p.y*1.25-0.3,0.); 17 | vec3 d=vec3(p.x+cos(time)*0.3,p.y,1.)/64.; 18 | vec4 c=vec4(0.); 19 | float t=0.; 20 | for(int i=0;i<75;i++) 21 | { 22 | if(h(o+d*t)<.4) 23 | { 24 | t-=5.; 25 | for(int j=0;j<5;j++) 26 | { 27 | if(h(o+d*t)<.4) 28 | break; 29 | t+=1.; 30 | } 31 | vec3 e=vec3(.01,.0,.0); 32 | vec3 n=vec3(.0); 33 | n.x=h(o+d*t)-h(vec3(o+d*t+e.xyy)); 34 | n.y=h(o+d*t)-h(vec3(o+d*t+e.yxy)); 35 | n.z=h(o+d*t)-h(vec3(o+d*t+e.yyx)); 36 | n=normalize(n); 37 | c+=max(dot(vec3(.0,.0,-.5),n),.0)+max(dot(vec3(.0,-.5,.5),n),.0)*.5; 38 | break; 39 | } 40 | t+=5.; 41 | } 42 | gl_FragColor=c+vec4(.1,.2,.5,1.)*(t*.025); 43 | } 44 | -------------------------------------------------------------------------------- /tests/real/monjori.frag: -------------------------------------------------------------------------------- 1 | uniform vec2 resolution; 2 | uniform float time; 3 | uniform sampler2D tex0; 4 | uniform sampler2D tex1; 5 | uniform sampler2D tex2; 6 | uniform sampler2D tex3; 7 | 8 | void main(void) 9 | { 10 | vec2 p = -1.0 + 2.0 * gl_FragCoord.xy / resolution.xy; 11 | float a = time*40.0; 12 | float d,e,f,g=1.0/40.0,h,i,r,q; 13 | e=400.0*(p.x*0.5+0.5); 14 | f=400.0*(p.y*0.5+0.5); 15 | i=200.0+sin(e*g+a/150.0)*20.0; 16 | d=200.0+cos(f*g/2.0)*18.0+cos(e*g)*7.0; 17 | r=sqrt(pow(i-e,2.0)+pow(d-f,2.0)); 18 | q=f/r; 19 | e=(r*cos(q))-a/2.0;f=(r*sin(q))-a/2.0; 20 | d=sin(e*g)*176.0+sin(e*g)*164.0+r; 21 | h=((f+d)+a/2.0)*g; 22 | i=cos(h+r*p.x/1.3)*(e+e+a)+cos(q*g*6.0)*(r+h/3.0); 23 | h=sin(f*g)*144.0-sin(e*g)*212.0*p.x; 24 | h=(h+(f-e)*q+sin(r-(a+h)/7.0)*10.0+i/4.0)*g; 25 | i+=cos(h*2.3*sin(a/350.0-q))*184.0*sin(q-(r*4.3+a/12.0)*g)+tan(r*g+h)*184.0*cos(r*g+h); 26 | i=mod(i/5.6,256.0)/64.0; 27 | if(i<0.0) i+=4.0; 28 | if(i>=2.0) i=4.0-i; 29 | d=r/350.0; 30 | d+=sin(d*d*8.0)*0.52; 31 | f=(sin(a*g)+1.0)/2.0; 32 | gl_FragColor = vec4(f*i/1.6,i/2.0+d/13.0,i,1.0)*d*p.x+vec4(i/1.3+d/8.0,i/2.0+d/18.0,i,1.0)*d*(1.0-p.x); 33 | } 34 | -------------------------------------------------------------------------------- /tests/real/monjori.frag.expected: -------------------------------------------------------------------------------- 1 | uniform vec2 resolution; 2 | uniform float time; 3 | uniform sampler2D tex0,tex1,tex2,tex3; 4 | void main() 5 | { 6 | vec2 p=-1.+2.*gl_FragCoord.xy/resolution.xy; 7 | float a=time*40.,d,e,f,h,i,r,q; 8 | e=4e2*(p.x*.5+.5); 9 | f=4e2*(p.y*.5+.5); 10 | i=2e2+sin(e*.025+a/150.)*20.; 11 | d=2e2+cos(f*.025/2.)*18.+cos(e*.025)*7.; 12 | r=sqrt(pow(i-e,2.)+pow(d-f,2.)); 13 | q=f/r; 14 | e=r*cos(q)-a/2.; 15 | f=r*sin(q)-a/2.; 16 | d=sin(e*.025)*176.+sin(e*.025)*164.+r; 17 | h=(f+d+a/2.)*.025; 18 | i=cos(h+r*p.x/1.3)*(e+e+a)+cos(q*.025*6.)*(r+h/3.); 19 | h=sin(f*.025)*144.-sin(e*.025)*212.*p.x; 20 | h=(h+(f-e)*q+sin(r-(a+h)/7.)*10.+i/4.)*.025; 21 | i=mod((i+cos(h*2.3*sin(a/350.-q))*184.*sin(q-(r*4.3+a/12.)*.025)+tan(r*.025+h)*184.*cos(r*.025+h))/5.6,256.)/64.; 22 | if(i<0.) 23 | i+=4.; 24 | if(i>=2.) 25 | i=4.-i; 26 | d=r/350.; 27 | d+=sin(d*d*8.)*.52; 28 | f=(sin(a*.025)+1.)/2.; 29 | gl_FragColor=vec4(f*i/1.6,i/2.+d/13.,i,1)*d*p.x+vec4(i/1.3+d/8.,i/2.+d/18.,i,1)*d*(1.-p.x); 30 | } 31 | -------------------------------------------------------------------------------- /tests/real/motion_blur.frag: -------------------------------------------------------------------------------- 1 | uniform vec2 resolution; 2 | uniform float time; 3 | uniform sampler2D tex0; 4 | uniform sampler2D tex1; 5 | uniform sampler2D tex2; 6 | uniform sampler2D tex3; 7 | 8 | vec3 deform( in vec2 p, float scale ) 9 | { 10 | vec2 uv; 11 | 12 | float mtime = scale+time; 13 | float a = atan(p.y,p.x); 14 | float r = sqrt(dot(p,p)); 15 | float s = r * (1.0+0.5*cos(mtime*1.7)); 16 | 17 | uv.x = .1*mtime +.05*p.y+.05*cos(-mtime+a*3.0)/s; 18 | uv.y = .1*mtime +.05*p.x+.05*sin(-mtime+a*3.0)/s; 19 | 20 | float w = 0.8-0.2*cos(mtime+3.0*a); 21 | 22 | vec3 res = texture2D(tex0,uv).xyz*w; 23 | return res*res; 24 | 25 | } 26 | 27 | void main(void) 28 | { 29 | vec2 p = -1.0 + 2.0 * gl_FragCoord.xy / resolution.xy; 30 | vec3 total = vec3(0.0); 31 | float w = 0.0; 32 | for( int i=0; i<20; i++ ) 33 | { 34 | vec3 res = deform(p,w); 35 | total += res; 36 | w += 0.02; 37 | } 38 | total /= 20.0; 39 | 40 | gl_FragColor = vec4( 3.0*total,1.0); 41 | } 42 | -------------------------------------------------------------------------------- /tests/real/mouton/fxaa.frag: -------------------------------------------------------------------------------- 1 | #version 150 2 | out vec4 fragColor; 3 | const vec2 iResolution = vec2(1920.,1080.); 4 | 5 | 6 | uniform sampler2D tex; 7 | 8 | void main(void) 9 | { 10 | vec2 rcpFrame = 1./iResolution; 11 | vec2 texcoord = gl_FragCoord.xy * rcpFrame; 12 | vec4 uv = vec4( texcoord, texcoord - (rcpFrame * 0.5)); 13 | 14 | vec3 rgbNW = textureLod(tex, uv.zw, 0.0).xyz; 15 | vec3 rgbNE = textureLod(tex, uv.zw + vec2(1,0)*rcpFrame.xy, 0.0).xyz; 16 | vec3 rgbSW = textureLod(tex, uv.zw + vec2(0,1)*rcpFrame.xy, 0.0).xyz; 17 | vec3 rgbSE = textureLod(tex, uv.zw + vec2(1,1)*rcpFrame.xy, 0.0).xyz; 18 | vec3 rgbM = textureLod(tex, uv.xy, 0.0).xyz; 19 | 20 | vec3 luma = vec3(0.299, 0.587, 0.114); 21 | float lumaNW = dot(rgbNW, luma); 22 | float lumaNE = dot(rgbNE, luma); 23 | float lumaSW = dot(rgbSW, luma); 24 | float lumaSE = dot(rgbSE, luma); 25 | float lumaM = dot(rgbM, luma); 26 | 27 | float lumaMin = min(lumaM, min(min(lumaNW, lumaNE), min(lumaSW, lumaSE))); 28 | float lumaMax = max(lumaM, max(max(lumaNW, lumaNE), max(lumaSW, lumaSE))); 29 | 30 | vec2 dir = vec2( -((lumaNW + lumaNE) - (lumaSW + lumaSE)), ((lumaNW + lumaSW) - (lumaNE + lumaSE))); 31 | float rcpDirMin = 1.0/(min(abs(dir.x), abs(dir.y)) + (1./128.)); 32 | 33 | dir = min(vec2( 8., 8.), 34 | max(vec2(-8., -8.), 35 | dir * rcpDirMin)) * rcpFrame.xy; 36 | 37 | vec3 rgbA = (1.0/2.0) * ( 38 | textureLod(tex, uv.xy + dir * (1.0/3.0 - 0.5), 0.0).xyz + 39 | textureLod(tex, uv.xy + dir * (2.0/3.0 - 0.5), 0.0).xyz); 40 | vec3 rgbB = rgbA * (1.0/2.0) + (1.0/4.0) * ( 41 | textureLod(tex, uv.xy + dir * (0.0/3.0 - 0.5), 0.0).xyz + 42 | textureLod(tex, uv.xy + dir * (3.0/3.0 - 0.5), 0.0).xyz); 43 | 44 | float lumaB = dot(rgbB, luma); 45 | 46 | if((lumaB < lumaMin) || (lumaB > lumaMax)) 47 | fragColor = vec4(rgbA,1.); 48 | else 49 | fragColor = vec4(rgbB,1.); 50 | } -------------------------------------------------------------------------------- /tests/real/postprocessing.frag: -------------------------------------------------------------------------------- 1 | uniform vec2 resolution; 2 | uniform float time; 3 | uniform sampler2D tex0; 4 | uniform sampler2D tex1; 5 | uniform sampler2D tex2; 6 | uniform sampler2D tex3; 7 | 8 | void main(void) 9 | { 10 | vec2 q = gl_FragCoord.xy / resolution.xy; 11 | vec2 uv = 0.5 + (q-0.5)*(0.9 + 0.1*sin(0.2*time)); 12 | 13 | vec3 oricol = texture2D(tex0,vec2(q.x,1.0-q.y)).xyz; 14 | vec3 col; 15 | 16 | col.r = texture2D(tex0,vec2(uv.x+0.003,-uv.y)).x; 17 | col.g = texture2D(tex0,vec2(uv.x+0.000,-uv.y)).y; 18 | col.b = texture2D(tex0,vec2(uv.x-0.003,-uv.y)).z; 19 | 20 | col = clamp(col*0.5+0.5*col*col*1.2,0.0,1.0); 21 | 22 | col *= 0.5 + 0.5*16.0*uv.x*uv.y*(1.0-uv.x)*(1.0-uv.y); 23 | 24 | col *= vec3(0.8,1.0,0.7); 25 | 26 | col *= 0.9+0.1*sin(10.0*time+uv.y*1000.0); 27 | 28 | col *= 0.97+0.03*sin(110.0*time); 29 | 30 | float comp = smoothstep( 0.2, 0.7, sin(time) ); 31 | col = mix( col, oricol, clamp(-2.0+2.0*q.x+3.0*comp,0.0,1.0) ); 32 | 33 | gl_FragColor = vec4(col,1.0); 34 | } 35 | -------------------------------------------------------------------------------- /tests/real/quaternion.frag: -------------------------------------------------------------------------------- 1 | uniform vec2 resolution; 2 | uniform float time; 3 | uniform sampler2D tex0; 4 | uniform sampler2D tex1; 5 | uniform sampler2D tex2; 6 | uniform sampler2D tex3; 7 | 8 | float jinteresct(in vec3 rO, in vec3 rD, in vec4 c, out float ao) 9 | { 10 | float mz2,md2,dist,t; 11 | float res=1000.0; 12 | vec4 z,nz; 13 | 14 | ao = 0.0; 15 | for(t=0.0;t<6.0;t+=dist) 16 | { 17 | ao += 1.0; 18 | vec3 p=rO+t*rD; 19 | 20 | // calc distance 21 | z=vec4(p,(c.y+c.x)*.3); 22 | md2=1.0; 23 | mz2=dot(z,z); 24 | 25 | for(int i=0;i<9;i++) 26 | { 27 | // |dz|^2 -> 4*|dz|^2 28 | md2*=4.0*mz2; 29 | // z -> z2 + c 30 | nz.x=z.x*z.x-dot(z.yzw,z.yzw); 31 | nz.yzw=2.0*z.x*z.yzw; 32 | z=nz+c; 33 | 34 | mz2=dot(z,z); 35 | if(mz2>4.0) 36 | break; 37 | } 38 | 39 | dist=0.25*sqrt(mz2/md2)*log(mz2); 40 | 41 | if(dist<0.0005) 42 | { 43 | res=t; 44 | break; 45 | } 46 | 47 | } 48 | 49 | return res; 50 | } 51 | 52 | 53 | vec3 calcNormal(in vec3 p, in vec4 c) 54 | { 55 | vec4 nz,ndz,dz[4]; 56 | 57 | vec4 z=vec4(p,(c.y+c.x)*.3); 58 | 59 | dz[0]=vec4(1.0,0.0,0.0,0.0); 60 | dz[1]=vec4(0.0,1.0,0.0,0.0); 61 | dz[2]=vec4(0.0,0.0,1.0,0.0); 62 | //dz[3]=vec4(0.0,0.0,0.0,1.0); 63 | 64 | for(int i=0;i<9;i++) 65 | { 66 | vec4 mz = vec4(z.x,-z.y,-z.z,-z.w); 67 | // derivative 68 | dz[0]=vec4(dot(mz,dz[0]),z.x*dz[0].yzw+dz[0].x*z.yzw); 69 | dz[1]=vec4(dot(mz,dz[1]),z.x*dz[1].yzw+dz[1].x*z.yzw); 70 | dz[2]=vec4(dot(mz,dz[2]),z.x*dz[2].yzw+dz[2].x*z.yzw); 71 | //dz[3]=vec4(dot(mz,dz[3]),z.x*dz[3].yzw+dz[3].x*z.yzw); 72 | 73 | // z = z2 + c 74 | nz.x=dot(z, mz); 75 | nz.yzw=2.0*z.x*z.yzw; 76 | z=nz+c; 77 | 78 | if(dot(z,z)>4.0) 79 | break; 80 | } 81 | 82 | return normalize(vec3(dot(z,dz[0]),dot(z,dz[1]),dot(z,dz[2]))); 83 | } 84 | 85 | 86 | void main(void) 87 | { 88 | vec2 p = -1.0 + 2.0 * gl_FragCoord.xy / resolution.xy; 89 | vec3 color = vec3(0.0); 90 | vec4 cccc = vec4( .7*cos(.5*time), .7*sin(.3*time), .7*cos(1.0*time), 0.0 ); 91 | vec3 edir = normalize(vec3(p,1.0)); 92 | vec3 wori = vec3(0.0,0.0,-2.0); 93 | 94 | float ao; 95 | float t = jinteresct(wori,edir,cccc,ao); 96 | if(t<100.0) 97 | { 98 | vec3 inter = wori + t*edir; 99 | vec3 nor = calcNormal(inter,cccc); 100 | 101 | float dif = .5 + .5*dot( nor, vec3(0.57703) ); 102 | ao = max( 1.0-ao*0.005, 0.0 ); 103 | 104 | color = vec3(1.0,.9,.5)*dif*ao + .5*vec3(.6,.7,.8)*ao; 105 | } 106 | else 107 | { 108 | color = vec3(0.5,0.51,0.52)+vec3(0.5,0.47,0.45)*p.y; 109 | } 110 | 111 | gl_FragColor = vec4(color,1.0); 112 | } 113 | -------------------------------------------------------------------------------- /tests/real/radial_blur.frag: -------------------------------------------------------------------------------- 1 | uniform vec2 resolution; 2 | uniform float time; 3 | uniform sampler2D tex0; 4 | uniform sampler2D tex1; 5 | uniform sampler2D tex2; 6 | uniform sampler2D tex3; 7 | 8 | vec3 deform( in vec2 p ) 9 | { 10 | vec2 uv; 11 | 12 | vec2 q = vec2( sin(1.1*time+p.x),sin(1.2*time+p.y) ); 13 | 14 | float a = atan(q.y,q.x); 15 | float r = sqrt(dot(q,q)); 16 | 17 | uv.x = sin(0.0+1.0*time)+p.x*sqrt(r*r+1.0); 18 | uv.y = sin(0.6+1.1*time)+p.y*sqrt(r*r+1.0); 19 | 20 | return texture2D(tex0,uv*.5).xyz; 21 | } 22 | 23 | void main(void) 24 | { 25 | vec2 p = -1.0 + 2.0 * gl_FragCoord.xy / resolution.xy; 26 | vec2 s = p; 27 | 28 | vec3 total = vec3(0.0); 29 | vec2 d = (vec2(0.0,0.0)-p)/40.0; 30 | float w = 1.0; 31 | for( int i=0; i<40; i++ ) 32 | { 33 | vec3 res = deform(s); 34 | res = smoothstep(0.1,1.0,res*res); 35 | total += w*res; 36 | w *= .99; 37 | s += d; 38 | } 39 | total /= 40.0; 40 | float r = 1.5/(1.0+dot(p,p)); 41 | gl_FragColor = vec4( total*r,1.0); 42 | } 43 | 44 | -------------------------------------------------------------------------------- /tests/real/star.frag: -------------------------------------------------------------------------------- 1 | uniform float time; 2 | uniform vec2 resolution; 3 | uniform vec4 mouse; 4 | uniform sampler2D tex0; 5 | uniform sampler2D tex1; 6 | uniform sampler2D tex2; 7 | uniform sampler2D tex3; 8 | 9 | void main(void) 10 | { 11 | vec2 uv; 12 | 13 | vec2 p = -1.0 + 2.0 * gl_FragCoord.xy / resolution.xy; 14 | float a = atan(p.y,p.x); 15 | float r = sqrt(dot(p,p)); 16 | float s = r * (1.0+0.8*cos(time*1.0)); 17 | 18 | uv.x = .02*p.y+.03*cos(-time+a*3.0)/s; 19 | uv.y = .1*time +.02*p.x+.03*sin(-time+a*3.0)/s; 20 | 21 | float w = .9 + pow(max(1.5-r,0.0),4.0); 22 | 23 | w*=0.6+0.4*cos(time+3.0*a); 24 | 25 | vec3 col = texture2D(tex0,uv).xyz; 26 | 27 | gl_FragColor = vec4(col*w,1.0); 28 | } 29 | -------------------------------------------------------------------------------- /tests/real/sult.expected: -------------------------------------------------------------------------------- 1 | // Generated with (https://github.com/laurentlb/Shader_Minifier/) 2 | #ifndef SULT_EXPECTED_ 3 | # define SULT_EXPECTED_ 4 | # define VAR_resolution "r" 5 | # define VAR_time "y" 6 | 7 | const char *sult_frag = 8 | "vec3 v=vec3(1),n=vec3(0,0,1),x=vec3(0,0,1.5);" 9 | "uniform vec2 r;" 10 | "uniform float y;" 11 | "vec3 rotatey(vec3 v,float y)" 12 | "{" 13 | "return vec3(v.x*cos(y)+v.z*sin(y),v.y,v.z*cos(y)-v.x*sin(y));" 14 | "}" 15 | "float m=0.;" 16 | "float s(vec3 v)" 17 | "{" 18 | "float x=y,c,k;" 19 | "v+=(sin(v.zxy*1.7+x)+sin(v.yzx+x*3.))*.2;" 20 | "k=length(v.xyz*vec3(1,1,.1)-vec3(0,-.1,x*.15-.3))-.34;" 21 | "v.xy=vec2(atan(v.x,v.y)*1.113,1.6-length(v.xy)-sin(x*2.)*.3);" 22 | "c=max(abs(v.y-.3)-.05,abs(length(fract(v.xz)-.5)-.4)-.03);" 23 | "m=step(k,c);" 24 | "return min(min(c,k),v.y-.2);" 25 | "}" 26 | "vec3 diffdark=vec3(.19,.2,.24),k=vec3(1),z=vec3(.45,.01,0),c=vec3(.17,0,0);" 27 | "void main()" 28 | "{" 29 | "vec2 d=-1.+2.*gl_FragCoord.xy/r.xy;" 30 | "vec3 a=normalize(rotatey(rotatey(vec3(d.y*.9,d.x*.9*1.33,1),0.).yxz,(90.+0.*y)*.035)),f=n+x*y;" 31 | "float u=1.,l=0.,g,w,C=0.,F,p,H,G;" 32 | "vec3 E=vec3(.01,0,0),D=E.yyy,B;" 33 | "for(;u>.1;)" 34 | "{" 35 | "for(g=C,w=1.;g<10.&&w>.005;g+=w)" 36 | "w=s(f+a*g);" 37 | "if(g<10.)" 38 | "f+=a*g,F=s(f),H=m,B=normalize(-vec3(F-s(f+E.xyy),F-s(f+E.yxy),F-s(f+E.yyx))),p=clamp(s(f+B*.05)*4.+s(f+B*.1)*2.+.5,.1,1.),l=H*.3,B=normalize(B+step(4.,5.)*m*sin(f.yzx*40.)*.05),a=reflect(a,B),G=clamp(dot(normalize(v),B),0.,1.),B=mix(mix(diffdark,k,G),z*(G+.2),H)+vec3(.7*pow(clamp(dot(normalize(v),a),0.,1.),12.)),D+=u*mix(B*p,c,g/10.),u*=l*(1.-g/10.),C=.1;" 39 | "else" 40 | " D+=u*c,u=0.;" 41 | "}" 42 | "gl_FragColor.xyz=D;" 43 | "gl_FragColor.w=1.;" 44 | "}"; 45 | 46 | #endif // SULT_EXPECTED_ 47 | -------------------------------------------------------------------------------- /tests/real/sult.frag: -------------------------------------------------------------------------------- 1 | // Scene from Sult by Loonies 2 | // Exclusive source release for ShaderToy 3 | // Blame the scene chosen on iq ;) 4 | // Feel free to be inspired, but please mention it (.readme) then :) 5 | // -Psycho/Loonies 6 | 7 | // Actual, ugly, size optimized 4k version with minimal changes for ShaderToy 8 | // but before auto-obfuscation (whitespaces, comments, variable names) 9 | 10 | // Inputs changed into more readable constants: 11 | float shaderparm=5.0, fov=.9, pitch=0.0, heading=90.0, dheading=0.0; 12 | vec3 lightdir=vec3(1,1,1), position=vec3(0,0,1), speed=vec3(0,0,1.5); 13 | 14 | // constants for the other worm tunnel part: 15 | //float shaderparm=8, fov=.8, pitch=0, heading=-90, dheading=0; 16 | //vec3 lightdir=vec3(1,1,1), position=vec3(0,0,0), speed=vec3(0,0,0); 17 | 18 | // shadertoy input 19 | uniform vec2 resolution; 20 | uniform float time; 21 | 22 | 23 | vec3 rotatey(vec3 r, float v) 24 | { return vec3(r.x*cos(v)+r.z*sin(v),r.y,r.z*cos(v)-r.x*sin(v)); 25 | } 26 | vec3 rotatex(vec3 r, float v) 27 | { return vec3(r.y*cos(v)+r.z*sin(v),r.x,r.z*cos(v)-r.y*sin(v)); 28 | } 29 | float mat=0.0, tmax=10.0; 30 | float eval(vec3 p) 31 | { 32 | ////// this is the (only) part that changes for the scenes in Sult 33 | float t = time,r,c=0.0,g,r2,r3; 34 | vec3 pp; 35 | p += ( sin(p.zxy*1.7+t)+sin(p.yzx+t*3.) )*.2; 36 | if (shaderparm<6.0) 37 | c = length(p.xyz*vec3(1,1,.1)-vec3(0,-.1,t*.15-.3))-.34; 38 | else 39 | c = length(p.xy+vec2(.0,.7))-.3+ (sin(p.z*17.0+t*.6)+sin(p.z*2.0)*6.0)*.01; 40 | 41 | p.xy = vec2( atan(p.x,p.y)*1.113, 1.6-length(p.xy)-sin(t*2.0)*.3); 42 | pp = fract(p.xzz+.5).xyz -.5; pp.y=(p.y-.35)*1.3; 43 | r = max( abs(p.y-.3)-.05, abs(length(fract(p.xz)-.5)-.4)-.03); 44 | mat = step(c,r); 45 | return min(min(r,c),p.y-.2); 46 | } 47 | vec3 diffdark= vec3(.19,.2,.24), difflight=vec3(1), 48 | diffrefl= vec3(.45,.01,0), background=vec3(.17,0,0); 49 | ////////// 50 | 51 | 52 | void main(void) 53 | { 54 | vec2 p = -1.0 + 2.0 * gl_FragCoord.xy / resolution.xy; 55 | vec3 vdir= normalize( 56 | rotatey(rotatey(vec3(p.y*fov,p.x*fov*1.33,1), 57 | -pitch*.035).yxz,(heading+dheading*time)*.035)), 58 | vpos= position + speed*time; 59 | 60 | float cf=1.0,rf=0.0,t,stp,tmin=0.0,c,r,m,d; 61 | vec3 e=vec3(.01,0,0),cx=e.yyy,n; 62 | while (cf>.1) 63 | { 64 | for (t=tmin,stp=1.0;t.005;t+=stp) 65 | stp = eval(vpos+vdir*t); 66 | if (tob(f))" 42 | "v=mix(v,vec4(cos(time*.3)*.5+.5,cos(time*.2)*.5+.5,sin(time*.3)*.5+.5,1),.3);" 43 | "v=(v+vec4(g)+(1.-min(f.y+1.9,1.))*vec4(1,.8,.7,1))*min(time*.5,1.);" 44 | "gl_FragColor=vec4(v.xyz,1);" 45 | "}"; 46 | 47 | #endif // TO_THE_ROAD_OF_RIBBON_EXPECTED_ 48 | -------------------------------------------------------------------------------- /tests/real/to_the_road_of_ribbon.frag: -------------------------------------------------------------------------------- 1 | uniform vec2 resolution; 2 | uniform float time; 3 | 4 | //Object A (tunnel) 5 | float oa(vec3 q) 6 | { 7 | return cos(q.x)+cos(q.y*1.5)+cos(q.z)+cos(q.y*20.)*.05; 8 | } 9 | 10 | //Object B (ribbon) 11 | float ob(vec3 q) 12 | { 13 | return length(max(abs(q-vec3(cos(q.z*1.5)*.3,-.5+cos(q.z)*.2,.0))-vec3(.125,.02,time+3.),vec3(.0))); 14 | } 15 | 16 | //Scene 17 | float o(vec3 q) 18 | { 19 | return min(oa(q),ob(q)); 20 | } 21 | 22 | //Get Normal 23 | vec3 gn(vec3 q) 24 | { 25 | vec3 f=vec3(.01,0,0); 26 | return normalize(vec3(o(q+f.xyy),o(q+f.yxy),o(q+f.yyx))); 27 | } 28 | 29 | //MainLoop 30 | void main(void) 31 | { 32 | vec2 p = -1.0 + 2.0 * gl_FragCoord.xy / resolution.xy; 33 | p.x *= resolution.x/resolution.y; 34 | 35 | vec4 c=vec4(1.0); 36 | vec3 org=vec3(sin(time)*.5,cos(time*.5)*.25+.25,time),dir=normalize(vec3(p.x*1.6,p.y,1.0)),q=org,pp; 37 | float d=.0; 38 | 39 | //First raymarching 40 | for(int i=0;i<64;i++) 41 | { 42 | d=o(q); 43 | q+=d*dir; 44 | } 45 | pp=q; 46 | float f=length(q-org)*0.02; 47 | 48 | //Second raymarching (reflection) 49 | dir=reflect(dir,gn(q)); 50 | q+=dir; 51 | for(int i=0;i<64;i++) 52 | { 53 | d=o(q); 54 | q+=d*dir; 55 | } 56 | c=max(dot(gn(q),vec3(.1,.1,.0)),.0)+vec4(.3,cos(time*.5)*.5+.5,sin(time*.5)*.5+.5,1.)*min(length(q-org)*.04,1.); 57 | 58 | //Ribbon Color 59 | if(oa(pp)>ob(pp))c=mix(c,vec4(cos(time*.3)*.5+.5,cos(time*.2)*.5+.5,sin(time*.3)*.5+.5,1.),.3); 60 | 61 | //Final Color 62 | vec4 fcolor = ((c+vec4(f))+(1.-min(pp.y+1.9,1.))*vec4(1.,.8,.7,1.))*min(time*.5,1.); 63 | gl_FragColor=vec4(fcolor.xyz,1.0); 64 | } 65 | -------------------------------------------------------------------------------- /tests/real/z_invert.frag.expected: -------------------------------------------------------------------------------- 1 | /* File generated with Shader Minifier 1.1.6 2 | * http://www.ctrl-alt-test.fr 3 | */ 4 | #ifndef Z_INVERT_FRAG_EXPECTED_ 5 | # define Z_INVERT_FRAG_EXPECTED_ 6 | # define VAR_RESOLUTION "s" 7 | # define VAR_TEX0 "y" 8 | # define VAR_TEX1 "o" 9 | # define VAR_TEX2 "r" 10 | # define VAR_TEX3 "z" 11 | # define VAR_TIME "c" 12 | 13 | const char *z_invert_frag = 14 | "uniform vec2 s;" 15 | "uniform float c;" 16 | "uniform sampler2D y,o,r,z;" 17 | "void main()" 18 | "{" 19 | "vec2 r=-1.+2.*gl_FragCoord.xy/s.xy,z;" 20 | "float x=atan(r.y,r.x),o=sqrt(dot(r,r));" 21 | "z.x=cos(.6+c)+cos(cos(1.2+c)+x)/o;" 22 | "z.y=cos(.3+c)+sin(cos(2.+c)+x)/o;" 23 | "vec3 f=texture2D(y,z*.25).xyz;" 24 | "gl_FragColor=vec4(f*o*o,1.);" 25 | "}"; 26 | 27 | #endif // Z_INVERT_FRAG_EXPECTED_ 28 | -------------------------------------------------------------------------------- /tests/shadertoy.h.glsl: -------------------------------------------------------------------------------- 1 | precision highp float; 2 | 3 | uniform vec3 iResolution; 4 | uniform float iTime; 5 | uniform float iTimeDelta; 6 | uniform int iFrame; 7 | uniform float iChannelTime[4]; 8 | uniform vec3 iChannelResolution[4]; 9 | uniform vec4 iMouse; 10 | uniform vec4 iDate; 11 | uniform float iSampleRate; 12 | 13 | uniform sampler2D iChannel0; 14 | uniform sampler2D iChannel1; 15 | uniform sampler2D iChannel2; 16 | uniform sampler2D iChannel3; 17 | 18 | // hack: make all samplers sampler2D 19 | // ( real shadertoy.com iChanneln declarations depend on channel settings ) 20 | #define samplerCube sampler2D 21 | vec4 _shadertoy_h_texture(sampler2D s,vec2 v){return vec4(0);} 22 | vec4 _shadertoy_h_texture(sampler2D s,vec2 v,float b){return vec4(0);} 23 | vec4 _shadertoy_h_texture(sampler2D s,vec3 v){return vec4(0);} 24 | #define texture _shadertoy_h_texture 25 | 26 | void mainImage (out vec4 O, vec2 f); 27 | out vec4 shadertoy_out_color; 28 | void main () { 29 | mainImage(shadertoy_out_color,gl_FragCoord.xy); 30 | } 31 | -------------------------------------------------------------------------------- /tests/unit/1.simple.frag: -------------------------------------------------------------------------------- 1 | void main() 2 | { 3 | gl_FragColor = vec4(0.2, 0.4, 0.6, 0.); 4 | } 5 | -------------------------------------------------------------------------------- /tests/unit/2.simple.frag: -------------------------------------------------------------------------------- 1 | void main() 2 | { 3 | gl_FragColor = vec4(0.2, 0.4, 0.6, 0.); 4 | } 5 | -------------------------------------------------------------------------------- /tests/unit/2.simple.opt.frag: -------------------------------------------------------------------------------- 1 | void main(){gl_FragColor=vec4(.2,.4,.6,0.);} -------------------------------------------------------------------------------- /tests/unit/arg-inlining.expected: -------------------------------------------------------------------------------- 1 | #version 300 es 2 | 3 | precision highp float; 4 | float noinline_canInlineWhenResolvable() 5 | { 6 | return 11.; 7 | } 8 | float noinline_cannotInlineWhenNotResolvable(float a) 9 | { 10 | return a+11.; 11 | } 12 | float noinline_cannotInlineWhenNotResolvable(vec2 a) 13 | { 14 | return length(a)+11.; 15 | } 16 | float noinline_canInlineWhenInParameter() 17 | { 18 | return 21.; 19 | } 20 | float noinline_cannotInlineWhenOutParameter(out float a) 21 | { 22 | return a+21.; 23 | } 24 | float noinline_cannotInlineWhenInOutParameter(inout float a) 25 | { 26 | return a+22.; 27 | } 28 | float noinline_canInlineWhenArgIsAlwaysTheSame() 29 | { 30 | return 31.; 31 | } 32 | float noinline_cannotInlineWhenArgsAreDifferent(float a) 33 | { 34 | return a+31.; 35 | } 36 | float noinline_canInlineWhenArgIsInlinable1() 37 | { 38 | return 20.; 39 | } 40 | float noinline_canInlineWhenArgIsInlinable2() 41 | { 42 | return float(-18)+40.; 43 | } 44 | float noinline_canInlineWhenArgIsInlinable3() 45 | { 46 | return 496.; 47 | } 48 | float noinline_canInlineWhenArgIsInlinable4() 49 | { 50 | return vec3(9).x; 51 | } 52 | float noinline_canInlineWhenArgIsInlinable5() 53 | { 54 | return acos(-1.)+40.; 55 | } 56 | float noinline_canInlineWhenArgIsInlinable6() 57 | { 58 | return 1./3.+40.; 59 | } 60 | float noinline_cannotInlineWhenArgIsNotInlinable(float a) 61 | { 62 | return a+41.; 63 | } 64 | float f() 65 | { 66 | float s=0.; 67 | s+=s+noinline_canInlineWhenResolvable(); 68 | s+=s+noinline_cannotInlineWhenNotResolvable(1.); 69 | s+=s+noinline_canInlineWhenInParameter(); 70 | s+=s+noinline_cannotInlineWhenOutParameter(s); 71 | s+=s+noinline_cannotInlineWhenInOutParameter(s); 72 | s+=s+noinline_canInlineWhenArgIsAlwaysTheSame(); 73 | s+=s+noinline_cannotInlineWhenArgsAreDifferent(1.); 74 | s+=s+noinline_cannotInlineWhenArgsAreDifferent(2.); 75 | s+=s+noinline_canInlineWhenArgIsInlinable1(); 76 | s+=s+noinline_canInlineWhenArgIsInlinable2(); 77 | s+=s+noinline_canInlineWhenArgIsInlinable3(); 78 | s+=s+noinline_canInlineWhenArgIsInlinable4(); 79 | s+=s+noinline_canInlineWhenArgIsInlinable5(); 80 | s+=s+noinline_canInlineWhenArgIsInlinable6(); 81 | s+=s+noinline_cannotInlineWhenArgIsNotInlinable(s); 82 | return s+s+noinline_cannotInlineWhenArgIsNotInlinable(acos(s)); 83 | } 84 | out vec4 fragColor; 85 | uniform sampler2D samp; 86 | vec3 dof() 87 | { 88 | float f=10.; 89 | for(;;) 90 | { 91 | vec3 a=texture(samp,vec2(0)).xyz; 92 | return a.zyx+a.xyz*(f*=f); 93 | } 94 | } 95 | void main() 96 | { 97 | f(); 98 | fragColor.xyz=dof(); 99 | } 100 | -------------------------------------------------------------------------------- /tests/unit/arg-inlining.frag: -------------------------------------------------------------------------------- 1 | #version 300 es 2 | precision highp float; 3 | 4 | // Argument inlining inlines the argument of a function call into the function body. 5 | 6 | float noinline_canInlineWhenResolvable(float a) { return a+10.; } 7 | float noinline_cannotInlineWhenNotResolvable(float a) { return a+11.; } 8 | float noinline_cannotInlineWhenNotResolvable(vec2 a) { return length(a)+11.; } 9 | 10 | float noinline_canInlineWhenInParameter(in float a) { return a+20.; } 11 | float noinline_cannotInlineWhenOutParameter(out float a) { return a+21.; } 12 | float noinline_cannotInlineWhenInOutParameter(inout float a) { return a+22.; } 13 | 14 | float noinline_canInlineWhenArgIsAlwaysTheSame(float a) { return a+30.; } 15 | float noinline_cannotInlineWhenArgsAreDifferent(float a) { return a+31.; } 16 | 17 | float noinline_canInlineWhenArgIsInlinable1(bool a) { return a?20.:40.; } 18 | float noinline_canInlineWhenArgIsInlinable2(int a) { return float(a)+40.; } 19 | float noinline_canInlineWhenArgIsInlinable3(float a) { return a+40.; } 20 | float noinline_canInlineWhenArgIsInlinable4(vec3 a) { return a.x; } 21 | float noinline_canInlineWhenArgIsInlinable5(float a) { return a+40.; } 22 | float noinline_canInlineWhenArgIsInlinable6(float a) { return a+40.; } 23 | float noinline_cannotInlineWhenArgIsNotInlinable(float a) { return a+41.; } 24 | 25 | float f() 26 | { 27 | float s = 0.; 28 | 29 | s += s + noinline_canInlineWhenResolvable(1.); 30 | s += s + noinline_cannotInlineWhenNotResolvable(1.); 31 | 32 | s += s + noinline_canInlineWhenInParameter(1.); 33 | s += s + noinline_cannotInlineWhenOutParameter(s); 34 | s += s + noinline_cannotInlineWhenInOutParameter(s); 35 | 36 | s += s + noinline_canInlineWhenArgIsAlwaysTheSame(1.); 37 | s += s + noinline_cannotInlineWhenArgsAreDifferent(1.); 38 | s += s + noinline_cannotInlineWhenArgsAreDifferent(2.); 39 | 40 | s += s + noinline_canInlineWhenArgIsInlinable1(true); 41 | s += s + noinline_canInlineWhenArgIsInlinable2(-18); 42 | s += s + noinline_canInlineWhenArgIsInlinable3(456.0); 43 | s += s + noinline_canInlineWhenArgIsInlinable4(vec3(9)); 44 | s += s + noinline_canInlineWhenArgIsInlinable5(acos(-1.)); 45 | s += s + noinline_canInlineWhenArgIsInlinable6(1./3.); 46 | s += s + noinline_cannotInlineWhenArgIsNotInlinable(s); 47 | s += s + noinline_cannotInlineWhenArgIsNotInlinable(acos(s)); 48 | 49 | return s; 50 | } 51 | 52 | 53 | // sampler types are immutable and cannot be locals, they must always be inlined (#496) 54 | out vec4 fragColor; 55 | uniform sampler2D samp; 56 | vec3 dof(sampler2D tex, float f) { 57 | for (;;) { 58 | vec3 a = texture(tex,vec2(0)).rgb; 59 | return a.zyx+a.xyz*(f*=f); 60 | } 61 | } 62 | 63 | 64 | void main() 65 | { 66 | f(); 67 | fragColor.xyz = dof(samp, 10.0); 68 | } 69 | -------------------------------------------------------------------------------- /tests/unit/array.frag: -------------------------------------------------------------------------------- 1 | #version 430 2 | 3 | float a[3+2] = float[5](3.4, 4.2, 5.0, 5.2, 1.1); 4 | 5 | const int size = 5; 6 | float b[size] = float[size](3.4, 4.2, 5.0, 5.2, 1.1); 7 | 8 | float c[] = float[](3.4, 4.2, 5.0, 5.2, 1.1); 9 | float d[5] = float[](3.4, 4.2, 5.0, 5.2, 1.1); 10 | float e[] = float[5](3.4, 4.2, 5.0, 5.2, 1.1); 11 | 12 | void arrayTypes() { 13 | vec4 a[3]; 14 | vec4[2] b[3]; 15 | vec4[3] c; 16 | 17 | int code[] = int[1](123); 18 | } 19 | 20 | float[2]func_bank(in float[2]res) 21 | { 22 | float a = res[0], b = res[1]; 23 | res[0] = a < b ? a : b; // min 24 | res[1] = a > b ? a : b; // max 25 | return res; 26 | } 27 | 28 | float f(float x) 29 | { 30 | float[2] test = float[](5., 7.); 31 | return func_bank(test)[0] == 5 && func_bank(test)[1] == 7 32 | ? x : x*x; 33 | } 34 | 35 | out vec4 fragColor; 36 | void main() { 37 | float[4] array = float[](1.,2.,3.,4.); 38 | fragColor = vec4(array.length()); 39 | } 40 | -------------------------------------------------------------------------------- /tests/unit/array.frag.expected: -------------------------------------------------------------------------------- 1 | // Generated with (https://github.com/laurentlb/Shader_Minifier/) 2 | #ifndef ARRAY_FRAG_EXPECTED_ 3 | # define ARRAY_FRAG_EXPECTED_ 4 | 5 | const char *array_frag = 6 | "#version 430\n" 7 | "float a[5]=float[5](3.4,4.2,5.,5.2,1.1),b[5]=float[5](3.4,4.2,5.,5.2,1.1),c[]=float[](3.4,4.2,5.,5.2,1.1),d[5]=float[](3.4,4.2,5.,5.2,1.1),e[]=float[5](3.4,4.2,5.,5.2,1.1);" 8 | "void arrayTypes()" 9 | "{}" 10 | "float[2] func_bank(float[2] res)" 11 | "{" 12 | "float a=res[0],b=res[1];" 13 | "res[0]=ab?" 17 | "a:" 18 | "b;" 19 | "return res;" 20 | "}" 21 | "float f(float x)" 22 | "{" 23 | "float[2] test=float[](5.,7.);" 24 | "return func_bank(test)[0]==5&&func_bank(test)[1]==7?" 25 | "x:" 26 | "x*x;" 27 | "}" 28 | "out vec4 fragColor;" 29 | "void main()" 30 | "{" 31 | "fragColor=vec4(4);" 32 | "}"; 33 | 34 | #endif // ARRAY_FRAG_EXPECTED_ 35 | -------------------------------------------------------------------------------- /tests/unit/augmented.frag: -------------------------------------------------------------------------------- 1 | #version 130 2 | 3 | #extension GL_EXT_gpu_shader4 : enable 4 | 5 | int foo(int x, int y) { 6 | int a=x; 7 | a=a+x; 8 | a=a*y; 9 | a=a>>x; 10 | a=a^y; 11 | a=a|y; 12 | return a; 13 | } 14 | 15 | int outputvar; 16 | 17 | void main() { 18 | outputvar = foo(0, 0); 19 | } 20 | -------------------------------------------------------------------------------- /tests/unit/augmented.frag.expected: -------------------------------------------------------------------------------- 1 | #version 130 2 | 3 | #extension GL_EXT_gpu_shader4:enable 4 | 5 | int foo(int x,int y) 6 | { 7 | return(x+x)*y>>x^y|y; 8 | } 9 | int outputvar; 10 | void main() 11 | { 12 | outputvar=foo(0,0); 13 | } 14 | -------------------------------------------------------------------------------- /tests/unit/blocks.expected: -------------------------------------------------------------------------------- 1 | // Generated with (https://github.com/laurentlb/Shader_Minifier/) 2 | #ifndef BLOCKS_EXPECTED_ 3 | # define BLOCKS_EXPECTED_ 4 | 5 | const char *blocks_frag = 6 | "float test_if()" 7 | "{" 8 | "int foo=2;" 9 | "float bar;" 10 | "if(foo==2)" 11 | "foo++;" 12 | "return foo<5?" 13 | "foo==3?" 14 | ".2:" 15 | ".3:" 16 | ".4;" 17 | "}" 18 | "int k=5;" 19 | "float test_for()" 20 | "{" 21 | "int foo=2,n=0;" 22 | "for(int i=0;i<4;i++)" 23 | "foo+=i;" 24 | "for(foo++;n<4;n++)" 25 | "{" 26 | "int k=n-1;" 27 | "foo+=k;" 28 | "}" 29 | "return 1./float(k);" 30 | "}" 31 | "int test_block()" 32 | "{" 33 | "for(int i=0;i<2;i++)" 34 | "{" 35 | "if(k==1)" 36 | "return k++,2;" 37 | "break;" 38 | "}" 39 | "}" 40 | "float removeUselessElseAfterReturn1(float f)" 41 | "{" 42 | "if(f<2.)" 43 | "return 1.;" 44 | "f=4.;" 45 | "return 5.;" 46 | "}" 47 | "float removeUselessElseAfterReturn2(float f)" 48 | "{" 49 | "float a=2.;" 50 | "if(f 0.0) 63 | r = sideEffect(1); 64 | else 65 | r = sideEffect(2); 66 | float r2; 67 | if (f > 1.0) { 68 | r2 = sideEffect(1); 69 | } else { 70 | sideEffect(99); 71 | r2 = sideEffect(2); 72 | } 73 | float r3; 74 | if (f > 1.0) { 75 | r3 = sideEffect(1); 76 | } else { 77 | r3 = sideEffect(2); 78 | sideEffect(99); 79 | } 80 | return r+r2+r3; 81 | } 82 | 83 | // Move-declarations bug (#458) 84 | uniform int A; 85 | uniform int B; 86 | vec4 O; 87 | void main() { 88 | O = vec4(0); 89 | float f = 1; 90 | if (B < 2) f = A; 91 | { 92 | float n = A + 1; 93 | if (B < 1) O.y=1; 94 | float f = f * n + n * n; 95 | O.x=f; 96 | } 97 | } 98 | -------------------------------------------------------------------------------- /tests/unit/conditionals.frag.expected: -------------------------------------------------------------------------------- 1 | #version 120 2 | 3 | int noinlinevar; 4 | bool success() 5 | { 6 | noinlinevar++; 7 | return true; 8 | } 9 | bool fail() 10 | { 11 | noinlinevar++; 12 | return false; 13 | } 14 | bool ternary() 15 | { 16 | return success(); 17 | } 18 | bool ternary2() 19 | { 20 | return success(); 21 | } 22 | bool or() 23 | { 24 | return true; 25 | } 26 | bool or2() 27 | { 28 | return success(); 29 | } 30 | bool or3() 31 | { 32 | return success(); 33 | } 34 | bool and() 35 | { 36 | return success(); 37 | } 38 | bool and2() 39 | { 40 | return false; 41 | } 42 | bool and3() 43 | { 44 | return success(); 45 | } 46 | int foo() 47 | { 48 | return 1; 49 | } 50 | int glo; 51 | int sideEffect(int n) 52 | { 53 | return glo+=n; 54 | } 55 | float ifStmtToExpr(float f) 56 | { 57 | float r=f>0.? 58 | sideEffect(1): 59 | sideEffect(2),r2=f>1.? 60 | sideEffect(1): 61 | (sideEffect(99),sideEffect(2)),r3; 62 | if(f>1.) 63 | r3=sideEffect(1); 64 | else 65 | r3=sideEffect(2),sideEffect(99); 66 | return r+r2+r3; 67 | } 68 | uniform int A,B; 69 | vec4 O; 70 | void main() 71 | { 72 | O=vec4(0); 73 | float f=1; 74 | if(B<2) 75 | f=A; 76 | { 77 | float n=A+1; 78 | if(B<1) 79 | O.y=1; 80 | n=f*n+n*n; 81 | O.x=n; 82 | } 83 | } 84 | -------------------------------------------------------------------------------- /tests/unit/deadcode.frag: -------------------------------------------------------------------------------- 1 | int f(int x) { 2 | #if FOO 3 | return x; 4 | #else 5 | return x + 2; 6 | #endif 7 | } 8 | 9 | void main() { 10 | int a = 2; 11 | f(a); 12 | return; 13 | f(a + 1); 14 | } 15 | -------------------------------------------------------------------------------- /tests/unit/deadcode.frag.expected: -------------------------------------------------------------------------------- 1 | int f() 2 | { 3 | 4 | #if FOO 5 | 6 | return 2; 7 | 8 | #else 9 | 10 | return 4; 11 | 12 | #endif 13 | 14 | } 15 | void main() 16 | { 17 | f(); 18 | return; 19 | } 20 | -------------------------------------------------------------------------------- /tests/unit/decimals.frag: -------------------------------------------------------------------------------- 1 | //NOCOMPILE 2 | void test () { 3 | x(3.141592653589793); 4 | x(3.1415927); 5 | //x(1e308); 6 | //x(3e38); 7 | //x(1e37); 8 | x(1e28); 9 | x(125.663704/180.); 10 | x(.6981316889); 11 | x(100000005.); 12 | x(1.24e27); 13 | x(1.20e27); 14 | x(1.00e27); 15 | x(1.24e4); 16 | x(1.20e4); 17 | x(1.00e4); 18 | x(1.24e3); 19 | x(1.20e3); 20 | x(1.00e3); 21 | x(1.24e2); 22 | x(1.20e2); 23 | x(1.00e2); 24 | x(1.24e1); 25 | x(1.20e1); 26 | x(1.00e1); 27 | x(1.24e0); 28 | x(1.20e0); 29 | x(1.00e0); 30 | x(1.24e-1); 31 | x(1.20e-1); 32 | x(1.00e-1); 33 | x(1.24e-2); 34 | x(1.20e-2); 35 | x(1.00e-2); 36 | x(1.24e-3); 37 | x(1.20e-3); 38 | x(1.00e-3); 39 | x(1.24e-4); 40 | x(1.20e-4); 41 | x(1.00e-4); 42 | x(1.24e-27); 43 | x(1.20e-27); 44 | x(1.00e-27); 45 | x(6e-29); 46 | x(8e-46); 47 | //x(3e-324); 48 | } 49 | -------------------------------------------------------------------------------- /tests/unit/decimals.frag.expected: -------------------------------------------------------------------------------- 1 | void test() 2 | { 3 | x(acos(-1.)); 4 | x(3.1415927); 5 | x(1e28); 6 | x(125.663704/180.); 7 | x(.6981316889); 8 | x(100000005.); 9 | x(124e25); 10 | x(12e26); 11 | x(1e27); 12 | x(124e2); 13 | x(12e3); 14 | x(1e4); 15 | x(1240.); 16 | x(12e2); 17 | x(1e3); 18 | x(124.); 19 | x(120.); 20 | x(1e2); 21 | x(12.4); 22 | x(12.); 23 | x(10.); 24 | x(1.24); 25 | x(1.2); 26 | x(1.); 27 | x(.124); 28 | x(.12); 29 | x(.1); 30 | x(.0124); 31 | x(.012); 32 | x(.01); 33 | x(.00124); 34 | x(.0012); 35 | x(.001); 36 | x(124e-6); 37 | x(12e-5); 38 | x(1e-4); 39 | x(0.); 40 | x(0.); 41 | x(0.); 42 | x(0.); 43 | x(0.); 44 | } 45 | -------------------------------------------------------------------------------- /tests/unit/empty_block.frag: -------------------------------------------------------------------------------- 1 | void more_semicolons(){} 2 | 3 | int f() { 4 | int x = 5; 5 | int y = 7; 6 | 7 | if (x < 3) { 8 | return 2; 9 | } else {;} 10 | 11 | if (x == 5) { 12 | ; 13 | } else {} 14 | 15 | if (y == 1); else; 16 | 17 | more_semicolons();;; 18 | return 3; 19 | } 20 | -------------------------------------------------------------------------------- /tests/unit/externals.expected: -------------------------------------------------------------------------------- 1 | // Generated with (https://github.com/laurentlb/Shader_Minifier/) 2 | #ifndef EXTERNALS_EXPECTED_ 3 | # define EXTERNALS_EXPECTED_ 4 | # define VAR_e "I" 5 | # define VAR_i "i" 6 | # define VAR_n "J" 7 | 8 | const char *externals_frag = 9 | "uniform int i,J,I;" 10 | "int H()" 11 | "{" 12 | "return i;" 13 | "}" 14 | "int G()" 15 | "{" 16 | "return J;" 17 | "}" 18 | "int F()" 19 | "{" 20 | "return I;" 21 | "}"; 22 | 23 | #endif // EXTERNALS_EXPECTED_ 24 | -------------------------------------------------------------------------------- /tests/unit/externals.frag: -------------------------------------------------------------------------------- 1 | uniform int i, n, e; 2 | 3 | int f() { 4 | int var1, var2, var3, var4, var5; 5 | return i; 6 | } 7 | 8 | int g() { 9 | int var1, var2, var3, var4, var5; 10 | return n; 11 | } 12 | 13 | int h() { 14 | int var1, var2, var3, var4, var5; 15 | return e; 16 | } 17 | -------------------------------------------------------------------------------- /tests/unit/externals.preserved.expected: -------------------------------------------------------------------------------- 1 | // Generated with (https://github.com/laurentlb/Shader_Minifier/) 2 | #ifndef EXTERNALS_PRESERVED_EXPECTED_ 3 | # define EXTERNALS_PRESERVED_EXPECTED_ 4 | 5 | const char *externals_frag = 6 | "uniform int i,n,e;" 7 | "int H()" 8 | "{" 9 | "return i;" 10 | "}" 11 | "int G()" 12 | "{" 13 | "return n;" 14 | "}" 15 | "int F()" 16 | "{" 17 | "return e;" 18 | "}"; 19 | 20 | #endif // EXTERNALS_PRESERVED_EXPECTED_ 21 | -------------------------------------------------------------------------------- /tests/unit/file name with-weird caractères.frag: -------------------------------------------------------------------------------- 1 | // maybe the real test data was the file name we made along the way 2 | void main() { gl_FragColor = vec4(0.33, 0.66, 0.99, 1.); } 3 | -------------------------------------------------------------------------------- /tests/unit/file name with-weird caractères.frag.c-variables.expected: -------------------------------------------------------------------------------- 1 | // Generated with (https://github.com/laurentlb/Shader_Minifier/) 2 | #ifndef FILE_NAME_WITH_WEIRD_CARACT_RES_FRAG_C_VARIABLES_EXPECTED_ 3 | # define FILE_NAME_WITH_WEIRD_CARACT_RES_FRAG_C_VARIABLES_EXPECTED_ 4 | 5 | const char *file_name_with_weird_caract_res_frag = 6 | "void main()" 7 | "{" 8 | "gl_FragColor=vec4(.33,.66,.99,1);" 9 | "}"; 10 | 11 | #endif // FILE_NAME_WITH_WEIRD_CARACT_RES_FRAG_C_VARIABLES_EXPECTED_ 12 | -------------------------------------------------------------------------------- /tests/unit/file name with-weird caractères.frag.js.expected: -------------------------------------------------------------------------------- 1 | // Generated with (https://github.com/laurentlb/Shader_Minifier/) 2 | 3 | var file_name_with_weird_caractères_frag = `void main(){gl_FragColor=vec4(.33,.66,.99,1);}` 4 | -------------------------------------------------------------------------------- /tests/unit/file name with-weird caractères.frag.json.expected: -------------------------------------------------------------------------------- 1 | {"mappings":{},"shaders":{"tests/unit/file name with-weird caractères.frag":"void main(){gl_FragColor=vec4(.33,.66,.99,1);}"}} 2 | -------------------------------------------------------------------------------- /tests/unit/file name with-weird caractères.frag.nasm.expected: -------------------------------------------------------------------------------- 1 | ; Generated with (https://github.com/laurentlb/Shader_Minifier/) 2 | 3 | _file_name_with_weird_caract_res_frag: 4 | db 'void main()' 5 | db '{' 6 | db 'gl_FragColor=vec4(.33,.66,.99,1);' 7 | db '}', 0 8 | -------------------------------------------------------------------------------- /tests/unit/file name with-weird caractères.frag.rust.expected: -------------------------------------------------------------------------------- 1 | // Generated with (https://github.com/laurentlb/Shader_Minifier/) 2 | 3 | pub const FILE_NAME_WITH_WEIRD_CARACTÈRES_FRAG: &'static [u8] = b"\ 4 | void main()\ 5 | {\ 6 | gl_FragColor=vec4(.33,.66,.99,1);\ 7 | }\0"; 8 | -------------------------------------------------------------------------------- /tests/unit/float.frag: -------------------------------------------------------------------------------- 1 | float floatPrecision(float x) { 2 | float a = 0.00000012345; 3 | float b = 1.234567891234; 4 | float c = 1234567.891234; 5 | float d = 123456700000000.; 6 | return a*x+b*x+c*x+d*x; 7 | } 8 | 9 | float largeNumbers(float x) { 10 | float a = 4.1e8; 11 | float b = 4.2e10; 12 | float c = 4.3e12; 13 | float d = 4.4e14; 14 | return a*x+b*x+c*x+d*x; 15 | } 16 | 17 | float smallNumbers(float x) { 18 | float a = 4e-1; 19 | float b = 4e-2; 20 | float c = 4e-3; 21 | float d = 4e-4; 22 | float e = 4e-8; 23 | float f = 4e-10; 24 | float g = 4e-12; 25 | float h = 4e-14; 26 | return a*x+b*x+c*x+d*x+e*x+f*x+g*x+h*x; 27 | } 28 | 29 | float zero(float x) { 30 | float a = 0.; 31 | float b = .0; 32 | float c = -.0; 33 | return a*x+b*x+c*x; 34 | } 35 | 36 | float x; 37 | 38 | void main() 39 | { 40 | float f1 = 1.5; 41 | float f2 = .0000003; 42 | float f3 = .42; 43 | float f6 = -2e-3; 44 | float f7 = 2E-9; 45 | float f8 = 2E+6; 46 | float f9 = 2e10; 47 | 48 | gl_FragColor=vec4(f1*x+f2*x+f3*x+f6*x+f7*x+f8*x+f9*x); 49 | } 50 | -------------------------------------------------------------------------------- /tests/unit/float.frag.expected: -------------------------------------------------------------------------------- 1 | // Generated with (https://github.com/laurentlb/Shader_Minifier/) 2 | #ifndef SHADER_MINIFIER_IMPL 3 | #ifndef SHADER_MINIFIER_HEADER 4 | # define SHADER_MINIFIER_HEADER 5 | #endif 6 | 7 | #else // if SHADER_MINIFIER_IMPL 8 | 9 | // tests/unit/float.frag 10 | "float floatPrecision(float x)" 11 | "{" 12 | "float a=12345e-11,b=1.234567891234,c=1234567.891234,d=1234567e8;" 13 | "return a*x+b*x+c*x+d*x;" 14 | "}" 15 | "float largeNumbers(float x)" 16 | "{" 17 | "float a=41e7,b=42e9,c=43e11,d=44e13;" 18 | "return a*x+b*x+c*x+d*x;" 19 | "}" 20 | "float smallNumbers(float x)" 21 | "{" 22 | "float a=.4,b=.04,c=.004,d=4e-4,e=4e-8,f=4e-10,g=4e-12,h=4e-14;" 23 | "return a*x+b*x+c*x+d*x+e*x+f*x+g*x+h*x;" 24 | "}" 25 | "float zero(float x)" 26 | "{" 27 | "float a=0.,b=0.,c=0.;" 28 | "return a*x+b*x+c*x;" 29 | "}" 30 | "float x;" 31 | "void main()" 32 | "{" 33 | "float f1=1.5,f2=3e-7,f3=.42,f6=-.002,f7=2e-9,f8=2e6,f9=2e10;" 34 | "gl_FragColor=vec4(f1*x+f2*x+f3*x+f6*x+f7*x+f8*x+f9*x);" 35 | "}", 36 | 37 | #endif 38 | -------------------------------------------------------------------------------- /tests/unit/forbidden.expected: -------------------------------------------------------------------------------- 1 | struct L{float t;}; 2 | float K() 3 | { 4 | return 42.; 5 | } 6 | -------------------------------------------------------------------------------- /tests/unit/forbidden.frag: -------------------------------------------------------------------------------- 1 | struct f { 2 | float f; 3 | }; 4 | 5 | float someFun() { 6 | return 42.0; 7 | } 8 | -------------------------------------------------------------------------------- /tests/unit/forward_declaration.frag: -------------------------------------------------------------------------------- 1 | void a(); 2 | void b(); 3 | void c(); 4 | void d(); 5 | 6 | void a() { 7 | b(); 8 | } 9 | 10 | void b() { 11 | c(); 12 | d(); 13 | } 14 | 15 | void e() { 16 | a(); 17 | c(); 18 | } 19 | 20 | int x; 21 | void c() {x++;} 22 | 23 | void d() {x++;} 24 | -------------------------------------------------------------------------------- /tests/unit/forward_declaration.frag.expected: -------------------------------------------------------------------------------- 1 | int x; 2 | void c() 3 | { 4 | x++; 5 | } 6 | void d() 7 | { 8 | x++; 9 | } 10 | void b() 11 | { 12 | c(); 13 | d(); 14 | } 15 | void a() 16 | { 17 | b(); 18 | } 19 | void e() 20 | { 21 | a(); 22 | c(); 23 | } 24 | -------------------------------------------------------------------------------- /tests/unit/function_comma.expected: -------------------------------------------------------------------------------- 1 | // Generated with (https://github.com/laurentlb/Shader_Minifier/) 2 | #ifndef FUNCTION_COMMA_EXPECTED_ 3 | # define FUNCTION_COMMA_EXPECTED_ 4 | 5 | const char *function_comma_frag = 6 | "float min(float a,float b)" 7 | "{" 8 | "return a OutputStream ) 7 | { 8 | PSSceneIn output = (PSSceneIn)0; 9 | int n = //[3.14159265358979323846264338327950288419716939937510//]; 10 | for( uint i=0; i<6; i+=2 ) 11 | { 12 | output.Pos = input[i].Pos; 13 | output.Norm = input[i].Norm; 14 | output.Tex = input[i].Tex; 15 | 16 | OutputStream.Append( output ); 17 | } 18 | 19 | OutputStream.RestartStrip(); 20 | } 21 | -------------------------------------------------------------------------------- /tests/unit/geometry.hlsl.expected: -------------------------------------------------------------------------------- 1 | // Generated with (https://github.com/laurentlb/Shader_Minifier/) 2 | #ifndef GEOMETRY_HLSL_EXPECTED_ 3 | # define GEOMETRY_HLSL_EXPECTED_ 4 | 5 | const char *geometry_hlsl = 6 | "[maxvertexcount(3)]\n" 7 | "void GSScene(triangleadj GSSceneIn input[6],inout TriangleStream OutputStream)" 8 | "{" 9 | "PSSceneIn output=(PSSceneIn)0;" 10 | "int n=3.14159265358979323846264338327950288419716939937510;" 11 | "for(uint i=0;i<6;i+=2)" 12 | "output.Pos=input[i].Pos,output.Norm=input[i].Norm,output.Tex=input[i].Tex,OutputStream.Append(output);" 13 | "OutputStream.RestartStrip();" 14 | "}"; 15 | 16 | #endif // GEOMETRY_HLSL_EXPECTED_ 17 | -------------------------------------------------------------------------------- /tests/unit/hexa.frag: -------------------------------------------------------------------------------- 1 | void main() 2 | { 3 | float n = float(0xff) / 1000.; 4 | float o = float(-0XFF) / 1000.; 5 | float p = n - o + float(4 * 0x0); 6 | gl_FragColor=vec4(.2,.4,n,0.); 7 | } 8 | -------------------------------------------------------------------------------- /tests/unit/inline-aggro.aggro.expected: -------------------------------------------------------------------------------- 1 | #version 150 2 | 3 | float inl1() 4 | { 5 | return 126.; 6 | } 7 | float inl2(float x) 8 | { 9 | return x>246913578.? 10 | 1e2: 11 | x>123456789.? 12 | 101.: 13 | 102.; 14 | } 15 | float inl3() 16 | { 17 | return 2.*acos(-1.)*.75; 18 | } 19 | float inl4() 20 | { 21 | return 2.*acos(-1.)*.75; 22 | } 23 | float inl5() 24 | { 25 | return 579.; 26 | } 27 | const float baz=2.*acos(-1.); 28 | float inl6() 29 | { 30 | return 2.*baz; 31 | } 32 | float notevil(float y) 33 | { 34 | return 42.+(y*=y); 35 | } 36 | float inl7(float u) 37 | { 38 | return 101.+notevil(u); 39 | } 40 | int inl8(ivec3 x) 41 | { 42 | x[1]+=1; 43 | return x[1]+1; 44 | } 45 | float noinl1() 46 | { 47 | return 101.; 48 | } 49 | float noinl2() 50 | { 51 | float f=42.; 52 | f++; 53 | return f; 54 | } 55 | float noinl3() 56 | { 57 | float f=42.; 58 | if(acos(-1.)<3.) 59 | f=101.; 60 | return f; 61 | } 62 | float noinl4() 63 | { 64 | float f=42.; 65 | for(f=0.;false;) 66 | ; 67 | return f; 68 | } 69 | float noinl5() 70 | { 71 | float f=42.; 72 | for(;false;f++) 73 | ; 74 | return f; 75 | } 76 | float noinl6(float x) 77 | { 78 | float f=x+1.; 79 | x=1e2; 80 | return f+2.; 81 | } 82 | float noinl7(const float x) 83 | { 84 | return x+1.2; 85 | } 86 | float noinl8() 87 | { 88 | return 3.; 89 | } 90 | float noinl9(float x) 91 | { 92 | float bar=x+1.; 93 | x=1e2; 94 | return bar+2.; 95 | } 96 | void evil(inout float x) 97 | { 98 | x=42.; 99 | } 100 | float noinl10() 101 | { 102 | float f=101.; 103 | evil(f); 104 | return f; 105 | } 106 | int noinl11(ivec3 x) 107 | { 108 | int i=1; 109 | x[i++]+=1; 110 | return x[i]+i; 111 | } 112 | int noinl12() 113 | { 114 | int i=10; 115 | for(;--i>0;) 116 | ; 117 | return 1; 118 | } 119 | -------------------------------------------------------------------------------- /tests/unit/inline-aggro.expected: -------------------------------------------------------------------------------- 1 | #version 150 2 | 3 | float inl1() 4 | { 5 | return 126.; 6 | } 7 | float inl2(float x) 8 | { 9 | return x>246913578.? 10 | 1e2: 11 | x>123456789.? 12 | 101.: 13 | 102.; 14 | } 15 | float inl3() 16 | { 17 | return 2.*acos(-1.)*.75; 18 | } 19 | float inl4() 20 | { 21 | return 2.*acos(-1.)*.75; 22 | } 23 | float inl5() 24 | { 25 | return 579.; 26 | } 27 | const float bar=acos(-1.),baz=2.*bar; 28 | float inl6() 29 | { 30 | return 2.*baz; 31 | } 32 | float notevil(float y) 33 | { 34 | return 42.+(y*=y); 35 | } 36 | float inl7(float u) 37 | { 38 | return 101.+notevil(u); 39 | } 40 | int inl8(ivec3 x) 41 | { 42 | x[1]+=1; 43 | return x[1]+1; 44 | } 45 | float noinl1() 46 | { 47 | return 101.; 48 | } 49 | float noinl2() 50 | { 51 | float f=42.; 52 | f++; 53 | return f; 54 | } 55 | float noinl3() 56 | { 57 | float f=42.; 58 | if(acos(-1.)<3.) 59 | f=101.; 60 | return f; 61 | } 62 | float noinl4() 63 | { 64 | float f=42.; 65 | for(f=0.;false;) 66 | ; 67 | return f; 68 | } 69 | float noinl5() 70 | { 71 | float f=42.; 72 | for(;false;f++) 73 | ; 74 | return f; 75 | } 76 | float noinl6(float x) 77 | { 78 | float f=x+1.; 79 | x=1e2; 80 | return f+2.; 81 | } 82 | float noinl7(const float x) 83 | { 84 | return x+1.2; 85 | } 86 | float noinl8() 87 | { 88 | return 3.; 89 | } 90 | float noinl9(float x) 91 | { 92 | float bar=x+1.; 93 | x=1e2; 94 | return bar+2.; 95 | } 96 | void evil(inout float x) 97 | { 98 | x=42.; 99 | } 100 | float noinl10() 101 | { 102 | float f=101.; 103 | evil(f); 104 | return f; 105 | } 106 | int noinl11(ivec3 x) 107 | { 108 | int i=1; 109 | x[i++]+=1; 110 | return x[i]+i; 111 | } 112 | int noinl12() 113 | { 114 | int i=10; 115 | for(;--i>0;) 116 | ; 117 | return 1; 118 | } 119 | -------------------------------------------------------------------------------- /tests/unit/inline-aggro.frag: -------------------------------------------------------------------------------- 1 | #version 150 2 | 3 | // *** Things we should inline 4 | 5 | float inl1() { 6 | float f = 42.0; 7 | float g = 2.0 * f; 8 | return f + g; 9 | } 10 | 11 | float inl2(float x) { 12 | float f = 123456789.0; 13 | if (x > 2.0*f) return 100.0; 14 | if (x > f) return 101.0; 15 | return 102.0; 16 | } 17 | 18 | float inl3() { 19 | const float f = acos(-1.0); 20 | const float g = 2.0*f; 21 | return 0.75*g; 22 | } 23 | 24 | float inl4() { 25 | const float f = acos(-1.0), g = 2.0*f; 26 | return 0.75*g; 27 | } 28 | 29 | const float foo = 123.0; 30 | float inl5() { 31 | float f = 456.0; 32 | return foo + f; 33 | } 34 | 35 | const float bar = acos(-1.0); 36 | const float baz = 2.0*bar; 37 | float inl6() { 38 | return 2.0 * baz; 39 | } 40 | 41 | float notevil(in float x, float y) { x = 42.0; return x + (y *= y); } 42 | float inl7(float u) { 43 | float f = 101.0; 44 | float z = notevil(f, u); 45 | return f + z; 46 | } 47 | 48 | int inl8(in ivec3 x) { 49 | int i = 1; 50 | 51 | // i is not technically in an lvalue position but not smart enough right now to see that. 52 | x[i] += 1; 53 | return x[i] + i; 54 | } 55 | 56 | // *** Things we shouldn't inline 57 | 58 | float noinl1() { 59 | float f = 42.0; 60 | f = 101.0; 61 | return f; 62 | } 63 | 64 | float noinl2() { 65 | float f = 42.0; 66 | f++; 67 | return f; 68 | } 69 | 70 | float noinl3() { 71 | float f = 42.0; 72 | if (acos(-1.0) < 3.0) { 73 | f = 101.0; 74 | } 75 | return f; 76 | } 77 | 78 | float noinl4() { 79 | float f = 42.0; 80 | for (f = 0.0; false;); 81 | return f; 82 | } 83 | 84 | float noinl5() { 85 | float f = 42.0; 86 | for (; false; f++); 87 | return f; 88 | } 89 | 90 | float noinl6(float x) { 91 | float f = x + 1.0; 92 | x = 100.0; 93 | return f + 2.0; 94 | } 95 | 96 | float noinl7(const float x) { 97 | return x + 1.2; 98 | } 99 | 100 | float quux = 1.0; 101 | float noinl8() { 102 | return quux + 2.0; 103 | } 104 | 105 | float noinl9(float x) { 106 | float bar = x + 1.0; // Shadows inlinable const above 107 | x = 100.0; 108 | return bar + 2.0; 109 | } 110 | 111 | void evil(inout float x) { x = 42.0; } 112 | float noinl10() { 113 | float f = 101.0; 114 | evil(f); 115 | return f; 116 | } 117 | 118 | int noinl11(in ivec3 x) { 119 | int i = 1; 120 | x[i++] += 1; 121 | return x[i] + i; 122 | } 123 | 124 | int noinl12() { 125 | int i = 10; 126 | while (--i > 0) { 127 | } 128 | return 1; 129 | } 130 | -------------------------------------------------------------------------------- /tests/unit/inline-fn-multiple.expected: -------------------------------------------------------------------------------- 1 | uniform vec3 v[42]; 2 | vec3 N() 3 | { 4 | return v[4]; 5 | } 6 | vec3 N(float N) 7 | { 8 | return v[4]+N; 9 | } 10 | -------------------------------------------------------------------------------- /tests/unit/inline-fn-multiple.frag: -------------------------------------------------------------------------------- 1 | uniform vec3 params[42]; 2 | 3 | vec3 i_getFoo() { 4 | return params[4]; 5 | } 6 | 7 | vec3 f1() { 8 | return i_getFoo(); 9 | } 10 | 11 | vec3 f2(float a) { 12 | return i_getFoo() + a; 13 | } 14 | -------------------------------------------------------------------------------- /tests/unit/inline-fn.aggro.expected: -------------------------------------------------------------------------------- 1 | float a() 2 | { 3 | return 5.; 4 | } 5 | float b(float g) 6 | { 7 | return(g+10.)*20.+30.+((g+10.1)*20.1+30.1); 8 | } 9 | float c() 10 | { 11 | return 154.; 12 | } 13 | float d() 14 | { 15 | return 54.; 16 | } 17 | float e() 18 | { 19 | return 84.; 20 | } 21 | float globalFloat=6.; 22 | float shadowedFunc(inout float notinlinable) 23 | { 24 | notinlinable=1.; 25 | return-1.; 26 | } 27 | float notShadowedFunc(inout float notinlinable) 28 | { 29 | notinlinable=2.; 30 | return-2.; 31 | } 32 | float shadowedVar=0.; 33 | float A1_PRESERVED() 34 | { 35 | return shadowedVar; 36 | } 37 | float A3_PRESERVED() 38 | { 39 | float a=10.; 40 | return shadowedFunc(a); 41 | } 42 | float B1_PRESERVED(float x) 43 | { 44 | return pow(2.,x); 45 | } 46 | float C1_PRESERVED() 47 | { 48 | float x=sin(0.); 49 | x++; 50 | return 3.+x; 51 | } 52 | float D3_PRESERVED(float d,float dd) 53 | { 54 | return d+d; 55 | } 56 | float glob; 57 | float watchout(out float x) 58 | { 59 | return x=9.; 60 | } 61 | float inuit(inout float greenland) 62 | { 63 | return greenland++; 64 | } 65 | float E1_PRESERVED(float bad1,float ok) 66 | { 67 | return bad1++; 68 | } 69 | float E3_PRESERVED(float bad3,float ok) 70 | { 71 | return bad3+=1.; 72 | } 73 | float E4_PRESERVED(float bad4,float ok) 74 | { 75 | return watchout(bad4); 76 | } 77 | float E5_PRESERVED(float bad5,float ok) 78 | { 79 | return inuit(bad5); 80 | } 81 | float F2_PRESERVED(out float ff) 82 | { 83 | return 7.; 84 | } 85 | float F3_PRESERVED(inout float f) 86 | { 87 | return 7.; 88 | } 89 | float PRAGMA_PRESERVED() 90 | { 91 | return 9.; 92 | } 93 | float setup() 94 | { 95 | return shadowedVar++; 96 | } 97 | float f() 98 | { 99 | float shadowedVar=-1.,shadowedFunc=-2.,_A3=A3_PRESERVED(),_A4=notShadowedFunc(globalFloat); 100 | int sep; 101 | sep++; 102 | sep++; 103 | float four=4.,five=5.,_D1=four+four,_D2=four+five,_D3=D3_PRESERVED(four+1.,sin(five)); 104 | four++,five++; 105 | sep++; 106 | float six=6.,ten=10.,_E1=E1_PRESERVED(six,ten),_E2=six+watchout(glob)-glob--*(glob*=ten)+inuit(glob),_E3=E3_PRESERVED(six,ten),_E4=E4_PRESERVED(six,ten),_E5=E5_PRESERVED(six,ten); 107 | six++,ten++; 108 | sep++; 109 | float o,_F2=F2_PRESERVED(o); 110 | o=F3_PRESERVED(o); 111 | sep++; 112 | setup(); 113 | shadowedVar++; 114 | shadowedFunc++; 115 | return shadowedVar+shadowedFunc+four+five+six+ten+A1_PRESERVED()+1.+_A3+_A4+(B1_PRESERVED(3.)+B1_PRESERVED(4.))+4.+C1_PRESERVED()+(3.+sin(0.))+_D1+_D2+_D3+_E1+_E2+_E3+_E4+_E5+7.+_F2+o+(vec3(9).x+vec3(8).x)+PRAGMA_PRESERVED(); 116 | } 117 | float g() 118 | { 119 | return 1.; 120 | } 121 | -------------------------------------------------------------------------------- /tests/unit/inline-fn.expected: -------------------------------------------------------------------------------- 1 | float a() 2 | { 3 | return 5.; 4 | } 5 | float b(float g) 6 | { 7 | return(g+10.)*20.+30.+((g+10.1)*20.1+30.1); 8 | } 9 | float c() 10 | { 11 | return 154.; 12 | } 13 | float d() 14 | { 15 | return 54.; 16 | } 17 | float e() 18 | { 19 | return 84.; 20 | } 21 | float globalFloat=6.; 22 | float shadowedFunc(inout float notinlinable) 23 | { 24 | notinlinable=1.; 25 | return-1.; 26 | } 27 | float notShadowedFunc(inout float notinlinable) 28 | { 29 | notinlinable=2.; 30 | return-2.; 31 | } 32 | float shadowedVar=0.; 33 | float A1_PRESERVED() 34 | { 35 | return shadowedVar; 36 | } 37 | float A3_PRESERVED() 38 | { 39 | float a=10.; 40 | return shadowedFunc(a); 41 | } 42 | float B1_PRESERVED(float x) 43 | { 44 | return pow(2.,x); 45 | } 46 | float C1_PRESERVED() 47 | { 48 | float x=sin(0.); 49 | x++; 50 | return 3.+x; 51 | } 52 | float D3_PRESERVED(float d,float dd) 53 | { 54 | return d+d; 55 | } 56 | float glob; 57 | float watchout(out float x) 58 | { 59 | return x=9.; 60 | } 61 | float inuit(inout float greenland) 62 | { 63 | return greenland++; 64 | } 65 | float E1_PRESERVED(float bad1,float ok) 66 | { 67 | return bad1++; 68 | } 69 | float E3_PRESERVED(float bad3,float ok) 70 | { 71 | return bad3+=1.; 72 | } 73 | float E4_PRESERVED(float bad4,float ok) 74 | { 75 | return watchout(bad4); 76 | } 77 | float E5_PRESERVED(float bad5,float ok) 78 | { 79 | return inuit(bad5); 80 | } 81 | float F2_PRESERVED(out float ff) 82 | { 83 | return 7.; 84 | } 85 | float F3_PRESERVED(inout float f) 86 | { 87 | return 7.; 88 | } 89 | float PRAGMA_PRESERVED() 90 | { 91 | return 9.; 92 | } 93 | float setup() 94 | { 95 | return shadowedVar++; 96 | } 97 | float f() 98 | { 99 | float shadowedVar=-1.,shadowedFunc=-2.,_A3=A3_PRESERVED(),_A4=notShadowedFunc(globalFloat); 100 | int sep; 101 | sep++; 102 | sep++; 103 | float four=4.,five=5.,_D1=four+four,_D2=four+five,_D3=D3_PRESERVED(four+1.,sin(five)); 104 | four++,five++; 105 | sep++; 106 | float six=6.,ten=10.,_E1=E1_PRESERVED(six,ten),_E2=six+watchout(glob)-glob--*(glob*=ten)+inuit(glob),_E3=E3_PRESERVED(six,ten),_E4=E4_PRESERVED(six,ten),_E5=E5_PRESERVED(six,ten); 107 | six++,ten++; 108 | sep++; 109 | float o,_F2=F2_PRESERVED(o); 110 | o=F3_PRESERVED(o); 111 | sep++; 112 | setup(); 113 | shadowedVar++; 114 | shadowedFunc++; 115 | return shadowedVar+shadowedFunc+four+five+six+ten+A1_PRESERVED()+1.+_A3+_A4+(B1_PRESERVED(3.)+B1_PRESERVED(4.))+4.+C1_PRESERVED()+(3.+sin(0.))+_D1+_D2+_D3+_E1+_E2+_E3+_E4+_E5+7.+_F2+o+(vec3(9).x+vec3(8).x)+PRAGMA_PRESERVED(); 116 | } 117 | float g() 118 | { 119 | return 1.; 120 | } 121 | -------------------------------------------------------------------------------- /tests/unit/inline.aggro.expected: -------------------------------------------------------------------------------- 1 | #version 420 2 | 3 | float result; 4 | void main() 5 | { 6 | result=.15; 7 | } 8 | int arithmetic() 9 | { 10 | return 40; 11 | } 12 | int vars(int arg,int arg2) 13 | { 14 | return arg*(arg+arg2); 15 | } 16 | int arithmetic2() 17 | { 18 | return 40; 19 | } 20 | int unusedVars() 21 | { 22 | return 30; 23 | } 24 | int unusedVars2() 25 | { 26 | return 18; 27 | } 28 | int multiPass() 29 | { 30 | return 3; 31 | } 32 | float multiPass2() 33 | { 34 | return 9.; 35 | } 36 | layout(binding=0)uniform atomic_uint hydrogen; 37 | uint builtin_with_or_without_side_effects(uint x) 38 | { 39 | uint not_inlined=atomicCounterIncrement(hydrogen); 40 | atomicCounterIncrement(hydrogen); 41 | return x+max(x*x,x+1)+not_inlined; 42 | } 43 | float dmin(float a,float b) 44 | { 45 | return a+b+a*b; 46 | } 47 | float reduce_consecutive_assignments(float x) 48 | { 49 | float dmat=dmin(dmin(dmin(dmin(dmin(34.+x,.2),.2),.3),.4),.2); 50 | dmat+=dmat*dmat; 51 | return dmat+x; 52 | } 53 | int dont_inline_lvalue() 54 | { 55 | return 3; 56 | } 57 | vec4 fragColor247; 58 | void main247() 59 | { 60 | fragColor247=vec4(3); 61 | } 62 | vec4 fragColor248; 63 | void main248() 64 | { 65 | fragColor248=vec4(3); 66 | } 67 | float arr[]=float[](3.4,4.2); 68 | void lvalues() 69 | { 70 | arr[1]=2.; 71 | } 72 | uniform int time; 73 | flat in int sync; 74 | int dependOnConst() 75 | { 76 | return(time+sync)*2*3; 77 | } 78 | float noinl179(float x) 79 | { 80 | float old=x; 81 | x=1e2; 82 | return old+x; 83 | } 84 | float inlineWithShadowing(float x) 85 | { 86 | if(x<0.) 87 | { 88 | float inl=3.4; 89 | inl++; 90 | } 91 | return sin(2.5); 92 | } 93 | float inline_uninitialized() 94 | { 95 | float c; 96 | return c; 97 | } 98 | float glo; 99 | float noinline_readsTheGlobal() 100 | { 101 | return glo; 102 | } 103 | float dontCompressAssigments() 104 | { 105 | glo=10.; 106 | glo=50.+noinline_readsTheGlobal(); 107 | return glo*glo; 108 | } 109 | vec3 repro(vec2 fragCoord,float iTime) 110 | { 111 | iTime+=(fragCoord.xy/(fragCoord*2.).xy).x*10.; 112 | vec3 used_many_times=vec3((fragCoord.y+sin(iTime*.5)*.4-fragCoord.x+iTime*.5)*normalize(vec3(0,0,1))),col=used_many_times,sky=col+used_many_times; 113 | vec4 cc=vec4(used_many_times-used_many_times,1); 114 | sky+=pow(max(dot(sky,used_many_times),0.),20.)*.03; 115 | col=vec3(dot(col+mix(sky,cc.xyz,cc.w)+used_many_times,used_many_times)); 116 | return col+pow(max(dot(sky,used_many_times),0.),6.)*.2; 117 | } 118 | vec3 g(float x) 119 | { 120 | float y=x*x; 121 | { 122 | float b=23.*x; 123 | y+=b*b+30.; 124 | } 125 | return vec3(10.*x*x)*2.+vec3(y); 126 | } 127 | vec3 vecs(float x) 128 | { 129 | return vec3(0)+vec3(4,3,4)+vec3(3,3,g(8.)*g(9.)); 130 | } 131 | -------------------------------------------------------------------------------- /tests/unit/inline.expected: -------------------------------------------------------------------------------- 1 | #version 420 2 | 3 | float result; 4 | void main() 5 | { 6 | result=.15; 7 | } 8 | int arithmetic() 9 | { 10 | return 40; 11 | } 12 | int vars(int arg,int arg2) 13 | { 14 | return arg*(arg+arg2); 15 | } 16 | int arithmetic2() 17 | { 18 | return 40; 19 | } 20 | int unusedVars() 21 | { 22 | return 30; 23 | } 24 | int unusedVars2() 25 | { 26 | return 18; 27 | } 28 | int multiPass() 29 | { 30 | return 3; 31 | } 32 | float multiPass2() 33 | { 34 | return 9.; 35 | } 36 | layout(binding=0)uniform atomic_uint hydrogen; 37 | uint builtin_with_or_without_side_effects(uint x) 38 | { 39 | uint not_inlined=atomicCounterIncrement(hydrogen); 40 | atomicCounterIncrement(hydrogen); 41 | return x+max(x*x,x+1)+not_inlined; 42 | } 43 | float dmin(float a,float b) 44 | { 45 | return a+b+a*b; 46 | } 47 | float reduce_consecutive_assignments(float x) 48 | { 49 | float dmat=dmin(dmin(dmin(dmin(dmin(34.+x,.2),.2),.3),.4),.2); 50 | dmat+=dmat*dmat; 51 | return dmat+x; 52 | } 53 | int dont_inline_lvalue() 54 | { 55 | return 3; 56 | } 57 | vec4 fragColor247; 58 | void main247() 59 | { 60 | fragColor247=vec4(3); 61 | } 62 | vec4 fragColor248; 63 | void main248() 64 | { 65 | fragColor248=vec4(3); 66 | } 67 | float arr[]=float[](3.4,4.2); 68 | void lvalues() 69 | { 70 | arr[1]=2.; 71 | } 72 | uniform int time; 73 | flat in int sync; 74 | int dependOnConst() 75 | { 76 | return(time+sync)*2*3; 77 | } 78 | float noinl179(float x) 79 | { 80 | float old=x; 81 | x=1e2; 82 | return old+x; 83 | } 84 | float inlineWithShadowing(float x) 85 | { 86 | if(x<0.) 87 | { 88 | float inl=3.4; 89 | inl++; 90 | } 91 | return sin(2.5); 92 | } 93 | float inline_uninitialized() 94 | { 95 | float c; 96 | return c; 97 | } 98 | float glo; 99 | float noinline_readsTheGlobal() 100 | { 101 | return glo; 102 | } 103 | float dontCompressAssigments() 104 | { 105 | glo=10.; 106 | glo=50.+noinline_readsTheGlobal(); 107 | return glo*glo; 108 | } 109 | vec3 repro(vec2 fragCoord,float iTime) 110 | { 111 | iTime+=(fragCoord.xy/(fragCoord*2.).xy).x*10.; 112 | vec3 used_many_times=vec3((fragCoord.y+sin(iTime*.5)*.4-fragCoord.x+iTime*.5)*normalize(vec3(0,0,1))),col=used_many_times,sky=col+used_many_times,camera=used_many_times; 113 | vec4 cc=vec4(camera-used_many_times,1); 114 | sky+=pow(max(dot(sky,used_many_times),0.),20.)*.03; 115 | col=vec3(dot(col+mix(sky,cc.xyz,cc.w)+camera,used_many_times)); 116 | return col+pow(max(dot(sky,used_many_times),0.),6.)*.2; 117 | } 118 | vec3 g(float x) 119 | { 120 | float y=x*x; 121 | { 122 | float b=23.*x; 123 | y+=b*b+30.; 124 | } 125 | return vec3(10.*x*x)*2.+vec3(y); 126 | } 127 | vec3 vecs(float x) 128 | { 129 | return vec3(0)+vec3(4,3,4)+vec3(3,3,g(8.)*g(9.)); 130 | } 131 | -------------------------------------------------------------------------------- /tests/unit/inline.frag: -------------------------------------------------------------------------------- 1 | #version 420 2 | 3 | float result; 4 | 5 | void main() 6 | { 7 | float x = 0.5; 8 | float i_y = 0.6*x; 9 | float a = x * i_y; 10 | result = a; 11 | } 12 | 13 | int arithmetic() 14 | { 15 | int i_a = 2; 16 | int i_b = 3; 17 | int i_c = i_a + i_b; 18 | return 4 * i_a * i_c; 19 | } 20 | 21 | int vars(int arg, int arg2) 22 | { 23 | int i_a = arg; 24 | int i_b = arg2; 25 | int i_c = i_a + i_b; 26 | return i_a * i_c; 27 | } 28 | 29 | int arithmetic2() 30 | { 31 | int a = 2; 32 | int b = 3; 33 | int c = a + b; 34 | return 4 * a * c; 35 | } 36 | 37 | int unusedVars() { 38 | int a = arithmetic(); 39 | int b = 13; 40 | int c = 10; 41 | int d = c * 3; 42 | return d; 43 | } 44 | 45 | int unusedVars2() { 46 | int var1 = 1, var2 = 2, var3 = 3, var4 = 4, var5 = 5, var6 = 6; 47 | int var7 = 7, var8 = 8, var9 = 9, var10 = 10, var11 = 11, var12 = 12; 48 | return var1 + var5 + var12; 49 | } 50 | 51 | int multiPass() 52 | { 53 | int one = 1; 54 | int two = one * 2; 55 | int three = two + 1; 56 | return three; 57 | } 58 | 59 | float multiPass2() { 60 | float i_a = 4.0; 61 | float b = i_a + 5.0; 62 | return b; 63 | } 64 | 65 | layout(binding=0) uniform atomic_uint hydrogen; 66 | uint builtin_with_or_without_side_effects(uint x) 67 | { 68 | uint not_inlined = atomicCounterIncrement(hydrogen); 69 | uint inlined = max(x * x, x + 1); 70 | atomicCounterIncrement(hydrogen); 71 | return x + inlined + not_inlined; 72 | } 73 | 74 | float dmin(float a, float b) 75 | { 76 | return a+b+a*b; 77 | } 78 | float reduce_consecutive_assignments(float x) 79 | { 80 | float dmat=34.+x; 81 | dmat=dmin(dmat,.2); 82 | dmat=dmin(dmat,.2); 83 | dmat=dmin(dmat,.3); 84 | dmat=dmin(dmat,.4); 85 | dmat=dmin(dmat,.2); 86 | dmat=dmat*dmat+dmat; 87 | return dmat+x; 88 | } 89 | 90 | // repro for #176 91 | int dont_inline_lvalue() { 92 | int a = 1; 93 | a = 2; 94 | return 3; 95 | } 96 | 97 | // repro for #247 98 | vec4 fragColor247; 99 | const float t247 = 1.5+(1.+.5); 100 | void main247() { 101 | fragColor247 = vec4(t247); 102 | } 103 | 104 | // repro for #248 105 | vec4 fragColor248; 106 | void main248() { 107 | float t = 1.5+(1.+.5); 108 | fragColor248 = vec4(t); 109 | } 110 | 111 | float arr[] = float[](3.4, 4.2); 112 | void lvalues() { 113 | int a = 1; 114 | arr[a] = 2.; 115 | } 116 | 117 | uniform int time; 118 | flat in int sync; 119 | 120 | int dependOnConst() { 121 | int x = time + sync; 122 | int y = x * 2; 123 | return y*3; 124 | } 125 | 126 | // repro for #179 127 | float noinl179(float x) { 128 | float old = x; 129 | x = 100.0; 130 | return old + x; 131 | } 132 | 133 | // repro for a bug 134 | float inlineWithShadowing(float x) { 135 | float inl = sin(2.5); 136 | if (x < 0.) 137 | { 138 | float inl = 3.4; 139 | inl++; 140 | } 141 | return inl; 142 | } 143 | 144 | // repro for a bug 145 | float inline_uninitialized() 146 | { 147 | // https://github.com/laurentlb/shader-minifier/issues/317 148 | // Error: 'c' : undeclared identifier 149 | float c; 150 | return c; 151 | } 152 | 153 | // repro for a bug 154 | float glo; 155 | float noinline_readsTheGlobal() 156 | { 157 | return glo; 158 | } 159 | float dontCompressAssigments() 160 | { 161 | glo = 10.; 162 | glo = 50. + noinline_readsTheGlobal(); 163 | return glo*glo; 164 | } 165 | 166 | // repro for dual-kind-mixing aggressive-inlining bug 167 | vec3 repro(vec2 fragCoord, float iTime) 168 | { 169 | float time = iTime*1.+(fragCoord.xy / (fragCoord*2.).xy).x*10.0; 170 | 171 | vec3 long_and_used_only_once = vec3((fragCoord.y+sin(time*.5)*.4 - fragCoord.x+time*.5)*normalize(vec3(0,0, 1.))); 172 | vec3 used_many_times = long_and_used_only_once; 173 | 174 | vec3 col = used_many_times; 175 | vec3 sky = col + used_many_times; 176 | vec3 camera = used_many_times; 177 | vec4 cc = vec4(camera - used_many_times, 1.); 178 | sky+= pow(max(dot(sky, used_many_times), 0.0), 20.0) * .03; 179 | col = vec3(dot(col + mix(sky, cc.xyz, cc.w) + camera, used_many_times)); 180 | return col + pow(max(dot(sky, used_many_times), 0.0), 6.0) * .2; 181 | } 182 | 183 | vec3 g(float x) 184 | { 185 | float y = x * x; 186 | vec3 b = vec3(10.0 * x * x); // b should be inlined (used only once) 187 | vec3 c = vec3(10.0, 20.0, 30.0); 188 | { 189 | float b = 23.0 * x; // even though there is another b in a sub block 190 | y += b * b + c.z; 191 | } 192 | return b * 2.0 + vec3(y); 193 | } 194 | 195 | vec3 vecs(float x) 196 | { 197 | return vec4(0.,0.,0.,1.25).xyz 198 | + vec2(3,4).yxy 199 | + vec4(1,2,3,g(8.)*g(9.)).zzw; 200 | } 201 | -------------------------------------------------------------------------------- /tests/unit/inline.no.expected: -------------------------------------------------------------------------------- 1 | #version 420 2 | 3 | float result; 4 | void main() 5 | { 6 | float x=.5; 7 | x*=.6*x; 8 | result=x; 9 | } 10 | int arithmetic() 11 | { 12 | return 40; 13 | } 14 | int vars(int arg,int arg2) 15 | { 16 | return arg*(arg+arg2); 17 | } 18 | int arithmetic2() 19 | { 20 | int a=2,b=3; 21 | b+=a; 22 | return 4*a*b; 23 | } 24 | int unusedVars() 25 | { 26 | int a=arithmetic(),b=13; 27 | a=10; 28 | return a*3; 29 | } 30 | int unusedVars2() 31 | { 32 | int var1=1,var2=2,var3=3,var4=4,var5=5,var6=6,var7=7; 33 | var7=8; 34 | var6=9; 35 | var4=10; 36 | var3=11; 37 | var2=12; 38 | return var1+var5+var2; 39 | } 40 | int multiPass() 41 | { 42 | int one=2; 43 | return one+1; 44 | } 45 | float multiPass2() 46 | { 47 | return 9.; 48 | } 49 | layout(binding=0)uniform atomic_uint hydrogen; 50 | uint builtin_with_or_without_side_effects(uint x) 51 | { 52 | uint not_inlined=atomicCounterIncrement(hydrogen),inlined=max(x*x,x+1); 53 | atomicCounterIncrement(hydrogen); 54 | return x+inlined+not_inlined; 55 | } 56 | float dmin(float a,float b) 57 | { 58 | return a+b+a*b; 59 | } 60 | float reduce_consecutive_assignments(float x) 61 | { 62 | float dmat=dmin(dmin(dmin(dmin(dmin(34.+x,.2),.2),.3),.4),.2); 63 | dmat+=dmat*dmat; 64 | return dmat+x; 65 | } 66 | int dont_inline_lvalue() 67 | { 68 | int a=2; 69 | return 3; 70 | } 71 | vec4 fragColor247; 72 | const float t247=3.; 73 | void main247() 74 | { 75 | fragColor247=vec4(t247); 76 | } 77 | vec4 fragColor248; 78 | void main248() 79 | { 80 | float t=3.; 81 | fragColor248=vec4(t); 82 | } 83 | float arr[]=float[](3.4,4.2); 84 | void lvalues() 85 | { 86 | int a=1; 87 | arr[a]=2.; 88 | } 89 | uniform int time; 90 | flat in int sync; 91 | int dependOnConst() 92 | { 93 | int x=(time+sync)*2; 94 | return x*3; 95 | } 96 | float noinl179(float x) 97 | { 98 | float old=x; 99 | x=1e2; 100 | return old+x; 101 | } 102 | float inlineWithShadowing(float x) 103 | { 104 | float inl=sin(2.5); 105 | if(x<0.) 106 | { 107 | float inl=3.4; 108 | inl++; 109 | } 110 | return inl; 111 | } 112 | float inline_uninitialized() 113 | { 114 | float c; 115 | return c; 116 | } 117 | float glo; 118 | float noinline_readsTheGlobal() 119 | { 120 | return glo; 121 | } 122 | float dontCompressAssigments() 123 | { 124 | glo=10.; 125 | glo=50.+noinline_readsTheGlobal(); 126 | return glo*glo; 127 | } 128 | vec3 repro(vec2 fragCoord,float iTime) 129 | { 130 | iTime+=(fragCoord.xy/(fragCoord*2.).xy).x*10.; 131 | vec3 long_and_used_only_once=vec3((fragCoord.y+sin(iTime*.5)*.4-fragCoord.x+iTime*.5)*normalize(vec3(0,0,1))),used_many_times=long_and_used_only_once,col=used_many_times,sky=col+used_many_times; 132 | long_and_used_only_once=used_many_times; 133 | vec4 cc=vec4(long_and_used_only_once-used_many_times,1); 134 | sky+=pow(max(dot(sky,used_many_times),0.),20.)*.03; 135 | col=vec3(dot(col+mix(sky,cc.xyz,cc.w)+long_and_used_only_once,used_many_times)); 136 | return col+pow(max(dot(sky,used_many_times),0.),6.)*.2; 137 | } 138 | vec3 g(float x) 139 | { 140 | float y=x*x; 141 | vec3 b=vec3(10.*x*x),c=vec3(10,20,30); 142 | { 143 | float b=23.*x; 144 | y+=b*b+c.z; 145 | } 146 | return b*2.+vec3(y); 147 | } 148 | vec3 vecs(float x) 149 | { 150 | return vec3(0)+vec3(4,3,4)+vec3(3,3,g(8.)*g(9.)); 151 | } 152 | -------------------------------------------------------------------------------- /tests/unit/inout.expected: -------------------------------------------------------------------------------- 1 | // Generated with (https://github.com/laurentlb/Shader_Minifier/) 2 | #ifndef SHADER_MINIFIER_IMPL 3 | #ifndef SHADER_MINIFIER_HEADER 4 | # define SHADER_MINIFIER_HEADER 5 | # define VAR_ambientLight "f" 6 | # define VAR_diffuseColor "p" 7 | # define VAR_emissiveColor "z" 8 | # define VAR_fragmentColor "r" 9 | # define VAR_mediumDensity "c" 10 | # define VAR_normal "m" 11 | # define VAR_specularColor "C" 12 | # define VAR_texture0 "v" 13 | # define VAR_viewVec "d" 14 | #endif 15 | 16 | #else // if SHADER_MINIFIER_IMPL 17 | 18 | // tests/unit/inout.frag 19 | "#version 330\n" 20 | "uniform samplerCube v;" 21 | "in vec3 m,d;" 22 | "out vec4 r;" 23 | "void main()" 24 | "{" 25 | "vec3 c=normalize(d),t=normalize(m);" 26 | "r=vec4(mix(vec3(.1,.2,.3)*texture(v,refract(-c,t,1./1.5)).xyz,texture(v,reflect(-c,t)).xyz,.1),1);" 27 | "}" 28 | "vec3 t(vec3 v,vec3 m,vec3 t)" 29 | "{" 30 | "float r=1.-clamp(dot(m,t),0.,1.);" 31 | "return r*r*r*r*r*(1.-v)+v;" 32 | "}" 33 | "vec3 t(vec3 v,vec3 m,vec3 r,vec3 c,vec3 d,float f)" 34 | "{" 35 | "m=normalize(v+m);" 36 | "f=1.+2048.*(1.-f)*(1.-f);" 37 | "return mix(c,vec3(pow(clamp(dot(m,r),0.,1.),f)*(f+4.)/8.),t(d,v,m));" 38 | "}", 39 | 40 | // tests/unit/inout2.frag 41 | "#version 330\n" 42 | "uniform samplerCube v;" 43 | "uniform float c;" 44 | "uniform vec3 f,p,z,C;" 45 | "in vec3 m,d;" 46 | "out vec4 r;" 47 | "vec3 t(vec3 v,vec3 m,vec3 t)" 48 | "{" 49 | "float r=1.-clamp(dot(m,t),0.,1.);" 50 | "return r*r*r*r*r*(1.-v)+v;" 51 | "}" 52 | "void main()" 53 | "{" 54 | "r=vec4(z+mix(p*f,f,.5),1);" 55 | "}" 56 | "vec3 t(vec3 v,vec3 m,vec3 f,vec3 c,vec3 d,float r)" 57 | "{" 58 | "m=normalize(v+m);" 59 | "r=1.+2048.*(1.-r)*(1.-r);" 60 | "return mix(c,vec3(pow(clamp(dot(m,f),0.,1.),r)*(r+4.)/8.),t(d,v,m));" 61 | "}", 62 | 63 | #endif 64 | -------------------------------------------------------------------------------- /tests/unit/inout.frag: -------------------------------------------------------------------------------- 1 | // Multifile test, part 1 2 | 3 | // The test is to ensure that exported variables are renamed in the same way 4 | // across multiple files. 5 | 6 | #version 330 7 | 8 | // These 4 variables should have the same name as in the other file. 9 | uniform samplerCube texture0; 10 | 11 | in vec3 normal; 12 | in vec3 viewVec; 13 | 14 | out vec4 fragmentColor; 15 | 16 | void main() 17 | { 18 | vec3 E = normalize(viewVec); 19 | vec3 N = normalize(normal); 20 | vec3 albedo = vec3(0.1, 0.2, 0.3); 21 | vec3 f0 = vec3(0.5, 0.5, 0.5); 22 | 23 | float IoR = 1.5; 24 | vec3 reflection = texture(texture0, reflect(-E, N)).rgb; 25 | vec3 refraction = texture(texture0, refract(-E, N, 1./IoR)).rgb; 26 | 27 | vec3 color = mix(albedo * refraction, reflection, 0.1); 28 | fragmentColor = vec4(color, 1.); 29 | } 30 | 31 | // These functions are same as in the other file. Ideally (for better compression), 32 | // the local variables and arguments should remain the same. 33 | vec3 Schlick(vec3 f0, vec3 E, vec3 H) 34 | { 35 | float x = 1. - clamp(dot(E, H), 0., 1.); 36 | return x*x*x*x*x * (1. - f0) + f0; 37 | } 38 | 39 | vec3 BlinnPhong(vec3 E, vec3 L, vec3 N, vec3 albedo, vec3 f0, float roughness) 40 | { 41 | vec3 H = normalize(E + L); 42 | float alpha = 1. + 2048. * (1. - roughness)*(1. - roughness); 43 | 44 | vec3 diffuse = albedo; 45 | vec3 specular = vec3(pow(clamp(dot(H, N), 0., 1.), alpha) * (alpha + 4.) / 8.); 46 | vec3 fresnel = Schlick(f0, E, H); 47 | 48 | return mix(diffuse, specular, fresnel); 49 | } 50 | -------------------------------------------------------------------------------- /tests/unit/inout2.frag: -------------------------------------------------------------------------------- 1 | // Multifile test, part 2 2 | 3 | #version 330 4 | 5 | uniform samplerCube texture0; 6 | 7 | uniform float mediumDensity; 8 | uniform vec3 ambientLight; 9 | uniform vec3 diffuseColor; 10 | uniform vec3 emissiveColor; 11 | uniform vec3 specularColor; 12 | 13 | in vec3 normal; 14 | in vec3 viewVec; 15 | 16 | out vec4 fragmentColor; 17 | 18 | vec3 Schlick(vec3 f0, vec3 E, vec3 H) 19 | { 20 | float x = 1. - clamp(dot(E, H), 0., 1.); 21 | return x*x*x*x*x * (1. - f0) + f0; 22 | } 23 | 24 | void main() 25 | { 26 | vec3 E = normalize(viewVec); 27 | vec3 N = normalize(normal); 28 | vec3 albedo = diffuseColor; 29 | vec3 f0 = specularColor; 30 | float schlick = 0.5; 31 | 32 | vec3 color = emissiveColor + mix(albedo * ambientLight, ambientLight, schlick); 33 | fragmentColor = vec4(color, 1.); 34 | } 35 | 36 | vec3 BlinnPhong(vec3 E, vec3 L, vec3 N, vec3 albedo, vec3 f0, float roughness) 37 | { 38 | vec3 H = normalize(E + L); 39 | float alpha = 1. + 2048. * (1. - roughness)*(1. - roughness); 40 | 41 | vec3 diffuse = albedo; 42 | vec3 specular = vec3(pow(clamp(dot(H, N), 0., 1.), alpha) * (alpha + 4.) / 8.); 43 | vec3 fresnel = Schlick(f0, E, H); 44 | 45 | return mix(diffuse, specular, fresnel); 46 | } 47 | -------------------------------------------------------------------------------- /tests/unit/interface-block-renaming.expected: -------------------------------------------------------------------------------- 1 | // Generated with (https://github.com/laurentlb/Shader_Minifier/) 2 | #ifndef SHADER_MINIFIER_IMPL 3 | #ifndef SHADER_MINIFIER_HEADER 4 | # define SHADER_MINIFIER_HEADER 5 | # define VAR_field "U" 6 | #endif 7 | 8 | #else // if SHADER_MINIFIER_IMPL 9 | 10 | // tests/unit/interface-block-renaming1.frag 11 | "#version 460\n" 12 | "uniform Uniform1{vec4 U;};", 13 | 14 | // tests/unit/interface-block-renaming2.frag 15 | "#version 460\n" 16 | "uniform Uniform1{vec4 U;};", 17 | 18 | #endif 19 | -------------------------------------------------------------------------------- /tests/unit/interface-block-renaming1.frag: -------------------------------------------------------------------------------- 1 | #version 460 2 | // https://github.com/laurentlb/shader-minifier/issues/430 3 | uniform Uniform1 { vec4 field; }; 4 | //uniform Uniform2 { vec4 field; } instance; // TODO 5 | -------------------------------------------------------------------------------- /tests/unit/interface-block-renaming2.frag: -------------------------------------------------------------------------------- 1 | #version 460 2 | // https://github.com/laurentlb/shader-minifier/issues/430 3 | uniform Uniform1 { vec4 field; }; 4 | //uniform Uniform2 { vec4 field; } instance; // TODO 5 | -------------------------------------------------------------------------------- /tests/unit/interface_block.frag: -------------------------------------------------------------------------------- 1 | #version 140 2 | 3 | uniform MyBlock 4 | { 5 | vec3 color; // treated as a global variable 6 | float alpha; 7 | }; 8 | 9 | void mainImage(out vec4 fragColor, in vec2 fragCoord) 10 | { 11 | fragColor = vec4(color, alpha); 12 | } 13 | -------------------------------------------------------------------------------- /tests/unit/interface_block.frag.expected: -------------------------------------------------------------------------------- 1 | #version 140 2 | 3 | uniform MyBlock{vec3 M;float v;}; 4 | void mainImage(out vec4 m,vec2 B) 5 | { 6 | m=vec4(M,v); 7 | } 8 | -------------------------------------------------------------------------------- /tests/unit/keyword_prefix.frag: -------------------------------------------------------------------------------- 1 | void do_something() {} 2 | 3 | void f() { 4 | do_something(); 5 | } 6 | -------------------------------------------------------------------------------- /tests/unit/keyword_prefix.frag.expected: -------------------------------------------------------------------------------- 1 | /* File generated with Shader Minifier 1.1.6 2 | * http://www.ctrl-alt-test.fr 3 | */ 4 | #ifndef KEYWORD_PREFIX_FRAG_EXPECTED_ 5 | # define KEYWORD_PREFIX_FRAG_EXPECTED_ 6 | 7 | const char *keyword_prefix_frag = 8 | "void d()" 9 | "{}" 10 | "void i()" 11 | "{" 12 | "d();" 13 | "}"; 14 | 15 | #endif // KEYWORD_PREFIX_FRAG_EXPECTED_ 16 | -------------------------------------------------------------------------------- /tests/unit/layout.comp: -------------------------------------------------------------------------------- 1 | #version 430 2 | 3 | layout(local_size_x = 32) in; // #22 4 | -------------------------------------------------------------------------------- /tests/unit/layout.frag: -------------------------------------------------------------------------------- 1 | #version 330 2 | 3 | // #486 4 | layout( location = 1 ) out vec4 f_color2; 5 | 6 | // #17 7 | layout(location=0) out vec4 f_color; 8 | //subroutine float functionType(int i); 9 | //layout(location = 0) subroutine uniform functionType tbl[2]; 10 | //layout(index = 1) subroutine (functionType) float func1(int i) { return i * 1.0/255.0; } 11 | //layout(index = 2) subroutine (functionType) float func2(int i) { return 1.0 - i * 1.0/255.0; } 12 | -------------------------------------------------------------------------------- /tests/unit/layout.frag.expected: -------------------------------------------------------------------------------- 1 | #version 330 2 | 3 | layout(location=1)out vec4 f_color2; 4 | layout(location=0)out vec4 f_color; 5 | -------------------------------------------------------------------------------- /tests/unit/layout.geom: -------------------------------------------------------------------------------- 1 | #version 150 2 | 3 | layout(triangles) in; // #29 4 | layout(triangle_strip, max_vertices = 3) out; // #29 5 | -------------------------------------------------------------------------------- /tests/unit/loop.frag: -------------------------------------------------------------------------------- 1 | float f(inout float noinlinevar){return 0.;} 2 | 3 | float a; 4 | void main() 5 | { 6 | float c; 7 | for (float d=0.; d<50.; ++d) 8 | { 9 | c+=cos(d); 10 | } 11 | float b; 12 | for (b=0.; b<50.; ++b) 13 | { 14 | c+=cos(c); 15 | } 16 | b = a; 17 | while (b<50.) 18 | { 19 | c+=cos(c); 20 | b++; 21 | } 22 | b = a; 23 | while (b<50.) 24 | { 25 | b++; 26 | } 27 | b = a; 28 | while (b<50.) 29 | { 30 | c+=cos(c); 31 | float arg; float d=f(arg); // d prevents moving b+=d to a for 32 | b+=d; 33 | } 34 | b = a; 35 | while (b<50.) 36 | { 37 | if (a < b) continue; // continue prevents moving b++ to a for 38 | b++; 39 | } 40 | b = a; 41 | while (b<50.) 42 | { 43 | if (a < b) a=b; else continue; // continue prevents moving b++ to a for 44 | b++; 45 | } 46 | b = a; 47 | while (b<50.) 48 | { 49 | a += b; 50 | { 51 | float a = b-a; 52 | if (a < b) a=b; else continue; // continue prevents moving b++ to a for 53 | } 54 | b++; 55 | } 56 | for (; b<50.; ++b) 57 | { 58 | c+=cos(b); 59 | } 60 | do 61 | b++; 62 | while (b<100.); 63 | do { 64 | if (a>10.)b++; 65 | b+=a; 66 | } while (b<100.); 67 | } 68 | -------------------------------------------------------------------------------- /tests/unit/loop.frag.expected: -------------------------------------------------------------------------------- 1 | // Generated with (https://github.com/laurentlb/Shader_Minifier/) 2 | #ifndef LOOP_FRAG_EXPECTED_ 3 | # define LOOP_FRAG_EXPECTED_ 4 | 5 | const char *loop_frag = 6 | "float f(inout float noinlinevar)" 7 | "{" 8 | "return 0.;" 9 | "}" 10 | "float a;" 11 | "void main()" 12 | "{" 13 | "float c;" 14 | "for(float d=0.;d<50.;++d)" 15 | "c+=cos(d);" 16 | "float b;" 17 | "for(b=0.;b<50.;++b)" 18 | "c+=cos(c);" 19 | "for(b=a;b<50.;b++)" 20 | "c+=cos(c);" 21 | "for(b=a;b<50.;b++)" 22 | ";" 23 | "for(b=a;b<50.;)" 24 | "{" 25 | "c+=cos(c);" 26 | "float arg;" 27 | "arg=f(arg);" 28 | "b+=arg;" 29 | "}" 30 | "for(b=a;b<50.;)" 31 | "{" 32 | "if(a10.)" 64 | "b++;" 65 | "b+=a;" 66 | "}" 67 | "while(b<1e2);" 68 | "}"; 69 | 70 | #endif // LOOP_FRAG_EXPECTED_ 71 | -------------------------------------------------------------------------------- /tests/unit/macros.expected: -------------------------------------------------------------------------------- 1 | // Generated with (https://github.com/laurentlb/Shader_Minifier/) 2 | #ifndef MACROS_EXPECTED_ 3 | # define MACROS_EXPECTED_ 4 | 5 | const char *macros_frag = 6 | "#define a $\n" 7 | "#define b ($+)\n" 8 | "#define c $+\n" 9 | "#define d abc def+ghi()\n" 10 | "#define e $\n" 11 | "#define f $\n" 12 | "#define g $\n" 13 | "#define h $\n" 14 | "#define i $\n" 15 | "#define j $\n" 16 | "#define k $\n" 17 | "#define l $\n" 18 | "#define m $\n" 19 | "#define n $\n" 20 | "#define o $\n" 21 | "#define p $\n" 22 | "int E()" 23 | "{" 24 | "int E=1,r=2,C=3,B=4,A=5,D=6,F=7;" 25 | "F=8;" 26 | "D=9;" 27 | "B=10;" 28 | "C=11;" 29 | "r=12;" 30 | "return E+A+r;" 31 | "}"; 32 | 33 | #endif // MACROS_EXPECTED_ 34 | -------------------------------------------------------------------------------- /tests/unit/macros.frag: -------------------------------------------------------------------------------- 1 | // Define a bunch of macros. Make sure Shader Minifier doesn't use 2 | // these names when renaming variables. 3 | // Also, test that the spaces are stripped. 4 | #define a $ 5 | #define b ( $+) 6 | #define c $ + 7 | #define d abc def + ghi () 8 | #define e $ 9 | #define f $ 10 | #define g $ 11 | #define h $ 12 | #define i $ 13 | #define j $ 14 | #define k $ 15 | #define l $ 16 | #define m $ 17 | #define n $ 18 | #define o $ 19 | #define p $ 20 | 21 | int foo() { 22 | int var1 = 1, var2 = 2, var3 = 3, var4 = 4, var5 = 5, var6 = 6; 23 | int var7 = 7, var8 = 8, var9 = 9, var10 = 10, var11 = 11, var12 = 12; 24 | return var1 + var5 + var12; 25 | } 26 | -------------------------------------------------------------------------------- /tests/unit/many_variables.expected: -------------------------------------------------------------------------------- 1 | // Generated with (https://github.com/laurentlb/Shader_Minifier/) 2 | #ifndef SHADER_MINIFIER_IMPL 3 | #ifndef SHADER_MINIFIER_HEADER 4 | # define SHADER_MINIFIER_HEADER 5 | #endif 6 | 7 | #else // if SHADER_MINIFIER_IMPL 8 | 9 | // tests/unit/many_variables.frag 10 | "int L(float i,float L,float J,float I,float H,float G,float F,float E,float D,float C,float B,float A)" 11 | "{" 12 | "i=G;" 13 | "int t=1,f=2,r=3,K=4;" 14 | "K=5;" 15 | "r=6;" 16 | "f=7;" 17 | "t=8;" 18 | "i=A;" 19 | "f=4;" 20 | "f=5;" 21 | "int M=6,N=7,O=8;" 22 | "float P=0.;" 23 | "int Q=1,R=2,S=3,T=4,U=5,V=6,W=7,X=8;" 24 | "float Y=0.;" 25 | "int Z=1,_=2,a=3,b=4,c=5,d=6,e=7,g=8;" 26 | "return t+O+X+g;" 27 | "}", 28 | 29 | #endif 30 | -------------------------------------------------------------------------------- /tests/unit/many_variables.frag: -------------------------------------------------------------------------------- 1 | // Lots of identifiers to force Shader Minifier to use 2-char idents. 2 | 3 | int fct(float a, float b, float c, float d, float e, float f, 4 | float g, float h, float i, float j, float k, float l) { 5 | float m = a, n = b, o = c, p = d, q = e, r = f; 6 | int v1 = 1, v2 = 2, v3 = 3, v4 = 4, v5 = 5, v6 = 6, v7 = 7, v8 = 8; 7 | float s = g, t = h, u = i, v = j, w = k, x = l; 8 | int a1 = 1, a2 = 2, a3 = 3, a4 = 4, a5 = 5, a6 = 6, a7 = 7, a8 = 8; 9 | float y = 0.; 10 | int b1 = 1, b2 = 2, b3 = 3, b4 = 4, b5 = 5, b6 = 6, b7 = 7, b8 = 8; 11 | float z = 0.; 12 | int c1 = 1, c2 = 2, c3 = 3, c4 = 4, c5 = 5, c6 = 6, c7 = 7, c8 = 8; 13 | return v8 + a8 + b8 + c8; 14 | } 15 | -------------------------------------------------------------------------------- /tests/unit/minus-zero.expected: -------------------------------------------------------------------------------- 1 | // Generated with (https://github.com/laurentlb/Shader_Minifier/) 2 | #ifndef SHADER_MINIFIER_IMPL 3 | #ifndef SHADER_MINIFIER_HEADER 4 | # define SHADER_MINIFIER_HEADER 5 | #endif 6 | 7 | #else // if SHADER_MINIFIER_IMPL 8 | 9 | // tests/unit/minus-zero.frag 10 | "void main()" 11 | "{" 12 | "float a=0.;" 13 | "}", 14 | 15 | #endif 16 | -------------------------------------------------------------------------------- /tests/unit/minus-zero.frag: -------------------------------------------------------------------------------- 1 | void main() 2 | { 3 | float a = -0.0; 4 | } 5 | -------------------------------------------------------------------------------- /tests/unit/nested_if.frag: -------------------------------------------------------------------------------- 1 | float getNum(float a) { 2 | // else statement, so curly braces are required 3 | if (a > 0.0) { 4 | if (a > 1.0) return 1.0; 5 | } 6 | else return 0.0; 7 | return a; 8 | } 9 | 10 | int nested(bool x, bool y) { 11 | if (x) { 12 | // no else statement, so curly braces can be removed 13 | if (y) { 14 | return 0; 15 | } 16 | } 17 | return 2; 18 | } 19 | 20 | int no_braces1(int x) { 21 | if (x < 0) { 22 | for (;;) 23 | if (x > 0) { 24 | return 0; 25 | } else { 26 | return 1; 27 | } 28 | } else { 29 | return 2; 30 | } 31 | } 32 | 33 | int dangling_else(int x) { 34 | if (x < 0) { 35 | for (;;) 36 | if (x > 0) { 37 | return 0; 38 | } else { 39 | if (x == 0) return 1; // dangling 40 | } 41 | } else { 42 | return 2; 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /tests/unit/nested_if.frag.expected: -------------------------------------------------------------------------------- 1 | float getNum(float a) 2 | { 3 | if(a>0.) 4 | { 5 | if(a>1.) 6 | return 1.; 7 | } 8 | else 9 | return 0.; 10 | return a; 11 | } 12 | int nested(bool x,bool y) 13 | { 14 | if(x) 15 | if(y) 16 | return 0; 17 | return 2; 18 | } 19 | int no_braces1(int x) 20 | { 21 | if(x<0) 22 | for(;;) 23 | if(x>0) 24 | return 0; 25 | else 26 | return 1; 27 | else 28 | return 2; 29 | } 30 | int dangling_else(int x) 31 | { 32 | if(x<0) 33 | { 34 | for(;;) 35 | if(x>0) 36 | return 0; 37 | else if(x==0) 38 | return 1; 39 | } 40 | else 41 | return 2; 42 | } 43 | -------------------------------------------------------------------------------- /tests/unit/numbers.frag: -------------------------------------------------------------------------------- 1 | #version 130 2 | 3 | uint large() { return 3812015801U; } 4 | 5 | vec4 f() 6 | { 7 | float oct = float(042) / 1000.; 8 | float oct2 = float(-071) / 1000.; 9 | int dec = 65535; 10 | int dec2 = -65536; 11 | float n = oct - oct2 + float(4 * 0x0) + float(dec + dec2) / 20.; 12 | return vec4(n,n,n,0.); 13 | } 14 | -------------------------------------------------------------------------------- /tests/unit/numbers.frag.expected: -------------------------------------------------------------------------------- 1 | #version 130 2 | 3 | uint large() 4 | { 5 | return 3812015801U; 6 | } 7 | vec4 f() 8 | { 9 | float n=float(34)/1e3-float(-57)/1e3+float(0)+float(-1)/20.; 10 | return vec4(n,n,n,0); 11 | } 12 | -------------------------------------------------------------------------------- /tests/unit/operators.expected: -------------------------------------------------------------------------------- 1 | // Generated with (https://github.com/laurentlb/Shader_Minifier/) 2 | #ifndef SHADER_MINIFIER_IMPL 3 | #ifndef SHADER_MINIFIER_HEADER 4 | # define SHADER_MINIFIER_HEADER 5 | #endif 6 | 7 | #else // if SHADER_MINIFIER_IMPL 8 | 9 | // tests/unit/operators.frag 10 | "#version 330\n" 11 | "float notmain()" 12 | "{" 13 | "int a=11,b=7,c=2;" 14 | "float f=1.4/3.,g=mod(8.,3.),z=122121;" 15 | "return a+b+c+f+g+z;" 16 | "}" 17 | "int no_parens(int a,int b,int c)" 18 | "{" 19 | "return a+b+c+a+b*c;" 20 | "}" 21 | "int no_parens2(int a,int b,int c)" 22 | "{" 23 | "int d=b*c*a;" 24 | "return a-b+1-d+c;" 25 | "}" 26 | "int other(int a,int b,int c,int d)" 27 | "{" 28 | "return a*b*(c*d)*(a*b);" 29 | "}" 30 | "float f(float x)" 31 | "{" 32 | "x=(x+=1.,length(vec3(x)));" 33 | "return x*x*sin((x*=x,x));" 34 | "}" 35 | "float desugar_compound_assignment_for_ternary(float x)" 36 | "{" 37 | "x+=x*x;" 38 | "x=x==sqrt(x)?" 39 | "x+cos(x):" 40 | "x*sin(x);" 41 | "return x*x;" 42 | "}" 43 | "float cool_ops(float g)" 44 | "{" 45 | "g=0.;" 46 | "g+=g+++ ++g;" 47 | "g/=-g+g;" 48 | "g-=-g--- --g;" 49 | "g*=g+g;" 50 | "return g+--g-++g;" 51 | "}" 52 | "float swap_op_order(float g)" 53 | "{" 54 | "float a=g*(g--*g--),b=g*((g+2.)*(g+3.));" 55 | "return a*b*g;" 56 | "}" 57 | "mat2 dont_swap_op_order(float g)" 58 | "{" 59 | "return mat3x2(g)*(mat4x3(g)*mat2x4(g));" 60 | "}", 61 | 62 | #endif 63 | -------------------------------------------------------------------------------- /tests/unit/operators.frag: -------------------------------------------------------------------------------- 1 | #version 330 2 | 3 | float notmain() 4 | { 5 | int a = 1 + 2 * 3 + 4; 6 | int b = 14 / 2; 7 | int c = 8 % 3; 8 | 9 | float f = 1.23456 * 2.1234; 10 | f = 1.4 / 2.; 11 | f = 1.4 / 3.; 12 | float g = mod(8., 3.); 13 | 14 | float z = 15 | (1. < 2. ? 1 : 2) + 16 | (1. > 2. ? 1 : 2) * 10 + 17 | (1. <= 2. ? 1 : 2) * 100 + 18 | (1. >= 2. ? 1 : 2) * 1000 + 19 | (1. == 2. ? 1 : 2) * 10000 + 20 | (1. != 2. ? 1 : 2) * 100000; 21 | 22 | return a+b+c+f+g+z; 23 | } 24 | 25 | int no_parens(int a, int b, int c) { 26 | return a + (b + c) + a + (b * c); 27 | } 28 | 29 | int no_parens2(int a, int b, int c) { 30 | int d = a*(b*c); 31 | return a - (b - 1) - (d - c); 32 | } 33 | 34 | int other(int a, int b, int c, int d) { 35 | return (a*b)*(c*d)*(a*b); 36 | } 37 | 38 | float f(float x) 39 | { 40 | float a = (x += 1.0, length(vec3(x))); 41 | return a*a*sin((a*=a, a)); 42 | } 43 | 44 | float desugar_compound_assignment_for_ternary(float x) 45 | { 46 | x += x * x; 47 | if (x == sqrt(x)) 48 | x += cos(x); 49 | else 50 | x *= sin(x); 51 | return x * x; 52 | } 53 | 54 | float cool_ops(float g) 55 | { 56 | float f = 0.0; 57 | f += +f++ + ++f; 58 | f /= -f - -f; 59 | f -= -f-- - --f; 60 | f *= +f + +f; 61 | f += --f + (- +(++f)); 62 | return f; 63 | } 64 | 65 | float swap_op_order(float g) 66 | { 67 | float a = g*((g--)*(g--)); 68 | float b = g*((g+2.)*(g+3.)); 69 | return a*b*g; 70 | } 71 | 72 | mat2 dont_swap_op_order(float g) 73 | { 74 | return mat3x2(g) * (mat4x3(g) * mat2x4(g)); 75 | } 76 | -------------------------------------------------------------------------------- /tests/unit/overload.expected: -------------------------------------------------------------------------------- 1 | // Generated with (https://github.com/laurentlb/Shader_Minifier/) 2 | #ifndef OVERLOAD_EXPECTED_ 3 | # define OVERLOAD_EXPECTED_ 4 | # define VAR_ZH "t" 5 | # define VAR__V "x" 6 | # define VAR_a_ "i" 7 | # define VAR_outputvar "f" 8 | # define VAR_stopinlining "v" 9 | 10 | const char *overload_frag = 11 | "#version 330\n" 12 | "uniform sampler2D x;" 13 | "uniform vec2 i;" 14 | "in vec2 t;" 15 | "out float v;" 16 | "out vec4 f;" 17 | "float h()" 18 | "{" 19 | "return v+.1;" 20 | "}" 21 | "float m()" 22 | "{" 23 | "return v+.2;" 24 | "}" 25 | "float h(int t)" 26 | "{" 27 | "return v+.3;" 28 | "}" 29 | "float m(float t)" 30 | "{" 31 | "return v+.4;" 32 | "}" 33 | "float h(bool t)" 34 | "{" 35 | "return v+.5;" 36 | "}" 37 | "float h(int t,int m)" 38 | "{" 39 | "return v+.6;" 40 | "}" 41 | "float h(int t,int m,int x,int f)" 42 | "{" 43 | "return v+.7;" 44 | "}" 45 | "float h(sampler2D t,float v)" 46 | "{" 47 | "return texelFetch(t,ivec2(255.*v)%256,0).x;" 48 | "}" 49 | "float h(sampler2D t,vec2 v)" 50 | "{" 51 | "return texelFetch(t,ivec2(255.*v)%256,0).x;" 52 | "}" 53 | "float h(sampler2D t,vec3 v)" 54 | "{" 55 | "float m=texelFetch(t,ivec2(255.*v.yz)%256,0).x;" 56 | "return texelFetch(t,ivec2(255.*v.x,255.*m)%256,0).x;" 57 | "}" 58 | "void main()" 59 | "{" 60 | "float v=0.,D=h(true)+h(0,1)-h(0,1,2,3),F=h(x,i*t);" 61 | "f=vec4(h()+2.*h(0),2.*m(1.2)-m(),D,F+v++);" 62 | "}"; 63 | 64 | #endif // OVERLOAD_EXPECTED_ 65 | -------------------------------------------------------------------------------- /tests/unit/overload.frag: -------------------------------------------------------------------------------- 1 | #version 330 2 | uniform sampler2D _V; 3 | uniform vec2 a_; 4 | in vec2 ZH; 5 | out float stopinlining; 6 | out vec4 outputvar; 7 | 8 | float f1() { return stopinlining+0.1; } 9 | float f2(void) { return stopinlining+0.2; } 10 | float f1(int x) { return stopinlining+0.3; } 11 | float f2(float y) { return stopinlining+0.4; } 12 | float f3(bool b) { return stopinlining+0.5; } 13 | float f3(int a, int b) { return stopinlining+0.6; } 14 | float f3(int a, int b, int c, int d) { return stopinlining+0.7; } 15 | 16 | float hashTex(sampler2D _V, float p) 17 | { 18 | return texelFetch(_V, ivec2(255. * p) % 256, 0).r; 19 | } 20 | float hashTex(sampler2D _V, vec2 p) 21 | { 22 | return texelFetch(_V, ivec2(255. * p) % 256, 0).r; 23 | } 24 | float hashTex(sampler2D _V, vec3 p) 25 | { 26 | float h = texelFetch(_V, ivec2(255. * p.yz) % 256, 0).r; 27 | return texelFetch(_V, ivec2(255. * p.x, 255. * h) % 256, 0).r; 28 | } 29 | 30 | void main() 31 | { 32 | float stopinlining = 0.; 33 | float a = f1() + 2. * f1(0); 34 | float b = 2. * f2(1.2) - f2(); 35 | float c = f3(true) + f3(0, 1) - f3(0, 1, 2, 3); 36 | float d = hashTex(_V, a_ * ZH); 37 | outputvar=vec4(a,b,c,d+stopinlining++); 38 | } 39 | -------------------------------------------------------------------------------- /tests/unit/pi.frag: -------------------------------------------------------------------------------- 1 | #version 400 2 | 3 | out vec4 fragColor; 4 | 5 | void main() { 6 | double pi = 3.141592653589793; 7 | double minus_pi = -3.141592653589793; 8 | double tau = 6.283185307179586; 9 | double minus_tau = -6.283185307179586; 10 | double half_pi = 1.5707963267948966; 11 | double minus_half_pi = -1.5707963267948966; 12 | double precise_pi = 3.14159265358979323846264338327950288419716939937510; 13 | fragColor = vec4(pi+minus_pi+tau+minus_tau+half_pi+minus_half_pi+precise_pi); 14 | } 15 | -------------------------------------------------------------------------------- /tests/unit/pi.frag.expected: -------------------------------------------------------------------------------- 1 | #version 400 2 | 3 | out vec4 fragColor; 4 | void main() 5 | { 6 | double pi=acos(-1.),minus_pi=-acos(-1.),tau=2.*acos(-1.),minus_tau=-2.*acos(-1.),half_pi=acos(0.),minus_half_pi=-acos(0.),precise_pi=acos(-1.); 7 | fragColor=vec4(pi+minus_pi+tau+minus_tau+half_pi+minus_half_pi+precise_pi); 8 | } 9 | -------------------------------------------------------------------------------- /tests/unit/precedence.frag: -------------------------------------------------------------------------------- 1 | float foo(bool a, bool b, bool c) { 2 | return (a?b:c)?.1:.2; 3 | } 4 | 5 | void main() 6 | { 7 | float f1 = 2. * 3. / 4. - 5. / 6.; 8 | float f2 = (true ? false ? 1. : 2. : 3. * 4.) * 5.; 9 | float f3 = 4. * (false ? (true ? 1. : 2.) : 3.); 10 | float f4 = float((2+3) * (4+5*6) - (7-8)); 11 | float f5 = (2.+f1) * (4.+f2*6.) - (7.-f3); 12 | 13 | float n = 1. / (f1 + f2 + f3); 14 | float o = 1. / (f4 * f5); 15 | 16 | gl_FragColor=vec4(n,o,n,0.); 17 | } 18 | -------------------------------------------------------------------------------- /tests/unit/precedence.frag.expected: -------------------------------------------------------------------------------- 1 | float foo(bool a,bool b,bool c) 2 | { 3 | return(a? 4 | b: 5 | c)? 6 | .1: 7 | .2; 8 | } 9 | void main() 10 | { 11 | float f1=1.5-5./6.,n=1./(f1+10.+12.); 12 | gl_FragColor=vec4(n,1./(float(171)*((2.+f1)*64.-7.+12.)),n,0); 13 | } 14 | -------------------------------------------------------------------------------- /tests/unit/precision.frag: -------------------------------------------------------------------------------- 1 | #version 300 es 2 | 3 | precision highp float; 4 | precision mediump int; 5 | precision lowp sampler2D; 6 | precision lowp samplerCube; 7 | 8 | lowp float foo(lowp float bar) { 9 | return 1.0; 10 | } 11 | -------------------------------------------------------------------------------- /tests/unit/precision.frag.expected: -------------------------------------------------------------------------------- 1 | #version 300 es 2 | 3 | precision highp float; 4 | precision mediump int; 5 | precision lowp sampler2D; 6 | precision lowp samplerCube; 7 | lowp float f(lowp float f) 8 | { 9 | return 1.; 10 | } 11 | -------------------------------------------------------------------------------- /tests/unit/preprocess.frag: -------------------------------------------------------------------------------- 1 | #version 130 2 | 3 | #define DEF bar 4 | #define foo() bar 5 | # 6 | 7 | #ifdef DEF 8 | void keep_ifdef() {} 9 | #endif 10 | 11 | #ifdef UNKNOWN 12 | void remove_ifdef() {} 13 | #endif 14 | 15 | #ifdef DEF 16 | # ifdef DEF // nested 17 | # ifdef UNKNOWN 18 | # ifdef DEF 19 | int remove_this_line; 20 | # endif 21 | int remove_this_line_too; 22 | # endif 23 | void keep_nested() {} 24 | # endif 25 | void keep_outernest() {} 26 | #endif 27 | 28 | #ifdef UNKNOWN 29 | int this_is_removed; 30 | #else 31 | void keep_else() {} 32 | #endif 33 | 34 | #undef DEF 35 | #ifdef DEF 36 | int removed_undefd() {} 37 | #endif 38 | 39 | void end() {} 40 | -------------------------------------------------------------------------------- /tests/unit/preprocess.frag.expected: -------------------------------------------------------------------------------- 1 | #version 130 2 | 3 | #define DEF bar 4 | 5 | #define foo()bar 6 | 7 | void keep_ifdef() 8 | {} 9 | void keep_nested() 10 | {} 11 | void keep_outernest() 12 | {} 13 | void keep_else() 14 | {} 15 | 16 | #undef DEF 17 | 18 | void end() 19 | {} 20 | -------------------------------------------------------------------------------- /tests/unit/preprocess_if.frag: -------------------------------------------------------------------------------- 1 | #version 130 2 | 3 | #define DEF 1 4 | 5 | #if 1 6 | void keep_if() {} 7 | #endif 8 | 9 | #if 0 10 | void remove_if() {} 11 | #endif 12 | 13 | #if DEF 14 | # if 0 15 | int remove_this_line; 16 | # elif 1 17 | void keep_nested() {} 18 | # endif 19 | void also_keep() {} 20 | # endif 21 | 22 | void end() {} 23 | -------------------------------------------------------------------------------- /tests/unit/preprocess_if.frag.expected: -------------------------------------------------------------------------------- 1 | #version 130 2 | 3 | #define DEF 1 4 | 5 | void keep_if() 6 | {} 7 | 8 | #if DEF 9 | 10 | void keep_nested() 11 | {} 12 | void also_keep() 13 | {} 14 | 15 | #endif 16 | 17 | void end() 18 | {} 19 | -------------------------------------------------------------------------------- /tests/unit/qualifiers.expected: -------------------------------------------------------------------------------- 1 | // Generated with (https://github.com/laurentlb/Shader_Minifier/) 2 | #ifndef QUALIFIERS_EXPECTED_ 3 | # define QUALIFIERS_EXPECTED_ 4 | # define VAR_foo "f" 5 | 6 | const char *qualifiers_frag = 7 | "#version 130\n" 8 | "in vec3 f;" 9 | "float v(float f)" 10 | "{" 11 | "return f;" 12 | "}" 13 | "float M(const float f)" 14 | "{" 15 | "return f;" 16 | "}" 17 | "float L(inout float f)" 18 | "{" 19 | "return f;" 20 | "}"; 21 | 22 | #endif // QUALIFIERS_EXPECTED_ 23 | -------------------------------------------------------------------------------- /tests/unit/qualifiers.frag: -------------------------------------------------------------------------------- 1 | #version 130 2 | 3 | in vec3 foo; 4 | 5 | float f(in float a) { 6 | return a; 7 | } 8 | 9 | float g(const in float a) { 10 | return a; 11 | } 12 | 13 | float h(inout float a) { 14 | return a; 15 | } 16 | -------------------------------------------------------------------------------- /tests/unit/rename_conflict.frag: -------------------------------------------------------------------------------- 1 | // test with --no-renaming-list i 2 | 3 | int foo(int a, int d) 4 | { 5 | return a + 1; 6 | } 7 | 8 | int i() 9 | { 10 | foo(0, 3); 11 | return 1; 12 | } 13 | 14 | int bar(int b, int c, int d) 15 | { 16 | return b + i(); 17 | } 18 | -------------------------------------------------------------------------------- /tests/unit/reuse-var.frag: -------------------------------------------------------------------------------- 1 | float simple_var_decl_reuse(float x) 2 | { 3 | float a = 1.+x; 4 | int b = 3+int(x); 5 | vec3 sep = vec3(0.); // prevents squeezeConsecutiveDeclarations 6 | int b2 = 5+int(a); 7 | float c = a; 8 | sep += vec3(0.); // prevents squeezeConsecutiveDeclarations 9 | float c2 = 9.+a; 10 | int d = 3+b+b2; 11 | sep += vec3(0.); // prevents squeezeConsecutiveDeclarations 12 | int d2 = d+b2-b; 13 | float e = c*c2; 14 | sep += vec3(0.); // prevents squeezeConsecutiveDeclarations 15 | float e2 = 4.-c-c2; 16 | int f = 3*d*d2; 17 | sep += vec3(0.); // prevents squeezeConsecutiveDeclarations 18 | int f2 = 4/d2-d; 19 | float g = e-float(f)+e2; 20 | int g2 = int(4.-g+e2+e); 21 | int h = 3*f-f2; 22 | sep += vec3(0.); // prevents squeezeConsecutiveDeclarations 23 | int h2 = 7*f2-f; 24 | return length(sep)+float(h*h2)*g*float(g2)*x + float(g2/h2-h); 25 | } 26 | float multidecl_var_decl_reuse(float x) 27 | { 28 | float a = 1.+x; 29 | int b = 3+int(x), b2 = 5+int(a); 30 | float c = a, c2 = 9.+a; 31 | int d = 3+b+b2, d2 = d+b2-b; 32 | float e = c*c2, e2 = 4.-c-c2; 33 | int f = 3*d*d2, f2 = 4/d2-d; 34 | float g = e-float(f)+e2, g2 = 4.-g+e2+e; 35 | int h = 3*f-f2, h2 = 7*f2-f; 36 | return float(h*h2)*g*g2*x + g2/float(h2-h); 37 | } 38 | vec2 map (in vec3 p) 39 | { 40 | vec2 tun = p.xy; 41 | tun.x++; 42 | vec3 q = vec3(tun,p.z); 43 | vec3 fs = p - vec3(2.85,0,0); 44 | vec2 center = floor(fs.xz) + .5; 45 | float height = .0465; 46 | height = smoothstep(.001,1.,height); 47 | float me = dot(fs-vec3(0,0,center.y), vec3(.05,.150+height,.25)); 48 | float next = dot(fs-vec3(0,0,center.y), vec3(.05,.001+height,.25)); 49 | float dlt = min(me, next); 50 | return vec2(dlt*dlt); 51 | } 52 | -------------------------------------------------------------------------------- /tests/unit/reuse-var.frag.expected: -------------------------------------------------------------------------------- 1 | float simple_var_decl_reuse(float x) 2 | { 3 | float a=1.+x; 4 | int b=3+int(x); 5 | vec3 sep=vec3(0); 6 | int b2=5+int(a); 7 | float c=a; 8 | sep+=vec3(0); 9 | a+=9.; 10 | int d=3+b+b2; 11 | sep+=vec3(0); 12 | b2=d+b2-b; 13 | float e=c*a; 14 | sep+=vec3(0); 15 | c=4.-c-a; 16 | b=3*d*b2; 17 | sep+=vec3(0); 18 | d=4/b2-d; 19 | a=e-float(b)+c; 20 | b2=int(4.-a+c+e); 21 | int h=3*b-d; 22 | sep+=vec3(0); 23 | d=7*d-b; 24 | return length(sep)+float(h*d)*a*float(b2)*x+float(b2/d-h); 25 | } 26 | float multidecl_var_decl_reuse(float x) 27 | { 28 | float a=1.+x; 29 | int b=3+int(x),b2=5+int(a); 30 | float c=a; 31 | a+=9.; 32 | int d=3+b+b2; 33 | b=d+b2-b; 34 | float e=c*a; 35 | c=4.-c-a; 36 | b2=3*d*b; 37 | d=4/b-d; 38 | a=e-float(b2)+c; 39 | e+=4.-a+c; 40 | b=3*b2-d; 41 | d=7*d-b2; 42 | return float(b*d)*a*e*x+e/float(d-b); 43 | } 44 | vec2 map(vec3 p) 45 | { 46 | vec2 tun=p.xy; 47 | tun.x++; 48 | vec3 fs=p-vec3(2.85,0,0); 49 | tun=floor(fs.xz)+.5; 50 | float height=smoothstep(.001,1.,.0465); 51 | height=min(dot(fs-vec3(0,0,tun.y),vec3(.05,.15+height,.25)),dot(fs-vec3(0,0,tun.y),vec3(.05,.001+height,.25))); 52 | return vec2(height*height); 53 | } 54 | -------------------------------------------------------------------------------- /tests/unit/shadowing.frag: -------------------------------------------------------------------------------- 1 | float f(float g) 2 | { 3 | float f = 0.0; 4 | f += f++ + ++f; 5 | return f; 6 | } 7 | float glob; 8 | float g(float f) 9 | { 10 | { 11 | f++; 12 | float f = f + 1.0, g = 9.0; 13 | glob+=f+=g; 14 | } 15 | return f; 16 | } 17 | 18 | #define noinline_random 4 19 | 20 | int m1() 21 | { 22 | int x = 1; 23 | if (noinline_random > 3) 24 | { 25 | int x = 2, y = x; // y is initialized to 2 26 | return y; 27 | } 28 | } 29 | 30 | struct S{ int x; }; 31 | 32 | S m2() 33 | { 34 | S S = S(0); // 'S' is only visible as a struct and constructor 35 | return S; // 'S' is now visible as a variable 36 | } 37 | 38 | int m4(int k) 39 | { 40 | //int k = k + 3; // redeclaration error of the name k 41 | { 42 | int k = k + 3; // 2nd k is parameter, initializing nested first k 43 | int m = k; // use of new k, which is hiding the parameter 44 | } 45 | return k; 46 | 47 | //int x = x; // Error if x has not been previously defined. 48 | // If the previous definition of x was in this 49 | // same scope, this causes a redeclaration error. 50 | } 51 | 52 | float m5(float k) 53 | { 54 | float m = 9.; 55 | m = 14.; 56 | { 57 | float k = k + 3.; // 2nd k is parameter, initializing nested first k 58 | m = k; // use of new k, which is hiding the parameter 59 | } 60 | return k + 2. * m; 61 | } 62 | 63 | float glo; 64 | void m6() 65 | { 66 | glo += m5(55.); 67 | } 68 | -------------------------------------------------------------------------------- /tests/unit/shadowing.frag.expected: -------------------------------------------------------------------------------- 1 | float f(float g) 2 | { 3 | g=0.; 4 | return g+g+++ ++g; 5 | } 6 | float glob; 7 | float g(float f) 8 | { 9 | { 10 | f++; 11 | float f=f+1.; 12 | glob+=f+=9.; 13 | } 14 | return f; 15 | } 16 | 17 | #define noinline_random 4 18 | 19 | int m1() 20 | { 21 | if(noinline_random>3) 22 | return 2; 23 | } 24 | struct S{int x;}; 25 | S m2() 26 | { 27 | return S(0); 28 | } 29 | int m4(int k) 30 | { 31 | return k; 32 | } 33 | float glo; 34 | void m6() 35 | { 36 | glo+=171.; 37 | } 38 | -------------------------------------------------------------------------------- /tests/unit/simple.frag: -------------------------------------------------------------------------------- 1 | #version 120 2 | 3 | void main() 4 | { 5 | gl_FragColor = vec4(0.2, 0.4, 0.6, 0.); 6 | } 7 | -------------------------------------------------------------------------------- /tests/unit/simplify.expected: -------------------------------------------------------------------------------- 1 | #version 330 2 | 3 | int i; 4 | float bar(float x) 5 | { 6 | float a=6.+x,b=34.+x,arr[2]=float[2](5.,float(float[2](7.,8.).length())); 7 | x=(a*=10,a*=20,a*=30,b++,arr[1]+arr[i++]); 8 | return a+b+x; 9 | } 10 | float baz(float a) 11 | { 12 | a=a+4.+sin(a); 13 | a=a+5.+sin(a); 14 | return a-a-a; 15 | } 16 | out vec3 outputvar; 17 | void notMain(float x) 18 | { 19 | outputvar.xyz=vec3(92)+vec3(bar(x)+baz(x)); 20 | } 21 | int foo442(float x) 22 | { 23 | return x>=1.&&x<=8.? 24 | 1: 25 | 2; 26 | } 27 | in vec3 camPos; 28 | float len() 29 | { 30 | return length(camPos); 31 | } 32 | float main450() 33 | { 34 | return len()+len(); 35 | } 36 | -------------------------------------------------------------------------------- /tests/unit/simplify.frag: -------------------------------------------------------------------------------- 1 | #version 330 2 | 3 | int i; 4 | 5 | float bar(float x) 6 | { 7 | float a = x; 8 | a = 6.; 9 | a = a + x; 10 | 11 | float b = x; 12 | b = b + x; 13 | b = 34.; 14 | b = b + x; 15 | 16 | float arr[2] = float[2](7.,8.); 17 | arr = float[2](5.,float(arr.length())); 18 | 19 | float m = 14.+length(vec3(sin(a *= 10), sin(a *= 20), sin(a *= 30)))+b++; 20 | m = arr[1] + arr[i++]; 21 | 22 | return a + b + m; 23 | } 24 | float baz(float a) 25 | { 26 | float b = a + 4.; 27 | b += sin(a); 28 | float c = b + 5.; 29 | c += sin(b); 30 | return c + (-(c - -c)); 31 | } 32 | 33 | int n = 2; 34 | float y = 47.; 35 | out vec3 outputvar; 36 | 37 | float foo(float a) { if (n == 1) return 0.; if (n == 2) return a; return 1.; } 38 | float foo(float a, float b) { if (y > a) return 0.; if (y < b) return a; return 1.; } 39 | 40 | void notMain(float x) { 41 | vec3 v = vec3(foo(42.) + foo(50., 70.)); 42 | outputvar.rgb = v + vec3(bar(x) + baz(x)); 43 | } 44 | 45 | // #442: function inlining when a parameter is read more than once, but the argument expr is pure and trivial, like a variable that's read (but not written) 46 | bool IsMoto(float mid) { 47 | return mid>=1.&&mid<=8.; 48 | } 49 | int foo442(float x) { 50 | if (IsMoto(x)) return 1; 51 | return 2; 52 | } 53 | 54 | // #450: argument inlining of read-only globals 55 | in vec3 camPos; 56 | float len(vec3 pos) { 57 | return length(pos); 58 | } 59 | float main450() { 60 | float a = len(camPos); 61 | float b = len(camPos); 62 | return a + b; 63 | } 64 | -------------------------------------------------------------------------------- /tests/unit/smoothstep.frag: -------------------------------------------------------------------------------- 1 | vec2 resolution = vec2(1., 1.); 2 | 3 | void main() 4 | { 5 | vec2 ref = vec2(1.2, 3.4); 6 | vec2 p = -1.0 + 2.0 * gl_FragCoord.xy / resolution.xy; 7 | float s = sqrt( dot(p,p) ); 8 | 9 | s = smoothstep(0.0,1.0,s); 10 | 11 | float ao = smoothstep(0.0,0.4,s) - 1.0 * smoothstep(0.4,0.7,s); 12 | 13 | float dom = 1.0 * smoothstep( (-0.1), (0.1), ref.y); // https://github.com/laurentlb/Shader_Minifier/issues/7 14 | } 15 | -------------------------------------------------------------------------------- /tests/unit/struct.frag: -------------------------------------------------------------------------------- 1 | #version 460 2 | // struct declaration in TypeDecl 3 | struct MarchData { // newName 4 | float dist; 5 | vec3 col; 6 | float spec; 7 | }; 8 | // struct in TLDecl 9 | MarchData m; 10 | uniform MyInterfaceBlock 11 | { 12 | // struct in interface block field 13 | MarchData march; 14 | /* Not allowed, at least on shadertoy. 15 | // anonymous struct declaration in interface block field 16 | struct { 17 | // struct identifier use in field in interface block 18 | MarchData abc; 19 | } struc; 20 | */ 21 | }; 22 | // struct identifier use in FunctionType.retType 23 | MarchData struct_as_ret() 24 | { 25 | return m; 26 | } 27 | // struct identifier use in FunctionType.args 28 | int struct_as_arg(MarchData m) 29 | { 30 | return 1; 31 | } 32 | int struct_uses() { 33 | // struct identifier use in Stmt.Decl 34 | MarchData m; 35 | // struct field access 36 | m.dist = 1.; 37 | m.spec = m.dist / 2.; 38 | // struct identifier use in constructor 39 | m = MarchData(1., vec3(1), m.spec); 40 | // anonymous struct declaration in Stmt.Decl 41 | struct { 42 | // struct identifier use in field in local 43 | MarchData abc; 44 | } s; 45 | // struct identifier use in Stmt.Decl 46 | for (MarchData m2; true; ) break; 47 | // anonymous struct declaration in Stmt.ForD 48 | for (struct { 49 | // struct identifier use in field in local 50 | MarchData abc; 51 | } s; true; ) break; 52 | return int(m.col.x + s.abc.dist + march.spec); 53 | } 54 | 55 | // anonymous struct declaration at top level 56 | struct { 57 | // struct identifier use in field in global struct 58 | MarchData abc; 59 | } s2; 60 | 61 | // bug test 62 | float v(vec4 w) 63 | { 64 | float MarchData = w.x-4.0; // reuse type name as var 65 | return w.w + MarchData*MarchData; // don't rename field `.w` 66 | } 67 | 68 | struct Foo {int A; int B;}; 69 | struct Bar {int A; int C; int B;}; 70 | 71 | Foo foo; 72 | Bar bar; 73 | 74 | void main() { 75 | foo.A = 1; 76 | foo.B = 2; 77 | bar.A = 3; 78 | bar.C = 4; 79 | bar.B = 5; 80 | } 81 | 82 | struct Baz {int A; int B;} baz; 83 | struct {int A; int B;}; // why is this even legal 84 | -------------------------------------------------------------------------------- /tests/unit/struct.frag.expected: -------------------------------------------------------------------------------- 1 | #version 460 2 | 3 | struct r{float t;vec3 r;float n;}; 4 | r e; 5 | uniform MyInterfaceBlock{r k;}; 6 | r M() 7 | { 8 | return e; 9 | } 10 | int M(r M) 11 | { 12 | return 1; 13 | } 14 | int i() 15 | { 16 | r s; 17 | s.t=1.; 18 | s.n=s.t/2.; 19 | s=r(1.,vec3(1),s.n); 20 | struct{r u;} e; 21 | for(r e;true;) 22 | break; 23 | for(struct{r u;} e;true;) 24 | break; 25 | return int(s.r.x+e.u.t+k.n); 26 | } 27 | struct{r u;} m; 28 | float M(vec4 s) 29 | { 30 | float e=s.x-4.; 31 | return s.w+e*e; 32 | } 33 | struct B{int i;int e;}; 34 | struct I{int i;int c;int e;}; 35 | B f; 36 | I s; 37 | void main() 38 | { 39 | f.i=1; 40 | f.e=2; 41 | s.i=3; 42 | s.c=4; 43 | s.e=5; 44 | } 45 | struct O{int i;int e;} N; 46 | -------------------------------------------------------------------------------- /tests/unit/struct2.frag: -------------------------------------------------------------------------------- 1 | 2 | float stretch, gunsUp, gunsForward, edWalk, edTwist, edDown, edShoot, doorOpen, glow; 3 | 4 | struct MarchData { 5 | // initially this looked like `float A,Z,e,R,T,Y,u,i,o,P,m,l,k,j,h,G,f,S,d,Q,W,X,c,v,B,n,_;` 6 | // but glslang has a bug and can't parse it: https://github.com/KhronosGroup/glslang/issues/3931 7 | vec3 mat; 8 | float specPower; 9 | float A; 10 | int Z; 11 | float e; 12 | int R; 13 | float T; 14 | int Y; 15 | float u; 16 | int i; 17 | float o; 18 | int P; 19 | float m; 20 | int l; 21 | float k; 22 | int j; 23 | float h; 24 | int G; 25 | float f; 26 | int S; 27 | float d; 28 | int Q; 29 | float W; 30 | int X; 31 | float c; 32 | int v; 33 | float B; 34 | int n; 35 | float _; 36 | int __; 37 | float a1; 38 | int a2; 39 | float a3; 40 | int a4; 41 | float a5; 42 | int a6; 43 | float a7; 44 | int a8; 45 | float a9; 46 | int a10; 47 | vec2 a11; 48 | float a12; 49 | int a13; 50 | float a14; 51 | int a15; 52 | float a16; 53 | int a17; 54 | float a18; 55 | int a19; 56 | float a20; 57 | int a21; 58 | float a22; 59 | int a23; 60 | float a24; 61 | int a25; 62 | float a26; 63 | int a27; 64 | float a28; 65 | int a29; 66 | float a30; 67 | }; 68 | 69 | struct AprilData { 70 | vec3 mat; 71 | float specPower; 72 | float A; 73 | float Z; 74 | int e; 75 | float R; 76 | int T; 77 | float Y; 78 | int u; 79 | float i; 80 | int o; 81 | float P; 82 | int m; 83 | float l; 84 | int k; 85 | float j; 86 | int h; 87 | float G; 88 | int f; 89 | float S; 90 | int d; 91 | float Q; 92 | int W; 93 | float X; 94 | int c; 95 | float v; 96 | int B; 97 | float a1; 98 | int n; 99 | float a2; 100 | int a3; 101 | float a4; 102 | int a5; 103 | float a6; 104 | int a7; 105 | float a8; 106 | int a9; 107 | float a10; 108 | vec2 a11; 109 | float a12; 110 | int a13; 111 | float a14; 112 | int a15; 113 | float a16; 114 | int a17; 115 | float a18; 116 | int a19; 117 | float a20; 118 | vec2 a21; 119 | vec3 a22; 120 | int a23; 121 | float a24; 122 | int a25; 123 | float a26; 124 | int a27; 125 | float a28; 126 | int a29; 127 | float a30; 128 | }; 129 | 130 | void set(inout MarchData mat, AprilData a) { 131 | mat.mat = vec3(0.36, 0.45, 0.5); 132 | mat.specPower = 30.0; 133 | mat.d = 1.0; 134 | a.a11 = vec2(a.a1, a.a2); 135 | a.a21 = a.a22.yx; 136 | } 137 | 138 | void mainImage(out vec4 fragColor, in vec2 fragCoord) { fragColor = vec4(1.0); } 139 | -------------------------------------------------------------------------------- /tests/unit/struct2.frag.expected: -------------------------------------------------------------------------------- 1 | float m,v,I,R,Q,P,O,N,x; 2 | struct L{vec3 t;float o;float a;int l;float f;int i;float n;int v;float c;int e;float u;int s;float r;int m;float d;int I;float y;int x;float g;int _;float Z;int Y;float X;int W;float V;int U;float T;int S;float R;int Q;float P;int O;float N;int M;float L;int K;float J;int H;float G;int F;vec2 E;float D;int C;float B;int A;float z;int w;float q;int p;float k;int j;float h;int b;float aa;int ab;float ac;int ad;float ae;int af;float ag;}; 3 | struct K{vec3 t;float o;float a;float l;int f;float i;int n;float v;int c;float e;int u;float s;int r;float m;int d;float I;int y;float x;int g;float _;int Z;float Y;int X;float W;int V;float U;int T;float P;int S;float O;int N;float M;int L;float K;int J;float H;int G;float F;vec2 E;float D;int C;float B;int A;float z;int w;float q;int p;float k;vec2 j;vec3 h;int b;float aa;int ab;float ac;int ad;float ae;int af;float ag;}; 4 | void e(inout L f,K i) 5 | { 6 | f.t=vec3(.36,.45,.5); 7 | f.o=30.; 8 | f.Z=1.; 9 | i.E=vec2(i.P,i.O); 10 | i.j=i.h.yx; 11 | } 12 | void mainImage(out vec4 v,vec2 i) 13 | { 14 | v=vec4(1); 15 | } 16 | -------------------------------------------------------------------------------- /tests/unit/struct_inheritance.hlsl: -------------------------------------------------------------------------------- 1 | template 2 | struct bool_literal { 3 | static const bool value = Value; 4 | }; 5 | 6 | struct true_type : bool_literal {}; 7 | struct false_type : bool_literal {}; 8 | 9 | struct is_floating_point : false_type {}; 10 | template <> struct is_floating_point : true_type {}; 11 | template <> struct is_floating_point : true_type {}; 12 | -------------------------------------------------------------------------------- /tests/unit/struct_inheritance.hlsl.expected: -------------------------------------------------------------------------------- 1 | template 2 | struct bool_literal{static const bool value=Value;}; 3 | struct true_type:bool_literal{}; 4 | struct false_type:bool_literal{}; 5 | struct is_floating_point:false_type{}; 6 | template<> 7 | struct is_floating_point:true_type{}; 8 | template<> 9 | struct is_floating_point:true_type{}; 10 | 11 | -------------------------------------------------------------------------------- /tests/unit/suffix.frag: -------------------------------------------------------------------------------- 1 | #version 400 2 | 3 | void main() 4 | { 5 | uint n1 = 41u; 6 | uint n2 = 42U; 7 | double f1 = 1.20LF; 8 | float f2 = 3.F; 9 | double f3 = .0003lf; 10 | float f7 = 2E-9f; 11 | 12 | float foo = - (- 2.f); 13 | } 14 | -------------------------------------------------------------------------------- /tests/unit/switch.expected: -------------------------------------------------------------------------------- 1 | #version 130 2 | 3 | void h() 4 | { 5 | switch(42){ 6 | case 42: 7 | break; 8 | } 9 | } 10 | 11 | #define GOOD 42 12 | 13 | void G() 14 | { 15 | switch(42){ 16 | case GOOD: 17 | break; 18 | } 19 | } 20 | void G(int G) 21 | { 22 | switch(G){ 23 | case 0: 24 | break; 25 | } 26 | } 27 | void h(int G) 28 | { 29 | switch(G+42){ 30 | case 0: 31 | break; 32 | } 33 | } 34 | float D() 35 | { 36 | switch(42){ 37 | case 42: 38 | 39 | 40 | return 6.6; 41 | case 43: 42 | 43 | return 7.7; 44 | default: 45 | return 0.; 46 | } 47 | } 48 | void b() 49 | {} 50 | int D(int G) 51 | { 52 | switch(G){ 53 | case 1: 54 | b(); 55 | case 2: 56 | b(); 57 | case 3: 58 | break; 59 | case 4: 60 | b(); 61 | b(); 62 | break; 63 | case 5: 64 | b(); 65 | b(); 66 | return 18; 67 | } 68 | return 1; 69 | } 70 | -------------------------------------------------------------------------------- /tests/unit/switch.frag: -------------------------------------------------------------------------------- 1 | #version 130 2 | 3 | void switchConst() { 4 | switch (42) { 5 | case 42: 6 | break; 7 | } 8 | } 9 | 10 | #define GOOD 42 11 | void switchDefine() { 12 | switch (42) { 13 | case GOOD: 14 | break; 15 | } 16 | } 17 | 18 | void switchArg(in int someArg) { 19 | switch (someArg) { 20 | case 0: 21 | break; 22 | } 23 | } 24 | 25 | void switchExpr(in int someArg) { 26 | switch (someArg + 42) { 27 | case 0: 28 | break; 29 | } 30 | } 31 | 32 | float switchMultiple() { 33 | switch (42) { 34 | case 42: 35 | float someVar = 4.2; 36 | float otherVar = 2.4; 37 | return someVar + otherVar; 38 | case 43: 39 | float anotherVar = 4.3; 40 | return anotherVar + 3.4; 41 | default: 42 | return 0.0; 43 | } 44 | } 45 | 46 | const int LBL1 = 1, LBL2 = 2, LBL3 = 3, LBL4 = 4, LBL5 = 5; 47 | void foo() {} 48 | 49 | int switchStringLabels(int value) 50 | { 51 | switch (value) 52 | { 53 | case LBL1: foo(); 54 | case LBL2: foo(); 55 | case LBL3: { foo(); break; } 56 | case LBL4: foo(); foo(); break; 57 | case LBL5: foo(); foo(); return 18; 58 | } 59 | return 1; 60 | } 61 | -------------------------------------------------------------------------------- /tests/unit/symbols.frag: -------------------------------------------------------------------------------- 1 | # extension GL_EXT_gpu_shader4 : enable 2 | # define TEST 3 | # ifndef A 4 | # endif 5 | 6 | vec3 color; // TLDecl 7 | 8 | struct s { // TypeDecl 9 | vec4 n, f; 10 | bool ok; 11 | }; 12 | 13 | float sdf(vec3 p) { // Function 14 | color = vec3(1.); 15 | return length(p) - 1.; 16 | } 17 | 18 | void main() { 19 | int ijk = 32; 20 | ijk += ijk; 21 | } -------------------------------------------------------------------------------- /tests/unit/symbols.frag.expected: -------------------------------------------------------------------------------- 1 | #extension GL_EXT_gpu_shader4:enable 2 | #define TEST 3 | #ifndef A 4 | #endif 5 | vec3 color;struct s{vec4 n,f;bool ok;};float sdf(vec3 p){color=vec3(1);return length(p)-1.;}void main(){int ijk=32;ijk+=ijk;} -------------------------------------------------------------------------------- /tests/unit/symbols.frag.sym: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/laurentlb/shader-minifier/686983819d150b5fd30bb6fbf6d1e60652f2e52d/tests/unit/symbols.frag.sym -------------------------------------------------------------------------------- /tests/unit/templates.hlsl: -------------------------------------------------------------------------------- 1 | template 2 | struct literal { 3 | T value; 4 | }; 5 | 6 | template 7 | literal DoSomething(T arg, literal b) { 8 | T a = arg; 9 | literal c = b; 10 | return c; 11 | } 12 | -------------------------------------------------------------------------------- /tests/unit/templates.hlsl.expected: -------------------------------------------------------------------------------- 1 | template 2 | struct literal{T value;}; 3 | template 4 | literal DoSomething(T arg,literal b) 5 | { 6 | return b; 7 | } 8 | -------------------------------------------------------------------------------- /tests/unit/ternary.frag: -------------------------------------------------------------------------------- 1 | #version 450 2 | 3 | // https://github.com/laurentlb/Shader_Minifier/issues/320 4 | float f0() { 5 | float a = 1., b = 1.; 6 | a == 1. ? b = 2. : b = 3.; 7 | return b; // 2 8 | } 9 | 10 | float f1() { 11 | float a = 1., b = 1.; 12 | a = true ? b = 2. : b = 3.; 13 | return a; 14 | } 15 | 16 | // Fix for #385 17 | 18 | out vec4 O; 19 | int k; 20 | void main() { 21 | int d=0,e=0; 22 | k==0 ? (sin(O.x),d=1) : (cos(O.x),e=2) ; 23 | O.x=float(d); 24 | O.y=float(e); 25 | } 26 | int f2() { 27 | k++ == 0 ? 1 : 2 ; 28 | return k; 29 | } 30 | -------------------------------------------------------------------------------- /tests/unit/ternary.frag.expected: -------------------------------------------------------------------------------- 1 | #version 450 2 | 3 | float f0() 4 | { 5 | return 2.; 6 | } 7 | float f1() 8 | { 9 | float b=1.; 10 | return b=2.; 11 | } 12 | out vec4 O; 13 | int k; 14 | void main() 15 | { 16 | int d=0,e=0; 17 | k==0? 18 | sin(O.x),d=1: 19 | (cos(O.x),e=2); 20 | O.x=float(d); 21 | O.y=float(e); 22 | } 23 | int f2() 24 | { 25 | k++; 26 | return k; 27 | } 28 | -------------------------------------------------------------------------------- /tests/unit/unused_assignments.frag: -------------------------------------------------------------------------------- 1 | #version 330 2 | int gi = 0; 3 | void preventMergingConsecutiveAssignments() { gi++; } 4 | 5 | void shouldRemoveAllAssignments() { 6 | float x = 1.; 7 | preventMergingConsecutiveAssignments(); 8 | x = sin(x); // this assignment is eventually unused 9 | preventMergingConsecutiveAssignments(); 10 | x = cos(x); // this assignment is unused 11 | } 12 | float shouldNotRemoveAnyAssignment() { 13 | float x = gi; 14 | preventMergingConsecutiveAssignments(); 15 | x = sin(x); // this assignment is NOT unused 16 | preventMergingConsecutiveAssignments(); 17 | x = cos(x); // this assignment is NOT unused 18 | preventMergingConsecutiveAssignments(); 19 | return x; 20 | } 21 | 22 | vec3 bewareThatAssignmentToAFieldIsNotAFullOverwrite(vec3 v) { 23 | v.x = 1.; // this assignment is unused 24 | preventMergingConsecutiveAssignments(); 25 | v = vec3(0.3); // this assignment is NOT unused 26 | preventMergingConsecutiveAssignments(); 27 | v.y = 0.; // this assignment is NOT unused 28 | preventMergingConsecutiveAssignments(); 29 | v.x += 1.; // this assignment is unused 30 | preventMergingConsecutiveAssignments(); 31 | vec3 vv = v.yyz; // this assignment is NOT unused 32 | preventMergingConsecutiveAssignments(); 33 | vv.x++; // this assignment is unused 34 | preventMergingConsecutiveAssignments(); 35 | vv = vec3(0.5); // this assignment is NOT unused 36 | preventMergingConsecutiveAssignments(); 37 | return vv; 38 | } 39 | 40 | void dontRemoveAssignmentsToOutParams(in int i, inout int io, out int o) { 41 | i = 4; // this assignment is unused 42 | o = 5; // this assignment is NOT unused 43 | io = 6; // this assignment is NOT unused 44 | } 45 | 46 | void dontRemoveUnusedAssignmentToGlobal() { 47 | gi = 8; 48 | gi = 9; 49 | } 50 | 51 | float removePureDeclInit() { 52 | vec3 i = vec3(0); 53 | preventMergingConsecutiveAssignments(); 54 | i = vec3(1); 55 | vec3 j = vec3(gi++); 56 | preventMergingConsecutiveAssignments(); 57 | j = vec3(1); 58 | return i.x * j.y; 59 | } 60 | 61 | int onlyRemove99AndAThenReturn15() { 62 | int a=1,b=99; 63 | a*=a+a+a; 64 | { 65 | int a = a; 66 | preventMergingConsecutiveAssignments(); 67 | a = 2; 68 | b=a*a; 69 | } 70 | preventMergingConsecutiveAssignments(); 71 | return a+a*b; 72 | } 73 | 74 | void main() { 75 | shouldRemoveAllAssignments(); 76 | shouldNotRemoveAnyAssignment(); 77 | bewareThatAssignmentToAFieldIsNotAFullOverwrite(vec4(1).xyz); 78 | int io = 2, o = 3; // o's assignment is unused! 79 | dontRemoveAssignmentsToOutParams(gi, io, o); 80 | dontRemoveUnusedAssignmentToGlobal(); 81 | removePureDeclInit(); 82 | onlyRemove99AndAThenReturn15(); 83 | } -------------------------------------------------------------------------------- /tests/unit/unused_assignments.frag.expected: -------------------------------------------------------------------------------- 1 | #version 330 2 | 3 | int gi=0; 4 | void preventMergingConsecutiveAssignments() 5 | { 6 | gi++; 7 | } 8 | void shouldRemoveAllAssignments() 9 | { 10 | preventMergingConsecutiveAssignments(); 11 | preventMergingConsecutiveAssignments(); 12 | } 13 | float shouldNotRemoveAnyAssignment() 14 | { 15 | float x=gi; 16 | preventMergingConsecutiveAssignments(); 17 | x=sin(x); 18 | preventMergingConsecutiveAssignments(); 19 | x=cos(x); 20 | preventMergingConsecutiveAssignments(); 21 | return x; 22 | } 23 | vec3 bewareThatAssignmentToAFieldIsNotAFullOverwrite(vec3 v) 24 | { 25 | preventMergingConsecutiveAssignments(); 26 | v=vec3(.3); 27 | preventMergingConsecutiveAssignments(); 28 | v.y=0.; 29 | preventMergingConsecutiveAssignments(); 30 | v.x+=1.; 31 | preventMergingConsecutiveAssignments(); 32 | v=v.yyz; 33 | preventMergingConsecutiveAssignments(); 34 | v.x++; 35 | preventMergingConsecutiveAssignments(); 36 | v=vec3(.5); 37 | preventMergingConsecutiveAssignments(); 38 | return v; 39 | } 40 | void dontRemoveAssignmentsToOutParams(int i,inout int io,out int o) 41 | { 42 | o=5; 43 | io=6; 44 | } 45 | void dontRemoveUnusedAssignmentToGlobal() 46 | { 47 | gi=8; 48 | gi=9; 49 | } 50 | float removePureDeclInit() 51 | { 52 | vec3 i; 53 | preventMergingConsecutiveAssignments(); 54 | i=vec3(1); 55 | vec3 j=vec3(gi++); 56 | preventMergingConsecutiveAssignments(); 57 | j=vec3(1); 58 | return i.x*j.y; 59 | } 60 | int onlyRemove99AndAThenReturn15() 61 | { 62 | int a=1,b; 63 | a*=a+a+a; 64 | { 65 | int a; 66 | preventMergingConsecutiveAssignments(); 67 | a=2; 68 | b=a*a; 69 | } 70 | preventMergingConsecutiveAssignments(); 71 | return a+a*b; 72 | } 73 | void main() 74 | { 75 | shouldRemoveAllAssignments(); 76 | shouldNotRemoveAnyAssignment(); 77 | bewareThatAssignmentToAFieldIsNotAFullOverwrite(vec4(1).xyz); 78 | int io=2,o; 79 | dontRemoveAssignmentsToOutParams(gi,io,o); 80 | dontRemoveUnusedAssignmentToGlobal(); 81 | removePureDeclInit(); 82 | onlyRemove99AndAThenReturn15(); 83 | } 84 | -------------------------------------------------------------------------------- /tests/unit/unused_removal.frag: -------------------------------------------------------------------------------- 1 | float f(); 2 | 3 | float actually_unreachable() { return 1.5; } 4 | float noinline_actually_unreachable2() { return 1.5; } 5 | 6 | float f(){ 7 | float r = 1.; 8 | 9 | return actually_unreachable(); 10 | } 11 | 12 | vec3 g() { return vec3(0.); } 13 | 14 | vec2 pos = vec2(0.5); 15 | 16 | // hidden() is unused and should be removed even if a parameter named 'hidden' is used in another function. 17 | int hidden() { 18 | int noinlinevar = 0; 19 | noinlinevar++; 20 | return noinlinevar; 21 | } 22 | 23 | float foo(float hidden) { 24 | float noinlinevar = 0.; 25 | noinlinevar++; 26 | return hidden+noinlinevar; 27 | } 28 | 29 | float glob; 30 | float side_effect() { 31 | return glob++; 32 | } 33 | 34 | vec4 noinline_test() 35 | { 36 | vec4 bb; 37 | return bb; 38 | } 39 | 40 | void main(){ 41 | float unused_var = side_effect(); 42 | 43 | if (false) { 44 | noinline_actually_unreachable2(); 45 | return; 46 | } 47 | gl_FragColor = vec4(foo(3.), g()) + noinline_test(); 48 | } 49 | -------------------------------------------------------------------------------- /tests/unit/unused_removal.frag.expected: -------------------------------------------------------------------------------- 1 | vec2 pos=vec2(.5); 2 | float glob; 3 | float foo() 4 | { 5 | float noinlinevar=0.; 6 | noinlinevar++; 7 | return 3.+noinlinevar; 8 | } 9 | vec4 noinline_test() 10 | { 11 | vec4 bb; 12 | return bb; 13 | } 14 | void main() 15 | { 16 | float unused_var=glob++; 17 | gl_FragColor=vec4(foo(),vec3(0))+noinline_test(); 18 | } 19 | -------------------------------------------------------------------------------- /tests/unit/vectors.frag: -------------------------------------------------------------------------------- 1 | float swizzles() { 2 | vec2 v1 = vec2(1., 1.); 3 | vec3 v2 = vec3(v1.x, v1.y, v1.x); 4 | vec3 v3 = vec3(v1.x, v2.x, v2.r); 5 | vec4 v4 = vec4(v1.xx, v1.y, v1.x); 6 | vec4 v5 = vec4(1., v2.z, v2.g, 2.); 7 | vec4 v6 = vec4(v1.x, v1.y, v2.r, v2.t); 8 | return v1.x + v2.x + v3.x + v4.x + v5.x + v6.x; 9 | } 10 | 11 | vec4 constructor() { 12 | return vec4(1., 1e2, 2e3, 3e4); 13 | } 14 | 15 | float constructors() { 16 | vec2 v2 = vec2(1e10, 1e10); 17 | vec3 v3 = vec3(v2, v2); 18 | vec4 v4 = vec4(v3, v2); 19 | return v2.x + v3.x + v4.x; 20 | } 21 | 22 | float withExtraComponents() { 23 | vec2 v2 = vec2(1); 24 | vec3 v3 = vec3(1, 2, v2.x); 25 | vec4 v4 = vec4(v2, v3.xy); 26 | vec3 v5 = vec3(1, v3.rg); 27 | return v2.x + v3.x + v4.x + v5.x; 28 | } 29 | 30 | float withExtraComponentsUnsafe(in vec3 a) { 31 | vec3 v1 = vec3(a.x); 32 | vec2 v3 = vec2(1.0, a.y); 33 | vec3 v4 = vec3(1.0, 2.0, a.y); 34 | return v1.x + v3.x + v4.x; 35 | } 36 | 37 | struct S{ 38 | vec2 p1; 39 | vec2 cp1; 40 | vec2 cp2; 41 | vec2 p2; 42 | }; 43 | 44 | vec2 calc(S points, float t) { 45 | // #282 - not a swizzle 46 | vec4 m1m2 = mix(vec4(points.p1, points.cp1), vec4(points.cp1, points.cp2), t); 47 | return m1m2.xy; 48 | } 49 | -------------------------------------------------------------------------------- /tests/unit/vectors.frag.expected: -------------------------------------------------------------------------------- 1 | float swizzles() 2 | { 3 | vec2 v1=vec2(1); 4 | vec3 v2=vec3(v1.xyx),v3=vec3(v1.x,v2.xx); 5 | vec4 v4=vec4(v1.xxyx),v5=vec4(1,v2.zy,2),v6=vec4(v1.xy,v2); 6 | return v1.x+v2.x+v3.x+v4.x+v5.x+v6.x; 7 | } 8 | vec4 constructor() 9 | { 10 | return vec4(1,100,2e3,3e4); 11 | } 12 | float constructors() 13 | { 14 | vec2 v2=vec2(1e10); 15 | vec3 v3=vec3(v2,v2); 16 | vec4 v4=vec4(v3,v2); 17 | return v2.x+v3.x+v4.x; 18 | } 19 | float withExtraComponents() 20 | { 21 | vec2 v2=vec2(1); 22 | vec3 v3=vec3(1,2,v2); 23 | vec4 v4=vec4(v2,v3); 24 | vec3 v5=vec3(1,v3); 25 | return v2.x+v3.x+v4.x+v5.x; 26 | } 27 | float withExtraComponentsUnsafe(vec3 a) 28 | { 29 | vec3 v1=vec3(a.x); 30 | vec2 v3=vec2(1,a.y); 31 | vec3 v4=vec3(1,2,a.y); 32 | return v1.x+v3.x+v4.x; 33 | } 34 | struct S{vec2 p1;vec2 cp1;vec2 cp2;vec2 p2;}; 35 | vec2 calc(S points,float t) 36 | { 37 | vec4 m1m2=mix(vec4(points.p1,points.cp1),vec4(points.cp1,points.cp2),t); 38 | return m1m2.xy; 39 | } 40 | -------------------------------------------------------------------------------- /tests/unit/verbatim.frag: -------------------------------------------------------------------------------- 1 | //[ 2 | // Test case for https://github.com/laurentlb/Shader_Minifier/issues/168 3 | //] 4 | 5 | //[ 6 | int foo(int x) { 7 | return 2; 8 | } 9 | //] 10 | 11 | int my_function() { 12 | int i = 2; 13 | //[ 14 | foo(1 + 1 ) ; 15 | //] 16 | return i; 17 | } 18 | 19 | int verbatim_with_newlines() { 20 | //[ 21 | 22 | 23 | int x; 24 | 25 | 26 | 27 | int y; 28 | 29 | 30 | 31 | //] 32 | return x + y; 33 | } 34 | -------------------------------------------------------------------------------- /tests/unit/verbatim.frag.expected: -------------------------------------------------------------------------------- 1 | // Generated with (https://github.com/laurentlb/Shader_Minifier/) 2 | #ifndef SHADER_MINIFIER_IMPL 3 | #ifndef SHADER_MINIFIER_HEADER 4 | # define SHADER_MINIFIER_HEADER 5 | #endif 6 | 7 | #else // if SHADER_MINIFIER_IMPL 8 | 9 | // tests/unit/verbatim.frag 10 | "//Test case for https://github.com/laurentlb/Shader_Minifier/issues/168\n" 11 | "int foo(int x){\nreturn 2;\n}\n" 12 | "int my_function()" 13 | "{" 14 | "int i=2;" 15 | "foo(1+1);\n" 16 | "return i;" 17 | "}" 18 | "int verbatim_with_newlines()" 19 | "{" 20 | "int x;\nint y;\n" 21 | "return x+y;" 22 | "}", 23 | 24 | #endif 25 | --------------------------------------------------------------------------------