Skip to content
shiphrahxPublic

About

No description, website, or topics provided.

Resources

Stars

0 stars

Watchers

0 watching

Forks

Latest commit

 

History

195 Commits

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Ascent

Two AI coding agents were given the same brief: build a hot-air balloon flight over late-winter Cappadocia that runs in a browser and looks as close to Unreal Engine 5 as a laptop allows.

Astra (OpenAI Codex) Opus (Claude Opus 5.5)
Astra in flight Opus in flight

Both builds are live at shiphrahx.github.io/ascent.

The experiment

The experiment compares how each agent approaches an open-ended real-time graphics problem: the techniques it picks, how it measures its own work, and how it reports what's still missing.

Each agent built its version from scratch, then worked through two rounds of fidelity plans. Every plan follows the same loop:

  • a review of what looks wrong, from the code and from captures of the running game
  • phased tasks, one commit per task
  • before and after captures from the same camera and hour
  • GPU cost and frame pacing measured after every step
  • a ranked list at the end of what's still short of the UE look

The plans and results: Astra/FIDELITY_PLAN.md, Astra/FIDELITY_PLAN_2.md, Opus/FIDELITY_PLAN.md, Opus/FIDELITY_PLAN_2.md and Opus/PERF_FIX.md.

Shared constraints

  • One standalone HTML file, every asset embedded, no network requests.
  • three.js on WebGL2, bundled with esbuild.
  • Procedural world: terrain, fairy chimneys, river, village, vegetation, a fleet of balloons, birds and horses.
  • A timelapse day cycle from sunrise to night, plus a snowstorm.
  • Three quality tiers (high, medium, lite). medium has to hold 60 fps on an AMD Radeon 890M integrated GPU.

Two approaches to the renderer

Astra builds on three.js. It extends the standard PBR materials through onBeforeCompile and uses three's addons for the main systems: CSM for cascaded shadows, Sky for scattering, Reflector for the river, EffectComposer and UnrealBloomPass for post. Its own passes add temporal filtering, histogram exposure, shadow history and terrain horizon fields.

Opus replaces most of three.js's rendering. Raw ShaderMaterials share a hand-written GLSL library, and each frame runs through an explicit pipeline:

sky LUT → terrain shadow heights → shadow cascades → jittered HDR scene
→ AO → volumetrics → transparents → temporal upsample → post

three.js is used mainly for buffers, render targets and draw calls.

Technology side by side

Area Astra Opus
three.js r180 r170
Anti-aliasing 4× MSAA on scene geometry, plus a temporal filter with depth reprojection and neighbourhood clipping (after Playdead's GDC 2016 talk). No FXAA. Jittered TAA with variance clipping in YCoCg, then temporal upsampling to display resolution
Resolution Fixed pixel budget per tier, native at 1440×900 Dynamic resolution; targets allocated once and drawn into a viewport so TAA history survives scale changes; frame pacing locked to the refresh rate
Sky three's Sky model, with a cloud ray-march (96 steps) cached in a 4096-wide texture and refreshed in tiles Physically based sky LUT (Rayleigh, Mie, ozone, planet shadow), plus moon, stars, Milky Way, 22° halo and sun dogs
Clouds Part of the cached sky texture; their shadows move across the ground Separate pass at a third of render size on high: Worley erosion, Beer and powder terms, multiple-scattering octaves, temporal accumulation
Atmosphere Aerial perspective coloured by the sky model, replacing three's grey FogExp2 Closed-form RGB aerial perspective from the LUT's coefficients; quarter-res ray-marched light shafts and snowstorm haze
Shadows CSM, 3 cascades out to 1.9 km, 4096 near map on high, fixed Poisson-disk filter, reprojected shadow history blending on lower tiers. Distant terrain shadows from a directional horizon field in a 3D texture. Own cascades (4 on high) fitted to frustum-slice spheres and texel-snapped to a fixed anchor, PCSS with 16 blue-noise taps, a 2048×1024 heightmap shadow with distance-based penumbra, screen-space contact shadows
Indirect light Terrain sky visibility from horizon angles, blurred ground radiance as a single bounce GTAO-style sky visibility over the heightmap, a 512×256 ground bounce map with mips, SSAO on indirect light only
Materials Fully procedural: seamless maps generated at build time from seeded noise fields, rock strata in world space with analytic filtering CC0 Poly Haven photo scans packed into 1024px JPEGs (albedo with baked AO, normal with height), triplanar on steep faces, parallax occlusion within 60 m, specular AA
Terrain Geological fields for strata terracing, drainage erosion and talus; far terrain as LOD rings 2.5 m core heightmap; on high a 1.25 m relief built on the GPU at load with gullies, strata ledges and scree
Water three's Reflector Mirrored-camera reflection with simplified shading, rendered every frame
Tone mapping AgX, chosen over ACES because it keeps detail in snow highlights UE5's filmic curve at its default settings
Exposure Histogram auto exposure Histogram eye adaptation plus local exposure
Post Bloom with no threshold, vignette on high, no motion blur or grain 7-level bloom, motion blur, close-up depth of field, edge chromatic aberration, film grain, heat shimmer
Draw calls Rigid balloon, bird and horse parts batched into instances (362 meshes in 26 batches), 22% fewer draws Instanced rocks, vegetation and village, with dithered LOD cross-fades
Test harness Playwright on Chromium puppeteer-core driving Edge
Source size ~217 KB ~500 KB
Output Astra/Ascent.html, 8.0 MB Opus/cappadocia.html, 6.3 MB

How each one measured itself

Astra runs the production shader functions against known inputs in GPU fixtures, and stamps every report with the build hash so stale numbers are rejected. Its light-stability tool runs a spectrum over frame luminance, which found the burner light pulsing at 3 Hz.

Opus reprojects every pixel through depth, the same way TAA does, and scores the second difference along that track against a flat-grey control. It splits the score by source (balloon, terrain, village, sky edges) and switches features off one at a time. This showed SSAO noise, not shadows, caused most of the flicker in flight.

Results

Each build's numbers come from its own write-up. The methods differ, so they aren't a direct comparison.

Astra on the Radeon 890M at 1440×900:

  • medium and lite hold 59.9 fps with a p99 of 17 ms.
  • high on the 890M runs at 41 fps.
  • Landscape flicker fell by about 20% on medium, short of the 70% target.
  • Remaining gaps: landform geometry, material scale, subpixel stability.

Opus at 1600×900:

  • high takes 9.9 ms of GPU time on an RTX 5070 Ti laptop.
  • medium takes 15.5 ms on the 890M and holds 60 fps at 0.9 render scale or above.
  • Shadow flicker in flight fell to 0.10 / 0.04, against a target of 0.30 / 0.20.
  • Remaining gaps: village and crew models, richer GI, cliffs that are still a heightfield.

About

No description, website, or topics provided.

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages