From d27d35818c8bfd7d3647e33822ce3e59cf6b089b Mon Sep 17 00:00:00 2001 From: Kharkunov Eugene Date: Wed, 15 May 2024 16:43:00 +0300 Subject: [PATCH 1/2] Frustrum culling for tilemap. --- .../src/gamesys/components/comp_tilegrid.cpp | 42 +++++++++++++++++-- 1 file changed, 38 insertions(+), 4 deletions(-) diff --git a/engine/gamesys/src/gamesys/components/comp_tilegrid.cpp b/engine/gamesys/src/gamesys/components/comp_tilegrid.cpp index 47ce2212850..926a936b79b 100644 --- a/engine/gamesys/src/gamesys/components/comp_tilegrid.cpp +++ b/engine/gamesys/src/gamesys/components/comp_tilegrid.cpp @@ -29,6 +29,7 @@ #include #include #include +#include #include "../gamesys_private.h" #include "../gamesys.h" @@ -55,9 +56,9 @@ namespace dmGameSystem // where the the box spans TILEGRID_REGION_SIZE tiles in each direction struct TileGridRegion { - uint8_t m_Dirty:1; - uint8_t m_Occupied:1; - uint8_t :6; + uint8_t m_Dirty : 1; + uint8_t m_Occupied : 1; + uint8_t : 6; }; struct TileGridLayer @@ -631,6 +632,39 @@ namespace dmGameSystem return where; } + static void RenderListFrustumCulling(dmRender::RenderListVisibilityParams const ¶ms) + { + DM_PROFILE("TileGridFrustrumCulling"); + TileGridWorld* tilegrid_world = (TileGridWorld*)params.m_UserData; + const dmIntersection::Frustum frustum = *params.m_Frustum; + uint32_t num_entries = params.m_NumEntries; + for (uint32_t i = 0; i < num_entries; ++i) + { + dmRender::RenderListEntry* entry = ¶ms.m_Entries[i]; + uint32_t index, layer, region_x, region_y; + //entry->m_UserData - encoded region info + DecodeGridAndLayer(entry->m_UserData, index, layer, region_x, region_y); + TileGridComponent* component = tilegrid_world->m_Components[index]; + + TileGridResource* resource = component->m_Resource; + TextureSetResource* texture_set = GetTextureSet(component); + int32_t tile_width = (int32_t)texture_set->m_TextureSet->m_TileWidth; + int32_t tile_height = (int32_t)texture_set->m_TextureSet->m_TileHeight; + + int32_t column_count = (int32_t)resource->m_ColumnCount; + int32_t row_count = (int32_t)resource->m_RowCount; + int32_t min_x = resource->m_MinCellX + region_x * TILEGRID_REGION_SIZE; + int32_t min_y = resource->m_MinCellY + region_y * TILEGRID_REGION_SIZE; + int32_t max_x = dmMath::Min(min_x + (int32_t)TILEGRID_REGION_SIZE, resource->m_MinCellX + column_count); + int32_t max_y = dmMath::Min(min_y + (int32_t)TILEGRID_REGION_SIZE, resource->m_MinCellY + row_count); + + dmVMath::Vector3 min_corner = dmVMath::Vector3(min_x * tile_width, min_y * tile_height, 0.f); + dmVMath::Vector3 max_corner = dmVMath::Vector3(max_x * tile_width, max_y * tile_height, 0.f); + bool intersect = dmIntersection::TestFrustumOBB(frustum, component->m_World, min_corner, max_corner); + entry->m_Visibility = intersect ? dmRender::VISIBILITY_FULL : dmRender::VISIBILITY_NONE; + } + } + static void RenderBatch(TileGridWorld* world, dmRender::HRenderContext render_context, dmRender::RenderListEntry *buf, uint32_t* begin, uint32_t* end) { DM_PROFILE("TileGridRenderBatch"); @@ -779,7 +813,7 @@ namespace dmGameSystem dmRender::HRenderContext render_context = context->m_RenderContext; dmRender::RenderListEntry* render_list = dmRender::RenderListAlloc(render_context, num_render_entries); - dmRender::HRenderListDispatch dispatch = dmRender::RenderListMakeDispatch(render_context, &RenderListDispatch, world); + dmRender::HRenderListDispatch dispatch = dmRender::RenderListMakeDispatch(render_context, &RenderListDispatch, &RenderListFrustumCulling, world); dmRender::RenderListEntry* write_ptr = render_list; for (uint32_t i = 0; i < n; ++i) From 652a9c1461eaf7b23d0e8c5a75d8ca12998b0168 Mon Sep 17 00:00:00 2001 From: Kharkunov Eugene Date: Fri, 31 May 2024 13:33:18 +0300 Subject: [PATCH 2/2] Review fixes. --- .../src/gamesys/components/comp_tilegrid.cpp | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/engine/gamesys/src/gamesys/components/comp_tilegrid.cpp b/engine/gamesys/src/gamesys/components/comp_tilegrid.cpp index 926a936b79b..3e9fb400385 100644 --- a/engine/gamesys/src/gamesys/components/comp_tilegrid.cpp +++ b/engine/gamesys/src/gamesys/components/comp_tilegrid.cpp @@ -655,11 +655,16 @@ namespace dmGameSystem int32_t row_count = (int32_t)resource->m_RowCount; int32_t min_x = resource->m_MinCellX + region_x * TILEGRID_REGION_SIZE; int32_t min_y = resource->m_MinCellY + region_y * TILEGRID_REGION_SIZE; - int32_t max_x = dmMath::Min(min_x + (int32_t)TILEGRID_REGION_SIZE, resource->m_MinCellX + column_count); - int32_t max_y = dmMath::Min(min_y + (int32_t)TILEGRID_REGION_SIZE, resource->m_MinCellY + row_count); - dmVMath::Vector3 min_corner = dmVMath::Vector3(min_x * tile_width, min_y * tile_height, 0.f); - dmVMath::Vector3 max_corner = dmVMath::Vector3(max_x * tile_width, max_y * tile_height, 0.f); + int32_t region_max_x = min_x + TILEGRID_REGION_SIZE; + int32_t tilemap_max_x = resource->m_MinCellX + column_count; + int32_t region_max_y = min_y + TILEGRID_REGION_SIZE; + int32_t tilemap_max_y = resource->m_MinCellY + row_count; + int32_t max_x = dmMath::Min(region_max_x, tilemap_max_x); + int32_t max_y = dmMath::Min(region_max_y, tilemap_max_y); + + dmVMath::Vector3 min_corner = dmVMath::Vector3((float)(min_x * tile_width), (float)(min_y * tile_height), 0.f); + dmVMath::Vector3 max_corner = dmVMath::Vector3((float)(max_x * tile_width), (float)(max_y * tile_height), 0.f); bool intersect = dmIntersection::TestFrustumOBB(frustum, component->m_World, min_corner, max_corner); entry->m_Visibility = intersect ? dmRender::VISIBILITY_FULL : dmRender::VISIBILITY_NONE; }