Merry Christmas!
Over the last couple weeks, I took it slow as it was Christmas, but did make some art in my engine to celebrate!
After Cameras, Another Problem Became Obvious
After the holidays, I looked at the current state of things. After cameras became real scene entities, one thing still stood out.
Lighting was still global.
It worked. It was adjustable. But it wasn’t authored.
That meant lighting changes leaked between scenes, couldn’t be reasoned about in isolation, and didn’t actually belong to the data model yet.
If cameras needed to live in the SceneGraph to be real, lighting needed to follow the same rule.
Lighting Becomes Scene Data
RetroEngine now treats lighting as part of the scene itself.
Each scene owns its own lighting state, serialized directly into
the .scene.json file alongside entities.
- directional light direction, color, and intensity
- ambient light color and intensity
- automatic fallback for older scenes without lighting data
When a scene is loaded, its lighting is restored exactly. When a scene has no lighting block, the engine falls back to sensible defaults.
No global state leaks. No surprises.
Lighting That Fits the Engine’s Goals
RetroEngine isn’t chasing modern physically based lighting.
That would be dishonest to the aesthetic and unnecessary for the kinds of scenes this engine is meant to build.
The lighting model is intentionally simple:
- a single directional light per scene
- a single ambient contribution
This mirrors how many 90s-era games were authored, even if the underlying hardware details varied.
The result is predictable, controllable lighting that works across low-poly meshes, sprites, and CRT output without fighting the style.
Lit vs Unlit Is Now Intentional
Another important distinction landed alongside scene lighting.
By default:
- 3D meshes use lit materials and respond to scene lighting
- 2D sprites default to unlit and ignore lighting entirely
That matches how these elements are usually meant to behave. Backgrounds and parallax layers stay stable. Foreground geometry gains depth and form.
For edge cases, materials can explicitly opt out of lighting. Nothing is forced, but the defaults are sane.
Sprite Features Move Into the Core Pipeline
This update also marks the end of RetroEngine’s separate 2D test renderer.
That pipeline existed for a reason. Early on, the 3D renderer couldn’t yet express everything sprites needed:
- UV offset and scrolling
- parallax relative to camera movement
- camera lock behavior
- independent scale control
Rather than forcing those concepts into an incomplete system, a small isolated 2D path made experimentation safer.
That phase is now over.
All sprite behavior is fully supported by the same unified render path used for meshes.
Sprites are no longer special cases. They are just entities.
One Renderer, One Set of Rules
With sprite features folded into the main renderer:
- the legacy 2D test pipeline has been removed
- there is only one render path to reason about
- materials, transforms, and camera behavior are consistent
- serialization applies uniformly across 2D and 3D
Removing code is always better than keeping temporary systems alive.
From this point forward, everything that draws is part of the engine proper.
Fixing the Hard Problems: Entity Lifetime
Unifying pipelines exposed a deeper issue that couldn’t be ignored anymore.
Entity duplication and deletion were fragile. In some cases, entities could end up sharing IDs. In others, deleting an entity could crash the renderer outright.
These weren’t cosmetic bugs. They were ownership problems.
The fix wasn’t a patch. It required making entity identity and GPU ownership explicit.
- entity IDs are now guaranteed unique
- duplication always produces a new identity
- GPU resources are released before entities are destroyed
- editor deletions are deferred safely outside iteration
Deleting an entity no longer risks invalid memory or stale GPU state.
The editor can finally be trusted not to hurt the engine.
Editor Quality-of-Life Improvements
Alongside the structural fixes, several editor pain points were cleaned up.
- the currently loaded scene name is now prominently displayed
- unsaved changes are clearly indicated
- saving correctly clears dirty state
- loading scenes no longer carries over stale lighting
None of these are flashy.
But when tools lie to you, you stop trusting them.
The editor now reflects the real state of the scene accurately.
Where RetroEngine Stands Now
- scene-authored cameras
- editor-only navigation camera
- scene-level lighting with serialization
- clear lit vs unlit material defaults
- unified sprite and mesh rendering pipeline
- safe duplication and deletion of entities
None of this is glamorous.
But it removes entire classes of future problems.
RetroEngine now feels less like a renderer with tools, and more like a place where a real game could live.