Skip to the content.

Runtime API reference

Concise, manually maintained reference for the production hair runtime. The runtime keeps three quality tiers as separate compiled shaders behind one authoring surface (HairMaterialProfile) plus groom-specific card data (HairGroomData) and a shared coverage policy (HairCoveragePolicy).

For authoring workflows, LUT contracts, shader switching internals, and the preserved-parameter list, see hair_material_authoring.md. For the optical wetness model and calibration, see hair_wetness.md.

HairMaterialProfile

Resource (class_name HairMaterialProfile). One authoring surface that selects the compiled lighting model and coverage path. Reusable across grooms.

Quality tiers

Serialized values remain stable for compatibility:

0  Approx / Kajiya-Kay
1  Fast Marschner
2  Cinematic Marschner
HairMaterialProfile.QualityTier.APPROX
HairMaterialProfile.QualityTier.FAST_MARSCHNER
HairMaterialProfile.QualityTier.CINEMATIC_MARSCHNER
Tier Intended use Main tradeoff
Approx / Kajiya-Kay Constrained hardware, fallback, non-Marschner comparison Lowest cost, least physical fidelity
Fast Marschner Normal production Marschner path Good quality/cost balance; fixed eta 1.55 LUT contract
Cinematic Marschner High-fidelity shots where extra per-light cost is acceptable Conditioned longitudinal 3D LUT is the most expensive production tier

The analytic Reference Marschner shader is a benchmark-only validation baseline outside the packaged addon; it is not part of the QualityTier enum. Benchmark cost ordering across the four development tiers (Reference included): Approx < Fast < Reference < Cinematic.

Exported properties

Every exported property carries an Inspector hover description.

Primary methods

get_shader_resource(viewport = null) -> Shader
get_effective_coverage_mode(viewport = null) -> int
apply_to(material, groom_data = null, viewport = null) -> bool
create_material(groom_data = null, viewport = null) -> ShaderMaterial
update_coverage_for_viewport(material, viewport, rendered_frame_index = -1) -> bool
bind_mode_resources(material) -> bool

Compatibility APIs retained for benchmark/experimental callers:

apply_to_shader_material(material) -> void
bind_quality_resources(material) -> bool

apply_to_shader_material() applies supported profile values to the material’s current shader without replacing it; bind_quality_resources() is an alias of bind_mode_resources().

HairGroomData

Resource (class_name HairGroomData). Groom-specific card textures owned by the card atlas that generated them. A HairMaterialProfile can be reused across many grooms; HairGroomData cannot.

Exported properties

Methods

is_complete() -> bool
validation_message() -> String
apply_to_shader_material(material, warn_on_failure = true) -> bool
from_shader_material(material) -> Resource   # static

HairCoveragePolicy

RefCounted (class_name HairCoveragePolicy). Static coverage strategy shared by HairMaterialProfile and HairCoverageController.

Coverage modes

HairCoveragePolicy.Mode.AUTO
HairCoveragePolicy.Mode.STATIC_BAYER
HairCoveragePolicy.Mode.TAA_BAYER
HairCoveragePolicy.Mode.ALPHA_TO_COVERAGE

AUTO follows both viewport AA state and the active rendering method:

Forward+ or Mobile + MSAA  -> Alpha-to-Coverage
otherwise Forward+ + TAA   -> 16-phase temporal Bayer
otherwise                  -> Static Bayer, phase 0

Static Bayer is the stable fallback; temporal Bayer advances once per rendered frame and is only selected automatically when TAA is actually available. A2C uses separate compiled shader variants because alpha_to_coverage is a shader render mode, not a runtime uniform switch.

Constants and static functions

TAA_PHASE_COUNT = 16

resolve(viewport, requested_mode = Mode.AUTO, rendering_method = "") -> int
bayer_phase(effective_mode, rendered_frame_index) -> int
uses_alpha_to_coverage(effective_mode) -> bool
mode_name(effective_mode) -> String

HairCoverageController

Node (class_name HairCoverageController). Registers materials whose viewport AA configuration may change after creation.

register_material(profile, material, viewport = null) -> bool
unregister_material(material) -> void
clear_materials() -> void

While registered, the controller re-resolves the effective coverage each frame and calls HairMaterialProfile.update_coverage_for_viewport() so the compiled variant and 16-phase Bayer index track the rendered-frame index.

Coverage modes at a glance

Mode Behavior
AUTO Viewport + rendering-method driven (see above); editor-safe without a viewport (stable Bayer)
STATIC_BAYER Fixed Bayer phase 0; deterministic presentation
TAA_BAYER 16-phase ordered dither advanced per rendered frame
ALPHA_TO_COVERAGE Compiled A2C shader variant, no Bayer phase