---
title: How the Unreal Engine Translates a Material Graph to HLSL
source: https://dev.epicgames.com/community/learning/knowledge-base/0qGY/how-the-unreal-engine-translates-a-material-graph-to-hlsl
authors: Matt Oztalay; co-author Joe Radak
published: 2022-02-15
last_updated: 2026-04-13
fetched: 2026-10-15
note: Epic Developer Community Knowledge Base（官方学习库）；英文要点摘录，供 wiki 引用
---

# How the Unreal Engine Translates a Material Graph to HLSL

- After Apply in Material Editor: (1) translate material graph to HLSL; (2) compile HLSL to GPU bytecode. Article focuses on (1). Shader permutations: not one shader per material — several depending on features/platforms/usages; see Understanding Shader Permutations (linked from article; separate fetch redirected to docs home).
- View generated shader: Window → Shader Code → HLSL Code (read-only). Copy to Notepad++/Rider/VS with HLSL highlighting.
- Template: Engine/Shaders/Private/MaterialTemplate.ush — structures/functions with "%s" placeholders filled by text replacement. Called from pixel shader BasePassPixelShader.usf.
- Filled by FMaterialCompiler; standard path uses FHLSLMaterialTranslator (inherits FMaterialCompiler). Also Lightmass / Proxy implementations.

## Call path
FMaterial::CacheShaders
- FMaterial::BeginCompileShaderMap
  - FHLSLMaterialTranslator::Translate
  - FHLSLMaterialTranslator::GetMaterialEnvironment
  - FHLSLMaterialTranslator::GetMaterialShaderCode
  - FPartialShaderMap::Compile

- Translate: prepare each material input pin's graph; ensure vertex interpolators, texture coordinates, material parameter collections, virtual texture samples, etc.; error reporting (e.g. per-pixel shading models with SingleLayerWater).
- GetMaterialEnvironment: sets defines used in final HLSL (#ifdefs for shading models / features).
- GetMaterialShaderCode: prints compiled data into template string.

## UMaterialExpression::Compile
- Nodes inherit UMaterialExpression; key methods Compile, GetCaption, GetKeywords. Declarations in headers; definitions in Engine/Source/Runtime/Engine/Private/Materials/MaterialExpressions.cpp. Each can define constants and FExpressionInput graph inputs.
- Compile returns int32 = array index of compiled result. Takes FMaterialCompiler*.
- Example UMaterialExpressionAdd::Compile: if pin connected compile input else Compiler->Constant(ConstA/ConstB); then Compiler->Add(...).

## Constant Folding (FHLSLMaterialTranslator::Add)
- Both constant → precompute on CPU, write literal result.
- One constant + parameter → hidden parameter combining them on CPU so GPU sees a fixed number.
- Both non-constant → emit "A + B".
- Example graph outcomes in CalcPixelMaterialInputs:
  - Roughness: PixelMaterialInputs.Roughness = (1.00000000 + 2.00000000);
  - Metallic: Material.ScalarExpressions[0].z (packed float4 uniform expressions)
  - Base Color: MaterialFloat Local1 = (Parameters.TexCoords[0].xy.r + Material.ScalarExpressions[0].y); then PixelMaterialInputs.BaseColor = Local1;
- Non-constant results stored as LocalN variables; hashed so duplicate subgraphs reuse LocalN.

## EmissiveColor editor quirk
- Editor-compiled materials lerp user emissive with a VectorExpression controlled by engine value for selection highlighting; optimized away in cooked shaders.

## References cited in article
- Tim Jones Shader Playground; Rider HLSL; Notepad++ HLSL UDL; UE4 Rendering Part 4 Deferred; HLSL Tools for VS (add .usf/.ush extensions).