UE5 Zenless Zone Zero Stylization
Custom NPR stylized renderer replicating ZZZ's aesthetic in UE5
Overview
This is a stylized renderer in Unreal Engine 5 intended to recreate the NPR style from the game Zenless Zone Zero, with some personal touches.
The model was taken from the official, publicly released MMD models. However, this means the model comes with neither normal maps nor light maps, which made it look slightly flat, with less control over the look of individual parts.
Toon Shading
The basic idea is still constructing a Lambert shader and plugging it into emission. However, this time I used the default lit shading model instead of the unlit model, which allowed support for features such as multiple lights and shadows cast by other objects.
Then I used a Curve Atlas to adjust the contrast of the image textures, which helped me achieve an overall punchier look.
If the model had light maps and normal maps, I would have implemented some metallic specular by constructing Blinn-Phong and masking it — using the light map — onto only the parts with a metallic value over a certain threshold. Also, I could use the normal map to map vertex positions for the basic Lambert shading model.
Post Process
I think what really carried this project is the post-process shaders. I used a custom stencil pass to mask out the character from the background, which allowed me to have a lot more control over the look of the shadows.
Shadow
For the shadow post-process, I basically did a very dense dotted effect with a Voronoi noise of only 1 octave, then applied a power to adjust its shape. Then I simply multiplied it onto the shadow part of the image.
Outline
The outline is done by using the SampleSceneDepth node, which allowed me to find drastic changes in the depth pass and use that as a mask to drive the outlines.
Vignette & Chromatic Aberration
For the vignette, I simply converted the 0–1 viewport UV space into −1 to 1, and then used the length as a radial mask.
For chromatic aberration, I just shifted the sampling viewport UV by a tiny amount to offset the red channel in one direction, and then the blue and green channels in the opposite direction.