// 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 // --------------------------------------------------------------------------- // SHADERLAB_SUBSTRATE — the project-level rendering scheme, derived from the engine's own SUBSTRATE_ENABLED // shader define (set from r.Substrate at material-shader-environment build time, ShaderCompiler.cpp). This // selects which surface-struct parameterization the SL_SURFACE body sees. It is a compile-time constant for // the whole material (Substrate is project-wide, not per-material), so it needs no per-permutation leak. // The C++ graph builder branches on the same source (Substrate::IsSubstrateEnabled()), keeping the two in sync. // --------------------------------------------------------------------------- #ifndef SHADERLAB_SUBSTRATE #ifdef SHADERLAB_IDE #define SHADERLAB_SUBSTRATE 1 // IDE default (Substrate authoring); override in shader-validator defines to check legacy. #elif defined(SUBSTRATE_ENABLED) #define SHADERLAB_SUBSTRATE SUBSTRATE_ENABLED #else #define SHADERLAB_SUBSTRATE 0 // Fallback if the engine define is somehow absent: bias to the legacy // (deletable) path. In practice SUBSTRATE_ENABLED is always set for // material shaders, so this branch is not expected to be taken. #endif #endif // Mode-specific surface/BSDF structs live in split files so the legacy scheme is deletable wholesale. #if SHADERLAB_SUBSTRATE #include "/Plugin/ShaderLab/Private/Surface_Substrate.ush" #else #include "/Plugin/ShaderLab/Private/Surface_Legacy.ush" #endif // --- Mode-independent output structs (identical fields/semantics in both schemes). --- // Unlit BSDF (SL_UNLIT): pure emissive / transmittance, no lighting. Under Substrate -> UnlitBSDF; // under legacy -> MSM_Unlit (only EmissiveColor feeds MP_EmissiveColor). Struct is shared either way. struct FShaderLabUnlit { float3 EmissiveColor; float3 TransmittanceColor; float3 Normal; }; FShaderLabUnlit ShaderLabDefaultUnlit() { FShaderLabUnlit U; U.EmissiveColor = float3(0, 0, 0); U.TransmittanceColor = float3(1, 1, 1); U.Normal = float3(0, 0, 1); return U; } // 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; }; 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 // `.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