diff options
author | Kévin Dietrich <kevin.dietrich@mailoo.org> | 2022-04-14 04:38:45 +0300 |
---|---|---|
committer | Kévin Dietrich <kevin.dietrich@mailoo.org> | 2022-04-14 04:39:28 +0300 |
commit | 3e25561d5184ad3d52cdaf6e16926cf85c2fa705 (patch) | |
tree | 37e1ae1688d1b167ea82e7c94f3d31bd53e3427f /source/blender/draw/intern/mesh_extractors | |
parent | 927cb5bfacadd4ce23643a37b6429487d11ec4a9 (diff) |
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.
Diffstat (limited to 'source/blender/draw/intern/mesh_extractors')
-rw-r--r-- | source/blender/draw/intern/mesh_extractors/extract_mesh_vbo_orco.cc | 67 |
1 files changed, 67 insertions, 0 deletions
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<GPUVertBuf *>(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<float(*)[4]>(GPU_vertbuf_get_data(coarse_vbo)); + + CustomData *cd_vdata = &mr->me->vdata; + float(*orco)[3] = static_cast<float(*)[3]>(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; |