跪拜 Guibai
← Back to the summary

The 1.4-MB FPS That Generates Everything: A Teardown of Saltline and an AI-Built Clone

After seeing that browser shooter of only about 1.4 MB, my first reaction was: I'm impressed. The dock after rain, the rust on cargo containers, the highlights on the gun, the gait of the mechanical dog—all of it fits inside an HTML file. Only after opening it did I realize that a small file can still hold a complete visual experience.

I then used GPT / Codex to build "Mist Harbor". After the previous WeChat article was published, many friends pointed out a gap in visual quality, and also asked: who did you reference? Is renaming it enough to call it self-developed? I went through the comments on the previous article and also searched recent private messages. The doubts about this project came mainly from comments. This time, I'll first clarify the source, then break down the technology that really impressed me.

First clarify the source, and respond to a few doubts

The file I initially received was called "JiMao Domestic 3A Masterpiece_V1.html", and the page said Fable5.2. Based on the Saltline clue everyone provided, I found a public mirror and compared the files: the sky, rendering, materials, rain, audio, and many other main implementations were consistent; the received version mainly changed the Chinese interface, fonts, title, and project description. Therefore, the technical highlights discussed in this article should be attributed to the underlying "Saltline" implementation, not as new technology added by the Chinese renamed version.

The public mirror description attributes the original work to the Claude Fable 5.2 experiment initiated by Felix Rieseberg, and links to the original Claude Artifact and release post. Here I complete the source attribution. The previous article only introduced the source based on the received file name, which could mislead; and "self-developed" should not be taken as verified fact merely because it appears on the page.

Mist Harbor explicitly references its rainy-harbor atmosphere, first-person shooting, mechanical guards, and the gameplay of shutting down three objectives and then evacuating; these similarities cannot be brushed over. My attempt was to re-implement and iterate with GPT/Codex, and the code organization and specific implementation differ; that does not mean there was no borrowing in gameplay and visual direction, nor should it be packaged as creation out of nowhere. Development was primarily AI-assisted.

I understand everyone wants the source and attribution to be clear. After getting that right, I'd rather bring the discussion back to the implementation itself: what did this small work do right, and what can we learn from it? This article does not judge the motives of those who renamed and spread it, nor does it reach a copyright conclusion for any work.

01-saltline-localized-gameplay.png

Real gameplay of the reference implementation: running the Saltline main body through the received "JiMao" Chinese interface. High quality, dynamic resolution off; 1500 × 748 browser window. The technical analysis below is attributed to Saltline.

1.4 MB, where exactly is it small?

The received HTML measures 1,425,707 bytes, about 1.43 MB in decimal, or about 1.36 MiB in binary. It contains Three.js, as well as the code for UI, game logic, and asset generation. A small file doesn't mean it doesn't use a 3D engine, nor that everything is hand-written low-level graphics code.

Its smartest move is replacing large amounts of "result data" with "generation rules": models are constructed from geometric parameters, textures are drawn with algorithms, and sound is synthesized from signals. Every large texture, audio clip, or complex model you don't store saves a big chunk of size. At browser startup, these rules are expanded into meshes, textures, and audio buffers.

Download: code + parameters + bundled graphics library
Startup: generate geometry, textures, sound, precompile shaders
Runtime: update gameplay and animation, render in real time on GPU

So I'll also respond to that very practical comment: this still consumes CPU, GPU, memory, and video memory. Especially high-resolution shadows, reflections, and multi-pass post-processing all have costs. Small package, light runtime, and good visuals are three separate metrics that need to be verified individually.

Good visuals start with getting 'objects' and 'surfaces' right

01 | Modeling has dimensions and manufacturing logic

A cargo container isn't just a cube painted different colors. Corrugations, corner castings, lock bars, door frames, and markings together tell you what it is; the gun is broken down into receiver, handguard, barrel, rails, and moving parts. The value of procedural modeling is being able to repeatedly generate structured objects with a small number of parameters. Close-up silhouettes, edge bevels, and proportions matter more to how it looks than blindly adding decoration.

02 | Procedural materials describe color, roughness, and surface relief simultaneously

It has a dedicated material generation pipeline that combines noise, scratches, rust, and paint damage. One part generates color, ORM (occlusion, roughness, metalness), and height data offscreen on the GPU, then derives normals from height, and caches them for material reuse. This is runtime baking; you don't have to regenerate all textures every frame. The rust locations also affect roughness and other data, so specular highlights can change with surface state.

03 | Large, medium, and small scales work together

Large-area stains break up regular repetition, medium-scale rust spots and wash marks tell the environment's story, small-scale scratches, grains, and micro-normals give something to see up close. A single tiled noise layer usually produces uniform dirt; stacking different scales and directions makes an object look long-used. Some materials also use triplanar mapping, projecting textures by world position and surface orientation, reducing the dependence on manual UV unwrapping for complex procedural geometry.

04 | Text, markings, and thin distant lines are also handled carefully

Cargo markings and warning signs can be drawn with Canvas and turned into decal textures. Thin-line structures like chain-link fences also consider coverage when scaled down at distance, to avoid popping in and out when you step back. These kinds of details rarely become marketing headlines, yet they directly affect the stability and credibility of the image.

The rain harbor's realism comes from a coordinated lighting system

05 | The sky participates in background, fog, and ambient light

The sky shader uses multi-layered noise for clouds, combined with sun direction to handle gaps in clouds, warm cloud edges, and the distant horizon. The relevant colors and sun parameters also feed environment reflections and fog. So the sky, metal reflections, and distant views in the scene tell the same weather story, making it less likely to see a disconnect like "overcast sky but objects look like noon."

06 | Soft shadows consider distance between occluder and receiving surface

It extends shadow sampling: first search occlusion depth, then estimate penumbra range based on distance, and finally filter. Treat it as an implementation of the PCSS idea rather than uniformly blurring all shadows. The contact point near the object should be solid, and the edge softens away from the contact, making objects easier to "stand on the ground."

07 | Wet ground isn't a shiny mirror

The ground transitions continuously from dry, damp, soaked, to puddles. Roughness, color, normals, and reflection intensity change together: puddles reflect relatively clear images, damp ground only leaves a blurrier sheen. Near water edges, world-space noise is layered to reduce banding caused by regular textures. This is a section I found particularly worth reading closely.

08 | Planar reflections, rain ripples, and ocean surface each do their job

Dock puddles use planar reflection to supplement environment reflection information; raindrops create diffuse normal perturbation on the water surface. The ocean separately handles wind waves, light-dark variation, and shore foam. Different bodies of water don't all get crudely slapped with a "bright blue material," so water's scale and position read more clearly.

09 | Rain knows where the roofs are

Rain streaks and splashes are mostly generated with instanced data and shaders, and visibility is handled with occlusion regions and ground info. Indoors under a canopy, the rain's visuals and sound change. Weather isn't just a transparent full-screen animation; it interacts with the scene.

02-saltline-localized-aim.png

Actual aiming view in the reference implementation. Independent first-person gun camera, weapon details, and rain harbor background together form the FPS experience.

From the scene to the final image, there's an entire processing chain in between

10 | HDR and exposure leave room for bright lights

It first stores a wider luminance range in an HDR buffer, then does exposure and tone mapping. The sun, lights, and sky don't have to be clipped into the same white too early. The implementation shows brightness adaptation and a combination of ACES and AgX-style curves; these adjustments determine how highlights roll off and how much shadow detail remains.

11 | Contact shadows and volumetric light are computed separately, then composited by depth

Screen-space ambient occlusion adds darkness at contact points, while volumetric light uses depth, shadows, and sun direction to add light-dark layering in the air. Both are computed at half resolution to control cost, then filtered and composited with depth in mind, minimizing the smearing of silhouettes together. Its virtue is that each step has a purpose, not just a list of effect names.

12 | Bloom, glare, and color grading all serve one image goal

Bloom does multi-level downsampling and upsampling to spread highlights; lens flare considers whether the sun is visible. Finally there's warm/cool separation, subtle grain, anti-aliasing, sharpening, and dithering to prevent banding. Restraint matters; "brighter, blurrier, more filters" is not automatically more realistic.

Guns, enemies, and sound turn pretty screenshots into a playable experience

13 | First-person weapon has its own camera and dynamic feedback

The world camera and the gun camera use different fields of view to balance scene perspective and weapon proportions; the weapon is driven by aiming, movement, firing, and reload states. Springs give recoil, sway, and return some inertia; movable magazines, bolt carriers, and hands add motion detail. The gun is a large object that's always on screen, so it deserves the most close-up detail.

14 | Mechanical dog's paws land first, then joints follow

Quadruped movement uses paw support, leg swing trajectories, and joint inverse kinematics, combined with body pitch, roll, and bounce. While the paw stays on the ground, the body can still move forward, which looks far more natural than the whole model bobbing up and down. Drones also have separate movement for the body, rotors, and sensors.

15 | Enemies have perception, memory, and attack rhythm

It distinguishes patrol, combat, and search states, checks line-of-sight occlusion, saves last known positions, uses grid A* for pathfinding, and simplifies routes. Attacks are limited by tokens and intervals to restrict how many can hit at once, and warnings are given. These decisions affect performance and whether players can read the combat, rather than just being drained by a group of enemies simultaneously.

16 | Sound is also synthesized in code, with attention to startup and spatial presence

Gunshots, shell casings, footsteps, wind and rain, and mechanical noises are generated as audio buffers by algorithms; different reverb is used indoors vs. outdoors, sound sources have spatial positions, and music intensity changes with state. Non-urgent sounds are generated in small batches over time to avoid blocking startup by synthesizing all audio at once. No large audio pack is downloaded, yet the runtime still has a complete auditory layer.

It also manages the cost of every frame carefully

17 | Repeated parts and short-lived effects are reused as much as possible

Static parts are merged by material and shadow conditions; instanced meshes, skeletal meshes, and parts needing independent movement are handled separately. Particles use fixed-capacity data buffers, and short-lived point lights are reused from a pool. Large amounts of rain streaks, sparks, and smoke therefore don't need to spawn a ton of new objects every frame.

18 | Quality has budgets, startup has pre-warming, and failure has fallback paths

The implementation offers multiple quality levels, dynamic resolution, pixel budgets, texture and shadow resolution limits; before entering the game it precompiles shaders and checks for capabilities required by advanced rendering. Expensive effects can be downgraded, and failures in some modules have fallback handling. It knows quality requires compute and leaves room for different devices.

Among these 18 points, none is unusual on its own. What shook me is that they're all packaged into a complete small scene that you can open and play, with a coherent visual direction. This reflects the completeness of this Fable work in procedural asset generation, graphics pipeline, and system integration. Based on a single work, I won't extend it into a ranking of all models or all tasks.

Where is Mist Harbor the same, and where does it differ?

The similarities are clear: both are Three.js browser FPS games, both rely on procedural geometry and real-time rendering, and both use the rain-harbor, mechanical enemies, three objectives, and evacuation structure. Later, Mist Harbor also studied procedural materials, wet-ground reflections, independent gun camera, spring animations, and quadruped IK. These commonalities should be acknowledged openly.

The difference, first, is in the asset route. The previous article's corresponding Mist Harbor 0.2 used locally scanned textures; the single-file offline version was 7,893,868 bytes, about 7.53 MiB. Scanned textures can quickly fill in surface detail, but the file grows larger and won't automatically fix model proportions, repetitive layouts, or lighting inconsistencies.

03-harbor-v02.png

Historical real-game screenshot of Mist Harbor 0.2, corresponding to the earlier implementation in the previous article; don't take it as the current 1.0.

1.0 switched to procedural materials and rebuilt the harbor area and weapons; the offline HTML is 853,360 bytes, about 0.814 MiB; the static directory is 853,568 bytes. Being smaller than the reference doesn't mean it looks better: the reference implementation still has more material variety, sound layering, scene organization, and tuning detail from which to learn.

04-harbor-v10.png

Real gameplay from Mist Harbor 1.0's official URL, high detail, auto-quality off, also 1500 × 748 browser window. The two screenshots are taken from each game's starting area, not a same-camera, same-condition performance benchmark.

Code organization also differs. Mist Harbor keeps modular development: game handles input, gameplay, and navigation; world handles the scene; terrain handles wet ground, ocean, and rain; art handles materials and post-processing; rifle handles the gun; weapon handles mechanical guards and sound effects; effects handles the particle pool; then it gets bundled into an offline HTML. Although the reference version ships as a single HTML, you can still see module boundaries inside; it's not without architecture.

Material generation also differs concretely: the reference has GPU offscreen baking and material caching; Mist Harbor 1.0 currently generates five sets of base color, normal, and roughness textures in JavaScript, then layers wetness and wear in world space. Both can be called procedural materials, but the generation location, material coverage, and organization of surface detail are different.

For navigation, early Mist Harbor used a shared BFS distance field for obstacle avoidance, and 1.0 added A* for last-known positions; Saltline's navigation has A*, obstacle inflation, and route line-of-sight simplification. Both solve similar problems, but details and completeness still differ. Being specific about these is more meaningful than saying "different technologies were used."

05-harbor-v10-interior.png

Mist Harbor 1.0 maintenance shed view, from local acceptance testing, camera position adjusted via test interface; used to show structures, lighting, and the gun light, not an unassisted human playthrough.

1.0 added a connection between the gun light and detection risk, and also fixed an instance-batching bug that made parts disappear: generating isn't the same as actually rendering. Now quantity checks confirm 4,823 static instances remain intact. These are concrete tasks in Mist Harbor's iteration, not a substitute for seriously comparing the reference's artistic output.

Previously, 21 local gameplay checks passed; the official URL also re-tested startup, shooting, and the gun light. But passing functional checks doesn't mean every visual matches the reference. You can compare composition, wet/dry layering, weapon silhouettes, and spatial details in the screenshots yourself, and you're welcome to play directly.

Learning together beats arguing over who's stronger

I truly admire the effect of this ~1.4 MB project. It reminds me that code size, effect names, and asset size are not the goal; what's hard is making shape, material, lighting, animation, sound, and gameplay work together.

Attribution and credit need to be taken seriously, and so does learning. I hope this piece lets us spend less time on labels and more time opening up implementations to look at: how puddles transition, how shadows soften, how paws land solidly, how audio is generated in batches. These are worth discussing and easy to experiment with in your own different subjects.

If you want to compare, I suggest experiencing both on the same computer and same browser. Tell me which part feels real, which still looks blocky, which weapon feedback is more comfortable, and your quality settings. I'll continue making changes based on specific feedback.

Play, source code, and attributions

Saltline original Claude Artifact (source entry)

Saltline original release post (Felix Rieseberg)

Saltline public mirror and description (mirror maintainer is not the original author)

Received "JiMao" Chinese comparison version playable

Mist Harbor 1.0 playable

Mist Harbor source code and version history

Mist Harbor 1.0 offline release

Note: This article is based on an analysis of the received HTML, the public Saltline mirror, and Mist Harbor's current code; original attribution follows the mirror's description and its source links, and I did not independently verify the original's complete generation process. This article does not treat works with different prompts, time budgets, and iteration counts as same-condition model benchmarks. The "52 minutes" from the previous article only refers to the early development scope, not the later 0.3 and 1.0 optimizations. Screenshots are from actual web runs or explicitly labeled historical/acceptance views; no generated images were passed off as real gameplay. The article was organized and written with AI assistance.

Welcome to follow WeChat public account: 数字机器莱西奥 (Digital Machine Lesio)