Kanda Graphics 0.6.0
Loading...
Searching...
No Matches
Outline

Overview

The outline feature visually highlights meshes by rendering an inflated version using backface culling (inverted hull technique). Outline thickness dynamically adjusts based on camera distance and can be controlled at runtime.

Setup

  1. Add Outline Authoring component to target entity
  2. Configure:
    • Material: Outline material (defaults to M_Outline)
    • ThicknessMultiplier: Outline width (0-1)
    • BakeNormals: Enables smooth normals for hard edges
    • CombineSubMeshes: Enables outlines on meshes with multiple submeshes

Technical Details

Mesh Processing

  • Smooth normals are baked into UV3 channel for better quality on hard edges
  • Submeshes are combined to handle multi-material meshes correctly
  • Both operations require mesh Read/Write enabled

Limitations

Child meshes receive individual outlines rather than a single combined outline.

Implementation

Two primary systems:

  • OutlineInitializationClientSystem: Material setup and mesh processing
  • OutlineRenderClientSystem: Outline renderer lifecycle management

The outline shader (Assets/Shaders/Outline) can be modified via Shader Graph.

Code Example

// System that pulses outline thickness and toggles visibility every few seconds
public partial struct PulsingOutlineSystem : ISystem
{
private double _lastToggleTime;
private const float ToggleInterval = 3f;
public void OnCreate(ref SystemState state)
{
state.RequireForUpdate();
}
public void OnUpdate(ref SystemState state)
{
var time = SystemAPI.Time.ElapsedTime;
var pulseValue = (math.sin((float)time * 2f) + 1f) * 0.5f;
// Toggle outline every ToggleInterval seconds
if (time - _lastToggleTime > ToggleInterval)
{
_lastToggleTime = time;
foreach (var (_, entity) in
SystemAPI.Query<RefRW>().WithEntityAccess())
{
var isEnabled = SystemAPI.IsComponentEnabled(entity);
SystemAPI.SetComponentEnabled(entity, !isEnabled);
}
}
// Update thickness for visible outlines
foreach (var outline in
SystemAPI.Query<RefRW>()
.WithEnabledComponent())
{
outline.ValueRW.ThicknessMultiplier = pulseValue;
}
}
}