// Copyright UShaderLab. All Rights Reserved. // Substrate-mode surface/BSDF output structs. Included by ShaderLabCommon.ush only when // SHADERLAB_SUBSTRATE != 0 (i.e. the project runs with r.Substrate=1). The legacy (non-Substrate) // counterpart is Surface_Legacy.ush. Keeping the two schemes in separate files makes the legacy path // deletable wholesale once UE drops the non-Substrate rendering path. #pragma once // 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. --- // 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; }; 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; } 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; }