bevyengine/bevy · critical

Too many triangles ({triangle_count}) in an emissive mesh, m

Error message

Too many triangles ({triangle_count}) in an emissive mesh, maximum is 65535.

What it means

GpuLightSource::new_emissive_mesh_light (scene/binder.rs:418-424) stores the emissive mesh's triangle count in the u32 `kind` field shifted left by one bit (the low bit is the light-kind tag), leaving only 16 bits for the count. A single emissive mesh with more than 65,535 triangles therefore panics with the actual count in the message.

Source

Thrown at crates/bevy_solari/src/scene/binder.rs:428

    base_color: Vec3,
    perceptual_roughness: f32,
    emissive: Vec3,
    metallic: f32,
    _padding: Vec3,
    reflectance: f32,
}

#[derive(ShaderType)]
struct GpuLightSource {
    kind: u32,
    id: u32,
}

impl GpuLightSource {
    fn new_emissive_mesh_light(instance_id: u32, triangle_count: u32) -> GpuLightSource {
        if triangle_count > u16::MAX as u32 {
            panic!("Too many triangles ({triangle_count}) in an emissive mesh, maximum is 65535.");
        }

        Self {
            kind: triangle_count << 1,
            id: instance_id,
        }
    }

    fn new_directional_light(directional_light_id: u32) -> GpuLightSource {
        Self {
            kind: 1,
            id: directional_light_id,
        }
    }
}

#[derive(ShaderType, Default)]
struct GpuDirectionalLight {

View on GitHub (pinned to 4805ca792c)

Solutions

  1. Split the emissive mesh so each part has at most 65,535 triangles
  2. Use a simplified low-poly emissive proxy for the light and keep the detailed mesh non-emissive
  3. Remove the emissive component from high-poly scenery that should not light the scene
  4. Decimate the mesh below the limit

Example fix

// before — one 200k-triangle emissive mesh
commands.spawn((
    high_poly_mesh,
    StandardMaterial { emissive: emissive_color, ..default() },
));

// after — detailed mesh stays non-emissive, low-poly proxy emits the light
commands.spawn((high_poly_mesh, StandardMaterial::default()));
commands.spawn((low_poly_proxy_mesh, StandardMaterial { emissive: emissive_color, ..default() }));
Defensive patterns

Strategy: validation

Validate before calling

fn tri_count(mesh: &Mesh) -> usize {
    match mesh.indices() {
        Some(indices) => indices.len() / 3,
        None => mesh.count_vertices() / 3,
    }
}

// before assigning an emissive material under Solari:
assert!(
    tri_count(&mesh) <= u16::MAX as usize,
    "emissive mesh too dense for Solari: {} triangles",
    tri_count(&mesh)
);

Prevention

When it happens

Trigger: Assigning an emissive material to any mesh with >65535 triangles while the Solari renderer processes the scene (indices.len()/3 above u16::MAX).

Common situations: High-poly GLTF imports whose materials are emissive; using emissive materials as decoration on dense scenery meshes; decimated-but-still-large models marked emissive.

Related errors


AI-assisted analysis of bevyengine/bevy@4805ca792c (2026-08-20). Data as JSON: /api/errors/dcf08bcb7f7d8000. Report an issue: GitHub.