diff --git a/Editor/Editor.cpp b/Editor/Editor.cpp index 249651037..0d42f29d3 100644 --- a/Editor/Editor.cpp +++ b/Editor/Editor.cpp @@ -1346,7 +1346,7 @@ void EditorComponent::Update(float dt) if (wiInput::Down(wiInput::MOUSE_BUTTON_LEFT)) { // if water, then put a water ripple onto it: - wiRenderer::PutWaterRipple("images/ripple.png", hovered.position); + scene.PutWaterRipple("images/ripple.png", hovered.position); } } else if (decalWnd.placementCheckBox.GetCheck() && wiInput::Press(wiInput::MOUSE_BUTTON_LEFT)) diff --git a/Editor/WeatherWindow.cpp b/Editor/WeatherWindow.cpp index efa3b0ba5..c85820a94 100644 --- a/Editor/WeatherWindow.cpp +++ b/Editor/WeatherWindow.cpp @@ -216,7 +216,7 @@ void WeatherWindow::Create(EditorComponent* editor) weather.SetOceanEnabled(args.bValue); if (!weather.IsOceanEnabled()) { - wiRenderer::OceanRegenerate(weather); + wiScene::GetScene().OceanRegenerate(); } }); AddWidget(&ocean_enabledCheckBox); @@ -234,7 +234,7 @@ void WeatherWindow::Create(EditorComponent* editor) if (std::abs(weather.oceanParameters.patch_length - args.fValue) > FLT_EPSILON) { weather.oceanParameters.patch_length = args.fValue; - wiRenderer::OceanRegenerate(weather); + wiScene::GetScene().OceanRegenerate(); } } }); @@ -252,7 +252,7 @@ void WeatherWindow::Create(EditorComponent* editor) if (std::abs(weather.oceanParameters.wave_amplitude - args.fValue) > FLT_EPSILON) { weather.oceanParameters.wave_amplitude = args.fValue; - wiRenderer::OceanRegenerate(weather); + wiScene::GetScene().OceanRegenerate(); } } }); @@ -284,7 +284,7 @@ void WeatherWindow::Create(EditorComponent* editor) if (std::abs(weather.oceanParameters.wind_dependency - args.fValue) > FLT_EPSILON) { weather.oceanParameters.wind_dependency = args.fValue; - wiRenderer::OceanRegenerate(weather); + wiScene::GetScene().OceanRegenerate(); } } }); @@ -353,7 +353,7 @@ void WeatherWindow::Create(EditorComponent* editor) ocean_resetButton.SetPos(XMFLOAT2(x - 100, y += step)); ocean_resetButton.OnClick([=](wiEventArgs args) { auto& weather = GetWeather(); - weather.oceanParameters = WeatherComponent::OceanParameters(); + weather.oceanParameters = wiOcean::OceanParameters(); }); AddWidget(&ocean_resetButton); diff --git a/WickedEngine/RenderPath3D.cpp b/WickedEngine/RenderPath3D.cpp index f96abfc8e..4971a5800 100644 --- a/WickedEngine/RenderPath3D.cpp +++ b/WickedEngine/RenderPath3D.cpp @@ -1151,7 +1151,7 @@ void RenderPath3D::RenderTransparents(CommandList cmd) const GraphicsDevice* device = wiRenderer::GetDevice(); // Water ripple rendering: - if(wiRenderer::IsWaterrippleRendering()) + if(!scene->waterRipples.empty()) { device->RenderPassBegin(&renderpass_waterripples, cmd); diff --git a/WickedEngine/wiOcean.cpp b/WickedEngine/wiOcean.cpp index 2ccc91d64..73de1c476 100644 --- a/WickedEngine/wiOcean.cpp +++ b/WickedEngine/wiOcean.cpp @@ -104,17 +104,15 @@ float Phillips(XMFLOAT2 K, XMFLOAT2 W, float v, float a, float dir_depend) -wiOcean::wiOcean(const WeatherComponent& weather) +void wiOcean::Create(const OceanParameters& params) { GraphicsDevice* device = wiRenderer::GetDevice(); - auto& params = weather.oceanParameters; - // Height map H(0) int height_map_size = (params.dmap_dim + 4) * (params.dmap_dim + 1); std::vector h0_data(height_map_size); std::vector omega_data(height_map_size); - initHeightMap(weather, h0_data.data(), omega_data.data()); + initHeightMap(params, h0_data.data(), omega_data.data()); int hmap_dim = params.dmap_dim; int input_full_size = (hmap_dim + 4) * (hmap_dim + 1); @@ -223,10 +221,8 @@ wiOcean::wiOcean(const WeatherComponent& weather) // Initialize the vector field. // wlen_x: width of wave tile, in meters // wlen_y: length of wave tile, in meters -void wiOcean::initHeightMap(const WeatherComponent& weather, XMFLOAT2* out_h0, float* out_omega) +void wiOcean::initHeightMap(const OceanParameters& params, XMFLOAT2* out_h0, float* out_omega) { - auto& params = weather.oceanParameters; - int i, j; XMFLOAT2 K; @@ -267,10 +263,8 @@ void wiOcean::initHeightMap(const WeatherComponent& weather, XMFLOAT2* out_h0, f } } -void wiOcean::UpdateDisplacementMap(const WeatherComponent& weather, CommandList cmd) const +void wiOcean::UpdateDisplacementMap(const OceanParameters& params, CommandList cmd) const { - auto& params = weather.oceanParameters; - GraphicsDevice* device = wiRenderer::GetDevice(); device->EventBegin("Ocean Simulation", cmd); @@ -349,10 +343,8 @@ void wiOcean::UpdateDisplacementMap(const WeatherComponent& weather, CommandList } -void wiOcean::Render(const CameraComponent& camera, const WeatherComponent& weather, CommandList cmd) const +void wiOcean::Render(const CameraComponent& camera, const OceanParameters& params, CommandList cmd) const { - auto& params = weather.oceanParameters; - GraphicsDevice* device = wiRenderer::GetDevice(); device->EventBegin("Ocean Rendering", cmd); diff --git a/WickedEngine/wiOcean.h b/WickedEngine/wiOcean.h index 05f4fe50d..cbdef26ce 100644 --- a/WickedEngine/wiOcean.h +++ b/WickedEngine/wiOcean.h @@ -9,22 +9,51 @@ class wiOcean { public: - wiOcean(const wiScene::WeatherComponent& weather); + struct OceanParameters + { + // Must be power of 2. + int dmap_dim = 512; + // Typical value is 1000 ~ 2000 + float patch_length = 50.0f; - void UpdateDisplacementMap(const wiScene::WeatherComponent& weather, wiGraphics::CommandList cmd) const; - void Render(const wiScene::CameraComponent& camera, const wiScene::WeatherComponent& weather, wiGraphics::CommandList cmd) const; + // Adjust the time interval for simulation. + float time_scale = 0.3f; + // Amplitude for transverse wave. Around 1.0 + float wave_amplitude = 1000.0f; + // Wind direction. Normalization not required. + XMFLOAT2 wind_dir = XMFLOAT2(0.8f, 0.6f); + // Around 100 ~ 1000 + float wind_speed = 600.0f; + // This value damps out the waves against the wind direction. + // Smaller value means higher wind dependency. + float wind_dependency = 0.07f; + // The amplitude for longitudinal wave. Must be positive. + float choppy_scale = 1.3f; + + + XMFLOAT3 waterColor = XMFLOAT3(0.0f, 3.0f / 255.0f, 31.0f / 255.0f); + float waterHeight = 0.0f; + uint32_t surfaceDetail = 4; + float surfaceDisplacementTolerance = 2; + }; + void Create(const OceanParameters& params); + + void UpdateDisplacementMap(const OceanParameters& params, wiGraphics::CommandList cmd) const; + void Render(const wiScene::CameraComponent& camera, const OceanParameters& params, wiGraphics::CommandList cmd) const; const wiGraphics::Texture* getDisplacementMap() const; const wiGraphics::Texture* getGradientMap() const; static void Initialize(); + bool IsValid() const { return displacementMap.IsValid(); } + protected: wiGraphics::Texture displacementMap; // (RGBA32F) wiGraphics::Texture gradientMap; // (RGBA16F) - void initHeightMap(const wiScene::WeatherComponent& weather, XMFLOAT2* out_h0, float* out_omega); + void initHeightMap(const OceanParameters& params, XMFLOAT2* out_h0, float* out_omega); // Initial height field H(0) generated by Phillips spectrum & Gauss distribution. diff --git a/WickedEngine/wiRenderer.cpp b/WickedEngine/wiRenderer.cpp index 199ebe096..66b6fdf5f 100644 --- a/WickedEngine/wiRenderer.cpp +++ b/WickedEngine/wiRenderer.cpp @@ -31,8 +31,6 @@ #include "shaders/ShaderInterop_Paint.h" #include -#include -#include #include using namespace std; @@ -119,8 +117,6 @@ struct VoxelizedSceneData uint32_t mips = 7; } voxelSceneData; -std::unique_ptr ocean; - Texture shadowMapArray_2D; Texture shadowMapArray_Cube; Texture shadowMapArray_Transparent_2D; @@ -128,8 +124,6 @@ Texture shadowMapArray_Transparent_Cube; std::vector renderpasses_shadow2D; std::vector renderpasses_shadowCube; -deque waterRipples; - std::vector> renderableBoxes; std::vector> renderableSpheres; std::vector> renderableCapsules; @@ -2614,8 +2608,6 @@ void ClearWorld(Scene& scene) { scene.Clear(); - waterRipples.clear(); - deferredMIPGenLock.lock(); deferredMIPGens.clear(); deferredMIPGenLock.unlock(); @@ -3659,20 +3651,6 @@ void UpdatePerFrameData( }); } - wiJobSystem::Execute(ctx, [&](wiJobArgs args) { - for (auto& x : waterRipples) - { - x.Update(dt * 60); - } - while ( - !waterRipples.empty() && - (waterRipples.front().params.opacity <= 0 + FLT_EPSILON || waterRipples.front().params.fade == 1) - ) - { - waterRipples.pop_front(); - } - }); - // Update Voxelization parameters: if (scene.objects.GetCount() > 0) { @@ -3691,18 +3669,6 @@ void UpdatePerFrameData( voxelSceneData.extents = XMFLOAT3(voxelSceneData.res * voxelSceneData.voxelsize, voxelSceneData.res * voxelSceneData.voxelsize, voxelSceneData.res * voxelSceneData.voxelsize); } - if (scene.weather.IsOceanEnabled()) - { - if (ocean == nullptr) - { - ocean = std::make_unique(scene.weather); - } - } - else if (ocean != nullptr) - { - ocean.reset(); - } - wiJobSystem::Wait(ctx); if (!device->CheckCapability(GRAPHICSDEVICE_CAPABILITY_RAYTRACING) && scene.BVH_invalid) @@ -4358,10 +4324,10 @@ void UpdateRenderData( } // Compute water simulation: - if (vis.scene->weather.IsOceanEnabled() && ocean != nullptr) + if (vis.scene->weather.IsOceanEnabled()) { range = wiProfiler::BeginRangeGPU("Ocean - Simulate", cmd); - ocean->UpdateDisplacementMap(vis.scene->weather, cmd); + vis.scene->ocean.UpdateDisplacementMap(vis.scene->weather.oceanParameters, cmd); wiProfiler::EndRange(range); } @@ -4517,21 +4483,6 @@ void OcclusionCulling_Render(const CameraComponent& camera_previous, const Visib wiProfiler::EndRange(range); // Occlusion Culling Render } -void PutWaterRipple(const std::string& image, const XMFLOAT3& pos) -{ - wiSprite img(image); - img.params.enableExtractNormalMap(); - img.params.blendFlag = BLENDMODE_ADDITIVE; - img.anim.fad = 0.01f; - img.anim.scaleX = 0.2f; - img.anim.scaleY = 0.2f; - img.params.pos = pos; - img.params.rotation = (wiRandom::getRandom(0, 1000)*0.001f) * 2 * 3.1415f; - img.params.siz = XMFLOAT2(1, 1); - img.params.quality = QUALITY_ANISOTROPIC; - img.params.pivot = XMFLOAT2(0.5f, 0.5f); - waterRipples.push_back(img); -} void DrawWaterRipples(const Visibility& vis, CommandList cmd) { // remove camera jittering @@ -4545,7 +4496,7 @@ void DrawWaterRipples(const Visibility& vis, CommandList cmd) XMMATRIX R = XMMatrixLookToLH(XMVectorZero(), dir, XMVector3Cross(vvv, dir)); device->EventBegin("Water Ripples", cmd); - for(auto& x : waterRipples) + for(auto& x : vis.scene->waterRipples) { x.params.customRotation = &R; x.params.customProjection = &VP; @@ -5332,9 +5283,9 @@ void DrawScene( device->BindResource(CS, &vis.scene->TLAS, TEXSLOT_ACCELERATION_STRUCTURE, cmd); } - if (transparent && ocean != nullptr) + if (transparent && vis.scene->weather.IsOceanEnabled()) { - ocean->Render(*vis.camera, vis.scene->weather, cmd); + vis.scene->ocean.Render(*vis.camera, vis.scene->weather.oceanParameters, cmd); } if (hairparticle) @@ -12206,7 +12157,6 @@ float GetVoxelRadianceRayStepSize() { return voxelSceneData.rayStepSize; } void SetVoxelRadianceRayStepSize(float value) { voxelSceneData.rayStepSize = value; } void SetGameSpeed(float value) { GameSpeed = std::max(0.0f, value); } float GetGameSpeed() { return GameSpeed; } -void OceanRegenerate(const WeatherComponent& weather) { if (ocean != nullptr) ocean = std::make_unique(weather); } void SetRaytraceBounceCount(uint32_t bounces) { raytraceBounceCount = bounces; @@ -12239,10 +12189,6 @@ bool GetTessellationEnabled() { return tessellationEnabled; } -bool IsWaterrippleRendering() -{ - return !waterRipples.empty(); -} void SetDisableAlbedoMaps(bool value) { disableAlbedoMaps = value; diff --git a/WickedEngine/wiRenderer.h b/WickedEngine/wiRenderer.h index b52e63619..bc08ee461 100644 --- a/WickedEngine/wiRenderer.h +++ b/WickedEngine/wiRenderer.h @@ -654,7 +654,6 @@ namespace wiRenderer BORDEREXPANDSTYLE borderExpand = BORDEREXPAND_DISABLE ); - void PutWaterRipple(const std::string& image, const XMFLOAT3& pos); void DrawWaterRipples(const Visibility& vis, wiGraphics::CommandList cmd); @@ -728,7 +727,6 @@ namespace wiRenderer void SetVoxelRadianceRayStepSize(float value); void SetGameSpeed(float value); float GetGameSpeed(); - void OceanRegenerate(const wiScene::WeatherComponent& weather); // regeenrates ocean if it is already created void SetRaytraceBounceCount(uint32_t bounces); uint32_t GetRaytraceBounceCount(); void SetRaytraceDebugBVHVisualizerEnabled(bool value); @@ -737,7 +735,6 @@ namespace wiRenderer bool GetRaytracedShadowsEnabled(); void SetTessellationEnabled(bool value); bool GetTessellationEnabled(); - bool IsWaterrippleRendering(); void SetDisableAlbedoMaps(bool value); bool IsDisableAlbedoMaps(); void SetRaytracedShadowsSampleCount(uint32_t value); diff --git a/WickedEngine/wiRenderer_BindLua.cpp b/WickedEngine/wiRenderer_BindLua.cpp index 9f2a5b034..9f12f4390 100644 --- a/WickedEngine/wiRenderer_BindLua.cpp +++ b/WickedEngine/wiRenderer_BindLua.cpp @@ -341,7 +341,7 @@ namespace wiRenderer_BindLua { XMFLOAT3 pos; XMStoreFloat3(&pos, v->vector); - wiRenderer::PutWaterRipple(wiLua::GetScriptPath() + name, pos); + wiScene::GetScene().PutWaterRipple(wiLua::GetScriptPath() + name, pos); } else wiLua::SError(L, "PutWaterRipple(String imagename, Vector position) argument is not a Vector!"); diff --git a/WickedEngine/wiScene.cpp b/WickedEngine/wiScene.cpp index 41753258d..dd2984474 100644 --- a/WickedEngine/wiScene.cpp +++ b/WickedEngine/wiScene.cpp @@ -1591,6 +1591,21 @@ namespace wiScene } } + // Update water ripples: + for (size_t i = 0; i < waterRipples.size(); ++i) + { + auto& ripple = waterRipples[i]; + ripple.Update(dt * 60); + + // Remove inactive ripples: + if (ripple.params.opacity <= 0 + FLT_EPSILON || ripple.params.fade >= 1 - FLT_EPSILON) + { + ripple = waterRipples.back(); + waterRipples.pop_back(); + i--; + } + } + } void Scene::Clear() { @@ -1627,6 +1642,7 @@ namespace wiScene TLAS = RaytracingAccelerationStructure(); BVH.Clear(); packedDecals.clear(); + waterRipples.clear(); } void Scene::Merge(Scene& other) { @@ -3467,6 +3483,11 @@ namespace wiScene { weather = weathers[0]; weather.most_important_light_index = ~0; + + if (weather.IsOceanEnabled() && !ocean.IsValid()) + { + OceanRegenerate(); + } } } void Scene::RunSoundUpdateSystem(wiJobSystem::context& ctx) @@ -3507,6 +3528,21 @@ namespace wiScene } } + void Scene::PutWaterRipple(const std::string& image, const XMFLOAT3& pos) + { + wiSprite img(image); + img.params.enableExtractNormalMap(); + img.params.blendFlag = BLENDMODE_ADDITIVE; + img.anim.fad = 0.01f; + img.anim.scaleX = 0.2f; + img.anim.scaleY = 0.2f; + img.params.pos = pos; + img.params.rotation = (wiRandom::getRandom(0, 1000) * 0.001f) * 2 * 3.1415f; + img.params.siz = XMFLOAT2(1, 1); + img.params.quality = QUALITY_ANISOTROPIC; + img.params.pivot = XMFLOAT2(0.5f, 0.5f); + waterRipples.push_back(img); + } XMVECTOR SkinVertex(const MeshComponent& mesh, const ArmatureComponent& armature, uint32_t index, XMVECTOR* N) { diff --git a/WickedEngine/wiScene.h b/WickedEngine/wiScene.h index ddc28c43d..2a70326e8 100644 --- a/WickedEngine/wiScene.h +++ b/WickedEngine/wiScene.h @@ -10,6 +10,8 @@ #include "wiResourceManager.h" #include "wiSpinLock.h" #include "wiGPUBVH.h" +#include "wiOcean.h" +#include "wiSprite.h" #include "wiECS.h" #include "wiScene_Decl.h" @@ -1130,34 +1132,7 @@ namespace wiScene float windWaveSize = 1; float windSpeed = 1; - struct OceanParameters - { - // Must be power of 2. - int dmap_dim = 512; - // Typical value is 1000 ~ 2000 - float patch_length = 50.0f; - - // Adjust the time interval for simulation. - float time_scale = 0.3f; - // Amplitude for transverse wave. Around 1.0 - float wave_amplitude = 1000.0f; - // Wind direction. Normalization not required. - XMFLOAT2 wind_dir = XMFLOAT2(0.8f, 0.6f); - // Around 100 ~ 1000 - float wind_speed = 600.0f; - // This value damps out the waves against the wind direction. - // Smaller value means higher wind dependency. - float wind_dependency = 0.07f; - // The amplitude for longitudinal wave. Must be positive. - float choppy_scale = 1.3f; - - - XMFLOAT3 waterColor = XMFLOAT3(0.0f, 3.0f / 255.0f, 31.0f / 255.0f); - float waterHeight = 0.0f; - uint32_t surfaceDetail = 4; - float surfaceDisplacementTolerance = 2; - }; - OceanParameters oceanParameters; + wiOcean::OceanParameters oceanParameters; std::string skyMapName; std::string colorGradingMapName; @@ -1305,12 +1280,14 @@ namespace wiScene BVH_invalid = true; } + // Occlusion query state: wiGraphics::GPUQueryHeap queryHeap[arraysize(ObjectComponent::occlusionQueries)]; std::vector queryResults; uint32_t writtenQueries[arraysize(queryHeap)] = {}; int queryheap_idx = 0; std::atomic queryAllocator{ 0 }; + // Environment probe cubemap array state: static const uint32_t envmapCount = 16; const uint32_t envmapRes = 128; const uint32_t envmapMIPs = 8; @@ -1318,24 +1295,36 @@ namespace wiScene wiGraphics::Texture envmapArray; std::vector renderpasses_envmap; + // Impostor texture array state: static const uint32_t maxImpostorCount = 8; const uint32_t impostorTextureDim = 128; wiGraphics::Texture impostorDepthStencil; wiGraphics::Texture impostorArray; std::vector renderpasses_impostor; + // Atlas packing border size in pixels: static const int atlasClampBorder = 1; + // Lightmap atlas state: wiGraphics::Texture lightmap; std::vector lightmap_rects; std::atomic lightmap_rect_allocator{ 0 }; mutable std::atomic_bool lightmap_repack_needed{ false }; mutable std::atomic_bool lightmap_refresh_needed{ false }; + // Decal atlas state: wiGraphics::Texture decalAtlas; mutable bool decal_repack_needed{ false }; std::unordered_map, wiRectPacker::rect_xywh> packedDecals; + // Ocean GPU state: + wiOcean ocean; + void OceanRegenerate() { ocean.Create(weather.oceanParameters); } + + // Simple water ripple sprites: + mutable std::vector waterRipples; + void PutWaterRipple(const std::string& image, const XMFLOAT3& pos); + // Update all components by a given timestep (in seconds): // This is an expensive function, prefer to call it only once per frame! void Update(float dt); diff --git a/WickedEngine/wiShaderCompiler.cpp b/WickedEngine/wiShaderCompiler.cpp index 2132df468..418d21ffd 100644 --- a/WickedEngine/wiShaderCompiler.cpp +++ b/WickedEngine/wiShaderCompiler.cpp @@ -74,6 +74,7 @@ namespace wiShaderCompiler args.push_back(L"-spirv"); args.push_back(L"-fspv-target-env=vulkan1.2"); args.push_back(L"-fvk-use-dx-layout"); + args.push_back(L"-fvk-use-dx-position-w"); //args.push_back(L"-fvk-b-shift"); args.push_back(L"0"); args.push_back(L"0"); args.push_back(L"-fvk-t-shift"); args.push_back(L"1000"); args.push_back(L"0"); args.push_back(L"-fvk-u-shift"); args.push_back(L"2000"); args.push_back(L"0");