Search Unity

  1. Welcome to the Unity Forums! Please take the time to read our Code of Conduct to familiarize yourself with the forum rules and how to post constructively.
  2. Dismiss Notice

Question How to get shader source code from script?

Discussion in 'Shader Graph' started by Misha_Kh, Apr 30, 2021.

  1. Misha_Kh

    Misha_Kh

    Joined:
    Apr 26, 2021
    Posts:
    5
    The main issue I trying to solve is that shader graphs are not working with unity's UI Mask (not maskable). This can be easily fixed by adding a few lines of code into generated shader code. What I try to do, is to automate the process: select shader graph asset in project -> choose menu button -> source code extracted from shader, lines added, new *.shader file created with modified code.
    So, that's the problem: how to get compiled code from script?

    I found out how to get particular Pass code (HLSL Program), but what about ShaderLab part?

    What I can do, is to grab generated code from Temp folder, or copy it from buffer. But for this, I need to press "View Generated Shader" or "Copy Shader"...
     
    UbiBenKenobi likes this.
  2. JohnOknelorfDev

    JohnOknelorfDev

    Joined:
    Oct 2, 2017
    Posts:
    20
    +1

    I would be happy to have this functionality at hand.
     
    Misha_Kh likes this.
  3. Misha_Kh

    Misha_Kh

    Joined:
    Apr 26, 2021
    Posts:
    5
    Personally I ended up with the next flow: choose shaderGraph file, press "Copy Shader" button, then go to my custom menu and launch my custom function - which will grab shader's code from clipboard, parse and modify it, and then creates a new shader file, and imports in via assets database. I'll ask the permission to share the code from my customer, let's see, what he'll answers.
     
  4. patrickb2022

    patrickb2022

    Joined:
    Oct 15, 2022
    Posts:
    2
    Hi, could anybody automate this?
     
  5. leohilbert

    leohilbert

    Joined:
    Nov 28, 2015
    Posts:
    17
    Until there is an official API you can use this (2021.3.18f1):
    Code (CSharp):
    1. private static string GenerateShaderCode(string shaderAssetPath, string shaderName = null)
    2. {
    3.     Type editorType =
    4.         Type.GetType("UnityEditor.ShaderGraph.ShaderGraphImporterEditor, Unity.ShaderGraph.Editor")!;
    5.     Type generatorType =
    6.         Type.GetType("UnityEditor.ShaderGraph.Generator, Unity.ShaderGraph.Editor")!;
    7.     Type modeType =
    8.         Type.GetType("UnityEditor.ShaderGraph.GenerationMode, Unity.ShaderGraph.Editor")!;
    9.  
    10.     MethodInfo method = editorType.GetMethod(
    11.         "<OnInspectorGUI>g__GetGraphData|2_0",
    12.         BindingFlags.NonPublic | BindingFlags.Static
    13.     )!;
    14.     shaderName ??= Path.GetFileNameWithoutExtension(shaderAssetPath);
    15.     var importer = AssetImporter.GetAtPath(shaderAssetPath);
    16.     object graphData = method.Invoke(null, new object[] { importer });
    17.  
    18.     // new Generator(graphData, null, GenerationMode.ForReals, assetName, null, true);
    19.     object forReals = ((FieldInfo)modeType.GetMember("ForReals")[0]).GetValue(null);
    20.     object generator = Activator.CreateInstance(
    21.         generatorType, graphData, null,
    22.         forReals, shaderName, null, true
    23.     );
    24.     object shaderCode = generatorType
    25.         .GetProperty("generatedShader", BindingFlags.Public | BindingFlags.Instance)!
    26.         .GetValue(generator);
    27.  
    28.     return (string)shaderCode;
    29. }
    It's hideous, but it works :D
     
    Last edited: May 26, 2023