From 82307269e89f61da5eb1fd582b431c28c5137ad0 Mon Sep 17 00:00:00 2001 From: Samuel Bouchet Date: Sun, 29 Mar 2026 15:11:42 +0200 Subject: [PATCH] Phase 7.1 tuning: reduce saturation, increase contrast, multi-angle screenshots MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Saturation 1.40→1.15, exposure 2.2→1.8 (less oversaturated) - Shadow factor 0.55→0.45 (more contrast between lit and shadow) - Ambient reduced slightly for better contrast - Screenshot mode: 4 camera views (landscape, sideview, topdown, backlit) - AO history reset between view changes (prevents temporal contamination) --- shaders/voxelShadowCS.hlsl | 4 +-- src/app/main.cpp | 49 ++++++++++++++++++++++++++++--------- src/voxel/VoxelRenderer.cpp | 23 ++++++++++++----- src/voxel/VoxelRenderer.h | 2 ++ 4 files changed, 59 insertions(+), 19 deletions(-) diff --git a/shaders/voxelShadowCS.hlsl b/shaders/voxelShadowCS.hlsl index 15748eb..bb1f269 100644 --- a/shaders/voxelShadowCS.hlsl +++ b/shaders/voxelShadowCS.hlsl @@ -107,7 +107,7 @@ void main(uint3 DTid : SV_DispatchThreadID) { float shadowFactor = 1.0; if (NdotL <= 0.0) { - shadowFactor = 0.55; // back-facing = fully in shadow + shadowFactor = 0.45; // back-facing = fully in shadow } else { RayDesc ray; ray.Origin = origin; @@ -120,7 +120,7 @@ void main(uint3 DTid : SV_DispatchThreadID) { [loop] while (q.Proceed()) {} if (q.CommittedStatus() == COMMITTED_TRIANGLE_HIT) { - shadowFactor = 0.55; + shadowFactor = 0.45; } } diff --git a/src/app/main.cpp b/src/app/main.cpp index 92e9045..53ae25b 100644 --- a/src/app/main.cpp +++ b/src/app/main.cpp @@ -195,20 +195,47 @@ int APIENTRY wWinMain( else { application.Run(); - // Screenshot mode: wait for rendering + AO convergence, then capture and quit + // Screenshot mode: cycle through multiple camera views if (renderPath.screenshotMode) { - screenshotFrameCounter++; - // Only start counting convergence frames once we have actual rendered quads - bool hasRendered = renderPath.renderer.getGpuMeshQuadCount() > 0; + struct CamView { float x, y, z, pitch, yaw; const char* name; }; + static const CamView views[] = { + { 270.f, 48.f, 240.f, -0.30f, 0.6f, "landscape" }, // wide terrain, slight down + { 272.f, 44.f, 248.f, -0.20f, 1.0f, "sideview" }, // side angle, ground level + { 268.f, 55.f, 242.f, -0.70f, 0.5f, "topdown" }, // steep top-down + { 275.f, 46.f, 235.f, -0.15f, 2.8f, "backlit" }, // looking toward sun + }; + static const int numViews = sizeof(views) / sizeof(views[0]); + static int currentView = 0; static int convergenceFrames = 0; + static bool waitingForRender = true; + + screenshotFrameCounter++; + + // Set camera for current view on first frame or after capture + if (screenshotFrameCounter == 1 || convergenceFrames == 0) { + renderPath.setCamera(views[currentView].x, views[currentView].y, + views[currentView].z, views[currentView].pitch, views[currentView].yaw); + } + + bool hasRendered = renderPath.renderer.getGpuMeshQuadCount() > 0; if (hasRendered) convergenceFrames++; - // Wait 60 frames after first render for AO temporal convergence - if (convergenceFrames == 60) { - bool ok = wi::helper::saveTextureToFile( - renderPath.getVoxelRT(), "bvle_screenshot.png"); - wi::backlog::post(ok ? "Screenshot saved: bvle_screenshot.png" - : "Screenshot FAILED"); - PostQuitMessage(0); + + // Wait 50 frames for AO convergence per view + if (convergenceFrames >= 50) { + char filename[64]; + snprintf(filename, sizeof(filename), "bvle_screenshot_%s.png", + views[currentView].name); + wi::helper::saveTextureToFile(renderPath.getVoxelRT(), filename); + + currentView++; + if (currentView >= numViews) { + PostQuitMessage(0); + } else { + convergenceFrames = 0; + renderPath.setCamera(views[currentView].x, views[currentView].y, + views[currentView].z, views[currentView].pitch, views[currentView].yaw); + renderPath.resetAOHistory(); // invalidate temporal AO for new view + } } } } diff --git a/src/voxel/VoxelRenderer.cpp b/src/voxel/VoxelRenderer.cpp index 2cac44c..a017b8e 100644 --- a/src/voxel/VoxelRenderer.cpp +++ b/src/voxel/VoxelRenderer.cpp @@ -1450,15 +1450,15 @@ void VoxelRenderer::render( cb.bleedMask = (1u << 1) | (1u << 2) | (1u << 4) | (1u << 5); cb.resistBleedMask = (1u << 1); cb.windTime = windTime_; - // Stylized lighting (Phase 7) — Wonderbox-inspired, iteration 4 - cb.skyAmbient = XMFLOAT4(0.65f, 0.68f, 0.75f, 0.0f); // very high ambient fill - cb.groundAmbient = XMFLOAT4(0.40f, 0.33f, 0.22f, 0.0f); // warm brown, high fill - cb.shadowTint = XMFLOAT4(0.55f, 0.45f, 0.72f, 0.0f); // purple-blue shadows - cb.fogColor = XMFLOAT4(0.80f, 0.75f, 0.60f, 1.0f); // warm sandy-golden fog + // Stylized lighting (Phase 7) — Wonderbox-inspired + cb.skyAmbient = XMFLOAT4(0.50f, 0.55f, 0.65f, 0.0f); // cool sky fill + cb.groundAmbient = XMFLOAT4(0.28f, 0.22f, 0.15f, 0.0f); // warm brown ground + cb.shadowTint = XMFLOAT4(0.50f, 0.42f, 0.70f, 0.0f); // purple-blue shadows + cb.fogColor = XMFLOAT4(0.78f, 0.73f, 0.60f, 1.0f); // warm sandy fog cb.fogParams = XMFLOAT4(0.004f, 0.0f, 0.0f, 0.0f); // fog density cb.rimColor = XMFLOAT4(0.90f, 0.80f, 0.55f, 0.0f); // warm golden rim cb.rimParams = XMFLOAT4(2.5f, 0.45f, 0.0f, 0.0f); // exponent, intensity - cb.toneMapParams = XMFLOAT4(1.40f, 2.2f, 0.0f, 0.0f); // vivid saturation, high exposure + cb.toneMapParams = XMFLOAT4(1.15f, 1.8f, 0.0f, 0.0f); // moderate saturation, good exposure dev->UpdateBuffer(&constantBuffer_, &cb, cmd, sizeof(cb)); // Save current VP for next frame's temporal reprojection XMStoreFloat4x4(&prevViewProjection_, vpMatrix); @@ -2780,4 +2780,15 @@ void VoxelRenderPath::Compose(CommandList cmd) const { wi::font::Draw(stats, fp, cmd); } +void VoxelRenderPath::setCamera(float x, float y, float z, float pitch, float yaw) { + cameraPos = { x, y, z }; + cameraPitch = pitch; + cameraYaw = yaw; +} + +void VoxelRenderPath::resetAOHistory() { + renderer.aoHistoryValid_ = false; + renderer.frameCounter_ = 0; +} + } // namespace voxel diff --git a/src/voxel/VoxelRenderer.h b/src/voxel/VoxelRenderer.h index df098f1..4fbe57b 100644 --- a/src/voxel/VoxelRenderer.h +++ b/src/voxel/VoxelRenderer.h @@ -317,6 +317,8 @@ public: bool debugMode = false; bool debugSmooth = false; bool screenshotMode = false; // CLI "screenshot": auto-position camera, capture, quit + void setCamera(float x, float y, float z, float pitch, float yaw); + void resetAOHistory(); // invalidate temporal AO after camera jump float cameraSpeed = 50.0f; float cameraSensitivity = 0.003f;