Files
UShaderLab/Shaders/Private/ShaderLabCommon.ush
2026-07-05 19:37:06 +08:00

202 lines
6.8 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
// ---------------------------------------------------------------------------
// 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
// `<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