Skip to content

feat: terrain rendering#91

Draft
ViTeXFTW wants to merge 50 commits intodevfrom
feat/terrain-rendering
Draft

feat: terrain rendering#91
ViTeXFTW wants to merge 50 commits intodevfrom
feat/terrain-rendering

Conversation

@ViTeXFTW
Copy link
Owner

Description

In an effort to support terrain rendering this PR will serve as the implementation for review along the way

Type of change

  • Bugfix
  • Feature
  • Formatting
  • Refactoring
  • Build
  • CI
  • Documentation
  • Tests
  • Other

greptile-apps[bot]

This comment was marked as outdated.

@ViTeXFTW ViTeXFTW changed the title Feat/terrain rendering feat: terrain rendering Feb 20, 2026
@ViTeXFTW ViTeXFTW force-pushed the feat/terrain-rendering branch from c4cbeba to 9011009 Compare February 20, 2026 15:16
greptile-apps[bot]

This comment was marked as outdated.

@ViTeXFTW ViTeXFTW force-pushed the feat/terrain-rendering branch 2 times, most recently from 3900a20 to 6e676bd Compare February 21, 2026 07:52
@ViTeXFTW ViTeXFTW force-pushed the feat/terrain-rendering branch from 6e676bd to 1a55851 Compare February 21, 2026 08:00
@ViTeXFTW ViTeXFTW marked this pull request as draft February 21, 2026 08:02
Repository owner deleted a comment from greptile-apps bot Feb 21, 2026
Repository owner deleted a comment from greptile-apps bot Feb 21, 2026
@ViTeXFTW
Copy link
Owner Author

@greptileai

@greptile-apps

This comment was marked as outdated.

greptile-apps[bot]

This comment was marked as outdated.

@greptile-apps

This comment was marked as outdated.

@ViTeXFTW ViTeXFTW force-pushed the feat/terrain-rendering branch from f8d986f to 31e0eb6 Compare February 21, 2026 12:54
@ViTeXFTW
Copy link
Owner Author

ViTeXFTW commented Feb 21, 2026

@greptileai

@greptile-apps

This comment was marked as outdated.

Copy link

@greptile-apps greptile-apps bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

25 files reviewed, 3 comments

Edit Code Review Agent Settings | Greptile

github-actions bot and others added 13 commits February 23, 2026 09:43
…peline, renderable)

Adds the full water surface rendering pipeline for map-based PolygonTrigger
water areas:

- src/render/water/water_mesh.hpp/.cpp: Polygon-to-GPU-mesh conversion using
  ear-clipping triangulation. Converts PolygonTrigger points (map cell coords)
  to world-space flat water surfaces. Generates UV coordinates for texture
  scrolling.

- src/render/water/water_renderable.hpp/.cpp: IRenderable implementation for
  water surfaces. Manages GPU buffers for all water polygons from a map file.
  Supports INI-driven water appearance (WaterSettings), per-frame time-based
  UV animation, and alpha-transparent rendering after terrain.

- shaders/water.vert/.frag: Two-layer scrolling UV water shader. Vertex shader
  outputs two UV sets at different scroll rates/directions for a cross-ripple
  effect. Fragment shader blends both samples and applies configurable opacity.

- src/lib/gfx/pipeline.hpp: Added WaterPushConstant (waterColor, time,
  uScrollRate, vScrollRate, uvScale) and PipelineCreateInfo::water() factory
  (alpha blend on, depth write off, two-sided, WaterVertex format).

- tests/water/test_water_mesh.cpp: 31 unit tests covering coordinate
  conversion, ear-clip triangulation (convex/concave, CW/CCW), polygon
  generation, bounding box correctness, and terrain-scale consistency.

https://claude.ai/code/session_015VJkdyPaCy7vByfWHZ17Zz
Adds SceneNode/Quadtree/SceneGraph spatial indexing infrastructure and
ObjectNode/ObjectResolver/ObjectPlacementUtils for placing W3D models
at map object positions with correct coordinate-system conversion.

- SceneNode: base class with position/rotationY/scale transforms, local
  and world bounding boxes, visibility flag, and worldTransform() matrix
- Quadtree: 2D spatial index in X/Z plane with frustum and rect queries;
  center-based single-child insertion avoids duplicate query results;
  subdivide() accesses nodes by index (not reference) to avoid UB from
  vector reallocation during push_back
- SceneGraph: owns SceneNodes, maintains Quadtree, provides queryVisible()
  for frustum-culled queries and queryAll() for full iteration
- ObjectNode: SceneNode subclass wrapping HLodModel* with templated draw()
  composing worldTransform with per-bone transforms; fromMapObject() factory
- ObjectPlacementUtils: Vulkan-free static utilities (templateNameToW3DName,
  mapPositionToVulkan Z-up->Y-up, isRoadPoint, isBridgePoint, shouldRender)
- ObjectResolver: caches loaded HLodModels by template name; resolve() looks
  up W3D path via AssetRegistry, extracts from BIG archive, parses and caches
- 47 new tests (scene_tests + object_resolver_tests); 100% pass rate

https://claude.ai/code/session_01JKxTAtdKkNECTCaiVV5Ywz
…-dTd3F

feat: complete phase 3 implementation for terrain atlas and terrain blend
…) [skip ci]

Co-authored-by: Claude <noreply@anthropic.com>
…Render inconsistency

- Fix critical bug in Quadtree::subdivide() where depth was hardcoded to 1
  when re-inserting entries after subdivision, causing incorrect depth
  tracking for multi-level trees. Pass depth through to subdivide() and
  use it when calling insertInto() to preserve correct tree depth.

- Fix MapObject::shouldRender() to exclude road/bridge points, aligning it
  with ObjectPlacementUtils::shouldRender(). Road/bridge points are
  placement markers, not renderable models, so both call sites now agree.

- Add regression test SubdivisionDepthIsTrackedCorrectly to verify that
  multi-level subdivision respects maxDepth limits.

https://claude.ai/code/session_01JKxTAtdKkNECTCaiVV5Ywz
feat: add scene graph with spatial indexing and object placement
6.1 Time-of-day lighting
- Add LightingState class (src/render/lighting_state.hpp/cpp) that wraps
  GlobalLighting, handles time-of-day slot selection (Morning/Afternoon/
  Evening/Night), and produces TerrainPushConstant and object lighting
  vectors for CPU-side consumers.
- Extend UniformBufferObject with lightDirection, ambientColor, diffuseColor
  vec4s so basic.frag reads scene lighting from the UBO instead of hardcoded
  constants.
- Update Renderer::updateUniformBuffer() to populate UBO lighting from
  LightingState when set, falling back to pre-Phase-6 defaults otherwise.
- Update standard() and skinned() descriptor binding 0 stage flags to expose
  UBO to the fragment shader.

6.2 Shadow color
- Decode GlobalLighting::shadowColor (ARGB uint32) in LightingState and
  expose it via TerrainPushConstant::shadowColor (vec4).
- terrain.frag blends diffuse result toward shadow colour to simulate cast
  shadows.

6.3 Cloud shadows
- Add cloud scroll/strength/time parameters to TerrainPushConstant.
- terrain.vert computes fragCloudCoord (world-space xz * scale + time*scroll).
- terrain.frag applies a 2-octave procedural FBM noise cloud shadow overlay
  without requiring an additional texture binding.
- LightingState::setCloudShadow() / disableCloudShadow() / update() manage
  cloud animation accumulation.
- TerrainRenderable::update(dt) forwards delta time to the push constant.

6.4 Minimap generation
- Add MinimapGenerator (src/render/terrain/terrain_minimap.hpp/cpp) with
  generate() (1:1 pixel per heightmap cell) and generateScaled() (bilinear
  downsampling) producing RGBA8 images from HeightMap data.

Tests (TDD)
- tests/render/test_lighting_state.cpp – 23 tests covering defaults,
  setGlobalLighting, time-of-day switching, push constant generation, ARGB
  shadow decoding, object lighting, and cloud animation.
- tests/terrain/test_terrain_minimap.cpp – 14 tests covering empty/invalid
  inputs, pixel count, gradient variation, bilinear scaling, edge clamping.
- Fix pre-existing test regression: update TestsObjectFlagHelpers to match
  MapObject::shouldRender() behavior introduced in f20af65 (road/bridge
  points are placement markers and correctly return false from shouldRender).
- Add GLFW_INCLUDE_NONE compile definition to suppress GL/gl.h inclusion in
  headless CI environments.

All 24 test targets pass (100%).

https://claude.ai/code/session_01St1oa77j4XRUuovTYQbAFn
…CmWz

feat: add lighting to rendering state and minmap generation from heightmap
@ViTeXFTW
Copy link
Owner Author

@greptileai

@greptile-apps

This comment was marked as outdated.

@ViTeXFTW
Copy link
Owner Author

ViTeXFTW commented Mar 1, 2026

@greptileai

Comment on lines +146 to +149
case BLEND_LONG_DIAG: return clamp((u + v) * 0.75, 0.0, 1.0);
case BLEND_LONG_DIAG_INV: return clamp(1.0 - (u + v) * 0.75, 0.0, 1.0);
case BLEND_LONG_DIAG_ALT: return clamp(((1.0 - u) + v) * 0.75, 0.0, 1.0);
case BLEND_LONG_DIAG_ALT_INV: return clamp(1.0 - ((1.0 - u) + v) * 0.75, 0.0, 1.0);
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

long diagonal blend formulas don't match CPU code in terrain_blend.cpp lines 44-54. Shader uses (u + v) * 0.75 and ((1.0 - u) + v) * 0.75, but CPU uses (2.0 * u + v) / 3.0 and (u + 2.0 * v) / 3.0. Will cause incorrect terrain blending.

Suggested change
case BLEND_LONG_DIAG: return clamp((u + v) * 0.75, 0.0, 1.0);
case BLEND_LONG_DIAG_INV: return clamp(1.0 - (u + v) * 0.75, 0.0, 1.0);
case BLEND_LONG_DIAG_ALT: return clamp(((1.0 - u) + v) * 0.75, 0.0, 1.0);
case BLEND_LONG_DIAG_ALT_INV: return clamp(1.0 - ((1.0 - u) + v) * 0.75, 0.0, 1.0);
case BLEND_LONG_DIAG: return clamp((2.0 * u + v) / 3.0, 0.0, 1.0);
case BLEND_LONG_DIAG_INV: return clamp(1.0 - (2.0 * u + v) / 3.0, 0.0, 1.0);
case BLEND_LONG_DIAG_ALT: return clamp((u + 2.0 * v) / 3.0, 0.0, 1.0);
case BLEND_LONG_DIAG_ALT_INV: return clamp(1.0 - (u + 2.0 * v) / 3.0, 0.0, 1.0);

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants