diff options
-rw-r--r-- | source/blender/draw/intern/draw_cache_impl_mesh.c | 68 | ||||
-rw-r--r-- | source/blender/gpu/GPU_batch.h | 2 | ||||
-rw-r--r-- | source/blender/gpu/intern/gpu_codegen.c | 8 |
3 files changed, 68 insertions, 10 deletions
diff --git a/source/blender/draw/intern/draw_cache_impl_mesh.c b/source/blender/draw/intern/draw_cache_impl_mesh.c index a50951c98d8..bc5c4f8aeb0 100644 --- a/source/blender/draw/intern/draw_cache_impl_mesh.c +++ b/source/blender/draw/intern/draw_cache_impl_mesh.c @@ -1822,6 +1822,7 @@ typedef struct MeshBatchCache { GPUVertBuf *loop_uv_tan; GPUVertBuf *loop_vcol; GPUVertBuf *loop_edge_fac; + GPUVertBuf *loop_orco; } ordered; /* Edit Mesh Data: @@ -2033,8 +2034,7 @@ static void mesh_batch_cache_discard_shaded_tri(MeshBatchCache *cache) GPU_VERTBUF_DISCARD_SAFE(cache->ordered.loop_pos_nor); GPU_VERTBUF_DISCARD_SAFE(cache->ordered.loop_uv_tan); GPU_VERTBUF_DISCARD_SAFE(cache->ordered.loop_vcol); - /* TODO */ - // GPU_VERTBUF_DISCARD_SAFE(cache->ordered.loop_orco); + GPU_VERTBUF_DISCARD_SAFE(cache->ordered.loop_orco); if (cache->surf_per_mat_tris) { for (int i = 0; i < cache->mat_len; i++) { @@ -2966,6 +2966,46 @@ static void mesh_create_loop_pos_and_nor(MeshRenderData *rdata, GPUVertBuf *vbo) } } +static void mesh_create_loop_orco(MeshRenderData *rdata, GPUVertBuf *vbo) +{ + const uint loops_len = mesh_render_data_loops_len_get(rdata); + + /* initialize vertex format */ + GPUVertFormat format = { 0 }; + GPUVertBufRaw vbo_step; + + /* FIXME(fclem): We use the last component as a way to differentiate from generic vertex attribs. + * This is a substential waste of Vram and should be done another way. Unfortunately, + * at the time of writting, I did not found any other "non disruptive" alternative. */ + uint attr_id = GPU_vertformat_attr_add(&format, "orco", GPU_COMP_F32, 4, GPU_FETCH_FLOAT); + + GPU_vertbuf_init_with_format(vbo, &format); + GPU_vertbuf_data_alloc(vbo, loops_len); + GPU_vertbuf_attr_get_raw_data(vbo, attr_id, &vbo_step); + + if (rdata->edit_bmesh) { + BMesh *bm = rdata->edit_bmesh->bm; + BMIter iter_efa, iter_loop; + BMFace *efa; + BMLoop *loop; + + BM_ITER_MESH (efa, &iter_efa, bm, BM_FACES_OF_MESH) { + BM_ITER_ELEM (loop, &iter_loop, efa, BM_LOOPS_OF_FACE) { + float *data = (float *)GPU_vertbuf_raw_step(&vbo_step); + copy_v3_v3(data, rdata->orco[BM_elem_index_get(loop->v)]); + data[3] = 0.0; /* Tag as not a generic attrib */ + } + } + } + else { + for (uint l = 0; l < loops_len; l++) { + float *data = (float *)GPU_vertbuf_raw_step(&vbo_step); + copy_v3_v3(data, rdata->orco[rdata->mloop[l].v]); + data[3] = 0.0; /* Tag as not a generic attrib */ + } + } +} + static void mesh_create_loop_uv_and_tan(MeshRenderData *rdata, GPUVertBuf *vbo) { const uint loops_len = mesh_render_data_loops_len_get(rdata); @@ -4593,8 +4633,7 @@ void DRW_mesh_batch_cache_create_requested( GPU_VERTBUF_DISCARD_SAFE(cache->ordered.loop_vcol); break; case CD_ORCO: - /* TODO */ - // GPU_VERTBUF_DISCARD_SAFE(cache->ordered.loop_orco); + GPU_VERTBUF_DISCARD_SAFE(cache->ordered.loop_orco); break; } } @@ -4784,10 +4823,19 @@ void DRW_mesh_batch_cache_create_requested( if (cache->cd_lused[CD_MLOOPCOL] != 0) { DRW_vbo_request(cache->surf_per_mat[i], &cache->ordered.loop_vcol); } - /* TODO */ - // if (cache->cd_vused[CD_ORCO] != 0) { - // DRW_vbo_request(cache->surf_per_mat[i], &cache->ordered.loop_orco); - // } + if (cache->cd_vused[CD_ORCO] != 0) { + /* OPTI : Only do that if there is modifiers that modify orcos. */ + CustomData *cd_vdata = (me->edit_mesh) ? &me->edit_mesh->bm->vdata : &me->vdata; + if (CustomData_get_layer(cd_vdata, CD_ORCO) != NULL && + ob->modifiers.first != NULL) + { + DRW_vbo_request(cache->surf_per_mat[i], &cache->ordered.loop_orco); + } + else if ((cache->cd_lused[CD_TANGENT] & DM_TANGENT_MASK_ORCO) == 0) { + /* Skip orco calculation if not needed by tangent generation. */ + cache->cd_vused[CD_ORCO] = 0; + } + } } } @@ -4797,6 +4845,7 @@ void DRW_mesh_batch_cache_create_requested( DRW_ADD_FLAG_FROM_VBO_REQUEST(mr_flag, cache->ordered.weights, MR_DATATYPE_VERT | MR_DATATYPE_DVERT); DRW_ADD_FLAG_FROM_VBO_REQUEST(mr_flag, cache->ordered.loop_pos_nor, MR_DATATYPE_VERT | MR_DATATYPE_POLY | MR_DATATYPE_LOOP); DRW_ADD_FLAG_FROM_VBO_REQUEST(mr_flag, cache->ordered.loop_uv_tan, MR_DATATYPE_VERT | MR_DATATYPE_POLY | MR_DATATYPE_LOOP | MR_DATATYPE_SHADING); + DRW_ADD_FLAG_FROM_VBO_REQUEST(mr_flag, cache->ordered.loop_orco, MR_DATATYPE_VERT | MR_DATATYPE_POLY | MR_DATATYPE_LOOP | MR_DATATYPE_SHADING); DRW_ADD_FLAG_FROM_VBO_REQUEST(mr_flag, cache->ordered.loop_vcol, MR_DATATYPE_VERT | MR_DATATYPE_POLY | MR_DATATYPE_LOOP | MR_DATATYPE_SHADING); DRW_ADD_FLAG_FROM_VBO_REQUEST(mr_flag, cache->ordered.loop_edge_fac, MR_DATATYPE_VERT | MR_DATATYPE_POLY | MR_DATATYPE_EDGE | MR_DATATYPE_LOOP); DRW_ADD_FLAG_FROM_IBO_REQUEST(mr_flag, cache->ibo.surf_tris, MR_DATATYPE_VERT | MR_DATATYPE_LOOP | MR_DATATYPE_POLY | MR_DATATYPE_LOOPTRI); @@ -4863,6 +4912,9 @@ void DRW_mesh_batch_cache_create_requested( if (DRW_vbo_requested(cache->ordered.loop_uv_tan)) { mesh_create_loop_uv_and_tan(rdata, cache->ordered.loop_uv_tan); } + if (DRW_vbo_requested(cache->ordered.loop_orco)) { + mesh_create_loop_orco(rdata, cache->ordered.loop_orco); + } if (DRW_vbo_requested(cache->ordered.loop_vcol)) { mesh_create_loop_vcol(rdata, cache->ordered.loop_vcol); } diff --git a/source/blender/gpu/GPU_batch.h b/source/blender/gpu/GPU_batch.h index 95eb59a57ae..3d013eb8af4 100644 --- a/source/blender/gpu/GPU_batch.h +++ b/source/blender/gpu/GPU_batch.h @@ -39,7 +39,7 @@ typedef enum { GPU_BATCH_READY_TO_DRAW } GPUBatchPhase; -#define GPU_BATCH_VBO_MAX_LEN 3 +#define GPU_BATCH_VBO_MAX_LEN 4 #define GPU_BATCH_VAO_STATIC_LEN 3 #define GPU_BATCH_VAO_DYN_ALLOC_COUNT 16 diff --git a/source/blender/gpu/intern/gpu_codegen.c b/source/blender/gpu/intern/gpu_codegen.c index cf770599fc7..b1d94d22f35 100644 --- a/source/blender/gpu/intern/gpu_codegen.c +++ b/source/blender/gpu/intern/gpu_codegen.c @@ -872,8 +872,9 @@ static char *code_generate_vertex(ListBase *nodes, const char *vert_code, bool u /* XXX FIXME : see notes in mesh_render_data_create() */ /* NOTE : Replicate changes to mesh_render_data_create() in draw_cache_impl_mesh.c */ if (input->attr_type == CD_ORCO) { - /* orco is computed from local positions, see below */ + /* OPTI : orco is computed from local positions, but only if no modifier is present. */ BLI_dynstr_append(ds, "uniform vec3 OrcoTexCoFactors[2];\n"); + BLI_dynstr_append(ds, "DEFINE_ATTR(vec4, orco);\n"); } else if (input->attr_name[0] == '\0') { BLI_dynstr_appendf(ds, "DEFINE_ATTR(%s, %s);\n", GPU_DATATYPE_STR[input->type], attr_prefix_get(input->attr_type)); @@ -976,6 +977,7 @@ static char *code_generate_vertex(ListBase *nodes, const char *vert_code, bool u BLI_dynstr_appendf( ds, "\tvar%d%s = OrcoTexCoFactors[0] + (ModelMatrixInverse * vec4(hair_get_strand_pos(), 1.0)).xyz * OrcoTexCoFactors[1];\n", input->attr_id, use_geom ? "g" : ""); + /* TODO: fix ORCO with modifiers. */ } else { BLI_dynstr_appendf( @@ -1018,6 +1020,10 @@ static char *code_generate_vertex(ListBase *nodes, const char *vert_code, bool u BLI_dynstr_appendf( ds, "\tvar%d%s = OrcoTexCoFactors[0] + position * OrcoTexCoFactors[1];\n", input->attr_id, use_geom ? "g" : ""); + /* See mesh_create_loop_orco() for explanation. */ + BLI_dynstr_appendf( + ds, "\tif (orco.w == 0.0) { var%d%s = orco.xyz * 0.5 + 0.5; }\n", + input->attr_id, use_geom ? "g" : ""); } else if (input->attr_type == CD_MCOL) { BLI_dynstr_appendf( |