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:
@@ -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);
|
||||
|
@@ -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;
|
||||
|
Reference in New Issue
Block a user