post: fix GPU herds — tested 1000 mixed animals, not projected
This commit is contained in:
@@ -280,7 +280,7 @@
|
||||
<p class="post__lead">Godot gives you one <code>Skeleton3D</code> per character. Want 200 animals in a herd? That's 200 skeleton nodes, 200 draw calls, and 200 <code>AnimationPlayer</code> ticks every frame. Want 1,000? Now you're measuring in seconds per frame, not frames per second.</p>
|
||||
|
||||
<div class="post__body">
|
||||
<p>We built a GPU skinned-instance renderer into Tinqs Engine that packs every pose into a single texture, uploads once, and draws every instance in one call. 25 crocodiles on screen right now. 1,000+ projected. Same bone count, same animation fidelity — a tiny fraction of the cost.</p>
|
||||
<p>We built a GPU skinned-instance renderer into Tinqs Engine that packs every pose into a single texture, uploads once, and draws every instance in one call. 25 crocodiles confirmed first. Then we threw 1,000 animals — 12 types mixed, random-walking — at it and the GPU didn't flinch. Same bone count, same animation fidelity, a tiny fraction of the cost.</p>
|
||||
<h2>Why the engine needs to change</h2>
|
||||
<p>The standard Godot approach — one <code>Skeleton3D</code> + one <code>MeshInstance3D</code> per character — works for a handful of animated entities. It breaks down hard at crowd scale:</p>
|
||||
<ul>
|
||||
@@ -325,7 +325,7 @@ data.update() # upload only dirty instances, not the whole texture</code></pre
|
||||
<p>The lesson: doctests catch logic. Rendering catches truth. You need both.</p>
|
||||
<h2>What's driving it</h2>
|
||||
<p>In <a href="https://www.arikigame.com" style="color: var(--c-lime);">Ariki</a>, the sim tracks animal migration across a 12km archipelago. <code>AnimalHerdRenderer.cs</code> groups sim <code>ViewerState.animals</code> by type, feeds positions to <code>skinned_herd.gd</code> (a reusable per-type herd backend), which drives the renderer. One <code>AnimationPlayer</code> animates a single driver skeleton; poses propagate to every instance.</p>
|
||||
<p>The crocodile herd scene is 25 instances, one draw call. The same pipeline projects to 200–1,000 before the GPU budget even notices.</p>
|
||||
<p>The crocodile herd scene was 25 instances, one draw call. The perf test scene does 1,000 animals across 12 types — Boar, Cow, Crab, Crocodile, Deer, Fish, Goat, Hen, Pig, Rabbit, Sheep, Tiger — each type its own GPU herd, all mixed, all random-walking, FPS holding steady.</p>
|
||||
<h2>What's deliberately not here</h2>
|
||||
<ul>
|
||||
<li><strong>No C# wrapper.</strong> Instantiate from GDScript via <code>ClassDB.instantiate()</code> — the binding surface is small and stable.</li>
|
||||
@@ -333,7 +333,7 @@ data.update() # upload only dirty instances, not the whole texture</code></pre
|
||||
<li><strong>No GPU occlusion or LOD.</strong> That's the game's job. The engine provides the tool; the game decides what to draw.</li>
|
||||
</ul>
|
||||
<h2>Get the build</h2>
|
||||
<p>Pre-built editor binaries with <code>agent_skinned</code> baked in — no engine compile required:</p>
|
||||
<p>Pre-built editor binaries with <code>agent_skinned</code> baked in — no engine compile required. The game's <code>animal_perf_test.tscn</code> lets you toggle 10 / 100 / 1000 animals and read live FPS:</p>
|
||||
<p>| Platform | Binary | Engine commit |</p>
|
||||
<p>|———-|——–|—————|</p>
|
||||
<p>| <strong>macOS ARM64</strong> | <a href="https://tinqs.com/tinqs/builds/media/branch/main/engine/macos-arm64/tinqs.macos.editor.arm64.mono" style="color: var(--c-lime);"><code>tinqs.macos.editor.arm64.mono</code></a> | <code>4fe1323</code> (4.6.4, Xcode 26.3) |</p>
|
||||
|
||||
|
Before
After
|
Reference in New Issue
Block a user