The following is an overview of the rendering pipeline so you can adapt the performance of strands based on your project's budget and use case.
The rendering pipeline is decomposed into the following stages:
- Simulation: The guides' motions are simulated based on the scene environment and groom component motion.
- Interpolation: The guides' motions are transferred onto the rendering strands, and applied surface skinning if a groom is bound to a skeletal mesh.
- Voxelization: Hair curves are voxelized to generate a density volume. This volume is used for computing shadow and hair transmittance during the lighting stage. For light using Deep Shadow, a dedicated deep shadow map is generated at this stage.
- Primary Visibility: The hair curves are rasterized for the current camera viewport and hair samples are allocated for use with lighting.
- Lighting: All hair samples are lit with shadow and transmission using voxel or deep shadow data.
- Composition: All hair samples regroup and compose the final hair pixel into the scene color buffer.
Overall, the performance of strands is impacted by the number of grooms, but more importantly, by their complexity, such as the number of curves and points they contain. The more curves a groom has, the costlier the rendering passes for Simulation, Interpolation, Voxelization, and Primary Visibility.
If performance is an issue in your project for the first four stages, you can try:
- Set LOD Mode to Auto to adapt performance automatically.
- For Primary Visibility, you can try to force using triangle strip geometry with
r.HairStrands.Strands.UseTriangleStrips
and balance the number of samples per pixel (2, 4, or 8) withr.HairStrands.Visibility.MSAA.SamplePerPixel
. - You can potentially lower the Interpolation and Voxelization cost by turning off the update of non-visible grooms with
r.HairStrands.Shadow.CastShadowWhenNonVisible
. However, these grooms will no longer cast shadows when not visible.
For lighting costs, you can try:
- Reduce the voxel size of strands with
r.HairStrands.Voxelization.Virtual.VoxelWorldSize
. The voxel size will be large, and the shadow will look coarser, but the voxelization and the lighting will be cheaper. - Increase the ray matching step scaling with
r.HairStrands.Voxelization.Raymarching.SteppingScale
to control the rate at which ray marching goes faster as you go further from the hit point. Adjusting the step scaling affects the lighting cost up to a certain limit but degrades the shadow and hair transmittance quality.
For environment lighting, you can try:
- Disable hair ambient occlusion (AO) with
r.HairStrands.SkyAO
. - Change the hair sky lighting integrator with
r.HairStrands.SkyLighting.IntegrationType
by selecting between 1 for quality and 2 for fast mode.
Debugging Grooms
The Level Editor viewport options contain useful visualizations for inspecting different aspects of grooms. You can access these options with Lit > Groom.

One example from the list of groom visualizations that is useful is Instances. With this visualization, you can inspect all visible instances' properties. The view shows each visible hair group and information about their LOD index, type of geometry, type of binding, simulation, RBF, and so on. For strands geometry, it also shows the number of active curves and points.
Click image for full size.
Guides is another useful visualization that displays the simulation guides for visible grooms.
Click image for full size.
To get a summary of all Groom assets, Groom Binding assets, and Groom Component memory footprint, you can use the console command r.HairStrands.Dump
to output information to the log. This output contains information about consumed memory on the CPU and GPU for these assets. You can also get a summary of information with the Memory visualization mode.
Click image for full size.
Groom Shadow Artifacts
Shadows cast by strands geometry are computed using voxelized curves by default. The default settings might not suit your use case and need to be adapted to your project using console variables. The strands are voxelized using a sparse voxel structure made of pages, which you can think of as "bricks" of voxels. When a groom is voxelized, the bricks are allocated to cover the groom. The size of these bricks adapts based on the distance to the grooms. If there are a lot of grooms in a level, or if the camera is really close to a large groom, it's possible to run out of pages.
You can increase the number of pages with the console variable r.HairStrands.Voxelization.Virtual.VoxelPageCountPerDim
. Increasing this value can cause allocated memory to quickly rise up.
If the camera gets close to a groom, the voxel resolution may appear too low. You can increase the voxel resolution by reducing the voxel size with the console command r.HairStrands.Voxelization.Virtual.VoxelWorldSize
.
You can visualize the groom voxels with the Voxels visualization mode. Hovering over the Draw Pages in the viewport shows the groom pages.
Click image for full size.
Known Limitations
- Frame rate depends on several factors: the size of the groom, its resolution, and the underlying hardware it's being run on. For example, you should expect a 30Hz or higher framerate with an RTX-2090Ti for a human-like groom at 1080p. Higher quality settings result in a significant performance drop.
- Depth of Field is supported but may produce some artifacts.
- Grooms rendered with the Path Tracer have a different appearance than the rasterizer output.
- Grooms do not yet support proper precomputed (Static / Stationary) lighting.