diff options
author | Kévin Dietrich <kevin.dietrich@mailoo.org> | 2022-05-31 17:18:08 +0300 |
---|---|---|
committer | Kévin Dietrich <kevin.dietrich@mailoo.org> | 2022-05-31 17:18:08 +0300 |
commit | a5dcae0c641604c033f852e41841f58460c40069 (patch) | |
tree | 5eab47cb9136ce8468b0393e349803dc3d3e8694 | |
parent | 765c16bbd08b06c2b17454bac695f51276f01e41 (diff) |
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.
-rw-r--r-- | source/blender/draw/intern/draw_cache_impl_subdivision.cc | 19 |
1 files changed, 19 insertions, 0 deletions
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<int> 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); |