# Overview

Useful links, guides and information on using Flora.

{% embed url="<https://youtu.be/qT5EFgaZBaQ?si=mI0p5Sn954KDo1Ea>" %}

Flora lets you render large numbers of objects as **instances** (drawn from shared prefab data instead of one full `GameObject` rendering path per item). It is designed for terrain foliage, container and instance-renderer workflows, converted scene prefabs, and runtime-spawned populations.

## Start Here

If you are new to BRG/instancing, follow this order:

1. [Getting Started](/getting-started)
2. [Samples](/samples)
3. [Scripts](/scripts)
4. [Rendering](/rendering)

## Common

* Render terrain trees/details with Flora: [Terrain Provider](/scripts/terrain-provider)
* Render instances without Unity `Terrain`: [Instance Container](/scripts/instance-container), [Instance Renderer](/scripts/instance-renderer), [Container Samples](/samples/container-samples)
* Convert existing prefab objects: [Conversion](/getting-started/conversion)
* Spawn and control instances in code: [System](/scripts/system)
* Tune visibility/performance: [Render Settings](/scripts/render-settings), [Density Settings](/scripts/density-settings), [Culling Pipeline](/rendering/culling-pipeline)
* Inspect rendering data: [Rendering Inspector](/rendering/rendering-inspector), [Debugging](/rendering/debugging)

## Concepts

* **BRG (Batch Renderer Group)**: Unity GPU-driven rendering path Flora uses for scalable draw submission.
* **Instance Container**: a serialized list of instance transforms for large static/semi-static sets.
* **Volume Override**: scene regions that override render/density settings.

## Samples

* [Tree Wrecking Ball](/samples/terrain-samples#tree-wrecking-ball)
* [Tree Effect](/samples/terrain-samples#tree-effect)
* [Fish Boids](/samples/runtime-samples#fish-boids)
* [Container Mesh Sample](/samples/container-samples#container-mesh-sample)
* [Container Prefab Sample](/samples/container-samples#container-prefab-sample)

## Additional Resources

* [Asset Store](https://u3d.as/3z4E)
* [Unity Forum](https://discussions.unity.com/t/released-50-off-new-flora-renderer/1670348)
* [Discord](https://discord.gg/bsTzQbCY)
* [Roadmap](https://trello.com/b/TLKPM8Eg/flora)

## Requirements

* **Unity 6 LTS, 6.3 LTS**
* **Compute Shader Support** on **Target Platform**
* **Universal, High Definition,** or **Custom Scriptable Render Pipeline**


# Getting Started

Step-by-step setup instructions for new users.

This page is the beginner path. If you are new to BRG and instancing, follow these sections in order.

## Flora

* Flora renders many objects as **instances** using shared prefab/template data.
* You still author with familiar Unity objects (prefabs, terrain, volumes), but Flora owns runtime draw/culling data.
* In current Flora, culling/drawing runs on Unity's **Batch Renderer Group (BRG)** path.

***

## Install

Install Flora from the Unity Asset Store: [Installing Asset Store Packages](https://docs.unity3d.com/6000.1/Documentation/Manual/upm-ui-import.html).

Use the **Flora Package Manager** to install or update Flora modules and optional add-ons.

<figure><img src="/files/953lfs8K9O5eNmwHmADh" alt="Flora Package Manager" width="375"><figcaption></figcaption></figure>

Open the package manager from **Window → Flora → Package Manager**.

**Expected outcome:** Flora menu items and samples are available.

***

## Scene Bootstrap

1. Create **Flora Scene Settings** from **GameObject > Flora > Scene Settings**.
2. Confirm terrain options:
   * `EnableTerrainFoliage` enabled
   * `AutoRegisterTerrains` enabled
3. Open **Project Settings → Graphics** and configure [Runtime Settings](/scripts/runtime-settings) if needed.
4. Add Flora overrides to the default volume profile or use **Add Render Settings Volume** in the Scene Settings inspector:
   * [Render Settings](/scripts/render-settings)
   * [Density Settings](/scripts/density-settings)

<figure><img src="/files/ScG4a87O1FaBz4XCViPZ" alt="Default Volume Profile with Flora settings"><figcaption></figcaption></figure>

**Expected outcome:** scene has global Flora control and default render/density behavior.

***

## Conversion

To convert existing prefab objects into Flora-rendered instances:

1. Select one or more prefab instances in Hierarchy.
2. Right-click → **Convert to Instance Renderer**.
3. Verify converted objects now use [`FloraInstanceRenderer`](/scripts/instance-renderer).

> See [Conversion](/getting-started/conversion) for all conversion options.

***

## First Run

1. Open [Container Mesh Sample](/samples/container-samples#container-mesh-sample) and press Play.
2. Open [Container Prefab Sample](/samples/container-samples#container-prefab-sample) and verify `FloraInstanceRenderer` and `FloraInstanceContainer` instances render correctly.
3. Open [Fish Boids](/samples/runtime-samples#fish-boids) sample and press Play.
4. Open [Tree Effect](/samples/terrain-samples#tree-effect) and verify terrain trees animate.
5. Open [Tree Wrecking Ball](/samples/terrain-samples#tree-wrecking-ball) and verify trees are disabled/replaced on impact.

If these pass, your Flora setup is functioning.

***

## Quick Troubleshooting

* Nothing renders: check [`EnableRendering`](/scripts/scene-settings).
* Terrain foliage missing: check [`EnableTerrainFoliage`](/scripts/scene-settings) and auto registration.
* Motion vectors missing: check [Runtime Settings](/scripts/runtime-settings) and [`AllowPerObjectMotionVectors`](/scripts/scene-settings).
* Need to inspect what Flora built: open [Rendering Inspector](/rendering/rendering-inspector) from **Window > Flora > Rendering Inspector** or the Scene Settings inspector.

> Relevant pages: [Runtime Settings](/scripts/runtime-settings), [Scene Settings](/scripts/scene-settings), [Samples](/samples)


# Conversion

Convert GameObject-based prefabs to instanced data and back again, with full round-trip support.

Flora provides multiple ways to convert **GameObject-based prefabs** into GPU-instanced data and back again. This is especially useful when working with *LODGroups* or *MeshRenderers* in large scenes.

> **Note:** In order to be rendered by Flora, each object must be part of a **prefab or prefab variant**. Flora uses the prefab asset to determine shared render states and to identify instance types in the scene.

***

## Contextual Menus

Flora includes several **context menu utilities** for converting *GameObjects* into:

* Instance Renderers using **Convert To Instance Renderer(s)**
* Instance Containers using **Create Instance Container(s)** and **Combine Instance Container(s)**
* Terrain Trees using **Convert To Tree**

These options appear when right-clicking a selection of prefab instances in either the **Scene View** or the **Hierarchy**.

***

### Instance Renderer

Adds a [`FloraInstanceRenderer`](/scripts/instance-renderer) component to any prefab instance that contains an *LODGroup* or *MeshRenderer*. This enables the prefab to be rendered using Flora’s instancing system.

<figure><img src="/files/6NmwXTZNiEe42H3vNuLE" alt="Convert to Instance Renderer" width="563"><figcaption></figcaption></figure>

***

### Instance Container

**Create Instance Container(s)** converts a group of prefab instances into a lightweight, [serialized container](/scripts/instance-container) of transforms.\
Ideal for static details or foliage that **don’t require**:

* Scripts
* Colliders

> **Note:** The original GameObjects will be **destroyed** after conversion.

Use **Combine Instance Container(s)** when multiple selected containers use the same prefab and should be merged into the active container.

<figure><img src="/files/q851ytMMz8FgrY0c4Z63" alt="Create Instance Container" width="485"><figcaption></figcaption></figure>

***

### Trees

Flora also includes utilities for converting **GameObjects into tree instances**, as long as the object is within the **bounds of a terrain**.

<figure><img src="/files/n7NljUc3ckk81DYIu3Fb" alt="Convert to Tree" width="476"><figcaption></figcaption></figure>

Converted trees can be **reverted back to GameObjects** using Flora’s [Editor Context Tools](/getting-started/editor-context):

1. Activate the context from the Scene View overlay.
2. Select instances in the **Scene View**.
3. Right-click to open the context menu.
4. Choose the option **Convert to GameObjects**.

<figure><img src="/files/omGHyL71q2uSJIK1zMVZ" alt="Convert trees back to GameObjects" width="563"><figcaption></figcaption></figure>

To convert **all trees of a specific prototype**, use the **Edit Trees** button in the **Terrain Inspector**.

<figure><img src="/files/coKM2zdu3DZnVzdstaTx" alt="Edit Trees in Terrain Inspector" width="460"><figcaption></figcaption></figure>


# Edit Mode

Provides specialized selection and manipulation tools for instances.

Flora provides a specialized [editor context](https://docs.unity3d.com/6000.1/Documentation/ScriptReference/EditorTools.EditorToolContext.html) for working with instances—allowing you to **select**, **move**, **rotate**, and **delete** instances in both containers and terrain trees. This is especially useful in scenarios where instances do not have associated *GameObjects*.

***

## Instance Editing Features

With the editor context active, you can use Unity’s built-in transform tools to:

* Select individual instances (e.g. trees or container instances)
* Move and rotate instances directly in the Scene View
* Delete instances

This functionality is available as long as:

* Flora is **enabled on the terrain**, and
* The **edit context** is active

***

## Activating the Context

To activate Flora's instance editing mode:

1. Look for the overlay toggle above the **Scene View** toolbar.
2. Click the icon with **three stacked dots** to enable the context.

<figure><img src="/files/4ItTSHENABtTNvYc1MyO" alt="Scene View overlay toggle" width="563"><figcaption></figcaption></figure>

> **Note:** If your shaders are not properly configured for instanced selection, picking may not work correctly. The "ScenePickingPass" must have the following pragmas:
>
> ```hlsl
> #pragma target 4.5
> #pragma multi_compile _ DOTS_INSTANCING_ON
> ```
>
> Additionally ensure the fragment shader returns `unity_SelectionID` and **not** `_SelectionID` .


# Samples

A set of pre-built scenes demonstrating Flora’s capabilities.

## Runtime

1. [Fish Boids](/samples/runtime-samples#fish-boids) - runtime spawning and transform updates.

## Container (Non-Terrain)

1. [Container Mesh Sample](/samples/container-samples#container-mesh-sample) - scene-authored container instancing without Unity `Terrain`.
2. [Container Prefab Sample](/samples/container-samples#container-prefab-sample) - prefab-based container instancing with `FloraInstanceRenderer` and `FloraInstanceContainer`.

## Terrain (Unity Terrain)

1. [Tree Effect](/samples/terrain-samples#tree-effect) - terrain-tree runtime animation.
2. [Tree Wrecking Ball](/samples/terrain-samples#tree-wrecking-ball) - instance query + disable + replacement flow.


# Runtime Samples

Samples showcasing Flora's runtime features.

## Fish Boids

The Fish Boids scene demonstrates runtime-driven instance animation at high counts using Flora + jobs.

<figure><img src="/files/aivaH4mTPFHQFme0I4pa" alt=""><figcaption></figcaption></figure>

### Scene Path

`Samples~/Examples/Fish/Scenes/FishBoidsSample.unity`

### What This Demonstrates

* Runtime creation and ownership of many instances
* Job-based transform simulation
* Batch update upload into Flora runtime

### APIs Exercised

* `FloraSystem.GetOrCreate()`
* `CreateInstances(...)`
* `ScheduleUpdateInstanceWorldTransforms(...)`
* `DestroyInstances(...)`

### Run and Verify

1. Open `FishBoidsSample` and press Play.
2. Confirm fish schools animate continuously.
3. Watch frame stability while instance counts are high.

**Expected result:** fish move smoothly as Flora instances without per-fish scene GameObjects for rendering.

### Common Failure Checks

* No fish visible: ensure Flora is active and sample objects enabled.
* Errors on disable: verify job dependencies complete before destroy/dispose.
* Motion vector artifacts: check runtime/scene motion-vector settings.

### Core Classes

#### FishSchool

```csharp
NativeArray<FloraInstanceTransform> m_Transforms;
NativeArray<FloraInstanceHandle> m_InstanceHandles;
JobHandle m_Dependency;

void OnEnable()
{
    m_Transforms = new NativeArray<FloraInstanceTransform>(SpawnCount, Allocator.Persistent);
    m_InstanceHandles = new NativeArray<FloraInstanceHandle>(SpawnCount, Allocator.Persistent);

    FloraSystem.GetOrCreate().CreateInstances(Prefab, gameObject, m_InstanceHandles, m_Transforms);
}

void OnDisable()
{
    m_Dependency.Complete();
    FloraSystem.Instance?.DestroyInstances(m_InstanceHandles);

    m_Transforms.Dispose();
    m_InstanceHandles.Dispose();
}
```


# Container Samples

Scenes showcasing FloraInstanceContainer and FloraInstanceRenderer workflows without Unity Terrain.

These scenes demonstrate `FloraInstanceContainer` and `FloraInstanceRenderer` workflows **without Unity `Terrain`**.

> These samples do **not** require a Unity `Terrain` component. They use `FloraInstanceContainer` to manage serialized collections of instances without individual GameObjects, and `FloraInstanceRenderer` to register prefab instances with the Flora system.

***

## Container Mesh Sample

This sample demonstrates a rotated wall mesh with **four** child `FloraInstanceContainer` objects. Each child container targets a different prefab, and all container instances maintain the wall's parent-space rotation/motion.

### Scene Path

`Samples~/Examples/Containers/Scenes/ContainerMeshSample.unity`

### What This Demonstrates

* Container-driven instancing on a rotated wall object without Unity `Terrain`.
* Four sub-containers, each with a different target prefab (`Heather`/`Fern` variants).
* Stable parent/child transform inheritance from the wall to all container content.

### Run and Verify

1. Open `ContainerMeshSample` and press Play.
2. Confirm four container groups render from container data across the rotated wall.
3. Confirm each container group uses its own prefab target.
4. Confirm all container instances rotate/move with the parent wall while keeping stable local offsets.

**Expected result:** all four container groups render on the rotated wall, keep their per-container prefab identity, and stay parent-locked to the wall transform without Unity `Terrain`.

### Common Failure Checks

* No instances visible: verify Flora scene rendering is enabled and the sample setup prefab is active.
* Incorrect instance placement/orientation: confirm the four containers remain parented under the rotated wall hierarchy.
* Wrong prefab assignment: verify each container's `Prefab` reference matches its intended variant.
* Unexpected terrain assumptions: this sample should run with no Unity `Terrain` component.

***

## Container Prefab Sample

This sample demonstrates hybrid prefab workflows using `FloraInstanceRenderer` and `FloraInstanceContainer`:

* Parent rock prefabs with `LODGroup` + `FloraInstanceRenderer` render as instanced prefab objects.
* Child `FloraInstanceContainer` objects hold non-`GameObject` plant instances that stay parent-relative.

> Canonical scene name is `ContainerPrefabSample` (sometimes referred to as "ContainerPrefabSamples" in conversation).

### Scene Path

`Samples~/Examples/Containers/Scenes/ContainerPrefabSample.unity`

### What This Demonstrates

* Rotating `LODGroup` rock prefabs rendered through `FloraInstanceRenderer`.
* Child `FloraInstanceContainer` plant content authored without per-plant `GameObject` render paths.
* Parent/child transform relationship preservation between instanced rock prefabs and child plant containers.
* Non-Terrain deployment of this hybrid `FloraInstanceRenderer` + `FloraInstanceContainer` workflow.

### Run and Verify

1. Open `ContainerPrefabSample` and press Play.
2. Confirm rotating rock prefabs render correctly as `LODGroup` instances through `FloraInstanceRenderer`.
3. Confirm child container plant instances move with their parent rocks and keep stable relative offsets.
4. Confirm all content renders correctly across the floor.


# Terrain Samples

Scenes showcasing runtime terrain features.

These scenes demonstrate terrain tree interaction workflows driven by Flora instance APIs.

***

## Tree Effect

This sample animates terrain tree instances inside a spherical influence volume.

<figure><img src="/files/XKobrUH0UysgRhViICDA" alt="Tree Effect sample"><figcaption></figcaption></figure>

### Scene Path

`Samples~/Examples/Terrain/Scenes/TreeEffectSample.unity`

### What This Demonstrates

* Tree instance query by sphere
* Local-to-world retrieval and update
* Per-instance runtime animation without converting trees to scene objects

### APIs Exercised

* `FindInstancesIntersectingSphereMatching(...)`
* `GetInstanceLocalToWorlds(...)`
* `UpdateInstanceLocalToWorlds(...)`
* `FloraInstanceFilter.ByTrees()`

### Run and Verify

1. Open `TreeEffectSample` and press Play.
2. Move/observe effect sphere region.
3. Confirm nearby trees animate and recover when leaving the region.

**Expected result:** only trees in-range are displaced/animated.

### Common Failure Checks

* No response: verify `EnableTerrainFoliage` and terrain auto-registration.
* Trees remain offset after stop: check cleanup/restore path in sample script.

***

## Tree Wrecking Ball

This sample demonstrates physics interaction that disables terrain-tree instances and spawns replacement rigidbody objects.

<figure><img src="/files/DzrLuO1ZIEeB6JGLoxLp" alt="Tree Wrecking Ball sample"><figcaption></figcaption></figure>

### Scene Path

`Samples~/Examples/Terrain/Scenes/WreckingBallSample.unity`

### What This Demonstrates

* Collision-region tree query
* Instance enable/disable control
* Runtime replacement with `GameObject` + `FloraInstanceRenderer`

### APIs Exercised

* `FindInstancesIntersectingSphereMatching(...)`
* `SetInstancesEnabled(...)`
* `GetInstanceWorldTransform(...)`
* `GetInstanceIdentitySource(...)`
* `GetInstanceOwnerTerrain(...)`

### Run and Verify

1. Open `WreckingBallSample` and press Play.
2. Let wrecking ball collide with trees.
3. Confirm impacted trees are hidden as Flora instances and replaced with rigidbody objects.

**Expected result:** collision zone trees convert to physics-driven replacements; Flora instances are disabled.

### Common Failure Checks

* Trees never disable: verify query region radius/position is valid.
* Replacements missing Flora rendering: ensure `FloraInstanceRenderer` is added and prefab assigned.


# Scripts

This section explains Flora components and runtime APIs from beginner to advanced.

## Read in This Order

1. [Runtime Settings](/scripts/runtime-settings) - project-wide feature gates.
2. [Scene Settings](/scripts/scene-settings) - scene-wide behavior.
3. [Render Settings](/scripts/render-settings) + [Density Settings](/scripts/density-settings) - volume overrides.
4. [Instance Renderer](/scripts/instance-renderer), [Instance Container](/scripts/instance-container), [Terrain Provider](/scripts/terrain-provider) - how content enters Flora.
5. [System](/scripts/system) - runtime create/update/query API.
6. [Instance Transform](/scripts/instance-transform) + [Instance Handle](/scripts/instance-handle) - data types used by code workflows.

## What This Affects

These components control:

* how instances are registered
* how they are rendered and culled
* how you query and modify them at runtime


# Runtime Settings

Defines global, project-wide settings for Flora.

This component defines project-wide runtime behavior for Flora and is serialized in Graphics Settings.

## What This Affects

* global GPU occlusion availability
* legacy light-probe availability
* per-object motion-vector availability

***

### Properties

#### <mark style="color:yellow;">DefaultCullingPipeline</mark> *(Obsolete)*

* Kept for backward compatibility.
* Has **no runtime effect** in current Flora.
* Flora now always uses BRG culling.

***

#### <mark style="color:yellow;">DisableGPUOcclusionCulling</mark>

Disables GPU-based occlusion culling globally.

* `false`: scene/camera settings can enable occlusion.
* `true`: occlusion stays off regardless of scene/camera toggles.

***

#### <mark style="color:yellow;">DisableLegacyLightProbes</mark>

Disables Unity’s legacy baked light probe path globally.

Use this when your project relies on APV/lightmaps and does not require legacy probe sampling.

***

#### <mark style="color:yellow;">DisablePerObjectMotionVectors</mark>

Disables motion vector support for Flora instances globally.

Use this to reduce memory and update cost when motion vectors are unnecessary.

***

### Usage

These settings are available in **Project Settings → Graphics** when using a supported SRP:

<figure><img src="/files/ScG4a87O1FaBz4XCViPZ" alt="Flora Graphics Settings UI" width="563"><figcaption></figcaption></figure>

## How To Verify

Toggle each setting and confirm scene behavior follows project-level gating (for example, occlusion or motion vectors stop applying globally).


# Scene Settings

Provides scene-wide configuration settings.

The **Scene Settings** component is a scene-wide singleton for Flora behavior.

Create or select it from **GameObject > Flora > Scene Settings**. If a Scene Settings object already exists, the menu item selects the existing object instead of creating a duplicate.

## What This Affects

* Scene render enable/disable
* Terrain foliage integration and auto-registration
* Scene-level occlusion, motion vectors, light probes, density gating
* Terrain detail streaming controls
* Live culling and graphics-buffer stats in the inspector

***

## Inspector

The Scene Settings inspector has two tabs:

* **Global** - scene feature flags, terrain foliage controls, and terrain detail streaming controls.
* **Stats** - live CPU culling, GPU culling, and graphics-buffer tables.

The status chips show whether Flora rendering and terrain foliage are active. Warning rows appear when project-level Runtime Settings prevent a scene feature from taking effect, such as globally disabled GPU occlusion, per-object motion vectors, or legacy light probes.

The action buttons open common tools:

* **Rendering Inspector** - opens [Rendering Inspector](/rendering/rendering-inspector).
* **Rendering Debugger** - opens [Debugging](/rendering/debugging).
* **Flora Graphics Settings** - opens Project Settings > Graphics for project-wide Runtime Settings.
* **Add Render Settings Volume** - adds a global Volume with `FloraRenderSettings` and `FloraDensitySettings` when the Scene Settings object does not already have a Volume.

The **Stats** tab enables culling-stat collection while it is visible and rendering is enabled. It refreshes periodically and shows CPU culling views, GPU culling views, and Flora graphics-buffer allocation data.

***

### Properties

#### <mark style="color:yellow;">OverrideCullingPipeline</mark> *(Obsolete)*

* Kept for migration compatibility.
* Has no effect in current Flora.

#### <mark style="color:yellow;">CullingPipelineOverride</mark> *(Obsolete)*

* Kept for migration compatibility.
* Has no effect in current Flora.

***

#### <mark style="color:yellow;">EnableRendering</mark>

* Master scene toggle for Flora rendering.

#### <mark style="color:yellow;">EnableTerrainFoliage</mark>

* Enables Flora rendering for terrain trees/details.

#### <mark style="color:yellow;">AutoRegisterTerrains</mark>

* Automatically registers active terrains using `FloraTerrainProvider`.

***

#### <mark style="color:yellow;">AllowGPUOcclusionCulling</mark>

* Scene-level gate for GPU occlusion.

#### <mark style="color:yellow;">AllowPerObjectMotionVectors</mark>

* Scene-level gate for per-object motion vectors.

#### <mark style="color:yellow;">AllowPerTreeMotionVectors</mark>

* Tree motion vectors; requires `AllowPerObjectMotionVectors`.

#### <mark style="color:yellow;">AllowPerDetailMotionVectors</mark>

* Detail motion vectors; requires `AllowPerObjectMotionVectors`.

#### <mark style="color:yellow;">AllowPerTreeLightProbes</mark>

* Enables per-tree probe sampling.

#### <mark style="color:yellow;">AllowPerDetailLightProbes</mark>

* Enables per-detail probe sampling.

#### <mark style="color:yellow;">AllowDensityCulling</mark>

* Enables density systems in this scene.

#### <mark style="color:yellow;">AllowLegacyLightProbes</mark>

* Enables legacy baked light-probe usage for scene content.

***

#### <mark style="color:yellow;">DetailStreamingMode</mark>

* Controls the overall terrain detail streaming behavior.
* `Immediate` spends as much work as needed to make visible details appear quickly.
* `Streamed` is the default mode and uses the responsiveness slider to control how aggressively Flora spends its per-frame streaming budget.
* `Custom` exposes Flora's internal per-frame rebuild and structural budgets directly for advanced tuning.

#### <mark style="color:yellow;">DetailStreamingResponsiveness</mark>

* Controls how aggressively Flora spends its streaming budget.
* Higher values make visible details catch up faster.
* Lower values spread work across more frames to reduce spikes.
* Ignored when `DetailStreamingMode` is `Immediate` or `Custom`.

#### <mark style="color:yellow;">CustomDetailPatchLayerBudgetPerFrame</mark>

* Advanced-only control used when `DetailStreamingMode` is `Custom`.
* Limits how many detail patch-layer rebuilds Flora may schedule per frame.
* `0` means unbounded.

#### <mark style="color:yellow;">CustomDetailStructuralInstanceBudgetPerFrame</mark>

* Advanced-only control used when `DetailStreamingMode` is `Custom`.
* Limits how many detail create/destroy instance operations Flora may apply per frame.
* `0` means unbounded.

#### <mark style="color:yellow;">DetailUnloadHysteresisSeconds</mark>

* Acts as an unload grace period.
* Flora keeps terrain details alive for this many seconds after they leave range before unloading them.
* Increasing it reduces rapid disappear/reappear popping when hovering near the detail distance boundary.

## Runtime User Settings Workflow

You can apply user-controlled render/density values at `Start` (or any runtime point) via the global Flora volume components:

```csharp
var sceneSettings = FloraSceneSettings.GetOrCreate();

var render = sceneSettings.GetGlobalRenderSettings();
render.MaxRenderDistance.Override(userRenderDistance);

var density = sceneSettings.GetGlobalDensitySettings();
density.GlobalDensityMode.Override(FloraDensityMode.RenderersOnly);
density.GlobalDensity.Override(userDensity);
```

Use `Override(...)` instead of assigning `.value` directly, so the volume parameter is actually active.

## How To Verify

* Disable `EnableRendering` and confirm Flora-rendered content disappears.
* Disable `EnableTerrainFoliage` and confirm terrain foliage returns to non-Flora behavior.
* Change the detail streaming controls and verify streaming behavior near distance boundaries.


# Render Settings

Controls instance culling and rendering options.

Attach this component to a [Volume](https://docs.unity3d.com/6000.1/Documentation/Manual/urp/Volumes.html) to override [scene-level](/scripts/scene-settings) culling and rendering parameters for Flora instances.

These overrides apply only within the volume’s bounds and can be blended like other volume-based settings.

Distance caps are composed using the smallest active non-zero value across scene/volume/template/terrain sources.

***

### Properties

#### <mark style="color:yellow;">MinScreenSizeMode</mark>

* Controls which objects `MinScreenSize` affects.
  * `Disabled` = minimum screen-size culling is disabled.
  * `RenderersOnly` = applies to renderer templates, but not LODGroups.
  * `RenderersAndLODGroups` = applies to renderer and LODGroup templates.

***

#### <mark style="color:yellow;">MinScreenSize</mark>

* The **minimum screen-space coverage** an instance must occupy to be rendered.
  * Instances smaller than this threshold are culled.
  * Useful for avoiding rendering of tiny or far-away instances.

***

#### <mark style="color:yellow;">MaxRenderDistance</mark>

* The maximum world-space distance from the camera at which instances will be rendered.
  * `0` = This cap is disabled.
  * Non-zero = Instances beyond this range are culled

***

#### <mark style="color:yellow;">MinShadowLOD</mark>

* The **minimum LOD index** used when rendering shadows for Flora instances.
  * `0` = Full detail (LOD0)
  * Higher values reduce shadow quality for distant or low-priority objects

***

#### <mark style="color:yellow;">MaxShadowDistance</mark>

* The maximum distance at which **shadows are drawn** for Flora instances.
  * `0` = This cap is disabled.
  * Non-zero = Additional shadow distance cap

***

#### <mark style="color:yellow;">CrossFadeDuration</mark>

* The duration of **LOD cross-fade transitions** (in seconds).
  * Affects LODGroups with animated cross-fading enabled
  * `0` = Instant LOD switch
  * Higher values result in smoother visual transitions between LOD levels

***

#### <mark style="color:yellow;">RandomizeLODTransition</mark>

* Adds per-instance variation to LOD transition thresholds.
  * `0` = no randomization.
  * Higher values reduce visible synchronized LOD popping across repeated instances.

***

#### <mark style="color:yellow;">MinScreenSizeAffectsLODGroups</mark> *(Obsolete)*

* Migrated to `MinScreenSizeMode`.
* Existing enabled overrides become `RenderersAndLODGroups`.
* Kept for older serialized assets only.

***

### Runtime Override Note

When setting values at runtime, use `VolumeParameter.Override(...)` so the override state is enabled:

```csharp
var sceneSettings = FloraSceneSettings.GetOrCreate();
var render = sceneSettings.GetGlobalRenderSettings();
render.MaxRenderDistance.Override(120f);
render.MaxShadowDistance.Override(80f);
```


# Density Settings

Controls how density-based culling is applied to instances.

This volume component controls how Flora reduces instance density for performance or style.

## What This Affects

* Total visible instance counts
* Distant/small-on-screen instance reduction
* Per-layer and per-size density targeting

Attach this component to a [Volume](https://docs.unity3d.com/6000.1/Documentation/Manual/urp/Volumes.html) to enable density culling effects within specific regions.

***

### Properties

#### <mark style="color:yellow;">GlobalDensityMode</mark>

* Controls how global density applies:
  * `Disabled`
  * `RenderersOnly`
  * `RenderersAndLODGroups`

> Migration note: `GlobalDensityEnabled` is obsolete and maps to this mode.

***

#### <mark style="color:yellow;">GlobalDensityMask</mark>

* Selects which instance layers are affected by global density.

***

#### <mark style="color:yellow;">GlobalDensity</mark>

* Fraction of instances to keep.
  * `1.0` = keep all
  * `0.5` = keep half
  * `0.0` = keep none of matching instances

***

#### <mark style="color:yellow;">GlobalDensitySizeThreshold</mark>

* Objects larger than this diagonal size are exempt from global density culling.

***

#### <mark style="color:yellow;">RangeDensityMode</mark>

* Controls how range density applies:
  * `Disabled`
  * `RenderersOnly`
  * `RenderersAndLODGroups`

> Migration note: `RangeDensityEnabled` and `RangeDensityAffectsLODGroups` are obsolete and map to this mode.

***

#### <mark style="color:yellow;">RangeDensityMask</mark>

* Selects which layers are affected by range-based density.

***

#### <mark style="color:yellow;">RangeDensity</mark>

* Minimum density for small-on-screen instances.

***

#### <mark style="color:yellow;">RangeDensityFalloff</mark>

* Controls how quickly density falls from full to `RangeDensity`.

> Migration note: `RangeDensityFalloffPower` is obsolete and maps to this field.

***

#### <mark style="color:yellow;">RangeDensityScreenPercentage</mark>

* Screen-size thresholds used for range-based density.
* Lower bound is constrained by [`MinScreenSize`](/scripts/render-settings#minscreensize).

## Runtime Override Note

Set both mode and value with `Override(...)` when applying user settings at runtime:

```csharp
var sceneSettings = FloraSceneSettings.GetOrCreate();
var density = sceneSettings.GetGlobalDensitySettings();

density.GlobalDensityMode.Override(FloraDensityMode.RenderersOnly);
density.GlobalDensity.Override(0.75f);

density.RangeDensityMode.Override(FloraDensityMode.RenderersOnly);
density.RangeDensity.Override(0.6f);
```

## How To Verify

* Lower `GlobalDensity` and confirm broad thinning.
* Enable range density and confirm stronger thinning for distant/small-on-screen instances.


# Additional Camera Settings

Provides additional settings for controlling how instances are rendered by a camera.

Attach this component to a [Camera](https://docs.unity3d.com/ScriptReference/Camera.html) to override Flora behavior per camera.

## What This Affects

* Per-camera occlusion usage
* Per-camera instance rendering enable/disable
* Per-camera LOD bias scaling
* Teleport-aware LOD transition reset

***

### Properties

#### <mark style="color:yellow;">AllowGPUOcclusionCulling</mark>

* Enables GPU occlusion work for this camera.
* Useful to disable for reflections/portal cameras when cost is not worth it.

***

#### <mark style="color:yellow;">DisableInstanceRendering</mark>

* Disables Flora instance rendering for this camera only.

***

#### <mark style="color:yellow;">LODBiasScale</mark>

* Scales LOD selection for this camera.

| Value   | Effect                    |
| ------- | ------------------------- |
| `1.0`   | No scaling (default)      |
| `< 1.0` | Favors higher-detail LODs |
| `> 1.0` | Favors lower-detail LODs  |

***

#### <mark style="color:yellow;">Teleported</mark>

* Set when camera teleports to reset LOD transition timing and avoid visible transition artifacts immediately after teleport.

## How To Verify

* Toggle `DisableInstanceRendering` and confirm only that camera stops drawing Flora instances.
* Change `LODBiasScale` and observe LOD transition behavior for that camera.


# Additional Renderer Settings

Provides additional rendering options for Flora on a per-prefab basis.

Attach this component to a prefab to add per-prefab caps for distance, shadows, and density participation.

***

### Properties

#### <mark style="color:yellow;">AdditionalPerInstanceData</mark>

* Allocates optional per-instance shader data for this prefab.
  * `RandomID` exposes a stable per-instance random value as `flora_RandomID` or the Shader Graph `InstanceRandomID` node.
  * `VariationColor` exposes a per-instance color as `flora_VariationColor` or the Shader Graph `InstanceVariationColor` node.
* Enable only the data your shaders need; each enabled flag increases per-instance data.
* See [Shaders and Materials](/rendering/shaders-and-materials) for shader setup.

#### <mark style="color:yellow;">InitialVariationColor</mark>

* Initial value for `VariationColor` instances.
* Ignored unless `AdditionalPerInstanceData` includes `VariationColor`.
* Individual instances can override it at runtime with `FloraSystem.SetInstanceVariationColor(...)` or `SetInstanceVariationColors(...)`.

#### <mark style="color:yellow;">MaxRenderDistance</mark>

* Adds a per-prefab **maximum render distance cap**.
  * `0` — Prefab cap disabled.
  * Non-zero — Combined with other active caps; the smallest non-zero cap wins.

#### <mark style="color:yellow;">MaxShadowDistance</mark>

* Adds a per-prefab **maximum shadow distance cap**.
  * `0` — Prefab cap disabled.
  * Non-zero — Combined with other active caps; the smallest non-zero cap wins.

#### <mark style="color:yellow;">MinShadowLOD</mark>

* Sets the **lowest LOD index** allowed for rendering shadows.
  * `0` — Highest detail.
  * Higher values reduce shadow fidelity to improve performance.

#### <mark style="color:yellow;">AffectedByGlobalDensity</mark>

* If enabled, instances can be culled based on the current [Global Density](/scripts/density-settings#globaldensity).

#### <mark style="color:yellow;">AffectedByRangeDensity</mark>

* If enabled, instances can be culled based on [Range Density](/scripts/density-settings#rangedensity) values in the scene.

#### <mark style="color:yellow;">AffectedByMinimumScreenSize</mark>

* If enabled, instances can be culled by [`MinScreenSize`](/scripts/render-settings#minscreensize).
* Disable this for prefabs that should ignore minimum screen-size culling even when the active [Render Settings](/scripts/render-settings) enable it.

#### <mark style="color:yellow;">RequiresPerInstanceRandomID</mark> *(Obsolete)*

* Migrated to `AdditionalPerInstanceData.RandomID`.
* Kept for older serialized assets only.


# Instance Renderer

Renders a prefab instance with Flora.

The `FloraInstanceRenderer` is a component that enables Flora rendering for a prefab instance with a `LODGroup` or `MeshRenderer`.

Adding this component to the **root object** of a prefab instance will automatically register it with the [FloraSystem](/scripts/system) and render the instance using GPU instancing.

Disabling or removing the component will:

* Unregister the instance from Flora
* Reactivate Unity’s built-in `MeshRenderer` or `LODGroup` rendering path

<figure><img src="/files/WBTvZhTvvvQiJg268kx4" alt="Flora Instance Renderer component"><figcaption></figcaption></figure>

***

### Properties

#### <mark style="color:yellow;">InstanceHandle</mark>

When the component is active, this property holds the `FloraInstanceHandle` for the instance.

* Use this handle to interact with the [FloraSystem](/scripts/system)
* If the component is disabled or destroyed, the handle becomes invalid


# Instance Container

A serialized collection of instances that do not require individual GameObjects.

The **Instance Container** component is designed to manage large groups of instanced meshes—such as foliage, debris, or props—**without requiring individual GameObjects**.

It serializes instance transform data, integrates with the central [FloraSystem](/scripts/system), and exposes a simple API for adding, updating, querying, and removing instances at runtime or in the editor.

See also: [Conversion](/getting-started/conversion)

> For workflows without Unity `Terrain`, this is the primary Flora path for managing large groups of instances without individual GameObjects. See [Container Mesh Sample](/samples/container-samples#container-mesh-sample) and [Container Prefab Sample](/samples/container-samples#container-prefab-sample).\
> For Unity `Terrain` trees/details, use [Terrain Provider](/scripts/terrain-provider).

<figure><img src="/files/HT9AU7koVOA7YZiyXllU" alt="Instance Container UI"><figcaption></figcaption></figure>

***

### Properties

#### <mark style="color:yellow;">Prefab</mark>

The prefab rendered by all instances in this container.\
Changing this will **rebuild** all instances.

#### <mark style="color:yellow;">InstanceHandles</mark>

An array of runtime **instance handles**, used internally by Flora to track each instance.

#### <mark style="color:yellow;">LocalTransforms</mark>

An array of **container-space transforms** (position, rotation, scale) for each instance.

***

### Example

Basic runtime usage for spawning instances into a container:

```csharp
public class FoliageSpawner : MonoBehaviour
{
    public FloraInstanceContainer container;
    public GameObject treePrefab;

    void Start()
    {
        container.Prefab = treePrefab;

        // Spawn 100 instances in a 10x10 grid
        for (int x = 0; x < 10; x++)
        for (int z = 0; z < 10; z++)
        {
            Vector3 pos = new Vector3(x * 2f, 0, z * 2f);
            container.AddInstance(pos, Quaternion.identity, Vector3.one, Space.World);
        }
    }
}
```


# Terrain Provider

A bridge component that links a Terrain object to the Flora.

The **Terrain Provider** component connects a Unity `Terrain` object to the [FloraSystem](/scripts/system), enabling Flora to take over **tree** and **detail mesh** rendering.

> This component is typically added automatically when the [SceneSettings](/scripts/scene-settings) singleton is present and **Auto Register Terrains** is enabled.
>
> **Scope:** This page applies to Unity `Terrain` integration (terrain trees/details).\
> For non-Terrain workflows, use [Instance Container](/scripts/instance-container) or [Instance Renderer](/scripts/instance-renderer). See [Container Samples](/samples/container-samples).

***

## Trees

Tree instances are **loaded** from the terrain when a camera, and its far plane, are within distance of the terrain’s [`treeDistance`](https://docs.unity3d.com/ScriptReference/Terrain-treeDistance.html) value.

<figure><img src="/files/5shpYrLGpIZxRzT8nTaO" alt="Terrain tree distance UI"><figcaption></figcaption></figure>

***

## Details

Detail instances (e.g. grass, rocks, debris) are loaded when a camera, and its far plane, are within the terrain’s [`detailObjectDistance`](https://docs.unity3d.com/ScriptReference/Terrain-detailObjectDistance.html) range.

* When a detail cell goes **out of range**, it is **unloaded after 3 seconds**
* This helps reduce **GPU memory usage** in large terrain scenes

> ⚠️ For large environments, keep **detailObjectDistance** at a reasonable level to avoid unnecessary memory usage.

Unlike Unity’s built-in rendering system, Flora **supports detail meshes with LODGroups**.

* If Flora is disabled, Unity will fall back to its built-in rendering
* However, only the **first LOD mesh** will be used in that fallback path

<figure><img src="/files/Mg95slUuUdWvGTSHBEKS" alt="Detail mesh preview with LODs"><figcaption></figcaption></figure>


# Instance Handle

A lightweight struct used to uniquely identify and reference individual instances.

A `FloraInstanceHandle` is a lightweight struct used to uniquely reference a single instance managed by the global [FloraSystem](/scripts/system).

Internally, Flora stores all instances in a **Structure of Arrays (SoA)** layout. Handles allow you to **query**, **modify**, or **track** instances over time without needing to know their location in memory.

***

### Validity

A handle is valid only if both its `Index` and `Version` match an **active** instance in the system.

When an instance is destroyed:

* Its version is incremented
* All previously held handles to that index become **invalid**

This prevents accidental access to stale data or reused slots.

***

### Usage

Use instance handles when you need precise, efficient control over individual instances—especially in procedural workflows or runtime simulations.

#### Creating Instances

```csharp
FloraInstanceHandle handle = FloraSystem.GetOrCreate().CreateInstance(
    prefab,
    parentObject,
    position,
    rotation,
    scale
);
```

### Destroying Instances

```csharp
FloraSystem.Instance.DestroyInstance(handle);
FloraSystem.Instance.DestroyInstances(handlesArray);
```

### Checking if an Instance Exists

```csharp
bool exists = handle.Exists();
```

### Enabling or Disabling an Instance

```csharp
bool isEnabled = FloraSystem.Instance.IsInstanceEnabled(handle);
FloraSystem.Instance.SetInstanceEnabled(handle, true);
```

### Getting Instance Transform or Bounds

```csharp
float3 position = FloraSystem.Instance.GetInstancePosition(handle);
Bounds bounds = FloraSystem.Instance.GetInstanceBounds(handle);
```


# Instance Transform

Represents an instance’s position, rotation, and scale

`FloraInstanceTransform` is a lightweight struct used to represent an instance’s **position**, **rotation**, and **scale**—either relative to a parent (`local space`) or in world space when no parent is assigned.

Its design and API are based on Unity’s [`LocalTransform`](https://docs.unity3d.com/Packages/com.unity.entities@1.0/api/Unity.Transforms.LocalTransform.html) from the Entities package.

***

### Usage

#### Defining an Instance Transform

Instances can be placed using local-space transform data relative to a parent `Transform`:

```csharp
var localTransform = new FloraInstanceTransform(localPosition, localRotation, localScale);
FloraSystem.Instance.CreateInstance(prefab, this.transform, localTransform);
```

#### Converting from a Unity Transform

You can construct a `FloraInstanceTransform` from a `Transform`, in either local or world space:

```csharp
var local = FloraInstanceTransform.FromUnityTransform(this.transform, Space.Self);
var world = FloraInstanceTransform.FromUnityTransform(this.transform, Space.World);
```

#### Writing Instance Transforms

To update an instance’s transform after creation:

```csharp
FloraSystem.Instance.UpdateInstanceWorldTransform(handle, transform);
```

You can also update multiple instances at once using arrays or native containers.

#### Transform Composition and Manipulation

`FloraInstanceTransform` includes utility methods for manipulating transform data:

```csharp
transform = transform.RotateY(math.radians(90)).Translate(new float3(0, 1, 0));
```


# System

The global system that stores and manages all Flora instances.

The `FloraSystem` is the global runtime API for Flora instances.

## What It Is

`FloraSystem` stores runtime instance data and provides methods to create, modify, query, and destroy instances.

## When To Use It

Use `FloraSystem` when you need runtime control (spawning, simulation updates, queries, bulk enable/disable).

## Access Pattern

Use `FloraSystem.GetOrCreate()` to guarantee an active system.

```csharp
var flora = FloraSystem.GetOrCreate();
```

***

## Core Tasks

### Create or destroy a single instance

```csharp
FloraInstanceHandle handle = FloraSystem.GetOrCreate()
    .CreateInstance(prefab, parent, pos, rot, scale);

FloraSystem.Instance?.DestroyInstance(handle);
```

### Create or destroy a batch of instances

```csharp
FloraSystem.GetOrCreate().CreateInstances(prefab, parentObj, handlesArray, transformsArray);
FloraSystem.Instance?.DestroyInstances(handlesArray);
```

### Control instance visibility

```csharp
FloraSystem.Instance?.SetInstanceEnabled(instanceHandle, false);
FloraSystem.Instance?.SetInstancesEnabled(instanceHandleArray, false);
```

### Query instances by sphere or bounds

```csharp
var inSphere = FloraSystem.Instance?.FindInstancesIntersectingSphereMatching(filter, sphere, Allocator.Temp);
var inBounds = FloraSystem.Instance?.FindInstancesIntersectingBoundsMatching(filter, bounds, Allocator.Temp);
```

`FindInstancesIntersectingSphere*` and `FindInstancesIntersectingBounds*` test each instance's render bounds. Use these when you need objects whose visible bounds overlap an area, such as impact volumes, damage zones, or visibility tools.

`FindInstanceOriginsWithinSphere*` and `FindInstanceOriginsWithinBounds*` test each instance's transform origin. Use these when the position itself must be inside the area, regardless of mesh bounds size.

Both query families support:

* unfiltered queries
* `FloraInstanceFilter` queries, such as `ByTrees()`, `ByLayerMask(...)`, `ByIdentitySource(...)`, and `ByRenderSource(...)`
* prefab instance ID queries using `NativeArray<int>`
* allocation-returning overloads with an `Allocator`
* caller-owned `NativeList<FloraInstanceHandle>` overloads that clear and reuse the result list

Origin-query entry points are:

* `FindInstanceOriginsWithinSphere(...)`
* `FindInstanceOriginsWithinSphereMatching(...)`
* `FindInstanceOriginsWithinBounds(...)`
* `FindInstanceOriginsWithinBoundsMatching(...)`

```csharp
using var results = new NativeList<FloraInstanceHandle>(Allocator.Temp);

flora.FindInstanceOriginsWithinSphereMatching(filter, sphere, results);
flora.SetInstancesEnabled(results.AsArray(), false);

flora.FindInstancesIntersectingBounds(bounds, results);
```

***

## Example

```csharp
var flora = FloraSystem.GetOrCreate();

var handles = new NativeArray<FloraInstanceHandle>(100, Allocator.Temp);
var transforms = new NativeArray<FloraInstanceTransform>(100, Allocator.Temp);

for (int i = 0; i < 100; i++)
    transforms[i] = FloraInstanceTransform.FromPositionRotationScale(RandomPosition(), quaternion.identity, 1f);

flora.CreateInstances(grassPrefab, owner, handles, transforms);

var sphere = new BoundingSphere(playerPos, 10f);
var filter = FloraInstanceFilter.ByIdentitySource(grassPrefab);
using var nearby = flora.FindInstanceOriginsWithinSphereMatching(filter, sphere, Allocator.Temp);

flora.SetInstancesEnabled(nearby.AsArray(), false);

handles.Dispose();
transforms.Dispose();
```

## How To Verify

* Created instances are visible and have valid handles.
* Render-bounds queries return instances whose visible bounds overlap the search area.
* Origin queries return instances whose transform position is inside the search area.
* Destroy/disable calls remove visibility and invalidate stale handles.

## Migration Note

Older `InSphere` and `InBounds` query names were replaced by the `FindInstancesIntersecting...` render-bounds query names.


# Rendering

An overview of key rendering features.

This section explains Flora rendering behavior and how to tune it safely.

## Beginner Path

1. [Culling Pipeline](/rendering/culling-pipeline) - current BRG behavior.
2. [Occlusion](/rendering/occlusion) - when hidden instances are skipped.
3. [Motion Vectors](/rendering/motion-vectors) - required for motion blur/TAA.
4. [Light Probes](/rendering/light-probes) - baked/APV lighting behavior.
5. [Rendering Inspector](/rendering/rendering-inspector) - inspect sources, templates, draws, buffers, and culling structure.
6. [Debugging](/rendering/debugging) - verify what Flora is doing with live overlays.

## What This Affects

* CPU draw submission cost
* GPU culling cost
* instance visibility behavior
* memory usage for motion vectors and probes


# Culling Pipeline

An overview of each available culling pipeline used in Flora.

## Current Behavior

Flora currently uses the **Batch Renderer Group (BRG)** culling path.

> The old per-project/per-scene culling pipeline selection fields are obsolete and have no runtime effect.

## What This Affects

* CPU-side draw submission scaling
* Culling behavior per camera/view/light
* Memory tradeoffs for per-instance runtime data

***

## Batch Renderer Group

BRG-compatible shaders usually work out of the box, but you must avoid stripping required BRG variants in builds.

**Keep BRG shader variants**

* **Edit → Project Settings → Graphics**
* Set **BatchRendererGroup variants** to **Keep all**

> See Unity’s [BRG Getting Started Guide](https://docs.unity3d.com/Manual/batch-renderer-group-getting-started.html) for details.

***

### Performance

* BRG reduces CPU overhead in large scenes.
* Benefits are strongest when instance counts/types are high.

***

### Memory

BRG stores additional per-instance matrix-related data to support current Flora runtime behavior. This generally trades more instance-buffer memory for better scalability and feature support.

***

### Known Limitation: Child LOD Renderer Transforms

Child renderers under an `LODGroup` with non-identity transforms do not render using child local transforms in BRG mode.

Mitigation:

* Bake child transforms into meshes (for example via [FBX Exporter](https://docs.unity3d.com/Packages/com.unity.formats.fbx@5.1/manual/index.html)).

***

## Migration Note (Older Flora Docs/Projects)

Older Flora versions documented a selectable RenderMesh pipeline path. In current Flora runtime, this is historical context only and not a selectable runtime path.


# Occlusion

Includes both baked and runtime GPU-based occlusion culling.

Flora supports two forms of occlusion culling: **GPU-based dynamic occlusion** and **Unity’s CPU-based baked occlusion**. Both systems help skip rendering instances that are not visible to the camera, improving performance in scenes with overdraw or high instance counts.

***

### GPU Dynamic Occlusion

Flora’s GPU occlusion system uses **compute shaders** and the **previous frame’s depth buffer** to determine visibility. Occluded instances are skipped during rendering.

#### Performance Considerations

* In scenes with **significant occlusion** and **high-vertex instances**, GPU occlusion can greatly reduce rendering cost.
* In scenes with **minimal occlusion**, the extra compute pass may **increase** GPU load unnecessarily.

> GPU occlusion is **scene-dependent** — always profile with and without it to measure the impact in your project.

#### Compatibility with [GPU Resident Drawer](/rendering/gpu-resident-drawer)

If you're using Unity’s **GPU Resident Drawer**, be aware:

* Flora and GPU Resident Drawer each maintain **separate occlusion resources.**
* Both systems perform **their own depth sampling passes.**
* This can result in **redundant GPU work**, particularly on lower-end hardware.

> **Recommendation:** Use **only one** GPU occlusion system per scene to avoid unnecessary overhead.

***

### Usage

GPU occlusion is **enabled by default**, but can be configured at multiple levels:

* **Project-wide:**\
  Via [`FloraRuntimeSettings`](/scripts/runtime-settings) → *Disable GPU Occlusion*
* **Per Scene:**\
  Via [`FloraSceneSettings`](/scripts/scene-settings) → *Allow GPU Occlusion*
* **Per Camera:**\
  Via [`FloraAdditionalCameraSettings`](/scripts/instancing-camera-settings) → *Allow GPU Occlusion*

***

### CPU Baked Occlusion

Flora also supports Unity’s built-in **CPU-based occlusion culling**, which uses pre-baked visibility data to cull geometry blocked by static objects.

#### Advantages

* Ideal for **lower-end platforms** (e.g., mobile) where GPU compute may be too costly.
* Requires **no runtime compute passes.**
* Automatically used by Flora if baked occlusion data is present in the scene.

#### Setup

No special configuration is needed.

As long as occlusion data is baked using Unity's built-in tools, Flora will use it automatically.

For more information, see Unity’s [Occlusion Culling documentation](https://docs.unity3d.com/Manual/OcclusionCulling.html).


# Motion Vectors

A simple overview of rendering dynamic instances.

Flora supports per-instance motion vectors for effects like TAA and motion blur.

## What This Affects

* Visual quality for moving instances.
* Memory usage (previous transform storage).
* Per-frame update cost for moving instances.

***

### Enabling Motion Vectors

1. In [Runtime Settings](/scripts/runtime-settings), ensure `DisablePerObjectMotionVectors` is **off**.
2. In [Scene Settings](/scripts/scene-settings), enable `AllowPerObjectMotionVectors`.
3. For terrain-specific paths, enable tree/detail motion vector toggles as needed.

***

### How It Works

If prefab renderers request per-object motion vectors, Flora stores previous transforms and emits motion-vector data for those instances.

> Tip: enable this only where needed to avoid unnecessary memory cost.

***

### Terrain Trees and Details

`SceneSettings` can separately enable motion vectors for terrain trees/details. These still depend on `AllowPerObjectMotionVectors`.

## How To Verify

* Enable motion vectors and confirm moving Flora instances contribute to motion blur/TAA.
* Disable either project or scene gate and confirm contribution stops.


# Light Probes

Accurate light probe sampling per instance for baked lighting.

Flora supports legacy baked probes and APV-compatible workflows.

## What This Affects

* Indirect lighting accuracy on instances.
* Per-instance memory use when probe data is stored.

***

### Legacy Light Probes

Per-instance legacy probe data is used when all of the following are true:

1. In [Scene Settings](/scripts/scene-settings), `AllowLegacyLightProbes` is enabled.
2. In [Runtime Settings](/scripts/runtime-settings), `DisableLegacyLightProbes` is disabled.
3. Prefab renderers use probe sampling (`BlendProbes`).
4. Scene contains baked probe data.

***

### Adaptive Probe Volumes (APV)

Flora is compatible with APV through SRP lighting workflows.

## How To Verify

* Bake probes/APV data.
* Compare instance lighting with probe toggles enabled/disabled.
* Confirm expected memory/performance tradeoff for dense instance sets.


# Shaders and Materials

How Flora works with your existing shaders, and what to consider when authoring new ones.

Flora supports a wide range of Unity shaders and includes utilities for patching both Shader Graph and manually authored shaders for compatibility with instancing and selection.

***

### Shader Requirements <a href="#patching-shaders" id="patching-shaders"></a>

Every pass **must** include the following **pragma**, and will only work when the shader target is greater than 4.5.

```hlsl
#pragma multi_compile _ DOTS_INSTANCING_ON
#pragma target 4.5
```

For Universal, you can use the following **include\_with\_pragmas** to automatically setup the pass for DOTS.

```hlsl
#include_with_pragmas "Packages/com.unity.render-pipelines.universal/ShaderLibrary/DOTS.hlsl"
```

Additionally for picking to work, ensure the **ScenePickingPass** correctly returns `unity_SelectionID` and not `_SelectionID`.

This is a common error in 3rd party shaders, and affects Amplify Shader Editor (a bug request has been submitted). For ASE, modify the template shader and replace the return result of `_SelectionID` with `unity_SelectionID` in the fragment shader of any templates you are using.

```hlsl
// return _SelectionID; Replace this line with:
return unity_SelectionID;
```


# Rendering Inspector

Inspect Flora rendering data, sources, templates, draws, buffers, and culling structure in the Unity Editor.

The **Flora Rendering Inspector** is an Editor-only window for inspecting the rendering data that Flora has built from your scene. Use it when content is missing, too expensive, using the wrong source, or grouped differently than expected.

Open it from:

* **Window > Flora > Rendering Inspector**
* The **Rendering Inspector** utility button in the [Scene Settings](/scripts/scene-settings) inspector

The inspector captures a snapshot of the active `FloraSystem`. Press **Refresh** after changing scene content, materials, render settings, or terrain state.

***

## What It Shows

The inspector is organized around the data Flora sends to BatchRendererGroup:

* **Sources** - authoring objects that generated instances, such as containers, prefab instances, and terrain content.
* **Templates** - shared render definitions built from source meshes, materials, LODs, lightmap data, and renderer settings.
* **Archetypes** - groups of instances that share the same template and instance data layout.
* **Draws** - mesh/material/submesh draw entries.
* **Graphics Domains** - BatchRendererGroup batch domains and shader property bindings.
* **Graphics Buffers** - allocated GPU buffers used by Flora.
* **Grid Chunks** - culling-grid chunks, when grid details are captured.

Select any row to inspect details and relationship links. Relationship rows can be clicked to jump between related sources, templates, draws, domains, chunks, and buffers.

***

## Browser Tabs

### All

Shows every major category in one tree. Use this for broad diagnosis or when you do not yet know which part of the rendering structure is relevant.

### Authoring

Groups data around authoring templates and sources. Use this to answer questions such as “which prefab or container produced this template?” or “how many instances came from this source?”

### Structure

Shows how templates, archetypes, chunks, and draws relate to each other. Use this when investigating batching, LOD layout, draw counts, or unexpected instance grouping.

### Grid

Shows culling-grid chunks. Opening this tab captures additional grid details, so use it when diagnosing spatial grouping, culling chunk counts, or bounds-related query behavior.

### Rendering

Focuses on rendering resources: draw entries, graphics domains, shader properties, and graphics buffers. Use this when diagnosing material bindings, DOTS instancing properties, memory footprint, or buffer allocation.

***

## Navigation Tools

* **Search** filters the visible tree by names, object paths, source kinds, shader property names, and related metadata.
* **Refresh** captures a new snapshot from the active `FloraSystem`.
* **Sort > Alphabetical** keeps objects grouped by name or stable index.
* **Sort > Count** prioritizes entries with larger instance, draw, chunk, or buffer counts.
* **Frame Bounds** buttons frame selectable scene bounds in the Scene View when bounds are available.
* **Reset Layout** restores the default browser/details split.

If no system is active, the summary reports that no Flora rendering information is available. Enter Play Mode or ensure a scene contains active Flora content and [Scene Settings](/scripts/scene-settings).

***

## Rendering Inspector vs Rendering Debugger

Use the **Rendering Inspector** to inspect Editor data structures and relationships.

Use Unity's **Rendering Debugger** for live visual overlays, debug shading, culling freeze, LOD forcing, and runtime/development-build debugging. See [Debugging](/rendering/debugging).


# Debugging

A guide to using the rendering debugger in Flora.

Flora integrates with Unity’s [Rendering Debugger](https://docs.unity3d.com/6000.2/Documentation/Manual/urp/features/rendering-debugger.html) to provide tools for visualizing and inspecting **instance behavior**, **culling**, and **performance** in real time.

For Editor-only inspection of sources, templates, draws, graphics buffers, and culling-grid structure, use the [Rendering Inspector](/rendering/rendering-inspector).

<figure><img src="/files/Yc1H68wTC0p6NE0spzfE" alt="Rendering Debugger tab"><figcaption></figcaption></figure>

***

## Accessing the Rendering Debugger

Flora adds a dedicated tab to Unity’s **Rendering Debugger** window.

### Access Options

* From the menu bar:\
  **Window → Flora → Rendering Debugger**
* In a development build (Play Mode or standalone):\
  **Ctrl + Shift + Backspace**

<figure><img src="/files/VtnOomGjI0CVKNJaG7qK" alt="Flora debugger hotkey" width="563"><figcaption></figcaption></figure>

The Flora panel is available when a `FloraSystem` is active. If the system is not running, the panel shows a **Not Running** message.

***

## Debug Properties

### General

#### Debug Shading Mode

Visualizes internal instance data using shader debug colors:

* **None** - disables Flora debug shading.
* **LOD** - colors instances by selected LOD.
* **InstanceHandle** - colors instances by handle. Editor only.
* **RandomID** - colors instances by the per-instance random value, when allocated.
* **Template** - colors instances by Flora template.
* **Draw** - colors instances by draw entry.
* **DrawVariant** - colors instances by draw variant.
* **CullingBatch** - colors instances by culling batch.
* **BatchDomain** - colors instances by BatchRendererGroup batch domain.

#### Display Culling Stats

Enables collection and display of GPU culling stats in the **Culling Stats** section.

#### Enable GPU Checks

Enables GPU validation checks in the culling system. This is intended for debugging rendering or culling issues and may affect performance.

***

### Freeze Camera

The **Freeze Camera** control freezes culling for a selected active game or Scene View camera. This lets you move other cameras or inspect the scene while keeping the selected camera's culling state fixed.

The camera list is refreshed while the debugger is active and includes up to six entries.

***

### LOD

Controls how Flora selects LODs while debugging:

* **None** - uses normal LOD selection.
* **ForceLOD** - forces all eligible instances to use the selected **LOD Index**.
* **OnlyLOD** - renders only the selected **LOD Index** and culls other LODs.

`LOD Index` is shown only when a LOD mode is active.

***

### GPU Occlusion

These controls are shown when GPU occlusion is available for the active Flora system. If GPU occlusion is disabled by [Runtime Settings](/scripts/runtime-settings), [Scene Settings](/scripts/scene-settings), or camera settings, the debugger shows an info message instead.

* **Force Never Occlude** - overrides the occlusion test so instances always pass. Use this to confirm whether missing instances are being removed by GPU occlusion.
* **Occlusion Overlay** - draws the occlusion test overlay.
* **Opacity** - controls the occlusion overlay opacity.
* **Count Visible** - includes visible-instance counts in the occlusion overlay.
* **Depth Overlay** - displays the occluder depth pyramid debug view.
* **Range Min / Range Max** - remaps the depth-overlay display range.

***

### Spatial Hash

Displays Flora's culling grid as procedural debug lines.

**Mode**

* **Disabled** - no spatial-hash overlay.
* **Heatmap** - visualizes occupancy/intensity.
* **Level** - visualizes culling-grid levels.

**Types**

* **Blocks** - top-level grid regions.
* **Cells** - mid-level grid cells.
* **Chunks** - instance chunks inside cells.

**Draw Distance** limits how far the overlay draws from the camera.

***

### Culling Stats

When **Display Culling Stats** is enabled, the debugger shows:

* **View Count**
* **Per View Stats**
  * View
  * Visible Draws
  * Visible Instances
  * Occluded Instances

These stats are useful for checking whether Flora is producing draw work for each view and whether GPU occlusion is removing instances.

***

## How To Verify

* Set **Debug Shading Mode** to **LOD** and confirm Flora instances are tinted by LOD.
* Enable **Display Culling Stats** and confirm view rows update while cameras render.
* Enable **Force Never Occlude** when GPU occlusion is active; missing instances that reappear were being occluded.
* Enable **Spatial Hash > Cells** and confirm the culling grid overlay follows active Flora content.


# GPU Resident Drawer

Details on how Flora works with Unity's GPU Resident Drawer.

Flora and Unity GPU Resident Drawer solve similar rendering problems with different content ownership models.

## Guidance

* Use Flora when you need terrain foliage support, container workflows, or runtime-created instance populations.
* Use GPU Resident Drawer for MeshRenderer-driven workflows where its defaults fit your project.

## What This Affects

* Memory footprint at high instance counts.
* Authoring workflow (`GameObject`-centric vs data-driven instancing).
* Occlusion workload if both systems run.

***

## Content Model Differences

* **GPU Resident Drawer**: active `GameObject` + `MeshRenderer` driven.
* **Flora**: supports terrain, containers, and runtime instance data without requiring one render `GameObject` path per instance.

Related Flora workflows:

* [Terrain Provider](/scripts/terrain-provider)
* [Instance Container](/scripts/instance-container)
* [Runtime Samples](/samples/runtime-samples#fish-boids)

***

## Occlusion Interaction

Both systems maintain separate occlusion resources. Running both over overlapping content can duplicate GPU work.

## Practical Recommendation

For the same content path, prefer one primary instancing/occlusion strategy and profile scene cost.


