Skip to main content

Rendering for a Console Without a Z-Buffer

Creator of Polygon Engine

The original PlayStation is not just a slow modern GPU. It is a different rendering model. That difference is the reason Polygon Engine treats PS1 rendering as a content and tooling problem, not only as a runtime problem.

The editor can show a clean 3D scene. The PS1 runtime has to turn that scene into ordered GPU primitives with no z-buffer, fixed-point transforms, small memory pools, and a very unforgiving camera near plane.

The Core Constraint

Modern engines usually rely on a z-buffer. If two triangles overlap on screen, the GPU can compare depth per pixel and keep the closest fragment. The PS1 GPU does not do that.

The PS1 pipeline is closer to this:

model vertices
-> GTE transform and projection
-> depth estimate
-> ordering table bucket
-> GPU primitive packet
-> draw in ordered submission

That means visibility is approximate. A triangle is not resolved per pixel against every other triangle. The engine picks an ordering bucket, inserts a primitive, and the GPU draws it when that bucket is processed.

Polygon Engine's runtime uses an ordering table length of 2048, with the first 64 buckets reserved for UI and foreground work. That gives a useful depth range, but it does not make arbitrary overlapping geometry safe.

Why Editor Geometry Lies

An editor viewport can make bad PS1 content look fine:

  • giant floors look stable because the preview can sort or rasterize more forgivingly,
  • overlapping walls look acceptable because the desktop path can hide depth ambiguity,
  • thin coplanar details look crisp until the PS1 ordering table flips them,
  • very close walls look fine until they cross the near plane,
  • transparent materials look correct until draw order becomes content-dependent.

The practical lesson is that PS1 scenes need authoring rules. The renderer alone cannot make every scene correct.

Ordering Table Policy in Polygon Engine

The runtime estimates depth and clamps primitives into ordering table buckets. It also computes GTE ordering scale values from the configured far distance, because a very large far plane spreads limited depth precision across too much space.

That is why the editor warns when PS1 far distance goes above roughly 32 world units. A larger range can be useful, but it reduces ordering precision and makes polygon overlap more visible.

The runtime currently combines several strategies:

ProblemRuntime/editor response
Depth buckets are finiteClamp primitives into a bounded ordering table
UI must stay readableReserve foreground buckets for authored UI
Large surfaces sort poorlyWarn and bake compatible static geometry into smaller chunks
Mesh triangles can conflict internallyUse per-mesh triangle sorting when appropriate
Transparent/double-sided surfaces are fragileValidate and warn in the editor

This is not a full visibility solver. It is a PS1-appropriate compromise.

Near-Plane Clipping

One of the most obvious PS1 rendering failures is a wall face disappearing when the player gets close. This happens when a primitive crosses the camera near plane and the renderer either rejects it too aggressively or projects invalid coordinates.

Polygon Engine's runtime handles this with conservative near-plane policy:

  • keep mesh chunks alive when their bounds touch the near plane,
  • let per-triangle clipping decide what survives,
  • clip triangles and quads against the complete visible frustum,
  • use safe projected coordinates when vertices get too close,
  • prevent lateral grazing from collapsing extreme coordinates into the GPU's signed screen-coordinate range,
  • avoid relying on a coarse object cull for close camera geometry.

That work was necessary for first-person scenes. In a first-person game, the camera constantly touches walls, terminals, pickups, and doors. Near-plane clipping is not an edge case; it is part of normal play.

Large Triangles Are a Content Bug

The PS1 can draw large polygons, but large polygons are harder to order. A single wall quad that spans a whole corridor can overlap many objects and still produce one approximate depth value. The larger the primitive, the more likely the order is wrong for part of the screen.

Polygon Engine pushes against that in two places:

  1. Authoring guidance: use smaller modular pieces for floors, walls, and thresholds.
  2. Build processing: compatible static Plane and Cube geometry can be baked into smaller staged mesh chunks.

The runtime also has a triangle sorting cap for mesh-local sorting. That cap keeps sorting useful without letting sorting itself become the frame-time problem.

The Supported Boundary

Polygon Engine does not claim to provide:

  • it does not add a z-buffer to PS1,
  • it does not make arbitrary interpenetrating geometry correct,
  • it does not turn every imported model into a PS1-safe layout,
  • it does not make transparency order-independent,
  • it does not remove the need for content budgets.

The design goal is narrower and more useful: provide a visual editor while keeping final geometry inside a PS1-shaped envelope.

A Better Mental Model

Think of PS1 rendering as a contract between the editor, build pipeline, and runtime:

Editor:
make risky geometry visible and editable

Build:
bake, chunk, validate, and stage runtime data

Runtime:
transform, clip, sort, and draw with predictable limits

User:
keep content modular, simple, and target-aware

That is the approach behind Polygon Engine. The PS1 is not a platform where the renderer can clean up every content mistake at the end. The tool has to guide the author before the runtime gets involved.

Continue Reading