Skip to content

Instantly share code, notes, and snippets.

@yasirkula
Last active August 13, 2024 09:03
Show Gist options
  • Save yasirkula/d8fa2fb5f22aefcc7a232f6feeb91db7 to your computer and use it in GitHub Desktop.
Save yasirkula/d8fa2fb5f22aefcc7a232f6feeb91db7 to your computer and use it in GitHub Desktop.
Stripping commonly unused shader variants in Unity's built-in render pipeline
//#define SHADER_COMPILATION_LOGGING
//#define SKIP_SHADER_COMPILATION
using System.Collections.Generic;
using UnityEditor.Build;
using UnityEditor.Rendering;
using UnityEngine;
using UnityEngine.Rendering;
public class ShaderStripper : IPreprocessShaders
{
private const string LOG_FILE_PATH = "Library/Shader Compilation Results.txt";
private static readonly ShaderKeyword[] SKIPPED_VARIANTS = new ShaderKeyword[]
{
new ShaderKeyword( "DIRECTIONAL_COOKIE" ),
new ShaderKeyword( "POINT_COOKIE" ),
//new ShaderKeyword( "LIGHTPROBE_SH" ), // Apparently used by lightmapping, as well
};
public int callbackOrder { get { return 0; } }
public void OnProcessShader( Shader shader, ShaderSnippetData snippet, IList<ShaderCompilerData> data )
{
// Don't strip essential shaders
string shaderName = shader.name;
if( shaderName.StartsWith( "Hidden/" ) || shaderName.StartsWith( "Unlit/" ) || shaderName.StartsWith( "Legacy Shaders/" ) || shaderName.StartsWith( "Particles/" ) )
return;
#if SHADER_COMPILATION_LOGGING
System.IO.File.AppendAllText( LOG_FILE_PATH, "\n\n\n\n===== " + shader.name + " " + snippet.passName + " " + snippet.passType + " " + snippet.shaderType + "\n" );
#endif
if( snippet.passType == PassType.Deferred || snippet.passType == PassType.LightPrePassBase || snippet.passType == PassType.LightPrePassFinal || snippet.passType == PassType.ScriptableRenderPipeline || snippet.passType == PassType.ScriptableRenderPipelineDefaultUnlit )
{
#if SHADER_COMPILATION_LOGGING
System.IO.File.AppendAllText( LOG_FILE_PATH, "Skipped shader variant because it uses SRP or Deferred shading\n" );
#endif
data.Clear();
}
for( int i = data.Count - 1; i >= 0; --i )
{
bool shouldSkipShaderVariant = false;
foreach( ShaderKeyword keywordToSkip in SKIPPED_VARIANTS )
{
if( data[i].shaderKeywordSet.IsEnabled( keywordToSkip ) )
{
shouldSkipShaderVariant = true;
break;
}
}
if( shouldSkipShaderVariant )
{
data.RemoveAt( i );
continue;
}
#if SHADER_COMPILATION_LOGGING
string keywords = "";
foreach( ShaderKeyword keyword in data[i].shaderKeywordSet.GetShaderKeywords() )
keywords += keyword.GetKeywordName() + " ";
if( keywords.Length == 0 )
keywords = "No keywords defined";
System.IO.File.AppendAllText( LOG_FILE_PATH, "- " + keywords + "\n" );
#endif
}
#if SKIP_SHADER_COMPILATION
for( int i = data.Count - 1; i >= 0; --i )
data.Clear();
#endif
}
}
@yasirkula
Copy link
Author

How To

Simply create a folder called Editor inside your Project window and add this script inside it.

This script is configured for Unity's built-in render pipeline with Forward rendering used (which is the case for most hyper-casual/casual mobile games).

  • Shaders in Hidden, Unlit, Legacy Shaders and Particles categories aren't stripped since they don't really have an impact in build size or shader compilation time (plus, let's not break any internal Unity stuff by mistake)
  • Shader variants for URP/LWRP/HDRP and deferred rendering are stripped (yes, Unity can compile SRP variants even when built-in render pipeline is used)
  • Shader variants that use light cookies are stripped (I've rarely seen them used in Unity games)
  • If you don't use fog, set Edit-Project Settings-Graphics-Fog Modes to Custom and disable all 3 fog modes
  • If your project doesn't really benefit from GPU instancing (i.e. it doesn't render thousands of copies of the same object in a scene), set Edit-Project Settings-Graphics-Instancing Variants to Strip All
  • Since we are using Forward rendering, disable Deferred, Deferred Reflections and Legacy Deferred in Edit-Project Settings-Graphics-Built-in Shader Settings
  • Disable Motion Vectors, Light Halo and Lens Flare in Edit-Project Settings-Graphics-Built-in Shader Settings if they aren't used

If you uncomment the #define SHADER_COMPILATION_LOGGING line, all shader variants that get compiled will be logged to UNITY_PROJECT_PATH/Library/Shader Compilation Results.txt after you build your project.

If you uncomment the #define SKIP_SHADER_COMPILATION line, none of the shaders will be compiled during a build. But they will still be logged to Shader Compilation Results.txt so this can be useful if you just want to see which shader variants will be compiled without actually waiting for them to be compiled.

@gakkossphynx
Copy link

Çok Başarılı, Teşekkürler 👍

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment