Sixth 3D - Realtime 3D engine

Table of Contents

1. Introduction

Example.png

Sixth 3D is a realtime 3D rendering engine written in pure Java. It runs entirely on the CPU — no GPU required, no OpenGL, no Vulkan, no native libraries. Just Java.

The motivation is simple: GPU-based 3D is a minefield of accidental complexity. Drivers are buggy or missing entirely. Features you need aren't supported on your target hardware. You run out of GPU RAM. You wrestle with platform-specific interop layers, shader compilation quirks, and dependency hell. Every GPU API comes with its own ecosystem of pain — version mismatches, incomplete implementations, vendor-specific workarounds. I want a library that "just works".

Sixth 3D takes a different path. By rendering everything in software on the CPU, the entire GPU problem space simply disappears. You add a Maven dependency, write some Java, and you have a 3D scene. It runs wherever Java runs.

This approach is quite practical for many use-cases. Modern systems ship with many CPU cores, and those with unified memory architectures offer high bandwidth between CPU and RAM. Software rendering that once seemed wasteful is now a reasonable choice where you need good-enough performance without the overhead of a full GPU pipeline. Java's JIT compiler helps too, optimizing hot rendering paths at runtime.

Beyond convenience, CPU rendering gives you complete control. You own every pixel. You can freely experiment with custom rendering algorithms, optimization strategies, and visual effects without being constrained by what a GPU API exposes. Instead of brute-forcing everything through a fixed GPU pipeline, you can implement clever, application-specific optimizations.

Sixth 3D is part of the larger Sixth project, with the long-term goal of providing a platform for 3D user interfaces and interactive data visualization. It can also be used as a standalone 3D engine in any Java project. See the demos for examples of what it can do today.

2. Understanding 3D engine

2.1. Main render loop

2.2. Coordinate System (X, Y, Z)

X right (+) / left (-) Y down (+) / up (-) Z away (+) / towards (-) Origin (0, 0, 0)

Sixth 3D uses a left-handed coordinate system with X pointing right and Y pointing down, matching standard 2D screen coordinates. This coordinate system should feel intuitive for people with preexisting 2D graphics background.

Axis Direction Meaning
X Horizontal, positive = RIGHT Objects with larger X appear to the right
Y Vertical, positive = DOWN Lower Y = higher visually (up)
Z Depth, positive = away from viewer Negative Z = closer to camera

Practical Examples

  • A point at (0, 0, 0) is at the origin.
  • A point at (100, 50, 200) is: 100 units right, 50 units down visually, 200 units away from the camera.
  • To place object A "above" object B, give A a smaller Y value than B.

The sixth-3d-demos project includes an interactive coordinate system reference showing X, Y, Z axes as colored arrows with a grid plane for spatial context.

2.3. Vertex

V (x, y, z) x y

A vertex is a single point in 3D space, defined by three coordinates: x, y, and z. Every 3D object is ultimately built from vertices. A vertex can also carry additional data beyond position.

  • Position: (x, y, z)
  • Can also store: color, texture UV, normal vector
  • A triangle = 3 vertices, a cube = 8 vertices
  • Vertex maps to Point3D class in Sixth 3D engine.

2.4. Edge

V₁ V₂ V₃ edge

An edge is a straight line segment connecting two vertices. Edges define the wireframe skeleton of a 3D model. In rendering, edges themselves are rarely drawn — they exist implicitly as boundaries of faces.

  • Edge = line from V₁ to V₂
  • A triangle has 3 edges
  • A cube has 12 edges
  • Wireframe mode renders edges visibly
  • Edge is related to and can be represented by the Line class in Sixth 3D engine.

2.5. Face (Triangle)

V₁ V₂ V₃ FACE

A face is a flat surface enclosed by edges. In most 3D engines, the fundamental face is a triangle — defined by exactly 3 vertices. Triangles are preferred because they are always planar (flat) and trivially simple to rasterize.

  • Triangle = 3 vertices + 3 edges
  • Always guaranteed to be coplanar
  • Quads (4 vertices) = 2 triangles
  • Complex shapes = many triangles (a "mesh")
  • Face maps to SolidTriangle, SolidPolygon, or TexturedTriangle in Sixth 3D.

2.6. Normal Vector

unit normal (perpendicular to surface) Light L · N = brightness

A normal is a vector perpendicular to a surface. It tells the renderer which direction a face is pointing. Normals are critical for lighting — the angle between the light direction and the normal determines how bright a surface appears.

  • Face normal: one normal per triangle
  • Vertex normal: one normal per vertex (averaged from adjacent faces for smooth shading)
  • dot(L, N) → surface brightness
  • Flat shading → face normals
  • Gouraud/Phong → vertex normals + interpolation

2.7. Mesh

triangulated section

A mesh is a collection of vertices, edges, and faces that together define the shape of a 3D object. Even curved surfaces like spheres are approximated by many small triangles — more triangles means a smoother appearance.

  • Mesh data = vertex array + index array
  • Index array avoids duplicating shared vertices
  • Cube: 8 vertices, 12 triangles
  • Smooth sphere: hundreds–thousands of triangles
  • vertices[] + indices[] → efficient storage
  • In Sixth 3D engine:
    • AbstractCoordinateShape: base class for single shapes with vertices (triangles, lines). Use when creating one primitive.
    • AbstractCompositeShape: groups multiple shapes into one object. Use for complex models that move/rotate together.

See the Shape Gallery demo for a visual showcase of all primitive shapes available in Sixth 3D, rendered in both wireframe and solid polygon styles with dynamic lighting.

2.8. Perspective correct textures

Affine distortion.png

Sixth 3D tries to do perspective-correct texture rendering. Read more about perspective-correct texture implementation.

2.9. Frustum & View Frustum Culling

Sixth 3D implements view frustum culling.

+Z (view direction) Camera Near Far visible region Top plane Bottom plane rendered culled culled

To understand frustum culling and object-level visibility optimization, read more about frustum & view frustum culling.

2.10. Constructive Solid Geometry

Sixth 3D allows performing boolean operations against geometry shapes. So one can subtract, unionize or intersect shapes.

Input A B subtract Result: A − B cavity B is the "cutter" carves out of A Cube with cavity interior faces visible

To understand CSG boolean operations, read more about Constructive Solid Geometry.

2.11. Winding Order & Backface Culling

CCW V₁ V₂ V₃ FRONT FACE ✓ CW BACK FACE ✗ (culled — not drawn)

The order in which a triangle's vertices are listed determines its winding order. In Sixth 3D, screen coordinates have Y-axis pointing down, which inverts the apparent winding direction compared to standard mathematical convention (Y-up). Counter-clockwise (CCW) in screen space means front-facing. Backface culling skips rendering triangles that face away from the camera — a major performance optimization.

  • CCW winding (in screen space) → front face (visible)
  • CW winding (in screen space) → back face (culled)
  • When viewing a polygon from outside: define vertices in counter-clockwise order as seen from the camera
  • Saves ~50% of triangle rendering
  • Implementation uses signed area: signedArea < 0 means front-facing (in Y-down screen coordinates, negative signed area corresponds to visually CCW winding)

In Sixth 3D, backface culling is optional and disabled by default. Enable it per-shape:

See the Winding Order demo for an interactive visualization.

2.12. Working with Colors

Sixth 3D uses its own Color class (not java.awt.Color):

import eu.svjatoslav.sixth.e3d.renderer.raster.Color;

// Using predefined colors
Color red = Color.RED;
Color green = Color.GREEN;
Color blue = Color.BLUE;

// Create custom color (R, G, B, A)
Color custom = new Color(255, 128, 64, 200); // semi-transparent orange

// Or use hex string
Color hex = new Color("FF8040CC"); // same orange with alpha

3. Developer tools

Developer tools.png

Press F12 anywhere in the application to open the Developer Tools panel. This debugging interface helps you understand what the engine is doing internally and diagnose rendering issues.

The Developer Tools panel provides real-time insight into the rendering pipeline with three diagnostic toggles, camera position display, frustum culling statistics, and a live log viewer that's always recording.

3.1. Render frame logging (always on)

Render frame diagnostics are always logged to a circular buffer. When you open the Developer Tools panel, you can see the complete rendering history.

Log entries include:

  • Abort conditions (bufferStrategy or renderingContext not available)
  • Blit exceptions
  • Buffer contents lost (triggers reinitialization)
  • Render frame exceptions

Use this for:

  • Diagnosing buffer strategy issues (screen tearing, blank frames)
  • Debugging rendering failures

3.2. Show polygon borders

Draws yellow outlines around all textured polygons to visualize:

  • Triangle tessellation patterns
  • Perspective-correct texture slicing
  • Polygon coverage and overlap

This is particularly useful when debugging:

  • Texture mapping issues
  • Perspective distortion problems
  • Mesh density and triangulation quality
  • Z-fighting between overlapping polygons

The yellow borders are rendered on top of the final image, making it easy to see the underlying geometric structure of textured surfaces.

3.3. Render alternate segments (overdraw debug)

Renders only even-numbered horizontal segments (0, 2, 4, 6) while leaving odd segments (1, 3, 5, 7) black.

The engine divides the screen into 8 horizontal segments for parallel multi-threaded rendering. This toggle helps detect overdraw (threads writing outside their allocated segment).

If you see rendering artifacts in the black segments, it indicates that threads are writing pixels outside their assigned area — a clear sign of a bug.

3.4. Show segment boundaries

Draws visible lines between horizontal rendering segments to show where the screen is divided for parallel multi-threaded rendering.

The engine divides the screen into 8 horizontal segments for parallel rendering. This toggle draws boundary lines between segments, making it easy to see exactly where each thread's rendered area begins and ends.

Useful for:

  • Verifying correct segment division
  • Debugging segment-related rendering issues
  • Understanding the parallel rendering architecture visually

3.5. Camera position

Displays the current camera coordinates and orientation in real-time:

Parameter Description
x, y, z Camera position in 3D world space
yaw Rotation around the Y axis (left/right)
pitch Rotation around the X axis (up/down)
roll Rotation around the Z axis (tilt)

The Copy button copies the full camera position string to the clipboard in a format ready to paste into bug reports or configuration files.

Use this for:

  • Reporting exact camera positions when filing bugs
  • Saving interesting viewpoints for later reference
  • Understanding camera movement during navigation
  • Sharing specific views with other developers

Example copied format:

500.00, -300.00, -800.00, 0.60, -0.50, -0.00

3.6. Frustum culling statistics

Shows real-time statistics about composite shape frustum culling efficiency:

Statistic Description
Total Number of composite shapes tested against the frustum
Culled Number of composites rejected (outside view frustum)
Culled % Percentage of composites that were culled (0-100%)

What is frustum culling?

Frustum culling is an optimization that skips rendering objects outside the camera's view. Before rendering each composite shape, the engine tests its bounding box against the view frustum. If the bounding box is completely outside the visible area, the entire composite (and all its children) are skipped.

How to interpret the numbers:

  • High cull % (60-90%): Excellent — most objects are being correctly culled
  • Medium cull % (20-60%): Moderate — some optimization benefit
  • Low cull % (0-20%): Limited benefit — either all objects are visible, or scene needs restructuring

Example:

Total: 473  Culled: 425  Culled %: 89.9%

This means 473 composite shapes were tested, 425 were outside the view and skipped entirely, and only 48 composites (with all their children) actually needed to be rendered. This is excellent culling efficiency.

The statistics update every 200ms while the panel is open. Note that the root composite is never frustum-tested (it's always rendered), so the "Total" count excludes it.

3.7. Live log viewer

The scrollable text area shows captured debug output in real-time:

  • Green text on black background for readability
  • Auto-scrolls to show latest entries
  • Updates every 500ms while panel is open
  • Captures logs even when panel is closed (replays when reopened)

Use the Clear Logs button to reset the log buffer for fresh diagnostic captures.

3.8. API access

You can access and control developer tools programmatically:

import eu.svjatoslav.sixth.e3d.gui.ViewPanel;
import eu.svjatoslav.sixth.e3d.gui.DeveloperTools;

ViewPanel viewPanel = ...; // get your view panel
DeveloperTools tools = viewPanel.getDeveloperTools();

// Enable diagnostics programmatically
tools.showPolygonBorders = true;
tools.renderAlternateSegments = false;
tools.showSegmentBoundaries = true;

This allows you to:

  • Enable debugging based on command-line flags
  • Toggle features during automated testing
  • Create custom debug overlays or controls
  • Integrate with external logging frameworks

3.9. Technical details

The Developer Tools panel is implemented as a JFrame that:

  • Centers on the parent ViewPanel window
  • Runs on the Event Dispatch Thread (EDT)
  • Does not block the render loop
  • Automatically closes when parent window closes
  • Updates statistics every 200ms while open

Log entries are stored in a circular buffer (DebugLogBuffer) with configurable capacity (default: 10,000 entries). When full, oldest entries are discarded.

Each ViewPanel has its own independent DeveloperTools instance, so multiple views can have different debug configurations simultaneously.

4. Source code

This program is free software: released under Creative Commons Zero (CC0) license

Program author:

Getting the source code:

4.1. Understanding the Sixth 3D source code

Created: 2026-04-04 Sat 15:41

Validate