diff --git a/WickedEngine/wiRenderPath3D.cpp b/WickedEngine/wiRenderPath3D.cpp index dc44c78dfc..0909175c2d 100644 --- a/WickedEngine/wiRenderPath3D.cpp +++ b/WickedEngine/wiRenderPath3D.cpp @@ -790,7 +790,7 @@ namespace wi ); } - if (wi::renderer::GetDDGIEnabled()) + if (wi::renderer::GetDDGIEnabled() && getSceneUpdateEnabled()) { wi::renderer::DDGI( *scene, @@ -1032,7 +1032,7 @@ namespace wi }); } - if (wi::renderer::GetVXGIEnabled()) + if (wi::renderer::GetVXGIEnabled() && getSceneUpdateEnabled()) { cmd = device->BeginCommandList(); wi::jobsystem::Execute(ctx, [cmd, this](wi::jobsystem::JobArgs args) { @@ -1041,19 +1041,22 @@ namespace wi } // Updating textures: - cmd = device->BeginCommandList(); - device->WaitCommandList(cmd, cmd_prepareframe_async); - wi::jobsystem::Execute(ctx, [cmd, this](wi::jobsystem::JobArgs args) { - wi::renderer::BindCommonResources(cmd); - wi::renderer::BindCameraCB( - *camera, - camera_previous, - camera_reflection, - cmd - ); - wi::renderer::RefreshLightmaps(*scene, cmd); - wi::renderer::RefreshEnvProbes(visibility_main, cmd); - }); + if (getSceneUpdateEnabled()) + { + cmd = device->BeginCommandList(); + device->WaitCommandList(cmd, cmd_prepareframe_async); + wi::jobsystem::Execute(ctx, [cmd, this](wi::jobsystem::JobArgs args) { + wi::renderer::BindCommonResources(cmd); + wi::renderer::BindCameraCB( + *camera, + camera_previous, + camera_reflection, + cmd + ); + wi::renderer::RefreshLightmaps(*scene, cmd); + wi::renderer::RefreshEnvProbes(visibility_main, cmd); + }); + } if (visibility_main.IsRequestedPlanarReflections()) { diff --git a/WickedEngine/wiRenderer.cpp b/WickedEngine/wiRenderer.cpp index bc70a88c8c..786c704912 100644 --- a/WickedEngine/wiRenderer.cpp +++ b/WickedEngine/wiRenderer.cpp @@ -6,7 +6,6 @@ #include "wiHelper.h" #include "wiTextureHelper.h" #include "wiEnums.h" -#include "wiRectPacker.h" #include "wiBacklog.h" #include "wiProfiler.h" #include "wiOcean.h" @@ -2476,7 +2475,7 @@ inline void CreateSpotLightShadowCam(const LightComponent& light, SHCAM& shcam) { shcam.init(light.position, light.rotation, 0.1f, light.GetRange(), light.outerConeAngle * 2); } -inline void CreateDirLightShadowCams(const LightComponent& light, CameraComponent camera, SHCAM* shcams, size_t shcam_count) +inline void CreateDirLightShadowCams(const LightComponent& light, CameraComponent camera, SHCAM* shcams, size_t shcam_count, const wi::rectpacker::Rect& shadow_rect) { // remove camera jittering camera.jitter = XMFLOAT2(0, 0); @@ -2542,7 +2541,7 @@ inline void CreateDirLightShadowCams(const LightComponent& light, CameraComponen // Snap cascade to texel grid: const XMVECTOR extent = XMVectorSubtract(vMax, vMin); - const XMVECTOR texelSize = extent / float(light.shadow_rect.w); + const XMVECTOR texelSize = extent / float(shadow_rect.w); vMin = XMVectorFloor(vMin / texelSize) * texelSize; vMax = XMVectorFloor(vMax / texelSize) * texelSize; center = (vMin + vMax) * 0.5f; @@ -3011,6 +3010,8 @@ void UpdateVisibility(Visibility& vis) // Cull lights: const uint32_t light_loop = (uint32_t)std::min(vis.scene->aabb_lights.size(), vis.scene->lights.GetCount()); vis.visibleLights.resize(light_loop); + vis.visibleLightShadowRects.clear(); + vis.visibleLightShadowRects.resize(light_loop); wi::jobsystem::Dispatch(ctx, light_loop, groupSize, [&](wi::jobsystem::JobArgs args) { // Setup stream compaction: @@ -3262,56 +3263,26 @@ void UpdateVisibility(Visibility& vis) } } - wi::profiler::EndRange(range); // Frustum Culling -} -void UpdatePerFrameData( - Scene& scene, - const Visibility& vis, - FrameCB& frameCB, - float dt -) -{ - // Update Voxelization parameters: - if (scene.objects.GetCount() > 0) - { - Scene::VXGI::ClipMap& clipmap = scene.vxgi.clipmaps[scene.vxgi.clipmap_to_update]; - clipmap.voxelsize = scene.vxgi.clipmaps[0].voxelsize * (1u << scene.vxgi.clipmap_to_update); - const float texelSize = clipmap.voxelsize * 2; - XMFLOAT3 center = XMFLOAT3(std::floor(vis.camera->Eye.x / texelSize) * texelSize, std::floor(vis.camera->Eye.y / texelSize) * texelSize, std::floor(vis.camera->Eye.z / texelSize) * texelSize); - clipmap.offsetfromPrevFrame.x = int((clipmap.center.x - center.x) / texelSize); - clipmap.offsetfromPrevFrame.y = -int((clipmap.center.y - center.y) / texelSize); - clipmap.offsetfromPrevFrame.z = int((clipmap.center.z - center.z) / texelSize); - clipmap.center = center; - XMFLOAT3 extents = XMFLOAT3(scene.vxgi.res * clipmap.voxelsize, scene.vxgi.res * clipmap.voxelsize, scene.vxgi.res * clipmap.voxelsize); - if (extents.x != clipmap.extents.x || extents.y != clipmap.extents.y || extents.z != clipmap.extents.z) - { - scene.vxgi.pre_clear = true; - } - clipmap.extents = extents; - } - // Shadow atlas packing: - if (!vis.visibleLights.empty() || vis.scene->weather.rain_amount > 0) + if ((vis.flags & Visibility::ALLOW_SHADOW_ATLAS_PACKING) && !vis.visibleLights.empty() || vis.scene->weather.rain_amount > 0) { auto range = wi::profiler::BeginRangeCPU("Shadowmap packing"); - static thread_local wi::rectpacker::State packer; float iterative_scaling = 1; while (iterative_scaling > 0.03f) { - packer.clear(); - if(vis.scene->weather.rain_amount > 0) + vis.shadow_packer.clear(); + if (vis.scene->weather.rain_amount > 0) { // Rain blocker: wi::rectpacker::Rect rect = {}; rect.id = -1; rect.w = rect.h = 128; - packer.add_rect(rect); + vis.shadow_packer.add_rect(rect); } for (uint32_t lightIndex : vis.visibleLights) { - LightComponent& light = scene.lights[lightIndex]; - light.shadow_rect = {}; + const LightComponent& light = vis.scene->lights[lightIndex]; if (!light.IsCastingShadow() || light.IsStatic()) continue; @@ -3362,56 +3333,53 @@ void UpdatePerFrameData( } if (rect.w > 8 && rect.h > 8) { - packer.add_rect(rect); + vis.shadow_packer.add_rect(rect); } } - if (!packer.rects.empty()) + if (!vis.shadow_packer.rects.empty()) { - if (packer.pack(8192)) + if (vis.shadow_packer.pack(8192)) { - for (auto& rect : packer.rects) + for (auto& rect : vis.shadow_packer.rects) { if (rect.id == -1) { // Rain blocker: if (rect.was_packed) { - scene.rain_blocker_dummy_light.shadow_rect = rect; + vis.rain_blocker_shadow_rect = rect; } else { - scene.rain_blocker_dummy_light.shadow_rect = {}; + vis.rain_blocker_shadow_rect = {}; } continue; } uint32_t lightIndex = uint32_t(rect.id); - LightComponent& light = scene.lights[lightIndex]; + wi::rectpacker::Rect& lightrect = vis.visibleLightShadowRects[lightIndex]; + const LightComponent& light = vis.scene->lights[lightIndex]; if (rect.was_packed) { - light.shadow_rect = rect; + lightrect = rect; // Remove slice multipliers from rect: switch (light.GetType()) { case LightComponent::DIRECTIONAL: - light.shadow_rect.w /= int(light.cascade_distances.size()); + lightrect.w /= int(light.cascade_distances.size()); break; case LightComponent::POINT: - light.shadow_rect.w /= 6; + lightrect.w /= 6; break; } } - else - { - light.direction = {}; - } } - if ((int)shadowMapAtlas.desc.width < packer.width || (int)shadowMapAtlas.desc.height < packer.height) + if ((int)shadowMapAtlas.desc.width < vis.shadow_packer.width || (int)shadowMapAtlas.desc.height < vis.shadow_packer.height) { TextureDesc desc; - desc.width = uint32_t(packer.width); - desc.height = uint32_t(packer.height); + desc.width = uint32_t(vis.shadow_packer.width); + desc.height = uint32_t(vis.shadow_packer.height); desc.format = format_depthbuffer_shadowmap; desc.bind_flags = BindFlag::DEPTH_STENCIL | BindFlag::SHADER_RESOURCE; desc.layout = ResourceState::SHADER_RESOURCE; @@ -3430,7 +3398,7 @@ void UpdatePerFrameData( device->SetName(&shadowMapAtlas_Transparent, "shadowMapAtlas_Transparent"); } - + break; } else @@ -3446,6 +3414,15 @@ void UpdatePerFrameData( wi::profiler::EndRange(range); } + wi::profiler::EndRange(range); // Frustum Culling +} +void UpdatePerFrameData( + Scene& scene, + const Visibility& vis, + FrameCB& frameCB, + float dt +) +{ // Calculate volumetric cloud shadow data: if (vis.scene->weather.IsVolumetricClouds() && vis.scene->weather.IsVolumetricCloudsCastShadow()) { @@ -3591,13 +3568,13 @@ void UpdatePerFrameData( frameCB.rain_blocker_matrix_prev = frameCB.rain_blocker_matrix; frameCB.rain_blocker_matrix_inverse_prev = frameCB.rain_blocker_matrix_inverse; frameCB.rain_blocker_mad = XMFLOAT4( - float(scene.rain_blocker_dummy_light.shadow_rect.w) / float(shadowMapAtlas.desc.width), - float(scene.rain_blocker_dummy_light.shadow_rect.h) / float(shadowMapAtlas.desc.height), - float(scene.rain_blocker_dummy_light.shadow_rect.x) / float(shadowMapAtlas.desc.width), - float(scene.rain_blocker_dummy_light.shadow_rect.y) / float(shadowMapAtlas.desc.height) + float(vis.rain_blocker_shadow_rect.w) / float(shadowMapAtlas.desc.width), + float(vis.rain_blocker_shadow_rect.h) / float(shadowMapAtlas.desc.height), + float(vis.rain_blocker_shadow_rect.x) / float(shadowMapAtlas.desc.width), + float(vis.rain_blocker_shadow_rect.y) / float(shadowMapAtlas.desc.height) ); SHCAM shcam; - CreateDirLightShadowCams(vis.scene->rain_blocker_dummy_light, *vis.camera, &shcam, 1); + CreateDirLightShadowCams(vis.scene->rain_blocker_dummy_light, *vis.camera, &shcam, 1, vis.rain_blocker_shadow_rect); XMStoreFloat4x4(&frameCB.rain_blocker_matrix, shcam.view_projection); XMStoreFloat4x4(&frameCB.rain_blocker_matrix_inverse, XMMatrixInverse(nullptr, shcam.view_projection)); } @@ -4031,13 +4008,14 @@ void UpdateRenderData( shaderentity.indices = ~0; bool shadow = light.IsCastingShadow() && !light.IsStatic(); + const wi::rectpacker::Rect& shadow_rect = vis.visibleLightShadowRects[lightIndex]; if (shadow) { - shaderentity.shadowAtlasMulAdd.x = light.shadow_rect.w * atlas_dim_rcp.x; - shaderentity.shadowAtlasMulAdd.y = light.shadow_rect.h * atlas_dim_rcp.y; - shaderentity.shadowAtlasMulAdd.z = light.shadow_rect.x * atlas_dim_rcp.x; - shaderentity.shadowAtlasMulAdd.w = light.shadow_rect.y * atlas_dim_rcp.y; + shaderentity.shadowAtlasMulAdd.x = shadow_rect.w * atlas_dim_rcp.x; + shaderentity.shadowAtlasMulAdd.y = shadow_rect.h * atlas_dim_rcp.y; + shaderentity.shadowAtlasMulAdd.z = shadow_rect.x * atlas_dim_rcp.x; + shaderentity.shadowAtlasMulAdd.w = shadow_rect.y * atlas_dim_rcp.y; shaderentity.SetIndices(matrixCounter, 0); } @@ -4050,7 +4028,7 @@ void UpdateRenderData( if (shadow && !light.cascade_distances.empty()) { SHCAM* shcams = (SHCAM*)alloca(sizeof(SHCAM) * light.cascade_distances.size()); - CreateDirLightShadowCams(light, *vis.camera, shcams, light.cascade_distances.size()); + CreateDirLightShadowCams(light, *vis.camera, shcams, light.cascade_distances.size(), shadow_rect); for (size_t cascade = 0; cascade < light.cascade_distances.size(); ++cascade) { std::memcpy(&matrixArray[matrixCounter++], &shcams[cascade].view_projection, sizeof(XMMATRIX)); @@ -5618,6 +5596,7 @@ void DrawShadowmaps( { continue; } + const wi::rectpacker::Rect& shadow_rect = vis.visibleLightShadowRects[lightIndex]; switch (light.GetType()) { @@ -5631,7 +5610,7 @@ void DrawShadowmaps( const uint32_t cascade_count = std::min((uint32_t)light.cascade_distances.size(), max_viewport_count); Viewport* viewports = (Viewport*)alloca(sizeof(Viewport) * cascade_count); SHCAM* shcams = (SHCAM*)alloca(sizeof(SHCAM) * cascade_count); - CreateDirLightShadowCams(light, *vis.camera, shcams, cascade_count); + CreateDirLightShadowCams(light, *vis.camera, shcams, cascade_count, shadow_rect); renderQueue.init(); bool transparentShadowsRequested = false; @@ -5674,10 +5653,10 @@ void DrawShadowmaps( cb.cameras[cascade].output_index = cascade; Viewport& vp = viewports[cascade]; - vp.top_left_x = float(light.shadow_rect.x + cascade * light.shadow_rect.w); - vp.top_left_y = float(light.shadow_rect.y); - vp.width = float(light.shadow_rect.w); - vp.height = float(light.shadow_rect.h); + vp.top_left_x = float(shadow_rect.x + cascade * shadow_rect.w); + vp.top_left_y = float(shadow_rect.y); + vp.width = float(shadow_rect.w); + vp.height = float(shadow_rect.h); vp.min_depth = 0.0f; vp.max_depth = 1.0f; } @@ -5702,10 +5681,10 @@ void DrawShadowmaps( device->BindDynamicConstantBuffer(cb, CBSLOT_RENDERER_CAMERA, cmd); Viewport vp; - vp.top_left_x = float(light.shadow_rect.x + cascade * light.shadow_rect.w); - vp.top_left_y = float(light.shadow_rect.y); - vp.width = float(light.shadow_rect.w); - vp.height = float(light.shadow_rect.h); + vp.top_left_x = float(shadow_rect.x + cascade * shadow_rect.w); + vp.top_left_y = float(shadow_rect.y); + vp.width = float(shadow_rect.w); + vp.height = float(shadow_rect.h); vp.min_depth = 0.0f; vp.max_depth = 1.0f; device->BindViewports(1, &vp, cmd); @@ -5773,10 +5752,10 @@ void DrawShadowmaps( device->BindDynamicConstantBuffer(cb, CBSLOT_RENDERER_CAMERA, cmd); Viewport vp; - vp.top_left_x = float(light.shadow_rect.x); - vp.top_left_y = float(light.shadow_rect.y); - vp.width = float(light.shadow_rect.w); - vp.height = float(light.shadow_rect.h); + vp.top_left_x = float(shadow_rect.x); + vp.top_left_y = float(shadow_rect.y); + vp.width = float(shadow_rect.w); + vp.height = float(shadow_rect.h); vp.min_depth = 0.0f; vp.max_depth = 1.0f; device->BindViewports(1, &vp, cmd); @@ -5801,10 +5780,10 @@ void DrawShadowmaps( device->BindDynamicConstantBuffer(cb, CBSLOT_RENDERER_CAMERA, cmd); Viewport vp; - vp.top_left_x = float(light.shadow_rect.x); - vp.top_left_y = float(light.shadow_rect.y); - vp.width = float(light.shadow_rect.w); - vp.height = float(light.shadow_rect.h); + vp.top_left_x = float(shadow_rect.x); + vp.top_left_y = float(shadow_rect.y); + vp.width = float(shadow_rect.w); + vp.height = float(shadow_rect.h); vp.min_depth = 0.0f; vp.max_depth = 1.0f; device->BindViewports(1, &vp, cmd); @@ -5854,10 +5833,10 @@ void DrawShadowmaps( frusta[camera_count] = cameras[shcam].frustum; camera_count++; } - vp[shcam].top_left_x = float(light.shadow_rect.x + shcam * light.shadow_rect.w); - vp[shcam].top_left_y = float(light.shadow_rect.y); - vp[shcam].width = float(light.shadow_rect.w); - vp[shcam].height = float(light.shadow_rect.h); + vp[shcam].top_left_x = float(shadow_rect.x + shcam * shadow_rect.w); + vp[shcam].top_left_y = float(shadow_rect.y); + vp[shcam].width = float(shadow_rect.w); + vp[shcam].height = float(shadow_rect.h); vp[shcam].min_depth = 0.0f; vp[shcam].max_depth = 1.0f; } @@ -5931,10 +5910,10 @@ void DrawShadowmaps( device->BindDynamicConstantBuffer(cb, CBSLOT_RENDERER_CAMERA, cmd); Viewport vp; - vp.top_left_x = float(light.shadow_rect.x + shcam * light.shadow_rect.w); - vp.top_left_y = float(light.shadow_rect.y); - vp.width = float(light.shadow_rect.w); - vp.height = float(light.shadow_rect.h); + vp.top_left_x = float(shadow_rect.x + shcam * shadow_rect.w); + vp.top_left_y = float(shadow_rect.y); + vp.width = float(shadow_rect.w); + vp.height = float(shadow_rect.h); vp.min_depth = 0; vp.max_depth = 1; device->BindViewports(1, &vp, cmd); @@ -5963,7 +5942,7 @@ void DrawShadowmaps( if(vis.scene->weather.rain_amount > 0) { SHCAM shcam; - CreateDirLightShadowCams(vis.scene->rain_blocker_dummy_light, *vis.camera, &shcam, 1); + CreateDirLightShadowCams(vis.scene->rain_blocker_dummy_light, *vis.camera, &shcam, 1, vis.rain_blocker_shadow_rect); renderQueue.init(); for (size_t i = 0; i < vis.scene->aabb_objects.size(); ++i) @@ -5995,10 +5974,10 @@ void DrawShadowmaps( cb.cameras[cascade].output_index = cascade; Viewport vp; - vp.top_left_x = float(vis.scene->rain_blocker_dummy_light.shadow_rect.x + cascade * vis.scene->rain_blocker_dummy_light.shadow_rect.w); - vp.top_left_y = float(vis.scene->rain_blocker_dummy_light.shadow_rect.y); - vp.width = float(vis.scene->rain_blocker_dummy_light.shadow_rect.w); - vp.height = float(vis.scene->rain_blocker_dummy_light.shadow_rect.h); + vp.top_left_x = float(vis.rain_blocker_shadow_rect.x + cascade * vis.rain_blocker_shadow_rect.w); + vp.top_left_y = float(vis.rain_blocker_shadow_rect.y); + vp.width = float(vis.rain_blocker_shadow_rect.w); + vp.height = float(vis.rain_blocker_shadow_rect.h); vp.min_depth = 0.0f; vp.max_depth = 1.0f; diff --git a/WickedEngine/wiRenderer.h b/WickedEngine/wiRenderer.h index 2f4b944309..dd8ca7baec 100644 --- a/WickedEngine/wiRenderer.h +++ b/WickedEngine/wiRenderer.h @@ -4,6 +4,7 @@ #include "wiGraphicsDevice.h" #include "wiScene.h" #include "wiECS.h" +#include "wiRectPacker.h" #include "wiPrimitive.h" #include "wiCanvas.h" #include "wiMath.h" @@ -109,6 +110,7 @@ namespace wi::renderer ALLOW_HAIRS = 1 << 5, ALLOW_REQUEST_REFLECTION = 1 << 6, ALLOW_OCCLUSION_CULLING = 1 << 7, + ALLOW_SHADOW_ATLAS_PACKING = 1 << 8, ALLOW_EVERYTHING = ~0u }; @@ -122,6 +124,9 @@ namespace wi::renderer wi::vector visibleEmitters; wi::vector visibleHairs; wi::vector visibleLights; + wi::rectpacker::State shadow_packer; + wi::rectpacker::Rect rain_blocker_shadow_rect; + wi::vector visibleLightShadowRects; std::atomic object_counter; std::atomic light_counter; diff --git a/WickedEngine/wiScene.cpp b/WickedEngine/wiScene.cpp index dd2e3135ee..1c58cbdebb 100644 --- a/WickedEngine/wiScene.cpp +++ b/WickedEngine/wiScene.cpp @@ -767,6 +767,25 @@ namespace wi::scene } } + // VXGI volume update: + // Note: this is using camera that the scene is associated with + { + VXGI::ClipMap& clipmap = vxgi.clipmaps[vxgi.clipmap_to_update]; + clipmap.voxelsize = vxgi.clipmaps[0].voxelsize * (1u << vxgi.clipmap_to_update); + const float texelSize = clipmap.voxelsize * 2; + XMFLOAT3 center = XMFLOAT3(std::floor(camera.Eye.x / texelSize) * texelSize, std::floor(camera.Eye.y / texelSize) * texelSize, std::floor(camera.Eye.z / texelSize) * texelSize); + clipmap.offsetfromPrevFrame.x = int((clipmap.center.x - center.x) / texelSize); + clipmap.offsetfromPrevFrame.y = -int((clipmap.center.y - center.y) / texelSize); + clipmap.offsetfromPrevFrame.z = int((clipmap.center.z - center.z) / texelSize); + clipmap.center = center; + XMFLOAT3 extents = XMFLOAT3(vxgi.res * clipmap.voxelsize, vxgi.res * clipmap.voxelsize, vxgi.res * clipmap.voxelsize); + if (extents.x != clipmap.extents.x || extents.y != clipmap.extents.y || extents.z != clipmap.extents.z) + { + vxgi.pre_clear = true; + } + clipmap.extents = extents; + } + // Shader scene resources: if (device->CheckCapability(GraphicsDeviceCapability::CACHE_COHERENT_UMA)) { @@ -4598,7 +4617,6 @@ namespace wi::scene ocean.occlusionQueries[queryheap_idx] = -1; // invalidate query } - rain_blocker_dummy_light.shadow_rect = {}; if (weather.rain_amount > 0) { GraphicsDevice* device = wi::graphics::GetDevice(); diff --git a/WickedEngine/wiScene_Components.h b/WickedEngine/wiScene_Components.h index fc714dc0b8..868eb5c3d9 100644 --- a/WickedEngine/wiScene_Components.h +++ b/WickedEngine/wiScene_Components.h @@ -1045,7 +1045,6 @@ namespace wi::scene XMFLOAT4 rotation = XMFLOAT4(0, 0, 0, 1); XMFLOAT3 scale = XMFLOAT3(1, 1, 1); mutable int occlusionquery = -1; - wi::rectpacker::Rect shadow_rect = {}; wi::vector lensFlareRimTextures; diff --git a/WickedEngine/wiVersion.cpp b/WickedEngine/wiVersion.cpp index 09044ea840..ee6b36939f 100644 --- a/WickedEngine/wiVersion.cpp +++ b/WickedEngine/wiVersion.cpp @@ -9,7 +9,7 @@ namespace wi::version // minor features, major updates, breaking compatibility changes const int minor = 71; // minor bug fixes, alterations, refactors, updates - const int revision = 375; + const int revision = 376; const std::string version_string = std::to_string(major) + "." + std::to_string(minor) + "." + std::to_string(revision);