Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--source/blender/draw/engines/eevee/eevee_materials.c11
-rw-r--r--source/blender/draw/intern/draw_cache.c10
-rw-r--r--source/blender/draw/intern/draw_cache.h7
-rw-r--r--source/blender/draw/intern/draw_cache_impl.h4
-rw-r--r--source/blender/draw/intern/draw_cache_impl_mesh.c380
5 files changed, 290 insertions, 122 deletions
diff --git a/source/blender/draw/engines/eevee/eevee_materials.c b/source/blender/draw/engines/eevee/eevee_materials.c
index c23918d5c2d..5393c8d305e 100644
--- a/source/blender/draw/engines/eevee/eevee_materials.c
+++ b/source/blender/draw/engines/eevee/eevee_materials.c
@@ -576,6 +576,7 @@ void EEVEE_materials_cache_populate(EEVEE_Data *vedata, EEVEE_SceneLayerData *sl
if (ELEM(ob->type, OB_MESH)) {
const int materials_len = MAX2(1, (is_sculpt_mode ? 1 : ob->totcol));
struct DRWShadingGroup **shgrp_array = BLI_array_alloca(shgrp_array, materials_len);
+ struct GPUMaterial **gpumat_array = BLI_array_alloca(gpumat_array, materials_len);
bool use_flat_nor = false;
@@ -602,9 +603,15 @@ void EEVEE_materials_cache_populate(EEVEE_Data *vedata, EEVEE_SceneLayerData *sl
shgrp = BLI_ghash_lookup(material_hash, (const void *)ma);
if (shgrp) {
shgrp_array[i] = shgrp; /* ADD_SHGROUP_CALL below */
+ /* This will have been created already, just perform a lookup. */
+ gpumat_array[i] = (use_gpumat) ? EEVEE_material_mesh_get(
+ draw_ctx->scene, ma,stl->effects->use_ao, stl->effects->use_bent_normals) : NULL;
continue;
}
+ /* May not be set below. */
+ gpumat_array[i] = NULL;
+
if (use_gpumat) {
Scene *scene = draw_ctx->scene;
struct GPUMaterial *gpumat = EEVEE_material_mesh_get(scene, ma,
@@ -616,6 +623,8 @@ void EEVEE_materials_cache_populate(EEVEE_Data *vedata, EEVEE_SceneLayerData *sl
BLI_ghash_insert(material_hash, ma, shgrp);
shgrp_array[i] = shgrp; /* ADD_SHGROUP_CALL below */
+
+ gpumat_array[i] = gpumat;
}
else {
/* Shader failed : pink color */
@@ -643,7 +652,7 @@ void EEVEE_materials_cache_populate(EEVEE_Data *vedata, EEVEE_SceneLayerData *sl
}
/* Get per-material split surface */
- struct Gwn_Batch **mat_geom = DRW_cache_object_surface_material_get(ob);
+ struct Gwn_Batch **mat_geom = DRW_cache_object_surface_material_get(ob, gpumat_array, materials_len);
if (mat_geom) {
for (int i = 0; i < materials_len; ++i) {
ADD_SHGROUP_CALL(shgrp_array[i], ob, mat_geom[i]);
diff --git a/source/blender/draw/intern/draw_cache.c b/source/blender/draw/intern/draw_cache.c
index 7636bce9aca..b62559fdb0e 100644
--- a/source/blender/draw/intern/draw_cache.c
+++ b/source/blender/draw/intern/draw_cache.c
@@ -522,11 +522,12 @@ Gwn_Batch *DRW_cache_object_surface_get(Object *ob)
}
}
-Gwn_Batch **DRW_cache_object_surface_material_get(struct Object *ob)
+Gwn_Batch **DRW_cache_object_surface_material_get(
+ struct Object *ob, struct GPUMaterial **gpumat_array, uint gpumat_array_len)
{
switch (ob->type) {
case OB_MESH:
- return DRW_cache_mesh_surface_shaded_get(ob);
+ return DRW_cache_mesh_surface_shaded_get(ob, gpumat_array, gpumat_array_len);
default:
return NULL;
}
@@ -2212,12 +2213,13 @@ Gwn_Batch *DRW_cache_mesh_surface_vert_colors_get(Object *ob)
}
/* Return list of batches */
-Gwn_Batch **DRW_cache_mesh_surface_shaded_get(Object *ob)
+Gwn_Batch **DRW_cache_mesh_surface_shaded_get(
+ Object *ob, struct GPUMaterial **gpumat_array, uint gpumat_array_len)
{
BLI_assert(ob->type == OB_MESH);
Mesh *me = ob->data;
- return DRW_mesh_batch_cache_get_surface_shaded(me);
+ return DRW_mesh_batch_cache_get_surface_shaded(me, gpumat_array, gpumat_array_len);
}
/* Return list of batches */
diff --git a/source/blender/draw/intern/draw_cache.h b/source/blender/draw/intern/draw_cache.h
index 0bb291caa9c..21fa652778b 100644
--- a/source/blender/draw/intern/draw_cache.h
+++ b/source/blender/draw/intern/draw_cache.h
@@ -27,6 +27,7 @@
#define __DRAW_CACHE_H__
struct Gwn_Batch;
+struct GPUMaterial;
struct Object;
struct ModifierData;
@@ -43,7 +44,8 @@ struct Gwn_Batch *DRW_cache_screenspace_circle_get(void);
/* Common Object */
struct Gwn_Batch *DRW_cache_object_wire_outline_get(struct Object *ob);
struct Gwn_Batch *DRW_cache_object_surface_get(struct Object *ob);
-struct Gwn_Batch **DRW_cache_object_surface_material_get(struct Object *ob);
+struct Gwn_Batch **DRW_cache_object_surface_material_get(
+ struct Object *ob, struct GPUMaterial **gpumat_array, uint gpumat_array_len);
/* Empties */
struct Gwn_Batch *DRW_cache_plain_axes_get(void);
@@ -118,7 +120,8 @@ struct Gwn_Batch *DRW_cache_mesh_verts_get(struct Object *ob);
struct Gwn_Batch *DRW_cache_mesh_edges_paint_overlay_get(struct Object *ob, bool use_wire, bool use_sel);
struct Gwn_Batch *DRW_cache_mesh_faces_weight_overlay_get(struct Object *ob);
struct Gwn_Batch *DRW_cache_mesh_verts_weight_overlay_get(struct Object *ob);
-struct Gwn_Batch **DRW_cache_mesh_surface_shaded_get(struct Object *ob);
+struct Gwn_Batch **DRW_cache_mesh_surface_shaded_get(
+ struct Object *ob, struct GPUMaterial **gpumat_array, uint gpumat_array_len);
struct Gwn_Batch **DRW_cache_mesh_surface_texpaint_get(struct Object *ob);
struct Gwn_Batch *DRW_cache_mesh_surface_texpaint_single_get(struct Object *ob);
diff --git a/source/blender/draw/intern/draw_cache_impl.h b/source/blender/draw/intern/draw_cache_impl.h
index f02f73d1f9d..9328f6f6314 100644
--- a/source/blender/draw/intern/draw_cache_impl.h
+++ b/source/blender/draw/intern/draw_cache_impl.h
@@ -27,6 +27,7 @@
#define __DRAW_CACHE_IMPL_H__
struct Gwn_Batch;
+struct GPUMaterial;
struct ListBase;
struct CurveCache;
struct ParticleSystem;
@@ -72,7 +73,8 @@ struct Gwn_Batch *DRW_lattice_batch_cache_get_overlay_verts(struct Lattice *lt);
/* Mesh */
-struct Gwn_Batch **DRW_mesh_batch_cache_get_surface_shaded(struct Mesh *me);
+struct Gwn_Batch **DRW_mesh_batch_cache_get_surface_shaded(
+ struct Mesh *me, struct GPUMaterial **gpumat_array, uint gpumat_array_len);
struct Gwn_Batch **DRW_mesh_batch_cache_get_surface_texpaint(struct Mesh *me);
struct Gwn_Batch *DRW_mesh_batch_cache_get_surface_texpaint_single(struct Mesh *me);
struct Gwn_Batch *DRW_mesh_batch_cache_get_weight_overlay_edges(struct Mesh *me, bool use_wire, bool use_sel);
diff --git a/source/blender/draw/intern/draw_cache_impl_mesh.c b/source/blender/draw/intern/draw_cache_impl_mesh.c
index a008af73549..c65799521b2 100644
--- a/source/blender/draw/intern/draw_cache_impl_mesh.c
+++ b/source/blender/draw/intern/draw_cache_impl_mesh.c
@@ -33,6 +33,7 @@
#include "BLI_utildefines.h"
#include "BLI_math_vector.h"
+#include "BLI_math_bits.h"
#include "BLI_string.h"
#include "DNA_mesh_types.h"
@@ -52,6 +53,7 @@
#include "GPU_batch.h"
#include "GPU_draw.h"
+#include "GPU_material.h"
#include "draw_cache_impl.h" /* own include */
@@ -236,7 +238,72 @@ static bool bm_edge_has_visible_face(const BMEdge *e)
}
-static MeshRenderData *mesh_render_data_create(Mesh *me, const int types)
+static void mesh_cd_calc_used_gpu_layers(
+ CustomData *UNUSED(cd_vdata), uchar cd_vused[CD_NUMTYPES],
+ CustomData *cd_ldata, uchar cd_lused[CD_NUMTYPES],
+ struct GPUMaterial **gpumat_array, int gpumat_array_len)
+{
+ GPUVertexAttribs gattribs = {0};
+
+ for (int i = 0; i < gpumat_array_len; i++) {
+ GPUMaterial *gpumat = gpumat_array[i];
+ if (gpumat) {
+ GPU_material_vertex_attributes(gpumat, &gattribs);
+ for (int j = 0; j < gattribs.totlayer; j++) {
+ const char *name = gattribs.layer[j].name;
+ switch (gattribs.layer[j].type) {
+ case CD_MTFACE:
+ {
+ int index = (name[0] != '\0') ?
+ CustomData_get_named_layer(cd_ldata, CD_MLOOPUV, name) :
+ CustomData_get_active_layer(cd_ldata, CD_MLOOPUV);
+ if (index != -1) {
+ cd_lused[CD_MLOOPUV] |= (1 << index);
+ }
+ break;
+ }
+ case CD_TANGENT:
+ {
+ int index = (name[0] != '\0') ?
+ CustomData_get_named_layer(cd_ldata, CD_MLOOPUV, name) :
+ CustomData_get_active_layer(cd_ldata, CD_MLOOPUV);
+ if (index != -1) {
+ cd_lused[CD_TANGENT] |= (1 << index);
+
+ /* TODO(campbell): investigate why this is needed T51919. */
+ cd_lused[CD_MLOOPUV] |= (1 << index);
+ }
+ break;
+ }
+ case CD_MCOL:
+ {
+ int index = (name[0] != '\0') ?
+ CustomData_get_named_layer(cd_ldata, CD_MLOOPCOL, name) :
+ CustomData_get_active_layer(cd_ldata, CD_MLOOPCOL);
+ if (index != -1) {
+ cd_lused[CD_MLOOPCOL] |= (1 << index);
+ }
+ break;
+ }
+ case CD_ORCO:
+ {
+ cd_vused[CD_ORCO] |= 1;
+ break;
+ }
+ }
+ }
+ }
+ }
+}
+
+/**
+ * TODO(campbell): 'gpumat_array' may include materials linked to the object.
+ * While not default, object materials should be supported.
+ * Although this only impacts the data thats generated, not the materials that display.
+ */
+static MeshRenderData *mesh_render_data_create_ex(
+ Mesh *me, const int types,
+ struct GPUMaterial **gpumat_array, uint gpumat_array_len)
{
MeshRenderData *rdata = MEM_callocN(sizeof(*rdata), __func__);
rdata->types = types;
@@ -371,33 +438,57 @@ static MeshRenderData *mesh_render_data_create(Mesh *me, const int types)
cd_ldata = &me->ldata;
}
+ /* Add edge/poly if we need them */
+ uchar cd_vused[CD_NUMTYPES] = {0};
+ uchar cd_lused[CD_NUMTYPES] = {0};
+
+ mesh_cd_calc_used_gpu_layers(
+ cd_vdata, cd_vused,
+ cd_ldata, cd_lused,
+ gpumat_array, gpumat_array_len);
+
rdata->cd.layers.uv_active = CustomData_get_active_layer(cd_ldata, CD_MLOOPUV);
rdata->cd.layers.vcol_active = CustomData_get_active_layer(cd_ldata, CD_MLOOPCOL);
rdata->cd.layers.tangent_active = rdata->cd.layers.uv_active;
- rdata->orco = CustomData_get_layer(cd_vdata, CD_ORCO);
- /* If orco is not available compute it ourselves */
- if (!rdata->orco) {
- if (me->edit_btmesh) {
- BMesh *bm = me->edit_btmesh->bm;
- rdata->orco = MEM_mallocN(sizeof(*rdata->orco) * rdata->vert_len, "orco mesh");
- BLI_assert((bm->elem_table_dirty & BM_VERT) == 0);
- BMVert **vtable = bm->vtable;
- for (int i = 0; i < bm->totvert; i++) {
- copy_v3_v3(rdata->orco[i], vtable[i]->co);
+ if ((cd_lused[CD_MLOOPUV] & (1 << rdata->cd.layers.uv_active)) == 0) {
+ rdata->cd.layers.uv_active = -1;
+ }
+ if ((cd_lused[CD_TANGENT] & (1 << rdata->cd.layers.tangent_active)) == 0) {
+ rdata->cd.layers.tangent_active = -1;
+ }
+ if ((cd_lused[CD_MLOOPCOL] & (1 << rdata->cd.layers.vcol_active)) == 0) {
+ rdata->cd.layers.vcol_active = -1;
+ }
+
+ if (cd_vused[CD_ORCO] & 1) {
+ rdata->orco = CustomData_get_layer(cd_vdata, CD_ORCO);
+ /* If orco is not available compute it ourselves */
+ if (!rdata->orco) {
+ if (me->edit_btmesh) {
+ BMesh *bm = me->edit_btmesh->bm;
+ rdata->orco = MEM_mallocN(sizeof(*rdata->orco) * rdata->vert_len, "orco mesh");
+ BLI_assert((bm->elem_table_dirty & BM_VERT) == 0);
+ BMVert **vtable = bm->vtable;
+ for (int i = 0; i < bm->totvert; i++) {
+ copy_v3_v3(rdata->orco[i], vtable[i]->co);
+ }
+ BKE_mesh_orco_verts_transform(me, rdata->orco, rdata->vert_len, 0);
}
- BKE_mesh_orco_verts_transform(me, rdata->orco, rdata->vert_len, 0);
- }
- else {
- rdata->orco = MEM_mallocN(sizeof(*rdata->orco) * rdata->vert_len, "orco mesh");
- MVert *mvert = rdata->mvert;
- for (int a = 0; a < rdata->vert_len; a++, mvert++) {
- copy_v3_v3(rdata->orco[a], mvert->co);
+ else {
+ rdata->orco = MEM_mallocN(sizeof(*rdata->orco) * rdata->vert_len, "orco mesh");
+ MVert *mvert = rdata->mvert;
+ for (int a = 0; a < rdata->vert_len; a++, mvert++) {
+ copy_v3_v3(rdata->orco[a], mvert->co);
+ }
+ BKE_mesh_orco_verts_transform(me, rdata->orco, rdata->vert_len, 0);
}
- BKE_mesh_orco_verts_transform(me, rdata->orco, rdata->vert_len, 0);
}
}
+ else {
+ rdata->orco = NULL;
+ }
const bool is_auto_smooth = (me->flag & ME_AUTOSMOOTH) != 0;
@@ -405,18 +496,25 @@ static MeshRenderData *mesh_render_data_create(Mesh *me, const int types)
#define me DONT_USE_THIS
#ifdef me /* quiet warning */
#endif
+ struct {
+ uint uv_len;
+ uint vcol_len;
+ } cd_layers_src = {
+ .uv_len = CustomData_number_of_layers(cd_ldata, CD_MLOOPUV),
+ .vcol_len = CustomData_number_of_layers(cd_ldata, CD_MLOOPCOL),
+ };
- rdata->cd.layers.uv_len = CustomData_number_of_layers(cd_ldata, CD_MLOOPUV);
- rdata->cd.layers.tangent_len = rdata->cd.layers.uv_len;
- rdata->cd.layers.vcol_len = CustomData_number_of_layers(cd_ldata, CD_MLOOPCOL);
+ rdata->cd.layers.uv_len = count_bits_i(cd_lused[CD_MLOOPUV]);
+ rdata->cd.layers.tangent_len = count_bits_i(cd_lused[CD_TANGENT]);
+ rdata->cd.layers.vcol_len = count_bits_i(cd_lused[CD_MLOOPCOL]);
rdata->cd.layers.uv = MEM_mallocN(sizeof(*rdata->cd.layers.uv) * rdata->cd.layers.uv_len, __func__);
rdata->cd.layers.vcol = MEM_mallocN(sizeof(*rdata->cd.layers.vcol) * rdata->cd.layers.vcol_len, __func__);
- rdata->cd.layers.tangent = MEM_mallocN(sizeof(*rdata->cd.layers.tangent) * rdata->cd.layers.uv_len, __func__);
+ rdata->cd.layers.tangent = MEM_mallocN(sizeof(*rdata->cd.layers.tangent) * rdata->cd.layers.tangent_len, __func__);
rdata->cd.uuid.uv = MEM_mallocN(sizeof(*rdata->cd.uuid.uv) * rdata->cd.layers.uv_len, __func__);
rdata->cd.uuid.vcol = MEM_mallocN(sizeof(*rdata->cd.uuid.vcol) * rdata->cd.layers.vcol_len, __func__);
- rdata->cd.uuid.tangent = MEM_mallocN(sizeof(*rdata->cd.uuid.tangent) * rdata->cd.layers.uv_len, __func__);
+ rdata->cd.uuid.tangent = MEM_mallocN(sizeof(*rdata->cd.uuid.tangent) * rdata->cd.layers.tangent_len, __func__);
rdata->cd.offset.uv = MEM_mallocN(sizeof(*rdata->cd.offset.uv) * rdata->cd.layers.uv_len, __func__);
rdata->cd.offset.vcol = MEM_mallocN(sizeof(*rdata->cd.offset.vcol) * rdata->cd.layers.vcol_len, __func__);
@@ -434,119 +532,167 @@ static MeshRenderData *mesh_render_data_create(Mesh *me, const int types)
* One solution to hash collision would be to format the cd layer name
* to a safe glsl var name, but without name clash.
* NOTE 2 : Replicate changes to code_generate_vertex_new() in gpu_codegen.c */
- for (int i = 0; i < rdata->cd.layers.vcol_len; ++i) {
- const char *name = CustomData_get_layer_name(cd_ldata, CD_MLOOPCOL, i);
- unsigned int hash = BLI_ghashutil_strhash_p(name);
- BLI_snprintf(rdata->cd.uuid.vcol[i], sizeof(*rdata->cd.uuid.vcol), "c%u", hash);
- rdata->cd.layers.vcol[i] = CustomData_get_layer_n(cd_ldata, CD_MLOOPCOL, i);
- if (rdata->edit_bmesh) {
- rdata->cd.offset.vcol[i] = CustomData_get_n_offset(&rdata->edit_bmesh->bm->ldata, CD_MLOOPCOL, i);
- }
+ if (rdata->cd.layers.vcol_len != 0) {
+ for (int i_src = 0, i_dst = 0; i_src < cd_layers_src.vcol_len; i_src++, i_dst++) {
+ if ((cd_lused[CD_MLOOPCOL] & (1 << i_src)) == 0) {
+ i_dst--;
+ if (rdata->cd.layers.vcol_active >= i_src) {
+ rdata->cd.layers.vcol_active--;
+ }
+ }
+ else {
+ const char *name = CustomData_get_layer_name(cd_ldata, CD_MLOOPCOL, i_src);
+ unsigned int hash = BLI_ghashutil_strhash_p(name);
+ BLI_snprintf(rdata->cd.uuid.vcol[i_dst], sizeof(*rdata->cd.uuid.vcol), "c%u", hash);
+ rdata->cd.layers.vcol[i_dst] = CustomData_get_layer_n(cd_ldata, CD_MLOOPCOL, i_src);
+ if (rdata->edit_bmesh) {
+ rdata->cd.offset.vcol[i_dst] = CustomData_get_n_offset(
+ &rdata->edit_bmesh->bm->ldata, CD_MLOOPCOL, i_src);
+ }
- /* Gather number of auto layers. */
- /* We only do vcols that are not overridden by uvs */
- if (CustomData_get_named_layer_index(cd_ldata, CD_MLOOPUV, name) == -1) {
- BLI_snprintf(
- rdata->cd.uuid.auto_mix[rdata->cd.layers.uv_len + i],
- sizeof(*rdata->cd.uuid.auto_mix), "a%u", hash);
- rdata->cd.layers.auto_vcol[i] = true;
+ /* Gather number of auto layers. */
+ /* We only do vcols that are not overridden by uvs */
+ if (CustomData_get_named_layer_index(cd_ldata, CD_MLOOPUV, name) == -1) {
+ BLI_snprintf(
+ rdata->cd.uuid.auto_mix[rdata->cd.layers.uv_len + i_dst],
+ sizeof(*rdata->cd.uuid.auto_mix), "a%u", hash);
+ rdata->cd.layers.auto_vcol[i_dst] = true;
+ }
+ }
}
}
/* Start Fresh */
+ CustomData_free_layers(cd_ldata, CD_TANGENT, rdata->loop_len);
CustomData_free_layers(cd_ldata, CD_MLOOPTANGENT, rdata->loop_len);
- for (int i = 0; i < rdata->cd.layers.uv_len; ++i) {
- const char *name = CustomData_get_layer_name(cd_ldata, CD_MLOOPUV, i);
- unsigned int hash = BLI_ghashutil_strhash_p(name);
- {
- /* UVs */
- BLI_snprintf(rdata->cd.uuid.uv[i], sizeof(*rdata->cd.uuid.uv), "u%u", hash);
- rdata->cd.layers.uv[i] = CustomData_get_layer_n(cd_ldata, CD_MLOOPUV, i);
- if (rdata->edit_bmesh) {
- rdata->cd.offset.uv[i] = CustomData_get_n_offset(&rdata->edit_bmesh->bm->ldata, CD_MLOOPUV, i);
+ if (rdata->cd.layers.uv_len != 0) {
+ for (int i_src = 0, i_dst = 0; i_src < cd_layers_src.uv_len; i_src++, i_dst++) {
+ if ((cd_lused[CD_MLOOPUV] & (1 << i_src)) == 0) {
+ i_dst--;
+ if (rdata->cd.layers.uv_active >= i_src) {
+ rdata->cd.layers.uv_active--;
+ }
}
- BLI_snprintf(rdata->cd.uuid.auto_mix[i], sizeof(*rdata->cd.uuid.auto_mix), "a%u", hash);
- }
+ else {
+ const char *name = CustomData_get_layer_name(cd_ldata, CD_MLOOPUV, i_src);
+ unsigned int hash = BLI_ghashutil_strhash_p(name);
- {
- /* Tangents*/
- BLI_snprintf(rdata->cd.uuid.tangent[i], sizeof(*rdata->cd.uuid.tangent), "t%u", hash);
-
- if (!CustomData_has_layer(&rdata->cd.output.ldata, CD_TANGENT)) {
-
- /* Tangent Names */
- char tangent_names[MAX_MTFACE][MAX_NAME];
- int tangent_names_len = 0;
- for (tangent_names_len = 0; tangent_names_len < rdata->cd.layers.uv_len; tangent_names_len++) {
- BLI_strncpy(
- tangent_names[tangent_names_len],
- CustomData_get_layer_name(cd_ldata, CD_MLOOPUV, tangent_names_len), MAX_NAME);
+ BLI_snprintf(rdata->cd.uuid.uv[i_dst], sizeof(*rdata->cd.uuid.uv), "u%u", hash);
+ rdata->cd.layers.uv[i_dst] = CustomData_get_layer_n(cd_ldata, CD_MLOOPUV, i_src);
+ if (rdata->edit_bmesh) {
+ rdata->cd.offset.uv[i_dst] = CustomData_get_n_offset(
+ &rdata->edit_bmesh->bm->ldata, CD_MLOOPUV, i_src);
}
+ BLI_snprintf(rdata->cd.uuid.auto_mix[i_dst], sizeof(*rdata->cd.uuid.auto_mix), "a%u", hash);
+ }
+ }
+ }
- if (rdata->edit_bmesh) {
- BMEditMesh *em = rdata->edit_bmesh;
- BMesh *bm = em->bm;
+ if (rdata->cd.layers.tangent_len != 0) {
- if (is_auto_smooth) {
- /* TODO: split normals, see below */
- }
+ /* -------------------------------------------------------------------- */
+ /* Pre-calculate tangents into 'rdata->cd.output.ldata' */
- bool calc_active_tangent = false;
- float (*poly_normals)[3] = rdata->poly_normals;
- float (*loop_normals)[3] = CustomData_get_layer(cd_ldata, CD_NORMAL);
-
- BKE_editmesh_loop_tangent_calc(
- em, calc_active_tangent,
- tangent_names, tangent_names_len,
- poly_normals, loop_normals,
- rdata->orco,
- &rdata->cd.output.ldata, bm->totloop,
- &rdata->cd.output.tangent_mask);
- }
- else {
+ BLI_assert(!CustomData_has_layer(&rdata->cd.output.ldata, CD_TANGENT));
+
+ /* Tangent Names */
+ char tangent_names[MAX_MTFACE][MAX_NAME];
+ for (int i_src = 0, i_dst = 0; i_src < cd_layers_src.uv_len; i_src++, i_dst++) {
+ if ((cd_lused[CD_TANGENT] & (1 << i_src)) == 0) {
+ i_dst--;
+ }
+ else {
+ BLI_strncpy(
+ tangent_names[i_dst],
+ CustomData_get_layer_name(cd_ldata, CD_MLOOPUV, i_src), MAX_NAME);
+ }
+ }
+
+ if (rdata->edit_bmesh) {
+ BMEditMesh *em = rdata->edit_bmesh;
+ BMesh *bm = em->bm;
+
+ if (is_auto_smooth) {
+ /* TODO: split normals, see below */
+ }
+
+ bool calc_active_tangent = false;
+ float (*poly_normals)[3] = rdata->poly_normals;
+ float (*loop_normals)[3] = CustomData_get_layer(cd_ldata, CD_NORMAL);
+
+ BKE_editmesh_loop_tangent_calc(
+ em, calc_active_tangent,
+ tangent_names, rdata->cd.layers.tangent_len,
+ poly_normals, loop_normals,
+ rdata->orco,
+ &rdata->cd.output.ldata, bm->totloop,
+ &rdata->cd.output.tangent_mask);
+ }
+ else {
#undef me
- if (is_auto_smooth) {
- if (!CustomData_has_layer(cd_ldata, CD_NORMAL)) {
- BKE_mesh_calc_normals_split(me);
- }
- }
+ if (is_auto_smooth) {
+ if (!CustomData_has_layer(cd_ldata, CD_NORMAL)) {
+ BKE_mesh_calc_normals_split(me);
+ }
+ }
- bool calc_active_tangent = false;
- const float (*poly_normals)[3] = rdata->poly_normals;
- const float (*loop_normals)[3] = CustomData_get_layer(cd_ldata, CD_NORMAL);
-
- BKE_mesh_calc_loop_tangent_ex(
- me->mvert,
- me->mpoly, me->totpoly,
- me->mloop,
- rdata->mlooptri, rdata->tri_len,
- cd_ldata,
- calc_active_tangent,
- tangent_names, tangent_names_len,
- poly_normals, loop_normals,
- rdata->orco,
- &rdata->cd.output.ldata, me->totloop,
- &rdata->cd.output.tangent_mask);
-
- /* If we store tangents in the mesh, set temporary. */
+ bool calc_active_tangent = false;
+ const float (*poly_normals)[3] = rdata->poly_normals;
+ const float (*loop_normals)[3] = CustomData_get_layer(cd_ldata, CD_NORMAL);
+
+ BKE_mesh_calc_loop_tangent_ex(
+ me->mvert,
+ me->mpoly, me->totpoly,
+ me->mloop,
+ rdata->mlooptri, rdata->tri_len,
+ cd_ldata,
+ calc_active_tangent,
+ tangent_names, rdata->cd.layers.tangent_len,
+ poly_normals, loop_normals,
+ rdata->orco,
+ &rdata->cd.output.ldata, me->totloop,
+ &rdata->cd.output.tangent_mask);
+
+ /* If we store tangents in the mesh, set temporary. */
#if 0
- CustomData_set_layer_flag(cd_ldata, CD_MLOOPTANGENT, CD_FLAG_TEMPORARY);
+ CustomData_set_layer_flag(cd_ldata, CD_TANGENT, CD_FLAG_TEMPORARY);
#endif
#define me DONT_USE_THIS
#ifdef me /* quiet warning */
#endif
+ }
+
+ /* End tangent calculation */
+ /* -------------------------------------------------------------------- */
+
+ BLI_assert(CustomData_number_of_layers(&rdata->cd.output.ldata, CD_TANGENT) == rdata->cd.layers.tangent_len);
+
+ for (int i_src = 0, i_dst = 0; i_src < cd_layers_src.uv_len; i_src++, i_dst++) {
+ if ((cd_lused[CD_TANGENT] & (1 << i_src)) == 0) {
+ i_dst--;
+ if (rdata->cd.layers.tangent_active >= i_src) {
+ rdata->cd.layers.tangent_active--;
}
}
- /* Done adding tangents. */
+ else {
+ const char *name = CustomData_get_layer_name(cd_ldata, CD_MLOOPUV, i_src);
+ unsigned int hash = BLI_ghashutil_strhash_p(name);
+
+ BLI_snprintf(rdata->cd.uuid.tangent[i_dst], sizeof(*rdata->cd.uuid.tangent), "t%u", hash);
+
+ /* Done adding tangents. */
- /* note: BKE_editmesh_loop_tangent_calc calculates 'CD_TANGENT',
- * not 'CD_MLOOPTANGENT' (as done below). It's OK, they're compatible. */
- rdata->cd.layers.tangent[i] = CustomData_get_layer_n(&rdata->cd.output.ldata, CD_TANGENT, i);
- if (rdata->tri_len != 0) {
- BLI_assert(rdata->cd.layers.tangent[i] != NULL);
+ /* note: BKE_editmesh_loop_tangent_calc calculates 'CD_TANGENT',
+ * not 'CD_MLOOPTANGENT' (as done below). It's OK, they're compatible. */
+
+ /* note: normally we'd use 'i_src' here, but 'i_dst' is in sync with 'rdata->cd.output' */
+ rdata->cd.layers.tangent[i_dst] = CustomData_get_layer_n(&rdata->cd.output.ldata, CD_TANGENT, i_dst);
+ if (rdata->tri_len != 0) {
+ BLI_assert(rdata->cd.layers.tangent[i_dst] != NULL);
+ }
}
}
}
@@ -586,6 +732,11 @@ static void mesh_render_data_free(MeshRenderData *rdata)
MEM_freeN(rdata);
}
+static MeshRenderData *mesh_render_data_create(Mesh *me, const int types)
+{
+ return mesh_render_data_create_ex(me, types, NULL, 0);
+}
+
/** \} */
@@ -3091,7 +3242,8 @@ Gwn_Batch *DRW_mesh_batch_cache_get_overlay_facedots(Mesh *me)
return cache->overlay_facedots;
}
-Gwn_Batch **DRW_mesh_batch_cache_get_surface_shaded(Mesh *me)
+Gwn_Batch **DRW_mesh_batch_cache_get_surface_shaded(
+ Mesh *me, struct GPUMaterial **gpumat_array, uint gpumat_array_len)
{
MeshBatchCache *cache = mesh_batch_cache_get(me);
@@ -3100,7 +3252,7 @@ Gwn_Batch **DRW_mesh_batch_cache_get_surface_shaded(Mesh *me)
const int datatype =
MR_DATATYPE_VERT | MR_DATATYPE_LOOP | MR_DATATYPE_LOOPTRI |
MR_DATATYPE_POLY | MR_DATATYPE_SHADING;
- MeshRenderData *rdata = mesh_render_data_create(me, datatype);
+ MeshRenderData *rdata = mesh_render_data_create_ex(me, datatype, gpumat_array, gpumat_array_len);
const int mat_len = mesh_render_data_mat_len_get(rdata);