Add test/Fixtures.h with an inline openGfxWindow() (same signature as the
16 per-file copies, plus EVENGINE_TEST_VIEW_W/H overrides for CI), a RAII
GfxFixture, and a TempDir helper. Migrate all 16 test files that hand-rolled
openGfxWindow to use the shared helper; windowed GPU tests now override their
view size from env vars instead of editing each file.
* chore(ci): add clang-format gate, CODEOWNERS and agent collaboration rules
* refactor(modules): clear remaining back-edges and split the largest TUs
Three known dependency back-edges are gone (module_depgraph.py KNOWN_BACK_EDGES
is now empty; --check passes with 0 violations, 0 cycles):
- window -> graphics: window queries the new IWindowSurfaceHost capability
(common/WindowSurfaceHost.h) instead of holding a Graphics pointer;
Window::setGraphics was removed and all call sites updated.
- window -> image: Window::setIcon was replaced by setIconRGBA(const uint8_t*,
w, h); the window no longer decodes ImageData.
- scene -> graphics: pickScreenAt / collectFrustumIdsAt implementations moved
to graphics/ScenePicking.cpp (graphics -> scene is a legal downward edge);
scene now depends only on spatial.
TU splits (pure moves, verified identical method sets and brace balance):
- vulkan/Graphics.cpp (5118 lines) -> Graphics.cpp (lifecycle), GraphicsPipeline,
Graphics2D, Graphics3D, GraphicsMesh + shared GraphicsInternal.h.
- scene/Scene.cpp -> Scene.cpp (script layer / host lifecycle / serialization)
+ SceneNodes.cpp + shared SceneInternal.h.
Verified with a real build (MSVC 19.51, prebuilt third-party): full build green;
window.* and Scene.* suites pass, including scene picking/culling and GPU cases.
* refactor(graphics): narrow Graphics interfaces and clear public-header leaks
Step 4 — interface segregation:
- New lean interfaces: IGraphics2D, IGraphics3D, IResourceFactory, IPostFX
(pure virtuals, forward-declared types only; graphics/Color.h extracted from
Canvas.h so modules that only need the color type stop pulling Canvas.h).
- Graphics now implements all four facets; consumers can depend on the narrow
interface they use instead of the 129-method god class.
- Migrated voxel (VoxelWorld::drawVisible -> IGraphics3D*) and model3d
(ModelRenderer::buildRenderable(s) -> IResourceFactory&).
- Graphics.h slims from 24 sub-header includes to a handful of small type
headers + forward declarations; the destructor moved out-of-line so
unique_ptr effect members are destroyed where types are complete.
Step 5 — header leaks (module_depgraph.py '*' marks: 14 -> 7):
- map/TileLayer.h, particles/ParticleEmitter.h, avatar/AvatarInstance.h,
animation/SpineAnim.h, map/TileSystem.h, model3d/ModelData.h,
model3d/ModelRenderer.h, audio/Audio.h + Source.h, image/ImageData.h +
Image.h, dialogue/Dialogue.h, procgen Palette/OutputSpec/TextureRecipe/
PbrMaterial -> forward declarations, includes moved to .cpp.
- voxel/VoxelWorld.h: terrain sampler Pimpl'd (unique_ptr + out-of-line
destructor), removing the procgen header dependency.
- gpgpu/vulkan backend headers stop pulling graphics/vulkan/Graphics.h.
- Remaining '*' marks are deliberate: tiny POD/enum headers (GridConfig,
MapObject, BlendMode, Color), an internal backend header
(GraphicsInternal.h -> filesystem), and lean interface references.
Verified with a full clean build (MSVC) and tests: window/Scene/voxel/
RenderSystem/Quad/shader/TextureSampler/resourceLifetime pass; broad suite
only shows the pre-existing PHYSFS-init filesystem-environment failures.
* feat(resources): revive ResourceManager as unified IAssetReloader-backed cache
* fix(resources): leak ResourceManager singleton to avoid exit-time teardown crashes
Cached CPU resources may own third-party handles (FreeType faces, Assimp
scenes, image decode handlers) whose libraries are torn down at process
exit in an unspecified TU order; destroying cached entries from the
singleton destructor can segfault at exit (seen on CI Windows in
model3d.materialApi.objMtl). Keep the singleton alive until OS reclaim;
explicit unload()/clear() still release entries during the run.
* refactor(devtools): consume business modules through capability interfaces
DevTools / cmdline no longer include business-module headers, so trimming
scene / physics / procgen / particles / audio / ui / graphics no longer
requires disabling devtools, and devtools can be switched off with
-DEVENGINE_MODULE_DEVTOOLS=OFF.
New capability interfaces in common/:
- ISceneQuery (scene) - host/node inspection + mutation + transform sync
- IRenderCapture (graphics) - render status, PNG capture, camera control,
visible-entity snapshot, entity-ID mask, G-buffer PNGs
- IPhysicsQuery (physics) - 2D world lifecycle + ray casts
- IProcgenQuery (procgen) - recipe listing, map/mesh generation
- IParticlesQuery (particles) - emitter status + one-shot emit
- IAudioQuery (audio) - volume / stop-all
- IEditorHost (ui) - declarative editor host (used by cmdline too)
Providers register in their module constructors. DevTools rewires McpServer
(render/scene/procgen/physics/particles/audio/host tools), SceneInspect
(now delegates to ISceneQuery + IRenderCapture) and RenderVision (uses
IRenderCapture::capturePngDataUrl); cmdline/Mcp.cpp uses IEditorHost.
manifest: devtools DEPS graphics scene physics procgen particles audio ui
image event filesystem -> event; cmdline DEPS filesystem ui -> filesystem.
Verified: full build green; devtools.mcp.* tests pass; broad suite shows
only the pre-existing PHYSFS-init filesystem-environment failures.
* style: apply clang-format to changed lines after dev merge
* fix(webgpu): include RenderControl/TextureSampler explicitly after Graphics.h slimming
* fix(webgpu): provide newFont/print stubs to satisfy IGraphics2D/IResourceFactory vtables
* fix(common): make ProcgenQuery.h self-sufficient (cstdint/utility for GCC)
Re-add test/hair.cpp and test/runtime.cpp (fixing the missing zeroerr include and enum comparisons), add graphics.resourceLifetime tests for the new release APIs, a test-source manifest check, module declared-layer check with unit tests, and a raw-string-literal regression test.
Adds EVENGINE_ANDROID_TEST_APP build mode: the unit_test sources are
compiled into libmain.so (SDL entry) and packaged by the existing Gradle
APK along with the test assets, so the full zeroerr suite can run on a
device via adb logcat.
- test/main.cpp: Android runner with LogcatBuf (cout/cerr -> logcat),
chdir to <files>/evengine_test, SDL_Init; keeps SDL_main symbol unmangled.
- test/PathBesideSource.h: shared pathBesideThisSource helper that maps
__FILE__ to the on-device unpacked tree on Android.
- EVTestActivity: unpacks assets/test + assets/examples to internal
storage and passes an optional --testcase filter from an intent extra.
- test/CMakeLists.txt: builds `main` instead of unit_test on Android,
excludes desktop-only devtools tests, links Android system libs.
- Makefile: build/android-debug-test, sync/android-test-assets,
run/android-test-debug, log/android-test targets.
- Gradle wrapper bumped to 8.5 for Java 21 compatibility.
- Updated shadow configuration to allow for automatic NDC bias calculation based on cascade texel size, enhancing shadow accuracy.
- Refactored shadow sampling functions to incorporate cascade-specific bias and texel calculations, improving visual quality and reducing artifacts.
- Adjusted shader code to implement new bias handling logic, ensuring compatibility with the updated shadow mapping approach.
- Enhanced test cases to validate the new shadow functionality and its integration with existing graphics features.
- Introduced a new toon shader for enhanced visual effects in 3D rendering.
- Updated vertex shaders across multiple files to use the inverse-transpose of the model matrix for normal calculations, ensuring correct normal transformations for non-uniform scaling.
- Added the mesh3d_toon.vert shader to the shader compilation script.
- Updated SPIR-V binaries for affected shaders to reflect the changes in normal matrix calculations.
- Enhanced test cases to validate the new toon shader functionality and its integration with existing graphics features.
- Added functionality to enable hardware MSAA (2x, 4x, 8x) for the 3D scene color pass, enhancing edge quality for 3D models and voxels.
- Introduced `setMsaaSamples` and `getMsaaSamples` methods in the Graphics API to control MSAA sample count.
- Updated RenderControl to include MSAA as a feature, with default settings for enabling/disabling.
- Modified the rendering pipeline to accommodate MSAA, including adjustments to render passes and framebuffers.
- Enhanced documentation and tests to cover new MSAA functionality and ensure stability across various scenarios.
* test(graphics): enable mipmaps and anisotropy in classic scene loads
ClassicScenes Assimp albedo, RenderImageAudit studio checkers/rock maps,
and RenderSystem3D motif/checker textures now use TextureCreateInfo::withMipmaps
so flythroughs exercise trilinear + anisotropic filtering while engine defaults stay off.
Co-authored-by: 西风逍遥游 <sunxfancy@gmail.com>
* fix(test): avoid REQUIRE on MipmapMode enum in ClassicScenes
zeroerr tries to stream enum values in assertion diagnostics and has no
operator<< for MipmapMode, which broke Linux/macOS/Windows CI builds.
Compare via static_cast<int> like TextureSampler.cpp.
Co-authored-by: 西风逍遥游 <sunxfancy@gmail.com>
* fix(test): use .get() in unique_ptr REQUIRE checks
zeroerr assertion diagnostics copy compared values; REQUIRE(unique_ptr)
fails to compile because unique_ptr is non-copyable.
Co-authored-by: 西风逍遥游 <sunxfancy@gmail.com>
---------
Co-authored-by: Cursor Agent <cursoragent@cursor.com>
- Added a new 3D rendering pipeline section in the documentation, detailing initialization, VKBuilder, and asynchronous frame handling.
- Updated the Ambient Occlusion module to support depth-based sampling, allowing for improved visual fidelity in 3D scenes.
- Introduced new shader functionalities for ambient occlusion and global illumination, enhancing the overall rendering quality.
- Updated GBuffer to include hardware depth texture for more accurate depth sampling in 3D rendering.
- Enhanced the RenderControl to manage new features for ambient occlusion and global illumination, ensuring they are enabled by default.
Co-authored-by: 西风逍遥游 <sunxfancy@gmail.com>
Shadow ortho now uses the same Vulkan Y-flip as the camera, with nearest depth sampling so manual PCF does not invent false umbra. Tonemap only compresses HDR peaks, and scene sun intensity is no longer overwritten per config.
Co-authored-by: Cursor <cursoragent@cursor.com>
Cascade selection used euclidean eye distance while splits are view-space
+Z, so a wide atrium sampled the wrong shadow map (half-frame black cut).
Fit CSM to a 64m shadow far, snap ortho bounds to texels, and scale depth
bias with world texel size.
Forward packing sorted point lights first and always shaded lights[0] as
a directional, so MultiPoint/IBL treated a world position as L and blew
out. Promote a real directional to the primary slot and zero that term
when only points exist.
Also: view-space position in mesh3d, two-sided mesh pipeline, mirrored
Assimp winding, alpha cutout, stable TBN, hemispheric ambient, and SDR
highlight compression. Sponza camera far/point intensities are last-mile
only after the engine fixes.
Co-authored-by: 西风逍遥游 <sunxfancy@gmail.com>
Record shadow and G-buffer into the in-flight swapchain command buffer, add Graphics::setVSync for IMMEDIATE present, and measure ClassicScenes FPS with image-audit snapshots.
Co-authored-by: Cursor <cursoragent@cursor.com>
Flip GLM RH_ZO projection Y for Vulkan NDC so world +Y is screen-up
(models were rendered upside-down). Switch 3D mesh pipelines to Clockwise
front faces to match the flipped winding, and align AO/volumetric NDC
reconstruction plus screenToRay.
Remove the leftover shader ambient floor so Camera3D ambient is honored.
Bake Assimp node transforms in Graphics::newMeshFromAssimp(world) and use
it from ClassicScenes/model3d. Add RenderScenes regression coverage for
orientation, ambient, shadows, gbuffer, and node baking without effect
cross-talk.
Co-authored-by: 西风逍遥游 <sunxfancy@gmail.com>
* feat(tests): classic scene flythroughs with render config switching
Add Cornell Box (committed), procedural metal/roughness chart, and
downloadable Sponza/DamagedHelmet tests that fly the camera while
cycling ambient, directional, shadows, point lights, and IBL.
Co-authored-by: 西风逍遥游 <sunxfancy@gmail.com>
* fix(tests): bake Assimp node transforms and light classic scenes
Apply scene-graph world matrices when spawning meshes, fix Cornell face
winding for inward normals, keep Sponza dielectric under missing MR
texture sampling, and link sndio when OpenAL builds that backend.
Co-authored-by: 西风逍遥游 <sunxfancy@gmail.com>
* docs(tests): note ClassicScenes coverage
Co-authored-by: 西风逍遥游 <sunxfancy@gmail.com>
---------
Co-authored-by: Cursor Agent <cursoragent@cursor.com>