The problem
Forward-shaded stylized renderers rarely get first-class access to shadow information the way deferred pipelines do. I set out to reconstruct a usable shadow mask post-hoc, then redraw it as a stylized hatch pattern instead of a soft shadow — while staying cheap enough for real-time use.
System overview
The plugin centers on UStylizedShadowsSubsystem, a UGameInstanceSubsystem
that owns a SceneCapture2D used to recover scene BaseColor at runtime.
A directional-light transform delegate and a 30 fps timer push camera and
light data into a MaterialParameterCollection, which a post-process
material reads to rebuild the shadow mask:
- Desaturation of the captured BaseColor
- Luminance-ratio thresholding to isolate occluded regions
- Albedo bias correction (dividing out BaseColor) so dark materials don’t get misread as shadow
- Specular suppression via Roughness multiplication
- Triplanar hatch-pattern blending across the reconstructed mask
Notable problems solved
- Incorrect subsystem override methods that silently no-op’d
- A timer firing before any
PlayerControllerexisted - A color-cancellation bug where the hatch pattern turned black on saturated surfaces, traced to how the post-process material blended scene color
Result
Isolated shader cost measured very low on an RTX 3070 at 1440p — the reconstruction step stays cheap relative to the rest of the frame.
The thesis names two framing contributions: the “Uncanny Valley of Digital Hatching” and the “Post-Process Gap” between what deferred and forward renderers expose to stylization passes.