Language Overview语言概览

NeoX shaders are written in a custom HLSL dialect that extends standard HLSL with engine-specific types, conventions, and cross-platform macros. The same source compiles to D3D11, OpenGL ES 3.0, and Metal via preprocessing.

NeoX 着色器使用自定义 HLSL 方言编写,在标准 HLSL 基础上扩展了引擎特定类型、约定和跨平台宏。同一份源码通过预处理编译为 D3D11、OpenGL ES 3.0 和 Metal。

Key difference from UE5: UE5 uses .usf/.ush files with a heavy macro layer (DECLARE_UNIFORM_BUFFER, FMaterialPixelParameters, etc.). NeoX uses cleaner, more direct HLSL — closer to what you'd write by hand — with struct-based interfaces (Material, View, Light, Fragment). 与 UE5 的关键差异:UE5 使用 .usf/.ush 文件配合厚重的宏层(DECLARE_UNIFORM_BUFFERFMaterialPixelParameters 等)。NeoX 使用更简洁、更直接的 HLSL——更接近手写——通过结构体接口(MaterialViewLightFragment)。

Core Data Types — The Four Struct Interface核心数据类型 — 四大结构体接口

All NeoX shaders communicate through four fundamental structs. This is the engine's "shader contract":

所有 NeoX 着色器通过四个基础结构体通信。这是引擎的"Shader 契约":

+=================================================================+ | NeoX Shader Data Flow | +=================================================================+ | | | +----------+ vs_main() +----------+ | | | Vertex | ===============>| Fragment | | | +----------+ +----+-----+ | | (input mesh) | | | v | | +--------------+ | | | ps_main() | | | +------+-------+ | | | | | +--------------+--------------+ | | v v v | | +----------+ +----------+ +----------+ | | | Material | | View | | Light | | | +----------+ +----------+ +----------+ | | albedo position direction | | normal direction color | | roughness distance attenuation | | metalness | | occlusion | | emissive | | shading_model | | | | +--------------+ | | |LightingResult| <== output | | +--------------+ | | direct_diff | | direct_spec | | env_diff | | env_spec | +=================================================================+
// Engine-provided structs (defined by pipeline)

struct Fragment {
  float4 position;           // SV_Position (clip space)
  float3 position_world;     // world-space position
  float4 position_screen;    // screen-space position
  float2 texcoord0;          // UV channel 0
  float3 normal_world;       // interpolated normal
  float3 tangent_world;      // interpolated tangent
  float3 binormal_world;     // interpolated binormal
};

struct Material {
  float3 albedo;             // base color (linear)
  float3 normal;             // world normal (after normal map)
  float  roughness;          // [0..1]
  float  metalness;          // [0..1]
  float  specular;           // specular intensity
  float  occlusion;          // ambient occlusion
  float3 emissive;           // self-illumination
  float3 tangent;            // for anisotropy / hair
  float4 sh;                 // spherical harmonics data
  uint   shading_model;      // enum: Isotropy, Skin, Hair...
  float  two_sided_sign;     // face direction sign
};

struct View {
  float3 position;           // camera world position
  float3 direction;          // normalized view direction
  float  distance;           // camera-to-pixel distance
};

struct Light {
  float3 direction;          // light direction (normalized)
  float3 color;              // light color * intensity
  float  attenuation;        // distance attenuation
};

Entry Points — vs_main / ps_main入口函数 — vs_main / ps_main

Every NeoX shader has two mandatory entry points. The vertex shader transforms geometry; the pixel shader evaluates materials and lighting:

每个 NeoX 着色器有两个必需入口点。顶点着色器变换几何体;像素着色器计算材质和光照:

// Vertex Shader (from forward_shading.hlsl)
Fragment vs_main(Vertex input) {
  Fragment frag = (Fragment)0;
  CommonVertex vert = TransformCommonVertex(input, vert_inter);
  
  ApplyVertexOffsetLocal(vert, vert.position);
  #if GPU_SKIN_ENABLE
    DoSkin(vert.blendWeights, vert.blendIndices, ...);
  #endif
  
  float4 world_position = Transform(vert.world_mat, vert.position);
  SetupFragment(vert, vert_inter, mtl_vtx_params, world_position, frag);
  return frag;
}

// Pixel Shader
float4 ps_main(Fragment input, bool is_front_face : SV_IsFrontFace) : SV_Target0 {
  Material mtl = (Material)0;
  View v = (View)0;
  v.position = CameraPosition;
  v.direction = normalize(input.position_world - CameraPosition);
  
  RawData raw_data = GetRawData(input);   // sample textures
  SetupMaterial(input, raw_data, mtl);    // fill Material struct
  
  // ... lighting calculation ...
  return final_color;
}

Cross-Platform Macros跨平台宏

NeoX targets three graphics APIs from a single source. Platform differences are resolved via these macros:

NeoX 从单一源码目标化三种图形 API。平台差异通过以下宏解决:

Macro Meaning含义 Use Case使用场景
NEOX_GLSLCompiling for OpenGL ES编译为 OpenGL ESUV Y-flip, depth range [0,1] vs [-1,1]UV Y翻转、深度范围差异
NEOX_METALCompiling for Metal编译为 MetalBuffer layout, texture access patternsBuffer 布局、纹理访问模式
GPU_SKIN_ENABLEGPU skinning activeGPU 蒙皮激活Bone transform in vertex shader顶点着色器中骨骼变换
NORMAL_MAP_ENABLENormal map bound法线贴图已绑定TBN transform for normal decoding法线解码的 TBN 变换
LIGHT_ENABLELighting active光照激活Include lighting.hlsl包含 lighting.hlsl
SHADOW_MAP_ENABLEShadow mapping active阴影贴图激活Include shadow.hlsl, sample shadow map包含 shadow.hlsl、采样阴影贴图
INSTANCE_TYPEInstancing mode实例化模式NONE / PRS / PRS_LM / VEGETATION / SKINNING
LOD_LEVELQuality LOD tier品质 LOD 层级Controls IBL, reflection probe quality控制 IBL、反射探针品质
// Platform-specific depth handling example
#ifdef NEOX_GLSL
  float depth = -(2 * output.z - 1);      // GL: [-1,1] range
#else
  float depth = 1 - output.z;              // D3D: [0,1] range
#endif

// Screen UV Y-flip for D3D
#ifndef NEOX_GLSL
  input.position_screen.y = 1 - input.position_screen.y;
#endif

Include Hierarchy包含层级

NeoX shaders follow a strict include hierarchy. Understanding this tree is essential for navigation:

NeoX 着色器遵循严格的包含层级。理解这棵树对导航至关重要:

forward_shading.hlsl (or deferred_shading_gbuffer.hlsl) +-- built_in/shadow/shadow.hlsl // shadow sampling (Render 3.0: CSM sphere-cull) +-- built_in/common/decal.hlsl // deferred decal application +-- built_in/common/lighting.hlsl // 1447 lines (was 1982), the lighting core | +-- built_in/common/function.hlsl // 977 lines (was 782), math utilities | +-- built_in/brdf/ggx/brdf.hlsl // BRDF functions | +-- built_in/common/rect_lighting.hlsl // NEW: extracted area-light functions | +-- built_in/common/ssss.hlsl // NEW: extracted SSS transmittance | +-- built_in/common/spherical_gaussian.hlsl // NEW: bent normal SG math | +-- built_in/common/gbuffer_struct.hlsl // NEW: shared GBuffer struct | +-- built_in/shading_models/ // per-model lighting | +-- isotropy.hlsl | +-- skin.hlsl | +-- hair.hlsl | +-- clearcoat.hlsl | +-- toon.hlsl | +-- cloth.hlsl (NEW) | +-- glint.hlsl (NEW) | +-- sheen.hlsl (NEW) | +-- water.hlsl (NEW) | +-- ... (16 models total, was 13) +-- built_in/debug/debug.hlsl // debug visualization material_*.hlsl (per-material code) +-- built_in/materials/material_common.hlsl // shared material interface
New vs replaced: The new lighting.hlsl (1,447 lines) replaces the old monolithic 1,982-line version by extracting area lights, SSS, and SG math into separate files (rect_lighting.hlsl, ssss.hlsl, spherical_gaussian.hlsl). New shading models added: cloth, glint, sheen, water (16 total, up from 13). shading_models/mobile_pbr.hlsl was removed (functionality merged into isotropy). All other shading model files in res/shader/ are still accessible to the new engine via fallback. 新版替换:lighting.hlsl(1,447 行)通过将区域光、SSS 和 SG 数学提取到独立文件(rect_lighting.hlslssss.hlslspherical_gaussian.hlsl)替换了旧版 1,982 行单体版本。新增着色模型:clothglintsheenwater(总计 16 个,从 13 个增加)。shading_models/mobile_pbr.hlsl 已移除(功能合并到 isotropy)。res/shader/ 中的所有其他着色模型文件仍通过回退机制对新引擎可用。

Utility Library — function.hlsl (977 lines)工具函数库 — function.hlsl (977 行)

The function.hlsl library provides optimized math primitives used throughout the entire shader codebase. It grew from 782 to 977 lines in the new engine:

function.hlsl 库提供整个着色器代码库中使用的优化数学原语。新引擎中从 782 行增长到 977 行:

Category类别 Functions函数 Description说明
Power幂运算Pow2, Pow3, Pow4, Pow5, PositiveClampedZeroPowFaster than pow() — unrolled multiplies; new: clamp-negative-base variant比 pow() 更快;新增:负基值截断变体
Fast trig快速三角acosFast, asinFast, atanFastPolynomial approximations (max error <0.01)多项式近似(最大误差 <0.01)
Color space色域转换srgb2linear, linear2srgb, RGB2HSV, HSV2RGB, RGB2YCoCg, YCoCg2RGBGamma/linear + new YCoCg color spaceGamma/线性 + 新增 YCoCg 色彩空间
Normal encoding法线编码6 schemes: Octahedron, Paraboloid...6 种方案GBuffer packing for deferred path延迟路径的 GBuffer 打包
Bit packing位打包PackFloatToRGBA, PackHalfFloat, PackFloat2ToRGBA, spvUnpackSnorm4x8Encode float/float2 to RGBA8; new SPIR-V snorm unpack浮点/float2 编码为 RGBA8;新增 SPIR-V snorm 解包
Dither抖动Dither16, Dither32, Dither64, Dither17Bayer matrix patterns for alpha ditheringBayer 矩阵图案用于 Alpha 抖动
Depth / Position深度/位置重建GetViewPositionFromDepth, GetWorldPositionFromDepthReconstruct view/world-space position from depth (new: world-space via InverseView)从深度重建视/世界空间位置(新增:通过 InverseView 的世界空间版本)
Mip levelMip 级别ComputeMipLevel, ComputeMipLevelAnisoNEW: manual mip level calculation from ddx/ddy新增:通过 ddx/ddy 手动计算 Mip 级别
Physical light物理光照CalculateBlackBodyNEW: black body radiator color from Kelvin temperature新增:由开尔文温度计算黑体辐射颜色
Tile memoryTile 内存GetDepthFromTileMemory, PixelWithDepthNEW: TBDR on-chip depth readback (mobile)新增:TBDR 片上深度回读(移动端)
UV utilitiesUV 工具CubeUV2EquirectangularUVNEW: cubemap to equirectangular UV remapping新增:立方体贴图到等距矩形 UV 重映射
New vs replaced: The new function.hlsl (977 lines) replaces the old 782-line version. New functions added: PositiveClampedZeroPow, RGB2YCoCg/YCoCg2RGB, GetWorldPositionFromDepth, PackFloat2ToRGBA, ComputeMipLevel, CalculateBlackBody, tile memory helpers, CubeUV2EquirectangularUV. Bug fixes: srgb2linear_real now explicitly initializes float real = 0.0f (was uninitialized). All old utility functions remain available. 新版替换:function.hlsl(977 行)替换旧版 782 行版本。新增函数:PositiveClampedZeroPowRGB2YCoCg/YCoCg2RGBGetWorldPositionFromDepthPackFloat2ToRGBAComputeMipLevelCalculateBlackBody、Tile 内存辅助函数、CubeUV2EquirectangularUV。Bug 修复:srgb2linear_real 现在显式初始化 float real = 0.0f(旧版未初始化)。所有旧版工具函数均保留。