Table of Contents
Rendering Notes
This document describes the current Stargate rendering implementation. The renderer is functional and visually close to the intended direction, but it is still a procedural prototype rather than a final model/rendering architecture.
Renderer Registration
LanteaCraftClient.registerRenderers registers:
ModBlockEntities.STARGATE_BASE -> StargateBaseRenderer
Only the base block has a block entity. The full rendered Stargate ring is therefore anchored to the base block entity, not to each individual frame block.
StargateBaseRenderer Responsibilities
StargateBaseRenderer currently owns all assembled-gate visual rendering:
- procedural ring shell geometry
- glyph ring overlay
- chevron geometry
- chevron lock lighting
- ring rotation during dialing
- active chevron state while connected
- bottom-row camouflage blocks
- event horizon disc
- kawoosh burst
- expanded render bounds/culling behavior
The normal stargate_base, stargate_ring, and stargate_chevron block models still exist, but the assembled gate's main visual identity is the BER.
Coordinate System
The renderer exits early unless the base block has assembled=true.
For assembled gates it:
- translates to the base block center and raises the origin to the ring center:
translate(0.5, 3.5, 0.5)
- rotates around Y by the negative base facing yaw
- draws the procedural ring in local XY with depth on local Z
Important dimensions:
- ring segments:
38 - chevrons:
9 - inner radius:
2.75 - moving/glyph inner radius:
2.90 - outer radius:
3.5 - ring depth:
0.15 - horizon radius: just inside the moving inner radius
Textures And RenderTypes
Frame/ring/chevrons:
textures/tileentity/stargate.png RenderType.entitySolid
Glyph ring:
textures/tileentity/stargate_glyphs.png RenderType.entityCutout
Event horizon/kawoosh:
textures/fx/eventhorizon.png RenderType.entityTranslucent
The frame texture is treated as a 16×16 tile atlas inside a 1024×1024 image. Tile constants select areas for outer ring, face, inner ring, unlit chevrons, and lit chevrons.
Shell Geometry
renderShell builds the ring from 38 radial segments.
For each segment it emits quads for:
- outer cylindrical wall
- inner cylindrical wall
- center face band
- moving/glyph ring band
- front bevels
- rear bevels
Lighting is forced to LightTexture.FULL_BRIGHT for the Stargate mesh, so the ring remains readable independent of world lighting.
Prototype Quality
- Normals are currently simplified as
(0,0,1)for all vertices. - Geometry is hand-authored in code and not backed by baked models.
- Ring dimensions are tuned visually, not derived from the legacy model source as a formal port.
Glyph Ring And Dialing Rotation
renderGlyphRing draws a textured annular band over the moving ring area.
During dialing:
dialingStatereadsStargateBaseBlockEntity.dialingAddress- each address symbol maps to an angle using the legacy 38-glyph alphabet
- ring rotation lerps to the target symbol angle
- easing is cosine-based
When connected and not dialing:
- the ring rests on the final connected symbol angle
- chevrons corresponding to the connected address remain lit
Prototype Quality
- The renderer has its own copy of the legacy glyph string instead of sharing
StargateAddress.LEGACY_GLYPHS. - The glyph ring is texture-coordinate based, not individual symbol meshes.
- Current behavior supports up to 9 chevron lock slots visually, but the gameplay address is currently 7 symbols.
Chevron Rendering
renderChevrons places nine chevrons around the ring.
Chevron constants:
- count:
9 - angular spacing:
360 / 9 - lock order:
{ 8, 7, 6, 3, 2, 1, 0, 5, 4 }
Each chevron:
- is rendered as two wedge-like front quads
- moves slightly when locked
- overlays lit quads when
lock > 0 - uses the lit chevron tile from
stargate.png
Implemented
- Chevrons light progressively during dialing.
- Lit chevrons remain active while the gate is connected.
- The destination/incoming gate is also put into a connected visual state by the dialing payload.
Prototype Quality
- Chevron order is hand-tuned and should be checked against legacy/show expectations.
- The final chevron placement/order was recently adjusted and needs another in-game pass.
- Chevron geometry is stylized and procedural, not a model import.
Event Horizon
The event horizon is drawn only when:
- the base BE is connected
- the BE has a level
- the gate is no longer in the dialing phase
renderEventHorizon draws:
- a short kawoosh burst if the gate has just opened
- the steady event horizon disc
The steady puddle:
- is a procedural circular mesh
- uses 10 radial bands and 38 angular segments
- uses translucent event horizon texture
- applies small Z displacement from
horizonRipple - animates UVs through
animatedUandanimatedV
The puddle does not spin as a whole. It ripples by changing per-vertex Z offset and UV sampling over time.
Prototype Quality
- It is a flat-ish translucent mesh with ripple displacement, not a fluid simulation.
- It has no collision/portal surface block.
- It renders from the base BER, so the base BE is the render anchor.
- Alpha/depth sorting may need testing with terrain, water, and other translucent objects.
Kawoosh
The kawoosh is also procedural.
Current behavior:
- lasts
18ticks - starts immediately after dialing duration completes
- expands from the center
- protrudes forward along local Z
- fades out as progress approaches 1
- uses the same event horizon texture/render type
Core methods:
renderKawooshkawooshDisplacementkawooshProfile
The shape is a center-heavy protrusion plus a smaller rim bulge and animated wave.
Prototype Quality
- The kawoosh is visually tuned, not physically or canonically accurate.
- It has no gameplay damage/destruction effect.
- It does not currently mask, clip, or interact with world blocks/entities.
- Timing is tied to BE dialing state, not an explicit server event packet.
Needs Testing
- Whether the kawoosh appears exactly once on fresh connection.
- Whether it incorrectly replays after chunk reload, dimension travel, or client reconnect.
- Visual quality at low FPS and high latency.
Bottom Camouflage Rendering
Bottom-row camouflage is stored on StargateBaseBlockEntity as a single BlockState.
renderBottomCamouflage renders seven copies of that block across local x=-3..3, at the bottom row of the gate.
The renderer uses Minecraft's block renderer:
Minecraft.getInstance().getBlockRenderer().renderSingleBlock(...)
Each rendered camouflage block is slightly scaled up (1.004) to reduce fighting with existing blocks/models.
Prototype Quality
- Only one camouflage state is stored for the whole bottom row.
- The state is reduced to the target block's default state, so orientation/properties are not preserved.
- There is no clearing interaction yet besides code support on the BE.
Culling And Bounds
The renderer overrides:
shouldRenderOffScreen→truegetViewDistance→128shouldRender→ distance check against expanded gate boundsgetRenderBoundingBox→ expanded AABB around the base
The bounds are:
new AABB(basePos).inflate(5, 5, 5).expandTowards(0, 6, 0)
This was added because the gate mesh is much larger than the base block and otherwise disappears when the base block leaves the camera frustum.
Prototype Quality
- The bounds are intentionally generous.
shouldRenderOffScreen=truehelps avoid base-frustum clipping but can increase render cost.- More precise bounds could be computed per facing.
Sound-Driven Visual State
Visual state is primarily derived from StargateBaseBlockEntity:
dialingAddressdialingStartGameTimedialingDurationTicksconnectedAddress
Server-side BE tick plays sounds:
- roll on dialing start
- chevron lock as each symbol progresses
- open after dialing completes
- ambient while connected
- close when connection clears
The renderer does not play sounds. It only visualizes the same BE state.
Known Risks And TODOs
Current Risks
- The renderer uses a copied legacy glyph string instead of the central address constant.
- The full ring depends on one block entity. If the base BE is missing or desynced, the whole visual disappears.
- Full-bright rendering may not match desired lighting once final art direction settles.
- Translucent event horizon sorting needs more testing.
- Geometry normals are placeholder-quality.
- Render cost should be profiled with many gates visible.
TODO Candidates
- Share the glyph alphabet constant with
StargateAddress. - Split rendering helpers into smaller classes once behavior stabilizes.
- Add a proper model/baked-geometry path if procedural maintenance gets painful.
- Add explicit client event/state for kawoosh instead of deriving it from persisted dialing time.
- Add configurable render distance/detail for active gates.
- Add a clear camouflage interaction and preserve more blockstate properties if needed.
- Revisit chevron lock order against legacy implementation.
