1
1

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.
This commit is contained in:
2022-04-14 03:38:45 +02:00
parent 927cb5bfac
commit 3e25561d51
2 changed files with 68 additions and 0 deletions

View File

@@ -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);

View File

@@ -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;