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:
Diffstat (limited to 'source/blender/draw')
-rw-r--r--source/blender/draw/CMakeLists.txt4
-rw-r--r--source/blender/draw/DRW_select_buffer.h14
-rw-r--r--source/blender/draw/engines/basic/basic_engine.c2
-rw-r--r--source/blender/draw/engines/eevee/eevee_data.c144
-rw-r--r--source/blender/draw/engines/eevee/eevee_effects.c29
-rw-r--r--source/blender/draw/engines/eevee/eevee_engine.c137
-rw-r--r--source/blender/draw/engines/eevee/eevee_lightcache.c1
-rw-r--r--source/blender/draw/engines/eevee/eevee_lightprobes.c4
-rw-r--r--source/blender/draw/engines/eevee/eevee_materials.c16
-rw-r--r--source/blender/draw/engines/eevee/eevee_mist.c2
-rw-r--r--source/blender/draw/engines/eevee/eevee_motion_blur.c598
-rw-r--r--source/blender/draw/engines/eevee/eevee_occlusion.c2
-rw-r--r--source/blender/draw/engines/eevee/eevee_private.h117
-rw-r--r--source/blender/draw/engines/eevee/eevee_render.c81
-rw-r--r--source/blender/draw/engines/eevee/eevee_renderpasses.c49
-rw-r--r--source/blender/draw/engines/eevee/eevee_screen_raytrace.c2
-rw-r--r--source/blender/draw/engines/eevee/eevee_shadows.c2
-rw-r--r--source/blender/draw/engines/eevee/eevee_subsurface.c25
-rw-r--r--source/blender/draw/engines/eevee/eevee_temporal_sampling.c41
-rw-r--r--source/blender/draw/engines/eevee/eevee_volumes.c2
-rw-r--r--source/blender/draw/engines/eevee/shaders/bsdf_common_lib.glsl15
-rw-r--r--source/blender/draw/engines/eevee/shaders/effect_motion_blur_frag.glsl247
-rw-r--r--source/blender/draw/engines/eevee/shaders/effect_temporal_aa.glsl19
-rw-r--r--source/blender/draw/engines/eevee/shaders/effect_velocity_resolve_frag.glsl18
-rw-r--r--source/blender/draw/engines/eevee/shaders/effect_velocity_tile_frag.glsl151
-rw-r--r--source/blender/draw/engines/eevee/shaders/object_motion_frag.glsl27
-rw-r--r--source/blender/draw/engines/eevee/shaders/object_motion_vert.glsl54
-rw-r--r--source/blender/draw/engines/external/external_engine.c2
-rw-r--r--source/blender/draw/engines/gpencil/gpencil_cache_utils.c8
-rw-r--r--source/blender/draw/engines/gpencil/gpencil_engine.c21
-rw-r--r--source/blender/draw/engines/gpencil/gpencil_engine.h2
-rw-r--r--source/blender/draw/engines/gpencil/gpencil_shader_fx.c8
-rw-r--r--source/blender/draw/engines/overlay/overlay_armature.c6
-rw-r--r--source/blender/draw/engines/overlay/overlay_edit_text.c27
-rw-r--r--source/blender/draw/engines/overlay/overlay_engine.c2
-rw-r--r--source/blender/draw/engines/overlay/overlay_extra.c2
-rw-r--r--source/blender/draw/engines/overlay/overlay_grid.c4
-rw-r--r--source/blender/draw/engines/overlay/overlay_private.h8
-rw-r--r--source/blender/draw/engines/overlay/overlay_shader.c33
-rw-r--r--source/blender/draw/engines/overlay/overlay_wireframe.c3
-rw-r--r--source/blender/draw/engines/overlay/shaders/armature_dof_solid_frag.glsl11
-rw-r--r--source/blender/draw/engines/overlay/shaders/armature_dof_vert.glsl4
-rw-r--r--source/blender/draw/engines/overlay/shaders/edit_mesh_vert.glsl2
-rw-r--r--source/blender/draw/engines/overlay/shaders/grid_frag.glsl7
-rw-r--r--source/blender/draw/engines/workbench/shaders/workbench_cavity_lib.glsl2
-rw-r--r--source/blender/draw/engines/workbench/shaders/workbench_volume_frag.glsl3
-rw-r--r--source/blender/draw/engines/workbench/workbench_engine.c37
-rw-r--r--source/blender/draw/engines/workbench/workbench_materials.c2
-rw-r--r--source/blender/draw/engines/workbench/workbench_private.h2
-rw-r--r--source/blender/draw/engines/workbench/workbench_transparent.c6
-rw-r--r--source/blender/draw/intern/DRW_render.h8
-rw-r--r--source/blender/draw/intern/draw_cache.c32
-rw-r--r--source/blender/draw/intern/draw_cache.h3
-rw-r--r--source/blender/draw/intern/draw_cache_extract.h3
-rw-r--r--source/blender/draw/intern/draw_cache_extract_mesh.c3415
-rw-r--r--source/blender/draw/intern/draw_cache_impl.h6
-rw-r--r--source/blender/draw/intern/draw_cache_impl_curve.c10
-rw-r--r--source/blender/draw/intern/draw_cache_impl_gpencil.c21
-rw-r--r--source/blender/draw/intern/draw_cache_impl_mesh.c98
-rw-r--r--source/blender/draw/intern/draw_cache_impl_metaball.c12
-rw-r--r--source/blender/draw/intern/draw_cache_inline.h24
-rw-r--r--source/blender/draw/intern/draw_common.h7
-rw-r--r--source/blender/draw/intern/draw_hair.c157
-rw-r--r--source/blender/draw/intern/draw_manager.c49
-rw-r--r--source/blender/draw/intern/draw_manager_data.c37
-rw-r--r--source/blender/draw/intern/draw_select_buffer.c7
66 files changed, 3935 insertions, 1959 deletions
diff --git a/source/blender/draw/CMakeLists.txt b/source/blender/draw/CMakeLists.txt
index a26c150cb51..1ddae11999b 100644
--- a/source/blender/draw/CMakeLists.txt
+++ b/source/blender/draw/CMakeLists.txt
@@ -214,6 +214,7 @@ data_to_c_simple(engines/eevee/shaders/effect_downsample_frag.glsl SRC)
data_to_c_simple(engines/eevee/shaders/effect_downsample_cube_frag.glsl SRC)
data_to_c_simple(engines/eevee/shaders/effect_gtao_frag.glsl SRC)
data_to_c_simple(engines/eevee/shaders/effect_velocity_resolve_frag.glsl SRC)
+data_to_c_simple(engines/eevee/shaders/effect_velocity_tile_frag.glsl SRC)
data_to_c_simple(engines/eevee/shaders/effect_minmaxz_frag.glsl SRC)
data_to_c_simple(engines/eevee/shaders/effect_mist_frag.glsl SRC)
data_to_c_simple(engines/eevee/shaders/effect_motion_blur_frag.glsl SRC)
@@ -224,6 +225,8 @@ data_to_c_simple(engines/eevee/shaders/effect_temporal_aa.glsl SRC)
data_to_c_simple(engines/eevee/shaders/lightprobe_planar_downsample_frag.glsl SRC)
data_to_c_simple(engines/eevee/shaders/lightprobe_planar_downsample_geom.glsl SRC)
data_to_c_simple(engines/eevee/shaders/lightprobe_planar_downsample_vert.glsl SRC)
+data_to_c_simple(engines/eevee/shaders/object_motion_frag.glsl SRC)
+data_to_c_simple(engines/eevee/shaders/object_motion_vert.glsl SRC)
data_to_c_simple(engines/eevee/shaders/prepass_frag.glsl SRC)
data_to_c_simple(engines/eevee/shaders/prepass_vert.glsl SRC)
data_to_c_simple(engines/eevee/shaders/shadow_accum_frag.glsl SRC)
@@ -310,6 +313,7 @@ data_to_c_simple(engines/basic/shaders/depth_frag.glsl SRC)
data_to_c_simple(engines/overlay/shaders/antialiasing_frag.glsl SRC)
data_to_c_simple(engines/overlay/shaders/antialiasing_vert.glsl SRC)
data_to_c_simple(engines/overlay/shaders/armature_dof_vert.glsl SRC)
+data_to_c_simple(engines/overlay/shaders/armature_dof_solid_frag.glsl SRC)
data_to_c_simple(engines/overlay/shaders/armature_envelope_outline_vert.glsl SRC)
data_to_c_simple(engines/overlay/shaders/armature_envelope_solid_frag.glsl SRC)
data_to_c_simple(engines/overlay/shaders/armature_envelope_solid_vert.glsl SRC)
diff --git a/source/blender/draw/DRW_select_buffer.h b/source/blender/draw/DRW_select_buffer.h
index 6ebc30d0382..66dee3a9aa9 100644
--- a/source/blender/draw/DRW_select_buffer.h
+++ b/source/blender/draw/DRW_select_buffer.h
@@ -56,16 +56,16 @@ struct ObjectOffsets {
uint vert;
};
-struct SELECTID_Context {
+typedef struct SELECTID_Context {
/* All context objects */
struct Object **objects;
- uint objects_len;
/* Array with only drawn objects. When a new object is found within the rect,
* it is added to the end of the list.
* The list is reset to any viewport or context update. */
- struct ObjectOffsets *index_offsets;
struct Object **objects_drawn;
+ struct ObjectOffsets *index_offsets;
+ uint objects_len;
uint objects_drawn_len;
/** Total number of element indices `index_offsets[object_drawn_len - 1].vert`. */
@@ -73,13 +73,13 @@ struct SELECTID_Context {
short select_mode;
+ /* rect is used to check which objects whose indexes need to be drawn. */
+ rcti last_rect;
+
/* To check for updates. */
float persmat[4][4];
bool is_dirty;
-
- /* rect is used to check which objects whose indexes need to be drawn. */
- rcti last_rect;
-};
+} SELECTID_Context;
/* draw_select_buffer.c */
bool DRW_select_buffer_elem_get(const uint sel_id,
diff --git a/source/blender/draw/engines/basic/basic_engine.c b/source/blender/draw/engines/basic/basic_engine.c
index bbc3c407f14..0dd3cc14234 100644
--- a/source/blender/draw/engines/basic/basic_engine.c
+++ b/source/blender/draw/engines/basic/basic_engine.c
@@ -131,7 +131,7 @@ static void basic_cache_init(void *vedata)
stl->g_data = MEM_callocN(sizeof(*stl->g_data), __func__);
}
- /* Twice for normal and infront objects. */
+ /* Twice for normal and in front objects. */
for (int i = 0; i < 2; i++) {
DRWState clip_state = (draw_ctx->sh_cfg == GPU_SHADER_CFG_CLIPPED) ? DRW_STATE_CLIP_PLANES : 0;
DRWState infront_state = (DRW_state_is_select() && (i == 1)) ? DRW_STATE_IN_FRONT_SELECT : 0;
diff --git a/source/blender/draw/engines/eevee/eevee_data.c b/source/blender/draw/engines/eevee/eevee_data.c
index a19af77124f..a4aa0e10198 100644
--- a/source/blender/draw/engines/eevee/eevee_data.c
+++ b/source/blender/draw/engines/eevee/eevee_data.c
@@ -24,11 +24,153 @@
#include "DRW_render.h"
+#include "BLI_ghash.h"
#include "BLI_memblock.h"
+#include "BKE_duplilist.h"
+
+#include "DEG_depsgraph_query.h"
+
+#include "GPU_vertex_buffer.h"
+
#include "eevee_lightcache.h"
#include "eevee_private.h"
+/* Motion Blur data. */
+
+static void eevee_motion_blur_mesh_data_free(void *val)
+{
+ EEVEE_GeometryMotionData *geom_mb = (EEVEE_GeometryMotionData *)val;
+ switch (geom_mb->type) {
+ case EEVEE_HAIR_GEOM_MOTION_DATA:
+ for (int i = 0; i < ARRAY_SIZE(geom_mb->vbo); i++) {
+ GPU_VERTBUF_DISCARD_SAFE(geom_mb->hair_pos[i]);
+ DRW_TEXTURE_FREE_SAFE(geom_mb->hair_pos_tx[i]);
+ }
+ break;
+
+ case EEVEE_MESH_GEOM_MOTION_DATA:
+ for (int i = 0; i < ARRAY_SIZE(geom_mb->vbo); i++) {
+ GPU_VERTBUF_DISCARD_SAFE(geom_mb->vbo[i]);
+ }
+ break;
+ }
+ MEM_freeN(val);
+}
+
+static uint eevee_object_key_hash(const void *key)
+{
+ EEVEE_ObjectKey *ob_key = (EEVEE_ObjectKey *)key;
+ uint hash = BLI_ghashutil_ptrhash(ob_key->ob);
+ hash = BLI_ghashutil_combine_hash(hash, BLI_ghashutil_ptrhash(ob_key->parent));
+ for (int i = 0; i < 16; i++) {
+ if (ob_key->id[i] != 0) {
+ hash = BLI_ghashutil_combine_hash(hash, BLI_ghashutil_inthash(ob_key->id[i]));
+ }
+ else {
+ break;
+ }
+ }
+ return hash;
+}
+
+/* Return false if equal. */
+static bool eevee_object_key_cmp(const void *a, const void *b)
+{
+ EEVEE_ObjectKey *key_a = (EEVEE_ObjectKey *)a;
+ EEVEE_ObjectKey *key_b = (EEVEE_ObjectKey *)b;
+
+ if (key_a->ob != key_b->ob) {
+ return true;
+ }
+ if (key_a->parent != key_b->parent) {
+ return true;
+ }
+ if (memcmp(key_a->id, key_b->id, sizeof(key_a->id)) != 0) {
+ return true;
+ }
+ return false;
+}
+
+void EEVEE_motion_blur_data_init(EEVEE_MotionBlurData *mb)
+{
+ if (mb->object == NULL) {
+ mb->object = BLI_ghash_new(eevee_object_key_hash, eevee_object_key_cmp, "EEVEE Object Motion");
+ }
+ if (mb->geom == NULL) {
+ mb->geom = BLI_ghash_new(BLI_ghashutil_ptrhash, BLI_ghashutil_ptrcmp, "EEVEE Mesh Motion");
+ }
+}
+
+void EEVEE_motion_blur_data_free(EEVEE_MotionBlurData *mb)
+{
+ if (mb->object) {
+ BLI_ghash_free(mb->object, MEM_freeN, MEM_freeN);
+ mb->object = NULL;
+ }
+ if (mb->geom) {
+ BLI_ghash_free(mb->geom, NULL, eevee_motion_blur_mesh_data_free);
+ mb->geom = NULL;
+ }
+}
+
+EEVEE_ObjectMotionData *EEVEE_motion_blur_object_data_get(EEVEE_MotionBlurData *mb,
+ Object *ob,
+ bool hair)
+{
+ if (mb->object == NULL) {
+ return NULL;
+ }
+
+ EEVEE_ObjectKey key, *key_p;
+ /* Small hack to avoid another comparisson. */
+ key.ob = (Object *)((char *)ob + hair);
+ DupliObject *dup = DRW_object_get_dupli(ob);
+ if (dup) {
+ key.parent = DRW_object_get_dupli_parent(ob);
+ memcpy(key.id, dup->persistent_id, sizeof(key.id));
+ }
+ else {
+ key.parent = key.ob;
+ memset(key.id, 0, sizeof(key.id));
+ }
+
+ EEVEE_ObjectMotionData *ob_step = BLI_ghash_lookup(mb->object, &key);
+ if (ob_step == NULL) {
+ key_p = MEM_mallocN(sizeof(*key_p), __func__);
+ memcpy(key_p, &key, sizeof(*key_p));
+
+ ob_step = MEM_callocN(sizeof(EEVEE_ObjectMotionData), __func__);
+
+ BLI_ghash_insert(mb->object, key_p, ob_step);
+ }
+ return ob_step;
+}
+
+EEVEE_GeometryMotionData *EEVEE_motion_blur_geometry_data_get(EEVEE_MotionBlurData *mb,
+ Object *ob,
+ bool hair)
+{
+ if (mb->geom == NULL) {
+ return NULL;
+ }
+
+ /* Use original data as key to ensure matching accross update. */
+ Object *ob_orig = DEG_get_original_object(ob);
+
+ void *key = (char *)ob_orig->data + hair;
+ EEVEE_GeometryMotionData *geom_step = BLI_ghash_lookup(mb->geom, key);
+ if (geom_step == NULL) {
+ geom_step = MEM_callocN(sizeof(EEVEE_GeometryMotionData), __func__);
+ geom_step->type = (hair) ? EEVEE_HAIR_GEOM_MOTION_DATA : EEVEE_MESH_GEOM_MOTION_DATA;
+ BLI_ghash_insert(mb->geom, key, geom_step);
+ }
+
+ return geom_step;
+}
+
+/* View Layer data. */
+
void EEVEE_view_layer_data_free(void *storage)
{
EEVEE_ViewLayerData *sldata = (EEVEE_ViewLayerData *)storage;
@@ -105,6 +247,8 @@ static void eevee_object_data_init(DrawData *dd)
{
EEVEE_ObjectEngineData *eevee_data = (EEVEE_ObjectEngineData *)dd;
eevee_data->shadow_caster_id = -1;
+ eevee_data->need_update = false;
+ eevee_data->geom_update = false;
}
EEVEE_ObjectEngineData *EEVEE_object_data_get(Object *ob)
diff --git a/source/blender/draw/engines/eevee/eevee_effects.c b/source/blender/draw/engines/eevee/eevee_effects.c
index ab846fe0f11..8c48ae65d9b 100644
--- a/source/blender/draw/engines/eevee/eevee_effects.c
+++ b/source/blender/draw/engines/eevee/eevee_effects.c
@@ -153,7 +153,7 @@ void EEVEE_effects_init(EEVEE_ViewLayerData *sldata,
effects->enabled_effects = 0;
effects->enabled_effects |= (G.debug_value == 9) ? EFFECT_VELOCITY_BUFFER : 0;
- effects->enabled_effects |= EEVEE_motion_blur_init(sldata, vedata, camera);
+ effects->enabled_effects |= EEVEE_motion_blur_init(sldata, vedata);
effects->enabled_effects |= EEVEE_bloom_init(sldata, vedata);
effects->enabled_effects |= EEVEE_depth_of_field_init(sldata, vedata, camera);
effects->enabled_effects |= EEVEE_temporal_sampling_init(sldata, vedata);
@@ -225,10 +225,13 @@ void EEVEE_effects_init(EEVEE_ViewLayerData *sldata,
*/
if ((effects->enabled_effects & EFFECT_VELOCITY_BUFFER) != 0) {
effects->velocity_tx = DRW_texture_pool_query_2d(
- size_fs[0], size_fs[1], GPU_RG16, &draw_engine_eevee_type);
+ size_fs[0], size_fs[1], GPU_RGBA16, &draw_engine_eevee_type);
- /* TODO output objects velocity during the mainpass. */
- // GPU_framebuffer_texture_attach(fbl->main_fb, effects->velocity_tx, 1, 0);
+ GPU_framebuffer_ensure_config(&fbl->velocity_fb,
+ {
+ GPU_ATTACHMENT_TEXTURE(dtxl->depth),
+ GPU_ATTACHMENT_TEXTURE(effects->velocity_tx),
+ });
GPU_framebuffer_ensure_config(
&fbl->velocity_resolve_fb,
@@ -328,14 +331,18 @@ void EEVEE_effects_cache_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata)
}
if ((effects->enabled_effects & EFFECT_VELOCITY_BUFFER) != 0) {
+ EEVEE_MotionBlurData *mb_data = &effects->motion_blur;
+
/* This pass compute camera motions to the non moving objects. */
DRW_PASS_CREATE(psl->velocity_resolve, DRW_STATE_WRITE_COLOR);
grp = DRW_shgroup_create(EEVEE_shaders_velocity_resolve_sh_get(), psl->velocity_resolve);
DRW_shgroup_uniform_texture_ref(grp, "depthBuffer", &e_data.depth_src);
DRW_shgroup_uniform_block(grp, "common_block", sldata->common_ubo);
DRW_shgroup_uniform_block(grp, "renderpass_block", sldata->renderpass_ubo.combined);
- DRW_shgroup_uniform_mat4(grp, "currPersinv", effects->velocity_curr_persinv);
- DRW_shgroup_uniform_mat4(grp, "pastPersmat", effects->velocity_past_persmat);
+
+ DRW_shgroup_uniform_mat4(grp, "prevViewProjMatrix", mb_data->camera[MB_PREV].persmat);
+ DRW_shgroup_uniform_mat4(grp, "currViewProjMatrixInv", mb_data->camera[MB_CURR].persinv);
+ DRW_shgroup_uniform_mat4(grp, "nextViewProjMatrix", mb_data->camera[MB_NEXT].persmat);
DRW_shgroup_call(grp, quad, NULL);
}
}
@@ -501,17 +508,19 @@ static void EEVEE_velocity_resolve(EEVEE_Data *vedata)
EEVEE_FramebufferList *fbl = vedata->fbl;
EEVEE_StorageList *stl = vedata->stl;
EEVEE_EffectsInfo *effects = stl->effects;
- struct DRWView *view = effects->taa_view;
if ((effects->enabled_effects & EFFECT_VELOCITY_BUFFER) != 0) {
DefaultTextureList *dtxl = DRW_viewport_texture_list_get();
e_data.depth_src = dtxl->depth;
- DRW_view_persmat_get(view, effects->velocity_curr_persinv, true);
GPU_framebuffer_bind(fbl->velocity_resolve_fb);
DRW_draw_pass(psl->velocity_resolve);
+
+ if (psl->velocity_object) {
+ GPU_framebuffer_bind(fbl->velocity_fb);
+ DRW_draw_pass(psl->velocity_object);
+ }
}
- DRW_view_persmat_get(view, effects->velocity_past_persmat, false);
}
void EEVEE_draw_effects(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata)
@@ -529,6 +538,7 @@ void EEVEE_draw_effects(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata)
effects->target_buffer = fbl->effect_color_fb; /* next target to render to */
/* Post process stack (order matters) */
+ EEVEE_velocity_resolve(vedata);
EEVEE_motion_blur_draw(vedata);
EEVEE_depth_of_field_draw(vedata);
@@ -537,7 +547,6 @@ void EEVEE_draw_effects(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata)
* Velocity resolve use a hack to exclude lookdev
* spheres from creating shimmering re-projection vectors. */
EEVEE_lookdev_draw(vedata);
- EEVEE_velocity_resolve(vedata);
EEVEE_temporal_sampling_draw(vedata);
EEVEE_bloom_draw(vedata);
diff --git a/source/blender/draw/engines/eevee/eevee_engine.c b/source/blender/draw/engines/eevee/eevee_engine.c
index b698574f9d7..bac96ab1079 100644
--- a/source/blender/draw/engines/eevee/eevee_engine.c
+++ b/source/blender/draw/engines/eevee/eevee_engine.c
@@ -166,7 +166,9 @@ static void eevee_cache_finish(void *vedata)
EEVEE_materials_cache_finish(sldata, vedata);
EEVEE_lights_cache_finish(sldata, vedata);
EEVEE_lightprobes_cache_finish(sldata, vedata);
+ EEVEE_renderpasses_cache_finish(sldata, vedata);
+ EEVEE_subsurface_draw_init(sldata, vedata);
EEVEE_effects_draw_init(sldata, vedata);
EEVEE_volumes_draw_init(sldata, vedata);
@@ -213,6 +215,10 @@ static void eevee_draw_scene(void *vedata)
loop_len = MAX2(1, scene->eevee.taa_samples);
}
+ if (stl->effects->bypass_drawing) {
+ loop_len = 0;
+ }
+
while (loop_len--) {
float clear_col[4] = {0.0f, 0.0f, 0.0f, 0.0f};
float clear_depth = 1.0f;
@@ -351,11 +357,18 @@ static void eevee_draw_scene(void *vedata)
EEVEE_renderpasses_draw(sldata, vedata);
}
+ if (stl->effects->bypass_drawing) {
+ /* Restore the depth from sample 1. */
+ GPU_framebuffer_blit(fbl->double_buffer_depth_fb, 0, dfbl->default_fb, 0, GPU_DEPTH_BIT);
+ }
+
EEVEE_renderpasses_draw_debug(vedata);
EEVEE_volumes_free_smoke_textures();
stl->g_data->view_updated = false;
+
+ DRW_view_set_active(NULL);
}
static void eevee_view_update(void *vedata)
@@ -370,7 +383,7 @@ static void eevee_id_object_update(void *UNUSED(vedata), Object *object)
{
EEVEE_LightProbeEngineData *ped = EEVEE_lightprobe_data_get(object);
if (ped != NULL && ped->dd.recalc != 0) {
- ped->need_update = (ped->dd.recalc & (ID_RECALC_TRANSFORM)) != 0;
+ ped->need_update = (ped->dd.recalc & ID_RECALC_TRANSFORM) != 0;
ped->dd.recalc = 0;
}
EEVEE_LightEngineData *led = EEVEE_light_data_get(object);
@@ -381,6 +394,7 @@ static void eevee_id_object_update(void *UNUSED(vedata), Object *object)
EEVEE_ObjectEngineData *oedata = EEVEE_object_data_get(object);
if (oedata != NULL && oedata->dd.recalc != 0) {
oedata->need_update = true;
+ oedata->geom_update = (oedata->dd.recalc & (ID_RECALC_GEOMETRY)) != 0;
oedata->dd.recalc = 0;
}
}
@@ -390,6 +404,11 @@ static void eevee_id_world_update(void *vedata, World *wo)
EEVEE_StorageList *stl = ((EEVEE_Data *)vedata)->stl;
LightCache *lcache = stl->g_data->light_cache;
+ if (lcache == NULL || lcache == stl->lookdev_lightcache) {
+ /* Avoid Lookdev viewport clearing the update flag (see T67741). */
+ return;
+ }
+
EEVEE_WorldEngineData *wedata = EEVEE_world_data_ensure(wo);
if (wedata != NULL && wedata->dd.recalc != 0) {
@@ -400,7 +419,7 @@ static void eevee_id_world_update(void *vedata, World *wo)
}
}
-static void eevee_id_update(void *vedata, ID *id)
+void eevee_id_update(void *vedata, ID *id)
{
/* Handle updates based on ID type. */
switch (GS(id->name)) {
@@ -416,23 +435,129 @@ static void eevee_id_update(void *vedata, ID *id)
}
}
+static void eevee_render_reset_passes(EEVEE_Data *vedata)
+{
+ /* Reset passlist. This is safe as they are stored into managed memory chunks. */
+ memset(vedata->psl, 0, sizeof(*vedata->psl));
+}
+
static void eevee_render_to_image(void *vedata,
RenderEngine *engine,
struct RenderLayer *render_layer,
const rcti *rect)
{
+ EEVEE_Data *ved = (EEVEE_Data *)vedata;
const DRWContextState *draw_ctx = DRW_context_state_get();
+ Depsgraph *depsgraph = draw_ctx->depsgraph;
+ Scene *scene = DEG_get_evaluated_scene(depsgraph);
+ EEVEE_ViewLayerData *sldata = EEVEE_view_layer_data_ensure();
+ const bool do_motion_blur = (scene->eevee.flag & SCE_EEVEE_MOTION_BLUR_ENABLED) != 0;
+ const bool do_motion_blur_fx = do_motion_blur && (scene->eevee.motion_blur_max > 0);
- if (!EEVEE_render_init(vedata, engine, draw_ctx->depsgraph)) {
+ if (!EEVEE_render_init(vedata, engine, depsgraph)) {
return;
}
+ EEVEE_PrivateData *g_data = ved->stl->g_data;
+
+ int steps = max_ii(1, scene->eevee.motion_blur_steps);
+ int time_steps_tot = (do_motion_blur) ? steps : 1;
+ g_data->render_tot_samples = divide_ceil_u(scene->eevee.taa_render_samples, time_steps_tot);
+ /* Centered on frame for now. */
+ float time = CFRA - scene->eevee.motion_blur_shutter / 2.0f;
+ float time_step = scene->eevee.motion_blur_shutter / time_steps_tot;
+ for (int i = 0; i < time_steps_tot && !RE_engine_test_break(engine); i++) {
+ float time_prev = time;
+ float time_curr = time + time_step * 0.5f;
+ float time_next = time + time_step;
+ time += time_step;
+
+ /* Previous motion step. */
+ if (do_motion_blur_fx) {
+ if (i > 0) {
+ /* The previous step of this iteration N is exactly the next step of iteration N - 1.
+ * So we just swap the resources to avoid too much re-evaluation. */
+ EEVEE_motion_blur_swap_data(vedata);
+ }
+ else {
+ EEVEE_motion_blur_step_set(ved, MB_PREV);
+ RE_engine_frame_set(engine, floorf(time_prev), fractf(time_prev));
+
+ EEVEE_render_view_sync(vedata, engine, depsgraph);
+ EEVEE_render_cache_init(sldata, vedata);
+
+ DRW_render_object_iter(vedata, engine, depsgraph, EEVEE_render_cache);
+
+ EEVEE_motion_blur_cache_finish(vedata);
+ EEVEE_materials_cache_finish(sldata, vedata);
+ eevee_render_reset_passes(vedata);
+ }
+ }
+
+ /* Next motion step. */
+ if (do_motion_blur_fx) {
+ EEVEE_motion_blur_step_set(ved, MB_NEXT);
+ RE_engine_frame_set(engine, floorf(time_next), fractf(time_next));
- DRW_render_object_iter(vedata, engine, draw_ctx->depsgraph, EEVEE_render_cache);
+ EEVEE_render_view_sync(vedata, engine, depsgraph);
+ EEVEE_render_cache_init(sldata, vedata);
- /* Actually do the rendering. */
- EEVEE_render_draw(vedata, engine, render_layer, rect);
+ DRW_render_object_iter(vedata, engine, depsgraph, EEVEE_render_cache);
+
+ EEVEE_motion_blur_cache_finish(vedata);
+ EEVEE_materials_cache_finish(sldata, vedata);
+ eevee_render_reset_passes(vedata);
+ }
+
+ /* Current motion step. */
+ {
+ if (do_motion_blur) {
+ EEVEE_motion_blur_step_set(ved, MB_CURR);
+ RE_engine_frame_set(engine, floorf(time_curr), fractf(time_curr));
+ }
+
+ EEVEE_render_view_sync(vedata, engine, depsgraph);
+ EEVEE_render_cache_init(sldata, vedata);
+
+ DRW_render_object_iter(vedata, engine, depsgraph, EEVEE_render_cache);
+
+ EEVEE_motion_blur_cache_finish(vedata);
+ EEVEE_volumes_cache_finish(sldata, vedata);
+ EEVEE_materials_cache_finish(sldata, vedata);
+ EEVEE_lights_cache_finish(sldata, vedata);
+ EEVEE_lightprobes_cache_finish(sldata, vedata);
+ EEVEE_renderpasses_cache_finish(sldata, vedata);
+
+ EEVEE_subsurface_draw_init(sldata, vedata);
+ EEVEE_effects_draw_init(sldata, vedata);
+ EEVEE_volumes_draw_init(sldata, vedata);
+ }
+
+ /* Actual drawing. */
+ {
+ EEVEE_renderpasses_output_init(sldata, vedata, g_data->render_tot_samples * time_steps_tot);
+
+ EEVEE_temporal_sampling_create_view(vedata);
+ EEVEE_render_draw(vedata, engine, render_layer, rect);
+
+ if (i < time_steps_tot - 1) {
+ /* Don't reset after the last loop. Since EEVEE_render_read_result
+ * might need some DRWPasses. */
+ DRW_cache_restart();
+ }
+ }
+ }
EEVEE_volumes_free_smoke_textures();
+ EEVEE_motion_blur_data_free(&ved->stl->effects->motion_blur);
+
+ if (RE_engine_test_break(engine)) {
+ return;
+ }
+
+ EEVEE_render_read_result(vedata, engine, render_layer, rect);
+
+ /* Restore original viewport size. */
+ DRW_render_viewport_size_set((int[2]){g_data->size_orig[0], g_data->size_orig[1]});
}
static void eevee_engine_free(void)
diff --git a/source/blender/draw/engines/eevee/eevee_lightcache.c b/source/blender/draw/engines/eevee/eevee_lightcache.c
index 4cdd166f09c..78d50a02fc7 100644
--- a/source/blender/draw/engines/eevee/eevee_lightcache.c
+++ b/source/blender/draw/engines/eevee/eevee_lightcache.c
@@ -849,6 +849,7 @@ static void eevee_lightbake_cache_create(EEVEE_Data *vedata, EEVEE_LightBake *lb
/* Disable volumetrics when baking. */
stl->effects->enabled_effects &= ~EFFECT_VOLUMETRIC;
+ EEVEE_subsurface_draw_init(sldata, vedata);
EEVEE_effects_draw_init(sldata, vedata);
EEVEE_volumes_draw_init(sldata, vedata);
diff --git a/source/blender/draw/engines/eevee/eevee_lightprobes.c b/source/blender/draw/engines/eevee/eevee_lightprobes.c
index 83b2a9bb6d4..71c8294d123 100644
--- a/source/blender/draw/engines/eevee/eevee_lightprobes.c
+++ b/source/blender/draw/engines/eevee/eevee_lightprobes.c
@@ -957,8 +957,8 @@ static void lightbake_render_scene_reflected(int layer, EEVEE_BakeRenderData *us
/* Slight modification: we handle refraction as normal
* shading and don't do SSRefraction. */
- DRW_draw_pass(psl->depth_ps);
- DRW_draw_pass(psl->depth_refract_ps);
+ DRW_draw_pass(psl->depth_clip_ps);
+ DRW_draw_pass(psl->depth_refract_clip_ps);
DRW_draw_pass(psl->probe_background);
EEVEE_create_minmax_buffer(vedata, tmp_planar_depth, layer);
diff --git a/source/blender/draw/engines/eevee/eevee_materials.c b/source/blender/draw/engines/eevee/eevee_materials.c
index cfc70baaf01..8537ad0e532 100644
--- a/source/blender/draw/engines/eevee/eevee_materials.c
+++ b/source/blender/draw/engines/eevee/eevee_materials.c
@@ -801,6 +801,8 @@ static void eevee_hair_cache_populate(EEVEE_Data *vedata,
*matcache.shadow_grp_p = DRW_shgroup_hair_create_sub(ob, psys, md, matcache.shadow_grp);
*cast_shadow = true;
}
+
+ EEVEE_motion_blur_hair_cache_populate(sldata, vedata, ob, psys, md);
}
#define ADD_SHGROUP_CALL(shgrp, ob, geom, oedata) \
@@ -851,8 +853,7 @@ void EEVEE_materials_cache_populate(EEVEE_Data *vedata,
*/
bool use_volume_material = (matcache[0].shading_gpumat &&
GPU_material_has_volume_output(matcache[0].shading_gpumat));
-
- if ((ob->dt >= OB_SOLID) || DRW_state_is_image_render()) {
+ if ((ob->dt >= OB_SOLID) || DRW_state_is_scene_render()) {
if (use_sculpt_pbvh) {
struct DRWShadingGroup **shgrps_array = BLI_array_alloca(shgrps_array, materials_len);
@@ -901,6 +902,9 @@ void EEVEE_materials_cache_populate(EEVEE_Data *vedata,
}
}
}
+
+ /* Motion Blur Vectors. */
+ EEVEE_motion_blur_cache_populate(sldata, vedata, ob);
}
/* Volumetrics */
@@ -946,17 +950,15 @@ void EEVEE_object_hair_cache_populate(EEVEE_Data *vedata,
eevee_hair_cache_populate(vedata, sldata, ob, NULL, NULL, HAIR_MATERIAL_NR, cast_shadow);
}
-void EEVEE_materials_cache_finish(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata)
+void EEVEE_materials_cache_finish(EEVEE_ViewLayerData *UNUSED(sldata), EEVEE_Data *vedata)
{
EEVEE_PrivateData *pd = vedata->stl->g_data;
EEVEE_EffectsInfo *effects = vedata->stl->effects;
BLI_ghash_free(pd->material_hash, NULL, NULL);
+ pd->material_hash = NULL;
SET_FLAG_FROM_TEST(effects->enabled_effects, effects->sss_surface_count > 0, EFFECT_SSS);
-
- /* TODO(fclem) this is not really clean. Init should not be done in cache finish. */
- EEVEE_subsurface_draw_init(sldata, vedata);
}
void EEVEE_materials_free(void)
@@ -1015,7 +1017,7 @@ void EEVEE_material_output_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata,
/* Should be enough precision for many samples. */
const eGPUTextureFormat texture_format = (tot_samples > 128) ? GPU_RGBA32F : GPU_RGBA16F;
- const bool do_clear = DRW_state_is_image_render() || (effects->taa_current_sample == 1);
+ const bool do_clear = (effects->taa_current_sample == 1);
/* Create FrameBuffer. */
GPU_framebuffer_ensure_config(&fbl->material_accum_fb,
{GPU_ATTACHMENT_TEXTURE(dtxl->depth), GPU_ATTACHMENT_LEAVE});
diff --git a/source/blender/draw/engines/eevee/eevee_mist.c b/source/blender/draw/engines/eevee/eevee_mist.c
index 7b942784ee9..1cedd334d67 100644
--- a/source/blender/draw/engines/eevee/eevee_mist.c
+++ b/source/blender/draw/engines/eevee/eevee_mist.c
@@ -75,7 +75,7 @@ void EEVEE_mist_output_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata)
{GPU_ATTACHMENT_NONE, GPU_ATTACHMENT_TEXTURE(txl->mist_accum)});
/* Clear texture. */
- if (DRW_state_is_image_render() || effects->taa_current_sample == 1) {
+ if (effects->taa_current_sample == 1) {
GPU_framebuffer_bind(fbl->mist_accum_fb);
GPU_framebuffer_clear_color(fbl->mist_accum_fb, clear);
}
diff --git a/source/blender/draw/engines/eevee/eevee_motion_blur.c b/source/blender/draw/engines/eevee/eevee_motion_blur.c
index a6e6b30a6b1..586ee780f1d 100644
--- a/source/blender/draw/engines/eevee/eevee_motion_blur.c
+++ b/source/blender/draw/engines/eevee/eevee_motion_blur.c
@@ -24,12 +24,19 @@
#include "DRW_render.h"
+#include "BLI_rand.h"
+#include "BLI_string_utils.h"
+
#include "BKE_animsys.h"
#include "BKE_camera.h"
#include "BKE_object.h"
+#include "BKE_screen.h"
#include "DNA_anim_types.h"
#include "DNA_camera_types.h"
+#include "DNA_mesh_types.h"
+#include "DNA_modifier_types.h"
+#include "DNA_particle_types.h"
#include "DNA_screen_types.h"
#include "ED_screen.h"
@@ -37,172 +44,517 @@
#include "DEG_depsgraph.h"
#include "DEG_depsgraph_query.h"
+#include "GPU_batch.h"
#include "GPU_texture.h"
#include "eevee_private.h"
static struct {
/* Motion Blur */
struct GPUShader *motion_blur_sh;
+ struct GPUShader *motion_blur_object_sh;
+ struct GPUShader *motion_blur_hair_sh;
+ struct GPUShader *velocity_tiles_sh;
+ struct GPUShader *velocity_tiles_expand_sh;
} e_data = {NULL}; /* Engine data */
+extern char datatoc_effect_velocity_tile_frag_glsl[];
extern char datatoc_effect_motion_blur_frag_glsl[];
+extern char datatoc_object_motion_frag_glsl[];
+extern char datatoc_object_motion_vert_glsl[];
+extern char datatoc_common_hair_lib_glsl[];
+extern char datatoc_common_view_lib_glsl[];
-static void eevee_motion_blur_camera_get_matrix_at_time(Scene *scene,
- ARegion *region,
- RegionView3D *rv3d,
- View3D *v3d,
- Object *camera,
- float time,
- float r_mat[4][4])
-{
- float obmat[4][4];
+#define EEVEE_VELOCITY_TILE_SIZE 32
- /* HACK */
- Object cam_cpy = *camera;
- Camera camdata_cpy = *(Camera *)(camera->data);
- cam_cpy.data = &camdata_cpy;
+static void eevee_create_shader_motion_blur(void)
+{
+ e_data.motion_blur_sh = DRW_shader_create_fullscreen(
+ datatoc_effect_motion_blur_frag_glsl,
+ "#define EEVEE_VELOCITY_TILE_SIZE " STRINGIFY(EEVEE_VELOCITY_TILE_SIZE) "\n");
+ e_data.motion_blur_object_sh = DRW_shader_create_with_lib(datatoc_object_motion_vert_glsl,
+ NULL,
+ datatoc_object_motion_frag_glsl,
+ datatoc_common_view_lib_glsl,
+ NULL);
+ e_data.velocity_tiles_sh = DRW_shader_create_fullscreen(
+ datatoc_effect_velocity_tile_frag_glsl,
+ "#define TILE_GATHER\n"
+ "#define EEVEE_VELOCITY_TILE_SIZE " STRINGIFY(EEVEE_VELOCITY_TILE_SIZE) "\n");
+ e_data.velocity_tiles_expand_sh = DRW_shader_create_fullscreen(
+ datatoc_effect_velocity_tile_frag_glsl,
+ "#define TILE_EXPANSION\n"
+ "#define EEVEE_VELOCITY_TILE_SIZE " STRINGIFY(EEVEE_VELOCITY_TILE_SIZE) "\n");
+
+ char *vert = BLI_string_joinN(datatoc_common_hair_lib_glsl, datatoc_object_motion_vert_glsl);
+ e_data.motion_blur_hair_sh = DRW_shader_create_with_lib(
+ vert, NULL, datatoc_object_motion_frag_glsl, datatoc_common_view_lib_glsl, "#define HAIR\n");
+ MEM_freeN(vert);
+}
- /* Reset original pointers, so direct evaluation does not attempt to flush
- * animation back to the original object: otherwise viewport with motion
- * blur enabled will always loose non-keyed changes. */
- cam_cpy.id.orig_id = NULL;
- camdata_cpy.id.orig_id = NULL;
+int EEVEE_motion_blur_init(EEVEE_ViewLayerData *UNUSED(sldata), EEVEE_Data *vedata)
+{
+ EEVEE_StorageList *stl = vedata->stl;
+ EEVEE_FramebufferList *fbl = vedata->fbl;
+ EEVEE_EffectsInfo *effects = stl->effects;
const DRWContextState *draw_ctx = DRW_context_state_get();
+ Scene *scene = draw_ctx->scene;
- /* Past matrix */
- /* FIXME : This is a temporal solution that does not take care of parent animations */
- /* Recalc Anim manually */
- BKE_animsys_evaluate_animdata(&camdata_cpy.id, camdata_cpy.adt, time, ADT_RECALC_ALL, false);
- BKE_object_where_is_calc_time(draw_ctx->depsgraph, scene, &cam_cpy, time);
+ /* Viewport not supported for now. */
+ if (!DRW_state_is_scene_render()) {
+ return 0;
+ }
+
+ effects->motion_blur_max = max_ii(0, scene->eevee.motion_blur_max);
+
+ if ((effects->motion_blur_max > 0) && (scene->eevee.flag & SCE_EEVEE_MOTION_BLUR_ENABLED)) {
+ if (!e_data.motion_blur_sh) {
+ eevee_create_shader_motion_blur();
+ }
- /* Compute winmat */
- CameraParams params;
- BKE_camera_params_init(&params);
+ if (DRW_state_is_scene_render()) {
+ int mb_step = effects->motion_blur_step;
+ DRW_view_viewmat_get(NULL, effects->motion_blur.camera[mb_step].viewmat, false);
+ DRW_view_persmat_get(NULL, effects->motion_blur.camera[mb_step].persmat, false);
+ DRW_view_persmat_get(NULL, effects->motion_blur.camera[mb_step].persinv, true);
+ }
- if (v3d != NULL) {
- BKE_camera_params_from_view3d(&params, draw_ctx->depsgraph, v3d, rv3d);
- BKE_camera_params_compute_viewplane(&params, region->winx, region->winy, 1.0f, 1.0f);
+ const float *fs_size = DRW_viewport_size_get();
+ int tx_size[2] = {1 + ((int)fs_size[0] / EEVEE_VELOCITY_TILE_SIZE),
+ 1 + ((int)fs_size[1] / EEVEE_VELOCITY_TILE_SIZE)};
+
+ effects->velocity_tiles_x_tx = DRW_texture_pool_query_2d(
+ tx_size[0], fs_size[1], GPU_RGBA16, &draw_engine_eevee_type);
+ GPU_framebuffer_ensure_config(&fbl->velocity_tiles_fb[0],
+ {
+ GPU_ATTACHMENT_NONE,
+ GPU_ATTACHMENT_TEXTURE(effects->velocity_tiles_x_tx),
+ });
+
+ effects->velocity_tiles_tx = DRW_texture_pool_query_2d(
+ tx_size[0], tx_size[1], GPU_RGBA16, &draw_engine_eevee_type);
+ GPU_framebuffer_ensure_config(&fbl->velocity_tiles_fb[1],
+ {
+ GPU_ATTACHMENT_NONE,
+ GPU_ATTACHMENT_TEXTURE(effects->velocity_tiles_tx),
+ });
+
+ return EFFECT_MOTION_BLUR | EFFECT_POST_BUFFER | EFFECT_VELOCITY_BUFFER;
}
- else {
- BKE_camera_params_from_object(&params, &cam_cpy);
- BKE_camera_params_compute_viewplane(
- &params, scene->r.xsch, scene->r.ysch, scene->r.xasp, scene->r.yasp);
+ return 0;
+}
+
+void EEVEE_motion_blur_step_set(EEVEE_Data *vedata, int step)
+{
+ BLI_assert(step < 3);
+ vedata->stl->effects->motion_blur_step = step;
+}
+
+static void eevee_motion_blur_sync_camera(EEVEE_Data *vedata)
+{
+ EEVEE_EffectsInfo *effects = vedata->stl->effects;
+ if (DRW_state_is_scene_render()) {
+ int mb_step = effects->motion_blur_step;
+ DRW_view_viewmat_get(NULL, effects->motion_blur.camera[mb_step].viewmat, false);
+ DRW_view_persmat_get(NULL, effects->motion_blur.camera[mb_step].persmat, false);
+ DRW_view_persmat_get(NULL, effects->motion_blur.camera[mb_step].persinv, true);
}
- BKE_camera_params_compute_matrix(&params);
+ effects->motion_blur_near_far[0] = fabsf(DRW_view_near_distance_get(NULL));
+ effects->motion_blur_near_far[1] = fabsf(DRW_view_far_distance_get(NULL));
+}
+
+void EEVEE_motion_blur_cache_init(EEVEE_ViewLayerData *UNUSED(sldata), EEVEE_Data *vedata)
+{
+ EEVEE_PassList *psl = vedata->psl;
+ EEVEE_StorageList *stl = vedata->stl;
+ EEVEE_EffectsInfo *effects = stl->effects;
+ EEVEE_MotionBlurData *mb_data = &effects->motion_blur;
+ DefaultTextureList *dtxl = DRW_viewport_texture_list_get();
+ const DRWContextState *draw_ctx = DRW_context_state_get();
+ Scene *scene = draw_ctx->scene;
+
+ if ((effects->enabled_effects & EFFECT_MOTION_BLUR) != 0) {
+ const float *fs_size = DRW_viewport_size_get();
+ int tx_size[2] = {GPU_texture_width(effects->velocity_tiles_tx),
+ GPU_texture_height(effects->velocity_tiles_tx)};
+
+ eevee_motion_blur_sync_camera(vedata);
+
+ DRWShadingGroup *grp;
+ {
+ DRW_PASS_CREATE(psl->velocity_tiles_x, DRW_STATE_WRITE_COLOR);
+ DRW_PASS_CREATE(psl->velocity_tiles, DRW_STATE_WRITE_COLOR);
+
+ /* Create max velocity tiles in 2 passes. One for X and one for Y */
+ GPUShader *sh = e_data.velocity_tiles_sh;
+ grp = DRW_shgroup_create(sh, psl->velocity_tiles_x);
+ DRW_shgroup_uniform_texture(grp, "velocityBuffer", effects->velocity_tx);
+ DRW_shgroup_uniform_ivec2_copy(grp, "velocityBufferSize", (int[2]){fs_size[0], fs_size[1]});
+ DRW_shgroup_uniform_vec2(grp, "viewportSize", DRW_viewport_size_get(), 1);
+ DRW_shgroup_uniform_vec2(grp, "viewportSizeInv", DRW_viewport_invert_size_get(), 1);
+ DRW_shgroup_uniform_ivec2_copy(grp, "gatherStep", (int[2]){1, 0});
+ DRW_shgroup_call_procedural_triangles(grp, NULL, 1);
+
+ grp = DRW_shgroup_create(sh, psl->velocity_tiles);
+ DRW_shgroup_uniform_texture(grp, "velocityBuffer", effects->velocity_tiles_x_tx);
+ DRW_shgroup_uniform_ivec2_copy(grp, "velocityBufferSize", (int[2]){tx_size[0], fs_size[1]});
+ DRW_shgroup_uniform_ivec2_copy(grp, "gatherStep", (int[2]){0, 1});
+ DRW_shgroup_call_procedural_triangles(grp, NULL, 1);
+
+ /* Expand max tiles by keeping the max tile in each tile neighborhood. */
+ DRW_PASS_CREATE(psl->velocity_tiles_expand[0], DRW_STATE_WRITE_COLOR);
+ DRW_PASS_CREATE(psl->velocity_tiles_expand[1], DRW_STATE_WRITE_COLOR);
+ for (int i = 0; i < 2; i++) {
+ GPUTexture *tile_tx = (i == 0) ? effects->velocity_tiles_tx : effects->velocity_tiles_x_tx;
+ GPUShader *sh_expand = e_data.velocity_tiles_expand_sh;
+ grp = DRW_shgroup_create(sh_expand, psl->velocity_tiles_expand[i]);
+ DRW_shgroup_uniform_ivec2_copy(grp, "velocityBufferSize", tx_size);
+ DRW_shgroup_uniform_texture(grp, "velocityBuffer", tile_tx);
+ DRW_shgroup_uniform_vec2(grp, "viewportSize", DRW_viewport_size_get(), 1);
+ DRW_shgroup_uniform_vec2(grp, "viewportSizeInv", DRW_viewport_invert_size_get(), 1);
+ DRW_shgroup_call_procedural_triangles(grp, NULL, 1);
+ }
+ }
+ {
+ DRW_PASS_CREATE(psl->motion_blur, DRW_STATE_WRITE_COLOR);
+ eGPUSamplerState state = 0;
+ int expand_steps = 1 + (max_ii(0, effects->motion_blur_max - 1) / EEVEE_VELOCITY_TILE_SIZE);
+ GPUTexture *tile_tx = (expand_steps & 1) ? effects->velocity_tiles_x_tx :
+ effects->velocity_tiles_tx;
+
+ grp = DRW_shgroup_create(e_data.motion_blur_sh, psl->motion_blur);
+ DRW_shgroup_uniform_texture(grp, "utilTex", EEVEE_materials_get_util_tex());
+ DRW_shgroup_uniform_texture_ref_ex(grp, "colorBuffer", &effects->source_buffer, state);
+ DRW_shgroup_uniform_texture_ref_ex(grp, "depthBuffer", &dtxl->depth, state);
+ DRW_shgroup_uniform_texture_ref_ex(grp, "velocityBuffer", &effects->velocity_tx, state);
+ DRW_shgroup_uniform_texture(grp, "tileMaxBuffer", tile_tx);
+ DRW_shgroup_uniform_float_copy(grp, "depthScale", scene->eevee.motion_blur_depth_scale);
+ DRW_shgroup_uniform_vec2(grp, "nearFar", effects->motion_blur_near_far, 1);
+ DRW_shgroup_uniform_bool_copy(grp, "isPerspective", DRW_view_is_persp_get(NULL));
+ DRW_shgroup_uniform_vec2(grp, "viewportSize", DRW_viewport_size_get(), 1);
+ DRW_shgroup_uniform_vec2(grp, "viewportSizeInv", DRW_viewport_invert_size_get(), 1);
+ DRW_shgroup_uniform_ivec2_copy(grp, "tileBufferSize", tx_size);
+ DRW_shgroup_call_procedural_triangles(grp, NULL, 1);
+ }
+ {
+ DRW_PASS_CREATE(psl->velocity_object, DRW_STATE_WRITE_COLOR | DRW_STATE_DEPTH_EQUAL);
+
+ grp = DRW_shgroup_create(e_data.motion_blur_object_sh, psl->velocity_object);
+ DRW_shgroup_uniform_mat4(grp, "prevViewProjMatrix", mb_data->camera[MB_PREV].persmat);
+ DRW_shgroup_uniform_mat4(grp, "currViewProjMatrix", mb_data->camera[MB_CURR].persmat);
+ DRW_shgroup_uniform_mat4(grp, "nextViewProjMatrix", mb_data->camera[MB_NEXT].persmat);
+
+ DRW_PASS_CREATE(psl->velocity_hair, DRW_STATE_WRITE_COLOR | DRW_STATE_DEPTH_EQUAL);
+
+ mb_data->hair_grp = grp = DRW_shgroup_create(e_data.motion_blur_hair_sh, psl->velocity_hair);
+ DRW_shgroup_uniform_mat4(grp, "prevViewProjMatrix", mb_data->camera[MB_PREV].persmat);
+ DRW_shgroup_uniform_mat4(grp, "currViewProjMatrix", mb_data->camera[MB_CURR].persmat);
+ DRW_shgroup_uniform_mat4(grp, "nextViewProjMatrix", mb_data->camera[MB_NEXT].persmat);
+
+ DRW_pass_link(psl->velocity_object, psl->velocity_hair);
+ }
- /* FIXME Should be done per view (MULTIVIEW) */
- normalize_m4_m4(obmat, cam_cpy.obmat);
- invert_m4(obmat);
- mul_m4_m4m4(r_mat, params.winmat, obmat);
+ EEVEE_motion_blur_data_init(mb_data);
+ }
+ else {
+ psl->motion_blur = NULL;
+ psl->velocity_object = NULL;
+ psl->velocity_hair = NULL;
+ }
}
-static void eevee_create_shader_motion_blur(void)
+void EEVEE_motion_blur_hair_cache_populate(EEVEE_ViewLayerData *UNUSED(sldata),
+ EEVEE_Data *vedata,
+ Object *ob,
+ ParticleSystem *psys,
+ ModifierData *md)
{
- e_data.motion_blur_sh = DRW_shader_create_fullscreen(datatoc_effect_motion_blur_frag_glsl, NULL);
+ EEVEE_PassList *psl = vedata->psl;
+ EEVEE_StorageList *stl = vedata->stl;
+ EEVEE_EffectsInfo *effects = stl->effects;
+ DRWShadingGroup *grp = NULL;
+
+ if (!DRW_state_is_scene_render() || psl->velocity_hair == NULL) {
+ return;
+ }
+
+ /* For now we assume hair objects are always moving. */
+ EEVEE_ObjectMotionData *mb_data = EEVEE_motion_blur_object_data_get(
+ &effects->motion_blur, ob, true);
+
+ if (mb_data) {
+ int mb_step = effects->motion_blur_step;
+ /* Store transform */
+ DRW_hair_duplimat_get(ob, psys, md, mb_data->obmat[mb_step]);
+
+ EEVEE_GeometryMotionData *mb_geom = EEVEE_motion_blur_geometry_data_get(
+ &effects->motion_blur, ob, true);
+
+ if (mb_step == MB_CURR) {
+ /* Fill missing matrices if the object was hidden in previous or next frame. */
+ if (is_zero_m4(mb_data->obmat[MB_PREV])) {
+ copy_m4_m4(mb_data->obmat[MB_PREV], mb_data->obmat[MB_CURR]);
+ }
+ if (is_zero_m4(mb_data->obmat[MB_NEXT])) {
+ copy_m4_m4(mb_data->obmat[MB_NEXT], mb_data->obmat[MB_CURR]);
+ }
+
+ grp = DRW_shgroup_hair_create_sub(ob, psys, md, effects->motion_blur.hair_grp);
+ DRW_shgroup_uniform_mat4(grp, "prevModelMatrix", mb_data->obmat[MB_PREV]);
+ DRW_shgroup_uniform_mat4(grp, "currModelMatrix", mb_data->obmat[MB_CURR]);
+ DRW_shgroup_uniform_mat4(grp, "nextModelMatrix", mb_data->obmat[MB_NEXT]);
+ DRW_shgroup_uniform_texture(grp, "prvBuffer", mb_geom->hair_pos_tx[MB_PREV]);
+ DRW_shgroup_uniform_texture(grp, "nxtBuffer", mb_geom->hair_pos_tx[MB_NEXT]);
+ DRW_shgroup_uniform_bool(grp, "useDeform", &mb_geom->use_deform, 1);
+ }
+ else {
+ /* Store vertex position buffer. */
+ mb_geom->hair_pos[mb_step] = DRW_hair_pos_buffer_get(ob, psys, md);
+ mb_geom->use_deform = true;
+ }
+ }
}
-int EEVEE_motion_blur_init(EEVEE_ViewLayerData *UNUSED(sldata), EEVEE_Data *vedata, Object *camera)
+void EEVEE_motion_blur_cache_populate(EEVEE_ViewLayerData *UNUSED(sldata),
+ EEVEE_Data *vedata,
+ Object *ob)
{
+ EEVEE_PassList *psl = vedata->psl;
EEVEE_StorageList *stl = vedata->stl;
EEVEE_EffectsInfo *effects = stl->effects;
+ DRWShadingGroup *grp = NULL;
- const DRWContextState *draw_ctx = DRW_context_state_get();
- const Scene *scene_eval = DEG_get_evaluated_scene(draw_ctx->depsgraph);
- Scene *scene = draw_ctx->scene;
+ if (!DRW_state_is_scene_render() || psl->velocity_object == NULL) {
+ return;
+ }
- View3D *v3d = draw_ctx->v3d;
- RegionView3D *rv3d = draw_ctx->rv3d;
- ARegion *region = draw_ctx->region;
+ const bool is_dupli = (ob->base_flag & BASE_FROM_DUPLI) != 0;
+ /* For now we assume dupli objects are moving. */
+ const bool object_moves = is_dupli || BKE_object_moves_in_time(ob, true);
+ const bool is_deform = BKE_object_is_deform_modified(DRW_context_state_get()->scene, ob);
- if (scene_eval->eevee.flag & SCE_EEVEE_MOTION_BLUR_ENABLED) {
- /* Update Motion Blur Matrices */
- if (camera && (camera->type == OB_CAMERA) && (camera->data != NULL)) {
- float persmat[4][4];
- float ctime = DEG_get_ctime(draw_ctx->depsgraph);
- float delta = scene_eval->eevee.motion_blur_shutter;
- Object *ob_camera_eval = DEG_get_evaluated_object(draw_ctx->depsgraph, camera);
+ if (!(object_moves || is_deform)) {
+ return;
+ }
- /* Viewport Matrix */
- /* Note: This does not have TAA jitter applied. */
- DRW_view_persmat_get(NULL, persmat, false);
+ EEVEE_ObjectMotionData *mb_data = EEVEE_motion_blur_object_data_get(
+ &effects->motion_blur, ob, false);
- bool view_is_valid = (stl->g_data->view_updated == false);
+ if (mb_data) {
+ int mb_step = effects->motion_blur_step;
+ /* Store transform */
+ copy_m4_m4(mb_data->obmat[mb_step], ob->obmat);
+
+ EEVEE_GeometryMotionData *mb_geom = EEVEE_motion_blur_geometry_data_get(
+ &effects->motion_blur, ob, false);
+
+ if (mb_step == MB_CURR) {
+ GPUBatch *batch = DRW_cache_object_surface_get(ob);
+ if (batch == NULL) {
+ return;
+ }
- if (draw_ctx->evil_C != NULL) {
- struct wmWindowManager *wm = CTX_wm_manager(draw_ctx->evil_C);
- view_is_valid = view_is_valid && (ED_screen_animation_no_scrub(wm) == NULL);
+ /* Fill missing matrices if the object was hidden in previous or next frame. */
+ if (is_zero_m4(mb_data->obmat[MB_PREV])) {
+ copy_m4_m4(mb_data->obmat[MB_PREV], mb_data->obmat[MB_CURR]);
+ }
+ if (is_zero_m4(mb_data->obmat[MB_NEXT])) {
+ copy_m4_m4(mb_data->obmat[MB_NEXT], mb_data->obmat[MB_CURR]);
}
- /* The view is jittered by the oglrenderer. So avoid testing in this case. */
- if (!DRW_state_is_image_render()) {
- view_is_valid = view_is_valid && compare_m4m4(persmat, effects->prev_drw_persmat, FLT_MIN);
- /* WATCH: assume TAA init code runs last. */
- if (scene_eval->eevee.taa_samples == 1) {
- /* Only if TAA is disabled. If not, TAA will update prev_drw_persmat itself. */
- copy_m4_m4(effects->prev_drw_persmat, persmat);
+ grp = DRW_shgroup_create(e_data.motion_blur_object_sh, psl->velocity_object);
+ DRW_shgroup_uniform_mat4(grp, "prevModelMatrix", mb_data->obmat[MB_PREV]);
+ DRW_shgroup_uniform_mat4(grp, "currModelMatrix", mb_data->obmat[MB_CURR]);
+ DRW_shgroup_uniform_mat4(grp, "nextModelMatrix", mb_data->obmat[MB_NEXT]);
+ DRW_shgroup_uniform_bool(grp, "useDeform", &mb_geom->use_deform, 1);
+
+ DRW_shgroup_call(grp, batch, ob);
+
+ if (mb_geom->use_deform) {
+ EEVEE_ObjectEngineData *oedata = EEVEE_object_data_ensure(ob);
+ if (!oedata->geom_update) {
+ /* FIXME(fclem) There can be false positive where the actual mesh is not updated.
+ * This avoids a crash but removes the motion blur from some object.
+ * Maybe an issue with depsgraph tagging. */
+ mb_geom->use_deform = false;
+ oedata->geom_update = false;
+
+ GPU_VERTBUF_DISCARD_SAFE(mb_geom->vbo[MB_PREV]);
+ GPU_VERTBUF_DISCARD_SAFE(mb_geom->vbo[MB_NEXT]);
}
+ /* Keep to modify later (after init). */
+ mb_geom->batch = batch;
}
+ }
+ else if (is_deform) {
+ /* Store vertex position buffer. */
+ mb_geom->vbo[mb_step] = DRW_cache_object_pos_vertbuf_get(ob);
+ mb_geom->use_deform = (mb_geom->vbo[mb_step] != NULL);
+ }
+ else {
+ mb_geom->vbo[mb_step] = NULL;
+ mb_geom->use_deform = false;
+ }
+ }
+}
+
+void EEVEE_motion_blur_cache_finish(EEVEE_Data *vedata)
+{
+ EEVEE_StorageList *stl = vedata->stl;
+ EEVEE_EffectsInfo *effects = stl->effects;
+ GHashIterator ghi;
- effects->motion_blur_mat_cached = view_is_valid && !DRW_state_is_image_render();
+ if ((effects->enabled_effects & EFFECT_MOTION_BLUR) == 0) {
+ return;
+ }
- /* Current matrix */
- if (effects->motion_blur_mat_cached == false) {
- eevee_motion_blur_camera_get_matrix_at_time(
- scene, region, rv3d, v3d, ob_camera_eval, ctime, effects->current_world_to_ndc);
- }
+ int mb_step = effects->motion_blur_step;
+
+ if (mb_step != MB_CURR) {
+ /* Push instances attributes to the GPU. */
+ DRW_render_instance_buffer_finish();
+
+ /* Need to be called after DRW_render_instance_buffer_finish() */
+ /* Also we weed to have a correct fbo bound for DRW_hair_update */
+ GPU_framebuffer_bind(vedata->fbl->main_fb);
+ DRW_hair_update();
- /* Only continue if camera is not being keyed */
- if (DRW_state_is_image_render() ||
- compare_m4m4(persmat, effects->current_world_to_ndc, 0.0001f)) {
- /* Past matrix */
- if (effects->motion_blur_mat_cached == false) {
- eevee_motion_blur_camera_get_matrix_at_time(
- scene, region, rv3d, v3d, ob_camera_eval, ctime - delta, effects->past_world_to_ndc);
-
-#if 0 /* for future high quality blur */
- /* Future matrix */
- eevee_motion_blur_camera_get_matrix_at_time(
- scene, region, rv3d, v3d, ob_camera_eval, ctime + delta, effects->future_world_to_ndc);
-#endif
- invert_m4_m4(effects->current_ndc_to_world, effects->current_world_to_ndc);
+ DRW_cache_restart();
+ }
+
+ for (BLI_ghashIterator_init(&ghi, effects->motion_blur.geom);
+ BLI_ghashIterator_done(&ghi) == false;
+ BLI_ghashIterator_step(&ghi)) {
+ EEVEE_GeometryMotionData *mb_geom = BLI_ghashIterator_getValue(&ghi);
+
+ if (!mb_geom->use_deform) {
+ continue;
+ }
+
+ switch (mb_geom->type) {
+ case EEVEE_HAIR_GEOM_MOTION_DATA:
+ if (mb_step == MB_CURR) {
+ /* TODO(fclem) Check if vertex count mismatch. */
+ mb_geom->use_deform = true;
}
+ else {
+ mb_geom->hair_pos[mb_step] = GPU_vertbuf_duplicate(mb_geom->hair_pos[mb_step]);
- effects->motion_blur_mat_cached = true;
- effects->motion_blur_samples = scene_eval->eevee.motion_blur_samples;
+ /* Create vbo immediately to bind to texture buffer. */
+ GPU_vertbuf_use(mb_geom->hair_pos[mb_step]);
- if (!e_data.motion_blur_sh) {
- eevee_create_shader_motion_blur();
+ mb_geom->hair_pos_tx[mb_step] = GPU_texture_create_from_vertbuf(
+ mb_geom->hair_pos[mb_step]);
+ }
+ break;
+
+ case EEVEE_MESH_GEOM_MOTION_DATA:
+ if (mb_step == MB_CURR) {
+ /* Modify batch to have data from adjacent frames. */
+ GPUBatch *batch = mb_geom->batch;
+ for (int i = 0; i < MB_CURR; i++) {
+ GPUVertBuf *vbo = mb_geom->vbo[i];
+ if (vbo && batch) {
+ if (vbo->vertex_len != batch->verts[0]->vertex_len) {
+ /* Vertex count mismatch, disable deform motion blur. */
+ mb_geom->use_deform = false;
+ }
+
+ if (mb_geom->use_deform == false) {
+ GPU_VERTBUF_DISCARD_SAFE(mb_geom->vbo[MB_PREV]);
+ GPU_VERTBUF_DISCARD_SAFE(mb_geom->vbo[MB_NEXT]);
+ break;
+ }
+ else {
+ /* Modify the batch to include the previous & next position. */
+ if (i == MB_PREV) {
+ GPU_batch_vertbuf_add_ex(batch, vbo, true);
+ mb_geom->vbo[i] = NULL;
+ }
+ else {
+ /* This VBO can be reuse by next time step. Don't pass ownership. */
+ GPU_batch_vertbuf_add_ex(batch, vbo, false);
+ }
+ }
+ }
+ }
+ }
+ else {
+ GPUVertBuf *vbo = mb_geom->vbo[mb_step];
+ /* If this assert fails, it means that different EEVEE_GeometryMotionDatas
+ * has been used for each motion blur step. */
+ BLI_assert(vbo);
+ if (vbo) {
+ /* Use the vbo to perform the copy on the GPU. */
+ GPU_vertbuf_use(vbo);
+ /* Perform a copy to avoid loosing it after RE_engine_frame_set(). */
+ mb_geom->vbo[mb_step] = vbo = GPU_vertbuf_duplicate(vbo);
+ /* Find and replace "pos" attrib name. */
+ int attrib_id = GPU_vertformat_attr_id_get(&vbo->format, "pos");
+ GPU_vertformat_attr_rename(
+ &vbo->format, attrib_id, (mb_step == MB_PREV) ? "prv" : "nxt");
+ }
}
+ break;
- return EFFECT_MOTION_BLUR | EFFECT_POST_BUFFER;
- }
+ default:
+ BLI_assert(0);
+ break;
}
}
-
- return 0;
}
-void EEVEE_motion_blur_cache_init(EEVEE_ViewLayerData *UNUSED(sldata), EEVEE_Data *vedata)
+void EEVEE_motion_blur_swap_data(EEVEE_Data *vedata)
{
- EEVEE_PassList *psl = vedata->psl;
EEVEE_StorageList *stl = vedata->stl;
EEVEE_EffectsInfo *effects = stl->effects;
- DefaultTextureList *dtxl = DRW_viewport_texture_list_get();
- struct GPUBatch *quad = DRW_cache_fullscreen_quad_get();
+ GHashIterator ghi;
- if ((effects->enabled_effects & EFFECT_MOTION_BLUR) != 0) {
- DRW_PASS_CREATE(psl->motion_blur, DRW_STATE_WRITE_COLOR);
+ BLI_assert((effects->enabled_effects & EFFECT_MOTION_BLUR) != 0);
- DRWShadingGroup *grp = DRW_shgroup_create(e_data.motion_blur_sh, psl->motion_blur);
- DRW_shgroup_uniform_int(grp, "samples", &effects->motion_blur_samples, 1);
- DRW_shgroup_uniform_mat4(grp, "currInvViewProjMatrix", effects->current_ndc_to_world);
- DRW_shgroup_uniform_mat4(grp, "pastViewProjMatrix", effects->past_world_to_ndc);
- DRW_shgroup_uniform_texture_ref(grp, "colorBuffer", &effects->source_buffer);
- DRW_shgroup_uniform_texture_ref(grp, "depthBuffer", &dtxl->depth);
- DRW_shgroup_call(grp, quad, NULL);
+ /* Camera Data. */
+ effects->motion_blur.camera[MB_PREV] = effects->motion_blur.camera[MB_CURR];
+
+ /* Object Data. */
+ for (BLI_ghashIterator_init(&ghi, effects->motion_blur.object);
+ BLI_ghashIterator_done(&ghi) == false;
+ BLI_ghashIterator_step(&ghi)) {
+ EEVEE_ObjectMotionData *mb_data = BLI_ghashIterator_getValue(&ghi);
+
+ copy_m4_m4(mb_data->obmat[MB_PREV], mb_data->obmat[MB_NEXT]);
+ }
+
+ /* Deformation Data. */
+ for (BLI_ghashIterator_init(&ghi, effects->motion_blur.geom);
+ BLI_ghashIterator_done(&ghi) == false;
+ BLI_ghashIterator_step(&ghi)) {
+ EEVEE_GeometryMotionData *mb_geom = BLI_ghashIterator_getValue(&ghi);
+
+ switch (mb_geom->type) {
+ case EEVEE_HAIR_GEOM_MOTION_DATA:
+ GPU_VERTBUF_DISCARD_SAFE(mb_geom->hair_pos[MB_PREV]);
+ DRW_TEXTURE_FREE_SAFE(mb_geom->hair_pos_tx[MB_PREV]);
+ mb_geom->hair_pos[MB_PREV] = mb_geom->hair_pos[MB_NEXT];
+ mb_geom->hair_pos_tx[MB_PREV] = mb_geom->hair_pos_tx[MB_NEXT];
+ break;
+
+ case EEVEE_MESH_GEOM_MOTION_DATA:
+ GPU_VERTBUF_DISCARD_SAFE(mb_geom->vbo[MB_PREV]);
+ mb_geom->vbo[MB_PREV] = mb_geom->vbo[MB_NEXT];
+
+ if (mb_geom->vbo[MB_NEXT]) {
+ GPUVertBuf *vbo = mb_geom->vbo[MB_NEXT];
+ int attrib_id = GPU_vertformat_attr_id_get(&vbo->format, "nxt");
+ GPU_vertformat_attr_rename(&vbo->format, attrib_id, "prv");
+ }
+ break;
+
+ default:
+ BLI_assert(0);
+ break;
+ }
}
}
@@ -216,6 +568,30 @@ void EEVEE_motion_blur_draw(EEVEE_Data *vedata)
/* Motion Blur */
if ((effects->enabled_effects & EFFECT_MOTION_BLUR) != 0) {
+ /* Create velocity max tiles in 2 passes. One for each dimension. */
+ GPU_framebuffer_bind(fbl->velocity_tiles_fb[0]);
+ DRW_draw_pass(psl->velocity_tiles_x);
+
+ GPU_framebuffer_bind(fbl->velocity_tiles_fb[1]);
+ DRW_draw_pass(psl->velocity_tiles);
+
+ /* Expand the tiles by reading the neighborhood. Do as many passes as required. */
+ int buf = 0;
+ for (int i = effects->motion_blur_max; i > 0; i -= EEVEE_VELOCITY_TILE_SIZE) {
+ GPU_framebuffer_bind(fbl->velocity_tiles_fb[buf]);
+
+ /* Change viewport to avoid invoking more pixel shaders than necessary since in one of the
+ * buffer the texture is way bigger in height. This avoid creating another texture and
+ * reduce VRAM usage. */
+ int w = GPU_texture_width(effects->velocity_tiles_tx);
+ int h = GPU_texture_height(effects->velocity_tiles_tx);
+ GPU_framebuffer_viewport_set(fbl->velocity_tiles_fb[buf], 0, 0, w, h);
+
+ DRW_draw_pass(psl->velocity_tiles_expand[buf]);
+
+ buf = buf ? 0 : 1;
+ }
+
GPU_framebuffer_bind(effects->target_buffer);
DRW_draw_pass(psl->motion_blur);
SWAP_BUFFERS();
@@ -225,4 +601,8 @@ void EEVEE_motion_blur_draw(EEVEE_Data *vedata)
void EEVEE_motion_blur_free(void)
{
DRW_SHADER_FREE_SAFE(e_data.motion_blur_sh);
+ DRW_SHADER_FREE_SAFE(e_data.motion_blur_object_sh);
+ DRW_SHADER_FREE_SAFE(e_data.motion_blur_hair_sh);
+ DRW_SHADER_FREE_SAFE(e_data.velocity_tiles_sh);
+ DRW_SHADER_FREE_SAFE(e_data.velocity_tiles_expand_sh);
}
diff --git a/source/blender/draw/engines/eevee/eevee_occlusion.c b/source/blender/draw/engines/eevee/eevee_occlusion.c
index f5ebbe08dd1..a075210967c 100644
--- a/source/blender/draw/engines/eevee/eevee_occlusion.c
+++ b/source/blender/draw/engines/eevee/eevee_occlusion.c
@@ -155,7 +155,7 @@ void EEVEE_occlusion_output_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata
{GPU_ATTACHMENT_NONE, GPU_ATTACHMENT_TEXTURE(txl->ao_accum)});
/* Clear texture. */
- if (DRW_state_is_image_render() || effects->taa_current_sample == 1) {
+ if (effects->taa_current_sample == 1) {
GPU_framebuffer_bind(fbl->ao_accum_fb);
GPU_framebuffer_clear_color(fbl->ao_accum_fb, clear);
}
diff --git a/source/blender/draw/engines/eevee/eevee_private.h b/source/blender/draw/engines/eevee/eevee_private.h
index 40008c5c364..5005c5a8ba9 100644
--- a/source/blender/draw/engines/eevee/eevee_private.h
+++ b/source/blender/draw/engines/eevee/eevee_private.h
@@ -29,6 +29,8 @@
#include "DNA_lightprobe_types.h"
+#include "BKE_camera.h"
+
struct EEVEE_ShadowCasterBuffer;
struct GPUFrameBuffer;
struct Object;
@@ -256,7 +258,12 @@ typedef struct EEVEE_PassList {
struct DRWPass *sss_translucency_ps;
struct DRWPass *color_downsample_ps;
struct DRWPass *color_downsample_cube_ps;
+ struct DRWPass *velocity_object;
+ struct DRWPass *velocity_hair;
struct DRWPass *velocity_resolve;
+ struct DRWPass *velocity_tiles_x;
+ struct DRWPass *velocity_tiles;
+ struct DRWPass *velocity_tiles_expand[2];
struct DRWPass *taa_resolve;
struct DRWPass *alpha_checker;
@@ -327,6 +334,8 @@ typedef struct EEVEE_FramebufferList {
struct GPUFrameBuffer *renderpass_fb;
struct GPUFrameBuffer *ao_accum_fb;
struct GPUFrameBuffer *velocity_resolve_fb;
+ struct GPUFrameBuffer *velocity_fb;
+ struct GPUFrameBuffer *velocity_tiles_fb[2];
struct GPUFrameBuffer *update_noise_fb;
@@ -556,6 +565,58 @@ enum {
PROBE_UPDATE_ALL = 0xFFFFFF,
};
+/* ************** MOTION BLUR ************ */
+
+#define MB_PREV 0
+#define MB_NEXT 1
+#define MB_CURR 2
+
+typedef struct EEVEE_MotionBlurData {
+ struct GHash *object;
+ struct GHash *geom;
+ struct {
+ float viewmat[4][4];
+ float persmat[4][4];
+ float persinv[4][4];
+ } camera[3];
+ DRWShadingGroup *hair_grp;
+} EEVEE_MotionBlurData;
+
+typedef struct EEVEE_ObjectKey {
+ /** Object or source object for duplis */
+ struct Object *ob;
+ /** Parent object for duplis */
+ struct Object *parent;
+ /** Dupli objects recursive unique identifier */
+ int id[16]; /* 2*MAX_DUPLI_RECUR */
+} EEVEE_ObjectKey;
+
+typedef struct EEVEE_ObjectMotionData {
+ float obmat[3][4][4];
+} EEVEE_ObjectMotionData;
+
+typedef enum eEEVEEMotionData {
+ EEVEE_MESH_GEOM_MOTION_DATA = 0,
+ EEVEE_HAIR_GEOM_MOTION_DATA,
+} eEEVEEMotionData;
+
+typedef struct EEVEE_GeometryMotionData {
+ eEEVEEMotionData type;
+ int use_deform; /* To disable deform mb if vertcount mismatch. */
+ union {
+ struct {
+ /* Mesh */
+ struct GPUBatch *batch; /* Batch for time = t. */
+ struct GPUVertBuf *vbo[2]; /* Vbo for time = t +/- step. */
+ };
+ struct {
+ /* Hair */
+ struct GPUVertBuf *hair_pos[2]; /* Position buffer for time = t +/- step. */
+ struct GPUTexture *hair_pos_tx[2]; /* Buffer Texture of the corresponding VBO. */
+ };
+ };
+} EEVEE_GeometryMotionData;
+
/* ************ EFFECTS DATA ************* */
typedef enum EEVEE_EffectsFlag {
@@ -607,9 +668,10 @@ typedef struct EEVEE_EffectsInfo {
int taa_render_sample;
int taa_total_sample;
float taa_alpha;
+ bool bypass_drawing;
bool prev_drw_support;
bool prev_is_navigating;
- float prev_drw_persmat[4][4];
+ float prev_drw_persmat[4][4]; /* Used for checking view validity and reprojection. */
struct DRWView *taa_view;
/* Ambient Occlusion */
int ao_depth_layer;
@@ -617,15 +679,24 @@ typedef struct EEVEE_EffectsInfo {
struct GPUTexture *gtao_horizons; /* Textures from pool */
struct GPUTexture *gtao_horizons_debug;
/* Motion Blur */
- float current_world_to_ndc[4][4];
float current_ndc_to_world[4][4];
+ float current_world_to_ndc[4][4];
+ float current_world_to_view[4][4];
float past_world_to_ndc[4][4];
- int motion_blur_samples;
- bool motion_blur_mat_cached;
+ float past_world_to_view[4][4];
+ CameraParams past_cam_params;
+ CameraParams current_cam_params;
+ char motion_blur_step; /* Which step we are evaluating. */
+ int motion_blur_max; /* Maximum distance in pixels a motion blured pixel can cover. */
+ float motion_blur_near_far[2]; /* Camera near/far clip distances (positive). */
+ bool cam_params_init;
+ /* TODO(fclem) Only used in render mode for now.
+ * This is because we are missing a per scene persistent place to hold this. */
+ struct EEVEE_MotionBlurData motion_blur;
/* Velocity Pass */
- float velocity_curr_persinv[4][4];
- float velocity_past_persmat[4][4];
struct GPUTexture *velocity_tx; /* Texture from pool */
+ struct GPUTexture *velocity_tiles_x_tx;
+ struct GPUTexture *velocity_tiles_tx;
/* Depth Of Field */
float dof_near_far[2];
float dof_params[2];
@@ -805,6 +876,7 @@ typedef struct EEVEE_ObjectEngineData {
bool ob_vis, ob_vis_dirty;
bool need_update;
+ bool geom_update;
uint shadow_caster_id;
} EEVEE_ObjectEngineData;
@@ -880,15 +952,25 @@ typedef struct EEVEE_PrivateData {
struct DRWView *world_views[6];
/** For rendering planar reflections. */
struct DRWView *planar_views[MAX_PLANAR];
+
+ int render_tot_samples;
} EEVEE_PrivateData; /* Transient data */
/* eevee_data.c */
+void EEVEE_motion_blur_data_init(EEVEE_MotionBlurData *mb);
+void EEVEE_motion_blur_data_free(EEVEE_MotionBlurData *mb);
void EEVEE_view_layer_data_free(void *sldata);
EEVEE_ViewLayerData *EEVEE_view_layer_data_get(void);
EEVEE_ViewLayerData *EEVEE_view_layer_data_ensure_ex(struct ViewLayer *view_layer);
EEVEE_ViewLayerData *EEVEE_view_layer_data_ensure(void);
EEVEE_ObjectEngineData *EEVEE_object_data_get(Object *ob);
EEVEE_ObjectEngineData *EEVEE_object_data_ensure(Object *ob);
+EEVEE_ObjectMotionData *EEVEE_motion_blur_object_data_get(EEVEE_MotionBlurData *mb,
+ Object *ob,
+ bool hair);
+EEVEE_GeometryMotionData *EEVEE_motion_blur_geometry_data_get(EEVEE_MotionBlurData *mb,
+ Object *ob,
+ bool hair);
EEVEE_LightProbeEngineData *EEVEE_lightprobe_data_get(Object *ob);
EEVEE_LightProbeEngineData *EEVEE_lightprobe_data_ensure(Object *ob);
EEVEE_LightEngineData *EEVEE_light_data_get(Object *ob);
@@ -896,6 +978,8 @@ EEVEE_LightEngineData *EEVEE_light_data_ensure(Object *ob);
EEVEE_WorldEngineData *EEVEE_world_data_get(World *wo);
EEVEE_WorldEngineData *EEVEE_world_data_ensure(World *wo);
+void eevee_id_update(void *vedata, ID *id);
+
/* eevee_materials.c */
struct GPUTexture *EEVEE_materials_get_util_tex(void); /* XXX */
void EEVEE_materials_init(EEVEE_ViewLayerData *sldata,
@@ -1112,8 +1196,17 @@ void EEVEE_subsurface_output_accumulate(EEVEE_ViewLayerData *sldata, EEVEE_Data
void EEVEE_subsurface_free(void);
/* eevee_motion_blur.c */
-int EEVEE_motion_blur_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata, Object *camera);
+int EEVEE_motion_blur_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata);
+void EEVEE_motion_blur_step_set(EEVEE_Data *vedata, int step);
void EEVEE_motion_blur_cache_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata);
+void EEVEE_motion_blur_cache_populate(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata, Object *ob);
+void EEVEE_motion_blur_hair_cache_populate(EEVEE_ViewLayerData *sldata,
+ EEVEE_Data *vedata,
+ Object *ob,
+ struct ParticleSystem *psys,
+ struct ModifierData *md);
+void EEVEE_motion_blur_swap_data(EEVEE_Data *vedata);
+void EEVEE_motion_blur_cache_finish(EEVEE_Data *vedata);
void EEVEE_motion_blur_draw(EEVEE_Data *vedata);
void EEVEE_motion_blur_free(void);
@@ -1127,6 +1220,7 @@ void EEVEE_renderpasses_init(EEVEE_Data *vedata);
void EEVEE_renderpasses_output_init(EEVEE_ViewLayerData *sldata,
EEVEE_Data *vedata,
uint tot_samples);
+void EEVEE_renderpasses_cache_finish(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata);
void EEVEE_renderpasses_output_accumulate(EEVEE_ViewLayerData *sldata,
EEVEE_Data *vedata,
bool post_effect);
@@ -1140,6 +1234,7 @@ bool EEVEE_renderpasses_only_first_sample_pass_active(EEVEE_Data *vedata);
/* eevee_temporal_sampling.c */
void EEVEE_temporal_sampling_reset(EEVEE_Data *vedata);
+void EEVEE_temporal_sampling_create_view(EEVEE_Data *vedata);
int EEVEE_temporal_sampling_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata);
void EEVEE_temporal_sampling_offset_calc(const double ht_point[2],
const float filter_size,
@@ -1183,6 +1278,10 @@ void EEVEE_effects_free(void);
bool EEVEE_render_init(EEVEE_Data *vedata,
struct RenderEngine *engine,
struct Depsgraph *depsgraph);
+void EEVEE_render_view_sync(EEVEE_Data *vedata,
+ struct RenderEngine *engine,
+ struct Depsgraph *depsgraph);
+void EEVEE_render_cache_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata);
void EEVEE_render_cache(void *vedata,
struct Object *ob,
struct RenderEngine *engine,
@@ -1191,6 +1290,10 @@ void EEVEE_render_draw(EEVEE_Data *vedata,
struct RenderEngine *engine,
struct RenderLayer *render_layer,
const struct rcti *rect);
+void EEVEE_render_read_result(EEVEE_Data *vedata,
+ struct RenderEngine *engine,
+ struct RenderLayer *rl,
+ const rcti *rect);
void EEVEE_render_update_passes(struct RenderEngine *engine,
struct Scene *scene,
struct ViewLayer *view_layer);
diff --git a/source/blender/draw/engines/eevee/eevee_render.c b/source/blender/draw/engines/eevee/eevee_render.c
index 89a5ad2198a..f903fa905e8 100644
--- a/source/blender/draw/engines/eevee/eevee_render.c
+++ b/source/blender/draw/engines/eevee/eevee_render.c
@@ -131,6 +131,29 @@ bool EEVEE_render_init(EEVEE_Data *ved, RenderEngine *engine, struct Depsgraph *
&sldata->common_data);
}
+ EEVEE_render_view_sync(vedata, engine, depsgraph);
+
+ /* TODO(sergey): Shall render hold pointer to an evaluated camera instead? */
+ struct Object *ob_camera_eval = DEG_get_evaluated_object(depsgraph, RE_GetCamera(engine->re));
+
+ DRWView *view = (DRWView *)DRW_view_default_get();
+ DRW_view_camtexco_set(view, camtexcofac);
+
+ /* `EEVEE_renderpasses_init` will set the active render passes used by `EEVEE_effects_init`.
+ * `EEVEE_effects_init` needs to go second for TAA. */
+ EEVEE_renderpasses_init(vedata);
+ EEVEE_effects_init(sldata, vedata, ob_camera_eval, false);
+ EEVEE_materials_init(sldata, vedata, stl, fbl);
+ EEVEE_shadows_init(sldata);
+ EEVEE_lightprobes_init(sldata, vedata);
+
+ return true;
+}
+
+void EEVEE_render_view_sync(EEVEE_Data *vedata, RenderEngine *engine, struct Depsgraph *depsgraph)
+{
+ EEVEE_PrivateData *g_data = vedata->stl->g_data;
+
/* Set the pers & view matrix. */
float winmat[4][4], viewmat[4][4], viewinv[4][4];
/* TODO(sergey): Shall render hold pointer to an evaluated camera instead? */
@@ -143,19 +166,13 @@ bool EEVEE_render_init(EEVEE_Data *ved, RenderEngine *engine, struct Depsgraph *
invert_m4_m4(viewmat, viewinv);
DRWView *view = DRW_view_create(viewmat, winmat, NULL, NULL, NULL);
- DRW_view_camtexco_set(view, camtexcofac);
+ DRW_view_reset();
DRW_view_default_set(view);
DRW_view_set_active(view);
+}
- /* `EEVEE_renderpasses_init` will set the active render passes used by `EEVEE_effects_init`.
- * `EEVEE_effects_init` needs to go second for TAA. */
- EEVEE_renderpasses_init(vedata);
- EEVEE_effects_init(sldata, vedata, ob_camera_eval, false);
- EEVEE_materials_init(sldata, vedata, stl, fbl);
- EEVEE_shadows_init(sldata);
- EEVEE_lightprobes_init(sldata, vedata);
-
- /* INIT CACHE */
+void EEVEE_render_cache_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata)
+{
EEVEE_bloom_cache_init(sldata, vedata);
EEVEE_depth_of_field_cache_init(sldata, vedata);
EEVEE_effects_cache_init(sldata, vedata);
@@ -168,8 +185,6 @@ bool EEVEE_render_init(EEVEE_Data *ved, RenderEngine *engine, struct Depsgraph *
EEVEE_subsurface_cache_init(sldata, vedata);
EEVEE_temporal_sampling_cache_init(sldata, vedata);
EEVEE_volumes_cache_init(sldata, vedata);
-
- return true;
}
/* Used by light cache. in this case engine is NULL. */
@@ -182,6 +197,8 @@ void EEVEE_render_cache(void *vedata,
EEVEE_LightProbesInfo *pinfo = sldata->probes;
bool cast_shadow = false;
+ eevee_id_update(vedata, &ob->id);
+
if (pinfo->vis_data.collection) {
/* Used for rendering probe with visibility groups. */
bool ob_vis = BKE_collection_has_object_recursive(pinfo->vis_data.collection, ob);
@@ -478,27 +495,12 @@ static void eevee_render_draw_background(EEVEE_Data *vedata)
void EEVEE_render_draw(EEVEE_Data *vedata, RenderEngine *engine, RenderLayer *rl, const rcti *rect)
{
- const DRWContextState *draw_ctx = DRW_context_state_get();
- const Scene *scene_eval = DEG_get_evaluated_scene(draw_ctx->depsgraph);
const char *viewname = RE_GetActiveRenderView(engine->re);
EEVEE_PassList *psl = vedata->psl;
EEVEE_StorageList *stl = vedata->stl;
EEVEE_FramebufferList *fbl = vedata->fbl;
DefaultTextureList *dtxl = DRW_viewport_texture_list_get();
EEVEE_ViewLayerData *sldata = EEVEE_view_layer_data_ensure();
- EEVEE_PrivateData *g_data = stl->g_data;
-
- /* FINISH CACHE */
- EEVEE_volumes_cache_finish(sldata, vedata);
- EEVEE_materials_cache_finish(sldata, vedata);
- EEVEE_lights_cache_finish(sldata, vedata);
- EEVEE_lightprobes_cache_finish(sldata, vedata);
-
- EEVEE_effects_draw_init(sldata, vedata);
- EEVEE_volumes_draw_init(sldata, vedata);
-
- /* Sort transparents before the loop. */
- DRW_pass_sort_shgroup_z(psl->transparent_pass);
/* Push instances attributes to the GPU. */
DRW_render_instance_buffer_finish();
@@ -508,20 +510,17 @@ void EEVEE_render_draw(EEVEE_Data *vedata, RenderEngine *engine, RenderLayer *rl
GPU_framebuffer_bind(fbl->main_fb);
DRW_hair_update();
- uint tot_sample = scene_eval->eevee.taa_render_samples;
+ /* Sort transparents before the loop. */
+ DRW_pass_sort_shgroup_z(psl->transparent_pass);
+
+ uint tot_sample = stl->g_data->render_tot_samples;
uint render_samples = 0;
/* SSR needs one iteration to start properly. */
- if (stl->effects->enabled_effects & EFFECT_SSR) {
+ if ((stl->effects->enabled_effects & EFFECT_SSR) && !stl->effects->ssr_was_valid_double_buffer) {
tot_sample += 1;
}
- EEVEE_renderpasses_output_init(sldata, vedata, tot_sample);
-
- if (RE_engine_test_break(engine)) {
- return;
- }
-
while (render_samples < tot_sample && !RE_engine_test_break(engine)) {
float clear_col[4] = {0.0f, 0.0f, 0.0f, 0.0f};
float clear_depth = 1.0f;
@@ -617,6 +616,15 @@ void EEVEE_render_draw(EEVEE_Data *vedata, RenderEngine *engine, RenderLayer *rl
RE_engine_update_progress(engine, (float)(render_samples++) / (float)tot_sample);
}
+}
+
+void EEVEE_render_read_result(EEVEE_Data *vedata,
+ RenderEngine *engine,
+ RenderLayer *rl,
+ const rcti *rect)
+{
+ const char *viewname = RE_GetActiveRenderView(engine->re);
+ EEVEE_ViewLayerData *sldata = EEVEE_view_layer_data_ensure();
eevee_render_result_combined(rl, viewname, rect, vedata, sldata);
eevee_render_result_mist(rl, viewname, rect, vedata, sldata);
@@ -631,9 +639,6 @@ void EEVEE_render_draw(EEVEE_Data *vedata, RenderEngine *engine, RenderLayer *rl
eevee_render_result_bloom(rl, viewname, rect, vedata, sldata);
eevee_render_result_volume_scatter(rl, viewname, rect, vedata, sldata);
eevee_render_result_volume_transmittance(rl, viewname, rect, vedata, sldata);
-
- /* Restore original viewport size. */
- DRW_render_viewport_size_set((int[2]){g_data->size_orig[0], g_data->size_orig[1]});
}
void EEVEE_render_update_passes(RenderEngine *engine, Scene *scene, ViewLayer *view_layer)
diff --git a/source/blender/draw/engines/eevee/eevee_renderpasses.c b/source/blender/draw/engines/eevee/eevee_renderpasses.c
index 9a47ca19e7b..be771d7cf42 100644
--- a/source/blender/draw/engines/eevee/eevee_renderpasses.c
+++ b/source/blender/draw/engines/eevee/eevee_renderpasses.c
@@ -136,24 +136,13 @@ void EEVEE_renderpasses_output_init(EEVEE_ViewLayerData *sldata,
{
EEVEE_FramebufferList *fbl = vedata->fbl;
EEVEE_TextureList *txl = vedata->txl;
- EEVEE_PassList *psl = vedata->psl;
EEVEE_StorageList *stl = vedata->stl;
EEVEE_EffectsInfo *effects = stl->effects;
EEVEE_PrivateData *g_data = stl->g_data;
- DefaultTextureList *dtxl = DRW_viewport_texture_list_get();
const bool needs_post_processing = (g_data->render_passes &
EEVEE_RENDERPASSES_WITH_POST_PROCESSING) > 0;
if (needs_post_processing) {
- if (e_data.postprocess_sh == NULL) {
- char *frag_str = BLI_string_joinN(datatoc_common_view_lib_glsl,
- datatoc_common_uniforms_lib_glsl,
- datatoc_bsdf_common_lib_glsl,
- datatoc_renderpass_postprocess_frag_glsl);
- e_data.postprocess_sh = DRW_shader_create_fullscreen(frag_str, NULL);
- MEM_freeN(frag_str);
- }
-
/* Create FrameBuffer. */
/* Should be enough to store the data needs for a single pass.
@@ -188,29 +177,51 @@ void EEVEE_renderpasses_output_init(EEVEE_ViewLayerData *sldata,
EEVEE_volumes_output_init(sldata, vedata, tot_samples);
}
- /* Create Pass. */
- DRW_PASS_CREATE(psl->renderpass_pass, DRW_STATE_WRITE_COLOR);
- DRWShadingGroup *grp = DRW_shgroup_create(e_data.postprocess_sh, psl->renderpass_pass);
/* We set a default texture as not all post processes uses the inputBuffer. */
g_data->renderpass_input = txl->color;
g_data->renderpass_col_input = txl->color;
g_data->renderpass_light_input = txl->color;
+ }
+ else {
+ /* Free unneeded memory */
+ DRW_TEXTURE_FREE_SAFE(txl->renderpass);
+ GPU_FRAMEBUFFER_FREE_SAFE(fbl->renderpass_fb);
+ }
+}
+
+void EEVEE_renderpasses_cache_finish(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata)
+{
+ EEVEE_PassList *psl = vedata->psl;
+ EEVEE_PrivateData *g_data = vedata->stl->g_data;
+ DefaultTextureList *dtxl = DRW_viewport_texture_list_get();
+
+ const bool needs_post_processing = (g_data->render_passes &
+ EEVEE_RENDERPASSES_WITH_POST_PROCESSING) > 0;
+ if (needs_post_processing) {
+ if (e_data.postprocess_sh == NULL) {
+ char *frag_str = BLI_string_joinN(datatoc_common_view_lib_glsl,
+ datatoc_common_uniforms_lib_glsl,
+ datatoc_bsdf_common_lib_glsl,
+ datatoc_renderpass_postprocess_frag_glsl);
+ e_data.postprocess_sh = DRW_shader_create_fullscreen(frag_str, NULL);
+ MEM_freeN(frag_str);
+ }
+
+ DRW_PASS_CREATE(psl->renderpass_pass, DRW_STATE_WRITE_COLOR);
+ DRWShadingGroup *grp = DRW_shgroup_create(e_data.postprocess_sh, psl->renderpass_pass);
DRW_shgroup_uniform_texture_ref(grp, "inputBuffer", &g_data->renderpass_input);
DRW_shgroup_uniform_texture_ref(grp, "inputColorBuffer", &g_data->renderpass_col_input);
DRW_shgroup_uniform_texture_ref(
grp, "inputSecondLightBuffer", &g_data->renderpass_light_input);
DRW_shgroup_uniform_texture_ref(grp, "depthBuffer", &dtxl->depth);
- DRW_shgroup_uniform_block(grp, "common_block", sldata->common_ubo);
- DRW_shgroup_uniform_block(grp, "renderpass_block", sldata->renderpass_ubo.combined);
+ DRW_shgroup_uniform_block_ref(grp, "common_block", &sldata->common_ubo);
+ DRW_shgroup_uniform_block_ref(grp, "renderpass_block", &sldata->renderpass_ubo.combined);
DRW_shgroup_uniform_int(grp, "currentSample", &g_data->renderpass_current_sample, 1);
DRW_shgroup_uniform_int(grp, "renderpassType", &g_data->renderpass_type, 1);
DRW_shgroup_uniform_int(grp, "postProcessType", &g_data->renderpass_postprocess, 1);
DRW_shgroup_call(grp, DRW_cache_fullscreen_quad_get(), NULL);
}
else {
- /* Free unneeded memory */
- DRW_TEXTURE_FREE_SAFE(txl->renderpass);
- GPU_FRAMEBUFFER_FREE_SAFE(fbl->renderpass_fb);
psl->renderpass_pass = NULL;
}
}
diff --git a/source/blender/draw/engines/eevee/eevee_screen_raytrace.c b/source/blender/draw/engines/eevee/eevee_screen_raytrace.c
index cece67334c5..32d758dba4b 100644
--- a/source/blender/draw/engines/eevee/eevee_screen_raytrace.c
+++ b/source/blender/draw/engines/eevee/eevee_screen_raytrace.c
@@ -358,7 +358,7 @@ void EEVEE_reflection_output_init(EEVEE_ViewLayerData *UNUSED(sldata),
{GPU_ATTACHMENT_NONE, GPU_ATTACHMENT_TEXTURE(txl->ssr_accum)});
/* Clear texture. */
- if (DRW_state_is_image_render() || effects->taa_current_sample == 1) {
+ if (effects->taa_current_sample == 1) {
GPU_framebuffer_bind(fbl->ssr_accum_fb);
GPU_framebuffer_clear_color(fbl->ssr_accum_fb, clear);
}
diff --git a/source/blender/draw/engines/eevee/eevee_shadows.c b/source/blender/draw/engines/eevee/eevee_shadows.c
index 84c50a22ae6..d0e430e115f 100644
--- a/source/blender/draw/engines/eevee/eevee_shadows.c
+++ b/source/blender/draw/engines/eevee/eevee_shadows.c
@@ -412,7 +412,7 @@ void EEVEE_shadow_output_init(EEVEE_ViewLayerData *sldata,
{GPU_ATTACHMENT_NONE, GPU_ATTACHMENT_TEXTURE(txl->shadow_accum)});
/* Clear texture. */
- if (DRW_state_is_image_render() || effects->taa_current_sample == 1) {
+ if (effects->taa_current_sample == 1) {
GPU_framebuffer_bind(fbl->shadow_accum_fb);
GPU_framebuffer_clear_color(fbl->shadow_accum_fb, clear);
}
diff --git a/source/blender/draw/engines/eevee/eevee_subsurface.c b/source/blender/draw/engines/eevee/eevee_subsurface.c
index 7674148f76a..ef4588f4aca 100644
--- a/source/blender/draw/engines/eevee/eevee_subsurface.c
+++ b/source/blender/draw/engines/eevee/eevee_subsurface.c
@@ -75,18 +75,8 @@ static void eevee_create_shader_subsurface(void)
MEM_freeN(frag_str);
}
-void EEVEE_subsurface_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata)
+void EEVEE_subsurface_init(EEVEE_ViewLayerData *UNUSED(sldata), EEVEE_Data *UNUSED(vedata))
{
- EEVEE_CommonUniformBuffer *common_data = &sldata->common_data;
- EEVEE_StorageList *stl = vedata->stl;
- EEVEE_EffectsInfo *effects = stl->effects;
-
- const DRWContextState *draw_ctx = DRW_context_state_get();
- const Scene *scene_eval = DEG_get_evaluated_scene(draw_ctx->depsgraph);
-
- effects->sss_sample_count = 1 + scene_eval->eevee.sss_samples * 2;
- effects->sss_surface_count = 0;
- common_data->sss_jitter_threshold = scene_eval->eevee.sss_jitter_threshold;
}
void EEVEE_subsurface_draw_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata)
@@ -197,22 +187,31 @@ void EEVEE_subsurface_output_init(EEVEE_ViewLayerData *UNUSED(sldata),
* already higher than one. This is noticeable when loading a file that has the diffuse light
* pass in look dev mode active. `texture_created` will make sure that newly created textures
* are cleared. */
- if (DRW_state_is_image_render() || effects->taa_current_sample == 1 || texture_created) {
+ if (effects->taa_current_sample == 1 || texture_created) {
float clear[4] = {0.0f, 0.0f, 0.0f, 0.0f};
GPU_framebuffer_bind(fbl->sss_accum_fb);
GPU_framebuffer_clear_color(fbl->sss_accum_fb, clear);
}
}
-void EEVEE_subsurface_cache_init(EEVEE_ViewLayerData *UNUSED(sldata), EEVEE_Data *vedata)
+void EEVEE_subsurface_cache_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata)
{
+ EEVEE_CommonUniformBuffer *common_data = &sldata->common_data;
+ EEVEE_EffectsInfo *effects = vedata->stl->effects;
EEVEE_PassList *psl = vedata->psl;
+ const DRWContextState *draw_ctx = DRW_context_state_get();
+ const Scene *scene_eval = DEG_get_evaluated_scene(draw_ctx->depsgraph);
+
/* Shaders */
if (!e_data.sss_sh[0]) {
eevee_create_shader_subsurface();
}
+ effects->sss_sample_count = 1 + scene_eval->eevee.sss_samples * 2;
+ effects->sss_surface_count = 0;
+ common_data->sss_jitter_threshold = scene_eval->eevee.sss_jitter_threshold;
+
/** Screen Space SubSurface Scattering overview
* TODO
*/
diff --git a/source/blender/draw/engines/eevee/eevee_temporal_sampling.c b/source/blender/draw/engines/eevee/eevee_temporal_sampling.c
index d57048f2c4e..714481c39f1 100644
--- a/source/blender/draw/engines/eevee/eevee_temporal_sampling.c
+++ b/source/blender/draw/engines/eevee/eevee_temporal_sampling.c
@@ -186,6 +186,18 @@ void EEVEE_temporal_sampling_reset(EEVEE_Data *vedata)
vedata->stl->effects->taa_current_sample = 1;
}
+void EEVEE_temporal_sampling_create_view(EEVEE_Data *vedata)
+{
+ EEVEE_EffectsInfo *effects = vedata->stl->effects;
+ /* Create a sub view to disable clipping planes (if any). */
+ const DRWView *default_view = DRW_view_default_get();
+ float viewmat[4][4], winmat[4][4];
+ DRW_view_viewmat_get(default_view, viewmat, false);
+ DRW_view_winmat_get(default_view, winmat, false);
+ effects->taa_view = DRW_view_create_sub(default_view, viewmat, winmat);
+ DRW_view_clip_planes_set(effects->taa_view, NULL, 0);
+}
+
int EEVEE_temporal_sampling_init(EEVEE_ViewLayerData *UNUSED(sldata), EEVEE_Data *vedata)
{
EEVEE_StorageList *stl = vedata->stl;
@@ -201,15 +213,9 @@ int EEVEE_temporal_sampling_init(EEVEE_ViewLayerData *UNUSED(sldata), EEVEE_Data
* we accumulate the redraw inside the drawing loop in eevee_draw_scene().
**/
effects->taa_render_sample = 1;
- effects->taa_view = NULL;
+ effects->bypass_drawing = false;
- /* Create a sub view to disable clipping planes (if any). */
- const DRWView *default_view = DRW_view_default_get();
- float viewmat[4][4], winmat[4][4];
- DRW_view_viewmat_get(default_view, viewmat, false);
- DRW_view_winmat_get(default_view, winmat, false);
- effects->taa_view = DRW_view_create_sub(default_view, viewmat, winmat);
- DRW_view_clip_planes_set(effects->taa_view, NULL, 0);
+ EEVEE_temporal_sampling_create_view(vedata);
const DRWContextState *draw_ctx = DRW_context_state_get();
const Scene *scene_eval = DEG_get_evaluated_scene(draw_ctx->depsgraph);
@@ -241,7 +247,6 @@ int EEVEE_temporal_sampling_init(EEVEE_ViewLayerData *UNUSED(sldata), EEVEE_Data
DRW_view_persmat_get(NULL, persmat, false);
view_is_valid = view_is_valid && compare_m4m4(persmat, effects->prev_drw_persmat, FLT_MIN);
- copy_m4_m4(effects->prev_drw_persmat, persmat);
/* Prevent ghosting from probe data. */
view_is_valid = view_is_valid && (effects->prev_drw_support == DRW_state_draw_support()) &&
@@ -251,7 +256,7 @@ int EEVEE_temporal_sampling_init(EEVEE_ViewLayerData *UNUSED(sldata), EEVEE_Data
if (((effects->taa_total_sample == 0) ||
(effects->taa_current_sample < effects->taa_total_sample)) ||
- DRW_state_is_image_render()) {
+ (!view_is_valid) || DRW_state_is_image_render()) {
if (view_is_valid) {
/* Viewport rendering updates the matrices in `eevee_draw_scene` */
if (!DRW_state_is_image_render()) {
@@ -264,7 +269,7 @@ int EEVEE_temporal_sampling_init(EEVEE_ViewLayerData *UNUSED(sldata), EEVEE_Data
}
}
else {
- effects->taa_current_sample = 1;
+ effects->bypass_drawing = true;
}
return repro_flag | EFFECT_TAA | EFFECT_DOUBLE_BUFFER | EFFECT_DEPTH_DOUBLE_BUFFER |
@@ -283,7 +288,7 @@ void EEVEE_temporal_sampling_cache_init(EEVEE_ViewLayerData *sldata, EEVEE_Data
EEVEE_TextureList *txl = vedata->txl;
EEVEE_EffectsInfo *effects = stl->effects;
- if ((effects->enabled_effects & (EFFECT_TAA | EFFECT_TAA_REPROJECT)) != 0) {
+ if (effects->enabled_effects & EFFECT_TAA) {
struct GPUShader *sh = EEVEE_shaders_taa_resolve_sh_get(effects->enabled_effects);
DRW_PASS_CREATE(psl->taa_resolve, DRW_STATE_WRITE_COLOR);
@@ -295,8 +300,9 @@ void EEVEE_temporal_sampling_cache_init(EEVEE_ViewLayerData *sldata, EEVEE_Data
DRW_shgroup_uniform_block(grp, "renderpass_block", sldata->renderpass_ubo.combined);
if (effects->enabled_effects & EFFECT_TAA_REPROJECT) {
- // DefaultTextureList *dtxl = DRW_viewport_texture_list_get();
- DRW_shgroup_uniform_texture_ref(grp, "velocityBuffer", &effects->velocity_tx);
+ DefaultTextureList *dtxl = DRW_viewport_texture_list_get();
+ DRW_shgroup_uniform_texture_ref(grp, "depthBuffer", &dtxl->depth);
+ DRW_shgroup_uniform_mat4(grp, "prevViewProjectionMatrix", effects->prev_drw_persmat);
}
else {
DRW_shgroup_uniform_float(grp, "alpha", &effects->taa_alpha, 1);
@@ -359,10 +365,13 @@ void EEVEE_temporal_sampling_draw(EEVEE_Data *vedata)
effects->taa_current_sample += 1;
}
else {
- if ((effects->taa_total_sample == 0) ||
- (effects->taa_current_sample < effects->taa_total_sample)) {
+ if (!DRW_state_is_playback() &&
+ ((effects->taa_total_sample == 0) ||
+ (effects->taa_current_sample < effects->taa_total_sample))) {
DRW_viewport_request_redraw();
}
}
+
+ DRW_view_persmat_get(NULL, effects->prev_drw_persmat, false);
}
}
diff --git a/source/blender/draw/engines/eevee/eevee_volumes.c b/source/blender/draw/engines/eevee/eevee_volumes.c
index 90860e94270..17f53113939 100644
--- a/source/blender/draw/engines/eevee/eevee_volumes.c
+++ b/source/blender/draw/engines/eevee/eevee_volumes.c
@@ -894,7 +894,7 @@ void EEVEE_volumes_output_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata,
GPU_ATTACHMENT_TEXTURE(txl->volume_transmittance_accum)});
/* Clear texture. */
- if (DRW_state_is_image_render() || effects->taa_current_sample == 1) {
+ if (effects->taa_current_sample == 1) {
GPU_framebuffer_bind(fbl->volumetric_accum_fb);
GPU_framebuffer_clear_color(fbl->volumetric_accum_fb, clear);
}
diff --git a/source/blender/draw/engines/eevee/shaders/bsdf_common_lib.glsl b/source/blender/draw/engines/eevee/shaders/bsdf_common_lib.glsl
index 402d306df45..393ecaf1fc5 100644
--- a/source/blender/draw/engines/eevee/shaders/bsdf_common_lib.glsl
+++ b/source/blender/draw/engines/eevee/shaders/bsdf_common_lib.glsl
@@ -877,6 +877,14 @@ Closure closure_mix(Closure cl1, Closure cl2, float fac)
{
Closure cl;
cl.holdout = mix(cl1.holdout, cl2.holdout, fac);
+
+ if (FLAG_TEST(cl1.flag, CLOSURE_HOLDOUT_FLAG)) {
+ fac = 1.0;
+ }
+ else if (FLAG_TEST(cl2.flag, CLOSURE_HOLDOUT_FLAG)) {
+ fac = 0.0;
+ }
+
cl.transmittance = mix(cl1.transmittance, cl2.transmittance, fac);
cl.radiance = mix(cl1.radiance, cl2.radiance, fac);
cl.flag = cl1.flag | cl2.flag;
@@ -958,7 +966,7 @@ void main()
{
Closure cl = nodetree_exec();
- float holdout = 1.0 - saturate(cl.holdout);
+ float holdout = saturate(1.0 - cl.holdout);
float transmit = saturate(avg(cl.transmittance));
float alpha = 1.0 - transmit;
@@ -972,8 +980,9 @@ void main()
* Since we do that using the blending pipeline we need to account for material transmittance. */
vol_scatter -= vol_scatter * cl.transmittance;
- outRadiance = vec4(cl.radiance * vol_transmit + vol_scatter, alpha * holdout);
- outTransmittance = vec4(cl.transmittance, transmit * holdout);
+ cl.radiance = cl.radiance * holdout * vol_transmit + vol_scatter;
+ outRadiance = vec4(cl.radiance, alpha * holdout);
+ outTransmittance = vec4(cl.transmittance, transmit) * holdout;
# else
outRadiance = vec4(cl.radiance, holdout);
ssrNormals = cl.ssr_normal;
diff --git a/source/blender/draw/engines/eevee/shaders/effect_motion_blur_frag.glsl b/source/blender/draw/engines/eevee/shaders/effect_motion_blur_frag.glsl
index b7935235d06..fbf507a2e40 100644
--- a/source/blender/draw/engines/eevee/shaders/effect_motion_blur_frag.glsl
+++ b/source/blender/draw/engines/eevee/shaders/effect_motion_blur_frag.glsl
@@ -1,64 +1,235 @@
+/*
+ * Based on:
+ * A Fast and Stable Feature-Aware Motion Blur Filter
+ * by Jean-Philippe Guertin, Morgan McGuire, Derek Nowrouzezahrai
+ *
+ * With modification from the presentation:
+ * Next Generation Post Processing in Call of Duty Advanced Warfare
+ * by Jorge Jimenez
+ */
uniform sampler2D colorBuffer;
uniform sampler2D depthBuffer;
+uniform sampler2D velocityBuffer;
+uniform sampler2D tileMaxBuffer;
-/* current frame */
-uniform mat4 currInvViewProjMatrix;
+#define KERNEL 8
-/* past frame frame */
-uniform mat4 pastViewProjMatrix;
+/* TODO(fclem) deduplicate this code. */
+uniform sampler2DArray utilTex;
+#define LUT_SIZE 64
+#define texelfetch_noise_tex(coord) texelFetch(utilTex, ivec3(ivec2(coord) % LUT_SIZE, 2.0), 0)
+
+uniform float depthScale;
+uniform ivec2 tileBufferSize;
+uniform vec2 viewportSize;
+uniform vec2 viewportSizeInv;
+uniform bool isPerspective;
+uniform vec2 nearFar; /* Near & far view depths values */
+
+#define linear_depth(z) \
+ ((isPerspective) ? (nearFar.x * nearFar.y) / (z * (nearFar.x - nearFar.y) + nearFar.y) : \
+ z * (nearFar.y - nearFar.x) + nearFar.x) /* Only true for camera view! */
in vec4 uvcoordsvar;
-out vec4 FragColor;
+out vec4 fragColor;
-#define MAX_SAMPLE 64
+#define saturate(a) clamp(a, 0.0, 1.0)
-uniform int samples;
+vec2 spread_compare(float center_motion_length, float sample_motion_length, float offset_length)
+{
+ return saturate(vec2(center_motion_length, sample_motion_length) - offset_length + 1.0);
+}
-float wang_hash_noise(uint s)
+vec2 depth_compare(float center_depth, float sample_depth)
{
- uint seed = (uint(gl_FragCoord.x) * 1664525u + uint(gl_FragCoord.y)) + s;
+ return saturate(0.5 + vec2(depthScale, -depthScale) * (sample_depth - center_depth));
+}
- seed = (seed ^ 61u) ^ (seed >> 16u);
- seed *= 9u;
- seed = seed ^ (seed >> 4u);
- seed *= 0x27d4eb2du;
- seed = seed ^ (seed >> 15u);
+/* Kill contribution if not going the same direction. */
+float dir_compare(vec2 offset, vec2 sample_motion, float sample_motion_length)
+{
+ if (sample_motion_length < 0.5) {
+ return 1.0;
+ }
+ return (dot(offset, sample_motion) > 0.0) ? 1.0 : 0.0;
+}
- float value = float(seed);
- value *= 1.0 / 4294967296.0;
- return fract(value);
+/* Return background (x) and foreground (y) weights. */
+vec2 sample_weights(float center_depth,
+ float sample_depth,
+ float center_motion_length,
+ float sample_motion_length,
+ float offset_length)
+{
+ /* Clasify foreground/background. */
+ vec2 depth_weight = depth_compare(center_depth, sample_depth);
+ /* Weight if sample is overlapping or under the center pixel. */
+ vec2 spread_weight = spread_compare(center_motion_length, sample_motion_length, offset_length);
+ return depth_weight * spread_weight;
}
-void main()
+vec4 decode_velocity(vec4 velocity)
{
- vec3 ndc_pos;
- ndc_pos.xy = uvcoordsvar.xy;
- ndc_pos.z = texture(depthBuffer, uvcoordsvar.xy).x;
+ velocity = velocity * 2.0 - 1.0;
+ /* Needed to match cycles. Can't find why... (fclem) */
+ velocity *= 0.5;
+ /* Transpose to pixelspace. */
+ velocity *= viewportSize.xyxy;
+ return velocity;
+}
- float inv_samples = 1.0 / float(samples);
- float noise = 2.0 * wang_hash_noise(0u) * inv_samples;
+vec4 sample_velocity(vec2 uv)
+{
+ vec4 data = texture(velocityBuffer, uv);
+ return decode_velocity(data);
+}
- /* Normalize Device Coordinates are [-1, +1]. */
- ndc_pos = ndc_pos * 2.0 - 1.0;
+vec2 sample_velocity(vec2 uv, const bool next)
+{
+ vec4 data = sample_velocity(uv);
+ data.xy = (next ? data.zw : data.xy);
+ return data.xy;
+}
- vec4 p = currInvViewProjMatrix * vec4(ndc_pos, 1.0);
- vec3 world_pos = p.xyz / p.w; /* Perspective divide */
+void gather_sample(vec2 screen_uv,
+ float center_depth,
+ float center_motion_len,
+ vec2 offset,
+ float offset_len,
+ const bool next,
+ inout vec4 accum,
+ inout vec4 accum_bg,
+ inout vec3 w_accum)
+{
+ vec2 sample_uv = screen_uv - offset * viewportSizeInv;
+ vec2 sample_motion = sample_velocity(sample_uv, next);
+ float sample_motion_len = length(sample_motion);
+ float sample_depth = linear_depth(texture(depthBuffer, sample_uv).r);
+ vec4 col = textureLod(colorBuffer, sample_uv, 0.0);
+
+ vec3 weights;
+ weights.xy = sample_weights(
+ center_depth, sample_depth, center_motion_len, sample_motion_len, offset_len);
+ weights.z = dir_compare(offset, sample_motion, sample_motion_len);
+ weights.xy *= weights.z;
+
+ accum += col * weights.y;
+ accum_bg += col * weights.x;
+ w_accum += weights;
+}
- /* Now find where was this pixel position
- * inside the past camera viewport */
- vec4 old_ndc = pastViewProjMatrix * vec4(world_pos, 1.0);
- old_ndc.xyz /= old_ndc.w; /* Perspective divide */
+void gather_blur(vec2 screen_uv,
+ vec2 center_motion,
+ float center_depth,
+ vec2 max_motion,
+ float ofs,
+ const bool next,
+ inout vec4 accum,
+ inout vec4 accum_bg,
+ inout vec3 w_accum)
+{
+ float center_motion_len = length(center_motion);
+ float max_motion_len = length(max_motion);
+
+ /* Tile boundaries randomization can fetch a tile where there is less motion than this pixel.
+ * Fix this by overriding the max_motion. */
+ if (max_motion_len < center_motion_len) {
+ max_motion_len = center_motion_len;
+ max_motion = center_motion;
+ }
- vec2 motion = (ndc_pos.xy - old_ndc.xy) * 0.25; /* 0.25 fit cycles ref */
+ if (max_motion_len < 0.5) {
+ return;
+ }
- float inc = 2.0 * inv_samples;
- float i = -1.0 + noise;
+ int i;
+ float t, inc = 1.0 / float(KERNEL);
+ for (i = 0, t = ofs * inc; i < KERNEL; i++, t += inc) {
+ gather_sample(screen_uv,
+ center_depth,
+ center_motion_len,
+ max_motion * t,
+ max_motion_len * t,
+ next,
+ accum,
+ accum_bg,
+ w_accum);
+ }
- FragColor = vec4(0.0);
- for (int j = 0; j < samples && j < MAX_SAMPLE; j++) {
- FragColor += textureLod(colorBuffer, uvcoordsvar.xy + motion * i, 0.0) * inv_samples;
- i += inc;
+ if (center_motion_len < 0.5) {
+ return;
}
+
+ for (i = 0, t = ofs * inc; i < KERNEL; i++, t += inc) {
+ /* Also sample in center motion direction.
+ * Allow to recover motion where there is conflicting
+ * motion between foreground and background. */
+ gather_sample(screen_uv,
+ center_depth,
+ center_motion_len,
+ center_motion * t,
+ center_motion_len * t,
+ next,
+ accum,
+ accum_bg,
+ w_accum);
+ }
+}
+
+void main()
+{
+ vec2 uv = uvcoordsvar.xy;
+
+ /* Data of the center pixel of the gather (target). */
+ float center_depth = linear_depth(texture(depthBuffer, uv).r);
+ vec4 center_motion = sample_velocity(uv);
+ vec4 center_color = textureLod(colorBuffer, uv, 0.0);
+
+ vec2 rand = texelfetch_noise_tex(gl_FragCoord.xy).xy;
+
+ /* Randomize tile boundary to avoid ugly discontinuities. Randomize 1/4th of the tile.
+ * Note this randomize only in one direction but in practice it's enough. */
+ rand.x = rand.x * 2.0 - 1.0;
+ ivec2 tile = ivec2(gl_FragCoord.xy + rand.x * float(EEVEE_VELOCITY_TILE_SIZE) * 0.25) /
+ EEVEE_VELOCITY_TILE_SIZE;
+ tile = clamp(tile, ivec2(0), tileBufferSize - 1);
+ vec4 max_motion = decode_velocity(texelFetch(tileMaxBuffer, tile, 0));
+
+ /* First (center) sample: time = T */
+ /* x: Background, y: Foreground, z: dir. */
+ vec3 w_accum = vec3(0.0, 0.0, 1.0);
+ vec4 accum_bg = vec4(0.0);
+ vec4 accum = vec4(0.0);
+ /* First linear gather. time = [T - delta, T] */
+ gather_blur(
+ uv, center_motion.xy, center_depth, max_motion.xy, rand.y, false, accum, accum_bg, w_accum);
+ /* Second linear gather. time = [T, T + delta] */
+ gather_blur(
+ uv, center_motion.zw, center_depth, max_motion.zw, rand.y, true, accum, accum_bg, w_accum);
+
+#if 1
+ /* Avoid division by 0.0. */
+ float w = 1.0 / (50.0 * float(KERNEL) * 4.0);
+ accum_bg += center_color * w;
+ w_accum.x += w;
+ /* Note: In Jimenez's presentation, they used center sample.
+ * We use background color as it contains more informations for foreground
+ * elements that have not enough weights.
+ * Yield beter blur in complex motion. */
+ center_color = accum_bg / w_accum.x;
+#endif
+ /* Merge background. */
+ accum += accum_bg;
+ w_accum.y += w_accum.x;
+ /* Balance accumulation for failled samples.
+ * We replace the missing foreground by the background. */
+ float blend_fac = saturate(1.0 - w_accum.y / w_accum.z);
+ fragColor = (accum / w_accum.z) + center_color * blend_fac;
+
+#if 0 /* For debugging. */
+ fragColor.rgb = fragColor.ggg;
+ fragColor.rg += max_motion.xy;
+#endif
}
diff --git a/source/blender/draw/engines/eevee/shaders/effect_temporal_aa.glsl b/source/blender/draw/engines/eevee/shaders/effect_temporal_aa.glsl
index 428318e3c68..b44645174bd 100644
--- a/source/blender/draw/engines/eevee/shaders/effect_temporal_aa.glsl
+++ b/source/blender/draw/engines/eevee/shaders/effect_temporal_aa.glsl
@@ -1,6 +1,6 @@
uniform sampler2D colorHistoryBuffer;
-uniform sampler2D velocityBuffer;
+uniform mat4 prevViewProjectionMatrix;
out vec4 FragColor;
@@ -38,16 +38,19 @@ vec3 clip_to_aabb(vec3 color, vec3 minimum, vec3 maximum, vec3 average)
*/
void main()
{
+ vec2 screen_res = vec2(textureSize(colorBuffer, 0).xy);
+ vec2 uv = gl_FragCoord.xy / screen_res;
ivec2 texel = ivec2(gl_FragCoord.xy);
- vec2 motion = texelFetch(velocityBuffer, texel, 0).rg;
-
- /* Decode from unsigned normalized 16bit texture. */
- motion = motion * 2.0 - 1.0;
/* Compute pixel position in previous frame. */
- vec2 screen_res = vec2(textureSize(colorBuffer, 0).xy);
- vec2 uv = gl_FragCoord.xy / screen_res;
- vec2 uv_history = uv - motion;
+ float depth = textureLod(depthBuffer, uv, 0.0).r;
+ vec3 pos = get_world_space_from_depth(uv, depth);
+ vec2 uv_history = project_point(prevViewProjectionMatrix, pos).xy * 0.5 + 0.5;
+
+ /* HACK: Reject lookdev spheres from TAA reprojection. */
+ if (depth == 0.0) {
+ uv_history = uv;
+ }
ivec2 texel_history = ivec2(uv_history * screen_res);
vec4 color_history = textureLod(colorHistoryBuffer, uv_history, 0.0);
diff --git a/source/blender/draw/engines/eevee/shaders/effect_velocity_resolve_frag.glsl b/source/blender/draw/engines/eevee/shaders/effect_velocity_resolve_frag.glsl
index 7d701bce5cb..d927fd78d30 100644
--- a/source/blender/draw/engines/eevee/shaders/effect_velocity_resolve_frag.glsl
+++ b/source/blender/draw/engines/eevee/shaders/effect_velocity_resolve_frag.glsl
@@ -1,8 +1,9 @@
-uniform mat4 currPersinv;
-uniform mat4 pastPersmat;
+uniform mat4 prevViewProjMatrix;
+uniform mat4 currViewProjMatrixInv;
+uniform mat4 nextViewProjMatrix;
-out vec2 outData;
+out vec4 outData;
void main()
{
@@ -12,13 +13,12 @@ void main()
float depth = texelFetch(depthBuffer, texel, 0).r;
- vec3 world_position = project_point(currPersinv, vec3(uv, depth) * 2.0 - 1.0);
- vec2 uv_history = project_point(pastPersmat, world_position).xy * 0.5 + 0.5;
+ vec3 world_position = project_point(currViewProjMatrixInv, vec3(uv, depth) * 2.0 - 1.0);
+ vec2 uv_prev = project_point(prevViewProjMatrix, world_position).xy * 0.5 + 0.5;
+ vec2 uv_next = project_point(nextViewProjMatrix, world_position).xy * 0.5 + 0.5;
- outData = uv - uv_history;
-
- /* HACK: Reject lookdev spheres from TAA reprojection. */
- outData = (depth > 0.0) ? outData : vec2(0.0);
+ outData.xy = uv_prev - uv;
+ outData.zw = uv_next - uv;
/* Encode to unsigned normalized 16bit texture. */
outData = outData * 0.5 + 0.5;
diff --git a/source/blender/draw/engines/eevee/shaders/effect_velocity_tile_frag.glsl b/source/blender/draw/engines/eevee/shaders/effect_velocity_tile_frag.glsl
new file mode 100644
index 00000000000..0eb598521af
--- /dev/null
+++ b/source/blender/draw/engines/eevee/shaders/effect_velocity_tile_frag.glsl
@@ -0,0 +1,151 @@
+/**
+ * Shaders that down-sample velocity buffer,
+ *
+ * Based on:
+ * A Fast and Stable Feature-Aware Motion Blur Filter
+ * by Jean-Philippe Guertin, Morgan McGuire, Derek Nowrouzezahrai
+ *
+ * Adapted from G3D Innovation Engine implementation.
+ */
+
+uniform sampler2D velocityBuffer;
+uniform vec2 viewportSize;
+uniform vec2 viewportSizeInv;
+uniform ivec2 velocityBufferSize;
+
+out vec4 tileMaxVelocity;
+
+vec4 sample_velocity(ivec2 texel)
+{
+ texel = clamp(texel, ivec2(0), velocityBufferSize - 1);
+ vec4 data = texelFetch(velocityBuffer, texel, 0);
+ /* Decode data. */
+ return (data * 2.0 - 1.0) * viewportSize.xyxy;
+}
+
+vec4 encode_velocity(vec4 velocity)
+{
+ return velocity * viewportSizeInv.xyxy * 0.5 + 0.5;
+}
+
+#ifdef TILE_GATHER
+
+uniform ivec2 gatherStep;
+
+void main()
+{
+ vec4 max_motion = vec4(0.0);
+ float max_motion_len_sqr_prev = 0.0;
+ float max_motion_len_sqr_next = 0.0;
+ ivec2 texel = ivec2(gl_FragCoord.xy);
+ texel = texel * gatherStep.yx + texel * EEVEE_VELOCITY_TILE_SIZE * gatherStep;
+
+ for (int i = 0; i < EEVEE_VELOCITY_TILE_SIZE; ++i) {
+ vec4 motion = sample_velocity(texel + i * gatherStep);
+ float motion_len_sqr_prev = dot(motion.xy, motion.xy);
+ float motion_len_sqr_next = dot(motion.zw, motion.zw);
+
+ if (motion_len_sqr_prev > max_motion_len_sqr_prev) {
+ max_motion_len_sqr_prev = motion_len_sqr_prev;
+ max_motion.xy = motion.xy;
+ }
+ if (motion_len_sqr_next > max_motion_len_sqr_next) {
+ max_motion_len_sqr_next = motion_len_sqr_next;
+ max_motion.zw = motion.zw;
+ }
+ }
+
+ tileMaxVelocity = encode_velocity(max_motion);
+}
+
+#else /* TILE_EXPANSION */
+
+bool neighbor_affect_this_tile(ivec2 offset, vec2 velocity)
+{
+ /* Manhattan distance to the tiles, which is used for
+ * differentiating corners versus middle blocks */
+ float displacement = float(abs(offset.x) + abs(offset.y));
+ /**
+ * Relative sign on each axis of the offset compared
+ * to the velocity for that tile. In order for a tile
+ * to affect the center tile, it must have a
+ * neighborhood velocity in which x and y both have
+ * identical or both have opposite signs relative to
+ * offset. If the offset coordinate is zero then
+ * velocity is irrelevant.
+ **/
+ vec2 point = sign(offset * velocity);
+
+ float dist = (point.x + point.y);
+ /**
+ * Here's an example of the logic for this code.
+ * In this diagram, the upper-left tile has offset = (-1, -1).
+ * V1 is velocity = (1, -2). point in this case = (-1, 1), and therefore dist = 0,
+ * so the upper-left tile does not affect the center.
+ *
+ * Now, look at another case. V2 = (-1, -2). point = (1, 1), so dist = 2 and the tile
+ * does affect the center.
+ *
+ * V2(-1,-2) V1(1, -2)
+ * \ /
+ * \ /
+ * \/___ ____ ____
+ * (-1, -1)| | | |
+ * |____|____|____|
+ * | | | |
+ * |____|____|____|
+ * | | | |
+ * |____|____|____|
+ **/
+ return (abs(dist) == displacement);
+}
+
+/**
+ * Only gather neighborhood velocity into tiles that could be affected by it.
+ * In the general case, only six of the eight neighbors contribute:
+ *
+ * This tile can't possibly be affected by the center one
+ * |
+ * v
+ * ____ ____ ____
+ * | | ///|/// |
+ * |____|////|//__|
+ * | |////|/ |
+ * |___/|////|____|
+ * | //|////| | <--- This tile can't possibly be affected by the center one
+ * |_///|///_|____|
+ **/
+void main()
+{
+ vec4 max_motion = vec4(0.0);
+ float max_motion_len_sqr_prev = -1.0;
+ float max_motion_len_sqr_next = -1.0;
+
+ ivec2 tile = ivec2(gl_FragCoord.xy);
+ ivec2 offset = ivec2(0);
+ for (offset.y = -1; offset.y <= 1; ++offset.y) {
+ for (offset.x = -1; offset.x <= 1; ++offset.x) {
+ vec4 motion = sample_velocity(tile + offset);
+ float motion_len_sqr_prev = dot(motion.xy, motion.xy);
+ float motion_len_sqr_next = dot(motion.zw, motion.zw);
+
+ if (motion_len_sqr_prev > max_motion_len_sqr_prev) {
+ if (neighbor_affect_this_tile(offset, motion.xy)) {
+ max_motion_len_sqr_prev = motion_len_sqr_prev;
+ max_motion.xy = motion.xy;
+ }
+ }
+
+ if (motion_len_sqr_next > max_motion_len_sqr_next) {
+ if (neighbor_affect_this_tile(offset, motion.zw)) {
+ max_motion_len_sqr_next = motion_len_sqr_next;
+ max_motion.zw = motion.zw;
+ }
+ }
+ }
+ }
+
+ tileMaxVelocity = encode_velocity(max_motion);
+}
+
+#endif \ No newline at end of file
diff --git a/source/blender/draw/engines/eevee/shaders/object_motion_frag.glsl b/source/blender/draw/engines/eevee/shaders/object_motion_frag.glsl
new file mode 100644
index 00000000000..66b098ef6c5
--- /dev/null
+++ b/source/blender/draw/engines/eevee/shaders/object_motion_frag.glsl
@@ -0,0 +1,27 @@
+
+uniform mat4 prevViewProjMatrix;
+uniform mat4 currViewProjMatrix;
+uniform mat4 nextViewProjMatrix;
+
+in vec3 prevWorldPos;
+in vec3 currWorldPos;
+in vec3 nextWorldPos;
+
+out vec4 outData;
+
+void main()
+{
+ vec4 prev_wpos = prevViewProjMatrix * vec4(prevWorldPos, 1.0);
+ vec4 curr_wpos = currViewProjMatrix * vec4(currWorldPos, 1.0);
+ vec4 next_wpos = nextViewProjMatrix * vec4(nextWorldPos, 1.0);
+
+ vec2 prev_uv = (prev_wpos.xy / prev_wpos.w);
+ vec2 curr_uv = (curr_wpos.xy / curr_wpos.w);
+ vec2 next_uv = (next_wpos.xy / next_wpos.w);
+
+ outData.xy = prev_uv - curr_uv;
+ outData.zw = next_uv - curr_uv;
+
+ /* Encode to unsigned normalized 16bit texture. */
+ outData = outData * 0.5 + 0.5;
+}
diff --git a/source/blender/draw/engines/eevee/shaders/object_motion_vert.glsl b/source/blender/draw/engines/eevee/shaders/object_motion_vert.glsl
new file mode 100644
index 00000000000..95cd69ba310
--- /dev/null
+++ b/source/blender/draw/engines/eevee/shaders/object_motion_vert.glsl
@@ -0,0 +1,54 @@
+
+uniform mat4 currModelMatrix;
+uniform mat4 prevModelMatrix;
+uniform mat4 nextModelMatrix;
+uniform bool useDeform;
+
+#ifdef HAIR
+uniform samplerBuffer prvBuffer; /* RGBA32F */
+uniform samplerBuffer nxtBuffer; /* RGBA32F */
+#else
+in vec3 pos;
+in vec3 prv; /* Previous frame position. */
+in vec3 nxt; /* Next frame position. */
+#endif
+
+out vec3 currWorldPos;
+out vec3 prevWorldPos;
+out vec3 nextWorldPos;
+
+void main()
+{
+#ifdef HAIR
+ bool is_persp = (ProjectionMatrix[3][3] == 0.0);
+ float time, thick_time, thickness;
+ vec3 tan, binor;
+ vec3 wpos;
+
+ hair_get_pos_tan_binor_time(is_persp,
+ ModelMatrixInverse,
+ ViewMatrixInverse[3].xyz,
+ ViewMatrixInverse[2].xyz,
+ wpos,
+ tan,
+ binor,
+ time,
+ thickness,
+ thick_time);
+
+ int id = hair_get_base_id();
+ vec3 pos = texelFetch(hairPointBuffer, id).point_position;
+ vec3 prv = texelFetch(prvBuffer, id).point_position;
+ vec3 nxt = texelFetch(nxtBuffer, id).point_position;
+#endif
+ prevWorldPos = (prevModelMatrix * vec4(useDeform ? prv : pos, 1.0)).xyz;
+ currWorldPos = (currModelMatrix * vec4(pos, 1.0)).xyz;
+ nextWorldPos = (nextModelMatrix * vec4(useDeform ? nxt : pos, 1.0)).xyz;
+ /* Use jittered projmatrix to be able to match exact sample depth (depth equal test).
+ * Note that currModelMatrix needs to also be equal to ModelMatrix for the samples to match. */
+#ifndef HAIR
+ gl_Position = ViewProjectionMatrix * vec4(currWorldPos, 1.0);
+#else
+ gl_Position = ViewProjectionMatrix * vec4(wpos, 1.0);
+#endif
+}
diff --git a/source/blender/draw/engines/external/external_engine.c b/source/blender/draw/engines/external/external_engine.c
index 2f448b784ed..3ef20dbe9ec 100644
--- a/source/blender/draw/engines/external/external_engine.c
+++ b/source/blender/draw/engines/external/external_engine.c
@@ -97,8 +97,6 @@ typedef struct EXTERNAL_PrivateData {
/* Do we need to update the depth or can we reuse the last calculated texture. */
bool need_depth;
bool update_depth;
-
- float last_persmat[4][4];
} EXTERNAL_PrivateData; /* Transient data */
/* Functions */
diff --git a/source/blender/draw/engines/gpencil/gpencil_cache_utils.c b/source/blender/draw/engines/gpencil/gpencil_cache_utils.c
index 2b811f1d52e..d97bf9255d2 100644
--- a/source/blender/draw/engines/gpencil/gpencil_cache_utils.c
+++ b/source/blender/draw/engines/gpencil/gpencil_cache_utils.c
@@ -159,7 +159,7 @@ void gpencil_object_cache_sort(GPENCIL_PrivateData *pd)
}
}
- /* Join both lists, adding infront. */
+ /* Join both lists, adding in front. */
if (pd->tobjects_infront.first != NULL) {
if (pd->tobjects.last != NULL) {
pd->tobjects.last->next = pd->tobjects_infront.first;
@@ -265,8 +265,10 @@ GPENCIL_tLayer *gpencil_layer_cache_add(GPENCIL_PrivateData *pd,
GPENCIL_VERTEX_MODE(gpd) || pd->is_render;
bool is_masked = (gpl->flag & GP_LAYER_USE_MASK) && !BLI_listbase_is_empty(&gpl->mask_layers);
- float vert_col_opacity = (overide_vertcol) ? (is_vert_col_mode ? 1.0f : 0.0f) :
- gpl->vertex_paint_opacity;
+ float vert_col_opacity = (overide_vertcol) ?
+ (is_vert_col_mode ? pd->vertex_paint_opacity : 0.0f) :
+ pd->is_render ? gpl->vertex_paint_opacity :
+ pd->vertex_paint_opacity;
/* Negate thickness sign to tag that strokes are in screen space.
* Convert to world units (by default, 1 meter = 2000 px). */
float thickness_scale = (is_screenspace) ? -1.0f : (gpd->pixfactor / GPENCIL_PIXEL_FACTOR);
diff --git a/source/blender/draw/engines/gpencil/gpencil_engine.c b/source/blender/draw/engines/gpencil/gpencil_engine.c
index 495de7ef10b..dded83bacf1 100644
--- a/source/blender/draw/engines/gpencil/gpencil_engine.c
+++ b/source/blender/draw/engines/gpencil/gpencil_engine.c
@@ -224,6 +224,7 @@ void GPENCIL_cache_init(void *ved)
const bool is_fade_layer = ((!hide_overlay) && (!pd->is_render) &&
(draw_ctx->v3d->gp_flag & V3D_GP_FADE_NOACTIVE_LAYERS));
pd->fade_layer_opacity = (is_fade_layer) ? draw_ctx->v3d->overlay.gpencil_fade_layer : -1.0f;
+ pd->vertex_paint_opacity = draw_ctx->v3d->overlay.gpencil_vertex_paint_opacity;
/* Fade GPencil Objects. */
const bool is_fade_object = ((!hide_overlay) && (!pd->is_render) &&
(draw_ctx->v3d->gp_flag & V3D_GP_FADE_OBJECTS) &&
@@ -383,7 +384,7 @@ static void gpencil_drawcall_flush(gpIterPopulateData *iter)
}
/* Group drawcalls that are consecutive and with the same type. Reduces GPU driver overhead. */
-static void gp_drawcall_add(
+static void gpencil_drawcall_add(
gpIterPopulateData *iter, struct GPUBatch *geom, bool instancing, int v_first, int v_count)
{
#if DISABLE_BATCHING
@@ -413,7 +414,7 @@ static void gpencil_stroke_cache_populate(bGPDlayer *gpl,
bGPDstroke *gps,
void *thunk);
-static void gp_sbuffer_cache_populate(gpIterPopulateData *iter)
+static void gpencil_sbuffer_cache_populate(gpIterPopulateData *iter)
{
iter->do_sbuffer_call = DRAW_NOW;
/* In order to draw the sbuffer stroke correctly mixed with other strokes,
@@ -450,7 +451,7 @@ static void gpencil_layer_cache_populate(bGPDlayer *gpl,
gpencil_drawcall_flush(iter);
if (iter->do_sbuffer_call) {
- gp_sbuffer_cache_populate(iter);
+ gpencil_sbuffer_cache_populate(iter);
}
else {
iter->do_sbuffer_call = !pd->do_fast_drawing && (gpd == pd->sbuffer_gpd) &&
@@ -492,8 +493,10 @@ static void gpencil_stroke_cache_populate(bGPDlayer *gpl,
(!iter->pd->simplify_fill) && ((gps->flag & GP_STROKE_NOFILL) == 0);
bool only_lines = gpl && gpf && gpl->actframe != gpf && iter->pd->use_multiedit_lines_only;
+ bool hide_onion = gpl && gpf && gpf->runtime.onion_id != 0 &&
+ ((gp_style->flag & GP_MATERIAL_HIDE_ONIONSKIN) != 0);
- if (hide_material || (!show_stroke && !show_fill) || only_lines) {
+ if (hide_material || (!show_stroke && !show_fill) || only_lines || hide_onion) {
return;
}
@@ -537,7 +540,7 @@ static void gpencil_stroke_cache_populate(bGPDlayer *gpl,
DRW_cache_gpencil_fills_get(iter->ob, iter->pd->cfra);
int vfirst = gps->runtime.fill_start * 3;
int vcount = gps->tot_triangles * 3;
- gp_drawcall_add(iter, geom, false, vfirst, vcount);
+ gpencil_drawcall_add(iter, geom, false, vfirst, vcount);
}
if (show_stroke) {
@@ -547,13 +550,13 @@ static void gpencil_stroke_cache_populate(bGPDlayer *gpl,
int vfirst = gps->runtime.stroke_start - 1;
/* Include "potential" cyclic vertex and start adj vertex (see shader). */
int vcount = gps->totpoints + 1 + 1;
- gp_drawcall_add(iter, geom, true, vfirst, vcount);
+ gpencil_drawcall_add(iter, geom, true, vfirst, vcount);
}
iter->stroke_index_last = gps->runtime.stroke_start + gps->totpoints + 1;
}
-static void gp_sbuffer_cache_populate_fast(GPENCIL_Data *vedata, gpIterPopulateData *iter)
+static void gpencil_sbuffer_cache_populate_fast(GPENCIL_Data *vedata, gpIterPopulateData *iter)
{
bGPdata *gpd = (bGPdata *)iter->ob->data;
if (gpd != iter->pd->sbuffer_gpd) {
@@ -630,13 +633,13 @@ void GPENCIL_cache_populate(void *ved, Object *ob)
gpencil_drawcall_flush(&iter);
if (iter.do_sbuffer_call) {
- gp_sbuffer_cache_populate(&iter);
+ gpencil_sbuffer_cache_populate(&iter);
}
gpencil_vfx_cache_populate(vedata, ob, iter.tgp_ob);
if (pd->do_fast_drawing) {
- gp_sbuffer_cache_populate_fast(vedata, &iter);
+ gpencil_sbuffer_cache_populate_fast(vedata, &iter);
}
}
diff --git a/source/blender/draw/engines/gpencil/gpencil_engine.h b/source/blender/draw/engines/gpencil/gpencil_engine.h
index cedd75af813..7baca28dca3 100644
--- a/source/blender/draw/engines/gpencil/gpencil_engine.h
+++ b/source/blender/draw/engines/gpencil/gpencil_engine.h
@@ -363,6 +363,8 @@ typedef struct GPENCIL_PrivateData {
float xray_alpha;
/* Mask invert uniform. */
int mask_invert;
+ /* Vertex Paint opacity. */
+ float vertex_paint_opacity;
} GPENCIL_PrivateData;
/* geometry batch cache functions */
diff --git a/source/blender/draw/engines/gpencil/gpencil_shader_fx.c b/source/blender/draw/engines/gpencil/gpencil_shader_fx.c
index 7ce7a726bb7..cf6e78f4702 100644
--- a/source/blender/draw/engines/gpencil/gpencil_shader_fx.c
+++ b/source/blender/draw/engines/gpencil/gpencil_shader_fx.c
@@ -262,6 +262,8 @@ static void gpencil_vfx_pixelize(PixelShaderFxData *fx, Object *ob, gpIterVfxDat
mul_v3_m4v3(ob_center, persmat, ob->obmat[3]);
mul_v3_fl(ob_center, 1.0f / w);
+ const bool use_antialiasing = ((fx->flag & FX_PIXEL_FILTER_NEAREST) == 0);
+
/* Convert to uvs. */
mul_v2_fl(ob_center, 0.5f);
add_v2_fl(ob_center, 0.5f);
@@ -285,7 +287,8 @@ static void gpencil_vfx_pixelize(PixelShaderFxData *fx, Object *ob, gpIterVfxDat
DRW_shgroup_uniform_vec2_copy(grp, "targetPixelSize", pixsize_uniform);
DRW_shgroup_uniform_vec2_copy(grp, "targetPixelOffset", ob_center);
DRW_shgroup_uniform_vec2_copy(grp, "accumOffset", (float[2]){pixel_size[0], 0.0f});
- DRW_shgroup_uniform_int_copy(grp, "sampCount", (pixel_size[0] / vp_size_inv[0] > 3.0) ? 2 : 1);
+ int samp_count = (pixel_size[0] / vp_size_inv[0] > 3.0) ? 2 : 1;
+ DRW_shgroup_uniform_int_copy(grp, "sampCount", use_antialiasing ? samp_count : 0);
DRW_shgroup_call_procedural_triangles(grp, NULL, 1);
}
@@ -294,7 +297,8 @@ static void gpencil_vfx_pixelize(PixelShaderFxData *fx, Object *ob, gpIterVfxDat
grp = gpencil_vfx_pass_create("Fx Pixelize Y", state, iter, sh);
DRW_shgroup_uniform_vec2_copy(grp, "targetPixelSize", pixsize_uniform);
DRW_shgroup_uniform_vec2_copy(grp, "accumOffset", (float[2]){0.0f, pixel_size[1]});
- DRW_shgroup_uniform_int_copy(grp, "sampCount", (pixel_size[1] / vp_size_inv[1] > 3.0) ? 2 : 1);
+ int samp_count = (pixel_size[1] / vp_size_inv[1] > 3.0) ? 2 : 1;
+ DRW_shgroup_uniform_int_copy(grp, "sampCount", use_antialiasing ? samp_count : 0);
DRW_shgroup_call_procedural_triangles(grp, NULL, 1);
}
}
diff --git a/source/blender/draw/engines/overlay/overlay_armature.c b/source/blender/draw/engines/overlay/overlay_armature.c
index 481dec340ba..7ccb5d5a753 100644
--- a/source/blender/draw/engines/overlay/overlay_armature.c
+++ b/source/blender/draw/engines/overlay/overlay_armature.c
@@ -228,11 +228,12 @@ void OVERLAY_armature_cache_init(OVERLAY_Data *vedata)
{
format = formats->instance_extra;
- sh = OVERLAY_shader_armature_degrees_of_freedom();
+ sh = OVERLAY_shader_armature_degrees_of_freedom_wire();
grp = DRW_shgroup_create(sh, armature_ps);
DRW_shgroup_uniform_block(grp, "globalsBlock", G_draw.block_ubo);
cb->dof_lines = BUF_INSTANCE(grp, format, DRW_cache_bone_dof_lines_get());
+ sh = OVERLAY_shader_armature_degrees_of_freedom_solid();
grp = DRW_shgroup_create(sh, armature_transp_ps);
DRW_shgroup_uniform_block(grp, "globalsBlock", G_draw.block_ubo);
cb->dof_sphere = BUF_INSTANCE(grp, format, DRW_cache_bone_dof_sphere_get());
@@ -2167,7 +2168,8 @@ static void armature_context_setup(ArmatureDrawContext *ctx,
ctx->do_relations = !DRW_state_is_select() && pd->armature.show_relations &&
(is_edit_mode | is_pose_mode);
ctx->const_color = DRW_state_is_select() ? select_const_color : const_color;
- ctx->const_wire = (((ob->base_flag & BASE_SELECTED) || (arm->drawtype == ARM_WIRE)) ?
+ ctx->const_wire = ((((ob->base_flag & BASE_SELECTED) && (pd->v3d_flag & V3D_SELECT_OUTLINE)) ||
+ (arm->drawtype == ARM_WIRE)) ?
1.5f :
((!is_filled || is_transparent) ? 1.0f : 0.0f));
}
diff --git a/source/blender/draw/engines/overlay/overlay_edit_text.c b/source/blender/draw/engines/overlay/overlay_edit_text.c
index c4d020adc11..4ee936f5ce6 100644
--- a/source/blender/draw/engines/overlay/overlay_edit_text.c
+++ b/source/blender/draw/engines/overlay/overlay_edit_text.c
@@ -53,13 +53,22 @@ void OVERLAY_edit_text_cache_init(OVERLAY_Data *vedata)
DRW_shgroup_uniform_vec4_copy(grp, "color", G_draw.block.colorWire);
}
{
- state = DRW_STATE_WRITE_COLOR | DRW_STATE_LOGIC_INVERT;
+ state = DRW_STATE_WRITE_COLOR | DRW_STATE_BLEND_ALPHA;
DRW_PASS_CREATE(psl->edit_text_overlay_ps, state | pd->clipping_state);
sh = OVERLAY_shader_uniform_color();
pd->edit_text_overlay_grp = grp = DRW_shgroup_create(sh, psl->edit_text_overlay_ps);
- DRW_shgroup_uniform_vec4_copy(grp, "color", (float[4]){1.0f, 1.0f, 1.0f, 1.0f});
+ DRW_shgroup_uniform_vec4(grp, "color", pd->edit_text.overlay_color, 1);
+
+ state = DRW_STATE_WRITE_COLOR | DRW_STATE_BLEND_MUL | DRW_STATE_DEPTH_GREATER_EQUAL |
+ pd->clipping_state;
+ DRW_PASS_INSTANCE_CREATE(psl->edit_text_darken_ps, psl->edit_text_overlay_ps, state);
+ }
+ {
+ /* Create view which will render everything (hopefully) behind the text geometry. */
+ DRWView *default_view = (DRWView *)DRW_view_default_get();
+ pd->view_edit_text = DRW_view_create_with_zoffset(default_view, draw_ctx->rv3d, -5.0f);
}
}
@@ -193,16 +202,24 @@ void OVERLAY_edit_text_cache_populate(OVERLAY_Data *vedata, Object *ob)
void OVERLAY_edit_text_draw(OVERLAY_Data *vedata)
{
+ OVERLAY_PrivateData *pd = vedata->stl->pd;
OVERLAY_PassList *psl = vedata->psl;
- DefaultFramebufferList *dfbl = DRW_viewport_framebuffer_list_get();
+ OVERLAY_FramebufferList *fbl = vedata->fbl;
if (DRW_state_is_fbo()) {
- /* Text overlay need final color for color inversion. */
- GPU_framebuffer_bind(dfbl->default_fb);
+ GPU_framebuffer_bind(fbl->overlay_default_fb);
}
DRW_draw_pass(psl->edit_text_wire_ps[0]);
DRW_draw_pass(psl->edit_text_wire_ps[1]);
+ DRW_view_set_active(pd->view_edit_text);
+
+ /* Alpha blended. */
+ copy_v4_fl4(pd->edit_text.overlay_color, 0.8f, 0.8f, 0.8f, 0.5f);
DRW_draw_pass(psl->edit_text_overlay_ps);
+
+ /* Multiply previous result where depth test fail. */
+ copy_v4_fl4(pd->edit_text.overlay_color, 0.0f, 0.0f, 0.0f, 1.0f);
+ DRW_draw_pass(psl->edit_text_darken_ps);
}
diff --git a/source/blender/draw/engines/overlay/overlay_engine.c b/source/blender/draw/engines/overlay/overlay_engine.c
index 61337ac8d1d..e76b3c82c1d 100644
--- a/source/blender/draw/engines/overlay/overlay_engine.c
+++ b/source/blender/draw/engines/overlay/overlay_engine.c
@@ -423,7 +423,7 @@ static void OVERLAY_cache_finish(void *vedata)
{
/* TODO(fclem) Only do this when really needed. */
{
- /* HACK we allocate the infront depth here to avoid the overhead when if is not needed. */
+ /* HACK we allocate the in front depth here to avoid the overhead when if is not needed. */
DefaultFramebufferList *dfbl = DRW_viewport_framebuffer_list_get();
DefaultTextureList *dtxl = DRW_viewport_texture_list_get();
diff --git a/source/blender/draw/engines/overlay/overlay_extra.c b/source/blender/draw/engines/overlay/overlay_extra.c
index 15bf26a5fa8..e591f54c750 100644
--- a/source/blender/draw/engines/overlay/overlay_extra.c
+++ b/source/blender/draw/engines/overlay/overlay_extra.c
@@ -1318,7 +1318,7 @@ static void OVERLAY_relationship_lines(OVERLAY_ExtraCallBuffers *cb,
else {
const bConstraintTypeInfo *cti = BKE_constraint_typeinfo_get(curcon);
- if ((cti && cti->get_constraint_targets) && (curcon->flag & CONSTRAINT_EXPAND)) {
+ if ((cti && cti->get_constraint_targets) && (curcon->ui_expand_flag && (1 << 0))) {
ListBase targets = {NULL, NULL};
bConstraintTarget *ct;
diff --git a/source/blender/draw/engines/overlay/overlay_grid.c b/source/blender/draw/engines/overlay/overlay_grid.c
index 5ed32de6d93..e3079870d8f 100644
--- a/source/blender/draw/engines/overlay/overlay_grid.c
+++ b/source/blender/draw/engines/overlay/overlay_grid.c
@@ -41,6 +41,7 @@ enum {
CLIP_ZPOS = (1 << 7),
CLIP_ZNEG = (1 << 8),
GRID_BACK = (1 << 9),
+ GRID_CAMERA = (1 << 10),
};
void OVERLAY_grid_init(OVERLAY_Data *vedata)
@@ -145,6 +146,9 @@ void OVERLAY_grid_init(OVERLAY_Data *vedata)
if (rv3d->persp == RV3D_CAMOB && v3d->camera && v3d->camera->type == OB_CAMERA) {
Object *camera_object = DEG_get_evaluated_object(draw_ctx->depsgraph, v3d->camera);
dist = ((Camera *)(camera_object->data))->clip_end;
+ shd->grid_flag |= GRID_CAMERA;
+ shd->zneg_flag |= GRID_CAMERA;
+ shd->zpos_flag |= GRID_CAMERA;
}
else {
dist = v3d->clip_end;
diff --git a/source/blender/draw/engines/overlay/overlay_private.h b/source/blender/draw/engines/overlay/overlay_private.h
index ed0a9cf6981..59fa58c0c03 100644
--- a/source/blender/draw/engines/overlay/overlay_private.h
+++ b/source/blender/draw/engines/overlay/overlay_private.h
@@ -71,6 +71,7 @@ typedef struct OVERLAY_PassList {
DRWPass *edit_mesh_normals_ps;
DRWPass *edit_particle_ps;
DRWPass *edit_text_overlay_ps;
+ DRWPass *edit_text_darken_ps;
DRWPass *edit_text_wire_ps[2];
DRWPass *extra_ps[2];
DRWPass *extra_blend_ps;
@@ -264,6 +265,7 @@ typedef struct OVERLAY_PrivateData {
DRWView *view_edit_faces_cage;
DRWView *view_edit_edges;
DRWView *view_edit_verts;
+ DRWView *view_edit_text;
DRWView *view_reference_images;
/** TODO get rid of this. */
@@ -300,6 +302,9 @@ typedef struct OVERLAY_PrivateData {
int handle_display;
} edit_curve;
struct {
+ float overlay_color[4];
+ } edit_text;
+ struct {
int ghost_ob;
int edit_ob;
bool do_zbufclip;
@@ -563,7 +568,8 @@ void OVERLAY_wireframe_draw(OVERLAY_Data *vedata);
void OVERLAY_wireframe_in_front_draw(OVERLAY_Data *vedata);
GPUShader *OVERLAY_shader_antialiasing(void);
-GPUShader *OVERLAY_shader_armature_degrees_of_freedom(void);
+GPUShader *OVERLAY_shader_armature_degrees_of_freedom_wire(void);
+GPUShader *OVERLAY_shader_armature_degrees_of_freedom_solid(void);
GPUShader *OVERLAY_shader_armature_envelope(bool use_outline);
GPUShader *OVERLAY_shader_armature_shape(bool use_outline);
GPUShader *OVERLAY_shader_armature_shape_wire(void);
diff --git a/source/blender/draw/engines/overlay/overlay_shader.c b/source/blender/draw/engines/overlay/overlay_shader.c
index 0610b8397a1..edf91c99531 100644
--- a/source/blender/draw/engines/overlay/overlay_shader.c
+++ b/source/blender/draw/engines/overlay/overlay_shader.c
@@ -31,6 +31,7 @@
extern char datatoc_antialiasing_frag_glsl[];
extern char datatoc_antialiasing_vert_glsl[];
extern char datatoc_armature_dof_vert_glsl[];
+extern char datatoc_armature_dof_solid_frag_glsl[];
extern char datatoc_armature_envelope_distance_frag_glsl[];
extern char datatoc_armature_envelope_outline_vert_glsl[];
extern char datatoc_armature_envelope_solid_frag_glsl[];
@@ -130,7 +131,8 @@ extern char datatoc_common_view_lib_glsl[];
typedef struct OVERLAY_Shaders {
GPUShader *antialiasing;
- GPUShader *armature_dof;
+ GPUShader *armature_dof_wire;
+ GPUShader *armature_dof_solid;
GPUShader *armature_envelope_outline;
GPUShader *armature_envelope_solid;
GPUShader *armature_shape_outline;
@@ -473,13 +475,13 @@ GPUShader *OVERLAY_shader_armature_stick(void)
return sh_data->armature_stick;
}
-GPUShader *OVERLAY_shader_armature_degrees_of_freedom(void)
+GPUShader *OVERLAY_shader_armature_degrees_of_freedom_wire(void)
{
const DRWContextState *draw_ctx = DRW_context_state_get();
const GPUShaderConfigData *sh_cfg = &GPU_shader_cfg_data[draw_ctx->sh_cfg];
OVERLAY_Shaders *sh_data = &e_data.sh_data[draw_ctx->sh_cfg];
- if (!sh_data->armature_dof) {
- sh_data->armature_dof = GPU_shader_create_from_arrays({
+ if (!sh_data->armature_dof_wire) {
+ sh_data->armature_dof_wire = GPU_shader_create_from_arrays({
.vert = (const char *[]){sh_cfg->lib,
datatoc_common_globals_lib_glsl,
datatoc_common_view_lib_glsl,
@@ -487,10 +489,31 @@ GPUShader *OVERLAY_shader_armature_degrees_of_freedom(void)
NULL},
.frag =
(const char *[]){datatoc_common_view_lib_glsl, datatoc_armature_wire_frag_glsl, NULL},
+ .defs = (const char *[]){sh_cfg->def, "#define EDGE\n", NULL},
+ });
+ }
+ return sh_data->armature_dof_wire;
+}
+
+GPUShader *OVERLAY_shader_armature_degrees_of_freedom_solid(void)
+{
+ const DRWContextState *draw_ctx = DRW_context_state_get();
+ const GPUShaderConfigData *sh_cfg = &GPU_shader_cfg_data[draw_ctx->sh_cfg];
+ OVERLAY_Shaders *sh_data = &e_data.sh_data[draw_ctx->sh_cfg];
+ if (!sh_data->armature_dof_solid) {
+ sh_data->armature_dof_solid = GPU_shader_create_from_arrays({
+ .vert = (const char *[]){sh_cfg->lib,
+ datatoc_common_globals_lib_glsl,
+ datatoc_common_view_lib_glsl,
+ datatoc_armature_dof_vert_glsl,
+ NULL},
+ .frag = (const char *[]){datatoc_common_view_lib_glsl,
+ datatoc_armature_dof_solid_frag_glsl,
+ NULL},
.defs = (const char *[]){sh_cfg->def, NULL},
});
}
- return sh_data->armature_dof;
+ return sh_data->armature_dof_solid;
}
GPUShader *OVERLAY_shader_armature_wire(void)
diff --git a/source/blender/draw/engines/overlay/overlay_wireframe.c b/source/blender/draw/engines/overlay/overlay_wireframe.c
index eebfc88fdce..ea45ad5190c 100644
--- a/source/blender/draw/engines/overlay/overlay_wireframe.c
+++ b/source/blender/draw/engines/overlay/overlay_wireframe.c
@@ -76,7 +76,8 @@ void OVERLAY_wireframe_cache_init(OVERLAY_Data *vedata)
DRWState state = DRW_STATE_FIRST_VERTEX_CONVENTION | DRW_STATE_WRITE_COLOR |
DRW_STATE_WRITE_DEPTH | DRW_STATE_DEPTH_LESS_EQUAL;
DRWPass *pass;
- GPUTexture **depth_tx = ((pd->xray_enabled || pd->xray_opacity > 0.0f) && DRW_state_is_fbo()) ?
+ GPUTexture **depth_tx = ((!pd->xray_enabled || pd->xray_opacity > 0.0f) &&
+ DRW_state_is_fbo()) ?
&txl->temp_depth_tx :
&txl->dummy_depth_tx;
diff --git a/source/blender/draw/engines/overlay/shaders/armature_dof_solid_frag.glsl b/source/blender/draw/engines/overlay/shaders/armature_dof_solid_frag.glsl
new file mode 100644
index 00000000000..e511aab69c1
--- /dev/null
+++ b/source/blender/draw/engines/overlay/shaders/armature_dof_solid_frag.glsl
@@ -0,0 +1,11 @@
+
+flat in vec4 finalColor;
+
+layout(location = 0) out vec4 fragColor;
+layout(location = 1) out vec4 lineOutput;
+
+void main()
+{
+ fragColor = finalColor;
+ lineOutput = vec4(0.0);
+}
diff --git a/source/blender/draw/engines/overlay/shaders/armature_dof_vert.glsl b/source/blender/draw/engines/overlay/shaders/armature_dof_vert.glsl
index b15554bbb6a..18a80fc1fb4 100644
--- a/source/blender/draw/engines/overlay/shaders/armature_dof_vert.glsl
+++ b/source/blender/draw/engines/overlay/shaders/armature_dof_vert.glsl
@@ -8,8 +8,10 @@ in vec4 color;
in mat4 inst_obmat;
flat out vec4 finalColor;
+#ifdef EDGE
flat out vec2 edgeStart;
noperspective out vec2 edgePos;
+#endif
vec3 sphere_project(float ax, float az)
{
@@ -35,7 +37,9 @@ void main()
gl_Position = point_world_to_ndc(world_pos);
finalColor = color;
+#ifdef EDGE
edgeStart = edgePos = ((gl_Position.xy / gl_Position.w) * 0.5 + 0.5) * sizeViewport.xy;
+#endif
#ifdef USE_WORLD_CLIP_PLANES
world_clip_planes_calc_clip_distance(world_pos);
diff --git a/source/blender/draw/engines/overlay/shaders/edit_mesh_vert.glsl b/source/blender/draw/engines/overlay/shaders/edit_mesh_vert.glsl
index 203f6cb1901..2cefab56722 100644
--- a/source/blender/draw/engines/overlay/shaders/edit_mesh_vert.glsl
+++ b/source/blender/draw/engines/overlay/shaders/edit_mesh_vert.glsl
@@ -83,7 +83,7 @@ void main()
finalColor = EDIT_MESH_facedot_color(norAndFlag.w);
/* Bias Facedot Z position in clipspace. */
- gl_Position.z -= 0.00035;
+ gl_Position.z -= (ProjectionMatrix[3][3] == 0.0) ? 0.00035 : 1e-6;
gl_PointSize = sizeFaceDot;
bool occluded = test_occlusion();
diff --git a/source/blender/draw/engines/overlay/shaders/grid_frag.glsl b/source/blender/draw/engines/overlay/shaders/grid_frag.glsl
index 9743f918ce3..317e9fe0447 100644
--- a/source/blender/draw/engines/overlay/shaders/grid_frag.glsl
+++ b/source/blender/draw/engines/overlay/shaders/grid_frag.glsl
@@ -28,7 +28,8 @@ uniform float gridSteps[STEPS_LEN] = float[](0.001, 0.01, 0.1, 1.0, 10.0, 100.0,
#define PLANE_XY (1 << 4)
#define PLANE_XZ (1 << 5)
#define PLANE_YZ (1 << 6)
-#define GRID_BACK (1 << 9) /* grid is behind objects */
+#define GRID_BACK (1 << 9) /* grid is behind objects */
+#define GRID_CAMERA (1 << 10) /* In camera view */
#define M_1_SQRTPI 0.5641895835477563 /* 1/sqrt(pi) */
@@ -104,7 +105,9 @@ void main()
fade *= 1.0 - smoothstep(0.0, gridDistance, dist - gridDistance);
}
else {
- dist = abs(gl_FragCoord.z * 2.0 - 1.0);
+ dist = gl_FragCoord.z * 2.0 - 1.0;
+ /* Avoid fading in +Z direction in camera view (see T70193). */
+ dist = ((gridFlag & GRID_CAMERA) != 0) ? clamp(dist, 0.0, 1.0) : abs(dist);
fade = 1.0 - smoothstep(0.0, 0.5, dist - 0.5);
dist = 1.0; /* avoid branch after */
diff --git a/source/blender/draw/engines/workbench/shaders/workbench_cavity_lib.glsl b/source/blender/draw/engines/workbench/shaders/workbench_cavity_lib.glsl
index 87d04144cde..d8cb4f86f7b 100644
--- a/source/blender/draw/engines/workbench/shaders/workbench_cavity_lib.glsl
+++ b/source/blender/draw/engines/workbench/shaders/workbench_cavity_lib.glsl
@@ -23,7 +23,7 @@ void cavity_compute(vec2 screenco,
float depth = texture(depthBuffer, screenco).x;
- /* Early out if background and infront. */
+ /* Early out if background and in front. */
if (depth == 1.0 || depth == 0.0) {
return;
}
diff --git a/source/blender/draw/engines/workbench/shaders/workbench_volume_frag.glsl b/source/blender/draw/engines/workbench/shaders/workbench_volume_frag.glsl
index 0c2b7850f94..2920a504062 100644
--- a/source/blender/draw/engines/workbench/shaders/workbench_volume_frag.glsl
+++ b/source/blender/draw/engines/workbench/shaders/workbench_volume_frag.glsl
@@ -107,7 +107,6 @@ void volume_properties(vec3 ls_pos, out vec3 scattering, out float extinction)
#ifdef USE_COBA
float val = sample_volume_texture(densityTexture, co).r;
vec4 tval = texture(transferTexture, val) * densityScale;
- tval.rgb = pow(tval.rgb, vec3(2.2));
scattering = tval.rgb * 1500.0;
extinction = max(1e-4, tval.a * 50.0);
#else
@@ -127,7 +126,7 @@ void volume_properties(vec3 ls_pos, out vec3 scattering, out float extinction)
# ifdef VOLUME_SMOKE
/* 800 is arbitrary and here to mimic old viewport. TODO make it a parameter */
- scattering += pow(emission.rgb, vec3(2.2)) * emission.a * 800.0;
+ scattering += emission.rgb * emission.a * 800.0;
# endif
#endif
}
diff --git a/source/blender/draw/engines/workbench/workbench_engine.c b/source/blender/draw/engines/workbench/workbench_engine.c
index 828a9127fb1..c8dde4d513b 100644
--- a/source/blender/draw/engines/workbench/workbench_engine.c
+++ b/source/blender/draw/engines/workbench/workbench_engine.c
@@ -174,8 +174,19 @@ static void workbench_cache_common_populate(WORKBENCH_PrivateData *wpd,
color_type, V3D_SHADING_MATERIAL_COLOR, V3D_SHADING_TEXTURE_COLOR);
if (use_single_drawcall) {
- struct GPUBatch *geom = (use_vcol) ? DRW_cache_mesh_surface_vertpaint_get(ob) :
- DRW_cache_object_surface_get(ob);
+ struct GPUBatch *geom;
+ if (use_vcol) {
+ if (ob->mode & OB_MODE_VERTEX_PAINT) {
+ geom = DRW_cache_mesh_surface_vertpaint_get(ob);
+ }
+ else {
+ geom = DRW_cache_mesh_surface_sculptcolors_get(ob);
+ }
+ }
+ else {
+ geom = DRW_cache_object_surface_get(ob);
+ }
+
if (geom) {
DRWShadingGroup *grp = workbench_material_setup(wpd, ob, 0, color_type, r_transp);
DRW_shgroup_call(grp, geom, ob);
@@ -240,15 +251,19 @@ static eV3DShadingColorType workbench_color_type_get(WORKBENCH_PrivateData *wpd,
const bool is_texpaint_mode = is_active && (wpd->ctx_mode == CTX_MODE_PAINT_TEXTURE);
const bool is_vertpaint_mode = is_active && (wpd->ctx_mode == CTX_MODE_PAINT_VERTEX);
- if ((color_type == V3D_SHADING_TEXTURE_COLOR) && (ob->dt < OB_TEXTURE)) {
- color_type = V3D_SHADING_MATERIAL_COLOR;
- }
- /* Disable color mode if data layer is unavailable. */
- if ((color_type == V3D_SHADING_TEXTURE_COLOR) && (me == NULL || me->mloopuv == NULL)) {
- color_type = V3D_SHADING_MATERIAL_COLOR;
+ if (color_type == V3D_SHADING_TEXTURE_COLOR) {
+ if (ob->dt < OB_TEXTURE) {
+ color_type = V3D_SHADING_MATERIAL_COLOR;
+ }
+ else if ((me == NULL) || (me->mloopuv == NULL)) {
+ /* Disable color mode if data layer is unavailable. */
+ color_type = V3D_SHADING_MATERIAL_COLOR;
+ }
}
- if ((color_type == V3D_SHADING_VERTEX_COLOR) && (me == NULL || me->mloopcol == NULL)) {
- color_type = V3D_SHADING_OBJECT_COLOR;
+ else if (color_type == V3D_SHADING_VERTEX_COLOR) {
+ if ((me == NULL) || !CustomData_has_layer(&me->vdata, CD_PROP_COLOR)) {
+ color_type = V3D_SHADING_OBJECT_COLOR;
+ }
}
if (r_sculpt_pbvh) {
@@ -379,7 +394,7 @@ void workbench_cache_finish(void *ved)
/* TODO(fclem) Only do this when really needed. */
{
- /* HACK we allocate the infront depth here to avoid the overhead when if is not needed. */
+ /* HACK we allocate the in front depth here to avoid the overhead when if is not needed. */
DefaultFramebufferList *dfbl = DRW_viewport_framebuffer_list_get();
DefaultTextureList *dtxl = DRW_viewport_texture_list_get();
diff --git a/source/blender/draw/engines/workbench/workbench_materials.c b/source/blender/draw/engines/workbench/workbench_materials.c
index 0b2d508fee5..d6d3ff8610b 100644
--- a/source/blender/draw/engines/workbench/workbench_materials.c
+++ b/source/blender/draw/engines/workbench/workbench_materials.c
@@ -57,7 +57,7 @@ void workbench_material_ubo_data(WORKBENCH_PrivateData *wpd,
case V3D_SHADING_RANDOM_COLOR: {
uint hash = BLI_ghashutil_strhash_p_murmur(ob->id.name);
if (ob->id.lib) {
- hash = (hash * 13) ^ BLI_ghashutil_strhash_p_murmur(ob->id.lib->name);
+ hash = (hash * 13) ^ BLI_ghashutil_strhash_p_murmur(ob->id.lib->filepath);
}
float hue = BLI_hash_int_01(hash);
float hsv[3] = {hue, HSV_SATURATION, HSV_VALUE};
diff --git a/source/blender/draw/engines/workbench/workbench_private.h b/source/blender/draw/engines/workbench/workbench_private.h
index 20b6d368ac0..ee9960ea0ef 100644
--- a/source/blender/draw/engines/workbench/workbench_private.h
+++ b/source/blender/draw/engines/workbench/workbench_private.h
@@ -293,7 +293,7 @@ typedef struct WORKBENCH_PrivateData {
/** Object IDs buffer for curvature & outline. */
struct GPUTexture *object_id_tx;
- /** Prepass infos for each draw types [transparent][infront][hair]. */
+ /** Pre-pass information for each draw types [transparent][infront][hair]. */
WORKBENCH_Prepass prepass[2][2][2];
/* Materials */
diff --git a/source/blender/draw/engines/workbench/workbench_transparent.c b/source/blender/draw/engines/workbench/workbench_transparent.c
index 5fd8229304a..1c40a350300 100644
--- a/source/blender/draw/engines/workbench/workbench_transparent.c
+++ b/source/blender/draw/engines/workbench/workbench_transparent.c
@@ -157,7 +157,7 @@ void workbench_transparent_draw_depth_pass(WORKBENCH_Data *data)
WORKBENCH_FramebufferList *fbl = data->fbl;
WORKBENCH_PassList *psl = data->psl;
- const bool do_xray_depth_pass = XRAY_ALPHA(wpd) > 0.0f;
+ const bool do_xray_depth_pass = !XRAY_FLAG_ENABLED(wpd) || XRAY_ALPHA(wpd) > 0.0f;
const bool do_transparent_depth_pass = psl->outline_ps || wpd->dof_enabled || do_xray_depth_pass;
if (do_transparent_depth_pass) {
@@ -165,14 +165,14 @@ void workbench_transparent_draw_depth_pass(WORKBENCH_Data *data)
if (!DRW_pass_is_empty(psl->transp_accum_ps)) {
GPU_framebuffer_bind(fbl->opaque_fb);
- /* TODO(fclem) Disable writting to first two buffers. Unecessary waste of bandwidth. */
+ /* TODO(fclem) Disable writing to first two buffers. Unnecessary waste of bandwidth. */
DRW_pass_state_set(psl->transp_accum_ps, state | wpd->cull_state | wpd->clip_state);
DRW_draw_pass(psl->transp_accum_ps);
}
if (!DRW_pass_is_empty(psl->transp_accum_infront_ps)) {
GPU_framebuffer_bind(fbl->opaque_infront_fb);
- /* TODO(fclem) Disable writting to first two buffers. Unecessary waste of bandwidth. */
+ /* TODO(fclem) Disable writing to first two buffers. Unnecessary waste of bandwidth. */
DRW_pass_state_set(psl->transp_accum_infront_ps, state | wpd->cull_state | wpd->clip_state);
DRW_draw_pass(psl->transp_accum_infront_ps);
}
diff --git a/source/blender/draw/intern/DRW_render.h b/source/blender/draw/intern/DRW_render.h
index 89dd6fa210c..555043ab408 100644
--- a/source/blender/draw/intern/DRW_render.h
+++ b/source/blender/draw/intern/DRW_render.h
@@ -462,6 +462,10 @@ void DRW_shgroup_uniform_texture_ex(DRWShadingGroup *shgroup,
const char *name,
const struct GPUTexture *tex,
eGPUSamplerState sampler_state);
+void DRW_shgroup_uniform_texture_ref_ex(DRWShadingGroup *shgroup,
+ const char *name,
+ GPUTexture **tex,
+ eGPUSamplerState sampler_state);
void DRW_shgroup_uniform_texture(DRWShadingGroup *shgroup,
const char *name,
const struct GPUTexture *tex);
@@ -569,7 +573,7 @@ void DRW_view_update_sub(DRWView *view, const float viewmat[4][4], const float w
const DRWView *DRW_view_default_get(void);
void DRW_view_default_set(DRWView *view);
-
+void DRW_view_reset(void);
void DRW_view_set_active(DRWView *view);
void DRW_view_clip_planes_set(DRWView *view, float (*planes)[4], int plane_len);
@@ -626,6 +630,8 @@ void DRW_custom_pipeline(DrawEngineType *draw_engine_type,
void (*callback)(void *vedata, void *user_data),
void *user_data);
+void DRW_cache_restart(void);
+
/* ViewLayers */
void *DRW_view_layer_engine_data_get(DrawEngineType *engine_type);
void **DRW_view_layer_engine_data_ensure_ex(struct ViewLayer *view_layer,
diff --git a/source/blender/draw/intern/draw_cache.c b/source/blender/draw/intern/draw_cache.c
index af5b9cd05dd..9f30cd85957 100644
--- a/source/blender/draw/intern/draw_cache.c
+++ b/source/blender/draw/intern/draw_cache.c
@@ -888,6 +888,32 @@ GPUBatch *DRW_cache_object_surface_get(Object *ob)
}
}
+/* Returns the vertbuf used by shaded surface batch. */
+GPUVertBuf *DRW_cache_object_pos_vertbuf_get(Object *ob)
+{
+ Mesh *me = BKE_object_get_evaluated_mesh(ob);
+ short type = (me != NULL) ? OB_MESH : ob->type;
+
+ switch (type) {
+ case OB_MESH:
+ return DRW_mesh_batch_cache_pos_vertbuf_get((me != NULL) ? me : ob->data);
+ case OB_CURVE:
+ case OB_SURF:
+ case OB_FONT:
+ return DRW_curve_batch_cache_pos_vertbuf_get(ob->data);
+ case OB_MBALL:
+ return DRW_mball_batch_cache_pos_vertbuf_get(ob);
+ case OB_HAIR:
+ return NULL;
+ case OB_POINTCLOUD:
+ return NULL;
+ case OB_VOLUME:
+ return NULL;
+ default:
+ return NULL;
+ }
+}
+
int DRW_cache_object_material_count_get(struct Object *ob)
{
Mesh *me = BKE_object_get_evaluated_mesh(ob);
@@ -2844,6 +2870,12 @@ GPUBatch *DRW_cache_mesh_surface_vertpaint_get(Object *ob)
return DRW_mesh_batch_cache_get_surface_vertpaint(ob->data);
}
+GPUBatch *DRW_cache_mesh_surface_sculptcolors_get(Object *ob)
+{
+ BLI_assert(ob->type == OB_MESH);
+ return DRW_mesh_batch_cache_get_surface_sculpt(ob->data);
+}
+
GPUBatch *DRW_cache_mesh_surface_weights_get(Object *ob)
{
BLI_assert(ob->type == OB_MESH);
diff --git a/source/blender/draw/intern/draw_cache.h b/source/blender/draw/intern/draw_cache.h
index 221fb89612f..2f289bf4110 100644
--- a/source/blender/draw/intern/draw_cache.h
+++ b/source/blender/draw/intern/draw_cache.h
@@ -63,6 +63,8 @@ struct GPUBatch **DRW_cache_object_surface_material_get(struct Object *ob,
struct GPUBatch *DRW_cache_object_face_wireframe_get(struct Object *ob);
int DRW_cache_object_material_count_get(struct Object *ob);
+struct GPUVertBuf *DRW_cache_object_pos_vertbuf_get(struct Object *ob);
+
/* Empties */
struct GPUBatch *DRW_cache_plain_axes_get(void);
struct GPUBatch *DRW_cache_single_arrow_get(void);
@@ -134,6 +136,7 @@ struct GPUBatch **DRW_cache_mesh_surface_shaded_get(struct Object *ob,
struct GPUBatch **DRW_cache_mesh_surface_texpaint_get(struct Object *ob);
struct GPUBatch *DRW_cache_mesh_surface_texpaint_single_get(struct Object *ob);
struct GPUBatch *DRW_cache_mesh_surface_vertpaint_get(struct Object *ob);
+struct GPUBatch *DRW_cache_mesh_surface_sculptcolors_get(struct Object *ob);
struct GPUBatch *DRW_cache_mesh_surface_weights_get(struct Object *ob);
struct GPUBatch *DRW_cache_mesh_surface_mesh_analysis_get(struct Object *ob);
struct GPUBatch *DRW_cache_mesh_face_wireframe_get(struct Object *ob);
diff --git a/source/blender/draw/intern/draw_cache_extract.h b/source/blender/draw/intern/draw_cache_extract.h
index f203c2ff1ea..302f9a0d3a8 100644
--- a/source/blender/draw/intern/draw_cache_extract.h
+++ b/source/blender/draw/intern/draw_cache_extract.h
@@ -53,6 +53,7 @@ typedef struct DRW_MeshCDMask {
uint32_t uv : 8;
uint32_t tan : 8;
uint32_t vcol : 8;
+ uint32_t sculpt_vcol : 8;
uint32_t orco : 1;
uint32_t tan_orco : 1;
/** Edit uv layer is from the base edit mesh as
@@ -62,7 +63,7 @@ typedef struct DRW_MeshCDMask {
typedef enum eMRIterType {
MR_ITER_LOOPTRI = 1 << 0,
- MR_ITER_LOOP = 1 << 1,
+ MR_ITER_POLY = 1 << 1,
MR_ITER_LEDGE = 1 << 2,
MR_ITER_LVERT = 1 << 3,
} eMRIterType;
diff --git a/source/blender/draw/intern/draw_cache_extract_mesh.c b/source/blender/draw/intern/draw_cache_extract_mesh.c
index f3dc8f0fd2a..c92722fad7e 100644
--- a/source/blender/draw/intern/draw_cache_extract_mesh.c
+++ b/source/blender/draw/intern/draw_cache_extract_mesh.c
@@ -128,7 +128,7 @@ typedef struct MeshRenderData {
BMEdge *eed_act;
BMFace *efa_act;
BMFace *efa_act_uv;
- /* Data created on-demand (usually not for bmesh-based data). */
+ /* Data created on-demand (usually not for #BMesh based data). */
MLoopTri *mlooptri;
float (*loop_normals)[3];
float (*poly_normals)[3];
@@ -145,17 +145,17 @@ static void mesh_render_data_update_loose_geom(MeshRenderData *mr,
mr->vert_loose_len = 0;
mr->edge_loose_len = 0;
- BLI_bitmap *lvert_map = BLI_BITMAP_NEW(mr->vert_len, "lvert map");
+ BLI_bitmap *lvert_map = BLI_BITMAP_NEW(mr->vert_len, __func__);
mr->ledges = MEM_mallocN(mr->edge_len * sizeof(int), __func__);
- const MEdge *medge = mr->medge;
- for (int e = 0; e < mr->edge_len; e++, medge++) {
- if (medge->flag & ME_LOOSEEDGE) {
- mr->ledges[mr->edge_loose_len++] = e;
+ const MEdge *med = mr->medge;
+ for (int med_index = 0; med_index < mr->edge_len; med_index++, med++) {
+ if (med->flag & ME_LOOSEEDGE) {
+ mr->ledges[mr->edge_loose_len++] = med_index;
}
/* Tag verts as not loose. */
- BLI_BITMAP_ENABLE(lvert_map, medge->v1);
- BLI_BITMAP_ENABLE(lvert_map, medge->v2);
+ BLI_BITMAP_ENABLE(lvert_map, med->v1);
+ BLI_BITMAP_ENABLE(lvert_map, med->v2);
}
if (mr->edge_loose_len < mr->edge_len) {
mr->ledges = MEM_reallocN(mr->ledges, mr->edge_loose_len * sizeof(*mr->ledges));
@@ -173,11 +173,11 @@ static void mesh_render_data_update_loose_geom(MeshRenderData *mr,
MEM_freeN(lvert_map);
- mr->loop_loose_len = mr->vert_loose_len + mr->edge_loose_len * 2;
+ mr->loop_loose_len = mr->vert_loose_len + (mr->edge_loose_len * 2);
}
}
else {
- /* BMesh */
+ /* #BMesh */
BMesh *bm = mr->bm;
if (iter_type & (MR_ITER_LEDGE | MR_ITER_LVERT)) {
int elem_id;
@@ -212,7 +212,9 @@ static void mesh_render_data_update_loose_geom(MeshRenderData *mr,
}
}
-/* Part of the creation of the MeshRenderData that happens in a thread. */
+/**
+ * Part of the creation of the #MeshRenderData that happens in a thread.
+ */
static void mesh_render_data_update_looptris(MeshRenderData *mr,
const eMRIterType iter_type,
const eMRDataType data_flag)
@@ -227,7 +229,7 @@ static void mesh_render_data_update_looptris(MeshRenderData *mr,
}
}
else {
- /* BMesh */
+ /* #BMesh */
if ((iter_type & MR_ITER_LOOPTRI) || (data_flag & MR_DATA_LOOPTRI)) {
/* Edit mode ensures this is valid, no need to calculate. */
BLI_assert((mr->bm->totloop == 0) || (mr->edit_bmesh->looptris != NULL));
@@ -278,9 +280,9 @@ static void mesh_render_data_update_normals(MeshRenderData *mr,
}
}
else {
- /* BMesh */
+ /* #BMesh */
if (data_flag & MR_DATA_POLY_NOR) {
- /* Use bmface->no instead. */
+ /* Use #BMFace.no instead. */
}
if (((data_flag & MR_DATA_LOOP_NOR) && is_auto_smooth) || (data_flag & MR_DATA_TAN_LOOP_NOR)) {
@@ -295,7 +297,7 @@ static void mesh_render_data_update_normals(MeshRenderData *mr,
}
mr->loop_normals = MEM_mallocN(sizeof(*mr->loop_normals) * mr->loop_len, __func__);
- int clnors_offset = CustomData_get_offset(&mr->bm->ldata, CD_CUSTOMLOOPNORMAL);
+ const int clnors_offset = CustomData_get_offset(&mr->bm->ldata, CD_CUSTOMLOOPNORMAL);
BM_loops_calc_normal_vcos(mr->bm,
vert_coords,
vert_normals,
@@ -419,7 +421,7 @@ static MeshRenderData *mesh_render_data_create(Mesh *me,
mr->p_origindex = CustomData_get_layer(&mr->me->pdata, CD_ORIGINDEX);
}
else {
- /* BMesh */
+ /* #BMesh */
BMesh *bm = mr->bm;
mr->vert_len = bm->totvert;
@@ -486,7 +488,7 @@ BLI_INLINE const float *bm_vert_no_get(const MeshRenderData *mr, const BMVert *e
}
else {
UNUSED_VARS(mr);
- return eve->co;
+ return eve->no;
}
}
@@ -505,48 +507,283 @@ BLI_INLINE const float *bm_face_no_get(const MeshRenderData *mr, const BMFace *e
/** \} */
/* ---------------------------------------------------------------------- */
-/** \name Mesh Elements Extract Iter
+/** \name Mesh Elements Extract: Loop Triangles
+ * \{ */
+
+typedef struct ExtractTriBMesh_Params {
+ BMLoop *(*looptris)[3];
+ int tri_range[2];
+} ExtractTriBMesh_Params;
+typedef void(ExtractTriBMeshFn)(const MeshRenderData *mr,
+ const ExtractTriBMesh_Params *params,
+ void *data);
+
+#define EXTRACT_TRIS_LOOPTRI_FOREACH_BM_BEGIN(elem_tri, index_tri, params) \
+ CHECK_TYPE(params, const ExtractTriBMesh_Params *); \
+ { \
+ const int _tri_index_end = (params)->tri_range[1]; \
+ BMLoop **elem_tri = (params)->looptris[(params)->tri_range[0]]; \
+ for (int index_tri = (params)->tri_range[0]; index_tri < _tri_index_end; \
+ index_tri += 1, elem_tri += 3)
+#define EXTRACT_TRIS_LOOPTRI_FOREACH_BM_END }
+
+typedef struct ExtractTriMesh_Params {
+ const MLoopTri *mlooptri;
+ int tri_range[2];
+} ExtractTriMesh_Params;
+typedef void(ExtractTriMeshFn)(const MeshRenderData *mr,
+ const ExtractTriMesh_Params *params,
+ void *data);
+
+#define EXTRACT_TRIS_LOOPTRI_FOREACH_MESH_BEGIN(elem_tri, index_tri, params) \
+ CHECK_TYPE(params, const ExtractTriMesh_Params *); \
+ { \
+ const int _tri_index_end = (params)->tri_range[1]; \
+ const MLoopTri *elem_tri = &(params)->mlooptri[(params)->tri_range[0]]; \
+ for (int index_tri = (params)->tri_range[0]; index_tri < _tri_index_end; \
+ index_tri += 1, elem_tri += 1)
+#define EXTRACT_TRIS_LOOPTRI_FOREACH_MESH_END }
+
+/** \} */
+
+/* ---------------------------------------------------------------------- */
+/** \name Mesh Elements Extract: Polygons, Loops
+ * \{ */
+
+typedef struct ExtractPolyBMesh_Params {
+ BMLoop *(*looptris)[3];
+ int poly_range[2];
+} ExtractPolyBMesh_Params;
+typedef void(ExtractPolyBMeshFn)(const MeshRenderData *mr,
+ const ExtractPolyBMesh_Params *params,
+ void *data);
+
+#define EXTRACT_POLY_FOREACH_BM_BEGIN(elem_poly, index_poly, params, mr) \
+ CHECK_TYPE(params, const ExtractPolyBMesh_Params *); \
+ { \
+ BLI_assert((mr->bm->elem_table_dirty & BM_FACE) == 0); \
+ BMFace **_ftable = mr->bm->ftable; \
+ const int _poly_index_end = (params)->poly_range[1]; \
+ for (int index_poly = (params)->poly_range[0]; index_poly < _poly_index_end; \
+ index_poly += 1) { \
+ BMFace *elem_poly = _ftable[index_poly]; \
+ (void)elem_poly;
+
+#define EXTRACT_POLY_FOREACH_BM_END \
+ } \
+ }
+
+/* Iterate over polygon and loop. */
+#define EXTRACT_POLY_AND_LOOP_FOREACH_BM_BEGIN(elem_loop, index_loop, params, mr) \
+ CHECK_TYPE(params, const ExtractPolyBMesh_Params *); \
+ { \
+ BLI_assert((mr->bm->elem_table_dirty & BM_FACE) == 0); \
+ BMFace **_ftable = mr->bm->ftable; \
+ const int _poly_index_end = (params)->poly_range[1]; \
+ for (int index_poly = (params)->poly_range[0]; index_poly < _poly_index_end; \
+ index_poly += 1) { \
+ BMFace *elem_face = _ftable[index_poly]; \
+ BMLoop *elem_loop, *l_first; \
+ elem_loop = l_first = BM_FACE_FIRST_LOOP(elem_face); \
+ do { \
+ const int index_loop = BM_elem_index_get(elem_loop); \
+ (void)index_loop; /* Quiet warning when unused. */
+
+#define EXTRACT_POLY_AND_LOOP_FOREACH_BM_END(elem_loop) \
+ } \
+ while ((elem_loop = elem_loop->next) != l_first) \
+ ; \
+ } \
+ }
+
+typedef struct ExtractPolyMesh_Params {
+ int poly_range[2];
+} ExtractPolyMesh_Params;
+typedef void(ExtractPolyMeshFn)(const MeshRenderData *mr,
+ const ExtractPolyMesh_Params *params,
+ void *data);
+
+#define EXTRACT_POLY_FOREACH_MESH_BEGIN(elem_poly, index_poly, params, mr) \
+ CHECK_TYPE(params, const ExtractPolyMesh_Params *); \
+ { \
+ const MPoly *_mpoly = mr->mpoly; \
+ const int _poly_index_end = (params)->poly_range[1]; \
+ for (int index_poly = (params)->poly_range[0]; index_poly < _poly_index_end; \
+ index_poly += 1) { \
+ const MPoly *elem_poly = &_mpoly[index_poly]; \
+ (void)elem_poly;
+
+#define EXTRACT_POLY_FOREACH_MESH_END \
+ } \
+ }
+
+/* Iterate over polygon and loop. */
+#define EXTRACT_POLY_AND_LOOP_FOREACH_MESH_BEGIN( \
+ elem_poly, index_poly, elem_loop, index_loop, params, mr) \
+ CHECK_TYPE(params, const ExtractPolyMesh_Params *); \
+ { \
+ const MPoly *_mpoly = mr->mpoly; \
+ const MLoop *_mloop = mr->mloop; \
+ const int _poly_index_end = (params)->poly_range[1]; \
+ for (int index_poly = (params)->poly_range[0]; index_poly < _poly_index_end; \
+ index_poly += 1) { \
+ const MPoly *elem_poly = &_mpoly[index_poly]; \
+ const int _index_end = elem_poly->loopstart + elem_poly->totloop; \
+ for (int index_loop = elem_poly->loopstart; index_loop < _index_end; index_loop += 1) { \
+ const MLoop *elem_loop = &_mloop[index_loop]; \
+ (void)elem_loop;
+
+#define EXTRACT_POLY_AND_LOOP_FOREACH_MESH_END \
+ } \
+ } \
+ }
+
+/** \} */
+
+/* ---------------------------------------------------------------------- */
+/** \name Mesh Elements Extract: Loose Edges
+ * \{ */
+
+typedef struct ExtractLEdgeBMesh_Params {
+ const int *ledge;
+ int ledge_range[2];
+} ExtractLEdgeBMesh_Params;
+typedef void(ExtractLEdgeBMeshFn)(const MeshRenderData *mr,
+ const ExtractLEdgeBMesh_Params *params,
+ void *data);
+
+#define EXTRACT_LEDGE_FOREACH_BM_BEGIN(elem_edge, index_ledge, params) \
+ CHECK_TYPE(params, const ExtractLEdgeBMesh_Params *); \
+ { \
+ BLI_assert((mr->bm->elem_table_dirty & BM_EDGE) == 0); \
+ BMEdge **_etable = mr->bm->etable; \
+ const int *_ledge = (params)->ledge; \
+ const int _ledge_index_end = (params)->ledge_range[1]; \
+ for (int index_ledge = (params)->ledge_range[0]; index_ledge < _ledge_index_end; \
+ index_ledge += 1) { \
+ BMEdge *elem_edge = _etable[_ledge[index_ledge]]; \
+ (void)elem_edge; /* Quiet warning when unused. */ \
+ {
+#define EXTRACT_LEDGE_FOREACH_BM_END \
+ } \
+ } \
+ }
+
+typedef struct ExtractLEdgeMesh_Params {
+ const int *ledge;
+ int ledge_range[2];
+} ExtractLEdgeMesh_Params;
+typedef void(ExtractLEdgeMeshFn)(const MeshRenderData *mr,
+ const ExtractLEdgeMesh_Params *params,
+ void *data);
+
+#define EXTRACT_LEDGE_FOREACH_MESH_BEGIN(elem_edge, index_ledge, params, mr) \
+ CHECK_TYPE(params, const ExtractLEdgeMesh_Params *); \
+ { \
+ const MEdge *_medge = mr->medge; \
+ const int *_ledge = (params)->ledge; \
+ const int _ledge_index_end = (params)->ledge_range[1]; \
+ for (int index_ledge = (params)->ledge_range[0]; index_ledge < _ledge_index_end; \
+ index_ledge += 1) { \
+ const MEdge *elem_edge = &_medge[_ledge[index_ledge]]; \
+ (void)elem_edge; /* Quiet warning when unused. */ \
+ {
+#define EXTRACT_LEDGE_FOREACH_MESH_END \
+ } \
+ } \
+ }
+
+/** \} */
+
+/* ---------------------------------------------------------------------- */
+/** \name Mesh Elements Extract: Loose Vertices
+ * \{ */
+
+typedef struct ExtractLVertBMesh_Params {
+ const int *lvert;
+ int lvert_range[2];
+} ExtractLVertBMesh_Params;
+typedef void(ExtractLVertBMeshFn)(const MeshRenderData *mr,
+ const ExtractLVertBMesh_Params *params,
+ void *data);
+
+#define EXTRACT_LVERT_FOREACH_BM_BEGIN(elem_vert, index_lvert, params) \
+ CHECK_TYPE(params, const ExtractLVertBMesh_Params *); \
+ { \
+ BLI_assert((mr->bm->elem_table_dirty & BM_FACE) == 0); \
+ BMVert **vtable = mr->bm->vtable; \
+ const int *lverts = (params)->lvert; \
+ const int _lvert_index_end = (params)->lvert_range[1]; \
+ for (int index_lvert = (params)->lvert_range[0]; index_lvert < _lvert_index_end; \
+ index_lvert += 1) { \
+ BMVert *elem_vert = vtable[lverts[index_lvert]]; \
+ (void)elem_vert; /* Quiet warning when unused. */ \
+ {
+#define EXTRACT_LVERT_FOREACH_BM_END \
+ } \
+ } \
+ }
+
+typedef struct ExtractLVertMesh_Params {
+ const int *lvert;
+ int lvert_range[2];
+} ExtractLVertMesh_Params;
+typedef void(ExtractLVertMeshFn)(const MeshRenderData *mr,
+ const ExtractLVertMesh_Params *params,
+ void *data);
+
+#define EXTRACT_LVERT_FOREACH_MESH_BEGIN(elem, index_lvert, params, mr) \
+ CHECK_TYPE(params, const ExtractLVertMesh_Params *); \
+ { \
+ const MVert *mvert = mr->mvert; \
+ const int *lverts = (params)->lvert; \
+ const int _lvert_index_end = (params)->lvert_range[1]; \
+ for (int index_lvert = (params)->lvert_range[0]; index_lvert < _lvert_index_end; \
+ index_lvert += 1) { \
+ const MVert *elem = &mvert[lverts[index_lvert]]; \
+ (void)elem; /* Quiet warning when unused. */ \
+ {
+#define EXTRACT_LVERT_FOREACH_MESH_END \
+ } \
+ } \
+ }
+
+/** \} */
+
+/* ---------------------------------------------------------------------- */
+/** \name Mesh Elements Extract Struct
* \{ */
typedef void *(ExtractInitFn)(const MeshRenderData *mr, void *buffer);
-typedef void(ExtractEditTriFn)(const MeshRenderData *mr, int t, BMLoop **e, void *data);
-typedef void(ExtractEditLoopFn)(const MeshRenderData *mr, int l, BMLoop *el, void *data);
-typedef void(ExtractEditLedgeFn)(const MeshRenderData *mr, int e, BMEdge *ed, void *data);
-typedef void(ExtractEditLvertFn)(const MeshRenderData *mr, int v, BMVert *ev, void *data);
-typedef void(ExtractTriFn)(const MeshRenderData *mr, int t, const MLoopTri *mlt, void *data);
-typedef void(ExtractLoopFn)(
- const MeshRenderData *mr, int l, const MLoop *mloop, int p, const MPoly *mpoly, void *data);
-typedef void(ExtractLedgeFn)(const MeshRenderData *mr, int e, const MEdge *medge, void *data);
-typedef void(ExtractLvertFn)(const MeshRenderData *mr, int v, const MVert *mvert, void *data);
typedef void(ExtractFinishFn)(const MeshRenderData *mr, void *buffer, void *data);
typedef struct MeshExtract {
- /** Executed on main thread and return user data for iter functions. */
+ /** Executed on main thread and return user data for iteration functions. */
ExtractInitFn *init;
/** Executed on one (or more if use_threading) worker thread(s). */
- ExtractEditTriFn *iter_looptri_bm;
- ExtractTriFn *iter_looptri;
- ExtractEditLoopFn *iter_loop_bm;
- ExtractLoopFn *iter_loop;
- ExtractEditLedgeFn *iter_ledge_bm;
- ExtractLedgeFn *iter_ledge;
- ExtractEditLvertFn *iter_lvert_bm;
- ExtractLvertFn *iter_lvert;
+ ExtractTriBMeshFn *iter_looptri_bm;
+ ExtractTriMeshFn *iter_looptri_mesh;
+ ExtractPolyBMeshFn *iter_poly_bm;
+ ExtractPolyMeshFn *iter_poly_mesh;
+ ExtractLEdgeBMeshFn *iter_ledge_bm;
+ ExtractLEdgeMeshFn *iter_ledge_mesh;
+ ExtractLVertBMeshFn *iter_lvert_bm;
+ ExtractLVertMeshFn *iter_lvert_mesh;
/** Executed on one worker thread after all elements iterations. */
ExtractFinishFn *finish;
/** Used to request common data. */
const eMRDataType data_flag;
- /** Used to know if the element callbacks are threadsafe and can be parallelized. */
+ /** Used to know if the element callbacks are thread-safe and can be parallelized. */
const bool use_threading;
} MeshExtract;
BLI_INLINE eMRIterType mesh_extract_iter_type(const MeshExtract *ext)
{
eMRIterType type = 0;
- SET_FLAG_FROM_TEST(type, (ext->iter_looptri_bm || ext->iter_looptri), MR_ITER_LOOPTRI);
- SET_FLAG_FROM_TEST(type, (ext->iter_loop_bm || ext->iter_loop), MR_ITER_LOOP);
- SET_FLAG_FROM_TEST(type, (ext->iter_ledge_bm || ext->iter_ledge), MR_ITER_LEDGE);
- SET_FLAG_FROM_TEST(type, (ext->iter_lvert_bm || ext->iter_lvert), MR_ITER_LVERT);
+ SET_FLAG_FROM_TEST(type, (ext->iter_looptri_bm || ext->iter_looptri_mesh), MR_ITER_LOOPTRI);
+ SET_FLAG_FROM_TEST(type, (ext->iter_poly_bm || ext->iter_poly_mesh), MR_ITER_POLY);
+ SET_FLAG_FROM_TEST(type, (ext->iter_ledge_bm || ext->iter_ledge_mesh), MR_ITER_LEDGE);
+ SET_FLAG_FROM_TEST(type, (ext->iter_lvert_bm || ext->iter_lvert_mesh), MR_ITER_LVERT);
return type;
}
@@ -583,15 +820,15 @@ static void *extract_tris_init(const MeshRenderData *mr, void *UNUSED(ibo))
}
}
else {
- const MPoly *mpoly = mr->mpoly;
- for (int p = 0; p < mr->poly_len; p++, mpoly++) {
- if (!(mr->use_hide && (mpoly->flag & ME_HIDE))) {
- int mat = min_ii(mpoly->mat_nr, mr->mat_len - 1);
- mat_tri_len[mat] += mpoly->totloop - 2;
+ const MPoly *mp = mr->mpoly;
+ for (int mp_index = 0; mp_index < mr->poly_len; mp_index++, mp++) {
+ if (!(mr->use_hide && (mp->flag & ME_HIDE))) {
+ int mat = min_ii(mp->mat_nr, mr->mat_len - 1);
+ mat_tri_len[mat] += mp->totloop - 2;
}
}
}
- /* Accumulate tri len per mat to have correct offsets. */
+ /* Accumulate triangle lengths per material to have correct offsets. */
int ofs = mat_tri_len[0];
mat_tri_len[0] = 0;
for (int i = 1; i < mr->mat_len; i++) {
@@ -608,51 +845,59 @@ static void *extract_tris_init(const MeshRenderData *mr, void *UNUSED(ibo))
return data;
}
-static void extract_tris_looptri_bmesh(const MeshRenderData *mr,
- int UNUSED(t),
- BMLoop **elt,
- void *_data)
+static void extract_tris_iter_looptri_bm(const MeshRenderData *mr,
+ const struct ExtractTriBMesh_Params *params,
+ void *_data)
{
- if (!BM_elem_flag_test(elt[0]->f, BM_ELEM_HIDDEN)) {
- MeshExtract_Tri_Data *data = _data;
- int *mat_tri_ofs = data->tri_mat_end;
- int mat = min_ii(elt[0]->f->mat_nr, mr->mat_len - 1);
- GPU_indexbuf_set_tri_verts(&data->elb,
- mat_tri_ofs[mat]++,
- BM_elem_index_get(elt[0]),
- BM_elem_index_get(elt[1]),
- BM_elem_index_get(elt[2]));
+ MeshExtract_Tri_Data *data = _data;
+ const int mat_last = mr->mat_len - 1;
+ EXTRACT_TRIS_LOOPTRI_FOREACH_BM_BEGIN(elt, _elt_index, params)
+ {
+ if (!BM_elem_flag_test(elt[0]->f, BM_ELEM_HIDDEN)) {
+ int *mat_tri_ofs = data->tri_mat_end;
+ const int mat = min_ii(elt[0]->f->mat_nr, mat_last);
+ GPU_indexbuf_set_tri_verts(&data->elb,
+ mat_tri_ofs[mat]++,
+ BM_elem_index_get(elt[0]),
+ BM_elem_index_get(elt[1]),
+ BM_elem_index_get(elt[2]));
+ }
}
+ EXTRACT_TRIS_LOOPTRI_FOREACH_BM_END;
}
-static void extract_tris_looptri_mesh(const MeshRenderData *mr,
- int UNUSED(t),
- const MLoopTri *mlt,
- void *_data)
+static void extract_tris_iter_looptri_mesh(const MeshRenderData *mr,
+ const struct ExtractTriMesh_Params *params,
+ void *_data)
{
- const MPoly *mpoly = &mr->mpoly[mlt->poly];
- if (!(mr->use_hide && (mpoly->flag & ME_HIDE))) {
- MeshExtract_Tri_Data *data = _data;
- int *mat_tri_ofs = data->tri_mat_end;
- int mat = min_ii(mpoly->mat_nr, mr->mat_len - 1);
- GPU_indexbuf_set_tri_verts(
- &data->elb, mat_tri_ofs[mat]++, mlt->tri[0], mlt->tri[1], mlt->tri[2]);
+ MeshExtract_Tri_Data *data = _data;
+ const int mat_last = mr->mat_len - 1;
+ EXTRACT_TRIS_LOOPTRI_FOREACH_MESH_BEGIN(mlt, _mlt_index, params)
+ {
+ const MPoly *mp = &mr->mpoly[mlt->poly];
+ if (!(mr->use_hide && (mp->flag & ME_HIDE))) {
+ int *mat_tri_ofs = data->tri_mat_end;
+ const int mat = min_ii(mp->mat_nr, mat_last);
+ GPU_indexbuf_set_tri_verts(
+ &data->elb, mat_tri_ofs[mat]++, mlt->tri[0], mlt->tri[1], mlt->tri[2]);
+ }
}
+ EXTRACT_TRIS_LOOPTRI_FOREACH_MESH_END;
}
static void extract_tris_finish(const MeshRenderData *mr, void *ibo, void *_data)
{
MeshExtract_Tri_Data *data = _data;
GPU_indexbuf_build_in_place(&data->elb, ibo);
- /* HACK Create ibo subranges and assign them to each GPUBatch. */
+ /* HACK: Create ibo sub-ranges and assign them to each #GPUBatch. */
if (mr->use_final_mesh && mr->cache->surface_per_mat && mr->cache->surface_per_mat[0]) {
BLI_assert(mr->cache->surface_per_mat[0]->elem == ibo);
for (int i = 0; i < mr->mat_len; i++) {
/* Multiply by 3 because these are triangle indices. */
- int start = data->tri_mat_start[i] * 3;
- int len = data->tri_mat_end[i] * 3 - data->tri_mat_start[i] * 3;
+ const int start = data->tri_mat_start[i] * 3;
+ const int len = data->tri_mat_end[i] * 3 - data->tri_mat_start[i] * 3;
GPUIndexBuf *sub_ibo = GPU_indexbuf_create_subrange(ibo, start, len);
- /* WARNING: We modify the GPUBatch here! */
+ /* WARNING: We modify the #GPUBatch here! */
GPU_batch_elembuf_set(mr->cache->surface_per_mat[i], sub_ibo, true);
}
}
@@ -662,18 +907,12 @@ static void extract_tris_finish(const MeshRenderData *mr, void *ibo, void *_data
}
static const MeshExtract extract_tris = {
- extract_tris_init,
- extract_tris_looptri_bmesh,
- extract_tris_looptri_mesh,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- extract_tris_finish,
- 0,
- false,
+ .init = extract_tris_init,
+ .iter_looptri_bm = extract_tris_iter_looptri_bm,
+ .iter_looptri_mesh = extract_tris_iter_looptri_mesh,
+ .finish = extract_tris_finish,
+ .data_flag = 0,
+ .use_threading = false,
};
/** \} */
@@ -691,71 +930,113 @@ static void *extract_lines_init(const MeshRenderData *mr, void *UNUSED(buf))
return elb;
}
-static void extract_lines_loop_bmesh(const MeshRenderData *UNUSED(mr),
- int l,
- BMLoop *loop,
- void *elb)
-{
- if (!BM_elem_flag_test(loop->e, BM_ELEM_HIDDEN)) {
- GPU_indexbuf_set_line_verts(elb, BM_elem_index_get(loop->e), l, BM_elem_index_get(loop->next));
- }
- else {
- GPU_indexbuf_set_line_restart(elb, BM_elem_index_get(loop->e));
- }
-}
-
-static void extract_lines_loop_mesh(const MeshRenderData *mr,
- int l,
- const MLoop *mloop,
- int UNUSED(p),
- const MPoly *mpoly,
- void *elb)
-{
- const MEdge *medge = &mr->medge[mloop->e];
- if (!((mr->use_hide && (medge->flag & ME_HIDE)) ||
- ((mr->extract_type == MR_EXTRACT_MAPPED) && (mr->e_origindex) &&
- (mr->e_origindex[mloop->e] == ORIGINDEX_NONE)))) {
- int loopend = mpoly->totloop + mpoly->loopstart - 1;
- int other_loop = (l == loopend) ? mpoly->loopstart : (l + 1);
- GPU_indexbuf_set_line_verts(elb, mloop->e, l, other_loop);
+static void extract_lines_iter_poly_bm(const MeshRenderData *mr,
+ const ExtractPolyBMesh_Params *params,
+ void *elb)
+{
+ /* Using poly & loop iterator would complicate accessing the adjacent loop. */
+ EXTRACT_POLY_FOREACH_BM_BEGIN(f, f_index, params, mr)
+ {
+ BMLoop *l_iter, *l_first;
+ /* Use #BMLoop.prev to match mesh order (to avoid minor differences in data extraction). */
+ l_iter = l_first = BM_FACE_FIRST_LOOP(f)->prev;
+ do {
+ if (!BM_elem_flag_test(l_iter->e, BM_ELEM_HIDDEN)) {
+ GPU_indexbuf_set_line_verts(elb,
+ BM_elem_index_get(l_iter->e),
+ BM_elem_index_get(l_iter),
+ BM_elem_index_get(l_iter->next));
+ }
+ else {
+ GPU_indexbuf_set_line_restart(elb, BM_elem_index_get(l_iter->e));
+ }
+ } while ((l_iter = l_iter->next) != l_first);
+ }
+ EXTRACT_POLY_FOREACH_BM_END;
+}
+
+static void extract_lines_iter_poly_mesh(const MeshRenderData *mr,
+ const ExtractPolyMesh_Params *params,
+ void *elb)
+{
+ /* Using poly & loop iterator would complicate accessing the adjacent loop. */
+ const MLoop *mloop = mr->mloop;
+ const MEdge *medge = mr->medge;
+ if (mr->use_hide || (mr->extract_type == MR_EXTRACT_MAPPED) || (mr->e_origindex != NULL)) {
+ EXTRACT_POLY_FOREACH_MESH_BEGIN(mp, mp_index, params, mr)
+ {
+ const int ml_index_last = mp->loopstart + (mp->totloop - 1);
+ int ml_index = ml_index_last, ml_index_next = mp->loopstart;
+ do {
+ const MLoop *ml = &mloop[ml_index];
+ const MEdge *med = &medge[ml->e];
+ if (!((mr->use_hide && (med->flag & ME_HIDE)) ||
+ ((mr->extract_type == MR_EXTRACT_MAPPED) && (mr->e_origindex) &&
+ (mr->e_origindex[ml->e] == ORIGINDEX_NONE)))) {
+ GPU_indexbuf_set_line_verts(elb, ml->e, ml_index, ml_index_next);
+ }
+ else {
+ GPU_indexbuf_set_line_restart(elb, ml->e);
+ }
+ } while ((ml_index = ml_index_next++) != ml_index_last);
+ }
+ EXTRACT_POLY_FOREACH_MESH_END;
}
else {
- GPU_indexbuf_set_line_restart(elb, mloop->e);
+ EXTRACT_POLY_FOREACH_MESH_BEGIN(mp, mp_index, params, mr)
+ {
+ const int ml_index_last = mp->loopstart + (mp->totloop - 1);
+ int ml_index = ml_index_last, ml_index_next = mp->loopstart;
+ do {
+ const MLoop *ml = &mloop[ml_index];
+ GPU_indexbuf_set_line_verts(elb, ml->e, ml_index, ml_index_next);
+ } while ((ml_index = ml_index_next++) != ml_index_last);
+ }
+ EXTRACT_POLY_FOREACH_MESH_END;
}
}
-static void extract_lines_ledge_bmesh(const MeshRenderData *mr, int e, BMEdge *eed, void *elb)
+static void extract_lines_iter_ledge_bm(const MeshRenderData *mr,
+ const ExtractLEdgeBMesh_Params *params,
+ void *elb)
{
- int ledge_idx = mr->edge_len + e;
- if (!BM_elem_flag_test(eed, BM_ELEM_HIDDEN)) {
- int l = mr->loop_len + e * 2;
- GPU_indexbuf_set_line_verts(elb, ledge_idx, l, l + 1);
- }
- else {
- GPU_indexbuf_set_line_restart(elb, ledge_idx);
+ EXTRACT_LEDGE_FOREACH_BM_BEGIN(eed, ledge_index, params)
+ {
+ const int l_index_offset = mr->edge_len + ledge_index;
+ if (!BM_elem_flag_test(eed, BM_ELEM_HIDDEN)) {
+ const int l_index = mr->loop_len + ledge_index * 2;
+ GPU_indexbuf_set_line_verts(elb, l_index_offset, l_index, l_index + 1);
+ }
+ else {
+ GPU_indexbuf_set_line_restart(elb, l_index_offset);
+ }
+ /* Don't render the edge twice. */
+ GPU_indexbuf_set_line_restart(elb, BM_elem_index_get(eed));
}
- /* Don't render the edge twice. */
- GPU_indexbuf_set_line_restart(elb, BM_elem_index_get(eed));
+ EXTRACT_LEDGE_FOREACH_BM_END;
}
-static void extract_lines_ledge_mesh(const MeshRenderData *mr,
- int e,
- const MEdge *medge,
- void *elb)
+static void extract_lines_iter_ledge_mesh(const MeshRenderData *mr,
+ const ExtractLEdgeMesh_Params *params,
+ void *elb)
{
- int ledge_idx = mr->edge_len + e;
- int edge_idx = mr->ledges[e];
- if (!((mr->use_hide && (medge->flag & ME_HIDE)) ||
- ((mr->extract_type == MR_EXTRACT_MAPPED) && (mr->e_origindex) &&
- (mr->e_origindex[edge_idx] == ORIGINDEX_NONE)))) {
- int l = mr->loop_len + e * 2;
- GPU_indexbuf_set_line_verts(elb, ledge_idx, l, l + 1);
- }
- else {
- GPU_indexbuf_set_line_restart(elb, ledge_idx);
+ EXTRACT_LEDGE_FOREACH_MESH_BEGIN(med, ledge_index, params, mr)
+ {
+ const int l_index_offset = mr->edge_len + ledge_index;
+ const int e_index = mr->ledges[ledge_index];
+ if (!((mr->use_hide && (med->flag & ME_HIDE)) ||
+ ((mr->extract_type == MR_EXTRACT_MAPPED) && (mr->e_origindex) &&
+ (mr->e_origindex[e_index] == ORIGINDEX_NONE)))) {
+ const int l_index = mr->loop_len + ledge_index * 2;
+ GPU_indexbuf_set_line_verts(elb, l_index_offset, l_index, l_index + 1);
+ }
+ else {
+ GPU_indexbuf_set_line_restart(elb, l_index_offset);
+ }
+ /* Don't render the edge twice. */
+ GPU_indexbuf_set_line_restart(elb, e_index);
}
- /* Don't render the edge twice. */
- GPU_indexbuf_set_line_restart(elb, edge_idx);
+ EXTRACT_LEDGE_FOREACH_MESH_END;
}
static void extract_lines_finish(const MeshRenderData *UNUSED(mr), void *ibo, void *elb)
@@ -765,18 +1046,14 @@ static void extract_lines_finish(const MeshRenderData *UNUSED(mr), void *ibo, vo
}
static const MeshExtract extract_lines = {
- extract_lines_init,
- NULL,
- NULL,
- extract_lines_loop_bmesh,
- extract_lines_loop_mesh,
- extract_lines_ledge_bmesh,
- extract_lines_ledge_mesh,
- NULL,
- NULL,
- extract_lines_finish,
- 0,
- false,
+ .init = extract_lines_init,
+ .iter_poly_bm = extract_lines_iter_poly_bm,
+ .iter_poly_mesh = extract_lines_iter_poly_mesh,
+ .iter_ledge_bm = extract_lines_iter_ledge_bm,
+ .iter_ledge_mesh = extract_lines_iter_ledge_mesh,
+ .finish = extract_lines_finish,
+ .data_flag = 0,
+ .use_threading = false,
};
/** \} */
@@ -803,18 +1080,14 @@ static void extract_lines_with_lines_loose_finish(const MeshRenderData *mr, void
}
static const MeshExtract extract_lines_with_lines_loose = {
- extract_lines_init,
- NULL,
- NULL,
- extract_lines_loop_bmesh,
- extract_lines_loop_mesh,
- extract_lines_ledge_bmesh,
- extract_lines_ledge_mesh,
- NULL,
- NULL,
- extract_lines_with_lines_loose_finish,
- 0,
- false,
+ .init = extract_lines_init,
+ .iter_poly_bm = extract_lines_iter_poly_bm,
+ .iter_poly_mesh = extract_lines_iter_poly_mesh,
+ .iter_ledge_bm = extract_lines_iter_ledge_bm,
+ .iter_ledge_mesh = extract_lines_iter_ledge_mesh,
+ .finish = extract_lines_with_lines_loose_finish,
+ .data_flag = 0,
+ .use_threading = false,
};
/** \} */
@@ -830,77 +1103,101 @@ static void *extract_points_init(const MeshRenderData *mr, void *UNUSED(buf))
return elb;
}
-BLI_INLINE void vert_set_bmesh(GPUIndexBufBuilder *elb, BMVert *eve, int loop)
+BLI_INLINE void vert_set_bm(GPUIndexBufBuilder *elb, BMVert *eve, int l_index)
{
- int vert_idx = BM_elem_index_get(eve);
+ const int v_index = BM_elem_index_get(eve);
if (!BM_elem_flag_test(eve, BM_ELEM_HIDDEN)) {
- GPU_indexbuf_set_point_vert(elb, vert_idx, loop);
+ GPU_indexbuf_set_point_vert(elb, v_index, l_index);
}
else {
- GPU_indexbuf_set_point_restart(elb, vert_idx);
+ GPU_indexbuf_set_point_restart(elb, v_index);
}
}
BLI_INLINE void vert_set_mesh(GPUIndexBufBuilder *elb,
const MeshRenderData *mr,
- int vert_idx,
- int loop)
+ const int v_index,
+ const int l_index)
{
- const MVert *mvert = &mr->mvert[vert_idx];
- if (!((mr->use_hide && (mvert->flag & ME_HIDE)) ||
+ const MVert *mv = &mr->mvert[v_index];
+ if (!((mr->use_hide && (mv->flag & ME_HIDE)) ||
((mr->extract_type == MR_EXTRACT_MAPPED) && (mr->v_origindex) &&
- (mr->v_origindex[vert_idx] == ORIGINDEX_NONE)))) {
- GPU_indexbuf_set_point_vert(elb, vert_idx, loop);
+ (mr->v_origindex[v_index] == ORIGINDEX_NONE)))) {
+ GPU_indexbuf_set_point_vert(elb, v_index, l_index);
}
else {
- GPU_indexbuf_set_point_restart(elb, vert_idx);
+ GPU_indexbuf_set_point_restart(elb, v_index);
}
}
-static void extract_points_loop_bmesh(const MeshRenderData *UNUSED(mr),
- int l,
- BMLoop *loop,
- void *elb)
+static void extract_points_iter_poly_bm(const MeshRenderData *mr,
+ const ExtractPolyBMesh_Params *params,
+ void *elb)
{
- vert_set_bmesh(elb, loop->v, l);
+ EXTRACT_POLY_AND_LOOP_FOREACH_BM_BEGIN(l, l_index, params, mr)
+ {
+ vert_set_bm(elb, l->v, l_index);
+ }
+ EXTRACT_POLY_AND_LOOP_FOREACH_BM_END(l);
}
-static void extract_points_loop_mesh(const MeshRenderData *mr,
- int l,
- const MLoop *mloop,
- int UNUSED(p),
- const MPoly *UNUSED(mpoly),
- void *elb)
+static void extract_points_iter_poly_mesh(const MeshRenderData *mr,
+ const ExtractPolyMesh_Params *params,
+ void *elb)
{
- vert_set_mesh(elb, mr, mloop->v, l);
+ EXTRACT_POLY_AND_LOOP_FOREACH_MESH_BEGIN(mp, mp_index, ml, ml_index, params, mr)
+ {
+ vert_set_mesh(elb, mr, ml->v, ml_index);
+ }
+ EXTRACT_POLY_AND_LOOP_FOREACH_MESH_END;
}
-static void extract_points_ledge_bmesh(const MeshRenderData *mr, int e, BMEdge *eed, void *elb)
+static void extract_points_iter_ledge_bm(const MeshRenderData *mr,
+ const ExtractLEdgeBMesh_Params *params,
+ void *elb)
{
- vert_set_bmesh(elb, eed->v1, mr->loop_len + e * 2);
- vert_set_bmesh(elb, eed->v2, mr->loop_len + e * 2 + 1);
+ EXTRACT_LEDGE_FOREACH_BM_BEGIN(eed, ledge_index, params)
+ {
+ vert_set_bm(elb, eed->v1, mr->loop_len + (ledge_index * 2));
+ vert_set_bm(elb, eed->v2, mr->loop_len + (ledge_index * 2) + 1);
+ }
+ EXTRACT_LEDGE_FOREACH_BM_END;
}
-static void extract_points_ledge_mesh(const MeshRenderData *mr,
- int e,
- const MEdge *medge,
- void *elb)
+static void extract_points_iter_ledge_mesh(const MeshRenderData *mr,
+ const ExtractLEdgeMesh_Params *params,
+ void *elb)
{
- vert_set_mesh(elb, mr, medge->v1, mr->loop_len + e * 2);
- vert_set_mesh(elb, mr, medge->v2, mr->loop_len + e * 2 + 1);
+ EXTRACT_LEDGE_FOREACH_MESH_BEGIN(med, ledge_index, params, mr)
+ {
+ vert_set_mesh(elb, mr, med->v1, mr->loop_len + (ledge_index * 2));
+ vert_set_mesh(elb, mr, med->v2, mr->loop_len + (ledge_index * 2) + 1);
+ }
+ EXTRACT_LEDGE_FOREACH_MESH_END;
}
-static void extract_points_lvert_bmesh(const MeshRenderData *mr, int v, BMVert *eve, void *elb)
+static void extract_points_iter_lvert_bm(const MeshRenderData *mr,
+ const ExtractLVertBMesh_Params *params,
+ void *elb)
{
- vert_set_bmesh(elb, eve, mr->loop_len + mr->edge_loose_len * 2 + v);
+ const int offset = mr->loop_len + (mr->edge_loose_len * 2);
+ EXTRACT_LVERT_FOREACH_BM_BEGIN(eve, lvert_index, params)
+ {
+ vert_set_bm(elb, eve, offset + lvert_index);
+ }
+ EXTRACT_LVERT_FOREACH_BM_END;
}
-static void extract_points_lvert_mesh(const MeshRenderData *mr,
- int v,
- const MVert *UNUSED(mvert),
- void *elb)
+static void extract_points_iter_lvert_mesh(const MeshRenderData *mr,
+ const ExtractLVertMesh_Params *params,
+ void *elb)
{
- vert_set_mesh(elb, mr, mr->lverts[v], mr->loop_len + mr->edge_loose_len * 2 + v);
+ const int offset = mr->loop_len + (mr->edge_loose_len * 2);
+ EXTRACT_LVERT_FOREACH_MESH_BEGIN(mv, lvert_index, params, mr)
+ {
+ vert_set_mesh(elb, mr, mr->lverts[lvert_index], offset + lvert_index);
+ }
+ EXTRACT_LVERT_FOREACH_MESH_END;
}
static void extract_points_finish(const MeshRenderData *UNUSED(mr), void *ibo, void *elb)
@@ -910,18 +1207,16 @@ static void extract_points_finish(const MeshRenderData *UNUSED(mr), void *ibo, v
}
static const MeshExtract extract_points = {
- extract_points_init,
- NULL,
- NULL,
- extract_points_loop_bmesh,
- extract_points_loop_mesh,
- extract_points_ledge_bmesh,
- extract_points_ledge_mesh,
- extract_points_lvert_bmesh,
- extract_points_lvert_mesh,
- extract_points_finish,
- 0,
- false,
+ .init = extract_points_init,
+ .iter_poly_bm = extract_points_iter_poly_bm,
+ .iter_poly_mesh = extract_points_iter_poly_mesh,
+ .iter_ledge_bm = extract_points_iter_ledge_bm,
+ .iter_ledge_mesh = extract_points_iter_ledge_mesh,
+ .iter_lvert_bm = extract_points_iter_lvert_bm,
+ .iter_lvert_mesh = extract_points_iter_lvert_mesh,
+ .finish = extract_points_finish,
+ .data_flag = 0,
+ .use_threading = false,
};
/** \} */
@@ -937,34 +1232,51 @@ static void *extract_fdots_init(const MeshRenderData *mr, void *UNUSED(buf))
return elb;
}
-static void extract_fdots_loop_bmesh(const MeshRenderData *UNUSED(mr),
- int UNUSED(l),
- BMLoop *loop,
- void *elb)
+static void extract_fdots_iter_poly_bm(const MeshRenderData *mr,
+ const ExtractPolyBMesh_Params *params,
+ void *elb)
{
- int face_idx = BM_elem_index_get(loop->f);
- if (!BM_elem_flag_test(loop->f, BM_ELEM_HIDDEN)) {
- GPU_indexbuf_set_point_vert(elb, face_idx, face_idx);
- }
- else {
- GPU_indexbuf_set_point_restart(elb, face_idx);
+ EXTRACT_POLY_FOREACH_BM_BEGIN(f, f_index, params, mr)
+ {
+ if (!BM_elem_flag_test(f, BM_ELEM_HIDDEN)) {
+ GPU_indexbuf_set_point_vert(elb, f_index, f_index);
+ }
+ else {
+ GPU_indexbuf_set_point_restart(elb, f_index);
+ }
}
+ EXTRACT_POLY_FOREACH_BM_END;
}
-static void extract_fdots_loop_mesh(const MeshRenderData *mr,
- int UNUSED(l),
- const MLoop *mloop,
- int p,
- const MPoly *mpoly,
- void *elb)
+static void extract_fdots_iter_poly_mesh(const MeshRenderData *mr,
+ const ExtractPolyMesh_Params *params,
+ void *elb)
{
- const MVert *mvert = &mr->mvert[mloop->v];
- if ((!mr->use_subsurf_fdots || (mvert->flag & ME_VERT_FACEDOT)) &&
- !(mr->use_hide && (mpoly->flag & ME_HIDE))) {
- GPU_indexbuf_set_point_vert(elb, p, p);
+ if (mr->use_subsurf_fdots) {
+ /* Check #ME_VERT_FACEDOT. */
+ EXTRACT_POLY_AND_LOOP_FOREACH_MESH_BEGIN(mp, mp_index, ml, ml_index, params, mr)
+ {
+ const MVert *mv = &mr->mvert[ml->v];
+ if ((mv->flag & ME_VERT_FACEDOT) && !(mr->use_hide && (mp->flag & ME_HIDE))) {
+ GPU_indexbuf_set_point_vert(elb, mp_index, mp_index);
+ }
+ else {
+ GPU_indexbuf_set_point_restart(elb, mp_index);
+ }
+ }
+ EXTRACT_POLY_AND_LOOP_FOREACH_MESH_END;
}
else {
- GPU_indexbuf_set_point_restart(elb, p);
+ EXTRACT_POLY_FOREACH_MESH_BEGIN(mp, mp_index, params, mr)
+ {
+ if (!(mr->use_hide && (mp->flag & ME_HIDE))) {
+ GPU_indexbuf_set_point_vert(elb, mp_index, mp_index);
+ }
+ else {
+ GPU_indexbuf_set_point_restart(elb, mp_index);
+ }
+ }
+ EXTRACT_POLY_FOREACH_MESH_END;
}
}
@@ -975,18 +1287,12 @@ static void extract_fdots_finish(const MeshRenderData *UNUSED(mr), void *ibo, vo
}
static const MeshExtract extract_fdots = {
- extract_fdots_init,
- NULL,
- NULL,
- extract_fdots_loop_bmesh,
- extract_fdots_loop_mesh,
- NULL,
- NULL,
- NULL,
- NULL,
- extract_fdots_finish,
- 0,
- false,
+ .init = extract_fdots_init,
+ .iter_poly_bm = extract_fdots_iter_poly_bm,
+ .iter_poly_mesh = extract_fdots_iter_poly_mesh,
+ .finish = extract_fdots_finish,
+ .data_flag = 0,
+ .use_threading = false,
};
/** \} */
@@ -1009,66 +1315,60 @@ static void *extract_lines_paint_mask_init(const MeshRenderData *mr, void *UNUSE
return data;
}
-static void extract_lines_paint_mask_loop_mesh(const MeshRenderData *mr,
- int l,
- const MLoop *mloop,
- int UNUSED(p),
- const MPoly *mpoly,
- void *_data)
-{
- MeshExtract_LinePaintMask_Data *data = (MeshExtract_LinePaintMask_Data *)_data;
- const int edge_idx = mloop->e;
- const MEdge *medge = &mr->medge[edge_idx];
- if (!((mr->use_hide && (medge->flag & ME_HIDE)) ||
- ((mr->extract_type == MR_EXTRACT_MAPPED) && (mr->e_origindex) &&
- (mr->e_origindex[edge_idx] == ORIGINDEX_NONE)))) {
-
- int loopend = mpoly->totloop + mpoly->loopstart - 1;
- int other_loop = (l == loopend) ? mpoly->loopstart : (l + 1);
- if (mpoly->flag & ME_FACE_SEL) {
- if (BLI_BITMAP_TEST_AND_SET_ATOMIC(data->select_map, edge_idx)) {
- /* Hide edge as it has more than 2 selected loop. */
- GPU_indexbuf_set_line_restart(&data->elb, edge_idx);
+static void extract_lines_paint_mask_iter_poly_mesh(const MeshRenderData *mr,
+ const ExtractPolyMesh_Params *params,
+ void *_data)
+{
+ MeshExtract_LinePaintMask_Data *data = _data;
+ EXTRACT_POLY_AND_LOOP_FOREACH_MESH_BEGIN(mp, mp_index, ml, ml_index, params, mr)
+ {
+ const int e_index = ml->e;
+ const MEdge *me = &mr->medge[e_index];
+ if (!((mr->use_hide && (me->flag & ME_HIDE)) ||
+ ((mr->extract_type == MR_EXTRACT_MAPPED) && (mr->e_origindex) &&
+ (mr->e_origindex[e_index] == ORIGINDEX_NONE)))) {
+
+ const int ml_index_last = mp->totloop + mp->loopstart - 1;
+ const int ml_index_other = (ml_index == ml_index_last) ? mp->loopstart : (ml_index + 1);
+ if (mp->flag & ME_FACE_SEL) {
+ if (BLI_BITMAP_TEST_AND_SET_ATOMIC(data->select_map, e_index)) {
+ /* Hide edge as it has more than 2 selected loop. */
+ GPU_indexbuf_set_line_restart(&data->elb, e_index);
+ }
+ else {
+ /* First selected loop. Set edge visible, overwriting any unselected loop. */
+ GPU_indexbuf_set_line_verts(&data->elb, e_index, ml_index, ml_index_other);
+ }
}
else {
- /* First selected loop. Set edge visible, overwritting any unsel loop. */
- GPU_indexbuf_set_line_verts(&data->elb, edge_idx, l, other_loop);
+ /* Set theses unselected loop only if this edge has no other selected loop. */
+ if (!BLI_BITMAP_TEST(data->select_map, e_index)) {
+ GPU_indexbuf_set_line_verts(&data->elb, e_index, ml_index, ml_index_other);
+ }
}
}
else {
- /* Set theses unselected loop only if this edge has no other selected loop. */
- if (!BLI_BITMAP_TEST(data->select_map, edge_idx)) {
- GPU_indexbuf_set_line_verts(&data->elb, edge_idx, l, other_loop);
- }
+ GPU_indexbuf_set_line_restart(&data->elb, e_index);
}
}
- else {
- GPU_indexbuf_set_line_restart(&data->elb, edge_idx);
- }
+ EXTRACT_POLY_AND_LOOP_FOREACH_MESH_END;
}
static void extract_lines_paint_mask_finish(const MeshRenderData *UNUSED(mr),
void *ibo,
void *_data)
{
- MeshExtract_LinePaintMask_Data *data = (MeshExtract_LinePaintMask_Data *)_data;
+ MeshExtract_LinePaintMask_Data *data = _data;
GPU_indexbuf_build_in_place(&data->elb, ibo);
MEM_freeN(data);
}
static const MeshExtract extract_lines_paint_mask = {
- extract_lines_paint_mask_init,
- NULL,
- NULL,
- NULL,
- extract_lines_paint_mask_loop_mesh,
- NULL,
- NULL,
- NULL,
- NULL,
- extract_lines_paint_mask_finish,
- 0,
- false,
+ .init = extract_lines_paint_mask_init,
+ .iter_poly_mesh = extract_lines_paint_mask_iter_poly_mesh,
+ .finish = extract_lines_paint_mask_finish,
+ .data_flag = 0,
+ .use_threading = false,
};
/** \} */
@@ -1090,7 +1390,7 @@ typedef struct MeshExtract_LineAdjacency_Data {
static void *extract_lines_adjacency_init(const MeshRenderData *mr, void *UNUSED(buf))
{
/* Similar to poly_to_tri_count().
- * There is always loop + tri - 1 edges inside a polygon.
+ * There is always (loop + triangle - 1) edges inside a polygon.
* Accumulate for all polys and you get : */
uint tess_edge_len = mr->loop_len + mr->tri_len - mr->poly_len;
@@ -1107,7 +1407,7 @@ BLI_INLINE void lines_adjacency_triangle(
uint v1, uint v2, uint v3, uint l1, uint l2, uint l3, MeshExtract_LineAdjacency_Data *data)
{
GPUIndexBufBuilder *elb = &data->elb;
- /* Iter around the triangle's edges. */
+ /* Iterate around the triangle's edges. */
for (int e = 0; e < 3; e++) {
SHIFT3(uint, v3, v2, v1);
SHIFT3(uint, l3, l2, l1);
@@ -1118,7 +1418,7 @@ BLI_INLINE void lines_adjacency_triangle(
int v_data = POINTER_AS_INT(*pval);
if (!value_is_init || v_data == NO_EDGE) {
/* Save the winding order inside the sign bit. Because the
- * edgehash sort the keys and we need to compare winding later. */
+ * Edge-hash sort the keys and we need to compare winding later. */
int value = (int)l1 + 1; /* 0 cannot be signed so add one. */
*pval = POINTER_FROM_INT((inv_indices) ? -value : value);
/* Store loop indices for remaining non-manifold edges. */
@@ -1130,7 +1430,7 @@ BLI_INLINE void lines_adjacency_triangle(
*pval = POINTER_FROM_INT(NO_EDGE);
bool inv_opposite = (v_data < 0);
uint l_opposite = (uint)abs(v_data) - 1;
- /* TODO Make this part threadsafe. */
+ /* TODO Make this part thread-safe. */
if (inv_opposite == inv_indices) {
/* Don't share edge if triangles have non matching winding. */
GPU_indexbuf_add_line_adj_verts(elb, l1, l2, l3, l1);
@@ -1144,42 +1444,48 @@ BLI_INLINE void lines_adjacency_triangle(
}
}
-static void extract_lines_adjacency_looptri_bmesh(const MeshRenderData *UNUSED(mr),
- int UNUSED(t),
- BMLoop **elt,
- void *data)
+static void extract_lines_adjacency_iter_looptri_bm(const MeshRenderData *UNUSED(mr),
+ const struct ExtractTriBMesh_Params *params,
+ void *data)
{
- if (!BM_elem_flag_test(elt[0]->f, BM_ELEM_HIDDEN)) {
- lines_adjacency_triangle(BM_elem_index_get(elt[0]->v),
- BM_elem_index_get(elt[1]->v),
- BM_elem_index_get(elt[2]->v),
- BM_elem_index_get(elt[0]),
- BM_elem_index_get(elt[1]),
- BM_elem_index_get(elt[2]),
- data);
+ EXTRACT_TRIS_LOOPTRI_FOREACH_BM_BEGIN(elt, _elt_index, params)
+ {
+ if (!BM_elem_flag_test(elt[0]->f, BM_ELEM_HIDDEN)) {
+ lines_adjacency_triangle(BM_elem_index_get(elt[0]->v),
+ BM_elem_index_get(elt[1]->v),
+ BM_elem_index_get(elt[2]->v),
+ BM_elem_index_get(elt[0]),
+ BM_elem_index_get(elt[1]),
+ BM_elem_index_get(elt[2]),
+ data);
+ }
}
+ EXTRACT_TRIS_LOOPTRI_FOREACH_BM_END;
}
-static void extract_lines_adjacency_looptri_mesh(const MeshRenderData *mr,
- int UNUSED(t),
- const MLoopTri *mlt,
- void *data)
+static void extract_lines_adjacency_iter_looptri_mesh(const MeshRenderData *mr,
+ const struct ExtractTriMesh_Params *params,
+ void *data)
{
- const MPoly *mpoly = &mr->mpoly[mlt->poly];
- if (!(mr->use_hide && (mpoly->flag & ME_HIDE))) {
- lines_adjacency_triangle(mr->mloop[mlt->tri[0]].v,
- mr->mloop[mlt->tri[1]].v,
- mr->mloop[mlt->tri[2]].v,
- mlt->tri[0],
- mlt->tri[1],
- mlt->tri[2],
- data);
+ EXTRACT_TRIS_LOOPTRI_FOREACH_MESH_BEGIN(mlt, _mlt_index, params)
+ {
+ const MPoly *mp = &mr->mpoly[mlt->poly];
+ if (!(mr->use_hide && (mp->flag & ME_HIDE))) {
+ lines_adjacency_triangle(mr->mloop[mlt->tri[0]].v,
+ mr->mloop[mlt->tri[1]].v,
+ mr->mloop[mlt->tri[2]].v,
+ mlt->tri[0],
+ mlt->tri[1],
+ mlt->tri[2],
+ data);
+ }
}
+ EXTRACT_TRIS_LOOPTRI_FOREACH_MESH_END;
}
static void extract_lines_adjacency_finish(const MeshRenderData *mr, void *ibo, void *_data)
{
- MeshExtract_LineAdjacency_Data *data = (MeshExtract_LineAdjacency_Data *)_data;
+ MeshExtract_LineAdjacency_Data *data = _data;
/* Create edges for remaining non manifold edges. */
EdgeHashIterator *ehi = BLI_edgehashIterator_new(data->eh);
for (; !BLI_edgehashIterator_isDone(ehi); BLI_edgehashIterator_step(ehi)) {
@@ -1209,18 +1515,12 @@ static void extract_lines_adjacency_finish(const MeshRenderData *mr, void *ibo,
#undef NO_EDGE
static const MeshExtract extract_lines_adjacency = {
- extract_lines_adjacency_init,
- extract_lines_adjacency_looptri_bmesh,
- extract_lines_adjacency_looptri_mesh,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- extract_lines_adjacency_finish,
- 0,
- false,
+ .init = extract_lines_adjacency_init,
+ .iter_looptri_bm = extract_lines_adjacency_iter_looptri_bm,
+ .iter_looptri_mesh = extract_lines_adjacency_iter_looptri_mesh,
+ .finish = extract_lines_adjacency_finish,
+ .data_flag = 0,
+ .use_threading = false,
};
/** \} */
@@ -1250,53 +1550,53 @@ BLI_INLINE void edituv_tri_add(
}
}
-static void extract_edituv_tris_looptri_bmesh(const MeshRenderData *UNUSED(mr),
- int UNUSED(t),
- BMLoop **elt,
- void *data)
+static void extract_edituv_tris_iter_looptri_bm(const MeshRenderData *UNUSED(mr),
+ const struct ExtractTriBMesh_Params *params,
+ void *data)
{
- edituv_tri_add(data,
- BM_elem_flag_test(elt[0]->f, BM_ELEM_HIDDEN),
- BM_elem_flag_test(elt[0]->f, BM_ELEM_SELECT),
- BM_elem_index_get(elt[0]),
- BM_elem_index_get(elt[1]),
- BM_elem_index_get(elt[2]));
+ EXTRACT_TRIS_LOOPTRI_FOREACH_BM_BEGIN(elt, _elt_index, params)
+ {
+ edituv_tri_add(data,
+ BM_elem_flag_test(elt[0]->f, BM_ELEM_HIDDEN),
+ BM_elem_flag_test(elt[0]->f, BM_ELEM_SELECT),
+ BM_elem_index_get(elt[0]),
+ BM_elem_index_get(elt[1]),
+ BM_elem_index_get(elt[2]));
+ }
+ EXTRACT_TRIS_LOOPTRI_FOREACH_BM_END;
}
-static void extract_edituv_tris_looptri_mesh(const MeshRenderData *mr,
- int UNUSED(t),
- const MLoopTri *mlt,
- void *data)
+static void extract_edituv_tris_iter_looptri_mesh(const MeshRenderData *mr,
+ const struct ExtractTriMesh_Params *params,
+ void *data)
{
- const MPoly *mpoly = &mr->mpoly[mlt->poly];
- edituv_tri_add(data,
- (mpoly->flag & ME_HIDE) != 0,
- (mpoly->flag & ME_FACE_SEL) != 0,
- mlt->tri[0],
- mlt->tri[1],
- mlt->tri[2]);
+ EXTRACT_TRIS_LOOPTRI_FOREACH_MESH_BEGIN(mlt, _mlt_index, params)
+ {
+ const MPoly *mp = &mr->mpoly[mlt->poly];
+ edituv_tri_add(data,
+ (mp->flag & ME_HIDE) != 0,
+ (mp->flag & ME_FACE_SEL) != 0,
+ mlt->tri[0],
+ mlt->tri[1],
+ mlt->tri[2]);
+ }
+ EXTRACT_TRIS_LOOPTRI_FOREACH_MESH_END;
}
static void extract_edituv_tris_finish(const MeshRenderData *UNUSED(mr), void *ibo, void *data)
{
- MeshExtract_EditUvElem_Data *extract_data = (MeshExtract_EditUvElem_Data *)data;
+ MeshExtract_EditUvElem_Data *extract_data = data;
GPU_indexbuf_build_in_place(&extract_data->elb, ibo);
MEM_freeN(extract_data);
}
static const MeshExtract extract_edituv_tris = {
- extract_edituv_tris_init,
- extract_edituv_tris_looptri_bmesh,
- extract_edituv_tris_looptri_mesh,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- extract_edituv_tris_finish,
- 0,
- false,
+ .init = extract_edituv_tris_init,
+ .iter_looptri_bm = extract_edituv_tris_iter_looptri_bm,
+ .iter_looptri_mesh = extract_edituv_tris_iter_looptri_mesh,
+ .finish = extract_edituv_tris_finish,
+ .data_flag = 0,
+ .use_threading = false,
};
/** \} */
@@ -1322,55 +1622,53 @@ BLI_INLINE void edituv_edge_add(
}
}
-static void extract_edituv_lines_loop_bmesh(const MeshRenderData *UNUSED(mr),
- int l,
- BMLoop *loop,
- void *data)
+static void extract_edituv_lines_iter_poly_bm(const MeshRenderData *mr,
+ const ExtractPolyBMesh_Params *params,
+ void *data)
{
- edituv_edge_add(data,
- BM_elem_flag_test(loop->f, BM_ELEM_HIDDEN),
- BM_elem_flag_test(loop->f, BM_ELEM_SELECT),
- l,
- BM_elem_index_get(loop->next));
+ EXTRACT_POLY_AND_LOOP_FOREACH_BM_BEGIN(loop, l_index, params, mr)
+ {
+ edituv_edge_add(data,
+ BM_elem_flag_test(loop->f, BM_ELEM_HIDDEN),
+ BM_elem_flag_test(loop->f, BM_ELEM_SELECT),
+ l_index,
+ BM_elem_index_get(loop->next));
+ }
+ EXTRACT_POLY_AND_LOOP_FOREACH_BM_END(loop);
}
-static void extract_edituv_lines_loop_mesh(const MeshRenderData *mr,
- int loop_idx,
- const MLoop *mloop,
- int UNUSED(p),
- const MPoly *mpoly,
- void *data)
+static void extract_edituv_lines_iter_poly_mesh(const MeshRenderData *mr,
+ const ExtractPolyMesh_Params *params,
+ void *data)
{
- int loopend = mpoly->totloop + mpoly->loopstart - 1;
- int loop_next_idx = (loop_idx == loopend) ? mpoly->loopstart : (loop_idx + 1);
- const bool real_edge = (mr->e_origindex == NULL || mr->e_origindex[mloop->e] != ORIGINDEX_NONE);
- edituv_edge_add(data,
- (mpoly->flag & ME_HIDE) != 0 || !real_edge,
- (mpoly->flag & ME_FACE_SEL) != 0,
- loop_idx,
- loop_next_idx);
+ EXTRACT_POLY_AND_LOOP_FOREACH_MESH_BEGIN(mp, mp_index, ml, ml_index, params, mr)
+ {
+ const int ml_index_last = mp->totloop + mp->loopstart - 1;
+ const int ml_index_next = (ml_index == ml_index_last) ? mp->loopstart : (ml_index + 1);
+ const bool real_edge = (mr->e_origindex == NULL || mr->e_origindex[ml->e] != ORIGINDEX_NONE);
+ edituv_edge_add(data,
+ (mp->flag & ME_HIDE) != 0 || !real_edge,
+ (mp->flag & ME_FACE_SEL) != 0,
+ ml_index,
+ ml_index_next);
+ }
+ EXTRACT_POLY_AND_LOOP_FOREACH_MESH_END;
}
static void extract_edituv_lines_finish(const MeshRenderData *UNUSED(mr), void *ibo, void *data)
{
- MeshExtract_EditUvElem_Data *extract_data = (MeshExtract_EditUvElem_Data *)data;
+ MeshExtract_EditUvElem_Data *extract_data = data;
GPU_indexbuf_build_in_place(&extract_data->elb, ibo);
MEM_freeN(extract_data);
}
static const MeshExtract extract_edituv_lines = {
- extract_edituv_lines_init,
- NULL,
- NULL,
- extract_edituv_lines_loop_bmesh,
- extract_edituv_lines_loop_mesh,
- NULL,
- NULL,
- NULL,
- NULL,
- extract_edituv_lines_finish,
- 0,
- false,
+ .init = extract_edituv_lines_init,
+ .iter_poly_bm = extract_edituv_lines_iter_poly_bm,
+ .iter_poly_mesh = extract_edituv_lines_iter_poly_mesh,
+ .finish = extract_edituv_lines_finish,
+ .data_flag = 0,
+ .use_threading = false,
};
/** \} */
@@ -1398,50 +1696,48 @@ BLI_INLINE void edituv_point_add(MeshExtract_EditUvElem_Data *data,
}
}
-static void extract_edituv_points_loop_bmesh(const MeshRenderData *UNUSED(mr),
- int l,
- BMLoop *loop,
- void *data)
+static void extract_edituv_points_iter_poly_bm(const MeshRenderData *mr,
+ const ExtractPolyBMesh_Params *params,
+ void *data)
{
- edituv_point_add(data,
- BM_elem_flag_test(loop->f, BM_ELEM_HIDDEN),
- BM_elem_flag_test(loop->f, BM_ELEM_SELECT),
- l);
+ EXTRACT_POLY_AND_LOOP_FOREACH_BM_BEGIN(l, l_index, params, mr)
+ {
+ edituv_point_add(data,
+ BM_elem_flag_test(l->f, BM_ELEM_HIDDEN),
+ BM_elem_flag_test(l->f, BM_ELEM_SELECT),
+ l_index);
+ }
+ EXTRACT_POLY_AND_LOOP_FOREACH_BM_END(l);
}
-static void extract_edituv_points_loop_mesh(const MeshRenderData *mr,
- int l,
- const MLoop *mloop,
- int UNUSED(p),
- const MPoly *mpoly,
- void *data)
+static void extract_edituv_points_iter_poly_mesh(const MeshRenderData *mr,
+ const ExtractPolyMesh_Params *params,
+ void *data)
{
- const bool real_vert = (mr->extract_type == MR_EXTRACT_MAPPED && (mr->v_origindex) &&
- mr->v_origindex[mloop->v] != ORIGINDEX_NONE);
- edituv_point_add(
- data, ((mpoly->flag & ME_HIDE) != 0) || !real_vert, (mpoly->flag & ME_FACE_SEL) != 0, l);
+ EXTRACT_POLY_AND_LOOP_FOREACH_MESH_BEGIN(mp, mp_index, ml, ml_index, params, mr)
+ {
+ const bool real_vert = (mr->extract_type == MR_EXTRACT_MAPPED && (mr->v_origindex) &&
+ mr->v_origindex[ml->v] != ORIGINDEX_NONE);
+ edituv_point_add(
+ data, ((mp->flag & ME_HIDE) != 0) || !real_vert, (mp->flag & ME_FACE_SEL) != 0, ml_index);
+ }
+ EXTRACT_POLY_AND_LOOP_FOREACH_MESH_END;
}
static void extract_edituv_points_finish(const MeshRenderData *UNUSED(mr), void *ibo, void *data)
{
- MeshExtract_EditUvElem_Data *extract_data = (MeshExtract_EditUvElem_Data *)data;
+ MeshExtract_EditUvElem_Data *extract_data = data;
GPU_indexbuf_build_in_place(&extract_data->elb, ibo);
MEM_freeN(extract_data);
}
static const MeshExtract extract_edituv_points = {
- extract_edituv_points_init,
- NULL,
- NULL,
- extract_edituv_points_loop_bmesh,
- extract_edituv_points_loop_mesh,
- NULL,
- NULL,
- NULL,
- NULL,
- extract_edituv_points_finish,
- 0,
- false,
+ .init = extract_edituv_points_init,
+ .iter_poly_bm = extract_edituv_points_iter_poly_bm,
+ .iter_poly_mesh = extract_edituv_points_iter_poly_mesh,
+ .finish = extract_edituv_points_finish,
+ .data_flag = 0,
+ .use_threading = false,
};
/** \} */
@@ -1462,64 +1758,75 @@ static void *extract_edituv_fdots_init(const MeshRenderData *mr, void *UNUSED(ib
BLI_INLINE void edituv_facedot_add(MeshExtract_EditUvElem_Data *data,
bool hidden,
bool selected,
- int face_idx)
+ int face_index)
{
if (!hidden && (data->sync_selection || selected)) {
- GPU_indexbuf_set_point_vert(&data->elb, face_idx, face_idx);
+ GPU_indexbuf_set_point_vert(&data->elb, face_index, face_index);
}
else {
- GPU_indexbuf_set_point_restart(&data->elb, face_idx);
+ GPU_indexbuf_set_point_restart(&data->elb, face_index);
}
}
-static void extract_edituv_fdots_loop_bmesh(const MeshRenderData *UNUSED(mr),
- int UNUSED(l),
- BMLoop *loop,
- void *data)
+static void extract_edituv_fdots_iter_poly_bm(const MeshRenderData *mr,
+ const ExtractPolyBMesh_Params *params,
+ void *data)
{
- edituv_facedot_add(data,
- BM_elem_flag_test(loop->f, BM_ELEM_HIDDEN),
- BM_elem_flag_test(loop->f, BM_ELEM_SELECT),
- BM_elem_index_get(loop->f));
+ EXTRACT_POLY_FOREACH_BM_BEGIN(f, f_index, params, mr)
+ {
+ edituv_facedot_add(
+ data, BM_elem_flag_test(f, BM_ELEM_HIDDEN), BM_elem_flag_test(f, BM_ELEM_SELECT), f_index);
+ }
+ EXTRACT_POLY_FOREACH_BM_END;
}
-static void extract_edituv_fdots_loop_mesh(const MeshRenderData *mr,
- int UNUSED(l),
- const MLoop *mloop,
- int p,
- const MPoly *mpoly,
- void *data)
+static void extract_edituv_fdots_iter_poly_mesh(const MeshRenderData *mr,
+ const ExtractPolyMesh_Params *params,
+ void *data)
{
- const bool real_fdot = (mr->extract_type == MR_EXTRACT_MAPPED && mr->p_origindex &&
- mr->p_origindex[p] != ORIGINDEX_NONE);
- const bool subd_fdot = (!mr->use_subsurf_fdots ||
- (mr->mvert[mloop->v].flag & ME_VERT_FACEDOT) != 0);
- edituv_facedot_add(data,
- ((mpoly->flag & ME_HIDE) != 0) || !real_fdot || !subd_fdot,
- (mpoly->flag & ME_FACE_SEL) != 0,
- p);
+ if (mr->use_subsurf_fdots) {
+ /* Check #ME_VERT_FACEDOT. */
+ EXTRACT_POLY_AND_LOOP_FOREACH_MESH_BEGIN(mp, mp_index, ml, ml_index, params, mr)
+ {
+ const bool real_fdot = (mr->extract_type == MR_EXTRACT_MAPPED && mr->p_origindex &&
+ mr->p_origindex[mp_index] != ORIGINDEX_NONE);
+ const bool subd_fdot = (!mr->use_subsurf_fdots ||
+ (mr->mvert[ml->v].flag & ME_VERT_FACEDOT) != 0);
+ edituv_facedot_add(data,
+ ((mp->flag & ME_HIDE) != 0) || !real_fdot || !subd_fdot,
+ (mp->flag & ME_FACE_SEL) != 0,
+ mp_index);
+ }
+ EXTRACT_POLY_AND_LOOP_FOREACH_MESH_END;
+ }
+ else {
+ EXTRACT_POLY_FOREACH_MESH_BEGIN(mp, mp_index, params, mr)
+ {
+ const bool real_fdot = (mr->extract_type == MR_EXTRACT_MAPPED && mr->p_origindex &&
+ mr->p_origindex[mp_index] != ORIGINDEX_NONE);
+ edituv_facedot_add(data,
+ ((mp->flag & ME_HIDE) != 0) || !real_fdot,
+ (mp->flag & ME_FACE_SEL) != 0,
+ mp_index);
+ }
+ EXTRACT_POLY_FOREACH_MESH_END;
+ }
}
static void extract_edituv_fdots_finish(const MeshRenderData *UNUSED(mr), void *ibo, void *_data)
{
- MeshExtract_EditUvElem_Data *data = (MeshExtract_EditUvElem_Data *)_data;
+ MeshExtract_EditUvElem_Data *data = _data;
GPU_indexbuf_build_in_place(&data->elb, ibo);
MEM_freeN(data);
}
static const MeshExtract extract_edituv_fdots = {
- extract_edituv_fdots_init,
- NULL,
- NULL,
- extract_edituv_fdots_loop_bmesh,
- extract_edituv_fdots_loop_mesh,
- NULL,
- NULL,
- NULL,
- NULL,
- extract_edituv_fdots_finish,
- 0,
- false,
+ .init = extract_edituv_fdots_init,
+ .iter_poly_bm = extract_edituv_fdots_iter_poly_bm,
+ .iter_poly_mesh = extract_edituv_fdots_iter_poly_mesh,
+ .finish = extract_edituv_fdots_finish,
+ .data_flag = 0,
+ .use_threading = false,
};
/** \} */
@@ -1542,7 +1849,7 @@ static void *extract_pos_nor_init(const MeshRenderData *mr, void *buf)
{
static GPUVertFormat format = {0};
if (format.attr_len == 0) {
- /* WARNING Adjust PosNorLoop struct accordingly. */
+ /* WARNING Adjust #PosNorLoop struct accordingly. */
GPU_vertformat_attr_add(&format, "pos", GPU_COMP_F32, 3, GPU_FETCH_FLOAT);
GPU_vertformat_attr_add(&format, "nor", GPU_COMP_I10, 4, GPU_FETCH_INT_TO_FLOAT_UNIT);
GPU_vertformat_alias_add(&format, "vnor");
@@ -1566,95 +1873,122 @@ static void *extract_pos_nor_init(const MeshRenderData *mr, void *buf)
}
}
else {
- const MVert *mvert = mr->mvert;
- for (int v = 0; v < mr->vert_len; v++, mvert++) {
- data->packed_nor[v] = GPU_normal_convert_i10_s3(mvert->no);
+ const MVert *mv = mr->mvert;
+ for (int v = 0; v < mr->vert_len; v++, mv++) {
+ data->packed_nor[v] = GPU_normal_convert_i10_s3(mv->no);
}
}
return data;
}
-static void extract_pos_nor_loop_bmesh(const MeshRenderData *mr, int l, BMLoop *loop, void *_data)
+static void extract_pos_nor_iter_poly_bm(const MeshRenderData *mr,
+ const ExtractPolyBMesh_Params *params,
+ void *_data)
{
MeshExtract_PosNor_Data *data = _data;
- PosNorLoop *vert = data->vbo_data + l;
- copy_v3_v3(vert->pos, bm_vert_co_get(mr, loop->v));
- vert->nor = data->packed_nor[BM_elem_index_get(loop->v)];
- BMFace *efa = loop->f;
- vert->nor.w = BM_elem_flag_test(efa, BM_ELEM_HIDDEN) ? -1 : 0;
+ EXTRACT_POLY_AND_LOOP_FOREACH_BM_BEGIN(l, l_index, params, mr)
+ {
+ PosNorLoop *vert = &data->vbo_data[l_index];
+ copy_v3_v3(vert->pos, bm_vert_co_get(mr, l->v));
+ vert->nor = data->packed_nor[BM_elem_index_get(l->v)];
+ BMFace *efa = l->f;
+ vert->nor.w = BM_elem_flag_test(efa, BM_ELEM_HIDDEN) ? -1 : 0;
+ }
+ EXTRACT_POLY_AND_LOOP_FOREACH_BM_END(l);
}
-static void extract_pos_nor_loop_mesh(const MeshRenderData *mr,
- int l,
- const MLoop *mloop,
- int UNUSED(p),
- const MPoly *mpoly,
- void *_data)
+static void extract_pos_nor_iter_poly_mesh(const MeshRenderData *mr,
+ const ExtractPolyMesh_Params *params,
+ void *_data)
{
MeshExtract_PosNor_Data *data = _data;
- PosNorLoop *vert = data->vbo_data + l;
- const MVert *mvert = &mr->mvert[mloop->v];
- copy_v3_v3(vert->pos, mvert->co);
- vert->nor = data->packed_nor[mloop->v];
- /* Flag for paint mode overlay. */
- if (mpoly->flag & ME_HIDE || mvert->flag & ME_HIDE ||
- ((mr->extract_type == MR_EXTRACT_MAPPED) && (mr->v_origindex) &&
- (mr->v_origindex[mloop->v] == ORIGINDEX_NONE))) {
- vert->nor.w = -1;
- }
- else if (mvert->flag & SELECT) {
- vert->nor.w = 1;
- }
- else {
- vert->nor.w = 0;
+ EXTRACT_POLY_AND_LOOP_FOREACH_MESH_BEGIN(mp, mp_index, ml, ml_index, params, mr)
+ {
+ PosNorLoop *vert = &data->vbo_data[ml_index];
+ const MVert *mv = &mr->mvert[ml->v];
+ copy_v3_v3(vert->pos, mv->co);
+ vert->nor = data->packed_nor[ml->v];
+ /* Flag for paint mode overlay. */
+ if (mp->flag & ME_HIDE || mv->flag & ME_HIDE ||
+ ((mr->extract_type == MR_EXTRACT_MAPPED) && (mr->v_origindex) &&
+ (mr->v_origindex[ml->v] == ORIGINDEX_NONE))) {
+ vert->nor.w = -1;
+ }
+ else if (mv->flag & SELECT) {
+ vert->nor.w = 1;
+ }
+ else {
+ vert->nor.w = 0;
+ }
}
+ EXTRACT_POLY_AND_LOOP_FOREACH_MESH_END;
}
-static void extract_pos_nor_ledge_bmesh(const MeshRenderData *mr, int e, BMEdge *eed, void *_data)
+static void extract_pos_nor_iter_ledge_bm(const MeshRenderData *mr,
+ const ExtractLEdgeBMesh_Params *params,
+ void *_data)
{
- int l = mr->loop_len + e * 2;
MeshExtract_PosNor_Data *data = _data;
- PosNorLoop *vert = data->vbo_data + l;
- copy_v3_v3(vert[0].pos, bm_vert_co_get(mr, eed->v1));
- copy_v3_v3(vert[1].pos, bm_vert_co_get(mr, eed->v2));
- vert[0].nor = data->packed_nor[BM_elem_index_get(eed->v1)];
- vert[1].nor = data->packed_nor[BM_elem_index_get(eed->v2)];
+ EXTRACT_LEDGE_FOREACH_BM_BEGIN(eed, ledge_index, params)
+ {
+ int l_index = mr->loop_len + ledge_index * 2;
+ PosNorLoop *vert = &data->vbo_data[l_index];
+ copy_v3_v3(vert[0].pos, bm_vert_co_get(mr, eed->v1));
+ copy_v3_v3(vert[1].pos, bm_vert_co_get(mr, eed->v2));
+ vert[0].nor = data->packed_nor[BM_elem_index_get(eed->v1)];
+ vert[1].nor = data->packed_nor[BM_elem_index_get(eed->v2)];
+ }
+ EXTRACT_LEDGE_FOREACH_BM_END;
}
-static void extract_pos_nor_ledge_mesh(const MeshRenderData *mr,
- int e,
- const MEdge *medge,
- void *_data)
+static void extract_pos_nor_iter_ledge_mesh(const MeshRenderData *mr,
+ const ExtractLEdgeMesh_Params *params,
+ void *_data)
{
- int l = mr->loop_len + e * 2;
MeshExtract_PosNor_Data *data = _data;
- PosNorLoop *vert = data->vbo_data + l;
- copy_v3_v3(vert[0].pos, mr->mvert[medge->v1].co);
- copy_v3_v3(vert[1].pos, mr->mvert[medge->v2].co);
- vert[0].nor = data->packed_nor[medge->v1];
- vert[1].nor = data->packed_nor[medge->v2];
+ EXTRACT_LEDGE_FOREACH_MESH_BEGIN(med, ledge_index, params, mr)
+ {
+ const int ml_index = mr->loop_len + ledge_index * 2;
+ PosNorLoop *vert = &data->vbo_data[ml_index];
+ copy_v3_v3(vert[0].pos, mr->mvert[med->v1].co);
+ copy_v3_v3(vert[1].pos, mr->mvert[med->v2].co);
+ vert[0].nor = data->packed_nor[med->v1];
+ vert[1].nor = data->packed_nor[med->v2];
+ }
+ EXTRACT_LEDGE_FOREACH_MESH_END;
}
-static void extract_pos_nor_lvert_bmesh(const MeshRenderData *mr, int v, BMVert *eve, void *_data)
+static void extract_pos_nor_iter_lvert_bm(const MeshRenderData *mr,
+ const ExtractLVertBMesh_Params *params,
+ void *_data)
{
- int l = mr->loop_len + mr->edge_loose_len * 2 + v;
MeshExtract_PosNor_Data *data = _data;
- PosNorLoop *vert = data->vbo_data + l;
- copy_v3_v3(vert->pos, bm_vert_co_get(mr, eve));
- vert->nor = data->packed_nor[BM_elem_index_get(eve)];
+ const int offset = mr->loop_len + (mr->edge_loose_len * 2);
+ EXTRACT_LVERT_FOREACH_BM_BEGIN(eve, lvert_index, params)
+ {
+ const int l_index = offset + lvert_index;
+ PosNorLoop *vert = &data->vbo_data[l_index];
+ copy_v3_v3(vert->pos, bm_vert_co_get(mr, eve));
+ vert->nor = data->packed_nor[BM_elem_index_get(eve)];
+ }
+ EXTRACT_LVERT_FOREACH_BM_END;
}
-static void extract_pos_nor_lvert_mesh(const MeshRenderData *mr,
- int v,
- const MVert *mvert,
- void *_data)
+static void extract_pos_nor_iter_lvert_mesh(const MeshRenderData *mr,
+ const ExtractLVertMesh_Params *params,
+ void *_data)
{
- int l = mr->loop_len + mr->edge_loose_len * 2 + v;
- int v_idx = mr->lverts[v];
MeshExtract_PosNor_Data *data = _data;
- PosNorLoop *vert = data->vbo_data + l;
- copy_v3_v3(vert->pos, mvert->co);
- vert->nor = data->packed_nor[v_idx];
+ const int offset = mr->loop_len + (mr->edge_loose_len * 2);
+ EXTRACT_LVERT_FOREACH_MESH_BEGIN(mv, lvert_index, params, mr)
+ {
+ const int ml_index = offset + lvert_index;
+ const int v_index = mr->lverts[lvert_index];
+ PosNorLoop *vert = &data->vbo_data[ml_index];
+ copy_v3_v3(vert->pos, mv->co);
+ vert->nor = data->packed_nor[v_index];
+ }
+ EXTRACT_LVERT_FOREACH_MESH_END;
}
static void extract_pos_nor_finish(const MeshRenderData *UNUSED(mr), void *UNUSED(vbo), void *data)
@@ -1663,18 +1997,16 @@ static void extract_pos_nor_finish(const MeshRenderData *UNUSED(mr), void *UNUSE
}
static const MeshExtract extract_pos_nor = {
- extract_pos_nor_init,
- NULL,
- NULL,
- extract_pos_nor_loop_bmesh,
- extract_pos_nor_loop_mesh,
- extract_pos_nor_ledge_bmesh,
- extract_pos_nor_ledge_mesh,
- extract_pos_nor_lvert_bmesh,
- extract_pos_nor_lvert_mesh,
- extract_pos_nor_finish,
- 0,
- true,
+ .init = extract_pos_nor_init,
+ .iter_poly_bm = extract_pos_nor_iter_poly_bm,
+ .iter_poly_mesh = extract_pos_nor_iter_poly_mesh,
+ .iter_ledge_bm = extract_pos_nor_iter_ledge_bm,
+ .iter_ledge_mesh = extract_pos_nor_iter_ledge_mesh,
+ .iter_lvert_bm = extract_pos_nor_iter_lvert_bm,
+ .iter_lvert_mesh = extract_pos_nor_iter_lvert_mesh,
+ .finish = extract_pos_nor_finish,
+ .data_flag = 0,
+ .use_threading = true,
};
/** \} */
@@ -1700,62 +2032,71 @@ static void *extract_lnor_hq_init(const MeshRenderData *mr, void *buf)
return vbo->data;
}
-static void extract_lnor_hq_loop_bmesh(const MeshRenderData *mr, int l, BMLoop *loop, void *data)
+static void extract_lnor_hq_iter_poly_bm(const MeshRenderData *mr,
+ const ExtractPolyBMesh_Params *params,
+ void *data)
{
if (mr->loop_normals) {
- normal_float_to_short_v3(&((gpuHQNor *)data)[l].x, mr->loop_normals[l]);
- }
- else if (BM_elem_flag_test(loop->f, BM_ELEM_SMOOTH)) {
- normal_float_to_short_v3(&((gpuHQNor *)data)[l].x, bm_vert_no_get(mr, loop->v));
+ EXTRACT_POLY_AND_LOOP_FOREACH_BM_BEGIN(_l, l_index, params, mr)
+ {
+ normal_float_to_short_v3(&((gpuHQNor *)data)[l_index].x, mr->loop_normals[l_index]);
+ }
+ EXTRACT_POLY_AND_LOOP_FOREACH_BM_END(_l);
}
else {
- normal_float_to_short_v3(&((gpuHQNor *)data)[l].x, bm_face_no_get(mr, loop->f));
+ EXTRACT_POLY_AND_LOOP_FOREACH_BM_BEGIN(l, l_index, params, mr)
+ {
+ if (BM_elem_flag_test(l->f, BM_ELEM_SMOOTH)) {
+ normal_float_to_short_v3(&((gpuHQNor *)data)[l_index].x, bm_vert_no_get(mr, l->v));
+ }
+ else {
+ normal_float_to_short_v3(&((gpuHQNor *)data)[l_index].x, bm_face_no_get(mr, l->f));
+ }
+ }
+ EXTRACT_POLY_AND_LOOP_FOREACH_BM_END(l);
}
}
-static void extract_lnor_hq_loop_mesh(
- const MeshRenderData *mr, int l, const MLoop *mloop, int p, const MPoly *mpoly, void *data)
+static void extract_lnor_hq_iter_poly_mesh(const MeshRenderData *mr,
+ const ExtractPolyMesh_Params *params,
+ void *data)
{
- gpuHQNor *lnor_data = &((gpuHQNor *)data)[l];
- if (mr->loop_normals) {
- normal_float_to_short_v3(&lnor_data->x, mr->loop_normals[l]);
- }
- else if (mpoly->flag & ME_SMOOTH) {
- copy_v3_v3_short(&lnor_data->x, mr->mvert[mloop->v].no);
- }
- else {
- normal_float_to_short_v3(&lnor_data->x, mr->poly_normals[p]);
- }
+ EXTRACT_POLY_AND_LOOP_FOREACH_MESH_BEGIN(mp, mp_index, ml, ml_index, params, mr)
+ {
+ gpuHQNor *lnor_data = &((gpuHQNor *)data)[ml_index];
+ if (mr->loop_normals) {
+ normal_float_to_short_v3(&lnor_data->x, mr->loop_normals[ml_index]);
+ }
+ else if (mp->flag & ME_SMOOTH) {
+ copy_v3_v3_short(&lnor_data->x, mr->mvert[ml->v].no);
+ }
+ else {
+ normal_float_to_short_v3(&lnor_data->x, mr->poly_normals[mp_index]);
+ }
- /* Flag for paint mode overlay.
- * Only use MR_EXTRACT_MAPPED in edit mode where it is used to display the edge-normals. In
- * paint mode it will use the unmapped data to draw the wireframe. */
- if (mpoly->flag & ME_HIDE ||
- (mr->edit_bmesh && mr->extract_type == MR_EXTRACT_MAPPED && (mr->v_origindex) &&
- mr->v_origindex[mloop->v] == ORIGINDEX_NONE)) {
- lnor_data->w = -1;
- }
- else if (mpoly->flag & ME_FACE_SEL) {
- lnor_data->w = 1;
- }
- else {
- lnor_data->w = 0;
+ /* Flag for paint mode overlay.
+ * Only use #MR_EXTRACT_MAPPED in edit mode where it is used to display the edge-normals.
+ * In paint mode it will use the un-mapped data to draw the wire-frame. */
+ if (mp->flag & ME_HIDE || (mr->edit_bmesh && mr->extract_type == MR_EXTRACT_MAPPED &&
+ (mr->v_origindex) && mr->v_origindex[ml->v] == ORIGINDEX_NONE)) {
+ lnor_data->w = -1;
+ }
+ else if (mp->flag & ME_FACE_SEL) {
+ lnor_data->w = 1;
+ }
+ else {
+ lnor_data->w = 0;
+ }
}
+ EXTRACT_POLY_AND_LOOP_FOREACH_MESH_END;
}
static const MeshExtract extract_lnor_hq = {
- extract_lnor_hq_init,
- NULL,
- NULL,
- extract_lnor_hq_loop_bmesh,
- extract_lnor_hq_loop_mesh,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- MR_DATA_LOOP_NOR,
- true,
+ .init = extract_lnor_hq_init,
+ .iter_poly_bm = extract_lnor_hq_iter_poly_bm,
+ .iter_poly_mesh = extract_lnor_hq_iter_poly_mesh,
+ .data_flag = MR_DATA_LOOP_NOR,
+ .use_threading = true,
};
/** \} */
@@ -1777,64 +2118,75 @@ static void *extract_lnor_init(const MeshRenderData *mr, void *buf)
return vbo->data;
}
-static void extract_lnor_loop_bmesh(const MeshRenderData *mr, int l, BMLoop *loop, void *data)
+static void extract_lnor_iter_poly_bm(const MeshRenderData *mr,
+ const ExtractPolyBMesh_Params *params,
+ void *data)
{
if (mr->loop_normals) {
- ((GPUPackedNormal *)data)[l] = GPU_normal_convert_i10_v3(mr->loop_normals[l]);
- }
- else if (BM_elem_flag_test(loop->f, BM_ELEM_SMOOTH)) {
- ((GPUPackedNormal *)data)[l] = GPU_normal_convert_i10_v3(bm_vert_no_get(mr, loop->v));
+ EXTRACT_POLY_AND_LOOP_FOREACH_BM_BEGIN(l, l_index, params, mr)
+ {
+ ((GPUPackedNormal *)data)[l_index] = GPU_normal_convert_i10_v3(mr->loop_normals[l_index]);
+ BMFace *efa = l->f;
+ ((GPUPackedNormal *)data)[l_index].w = BM_elem_flag_test(efa, BM_ELEM_HIDDEN) ? -1 : 0;
+ }
+ EXTRACT_POLY_AND_LOOP_FOREACH_BM_END(l);
}
else {
- ((GPUPackedNormal *)data)[l] = GPU_normal_convert_i10_v3(bm_face_no_get(mr, loop->f));
+ EXTRACT_POLY_AND_LOOP_FOREACH_BM_BEGIN(l, l_index, params, mr)
+ {
+ if (BM_elem_flag_test(l->f, BM_ELEM_SMOOTH)) {
+ ((GPUPackedNormal *)data)[l_index] = GPU_normal_convert_i10_v3(bm_vert_no_get(mr, l->v));
+ }
+ else {
+ ((GPUPackedNormal *)data)[l_index] = GPU_normal_convert_i10_v3(bm_face_no_get(mr, l->f));
+ }
+ BMFace *efa = l->f;
+ ((GPUPackedNormal *)data)[l_index].w = BM_elem_flag_test(efa, BM_ELEM_HIDDEN) ? -1 : 0;
+ }
+ EXTRACT_POLY_AND_LOOP_FOREACH_BM_END(l);
}
- BMFace *efa = loop->f;
- ((GPUPackedNormal *)data)[l].w = BM_elem_flag_test(efa, BM_ELEM_HIDDEN) ? -1 : 0;
}
-static void extract_lnor_loop_mesh(
- const MeshRenderData *mr, int l, const MLoop *mloop, int p, const MPoly *mpoly, void *data)
+static void extract_lnor_iter_poly_mesh(const MeshRenderData *mr,
+ const ExtractPolyMesh_Params *params,
+ void *data)
{
- GPUPackedNormal *lnor_data = &((GPUPackedNormal *)data)[l];
- if (mr->loop_normals) {
- *lnor_data = GPU_normal_convert_i10_v3(mr->loop_normals[l]);
- }
- else if (mpoly->flag & ME_SMOOTH) {
- *lnor_data = GPU_normal_convert_i10_s3(mr->mvert[mloop->v].no);
- }
- else {
- *lnor_data = GPU_normal_convert_i10_v3(mr->poly_normals[p]);
- }
+ EXTRACT_POLY_AND_LOOP_FOREACH_MESH_BEGIN(mp, mp_index, ml, ml_index, params, mr)
+ {
+ GPUPackedNormal *lnor_data = &((GPUPackedNormal *)data)[ml_index];
+ if (mr->loop_normals) {
+ *lnor_data = GPU_normal_convert_i10_v3(mr->loop_normals[ml_index]);
+ }
+ else if (mp->flag & ME_SMOOTH) {
+ *lnor_data = GPU_normal_convert_i10_s3(mr->mvert[ml->v].no);
+ }
+ else {
+ *lnor_data = GPU_normal_convert_i10_v3(mr->poly_normals[mp_index]);
+ }
- /* Flag for paint mode overlay.
- * Only use MR_EXTRACT_MAPPED in edit mode where it is used to display the edge-normals. In
- * paint mode it will use the unmapped data to draw the wireframe. */
- if (mpoly->flag & ME_HIDE ||
- (mr->edit_bmesh && mr->extract_type == MR_EXTRACT_MAPPED && (mr->v_origindex) &&
- mr->v_origindex[mloop->v] == ORIGINDEX_NONE)) {
- lnor_data->w = -1;
- }
- else if (mpoly->flag & ME_FACE_SEL) {
- lnor_data->w = 1;
- }
- else {
- lnor_data->w = 0;
+ /* Flag for paint mode overlay.
+ * Only use MR_EXTRACT_MAPPED in edit mode where it is used to display the edge-normals.
+ * In paint mode it will use the un-mapped data to draw the wire-frame. */
+ if (mp->flag & ME_HIDE || (mr->edit_bmesh && mr->extract_type == MR_EXTRACT_MAPPED &&
+ (mr->v_origindex) && mr->v_origindex[ml->v] == ORIGINDEX_NONE)) {
+ lnor_data->w = -1;
+ }
+ else if (mp->flag & ME_FACE_SEL) {
+ lnor_data->w = 1;
+ }
+ else {
+ lnor_data->w = 0;
+ }
}
+ EXTRACT_POLY_AND_LOOP_FOREACH_MESH_END;
}
static const MeshExtract extract_lnor = {
- extract_lnor_init,
- NULL,
- NULL,
- extract_lnor_loop_bmesh,
- extract_lnor_loop_mesh,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- MR_DATA_LOOP_NOR,
- true,
+ .init = extract_lnor_init,
+ .iter_poly_bm = extract_lnor_iter_poly_bm,
+ .iter_poly_mesh = extract_lnor_iter_poly_mesh,
+ .data_flag = MR_DATA_LOOP_NOR,
+ .use_threading = true,
};
/** \} */
@@ -1878,7 +2230,7 @@ static void *extract_uv_init(const MeshRenderData *mr, void *buf)
/* Active display layer name. */
if (i == CustomData_get_active_layer(cd_ldata, CD_MLOOPUV)) {
GPU_vertformat_alias_add(&format, "au");
- /* Alias to pos for edit uvs. */
+ /* Alias to `pos` for edit uvs. */
GPU_vertformat_alias_add(&format, "pos");
}
/* Stencil mask uv layer name. */
@@ -1904,20 +2256,21 @@ static void *extract_uv_init(const MeshRenderData *mr, void *buf)
if (uv_layers & (1 << i)) {
if (mr->extract_type == MR_EXTRACT_BMESH) {
int cd_ofs = CustomData_get_n_offset(cd_ldata, CD_MLOOPUV, i);
- BMIter f_iter, l_iter;
+ BMIter f_iter;
BMFace *efa;
- BMLoop *loop;
BM_ITER_MESH (efa, &f_iter, mr->bm, BM_FACES_OF_MESH) {
- BM_ITER_ELEM (loop, &l_iter, efa, BM_LOOPS_OF_FACE) {
- MLoopUV *luv = BM_ELEM_CD_GET_VOID_P(loop, cd_ofs);
+ BMLoop *l_iter, *l_first;
+ l_iter = l_first = BM_FACE_FIRST_LOOP(efa);
+ do {
+ MLoopUV *luv = BM_ELEM_CD_GET_VOID_P(l_iter, cd_ofs);
memcpy(uv_data, luv->uv, sizeof(*uv_data));
uv_data++;
- }
+ } while ((l_iter = l_iter->next) != l_first);
}
}
else {
MLoopUV *layer_data = CustomData_get_layer_n(cd_ldata, CD_MLOOPUV, i);
- for (int l = 0; l < mr->loop_len; l++, uv_data++, layer_data++) {
+ for (int ml_index = 0; ml_index < mr->loop_len; ml_index++, uv_data++, layer_data++) {
memcpy(uv_data, layer_data->uv, sizeof(*uv_data));
}
}
@@ -1928,18 +2281,9 @@ static void *extract_uv_init(const MeshRenderData *mr, void *buf)
}
static const MeshExtract extract_uv = {
- extract_uv_init,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- 0,
- false,
+ .init = extract_uv_init,
+ .data_flag = 0,
+ .use_threading = false,
};
/** \} */
@@ -1987,7 +2331,7 @@ static void extract_tan_ex(const MeshRenderData *mr, GPUVertBuf *vbo, const bool
}
}
if (use_orco_tan && orco == NULL) {
- /* If orco is not available compute it ourselves */
+ /* If `orco` is not available compute it ourselves */
orco_allocated = true;
orco = MEM_mallocN(sizeof(*orco) * mr->vert_len, __func__);
@@ -2001,17 +2345,18 @@ static void extract_tan_ex(const MeshRenderData *mr, GPUVertBuf *vbo, const bool
}
}
else {
- const MVert *mvert = mr->mvert;
- for (int v = 0; v < mr->vert_len; v++, mvert++) {
- copy_v3_v3(orco[v], mvert->co);
+ const MVert *mv = mr->mvert;
+ for (int v = 0; v < mr->vert_len; v++, mv++) {
+ copy_v3_v3(orco[v], mv->co);
}
}
BKE_mesh_orco_verts_transform(mr->me, orco, mr->vert_len, 0);
}
/* Start Fresh */
- CustomData_free_layers(cd_ldata, CD_TANGENT, mr->loop_len);
-
+ CustomData loop_data;
+ CustomData_reset(&loop_data);
+ CustomData *ldata = cd_ldata;
if (tan_len != 0 || use_orco_tan) {
short tangent_mask = 0;
bool calc_active_tangent = false;
@@ -2041,9 +2386,10 @@ static void extract_tan_ex(const MeshRenderData *mr, GPUVertBuf *vbo, const bool
mr->poly_normals,
mr->loop_normals,
orco,
- cd_ldata,
+ &loop_data,
mr->loop_len,
&tangent_mask);
+ ldata = &loop_data;
}
}
@@ -2075,18 +2421,18 @@ static void extract_tan_ex(const MeshRenderData *mr, GPUVertBuf *vbo, const bool
short(*tan_data)[4] = (short(*)[4])vbo->data;
for (int i = 0; i < tan_len; i++) {
const char *name = tangent_names[i];
- float(*layer_data)[4] = (float(*)[4])CustomData_get_layer_named(cd_ldata, CD_TANGENT, name);
- for (int l = 0; l < mr->loop_len; l++) {
- normal_float_to_short_v3(*tan_data, layer_data[l]);
- (*tan_data)[3] = (layer_data[l][3] > 0.0f) ? SHRT_MAX : SHRT_MIN;
+ float(*layer_data)[4] = (float(*)[4])CustomData_get_layer_named(ldata, CD_TANGENT, name);
+ for (int ml_index = 0; ml_index < mr->loop_len; ml_index++) {
+ normal_float_to_short_v3(*tan_data, layer_data[ml_index]);
+ (*tan_data)[3] = (layer_data[ml_index][3] > 0.0f) ? SHRT_MAX : SHRT_MIN;
tan_data++;
}
}
if (use_orco_tan) {
- float(*layer_data)[4] = (float(*)[4])CustomData_get_layer_n(cd_ldata, CD_TANGENT, 0);
- for (int l = 0; l < mr->loop_len; l++) {
- normal_float_to_short_v3(*tan_data, layer_data[l]);
- (*tan_data)[3] = (layer_data[l][3] > 0.0f) ? SHRT_MAX : SHRT_MIN;
+ float(*layer_data)[4] = (float(*)[4])CustomData_get_layer_n(ldata, CD_TANGENT, 0);
+ for (int ml_index = 0; ml_index < mr->loop_len; ml_index++) {
+ normal_float_to_short_v3(*tan_data, layer_data[ml_index]);
+ (*tan_data)[3] = (layer_data[ml_index][3] > 0.0f) ? SHRT_MAX : SHRT_MIN;
tan_data++;
}
}
@@ -2095,24 +2441,25 @@ static void extract_tan_ex(const MeshRenderData *mr, GPUVertBuf *vbo, const bool
GPUPackedNormal *tan_data = (GPUPackedNormal *)vbo->data;
for (int i = 0; i < tan_len; i++) {
const char *name = tangent_names[i];
- float(*layer_data)[4] = (float(*)[4])CustomData_get_layer_named(cd_ldata, CD_TANGENT, name);
- for (int l = 0; l < mr->loop_len; l++) {
- *tan_data = GPU_normal_convert_i10_v3(layer_data[l]);
- tan_data->w = (layer_data[l][3] > 0.0f) ? 1 : -2;
+ float(*layer_data)[4] = (float(*)[4])CustomData_get_layer_named(ldata, CD_TANGENT, name);
+ for (int ml_index = 0; ml_index < mr->loop_len; ml_index++) {
+ *tan_data = GPU_normal_convert_i10_v3(layer_data[ml_index]);
+ tan_data->w = (layer_data[ml_index][3] > 0.0f) ? 1 : -2;
tan_data++;
}
}
if (use_orco_tan) {
- float(*layer_data)[4] = (float(*)[4])CustomData_get_layer_n(cd_ldata, CD_TANGENT, 0);
- for (int l = 0; l < mr->loop_len; l++) {
- *tan_data = GPU_normal_convert_i10_v3(layer_data[l]);
- tan_data->w = (layer_data[l][3] > 0.0f) ? 1 : -2;
+ float(*layer_data)[4] = (float(*)[4])CustomData_get_layer_n(ldata, CD_TANGENT, 0);
+ for (int ml_index = 0; ml_index < mr->loop_len; ml_index++) {
+ *tan_data = GPU_normal_convert_i10_v3(layer_data[ml_index]);
+ tan_data->w = (layer_data[ml_index][3] > 0.0f) ? 1 : -2;
tan_data++;
}
}
}
- CustomData_free_layers(cd_ldata, CD_TANGENT, mr->loop_len);
+ CustomData_free_layers(ldata, CD_TANGENT, mr->loop_len);
+ CustomData_free(&loop_data, mr->loop_len);
}
static void *extract_tan_init(const MeshRenderData *mr, void *buf)
@@ -2122,18 +2469,9 @@ static void *extract_tan_init(const MeshRenderData *mr, void *buf)
}
static const MeshExtract extract_tan = {
- extract_tan_init,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- MR_DATA_POLY_NOR | MR_DATA_TAN_LOOP_NOR | MR_DATA_LOOPTRI,
- false,
+ .init = extract_tan_init,
+ .data_flag = MR_DATA_POLY_NOR | MR_DATA_TAN_LOOP_NOR | MR_DATA_LOOPTRI,
+ .use_threading = false,
};
/** \} */
@@ -2149,18 +2487,9 @@ static void *extract_tan_hq_init(const MeshRenderData *mr, void *buf)
}
static const MeshExtract extract_tan_hq = {
- extract_tan_hq_init,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- MR_DATA_POLY_NOR | MR_DATA_TAN_LOOP_NOR | MR_DATA_LOOPTRI,
- false,
+ .init = extract_tan_hq_init,
+ .data_flag = MR_DATA_POLY_NOR | MR_DATA_TAN_LOOP_NOR | MR_DATA_LOOPTRI,
+ .use_threading = false,
};
/** \} */
@@ -2175,7 +2504,9 @@ static void *extract_vcol_init(const MeshRenderData *mr, void *buf)
GPU_vertformat_deinterleave(&format);
CustomData *cd_ldata = (mr->extract_type == MR_EXTRACT_BMESH) ? &mr->bm->ldata : &mr->me->ldata;
+ CustomData *cd_vdata = (mr->extract_type == MR_EXTRACT_BMESH) ? &mr->bm->vdata : &mr->me->vdata;
uint32_t vcol_layers = mr->cache->cd_used.vcol;
+ uint32_t svcol_layers = mr->cache->cd_used.sculpt_vcol;
for (int i = 0; i < MAX_MCOL; i++) {
if (vcol_layers & (1 << i)) {
@@ -2192,14 +2523,42 @@ static void *extract_vcol_init(const MeshRenderData *mr, void *buf)
if (i == CustomData_get_active_layer(cd_ldata, CD_MLOOPCOL)) {
GPU_vertformat_alias_add(&format, "ac");
}
+
/* Gather number of auto layers. */
- /* We only do vcols that are not overridden by uvs */
+ /* We only do `vcols` that are not overridden by `uvs` and sculpt vertex colors. */
+ if (CustomData_get_named_layer_index(cd_ldata, CD_MLOOPUV, layer_name) == -1 &&
+ CustomData_get_named_layer_index(cd_vdata, CD_PROP_COLOR, layer_name) == -1) {
+ BLI_snprintf(attr_name, sizeof(attr_name), "a%s", attr_safe_name);
+ GPU_vertformat_alias_add(&format, attr_name);
+ }
+ }
+ }
+
+ /* Sculpt Vertex Colors */
+ for (int i = 0; i < 8; i++) {
+ if (svcol_layers & (1 << i)) {
+ char attr_name[32], attr_safe_name[GPU_MAX_SAFE_ATTR_NAME];
+ const char *layer_name = CustomData_get_layer_name(cd_vdata, CD_PROP_COLOR, i);
+ GPU_vertformat_safe_attr_name(layer_name, attr_safe_name, GPU_MAX_SAFE_ATTR_NAME);
+
+ BLI_snprintf(attr_name, sizeof(attr_name), "c%s", attr_safe_name);
+ GPU_vertformat_attr_add(&format, attr_name, GPU_COMP_U16, 4, GPU_FETCH_INT_TO_FLOAT_UNIT);
+
+ if (i == CustomData_get_render_layer(cd_vdata, CD_PROP_COLOR)) {
+ GPU_vertformat_alias_add(&format, "c");
+ }
+ if (i == CustomData_get_active_layer(cd_vdata, CD_PROP_COLOR)) {
+ GPU_vertformat_alias_add(&format, "ac");
+ }
+ /* 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, layer_name) == -1) {
BLI_snprintf(attr_name, sizeof(attr_name), "a%s", attr_safe_name);
GPU_vertformat_alias_add(&format, attr_name);
}
}
}
+
GPUVertBuf *vbo = buf;
GPU_vertbuf_init_with_format(vbo, &format);
GPU_vertbuf_data_alloc(vbo, mr->loop_len);
@@ -2209,27 +2568,30 @@ static void *extract_vcol_init(const MeshRenderData *mr, void *buf)
} gpuMeshVcol;
gpuMeshVcol *vcol_data = (gpuMeshVcol *)vbo->data;
+ MLoop *loops = CustomData_get_layer(cd_ldata, CD_MLOOP);
+
for (int i = 0; i < MAX_MCOL; i++) {
if (vcol_layers & (1 << i)) {
if (mr->extract_type == MR_EXTRACT_BMESH) {
int cd_ofs = CustomData_get_n_offset(cd_ldata, CD_MLOOPCOL, i);
- BMIter f_iter, l_iter;
+ BMIter f_iter;
BMFace *efa;
- BMLoop *loop;
BM_ITER_MESH (efa, &f_iter, mr->bm, BM_FACES_OF_MESH) {
- BM_ITER_ELEM (loop, &l_iter, efa, BM_LOOPS_OF_FACE) {
- const MLoopCol *mloopcol = BM_ELEM_CD_GET_VOID_P(loop, cd_ofs);
+ BMLoop *l_iter, *l_first;
+ l_iter = l_first = BM_FACE_FIRST_LOOP(efa);
+ do {
+ const MLoopCol *mloopcol = BM_ELEM_CD_GET_VOID_P(l_iter, cd_ofs);
vcol_data->r = unit_float_to_ushort_clamp(BLI_color_from_srgb_table[mloopcol->r]);
vcol_data->g = unit_float_to_ushort_clamp(BLI_color_from_srgb_table[mloopcol->g]);
vcol_data->b = unit_float_to_ushort_clamp(BLI_color_from_srgb_table[mloopcol->b]);
vcol_data->a = unit_float_to_ushort_clamp(mloopcol->a * (1.0f / 255.0f));
vcol_data++;
- }
+ } while ((l_iter = l_iter->next) != l_first);
}
}
else {
const MLoopCol *mloopcol = (MLoopCol *)CustomData_get_layer_n(cd_ldata, CD_MLOOPCOL, i);
- for (int l = 0; l < mr->loop_len; l++, mloopcol++, vcol_data++) {
+ for (int ml_index = 0; ml_index < mr->loop_len; ml_index++, mloopcol++, vcol_data++) {
vcol_data->r = unit_float_to_ushort_clamp(BLI_color_from_srgb_table[mloopcol->r]);
vcol_data->g = unit_float_to_ushort_clamp(BLI_color_from_srgb_table[mloopcol->g]);
vcol_data->b = unit_float_to_ushort_clamp(BLI_color_from_srgb_table[mloopcol->b]);
@@ -2237,22 +2599,45 @@ static void *extract_vcol_init(const MeshRenderData *mr, void *buf)
}
}
}
+
+ if (svcol_layers & (1 << i)) {
+ if (mr->extract_type == MR_EXTRACT_BMESH) {
+ int cd_ofs = CustomData_get_n_offset(cd_vdata, CD_PROP_COLOR, i);
+ BMIter f_iter;
+ BMFace *efa;
+ BM_ITER_MESH (efa, &f_iter, mr->bm, BM_FACES_OF_MESH) {
+ BMLoop *l_iter, *l_first;
+ l_iter = l_first = BM_FACE_FIRST_LOOP(efa);
+ do {
+ const MPropCol *prop_col = BM_ELEM_CD_GET_VOID_P(l_iter->v, cd_ofs);
+ vcol_data->r = unit_float_to_ushort_clamp(prop_col->color[0]);
+ vcol_data->g = unit_float_to_ushort_clamp(prop_col->color[1]);
+ vcol_data->b = unit_float_to_ushort_clamp(prop_col->color[2]);
+ vcol_data->a = unit_float_to_ushort_clamp(prop_col->color[3]);
+ vcol_data++;
+ } while ((l_iter = l_iter->next) != l_first);
+ }
+ }
+ else {
+ MPropCol *vcol = CustomData_get_layer_n(cd_vdata, CD_PROP_COLOR, i);
+ for (int ml_index = 0; ml_index < mr->loop_len; ml_index++, vcol_data++) {
+ vcol_data->r = unit_float_to_ushort_clamp(vcol[loops[ml_index].v].color[0]);
+ vcol_data->g = unit_float_to_ushort_clamp(vcol[loops[ml_index].v].color[1]);
+ vcol_data->b = unit_float_to_ushort_clamp(vcol[loops[ml_index].v].color[2]);
+ vcol_data->a = unit_float_to_ushort_clamp(vcol[loops[ml_index].v].color[3]);
+ }
+ }
+
+ vcol_data += mr->loop_len;
+ }
}
return NULL;
}
static const MeshExtract extract_vcol = {
- extract_vcol_init,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- 0,
- false,
+ .init = extract_vcol_init,
+ .data_flag = 0,
+ .use_threading = false,
};
/** \} */
@@ -2271,7 +2656,7 @@ static void *extract_orco_init(const MeshRenderData *mr, void *buf)
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 Vram and should be done another way.
+ * 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);
@@ -2286,33 +2671,37 @@ static void *extract_orco_init(const MeshRenderData *mr, void *buf)
MeshExtract_Orco_Data *data = MEM_mallocN(sizeof(*data), __func__);
data->vbo_data = (float(*)[4])vbo->data;
data->orco = CustomData_get_layer(cd_vdata, CD_ORCO);
- /* Make sure orco layer was requested only if needed! */
+ /* Make sure `orco` layer was requested only if needed! */
BLI_assert(data->orco);
return data;
}
-static void extract_orco_loop_bmesh(const MeshRenderData *UNUSED(mr),
- int l,
- BMLoop *loop,
- void *data)
+static void extract_orco_iter_poly_bm(const MeshRenderData *mr,
+ const ExtractPolyBMesh_Params *params,
+ void *data)
{
MeshExtract_Orco_Data *orco_data = (MeshExtract_Orco_Data *)data;
- float *loop_orco = orco_data->vbo_data[l];
- copy_v3_v3(loop_orco, orco_data->orco[BM_elem_index_get(loop->v)]);
- loop_orco[3] = 0.0; /* Tag as not a generic attribute. */
+ EXTRACT_POLY_AND_LOOP_FOREACH_BM_BEGIN(loop, l_index, params, mr)
+ {
+ float *loop_orco = orco_data->vbo_data[l_index];
+ copy_v3_v3(loop_orco, orco_data->orco[BM_elem_index_get(loop->v)]);
+ loop_orco[3] = 0.0; /* Tag as not a generic attribute. */
+ }
+ EXTRACT_POLY_AND_LOOP_FOREACH_BM_END(loop);
}
-static void extract_orco_loop_mesh(const MeshRenderData *UNUSED(mr),
- int l,
- const MLoop *mloop,
- int UNUSED(p),
- const MPoly *UNUSED(mpoly),
- void *data)
+static void extract_orco_iter_poly_mesh(const MeshRenderData *mr,
+ const ExtractPolyMesh_Params *params,
+ void *data)
{
- MeshExtract_Orco_Data *orco_data = (MeshExtract_Orco_Data *)data;
- float *loop_orco = orco_data->vbo_data[l];
- copy_v3_v3(loop_orco, orco_data->orco[mloop->v]);
- loop_orco[3] = 0.0; /* Tag as not a generic attribute. */
+ EXTRACT_POLY_AND_LOOP_FOREACH_MESH_BEGIN(mp, mp_index, ml, ml_index, params, mr)
+ {
+ MeshExtract_Orco_Data *orco_data = (MeshExtract_Orco_Data *)data;
+ float *loop_orco = orco_data->vbo_data[ml_index];
+ copy_v3_v3(loop_orco, orco_data->orco[ml->v]);
+ loop_orco[3] = 0.0; /* Tag as not a generic attribute. */
+ }
+ EXTRACT_POLY_AND_LOOP_FOREACH_MESH_END;
}
static void extract_orco_finish(const MeshRenderData *UNUSED(mr), void *UNUSED(buf), void *data)
@@ -2321,18 +2710,12 @@ static void extract_orco_finish(const MeshRenderData *UNUSED(mr), void *UNUSED(b
}
static const MeshExtract extract_orco = {
- extract_orco_init,
- NULL,
- NULL,
- extract_orco_loop_bmesh,
- extract_orco_loop_mesh,
- NULL,
- NULL,
- NULL,
- NULL,
- extract_orco_finish,
- 0,
- true,
+ .init = extract_orco_init,
+ .iter_poly_bm = extract_orco_iter_poly_bm,
+ .iter_poly_mesh = extract_orco_iter_poly_mesh,
+ .finish = extract_orco_finish,
+ .data_flag = 0,
+ .use_threading = true,
};
/** \} */
@@ -2359,7 +2742,7 @@ static float loop_edge_factor_get(const float f_no[3],
cross_v3_v3v3(enor, v_no, evec);
normalize_v3(enor);
float d = fabsf(dot_v3v3(enor, f_no));
- /* Rescale to the slider range. */
+ /* Re-scale to the slider range. */
d *= (1.0f / 0.065f);
CLAMP(d, 0.0f, 1.0f);
return d;
@@ -2383,9 +2766,9 @@ static void *extract_edge_fac_init(const MeshRenderData *mr, void *buf)
/* HACK(fclem) Detecting the need for edge render.
* We could have a flag in the mesh instead or check the modifier stack. */
- const MEdge *medge = mr->medge;
- for (int e = 0; e < mr->edge_len; e++, medge++) {
- if ((medge->flag & ME_EDGERENDER) == 0) {
+ const MEdge *med = mr->medge;
+ for (int e_index = 0; e_index < mr->edge_len; e_index++, med++) {
+ if ((med->flag & ME_EDGERENDER) == 0) {
data->use_edge_render = true;
break;
}
@@ -2401,81 +2784,103 @@ static void *extract_edge_fac_init(const MeshRenderData *mr, void *buf)
return data;
}
-static void extract_edge_fac_loop_bmesh(const MeshRenderData *mr, int l, BMLoop *loop, void *_data)
+static void extract_edge_fac_iter_poly_bm(const MeshRenderData *mr,
+ const ExtractPolyBMesh_Params *params,
+ void *_data)
{
- MeshExtract_EdgeFac_Data *data = (MeshExtract_EdgeFac_Data *)_data;
- if (BM_edge_is_manifold(loop->e)) {
- float ratio = loop_edge_factor_get(bm_face_no_get(mr, loop->f),
- bm_vert_co_get(mr, loop->v),
- bm_vert_no_get(mr, loop->v),
- bm_vert_co_get(mr, loop->next->v));
- data->vbo_data[l] = ratio * 253 + 1;
- }
- else {
- data->vbo_data[l] = 255;
+ MeshExtract_EdgeFac_Data *data = _data;
+ EXTRACT_POLY_AND_LOOP_FOREACH_BM_BEGIN(l, l_index, params, mr)
+ {
+ if (BM_edge_is_manifold(l->e)) {
+ float ratio = loop_edge_factor_get(bm_face_no_get(mr, l->f),
+ bm_vert_co_get(mr, l->v),
+ bm_vert_no_get(mr, l->v),
+ bm_vert_co_get(mr, l->next->v));
+ data->vbo_data[l_index] = ratio * 253 + 1;
+ }
+ else {
+ data->vbo_data[l_index] = 255;
+ }
}
+ EXTRACT_POLY_AND_LOOP_FOREACH_BM_END(l);
}
-static void extract_edge_fac_loop_mesh(
- const MeshRenderData *mr, int l, const MLoop *mloop, int p, const MPoly *mpoly, void *_data)
+static void extract_edge_fac_iter_poly_mesh(const MeshRenderData *mr,
+ const ExtractPolyMesh_Params *params,
+ void *_data)
{
MeshExtract_EdgeFac_Data *data = (MeshExtract_EdgeFac_Data *)_data;
+
if (data->use_edge_render) {
- const MEdge *medge = &mr->medge[mloop->e];
- data->vbo_data[l] = (medge->flag & ME_EDGERENDER) ? 255 : 0;
+ EXTRACT_POLY_AND_LOOP_FOREACH_MESH_BEGIN(mp, mp_index, ml, ml_index, params, mr)
+ {
+ const MEdge *med = &mr->medge[ml->e];
+ data->vbo_data[ml_index] = (med->flag & ME_EDGERENDER) ? 255 : 0;
+ }
+ EXTRACT_POLY_AND_LOOP_FOREACH_MESH_END;
}
else {
- /* Count loop per edge to detect non-manifold. */
- if (data->edge_loop_count[mloop->e] < 3) {
- data->edge_loop_count[mloop->e]++;
- }
- if (data->edge_loop_count[mloop->e] == 2) {
- /* Manifold */
- int loopend = mpoly->totloop + mpoly->loopstart - 1;
- int other_loop = (l == loopend) ? mpoly->loopstart : (l + 1);
- const MLoop *mloop_next = &mr->mloop[other_loop];
- const MVert *v1 = &mr->mvert[mloop->v];
- const MVert *v2 = &mr->mvert[mloop_next->v];
- float vnor_f[3];
- normal_short_to_float_v3(vnor_f, v1->no);
- float ratio = loop_edge_factor_get(mr->poly_normals[p], v1->co, vnor_f, v2->co);
- data->vbo_data[l] = ratio * 253 + 1;
- }
- else {
- /* Non-manifold */
- data->vbo_data[l] = 255;
+ EXTRACT_POLY_AND_LOOP_FOREACH_MESH_BEGIN(mp, mp_index, ml, ml_index, params, mr)
+ {
+ /* Count loop per edge to detect non-manifold. */
+ if (data->edge_loop_count[ml->e] < 3) {
+ data->edge_loop_count[ml->e]++;
+ }
+ if (data->edge_loop_count[ml->e] == 2) {
+ /* Manifold */
+ const int ml_index_last = mp->totloop + mp->loopstart - 1;
+ const int ml_index_other = (ml_index == ml_index_last) ? mp->loopstart : (ml_index + 1);
+ const MLoop *ml_next = &mr->mloop[ml_index_other];
+ const MVert *v1 = &mr->mvert[ml->v];
+ const MVert *v2 = &mr->mvert[ml_next->v];
+ float vnor_f[3];
+ normal_short_to_float_v3(vnor_f, v1->no);
+ float ratio = loop_edge_factor_get(mr->poly_normals[mp_index], v1->co, vnor_f, v2->co);
+ data->vbo_data[ml_index] = ratio * 253 + 1;
+ }
+ else {
+ /* Non-manifold */
+ data->vbo_data[ml_index] = 255;
+ }
}
+ EXTRACT_POLY_AND_LOOP_FOREACH_MESH_END;
}
}
-static void extract_edge_fac_ledge_bmesh(const MeshRenderData *mr,
- int e,
- BMEdge *UNUSED(eed),
- void *_data)
+static void extract_edge_fac_iter_ledge_bm(const MeshRenderData *mr,
+ const ExtractLEdgeBMesh_Params *params,
+ void *_data)
{
- MeshExtract_EdgeFac_Data *data = (MeshExtract_EdgeFac_Data *)_data;
- data->vbo_data[mr->loop_len + e * 2 + 0] = 255;
- data->vbo_data[mr->loop_len + e * 2 + 1] = 255;
+ MeshExtract_EdgeFac_Data *data = _data;
+ EXTRACT_LEDGE_FOREACH_BM_BEGIN(eed, ledge_index, params)
+ {
+ data->vbo_data[mr->loop_len + (ledge_index * 2) + 0] = 255;
+ data->vbo_data[mr->loop_len + (ledge_index * 2) + 1] = 255;
+ }
+ EXTRACT_LEDGE_FOREACH_BM_END;
}
-static void extract_edge_fac_ledge_mesh(const MeshRenderData *mr,
- int e,
- const MEdge *UNUSED(edge),
- void *_data)
+static void extract_edge_fac_iter_ledge_mesh(const MeshRenderData *mr,
+ const ExtractLEdgeMesh_Params *params,
+ void *_data)
{
- MeshExtract_EdgeFac_Data *data = (MeshExtract_EdgeFac_Data *)_data;
- data->vbo_data[mr->loop_len + e * 2 + 0] = 255;
- data->vbo_data[mr->loop_len + e * 2 + 1] = 255;
+ MeshExtract_EdgeFac_Data *data = _data;
+ EXTRACT_LEDGE_FOREACH_MESH_BEGIN(med, ledge_index, params, mr)
+ {
+ data->vbo_data[mr->loop_len + ledge_index * 2 + 0] = 255;
+ data->vbo_data[mr->loop_len + ledge_index * 2 + 1] = 255;
+ }
+ EXTRACT_LEDGE_FOREACH_MESH_END;
}
static void extract_edge_fac_finish(const MeshRenderData *mr, void *buf, void *_data)
{
- MeshExtract_EdgeFac_Data *data = (MeshExtract_EdgeFac_Data *)_data;
+ MeshExtract_EdgeFac_Data *data = _data;
if (GPU_crappy_amd_driver()) {
GPUVertBuf *vbo = (GPUVertBuf *)buf;
- /* Some AMD drivers strangely crash with VBOs with a one byte format.
- * To workaround we reinit the vbo with another format and convert
+ /* Some AMD drivers strangely crash with VBO's with a one byte format.
+ * To workaround we reinitialize the VBO with another format and convert
* all bytes to floats. */
static GPUVertFormat format = {0};
if (format.attr_len == 0) {
@@ -2490,8 +2895,8 @@ static void extract_edge_fac_finish(const MeshRenderData *mr, void *buf, void *_
GPU_vertbuf_data_alloc(vbo, buf_len);
float *fdata = (float *)vbo->data;
- for (int l = 0; l < buf_len; l++, fdata++) {
- *fdata = data->vbo_data[l] / 255.0f;
+ for (int ml_index = 0; ml_index < buf_len; ml_index++, fdata++) {
+ *fdata = data->vbo_data[ml_index] / 255.0f;
}
/* Free old byte data. */
MEM_freeN(data->vbo_data);
@@ -2500,18 +2905,14 @@ static void extract_edge_fac_finish(const MeshRenderData *mr, void *buf, void *_
}
static const MeshExtract extract_edge_fac = {
- extract_edge_fac_init,
- NULL,
- NULL,
- extract_edge_fac_loop_bmesh,
- extract_edge_fac_loop_mesh,
- extract_edge_fac_ledge_bmesh,
- extract_edge_fac_ledge_mesh,
- NULL,
- NULL,
- extract_edge_fac_finish,
- MR_DATA_POLY_NOR,
- false,
+ .init = extract_edge_fac_init,
+ .iter_poly_bm = extract_edge_fac_iter_poly_bm,
+ .iter_poly_mesh = extract_edge_fac_iter_poly_mesh,
+ .iter_ledge_bm = extract_edge_fac_iter_ledge_bm,
+ .iter_ledge_mesh = extract_edge_fac_iter_ledge_mesh,
+ .finish = extract_edge_fac_finish,
+ .data_flag = MR_DATA_POLY_NOR,
+ .use_threading = false,
};
/** \} */
@@ -2522,8 +2923,8 @@ static const MeshExtract extract_edge_fac = {
typedef struct MeshExtract_Weight_Data {
float *vbo_data;
const DRW_MeshWeightState *wstate;
- const MDeformVert *dvert; /* For Mesh. */
- int cd_ofs; /* For BMesh. */
+ const MDeformVert *dvert; /* For #Mesh. */
+ int cd_ofs; /* For #BMesh. */
} MeshExtract_Weight_Data;
static float evaluate_vertex_weight(const MDeformVert *dvert, const DRW_MeshWeightState *wstate)
@@ -2609,27 +3010,49 @@ static void *extract_weights_init(const MeshRenderData *mr, void *buf)
return data;
}
-static void extract_weights_loop_bmesh(const MeshRenderData *UNUSED(mr),
- int l,
- BMLoop *loop,
- void *_data)
+static void extract_weights_iter_poly_bm(const MeshRenderData *mr,
+ const ExtractPolyBMesh_Params *params,
+ void *_data)
{
- MeshExtract_Weight_Data *data = (MeshExtract_Weight_Data *)_data;
- const MDeformVert *dvert = (data->cd_ofs != -1) ? BM_ELEM_CD_GET_VOID_P(loop->v, data->cd_ofs) :
- NULL;
- data->vbo_data[l] = evaluate_vertex_weight(dvert, data->wstate);
+ MeshExtract_Weight_Data *data = _data;
+ if (data->cd_ofs != -1) {
+ EXTRACT_POLY_AND_LOOP_FOREACH_BM_BEGIN(l, l_index, params, mr)
+ {
+ const MDeformVert *dvert = BM_ELEM_CD_GET_VOID_P(l->v, data->cd_ofs);
+ data->vbo_data[l_index] = evaluate_vertex_weight(dvert, data->wstate);
+ }
+ EXTRACT_POLY_AND_LOOP_FOREACH_BM_END(l);
+ }
+ else {
+ EXTRACT_POLY_AND_LOOP_FOREACH_BM_BEGIN(l, l_index, params, mr)
+ {
+ data->vbo_data[l_index] = evaluate_vertex_weight(NULL, data->wstate);
+ }
+ EXTRACT_POLY_AND_LOOP_FOREACH_BM_END(l);
+ }
}
-static void extract_weights_loop_mesh(const MeshRenderData *UNUSED(mr),
- int l,
- const MLoop *mloop,
- int UNUSED(p),
- const MPoly *UNUSED(mpoly),
- void *_data)
+static void extract_weights_iter_poly_mesh(const MeshRenderData *mr,
+ const ExtractPolyMesh_Params *params,
+ void *_data)
{
- MeshExtract_Weight_Data *data = (MeshExtract_Weight_Data *)_data;
- const MDeformVert *dvert = data->dvert ? &data->dvert[mloop->v] : NULL;
- data->vbo_data[l] = evaluate_vertex_weight(dvert, data->wstate);
+ MeshExtract_Weight_Data *data = _data;
+ if (data->dvert != NULL) {
+ EXTRACT_POLY_AND_LOOP_FOREACH_MESH_BEGIN(mp, mp_index, ml, ml_index, params, mr)
+ {
+ const MDeformVert *dvert = &data->dvert[ml->v];
+ data->vbo_data[ml_index] = evaluate_vertex_weight(dvert, data->wstate);
+ }
+ EXTRACT_POLY_AND_LOOP_FOREACH_MESH_END;
+ }
+ else {
+ const MDeformVert *dvert = NULL;
+ EXTRACT_POLY_AND_LOOP_FOREACH_MESH_BEGIN(mp, mp_index, ml, ml_index, params, mr)
+ {
+ data->vbo_data[ml_index] = evaluate_vertex_weight(dvert, data->wstate);
+ }
+ EXTRACT_POLY_AND_LOOP_FOREACH_MESH_END;
+ }
}
static void extract_weights_finish(const MeshRenderData *UNUSED(mr), void *UNUSED(buf), void *data)
@@ -2638,18 +3061,12 @@ static void extract_weights_finish(const MeshRenderData *UNUSED(mr), void *UNUSE
}
static const MeshExtract extract_weights = {
- extract_weights_init,
- NULL,
- NULL,
- extract_weights_loop_bmesh,
- extract_weights_loop_mesh,
- NULL,
- NULL,
- NULL,
- NULL,
- extract_weights_finish,
- 0,
- true,
+ .init = extract_weights_init,
+ .iter_poly_bm = extract_weights_iter_poly_bm,
+ .iter_poly_mesh = extract_weights_iter_poly_mesh,
+ .finish = extract_weights_finish,
+ .data_flag = 0,
+ .use_threading = true,
};
/** \} */
@@ -2756,31 +3173,31 @@ static void mesh_render_data_edge_flag(const MeshRenderData *mr, BMEdge *eed, Ed
}
static void mesh_render_data_loop_flag(const MeshRenderData *mr,
- BMLoop *loop,
+ BMLoop *l,
const int cd_ofs,
EditLoopData *eattr)
{
if (cd_ofs == -1) {
return;
}
- MLoopUV *luv = BM_ELEM_CD_GET_VOID_P(loop, cd_ofs);
+ MLoopUV *luv = BM_ELEM_CD_GET_VOID_P(l, cd_ofs);
if (luv != NULL && (luv->flag & MLOOPUV_PINNED)) {
eattr->v_flag |= VFLAG_VERT_UV_PINNED;
}
- if (uvedit_uv_select_test_ex(mr->toolsettings, loop, cd_ofs)) {
+ if (uvedit_uv_select_test_ex(mr->toolsettings, l, cd_ofs)) {
eattr->v_flag |= VFLAG_VERT_UV_SELECT;
}
}
static void mesh_render_data_loop_edge_flag(const MeshRenderData *mr,
- BMLoop *loop,
+ BMLoop *l,
const int cd_ofs,
EditLoopData *eattr)
{
if (cd_ofs == -1) {
return;
}
- if (uvedit_edge_select_test_ex(mr->toolsettings, loop, cd_ofs)) {
+ if (uvedit_edge_select_test_ex(mr->toolsettings, l, cd_ofs)) {
eattr->v_flag |= VFLAG_EDGE_UV_SELECT;
eattr->v_flag |= VFLAG_VERT_UV_SELECT;
}
@@ -2800,7 +3217,7 @@ static void *extract_edit_data_init(const MeshRenderData *mr, void *buf)
{
static GPUVertFormat format = {0};
if (format.attr_len == 0) {
- /* WARNING Adjust EditLoopData struct accordingly. */
+ /* WARNING: Adjust #EditLoopData struct accordingly. */
GPU_vertformat_attr_add(&format, "data", GPU_COMP_U8, 4, GPU_FETCH_INT);
GPU_vertformat_alias_add(&format, "flag");
}
@@ -2810,114 +3227,130 @@ static void *extract_edit_data_init(const MeshRenderData *mr, void *buf)
return vbo->data;
}
-static void extract_edit_data_loop_bmesh(const MeshRenderData *mr,
- int l,
- BMLoop *loop,
- void *_data)
+static void extract_edit_data_iter_poly_bm(const MeshRenderData *mr,
+ const ExtractPolyBMesh_Params *params,
+ void *_data)
{
- EditLoopData *data = (EditLoopData *)_data + l;
- memset(data, 0x0, sizeof(*data));
- mesh_render_data_face_flag(mr, loop->f, -1, data);
- mesh_render_data_edge_flag(mr, loop->e, data);
- mesh_render_data_vert_flag(mr, loop->v, data);
-}
-static void extract_edit_data_loop_mesh(const MeshRenderData *mr,
- int l,
- const MLoop *mloop,
- int p,
- const MPoly *UNUSED(mpoly),
- void *_data)
-{
- EditLoopData *data = (EditLoopData *)_data + l;
- memset(data, 0x0, sizeof(*data));
- BMFace *efa = bm_original_face_get(mr, p);
- BMEdge *eed = bm_original_edge_get(mr, mloop->e);
- BMVert *eve = bm_original_vert_get(mr, mloop->v);
- if (efa) {
- mesh_render_data_face_flag(mr, efa, -1, data);
- }
- if (eed) {
- mesh_render_data_edge_flag(mr, eed, data);
- }
- if (eve) {
- mesh_render_data_vert_flag(mr, eve, data);
+ EXTRACT_POLY_AND_LOOP_FOREACH_BM_BEGIN(l, l_index, params, mr)
+ {
+ EditLoopData *data = (EditLoopData *)_data + l_index;
+ memset(data, 0x0, sizeof(*data));
+ mesh_render_data_face_flag(mr, l->f, -1, data);
+ mesh_render_data_edge_flag(mr, l->e, data);
+ mesh_render_data_vert_flag(mr, l->v, data);
}
+ EXTRACT_POLY_AND_LOOP_FOREACH_BM_END(l);
}
-static void extract_edit_data_ledge_bmesh(const MeshRenderData *mr,
- int e,
- BMEdge *eed,
- void *_data)
+static void extract_edit_data_iter_poly_mesh(const MeshRenderData *mr,
+ const ExtractPolyMesh_Params *params,
+ void *_data)
{
- EditLoopData *data = (EditLoopData *)_data + mr->loop_len + e * 2;
- memset(data, 0x0, sizeof(*data) * 2);
- mesh_render_data_edge_flag(mr, eed, &data[0]);
- data[1] = data[0];
- mesh_render_data_vert_flag(mr, eed->v1, &data[0]);
- mesh_render_data_vert_flag(mr, eed->v2, &data[1]);
+ EXTRACT_POLY_AND_LOOP_FOREACH_MESH_BEGIN(mp, mp_index, ml, ml_index, params, mr)
+ {
+ EditLoopData *data = (EditLoopData *)_data + ml_index;
+ memset(data, 0x0, sizeof(*data));
+ BMFace *efa = bm_original_face_get(mr, mp_index);
+ BMEdge *eed = bm_original_edge_get(mr, ml->e);
+ BMVert *eve = bm_original_vert_get(mr, ml->v);
+ if (efa) {
+ mesh_render_data_face_flag(mr, efa, -1, data);
+ }
+ if (eed) {
+ mesh_render_data_edge_flag(mr, eed, data);
+ }
+ if (eve) {
+ mesh_render_data_vert_flag(mr, eve, data);
+ }
+ }
+ EXTRACT_POLY_AND_LOOP_FOREACH_MESH_END;
}
-static void extract_edit_data_ledge_mesh(const MeshRenderData *mr,
- int e,
- const MEdge *edge,
- void *_data)
+static void extract_edit_data_iter_ledge_bm(const MeshRenderData *mr,
+ const ExtractLEdgeBMesh_Params *params,
+ void *_data)
{
- EditLoopData *data = (EditLoopData *)_data + mr->loop_len + e * 2;
- memset(data, 0x0, sizeof(*data) * 2);
- int e_idx = mr->ledges[e];
- BMEdge *eed = bm_original_edge_get(mr, e_idx);
- BMVert *eve1 = bm_original_vert_get(mr, edge->v1);
- BMVert *eve2 = bm_original_vert_get(mr, edge->v2);
- if (eed) {
+ EXTRACT_LEDGE_FOREACH_BM_BEGIN(eed, ledge_index, params)
+ {
+ EditLoopData *data = (EditLoopData *)_data + mr->loop_len + (ledge_index * 2);
+ memset(data, 0x0, sizeof(*data) * 2);
mesh_render_data_edge_flag(mr, eed, &data[0]);
data[1] = data[0];
+ mesh_render_data_vert_flag(mr, eed->v1, &data[0]);
+ mesh_render_data_vert_flag(mr, eed->v2, &data[1]);
+ }
+ EXTRACT_LEDGE_FOREACH_BM_END;
+}
+
+static void extract_edit_data_iter_ledge_mesh(const MeshRenderData *mr,
+ const ExtractLEdgeMesh_Params *params,
+ void *_data)
+{
+ EXTRACT_LEDGE_FOREACH_MESH_BEGIN(med, ledge_index, params, mr)
+ {
+ EditLoopData *data = (EditLoopData *)_data + mr->loop_len + ledge_index * 2;
+ memset(data, 0x0, sizeof(*data) * 2);
+ const int e_index = mr->ledges[ledge_index];
+ BMEdge *eed = bm_original_edge_get(mr, e_index);
+ BMVert *eve1 = bm_original_vert_get(mr, med->v1);
+ BMVert *eve2 = bm_original_vert_get(mr, med->v2);
+ if (eed) {
+ mesh_render_data_edge_flag(mr, eed, &data[0]);
+ data[1] = data[0];
+ }
+ if (eve1) {
+ mesh_render_data_vert_flag(mr, eve1, &data[0]);
+ }
+ if (eve2) {
+ mesh_render_data_vert_flag(mr, eve2, &data[1]);
+ }
}
- if (eve1) {
- mesh_render_data_vert_flag(mr, eve1, &data[0]);
- }
- if (eve2) {
- mesh_render_data_vert_flag(mr, eve2, &data[1]);
- }
+ EXTRACT_LEDGE_FOREACH_MESH_END;
}
-static void extract_edit_data_lvert_bmesh(const MeshRenderData *mr,
- int v,
- BMVert *eve,
- void *_data)
+static void extract_edit_data_iter_lvert_bm(const MeshRenderData *mr,
+ const ExtractLVertBMesh_Params *params,
+ void *_data)
{
- EditLoopData *data = (EditLoopData *)_data + mr->loop_len + mr->edge_loose_len * 2 + v;
- memset(data, 0x0, sizeof(*data));
- mesh_render_data_vert_flag(mr, eve, data);
+ const int offset = mr->loop_len + (mr->edge_loose_len * 2);
+ EXTRACT_LVERT_FOREACH_BM_BEGIN(eve, lvert_index, params)
+ {
+ EditLoopData *data = (EditLoopData *)_data + offset + lvert_index;
+ memset(data, 0x0, sizeof(*data));
+ mesh_render_data_vert_flag(mr, eve, data);
+ }
+ EXTRACT_LVERT_FOREACH_BM_END;
}
-static void extract_edit_data_lvert_mesh(const MeshRenderData *mr,
- int v,
- const MVert *UNUSED(mvert),
- void *_data)
+static void extract_edit_data_iter_lvert_mesh(const MeshRenderData *mr,
+ const ExtractLVertMesh_Params *params,
+ void *_data)
{
- EditLoopData *data = (EditLoopData *)_data + mr->loop_len + mr->edge_loose_len * 2 + v;
- memset(data, 0x0, sizeof(*data));
- int v_idx = mr->lverts[v];
- BMVert *eve = bm_original_vert_get(mr, v_idx);
- if (eve) {
- mesh_render_data_vert_flag(mr, eve, data);
+ const int offset = mr->loop_len + (mr->edge_loose_len * 2);
+ EXTRACT_LVERT_FOREACH_MESH_BEGIN(mv, lvert_index, params, mr)
+ {
+ EditLoopData *data = (EditLoopData *)_data + offset + lvert_index;
+ memset(data, 0x0, sizeof(*data));
+ const int v_index = mr->lverts[lvert_index];
+ BMVert *eve = bm_original_vert_get(mr, v_index);
+ if (eve) {
+ mesh_render_data_vert_flag(mr, eve, data);
+ }
}
+ EXTRACT_LVERT_FOREACH_MESH_END;
}
static const MeshExtract extract_edit_data = {
- extract_edit_data_init,
- NULL,
- NULL,
- extract_edit_data_loop_bmesh,
- extract_edit_data_loop_mesh,
- extract_edit_data_ledge_bmesh,
- extract_edit_data_ledge_mesh,
- extract_edit_data_lvert_bmesh,
- extract_edit_data_lvert_mesh,
- NULL,
- 0,
- true,
+ .init = extract_edit_data_init,
+ .iter_poly_bm = extract_edit_data_iter_poly_bm,
+ .iter_poly_mesh = extract_edit_data_iter_poly_mesh,
+ .iter_ledge_bm = extract_edit_data_iter_ledge_bm,
+ .iter_ledge_mesh = extract_edit_data_iter_ledge_mesh,
+ .iter_lvert_bm = extract_edit_data_iter_lvert_bm,
+ .iter_lvert_mesh = extract_edit_data_iter_lvert_mesh,
+ .data_flag = 0,
+ .use_threading = true,
};
/** \} */
@@ -2935,7 +3368,7 @@ static void *extract_edituv_data_init(const MeshRenderData *mr, void *buf)
{
static GPUVertFormat format = {0};
if (format.attr_len == 0) {
- /* WARNING Adjust EditLoopData struct accordingly. */
+ /* WARNING: Adjust #EditLoopData struct accordingly. */
GPU_vertformat_attr_add(&format, "data", GPU_COMP_U8, 4, GPU_FETCH_INT);
GPU_vertformat_alias_add(&format, "flag");
}
@@ -2952,51 +3385,59 @@ static void *extract_edituv_data_init(const MeshRenderData *mr, void *buf)
return data;
}
-static void extract_edituv_data_loop_bmesh(const MeshRenderData *mr,
- int l,
- BMLoop *loop,
- void *_data)
+static void extract_edituv_data_iter_poly_bm(const MeshRenderData *mr,
+ const ExtractPolyBMesh_Params *params,
+ void *_data)
{
- MeshExtract_EditUVData_Data *data = (MeshExtract_EditUVData_Data *)_data;
- EditLoopData *eldata = data->vbo_data + l;
- memset(eldata, 0x0, sizeof(*eldata));
- mesh_render_data_loop_flag(mr, loop, data->cd_ofs, eldata);
- mesh_render_data_face_flag(mr, loop->f, data->cd_ofs, eldata);
- mesh_render_data_loop_edge_flag(mr, loop, data->cd_ofs, eldata);
-}
-
-static void extract_edituv_data_loop_mesh(
- const MeshRenderData *mr, int l, const MLoop *mloop, int p, const MPoly *mpoly, void *_data)
-{
- MeshExtract_EditUVData_Data *data = (MeshExtract_EditUVData_Data *)_data;
- EditLoopData *eldata = data->vbo_data + l;
- memset(eldata, 0x0, sizeof(*eldata));
- BMFace *efa = bm_original_face_get(mr, p);
- if (efa) {
- BMEdge *eed = bm_original_edge_get(mr, mloop->e);
- BMVert *eve = bm_original_vert_get(mr, mloop->v);
- if (eed && eve) {
- /* Loop on an edge endpoint. */
- BMLoop *loop = BM_face_edge_share_loop(efa, eed);
- mesh_render_data_loop_flag(mr, loop, data->cd_ofs, eldata);
- mesh_render_data_loop_edge_flag(mr, loop, data->cd_ofs, eldata);
- }
- else {
- if (eed == NULL) {
- /* Find if the loop's vert is not part of an edit edge.
- * For this, we check if the previous loop was on an edge. */
- int loopend = mpoly->loopstart + mpoly->totloop - 1;
- int l_prev = (l == mpoly->loopstart) ? loopend : (l - 1);
- const MLoop *mloop_prev = &mr->mloop[l_prev];
- eed = bm_original_edge_get(mr, mloop_prev->e);
+ EXTRACT_POLY_AND_LOOP_FOREACH_BM_BEGIN(l, l_index, params, mr)
+ {
+ MeshExtract_EditUVData_Data *data = _data;
+ EditLoopData *eldata = &data->vbo_data[l_index];
+ memset(eldata, 0x0, sizeof(*eldata));
+ mesh_render_data_loop_flag(mr, l, data->cd_ofs, eldata);
+ mesh_render_data_face_flag(mr, l->f, data->cd_ofs, eldata);
+ mesh_render_data_loop_edge_flag(mr, l, data->cd_ofs, eldata);
+ }
+ EXTRACT_POLY_AND_LOOP_FOREACH_BM_END(l);
+}
+
+static void extract_edituv_data_iter_poly_mesh(const MeshRenderData *mr,
+ const ExtractPolyMesh_Params *params,
+ void *_data)
+{
+ MeshExtract_EditUVData_Data *data = _data;
+ EXTRACT_POLY_AND_LOOP_FOREACH_MESH_BEGIN(mp, mp_index, ml, ml_index, params, mr)
+ {
+ EditLoopData *eldata = &data->vbo_data[ml_index];
+ memset(eldata, 0x0, sizeof(*eldata));
+ BMFace *efa = bm_original_face_get(mr, mp_index);
+ if (efa) {
+ BMEdge *eed = bm_original_edge_get(mr, ml->e);
+ BMVert *eve = bm_original_vert_get(mr, ml->v);
+ if (eed && eve) {
+ /* Loop on an edge endpoint. */
+ BMLoop *l = BM_face_edge_share_loop(efa, eed);
+ mesh_render_data_loop_flag(mr, l, data->cd_ofs, eldata);
+ mesh_render_data_loop_edge_flag(mr, l, data->cd_ofs, eldata);
}
- if (eed) {
- /* Mapped points on an edge between two edit verts. */
- BMLoop *loop = BM_face_edge_share_loop(efa, eed);
- mesh_render_data_loop_edge_flag(mr, loop, data->cd_ofs, eldata);
+ else {
+ if (eed == NULL) {
+ /* Find if the loop's vert is not part of an edit edge.
+ * For this, we check if the previous loop was on an edge. */
+ const int ml_index_last = mp->loopstart + mp->totloop - 1;
+ const int l_prev = (ml_index == mp->loopstart) ? ml_index_last : (ml_index - 1);
+ const MLoop *ml_prev = &mr->mloop[l_prev];
+ eed = bm_original_edge_get(mr, ml_prev->e);
+ }
+ if (eed) {
+ /* Mapped points on an edge between two edit verts. */
+ BMLoop *l = BM_face_edge_share_loop(efa, eed);
+ mesh_render_data_loop_edge_flag(mr, l, data->cd_ofs, eldata);
+ }
}
}
}
+ EXTRACT_POLY_AND_LOOP_FOREACH_MESH_END;
}
static void extract_edituv_data_finish(const MeshRenderData *UNUSED(mr),
@@ -3007,18 +3448,12 @@ static void extract_edituv_data_finish(const MeshRenderData *UNUSED(mr),
}
static const MeshExtract extract_edituv_data = {
- extract_edituv_data_init,
- NULL,
- NULL,
- extract_edituv_data_loop_bmesh,
- extract_edituv_data_loop_mesh,
- NULL,
- NULL,
- NULL,
- NULL,
- extract_edituv_data_finish,
- 0,
- true,
+ .init = extract_edituv_data_init,
+ .iter_poly_bm = extract_edituv_data_iter_poly_bm,
+ .iter_poly_mesh = extract_edituv_data_iter_poly_mesh,
+ .finish = extract_edituv_data_finish,
+ .data_flag = 0,
+ .use_threading = true,
};
/** \} */
@@ -3078,13 +3513,13 @@ static void mesh_stretch_area_finish(const MeshRenderData *mr, void *buf, void *
}
else if (mr->extract_type == MR_EXTRACT_MAPPED) {
const MLoopUV *uv_data = CustomData_get_layer(&mr->me->ldata, CD_MLOOPUV);
- const MPoly *mpoly = mr->mpoly;
- for (int p = 0; p < mr->poly_len; p++, mpoly++) {
- float area = BKE_mesh_calc_poly_area(mpoly, &mr->mloop[mpoly->loopstart], mr->mvert);
- float uvarea = BKE_mesh_calc_poly_uv_area(mpoly, uv_data);
+ const MPoly *mp = mr->mpoly;
+ for (int mp_index = 0; mp_index < mr->poly_len; mp_index++, mp++) {
+ float area = BKE_mesh_calc_poly_area(mp, &mr->mloop[mp->loopstart], mr->mvert);
+ float uvarea = BKE_mesh_calc_poly_uv_area(mp, uv_data);
tot_area += area;
tot_uv_area += uvarea;
- area_ratio[p] = area_ratio_get(area, uvarea);
+ area_ratio[mp_index] = area_ratio_get(area, uvarea);
}
}
else {
@@ -3097,8 +3532,8 @@ static void mesh_stretch_area_finish(const MeshRenderData *mr, void *buf, void *
/* Convert in place to avoid an extra allocation */
uint16_t *poly_stretch = (uint16_t *)area_ratio;
- for (int p = 0; p < mr->poly_len; p++) {
- poly_stretch[p] = area_ratio[p] * SHRT_MAX;
+ for (int mp_index = 0; mp_index < mr->poly_len; mp_index++) {
+ poly_stretch[mp_index] = area_ratio[mp_index] * SHRT_MAX;
}
/* Copy face data for each loop. */
@@ -3108,18 +3543,18 @@ static void mesh_stretch_area_finish(const MeshRenderData *mr, void *buf, void *
if (mr->extract_type == MR_EXTRACT_BMESH) {
BMFace *efa;
BMIter f_iter;
- int f, l = 0;
+ int f, l_index = 0;
BM_ITER_MESH_INDEX (efa, &f_iter, mr->bm, BM_FACES_OF_MESH, f) {
- for (int i = 0; i < efa->len; i++, l++) {
- loop_stretch[l] = poly_stretch[f];
+ for (int i = 0; i < efa->len; i++, l_index++) {
+ loop_stretch[l_index] = poly_stretch[f];
}
}
}
else if (mr->extract_type == MR_EXTRACT_MAPPED) {
- const MPoly *mpoly = mr->mpoly;
- for (int p = 0, l = 0; p < mr->poly_len; p++, mpoly++) {
- for (int i = 0; i < mpoly->totloop; i++, l++) {
- loop_stretch[l] = poly_stretch[p];
+ const MPoly *mp = mr->mpoly;
+ for (int mp_index = 0, l_index = 0; mp_index < mr->poly_len; mp_index++, mp++) {
+ for (int i = 0; i < mp->totloop; i++, l_index++) {
+ loop_stretch[l_index] = poly_stretch[mp_index];
}
}
}
@@ -3132,18 +3567,10 @@ static void mesh_stretch_area_finish(const MeshRenderData *mr, void *buf, void *
}
static const MeshExtract extract_stretch_area = {
- extract_stretch_area_init,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- mesh_stretch_area_finish,
- 0,
- false,
+ .init = extract_stretch_area_init,
+ .finish = mesh_stretch_area_finish,
+ .data_flag = 0,
+ .use_threading = false,
};
/** \} */
@@ -3190,7 +3617,7 @@ static short v2_to_short_angle(float v[2])
static void edituv_get_stretch_angle(float auv[2][2], float av[2][3], UVStretchAngle *r_stretch)
{
- /* Send uvs to the shader and let it compute the aspect corrected angle. */
+ /* Send UV's to the shader and let it compute the aspect corrected angle. */
r_stretch->uv_angles[0] = v2_to_short_angle(auv[0]);
r_stretch->uv_angles[1] = v2_to_short_angle(auv[1]);
/* Compute 3D angle here. */
@@ -3208,7 +3635,7 @@ static void *extract_stretch_angle_init(const MeshRenderData *mr, void *buf)
{
static GPUVertFormat format = {0};
if (format.attr_len == 0) {
- /* WARNING Adjust UVStretchAngle struct accordingly. */
+ /* Waning: adjust #UVStretchAngle struct accordingly. */
GPU_vertformat_attr_add(&format, "angle", GPU_COMP_I16, 1, GPU_FETCH_INT_TO_FLOAT_UNIT);
GPU_vertformat_attr_add(&format, "uv_angles", GPU_COMP_I16, 2, GPU_FETCH_INT_TO_FLOAT_UNIT);
}
@@ -3220,7 +3647,7 @@ static void *extract_stretch_angle_init(const MeshRenderData *mr, void *buf)
MeshExtract_StretchAngle_Data *data = MEM_callocN(sizeof(*data), __func__);
data->vbo_data = (UVStretchAngle *)vbo->data;
- /* Special iter nneded to save about half of the computing cost. */
+ /* Special iterator needed to save about half of the computing cost. */
if (mr->extract_type == MR_EXTRACT_BMESH) {
data->cd_ofs = CustomData_get_offset(&mr->bm->ldata, CD_MLOOPUV);
}
@@ -3233,94 +3660,95 @@ static void *extract_stretch_angle_init(const MeshRenderData *mr, void *buf)
return data;
}
-static void extract_stretch_angle_loop_bmesh(const MeshRenderData *mr,
- int l,
- BMLoop *loop,
- void *_data)
+static void extract_stretch_angle_iter_poly_bm(const MeshRenderData *mr,
+ const ExtractPolyBMesh_Params *params,
+ void *_data)
{
- MeshExtract_StretchAngle_Data *data = (MeshExtract_StretchAngle_Data *)_data;
+ MeshExtract_StretchAngle_Data *data = _data;
float(*auv)[2] = data->auv, *last_auv = data->last_auv;
float(*av)[3] = data->av, *last_av = data->last_av;
- const MLoopUV *luv, *luv_next;
- BMLoop *l_next = loop->next;
- BMFace *efa = loop->f;
- if (loop == efa->l_first) {
- /* First loop in face. */
- BMLoop *l_tmp = loop->prev;
- BMLoop *l_next_tmp = loop;
- luv = BM_ELEM_CD_GET_VOID_P(l_tmp, data->cd_ofs);
- luv_next = BM_ELEM_CD_GET_VOID_P(l_next_tmp, data->cd_ofs);
- compute_normalize_edge_vectors(auv,
- av,
- luv->uv,
- luv_next->uv,
- bm_vert_co_get(mr, l_tmp->v),
- bm_vert_co_get(mr, l_next_tmp->v));
- /* Save last edge. */
- copy_v2_v2(last_auv, auv[1]);
- copy_v3_v3(last_av, av[1]);
- }
- if (l_next == efa->l_first) {
- /* Move previous edge. */
- copy_v2_v2(auv[0], auv[1]);
- copy_v3_v3(av[0], av[1]);
- /* Copy already calculated last edge. */
- copy_v2_v2(auv[1], last_auv);
- copy_v3_v3(av[1], last_av);
+ EXTRACT_POLY_AND_LOOP_FOREACH_BM_BEGIN(l, l_index, params, mr)
+ {
+ const MLoopUV *luv, *luv_next;
+ BMLoop *l_next = l->next;
+ BMFace *efa = l->f;
+ if (l == BM_FACE_FIRST_LOOP(efa)) {
+ /* First loop in face. */
+ BMLoop *l_tmp = l->prev;
+ BMLoop *l_next_tmp = l;
+ luv = BM_ELEM_CD_GET_VOID_P(l_tmp, data->cd_ofs);
+ luv_next = BM_ELEM_CD_GET_VOID_P(l_next_tmp, data->cd_ofs);
+ compute_normalize_edge_vectors(auv,
+ av,
+ luv->uv,
+ luv_next->uv,
+ bm_vert_co_get(mr, l_tmp->v),
+ bm_vert_co_get(mr, l_next_tmp->v));
+ /* Save last edge. */
+ copy_v2_v2(last_auv, auv[1]);
+ copy_v3_v3(last_av, av[1]);
+ }
+ if (l_next == BM_FACE_FIRST_LOOP(efa)) {
+ /* Move previous edge. */
+ copy_v2_v2(auv[0], auv[1]);
+ copy_v3_v3(av[0], av[1]);
+ /* Copy already calculated last edge. */
+ copy_v2_v2(auv[1], last_auv);
+ copy_v3_v3(av[1], last_av);
+ }
+ else {
+ luv = BM_ELEM_CD_GET_VOID_P(l, data->cd_ofs);
+ luv_next = BM_ELEM_CD_GET_VOID_P(l_next, data->cd_ofs);
+ compute_normalize_edge_vectors(
+ auv, av, luv->uv, luv_next->uv, bm_vert_co_get(mr, l->v), bm_vert_co_get(mr, l_next->v));
+ }
+ edituv_get_stretch_angle(auv, av, &data->vbo_data[l_index]);
}
- else {
- luv = BM_ELEM_CD_GET_VOID_P(loop, data->cd_ofs);
- luv_next = BM_ELEM_CD_GET_VOID_P(l_next, data->cd_ofs);
- compute_normalize_edge_vectors(auv,
- av,
- luv->uv,
- luv_next->uv,
- bm_vert_co_get(mr, loop->v),
- bm_vert_co_get(mr, l_next->v));
- }
- edituv_get_stretch_angle(auv, av, data->vbo_data + l);
-}
-
-static void extract_stretch_angle_loop_mesh(const MeshRenderData *mr,
- int l,
- const MLoop *UNUSED(mloop),
- int UNUSED(p),
- const MPoly *mpoly,
- void *_data)
+ EXTRACT_POLY_AND_LOOP_FOREACH_BM_END(l);
+}
+
+static void extract_stretch_angle_iter_poly_mesh(const MeshRenderData *mr,
+ const ExtractPolyMesh_Params *params,
+ void *_data)
{
- MeshExtract_StretchAngle_Data *data = (MeshExtract_StretchAngle_Data *)_data;
- float(*auv)[2] = data->auv, *last_auv = data->last_auv;
- float(*av)[3] = data->av, *last_av = data->last_av;
- int l_next = l + 1, loopend = mpoly->loopstart + mpoly->totloop;
- const MVert *v, *v_next;
- if (l == mpoly->loopstart) {
- /* First loop in face. */
- int l_tmp = loopend - 1;
- int l_next_tmp = mpoly->loopstart;
- v = &mr->mvert[mr->mloop[l_tmp].v];
- v_next = &mr->mvert[mr->mloop[l_next_tmp].v];
- compute_normalize_edge_vectors(
- auv, av, data->luv[l_tmp].uv, data->luv[l_next_tmp].uv, v->co, v_next->co);
- /* Save last edge. */
- copy_v2_v2(last_auv, auv[1]);
- copy_v3_v3(last_av, av[1]);
- }
- if (l_next == loopend) {
- l_next = mpoly->loopstart;
- /* Move previous edge. */
- copy_v2_v2(auv[0], auv[1]);
- copy_v3_v3(av[0], av[1]);
- /* Copy already calculated last edge. */
- copy_v2_v2(auv[1], last_auv);
- copy_v3_v3(av[1], last_av);
- }
- else {
- v = &mr->mvert[mr->mloop[l].v];
- v_next = &mr->mvert[mr->mloop[l_next].v];
- compute_normalize_edge_vectors(
- auv, av, data->luv[l].uv, data->luv[l_next].uv, v->co, v_next->co);
+ MeshExtract_StretchAngle_Data *data = _data;
+
+ EXTRACT_POLY_AND_LOOP_FOREACH_MESH_BEGIN(mp, mp_index, ml, ml_index, params, mr)
+ {
+ float(*auv)[2] = data->auv, *last_auv = data->last_auv;
+ float(*av)[3] = data->av, *last_av = data->last_av;
+ int l_next = ml_index + 1, ml_index_end = mp->loopstart + mp->totloop;
+ const MVert *v, *v_next;
+ if (ml_index == mp->loopstart) {
+ /* First loop in face. */
+ const int ml_index_last = ml_index_end - 1;
+ const int l_next_tmp = mp->loopstart;
+ v = &mr->mvert[mr->mloop[ml_index_last].v];
+ v_next = &mr->mvert[mr->mloop[l_next_tmp].v];
+ compute_normalize_edge_vectors(
+ auv, av, data->luv[ml_index_last].uv, data->luv[l_next_tmp].uv, v->co, v_next->co);
+ /* Save last edge. */
+ copy_v2_v2(last_auv, auv[1]);
+ copy_v3_v3(last_av, av[1]);
+ }
+ if (l_next == ml_index_end) {
+ l_next = mp->loopstart;
+ /* Move previous edge. */
+ copy_v2_v2(auv[0], auv[1]);
+ copy_v3_v3(av[0], av[1]);
+ /* Copy already calculated last edge. */
+ copy_v2_v2(auv[1], last_auv);
+ copy_v3_v3(av[1], last_av);
+ }
+ else {
+ v = &mr->mvert[mr->mloop[ml_index].v];
+ v_next = &mr->mvert[mr->mloop[l_next].v];
+ compute_normalize_edge_vectors(
+ auv, av, data->luv[ml_index].uv, data->luv[l_next].uv, v->co, v_next->co);
+ }
+ edituv_get_stretch_angle(auv, av, &data->vbo_data[ml_index]);
}
- edituv_get_stretch_angle(auv, av, data->vbo_data + l);
+ EXTRACT_POLY_AND_LOOP_FOREACH_MESH_END;
}
static void extract_stretch_angle_finish(const MeshRenderData *UNUSED(mr),
@@ -3331,18 +3759,12 @@ static void extract_stretch_angle_finish(const MeshRenderData *UNUSED(mr),
}
static const MeshExtract extract_stretch_angle = {
- extract_stretch_angle_init,
- NULL,
- NULL,
- extract_stretch_angle_loop_bmesh,
- extract_stretch_angle_loop_mesh,
- NULL,
- NULL,
- NULL,
- NULL,
- extract_stretch_angle_finish,
- 0,
- false,
+ .init = extract_stretch_angle_init,
+ .iter_poly_bm = extract_stretch_angle_iter_poly_bm,
+ .iter_poly_mesh = extract_stretch_angle_iter_poly_mesh,
+ .finish = extract_stretch_angle_finish,
+ .data_flag = 0,
+ .use_threading = false,
};
/** \} */
@@ -3414,28 +3836,30 @@ static void statvis_calc_overhang(const MeshRenderData *mr, float *r_overhang)
normalize_v3(dir);
if (mr->extract_type == MR_EXTRACT_BMESH) {
- int l = 0;
+ int l_index = 0;
BM_ITER_MESH (f, &iter, bm, BM_FACES_OF_MESH) {
float fac = angle_normalized_v3v3(bm_face_no_get(mr, f), dir) / (float)M_PI;
fac = overhang_remap(fac, min, max, minmax_irange);
- for (int i = 0; i < f->len; i++, l++) {
- r_overhang[l] = fac;
+ for (int i = 0; i < f->len; i++, l_index++) {
+ r_overhang[l_index] = fac;
}
}
}
else {
- const MPoly *mpoly = mr->mpoly;
- for (int p = 0, l = 0; p < mr->poly_len; p++, mpoly++) {
- float fac = angle_normalized_v3v3(mr->poly_normals[p], dir) / (float)M_PI;
+ const MPoly *mp = mr->mpoly;
+ for (int mp_index = 0, l_index = 0; mp_index < mr->poly_len; mp_index++, mp++) {
+ float fac = angle_normalized_v3v3(mr->poly_normals[mp_index], dir) / (float)M_PI;
fac = overhang_remap(fac, min, max, minmax_irange);
- for (int i = 0; i < mpoly->totloop; i++, l++) {
- r_overhang[l] = fac;
+ for (int i = 0; i < mp->totloop; i++, l_index++) {
+ r_overhang[l_index] = fac;
}
}
}
}
-/* so we can use jitter values for face interpolation */
+/**
+ * Needed so we can use jitter values for face interpolation.
+ */
static void uv_from_jitter_v2(float uv[2])
{
uv[0] += 0.5f;
@@ -3527,12 +3951,12 @@ static void statvis_calc_thickness(const MeshRenderData *mr, float *r_thickness)
BMIter iter;
BMFace *f;
- int l = 0;
+ int l_index = 0;
BM_ITER_MESH (f, &iter, bm, BM_FACES_OF_MESH) {
float fac = face_dists[BM_elem_index_get(f)];
fac = thickness_remap(fac, min, max, minmax_irange);
- for (int i = 0; i < f->len; i++, l++) {
- r_thickness[l] = fac;
+ for (int i = 0; i < f->len; i++, l_index++) {
+ r_thickness[l_index] = fac;
}
}
}
@@ -3573,12 +3997,12 @@ static void statvis_calc_thickness(const MeshRenderData *mr, float *r_thickness)
}
}
- const MPoly *mpoly = mr->mpoly;
- for (int p = 0, l = 0; p < mr->poly_len; p++, mpoly++) {
- float fac = face_dists[p];
+ const MPoly *mp = mr->mpoly;
+ for (int mp_index = 0, l_index = 0; mp_index < mr->poly_len; mp_index++, mp++) {
+ float fac = face_dists[mp_index];
fac = thickness_remap(fac, min, max, minmax_irange);
- for (int i = 0; i < mpoly->totloop; i++, l++) {
- r_thickness[l] = fac;
+ for (int i = 0; i < mp->totloop; i++, l_index++) {
+ r_thickness[l_index] = fac;
}
}
}
@@ -3629,8 +4053,8 @@ static void statvis_calc_intersect(const MeshRenderData *mr, float *r_intersect)
{
BMEditMesh *em = mr->edit_bmesh;
- for (int l = 0; l < mr->loop_len; l++) {
- r_intersect[l] = -1.0f;
+ for (int l_index = 0; l_index < mr->loop_len; l_index++) {
+ r_intersect[l_index] = -1.0f;
}
if (mr->extract_type == MR_EXTRACT_BMESH) {
@@ -3651,9 +4075,9 @@ static void statvis_calc_intersect(const MeshRenderData *mr, float *r_intersect)
for (int j = 0; j < 2; j++) {
BMFace *f_hit = f_hit_pair[j];
BMLoop *l_first = BM_FACE_FIRST_LOOP(f_hit);
- int l = BM_elem_index_get(l_first);
- for (int k = 0; k < f_hit->len; k++, l++) {
- r_intersect[l] = 1.0f;
+ int l_index = BM_elem_index_get(l_first);
+ for (int k = 0; k < f_hit->len; k++, l_index++) {
+ r_intersect[l_index] = 1.0f;
}
}
}
@@ -3680,9 +4104,9 @@ static void statvis_calc_intersect(const MeshRenderData *mr, float *r_intersect)
};
for (int j = 0; j < 2; j++) {
const MPoly *f_hit = f_hit_pair[j];
- int l = f_hit->loopstart;
- for (int k = 0; k < f_hit->totloop; k++, l++) {
- r_intersect[l] = 1.0f;
+ int l_index = f_hit->loopstart;
+ for (int k = 0; k < f_hit->totloop; k++, l_index++) {
+ r_intersect[l_index] = 1.0f;
}
}
}
@@ -3725,9 +4149,9 @@ static void statvis_calc_distort(const MeshRenderData *mr, float *r_distort)
BM_mesh_elem_index_ensure(em->bm, BM_VERT);
}
- int l = 0;
- int p = 0;
- BM_ITER_MESH_INDEX (f, &iter, bm, BM_FACES_OF_MESH, p) {
+ int l_index = 0;
+ int f_index = 0;
+ BM_ITER_MESH_INDEX (f, &iter, bm, BM_FACES_OF_MESH, f_index) {
float fac = -1.0f;
if (f->len > 3) {
@@ -3739,7 +4163,7 @@ static void statvis_calc_distort(const MeshRenderData *mr, float *r_distort)
const float *no_face;
float no_corner[3];
if (mr->bm_vert_coords != NULL) {
- no_face = mr->bm_poly_normals[p];
+ no_face = mr->bm_poly_normals[f_index];
BM_loop_calc_face_normal_safe_vcos(l_iter, no_face, mr->bm_vert_coords, no_corner);
}
else {
@@ -3758,24 +4182,24 @@ static void statvis_calc_distort(const MeshRenderData *mr, float *r_distort)
}
fac = distort_remap(fac, min, max, minmax_irange);
- for (int i = 0; i < f->len; i++, l++) {
- r_distort[l] = fac;
+ for (int i = 0; i < f->len; i++, l_index++) {
+ r_distort[l_index] = fac;
}
}
}
else {
- const MPoly *mpoly = mr->mpoly;
- for (int p = 0, l = 0; p < mr->poly_len; p++, mpoly++) {
+ const MPoly *mp = mr->mpoly;
+ for (int mp_index = 0, l_index = 0; mp_index < mr->poly_len; mp_index++, mp++) {
float fac = -1.0f;
- if (mpoly->totloop > 3) {
- float *f_no = mr->poly_normals[p];
+ if (mp->totloop > 3) {
+ float *f_no = mr->poly_normals[mp_index];
fac = 0.0f;
- for (int i = 1; i <= mpoly->totloop; i++) {
- const MLoop *l_prev = &mr->mloop[mpoly->loopstart + (i - 1) % mpoly->totloop];
- const MLoop *l_curr = &mr->mloop[mpoly->loopstart + (i + 0) % mpoly->totloop];
- const MLoop *l_next = &mr->mloop[mpoly->loopstart + (i + 1) % mpoly->totloop];
+ for (int i = 1; i <= mp->totloop; i++) {
+ const MLoop *l_prev = &mr->mloop[mp->loopstart + (i - 1) % mp->totloop];
+ const MLoop *l_curr = &mr->mloop[mp->loopstart + (i + 0) % mp->totloop];
+ const MLoop *l_next = &mr->mloop[mp->loopstart + (i + 1) % mp->totloop];
float no_corner[3];
normal_tri_v3(no_corner,
mr->mvert[l_prev->v].co,
@@ -3791,8 +4215,8 @@ static void statvis_calc_distort(const MeshRenderData *mr, float *r_distort)
}
fac = distort_remap(fac, min, max, minmax_irange);
- for (int i = 0; i < mpoly->totloop; i++, l++) {
- r_distort[l] = fac;
+ for (int i = 0; i < mp->totloop; i++, l_index++) {
+ r_distort[l_index] = fac;
}
}
}
@@ -3825,11 +4249,10 @@ static void statvis_calc_sharp(const MeshRenderData *mr, float *r_sharp)
copy_vn_fl(vert_angles, mr->vert_len, -M_PI);
if (mr->extract_type == MR_EXTRACT_BMESH) {
- BMIter iter, l_iter;
+ BMIter iter;
BMesh *bm = em->bm;
BMFace *efa;
BMEdge *e;
- BMLoop *loop;
/* first assign float values to verts */
BM_ITER_MESH (e, &iter, bm, BM_EDGES_OF_MESH) {
float angle = BM_edge_calc_face_angle_signed(e);
@@ -3840,35 +4263,37 @@ static void statvis_calc_sharp(const MeshRenderData *mr, float *r_sharp)
}
/* Copy vert value to loops. */
BM_ITER_MESH (efa, &iter, bm, BM_FACES_OF_MESH) {
- BM_ITER_ELEM (loop, &l_iter, efa, BM_LOOPS_OF_FACE) {
- int l = BM_elem_index_get(loop);
- int v = BM_elem_index_get(loop->v);
- r_sharp[l] = sharp_remap(vert_angles[v], min, max, minmax_irange);
- }
+ BMLoop *l_iter, *l_first;
+ l_iter = l_first = BM_FACE_FIRST_LOOP(efa);
+ do {
+ int l_index = BM_elem_index_get(l_iter);
+ int v_index = BM_elem_index_get(l_iter->v);
+ r_sharp[l_index] = sharp_remap(vert_angles[v_index], min, max, minmax_irange);
+ } while ((l_iter = l_iter->next) != l_first);
}
}
else {
/* first assign float values to verts */
- const MPoly *mpoly = mr->mpoly;
+ const MPoly *mp = mr->mpoly;
EdgeHash *eh = BLI_edgehash_new_ex(__func__, mr->edge_len);
- for (int p = 0; p < mr->poly_len; p++, mpoly++) {
- for (int i = 0; i < mpoly->totloop; i++) {
- const MLoop *l_curr = &mr->mloop[mpoly->loopstart + (i + 0) % mpoly->totloop];
- const MLoop *l_next = &mr->mloop[mpoly->loopstart + (i + 1) % mpoly->totloop];
+ for (int mp_index = 0; mp_index < mr->poly_len; mp_index++, mp++) {
+ for (int i = 0; i < mp->totloop; i++) {
+ const MLoop *l_curr = &mr->mloop[mp->loopstart + (i + 0) % mp->totloop];
+ const MLoop *l_next = &mr->mloop[mp->loopstart + (i + 1) % mp->totloop];
const MVert *v_curr = &mr->mvert[l_curr->v];
const MVert *v_next = &mr->mvert[l_next->v];
float angle;
void **pval;
bool value_is_init = BLI_edgehash_ensure_p(eh, l_curr->v, l_next->v, &pval);
if (!value_is_init) {
- *pval = mr->poly_normals[p];
+ *pval = mr->poly_normals[mp_index];
/* non-manifold edge, yet... */
continue;
}
else if (*pval != NULL) {
- const float *f1_no = mr->poly_normals[p];
+ const float *f1_no = mr->poly_normals[mp_index];
const float *f2_no = *pval;
angle = angle_normalized_v3v3(f1_no, f2_no);
angle = is_edge_convex_v3(v_curr->co, v_next->co, f1_no, f2_no) ? angle : -angle;
@@ -3901,9 +4326,9 @@ static void statvis_calc_sharp(const MeshRenderData *mr, float *r_sharp)
BLI_edgehashIterator_free(ehi);
BLI_edgehash_free(eh, NULL);
- const MLoop *mloop = mr->mloop;
- for (int l = 0; l < mr->loop_len; l++, mloop++) {
- r_sharp[l] = sharp_remap(vert_angles[mloop->v], min, max, minmax_irange);
+ const MLoop *ml = mr->mloop;
+ for (int l_index = 0; l_index < mr->loop_len; l_index++, ml++) {
+ r_sharp[l_index] = sharp_remap(vert_angles[ml->v], min, max, minmax_irange);
}
}
@@ -3937,20 +4362,12 @@ static void extract_mesh_analysis_finish(const MeshRenderData *mr, void *buf, vo
}
static const MeshExtract extract_mesh_analysis = {
- extract_mesh_analysis_init,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- extract_mesh_analysis_finish,
- /* This is not needed for all vis type.
- * Maybe split into different extract. */
- MR_DATA_POLY_NOR | MR_DATA_LOOPTRI,
- false,
+ .init = extract_mesh_analysis_init,
+ .finish = extract_mesh_analysis_finish,
+ /* This is not needed for all visualization types.
+ * * Maybe split into different extract. */
+ .data_flag = MR_DATA_POLY_NOR | MR_DATA_LOOPTRI,
+ .use_threading = false,
};
/** \} */
@@ -3975,49 +4392,46 @@ static void *extract_fdots_pos_init(const MeshRenderData *mr, void *buf)
return vbo->data;
}
-static void extract_fdots_pos_loop_bmesh(const MeshRenderData *mr,
- int UNUSED(l),
- BMLoop *loop,
- void *data)
+static void extract_fdots_pos_iter_poly_bm(const MeshRenderData *mr,
+ const ExtractPolyBMesh_Params *params,
+ void *data)
{
- float(*center)[3] = (float(*)[3])data;
- float w = 1.0f / (float)loop->f->len;
- madd_v3_v3fl(center[BM_elem_index_get(loop->f)], bm_vert_co_get(mr, loop->v), w);
+ float(*center)[3] = data;
+ EXTRACT_POLY_AND_LOOP_FOREACH_BM_BEGIN(l, l_index, params, mr)
+ {
+ float w = 1.0f / (float)l->f->len;
+ madd_v3_v3fl(center[BM_elem_index_get(l->f)], bm_vert_co_get(mr, l->v), w);
+ }
+ EXTRACT_POLY_AND_LOOP_FOREACH_BM_END(l);
}
-static void extract_fdots_pos_loop_mesh(const MeshRenderData *mr,
- int UNUSED(l),
- const MLoop *mloop,
- int p,
- const MPoly *mpoly,
- void *data)
+static void extract_fdots_pos_iter_poly_mesh(const MeshRenderData *mr,
+ const ExtractPolyMesh_Params *params,
+ void *data)
{
float(*center)[3] = (float(*)[3])data;
- const MVert *mvert = &mr->mvert[mloop->v];
- if (mr->use_subsurf_fdots) {
- if (mvert->flag & ME_VERT_FACEDOT) {
- copy_v3_v3(center[p], mvert->co);
+ EXTRACT_POLY_AND_LOOP_FOREACH_MESH_BEGIN(mp, mp_index, ml, ml_index, params, mr)
+ {
+ const MVert *mv = &mr->mvert[ml->v];
+ if (mr->use_subsurf_fdots) {
+ if (mv->flag & ME_VERT_FACEDOT) {
+ copy_v3_v3(center[mp_index], mv->co);
+ }
+ }
+ else {
+ float w = 1.0f / (float)mp->totloop;
+ madd_v3_v3fl(center[mp_index], mv->co, w);
}
}
- else {
- float w = 1.0f / (float)mpoly->totloop;
- madd_v3_v3fl(center[p], mvert->co, w);
- }
+ EXTRACT_POLY_AND_LOOP_FOREACH_MESH_END;
}
static const MeshExtract extract_fdots_pos = {
- extract_fdots_pos_init,
- NULL,
- NULL,
- extract_fdots_pos_loop_bmesh,
- extract_fdots_pos_loop_mesh,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- 0,
- true,
+ .init = extract_fdots_pos_init,
+ .iter_poly_bm = extract_fdots_pos_iter_poly_bm,
+ .iter_poly_mesh = extract_fdots_pos_iter_poly_mesh,
+ .data_flag = 0,
+ .use_threading = true,
};
/** \} */
@@ -4090,18 +4504,10 @@ static void extract_fdots_nor_finish(const MeshRenderData *mr, void *buf, void *
}
static const MeshExtract extract_fdots_nor = {
- extract_fdots_nor_init,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- extract_fdots_nor_finish,
- MR_DATA_POLY_NOR,
- false,
+ .init = extract_fdots_nor_init,
+ .finish = extract_fdots_nor_finish,
+ .data_flag = MR_DATA_POLY_NOR,
+ .use_threading = false,
};
/** \} */
@@ -4145,30 +4551,42 @@ static void *extract_fdots_uv_init(const MeshRenderData *mr, void *buf)
return data;
}
-static void extract_fdots_uv_loop_bmesh(const MeshRenderData *UNUSED(mr),
- int UNUSED(l),
- BMLoop *loop,
- void *_data)
+static void extract_fdots_uv_iter_poly_bm(const MeshRenderData *mr,
+ const ExtractPolyBMesh_Params *params,
+ void *_data)
{
- MeshExtract_FdotUV_Data *data = (MeshExtract_FdotUV_Data *)_data;
- float w = 1.0f / (float)loop->f->len;
- const MLoopUV *luv = BM_ELEM_CD_GET_VOID_P(loop, data->cd_ofs);
- madd_v2_v2fl(data->vbo_data[BM_elem_index_get(loop->f)], luv->uv, w);
+ MeshExtract_FdotUV_Data *data = _data;
+ EXTRACT_POLY_AND_LOOP_FOREACH_BM_BEGIN(l, l_index, params, mr)
+ {
+ float w = 1.0f / (float)l->f->len;
+ const MLoopUV *luv = BM_ELEM_CD_GET_VOID_P(l, data->cd_ofs);
+ madd_v2_v2fl(data->vbo_data[BM_elem_index_get(l->f)], luv->uv, w);
+ }
+ EXTRACT_POLY_AND_LOOP_FOREACH_BM_END(l);
}
-static void extract_fdots_uv_loop_mesh(
- const MeshRenderData *mr, int l, const MLoop *mloop, int p, const MPoly *mpoly, void *_data)
+static void extract_fdots_uv_iter_poly_mesh(const MeshRenderData *mr,
+ const ExtractPolyMesh_Params *params,
+ void *_data)
{
- MeshExtract_FdotUV_Data *data = (MeshExtract_FdotUV_Data *)_data;
+ MeshExtract_FdotUV_Data *data = _data;
if (mr->use_subsurf_fdots) {
- const MVert *mvert = &mr->mvert[mloop->v];
- if (mvert->flag & ME_VERT_FACEDOT) {
- copy_v2_v2(data->vbo_data[p], data->uv_data[l].uv);
+ EXTRACT_POLY_AND_LOOP_FOREACH_MESH_BEGIN(mp, mp_index, ml, ml_index, params, mr)
+ {
+ const MVert *mv = &mr->mvert[ml->v];
+ if (mv->flag & ME_VERT_FACEDOT) {
+ copy_v2_v2(data->vbo_data[mp_index], data->uv_data[ml_index].uv);
+ }
}
+ EXTRACT_POLY_AND_LOOP_FOREACH_MESH_END;
}
else {
- float w = 1.0f / (float)mpoly->totloop;
- madd_v2_v2fl(data->vbo_data[p], data->uv_data[l].uv, w);
+ EXTRACT_POLY_AND_LOOP_FOREACH_MESH_BEGIN(mp, mp_index, ml, ml_index, params, mr)
+ {
+ float w = 1.0f / (float)mp->totloop;
+ madd_v2_v2fl(data->vbo_data[mp_index], data->uv_data[ml_index].uv, w);
+ }
+ EXTRACT_POLY_AND_LOOP_FOREACH_MESH_END;
}
}
@@ -4180,18 +4598,12 @@ static void extract_fdots_uv_finish(const MeshRenderData *UNUSED(mr),
}
static const MeshExtract extract_fdots_uv = {
- extract_fdots_uv_init,
- NULL,
- NULL,
- extract_fdots_uv_loop_bmesh,
- extract_fdots_uv_loop_mesh,
- NULL,
- NULL,
- NULL,
- NULL,
- extract_fdots_uv_finish,
- 0,
- true,
+ .init = extract_fdots_uv_init,
+ .iter_poly_bm = extract_fdots_uv_iter_poly_bm,
+ .iter_poly_mesh = extract_fdots_uv_iter_poly_mesh,
+ .finish = extract_fdots_uv_finish,
+ .data_flag = 0,
+ .use_threading = true,
};
/** \} */
@@ -4220,31 +4632,35 @@ static void *extract_fdots_edituv_data_init(const MeshRenderData *mr, void *buf)
return data;
}
-static void extract_fdots_edituv_data_loop_bmesh(const MeshRenderData *mr,
- int UNUSED(l),
- BMLoop *loop,
- void *_data)
+static void extract_fdots_edituv_data_iter_poly_bm(const MeshRenderData *mr,
+ const ExtractPolyBMesh_Params *params,
+ void *_data)
{
- MeshExtract_EditUVFdotData_Data *data = (MeshExtract_EditUVFdotData_Data *)_data;
- EditLoopData *eldata = data->vbo_data + BM_elem_index_get(loop->f);
- memset(eldata, 0x0, sizeof(*eldata));
- mesh_render_data_face_flag(mr, loop->f, data->cd_ofs, eldata);
+ MeshExtract_EditUVFdotData_Data *data = _data;
+ EXTRACT_POLY_FOREACH_BM_BEGIN(f, f_index, params, mr)
+ {
+ EditLoopData *eldata = &data->vbo_data[BM_elem_index_get(f)];
+ memset(eldata, 0x0, sizeof(*eldata));
+ mesh_render_data_face_flag(mr, f, data->cd_ofs, eldata);
+ }
+ EXTRACT_POLY_FOREACH_BM_END;
}
-static void extract_fdots_edituv_data_loop_mesh(const MeshRenderData *mr,
- int UNUSED(l),
- const MLoop *UNUSED(mloop),
- int p,
- const MPoly *UNUSED(mpoly),
- void *_data)
+static void extract_fdots_edituv_data_iter_poly_mesh(const MeshRenderData *mr,
+ const ExtractPolyMesh_Params *params,
+ void *_data)
{
- MeshExtract_EditUVFdotData_Data *data = (MeshExtract_EditUVFdotData_Data *)_data;
- EditLoopData *eldata = data->vbo_data + p;
- memset(eldata, 0x0, sizeof(*eldata));
- BMFace *efa = bm_original_face_get(mr, p);
- if (efa) {
- mesh_render_data_face_flag(mr, efa, data->cd_ofs, eldata);
+ MeshExtract_EditUVFdotData_Data *data = _data;
+ EXTRACT_POLY_FOREACH_MESH_BEGIN(mp, mp_index, params, mr)
+ {
+ EditLoopData *eldata = &data->vbo_data[mp_index];
+ memset(eldata, 0x0, sizeof(*eldata));
+ BMFace *efa = bm_original_face_get(mr, mp_index);
+ if (efa) {
+ mesh_render_data_face_flag(mr, efa, data->cd_ofs, eldata);
+ }
}
+ EXTRACT_POLY_FOREACH_MESH_END;
}
static void extract_fdots_edituv_data_finish(const MeshRenderData *UNUSED(mr),
@@ -4255,18 +4671,12 @@ static void extract_fdots_edituv_data_finish(const MeshRenderData *UNUSED(mr),
}
static const MeshExtract extract_fdots_edituv_data = {
- extract_fdots_edituv_data_init,
- NULL,
- NULL,
- extract_fdots_edituv_data_loop_bmesh,
- extract_fdots_edituv_data_loop_mesh,
- NULL,
- NULL,
- NULL,
- NULL,
- extract_fdots_edituv_data_finish,
- 0,
- true,
+ .init = extract_fdots_edituv_data_init,
+ .iter_poly_bm = extract_fdots_edituv_data_iter_poly_bm,
+ .iter_poly_mesh = extract_fdots_edituv_data_iter_poly_mesh,
+ .finish = extract_fdots_edituv_data_finish,
+ .data_flag = 0,
+ .use_threading = true,
};
/** \} */
@@ -4317,18 +4727,9 @@ static void *extract_skin_roots_init(const MeshRenderData *mr, void *buf)
}
static const MeshExtract extract_skin_roots = {
- extract_skin_roots_init,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- 0,
- false,
+ .init = extract_skin_roots_init,
+ .data_flag = 0,
+ .use_threading = false,
};
/** \} */
@@ -4350,157 +4751,183 @@ static void *extract_select_idx_init(const MeshRenderData *mr, void *buf)
return vbo->data;
}
-/* TODO Use glVertexID to get loop index and use the data structure on the CPU to retrieve the
+/* TODO Use #glVertexID to get loop index and use the data structure on the CPU to retrieve the
* select element associated with this loop ID. This would remove the need for this separate
- * index VBOs. We could upload the p/e/v_origindex as a buffer texture and sample it inside the
+ * index VBO's. We could upload the p/e/v_origindex as a buffer texture and sample it inside the
* shader to output original index. */
-static void extract_poly_idx_loop_bmesh(const MeshRenderData *UNUSED(mr),
- int l,
- BMLoop *loop,
- void *data)
+static void extract_poly_idx_iter_poly_bm(const MeshRenderData *mr,
+ const ExtractPolyBMesh_Params *params,
+ void *data)
{
- ((uint32_t *)data)[l] = BM_elem_index_get(loop->f);
+ EXTRACT_POLY_AND_LOOP_FOREACH_BM_BEGIN(l, l_index, params, mr)
+ {
+ ((uint32_t *)data)[l_index] = BM_elem_index_get(l->f);
+ }
+ EXTRACT_POLY_AND_LOOP_FOREACH_BM_END(l);
}
-static void extract_edge_idx_loop_bmesh(const MeshRenderData *UNUSED(mr),
- int l,
- BMLoop *loop,
- void *data)
+static void extract_edge_idx_iter_poly_bm(const MeshRenderData *mr,
+ const ExtractPolyBMesh_Params *params,
+ void *data)
{
- ((uint32_t *)data)[l] = BM_elem_index_get(loop->e);
+ EXTRACT_POLY_AND_LOOP_FOREACH_BM_BEGIN(l, l_index, params, mr)
+ {
+ ((uint32_t *)data)[l_index] = BM_elem_index_get(l->e);
+ }
+ EXTRACT_POLY_AND_LOOP_FOREACH_BM_END(l);
}
-static void extract_vert_idx_loop_bmesh(const MeshRenderData *UNUSED(mr),
- int l,
- BMLoop *loop,
- void *data)
+static void extract_vert_idx_iter_poly_bm(const MeshRenderData *mr,
+ const ExtractPolyBMesh_Params *params,
+ void *data)
{
- ((uint32_t *)data)[l] = BM_elem_index_get(loop->v);
+ EXTRACT_POLY_AND_LOOP_FOREACH_BM_BEGIN(l, l_index, params, mr)
+ {
+ ((uint32_t *)data)[l_index] = BM_elem_index_get(l->v);
+ }
+ EXTRACT_POLY_AND_LOOP_FOREACH_BM_END(l);
}
-static void extract_edge_idx_ledge_bmesh(const MeshRenderData *mr, int e, BMEdge *eed, void *data)
+static void extract_edge_idx_iter_ledge_bm(const MeshRenderData *mr,
+ const ExtractLEdgeBMesh_Params *params,
+ void *data)
{
- ((uint32_t *)data)[mr->loop_len + e * 2 + 0] = BM_elem_index_get(eed);
- ((uint32_t *)data)[mr->loop_len + e * 2 + 1] = BM_elem_index_get(eed);
+ EXTRACT_LEDGE_FOREACH_BM_BEGIN(eed, ledge_index, params)
+ {
+ ((uint32_t *)data)[mr->loop_len + ledge_index * 2 + 0] = BM_elem_index_get(eed);
+ ((uint32_t *)data)[mr->loop_len + ledge_index * 2 + 1] = BM_elem_index_get(eed);
+ }
+ EXTRACT_LEDGE_FOREACH_BM_END;
}
-static void extract_vert_idx_ledge_bmesh(const MeshRenderData *mr, int e, BMEdge *eed, void *data)
+static void extract_vert_idx_iter_ledge_bm(const MeshRenderData *mr,
+ const ExtractLEdgeBMesh_Params *params,
+ void *data)
{
- ((uint32_t *)data)[mr->loop_len + e * 2 + 0] = BM_elem_index_get(eed->v1);
- ((uint32_t *)data)[mr->loop_len + e * 2 + 1] = BM_elem_index_get(eed->v2);
+ EXTRACT_LEDGE_FOREACH_BM_BEGIN(eed, ledge_index, params)
+ {
+ ((uint32_t *)data)[mr->loop_len + ledge_index * 2 + 0] = BM_elem_index_get(eed->v1);
+ ((uint32_t *)data)[mr->loop_len + ledge_index * 2 + 1] = BM_elem_index_get(eed->v2);
+ }
+ EXTRACT_LEDGE_FOREACH_BM_END;
}
-static void extract_vert_idx_lvert_bmesh(const MeshRenderData *mr, int v, BMVert *eve, void *data)
+static void extract_vert_idx_iter_lvert_bm(const MeshRenderData *mr,
+ const ExtractLVertBMesh_Params *params,
+ void *data)
{
- ((uint32_t *)data)[mr->loop_len + mr->edge_loose_len * 2 + v] = BM_elem_index_get(eve);
+ const int offset = mr->loop_len + (mr->edge_loose_len * 2);
+ EXTRACT_LVERT_FOREACH_BM_BEGIN(eve, lvert_index, params)
+ {
+ ((uint32_t *)data)[offset + lvert_index] = BM_elem_index_get(eve);
+ }
+ EXTRACT_LVERT_FOREACH_BM_END;
}
-static void extract_poly_idx_loop_mesh(const MeshRenderData *mr,
- int l,
- const MLoop *UNUSED(mloop),
- int p,
- const MPoly *UNUSED(mpoly),
- void *data)
+static void extract_poly_idx_iter_poly_mesh(const MeshRenderData *mr,
+ const ExtractPolyMesh_Params *params,
+ void *data)
{
- ((uint32_t *)data)[l] = (mr->p_origindex) ? mr->p_origindex[p] : p;
+ EXTRACT_POLY_AND_LOOP_FOREACH_MESH_BEGIN(mp, mp_index, ml, ml_index, params, mr)
+ {
+ ((uint32_t *)data)[ml_index] = (mr->p_origindex) ? mr->p_origindex[mp_index] : mp_index;
+ }
+ EXTRACT_POLY_AND_LOOP_FOREACH_MESH_END;
}
-static void extract_edge_idx_loop_mesh(const MeshRenderData *mr,
- int l,
- const MLoop *mloop,
- int UNUSED(p),
- const MPoly *UNUSED(mpoly),
- void *data)
+static void extract_edge_idx_iter_poly_mesh(const MeshRenderData *mr,
+ const ExtractPolyMesh_Params *params,
+ void *data)
{
- ((uint32_t *)data)[l] = (mr->e_origindex) ? mr->e_origindex[mloop->e] : mloop->e;
+ EXTRACT_POLY_AND_LOOP_FOREACH_MESH_BEGIN(mp, mp_index, ml, ml_index, params, mr)
+ {
+ ((uint32_t *)data)[ml_index] = (mr->e_origindex) ? mr->e_origindex[ml->e] : ml->e;
+ }
+ EXTRACT_POLY_AND_LOOP_FOREACH_MESH_END;
}
-static void extract_vert_idx_loop_mesh(const MeshRenderData *mr,
- int l,
- const MLoop *mloop,
- int UNUSED(p),
- const MPoly *UNUSED(mpoly),
- void *data)
+static void extract_vert_idx_iter_poly_mesh(const MeshRenderData *mr,
+ const ExtractPolyMesh_Params *params,
+ void *data)
{
- ((uint32_t *)data)[l] = (mr->v_origindex) ? mr->v_origindex[mloop->v] : mloop->v;
+ EXTRACT_POLY_AND_LOOP_FOREACH_MESH_BEGIN(mp, mp_index, ml, ml_index, params, mr)
+ {
+ ((uint32_t *)data)[ml_index] = (mr->v_origindex) ? mr->v_origindex[ml->v] : ml->v;
+ }
+ EXTRACT_POLY_AND_LOOP_FOREACH_MESH_END;
}
-static void extract_edge_idx_ledge_mesh(const MeshRenderData *mr,
- int e,
- const MEdge *UNUSED(medge),
- void *data)
+static void extract_edge_idx_iter_ledge_mesh(const MeshRenderData *mr,
+ const ExtractLEdgeMesh_Params *params,
+ void *data)
{
- int e_idx = mr->ledges[e];
- int e_orig = (mr->e_origindex) ? mr->e_origindex[e_idx] : e_idx;
- ((uint32_t *)data)[mr->loop_len + e * 2 + 0] = e_orig;
- ((uint32_t *)data)[mr->loop_len + e * 2 + 1] = e_orig;
+ EXTRACT_LEDGE_FOREACH_MESH_BEGIN(med, ledge_index, params, mr)
+ {
+ const int e_index = mr->ledges[ledge_index];
+ const int e_orig = (mr->e_origindex) ? mr->e_origindex[e_index] : e_index;
+ ((uint32_t *)data)[mr->loop_len + ledge_index * 2 + 0] = e_orig;
+ ((uint32_t *)data)[mr->loop_len + ledge_index * 2 + 1] = e_orig;
+ }
+ EXTRACT_LEDGE_FOREACH_MESH_END;
}
-static void extract_vert_idx_ledge_mesh(const MeshRenderData *mr,
- int e,
- const MEdge *medge,
- void *data)
+static void extract_vert_idx_iter_ledge_mesh(const MeshRenderData *mr,
+ const ExtractLEdgeMesh_Params *params,
+ void *data)
{
- int v1_orig = (mr->v_origindex) ? mr->v_origindex[medge->v1] : medge->v1;
- int v2_orig = (mr->v_origindex) ? mr->v_origindex[medge->v2] : medge->v2;
- ((uint32_t *)data)[mr->loop_len + e * 2 + 0] = v1_orig;
- ((uint32_t *)data)[mr->loop_len + e * 2 + 1] = v2_orig;
+ EXTRACT_LEDGE_FOREACH_MESH_BEGIN(med, ledge_index, params, mr)
+ {
+ int v1_orig = (mr->v_origindex) ? mr->v_origindex[med->v1] : med->v1;
+ int v2_orig = (mr->v_origindex) ? mr->v_origindex[med->v2] : med->v2;
+ ((uint32_t *)data)[mr->loop_len + ledge_index * 2 + 0] = v1_orig;
+ ((uint32_t *)data)[mr->loop_len + ledge_index * 2 + 1] = v2_orig;
+ }
+ EXTRACT_LEDGE_FOREACH_MESH_END;
}
-static void extract_vert_idx_lvert_mesh(const MeshRenderData *mr,
- int v,
- const MVert *UNUSED(mvert),
- void *data)
+static void extract_vert_idx_iter_lvert_mesh(const MeshRenderData *mr,
+ const ExtractLVertMesh_Params *params,
+ void *data)
{
- int v_idx = mr->lverts[v];
- int v_orig = (mr->v_origindex) ? mr->v_origindex[v_idx] : v_idx;
- ((uint32_t *)data)[mr->loop_len + mr->edge_loose_len * 2 + v] = v_orig;
+ const int offset = mr->loop_len + (mr->edge_loose_len * 2);
+ EXTRACT_LVERT_FOREACH_MESH_BEGIN(med, lvert_index, params, mr)
+ {
+ const int v_index = mr->lverts[lvert_index];
+ const int v_orig = (mr->v_origindex) ? mr->v_origindex[v_index] : v_index;
+ ((uint32_t *)data)[offset + lvert_index] = v_orig;
+ }
+ EXTRACT_LVERT_FOREACH_MESH_END;
}
static const MeshExtract extract_poly_idx = {
- extract_select_idx_init,
- NULL,
- NULL,
- extract_poly_idx_loop_bmesh,
- extract_poly_idx_loop_mesh,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- 0,
- true,
+ .init = extract_select_idx_init,
+ .iter_poly_bm = extract_poly_idx_iter_poly_bm,
+ .iter_poly_mesh = extract_poly_idx_iter_poly_mesh,
+ .data_flag = 0,
+ .use_threading = true,
};
static const MeshExtract extract_edge_idx = {
- extract_select_idx_init,
- NULL,
- NULL,
- extract_edge_idx_loop_bmesh,
- extract_edge_idx_loop_mesh,
- extract_edge_idx_ledge_bmesh,
- extract_edge_idx_ledge_mesh,
- NULL,
- NULL,
- NULL,
- 0,
- true,
+ .init = extract_select_idx_init,
+ .iter_poly_bm = extract_edge_idx_iter_poly_bm,
+ .iter_poly_mesh = extract_edge_idx_iter_poly_mesh,
+ .iter_ledge_bm = extract_edge_idx_iter_ledge_bm,
+ .iter_ledge_mesh = extract_edge_idx_iter_ledge_mesh,
+ .data_flag = 0,
+ .use_threading = true,
};
static const MeshExtract extract_vert_idx = {
- extract_select_idx_init,
- NULL,
- NULL,
- extract_vert_idx_loop_bmesh,
- extract_vert_idx_loop_mesh,
- extract_vert_idx_ledge_bmesh,
- extract_vert_idx_ledge_mesh,
- extract_vert_idx_lvert_bmesh,
- extract_vert_idx_lvert_mesh,
- NULL,
- 0,
- true,
+ .init = extract_select_idx_init,
+ .iter_poly_bm = extract_vert_idx_iter_poly_bm,
+ .iter_poly_mesh = extract_vert_idx_iter_poly_mesh,
+ .iter_ledge_bm = extract_vert_idx_iter_ledge_bm,
+ .iter_ledge_mesh = extract_vert_idx_iter_ledge_mesh,
+ .iter_lvert_bm = extract_vert_idx_iter_lvert_bm,
+ .iter_lvert_mesh = extract_vert_idx_iter_lvert_mesh,
+ .data_flag = 0,
+ .use_threading = true,
};
static void *extract_select_fdot_idx_init(const MeshRenderData *mr, void *buf)
@@ -4516,37 +4943,43 @@ static void *extract_select_fdot_idx_init(const MeshRenderData *mr, void *buf)
return vbo->data;
}
-static void extract_fdot_idx_loop_bmesh(const MeshRenderData *UNUSED(mr),
- int UNUSED(l),
- BMLoop *loop,
- void *data)
+static void extract_fdot_idx_iter_poly_bm(const MeshRenderData *mr,
+ const ExtractPolyBMesh_Params *params,
+ void *data)
{
- ((uint32_t *)data)[BM_elem_index_get(loop->f)] = BM_elem_index_get(loop->f);
+ EXTRACT_POLY_FOREACH_BM_BEGIN(f, f_index, params, mr)
+ {
+ ((uint32_t *)data)[f_index] = f_index;
+ }
+ EXTRACT_POLY_FOREACH_BM_END;
}
-static void extract_fdot_idx_loop_mesh(const MeshRenderData *mr,
- int UNUSED(l),
- const MLoop *UNUSED(mloop),
- int p,
- const MPoly *UNUSED(mpoly),
- void *data)
+static void extract_fdot_idx_iter_poly_mesh(const MeshRenderData *mr,
+ const ExtractPolyMesh_Params *params,
+ void *data)
{
- ((uint32_t *)data)[p] = (mr->p_origindex) ? mr->p_origindex[p] : p;
+ if (mr->p_origindex != NULL) {
+ EXTRACT_POLY_FOREACH_MESH_BEGIN(mp, mp_index, params, mr)
+ {
+ ((uint32_t *)data)[mp_index] = mr->p_origindex[mp_index];
+ }
+ EXTRACT_POLY_FOREACH_MESH_END;
+ }
+ else {
+ EXTRACT_POLY_FOREACH_MESH_BEGIN(mp, mp_index, params, mr)
+ {
+ ((uint32_t *)data)[mp_index] = mp_index;
+ }
+ EXTRACT_POLY_FOREACH_MESH_END;
+ }
}
static const MeshExtract extract_fdot_idx = {
- extract_select_fdot_idx_init,
- NULL,
- NULL,
- extract_fdot_idx_loop_bmesh,
- extract_fdot_idx_loop_mesh,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- 0,
- true,
+ .init = extract_select_fdot_idx_init,
+ .iter_poly_bm = extract_fdot_idx_iter_poly_bm,
+ .iter_poly_mesh = extract_fdot_idx_iter_poly_mesh,
+ .data_flag = 0,
+ .use_threading = true,
};
/** \} */
@@ -4589,9 +5022,9 @@ static ExtractTaskData *extract_task_data_create_mesh_extract(const MeshRenderDa
taskdata->extract = extract;
taskdata->buf = buf;
- /* ExtractUserData is shared between the iterations as it holds counters to detect if the
- * extraction is finished. To make sure the duplication of the userdata does not create a new
- * instance of the counters we allocate the userdata in its own container.
+ /* #ExtractUserData is shared between the iterations as it holds counters to detect if the
+ * extraction is finished. To make sure the duplication of the user_data does not create a new
+ * instance of the counters we allocate the user_data in its own container.
*
* This structure makes sure that when extract_init is called, that the user data of all
* iterations are updated. */
@@ -4628,67 +5061,69 @@ BLI_INLINE void mesh_extract_iter(const MeshRenderData *mr,
switch (mr->extract_type) {
case MR_EXTRACT_BMESH:
if (iter_type & MR_ITER_LOOPTRI) {
- int t_end = min_ii(mr->tri_len, end);
- for (int t = start; t < t_end; t++) {
- BMLoop **elt = &mr->edit_bmesh->looptris[t][0];
- extract->iter_looptri_bm(mr, t, elt, user_data);
- }
+ extract->iter_looptri_bm(mr,
+ &(const ExtractTriBMesh_Params){
+ .looptris = mr->edit_bmesh->looptris,
+ .tri_range = {start, min_ii(mr->tri_len, end)},
+ },
+ user_data);
}
- if (iter_type & MR_ITER_LOOP) {
- int l_end = min_ii(mr->poly_len, end);
- for (int f = start; f < l_end; f++) {
- BMFace *efa = BM_face_at_index(mr->bm, f);
- BMLoop *loop;
- BMIter l_iter;
- BM_ITER_ELEM (loop, &l_iter, efa, BM_LOOPS_OF_FACE) {
- extract->iter_loop_bm(mr, BM_elem_index_get(loop), loop, user_data);
- }
- }
+ if (iter_type & MR_ITER_POLY) {
+ extract->iter_poly_bm(mr,
+ &(const ExtractPolyBMesh_Params){
+ .poly_range = {start, min_ii(mr->poly_len, end)},
+ },
+ user_data);
}
if (iter_type & MR_ITER_LEDGE) {
- int le_end = min_ii(mr->edge_loose_len, end);
- for (int e = start; e < le_end; e++) {
- BMEdge *eed = BM_edge_at_index(mr->bm, mr->ledges[e]);
- extract->iter_ledge_bm(mr, e, eed, user_data);
- }
+ extract->iter_ledge_bm(mr,
+ &(const ExtractLEdgeBMesh_Params){
+ .ledge = mr->ledges,
+ .ledge_range = {start, min_ii(mr->edge_loose_len, end)},
+ },
+ user_data);
}
if (iter_type & MR_ITER_LVERT) {
- int lv_end = min_ii(mr->vert_loose_len, end);
- for (int v = start; v < lv_end; v++) {
- BMVert *eve = BM_vert_at_index(mr->bm, mr->lverts[v]);
- extract->iter_lvert_bm(mr, v, eve, user_data);
- }
+ extract->iter_lvert_bm(mr,
+ &(const ExtractLVertBMesh_Params){
+ .lvert = mr->lverts,
+ .lvert_range = {start, min_ii(mr->vert_loose_len, end)},
+ },
+ user_data);
}
break;
case MR_EXTRACT_MAPPED:
case MR_EXTRACT_MESH:
if (iter_type & MR_ITER_LOOPTRI) {
- int t_end = min_ii(mr->tri_len, end);
- for (int t = start; t < t_end; t++) {
- extract->iter_looptri(mr, t, &mr->mlooptri[t], user_data);
- }
+ extract->iter_looptri_mesh(mr,
+ &(const ExtractTriMesh_Params){
+ .mlooptri = mr->mlooptri,
+ .tri_range = {start, min_ii(mr->tri_len, end)},
+ },
+ user_data);
}
- if (iter_type & MR_ITER_LOOP) {
- int l_end = min_ii(mr->poly_len, end);
- for (int p = start; p < l_end; p++) {
- const MPoly *mpoly = &mr->mpoly[p];
- int l = mpoly->loopstart;
- for (int i = 0; i < mpoly->totloop; i++, l++) {
- extract->iter_loop(mr, l, &mr->mloop[l], p, mpoly, user_data);
- }
- }
+ if (iter_type & MR_ITER_POLY) {
+ extract->iter_poly_mesh(mr,
+ &(const ExtractPolyMesh_Params){
+ .poly_range = {start, min_ii(mr->poly_len, end)},
+ },
+ user_data);
}
if (iter_type & MR_ITER_LEDGE) {
- int le_end = min_ii(mr->edge_loose_len, end);
- for (int e = start; e < le_end; e++) {
- extract->iter_ledge(mr, e, &mr->medge[mr->ledges[e]], user_data);
- }
+ extract->iter_ledge_mesh(mr,
+ &(const ExtractLEdgeMesh_Params){
+ .ledge = mr->ledges,
+ .ledge_range = {start, min_ii(mr->edge_loose_len, end)},
+ },
+ user_data);
}
if (iter_type & MR_ITER_LVERT) {
- int lv_end = min_ii(mr->vert_loose_len, end);
- for (int v = start; v < lv_end; v++) {
- extract->iter_lvert(mr, v, &mr->mvert[mr->lverts[v]], user_data);
- }
+ extract->iter_lvert_mesh(mr,
+ &(const ExtractLVertMesh_Params){
+ .lvert = mr->lverts,
+ .lvert_range = {start, min_ii(mr->vert_loose_len, end)},
+ },
+ user_data);
}
break;
}
@@ -4915,10 +5350,10 @@ static void extract_task_create(struct TaskGraph *task_graph,
task_graph, task_node_user_data_init, taskdata, MR_ITER_LOOPTRI, i, chunk_size);
}
}
- if (taskdata->iter_type & MR_ITER_LOOP) {
+ if (taskdata->iter_type & MR_ITER_POLY) {
for (int i = 0; i < mr->poly_len; i += chunk_size) {
extract_range_task_create(
- task_graph, task_node_user_data_init, taskdata, MR_ITER_LOOP, i, chunk_size);
+ task_graph, task_node_user_data_init, taskdata, MR_ITER_POLY, i, chunk_size);
}
}
if (taskdata->iter_type & MR_ITER_LEDGE) {
@@ -4973,9 +5408,9 @@ void mesh_buffer_cache_create_requested(struct TaskGraph *task_graph,
* `extract_single_threaded_task_node`.
*
* Other extractions will create a node for each loop exceeding 8192 items. these nodes are
- * linked to the `user_data_init_task_node`. the `user_data_init_task_node` prepares the userdata
- * needed for the extraction based on the data extracted from the mesh. counters are used to
- * check if the finalize of a task has to be called.
+ * linked to the `user_data_init_task_node`. the `user_data_init_task_node` prepares the
+ * user_data needed for the extraction based on the data extracted from the mesh.
+ * counters are used to check if the finalize of a task has to be called.
*
* Mesh extraction sub graph
*
diff --git a/source/blender/draw/intern/draw_cache_impl.h b/source/blender/draw/intern/draw_cache_impl.h
index 191d75342d0..5cf1c24af0b 100644
--- a/source/blender/draw/intern/draw_cache_impl.h
+++ b/source/blender/draw/intern/draw_cache_impl.h
@@ -170,6 +170,7 @@ struct GPUBatch **DRW_mesh_batch_cache_get_surface_shaded(struct Mesh *me,
struct GPUBatch **DRW_mesh_batch_cache_get_surface_texpaint(struct Mesh *me);
struct GPUBatch *DRW_mesh_batch_cache_get_surface_texpaint_single(struct Mesh *me);
struct GPUBatch *DRW_mesh_batch_cache_get_surface_vertpaint(struct Mesh *me);
+struct GPUBatch *DRW_mesh_batch_cache_get_surface_sculpt(struct Mesh *me);
struct GPUBatch *DRW_mesh_batch_cache_get_surface_weights(struct Mesh *me);
/* edit-mesh drawing */
struct GPUBatch *DRW_mesh_batch_cache_get_edit_triangles(struct Mesh *me);
@@ -199,6 +200,11 @@ struct GPUBatch *DRW_mesh_batch_cache_get_edituv_facedots(struct Mesh *me);
struct GPUBatch *DRW_mesh_batch_cache_get_uv_edges(struct Mesh *me);
struct GPUBatch *DRW_mesh_batch_cache_get_edit_mesh_analysis(struct Mesh *me);
+/* For direct data access. */
+struct GPUVertBuf *DRW_mesh_batch_cache_pos_vertbuf_get(struct Mesh *me);
+struct GPUVertBuf *DRW_curve_batch_cache_pos_vertbuf_get(struct Curve *cu);
+struct GPUVertBuf *DRW_mball_batch_cache_pos_vertbuf_get(struct Object *ob);
+
int DRW_mesh_material_count_get(struct Mesh *me);
/* See 'common_globals_lib.glsl' for duplicate defines. */
diff --git a/source/blender/draw/intern/draw_cache_impl_curve.c b/source/blender/draw/intern/draw_cache_impl_curve.c
index 8798549a416..73e0ff7ef83 100644
--- a/source/blender/draw/intern/draw_cache_impl_curve.c
+++ b/source/blender/draw/intern/draw_cache_impl_curve.c
@@ -903,6 +903,16 @@ GPUBatch **DRW_curve_batch_cache_get_surface_shaded(struct Curve *cu,
return cache->surf_per_mat;
}
+GPUVertBuf *DRW_curve_batch_cache_pos_vertbuf_get(struct Curve *cu)
+{
+ CurveBatchCache *cache = curve_batch_cache_get(cu);
+ /* Request surface to trigger the vbo filling. Otherwise it may do nothing. */
+ DRW_batch_request(&cache->batch.surfaces);
+
+ DRW_vbo_request(NULL, &cache->ordered.loop_pos_nor);
+ return cache->ordered.loop_pos_nor;
+}
+
GPUBatch *DRW_curve_batch_cache_get_wireframes_face(Curve *cu)
{
CurveBatchCache *cache = curve_batch_cache_get(cu);
diff --git a/source/blender/draw/intern/draw_cache_impl_gpencil.c b/source/blender/draw/intern/draw_cache_impl_gpencil.c
index b4974330043..53e04fb61ee 100644
--- a/source/blender/draw/intern/draw_cache_impl_gpencil.c
+++ b/source/blender/draw/intern/draw_cache_impl_gpencil.c
@@ -349,10 +349,10 @@ static void gpencil_stroke_iter_cb(bGPDlayer *UNUSED(gpl),
}
}
-static void gp_object_verts_count_cb(bGPDlayer *UNUSED(gpl),
- bGPDframe *UNUSED(gpf),
- bGPDstroke *gps,
- void *thunk)
+static void gpencil_object_verts_count_cb(bGPDlayer *UNUSED(gpl),
+ bGPDframe *UNUSED(gpf),
+ bGPDstroke *gps,
+ void *thunk)
{
gpIterData *iter = (gpIterData *)thunk;
@@ -387,7 +387,7 @@ static void gpencil_batches_ensure(Object *ob, GpencilBatchCache *cache, int cfr
.tri_len = 0,
};
BKE_gpencil_visible_stroke_iter(
- NULL, ob, NULL, gp_object_verts_count_cb, &iter, do_onion, cfra);
+ NULL, ob, NULL, gpencil_object_verts_count_cb, &iter, do_onion, cfra);
/* Create VBOs. */
GPUVertFormat *format = gpencil_stroke_format();
@@ -441,10 +441,10 @@ GPUBatch *DRW_cache_gpencil_fills_get(Object *ob, int cfra)
return cache->fill_batch;
}
-static void gp_lines_indices_cb(bGPDlayer *UNUSED(gpl),
- bGPDframe *UNUSED(gpf),
- bGPDstroke *gps,
- void *thunk)
+static void gpencil_lines_indices_cb(bGPDlayer *UNUSED(gpl),
+ bGPDframe *UNUSED(gpf),
+ bGPDstroke *gps,
+ void *thunk)
{
gpIterData *iter = (gpIterData *)thunk;
int pts_len = gps->totpoints + gpencil_stroke_is_cyclic(gps);
@@ -477,7 +477,8 @@ GPUBatch *DRW_cache_gpencil_face_wireframe_get(Object *ob)
/* IMPORTANT: Keep in sync with gpencil_edit_batches_ensure() */
bool do_onion = true;
- BKE_gpencil_visible_stroke_iter(NULL, ob, NULL, gp_lines_indices_cb, &iter, do_onion, cfra);
+ BKE_gpencil_visible_stroke_iter(
+ NULL, ob, NULL, gpencil_lines_indices_cb, &iter, do_onion, cfra);
GPUIndexBuf *ibo = GPU_indexbuf_build(&iter.ibo);
diff --git a/source/blender/draw/intern/draw_cache_impl_mesh.c b/source/blender/draw/intern/draw_cache_impl_mesh.c
index 99e285a18f1..ea1717f0684 100644
--- a/source/blender/draw/intern/draw_cache_impl_mesh.c
+++ b/source/blender/draw/intern/draw_cache_impl_mesh.c
@@ -112,6 +112,21 @@ BLI_INLINE const CustomData *mesh_cd_ldata_get_from_mesh(const Mesh *me)
return &me->ldata;
}
+BLI_INLINE const CustomData *mesh_cd_vdata_get_from_mesh(const Mesh *me)
+{
+ switch ((eMeshWrapperType)me->runtime.wrapper_type) {
+ case ME_WRAPPER_TYPE_MDATA:
+ return &me->vdata;
+ break;
+ case ME_WRAPPER_TYPE_BMESH:
+ return &me->edit_mesh->bm->vdata;
+ break;
+ }
+
+ BLI_assert(0);
+ return &me->vdata;
+}
+
static void mesh_cd_calc_active_uv_layer(const Mesh *me, DRW_MeshCDMask *cd_used)
{
const Mesh *me_final = (me->edit_mesh) ? me->edit_mesh->mesh_eval_final : me;
@@ -135,7 +150,19 @@ static void mesh_cd_calc_active_mask_uv_layer(const Mesh *me, DRW_MeshCDMask *cd
static void mesh_cd_calc_active_vcol_layer(const Mesh *me, DRW_MeshCDMask *cd_used)
{
const Mesh *me_final = (me->edit_mesh) ? me->edit_mesh->mesh_eval_final : me;
- const CustomData *cd_ldata = mesh_cd_ldata_get_from_mesh(me_final);
+ const CustomData *cd_vdata = mesh_cd_vdata_get_from_mesh(me_final);
+
+ int layer = CustomData_get_active_layer(cd_vdata, CD_PROP_COLOR);
+ if (layer != -1) {
+ cd_used->sculpt_vcol |= (1 << layer);
+ }
+}
+
+static void mesh_cd_calc_active_mloopcol_layer(const Mesh *me, DRW_MeshCDMask *cd_used)
+{
+ const Mesh *me_final = (me->edit_mesh) ? me->edit_mesh->mesh_eval_final : me;
+ const CustomData *cd_ldata = &me_final->ldata;
+
int layer = CustomData_get_active_layer(cd_ldata, CD_MLOOPCOL);
if (layer != -1) {
cd_used->vcol |= (1 << layer);
@@ -148,6 +175,7 @@ static DRW_MeshCDMask mesh_cd_calc_used_gpu_layers(const Mesh *me,
{
const Mesh *me_final = (me->edit_mesh) ? me->edit_mesh->mesh_eval_final : me;
const CustomData *cd_ldata = mesh_cd_ldata_get_from_mesh(me_final);
+ const CustomData *cd_vdata = mesh_cd_vdata_get_from_mesh(me_final);
/* See: DM_vertex_attributes_from_gpu for similar logic */
DRW_MeshCDMask cd_used;
@@ -175,6 +203,11 @@ static DRW_MeshCDMask mesh_cd_calc_used_gpu_layers(const Mesh *me,
layer = CustomData_get_named_layer(cd_ldata, CD_MLOOPCOL, name);
type = CD_MCOL;
}
+
+ if (layer == -1) {
+ layer = CustomData_get_named_layer(cd_vdata, CD_PROP_COLOR, name);
+ type = CD_PROP_COLOR;
+ }
#if 0 /* Tangents are always from UV's - this will never happen. */
if (layer == -1) {
layer = CustomData_get_named_layer(cd_ldata, CD_TANGENT, name);
@@ -222,7 +255,20 @@ static DRW_MeshCDMask mesh_cd_calc_used_gpu_layers(const Mesh *me,
}
break;
}
+ case CD_PROP_COLOR: {
+ /* Sculpt Vertex Colors */
+ if (layer == -1) {
+ layer = (name[0] != '\0') ?
+ CustomData_get_named_layer(cd_vdata, CD_PROP_COLOR, name) :
+ CustomData_get_render_layer(cd_vdata, CD_PROP_COLOR);
+ }
+ if (layer != -1) {
+ cd_used.sculpt_vcol |= (1 << layer);
+ }
+ break;
+ }
case CD_MCOL: {
+ /* Vertex Color Data */
if (layer == -1) {
layer = (name[0] != '\0') ? CustomData_get_named_layer(cd_ldata, CD_MLOOPCOL, name) :
CustomData_get_render_layer(cd_ldata, CD_MLOOPCOL);
@@ -230,6 +276,7 @@ static DRW_MeshCDMask mesh_cd_calc_used_gpu_layers(const Mesh *me,
if (layer != -1) {
cd_used.vcol |= (1 << layer);
}
+
break;
}
case CD_ORCO: {
@@ -679,10 +726,22 @@ static void texpaint_request_active_vcol(MeshBatchCache *cache, Mesh *me)
{
DRW_MeshCDMask cd_needed;
mesh_cd_layers_type_clear(&cd_needed);
- mesh_cd_calc_active_vcol_layer(me, &cd_needed);
+ mesh_cd_calc_active_mloopcol_layer(me, &cd_needed);
BLI_assert(cd_needed.vcol != 0 &&
- "No vcol layer available in vertpaint, but batches requested anyway!");
+ "No MLOOPCOL layer available in vertpaint, but batches requested anyway!");
+
+ mesh_cd_layers_type_merge(&cache->cd_needed, cd_needed);
+}
+
+static void sculpt_request_active_vcol(MeshBatchCache *cache, Mesh *me)
+{
+ DRW_MeshCDMask cd_needed;
+ mesh_cd_layers_type_clear(&cd_needed);
+ mesh_cd_calc_active_vcol_layer(me, &cd_needed);
+
+ BLI_assert(cd_needed.sculpt_vcol != 0 &&
+ "No MPropCol layer available in Sculpt, but batches requested anyway!");
mesh_cd_layers_type_merge(&cache->cd_needed, cd_needed);
}
@@ -799,6 +858,14 @@ GPUBatch *DRW_mesh_batch_cache_get_surface_vertpaint(Mesh *me)
return DRW_batch_request(&cache->batch.surface);
}
+GPUBatch *DRW_mesh_batch_cache_get_surface_sculpt(Mesh *me)
+{
+ MeshBatchCache *cache = mesh_batch_cache_get(me);
+ sculpt_request_active_vcol(cache, me);
+ mesh_batch_cache_add_request(cache, MBC_SURFACE);
+ return DRW_batch_request(&cache->batch.surface);
+}
+
int DRW_mesh_material_count_get(Mesh *me)
{
return mesh_render_mat_len_get(me);
@@ -810,6 +877,23 @@ int DRW_mesh_material_count_get(Mesh *me)
/** \name Edit Mode API
* \{ */
+GPUVertBuf *DRW_mesh_batch_cache_pos_vertbuf_get(Mesh *me)
+{
+ MeshBatchCache *cache = mesh_batch_cache_get(me);
+ /* Request surface to trigger the vbo filling. Otherwise it may do nothing. */
+ mesh_batch_cache_add_request(cache, MBC_SURFACE);
+ DRW_batch_request(&cache->batch.surface);
+
+ DRW_vbo_request(NULL, &cache->final.vbo.pos_nor);
+ return cache->final.vbo.pos_nor;
+}
+
+/** \} */
+
+/* ---------------------------------------------------------------------- */
+/** \name Edit Mode API
+ * \{ */
+
GPUBatch *DRW_mesh_batch_cache_get_edit_triangles(Mesh *me)
{
MeshBatchCache *cache = mesh_batch_cache_get(me);
@@ -1120,7 +1204,9 @@ void DRW_mesh_batch_cache_create_requested(struct TaskGraph *task_graph,
if (cache->cd_used.orco != cache->cd_needed.orco) {
GPU_VERTBUF_DISCARD_SAFE(mbuffercache->vbo.orco);
}
- if ((cache->cd_used.vcol & cache->cd_needed.vcol) != cache->cd_needed.vcol) {
+ if (((cache->cd_used.vcol & cache->cd_needed.vcol) != cache->cd_needed.vcol) ||
+ ((cache->cd_used.sculpt_vcol & cache->cd_needed.sculpt_vcol) !=
+ cache->cd_needed.sculpt_vcol)) {
GPU_VERTBUF_DISCARD_SAFE(mbuffercache->vbo.vcol);
}
}
@@ -1201,7 +1287,7 @@ void DRW_mesh_batch_cache_create_requested(struct TaskGraph *task_graph,
if (cache->cd_used.uv != 0) {
DRW_vbo_request(cache->batch.surface, &mbufcache->vbo.uv);
}
- if (cache->cd_used.vcol != 0) {
+ if (cache->cd_used.vcol != 0 || cache->cd_used.sculpt_vcol != 0) {
DRW_vbo_request(cache->batch.surface, &mbufcache->vbo.vcol);
}
}
@@ -1269,7 +1355,7 @@ void DRW_mesh_batch_cache_create_requested(struct TaskGraph *task_graph,
if ((cache->cd_used.tan != 0) || (cache->cd_used.tan_orco != 0)) {
DRW_vbo_request(cache->surface_per_mat[i], &mbufcache->vbo.tan);
}
- if (cache->cd_used.vcol != 0) {
+ if (cache->cd_used.vcol != 0 || cache->cd_used.sculpt_vcol != 0) {
DRW_vbo_request(cache->surface_per_mat[i], &mbufcache->vbo.vcol);
}
if (cache->cd_used.orco != 0) {
diff --git a/source/blender/draw/intern/draw_cache_impl_metaball.c b/source/blender/draw/intern/draw_cache_impl_metaball.c
index c14e66c2b47..076d32ffe1f 100644
--- a/source/blender/draw/intern/draw_cache_impl_metaball.c
+++ b/source/blender/draw/intern/draw_cache_impl_metaball.c
@@ -274,6 +274,18 @@ struct GPUBatch *DRW_metaball_batch_cache_get_edge_detection(struct Object *ob,
return cache->edge_detection;
}
+struct GPUVertBuf *DRW_mball_batch_cache_pos_vertbuf_get(Object *ob)
+{
+ if (!BKE_mball_is_basis(ob)) {
+ return NULL;
+ }
+
+ MetaBall *mb = ob->data;
+ MetaBallBatchCache *cache = metaball_batch_cache_get(mb);
+
+ return mball_batch_cache_get_pos_and_normals(ob, cache);
+}
+
int DRW_metaball_material_count_get(MetaBall *mb)
{
return max_ii(1, mb->totcol);
diff --git a/source/blender/draw/intern/draw_cache_inline.h b/source/blender/draw/intern/draw_cache_inline.h
index a067434f3bb..67f44b5fb0c 100644
--- a/source/blender/draw/intern/draw_cache_inline.h
+++ b/source/blender/draw/intern/draw_cache_inline.h
@@ -90,17 +90,19 @@ BLI_INLINE void DRW_vbo_request(GPUBatch *batch, GPUVertBuf **vbo)
if (*vbo == NULL) {
*vbo = MEM_callocN(sizeof(GPUVertBuf), "GPUVertBuf");
}
- /* HACK set first vbo if not init. */
- if (batch->verts[0] == NULL) {
- GPU_batch_vao_cache_clear(batch);
- batch->verts[0] = *vbo;
- }
- else {
- /* HACK: bypass assert */
- int vbo_vert_len = (*vbo)->vertex_len;
- (*vbo)->vertex_len = batch->verts[0]->vertex_len;
- GPU_batch_vertbuf_add(batch, *vbo);
- (*vbo)->vertex_len = vbo_vert_len;
+ if (batch != NULL) {
+ /* HACK set first vbo if not init. */
+ if (batch->verts[0] == NULL) {
+ GPU_batch_vao_cache_clear(batch);
+ batch->verts[0] = *vbo;
+ }
+ else {
+ /* HACK: bypass assert */
+ int vbo_vert_len = (*vbo)->vertex_len;
+ (*vbo)->vertex_len = batch->verts[0]->vertex_len;
+ GPU_batch_vertbuf_add(batch, *vbo);
+ (*vbo)->vertex_len = vbo_vert_len;
+ }
}
}
diff --git a/source/blender/draw/intern/draw_common.h b/source/blender/draw/intern/draw_common.h
index 656d72b2808..81c0e97a1a8 100644
--- a/source/blender/draw/intern/draw_common.h
+++ b/source/blender/draw/intern/draw_common.h
@@ -176,6 +176,13 @@ struct DRWShadingGroup *DRW_shgroup_hair_create_sub(struct Object *object,
struct ParticleSystem *psys,
struct ModifierData *md,
struct DRWShadingGroup *shgrp);
+struct GPUVertBuf *DRW_hair_pos_buffer_get(struct Object *object,
+ struct ParticleSystem *psys,
+ struct ModifierData *md);
+void DRW_hair_duplimat_get(struct Object *object,
+ struct ParticleSystem *psys,
+ struct ModifierData *md,
+ float (*dupli_mat)[4]);
void DRW_hair_init(void);
void DRW_hair_update(void);
diff --git a/source/blender/draw/intern/draw_hair.c b/source/blender/draw/intern/draw_hair.c
index 2fdaf0d5345..6cfba0e2a78 100644
--- a/source/blender/draw/intern/draw_hair.c
+++ b/source/blender/draw/intern/draw_hair.c
@@ -124,32 +124,109 @@ void DRW_hair_init(void)
}
}
-DRWShadingGroup *DRW_shgroup_hair_create_sub(Object *object,
- ParticleSystem *psys,
- ModifierData *md,
- DRWShadingGroup *shgrp_parent)
+static ParticleHairCache *drw_hair_particle_cache_get(
+ Object *object, ParticleSystem *psys, ModifierData *md, int subdiv, int thickness_res)
+{
+ bool update;
+ ParticleHairCache *cache;
+ if (psys) {
+ /* Old particle hair. */
+ update = particles_ensure_procedural_data(object, psys, md, &cache, subdiv, thickness_res);
+ }
+ else {
+ /* New hair object. */
+ update = hair_ensure_procedural_data(object, &cache, subdiv, thickness_res);
+ }
+
+ if (update) {
+ int final_points_len = cache->final[subdiv].strands_res * cache->strands_len;
+ if (final_points_len > 0) {
+ GPUShader *tf_shader = hair_refine_shader_get(PART_REFINE_CATMULL_ROM);
+
+#ifdef USE_TRANSFORM_FEEDBACK
+ DRWShadingGroup *tf_shgrp = DRW_shgroup_transform_feedback_create(
+ tf_shader, g_tf_pass, cache->final[subdiv].proc_buf);
+#else
+ DRWShadingGroup *tf_shgrp = DRW_shgroup_create(tf_shader, g_tf_pass);
+
+ ParticleRefineCall *pr_call = MEM_mallocN(sizeof(*pr_call), __func__);
+ pr_call->next = g_tf_calls;
+ pr_call->vbo = cache->final[subdiv].proc_buf;
+ pr_call->shgrp = tf_shgrp;
+ pr_call->vert_len = final_points_len;
+ g_tf_calls = pr_call;
+ DRW_shgroup_uniform_int(tf_shgrp, "targetHeight", &g_tf_target_height, 1);
+ DRW_shgroup_uniform_int(tf_shgrp, "targetWidth", &g_tf_target_width, 1);
+ DRW_shgroup_uniform_int(tf_shgrp, "idOffset", &g_tf_id_offset, 1);
+#endif
+
+ DRW_shgroup_uniform_texture(tf_shgrp, "hairPointBuffer", cache->point_tex);
+ DRW_shgroup_uniform_texture(tf_shgrp, "hairStrandBuffer", cache->strand_tex);
+ DRW_shgroup_uniform_texture(tf_shgrp, "hairStrandSegBuffer", cache->strand_seg_tex);
+ DRW_shgroup_uniform_int(tf_shgrp, "hairStrandsRes", &cache->final[subdiv].strands_res, 1);
+ DRW_shgroup_call_procedural_points(tf_shgrp, NULL, final_points_len);
+ }
+ }
+ return cache;
+}
+
+/* Note: Only valid after DRW_hair_update(). */
+GPUVertBuf *DRW_hair_pos_buffer_get(Object *object, ParticleSystem *psys, ModifierData *md)
{
- /* TODO(fclem): Pass the scene as parameter */
const DRWContextState *draw_ctx = DRW_context_state_get();
Scene *scene = draw_ctx->scene;
- float dupli_mat[4][4];
- Object *dupli_parent = DRW_object_get_dupli_parent(object);
- DupliObject *dupli_object = DRW_object_get_dupli(object);
int subdiv = scene->r.hair_subdiv;
int thickness_res = (scene->r.hair_type == SCE_HAIR_SHAPE_STRAND) ? 1 : 2;
- ParticleHairCache *hair_cache;
- bool need_ft_update;
+ ParticleHairCache *cache = drw_hair_particle_cache_get(object, psys, md, subdiv, thickness_res);
+
+ return cache->final[subdiv].proc_buf;
+}
+
+void DRW_hair_duplimat_get(Object *object,
+ ParticleSystem *psys,
+ ModifierData *UNUSED(md),
+ float (*dupli_mat)[4])
+{
+ Object *dupli_parent = DRW_object_get_dupli_parent(object);
+ DupliObject *dupli_object = DRW_object_get_dupli(object);
+
if (psys) {
- /* Old particle hair. */
- need_ft_update = particles_ensure_procedural_data(
- object, psys, md, &hair_cache, subdiv, thickness_res);
+ if ((dupli_parent != NULL) && (dupli_object != NULL)) {
+ if (dupli_object->type & OB_DUPLICOLLECTION) {
+ copy_m4_m4(dupli_mat, dupli_parent->obmat);
+ }
+ else {
+ copy_m4_m4(dupli_mat, dupli_object->ob->obmat);
+ invert_m4(dupli_mat);
+ mul_m4_m4m4(dupli_mat, object->obmat, dupli_mat);
+ }
+ }
+ else {
+ unit_m4(dupli_mat);
+ }
}
else {
/* New hair object. */
- need_ft_update = hair_ensure_procedural_data(object, &hair_cache, subdiv, thickness_res);
+ copy_m4_m4(dupli_mat, object->obmat);
}
+}
+
+DRWShadingGroup *DRW_shgroup_hair_create_sub(Object *object,
+ ParticleSystem *psys,
+ ModifierData *md,
+ DRWShadingGroup *shgrp_parent)
+{
+ const DRWContextState *draw_ctx = DRW_context_state_get();
+ Scene *scene = draw_ctx->scene;
+ float dupli_mat[4][4];
+
+ int subdiv = scene->r.hair_subdiv;
+ int thickness_res = (scene->r.hair_type == SCE_HAIR_SHAPE_STRAND) ? 1 : 2;
+
+ ParticleHairCache *hair_cache = drw_hair_particle_cache_get(
+ object, psys, md, subdiv, thickness_res);
DRWShadingGroup *shgrp = DRW_shgroup_create_sub(shgrp_parent);
@@ -177,25 +254,7 @@ DRWShadingGroup *DRW_shgroup_hair_create_sub(Object *object,
DRW_shgroup_uniform_texture(shgrp, "ac", g_dummy_texture);
}
- if (psys) {
- if ((dupli_parent != NULL) && (dupli_object != NULL)) {
- if (dupli_object->type & OB_DUPLICOLLECTION) {
- copy_m4_m4(dupli_mat, dupli_parent->obmat);
- }
- else {
- copy_m4_m4(dupli_mat, dupli_object->ob->obmat);
- invert_m4(dupli_mat);
- mul_m4_m4m4(dupli_mat, object->obmat, dupli_mat);
- }
- }
- else {
- unit_m4(dupli_mat);
- }
- }
- else {
- /* New hair object. */
- copy_m4_m4(dupli_mat, object->obmat);
- }
+ DRW_hair_duplimat_get(object, psys, md, dupli_mat);
/* Get hair shape parameters. */
float hair_rad_shape, hair_rad_root, hair_rad_tip;
@@ -229,38 +288,6 @@ DRWShadingGroup *DRW_shgroup_hair_create_sub(Object *object,
GPUBatch *geom = hair_cache->final[subdiv].proc_hairs[thickness_res - 1];
DRW_shgroup_call_no_cull(shgrp, geom, object);
- /* Transform Feedback subdiv. */
- if (need_ft_update) {
- int final_points_len = hair_cache->final[subdiv].strands_res * hair_cache->strands_len;
- if (final_points_len) {
- GPUShader *tf_shader = hair_refine_shader_get(PART_REFINE_CATMULL_ROM);
-
-#ifdef USE_TRANSFORM_FEEDBACK
- DRWShadingGroup *tf_shgrp = DRW_shgroup_transform_feedback_create(
- tf_shader, g_tf_pass, hair_cache->final[subdiv].proc_buf);
-#else
- DRWShadingGroup *tf_shgrp = DRW_shgroup_create(tf_shader, g_tf_pass);
-
- ParticleRefineCall *pr_call = MEM_mallocN(sizeof(*pr_call), __func__);
- pr_call->next = g_tf_calls;
- pr_call->vbo = hair_cache->final[subdiv].proc_buf;
- pr_call->shgrp = tf_shgrp;
- pr_call->vert_len = final_points_len;
- g_tf_calls = pr_call;
- DRW_shgroup_uniform_int(tf_shgrp, "targetHeight", &g_tf_target_height, 1);
- DRW_shgroup_uniform_int(tf_shgrp, "targetWidth", &g_tf_target_width, 1);
- DRW_shgroup_uniform_int(tf_shgrp, "idOffset", &g_tf_id_offset, 1);
-#endif
-
- DRW_shgroup_uniform_texture(tf_shgrp, "hairPointBuffer", hair_cache->point_tex);
- DRW_shgroup_uniform_texture(tf_shgrp, "hairStrandBuffer", hair_cache->strand_tex);
- DRW_shgroup_uniform_texture(tf_shgrp, "hairStrandSegBuffer", hair_cache->strand_seg_tex);
- DRW_shgroup_uniform_int(
- tf_shgrp, "hairStrandsRes", &hair_cache->final[subdiv].strands_res, 1);
- DRW_shgroup_call_procedural_points(tf_shgrp, NULL, final_points_len);
- }
- }
-
return shgrp;
}
diff --git a/source/blender/draw/intern/draw_manager.c b/source/blender/draw/intern/draw_manager.c
index 10ef8d9c4c8..3e42c4cdb23 100644
--- a/source/blender/draw/intern/draw_manager.c
+++ b/source/blender/draw/intern/draw_manager.c
@@ -373,6 +373,8 @@ void DRW_render_viewport_size_set(int size[2])
{
DST.size[0] = size[0];
DST.size[1] = size[1];
+ DST.inv_size[0] = 1.0f / size[0];
+ DST.inv_size[1] = 1.0f / size[1];
}
const float *DRW_viewport_size_get(void)
@@ -1635,13 +1637,6 @@ bool DRW_render_check_grease_pencil(Depsgraph *depsgraph)
return false;
}
-static void drw_view_reset(void)
-{
- DST.view_default = NULL;
- DST.view_active = NULL;
- DST.view_previous = NULL;
-}
-
static void DRW_render_gpencil_to_image(RenderEngine *engine,
struct RenderLayer *render_layer,
const rcti *rect)
@@ -1719,7 +1714,7 @@ void DRW_render_gpencil(struct RenderEngine *engine, struct Depsgraph *depsgraph
for (RenderView *render_view = render_result->views.first; render_view != NULL;
render_view = render_view->next) {
RE_SetActiveRenderView(render, render_view->name);
- drw_view_reset();
+ DRW_view_reset();
DST.buffer_finish_called = false;
DRW_render_gpencil_to_image(engine, render_layer, &render_rect);
}
@@ -1827,7 +1822,7 @@ void DRW_render_to_image(RenderEngine *engine, struct Depsgraph *depsgraph)
for (RenderView *render_view = render_result->views.first; render_view != NULL;
render_view = render_view->next) {
RE_SetActiveRenderView(render, render_view->name);
- drw_view_reset();
+ DRW_view_reset();
engine_type->draw_engine->render_to_image(data, engine, render_layer, &render_rect);
DST.buffer_finish_called = false;
}
@@ -1949,6 +1944,28 @@ void DRW_custom_pipeline(DrawEngineType *draw_engine_type,
#endif
}
+/* Used when the render engine want to redo another cache populate inside the same render frame. */
+void DRW_cache_restart(void)
+{
+ /* Save viewport size. */
+ float size[2], inv_size[2];
+ copy_v2_v2(size, DST.size);
+ copy_v2_v2(inv_size, DST.inv_size);
+
+ /* Force cache to reset. */
+ drw_viewport_cache_resize();
+
+ drw_viewport_var_init();
+
+ DST.buffer_finish_called = false;
+
+ DRW_hair_init();
+
+ /* Restore. */
+ copy_v2_v2(DST.size, size);
+ copy_v2_v2(DST.inv_size, inv_size);
+}
+
static struct DRWSelectBuffer {
struct GPUFrameBuffer *framebuffer_depth_only;
struct GPUTexture *texture_depth;
@@ -2374,6 +2391,17 @@ void DRW_draw_depth_loop_gpencil(struct Depsgraph *depsgraph,
void DRW_draw_select_id(Depsgraph *depsgraph, ARegion *region, View3D *v3d, const rcti *rect)
{
+ SELECTID_Context *sel_ctx = DRW_select_engine_context_get();
+ GPUViewport *viewport = WM_draw_region_get_viewport(region);
+ if (!viewport) {
+ /* Selection engine requires a viewport.
+ * TODO (germano): This should be done internally in the engine. */
+ sel_ctx->is_dirty = true;
+ sel_ctx->objects_drawn_len = 0;
+ sel_ctx->index_drawn_len = 1;
+ return;
+ }
+
Scene *scene = DEG_get_evaluated_scene(depsgraph);
ViewLayer *view_layer = DEG_get_evaluated_view_layer(depsgraph);
@@ -2394,14 +2422,13 @@ void DRW_draw_select_id(Depsgraph *depsgraph, ARegion *region, View3D *v3d, cons
drw_context_state_init();
/* Setup viewport */
- DST.viewport = WM_draw_region_get_viewport(region);
+ DST.viewport = viewport;
drw_viewport_var_init();
/* Update ubos */
DRW_globals_update();
/* Init Select Engine */
- struct SELECTID_Context *sel_ctx = DRW_select_engine_context_get();
sel_ctx->last_rect = *rect;
use_drw_engine(&draw_engine_select_type);
diff --git a/source/blender/draw/intern/draw_manager_data.c b/source/blender/draw/intern/draw_manager_data.c
index 07fb97236fb..3d83b918757 100644
--- a/source/blender/draw/intern/draw_manager_data.c
+++ b/source/blender/draw/intern/draw_manager_data.c
@@ -76,7 +76,7 @@ static void draw_call_sort(DRWCommand *array, DRWCommand *array_tmp, int array_l
for (int i = 1; i < ARRAY_SIZE(idx); i++) {
idx[i] += idx[i - 1];
}
- /* Traverse in reverse to not change the order of the resource ids. */
+ /* Traverse in reverse to not change the order of the resource ID's. */
for (int src = array_len - 1; src >= 0; src--) {
array_tmp[--idx[KEY(array[src])]] = array[src];
}
@@ -116,7 +116,7 @@ void drw_resource_buffer_finish(ViewportMemoryPool *vmempool)
vmempool->ubo_len = ubo_len;
}
- /* Remove unecessary buffers */
+ /* Remove unnecessary buffers */
for (int i = ubo_len; i < vmempool->ubo_len; i++) {
GPU_uniformbuffer_free(vmempool->matrices_ubo[i]);
GPU_uniformbuffer_free(vmempool->obinfos_ubo[i]);
@@ -151,7 +151,7 @@ void drw_resource_buffer_finish(ViewportMemoryPool *vmempool)
BLI_memblock_iternew(vmempool->commands, &iter);
while ((chunk = BLI_memblock_iterstep(&iter))) {
bool sortable = true;
- /* We can only sort chunks that contain DRWCommandDraw only. */
+ /* We can only sort chunks that contain #DRWCommandDraw only. */
for (int i = 0; i < ARRAY_SIZE(chunk->command_type) && sortable; i++) {
if (chunk->command_type[i] != 0) {
sortable = false;
@@ -179,7 +179,7 @@ static void drw_shgroup_uniform_create_ex(DRWShadingGroup *shgroup,
int arraysize)
{
if (loc == -1) {
- /* Nice to enable eventually, for now eevee uses uniforms that might not exist. */
+ /* Nice to enable eventually, for now EEVEE uses uniforms that might not exist. */
// BLI_assert(0);
return;
}
@@ -262,11 +262,19 @@ void DRW_shgroup_uniform_texture(DRWShadingGroup *shgroup, const char *name, con
DRW_shgroup_uniform_texture_ex(shgroup, name, tex, GPU_SAMPLER_MAX);
}
-void DRW_shgroup_uniform_texture_ref(DRWShadingGroup *shgroup, const char *name, GPUTexture **tex)
+void DRW_shgroup_uniform_texture_ref_ex(DRWShadingGroup *shgroup,
+ const char *name,
+ GPUTexture **tex,
+ eGPUSamplerState sampler_state)
{
BLI_assert(tex != NULL);
int loc = GPU_shader_get_texture_binding(shgroup->shader, name);
- drw_shgroup_uniform_create_ex(shgroup, loc, DRW_UNIFORM_TEXTURE_REF, tex, GPU_SAMPLER_MAX, 0, 1);
+ drw_shgroup_uniform_create_ex(shgroup, loc, DRW_UNIFORM_TEXTURE_REF, tex, sampler_state, 0, 1);
+}
+
+void DRW_shgroup_uniform_texture_ref(DRWShadingGroup *shgroup, const char *name, GPUTexture **tex)
+{
+ DRW_shgroup_uniform_texture_ref_ex(shgroup, name, tex, GPU_SAMPLER_MAX);
}
void DRW_shgroup_uniform_block(DRWShadingGroup *shgroup,
@@ -424,7 +432,7 @@ void DRW_shgroup_uniform_vec4_array_copy(DRWShadingGroup *shgroup,
int location = GPU_shader_get_uniform(shgroup->shader, name);
if (location == -1) {
- /* Nice to enable eventually, for now eevee uses uniforms that might not exist. */
+ /* Nice to enable eventually, for now EEVEE uses uniforms that might not exist. */
// BLI_assert(0);
return;
}
@@ -530,6 +538,11 @@ static void drw_call_culling_init(DRWCullingState *cull, Object *ob)
mul_v3_m4v3(corner, ob->obmat, bbox->vec[0]);
mul_m4_v3(ob->obmat, cull->bsphere.center);
cull->bsphere.radius = len_v3v3(cull->bsphere.center, corner);
+
+ /* Bypass test for very large objects (see T67319). */
+ if (UNLIKELY(cull->bsphere.radius > 1e12)) {
+ cull->bsphere.radius = -1.0f;
+ }
}
else {
/* Bypass test. */
@@ -569,7 +582,7 @@ uint32_t DRW_object_resource_id_get(Object *UNUSED(ob))
/* Handle not yet allocated. Return next handle. */
handle = DST.resource_handle;
}
- return handle;
+ return handle & ~(1 << 31);
}
static DRWResourceHandle drw_resource_handle(DRWShadingGroup *shgroup,
@@ -1786,6 +1799,14 @@ const DRWView *DRW_view_default_get(void)
return DST.view_default;
}
+/* WARNING: Only use in render AND only if you are going to set view_default again. */
+void DRW_view_reset(void)
+{
+ DST.view_default = NULL;
+ DST.view_active = NULL;
+ DST.view_previous = NULL;
+}
+
/* MUST only be called once per render and only in render mode. Sets default view. */
void DRW_view_default_set(DRWView *view)
{
diff --git a/source/blender/draw/intern/draw_select_buffer.c b/source/blender/draw/intern/draw_select_buffer.c
index 81c9f400f6e..558d5441136 100644
--- a/source/blender/draw/intern/draw_select_buffer.c
+++ b/source/blender/draw/intern/draw_select_buffer.c
@@ -122,7 +122,6 @@ uint *DRW_select_buffer_read(struct Depsgraph *depsgraph,
/**
* \param rect: The rectangle to sample indices from (min/max inclusive).
- * \param mask: Specifies the rect pixels (optional).
* \returns a #BLI_bitmap the length of \a bitmap_len or NULL on failure.
*/
uint *DRW_select_buffer_bitmap_from_rect(struct Depsgraph *depsgraph,
@@ -165,10 +164,10 @@ uint *DRW_select_buffer_bitmap_from_rect(struct Depsgraph *depsgraph,
}
/**
- * \param bitmap_len: Number of indices in the selection id buffer.
* \param center: Circle center.
* \param radius: Circle radius.
- * \returns a #BLI_bitmap the length of \a bitmap_len or NULL on failure.
+ * \param r_bitmap_len: Number of indices in the selection id buffer.
+ * \returns a #BLI_bitmap the length of \a r_bitmap_len or NULL on failure.
*/
uint *DRW_select_buffer_bitmap_from_circle(struct Depsgraph *depsgraph,
struct ARegion *region,
@@ -338,7 +337,7 @@ uint DRW_select_buffer_sample_point(struct Depsgraph *depsgraph,
/**
* Find the selection id closest to \a center.
- * \param dist[in,out]: Use to initialize the distance,
+ * \param dist: Use to initialize the distance,
* when found, this value is set to the distance of the selection that's returned.
*/
uint DRW_select_buffer_find_nearest_to_point(struct Depsgraph *depsgraph,