Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,8 @@ npx skills add Unity-Technologies/skills
| `ui-uitk` | UI Toolkit (Unity 6.0+) — author UXML/USS, flex layout, custom elements, Painter2D, runtime binding |
| `ui-ugui` | uGUI — Canvas hierarchies, RectTransform anchoring, Layout Groups, prefab UI |
| `ui-imgui` | IMGUI editor tooling — EditorWindows, custom Inspectors, PropertyDrawers |
| `validate-urp-render-graph-renderer-feature` | Reviews a Unity 6+ URP `ScriptableRendererFeature` built on Render Graph |
| `shader-graph-create-custom-node` | Custom Shader Graph nodes from HLSL |

## Usage

Expand Down
25 changes: 25 additions & 0 deletions skills/shader-graph-create-custom-node/SKILL.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
---
name: shader-graph-create-custom-node
description: "Generates custom Shader Graph nodes from HLSL code. Use when the user wants to create a new Shader Graph node or make existing HLSL code work as a reflected function node."
required_packages:
com.unity.shadergraph: ">=17.5.0"
---
# Generating a custom Shader Graph node

## Step 1: Generate an HLSL function definition
- The function must be preceded by the preprocessor define `UNITY_EXPORT_REFLECTION`

## Step 2: Decorate with Shader Graph hint tags
- See `resources/all_hints.hlsl` for all valid hint tags and usage patterns
- C#-style documentation tags are supported outside of `funchints` or `paramhints` blocks
- Required function hints:
- `sg:ProviderKey`
- `sg:SearchCategory`
- `sg:SearchTerms`
- `sg:DisplayName`

## Step 3: Write the code to an asset
- Search the project for a `ShaderInclude` asset (`.hlsl`) that already contains custom Shader Graph nodes
- If a matching asset exists, show the user its current contents and ask for confirmation before appending the new code
- If no matching asset exists, create a new `.hlsl` asset
- Ensure the file begins with `#include "ShaderApiReflectionSupport.hlsl"`
182 changes: 182 additions & 0 deletions skills/shader-graph-create-custom-node/resources/all_hints.hlsl
Original file line number Diff line number Diff line change
@@ -0,0 +1,182 @@
#include "ShaderApiReflectionSupport.hlsl"

namespace Namespace
{
struct CustomStruct
{
float Value;
};

/// <funchints>
/// <sg:ProviderKey>AllHintsUniqueStableID</sg:ProviderKey>
/// <sg:DisplayName>All Known Hints</sg:DisplayName>
/// <sg:ReturnDisplayName>Final Result</sg:ReturnDisplayName>
/// <sg:SearchCategory>Hints/All</sg:SearchCategory>
/// <sg:SearchTerms>Features, Reflected, Every, Hint</sg:SearchTerms>
/// <sg:SearchName>All Hints Search Name</sg:SearchName>
/// </funchints>
/// <paramhints name="a">
/// <sg:DisplayName>Custom Struct Value</sg:DisplayName>
/// <sg:Default>0.5</sg:Default>
/// <sg:External>Namespace</sg:External>
/// </paramhints>
/// <paramhints name="c3">
/// <sg:DisplayName>Color 3</sg:DisplayName>
/// <sg:Color />
/// <sg:Default>1,1,0</sg:Default>
/// </paramhints>
/// <paramhints name="c4">
/// <sg:DisplayName>Color 4</sg:DisplayName>
/// <sg:Color />
/// <sg:Default>1,1,0,1</sg:Default>
/// </paramhints>
/// <paramhints name="sc3">
/// <sg:DisplayName>Static Color 3</sg:DisplayName>
/// <sg:Color />
/// <sg:Static />
/// <sg:Default>1,1,0</sg:Default>
/// </paramhints>
/// <paramhints name="sc4">
/// <sg:DisplayName>Static Color 4</sg:DisplayName>
/// <sg:Color />
/// <sg:Static />
/// <sg:Default>1,1,0,1</sg:Default>
/// </paramhints>
/// <paramhints name="d">
/// <sg:DisplayName>Dropdown</sg:DisplayName>
/// <sg:Dropdown>OptionA, OptionB, OptionC</sg:Dropdown>
/// <sg:Default>1</sg:Default>
/// </paramhints>
/// <paramhints name="sd">
/// <sg:DisplayName>Dropdown</sg:DisplayName>
/// <sg:Dropdown>OptionA, OptionB, OptionC</sg:Dropdown>
/// <sg:Static />
/// <sg:Default>2</sg:Default>
/// </paramhints>
/// <paramhints name="r">
/// <sg:DisplayName>Range</sg:DisplayName>
/// <sg:Range>0, 1</sg:Range>
/// <sg:Default>0.75</sg:Default>
/// </paramhints>
/// <paramhints name="sr">
/// <sg:DisplayName>Range</sg:DisplayName>
/// <sg:Static />
/// <sg:Range>0, 1</sg:Range>
/// <sg:Default>0.25</sg:Default>
/// </paramhints>
/// <paramhints name="sb">
/// <sg:DisplayName>Toggle</sg:DisplayName>
/// <sg:Static />
/// <sg:Default>1</sg:Default>
/// </paramhints>
/// <paramhints name="si">
/// <sg:DisplayName>Integer</sg:DisplayName>
/// <sg:Static />
/// <sg:Default>5</sg:Default>
/// </paramhints>
UNITY_EXPORT_REFLECTION float3 AllHints(
inout CustomStruct a,
float3 c3,
inout float4 c4,
float3 sc3,
float4 sc4,
inout uint d,
uint sd,
float r,
float sr,
bool sb,
int si
)
{
return float3(a.Value, sr, sc4.r);
}

} // Namespace

/// <funchints>
/// <sg:ProviderKey>GoodReferables</sg:ProviderKey>
/// </funchints>
/// <paramhints name="UV">
/// <UV/>
/// <Default>UV2</Default>
/// </paramhints>
/// <paramhints name="alsoUV">
/// <sg:Referable>UV</sg:Referable>
/// <Default>UV1</Default>
/// </paramhints>
/// <paramhints name="Position">
/// <Position/>
/// <Default>AbsoluteWorld</Default>
/// </paramhints>
/// <paramhints name="Normal">
/// <Normal/>
/// <Default>World</Default>
/// </paramhints>
/// <paramhints name="Tangent">
/// <Tangent/>
/// <Default>Object</Default>
/// </paramhints>
/// <paramhints name="Bitangent">
/// <Bitangent/>
/// <Default>Tangent</Default>
/// </paramhints>
/// <paramhints name="ViewDirection">
/// <ViewDirection/>
/// <Default>Screen</Default>
/// </paramhints>
/// <paramhints name="VertColor">
/// <VertexColor/>
/// </paramhints>
/// <paramhints name="ScreenPosition">
/// <ScreenPosition/>
/// <Default>Pixel</Default>
/// </paramhints>
/// <paramhints name="defaultValue">
/// <Default>1,0,0</Default>
/// </paramhints>
UNITY_EXPORT_REFLECTION float3 ReferableGood(float2 UV,
float2 alsoUV,
float3 Position,
float3 Normal,
float3 Tangent,
float3 Bitangent,
float3 ViewDirection,
float4 VertColor,
float4 ScreenPosition,
float3 defaultValue)
{
return float3(1,1,0);
}

/// <funchints>
/// <sg:ProviderKey>PrecisionTest</sg:ProviderKey>
/// <Precision/>
/// </funchints>
/// <paramhints name="a">
/// <Dynamic/>
/// </paramhints>
/// <paramhints name="b">
/// <Dynamic/>
/// </paramhints>
/// <paramhints name="c">
/// <Dynamic/>
/// </paramhints>
UNITY_EXPORT_REFLECTION float2 PrecisionTest(float a, half b, out float c)
{
c = a + b;
return (a,b);
}

/// <funchints>
/// <sg:ProviderKey>LinkageExample</sg:ProviderKey>
/// </funchints>
/// <paramhints name="test">
/// <Linkage>other</Linkage>
/// </paramhints>
UNITY_EXPORT_REFLECTION float3 LinkageExample(bool test, float other)
{
if (test)
return float3(other, 0, 0);
else
return float3(0, other, 0);
}
Loading