Ever wanted to write complex material functions directly in HLSL? Now you can!
Unreal Engine 4.26, 4.27 and 5.0 are supported. 4.25 cannot be supported as custom nodes have a single output in that version.
Demo: https://twitter.com/phyronnaz/status/1452553917204733953
Discord: https://discord.gg/UjtexdkWxC
Marketplace: https://www.unrealengine.com/marketplace/en-US/product/hlsl-material
- HLSL support: write all your functions in a single hlsl file and use any of them in regular materials
- Team-friendly: regular material functions are generated, so your team members don't need the plugin to use them!
- Live updates: material functions & opened material editors are refreshed when saving the hlsl file (Windows only)
- Comment support: comments are parsed & pin tooltips are set accordingly
- Smart updates: only modified functions are updated
- Texture parameters support
- Bool parameters support
- Define support
- Includes support (with auto updates when included files are edited)
- Default value support
- Clickable errors: errors are properly displayed relative to your file(s), and clicking them will open your IDE
Download the repo as a zip and extract it under your project Plugins folder so you have YourProject/Plugins/HLSLMaterial/HLSLMaterial.uplugin
Visual Studio will be required.
- Create a new
HLSL Material Function Library
(right click Content Browser -> Material & Textures). This asset will be the link between your hlsl file and all the generated material functions. - Set the
File
on it to point to your HLSL file - Add functions to the file
- Material functions will be created when you save the HLSL file
- You can also disable the automatic updates and manually right click the asset ->
Update from HLSL
- All return types must be
void
to ensure the pins are all properly named - To mark a parameter as an output, use
out
: eg,out float3 MyOutput
- Comments must use the
//
syntax,/*
is not supported @param
in comments will be parsed & put into the pin tooltips
// Ray-sphere intersection
// @param RayOrigin The origin of the ray
// @param RayDirection The direction of the ray
// @param SphereCenter The center of the sphere
// @param SphereRadius The radius of the sphere
// @param Distance The distance from the ray origin to the hit on the sphere
void RaySphereIntersect(float3 RayOrigin, float3 RayDirection, float3 SphereCenter, float SphereRadius, out float Distance)
{
float a = dot(RayDirection, RayDirection);
float3 SphereCenterToRayOrigin = RayOrigin - SphereCenter;
float b = 2.0 * dot(RayDirection, SphereCenterToRayOrigin);
float c = dot(SphereCenterToRayOrigin, SphereCenterToRayOrigin) - (SphereRadius * SphereRadius);
float Discriminant = b * b - 4.0 * a* c;
if (Discriminant < 0.0)
{
Distance = -1.0;
}
else
{
Distance = (-b - sqrt(Discriminant)) / 2 * a;
}
}
#define BLUE 1
void Test(
out float3 Color,
float Red = 1.f,
bool Green = false,
Texture2D Texture,
SamplerState TextureSampler,
FMaterialPixelParameters Parameters)
{
Color.r = Red;
Color.g = Green ? 1 : 0;
Color.b = BLUE;
const float2 UVs = GetSceneTextureUV(Parameters);
Color = Texture2DSample(Texture, TextureSampler, UVs);
}
For textures, an additional parameter named YourTextureParameterSampler
of type SamplerState
will automatically be added by Unreal:
void Test(Texture2D MyTexture, float2 UVs, out float3 Color)
{
Color = Texture2DSample(MyTexture, MyTextureSampler, UVs).rgb;
}
The plugin manually parses the functions in the HLSL file. From there, it creates new material functions with a Custom node holding the function body.
The logic is pretty simple & straightforward, so it should be relatively robust.
Material functions are generated next to your library asset, under YourFunctionLibraryAsset_Generated/
.
Once they are generated, you should be able to move them anywhere - the library keeps a ref to them.
If you rename a function in your HLSL file, you need to manually rename the corresponding material function in Unreal, ideally before saving the HLSL. Otherwise, a new one will be created with the new name.
The plugin will never delete any asset. If you remove a function from the HLSL, it is up to you to remove it from Unreal.
You don't need to check in the HLSL file or the library - simply checking in the generated functions should be enough. However, if your teammates are also using the plugin it might be best to check in everything.