From 3e25561d5184ad3d52cdaf6e16926cf85c2fa705 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?K=C3=A9vin=20Dietrich?= Date: Thu, 14 Apr 2022 03:38:45 +0200 Subject: Fix part of T96596: wrong generated coordinates with GPU subdivision Problem is that the orco layer was not taken care of by the GPU subdivision routines. This only handles the issues for EEVEE/Workbench. For Cycles, this would need to be handled at the wrapper level somehow. --- .../blender/draw/intern/draw_cache_extract_mesh.cc | 1 + .../mesh_extractors/extract_mesh_vbo_orco.cc | 67 ++++++++++++++++++++++ 2 files changed, 68 insertions(+) (limited to 'source/blender/draw/intern') diff --git a/source/blender/draw/intern/draw_cache_extract_mesh.cc b/source/blender/draw/intern/draw_cache_extract_mesh.cc index 717ea00fc0c..8a7b4fc9703 100644 --- a/source/blender/draw/intern/draw_cache_extract_mesh.cc +++ b/source/blender/draw/intern/draw_cache_extract_mesh.cc @@ -844,6 +844,7 @@ static void mesh_buffer_cache_create_requested_subdiv(MeshBatchCache *cache, EXTRACT_ADD_REQUESTED(vbo, edituv_stretch_angle); EXTRACT_ADD_REQUESTED(ibo, lines_paint_mask); EXTRACT_ADD_REQUESTED(ibo, lines_adjacency); + EXTRACT_ADD_REQUESTED(vbo, orco); EXTRACT_ADD_REQUESTED(vbo, vcol); EXTRACT_ADD_REQUESTED(vbo, weights); EXTRACT_ADD_REQUESTED(vbo, sculpt_data); diff --git a/source/blender/draw/intern/mesh_extractors/extract_mesh_vbo_orco.cc b/source/blender/draw/intern/mesh_extractors/extract_mesh_vbo_orco.cc index d4c801ab066..ed1a0ccd178 100644 --- a/source/blender/draw/intern/mesh_extractors/extract_mesh_vbo_orco.cc +++ b/source/blender/draw/intern/mesh_extractors/extract_mesh_vbo_orco.cc @@ -7,6 +7,8 @@ #include "extract_mesh.h" +#include "draw_subdivision.h" + namespace blender::draw { /* ---------------------------------------------------------------------- */ @@ -77,12 +79,77 @@ static void extract_orco_iter_poly_mesh(const MeshRenderData *mr, } } +static void extract_orco_init_subdiv(const DRWSubdivCache *subdiv_cache, + const MeshRenderData *mr, + struct MeshBatchCache *UNUSED(cache), + void *buffer, + void *UNUSED(data)) +{ + static GPUVertFormat format = {0}; + if (format.attr_len == 0) { + /* FIXME(fclem): We use the last component as a way to differentiate from generic vertex + * attributes. This is a substantial waste of video-ram and should be done another way. + * Unfortunately, at the time of writing, I did not found any other "non disruptive" + * alternative. */ + GPU_vertformat_attr_add(&format, "orco", GPU_COMP_F32, 4, GPU_FETCH_FLOAT); + } + + GPUVertBuf *dst_buffer = static_cast(buffer); + GPU_vertbuf_init_build_on_device(dst_buffer, &format, subdiv_cache->num_subdiv_loops); + + GPUVertBuf *coarse_vbo = GPU_vertbuf_calloc(); + /* Dynamic as we upload and interpolate layers one at a time. */ + GPU_vertbuf_init_with_format_ex(coarse_vbo, &format, GPU_USAGE_DYNAMIC); + GPU_vertbuf_data_alloc(coarse_vbo, mr->loop_len); + + float(*coarse_vbo_data)[4] = static_cast(GPU_vertbuf_get_data(coarse_vbo)); + + CustomData *cd_vdata = &mr->me->vdata; + float(*orco)[3] = static_cast(CustomData_get_layer(cd_vdata, CD_ORCO)); + + if (mr->extract_type == MR_EXTRACT_MESH) { + const MLoop *mloop = mr->mloop; + const MPoly *mp = mr->mpoly; + + int ml_index = 0; + for (int i = 0; i < mr->poly_len; i++, mp++) { + const MLoop *ml = &mloop[mp->loopstart]; + + for (int j = 0; j < mp->totloop; j++, ml++, ml_index++) { + float *loop_orco = coarse_vbo_data[ml_index]; + copy_v3_v3(loop_orco, orco[ml->v]); + loop_orco[3] = 0.0; /* Tag as not a generic attribute. */ + } + } + } + else { + BMIter iter; + BMFace *f; + BM_ITER_MESH (f, &iter, mr->bm, BM_FACES_OF_MESH) { + BMLoop *l_iter; + BMLoop *l_first; + l_iter = l_first = BM_FACE_FIRST_LOOP(f); + do { + const int l_index = BM_elem_index_get(l_iter); + float *loop_orco = coarse_vbo_data[l_index]; + copy_v3_v3(loop_orco, orco[BM_elem_index_get(l_iter->v)]); + loop_orco[3] = 0.0; /* Tag as not a generic attribute. */ + } while ((l_iter = l_iter->next) != l_first); + } + } + + draw_subdiv_interp_custom_data(subdiv_cache, coarse_vbo, dst_buffer, 4, 0, false); + + GPU_vertbuf_discard(coarse_vbo); +} + constexpr MeshExtract create_extractor_orco() { MeshExtract extractor = {nullptr}; extractor.init = extract_orco_init; extractor.iter_poly_bm = extract_orco_iter_poly_bm; extractor.iter_poly_mesh = extract_orco_iter_poly_mesh; + extractor.init_subdiv = extract_orco_init_subdiv; extractor.data_type = MR_DATA_NONE; extractor.data_size = sizeof(MeshExtract_Orco_Data); extractor.use_threading = true; -- cgit v1.2.3