Files
UShaderLab/Shaders/Private/ShaderLabCommon.ush
2026-07-05 13:23:08 +08:00

494 lines
13 KiB
Plaintext

// Copyright UShaderLab. All Rights Reserved.
// Shared struct definitions for ShaderLab-generated Custom HLSL nodes.
// Included by every generated UMaterialExpressionCustom node via IncludeFilePaths.
#pragma once
// Per-pixel/vertex inputs are read through `UE_NodeName(...)` intrinsics (resolved by the graph
// builder to real material expression nodes), not through a context struct.
// ---------------------------------------------------------------------------
// Read-only project/engine-driven permutation macros. The graph builder leaks SHADERLAB_QUALITY /
// SHADERLAB_FEATURELEVEL / SHADERLAB_SHADINGPATH (via a before-attributes QualitySwitch/FeatureLevelSwitch/
// ShadingPathSwitch, same mechanism as static switches) so a body can `#if` on them to adapt per permutation.
// These are NOT author-settable — the engine picks the permutation. Compare against the ordered constants
// below (ordered low->high so `<=`/`>=` are meaningful).
// ---------------------------------------------------------------------------
#define QUALITY_LOW 0
#define QUALITY_MEDIUM 1
#define QUALITY_HIGH 2
#define QUALITY_EPIC 3
#define FEATURELEVEL_ES31 0
#define FEATURELEVEL_SM5 1
#define FEATURELEVEL_SM6 2
#define SHADINGPATH_DEFERRED 0
#define SHADINGPATH_FORWARD 1
#define SHADINGPATH_MOBILE 2
#ifdef SHADERLAB_IDE
// IDE only: give the leaked macros a default so `#if SHADERLAB_QUALITY ...` completes/checks. At real
// compile these come from the graph's before-attributes switch nodes (SHADERLAB_IDE is never defined then).
#ifndef SHADERLAB_QUALITY
#define SHADERLAB_QUALITY QUALITY_HIGH
#endif
#ifndef SHADERLAB_FEATURELEVEL
#define SHADERLAB_FEATURELEVEL FEATURELEVEL_SM6
#endif
#ifndef SHADERLAB_SHADINGPATH
#define SHADERLAB_SHADINGPATH SHADINGPATH_DEFERRED
#endif
#endif
// A single Substrate Slab BSDF layer, filled by an SL_SLAB() body in a multi-slab shader. These 18 fields
// mirror the pins of UMaterialExpressionSubstrateSlabBSDF one-for-one (name/order/type). A slab is only a
// BSDF layer — material-level outputs (Opacity/Refraction/...) are NOT slab concerns: set them once per
// material via an SL_MATERIAL() block (FShaderLabMaterialOutput). Defaults mirror the node's pin defaults.
struct FShaderLabSlab
{
float3 DiffuseAlbedo;
float3 F0;
float3 F90;
float Roughness;
float Anisotropy;
float3 Normal;
float3 Tangent;
float3 SSSMFP;
float SSSMFPScale;
float SSSPhaseAnisotropy;
float3 EmissiveColor;
float SecondRoughness;
float SecondRoughnessWeight;
float FuzzRoughness;
float FuzzAmount;
float3 FuzzColor;
float GlintValue;
float2 GlintUV;
};
// Material-level (whole-material) pixel-stage outputs, filled by an SL_MATERIAL() block in a multi-slab
// shader. Each field maps to a main-material-node pin (NOT a slab pin); which are active depends on the
// material Domain/BlendMode (validated by the graph builder mirroring the engine's IsPropertyActive):
// Opacity — translucency coverage (routed through a Substrate Weight over the material)
// OpacityMask — Masked blend cutout
// Refraction — scalar IOR (RefractionMethod = IndexOfRefraction); 1.0 = no bending
// PixelDepthOffset — world-unit depth push toward camera
// AmbientOcclusion — ambient occlusion (Lit)
// SurfaceThickness — thin-surface thickness in cm (only when the material is a thin surface)
struct FShaderLabMaterialOutput
{
float Opacity;
float OpacityMask;
float Refraction;
float PixelDepthOffset;
float AmbientOcclusion;
float SurfaceThickness;
};
// Simple single-entry surface, filled by the SL_SURFACE(...) body. It is the one-stop path: the 18 Slab
// shading fields (== FShaderLabSlab) PLUS the material-level outputs (== FShaderLabMaterialOutput), so a
// simple opaque/masked/translucent material can be written in one block. Multi-slab shaders instead split
// these across SL_SLAB (FShaderLabSlab) + SL_MATERIAL (FShaderLabMaterialOutput). Slab-field defaults
// mirror the SubstrateSlabBSDF pin defaults; material-output defaults mirror the main-node pin defaults.
struct FShaderLabSurface
{
float3 DiffuseAlbedo;
float3 F0;
float3 F90;
float Roughness;
float Anisotropy;
float3 Normal;
float3 Tangent;
float3 SSSMFP;
float SSSMFPScale;
float SSSPhaseAnisotropy;
float3 EmissiveColor;
float SecondRoughness;
float SecondRoughnessWeight;
float FuzzRoughness;
float FuzzAmount;
float3 FuzzColor;
float GlintValue;
float2 GlintUV;
// Material-level outputs (single-Surface sugar). See FShaderLabMaterialOutput for pin semantics.
float Opacity;
float OpacityMask;
float Refraction;
float PixelDepthOffset;
float AmbientOcclusion;
float SurfaceThickness;
};
// --- Additional Substrate BSDF output structs. Each mirrors the pins of its engine BSDF node; the graph
// builder wires only the fields a body writes, leaving the rest at the node's native default. ---
// Unlit BSDF (SL_UNLIT): pure emissive / transmittance, no lighting.
struct FShaderLabUnlit
{
float3 EmissiveColor;
float3 TransmittanceColor;
float3 Normal;
};
// Hair BSDF (SL_HAIR): hair-fiber shading.
struct FShaderLabHair
{
float3 BaseColor;
float Scatter;
float Specular;
float Roughness;
float3 Backlit;
float3 Tangent;
float3 EmissiveColor;
};
// Eye BSDF (SL_EYE): cornea / iris / sclera shading.
struct FShaderLabEye
{
float3 DiffuseColor;
float Roughness;
float3 CorneaNormal;
float3 IrisNormal;
float3 IrisPlaneNormal;
float IrisMask;
float IrisDistance;
float3 EmissiveColor;
};
// Single Layer Water BSDF (SL_WATER): water surface + underwater scattering.
struct FShaderLabWater
{
float3 BaseColor;
float Metallic;
float Specular;
float Roughness;
float3 Normal;
float3 EmissiveColor;
float3 TopMaterialOpacity;
float3 WaterAlbedo;
float3 WaterExtinction;
float WaterPhaseG;
float3 ColorScaleBehindWater;
};
// Volumetric-Fog-Cloud BSDF (SL_VOLUME, Domain = Volume): participating media.
struct FShaderLabVolume
{
float3 Albedo;
float3 Extinction;
float3 EmissiveColor;
float AmbientOcclusion;
};
// Simple Clear Coat BSDF (SL_CLEARCOAT): bottom layer + clear coat top.
struct FShaderLabClearCoat
{
float3 DiffuseAlbedo;
float3 F0;
float Roughness;
float ClearCoatCoverage;
float ClearCoatRoughness;
float3 Normal;
float3 EmissiveColor;
float3 BottomNormal;
};
// Toon BSDF (SL_TOON, experimental): stylized shading.
struct FShaderLabToon
{
float3 BaseColor;
float Metallic;
float Specular;
float Roughness;
float3 Normal;
float3 EmissiveColor;
float2 PatternUVs;
float Anisotropy;
float3 Tangent;
};
// Light Function (SL_LIGHTFUNCTION, Domain = LightFunction): per-light modulation color.
struct FShaderLabLightFunction
{
float3 Color;
};
FShaderLabUnlit ShaderLabDefaultUnlit()
{
FShaderLabUnlit U;
U.EmissiveColor = float3(0, 0, 0);
U.TransmittanceColor = float3(1, 1, 1);
U.Normal = float3(0, 0, 1);
return U;
}
FShaderLabHair ShaderLabDefaultHair()
{
FShaderLabHair H;
H.BaseColor = float3(0, 0, 0);
H.Scatter = 0;
H.Specular = 0.5;
H.Roughness = 0.5;
H.Backlit = float3(0, 0, 0);
H.Tangent = float3(1, 0, 0);
H.EmissiveColor = float3(0, 0, 0);
return H;
}
FShaderLabEye ShaderLabDefaultEye()
{
FShaderLabEye E;
E.DiffuseColor = float3(0, 0, 0);
E.Roughness = 0.5;
E.CorneaNormal = float3(0, 0, 1);
E.IrisNormal = float3(0, 0, 1);
E.IrisPlaneNormal = float3(0, 0, 1);
E.IrisMask = 0;
E.IrisDistance = 0;
E.EmissiveColor = float3(0, 0, 0);
return E;
}
FShaderLabWater ShaderLabDefaultWater()
{
FShaderLabWater W;
W.BaseColor = float3(0, 0, 0);
W.Metallic = 0;
W.Specular = 0.5;
W.Roughness = 0.5;
W.Normal = float3(0, 0, 1);
W.EmissiveColor = float3(0, 0, 0);
W.TopMaterialOpacity = float3(0, 0, 0);
W.WaterAlbedo = float3(0, 0, 0);
W.WaterExtinction = float3(0, 0, 0);
W.WaterPhaseG = 0;
W.ColorScaleBehindWater = float3(1, 1, 1);
return W;
}
FShaderLabVolume ShaderLabDefaultVolume()
{
FShaderLabVolume V;
V.Albedo = float3(0, 0, 0);
V.Extinction = float3(0, 0, 0);
V.EmissiveColor = float3(0, 0, 0);
V.AmbientOcclusion = 1;
return V;
}
FShaderLabClearCoat ShaderLabDefaultClearCoat()
{
FShaderLabClearCoat C;
C.DiffuseAlbedo = float3(0.18, 0.18, 0.18);
C.F0 = float3(0.04, 0.04, 0.04);
C.Roughness = 0.5;
C.ClearCoatCoverage = 0.5;
C.ClearCoatRoughness = 0.5;
C.Normal = float3(0, 0, 1);
C.EmissiveColor = float3(0, 0, 0);
C.BottomNormal = float3(0, 0, 1);
return C;
}
FShaderLabToon ShaderLabDefaultToon()
{
FShaderLabToon T;
T.BaseColor = float3(0.18, 0.18, 0.18);
T.Metallic = 0;
T.Specular = 0.5;
T.Roughness = 0.5;
T.Normal = float3(0, 0, 1);
T.EmissiveColor = float3(0, 0, 0);
T.PatternUVs = float2(0, 0);
T.Anisotropy = 0;
T.Tangent = float3(1, 0, 0);
return T;
}
FShaderLabLightFunction ShaderLabDefaultLightFunction()
{
FShaderLabLightFunction L;
L.Color = float3(1, 1, 1);
return L;
}
// Output for the PostProcess(...) entry (Domain = PostProcess). Color feeds the material EmissiveColor.
struct FShaderLabPostProcess
{
float3 Color;
float Opacity;
};
// Output for the UI(...) entry (Domain = UI). Color feeds EmissiveColor, Opacity the material Opacity.
struct FShaderLabUI
{
float3 Color;
float Opacity;
};
// Vertex-stage outputs filled by the optional Vertex(...) body.
struct FShaderLabVertex
{
float3 WorldPositionOffset;
float Displacement;
// Customized UVs 0-7 (mirrors the engine's 8 MP_CustomizedUVs slots). A written slot i requires
// SL_SETTINGS(NumCustomizedUVs = N) with N > i, otherwise the graph builder errors (writing a slot the
// material never allocates would silently pass through the raw vertex texcoord).
float2 CustomizedUV0;
float2 CustomizedUV1;
float2 CustomizedUV2;
float2 CustomizedUV3;
float2 CustomizedUV4;
float2 CustomizedUV5;
float2 CustomizedUV6;
float2 CustomizedUV7;
};
FShaderLabSurface ShaderLabDefaultSurface()
{
FShaderLabSurface S;
S.DiffuseAlbedo = float3(0.18, 0.18, 0.18);
S.F0 = float3(0.04, 0.04, 0.04);
S.F90 = float3(1, 1, 1);
S.Roughness = 0.5;
S.Anisotropy = 0;
S.Normal = float3(0, 0, 1);
S.Tangent = float3(1, 0, 0);
S.SSSMFP = float3(0, 0, 0);
S.SSSMFPScale = 1;
S.SSSPhaseAnisotropy = 1;
S.EmissiveColor = float3(0, 0, 0);
S.SecondRoughness = 0.5;
S.SecondRoughnessWeight = 0;
S.FuzzRoughness = 0.5;
S.FuzzAmount = 0;
S.FuzzColor = float3(0, 0, 0);
S.GlintValue = 1;
S.GlintUV = float2(0, 0);
S.Opacity = 1;
S.OpacityMask = 1;
S.Refraction = 1.0;
S.PixelDepthOffset = 0.0;
S.AmbientOcclusion = 1;
S.SurfaceThickness = 0.01; // SUBSTRATE_LAYER_DEFAULT_THICKNESS_CM
return S;
}
FShaderLabSlab ShaderLabDefaultSlab()
{
FShaderLabSlab S;
S.DiffuseAlbedo = float3(0.18, 0.18, 0.18);
S.F0 = float3(0.04, 0.04, 0.04);
S.F90 = float3(1, 1, 1);
S.Roughness = 0.5;
S.Anisotropy = 0;
S.Normal = float3(0, 0, 1);
S.Tangent = float3(1, 0, 0);
S.SSSMFP = float3(0, 0, 0);
S.SSSMFPScale = 1;
S.SSSPhaseAnisotropy = 1;
S.EmissiveColor = float3(0, 0, 0);
S.SecondRoughness = 0.5;
S.SecondRoughnessWeight = 0;
S.FuzzRoughness = 0.5;
S.FuzzAmount = 0;
S.FuzzColor = float3(0, 0, 0);
S.GlintValue = 1;
S.GlintUV = float2(0, 0);
return S;
}
FShaderLabMaterialOutput ShaderLabDefaultMaterialOutput()
{
FShaderLabMaterialOutput O;
O.Opacity = 1;
O.OpacityMask = 1;
O.Refraction = 1.0;
O.PixelDepthOffset = 0.0;
O.AmbientOcclusion = 1;
O.SurfaceThickness = 0.01; // SUBSTRATE_LAYER_DEFAULT_THICKNESS_CM
return O;
}
FShaderLabPostProcess ShaderLabDefaultPostProcess()
{
FShaderLabPostProcess P;
P.Color = float3(0, 0, 0);
P.Opacity = 1;
return P;
}
FShaderLabUI ShaderLabDefaultUI()
{
FShaderLabUI U;
U.Color = float3(0, 0, 0);
U.Opacity = 1;
return U;
}
FShaderLabVertex ShaderLabDefaultVertex()
{
FShaderLabVertex V;
V.WorldPositionOffset = float3(0, 0, 0);
V.Displacement = 0;
V.CustomizedUV0 = float2(0, 0);
V.CustomizedUV1 = float2(0, 0);
V.CustomizedUV2 = float2(0, 0);
V.CustomizedUV3 = float2(0, 0);
V.CustomizedUV4 = float2(0, 0);
V.CustomizedUV5 = float2(0, 0);
V.CustomizedUV6 = float2(0, 0);
V.CustomizedUV7 = float2(0, 0);
return V;
}
// Runtime Virtual Texture WRITE channels, filled by an SL_RVTOUTPUT() body. Mirrors the pins of
// UMaterialExpressionRuntimeVirtualTextureOutput; the graph builder wires each written field to the
// matching pin (unwritten fields keep the node's own default). Which fields the RVT actually stores is
// governed by the RVT asset's material type, not this struct.
struct FShaderLabRVTOutput
{
float3 BaseColor;
float Specular;
float Roughness;
float3 Normal;
float WorldHeight;
float Opacity;
float Mask;
float Displacement;
float4 Mask4;
};
FShaderLabRVTOutput ShaderLabDefaultRVTOutput()
{
FShaderLabRVTOutput O;
O.BaseColor = float3(0, 0, 0);
O.Specular = 0.5;
O.Roughness = 0.5;
O.Normal = float3(0, 0, 1);
O.WorldHeight = 0;
O.Opacity = 1;
O.Mask = 1;
O.Displacement = 0;
O.Mask4 = float4(0, 0, 0, 0);
return O;
}
#ifdef SHADERLAB_IDE
// IDE-only: the result struct of an SL_RVTSAMPLE Runtime Virtual Texture READ. A body reads channels via
// `<Name>.BaseColor` etc.; at real compile the graph builder rewrites those member accesses into wired
// inputs carrying the RVT sample node's output pins, so this type never reaches the shader compiler.
struct FShaderLabRVT
{
float3 BaseColor;
float3 Normal;
float Roughness;
float Specular;
float WorldHeight;
float Mask;
float Displacement;
float4 Mask4;
};
#endif // SHADERLAB_IDE