From a5dcae0c641604c033f852e41841f58460c40069 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?K=C3=A9vin=20Dietrich?= Date: Tue, 31 May 2022 16:18:08 +0200 Subject: Fix T97877: broken shadows with GPU subdivision Issues stems from the mesh not being watertight. This was caused by floating point precision issues when evaluating patch coordinates at patch boundaries (loops/corners in different patches pointing to the same vertex). To fix this we ensure that all loops pointing to the same vertex share the same patch coordinate. This keeps code simple, and does not require to track precision issues in floating point math all over the place. --- .../draw/intern/draw_cache_impl_subdivision.cc | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/source/blender/draw/intern/draw_cache_impl_subdivision.cc b/source/blender/draw/intern/draw_cache_impl_subdivision.cc index 3a5593fa2a5..9241ef67a55 100644 --- a/source/blender/draw/intern/draw_cache_impl_subdivision.cc +++ b/source/blender/draw/intern/draw_cache_impl_subdivision.cc @@ -1095,6 +1095,25 @@ static bool draw_subdiv_build_cache(DRWSubdivCache *cache, cache->resolution = to_mesh_settings.resolution; cache->num_coarse_poly = mesh_eval->totpoly; + /* To avoid floating point precision issues when evaluating patches at patch boundaries, + * ensure that all loops sharing a vertex use the same patch coordinate. This could cause + * the mesh to not be watertight, leading to shadowing artifacts (see T97877). */ + blender::Vector first_loop_index(cache->num_subdiv_verts, -1); + + for (int i = 0; i < cache->num_subdiv_loops; i++) { + const int vertex = cache_building_context.subdiv_loop_subdiv_vert_index[i]; + if (first_loop_index[vertex] != -1) { + continue; + } + first_loop_index[vertex] = i; + } + + for (int i = 0; i < cache->num_subdiv_loops; i++) { + const int vertex = cache_building_context.subdiv_loop_subdiv_vert_index[i]; + cache_building_context.patch_coords[i] = + cache_building_context.patch_coords[first_loop_index[vertex]]; + } + /* Cleanup. */ MEM_SAFE_FREE(cache_building_context.vert_origindex_map); MEM_SAFE_FREE(cache_building_context.edge_origindex_map); -- cgit v1.2.3