Last active
June 21, 2026 17:34
-
-
Save adammyhre/a8d21f95b4780035625195b8679fbff0 to your computer and use it in GitHub Desktop.
Shader Function Reflection API Examples
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| // Example 2 — Customizing the node with XML hints (Unity 6.5+) | |
| // | |
| // The same three ingredients as Example 1, plus reflection hints that change | |
| // how the node looks and behaves in Shader Graph: | |
| // | |
| // funchints -> customize the node as a whole (name, search category...) | |
| // paramhints -> customize an individual port (display name, color picker, | |
| // slider range, default value...) | |
| // | |
| // Hint validation is strict and type-aware: | |
| // <sg:Color/> only valid on float3/float4 (and half variants) | |
| // <sg:Range> only valid on a float/half scalar (synonym: Slider) | |
| // <sg:Default> a comma separated list of floats | |
| // | |
| // This node desaturates the input color, then tints it - a quick duotone / | |
| // sepia look driven entirely by the Tint color picker and Strength slider. | |
| #include "ShaderApiReflectionSupport.hlsl" | |
| ///<funchints> | |
| /// <sg:ProviderKey>Malevolent.Colorize</sg:ProviderKey> | |
| /// <sg:DisplayName>Colorize</sg:DisplayName> | |
| /// <sg:SearchCategory>Malevolent/Color</sg:SearchCategory> | |
| ///</funchints> | |
| ///<paramhints name = "tint"> | |
| /// <sg:DisplayName>Tint</sg:DisplayName> | |
| /// <sg:Color/> | |
| /// <sg:Default>1, 0.4, 0.1</sg:Default> | |
| ///</paramhints> | |
| ///<paramhints name = "strength"> | |
| /// <sg:DisplayName>Strength</sg:DisplayName> | |
| /// <sg:Range>0, 1</sg:Range> | |
| /// <sg:Default>0.75</sg:Default> | |
| ///</paramhints> | |
| UNITY_EXPORT_REFLECTION | |
| float3 Colorize(float3 color, float3 tint, float strength) { | |
| float luma = dot(color, float3(0.2126, 0.7152, 0.0722)); | |
| return lerp(color, luma * tint, strength); | |
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| // Example 3 — Procedural energy / lava field (Unity 6.5+) | |
| // | |
| // Two things this example shows off that the first two didn't: | |
| // | |
| // 1. Helper functions. Only the function marked with UNITY_EXPORT_REFLECTION | |
| // becomes a node. Everything else in the file (Hash, ValueNoise, Fbm) is | |
| // just normal HLSL that the exported function is free to call. This is how | |
| // you wrap noise, SDFs, or SRP Shader Library functions behind one clean node. | |
| // | |
| // 2. Multiple outputs via 'out' parameters. The reflection API supports | |
| // in / out / inout parameters and a void return type, so a single node can | |
| // drive both Base Color and Emission on the master stack. | |
| #include "ShaderApiReflectionSupport.hlsl" | |
| // --- Helper functions (not reflected, just plain HLSL) ---------------------- | |
| float Hash(float2 p) { | |
| p = frac(p * float2(123.34, 456.21)); | |
| p += dot(p, p + 45.32); | |
| return frac(p.x * p.y); | |
| } | |
| float ValueNoise(float2 uv) { | |
| float2 i = floor(uv); | |
| float2 f = frac(uv); | |
| float a = Hash(i); | |
| float b = Hash(i + float2(1, 0)); | |
| float c = Hash(i + float2(0, 1)); | |
| float d = Hash(i + float2(1, 1)); | |
| float2 u = f * f * (3.0 - 2.0 * f); | |
| return lerp(lerp(a, b, u.x), lerp(c, d, u.x), u.y); | |
| } | |
| float Fbm(float2 uv) { | |
| float sum = 0.0; | |
| float amp = 0.5; | |
| [unroll] | |
| for (int i = 0; i < 5; i++) { | |
| sum += amp * ValueNoise(uv); | |
| uv *= 2.0; | |
| amp *= 0.5; | |
| } | |
| return sum; | |
| } | |
| // --- The reflected node ----------------------------------------------------- | |
| ///<funchints> | |
| /// <sg:ProviderKey>Malevolent.EnergyField</sg:ProviderKey> | |
| /// <sg:DisplayName>Energy Field</sg:DisplayName> | |
| /// <sg:SearchCategory>Malevolent/Procedural</sg:SearchCategory> | |
| ///</funchints> | |
| ///<paramhints name = "coolColor"> | |
| /// <sg:DisplayName>Cool Color</sg:DisplayName> | |
| /// <sg:Color/> | |
| /// <sg:Default>0.05, 0.0, 0.2</sg:Default> | |
| ///</paramhints> | |
| ///<paramhints name = "hotColor"> | |
| /// <sg:DisplayName>Hot Color</sg:DisplayName> | |
| /// <sg:Color/> | |
| /// <sg:Default>1.0, 0.45, 0.1</sg:Default> | |
| ///</paramhints> | |
| ///<paramhints name = "scale"> | |
| /// <sg:DisplayName>Scale</sg:DisplayName> | |
| /// <sg:Range>1, 16</sg:Range> | |
| /// <sg:Default>4</sg:Default> | |
| ///</paramhints> | |
| ///<paramhints name = "speed"> | |
| /// <sg:DisplayName>Speed</sg:DisplayName> | |
| /// <sg:Range>0, 2</sg:Range> | |
| /// <sg:Default>0.5</sg:Default> | |
| ///</paramhints> | |
| UNITY_EXPORT_REFLECTION | |
| void EnergyField( | |
| float2 uv, | |
| float time, | |
| float3 coolColor, | |
| float3 hotColor, | |
| float scale, | |
| float speed, | |
| out float3 albedo, | |
| out float3 emission) { | |
| float n = Fbm(uv * scale + time * speed); | |
| float ramp = saturate(n * n * 2.0); | |
| albedo = lerp(coolColor, hotColor, ramp); | |
| emission = hotColor * pow(ramp, 3.0) * 4.0; | |
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| // Extra — Wrapping an SRP Shader Library function (Unity 6.5+) | |
| // | |
| // One of the headline use cases for the reflection API: surfacing functions | |
| // that already live in the SRP Shader Library without writing a Custom Function | |
| // node by hand. Here we expose Unity's perceptual-quality desaturation helper | |
| // (Luminance + a simple saturation control) as a one-click node. | |
| // | |
| // Because the file includes Color.hlsl, the wrapped function has access to | |
| // everything in the URP/Core shader library. | |
| #include "ShaderApiReflectionSupport.hlsl" | |
| #include "Packages/com.unity.render-pipelines.core/ShaderLibrary/Color.hlsl" | |
| ///<funchints> | |
| /// <sg:ProviderKey>Malevolent.Saturation</sg:ProviderKey> | |
| /// <sg:DisplayName>Saturation</sg:DisplayName> | |
| /// <sg:SearchCategory>Malevolent/Color</sg:SearchCategory> | |
| ///</funchints> | |
| ///<paramhints name = "amount"> | |
| /// <sg:DisplayName>Amount</sg:DisplayName> | |
| /// <sg:Range>0, 2</sg:Range> | |
| /// <sg:Default>1</sg:Default> | |
| ///</paramhints> | |
| UNITY_EXPORT_REFLECTION | |
| float3 Saturation(float3 color, float amount) { | |
| // Luminance() comes from the SRP Core Color library include above. | |
| float luma = Luminance(color); | |
| return lerp(luma.xxx, color, amount); | |
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| // Example 1 — Basics of the Shader Function Reflection API (Unity 6.5+) | |
| // | |
| // Three ingredients are all you need to turn a plain HLSL function into a | |
| // Shader Graph node: | |
| // 1. #include "ShaderApiReflectionSupport.hlsl" (gives us the macro) | |
| // 2. UNITY_EXPORT_REFLECTION (marks the function for reflection) | |
| // 3. an <sg:ProviderKey> hint (makes it show up in the Create Node menu) | |
| // | |
| // Input/output ports are reflected straight from the function signature, so | |
| // the three parameters below become three input ports, and the float2 return | |
| // value becomes the output port. | |
| #include "ShaderApiReflectionSupport.hlsl" | |
| ///<funchints> | |
| ///</funchints> | |
| ///<funchints> | |
| /// <sg:ProviderKey>Malevolent.ScrollingUV</sg:ProviderKey> | |
| /// <sg:SearchCategory>Malevolent/UV</sg:SearchCategory> | |
| ///</funchints> | |
| UNITY_EXPORT_REFLECTION | |
| float2 ScrollingUV(float2 uv, float2 speed, float time) { | |
| return uv + frac(speed * time); | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment