Skip to content

Instantly share code, notes, and snippets.

@kraj0t
Last active April 30, 2024 16:16
Show Gist options
  • Save kraj0t/3275c44b1d200b9997e625d66f1be9f1 to your computer and use it in GitHub Desktop.
Save kraj0t/3275c44b1d200b9997e625d66f1be9f1 to your computer and use it in GitHub Desktop.
How to include C# code in an HLSL file - useful for sharing code between CPU and shader without duplicating any files
// Share code between HLSL (shaders) and C#
//
// Limitations:
// - Cannot use #include
// - Must use defines to hide certain keywords, such as public, private, protected, or any other object-oriented programming keywords
// - Use defines to convert half or fixed to your desired C# equivalent
// - Must always write f after float literals
// - Use #if !MY_DEFINE instead of #ifndef MY_DEFINE
// - #define cannot be used with a value in C#, not even inside an '#if SHADER_TARGET' block. Therefore, you have two options for declaring valued constants:
// a. Declare each constant separately in HLSL (using 'static const float MyConstant = 1.0f') and in C# (using 'const float MyConstant = 1.0f'). C# does not support 'static const'.
// b. Declare the constants inside the methods in your shared code using 'const float MyConstant = 1.0f;'
// Include guard that works identically in both HLSL and C#
#if !MY_CODE_INCLUDED
#define MY_CODE_INCLUDED
// SHADER_TARGET is a preprocessor directive that is defined for shaders, but not for C# code. We can use it to know if we are being included from a shader.
#if SHADER_TARGET
// HLSL exclusive header section: HLSL constants, macros, remove the C# keywords...
// These defines let your C# code use certain keywords normally, because they will get replaced with "" in HLSL. Feel free to add others.
#define public
#define private
#define internal
#else
// C# exclusive header section: references, class, namespace...
// The two lines below let you use HLSL syntax in C# such as float3, mul, lerp, etc.
using Unity.Mathematics;
using static Unity.Mathematics.math;
public static class UsingCsCodeInHLSL
{
#endif
//////// SHARED CODE START ////////
float3 TestFunctionWrittenInCs(float3 color)
{
float lum = dot(color, float3(0.2126f, 0.7152f, 0.0722f));
return float3(lum, lum, lum);
}
//////// SHARED CODE END ////////
// End the C# class
#if !SHADER_TARGET
}
#endif
#endif // MY_CODE_INCLUDED
Shader "Unlit/UsingCsCodeInHLSL"
{
Properties
{
_MainTex ("Texture", 2D) = "white" {}
}
SubShader
{
Pass
{
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
// Include the C# file
#include "UsingCsCodeInHLSL.cs"
struct v2f
{
float2 uv : TEXCOORD0;
float4 vertex : SV_POSITION;
};
sampler2D _MainTex;
float4 _MainTex_ST;
v2f vert (float4 vertex : POSITION, float2 uv : TEXCOORD0)
{
v2f o;
o.vertex = UnityObjectToClipPos(vertex);
o.uv = uv;
return o;
}
fixed4 frag (v2f i) : SV_Target
{
fixed4 col = tex2D(_MainTex, i.uv);
// Use the C# code!
col.rgb = TestFunctionWrittenInCs(col.rgb);
return col;
}
ENDCG
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment