====== 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 16x16 tile atlas inside a 1024x1024 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: * ''dialingState'' reads ''StargateBaseBlockEntity.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 ''animatedU'' and ''animatedV'' 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 ''18'' ticks * 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: * ''renderKawoosh'' * ''kawooshDisplacement'' * ''kawooshProfile'' 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'' -> ''true'' * ''getViewDistance'' -> ''128'' * ''shouldRender'' -> distance check against expanded gate bounds * ''getRenderBoundingBox'' -> 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=true'' helps 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'': * ''dialingAddress'' * ''dialingStartGameTime'' * ''dialingDurationTicks'' * ''connectedAddress'' 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.