diff --git a/data/shaders/screen_space_shadows/bend_sss.hlsl b/data/shaders/screen_space_shadows/bend_sss.hlsl index e745fcae1..918513ec6 100644 --- a/data/shaders/screen_space_shadows/bend_sss.hlsl +++ b/data/shaders/screen_space_shadows/bend_sss.hlsl @@ -24,9 +24,9 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. //======================= #define WAVE_SIZE 64 -#define SAMPLE_COUNT 256 -#define HARD_SHADOW_SAMPLES 16 -#define FADE_OUT_SAMPLES 8 +#define SAMPLE_COUNT 256 // shadow samples per-pixel, determines overall cost, default: 60 +#define HARD_SHADOW_SAMPLES 1 // initial shadow samples that will produce a hard shadow, and not perform sample-averaging, defauult: 4 +#define FADE_OUT_SAMPLES 64 // samples that will fade out at the end of the shadow (for a minor cost), default : 8 #include "bend_sss_gpu.hlsl" @@ -41,18 +41,18 @@ void main_cs { DispatchParameters in_parameters; in_parameters.SetDefaults(); - in_parameters.LightCoordinate = pass_get_f4_value(); // Values stored in DispatchList::LightCoordinate_Shader by BuildDispatchList() - in_parameters.WaveOffset = pass_get_f2_value(); // Values stored in DispatchData::WaveOffset_Shader by BuildDispatchList() - in_parameters.NearDepthValue = pass_get_f3_value().x; // Set to the Depth Buffer Value for the near clip plane, as determined by renderer projection matrix setup (typically 1). - in_parameters.FarDepthValue = pass_get_f3_value().y; // Set to the Depth Buffer Value for the far clip plane, as determined by renderer projection matrix setup (typically 0). + in_parameters.LightCoordinate = pass_get_f4_value(); // values stored in DispatchList::LightCoordinate_Shader by BuildDispatchList() + in_parameters.WaveOffset = pass_get_f2_value(); // values stored in DispatchData::WaveOffset_Shader by BuildDispatchList() + in_parameters.NearDepthValue = pass_get_f3_value().x; // set to the Depth Buffer Value for the near clip plane, as determined by renderer projection matrix setup (typically 1). + in_parameters.FarDepthValue = pass_get_f3_value().y; // set to the Depth Buffer Value for the far clip plane, as determined by renderer projection matrix setup (typically 0). in_parameters.ArraySliceIndex = pass_get_f3_value().z; - in_parameters.InvDepthTextureSize = pass_get_f3_value2().xy; // Inverse of the texture dimensions for 'DepthTexture' (used to convert from pixel coordinates to UVs) + in_parameters.InvDepthTextureSize = pass_get_f3_value2().xy; // inverse of the texture dimensions for 'DepthTexture' (used to convert from pixel coordinates to UVs) in_parameters.DepthTexture = tex; in_parameters.OutputTexture = tex_uav_sss; - in_parameters.PointBorderSampler = samplers[sampler_point_clamp_border]; // A point sampler, with Wrap Mode set to Clamp-To-Border-Color (D3D12_TEXTURE_ADDRESS_MODE_BORDER), and Border Color set to "FarDepthValue" (typically zero), or some other far-depth value out of DepthBounds. - in_parameters.DebugOutputEdgeMask = false; // Use this to visualize edges, for tuning the 'BilinearThreshold' value. - in_parameters.DebugOutputThreadIndex = false; // Debug output to visualize layout of compute threads - in_parameters.DebugOutputWaveIndex = false; // Debug output to visualize layout of compute wavefronts, useful to sanity check the Light Coordinate is being computed correctly. + in_parameters.PointBorderSampler = samplers[sampler_point_clamp_border]; // a point sampler, with Wrap Mode set to Clamp-To-Border-Color (D3D12_TEXTURE_ADDRESS_MODE_BORDER), and Border Color set to "FarDepthValue" (typically zero), or some other far-depth value out of DepthBounds. + in_parameters.DebugOutputEdgeMask = false; // use this to visualize edges, for tuning the 'BilinearThreshold' value. + in_parameters.DebugOutputThreadIndex = false; // debug output to visualize layout of compute threads + in_parameters.DebugOutputWaveIndex = false; // debug output to visualize layout of compute wavefronts, useful to sanity check the Light Coordinate is being computed correctly. WriteScreenSpaceShadow(in_parameters, Gid, GTid.x); } diff --git a/data/shaders/screen_space_shadows/sss.hlsl b/data/shaders/screen_space_shadows/sss.hlsl deleted file mode 100644 index f58fb5ad5..000000000 --- a/data/shaders/screen_space_shadows/sss.hlsl +++ /dev/null @@ -1,42 +0,0 @@ -/* -Copyright(c) 2016-2024 Panos Karabelas - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and / or sell -copies of the Software, and to permit persons to whom the Software is furnished -to do so, subject to the following conditions : - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS -FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE AUTHORS OR -COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER -IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN -CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -*/ - -//= INCLUDES ======================= -#include "../common.hlsl" -#include "screen_space_shadows.hlsl" -//================================== - -[numthreads(THREAD_GROUP_COUNT_X, THREAD_GROUP_COUNT_Y, 1)] -void mainCS(uint3 thread_id : SV_DispatchThreadID) -{ - // create surface - Surface surface; - surface.Build(thread_id.xy, true, true, true); - - // create light - Light light; - light.Build(surface); - - float shadow = ScreenSpaceShadows(surface, light); - int array_slice_index = pass_get_f3_value().z; - - tex_uav4[int3(thread_id.xy, array_slice_index)] = shadow; -} diff --git a/runtime/Rendering/Font/Font.cpp b/runtime/Rendering/Font/Font.cpp index 8d6a342bf..738ac6d3e 100644 --- a/runtime/Rendering/Font/Font.cpp +++ b/runtime/Rendering/Font/Font.cpp @@ -109,20 +109,8 @@ namespace Spartan Vector2 cursor = position; float starting_pos_x = cursor.x; - // allocate ahead of time - { - // calculate the required size for vertices and indices - size_t required_vertices_count = text.length() * 6; // 6 vertices per character - size_t required_indices_count = required_vertices_count; // 1 index per vertex - - // reserve memory for class members - m_vertices.reserve(required_vertices_count); - m_indices.reserve(required_indices_count); - - // clear existing data (reuse preallocated memory) - m_vertices.clear(); - m_indices.clear(); - } + m_vertices.clear(); + m_indices.clear(); // generate vertices - draw each latter onto a quad for (char character : text) @@ -189,41 +177,45 @@ namespace Spartan if (m_font_data.empty()) return; - // combine all vertices/indices into one - vector vertices; - vector indices; - uint32_t vertex_offset = 0; - - for (const FontData& text_data : m_font_data) + // merge all vertices and indices { - vertices.insert(vertices.end(), text_data.vertices.begin(), text_data.vertices.end()); - for (uint32_t index : text_data.indices) + m_vertices.clear(); + m_indices.clear(); + + uint32_t vertex_offset = 0; + for (const FontData& text_data : m_font_data) { - indices.push_back(index + vertex_offset); + m_vertices.insert(m_vertices.end(), text_data.vertices.begin(), text_data.vertices.end()); + for (uint32_t index : text_data.indices) + { + m_indices.push_back(index + vertex_offset); + } + vertex_offset += static_cast(text_data.vertices.size()); } - vertex_offset += static_cast(text_data.vertices.size()); } - + // grow buffers if needed { - if (vertices.size() > m_buffer_vertex->GetElementCount()) + if (m_vertices.size() > m_buffer_vertex->GetElementCount()) { - m_buffer_vertex = make_shared(RHI_Buffer_Type::Vertex, - sizeof(vertices[0]), - static_cast(vertices.size()), - static_cast(&vertices[0]), - true, + m_buffer_vertex = make_shared( + RHI_Buffer_Type::Vertex, // type + sizeof(m_vertices[0]), // stride + static_cast(m_vertices.size()), // element count + static_cast(&m_vertices[0]), // data + true, // mappable "font_vertex" ); } - if (indices.size() > m_buffer_index->GetElementCount()) + if (m_indices.size() > m_buffer_index->GetElementCount()) { - m_buffer_index = make_shared(RHI_Buffer_Type::Index, - sizeof(indices[0]), - static_cast(indices.size()), - static_cast(&indices[0]), - true, + m_buffer_index = make_shared( + RHI_Buffer_Type::Index, // type + sizeof(m_indices[0]), // stride + static_cast(m_indices.size()), // element count + static_cast(&m_indices[0]), // data + true, // mappable "font_index" ); } @@ -231,36 +223,40 @@ namespace Spartan // update vertex buffer in chunks { - const size_t vertex_size = sizeof(vertices[0]); - size_t vertices_size = vertices.size() * vertex_size; + const size_t vertex_size = sizeof(m_vertices[0]); + size_t size = m_vertices.size() * vertex_size; size_t offset = 0; // zero out memset(m_buffer_vertex->GetMappedData(), 0, m_buffer_vertex->GetObjectSize()); // update - while (offset < vertices_size) + while (offset < size) { - size_t current_chunk_size = min(static_cast(rhi_max_buffer_update_size), vertices_size - offset); - cmd_list->UpdateBuffer(m_buffer_vertex.get(), offset, current_chunk_size, &vertices[offset / vertex_size]); + size_t current_chunk_size = min(static_cast(rhi_max_buffer_update_size), size - offset); + + cmd_list->UpdateBuffer(m_buffer_vertex.get(), offset, current_chunk_size, &m_vertices[offset / vertex_size]); + offset += current_chunk_size; } } // update index buffer in chunks { - const size_t index_size = sizeof(indices[0]); + const size_t index_size = sizeof(m_indices[0]); + size_t size = m_indices.size() * index_size; size_t offset = 0; - size_t indices_size = indices.size() * index_size; // zero out memset(m_buffer_index->GetMappedData(), 0, m_buffer_index->GetObjectSize()); // update - while (offset < indices_size) + while (offset < size) { - size_t current_chunk_size = min(static_cast(rhi_max_buffer_update_size), indices_size - offset); - cmd_list->UpdateBuffer(m_buffer_index.get(), offset, current_chunk_size, &indices[offset / index_size]); + size_t current_chunk_size = min(static_cast(rhi_max_buffer_update_size), size - offset); + + cmd_list->UpdateBuffer(m_buffer_index.get(), offset, current_chunk_size, &m_indices[offset / index_size]); + offset += current_chunk_size; } } diff --git a/runtime/Rendering/Renderer.cpp b/runtime/Rendering/Renderer.cpp index f1dcd0a04..31e1065d1 100644 --- a/runtime/Rendering/Renderer.cpp +++ b/runtime/Rendering/Renderer.cpp @@ -139,12 +139,47 @@ namespace Spartan void Renderer::Initialize() { - if (Debugging::IsRenderdocEnabled()) + // device { - RenderDoc::OnPreDeviceCreation(); + if (Debugging::IsRenderdocEnabled()) + { + RenderDoc::OnPreDeviceCreation(); + } + + RHI_Device::Initialize(); } - RHI_Device::Initialize(); + // set options (after the device has been created since it can clamp values like max shadow resolution etc) + m_options.clear(); + SetOption(Renderer_Option::WhitePoint, 350.0f); + SetOption(Renderer_Option::Tonemapping, static_cast(Renderer_Tonemapping::Max)); + SetOption(Renderer_Option::Bloom, 1.0f); // non-zero values activate it and control the intensity + SetOption(Renderer_Option::MotionBlur, 1.0f); + SetOption(Renderer_Option::DepthOfField, 1.0f); + SetOption(Renderer_Option::ScreenSpaceAmbientOcclusion, 1.0f); + SetOption(Renderer_Option::ScreenSpaceShadows, static_cast(Renderer_ScreenspaceShadow::Bend)); + SetOption(Renderer_Option::ScreenSpaceReflections, 1.0f); + SetOption(Renderer_Option::GlobalIllumination, 0.5f); // 0.5 is the percentage of the internal resolution (options are 25%, 50%, 75% and 100%) + SetOption(Renderer_Option::Anisotropy, 16.0f); + SetOption(Renderer_Option::ShadowResolution, 4096.0f); + SetOption(Renderer_Option::Exposure, 1.0f); + SetOption(Renderer_Option::Sharpness, 0.0f); // becomes the upsampler's sharpness as well + SetOption(Renderer_Option::Fog, 1.0f); // controls the intensity of the volumetric fog as well + SetOption(Renderer_Option::FogVolumetric, 1.0f); // these is only a toggle for the volumetric fog + SetOption(Renderer_Option::Antialiasing, static_cast(Renderer_Antialiasing::Taa)); // this is using fsr 3 for taa + SetOption(Renderer_Option::Upsampling, static_cast(Renderer_Upsampling::Fsr3)); + SetOption(Renderer_Option::ResolutionScale, 1.0f); + SetOption(Renderer_Option::VariableRateShading, 0.0f); + SetOption(Renderer_Option::Vsync, 0.0f); + SetOption(Renderer_Option::TransformHandle, 1.0f); + SetOption(Renderer_Option::SelectionOutline, 1.0f); + SetOption(Renderer_Option::Grid, 1.0f); + SetOption(Renderer_Option::Lights, 1.0f); + SetOption(Renderer_Option::Physics, 0.0f); + SetOption(Renderer_Option::PerformanceMetrics, 1.0f); + SetOption(Renderer_Option::OcclusionCulling, 0.0f); // disabled by default as it's a WIP (you can see the query delays) + + // resolution { @@ -166,18 +201,22 @@ namespace Spartan } // swap chain - swap_chain = make_shared - ( - Window::GetHandleSDL(), - Window::GetWidth(), - Window::GetHeight(), - // present mode: for v-sync, we could mailbox for lower latency, but fifo is always supported, so we'll assume that - // note: fifo is not supported on linux, it will be ignored - GetOption(Renderer_Option::Vsync) ? RHI_Present_Mode::Fifo : RHI_Present_Mode::Immediate, - swap_chain_buffer_count, - Display::GetHdr(), - "renderer" - ); + { + swap_chain = make_shared + ( + Window::GetHandleSDL(), + Window::GetWidth(), + Window::GetHeight(), + // present mode: for v-sync, we could mailbox for lower latency, but fifo is always supported, so we'll assume that + // note: fifo is not supported on linux, it will be ignored + GetOption(Renderer_Option::Vsync) ? RHI_Present_Mode::Fifo : RHI_Present_Mode::Immediate, + swap_chain_buffer_count, + Display::GetHdr(), + "renderer" + ); + + SetOption(Renderer_Option::Hdr, swap_chain->IsHdr() ? 1.0f : 0.0f); + } // third party tool initialization ThreadPool::AddTask([]() @@ -223,37 +262,6 @@ namespace Spartan // fire SP_FIRE_EVENT(EventType::RendererOnInitialized); } - - // options - m_options.clear(); - SetOption(Renderer_Option::Hdr, swap_chain->IsHdr() ? 1.0f : 0.0f); - SetOption(Renderer_Option::WhitePoint, 350.0f); - SetOption(Renderer_Option::Tonemapping, static_cast(Renderer_Tonemapping::Max)); - SetOption(Renderer_Option::Bloom, 1.0f); // non-zero values activate it and control the intensity - SetOption(Renderer_Option::MotionBlur, 1.0f); - SetOption(Renderer_Option::DepthOfField, 1.0f); - SetOption(Renderer_Option::ScreenSpaceAmbientOcclusion, 1.0f); - SetOption(Renderer_Option::ScreenSpaceShadows, static_cast(Renderer_ScreenspaceShadow::Bend)); - SetOption(Renderer_Option::ScreenSpaceReflections, 1.0f); - SetOption(Renderer_Option::GlobalIllumination, 0.5f); // 0.5 is the percentage of the internal resolution (options are 25%, 50%, 75% and 100%) - SetOption(Renderer_Option::Anisotropy, 16.0f); - SetOption(Renderer_Option::ShadowResolution, 4096.0f); - SetOption(Renderer_Option::Exposure, 1.0f); - SetOption(Renderer_Option::Sharpness, 0.0f); // becomes the upsampler's sharpness as well - SetOption(Renderer_Option::Fog, 1.0f); // controls the intensity of the volumetric fog as well - SetOption(Renderer_Option::FogVolumetric, 1.0f); // these is only a toggle for the volumetric fog - SetOption(Renderer_Option::Antialiasing, static_cast(Renderer_Antialiasing::Taa)); // this is using fsr 3 for taa - SetOption(Renderer_Option::Upsampling, static_cast(Renderer_Upsampling::Fsr3)); - SetOption(Renderer_Option::ResolutionScale, 1.0f); - SetOption(Renderer_Option::VariableRateShading, 0.0f); - SetOption(Renderer_Option::Vsync, 0.0f); - SetOption(Renderer_Option::TransformHandle, 1.0f); - SetOption(Renderer_Option::SelectionOutline, 1.0f); - SetOption(Renderer_Option::Grid, 1.0f); - SetOption(Renderer_Option::Lights, 1.0f); - SetOption(Renderer_Option::Physics, 0.0f); - SetOption(Renderer_Option::PerformanceMetrics, 1.0f); - SetOption(Renderer_Option::OcclusionCulling, 0.0f); // disabled by default as it's a WIP (you can see the query delays) } void Renderer::Shutdown() diff --git a/runtime/Rendering/Renderer_Passes.cpp b/runtime/Rendering/Renderer_Passes.cpp index 8559d6717..88fe9c6eb 100644 --- a/runtime/Rendering/Renderer_Passes.cpp +++ b/runtime/Rendering/Renderer_Passes.cpp @@ -987,8 +987,6 @@ namespace Spartan break; } - float near = 1.0f; - float far = 0.0f; Math::Matrix view_projection = GetCamera()->GetViewProjectionMatrix(); Vector4 p = {}; if (light->GetLightType() == LightType::Directional) @@ -1016,6 +1014,8 @@ namespace Spartan ); // light index writes into the texture array index + float near = 1.0f; + float far = 0.0f; m_pcb_pass_cpu.set_f3_value(near, far, array_slice_index++); m_pcb_pass_cpu.set_f3_value2(1.0f / tex_sss->GetWidth(), 1.0f / tex_sss->GetHeight(), 0.0f); diff --git a/runtime/World/Components/Light.cpp b/runtime/World/Components/Light.cpp index ad8967b1a..2a251175c 100644 --- a/runtime/World/Components/Light.cpp +++ b/runtime/World/Components/Light.cpp @@ -38,12 +38,12 @@ namespace Spartan { namespace { - float orthographic_extent_near = 12.0f; + float orthographic_extent_near = 16.0f; float orthographic_extent_far = 128.0f; float get_world_depth() { - return World::GetBoundinBox().GetExtents().Abs().Max(); + return World::GetBoundinBox().GetExtents().Abs().Max() * 2.0f; } float get_sensible_range(const LightType type) @@ -439,7 +439,7 @@ namespace Spartan { target = camera->GetEntity()->GetPosition(); } - Vector3 position = target - GetEntity()->GetForward() * get_world_depth() * 3.0f; + Vector3 position = target - GetEntity()->GetForward() * get_world_depth() * 1.5f; m_matrix_view[0] = Matrix::CreateLookAtLH(position, target, Vector3::Up); // near m_matrix_view[1] = m_matrix_view[0]; // far @@ -457,37 +457,32 @@ namespace Spartan void Light::ComputeProjectionMatrix() { - if (!m_texture_depth) - return; - - float near_plane = 0.01f; + const float near_plane = 0.01f; if (m_light_type == LightType::Directional) { for (uint32_t i = 0; i < 2; i++) { - // determine the orthographic extent based on the cascade index - float extent = (i == 0) ? orthographic_extent_near : orthographic_extent_far; - - // orthographic bounds - float left = -extent; - float right = extent; - float bottom = -extent; - float top = extent; - float far_plane = get_world_depth() * 4.0f; - + float extent = (i == 0) ? orthographic_extent_near : orthographic_extent_far; + float left = -extent; + float right = extent; + float bottom = -extent; + float top = extent; + float far_plane = get_world_depth() * 4.0f; m_matrix_projection[i] = Matrix::CreateOrthoOffCenterLH(left, right, bottom, top, far_plane, near_plane); - m_frustums[i] = Frustum(m_matrix_view[i], m_matrix_projection[i], far_plane - near_plane); + m_frustums[i] = Frustum(m_matrix_view[i], m_matrix_projection[i], far_plane - near_plane); } } else if (m_light_type == LightType::Spot) { + if (!m_texture_depth) + return; + const float aspect_ratio = static_cast(m_texture_depth->GetWidth()) / static_cast(m_texture_depth->GetHeight()); const float fov = m_angle_rad * 2.0f; - Matrix projection = Matrix::CreatePerspectiveFieldOfViewLH(fov, aspect_ratio, m_range, near_plane); - - m_matrix_projection[0] = projection; - m_frustums[0] = Frustum(m_matrix_view[0], projection, m_range); + Matrix projection = Matrix::CreatePerspectiveFieldOfViewLH(fov, aspect_ratio, m_range, near_plane); + m_matrix_projection[0] = projection; + m_frustums[0] = Frustum(m_matrix_view[0], projection, m_range); } }