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:
authorLukas Toenne <lukas.toenne@gmail.com>2018-12-18 13:58:54 +0300
committerLukas Toenne <lukas.toenne@gmail.com>2018-12-18 13:58:54 +0300
commitfdca73fd4aea4a1a0a2e37b8ccc82951cfb08ca2 (patch)
treec6c6492d1c33522e4b088f2cd44076e6e4de54de /source/blender/draw
parentb62f226cac06431aa17eb692b47de0dd58cf68ad (diff)
parentd3e1b043c37398ac1e1027a6004239dee8a055f0 (diff)
Merge branch 'blender2.8' into hair_object
Diffstat (limited to 'source/blender/draw')
-rw-r--r--source/blender/draw/CMakeLists.txt7
-rw-r--r--source/blender/draw/engines/eevee/eevee_effects.c8
-rw-r--r--source/blender/draw/engines/eevee/eevee_lightcache.c2
-rw-r--r--source/blender/draw/engines/eevee/eevee_lookdev.c4
-rw-r--r--source/blender/draw/engines/eevee/eevee_materials.c6
-rw-r--r--source/blender/draw/engines/eevee/eevee_occlusion.c8
-rw-r--r--source/blender/draw/engines/eevee/shaders/ambient_occlusion_lib.glsl17
-rw-r--r--source/blender/draw/engines/gpencil/gpencil_cache_utils.c10
-rw-r--r--source/blender/draw/engines/gpencil/gpencil_draw_cache_impl.c94
-rw-r--r--source/blender/draw/engines/gpencil/gpencil_draw_utils.c285
-rw-r--r--source/blender/draw/engines/gpencil/gpencil_engine.c256
-rw-r--r--source/blender/draw/engines/gpencil/gpencil_engine.h35
-rw-r--r--source/blender/draw/engines/gpencil/gpencil_render.c2
-rw-r--r--source/blender/draw/engines/gpencil/gpencil_shader_fx.c9
-rw-r--r--source/blender/draw/engines/gpencil/shaders/gpencil_blend_frag.glsl155
-rw-r--r--source/blender/draw/engines/gpencil/shaders/gpencil_stroke_geom.glsl20
-rw-r--r--source/blender/draw/engines/workbench/shaders/workbench_cavity_frag.glsl25
-rw-r--r--source/blender/draw/engines/workbench/shaders/workbench_common_lib.glsl92
-rw-r--r--source/blender/draw/engines/workbench/shaders/workbench_curvature_lib.glsl41
-rw-r--r--source/blender/draw/engines/workbench/shaders/workbench_data_lib.glsl11
-rw-r--r--source/blender/draw/engines/workbench/shaders/workbench_deferred_background_frag.glsl39
-rw-r--r--source/blender/draw/engines/workbench/shaders/workbench_deferred_composite_frag.glsl127
-rw-r--r--source/blender/draw/engines/workbench/shaders/workbench_forward_composite_frag.glsl10
-rw-r--r--source/blender/draw/engines/workbench/shaders/workbench_forward_transparent_accum_frag.glsl48
-rw-r--r--source/blender/draw/engines/workbench/shaders/workbench_prepass_frag.glsl96
-rw-r--r--source/blender/draw/engines/workbench/shaders/workbench_prepass_vert.glsl3
-rw-r--r--source/blender/draw/engines/workbench/shaders/workbench_shadow_geom.glsl25
-rw-r--r--source/blender/draw/engines/workbench/shaders/workbench_world_light_lib.glsl207
-rw-r--r--source/blender/draw/engines/workbench/workbench_data.c57
-rw-r--r--source/blender/draw/engines/workbench/workbench_deferred.c325
-rw-r--r--source/blender/draw/engines/workbench/workbench_effect_taa.c3
-rw-r--r--source/blender/draw/engines/workbench/workbench_engine.c6
-rw-r--r--source/blender/draw/engines/workbench/workbench_engine.h2
-rw-r--r--source/blender/draw/engines/workbench/workbench_forward.c116
-rw-r--r--source/blender/draw/engines/workbench/workbench_materials.c133
-rw-r--r--source/blender/draw/engines/workbench/workbench_private.h62
-rw-r--r--source/blender/draw/engines/workbench/workbench_studiolight.c43
-rw-r--r--source/blender/draw/intern/DRW_render.h12
-rw-r--r--source/blender/draw/intern/draw_armature.c6
-rw-r--r--source/blender/draw/intern/draw_cache.c423
-rw-r--r--source/blender/draw/intern/draw_cache.h43
-rw-r--r--source/blender/draw/intern/draw_cache_impl.h117
-rw-r--r--source/blender/draw/intern/draw_cache_impl_curve.c1125
-rw-r--r--source/blender/draw/intern/draw_cache_impl_displist.c365
-rw-r--r--source/blender/draw/intern/draw_cache_impl_lattice.c2
-rw-r--r--source/blender/draw/intern/draw_cache_impl_mesh.c3823
-rw-r--r--source/blender/draw/intern/draw_cache_impl_metaball.c81
-rw-r--r--source/blender/draw/intern/draw_cache_impl_particles.c210
-rw-r--r--source/blender/draw/intern/draw_common.c50
-rw-r--r--source/blender/draw/intern/draw_common.h1
-rw-r--r--source/blender/draw/intern/draw_hair.c35
-rw-r--r--source/blender/draw/intern/draw_manager.c143
-rw-r--r--source/blender/draw/intern/draw_manager.h4
-rw-r--r--source/blender/draw/intern/draw_manager_data.c6
-rw-r--r--source/blender/draw/intern/draw_manager_exec.c71
-rw-r--r--source/blender/draw/intern/draw_manager_shader.c7
-rw-r--r--source/blender/draw/intern/draw_manager_texture.c3
-rw-r--r--source/blender/draw/intern/draw_view.c12
-rw-r--r--source/blender/draw/modes/edit_curve_mode.c23
-rw-r--r--source/blender/draw/modes/edit_mesh_mode.c150
-rw-r--r--source/blender/draw/modes/edit_mesh_mode_text.c2
-rw-r--r--source/blender/draw/modes/edit_text_mode.c88
-rw-r--r--source/blender/draw/modes/object_mode.c114
-rw-r--r--source/blender/draw/modes/overlay_mode.c207
-rw-r--r--source/blender/draw/modes/paint_texture_mode.c89
-rw-r--r--source/blender/draw/modes/paint_vertex_mode.c20
-rw-r--r--source/blender/draw/modes/paint_weight_mode.c32
-rw-r--r--source/blender/draw/modes/particle_mode.c54
-rw-r--r--source/blender/draw/modes/pose_mode.c4
-rw-r--r--source/blender/draw/modes/shaders/common_fullscreen_vert.glsl2
-rw-r--r--source/blender/draw/modes/shaders/common_globals_lib.glsl1
-rw-r--r--source/blender/draw/modes/shaders/common_hair_lib.glsl5
-rw-r--r--source/blender/draw/modes/shaders/edit_curve_overlay_normals_vert.glsl23
-rw-r--r--source/blender/draw/modes/shaders/edit_mesh_overlay_frag.glsl2
-rw-r--r--source/blender/draw/modes/shaders/edit_mesh_overlay_geom_tri.glsl4
-rw-r--r--source/blender/draw/modes/shaders/edit_mesh_overlay_points_vert.glsl4
-rw-r--r--source/blender/draw/modes/shaders/edit_mesh_overlay_vert.glsl20
-rw-r--r--source/blender/draw/modes/shaders/object_empty_image_vert.glsl1
-rw-r--r--source/blender/draw/modes/shaders/object_grid_vert.glsl4
-rw-r--r--source/blender/draw/modes/shaders/object_loose_points_frag.glsl19
-rw-r--r--source/blender/draw/modes/shaders/overlay_face_wireframe_frag.glsl16
-rw-r--r--source/blender/draw/modes/shaders/overlay_face_wireframe_geom.glsl111
-rw-r--r--source/blender/draw/modes/shaders/overlay_face_wireframe_vert.glsl186
-rw-r--r--source/blender/draw/modes/shaders/paint_face_vert.glsl14
-rw-r--r--source/blender/draw/modes/shaders/paint_texture_vert.glsl5
-rw-r--r--source/blender/draw/modes/shaders/paint_vert_frag.glsl8
-rw-r--r--source/blender/draw/modes/shaders/paint_vertex_vert.glsl4
-rw-r--r--source/blender/draw/modes/shaders/paint_wire_frag.glsl18
-rw-r--r--source/blender/draw/modes/shaders/paint_wire_vert.glsl24
-rw-r--r--source/blender/draw/modes/shaders/particle_strand_frag.glsl23
-rw-r--r--source/blender/draw/modes/shaders/particle_strand_vert.glsl79
91 files changed, 5569 insertions, 4715 deletions
diff --git a/source/blender/draw/CMakeLists.txt b/source/blender/draw/CMakeLists.txt
index 9f2fa378e3c..2671a6e0f0a 100644
--- a/source/blender/draw/CMakeLists.txt
+++ b/source/blender/draw/CMakeLists.txt
@@ -226,6 +226,7 @@ data_to_c_simple(engines/workbench/shaders/workbench_checkerboard_depth_frag.gls
data_to_c_simple(engines/workbench/shaders/workbench_common_lib.glsl SRC)
data_to_c_simple(engines/workbench/shaders/workbench_data_lib.glsl SRC)
data_to_c_simple(engines/workbench/shaders/workbench_deferred_composite_frag.glsl SRC)
+data_to_c_simple(engines/workbench/shaders/workbench_deferred_background_frag.glsl SRC)
data_to_c_simple(engines/workbench/shaders/workbench_effect_fxaa_frag.glsl SRC)
data_to_c_simple(engines/workbench/shaders/workbench_effect_taa_frag.glsl SRC)
data_to_c_simple(engines/workbench/shaders/workbench_forward_composite_frag.glsl SRC)
@@ -233,6 +234,7 @@ data_to_c_simple(engines/workbench/shaders/workbench_forward_depth_frag.glsl SRC
data_to_c_simple(engines/workbench/shaders/workbench_forward_transparent_accum_frag.glsl SRC)
data_to_c_simple(engines/workbench/shaders/workbench_ghost_resolve_frag.glsl SRC)
data_to_c_simple(engines/workbench/shaders/workbench_object_outline_lib.glsl SRC)
+data_to_c_simple(engines/workbench/shaders/workbench_curvature_lib.glsl SRC)
data_to_c_simple(engines/workbench/shaders/workbench_prepass_vert.glsl SRC)
data_to_c_simple(engines/workbench/shaders/workbench_prepass_frag.glsl SRC)
data_to_c_simple(engines/workbench/shaders/workbench_shadow_vert.glsl SRC)
@@ -275,13 +277,13 @@ data_to_c_simple(modes/shaders/edit_mesh_overlay_geom_edge.glsl SRC)
data_to_c_simple(modes/shaders/edit_mesh_overlay_points_vert.glsl SRC)
data_to_c_simple(modes/shaders/edit_mesh_overlay_facedot_frag.glsl SRC)
data_to_c_simple(modes/shaders/edit_mesh_overlay_facedot_vert.glsl SRC)
-data_to_c_simple(modes/shaders/edit_mesh_overlay_ghost_clear_vert.glsl SRC)
data_to_c_simple(modes/shaders/edit_mesh_overlay_mix_frag.glsl SRC)
data_to_c_simple(modes/shaders/edit_mesh_overlay_facefill_vert.glsl SRC)
data_to_c_simple(modes/shaders/edit_mesh_overlay_facefill_frag.glsl SRC)
data_to_c_simple(modes/shaders/edit_curve_overlay_handle_vert.glsl SRC)
data_to_c_simple(modes/shaders/edit_curve_overlay_handle_geom.glsl SRC)
data_to_c_simple(modes/shaders/edit_curve_overlay_loosevert_vert.glsl SRC)
+data_to_c_simple(modes/shaders/edit_curve_overlay_normals_vert.glsl SRC)
data_to_c_simple(modes/shaders/edit_hair_overlay_frag.glsl SRC)
data_to_c_simple(modes/shaders/edit_hair_overlay_loosevert_vert.glsl SRC)
data_to_c_simple(modes/shaders/edit_lattice_overlay_frag.glsl SRC)
@@ -309,12 +311,14 @@ data_to_c_simple(modes/shaders/object_mball_handles_vert.glsl SRC)
data_to_c_simple(modes/shaders/object_particle_prim_vert.glsl SRC)
data_to_c_simple(modes/shaders/object_particle_dot_vert.glsl SRC)
data_to_c_simple(modes/shaders/object_particle_dot_frag.glsl SRC)
+data_to_c_simple(modes/shaders/object_loose_points_frag.glsl SRC)
data_to_c_simple(modes/shaders/paint_texture_frag.glsl SRC)
data_to_c_simple(modes/shaders/paint_texture_vert.glsl SRC)
data_to_c_simple(modes/shaders/paint_vertex_frag.glsl SRC)
data_to_c_simple(modes/shaders/paint_vertex_vert.glsl SRC)
data_to_c_simple(modes/shaders/paint_weight_frag.glsl SRC)
data_to_c_simple(modes/shaders/paint_weight_vert.glsl SRC)
+data_to_c_simple(modes/shaders/paint_face_vert.glsl SRC)
data_to_c_simple(modes/shaders/paint_wire_frag.glsl SRC)
data_to_c_simple(modes/shaders/paint_wire_vert.glsl SRC)
data_to_c_simple(modes/shaders/paint_vert_frag.glsl SRC)
@@ -330,6 +334,7 @@ data_to_c_simple(engines/gpencil/shaders/gpencil_stroke_geom.glsl SRC)
data_to_c_simple(engines/gpencil/shaders/gpencil_stroke_frag.glsl SRC)
data_to_c_simple(engines/gpencil/shaders/gpencil_zdepth_mix_frag.glsl SRC)
data_to_c_simple(engines/gpencil/shaders/gpencil_simple_mix_frag.glsl SRC)
+data_to_c_simple(engines/gpencil/shaders/gpencil_blend_frag.glsl SRC)
data_to_c_simple(engines/gpencil/shaders/gpencil_point_vert.glsl SRC)
data_to_c_simple(engines/gpencil/shaders/gpencil_point_geom.glsl SRC)
data_to_c_simple(engines/gpencil/shaders/gpencil_point_frag.glsl SRC)
diff --git a/source/blender/draw/engines/eevee/eevee_effects.c b/source/blender/draw/engines/eevee/eevee_effects.c
index 48a73ccef18..787957a4a33 100644
--- a/source/blender/draw/engines/eevee/eevee_effects.c
+++ b/source/blender/draw/engines/eevee/eevee_effects.c
@@ -460,10 +460,10 @@ void EEVEE_create_minmax_buffer(EEVEE_Data *vedata, GPUTexture *depth_src, int l
/* Restore */
GPU_framebuffer_bind(fbl->main_fb);
- if (GPU_mip_render_workaround()) {
- /* Fix dot corruption on intel HD5XX/HD6XX series.
- * It seems affected drivers are the same that needs
- * GPU_mip_render_workaround. */
+ if (GPU_mip_render_workaround() ||
+ GPU_type_matches(GPU_DEVICE_INTEL_UHD, GPU_OS_WIN, GPU_DRIVER_ANY))
+ {
+ /* Fix dot corruption on intel HD5XX/HD6XX series. */
GPU_flush();
}
}
diff --git a/source/blender/draw/engines/eevee/eevee_lightcache.c b/source/blender/draw/engines/eevee/eevee_lightcache.c
index 451e7174a94..71082268f10 100644
--- a/source/blender/draw/engines/eevee/eevee_lightcache.c
+++ b/source/blender/draw/engines/eevee/eevee_lightcache.c
@@ -1050,7 +1050,7 @@ void EEVEE_lightbake_update(void *custom_data)
EEVEE_lightcache_info_update(&lbake->scene->eevee);
- DEG_id_tag_update(&scene_orig->id, DEG_TAG_COPY_ON_WRITE);
+ DEG_id_tag_update(&scene_orig->id, ID_RECALC_COPY_ON_WRITE);
}
static bool lightbake_do_sample(EEVEE_LightBake *lbake, void (*render_callback)(void *ved, void *user_data))
diff --git a/source/blender/draw/engines/eevee/eevee_lookdev.c b/source/blender/draw/engines/eevee/eevee_lookdev.c
index e46526ce6af..aa2f480597b 100644
--- a/source/blender/draw/engines/eevee/eevee_lookdev.c
+++ b/source/blender/draw/engines/eevee/eevee_lookdev.c
@@ -62,8 +62,8 @@ void EEVEE_lookdev_cache_init(
const DRWContextState *draw_ctx = DRW_context_state_get();
View3D *v3d = draw_ctx->v3d;
if (LOOK_DEV_STUDIO_LIGHT_ENABLED(v3d)) {
- StudioLight *sl = BKE_studiolight_find(v3d->shading.studio_light, STUDIOLIGHT_ORIENTATIONS_MATERIAL_MODE);
- if (sl && (sl->flag & STUDIOLIGHT_ORIENTATION_WORLD)) {
+ StudioLight *sl = BKE_studiolight_find(v3d->shading.lookdev_light, STUDIOLIGHT_ORIENTATIONS_MATERIAL_MODE);
+ if (sl && (sl->flag & STUDIOLIGHT_TYPE_WORLD)) {
GPUShader *shader = EEVEE_shaders_default_studiolight_sh_get();
struct GPUBatch *geom = DRW_cache_fullscreen_quad_get();
GPUTexture *tex = NULL;
diff --git a/source/blender/draw/engines/eevee/eevee_materials.c b/source/blender/draw/engines/eevee/eevee_materials.c
index bda6c633523..a2ceb2a5190 100644
--- a/source/blender/draw/engines/eevee/eevee_materials.c
+++ b/source/blender/draw/engines/eevee/eevee_materials.c
@@ -1401,7 +1401,7 @@ static void material_transparent(
DRW_shgroup_uniform_float(*shgrp, "roughness", rough_p, 1);
}
- const bool use_prepass = ((ma->blend_flag & MA_BL_HIDE_BACKSIDE) != 0);
+ const bool use_prepass = ((ma->blend_flag & MA_BL_HIDE_BACKFACE) != 0);
DRWState all_state = (
DRW_STATE_WRITE_DEPTH | DRW_STATE_WRITE_COLOR | DRW_STATE_CULL_BACK |
@@ -1655,14 +1655,10 @@ void EEVEE_materials_cache_populate(EEVEE_Data *vedata, EEVEE_ViewLayerData *sld
const bool do_cull = (draw_ctx->v3d && (draw_ctx->v3d->flag2 & V3D_BACKFACE_CULLING));
const bool is_active = (ob == draw_ctx->obact);
const bool is_sculpt_mode = is_active && (draw_ctx->object_mode & OB_MODE_SCULPT) != 0;
-#if 0
- const bool is_sculpt_mode_draw = is_sculpt_mode && (draw_ctx->v3d->flag2 & V3D_SHOW_MODE_SHADE_OVERRIDE) == 0;
-#else
/* For now just force fully shaded with eevee when supported. */
const bool is_sculpt_mode_draw =
is_sculpt_mode &&
((ob->sculpt && ob->sculpt->pbvh) && (BKE_pbvh_type(ob->sculpt->pbvh) != PBVH_FACES));
-#endif
const bool is_default_mode_shader = is_sculpt_mode;
/* First get materials for this mesh. */
diff --git a/source/blender/draw/engines/eevee/eevee_occlusion.c b/source/blender/draw/engines/eevee/eevee_occlusion.c
index 03aee102136..3763e13533d 100644
--- a/source/blender/draw/engines/eevee/eevee_occlusion.c
+++ b/source/blender/draw/engines/eevee/eevee_occlusion.c
@@ -253,10 +253,10 @@ void EEVEE_occlusion_compute(
DRW_draw_pass(psl->ao_horizon_search);
}
- if (GPU_mip_render_workaround()) {
- /* Fix dot corruption on intel HD5XX/HD6XX series.
- * It seems affected drivers are the same that needs
- * GPU_mip_render_workaround. */
+ if (GPU_mip_render_workaround() ||
+ GPU_type_matches(GPU_DEVICE_INTEL_UHD, GPU_OS_WIN, GPU_DRIVER_ANY))
+ {
+ /* Fix dot corruption on intel HD5XX/HD6XX series. */
GPU_flush();
}
diff --git a/source/blender/draw/engines/eevee/shaders/ambient_occlusion_lib.glsl b/source/blender/draw/engines/eevee/shaders/ambient_occlusion_lib.glsl
index 40c6bb1f1e0..4c9d04ff339 100644
--- a/source/blender/draw/engines/eevee/shaders/ambient_occlusion_lib.glsl
+++ b/source/blender/draw/engines/eevee/shaders/ambient_occlusion_lib.glsl
@@ -177,12 +177,11 @@ void integrate_slice(vec3 normal, vec2 t_phi, vec2 horizons, inout float visibil
visibility += vis;
- /* Finding Bent normal */
+ /* O. Klehm, T. Ritschel, E. Eisemann, H.-P. Seidel
+ * Bent Normals and Cones in Screen-space
+ * Sec. 3.1 : Bent normals */
float b_angle = (h.x + h.y) * 0.5;
- /* The 0.5 factor below is here to equilibrate the accumulated vectors.
- * (sin(b_angle) * -t_phi) will accumulate to (phi_step * result_nor.xy * 0.5).
- * (cos(b_angle) * 0.5) will accumulate to (phi_step * result_nor.z * 0.5). */
- bent_normal += vec3(sin(b_angle) * -t_phi, cos(b_angle) * 0.5);
+ bent_normal += vec3(sin(b_angle) * -t_phi, cos(b_angle)) * vis;
}
void gtao_deferred(
@@ -203,9 +202,9 @@ void gtao_deferred(
integrate_slice(normal, dirs.xy, horizons.xy, visibility, bent_normal);
integrate_slice(normal, dirs.zw, horizons.zw, visibility, bent_normal);
- visibility *= 0.5; /* We integrated 2 slices. */
+ bent_normal = normalize(bent_normal / visibility);
- bent_normal = normalize(bent_normal);
+ visibility *= 0.5; /* We integrated 2 slices. */
}
void gtao(vec3 normal, vec3 position, vec4 noise, out float visibility, out vec3 bent_normal)
@@ -222,7 +221,7 @@ void gtao(vec3 normal, vec3 position, vec4 noise, out float visibility, out vec3
vec2 horizons = search_horizon_sweep(dir, position, uvs, noise.y, max_dir);
integrate_slice(normal, dir, horizons, visibility, bent_normal);
- bent_normal = normalize(bent_normal);
+ bent_normal = normalize(bent_normal / visibility);
}
/* Multibounce approximation base on surface albedo.
@@ -261,7 +260,7 @@ float occlusion_compute(vec3 N, vec3 vpos, float user_occlusion, vec4 rand, out
if ((int(aoSettings) & USE_BENT_NORMAL) != 0) {
/* The bent normal will show the facet look of the mesh. Try to minimize this. */
- float mix_fac = visibility * visibility;
+ float mix_fac = visibility * visibility * visibility;
bent_normal = normalize(mix(bent_normal, vnor, mix_fac));
bent_normal = transform_direction(ViewMatrixInverse, bent_normal);
diff --git a/source/blender/draw/engines/gpencil/gpencil_cache_utils.c b/source/blender/draw/engines/gpencil/gpencil_cache_utils.c
index 15ac3f37add..63af8ecc141 100644
--- a/source/blender/draw/engines/gpencil/gpencil_cache_utils.c
+++ b/source/blender/draw/engines/gpencil/gpencil_cache_utils.c
@@ -83,8 +83,12 @@ tGPencilObjectCache *gpencil_object_cache_add(
cache_elem->pixfactor = cache_elem->gpd->pixfactor;
cache_elem->shader_fx = ob_orig->shader_fx;
- cache_elem->init_grp = NULL;
- cache_elem->end_grp = NULL;
+ /* shgrp array */
+ cache_elem->tot_layers = 0;
+ int totgpl = BLI_listbase_count(&cache_elem->gpd->layers);
+ if (totgpl > 0) {
+ cache_elem->shgrp_array = MEM_callocN(sizeof(tGPencilObjectCache_shgrp) * totgpl, __func__);
+ }
/* calculate zdepth from point of view */
float zdepth = 0.0;
@@ -182,7 +186,7 @@ static bool gpencil_batch_cache_valid(GpencilBatchCache *cache, bGPdata *gpd, in
else if (gpd->flag & GP_DATA_CACHE_IS_DIRTY) {
valid = false;
}
- else if (gpd->flag & GP_DATA_SHOW_ONIONSKINS) {
+ else if (DRW_gpencil_onion_active(gpd)) {
/* if onion, set as dirty always
* This reduces performance, but avoid any crash in the multiple
* overlay and multiwindow options and keep all windows working
diff --git a/source/blender/draw/engines/gpencil/gpencil_draw_cache_impl.c b/source/blender/draw/engines/gpencil/gpencil_draw_cache_impl.c
index 6289e76664d..0f37e8824ee 100644
--- a/source/blender/draw/engines/gpencil/gpencil_draw_cache_impl.c
+++ b/source/blender/draw/engines/gpencil/gpencil_draw_cache_impl.c
@@ -245,7 +245,6 @@ GPUBatch *DRW_gpencil_get_buffer_stroke_geom(bGPdata *gpd, short thickness)
{
const DRWContextState *draw_ctx = DRW_context_state_get();
Scene *scene = draw_ctx->scene;
- View3D *v3d = draw_ctx->v3d;
ARegion *ar = draw_ctx->ar;
RegionView3D *rv3d = draw_ctx->rv3d;
ToolSettings *ts = scene->toolsettings;
@@ -253,6 +252,9 @@ GPUBatch *DRW_gpencil_get_buffer_stroke_geom(bGPdata *gpd, short thickness)
tGPspoint *points = gpd->runtime.sbuffer;
int totpoints = gpd->runtime.sbuffer_size;
+ /* if cyclic needs more vertex */
+ int cyclic_add = (gpd->runtime.sbuffer_sflag & GP_STROKE_CYCLIC) ? 1 : 0;
+ int totvertex = totpoints + cyclic_add + 2;
static GPUVertFormat format = { 0 };
static uint pos_id, color_id, thickness_id, uvdata_id;
@@ -264,17 +266,17 @@ GPUBatch *DRW_gpencil_get_buffer_stroke_geom(bGPdata *gpd, short thickness)
}
GPUVertBuf *vbo = GPU_vertbuf_create_with_format(&format);
- GPU_vertbuf_data_alloc(vbo, totpoints + 2);
+ GPU_vertbuf_data_alloc(vbo, totvertex);
/* draw stroke curve */
const tGPspoint *tpt = points;
- bGPDspoint pt, pt2;
+ bGPDspoint pt, pt2, pt3;
int idx = 0;
/* get origin to reproject point */
float origin[3];
bGPDlayer *gpl = BKE_gpencil_layer_getactive(gpd);
- ED_gp_get_drawing_reference(v3d, scene, ob, gpl, ts->gpencil_v3d_align, origin);
+ ED_gp_get_drawing_reference(scene, ob, gpl, ts->gpencil_v3d_align, origin);
for (int i = 0; i < totpoints; i++, tpt++) {
ED_gpencil_tpoint_to_point(ar, origin, tpt, &pt);
@@ -282,19 +284,22 @@ GPUBatch *DRW_gpencil_get_buffer_stroke_geom(bGPdata *gpd, short thickness)
/* first point for adjacency (not drawn) */
if (i == 0) {
- if (totpoints > 1) {
- ED_gpencil_tpoint_to_point(ar, origin, &points[1], &pt2);
+ if (gpd->runtime.sbuffer_sflag & GP_STROKE_CYCLIC && totpoints > 2) {
+ ED_gpencil_tpoint_to_point(ar, origin, &points[totpoints - 1], &pt2);
gpencil_set_stroke_point(
- vbo, &pt2, idx,
- pos_id, color_id, thickness_id, uvdata_id, thickness, gpd->runtime.scolor);
+ vbo, &pt2, idx,
+ pos_id, color_id, thickness_id, uvdata_id, thickness, gpd->runtime.scolor);
+ idx++;
}
else {
+ ED_gpencil_tpoint_to_point(ar, origin, &points[1], &pt2);
gpencil_set_stroke_point(
- vbo, &pt, idx,
- pos_id, color_id, thickness_id, uvdata_id, thickness, gpd->runtime.scolor);
+ vbo, &pt2, idx,
+ pos_id, color_id, thickness_id, uvdata_id, thickness, gpd->runtime.scolor);
+ idx++;
}
- idx++;
}
+
/* set point */
gpencil_set_stroke_point(
vbo, &pt, idx,
@@ -303,16 +308,27 @@ GPUBatch *DRW_gpencil_get_buffer_stroke_geom(bGPdata *gpd, short thickness)
}
/* last adjacency point (not drawn) */
- if (totpoints > 2) {
- ED_gpencil_tpoint_to_point(ar, origin, &points[totpoints - 2], &pt2);
+ if (gpd->runtime.sbuffer_sflag & GP_STROKE_CYCLIC && totpoints > 2) {
+ /* draw line to first point to complete the cycle */
+ ED_gpencil_tpoint_to_point(ar, origin, &points[0], &pt2);
gpencil_set_stroke_point(
- vbo, &pt2, idx,
- pos_id, color_id, thickness_id, uvdata_id, thickness, gpd->runtime.scolor);
+ vbo, &pt2, idx,
+ pos_id, color_id, thickness_id, uvdata_id, thickness, gpd->runtime.scolor);
+ idx++;
+ /* now add adjacency point (not drawn) */
+ ED_gpencil_tpoint_to_point(ar, origin, &points[1], &pt3);
+ gpencil_set_stroke_point(
+ vbo, &pt3, idx,
+ pos_id, color_id, thickness_id, uvdata_id, thickness, gpd->runtime.scolor);
+ idx++;
}
+ /* last adjacency point (not drawn) */
else {
+ ED_gpencil_tpoint_to_point(ar, origin, &points[totpoints - 2], &pt2);
gpencil_set_stroke_point(
- vbo, &pt, idx,
- pos_id, color_id, thickness_id, uvdata_id, thickness, gpd->runtime.scolor);
+ vbo, &pt2, idx,
+ pos_id, color_id, thickness_id, uvdata_id, thickness, gpd->runtime.scolor);
+ idx++;
}
return GPU_batch_create_ex(GPU_PRIM_LINE_STRIP_ADJ, vbo, NULL, GPU_BATCH_OWNS_VBO);
@@ -323,7 +339,6 @@ GPUBatch *DRW_gpencil_get_buffer_point_geom(bGPdata *gpd, short thickness)
{
const DRWContextState *draw_ctx = DRW_context_state_get();
Scene *scene = draw_ctx->scene;
- View3D *v3d = draw_ctx->v3d;
ARegion *ar = draw_ctx->ar;
RegionView3D *rv3d = draw_ctx->rv3d;
ToolSettings *ts = scene->toolsettings;
@@ -352,7 +367,7 @@ GPUBatch *DRW_gpencil_get_buffer_point_geom(bGPdata *gpd, short thickness)
/* get origin to reproject point */
float origin[3];
bGPDlayer *gpl = BKE_gpencil_layer_getactive(gpd);
- ED_gp_get_drawing_reference(v3d, scene, ob, gpl, ts->gpencil_v3d_align, origin);
+ ED_gp_get_drawing_reference(scene, ob, gpl, ts->gpencil_v3d_align, origin);
for (int i = 0; i < totpoints; i++, tpt++) {
ED_gpencil_tpoint_to_point(ar, origin, tpt, &pt);
@@ -369,6 +384,40 @@ GPUBatch *DRW_gpencil_get_buffer_point_geom(bGPdata *gpd, short thickness)
return GPU_batch_create_ex(GPU_PRIM_POINTS, vbo, NULL, GPU_BATCH_OWNS_VBO);
}
+/* create batch geometry data for current buffer control point shader */
+GPUBatch *DRW_gpencil_get_buffer_ctrlpoint_geom(bGPdata *gpd)
+{
+ bGPDcontrolpoint *cps = gpd->runtime.cp_points;
+ int totpoints = gpd->runtime.tot_cp_points;
+
+ static GPUVertFormat format = { 0 };
+ static uint pos_id, color_id, size_id;
+ if (format.attr_len == 0) {
+ pos_id = GPU_vertformat_attr_add(&format, "pos", GPU_COMP_F32, 3, GPU_FETCH_FLOAT);
+ size_id = GPU_vertformat_attr_add(&format, "size", GPU_COMP_F32, 1, GPU_FETCH_FLOAT);
+ color_id = GPU_vertformat_attr_add(&format, "color", GPU_COMP_F32, 4, GPU_FETCH_FLOAT);
+ }
+
+ GPUVertBuf *vbo = GPU_vertbuf_create_with_format(&format);
+ GPU_vertbuf_data_alloc(vbo, totpoints);
+
+ int idx = 0;
+ for (int i = 0; i < gpd->runtime.tot_cp_points; i++) {
+ bGPDcontrolpoint *cp = &cps[i];
+
+ GPU_vertbuf_attr_set(vbo, color_id, idx, cp->color);
+
+ /* scale size */
+ float size = cp->size * 0.8f;
+ GPU_vertbuf_attr_set(vbo, size_id, idx, &size);
+
+ GPU_vertbuf_attr_set(vbo, pos_id, idx, &cp->x);
+ idx++;
+ }
+
+ return GPU_batch_create_ex(GPU_PRIM_POINTS, vbo, NULL, GPU_BATCH_OWNS_VBO);
+}
+
/* create batch geometry data for current buffer fill shader */
GPUBatch *DRW_gpencil_get_buffer_fill_geom(bGPdata *gpd)
{
@@ -384,7 +433,6 @@ GPUBatch *DRW_gpencil_get_buffer_fill_geom(bGPdata *gpd)
const DRWContextState *draw_ctx = DRW_context_state_get();
Scene *scene = draw_ctx->scene;
- View3D *v3d = draw_ctx->v3d;
ARegion *ar = draw_ctx->ar;
ToolSettings *ts = scene->toolsettings;
Object *ob = draw_ctx->obact;
@@ -392,7 +440,7 @@ GPUBatch *DRW_gpencil_get_buffer_fill_geom(bGPdata *gpd)
/* get origin to reproject point */
float origin[3];
bGPDlayer *gpl = BKE_gpencil_layer_getactive(gpd);
- ED_gp_get_drawing_reference(v3d, scene, ob, gpl, ts->gpencil_v3d_align, origin);
+ ED_gp_get_drawing_reference(scene, ob, gpl, ts->gpencil_v3d_align, origin);
int tot_triangles = totpoints - 2;
/* allocate memory for temporary areas */
@@ -455,7 +503,7 @@ void DRW_gpencil_get_edit_geom(struct GpencilBatchCacheElem *be, bGPDstroke *gps
const DRWContextState *draw_ctx = DRW_context_state_get();
Object *ob = draw_ctx->obact;
bGPdata *gpd = ob->data;
- bool is_weight_paint = (gpd) && (gpd->flag & GP_DATA_STROKE_WEIGHTMODE);
+ const bool is_weight_paint = (gpd) && (gpd->flag & GP_DATA_STROKE_WEIGHTMODE);
int vgindex = ob->actdef - 1;
if (!BLI_findlink(&ob->defbase, vgindex)) {
@@ -553,7 +601,7 @@ void DRW_gpencil_get_edlin_geom(struct GpencilBatchCacheElem *be, bGPDstroke *gp
const DRWContextState *draw_ctx = DRW_context_state_get();
Object *ob = draw_ctx->obact;
bGPdata *gpd = ob->data;
- bool is_weight_paint = (gpd) && (gpd->flag & GP_DATA_STROKE_WEIGHTMODE);
+ const bool is_weight_paint = (gpd) && (gpd->flag & GP_DATA_STROKE_WEIGHTMODE);
int vgindex = ob->actdef - 1;
if (!BLI_findlink(&ob->defbase, vgindex)) {
diff --git a/source/blender/draw/engines/gpencil/gpencil_draw_utils.c b/source/blender/draw/engines/gpencil/gpencil_draw_utils.c
index c8b70953f87..32bf80d4757 100644
--- a/source/blender/draw/engines/gpencil/gpencil_draw_utils.c
+++ b/source/blender/draw/engines/gpencil/gpencil_draw_utils.c
@@ -73,7 +73,9 @@ static void gpencil_calc_vertex(
{
Object *ob = cache_ob->ob;
const DRWContextState *draw_ctx = DRW_context_state_get();
- bGPDframe *gpf = NULL;
+ const bool main_onion = draw_ctx->v3d != NULL ? (draw_ctx->v3d->gp_flag & V3D_GP_SHOW_ONION_SKIN) : true;
+ const bool do_onion = (bool)((gpd->flag & GP_DATA_STROKE_WEIGHTMODE) == 0) &&
+ main_onion && DRW_gpencil_onion_active(gpd);
const bool time_remap = BKE_gpencil_has_time_modifiers(ob);
@@ -81,28 +83,41 @@ static void gpencil_calc_vertex(
cache_ob->tot_triangles = 0;
for (bGPDlayer *gpl = gpd->layers.first; gpl; gpl = gpl->next) {
+ bGPDframe *init_gpf = NULL;
+ const bool is_onion = ((do_onion) && (gpl->onion_flag & GP_LAYER_ONIONSKIN));
if (gpl->flag & GP_LAYER_HIDE) {
continue;
}
- /* verify time modifiers */
- if ((time_remap) && (!stl->storage->simplify_modif)) {
- int remap_cfra = BKE_gpencil_time_modifier(
- draw_ctx->depsgraph, draw_ctx->scene, ob, gpl, cfra_eval,
- stl->storage->is_render);
- gpf = BKE_gpencil_layer_getframe(gpl, remap_cfra, GP_GETFRAME_USE_PREV);
+ /* if onion skin need to count all frames of the layer */
+ if (is_onion) {
+ init_gpf = gpl->actframe;
}
else {
- gpf = gpl->actframe;
+ /* verify time modifiers */
+ if ((time_remap) && (!stl->storage->simplify_modif)) {
+ int remap_cfra = BKE_gpencil_time_modifier(
+ draw_ctx->depsgraph, draw_ctx->scene, ob, gpl, cfra_eval,
+ stl->storage->is_render);
+ init_gpf = BKE_gpencil_layer_getframe(gpl, remap_cfra, GP_GETFRAME_USE_PREV);
+ }
+ else {
+ init_gpf = gpl->actframe;
+ }
}
- if (gpf == NULL) {
+ if (init_gpf == NULL) {
continue;
}
- for (bGPDstroke *gps = gpf->strokes.first; gps; gps = gps->next) {
- cache_ob->tot_vertex += gps->totpoints + 3;
- cache_ob->tot_triangles += gps->totpoints - 1;
+ for (bGPDframe *gpf = init_gpf; gpf; gpf = gpf->next) {
+ for (bGPDstroke *gps = gpf->strokes.first; gps; gps = gps->next) {
+ cache_ob->tot_vertex += gps->totpoints + 3;
+ cache_ob->tot_triangles += gps->totpoints - 1;
+ }
+ if (!is_onion) {
+ break;
+ }
}
}
@@ -244,13 +259,15 @@ static void gpencil_stroke_2d_flat(const bGPDspoint *points, int totpoints, floa
}
/* recalc the internal geometry caches for fill and uvs */
-static void DRW_gpencil_recalc_geometry_caches(Object *ob, MaterialGPencilStyle *gp_style, bGPDstroke *gps)
+static void DRW_gpencil_recalc_geometry_caches(
+ Object *ob, bGPDlayer *gpl, MaterialGPencilStyle *gp_style, bGPDstroke *gps)
{
if (gps->flag & GP_STROKE_RECALC_CACHES) {
/* Calculate triangles cache for filling area (must be done only after changes) */
if ((gps->tot_triangles == 0) || (gps->triangles == NULL)) {
if ((gps->totpoints > 2) &&
- ((gp_style->fill_rgba[3] > GPENCIL_ALPHA_OPACITY_THRESH) || (gp_style->fill_style > 0)))
+ ((gp_style->fill_rgba[3] > GPENCIL_ALPHA_OPACITY_THRESH) ||
+ (gp_style->fill_style > 0) || (gpl->blend_mode != eGplBlendMode_Normal)))
{
DRW_gpencil_triangulate_stroke_fill(ob, gps);
}
@@ -364,6 +381,17 @@ static DRWShadingGroup *DRW_gpencil_shgroup_fill_create(
return grp;
}
+/* check if some onion is enabled */
+bool DRW_gpencil_onion_active(bGPdata *gpd)
+{
+ for (bGPDlayer *gpl = gpd->layers.first; gpl; gpl = gpl->next) {
+ if (gpl->onion_flag & GP_LAYER_ONIONSKIN) {
+ return true;
+ }
+ }
+ return false;
+}
+
/* create shading group for strokes */
DRWShadingGroup *DRW_gpencil_shgroup_stroke_create(
GPENCIL_e_data *e_data, GPENCIL_Data *vedata, DRWPass *pass, GPUShader *shader, Object *ob,
@@ -421,7 +449,7 @@ DRWShadingGroup *DRW_gpencil_shgroup_stroke_create(
DRW_shgroup_uniform_int(grp, "xraymode", (const int *) &gpd->xray_mode, 1);
}
else {
- /* for drawing always on front */
+ /* for drawing always on predefined z-depth */
DRW_shgroup_uniform_int(grp, "xraymode", &stl->storage->xray, 1);
}
@@ -514,7 +542,7 @@ static DRWShadingGroup *DRW_gpencil_shgroup_point_create(
DRW_shgroup_uniform_int(grp, "xraymode", (const int *)&gpd->xray_mode, 1);
}
else {
- /* for drawing always on front */
+ /* for drawing always on on predefined z-depth */
DRW_shgroup_uniform_int(grp, "xraymode", &stl->storage->xray, 1);
}
@@ -559,7 +587,10 @@ static void gpencil_add_fill_vertexdata(
/* set color using material, tint color and opacity */
interp_v3_v3v3(tfill, gps->runtime.tmp_fill_rgba, tintcolor, tintcolor[3]);
tfill[3] = gps->runtime.tmp_fill_rgba[3] * opacity;
- if ((tfill[3] > GPENCIL_ALPHA_OPACITY_THRESH) || (gp_style->fill_style > 0)) {
+ if ((tfill[3] > GPENCIL_ALPHA_OPACITY_THRESH) ||
+ (gp_style->fill_style > 0) ||
+ (gpl->blend_mode != eGplBlendMode_Normal))
+ {
if (cache->is_dirty) {
const float *color;
if (!onion) {
@@ -581,7 +612,8 @@ static void gpencil_add_fill_vertexdata(
/* add to list of groups */
if (old_len < cache->b_fill.vbo_len) {
cache->grp_cache = gpencil_group_cache_add(
- cache->grp_cache, gpl, gpf, gps, eGpencilBatchGroupType_Fill, onion,
+ cache->grp_cache, gpl, gpf, gps,
+ eGpencilBatchGroupType_Fill, onion,
cache->b_fill.vbo_len,
&cache->grp_size, &cache->grp_used);
}
@@ -637,7 +669,8 @@ static void gpencil_add_stroke_vertexdata(
/* add to list of groups */
if (old_len < cache->b_stroke.vbo_len) {
cache->grp_cache = gpencil_group_cache_add(
- cache->grp_cache, gpl, gpf, gps, eGpencilBatchGroupType_Stroke, onion,
+ cache->grp_cache, gpl, gpf, gps,
+ eGpencilBatchGroupType_Stroke, onion,
cache->b_stroke.vbo_len,
&cache->grp_size, &cache->grp_used);
}
@@ -687,7 +720,8 @@ static void gpencil_add_editpoints_vertexdata(
/* add to list of groups */
cache->grp_cache = gpencil_group_cache_add(
- cache->grp_cache, gpl, gpf, gps, eGpencilBatchGroupType_Edlin, false,
+ cache->grp_cache, gpl, gpf, gps,
+ eGpencilBatchGroupType_Edlin, false,
cache->b_edlin.vbo_len,
&cache->grp_size, &cache->grp_used);
}
@@ -699,7 +733,8 @@ static void gpencil_add_editpoints_vertexdata(
/* add to list of groups */
cache->grp_cache = gpencil_group_cache_add(
- cache->grp_cache, gpl, gpf, gps, eGpencilBatchGroupType_Edit, false,
+ cache->grp_cache, gpl, gpf, gps,
+ eGpencilBatchGroupType_Edit, false,
cache->b_edit.vbo_len,
&cache->grp_size, &cache->grp_used);
}
@@ -771,13 +806,14 @@ static void gpencil_draw_strokes(
/* be sure recalc all cache in source stroke to avoid recalculation when frame change
* and improve fps */
if (src_gps) {
- DRW_gpencil_recalc_geometry_caches(ob, gp_style, src_gps);
+ DRW_gpencil_recalc_geometry_caches(ob, gpl, gp_style, src_gps);
}
/* if the fill has any value, it's considered a fill and is not drawn if simplify fill is enabled */
if ((stl->storage->simplify_fill) && (scene->r.simplify_gpencil & SIMPLIFY_GPENCIL_REMOVE_FILL_LINE)) {
if ((gp_style->fill_rgba[3] > GPENCIL_ALPHA_OPACITY_THRESH) ||
- (gp_style->fill_style > GP_STYLE_FILL_STYLE_SOLID))
+ (gp_style->fill_style > GP_STYLE_FILL_STYLE_SOLID) ||
+ (gpl->blend_mode != eGplBlendMode_Normal))
{
GP_SET_SRC_GPS(src_gps);
continue;
@@ -798,21 +834,28 @@ static void gpencil_draw_strokes(
}
}
- /* fill */
- if ((gp_style->flag & GP_STYLE_FILL_SHOW) &&
- (!stl->storage->simplify_fill))
- {
- gpencil_add_fill_vertexdata(
- cache, ob, gpl, derived_gpf, gps,
- opacity, tintcolor, false, custonion);
- }
- /* stroke */
- if ((gp_style->flag & GP_STYLE_STROKE_SHOW) &&
- (gp_style->stroke_rgba[3] > GPENCIL_ALPHA_OPACITY_THRESH))
+ /* hide any blend layer */
+ if ((!stl->storage->simplify_blend) ||
+ (gpl->blend_mode == eGplBlendMode_Normal))
{
- gpencil_add_stroke_vertexdata(
- cache, ob, gpl, derived_gpf, gps,
- opacity, tintcolor, false, custonion);
+ /* fill */
+ if ((gp_style->flag & GP_STYLE_FILL_SHOW) &&
+ (!stl->storage->simplify_fill) &&
+ ((gps->flag & GP_STROKE_NOFILL) == 0))
+ {
+ gpencil_add_fill_vertexdata(
+ cache, ob, gpl, derived_gpf, gps,
+ opacity, tintcolor, false, custonion);
+ }
+ /* stroke */
+ if ((gp_style->flag & GP_STYLE_STROKE_SHOW) &&
+ ((gp_style->stroke_rgba[3] > GPENCIL_ALPHA_OPACITY_THRESH) ||
+ (gpl->blend_mode == eGplBlendMode_Normal)))
+ {
+ gpencil_add_stroke_vertexdata(
+ cache, ob, gpl, derived_gpf, gps,
+ opacity, tintcolor, false, custonion);
+ }
}
}
@@ -1133,6 +1176,9 @@ void DRW_gpencil_populate_buffer_strokes(GPENCIL_e_data *e_data, void *vedata, T
{
GPENCIL_PassList *psl = ((GPENCIL_Data *)vedata)->psl;
GPENCIL_StorageList *stl = ((GPENCIL_Data *)vedata)->stl;
+ const DRWContextState *draw_ctx = DRW_context_state_get();
+ View3D *v3d = draw_ctx->v3d;
+ const bool overlay = v3d != NULL ? (bool)((v3d->flag2 & V3D_RENDER_OVERRIDE) == 0) : true;
Brush *brush = BKE_paint_brush(&ts->gp_paint->paint);
bGPdata *gpd_eval = ob->data;
/* need the original to avoid cow overhead while drawing */
@@ -1156,7 +1202,7 @@ void DRW_gpencil_populate_buffer_strokes(GPENCIL_e_data *e_data, void *vedata, T
/* Check if may need to draw the active stroke cache, only if this layer is the active layer
* that is being edited. (Stroke buffer is currently stored in gp-data)
*/
- if (ED_gpencil_session_active() && (gpd->runtime.sbuffer_size > 0)) {
+ if (gpd->runtime.sbuffer_size > 0) {
if ((gpd->runtime.sbuffer_sflag & GP_STROKE_ERASER) == 0) {
/* It should also be noted that sbuffer contains temporary point types
* i.e. tGPspoints NOT bGPDspoints
@@ -1166,11 +1212,11 @@ void DRW_gpencil_populate_buffer_strokes(GPENCIL_e_data *e_data, void *vedata, T
if (gpd->runtime.sbuffer_size > 1) {
if ((gp_style) && (gp_style->mode == GP_STYLE_MODE_LINE)) {
stl->g_data->shgrps_drawing_stroke = DRW_gpencil_shgroup_stroke_create(
- e_data, vedata, psl->drawing_pass, e_data->gpencil_stroke_sh, NULL, gpd, gp_style, -1, false);
+ e_data, vedata, psl->drawing_pass, e_data->gpencil_stroke_sh, NULL, gpd, gp_style, -1, false);
}
else {
stl->g_data->shgrps_drawing_stroke = DRW_gpencil_shgroup_point_create(
- e_data, vedata, psl->drawing_pass, e_data->gpencil_point_sh, NULL, gpd, gp_style, -1, false);
+ e_data, vedata, psl->drawing_pass, e_data->gpencil_point_sh, NULL, gpd, gp_style, -1, false);
}
/* clean previous version of the batch */
@@ -1183,18 +1229,18 @@ void DRW_gpencil_populate_buffer_strokes(GPENCIL_e_data *e_data, void *vedata, T
/* use unit matrix because the buffer is in screen space and does not need conversion */
if (gpd->runtime.mode == GP_STYLE_MODE_LINE) {
e_data->batch_buffer_stroke = DRW_gpencil_get_buffer_stroke_geom(
- gpd, lthick);
+ gpd, lthick);
}
else {
e_data->batch_buffer_stroke = DRW_gpencil_get_buffer_point_geom(
- gpd, lthick);
+ gpd, lthick);
}
if (gp_style->flag & GP_STYLE_STROKE_SHOW) {
DRW_shgroup_call_add(
- stl->g_data->shgrps_drawing_stroke,
- e_data->batch_buffer_stroke,
- stl->storage->unit_matrix);
+ stl->g_data->shgrps_drawing_stroke,
+ e_data->batch_buffer_stroke,
+ stl->storage->unit_matrix);
}
if ((gpd->runtime.sbuffer_size >= 3) &&
@@ -1208,7 +1254,7 @@ void DRW_gpencil_populate_buffer_strokes(GPENCIL_e_data *e_data, void *vedata, T
gpd->runtime.sfill[3] = 0.5f;
}
stl->g_data->shgrps_drawing_fill = DRW_shgroup_create(
- e_data->gpencil_drawing_fill_sh, psl->drawing_pass);
+ e_data->gpencil_drawing_fill_sh, psl->drawing_pass);
/* clean previous version of the batch */
if (stl->storage->buffer_fill) {
@@ -1219,15 +1265,44 @@ void DRW_gpencil_populate_buffer_strokes(GPENCIL_e_data *e_data, void *vedata, T
e_data->batch_buffer_fill = DRW_gpencil_get_buffer_fill_geom(gpd);
DRW_shgroup_call_add(
- stl->g_data->shgrps_drawing_fill,
- e_data->batch_buffer_fill,
- stl->storage->unit_matrix);
+ stl->g_data->shgrps_drawing_fill,
+ e_data->batch_buffer_fill,
+ stl->storage->unit_matrix);
stl->storage->buffer_fill = true;
}
stl->storage->buffer_stroke = true;
}
}
}
+
+ /* control points */
+ if ((overlay) && (gpd->runtime.tot_cp_points > 0) &&
+ ((gpd->runtime.sbuffer_sflag & GP_STROKE_ERASER) == 0) &&
+ ((v3d->gizmo_flag & V3D_GIZMO_HIDE) == 0) &&
+ ((v3d->gizmo_flag & V3D_GIZMO_HIDE_TOOL) == 0))
+ {
+
+ DRWShadingGroup *shgrp = DRW_shgroup_create(
+ e_data->gpencil_edit_point_sh, psl->drawing_pass);
+ const float *viewport_size = DRW_viewport_size_get();
+ DRW_shgroup_uniform_vec2(shgrp, "Viewport", viewport_size, 1);
+
+ /* clean previous version of the batch */
+ if (stl->storage->buffer_ctrlpoint) {
+ GPU_BATCH_DISCARD_SAFE(e_data->batch_buffer_ctrlpoint);
+ MEM_SAFE_FREE(e_data->batch_buffer_ctrlpoint);
+ stl->storage->buffer_ctrlpoint = false;
+ }
+
+ e_data->batch_buffer_ctrlpoint = DRW_gpencil_get_buffer_ctrlpoint_geom(gpd);
+
+ DRW_shgroup_call_add(
+ shgrp,
+ e_data->batch_buffer_ctrlpoint,
+ stl->storage->unit_matrix);
+
+ stl->storage->buffer_ctrlpoint = true;
+ }
}
/* create all missing batches */
@@ -1253,12 +1328,21 @@ static void DRW_gpencil_create_batches(GpencilBatchCache *cache)
/* create all shading groups */
static void DRW_gpencil_shgroups_create(
GPENCIL_e_data *e_data, void *vedata,
- Object *ob, bGPdata *gpd,
+ Object *ob,
GpencilBatchCache *cache, tGPencilObjectCache *cache_ob)
{
GPENCIL_StorageList *stl = ((GPENCIL_Data *)vedata)->stl;
GPENCIL_PassList *psl = ((GPENCIL_Data *)vedata)->psl;
+ bGPdata *gpd = (bGPdata *)ob->data;
+
+ GpencilBatchGroup *elm = NULL;
DRWShadingGroup *shgrp = NULL;
+ tGPencilObjectCache_shgrp *array_elm = NULL;
+
+ bGPDlayer *gpl = NULL;
+ bGPDlayer *gpl_prev = NULL;
+ int idx = 0;
+ bool tag_first = false;
int start_stroke = 0;
int start_point = 0;
@@ -1266,12 +1350,27 @@ static void DRW_gpencil_shgroups_create(
int start_edit = 0;
int start_edlin = 0;
- cache_ob->init_grp = NULL;
- cache_ob->end_grp = NULL;
-
for (int i = 0; i < cache->grp_used; i++) {
- GpencilBatchGroup *elm = &cache->grp_cache[i];
- bGPDlayer *gpl = elm->gpl;
+ elm = &cache->grp_cache[i];
+ array_elm = &cache_ob->shgrp_array[idx];
+
+ /* save last group when change */
+ if (gpl_prev == NULL) {
+ gpl_prev = elm->gpl;
+ tag_first = true;
+ }
+ else {
+ if (elm->gpl != gpl_prev) {
+ /* first layer is always blend Normal */
+ array_elm->mode = idx == 0 ? eGplBlendMode_Normal: gpl->blend_mode;
+ array_elm->end_shgrp = shgrp;
+ gpl_prev = elm->gpl;
+ tag_first = true;
+ idx++;
+ }
+ }
+
+ gpl = elm->gpl;
bGPDframe *gpf = elm->gpf;
bGPDstroke *gps = elm->gps;
MaterialGPencilStyle *gp_style = BKE_material_gpencil_settings_get(ob, gps->mat_nr + 1);
@@ -1335,28 +1434,32 @@ static void DRW_gpencil_shgroups_create(
}
case eGpencilBatchGroupType_Edit:
{
- const int len = elm->vertex_idx - start_edit;
- /* use always the same group */
- DRW_shgroup_call_range_add(
- stl->g_data->shgrps_edit_point,
- cache->b_edit.batch,
- (!cache_ob->is_dup_ob) ? gpf->runtime.viewmatrix : cache_ob->obmat,
- start_edit, len);
-
- start_edit = elm->vertex_idx;
+ if (stl->g_data->shgrps_edit_point) {
+ const int len = elm->vertex_idx - start_edit;
+ /* use always the same group */
+ DRW_shgroup_call_range_add(
+ stl->g_data->shgrps_edit_point,
+ cache->b_edit.batch,
+ (!cache_ob->is_dup_ob) ? gpf->runtime.viewmatrix : cache_ob->obmat,
+ start_edit, len);
+
+ start_edit = elm->vertex_idx;
+ }
break;
}
case eGpencilBatchGroupType_Edlin:
{
- const int len = elm->vertex_idx - start_edlin;
- /* use always the same group */
- DRW_shgroup_call_range_add(
- stl->g_data->shgrps_edit_line,
- cache->b_edlin.batch,
- (!cache_ob->is_dup_ob) ? gpf->runtime.viewmatrix : cache_ob->obmat,
- start_edlin, len);
-
- start_edlin = elm->vertex_idx;
+ if (stl->g_data->shgrps_edit_line) {
+ const int len = elm->vertex_idx - start_edlin;
+ /* use always the same group */
+ DRW_shgroup_call_range_add(
+ stl->g_data->shgrps_edit_line,
+ cache->b_edlin.batch,
+ (!cache_ob->is_dup_ob) ? gpf->runtime.viewmatrix : cache_ob->obmat,
+ start_edlin, len);
+
+ start_edlin = elm->vertex_idx;
+ }
break;
}
default:
@@ -1365,14 +1468,22 @@ static void DRW_gpencil_shgroups_create(
}
}
/* save first group */
- if ((shgrp != NULL) && (cache_ob->init_grp == NULL)) {
- cache_ob->init_grp = shgrp;
+ if ((shgrp != NULL) && (tag_first)) {
+ array_elm = &cache_ob->shgrp_array[idx];
+ array_elm->mode = idx == 0 ? eGplBlendMode_Normal: gpl->blend_mode;
+ array_elm->clamp_layer = gpl->flag & GP_LAYER_USE_MASK;
+ array_elm->blend_opacity = gpl->opacity;
+ array_elm->init_shgrp = shgrp;
+ cache_ob->tot_layers++;
+
+ tag_first = false;
}
}
/* save last group */
if (shgrp != NULL) {
- cache_ob->end_grp = shgrp;
+ array_elm->mode = idx == 0 ? eGplBlendMode_Normal : gpl->blend_mode;
+ array_elm->end_shgrp = shgrp;
}
}
/* populate a datablock for multiedit (no onions, no modifiers) */
@@ -1425,7 +1536,7 @@ void DRW_gpencil_populate_multiedit(
/* create batchs and shading groups */
DRW_gpencil_create_batches(cache);
- DRW_gpencil_shgroups_create(e_data, vedata, ob, gpd, cache, cache_ob);
+ DRW_gpencil_shgroups_create(e_data, vedata, ob, cache, cache_ob);
cache->is_dirty = false;
}
@@ -1450,7 +1561,8 @@ void DRW_gpencil_populate_datablock(
bGPDframe *derived_gpf = NULL;
const bool main_onion = v3d != NULL ? (v3d->gp_flag & V3D_GP_SHOW_ONION_SKIN) : true;
- const bool do_onion = (bool)((gpd->flag & GP_DATA_STROKE_WEIGHTMODE) == 0) && main_onion;
+ const bool do_onion = (bool)((gpd->flag & GP_DATA_STROKE_WEIGHTMODE) == 0) &&
+ main_onion && DRW_gpencil_onion_active(gpd);
const bool overlay = v3d != NULL ? (bool)((v3d->flag2 & V3D_RENDER_OVERRIDE) == 0) : true;
const bool time_remap = BKE_gpencil_has_time_modifiers(ob);
@@ -1465,7 +1577,7 @@ void DRW_gpencil_populate_datablock(
/* if object is duplicate, only create shading groups */
if (cache_ob->is_dup_ob) {
- DRW_gpencil_shgroups_create(e_data, vedata, ob, gpd, cache, cache_ob);
+ DRW_gpencil_shgroups_create(e_data, vedata, ob, cache, cache_ob);
return;
}
@@ -1481,8 +1593,9 @@ void DRW_gpencil_populate_datablock(
/* draw normal strokes */
for (bGPDlayer *gpl = gpd->layers.first; gpl; gpl = gpl->next) {
/* don't draw layer if hidden */
- if (gpl->flag & GP_LAYER_HIDE)
+ if (gpl->flag & GP_LAYER_HIDE) {
continue;
+ }
/* filter view layer to gp layers in the same view layer (for compo) */
if ((stl->storage->is_render) && (gpl->viewlayername[0] != '\0')) {
@@ -1511,7 +1624,7 @@ void DRW_gpencil_populate_datablock(
opacity = opacity * v3d->overlay.xray_alpha_bone;
}
/* fade no active layers */
- if ((overlay) && (draw_ctx->object_mode == OB_MODE_GPENCIL_PAINT) &&
+ if ((overlay) && (draw_ctx->object_mode == OB_MODE_PAINT_GPENCIL) &&
(v3d->gp_flag & V3D_GP_FADE_NOACTIVE_LAYERS) &&
(draw_ctx->obact) && (draw_ctx->obact == ob) &&
(gpl != gpl_active))
@@ -1535,8 +1648,7 @@ void DRW_gpencil_populate_datablock(
/* draw onion skins */
if (!ID_IS_LINKED(&gpd->id)) {
- if ((gpd->flag & GP_DATA_SHOW_ONIONSKINS) &&
- (do_onion) && (gpl->onion_flag & GP_LAYER_ONIONSKIN) &&
+ if ((do_onion) && (gpl->onion_flag & GP_LAYER_ONIONSKIN) &&
((!playing) || (gpd->onion_flag & GP_ONION_GHOST_ALWAYS)) &&
(!cache_ob->is_dup_ob) && (gpd->id.us <= 1))
{
@@ -1560,7 +1672,7 @@ void DRW_gpencil_populate_datablock(
/* create batchs and shading groups */
DRW_gpencil_create_batches(cache);
- DRW_gpencil_shgroups_create(e_data, vedata, ob, gpd, cache, cache_ob);
+ DRW_gpencil_shgroups_create(e_data, vedata, ob, cache, cache_ob);
cache->is_dirty = false;
}
@@ -1574,9 +1686,10 @@ void DRW_gpencil_populate_particles(GPENCIL_e_data *e_data, void *vedata)
tGPencilObjectCache *cache_ob = &stl->g_data->gp_object_cache[i];
Object *ob = cache_ob->ob;
if (cache_ob->is_dup_ob) {
- bGPdata *gpd = (bGPdata *)ob->data;
GpencilBatchCache *cache = ob->runtime.gpencil_cache;
- DRW_gpencil_shgroups_create(e_data, vedata, ob, gpd, cache, cache_ob);
+ if (cache != NULL) {
+ DRW_gpencil_shgroups_create(e_data, vedata, ob, cache, cache_ob);
+ }
}
}
}
diff --git a/source/blender/draw/engines/gpencil/gpencil_engine.c b/source/blender/draw/engines/gpencil/gpencil_engine.c
index 7be06d501f1..dc62ca34c92 100644
--- a/source/blender/draw/engines/gpencil/gpencil_engine.c
+++ b/source/blender/draw/engines/gpencil/gpencil_engine.c
@@ -64,6 +64,7 @@ extern char datatoc_gpencil_paper_frag_glsl[];
extern char datatoc_gpencil_edit_point_vert_glsl[];
extern char datatoc_gpencil_edit_point_geom_glsl[];
extern char datatoc_gpencil_edit_point_frag_glsl[];
+extern char datatoc_gpencil_blend_frag_glsl[];
/* *********** STATIC *********** */
static GPENCIL_e_data e_data = {NULL}; /* Engine data */
@@ -89,7 +90,7 @@ void DRW_gpencil_multisample_ensure(GPENCIL_Data *vedata, int rect_w, int rect_h
}
if (txl->multisample_depth == NULL) {
txl->multisample_depth = GPU_texture_create_2D_multisample(
- rect_w, rect_h, GPU_DEPTH24_STENCIL8, NULL, samples, NULL);
+ rect_w, rect_h, GPU_DEPTH_COMPONENT24, NULL, samples, NULL);
}
GPU_framebuffer_ensure_config(
&fbl->multisample_fb, {
@@ -114,58 +115,66 @@ static void GPENCIL_create_framebuffers(void *vedata)
const int size[2] = { (int)viewport_size[0], (int)viewport_size[1] };
/* create multiframe framebuffer for AA */
- if (stl->storage->multisamples > 0) {
+ if ((stl->storage->framebuffer_flag & GP_FRAMEBUFFER_MULTISAMPLE) &&
+ (stl->storage->multisamples > 0))
+ {
DRW_gpencil_multisample_ensure(vedata, size[0], size[1]);
}
- /* temp textures */
- e_data.temp_depth_tx_a = DRW_texture_pool_query_2D(size[0], size[1], GPU_DEPTH24_STENCIL8,
- &draw_engine_gpencil_type);
- e_data.temp_color_tx_a = DRW_texture_pool_query_2D(size[0], size[1], fb_format,
- &draw_engine_gpencil_type);
- GPU_framebuffer_ensure_config(
- &fbl->temp_fb_a, {
- GPU_ATTACHMENT_TEXTURE(e_data.temp_depth_tx_a),
- GPU_ATTACHMENT_TEXTURE(e_data.temp_color_tx_a)
- });
-
- e_data.temp_depth_tx_b = DRW_texture_pool_query_2D(
- size[0], size[1], GPU_DEPTH24_STENCIL8,
- &draw_engine_gpencil_type);
- e_data.temp_color_tx_b = DRW_texture_pool_query_2D(
- size[0], size[1], fb_format,
- &draw_engine_gpencil_type);
- GPU_framebuffer_ensure_config(
- &fbl->temp_fb_b, {
- GPU_ATTACHMENT_TEXTURE(e_data.temp_depth_tx_b),
- GPU_ATTACHMENT_TEXTURE(e_data.temp_color_tx_b)
- });
-
- /* used for rim and shadow FX effects */
- e_data.temp_depth_tx_fx = DRW_texture_pool_query_2D(
- size[0], size[1], GPU_DEPTH24_STENCIL8,
- &draw_engine_gpencil_type);
- e_data.temp_color_tx_fx = DRW_texture_pool_query_2D(
- size[0], size[1], fb_format,
- &draw_engine_gpencil_type);
- GPU_framebuffer_ensure_config(
- &fbl->temp_fb_fx, {
- GPU_ATTACHMENT_TEXTURE(e_data.temp_depth_tx_fx),
- GPU_ATTACHMENT_TEXTURE(e_data.temp_color_tx_fx),
- });
+ /* Framebufers for basic object drawing */
+ if (stl->storage->framebuffer_flag & GP_FRAMEBUFFER_BASIC) {
+ /* temp textures for ping-pong buffers */
+ e_data.temp_depth_tx_a = DRW_texture_pool_query_2D(
+ size[0], size[1], GPU_DEPTH_COMPONENT24,
+ &draw_engine_gpencil_type);
+ e_data.temp_color_tx_a = DRW_texture_pool_query_2D(size[0], size[1], fb_format,
+ &draw_engine_gpencil_type);
+ GPU_framebuffer_ensure_config(
+ &fbl->temp_fb_a, {
+ GPU_ATTACHMENT_TEXTURE(e_data.temp_depth_tx_a),
+ GPU_ATTACHMENT_TEXTURE(e_data.temp_color_tx_a)
+ });
+
+ e_data.temp_depth_tx_b = DRW_texture_pool_query_2D(
+ size[0], size[1], GPU_DEPTH_COMPONENT24,
+ &draw_engine_gpencil_type);
+ e_data.temp_color_tx_b = DRW_texture_pool_query_2D(
+ size[0], size[1], fb_format,
+ &draw_engine_gpencil_type);
+ GPU_framebuffer_ensure_config(
+ &fbl->temp_fb_b, {
+ GPU_ATTACHMENT_TEXTURE(e_data.temp_depth_tx_b),
+ GPU_ATTACHMENT_TEXTURE(e_data.temp_color_tx_b)
+ });
+
+ /* used for FX effects and Layer blending */
+ e_data.temp_depth_tx_fx = DRW_texture_pool_query_2D(
+ size[0], size[1], GPU_DEPTH_COMPONENT24,
+ &draw_engine_gpencil_type);
+ e_data.temp_color_tx_fx = DRW_texture_pool_query_2D(
+ size[0], size[1], fb_format,
+ &draw_engine_gpencil_type);
+ GPU_framebuffer_ensure_config(
+ &fbl->temp_fb_fx, {
+ GPU_ATTACHMENT_TEXTURE(e_data.temp_depth_tx_fx),
+ GPU_ATTACHMENT_TEXTURE(e_data.temp_color_tx_fx),
+ });
+ }
/* background framebuffer to speed up drawing process (always 16 bits) */
- e_data.background_depth_tx = DRW_texture_pool_query_2D(
- size[0], size[1], GPU_DEPTH24_STENCIL8,
- &draw_engine_gpencil_type);
- e_data.background_color_tx = DRW_texture_pool_query_2D(
- size[0], size[1], GPU_RGBA32F,
- &draw_engine_gpencil_type);
- GPU_framebuffer_ensure_config(
- &fbl->background_fb, {
- GPU_ATTACHMENT_TEXTURE(e_data.background_depth_tx),
- GPU_ATTACHMENT_TEXTURE(e_data.background_color_tx)
- });
+ if (stl->storage->framebuffer_flag & GP_FRAMEBUFFER_DRAW) {
+ e_data.background_depth_tx = DRW_texture_pool_query_2D(
+ size[0], size[1], GPU_DEPTH_COMPONENT24,
+ &draw_engine_gpencil_type);
+ e_data.background_color_tx = DRW_texture_pool_query_2D(
+ size[0], size[1], GPU_RGBA32F,
+ &draw_engine_gpencil_type);
+ GPU_framebuffer_ensure_config(
+ &fbl->background_fb, {
+ GPU_ATTACHMENT_TEXTURE(e_data.background_depth_tx),
+ GPU_ATTACHMENT_TEXTURE(e_data.background_color_tx)
+ });
+ }
}
}
@@ -221,6 +230,11 @@ static void GPENCIL_create_shaders(void)
e_data.gpencil_simple_fullscreen_sh = DRW_shader_create_fullscreen(datatoc_gpencil_simple_mix_frag_glsl, NULL);
}
+ /* blend */
+ if (!e_data.gpencil_blend_fullscreen_sh) {
+ e_data.gpencil_blend_fullscreen_sh = DRW_shader_create_fullscreen(datatoc_gpencil_blend_frag_glsl, NULL);
+ }
+
/* shaders for use when drawing */
if (!e_data.gpencil_background_sh) {
e_data.gpencil_background_sh = DRW_shader_create_fullscreen(datatoc_gpencil_background_frag_glsl, NULL);
@@ -243,9 +257,6 @@ void GPENCIL_engine_init(void *vedata)
stl->storage->multisamples = U.gpencil_multisamples;
- /* create framebuffers */
- GPENCIL_create_framebuffers(vedata);
-
/* create shaders */
GPENCIL_create_shaders();
GPENCIL_create_fx_shaders(&e_data);
@@ -266,6 +277,7 @@ static void GPENCIL_engine_free(void)
DRW_SHADER_FREE_SAFE(e_data.gpencil_edit_point_sh);
DRW_SHADER_FREE_SAFE(e_data.gpencil_fullscreen_sh);
DRW_SHADER_FREE_SAFE(e_data.gpencil_simple_fullscreen_sh);
+ DRW_SHADER_FREE_SAFE(e_data.gpencil_blend_fullscreen_sh);
DRW_SHADER_FREE_SAFE(e_data.gpencil_background_sh);
DRW_SHADER_FREE_SAFE(e_data.gpencil_paper_sh);
@@ -277,6 +289,9 @@ static void GPENCIL_engine_free(void)
GPU_BATCH_DISCARD_SAFE(e_data.batch_buffer_fill);
MEM_SAFE_FREE(e_data.batch_buffer_fill);
+ GPU_BATCH_DISCARD_SAFE(e_data.batch_buffer_ctrlpoint);
+ MEM_SAFE_FREE(e_data.batch_buffer_ctrlpoint);
+
GPU_BATCH_DISCARD_SAFE(e_data.batch_grid);
MEM_SAFE_FREE(e_data.batch_grid);
@@ -371,6 +386,7 @@ void GPENCIL_cache_init(void *vedata)
stl->storage->simplify_fill = GP_SIMPLIFY_FILL(scene, stl->storage->is_playing);
stl->storage->simplify_modif = GP_SIMPLIFY_MODIF(scene, stl->storage->is_playing);
stl->storage->simplify_fx = GP_SIMPLIFY_FX(scene, stl->storage->is_playing);
+ stl->storage->simplify_blend = GP_SIMPLIFY_BLEND(scene, stl->storage->is_playing);
/* save pixsize */
stl->storage->pixsize = DRW_viewport_pixelsize_get();
@@ -485,6 +501,21 @@ void GPENCIL_cache_init(void *vedata)
stl->g_data->shgrps_grid = DRW_shgroup_create(e_data.gpencil_line_sh, psl->grid_pass);
}
+ /* blend layers pass */
+ psl->blend_pass = DRW_pass_create(
+ "GPencil Blend Layers Pass",
+ DRW_STATE_WRITE_COLOR | DRW_STATE_BLEND | DRW_STATE_WRITE_DEPTH | DRW_STATE_DEPTH_LESS);
+ DRWShadingGroup *blend_shgrp = DRW_shgroup_create(e_data.gpencil_blend_fullscreen_sh, psl->blend_pass);
+ DRW_shgroup_call_add(blend_shgrp, quad, NULL);
+ DRW_shgroup_uniform_texture_ref(blend_shgrp, "strokeColor", &e_data.temp_color_tx_a);
+ DRW_shgroup_uniform_texture_ref(blend_shgrp, "strokeDepth", &e_data.temp_depth_tx_a);
+ DRW_shgroup_uniform_texture_ref(blend_shgrp, "blendColor", &e_data.temp_color_tx_fx);
+ DRW_shgroup_uniform_texture_ref(blend_shgrp, "blendDepth", &e_data.temp_depth_tx_fx);
+ DRW_shgroup_uniform_int(blend_shgrp, "mode", &stl->storage->blend_mode, 1);
+ DRW_shgroup_uniform_int(blend_shgrp, "clamp_layer", &stl->storage->clamp_layer, 1);
+ DRW_shgroup_uniform_float(blend_shgrp, "blend_opacity", &stl->storage->blend_opacity, 1);
+ DRW_shgroup_uniform_int(mix_shgrp, "tonemapping", &stl->storage->tonemapping, 1);
+
/* create effects passes */
if (!stl->storage->simplify_fx) {
GPENCIL_create_fx_passes(psl);
@@ -540,6 +571,10 @@ void GPENCIL_cache_populate(void *vedata, Object *ob)
if (ob->type == OB_GPENCIL && ob->data) {
bGPdata *gpd = (bGPdata *)ob->data;
+ /* enable multisample and basic framebuffer creation */
+ stl->storage->framebuffer_flag |= GP_FRAMEBUFFER_MULTISAMPLE;
+ stl->storage->framebuffer_flag |= GP_FRAMEBUFFER_BASIC;
+
/* when start/stop animation the cache must be set as dirty to reset all data */
if (stl->storage->reset_cache) {
gpd->flag |= GP_DATA_CACHE_IS_DIRTY;
@@ -598,7 +633,18 @@ void GPENCIL_cache_populate(void *vedata, Object *ob)
void GPENCIL_cache_finish(void *vedata)
{
+ GPENCIL_StorageList *stl = ((GPENCIL_Data *)vedata)->stl;
+
+ /* draw particles */
DRW_gpencil_populate_particles(&e_data, vedata);
+
+ if (stl->g_data->session_flag & (GP_DRW_PAINT_IDLE | GP_DRW_PAINT_FILLING)) {
+ stl->storage->framebuffer_flag |= GP_FRAMEBUFFER_DRAW;
+ }
+
+ /* create framebuffers */
+ GPENCIL_create_framebuffers(vedata);
+
}
/* helper function to sort inverse gpencil objects using qsort */
@@ -639,12 +685,40 @@ static void gpencil_free_obj_runtime(GPENCIL_StorageList *stl)
tGPencilObjectCache *cache_ob = &stl->g_data->gp_object_cache[i];
bGPdata *gpd = cache_ob->gpd;
gpd->flag &= ~GP_DATA_CACHE_IS_DIRTY;
+
+ /* free shgrp array */
+ cache_ob->tot_layers = 0;
+ MEM_SAFE_FREE(cache_ob->shgrp_array);
}
/* free the cache itself */
MEM_SAFE_FREE(stl->g_data->gp_object_cache);
}
+static void gpencil_draw_pass_range(
+ GPENCIL_FramebufferList *fbl, GPENCIL_StorageList *stl,
+ GPENCIL_PassList *psl, GPENCIL_TextureList *txl,
+ GPUFrameBuffer *fb,
+ DRWShadingGroup *init_shgrp, DRWShadingGroup *end_shgrp, bool multi)
+{
+ if (init_shgrp == NULL) {
+ return;
+ }
+
+ /* previews don't use AA */
+ if ((!stl->storage->is_mat_preview) && (multi)) {
+ MULTISAMPLE_GP_SYNC_ENABLE(stl->storage->multisamples, fbl);
+ }
+
+ DRW_draw_pass_subset(
+ psl->stroke_pass, init_shgrp, end_shgrp);
+
+ if ((!stl->storage->is_mat_preview) && (multi)) {
+ MULTISAMPLE_GP_SYNC_DISABLE(stl->storage->multisamples, fbl, fb, txl);
+ }
+
+}
+
/* draw scene */
void GPENCIL_draw_scene(void *ved)
{
@@ -657,6 +731,10 @@ void GPENCIL_draw_scene(void *ved)
GPENCIL_TextureList *txl = ((GPENCIL_Data *)vedata)->txl;
tGPencilObjectCache *cache_ob;
+ tGPencilObjectCache_shgrp *array_elm = NULL;
+ DRWShadingGroup *init_shgrp = NULL;
+ DRWShadingGroup *end_shgrp = NULL;
+
const float clearcol[4] = { 0.0f, 0.0f, 0.0f, 0.0f };
const DRWContextState *draw_ctx = DRW_context_state_get();
@@ -664,6 +742,8 @@ void GPENCIL_draw_scene(void *ved)
Object *obact = draw_ctx->obact;
const bool playing = stl->storage->is_playing;
const bool is_render = stl->storage->is_render;
+ bGPdata *gpd_act = (obact) && (obact->type == OB_GPENCIL) ? (bGPdata *)obact->data : NULL;
+ const bool is_edit = GPENCIL_ANY_EDIT_MODE(gpd_act);
/* paper pass to display a comfortable area to draw over complex scenes with geometry */
if ((!is_render) && (obact) && (obact->type == OB_GPENCIL)) {
@@ -712,7 +792,7 @@ void GPENCIL_draw_scene(void *ved)
for (int i = 0; i < stl->g_data->gp_cache_used; i++) {
cache_ob = &stl->g_data->gp_object_cache[i];
bGPdata *gpd = cache_ob->gpd;
-
+ init_shgrp = NULL;
/* Render stroke in separated framebuffer */
GPU_framebuffer_bind(fbl->temp_fb_a);
GPU_framebuffer_clear_color_depth(fbl->temp_fb_a, clearcol, 1.0f);
@@ -720,19 +800,69 @@ void GPENCIL_draw_scene(void *ved)
/* Stroke Pass:
* draw only a subset that usually starts with a fill and ends with stroke
*/
- if (cache_ob->init_grp) {
- /* previews don't use AA */
- if (!stl->storage->is_mat_preview) {
- MULTISAMPLE_GP_SYNC_ENABLE(stl->storage->multisamples, fbl);
- }
+ bool use_blend = false;
+ if (cache_ob->tot_layers > 0) {
+ for (int e = 0; e < cache_ob->tot_layers; e++) {
+ bool is_last = e == cache_ob->tot_layers - 1 ? true : false;
+ array_elm = &cache_ob->shgrp_array[e];
+
+ if (((array_elm->mode == eGplBlendMode_Normal) &&
+ (!use_blend) && (!array_elm->clamp_layer)) ||
+ (e == 0))
+ {
+ if (init_shgrp == NULL) {
+ init_shgrp = array_elm->init_shgrp;
+ }
+ end_shgrp = array_elm->end_shgrp;
+ }
+ else {
+ use_blend = true;
+ /* draw pending groups */
+ gpencil_draw_pass_range(
+ fbl, stl, psl, txl, fbl->temp_fb_a,
+ init_shgrp, end_shgrp, is_last);
+
+ /* draw current group in separated texture */
+ init_shgrp = array_elm->init_shgrp;
+ end_shgrp = array_elm->end_shgrp;
+
+ GPU_framebuffer_bind(fbl->temp_fb_fx);
+ GPU_framebuffer_clear_color_depth(fbl->temp_fb_fx, clearcol, 1.0f);
+ gpencil_draw_pass_range(
+ fbl, stl, psl, txl, fbl->temp_fb_fx,
+ init_shgrp, end_shgrp,
+ is_last);
+
+ /* Blend A texture and FX texture */
+ GPU_framebuffer_bind(fbl->temp_fb_b);
+ GPU_framebuffer_clear_color_depth(fbl->temp_fb_b, clearcol, 1.0f);
+ stl->storage->blend_mode = array_elm->mode;
+ stl->storage->clamp_layer = (int)array_elm->clamp_layer;
+ stl->storage->blend_opacity = array_elm->blend_opacity;
+ stl->storage->tonemapping = stl->storage->is_render ? 1 : 0;
+ DRW_draw_pass(psl->blend_pass);
+ stl->storage->tonemapping = 0;
+
+ /* Copy B texture to A texture to follow loop */
+ e_data.input_depth_tx = e_data.temp_depth_tx_b;
+ e_data.input_color_tx = e_data.temp_color_tx_b;
+
+ GPU_framebuffer_bind(fbl->temp_fb_a);
+ GPU_framebuffer_clear_color_depth(fbl->temp_fb_a, clearcol, 1.0f);
+ DRW_draw_pass(psl->mix_pass_noblend);
+
+ /* prepare next group */
+ init_shgrp = NULL;
+ }
- DRW_draw_pass_subset(
- psl->stroke_pass, cache_ob->init_grp, cache_ob->end_grp);
-
- if (!stl->storage->is_mat_preview) {
- MULTISAMPLE_GP_SYNC_DISABLE(stl->storage->multisamples, fbl, fbl->temp_fb_a, txl);
}
+ /* last group */
+ gpencil_draw_pass_range(
+ fbl, stl, psl, txl, fbl->temp_fb_a,
+ init_shgrp, end_shgrp,
+ true);
}
+
/* Current buffer drawing */
if ((!is_render) && (cache_ob->is_dup_ob == false)) {
DRW_draw_pass(psl->drawing_pass);
@@ -770,7 +900,7 @@ void GPENCIL_draw_scene(void *ved)
}
}
/* edit points */
- if ((!is_render) && (!playing)) {
+ if ((!is_render) && (!playing) && (is_edit)) {
DRW_draw_pass(psl->edit_pass);
}
}
diff --git a/source/blender/draw/engines/gpencil/gpencil_engine.h b/source/blender/draw/engines/gpencil/gpencil_engine.h
index 0fe25ba9f0f..6f2b40136ca 100644
--- a/source/blender/draw/engines/gpencil/gpencil_engine.h
+++ b/source/blender/draw/engines/gpencil/gpencil_engine.h
@@ -54,17 +54,23 @@ struct RenderLayer;
#define GP_SIMPLIFY_FILL(scene, playing) ((GP_SIMPLIFY_ONPLAY(playing) && (GP_SIMPLIFY(scene)) && (scene->r.simplify_gpencil & SIMPLIFY_GPENCIL_FILL)))
#define GP_SIMPLIFY_MODIF(scene, playing) ((GP_SIMPLIFY_ONPLAY(playing) && (GP_SIMPLIFY(scene)) && (scene->r.simplify_gpencil & SIMPLIFY_GPENCIL_MODIFIER)))
#define GP_SIMPLIFY_FX(scene, playing) ((GP_SIMPLIFY_ONPLAY(playing) && (GP_SIMPLIFY(scene)) && (scene->r.simplify_gpencil & SIMPLIFY_GPENCIL_FX)))
+#define GP_SIMPLIFY_BLEND(scene, playing) ((GP_SIMPLIFY_ONPLAY(playing) && (GP_SIMPLIFY(scene)) && (scene->r.simplify_gpencil & SIMPLIFY_GPENCIL_BLEND)))
#define GP_IS_CAMERAVIEW ((rv3d != NULL) && (rv3d->persp == RV3D_CAMOB && v3d->camera))
/* *********** OBJECTS CACHE *********** */
+typedef struct tGPencilObjectCache_shgrp {
+ int mode;
+ bool clamp_layer;
+ float blend_opacity;
+ DRWShadingGroup *init_shgrp;
+ DRWShadingGroup *end_shgrp;
+} tGPencilObjectCache_shgrp;
/* used to save gpencil object data for drawing */
typedef struct tGPencilObjectCache {
struct Object *ob;
struct bGPdata *gpd;
- DRWShadingGroup *init_grp;
- DRWShadingGroup *end_grp;
int idx; /*original index, can change after sort */
/* effects */
@@ -90,6 +96,11 @@ typedef struct tGPencilObjectCache {
/* GPU data size */
int tot_vertex;
int tot_triangles;
+
+ /* Save shader groups by layer */
+ int tot_layers;
+ tGPencilObjectCache_shgrp *shgrp_array;
+
} tGPencilObjectCache;
/* *********** LISTS *********** */
@@ -122,15 +133,23 @@ typedef struct GPENCIL_Storage {
bool reset_cache;
bool buffer_stroke;
bool buffer_fill;
+ bool buffer_ctrlpoint;
const float *pixsize;
float render_pixsize;
int tonemapping;
short multisamples;
+ short framebuffer_flag; /* flag what framebuffer need to create */
+
+ int blend_mode;
+ int clamp_layer;
+ float blend_opacity;
+
/* simplify settings*/
bool simplify_fill;
bool simplify_modif;
bool simplify_fx;
+ bool simplify_blend;
/* Render Matrices and data */
float persmat[4][4], persinv[4][4];
@@ -143,6 +162,12 @@ typedef struct GPENCIL_Storage {
Object *camera; /* camera pointer for render mode */
} GPENCIL_Storage;
+typedef enum eGpencilFramebuffer_Flag {
+ GP_FRAMEBUFFER_MULTISAMPLE = (1 << 0),
+ GP_FRAMEBUFFER_BASIC = (1 << 1),
+ GP_FRAMEBUFFER_DRAW = (1 << 2),
+} eGpencilFramebuffer_Flag;
+
typedef struct GPENCIL_StorageList {
struct GPENCIL_Storage *storage;
struct g_data *g_data;
@@ -158,6 +183,7 @@ typedef struct GPENCIL_PassList {
struct DRWPass *background_pass;
struct DRWPass *paper_pass;
struct DRWPass *grid_pass;
+ struct DRWPass *blend_pass;
/* effects */
struct DRWPass *fx_shader_pass;
@@ -232,6 +258,7 @@ typedef struct GPENCIL_e_data {
struct GPUShader *gpencil_drawing_fill_sh;
struct GPUShader *gpencil_fullscreen_sh;
struct GPUShader *gpencil_simple_fullscreen_sh;
+ struct GPUShader *gpencil_blend_fullscreen_sh;
struct GPUShader *gpencil_background_sh;
struct GPUShader *gpencil_paper_sh;
@@ -273,6 +300,7 @@ typedef struct GPENCIL_e_data {
/* for buffer only one batch is nedeed because the drawing is only of one stroke */
GPUBatch *batch_buffer_stroke;
GPUBatch *batch_buffer_fill;
+ GPUBatch *batch_buffer_ctrlpoint;
/* grid geometry */
GPUBatch *batch_grid;
@@ -360,6 +388,7 @@ void DRW_gpencil_get_edlin_geom(struct GpencilBatchCacheElem *be, struct bGPDstr
struct GPUBatch *DRW_gpencil_get_buffer_stroke_geom(struct bGPdata *gpd, short thickness);
struct GPUBatch *DRW_gpencil_get_buffer_fill_geom(struct bGPdata *gpd);
struct GPUBatch *DRW_gpencil_get_buffer_point_geom(struct bGPdata *gpd, short thickness);
+struct GPUBatch *DRW_gpencil_get_buffer_ctrlpoint_geom(struct bGPdata *gpd);
struct GPUBatch *DRW_gpencil_get_grid(Object *ob);
/* object cache functions */
@@ -367,6 +396,8 @@ struct tGPencilObjectCache *gpencil_object_cache_add(
struct tGPencilObjectCache *cache_array, struct Object *ob,
int *gp_cache_size, int *gp_cache_used);
+bool DRW_gpencil_onion_active(struct bGPdata *gpd);
+
/* shading groups cache functions */
struct GpencilBatchGroup *gpencil_group_cache_add(
struct GpencilBatchGroup *cache_array,
diff --git a/source/blender/draw/engines/gpencil/gpencil_render.c b/source/blender/draw/engines/gpencil/gpencil_render.c
index 8dc15472a20..51a8209fbf2 100644
--- a/source/blender/draw/engines/gpencil/gpencil_render.c
+++ b/source/blender/draw/engines/gpencil/gpencil_render.c
@@ -85,7 +85,7 @@ void GPENCIL_render_init(GPENCIL_Data *ved, RenderEngine *engine, struct Depsgra
}
vedata->render_depth_tx = DRW_texture_pool_query_2D(
- size[0], size[1], GPU_DEPTH24_STENCIL8,
+ size[0], size[1], GPU_DEPTH_COMPONENT24,
&draw_engine_gpencil_type);
vedata->render_color_tx = DRW_texture_pool_query_2D(
size[0], size[1], GPU_RGBA32F,
diff --git a/source/blender/draw/engines/gpencil/gpencil_shader_fx.c b/source/blender/draw/engines/gpencil/gpencil_shader_fx.c
index fcadf296253..225dc1a58d7 100644
--- a/source/blender/draw/engines/gpencil/gpencil_shader_fx.c
+++ b/source/blender/draw/engines/gpencil/gpencil_shader_fx.c
@@ -82,9 +82,9 @@ static bool effect_is_active(bGPdata *gpd, ShaderFxData *fx, bool is_render)
/**
* Get normal of draw using one stroke of visible layer
- * \param gpd GP datablock
- * \param r_point Point on plane
- * \param r_normal Normal vector
+ * \param gpd: GP datablock
+ * \param r_point: Point on plane
+ * \param r_normal: Normal vector
*/
static bool get_normal_vector(bGPdata *gpd, float r_point[3], float r_normal[3])
{
@@ -443,6 +443,9 @@ static void DRW_gpencil_fx_shadow(
}
ShadowShaderFxData *fxd = (ShadowShaderFxData *)fx;
if ((!fxd->object) && (fxd->flag & FX_SHADOW_USE_OBJECT)) {
+ fxd->runtime.fx_sh = NULL;
+ fxd->runtime.fx_sh_b = NULL;
+ fxd->runtime.fx_sh_c = NULL;
return;
}
diff --git a/source/blender/draw/engines/gpencil/shaders/gpencil_blend_frag.glsl b/source/blender/draw/engines/gpencil/shaders/gpencil_blend_frag.glsl
new file mode 100644
index 00000000000..f5696116eea
--- /dev/null
+++ b/source/blender/draw/engines/gpencil/shaders/gpencil_blend_frag.glsl
@@ -0,0 +1,155 @@
+in vec4 uvcoordsvar;
+
+out vec4 FragColor;
+
+uniform sampler2D strokeColor;
+uniform sampler2D strokeDepth;
+uniform sampler2D blendColor;
+uniform sampler2D blendDepth;
+uniform int mode;
+uniform int clamp_layer;
+uniform float blend_opacity;
+uniform int tonemapping;
+
+#define ON 1
+#define OFF 0
+
+#define MODE_NORMAL 0
+#define MODE_OVERLAY 1
+#define MODE_ADD 2
+#define MODE_SUB 3
+#define MODE_MULTIPLY 4
+#define MODE_DIVIDE 5
+
+float overlay_color(float a, float b)
+{
+ float rtn;
+ if (a < 0.5) {
+ rtn = 2.0 * a * b;
+ }
+ else {
+ rtn = 1.0 - 2.0 * (1.0 - a) * (1.0 - b);
+ }
+
+ return rtn;
+}
+
+vec4 get_blend_color(int mode, vec4 src_color, vec4 blend_color)
+{
+ vec4 mix_color = blend_color;
+ vec4 outcolor;
+
+ if (mix_color.a == 0) {
+ outcolor = src_color;
+ }
+ else if (mode == MODE_OVERLAY) {
+ mix_color.rgb = mix_color.rgb * mix_color.a * blend_opacity;
+ outcolor.r = overlay_color(src_color.r, mix_color.r);
+ outcolor.g = overlay_color(src_color.g, mix_color.g);
+ outcolor.b = overlay_color(src_color.b, mix_color.b);
+ outcolor.a = src_color.a;
+ }
+ else if (mode == MODE_ADD){
+ mix_color.rgb = mix_color.rgb * mix_color.a * blend_opacity;
+ outcolor = src_color + mix_color;
+ outcolor.a = src_color.a;
+ }
+ else if (mode == MODE_SUB){
+ outcolor = src_color - mix_color;
+ outcolor.a = clamp(src_color.a - (mix_color.a * blend_opacity), 0.0, 1.0);
+ }
+ else if (mode == MODE_MULTIPLY) {
+ /* interpolate between 1 and color using opacity */
+ mix_color.rgb = mix(vec3(1,1,1), mix_color.rgb * mix_color.a, blend_opacity);
+ outcolor = src_color * mix_color;
+ outcolor.a = src_color.a;
+ }
+ else if (mode == MODE_DIVIDE) {
+ mix_color.rgb = mix_color.rgb * mix_color.a * blend_opacity;
+ outcolor = src_color / mix_color;
+ outcolor.a = src_color.a;
+ }
+ else {
+ outcolor = mix_color * blend_opacity;;
+ outcolor.a = src_color.a;
+ }
+
+ return outcolor;
+}
+
+float linearrgb_to_srgb(float c)
+{
+ if (c < 0.0031308)
+ return (c < 0.0) ? 0.0 : c * 12.92;
+ else
+ return 1.055 * pow(c, 1.0 / 2.4) - 0.055;
+}
+
+vec4 tone(vec4 stroke_color)
+{
+ if (tonemapping == 1) {
+ vec4 color = vec4(0, 0, 0, stroke_color.a);
+ color.r = linearrgb_to_srgb(stroke_color.r);
+ color.g = linearrgb_to_srgb(stroke_color.g);
+ color.b = linearrgb_to_srgb(stroke_color.b);
+ return color;
+ }
+ else {
+ return stroke_color;
+ }
+}
+
+void main()
+{
+ vec4 outcolor;
+ ivec2 uv = ivec2(gl_FragCoord.xy);
+ vec4 stroke_color = texelFetch(strokeColor, uv, 0).rgba;
+ float stroke_depth = texelFetch(strokeDepth, uv, 0).r;
+
+ vec4 mix_color = texelFetch(blendColor, uv, 0).rgba;
+ float mix_depth = texelFetch(blendDepth, uv, 0).r;
+
+ /* premult alpha factor to remove double blend effects */
+ if (stroke_color.a > 0) {
+ stroke_color = vec4(vec3(stroke_color.rgb / stroke_color.a), stroke_color.a);
+ }
+ if (mix_color.a > 0) {
+ mix_color = vec4(vec3(mix_color.rgb / mix_color.a), mix_color.a);
+ }
+
+ /* Normal mode */
+ if (mode == MODE_NORMAL) {
+ if (stroke_color.a > 0) {
+ if (mix_color.a > 0) {
+ FragColor = vec4(mix(stroke_color.rgb, mix_color.rgb, mix_color.a), stroke_color.a);
+ gl_FragDepth = mix_depth;
+ }
+ else {
+ FragColor = stroke_color;
+ gl_FragDepth = stroke_depth;
+ }
+ }
+ else {
+ if (clamp_layer == ON) {
+ discard;
+ }
+ else {
+ FragColor = mix_color;
+ gl_FragDepth = mix_depth;
+ }
+ }
+ FragColor = tone(FragColor);
+ return;
+ }
+
+ /* if not using mask, return mix color */
+ if ((stroke_color.a == 0) && (clamp_layer == OFF)) {
+ FragColor = tone(mix_color);
+ gl_FragDepth = mix_depth;
+ return;
+ }
+
+ /* apply blend mode */
+ FragColor = tone(get_blend_color(mode, stroke_color, mix_color));
+ gl_FragDepth = stroke_depth;
+}
diff --git a/source/blender/draw/engines/gpencil/shaders/gpencil_stroke_geom.glsl b/source/blender/draw/engines/gpencil/shaders/gpencil_stroke_geom.glsl
index f9054b44996..748f69ab21a 100644
--- a/source/blender/draw/engines/gpencil/shaders/gpencil_stroke_geom.glsl
+++ b/source/blender/draw/engines/gpencil/shaders/gpencil_stroke_geom.glsl
@@ -45,6 +45,22 @@ float getZdepth(vec4 point)
/* in front by default */
return 0.000001;
}
+
+/* check equality but with a small tolerance */
+bool is_equal(vec4 p1, vec4 p2)
+{
+ float limit = 0.0001;
+ float x = abs(p1.x - p2.x);
+ float y = abs(p1.y - p2.y);
+ float z = abs(p1.z - p2.z);
+
+ if ((x < limit) && (y < limit) && (z < limit)) {
+ return true;
+ }
+
+ return false;
+}
+
void main(void)
{
float MiterLimit = 0.75;
@@ -143,7 +159,7 @@ void main(void)
}
/* generate the start endcap (alpha < 0 used as endcap flag)*/
- if ((P0 == P2) && (color_type == GPENCIL_COLOR_SOLID)){
+ if (is_equal(P0,P2) && (color_type == GPENCIL_COLOR_SOLID)){
mTexCoord = vec2(2, 1);
mColor = vec4(finalColor[1].rgb, finalColor[1].a * -1.0) ;
vec2 svn1 = normalize(sp1 - sp2) * length_a * 4.0;
@@ -183,7 +199,7 @@ void main(void)
EmitVertex();
/* generate the end endcap (alpha < 0 used as endcap flag)*/
- if ((P1 == P3) && (color_type == GPENCIL_COLOR_SOLID)){
+ if (is_equal(P1,P3) && (color_type == GPENCIL_COLOR_SOLID) && (finaluvdata[2].x > 0)){
mTexCoord = vec2(finaluvdata[2].x, 2);
mColor = vec4(finalColor[2].rgb, finalColor[2].a * -1.0) ;
uvfac = finaluvdata[2].x;
diff --git a/source/blender/draw/engines/workbench/shaders/workbench_cavity_frag.glsl b/source/blender/draw/engines/workbench/shaders/workbench_cavity_frag.glsl
index fafb164a694..769d453bb18 100644
--- a/source/blender/draw/engines/workbench/shaders/workbench_cavity_frag.glsl
+++ b/source/blender/draw/engines/workbench/shaders/workbench_cavity_frag.glsl
@@ -3,6 +3,7 @@ out vec4 fragColor;
uniform sampler2D depthBuffer;
uniform sampler2D colorBuffer;
uniform sampler2D normalBuffer;
+uniform usampler2D objectId;
uniform vec2 invertedViewportSize;
uniform mat4 WinMatrix; /* inverse WinMatrix */
@@ -10,6 +11,7 @@ uniform mat4 WinMatrix; /* inverse WinMatrix */
uniform vec4 viewvecs[3];
uniform vec4 ssao_params;
uniform vec4 ssao_settings;
+uniform vec2 curvature_settings;
uniform sampler2D ssao_jitter;
layout(std140) uniform samples_block {
@@ -23,7 +25,7 @@ layout(std140) uniform samples_block {
#define ssao_distance ssao_settings.x
#define ssao_factor_cavity ssao_settings.y
#define ssao_factor_edge ssao_settings.z
-#define ssao_attenuation ssao_settings.a
+#define ssao_attenuation ssao_settings.w
vec3 get_view_space_from_depth(in vec2 uvcoords, in float depth)
{
@@ -54,17 +56,22 @@ void main()
vec2 screenco = vec2(gl_FragCoord.xy) * invertedViewportSize;
ivec2 texel = ivec2(gl_FragCoord.xy);
+ float cavity = 0.0, edges = 0.0, curvature = 0.0;
+
+#ifdef USE_CAVITY
float depth = texelFetch(depthBuffer, texel, 0).x;
vec3 position = get_view_space_from_depth(screenco, depth);
+ vec3 normal_viewport = workbench_normal_decode(texelFetch(normalBuffer, texel, 0).rg);
- vec4 diffuse_color = texelFetch(colorBuffer, texel, 0);
- vec3 normal_viewport = normal_decode(texelFetch(normalBuffer, texel, 0).rg);
- if (diffuse_color.a == 0.0) {
- normal_viewport = -normal_viewport;
- }
-
- float cavity = 0.0, edges = 0.0;
ssao_factors(depth, normal_viewport, position, screenco, cavity, edges);
+#endif
+
+#ifdef USE_CURVATURE
+ curvature = calculate_curvature(objectId, normalBuffer, texel, curvature_settings.x, curvature_settings.y);
+#endif
+
+ float final_cavity_factor = clamp((1.0 - cavity) * (1.0 + edges) * (1.0 + curvature), 0.0, 4.0);
- fragColor = vec4(cavity, edges, 0.0, 1.0);
+ /* Using UNORM render target so compress the range. */
+ fragColor = vec4(final_cavity_factor / CAVITY_BUFFER_RANGE);
}
diff --git a/source/blender/draw/engines/workbench/shaders/workbench_common_lib.glsl b/source/blender/draw/engines/workbench/shaders/workbench_common_lib.glsl
index c56e02e72d6..25942b162ee 100644
--- a/source/blender/draw/engines/workbench/shaders/workbench_common_lib.glsl
+++ b/source/blender/draw/engines/workbench/shaders/workbench_common_lib.glsl
@@ -2,6 +2,8 @@
#define EPSILON 0.00001
#define M_PI 3.14159265358979323846
+#define CAVITY_BUFFER_RANGE 4.0
+
/* 4x4 bayer matrix prepared for 8bit UNORM precision error. */
#define P(x) (((x + 0.5) * (1.0 / 16.0) - 0.5) * (1.0 / 255.0))
const vec4 dither_mat4x4[4] = vec4[4](
@@ -17,9 +19,13 @@ float bayer_dither_noise() {
return dither_mat4x4[tx1.x][tx1.y];
}
+#ifdef WORKBENCH_ENCODE_NORMALS
+
+#define WB_Normal vec2
+
/* From http://aras-p.info/texts/CompactNormalStorage.html
* Using Method #4: Spheremap Transform */
-vec3 normal_decode(vec2 enc)
+vec3 workbench_normal_decode(WB_Normal enc)
{
vec2 fenc = enc.xy * 4.0 - 2.0;
float f = dot(fenc, fenc);
@@ -32,37 +38,53 @@ vec3 normal_decode(vec2 enc)
/* From http://aras-p.info/texts/CompactNormalStorage.html
* Using Method #4: Spheremap Transform */
-vec2 normal_encode(vec3 n)
+WB_Normal workbench_normal_encode(vec3 n)
{
float p = sqrt(n.z * 8.0 + 8.0);
- return vec2(n.xy / p + 0.5);
+ n.xy = clamp(n.xy / p + 0.5, 0.0, 1.0);
+ return n.xy;
}
-void fresnel(vec3 I, vec3 N, float ior, out float kr)
+#else
+#define WB_Normal vec3
+/* Well just do nothing... */
+# define workbench_normal_encode(a) (a)
+# define workbench_normal_decode(a) (a)
+#endif /* WORKBENCH_ENCODE_NORMALS */
+
+/* Encoding into the alpha of a RGBA8 UNORM texture. */
+#define TARGET_BITCOUNT 8u
+#define METALLIC_BITS 3u /* Metallic channel is less important. */
+#define ROUGHNESS_BITS (TARGET_BITCOUNT - METALLIC_BITS)
+#define TOTAL_BITS (METALLIC_BITS + ROUGHNESS_BITS)
+
+/* Encode 2 float into 1 with the desired precision. */
+float workbench_float_pair_encode(float v1, float v2)
{
- float cosi = clamp(dot(I, N), -1.0, 1.0);
- float etai = 1.0;
- float etat = ior;
- if (cosi > 0) {
- etat = 1.0;
- etai = ior;
- }
+ // const uint total_mask = ~(0xFFFFFFFFu << TOTAL_BITS);
+ // const uint v1_mask = ~(0xFFFFFFFFu << ROUGHNESS_BITS);
+ // const uint v2_mask = ~(0xFFFFFFFFu << METALLIC_BITS);
+ /* Same as above because some compiler are dumb af. and think we use mediump int. */
+ const int total_mask = 0xFF;
+ const int v1_mask = 0x1F;
+ const int v2_mask = 0x7;
+ int iv1 = int(v1 * float(v1_mask));
+ int iv2 = int(v2 * float(v2_mask)) << int(ROUGHNESS_BITS);
+ return float(iv1 | iv2) * (1.0 / float(total_mask));
+}
- // Compute sini using Snell's law
- float sint = etai / etat * sqrt(max(0.0, 1.0 - cosi * cosi));
- // Total internal reflection
- if (sint >= 1) {
- kr = 1;
- }
- else {
- float cost = sqrt(max(0.0, 1.0 - sint * sint));
- cosi = abs(cosi);
- float Rs = ((etat * cosi) - (etai * cost)) / ((etat * cosi) + (etai * cost));
- float Rp = ((etai * cosi) - (etat * cost)) / ((etai * cosi) + (etat * cost));
- kr = (Rs * Rs + Rp * Rp) / 2;
- }
- // As a consequence of the conservation of energy, transmittance is given by:
- // kt = 1 - kr;
+void workbench_float_pair_decode(float data, out float v1, out float v2)
+{
+ // const uint total_mask = ~(0xFFFFFFFFu << TOTAL_BITS);
+ // const uint v1_mask = ~(0xFFFFFFFFu << ROUGHNESS_BITS);
+ // const uint v2_mask = ~(0xFFFFFFFFu << METALLIC_BITS);
+ /* Same as above because some compiler are dumb af. and think we use mediump int. */
+ const int total_mask = 0xFF;
+ const int v1_mask = 0x1F;
+ const int v2_mask = 0x7;
+ int idata = int(data * float(total_mask));
+ v1 = float(idata & v1_mask) * (1.0 / float(v1_mask));
+ v2 = float(idata >> int(ROUGHNESS_BITS)) * (1.0 / float(v2_mask));
}
float calculate_transparent_weight(float z, float alpha)
@@ -119,3 +141,21 @@ vec2 matcap_uv_compute(vec3 I, vec3 N, bool flipped)
}
return matcap_uv * 0.496 + 0.5;
}
+
+float srgb_to_linearrgb(float c)
+{
+ if (c < 0.04045)
+ return (c < 0.0) ? 0.0 : c * (1.0 / 12.92);
+ else
+ return pow((c + 0.055) * (1.0 / 1.055), 2.4);
+}
+
+vec4 srgb_to_linearrgb(vec4 col_from)
+{
+ vec4 col_to;
+ col_to.r = srgb_to_linearrgb(col_from.r);
+ col_to.g = srgb_to_linearrgb(col_from.g);
+ col_to.b = srgb_to_linearrgb(col_from.b);
+ col_to.a = col_from.a;
+ return col_to;
+}
diff --git a/source/blender/draw/engines/workbench/shaders/workbench_curvature_lib.glsl b/source/blender/draw/engines/workbench/shaders/workbench_curvature_lib.glsl
new file mode 100644
index 00000000000..d0281f6c85c
--- /dev/null
+++ b/source/blender/draw/engines/workbench/shaders/workbench_curvature_lib.glsl
@@ -0,0 +1,41 @@
+#ifndef CURVATURE_OFFSET
+# define CURVATURE_OFFSET 1
+#endif
+
+float curvature_soft_clamp(float curvature, float control)
+{
+ if (curvature < 0.5 / control) {
+ return curvature * (1.0 - curvature * control);
+ }
+ return 0.25 / control;
+}
+
+float calculate_curvature(usampler2D objectId, sampler2D normalBuffer, ivec2 texel, float ridge, float valley)
+{
+ uint object_up = texelFetchOffset(objectId, texel, 0, ivec2(0, CURVATURE_OFFSET)).r;
+ uint object_down = texelFetchOffset(objectId, texel, 0, ivec2(0, -CURVATURE_OFFSET)).r;
+ uint object_left = texelFetchOffset(objectId, texel, 0, ivec2(-CURVATURE_OFFSET, 0)).r;
+ uint object_right = texelFetchOffset(objectId, texel, 0, ivec2( CURVATURE_OFFSET, 0)).r;
+
+ if((object_up != object_down) || (object_right != object_left)) {
+ return 0.0;
+ }
+
+ vec2 normal_up = texelFetchOffset(normalBuffer, texel, 0, ivec2(0, CURVATURE_OFFSET)).rg;
+ vec2 normal_down = texelFetchOffset(normalBuffer, texel, 0, ivec2(0, -CURVATURE_OFFSET)).rg;
+ vec2 normal_left = texelFetchOffset(normalBuffer, texel, 0, ivec2(-CURVATURE_OFFSET, 0)).rg;
+ vec2 normal_right = texelFetchOffset(normalBuffer, texel, 0, ivec2( CURVATURE_OFFSET, 0)).rg;
+
+ normal_up = workbench_normal_decode(normal_up ).rg;
+ normal_down = workbench_normal_decode(normal_down ).rg;
+ normal_left = workbench_normal_decode(normal_left ).rg;
+ normal_right = workbench_normal_decode(normal_right).rg;
+
+ float normal_diff = ((normal_up.g - normal_down.g) + (normal_right.r - normal_left.r));
+
+ if (normal_diff < 0) {
+ return -2.0 * curvature_soft_clamp(-normal_diff, valley);
+ }
+
+ return 2.0 * curvature_soft_clamp(normal_diff, ridge);
+}
diff --git a/source/blender/draw/engines/workbench/shaders/workbench_data_lib.glsl b/source/blender/draw/engines/workbench/shaders/workbench_data_lib.glsl
index 7ba6b3a5193..6deb29f6bca 100644
--- a/source/blender/draw/engines/workbench/shaders/workbench_data_lib.glsl
+++ b/source/blender/draw/engines/workbench/shaders/workbench_data_lib.glsl
@@ -1,17 +1,20 @@
struct LightData {
- vec4 light_direction_vs;
+ vec4 direction;
vec4 specular_color;
+ vec4 diffuse_color_wrap; /* rgb: diffuse col a: wrapped lighting factor */
};
struct WorldData {
- vec3 spherical_harmonics_coefs[STUDIOLIGHT_SH_MAX_COMPONENTS];
vec4 background_color_low;
vec4 background_color_high;
vec4 object_outline_color;
vec4 shadow_direction_vs;
- LightData lights[3];
+ LightData lights[4];
+ vec4 ambient_color;
int num_lights;
int matcap_orientation;
float background_alpha;
- int pad[1];
+ float curvature_ridge;
+ float curvature_valley;
+ int pad[3];
};
diff --git a/source/blender/draw/engines/workbench/shaders/workbench_deferred_background_frag.glsl b/source/blender/draw/engines/workbench/shaders/workbench_deferred_background_frag.glsl
new file mode 100644
index 00000000000..9e4394238ff
--- /dev/null
+++ b/source/blender/draw/engines/workbench/shaders/workbench_deferred_background_frag.glsl
@@ -0,0 +1,39 @@
+
+uniform usampler2D objectId;
+
+uniform vec2 invertedViewportSize;
+
+out vec4 fragColor;
+
+layout(std140) uniform world_block {
+ WorldData world_data;
+};
+
+void main()
+{
+ vec2 uv_viewport = gl_FragCoord.xy * invertedViewportSize;
+ vec3 background = background_color(world_data, uv_viewport.y);
+
+#ifndef V3D_SHADING_OBJECT_OUTLINE
+
+ fragColor = vec4(background, world_data.background_alpha);
+
+#else /* !V3D_SHADING_OBJECT_OUTLINE */
+
+ ivec2 texel = ivec2(gl_FragCoord.xy);
+ uint object_id = texelFetch(objectId, texel, 0).r;
+ float object_outline = calculate_object_outline(objectId, texel, object_id);
+
+ if (object_outline == 0.0) {
+ fragColor = vec4(background, world_data.background_alpha);
+ }
+ else {
+ /* Do correct alpha blending. */
+ vec4 background_color = vec4(background, 1.0) * world_data.background_alpha;
+ vec4 outline_color = vec4(world_data.object_outline_color.rgb, 1.0);
+ fragColor = mix(outline_color, background_color, object_outline);
+ fragColor = vec4(fragColor.rgb / max(1e-8, fragColor.a), fragColor.a);
+ }
+
+#endif /* !V3D_SHADING_OBJECT_OUTLINE */
+}
diff --git a/source/blender/draw/engines/workbench/shaders/workbench_deferred_composite_frag.glsl b/source/blender/draw/engines/workbench/shaders/workbench_deferred_composite_frag.glsl
index 508aeb1f0c1..40e166bc7ac 100644
--- a/source/blender/draw/engines/workbench/shaders/workbench_deferred_composite_frag.glsl
+++ b/source/blender/draw/engines/workbench/shaders/workbench_deferred_composite_frag.glsl
@@ -1,24 +1,23 @@
out vec4 fragColor;
uniform mat4 ProjectionMatrix;
+uniform mat4 ViewMatrixInverse;
uniform usampler2D objectId;
-uniform sampler2D colorBuffer;
-uniform sampler2D specularBuffer;
+uniform sampler2D materialBuffer;
uniform sampler2D normalBuffer;
/* normalBuffer contains viewport normals */
uniform sampler2D cavityBuffer;
+uniform sampler2D matcapImage;
uniform vec2 invertedViewportSize;
uniform vec4 viewvecs[3];
uniform float shadowMultiplier;
uniform float lightMultiplier;
uniform float shadowShift = 0.1;
-uniform mat3 normalWorldMatrix;
+uniform float shadowFocus = 1.0;
-#ifdef STUDIOLIGHT_ORIENTATION_VIEWNORMAL
-uniform sampler2D matcapImage;
-#endif
+uniform vec3 materialSingleColor;
layout(std140) uniform world_block {
WorldData world_data;
@@ -28,102 +27,72 @@ void main()
{
ivec2 texel = ivec2(gl_FragCoord.xy);
vec2 uv_viewport = gl_FragCoord.xy * invertedViewportSize;
- uint object_id = texelFetch(objectId, texel, 0).r;
-#ifndef V3D_SHADING_OBJECT_OUTLINE
- if (object_id == NO_OBJECT_ID) {
- fragColor = vec4(background_color(world_data, uv_viewport.y), world_data.background_alpha);
- return;
- }
-#else /* !V3D_SHADING_OBJECT_OUTLINE */
- float object_outline = calculate_object_outline(objectId, texel, object_id);
+ float roughness, metallic;
+ vec3 base_color;
- if (object_id == NO_OBJECT_ID) {
- vec3 background = background_color(world_data, uv_viewport.y);
- if (object_outline == 0.0) {
- fragColor = vec4(background, world_data.background_alpha);
- }
- else {
- /* Do correct alpha blending. */
- vec4 background_color = vec4(background, 1.0) * world_data.background_alpha;
- vec4 outline_color = vec4(world_data.object_outline_color.rgb, 1.0);
- fragColor = mix(outline_color, background_color, object_outline);
- fragColor = vec4(fragColor.rgb / max(1e-8, fragColor.a), fragColor.a);
- }
- return;
- }
-#endif /* !V3D_SHADING_OBJECT_OUTLINE */
-
- vec4 diffuse_color = texelFetch(colorBuffer, texel, 0);
+#ifndef MATDATA_PASS_ENABLED
+ base_color = materialSingleColor;
+ metallic = 0.0;
+ roughness = 0.5;
+#else
+ vec4 material_data = texelFetch(materialBuffer, texel, 0);
+ base_color = material_data.rgb;
+ workbench_float_pair_decode(material_data.a, roughness, metallic);
+#endif
/* Do we need normals */
#ifdef NORMAL_VIEWPORT_PASS_ENABLED
-# ifdef WORKBENCH_ENCODE_NORMALS
- vec3 normal_viewport = normal_decode(texelFetch(normalBuffer, texel, 0).rg);
- if (diffuse_color.a == 0.0) {
- normal_viewport = -normal_viewport;
- }
-# else /* WORKBENCH_ENCODE_NORMALS */
- vec3 normal_viewport = texelFetch(normalBuffer, texel, 0).rgb;
-# endif /* WORKBENCH_ENCODE_NORMALS */
+ vec3 normal_viewport = workbench_normal_decode(texelFetch(normalBuffer, texel, 0).rg);
#endif
vec3 I_vs = view_vector_from_screen_uv(uv_viewport, viewvecs, ProjectionMatrix);
-#ifdef STUDIOLIGHT_ORIENTATION_VIEWNORMAL
+ /* -------- SHADING --------- */
+#ifdef V3D_LIGHTING_FLAT
+ vec3 shaded_color = base_color;
+
+#elif defined(V3D_LIGHTING_MATCAP)
+ /* When using matcaps, the metallic is the backface sign. */
+ normal_viewport = (metallic > 0.0) ? normal_viewport : -normal_viewport;
bool flipped = world_data.matcap_orientation != 0;
vec2 matcap_uv = matcap_uv_compute(I_vs, normal_viewport, flipped);
- diffuse_color = textureLod(matcapImage, matcap_uv, 0.0);
-#endif
+ vec3 matcap = textureLod(matcapImage, matcap_uv, 0.0).rgb;
+ vec3 shaded_color = matcap * base_color;
-#ifdef V3D_SHADING_SPECULAR_HIGHLIGHT
- vec4 specular_data = texelFetch(specularBuffer, texel, 0);
- vec3 specular_color = get_world_specular_lights(world_data, specular_data, normal_viewport, I_vs);
-#else
- vec3 specular_color = vec3(0.0);
-#endif
+#elif defined(V3D_LIGHTING_STUDIO)
-#ifdef V3D_LIGHTING_FLAT
- vec3 diffuse_light = vec3(1.0);
-#endif
-
-#ifdef V3D_LIGHTING_MATCAP
- vec3 diffuse_light = texelFetch(specularBuffer, texel, 0).rgb;
-#endif
-
-#ifdef V3D_LIGHTING_STUDIO
-# ifdef STUDIOLIGHT_ORIENTATION_CAMERA
- vec3 diffuse_light = get_camera_diffuse_light(world_data, normal_viewport);
+# ifdef V3D_SHADING_SPECULAR_HIGHLIGHT
+ vec3 specular_color = mix(vec3(0.05), base_color, metallic);
+ vec3 diffuse_color = mix(base_color, vec3(0.0), metallic);
+# else
+ roughness = 0.0;
+ vec3 specular_color = vec3(0.0);
+ vec3 diffuse_color = base_color;
# endif
-# ifdef STUDIOLIGHT_ORIENTATION_WORLD
- vec3 normal_world = normalWorldMatrix * normal_viewport;
- vec3 diffuse_light = get_world_diffuse_light(world_data, normal_world);
-# endif
+ vec3 shaded_color = get_world_lighting(world_data,
+ diffuse_color, specular_color, roughness,
+ normal_viewport, I_vs);
#endif
- vec3 shaded_color = diffuse_light * diffuse_color.rgb + specular_color;
-#ifdef V3D_SHADING_CAVITY
- vec2 cavity = texelFetch(cavityBuffer, texel, 0).rg;
- shaded_color *= 1.0 - cavity.x;
- shaded_color *= 1.0 + cavity.y;
+ /* -------- POST EFFECTS --------- */
+#ifdef WB_CAVITY
+ /* Using UNORM texture so decompress the range */
+ shaded_color *= texelFetch(cavityBuffer, texel, 0).r * CAVITY_BUFFER_RANGE;
#endif
#ifdef V3D_SHADING_SHADOW
float light_factor = -dot(normal_viewport, world_data.shadow_direction_vs.xyz);
- /* The step function might be ok for meshes but it's
- * clearly not the case for hairs. Do smoothstep in this case. */
- float shadow_mix = smoothstep(1.0, shadowShift, light_factor);
- float light_multiplier = mix(lightMultiplier, shadowMultiplier, shadow_mix);
-
-#else /* V3D_SHADING_SHADOW */
- float light_multiplier = 1.0;
-#endif /* V3D_SHADING_SHADOW */
-
- shaded_color *= light_multiplier;
+ float shadow_mix = smoothstep(shadowFocus, shadowShift, light_factor);
+ shaded_color *= mix(lightMultiplier, shadowMultiplier, shadow_mix);
+#endif
#ifdef V3D_SHADING_OBJECT_OUTLINE
+ uint object_id = texelFetch(objectId, texel, 0).r;
+ float object_outline = calculate_object_outline(objectId, texel, object_id);
shaded_color = mix(world_data.object_outline_color.rgb, shaded_color, object_outline);
-#endif /* V3D_SHADING_OBJECT_OUTLINE */
+#endif
+
fragColor = vec4(shaded_color, 1.0);
}
diff --git a/source/blender/draw/engines/workbench/shaders/workbench_forward_composite_frag.glsl b/source/blender/draw/engines/workbench/shaders/workbench_forward_composite_frag.glsl
index 1d9f37274bd..cb5516ca34f 100644
--- a/source/blender/draw/engines/workbench/shaders/workbench_forward_composite_frag.glsl
+++ b/source/blender/draw/engines/workbench/shaders/workbench_forward_composite_frag.glsl
@@ -13,25 +13,23 @@ void main()
{
ivec2 texel = ivec2(gl_FragCoord.xy);
vec2 uv_viewport = gl_FragCoord.xy * invertedViewportSize;
- uint object_id = texelFetch(objectId, texel, 0).r;
/* Listing 4 */
vec4 trans_accum = texelFetch(transparentAccum, texel, 0);
float trans_revealage = trans_accum.a;
trans_accum.a = texelFetch(transparentRevealage, texel, 0).r;
-#ifdef V3D_SHADING_OBJECT_OUTLINE
- float outline = calculate_object_outline(objectId, texel, object_id);
-#else /* V3D_SHADING_OBJECT_OUTLINE */
- float outline = 1.0;
-#endif /* V3D_SHADING_OBJECT_OUTLINE */
vec3 bg_color = background_color(world_data, uv_viewport.y);
/* TODO: Bypass the whole shader if there is no xray pass and no outline pass. */
vec3 trans_color = trans_accum.rgb / clamp(trans_accum.a, 1e-4, 5e4);
vec3 color = mix(trans_color, bg_color, trans_revealage);
+#ifdef V3D_SHADING_OBJECT_OUTLINE
+ uint object_id = texelFetch(objectId, texel, 0).r;
+ float outline = calculate_object_outline(objectId, texel, object_id);
color = mix(world_data.object_outline_color.rgb, color, outline);
+#endif
fragColor = vec4(color, 1.0);
}
diff --git a/source/blender/draw/engines/workbench/shaders/workbench_forward_transparent_accum_frag.glsl b/source/blender/draw/engines/workbench/shaders/workbench_forward_transparent_accum_frag.glsl
index 67a22073a4b..aed86937e0d 100644
--- a/source/blender/draw/engines/workbench/shaders/workbench_forward_transparent_accum_frag.glsl
+++ b/source/blender/draw/engines/workbench/shaders/workbench_forward_transparent_accum_frag.glsl
@@ -1,16 +1,16 @@
-#ifdef V3D_SHADING_TEXTURE_COLOR
-uniform sampler2D image;
+
uniform float ImageTransparencyCutoff = 0.1;
+uniform sampler2D image;
+uniform bool imageSrgb;
-#endif
uniform mat4 ProjectionMatrix;
-uniform mat3 normalWorldMatrix;
+uniform mat4 ViewMatrixInverse;
uniform float alpha = 0.5;
uniform vec2 invertedViewportSize;
uniform vec4 viewvecs[3];
-uniform vec4 materialDiffuseColor;
-uniform vec4 materialSpecularColor;
+uniform vec3 materialDiffuseColor;
+uniform vec3 materialSpecularColor;
uniform float materialRoughness;
#ifdef NORMAL_VIEWPORT_PASS_ENABLED
@@ -33,15 +33,17 @@ layout(location=1) out float revealageAccum; /* revealage actually stored in tra
void main()
{
vec4 diffuse_color;
- vec3 diffuse_light = vec3(1.0);
#ifdef V3D_SHADING_TEXTURE_COLOR
diffuse_color = texture(image, uv_interp);
if (diffuse_color.a < ImageTransparencyCutoff) {
discard;
}
+ if (imageSrgb) {
+ diffuse_color = srgb_to_linearrgb(diffuse_color);
+ }
#else
- diffuse_color = materialDiffuseColor;
+ diffuse_color = vec4(materialDiffuseColor, 1.0);
#endif /* V3D_SHADING_TEXTURE_COLOR */
vec2 uv_viewport = gl_FragCoord.xy * invertedViewportSize;
@@ -51,30 +53,22 @@ void main()
vec3 nor = normalize(normal_viewport);
#endif
-#ifdef V3D_LIGHTING_MATCAP
+ /* -------- SHADING --------- */
+#ifdef V3D_LIGHTING_FLAT
+ vec3 shaded_color = diffuse_color.rgb;
+
+#elif defined(V3D_LIGHTING_MATCAP)
bool flipped = world_data.matcap_orientation != 0;
vec2 matcap_uv = matcap_uv_compute(I_vs, nor, flipped);
- diffuse_light = texture(matcapImage, matcap_uv).rgb;
-#endif
-
-#ifdef V3D_SHADING_SPECULAR_HIGHLIGHT
- vec3 specular_color = get_world_specular_lights(world_data, vec4(materialSpecularColor.rgb, materialRoughness), nor, I_vs);
-#else
- vec3 specular_color = vec3(0.0);
-#endif
+ vec3 matcap = textureLod(matcapImage, matcap_uv, 0.0).rgb;
+ vec3 shaded_color = matcap * diffuse_color.rgb;
-#ifdef V3D_LIGHTING_STUDIO
-# ifdef STUDIOLIGHT_ORIENTATION_CAMERA
- diffuse_light = get_camera_diffuse_light(world_data, nor);
-# endif
-# ifdef STUDIOLIGHT_ORIENTATION_WORLD
- vec3 normal_world = normalWorldMatrix * nor;
- diffuse_light = get_world_diffuse_light(world_data, normal_world);
-# endif
+#elif defined(V3D_LIGHTING_STUDIO)
+ vec3 shaded_color = get_world_lighting(world_data,
+ diffuse_color.rgb, materialSpecularColor, materialRoughness,
+ nor, I_vs);
#endif
- vec3 shaded_color = diffuse_light * diffuse_color.rgb + specular_color;
-
/* Based on :
* McGuire and Bavoil, Weighted Blended Order-Independent Transparency, Journal of
* Computer Graphics Techniques (JCGT), vol. 2, no. 2, 122–141, 2013
diff --git a/source/blender/draw/engines/workbench/shaders/workbench_prepass_frag.glsl b/source/blender/draw/engines/workbench/shaders/workbench_prepass_frag.glsl
index 62c7e4515cd..2ce816c6484 100644
--- a/source/blender/draw/engines/workbench/shaders/workbench_prepass_frag.glsl
+++ b/source/blender/draw/engines/workbench/shaders/workbench_prepass_frag.glsl
@@ -1,81 +1,81 @@
uniform int object_id = 0;
-uniform vec4 materialDiffuseColor;
-uniform vec4 materialSpecularColor;
+uniform vec3 materialDiffuseColor;
+uniform float materialMetallic;
uniform float materialRoughness;
-#ifdef V3D_SHADING_TEXTURE_COLOR
uniform sampler2D image;
uniform float ImageTransparencyCutoff = 0.1;
-
-#endif
+uniform bool imageSrgb;
#ifdef NORMAL_VIEWPORT_PASS_ENABLED
in vec3 normal_viewport;
-#endif /* NORMAL_VIEWPORT_PASS_ENABLED */
+#endif
#ifdef V3D_SHADING_TEXTURE_COLOR
in vec2 uv_interp;
-#endif /* V3D_SHADING_TEXTURE_COLOR */
+#endif
#ifdef HAIR_SHADER
flat in float hair_rand;
#endif
-layout(location=0) out uint objectId;
-layout(location=1) out vec4 diffuseColor;
-layout(location=2) out vec4 specularColor;
+#ifdef MATDATA_PASS_ENABLED
+layout(location=0) out vec4 materialData;
+#endif
+#ifdef OBJECT_ID_PASS_ENABLED
+layout(location=1) out uint objectId;
+#endif
#ifdef NORMAL_VIEWPORT_PASS_ENABLED
-# ifdef WORKBENCH_ENCODE_NORMALS
-layout(location=3) out vec2 normalViewport;
-# else /* WORKBENCH_ENCODE_NORMALS */
-layout(location=3) out vec3 normalViewport;
-# endif /* WORKBENCH_ENCODE_NORMALS */
-#endif /* NORMAL_VIEWPORT_PASS_ENABLED */
+layout(location=2) out WB_Normal normalViewport;
+#endif
void main()
{
- objectId = uint(object_id);
-
-#ifdef NORMAL_VIEWPORT_PASS_ENABLED
- vec3 n = (gl_FrontFacing) ? normal_viewport : -normal_viewport;
- n = normalize(n);
-#endif
+#ifdef MATDATA_PASS_ENABLED
+ float metallic, roughness;
+ vec4 color;
-#ifdef V3D_SHADING_TEXTURE_COLOR
- diffuseColor = texture(image, uv_interp);
- if (diffuseColor.a < ImageTransparencyCutoff) {
+# ifdef V3D_SHADING_TEXTURE_COLOR
+ color = texture(image, uv_interp);
+ if (color.a < ImageTransparencyCutoff) {
discard;
}
-#else
- diffuseColor = vec4(materialDiffuseColor.rgb, 0.0);
-# ifdef STUDIOLIGHT_ORIENTATION_VIEWNORMAL
- specularColor = vec4(materialDiffuseColor.rgb, 0.0);
-
+ if (imageSrgb) {
+ color = srgb_to_linearrgb(color);
+ }
+# else
+ color.rgb = materialDiffuseColor;
# endif
-#endif /* V3D_SHADING_TEXTURE_COLOR */
-#ifdef HAIR_SHADER
- float hair_color_variation = hair_rand * 0.1;
- diffuseColor.rgb = clamp(diffuseColor.rgb - hair_color_variation, 0.0, 1.0);
-#endif
+# ifdef V3D_LIGHTING_MATCAP
+ /* Encode front facing in metallic channel. */
+ metallic = float(gl_FrontFacing);
+ roughness = 0.0;
+# else
+ metallic = materialMetallic;
+ roughness = materialRoughness;
+# endif
-#ifdef V3D_SHADING_SPECULAR_HIGHLIGHT
- specularColor = vec4(materialSpecularColor.rgb, materialRoughness);
# ifdef HAIR_SHADER
- specularColor.rgb = clamp(specularColor.rgb - hair_color_variation, 0.0, 1.0);
+ /* Add some variation to the hairs to avoid uniform look. */
+ float hair_variation = hair_rand * 0.1;
+ color = clamp(color - hair_variation, 0.0, 1.0);
+ metallic = clamp(materialMetallic - hair_variation, 0.0, 1.0);
+ roughness = clamp(materialRoughness - hair_variation, 0.0, 1.0);
# endif
+
+ materialData.rgb = color.rgb;
+ materialData.a = workbench_float_pair_encode(roughness, metallic);
+#endif /* MATDATA_PASS_ENABLED */
+
+#ifdef OBJECT_ID_PASS_ENABLED
+ objectId = uint(object_id);
#endif
#ifdef NORMAL_VIEWPORT_PASS_ENABLED
-# ifdef WORKBENCH_ENCODE_NORMALS
- diffuseColor.a = float(gl_FrontFacing);
- normalViewport = normal_encode(n);
-# else /* WORKBENCH_ENCODE_NORMALS */
- normalViewport = n;
-# endif /* WORKBENCH_ENCODE_NORMALS */
-# ifdef HAIR_SHADER
- diffuseColor.a = 0.5;
-# endif
-#endif /* NORMAL_VIEWPORT_PASS_ENABLED */
+ vec3 n = (gl_FrontFacing) ? normal_viewport : -normal_viewport;
+ n = normalize(n);
+ normalViewport = workbench_normal_encode(n);
+#endif
}
diff --git a/source/blender/draw/engines/workbench/shaders/workbench_prepass_vert.glsl b/source/blender/draw/engines/workbench/shaders/workbench_prepass_vert.glsl
index 66245ef0304..130575cbe9a 100644
--- a/source/blender/draw/engines/workbench/shaders/workbench_prepass_vert.glsl
+++ b/source/blender/draw/engines/workbench/shaders/workbench_prepass_vert.glsl
@@ -8,7 +8,8 @@ uniform mat3 NormalMatrix;
#ifndef HAIR_SHADER
in vec3 pos;
in vec3 nor;
-in vec2 uv;
+in vec2 u; /* active texture layer */
+#define uv u
#else /* HAIR_SHADER */
# ifdef V3D_SHADING_TEXTURE_COLOR
uniform samplerBuffer u; /* active texture layer */
diff --git a/source/blender/draw/engines/workbench/shaders/workbench_shadow_geom.glsl b/source/blender/draw/engines/workbench/shaders/workbench_shadow_geom.glsl
index 7418f86a58e..a2f23fbf3dc 100644
--- a/source/blender/draw/engines/workbench/shaders/workbench_shadow_geom.glsl
+++ b/source/blender/draw/engines/workbench/shaders/workbench_shadow_geom.glsl
@@ -55,20 +55,19 @@ void main()
vec3 v12 = vData[2].pos - vData[1].pos;
vec3 v13 = vData[3].pos - vData[1].pos;
-#ifdef DEGENERATE_THRESHOLD
- vec3 v20 = vData[0].pos - vData[2].pos;
- vec3 v23 = vData[3].pos - vData[2].pos;
+ vec3 n1 = cross(v12, v10);
+ vec3 n2 = cross(v13, v12);
- vec4 edges_lensqr = vec4(len_sqr(v10), len_sqr(v13), len_sqr(v20), len_sqr(v23));
- bvec4 degen_edges = lessThan(edges_lensqr, vec4(DEGENERATE_THRESHOLD));
+#ifdef DEGENERATE_THRESHOLD
+ /* Check if area is null */
+ vec2 faces_area = vec2(len_sqr(n1), len_sqr(n2));
+ bvec2 degen_faces = lessThan(abs(faces_area), vec2(DEGENERATE_THRESHOLD));
/* Both triangles are degenerate, abort. */
- if (any(degen_edges.xz) && any(degen_edges.yw))
+ if (all(degen_faces))
return;
#endif
- vec3 n1 = cross(v12, v10);
- vec3 n2 = cross(v13, v12);
vec2 facing = vec2(dot(n1, lightDirection),
dot(n2, lightDirection));
@@ -81,15 +80,15 @@ void main()
# ifndef DOUBLE_MANIFOLD
/* If the mesh is known to be manifold and we don't use double count,
* only create an quad if the we encounter a facing geom. */
- if ((any(degen_edges.xz) && backface.y) ||
- (any(degen_edges.yw) && backface.x))
+ if ((degen_faces.x && backface.y) ||
+ (degen_faces.y && backface.x))
return;
# endif
/* If one of the 2 triangles is degenerate, replace edge by a non-manifold one. */
- backface.x = (any(degen_edges.xz)) ? !backface.y : backface.x;
- backface.y = (any(degen_edges.yw)) ? !backface.x : backface.y;
- is_manifold = (any(degen_edges)) ? false : is_manifold;
+ backface.x = (degen_faces.x) ? !backface.y : backface.x;
+ backface.y = (degen_faces.y) ? !backface.x : backface.y;
+ is_manifold = (any(degen_faces)) ? false : is_manifold;
#endif
/* If both faces face the same direction it's not an outline edge. */
diff --git a/source/blender/draw/engines/workbench/shaders/workbench_world_light_lib.glsl b/source/blender/draw/engines/workbench/shaders/workbench_world_light_lib.glsl
index ab48aa5fa03..dbc29299fdc 100644
--- a/source/blender/draw/engines/workbench/shaders/workbench_world_light_lib.glsl
+++ b/source/blender/draw/engines/workbench/shaders/workbench_world_light_lib.glsl
@@ -1,129 +1,114 @@
-#define BLINN
-#if STUDIOLIGHT_SH_BANDS == 2
-vec3 spherical_harmonics(vec3 N, vec3 sh_coefs[STUDIOLIGHT_SH_MAX_COMPONENTS])
+/* [Drobot2014a] Low Level Optimizations for GCN */
+vec4 fast_rcp(vec4 v)
{
- /* http://www.geomerics.com/wp-content/uploads/2015/08/CEDEC_Geomerics_ReconstructingDiffuseLighting1.pdf */
- /* Highly optimized form, precompute as much as we can. */
- /**
- * R1 = 0.5 * vec3(L3.r, L2.r, L1.r);
- * sh_coefs[0..2] = R1 / length(R1);
- **/
- vec3 q;
- q.x = dot(sh_coefs[1], N);
- q.y = dot(sh_coefs[2], N);
- q.z = dot(sh_coefs[3], N);
- q = 0.5 * q + 0.5;
-
- /**
- * R0 = L0.r;
- * lr1_r0 = lenR1 / R0;
- * p = 1.0 + 2.0 * lr1_r0;
- * a = (1.0 - lr1_r0) / (1.0 + lr1_r0);
- * return R0 * (a + (1.0 - a) * (p + 1.0) * pow(q, p));
- *
- * sh_coefs[4] = p;
- * sh_coefs[5] = R0 * a;
- * sh_coefs[0] = R0 * (1.0 - a) * (p + 1.0);
- **/
- q = pow(q, sh_coefs[4]);
- return sh_coefs[0] * q + sh_coefs[5];
+ return intBitsToFloat(0x7eef370b - floatBitsToInt(v));
}
-#else
-
-vec3 spherical_harmonics(vec3 N, vec3 sh_coefs[STUDIOLIGHT_SH_MAX_COMPONENTS])
+vec3 brdf_approx(vec3 spec_color, float roughness, float NV)
{
- vec3 sh = 0.282095 * sh_coefs[0];
-
-# if STUDIOLIGHT_SH_BANDS > 1
- float nx = N.x;
- float ny = N.y;
- float nz = N.z;
- sh += -0.488603 * nz * sh_coefs[1];
- sh += 0.488603 * ny * sh_coefs[2];
- sh += -0.488603 * nx * sh_coefs[3];
-# endif
-# if STUDIOLIGHT_SH_BANDS > 2
- float nx2 = nx * nx;
- float ny2 = ny * ny;
- float nz2 = nz * nz;
- sh += 1.092548 * nx * nz * sh_coefs[4];
- sh += -1.092548 * nz * ny * sh_coefs[5];
- sh += 0.315392 * (3.0 * ny2 - 1.0) * sh_coefs[6];
- sh += -1.092548 * nx * ny * sh_coefs[7];
- sh += 0.546274 * (nx2 - nz2) * sh_coefs[8];
-# endif
-# if STUDIOLIGHT_SH_BANDS > 4
- float nx4 = nx2 * nx2;
- float ny4 = ny2 * ny2;
- float nz4 = nz2 * nz2;
- sh += (2.5033429417967046 * nx * nz * (nx2 - nz2)) * sh_coefs[9];
- sh += (-1.7701307697799304 * nz * ny * (3.0 * nx2 - nz2)) * sh_coefs[10];
- sh += (0.9461746957575601 * nz * nx * (-1.0 +7.0*ny2)) * sh_coefs[11];
- sh += (-0.6690465435572892 * nz * ny * (-3.0 + 7.0 * ny2)) * sh_coefs[12];
- sh += ((105.0*ny4-90.0*ny2+9.0)/28.359261614) * sh_coefs[13];
- sh += (-0.6690465435572892 * nx * ny * (-3.0 + 7.0 * ny2)) * sh_coefs[14];
- sh += (0.9461746957575601 * (nx2 - nz2) * (-1.0 + 7.0 * ny2)) * sh_coefs[15];
- sh += (-1.7701307697799304 * nx * ny * (nx2 - 3.0 * nz2)) * sh_coefs[16];
- sh += (0.6258357354491761 * (nx4 - 6.0 * nz2 * nx2 + nz4)) * sh_coefs[17];
-# endif
- return sh;
+ /* Very rough own approx. We don't need it to be correct, just fast.
+ * Just simulate fresnel effect with roughness attenuation. */
+ float fresnel = exp2(-8.35 * NV) * (1.0 - roughness);
+ return mix(spec_color, vec3(1.0), fresnel);
}
-#endif
-vec3 get_world_diffuse_light(WorldData world_data, vec3 N)
+void prep_specular(
+ vec3 L, vec3 I, vec3 N, vec3 R,
+ out float NL, out float wrapped_NL, out float spec_angle)
{
- return spherical_harmonics(N, world_data.spherical_harmonics_coefs);
+ wrapped_NL = dot(L, R);
+ vec3 half_dir = normalize(L + I);
+ spec_angle = clamp(dot(half_dir, N), 0.0, 1.0);
+ NL = clamp(dot(L, N), 0.0, 1.0);
}
-vec3 get_camera_diffuse_light(WorldData world_data, vec3 N)
+/* Normalized Blinn shading */
+vec4 blinn_specular(vec4 shininess, vec4 spec_angle, vec4 NL)
{
- return spherical_harmonics(vec3(N.x, -N.z, N.y), world_data.spherical_harmonics_coefs);
+ /* Pi is already divided in the lamp power.
+ * normalization_factor = (shininess + 8.0) / (8.0 * M_PI) */
+ vec4 normalization_factor = shininess * 0.125 + 1.0;
+ vec4 spec_light = pow(spec_angle, shininess) * NL * normalization_factor;
+
+ return spec_light;
}
-/* N And I are in View Space. */
-vec3 get_world_specular_light(vec4 specular_data, LightData light_data, vec3 N, vec3 I)
+/* NL need to be unclamped. w in [0..1] range. */
+vec4 wrapped_lighting(vec4 NL, vec4 w)
{
-#ifdef V3D_SHADING_SPECULAR_HIGHLIGHT
- vec3 specular_light = specular_data.rgb * light_data.specular_color.rgb * light_data.specular_color.a;
-
- float shininess = exp2(10.0 * (1.0 - specular_data.a) + 1);
-
-# ifdef BLINN
- float normalization_factor = (shininess + 8.0) / (8.0 * M_PI);
- vec3 L = -light_data.light_direction_vs.xyz;
- vec3 halfDir = normalize(L + I);
- float spec_angle = max(dot(halfDir, N), 0.0);
- float NL = max(dot(L, N), 0.0);
- float specular_influence = pow(spec_angle, shininess) * NL * normalization_factor;
-
-# else
- vec3 reflection_vector = reflect(I, N);
- float spec_angle = max(dot(light_data.light_direction_vs.xyz, reflection_vector), 0.0);
- float specular_influence = pow(spec_angle, shininess);
-# endif
-
- vec3 specular_color = specular_light * specular_influence;
-
-#else /* V3D_SHADING_SPECULAR_HIGHLIGHT */
- vec3 specular_color = vec3(0.0);
-#endif /* V3D_SHADING_SPECULAR_HIGHLIGHT */
- return specular_color;
+ vec4 w_1 = w + 1.0;
+ vec4 denom = fast_rcp(w_1 * w_1);
+ return clamp((NL + w) * denom, 0.0, 1.0);
}
-vec3 get_world_specular_lights(WorldData world_data, vec4 specular_data, vec3 N, vec3 I)
+vec3 get_world_lighting(
+ WorldData world_data,
+ vec3 diffuse_color, vec3 specular_color, float roughness,
+ vec3 N, vec3 I)
{
- vec3 specular_light = vec3(0.0);
- /* Manual loop unrolling provide much better perf. */
- if (world_data.num_lights > 0) {
- specular_light += get_world_specular_light(specular_data, world_data.lights[0], N, I);
- }
- if (world_data.num_lights > 1) {
- specular_light += get_world_specular_light(specular_data, world_data.lights[1], N, I);
- }
- if (world_data.num_lights > 2) {
- specular_light += get_world_specular_light(specular_data, world_data.lights[2], N, I);
- }
- return specular_light;
+ vec3 specular_light = world_data.ambient_color.rgb;
+ vec3 diffuse_light = world_data.ambient_color.rgb;
+ vec4 wrap = vec4(
+ world_data.lights[0].diffuse_color_wrap.a,
+ world_data.lights[1].diffuse_color_wrap.a,
+ world_data.lights[2].diffuse_color_wrap.a,
+ world_data.lights[3].diffuse_color_wrap.a
+ );
+
+#ifdef V3D_SHADING_SPECULAR_HIGHLIGHT
+ /* Prepare Specular computation. Eval 4 lights at once. */
+ vec3 R = -reflect(I, N);
+ vec4 spec_angle, spec_NL, wrap_NL;
+ prep_specular(world_data.lights[0].direction.xyz, I, N, R, spec_NL.x, wrap_NL.x, spec_angle.x);
+ prep_specular(world_data.lights[1].direction.xyz, I, N, R, spec_NL.y, wrap_NL.y, spec_angle.y);
+ prep_specular(world_data.lights[2].direction.xyz, I, N, R, spec_NL.z, wrap_NL.z, spec_angle.z);
+ prep_specular(world_data.lights[3].direction.xyz, I, N, R, spec_NL.w, wrap_NL.w, spec_angle.w);
+
+ vec4 gloss = vec4(1.0 - roughness);
+ /* Reduce gloss for smooth light. (simulate bigger light) */
+ gloss *= 1.0 - wrap;
+ vec4 shininess = exp2(10.0 * gloss + 1.0);
+
+ vec4 spec_light = blinn_specular(shininess, spec_angle, spec_NL);
+
+ /* Simulate Env. light. */
+ vec4 w = mix(wrap, vec4(1.0), roughness);
+ vec4 spec_env = wrapped_lighting(wrap_NL, w);
+
+ spec_light = mix(spec_light, spec_env, wrap * wrap);
+
+ /* Multiply result by lights specular colors. */
+ specular_light += spec_light.x * world_data.lights[0].specular_color.rgb;
+ specular_light += spec_light.y * world_data.lights[1].specular_color.rgb;
+ specular_light += spec_light.z * world_data.lights[2].specular_color.rgb;
+ specular_light += spec_light.w * world_data.lights[3].specular_color.rgb;
+
+ float NV = clamp(dot(N, I), 0.0, 1.0);
+ specular_color = brdf_approx(specular_color, roughness, NV);
+#endif
+ specular_light *= specular_color;
+
+ /* Prepare diffuse computation. Eval 4 lights at once. */
+ vec4 diff_NL;
+ diff_NL.x = dot(world_data.lights[0].direction.xyz, N);
+ diff_NL.y = dot(world_data.lights[1].direction.xyz, N);
+ diff_NL.z = dot(world_data.lights[2].direction.xyz, N);
+ diff_NL.w = dot(world_data.lights[3].direction.xyz, N);
+
+ vec4 diff_light = wrapped_lighting(diff_NL, wrap);
+
+ /* Multiply result by lights diffuse colors. */
+ diffuse_light += diff_light.x * world_data.lights[0].diffuse_color_wrap.rgb;
+ diffuse_light += diff_light.y * world_data.lights[1].diffuse_color_wrap.rgb;
+ diffuse_light += diff_light.z * world_data.lights[2].diffuse_color_wrap.rgb;
+ diffuse_light += diff_light.w * world_data.lights[3].diffuse_color_wrap.rgb;
+
+ /* Energy conservation with colored specular look strange.
+ * Limit this strangeness by using mono-chromatic specular intensity. */
+ float spec_energy = dot(specular_color, vec3(0.33333));
+
+ diffuse_light *= diffuse_color * (1.0 - spec_energy);
+
+ return diffuse_light + specular_light;
}
diff --git a/source/blender/draw/engines/workbench/workbench_data.c b/source/blender/draw/engines/workbench/workbench_data.c
index aa99883bb6b..ab9417705e5 100644
--- a/source/blender/draw/engines/workbench/workbench_data.c
+++ b/source/blender/draw/engines/workbench/workbench_data.c
@@ -24,7 +24,7 @@ void workbench_private_data_init(WORKBENCH_PrivateData *wpd)
wpd->use_color_view_settings = true;
}
else if (v3d->shading.type == OB_RENDER &&
- BKE_scene_uses_blender_opengl(scene))
+ BKE_scene_uses_blender_workbench(scene))
{
wpd->shading = scene->display.shading;
wpd->use_color_view_settings = true;
@@ -36,17 +36,17 @@ void workbench_private_data_init(WORKBENCH_PrivateData *wpd)
if (wpd->shading.light == V3D_LIGHTING_MATCAP) {
wpd->studio_light = BKE_studiolight_find(
- wpd->shading.matcap, STUDIOLIGHT_ORIENTATION_VIEWNORMAL);
+ wpd->shading.matcap, STUDIOLIGHT_TYPE_MATCAP);
}
else {
wpd->studio_light = BKE_studiolight_find(
- wpd->shading.studio_light, STUDIOLIGHT_ORIENTATION_CAMERA | STUDIOLIGHT_ORIENTATION_WORLD);
+ wpd->shading.studio_light, STUDIOLIGHT_TYPE_STUDIO);
}
/* If matcaps are missing, use this as fallback. */
if (UNLIKELY(wpd->studio_light == NULL)) {
wpd->studio_light = BKE_studiolight_find(
- wpd->shading.studio_light, STUDIOLIGHT_ORIENTATION_CAMERA | STUDIOLIGHT_ORIENTATION_WORLD);
+ wpd->shading.studio_light, STUDIOLIGHT_TYPE_STUDIO);
}
wpd->shadow_multiplier = 1.0 - wpd->shading.shadow_intensity;
@@ -55,13 +55,14 @@ void workbench_private_data_init(WORKBENCH_PrivateData *wpd)
wd->matcap_orientation = (wpd->shading.flag & V3D_SHADING_MATCAP_FLIP_X) != 0;
wd->background_alpha = (DRW_state_is_image_render() && scene->r.alphamode == R_ALPHAPREMUL) ? 0.0f : 1.0f;
- if (!v3d || ((v3d->shading.background_type == V3D_SHADING_BACKGROUND_WORLD) &&
- (scene->world != NULL)))
+ if ((scene->world != NULL) &&
+ (!v3d || (v3d && ((v3d->shading.background_type == V3D_SHADING_BACKGROUND_WORLD) ||
+ (v3d->shading.type == OB_RENDER)))))
{
copy_v3_v3(wd->background_color_low, &scene->world->horr);
copy_v3_v3(wd->background_color_high, &scene->world->horr);
}
- else if (v3d->shading.background_type == V3D_SHADING_BACKGROUND_VIEWPORT) {
+ else if (v3d && (v3d->shading.background_type == V3D_SHADING_BACKGROUND_VIEWPORT)) {
copy_v3_v3(wd->background_color_low, v3d->shading.background_color);
copy_v3_v3(wd->background_color_high, v3d->shading.background_color);
}
@@ -79,11 +80,14 @@ void workbench_private_data_init(WORKBENCH_PrivateData *wpd)
zero_v3(wd->background_color_high);
}
- studiolight_update_world(wpd->studio_light, wd);
+ studiolight_update_world(wpd, wpd->studio_light, wd);
copy_v3_v3(wd->object_outline_color, wpd->shading.object_outline_color);
wd->object_outline_color[3] = 1.0f;
+ wd->curvature_ridge = 0.5f / max_ff(SQUARE(wpd->shading.curvature_ridge_factor), 1e-4f);
+ wd->curvature_valley = 0.7f / max_ff(SQUARE(wpd->shading.curvature_valley_factor), 1e-4f);
+
wpd->world_ubo = DRW_uniformbuffer_create(sizeof(WORKBENCH_UBO_World), &wpd->world_data);
/* Cavity settings */
@@ -108,7 +112,12 @@ void workbench_private_data_init(WORKBENCH_PrivateData *wpd)
wpd->ssao_params[3] = 0;
/* distance, factor, factor, attenuation */
- copy_v4_fl4(wpd->ssao_settings, scene->display.matcap_ssao_distance, wpd->shading.cavity_valley_factor, wpd->shading.cavity_ridge_factor, scene->display.matcap_ssao_attenuation);
+ copy_v4_fl4(
+ wpd->ssao_settings,
+ scene->display.matcap_ssao_distance,
+ wpd->shading.cavity_valley_factor,
+ wpd->shading.cavity_ridge_factor,
+ scene->display.matcap_ssao_attenuation);
/* invert the view matrix */
DRW_viewport_matrix_get(wpd->winmat, DRW_MAT_WIN);
@@ -153,32 +162,12 @@ void workbench_private_data_get_light_direction(WORKBENCH_PrivateData *wpd, floa
DRW_viewport_matrix_get(view_matrix, DRW_MAT_VIEW);
copy_v3_v3(r_light_direction, scene->display.light_direction);
- negate_v3(r_light_direction);
-
- {
- WORKBENCH_UBO_Light *light = &wd->lights[0];
- mul_v3_mat3_m4v3(light->light_direction_vs, view_matrix, r_light_direction);
- light->light_direction_vs[3] = 0.0f;
- copy_v3_fl(light->specular_color, 1.0f);
- light->energy = 1.0f;
- copy_v4_v4(wd->shadow_direction_vs, light->light_direction_vs);
- wd->num_lights = 1;
- }
+ SWAP(float, r_light_direction[2], r_light_direction[1]);
+ r_light_direction[2] = -r_light_direction[2];
+ r_light_direction[0] = -r_light_direction[0];
- if (!STUDIOLIGHT_ORIENTATION_WORLD_ENABLED(wpd)) {
- int light_index = 0;
- for (int index = 0 ; index < 3; index++) {
- SolidLight *sl = &U.light[index];
- if (sl->flag) {
- WORKBENCH_UBO_Light *light = &wd->lights[light_index++];
- copy_v4_v4(light->light_direction_vs, sl->vec);
- negate_v3(light->light_direction_vs);
- copy_v4_v4(light->specular_color, sl->spec);
- light->energy = 1.0f;
- }
- }
- wd->num_lights = light_index;
- }
+ /* Shadow direction. */
+ mul_v3_mat3_m4v3(wd->shadow_direction_vs, view_matrix, r_light_direction);
DRW_uniformbuffer_update(wpd->world_ubo, wd);
}
diff --git a/source/blender/draw/engines/workbench/workbench_deferred.c b/source/blender/draw/engines/workbench/workbench_deferred.c
index 2a5d97078b8..8663bd559e4 100644
--- a/source/blender/draw/engines/workbench/workbench_deferred.c
+++ b/source/blender/draw/engines/workbench/workbench_deferred.c
@@ -31,6 +31,7 @@
#include "BLI_dynstr.h"
#include "BLI_utildefines.h"
#include "BLI_rand.h"
+#include "BLI_string_utils.h"
#include "BKE_hair.h"
#include "BKE_node.h"
@@ -47,6 +48,7 @@
#include "GPU_shader.h"
#include "GPU_texture.h"
+#include "GPU_extensions.h"
#include "../eevee/eevee_lut.h" /* TODO find somewhere to share blue noise Table */
@@ -59,9 +61,10 @@
#endif
static struct {
- struct GPUShader *prepass_sh_cache[MAX_SHADERS];
- struct GPUShader *composite_sh_cache[MAX_SHADERS];
- struct GPUShader *cavity_sh;
+ struct GPUShader *prepass_sh_cache[MAX_PREPASS_SHADERS];
+ struct GPUShader *composite_sh_cache[MAX_COMPOSITE_SHADERS];
+ struct GPUShader *cavity_sh[MAX_CAVITY_SHADERS];
+ struct GPUShader *background_sh[2];
struct GPUShader *ghost_resolve_sh;
struct GPUShader *shadow_fail_sh;
struct GPUShader *shadow_fail_manifold_sh;
@@ -74,13 +77,12 @@ static struct {
struct GPUTexture *object_id_tx; /* ref only, not alloced */
struct GPUTexture *color_buffer_tx; /* ref only, not alloced */
struct GPUTexture *cavity_buffer_tx; /* ref only, not alloced */
- struct GPUTexture *specular_buffer_tx; /* ref only, not alloced */
+ struct GPUTexture *metallic_buffer_tx; /* ref only, not alloced */
struct GPUTexture *normal_buffer_tx; /* ref only, not alloced */
struct GPUTexture *composite_buffer_tx; /* ref only, not alloced */
SceneDisplay display; /* world light direction for shadows */
int next_object_id;
- float normal_world_matrix[3][3];
struct GPUUniformBuffer *sampling_ubo;
struct GPUTexture *jitter_tx;
@@ -94,6 +96,7 @@ extern char datatoc_workbench_prepass_vert_glsl[];
extern char datatoc_workbench_prepass_frag_glsl[];
extern char datatoc_workbench_cavity_frag_glsl[];
extern char datatoc_workbench_deferred_composite_frag_glsl[];
+extern char datatoc_workbench_deferred_background_frag_glsl[];
extern char datatoc_workbench_ghost_resolve_frag_glsl[];
extern char datatoc_workbench_shadow_vert_glsl[];
@@ -106,6 +109,7 @@ extern char datatoc_workbench_cavity_lib_glsl[];
extern char datatoc_workbench_common_lib_glsl[];
extern char datatoc_workbench_data_lib_glsl[];
extern char datatoc_workbench_object_outline_lib_glsl[];
+extern char datatoc_workbench_curvature_lib_glsl[];
extern char datatoc_workbench_world_light_lib_glsl[];
extern char datatoc_gpu_shader_depth_only_frag_glsl[];
@@ -120,12 +124,15 @@ static char *workbench_build_composite_frag(WORKBENCH_PrivateData *wpd)
BLI_dynstr_append(ds, datatoc_workbench_common_lib_glsl);
BLI_dynstr_append(ds, datatoc_workbench_background_lib_glsl);
- if ((wpd->shading.light & V3D_LIGHTING_MATCAP) || (wpd->shading.light & V3D_LIGHTING_STUDIO) || (wpd->shading.flag & V3D_SHADING_SPECULAR_HIGHLIGHT)) {
+ if (!FLAT_ENABLED(wpd)) {
BLI_dynstr_append(ds, datatoc_workbench_world_light_lib_glsl);
}
- if (wpd->shading.flag & V3D_SHADING_OBJECT_OUTLINE) {
+ if (OBJECT_OUTLINE_ENABLED(wpd)) {
BLI_dynstr_append(ds, datatoc_workbench_object_outline_lib_glsl);
}
+ if (CURVATURE_ENABLED(wpd)) {
+ BLI_dynstr_append(ds, datatoc_workbench_curvature_lib_glsl);
+ }
BLI_dynstr_append(ds, datatoc_workbench_deferred_composite_frag_glsl);
@@ -166,13 +173,26 @@ static char *workbench_build_prepass_vert(bool is_hair)
return str;
}
-static char *workbench_build_cavity_frag(void)
+static char *workbench_build_cavity_frag(bool cavity, bool curvature, bool high_dpi)
{
char *str = NULL;
DynStr *ds = BLI_dynstr_new();
+ if (cavity) {
+ BLI_dynstr_append(ds, "#define USE_CAVITY\n");
+ }
+ if (curvature) {
+ BLI_dynstr_append(ds, "#define USE_CURVATURE\n");
+ }
+ if (high_dpi) {
+ BLI_dynstr_append(ds, "#define CURVATURE_OFFSET 2\n");
+ }
+ if (NORMAL_ENCODING_ENABLED()) {
+ BLI_dynstr_append(ds, "#define WORKBENCH_ENCODE_NORMALS\n");
+ }
BLI_dynstr_append(ds, datatoc_workbench_common_lib_glsl);
+ BLI_dynstr_append(ds, datatoc_workbench_curvature_lib_glsl);
BLI_dynstr_append(ds, datatoc_workbench_cavity_frag_glsl);
BLI_dynstr_append(ds, datatoc_workbench_cavity_lib_glsl);
@@ -181,45 +201,79 @@ static char *workbench_build_cavity_frag(void)
return str;
}
-static void ensure_deferred_shaders(WORKBENCH_PrivateData *wpd, int index, bool use_textures, bool is_hair)
+static GPUShader *workbench_cavity_shader_get(bool cavity, bool curvature)
{
+ const bool high_dpi = (U.pixelsize > 1.5f);
+ int index = 0;
+ SET_FLAG_FROM_TEST(index, cavity, 1 << 0);
+ SET_FLAG_FROM_TEST(index, curvature, 1 << 1);
+ SET_FLAG_FROM_TEST(index, high_dpi, 1 << 2);
+
+ GPUShader **sh = &e_data.cavity_sh[index];
+ if (*sh == NULL) {
+ char *cavity_frag = workbench_build_cavity_frag(cavity, curvature, high_dpi);
+ *sh = DRW_shader_create_fullscreen(cavity_frag, NULL);
+ MEM_freeN(cavity_frag);
+ }
+ return *sh;
+}
+
+static GPUShader *ensure_deferred_prepass_shader(WORKBENCH_PrivateData *wpd, bool use_textures, bool is_hair)
+{
+ int index = workbench_material_get_prepass_shader_index(wpd, use_textures, is_hair);
if (e_data.prepass_sh_cache[index] == NULL) {
char *defines = workbench_material_build_defines(wpd, use_textures, is_hair);
- char *composite_frag = workbench_build_composite_frag(wpd);
char *prepass_vert = workbench_build_prepass_vert(is_hair);
char *prepass_frag = workbench_build_prepass_frag();
e_data.prepass_sh_cache[index] = DRW_shader_create(
prepass_vert, NULL,
prepass_frag, defines);
- if (!use_textures && !is_hair) {
- e_data.composite_sh_cache[index] = DRW_shader_create_fullscreen(composite_frag, defines);
- }
MEM_freeN(prepass_vert);
MEM_freeN(prepass_frag);
+ MEM_freeN(defines);
+ }
+ return e_data.prepass_sh_cache[index];
+}
+
+static GPUShader *ensure_deferred_composite_shader(WORKBENCH_PrivateData *wpd)
+{
+ int index = workbench_material_get_composite_shader_index(wpd);
+ if (e_data.composite_sh_cache[index] == NULL) {
+ char *defines = workbench_material_build_defines(wpd, false, false);
+ char *composite_frag = workbench_build_composite_frag(wpd);
+ e_data.composite_sh_cache[index] = DRW_shader_create_fullscreen(composite_frag, defines);
MEM_freeN(composite_frag);
MEM_freeN(defines);
}
+ return e_data.composite_sh_cache[index];
}
-static void select_deferred_shaders(WORKBENCH_PrivateData *wpd)
+static GPUShader *ensure_background_shader(WORKBENCH_PrivateData *wpd)
{
- int index_solid = workbench_material_get_shader_index(wpd, false, false);
- int index_solid_hair = workbench_material_get_shader_index(wpd, false, true);
- int index_texture = workbench_material_get_shader_index(wpd, true, false);
- int index_texture_hair = workbench_material_get_shader_index(wpd, true, true);
-
- ensure_deferred_shaders(wpd, index_solid, false, false);
- ensure_deferred_shaders(wpd, index_solid_hair, false, true);
- ensure_deferred_shaders(wpd, index_texture, true, false);
- ensure_deferred_shaders(wpd, index_texture_hair, true, true);
-
- wpd->prepass_solid_sh = e_data.prepass_sh_cache[index_solid];
- wpd->prepass_solid_hair_sh = e_data.prepass_sh_cache[index_solid_hair];
- wpd->prepass_texture_sh = e_data.prepass_sh_cache[index_texture];
- wpd->prepass_texture_hair_sh = e_data.prepass_sh_cache[index_texture_hair];
- wpd->composite_sh = e_data.composite_sh_cache[index_solid];
+ const int index = OBJECT_OUTLINE_ENABLED(wpd) ? 1 : 0;
+ if (e_data.background_sh[index] == NULL) {
+ const char *defines = (index) ? "#define V3D_SHADING_OBJECT_OUTLINE\n" : NULL;
+ char *frag = BLI_string_joinN(
+ datatoc_workbench_data_lib_glsl,
+ datatoc_workbench_common_lib_glsl,
+ datatoc_workbench_background_lib_glsl,
+ datatoc_workbench_object_outline_lib_glsl,
+ datatoc_workbench_deferred_background_frag_glsl);
+ e_data.background_sh[index] = DRW_shader_create_fullscreen(frag, defines);
+ MEM_freeN(frag);
+ }
+ return e_data.background_sh[index];
}
+static void select_deferred_shaders(WORKBENCH_PrivateData *wpd)
+{
+ wpd->prepass_solid_sh = ensure_deferred_prepass_shader(wpd, false, false);
+ wpd->prepass_solid_hair_sh = ensure_deferred_prepass_shader(wpd, false, true);
+ wpd->prepass_texture_sh = ensure_deferred_prepass_shader(wpd, true, false);
+ wpd->prepass_texture_hair_sh = ensure_deferred_prepass_shader(wpd, true, true);
+ wpd->composite_sh = ensure_deferred_composite_shader(wpd);
+ wpd->background_sh = ensure_background_shader(wpd);
+}
/* Using Hammersley distribution */
static float *create_disk_samples(int num_samples, int num_iterations)
@@ -294,14 +348,15 @@ void workbench_deferred_engine_init(WORKBENCH_Data *vedata)
}
if (!e_data.next_object_id) {
- memset(e_data.prepass_sh_cache, 0x00, sizeof(struct GPUShader *) * MAX_SHADERS);
- memset(e_data.composite_sh_cache, 0x00, sizeof(struct GPUShader *) * MAX_SHADERS);
+ memset(e_data.prepass_sh_cache, 0, sizeof(e_data.prepass_sh_cache));
+ memset(e_data.composite_sh_cache, 0, sizeof(e_data.composite_sh_cache));
e_data.next_object_id = 1;
#ifdef DEBUG_SHADOW_VOLUME
const char *shadow_frag = datatoc_workbench_shadow_debug_frag_glsl;
#else
const char *shadow_frag = datatoc_gpu_shader_depth_only_frag_glsl;
#endif
+ /* TODO only compile on demand */
e_data.shadow_pass_sh = DRW_shader_create(
datatoc_workbench_shadow_vert_glsl,
datatoc_workbench_shadow_geom_glsl,
@@ -336,10 +391,6 @@ void workbench_deferred_engine_init(WORKBENCH_Data *vedata)
shadow_frag,
"#define SHADOW_FAIL\n");
- char *cavity_frag = workbench_build_cavity_frag();
- e_data.cavity_sh = DRW_shader_create_fullscreen(cavity_frag, NULL);
- MEM_freeN(cavity_frag);
-
e_data.ghost_resolve_sh = DRW_shader_create_fullscreen(datatoc_workbench_ghost_resolve_frag_glsl, NULL);
}
workbench_volume_engine_init();
@@ -352,27 +403,35 @@ void workbench_deferred_engine_init(WORKBENCH_Data *vedata)
{
const float *viewport_size = DRW_viewport_size_get();
const int size[2] = {(int)viewport_size[0], (int)viewport_size[1]};
- e_data.object_id_tx = DRW_texture_pool_query_2D(size[0], size[1], GPU_R32UI, &draw_engine_workbench_solid);
- e_data.color_buffer_tx = DRW_texture_pool_query_2D(size[0], size[1], GPU_RGBA8, &draw_engine_workbench_solid);
- e_data.cavity_buffer_tx = DRW_texture_pool_query_2D(size[0], size[1], GPU_RG16, &draw_engine_workbench_solid);
- e_data.specular_buffer_tx = DRW_texture_pool_query_2D(size[0], size[1], GPU_RGBA8, &draw_engine_workbench_solid);
- e_data.composite_buffer_tx = DRW_texture_pool_query_2D(
- size[0], size[1], GPU_RGBA16F, &draw_engine_workbench_solid);
-
- if (NORMAL_ENCODING_ENABLED()) {
- e_data.normal_buffer_tx = DRW_texture_pool_query_2D(
- size[0], size[1], GPU_RG16, &draw_engine_workbench_solid);
+ const GPUTextureFormat nor_tex_format = NORMAL_ENCODING_ENABLED() ? GPU_RG16 : GPU_RGBA32F;
+ const GPUTextureFormat comp_tex_format = DRW_state_is_image_render() ? GPU_RGBA16F : GPU_R11F_G11F_B10F;
+ const GPUTextureFormat id_tex_format = OBJECT_ID_PASS_ENABLED(wpd) ? GPU_R32UI : GPU_R8;
+
+ e_data.object_id_tx = NULL;
+ e_data.color_buffer_tx = NULL;
+ e_data.composite_buffer_tx = NULL;
+ e_data.normal_buffer_tx = NULL;
+ e_data.cavity_buffer_tx = NULL;
+
+ e_data.composite_buffer_tx = DRW_texture_pool_query_2D(size[0], size[1], comp_tex_format, &draw_engine_workbench_solid);
+
+ if (MATDATA_PASS_ENABLED(wpd) || GPU_unused_fb_slot_workaround()) {
+ e_data.color_buffer_tx = DRW_texture_pool_query_2D(size[0], size[1], GPU_RGBA8, &draw_engine_workbench_solid);
}
- else {
- e_data.normal_buffer_tx = DRW_texture_pool_query_2D(
- size[0], size[1], GPU_RGBA32F, &draw_engine_workbench_solid);
+ if (OBJECT_ID_PASS_ENABLED(wpd) || GPU_unused_fb_slot_workaround()) {
+ e_data.object_id_tx = DRW_texture_pool_query_2D(size[0], size[1], id_tex_format, &draw_engine_workbench_solid);
+ }
+ if (NORMAL_VIEWPORT_PASS_ENABLED(wpd)) {
+ e_data.normal_buffer_tx = DRW_texture_pool_query_2D(size[0], size[1], nor_tex_format, &draw_engine_workbench_solid);
+ }
+ if (CAVITY_ENABLED(wpd)) {
+ e_data.cavity_buffer_tx = DRW_texture_pool_query_2D(size[0], size[1], GPU_R16, &draw_engine_workbench_solid);
}
GPU_framebuffer_ensure_config(&fbl->prepass_fb, {
GPU_ATTACHMENT_TEXTURE(dtxl->depth),
- GPU_ATTACHMENT_TEXTURE(e_data.object_id_tx),
GPU_ATTACHMENT_TEXTURE(e_data.color_buffer_tx),
- GPU_ATTACHMENT_TEXTURE(e_data.specular_buffer_tx),
+ GPU_ATTACHMENT_TEXTURE(e_data.object_id_tx),
GPU_ATTACHMENT_TEXTURE(e_data.normal_buffer_tx),
});
GPU_framebuffer_ensure_config(&fbl->cavity_fb, {
@@ -387,10 +446,22 @@ void workbench_deferred_engine_init(WORKBENCH_Data *vedata)
GPU_ATTACHMENT_NONE,
GPU_ATTACHMENT_TEXTURE(e_data.composite_buffer_tx),
});
+
+ if (!MATDATA_PASS_ENABLED(wpd) && !GPU_unused_fb_slot_workaround()) {
+ e_data.color_buffer_tx = DRW_texture_pool_query_2D(size[0], size[1], GPU_RGBA8, &draw_engine_workbench_solid);
+ }
+
GPU_framebuffer_ensure_config(&fbl->effect_fb, {
GPU_ATTACHMENT_NONE,
GPU_ATTACHMENT_TEXTURE(e_data.color_buffer_tx),
});
+
+ if (OBJECT_ID_PASS_ENABLED(wpd)) {
+ GPU_framebuffer_ensure_config(&fbl->id_clear_fb, {
+ GPU_ATTACHMENT_NONE,
+ GPU_ATTACHMENT_TEXTURE(e_data.object_id_tx),
+ });
+ }
}
{
@@ -437,21 +508,29 @@ void workbench_deferred_engine_init(WORKBENCH_Data *vedata)
workbench_aa_create_pass(vedata, &e_data.color_buffer_tx);
}
- {
+ if (CAVITY_ENABLED(wpd)) {
int state = DRW_STATE_WRITE_COLOR;
+ GPUShader *shader = workbench_cavity_shader_get(SSAO_ENABLED(wpd), CURVATURE_ENABLED(wpd));
psl->cavity_pass = DRW_pass_create("Cavity", state);
- DRWShadingGroup *grp = DRW_shgroup_create(e_data.cavity_sh, psl->cavity_pass);
- DRW_shgroup_uniform_texture_ref(grp, "depthBuffer", &dtxl->depth);
- DRW_shgroup_uniform_texture_ref(grp, "colorBuffer", &e_data.color_buffer_tx);
+ DRWShadingGroup *grp = DRW_shgroup_create(shader, psl->cavity_pass);
DRW_shgroup_uniform_texture_ref(grp, "normalBuffer", &e_data.normal_buffer_tx);
-
- DRW_shgroup_uniform_vec2(grp, "invertedViewportSize", DRW_viewport_invert_size_get(), 1);
- DRW_shgroup_uniform_vec4(grp, "viewvecs[0]", (float *)wpd->viewvecs, 3);
- DRW_shgroup_uniform_vec4(grp, "ssao_params", wpd->ssao_params, 1);
- DRW_shgroup_uniform_vec4(grp, "ssao_settings", wpd->ssao_settings, 1);
- DRW_shgroup_uniform_mat4(grp, "WinMatrix", wpd->winmat);
- DRW_shgroup_uniform_texture(grp, "ssao_jitter", e_data.jitter_tx);
DRW_shgroup_uniform_block(grp, "samples_block", e_data.sampling_ubo);
+
+ if (SSAO_ENABLED(wpd)) {
+ DRW_shgroup_uniform_texture_ref(grp, "depthBuffer", &dtxl->depth);
+ DRW_shgroup_uniform_vec2(grp, "invertedViewportSize", DRW_viewport_invert_size_get(), 1);
+ DRW_shgroup_uniform_vec4(grp, "viewvecs[0]", (float *)wpd->viewvecs, 3);
+ DRW_shgroup_uniform_vec4(grp, "ssao_params", wpd->ssao_params, 1);
+ DRW_shgroup_uniform_vec4(grp, "ssao_settings", wpd->ssao_settings, 1);
+ DRW_shgroup_uniform_mat4(grp, "WinMatrix", wpd->winmat);
+ DRW_shgroup_uniform_texture(grp, "ssao_jitter", e_data.jitter_tx);
+ }
+
+ if (CURVATURE_ENABLED(wpd)) {
+ DRW_shgroup_uniform_texture_ref(grp, "objectId", &e_data.object_id_tx);
+ DRW_shgroup_uniform_vec2(grp, "curvature_settings", &wpd->world_data.curvature_ridge, 1);
+ }
+
DRW_shgroup_call_add(grp, DRW_cache_fullscreen_quad_get(), NULL);
}
}
@@ -462,25 +541,31 @@ static void workbench_setup_ghost_framebuffer(WORKBENCH_FramebufferList *fbl)
const int size[2] = {(int)viewport_size[0], (int)viewport_size[1]};
e_data.ghost_depth_tx = DRW_texture_pool_query_2D(size[0], size[1], GPU_DEPTH_COMPONENT24, &draw_engine_workbench_solid);
+
GPU_framebuffer_ensure_config(&fbl->ghost_prepass_fb, {
GPU_ATTACHMENT_TEXTURE(e_data.ghost_depth_tx),
- GPU_ATTACHMENT_TEXTURE(e_data.object_id_tx),
GPU_ATTACHMENT_TEXTURE(e_data.color_buffer_tx),
- GPU_ATTACHMENT_TEXTURE(e_data.specular_buffer_tx),
+ GPU_ATTACHMENT_TEXTURE(e_data.object_id_tx),
GPU_ATTACHMENT_TEXTURE(e_data.normal_buffer_tx),
});
}
void workbench_deferred_engine_free(void)
{
- for (int index = 0; index < MAX_SHADERS; index++) {
+ for (int index = 0; index < MAX_PREPASS_SHADERS; index++) {
DRW_SHADER_FREE_SAFE(e_data.prepass_sh_cache[index]);
+ }
+ for (int index = 0; index < MAX_COMPOSITE_SHADERS; index++) {
DRW_SHADER_FREE_SAFE(e_data.composite_sh_cache[index]);
}
- DRW_SHADER_FREE_SAFE(e_data.cavity_sh);
+ for (int index = 0; index < MAX_CAVITY_SHADERS; ++index) {
+ DRW_SHADER_FREE_SAFE(e_data.cavity_sh[index]);
+ }
DRW_SHADER_FREE_SAFE(e_data.ghost_resolve_sh);
DRW_UBO_FREE_SAFE(e_data.sampling_ubo);
DRW_TEXTURE_FREE_SAFE(e_data.jitter_tx);
+ DRW_SHADER_FREE_SAFE(e_data.background_sh[0]);
+ DRW_SHADER_FREE_SAFE(e_data.background_sh[1]);
DRW_SHADER_FREE_SAFE(e_data.shadow_pass_sh);
DRW_SHADER_FREE_SAFE(e_data.shadow_pass_manifold_sh);
@@ -496,27 +581,32 @@ void workbench_deferred_engine_free(void)
static void workbench_composite_uniforms(WORKBENCH_PrivateData *wpd, DRWShadingGroup *grp)
{
- DRW_shgroup_uniform_texture_ref(grp, "colorBuffer", &e_data.color_buffer_tx);
- DRW_shgroup_uniform_texture_ref(grp, "objectId", &e_data.object_id_tx);
+ DRW_shgroup_uniform_block(grp, "world_block", wpd->world_ubo);
+ if (MATDATA_PASS_ENABLED(wpd)) {
+ DRW_shgroup_uniform_texture_ref(grp, "materialBuffer", &e_data.color_buffer_tx);
+ }
+ else {
+ DRW_shgroup_uniform_vec3(grp, "materialSingleColor", wpd->shading.single_color, 1);
+ }
+ if (OBJECT_OUTLINE_ENABLED(wpd)) {
+ DRW_shgroup_uniform_texture_ref(grp, "objectId", &e_data.object_id_tx);
+ }
if (NORMAL_VIEWPORT_COMP_PASS_ENABLED(wpd)) {
DRW_shgroup_uniform_texture_ref(grp, "normalBuffer", &e_data.normal_buffer_tx);
}
if (CAVITY_ENABLED(wpd)) {
DRW_shgroup_uniform_texture_ref(grp, "cavityBuffer", &e_data.cavity_buffer_tx);
}
- if (SPECULAR_HIGHLIGHT_ENABLED(wpd) || MATCAP_ENABLED(wpd)) {
- DRW_shgroup_uniform_texture_ref(grp, "specularBuffer", &e_data.specular_buffer_tx);
+ if (SPECULAR_HIGHLIGHT_ENABLED(wpd) || STUDIOLIGHT_TYPE_MATCAP_ENABLED(wpd)) {
DRW_shgroup_uniform_vec4(grp, "viewvecs[0]", (float *)wpd->viewvecs, 3);
}
- DRW_shgroup_uniform_block(grp, "world_block", wpd->world_ubo);
- DRW_shgroup_uniform_vec2(grp, "invertedViewportSize", DRW_viewport_invert_size_get(), 1);
-
- if (STUDIOLIGHT_ORIENTATION_VIEWNORMAL_ENABLED(wpd)) {
+ if (SPECULAR_HIGHLIGHT_ENABLED(wpd) || STUDIOLIGHT_TYPE_MATCAP_ENABLED(wpd)) {
+ DRW_shgroup_uniform_vec2(grp, "invertedViewportSize", DRW_viewport_invert_size_get(), 1);
+ }
+ if (STUDIOLIGHT_TYPE_MATCAP_ENABLED(wpd)) {
BKE_studiolight_ensure_flag(wpd->studio_light, STUDIOLIGHT_EQUIRECT_RADIANCE_GPUTEXTURE);
- DRW_shgroup_uniform_texture(grp, "matcapImage", wpd->studio_light->equirect_radiance_gputexture );
+ DRW_shgroup_uniform_texture(grp, "matcapImage", wpd->studio_light->equirect_radiance_gputexture);
}
-
- workbench_material_set_normal_world_matrix(grp, wpd, e_data.normal_world_matrix);
}
void workbench_deferred_cache_init(WORKBENCH_Data *vedata)
@@ -533,22 +623,39 @@ void workbench_deferred_cache_init(WORKBENCH_Data *vedata)
select_deferred_shaders(wpd);
+ /* Background Pass */
+ {
+ psl->background_pass = DRW_pass_create(
+ "Background", DRW_STATE_WRITE_COLOR | DRW_STATE_DEPTH_EQUAL);
+ grp = DRW_shgroup_create(wpd->background_sh, psl->background_pass);
+ DRW_shgroup_uniform_block(grp, "world_block", wpd->world_ubo);
+ DRW_shgroup_uniform_vec2(grp, "invertedViewportSize", DRW_viewport_invert_size_get(), 1);
+ if (OBJECT_OUTLINE_ENABLED(wpd)) {
+ DRW_shgroup_uniform_texture_ref(grp, "objectId", &e_data.object_id_tx);
+ }
+ DRW_shgroup_call_add(grp, DRW_cache_fullscreen_quad_get(), NULL);
+ }
+
/* Deferred Mix Pass */
{
workbench_private_data_get_light_direction(wpd, e_data.display.light_direction);
studiolight_update_light(wpd, e_data.display.light_direction);
- e_data.display.shadow_shift = scene->display.shadow_shift;
+ float shadow_focus = scene->display.shadow_focus;
+ /* Clamp to avoid overshadowing and shading errors. */
+ CLAMP(shadow_focus, 0.0001f, 0.99999f);
+ shadow_focus = 1.0f - shadow_focus * (1.0f - scene->display.shadow_shift);
if (SHADOW_ENABLED(wpd)) {
psl->composite_pass = DRW_pass_create(
- "Composite", DRW_STATE_WRITE_COLOR | DRW_STATE_STENCIL_EQUAL);
+ "Composite", DRW_STATE_WRITE_COLOR | DRW_STATE_STENCIL_EQUAL | DRW_STATE_DEPTH_GREATER);
grp = DRW_shgroup_create(wpd->composite_sh, psl->composite_pass);
workbench_composite_uniforms(wpd, grp);
DRW_shgroup_stencil_mask(grp, 0x00);
DRW_shgroup_uniform_float_copy(grp, "lightMultiplier", 1.0f);
DRW_shgroup_uniform_float(grp, "shadowMultiplier", &wpd->shadow_multiplier, 1);
- DRW_shgroup_uniform_float(grp, "shadowShift", &scene->display.shadow_shift, 1);
+ DRW_shgroup_uniform_float_copy(grp, "shadowShift", scene->display.shadow_shift);
+ DRW_shgroup_uniform_float_copy(grp, "shadowFocus", shadow_focus);
DRW_shgroup_call_add(grp, DRW_cache_fullscreen_quad_get(), NULL);
/* Stencil Shadow passes. */
@@ -580,20 +687,21 @@ void workbench_deferred_cache_init(WORKBENCH_Data *vedata)
grp = DRW_shgroup_create(e_data.shadow_caps_manifold_sh, psl->shadow_depth_fail_caps_mani_pass);
DRW_shgroup_stencil_mask(grp, 0xFF);
- psl->composite_shadow_pass = DRW_pass_create("Composite Shadow", DRW_STATE_WRITE_COLOR | DRW_STATE_STENCIL_NEQUAL);
+ psl->composite_shadow_pass = DRW_pass_create(
+ "Composite Shadow", DRW_STATE_WRITE_COLOR | DRW_STATE_STENCIL_NEQUAL | DRW_STATE_DEPTH_GREATER);
grp = DRW_shgroup_create(wpd->composite_sh, psl->composite_shadow_pass);
DRW_shgroup_stencil_mask(grp, 0x00);
workbench_composite_uniforms(wpd, grp);
DRW_shgroup_uniform_float(grp, "lightMultiplier", &wpd->shadow_multiplier, 1);
DRW_shgroup_uniform_float(grp, "shadowMultiplier", &wpd->shadow_multiplier, 1);
- DRW_shgroup_uniform_float(grp, "shadowShift", &scene->display.shadow_shift, 1);
+ DRW_shgroup_uniform_float_copy(grp, "shadowShift", scene->display.shadow_shift);
+ DRW_shgroup_uniform_float_copy(grp, "shadowFocus", shadow_focus);
DRW_shgroup_call_add(grp, DRW_cache_fullscreen_quad_get(), NULL);
#endif
-
}
else {
psl->composite_pass = DRW_pass_create(
- "Composite", DRW_STATE_WRITE_COLOR);
+ "Composite", DRW_STATE_WRITE_COLOR | DRW_STATE_DEPTH_GREATER);
grp = DRW_shgroup_create(wpd->composite_sh, psl->composite_pass);
workbench_composite_uniforms(wpd, grp);
DRW_shgroup_call_add(grp, DRW_cache_fullscreen_quad_get(), NULL);
@@ -629,7 +737,7 @@ static WORKBENCH_MaterialData *get_or_create_material_data(
workbench_material_copy(material, &material_template);
DRW_shgroup_stencil_mask(material->shgrp, (ob->dtx & OB_DRAWXRAY) ? 0x00 : 0xFF);
DRW_shgroup_uniform_int(material->shgrp, "object_id", &material->object_id, 1);
- workbench_material_shgroup_uniform(wpd, material->shgrp, material, ob);
+ workbench_material_shgroup_uniform(wpd, material->shgrp, material, ob, true, true);
BLI_ghash_insert(wpd->material_hash, POINTER_FROM_UINT(hash), material);
}
@@ -641,10 +749,7 @@ static void workbench_cache_populate_particles(WORKBENCH_Data *vedata, Object *o
WORKBENCH_StorageList *stl = vedata->stl;
WORKBENCH_PassList *psl = vedata->psl;
WORKBENCH_PrivateData *wpd = stl->g_data;
- const DRWContextState *draw_ctx = DRW_context_state_get();
- if (ob == draw_ctx->object_edit) {
- return;
- }
+
for (ModifierData *md = ob->modifiers.first; md; md = md->next) {
if (md->type != eModifierType_ParticleSystem) {
continue;
@@ -675,7 +780,7 @@ static void workbench_cache_populate_particles(WORKBENCH_Data *vedata, Object *o
shader);
DRW_shgroup_stencil_mask(shgrp, (ob->dtx & OB_DRAWXRAY) ? 0x00 : 0xFF);
DRW_shgroup_uniform_int(shgrp, "object_id", &material->object_id, 1);
- workbench_material_shgroup_uniform(wpd, shgrp, material, ob);
+ workbench_material_shgroup_uniform(wpd, shgrp, material, ob, true, true);
}
}
}
@@ -702,7 +807,7 @@ static void workbench_cache_populate_hair(WORKBENCH_Data *vedata, Object *ob)
DRWShadingGroup *shgrp = DRW_shgroup_hair_create(ob, hsys, psl->prepass_hair_pass, shader);
DRW_shgroup_stencil_mask(shgrp, 0xFF);
DRW_shgroup_uniform_int(shgrp, "object_id", &material->object_id, 1);
- workbench_material_shgroup_uniform(wpd, shgrp, material, ob);
+ workbench_material_shgroup_uniform(wpd, shgrp, material, ob, true, true);
}
void workbench_deferred_solid_cache_populate(WORKBENCH_Data *vedata, Object *ob)
@@ -741,28 +846,22 @@ void workbench_deferred_solid_cache_populate(WORKBENCH_Data *vedata, Object *ob)
if (ELEM(ob->type, OB_MESH, OB_CURVE, OB_SURF, OB_FONT, OB_MBALL, OB_HAIR)) {
const bool is_active = (ob == draw_ctx->obact);
const bool is_sculpt_mode = is_active && (draw_ctx->object_mode & OB_MODE_SCULPT) != 0;
+ const bool use_hide = is_active && DRW_object_use_hide_faces(ob);
bool is_drawn = false;
if (!is_sculpt_mode && TEXTURE_DRAWING_ENABLED(wpd) && ELEM(ob->type, OB_MESH)) {
const Mesh *me = ob->data;
if (me->mloopuv) {
const int materials_len = MAX2(1, (is_sculpt_mode ? 1 : ob->totcol));
- struct GPUMaterial **gpumat_array = BLI_array_alloca(gpumat_array, materials_len);
- struct GPUBatch **geom_array = me->totcol ? DRW_cache_mesh_surface_texpaint_get(ob) : NULL;
- if (materials_len > 0 && geom_array) {
- for (int i = 0; i < materials_len; i++) {
- if (geom_array[i] == NULL) {
- continue;
- }
-
- Material *mat = give_current_material(ob, i + 1);
- Image *image;
- ED_object_get_active_image(ob, i + 1, &image, NULL, NULL, NULL);
- int color_type = workbench_material_determine_color_type(wpd, image, ob);
- material = get_or_create_material_data(vedata, ob, mat, image, color_type);
- DRW_shgroup_call_object_add(material->shgrp, geom_array[i], ob);
- }
- is_drawn = true;
+ struct GPUBatch **geom_array = DRW_cache_mesh_surface_texpaint_get(ob);
+ for (int i = 0; i < materials_len; i++) {
+ Material *mat = give_current_material(ob, i + 1);
+ Image *image;
+ ED_object_get_active_image(ob, i + 1, &image, NULL, NULL, NULL);
+ int color_type = workbench_material_determine_color_type(wpd, image, ob);
+ material = get_or_create_material_data(vedata, ob, mat, image, color_type);
+ DRW_shgroup_call_object_add(material->shgrp, geom_array[i], ob);
}
+ is_drawn = true;
}
}
@@ -813,7 +912,7 @@ void workbench_deferred_solid_cache_populate(WORKBENCH_Data *vedata, Object *ob)
bool is_manifold;
struct GPUBatch *geom_shadow = DRW_cache_object_edge_detection_get(ob, &is_manifold);
if (geom_shadow) {
- if (is_sculpt_mode) {
+ if (is_sculpt_mode || use_hide) {
/* Currently unsupported in sculpt mode. We could revert to the slow
* method in this case but I'm not sure if it's a good idea given that
* sculpted meshes are heavy to begin with. */
@@ -896,8 +995,15 @@ void workbench_deferred_draw_background(WORKBENCH_Data *vedata)
uint clear_stencil = 0x00;
DRW_stats_group_start("Clear Background");
+
+ if (OBJECT_ID_PASS_ENABLED(wpd)) {
+ /* From all the color buffers, only object id needs to be cleared. */
+ GPU_framebuffer_bind(fbl->id_clear_fb);
+ GPU_framebuffer_clear_color(fbl->id_clear_fb, clear_color);
+ }
+
GPU_framebuffer_bind(fbl->prepass_fb);
- int clear_bits = GPU_DEPTH_BIT | GPU_COLOR_BIT;
+ int clear_bits = GPU_DEPTH_BIT;
SET_FLAG_FROM_TEST(clear_bits, SHADOW_ENABLED(wpd), GPU_STENCIL_BIT);
GPU_framebuffer_clear(fbl->prepass_fb, clear_bits, clear_color, clear_depth, clear_stencil);
DRW_stats_group_end();
@@ -987,6 +1093,9 @@ void workbench_deferred_draw_scene(WORKBENCH_Data *vedata)
DRW_draw_pass(psl->ghost_prepass_hair_pass);
}
+ GPU_framebuffer_bind(fbl->composite_fb);
+ DRW_draw_pass(psl->background_pass);
+
if (wpd->volumes_do) {
GPU_framebuffer_bind(fbl->volume_fb);
DRW_draw_pass(psl->volume_pass);
diff --git a/source/blender/draw/engines/workbench/workbench_effect_taa.c b/source/blender/draw/engines/workbench/workbench_effect_taa.c
index 403338d55c4..929281daaf4 100644
--- a/source/blender/draw/engines/workbench/workbench_effect_taa.c
+++ b/source/blender/draw/engines/workbench/workbench_effect_taa.c
@@ -171,7 +171,8 @@ DRWPass *workbench_taa_create_pass(WORKBENCH_Data *vedata, GPUTexture **color_bu
int previous_jitter_index = effect_info->jitter_index;
{
- DRW_texture_ensure_fullscreen_2D(&txl->history_buffer_tx, GPU_RGBA16F, 0);
+ const GPUTextureFormat hist_buffer_format = DRW_state_is_image_render() ? GPU_RGBA16F : GPU_RGBA8;
+ DRW_texture_ensure_fullscreen_2D(&txl->history_buffer_tx, hist_buffer_format, 0);
DRW_texture_ensure_fullscreen_2D(&txl->depth_buffer_tx, GPU_DEPTH24_STENCIL8, 0);
}
diff --git a/source/blender/draw/engines/workbench/workbench_engine.c b/source/blender/draw/engines/workbench/workbench_engine.c
index 642c5820895..180932b9b64 100644
--- a/source/blender/draw/engines/workbench/workbench_engine.c
+++ b/source/blender/draw/engines/workbench/workbench_engine.c
@@ -31,12 +31,12 @@
#include "workbench_engine.h"
#include "workbench_private.h"
-#define OPENGL_ENGINE "BLENDER_OPENGL"
+#define WORKBENCH_ENGINE "BLENDER_WORKBENCH"
/* Note: currently unused, we may want to register so we can see this when debugging the view. */
-RenderEngineType DRW_engine_viewport_opengl_type = {
+RenderEngineType DRW_engine_viewport_workbench_type = {
NULL, NULL,
- OPENGL_ENGINE, N_("OpenGL"), RE_INTERNAL,
+ WORKBENCH_ENGINE, N_("Workbench"), RE_INTERNAL,
NULL, &DRW_render_to_image, NULL, NULL, NULL, NULL,
&workbench_render_update_passes,
&draw_engine_workbench_solid,
diff --git a/source/blender/draw/engines/workbench/workbench_engine.h b/source/blender/draw/engines/workbench/workbench_engine.h
index 24f68cacd21..a7f168db093 100644
--- a/source/blender/draw/engines/workbench/workbench_engine.h
+++ b/source/blender/draw/engines/workbench/workbench_engine.h
@@ -28,6 +28,6 @@
extern DrawEngineType draw_engine_workbench_solid;
extern DrawEngineType draw_engine_workbench_transparent;
-extern RenderEngineType DRW_engine_viewport_opengl_type;
+extern RenderEngineType DRW_engine_viewport_workbench_type;
#endif /* __WORKBENCH_ENGINE_H__ */
diff --git a/source/blender/draw/engines/workbench/workbench_forward.c b/source/blender/draw/engines/workbench/workbench_forward.c
index b5b4a3ec364..835bb09dcd5 100644
--- a/source/blender/draw/engines/workbench/workbench_forward.c
+++ b/source/blender/draw/engines/workbench/workbench_forward.c
@@ -51,8 +51,8 @@
/* *********** STATIC *********** */
static struct {
- struct GPUShader *composite_sh_cache[MAX_SHADERS];
- struct GPUShader *transparent_accum_sh_cache[MAX_SHADERS];
+ struct GPUShader *composite_sh_cache[2];
+ struct GPUShader *transparent_accum_sh_cache[MAX_ACCUM_SHADERS];
struct GPUShader *object_outline_sh;
struct GPUShader *object_outline_texture_sh;
struct GPUShader *object_outline_hair_sh;
@@ -64,7 +64,6 @@ static struct {
struct GPUTexture *composite_buffer_tx; /* ref only, not alloced */
int next_object_id;
- float normal_world_matrix[3][3];
} e_data = {{NULL}};
/* Shaders */
@@ -77,6 +76,7 @@ extern char datatoc_workbench_data_lib_glsl[];
extern char datatoc_workbench_background_lib_glsl[];
extern char datatoc_workbench_checkerboard_depth_frag_glsl[];
extern char datatoc_workbench_object_outline_lib_glsl[];
+extern char datatoc_workbench_curvature_lib_glsl[];
extern char datatoc_workbench_prepass_vert_glsl[];
extern char datatoc_workbench_common_lib_glsl[];
extern char datatoc_workbench_world_light_lib_glsl[];
@@ -125,6 +125,7 @@ static char *workbench_build_forward_composite_frag(void)
BLI_dynstr_append(ds, datatoc_workbench_common_lib_glsl);
BLI_dynstr_append(ds, datatoc_workbench_background_lib_glsl);
BLI_dynstr_append(ds, datatoc_workbench_object_outline_lib_glsl);
+ BLI_dynstr_append(ds, datatoc_workbench_curvature_lib_glsl);
BLI_dynstr_append(ds, datatoc_workbench_forward_composite_frag_glsl);
str = BLI_dynstr_get_cstring(ds);
@@ -168,9 +169,8 @@ static WORKBENCH_MaterialData *get_or_create_material_data(
DRW_shgroup_uniform_block(grp, "world_block", wpd->world_ubo);
DRW_shgroup_uniform_float(grp, "alpha", &wpd->shading.xray_alpha, 1);
DRW_shgroup_uniform_vec4(grp, "viewvecs[0]", (float *)wpd->viewvecs, 3);
- workbench_material_set_normal_world_matrix(grp, wpd, e_data.normal_world_matrix);
workbench_material_copy(material, &material_template);
- if (STUDIOLIGHT_ORIENTATION_VIEWNORMAL_ENABLED(wpd)) {
+ if (STUDIOLIGHT_TYPE_MATCAP_ENABLED(wpd)) {
BKE_studiolight_ensure_flag(wpd->studio_light, STUDIOLIGHT_EQUIRECT_RADIANCE_GPUTEXTURE);
DRW_shgroup_uniform_texture(grp, "matcapImage", wpd->studio_light->equirect_radiance_gputexture );
}
@@ -178,7 +178,7 @@ static WORKBENCH_MaterialData *get_or_create_material_data(
DRW_shgroup_uniform_vec2(grp, "invertedViewportSize", DRW_viewport_invert_size_get(), 1);
}
- workbench_material_shgroup_uniform(wpd, grp, material, ob);
+ workbench_material_shgroup_uniform(wpd, grp, material, ob, false, false);
material->shgrp = grp;
/* Depth */
@@ -199,16 +199,9 @@ static WORKBENCH_MaterialData *get_or_create_material_data(
return material;
}
-static void ensure_forward_shaders(WORKBENCH_PrivateData *wpd, int index, bool use_textures, bool is_hair)
+static GPUShader *ensure_forward_accum_shaders(WORKBENCH_PrivateData *wpd, bool use_textures, bool is_hair)
{
- if (e_data.composite_sh_cache[index] == NULL && !use_textures && !is_hair) {
- char *defines = workbench_material_build_defines(wpd, use_textures, is_hair);
- char *composite_frag = workbench_build_forward_composite_frag();
- e_data.composite_sh_cache[index] = DRW_shader_create_fullscreen(composite_frag, defines);
- MEM_freeN(composite_frag);
- MEM_freeN(defines);
- }
-
+ int index = workbench_material_get_accum_shader_index(wpd, use_textures, is_hair);
if (e_data.transparent_accum_sh_cache[index] == NULL) {
char *defines = workbench_material_build_defines(wpd, use_textures, is_hair);
char *transparent_accum_vert = workbench_build_forward_vert(is_hair);
@@ -220,25 +213,29 @@ static void ensure_forward_shaders(WORKBENCH_PrivateData *wpd, int index, bool u
MEM_freeN(transparent_accum_frag);
MEM_freeN(defines);
}
+ return e_data.transparent_accum_sh_cache[index];
+}
+
+static GPUShader *ensure_forward_composite_shaders(WORKBENCH_PrivateData *wpd)
+{
+ int index = OBJECT_OUTLINE_ENABLED(wpd) ? 1 : 0;
+ if (e_data.composite_sh_cache[index] == NULL) {
+ char *defines = workbench_material_build_defines(wpd, false, false);
+ char *composite_frag = workbench_build_forward_composite_frag();
+ e_data.composite_sh_cache[index] = DRW_shader_create_fullscreen(composite_frag, defines);
+ MEM_freeN(composite_frag);
+ MEM_freeN(defines);
+ }
+ return e_data.composite_sh_cache[index];
}
static void select_forward_shaders(WORKBENCH_PrivateData *wpd)
{
- int index_solid = workbench_material_get_shader_index(wpd, false, false);
- int index_solid_hair = workbench_material_get_shader_index(wpd, false, true);
- int index_texture = workbench_material_get_shader_index(wpd, true, false);
- int index_texture_hair = workbench_material_get_shader_index(wpd, true, true);
-
- ensure_forward_shaders(wpd, index_solid, false, false);
- ensure_forward_shaders(wpd, index_solid_hair, false, true);
- ensure_forward_shaders(wpd, index_texture, true, false);
- ensure_forward_shaders(wpd, index_texture_hair, true, true);
-
- wpd->composite_sh = e_data.composite_sh_cache[index_solid];
- wpd->transparent_accum_sh = e_data.transparent_accum_sh_cache[index_solid];
- wpd->transparent_accum_hair_sh = e_data.transparent_accum_sh_cache[index_solid_hair];
- wpd->transparent_accum_texture_sh = e_data.transparent_accum_sh_cache[index_texture];
- wpd->transparent_accum_texture_hair_sh = e_data.transparent_accum_sh_cache[index_texture_hair];
+ wpd->composite_sh = ensure_forward_composite_shaders(wpd);
+ wpd->transparent_accum_sh = ensure_forward_accum_shaders(wpd, false, false);
+ wpd->transparent_accum_hair_sh = ensure_forward_accum_shaders(wpd, false, true);
+ wpd->transparent_accum_texture_sh = ensure_forward_accum_shaders(wpd, true, false);
+ wpd->transparent_accum_texture_hair_sh = ensure_forward_accum_shaders(wpd, true, true);
}
/* public functions */
@@ -266,8 +263,8 @@ void workbench_forward_engine_init(WORKBENCH_Data *vedata)
if (!e_data.next_object_id) {
e_data.next_object_id = 1;
- memset(e_data.composite_sh_cache, 0x00, sizeof(struct GPUShader *) * MAX_SHADERS);
- memset(e_data.transparent_accum_sh_cache, 0x00, sizeof(struct GPUShader *) * MAX_SHADERS);
+ memset(e_data.composite_sh_cache, 0x00, sizeof(e_data.composite_sh_cache));
+ memset(e_data.transparent_accum_sh_cache, 0x00, sizeof(e_data.transparent_accum_sh_cache));
char *defines = workbench_material_build_defines(wpd, false, false);
char *defines_texture = workbench_material_build_defines(wpd, true, false);
@@ -393,8 +390,10 @@ void workbench_forward_engine_init(WORKBENCH_Data *vedata)
void workbench_forward_engine_free()
{
- for (int index = 0; index < MAX_SHADERS; index++) {
+ for (int index = 0; index < 2; index++) {
DRW_SHADER_FREE_SAFE(e_data.composite_sh_cache[index]);
+ }
+ for (int index = 0; index < MAX_ACCUM_SHADERS; index++) {
DRW_SHADER_FREE_SAFE(e_data.transparent_accum_sh_cache[index]);
}
DRW_SHADER_FREE_SAFE(e_data.object_outline_sh);
@@ -416,11 +415,7 @@ static void workbench_forward_cache_populate_particles(WORKBENCH_Data *vedata, O
WORKBENCH_StorageList *stl = vedata->stl;
WORKBENCH_PassList *psl = vedata->psl;
WORKBENCH_PrivateData *wpd = stl->g_data;
- const DRWContextState *draw_ctx = DRW_context_state_get();
- if (ob == draw_ctx->object_edit) {
- return;
- }
for (ModifierData *md = ob->modifiers.first; md; md = md->next) {
if (md->type != eModifierType_ParticleSystem) {
continue;
@@ -449,15 +444,14 @@ static void workbench_forward_cache_populate_particles(WORKBENCH_Data *vedata, O
ob, psys, md,
psl->transparent_accum_pass,
shader);
- workbench_material_set_normal_world_matrix(shgrp, wpd, e_data.normal_world_matrix);
DRW_shgroup_uniform_block(shgrp, "world_block", wpd->world_ubo);
- workbench_material_shgroup_uniform(wpd, shgrp, material, ob);
+ workbench_material_shgroup_uniform(wpd, shgrp, material, ob, false, false);
DRW_shgroup_uniform_vec4(shgrp, "viewvecs[0]", (float *)wpd->viewvecs, 3);
/* Hairs have lots of layer and can rapidly become the most prominent surface.
* So lower their alpha artificially. */
float hair_alpha = XRAY_ALPHA(wpd) * 0.33f;
DRW_shgroup_uniform_float_copy(shgrp, "alpha", hair_alpha);
- if (STUDIOLIGHT_ORIENTATION_VIEWNORMAL_ENABLED(wpd)) {
+ if (STUDIOLIGHT_TYPE_MATCAP_ENABLED(wpd)) {
BKE_studiolight_ensure_flag(wpd->studio_light, STUDIOLIGHT_EQUIRECT_RADIANCE_GPUTEXTURE);
DRW_shgroup_uniform_texture(shgrp, "matcapImage", wpd->studio_light->equirect_radiance_gputexture );
}
@@ -492,15 +486,14 @@ static void workbench_forward_cache_populate_hair(WORKBENCH_Data *vedata, Object
? wpd->transparent_accum_hair_sh
: wpd->transparent_accum_texture_hair_sh;
DRWShadingGroup *shgrp = DRW_shgroup_hair_create(ob, hsys, psl->transparent_accum_pass, shader);
- workbench_material_set_normal_world_matrix(shgrp, wpd, e_data.normal_world_matrix);
DRW_shgroup_uniform_block(shgrp, "world_block", wpd->world_ubo);
- workbench_material_shgroup_uniform(wpd, shgrp, material, ob);
+ workbench_material_shgroup_uniform(wpd, shgrp, material, ob, false, false);
DRW_shgroup_uniform_vec4(shgrp, "viewvecs[0]", (float *)wpd->viewvecs, 3);
/* Hairs have lots of layer and can rapidly become the most prominent surface.
* So lower their alpha artificially. */
float hair_alpha = wpd->shading.xray_alpha * 0.33f;
DRW_shgroup_uniform_float_copy(shgrp, "alpha", hair_alpha);
- if (STUDIOLIGHT_ORIENTATION_VIEWNORMAL_ENABLED(wpd)) {
+ if (STUDIOLIGHT_TYPE_MATCAP_ENABLED(wpd)) {
BKE_studiolight_ensure_flag(wpd->studio_light, STUDIOLIGHT_EQUIRECT_RADIANCE_GPUTEXTURE);
DRW_shgroup_uniform_texture(shgrp, "matcapImage", wpd->studio_light->equirect_radiance_gputexture );
}
@@ -553,33 +546,26 @@ void workbench_forward_cache_populate(WORKBENCH_Data *vedata, Object *ob)
const Mesh *me = ob->data;
if (me->mloopuv) {
const int materials_len = MAX2(1, (is_sculpt_mode ? 1 : ob->totcol));
- struct GPUMaterial **gpumat_array = BLI_array_alloca(gpumat_array, materials_len);
- struct GPUBatch **geom_array = me->totcol ? DRW_cache_mesh_surface_texpaint_get(ob) : NULL;
- if (materials_len > 0 && geom_array) {
- for (int i = 0; i < materials_len; i++) {
- if (geom_array[i] == NULL) {
- continue;
- }
+ struct GPUBatch **geom_array = DRW_cache_mesh_surface_texpaint_get(ob);
+ for (int i = 0; i < materials_len; i++) {
+ Material *mat = give_current_material(ob, i + 1);
+ Image *image;
+ ED_object_get_active_image(ob, i + 1, &image, NULL, NULL, NULL);
+ /* use OB_SOLID when no texture could be determined */
- Material *mat = give_current_material(ob, i + 1);
- Image *image;
- ED_object_get_active_image(ob, i + 1, &image, NULL, NULL, NULL);
+ int color_type = wpd->shading.color_type;
+ if (color_type == V3D_SHADING_TEXTURE_COLOR) {
/* use OB_SOLID when no texture could be determined */
-
- int color_type = wpd->shading.color_type;
- if (color_type == V3D_SHADING_TEXTURE_COLOR) {
- /* use OB_SOLID when no texture could be determined */
- if (image == NULL) {
- color_type = V3D_SHADING_MATERIAL_COLOR;
- }
+ if (image == NULL) {
+ color_type = V3D_SHADING_MATERIAL_COLOR;
}
-
- material = get_or_create_material_data(vedata, ob, mat, image, color_type);
- DRW_shgroup_call_object_add(material->shgrp_object_outline, geom_array[i], ob);
- DRW_shgroup_call_object_add(material->shgrp, geom_array[i], ob);
}
- is_drawn = true;
+
+ material = get_or_create_material_data(vedata, ob, mat, image, color_type);
+ DRW_shgroup_call_object_add(material->shgrp_object_outline, geom_array[i], ob);
+ DRW_shgroup_call_object_add(material->shgrp, geom_array[i], ob);
}
+ is_drawn = true;
}
}
diff --git a/source/blender/draw/engines/workbench/workbench_materials.c b/source/blender/draw/engines/workbench/workbench_materials.c
index 2faa9e288f8..5360cf3683b 100644
--- a/source/blender/draw/engines/workbench/workbench_materials.c
+++ b/source/blender/draw/engines/workbench/workbench_materials.c
@@ -4,24 +4,27 @@
#include "BIF_gl.h"
+#include "BKE_image.h"
+
#include "BLI_dynstr.h"
#include "BLI_hash.h"
#define HSV_SATURATION 0.5
-#define HSV_VALUE 0.9
+#define HSV_VALUE 0.8
void workbench_material_update_data(WORKBENCH_PrivateData *wpd, Object *ob, Material *mat, WORKBENCH_MaterialData *data)
{
/* When V3D_SHADING_TEXTURE_COLOR is active, use V3D_SHADING_MATERIAL_COLOR as fallback when no texture could be determined */
int color_type = wpd->shading.color_type == V3D_SHADING_TEXTURE_COLOR ? V3D_SHADING_MATERIAL_COLOR : wpd->shading.color_type;
- static float default_diffuse_color[] = {0.8f, 0.8f, 0.8f, 1.0f};
- static float default_specular_color[] = {0.5f, 0.5f, 0.5f, 0.5f};
- copy_v4_v4(data->diffuse_color, default_diffuse_color);
- copy_v4_v4(data->specular_color, default_specular_color);
- data->roughness = 0.5f;
+ copy_v3_fl3(data->diffuse_color, 0.8f, 0.8f, 0.8f);
+ copy_v3_v3(data->base_color, data->diffuse_color);
+ copy_v3_fl3(data->specular_color, 0.05f, 0.05f, 0.05f); /* Dielectric: 5% reflective. */
+ data->metallic = 0.0f;
+ data->roughness = 0.5f; /* sqrtf(0.25f); */
if (color_type == V3D_SHADING_SINGLE_COLOR) {
copy_v3_v3(data->diffuse_color, wpd->shading.single_color);
+ copy_v3_v3(data->base_color, data->diffuse_color);
}
else if (color_type == V3D_SHADING_RANDOM_COLOR) {
uint hash = BLI_ghashutil_strhash_p_murmur(ob->id.name);
@@ -32,13 +35,23 @@ void workbench_material_update_data(WORKBENCH_PrivateData *wpd, Object *ob, Mate
float hue = BLI_hash_int_01(hash);
float hsv[3] = {hue, HSV_SATURATION, HSV_VALUE};
hsv_to_rgb_v(hsv, data->diffuse_color);
+ copy_v3_v3(data->base_color, data->diffuse_color);
}
else {
/* V3D_SHADING_MATERIAL_COLOR */
if (mat) {
- copy_v3_v3(data->diffuse_color, &mat->r);
- copy_v3_v3(data->specular_color, &mat->specr);
- data->roughness = mat->roughness;
+ if (SPECULAR_HIGHLIGHT_ENABLED(wpd)) {
+ copy_v3_v3(data->base_color, &mat->r);
+ mul_v3_v3fl(data->diffuse_color, &mat->r, 1.0f - mat->metallic);
+ mul_v3_v3fl(data->specular_color, &mat->r, mat->metallic);
+ add_v3_fl(data->specular_color, 0.05f * (1.0f - mat->metallic));
+ data->metallic = mat->metallic;
+ data->roughness = sqrtf(mat->roughness); /* Remap to disney roughness. */
+ }
+ else {
+ copy_v3_v3(data->base_color, &mat->r);
+ copy_v3_v3(data->diffuse_color, &mat->r);
+ }
}
}
}
@@ -55,8 +68,8 @@ char *workbench_material_build_defines(WORKBENCH_PrivateData *wpd, bool use_text
if (wpd->shading.flag & V3D_SHADING_SHADOW) {
BLI_dynstr_appendf(ds, "#define V3D_SHADING_SHADOW\n");
}
- if (CAVITY_ENABLED(wpd)) {
- BLI_dynstr_appendf(ds, "#define V3D_SHADING_CAVITY\n");
+ if (SSAO_ENABLED(wpd) || CURVATURE_ENABLED(wpd)) {
+ BLI_dynstr_appendf(ds, "#define WB_CAVITY\n");
}
if (SPECULAR_HIGHLIGHT_ENABLED(wpd)) {
BLI_dynstr_appendf(ds, "#define V3D_SHADING_SPECULAR_HIGHLIGHT\n");
@@ -70,14 +83,11 @@ char *workbench_material_build_defines(WORKBENCH_PrivateData *wpd, bool use_text
if (MATCAP_ENABLED(wpd)) {
BLI_dynstr_appendf(ds, "#define V3D_LIGHTING_MATCAP\n");
}
- if (STUDIOLIGHT_ORIENTATION_WORLD_ENABLED(wpd)) {
- BLI_dynstr_appendf(ds, "#define STUDIOLIGHT_ORIENTATION_WORLD\n");
- }
- if (STUDIOLIGHT_ORIENTATION_CAMERA_ENABLED(wpd)) {
- BLI_dynstr_appendf(ds, "#define STUDIOLIGHT_ORIENTATION_CAMERA\n");
+ if (OBJECT_ID_PASS_ENABLED(wpd)) {
+ BLI_dynstr_appendf(ds, "#define OBJECT_ID_PASS_ENABLED\n");
}
- if (STUDIOLIGHT_ORIENTATION_VIEWNORMAL_ENABLED(wpd)) {
- BLI_dynstr_appendf(ds, "#define STUDIOLIGHT_ORIENTATION_VIEWNORMAL\n");
+ if (MATDATA_PASS_ENABLED(wpd)) {
+ BLI_dynstr_appendf(ds, "#define MATDATA_PASS_ENABLED\n");
}
if (NORMAL_VIEWPORT_PASS_ENABLED(wpd)) {
BLI_dynstr_appendf(ds, "#define NORMAL_VIEWPORT_PASS_ENABLED\n");
@@ -92,9 +102,6 @@ char *workbench_material_build_defines(WORKBENCH_PrivateData *wpd, bool use_text
BLI_dynstr_appendf(ds, "#define HAIR_SHADER\n");
}
- BLI_dynstr_appendf(ds, "#define STUDIOLIGHT_SH_BANDS %d\n", STUDIOLIGHT_SH_BANDS);
- BLI_dynstr_appendf(ds, "#define STUDIOLIGHT_SH_MAX_COMPONENTS %d\n", WORKBENCH_SH_DATA_LEN);
-
str = BLI_dynstr_get_cstring(ds);
BLI_dynstr_free(ds);
return str;
@@ -128,40 +135,42 @@ uint workbench_material_get_hash(WORKBENCH_MaterialData *material_template, bool
return result;
}
-int workbench_material_get_shader_index(WORKBENCH_PrivateData *wpd, bool use_textures, bool is_hair)
+int workbench_material_get_composite_shader_index(WORKBENCH_PrivateData *wpd)
{
- /* NOTE: change MAX_SHADERS accordingly when modifying this function. */
+ /* NOTE: change MAX_COMPOSITE_SHADERS accordingly when modifying this function. */
int index = 0;
- /* 1 bit V3D_SHADING_TEXTURE_COLOR */
- SET_FLAG_FROM_TEST(index, use_textures, 1 << 0);
- /* 2 bits FLAT/STUDIO/MATCAP/SCENE */
- SET_FLAG_FROM_TEST(index, wpd->shading.light, wpd->shading.light << 1);
- /* 1 bit V3D_SHADING_SPECULAR_HIGHLIGHT */
- SET_FLAG_FROM_TEST(index, wpd->shading.flag & V3D_SHADING_SPECULAR_HIGHLIGHT, 1 << 3);
- SET_FLAG_FROM_TEST(index, wpd->shading.flag & V3D_SHADING_SHADOW, 1 << 4);
- SET_FLAG_FROM_TEST(index, wpd->shading.flag & V3D_SHADING_CAVITY, 1 << 5);
- SET_FLAG_FROM_TEST(index, wpd->shading.flag & V3D_SHADING_OBJECT_OUTLINE, 1 << 6);
- /* 2 bits STUDIOLIGHT_ORIENTATION */
- SET_FLAG_FROM_TEST(index, wpd->studio_light->flag & STUDIOLIGHT_ORIENTATION_WORLD, 1 << 7);
- SET_FLAG_FROM_TEST(index, wpd->studio_light->flag & STUDIOLIGHT_ORIENTATION_VIEWNORMAL, 1 << 8);
- /* 1 bit for hair */
- SET_FLAG_FROM_TEST(index, is_hair, 1 << 9);
+ /* 2 bits FLAT/STUDIO/MATCAP + Specular highlight */
+ index = SPECULAR_HIGHLIGHT_ENABLED(wpd) ? 3 : wpd->shading.light;
+ SET_FLAG_FROM_TEST(index, wpd->shading.flag & V3D_SHADING_SHADOW, 1 << 2);
+ SET_FLAG_FROM_TEST(index, wpd->shading.flag & V3D_SHADING_CAVITY, 1 << 3);
+ SET_FLAG_FROM_TEST(index, wpd->shading.flag & V3D_SHADING_OBJECT_OUTLINE, 1 << 4);
+ SET_FLAG_FROM_TEST(index, MATDATA_PASS_ENABLED(wpd), 1 << 5);
return index;
}
-void workbench_material_set_normal_world_matrix(
- DRWShadingGroup *grp, WORKBENCH_PrivateData *wpd, float persistent_matrix[3][3])
+int workbench_material_get_prepass_shader_index(
+ WORKBENCH_PrivateData *wpd, bool use_textures, bool is_hair)
{
- if (STUDIOLIGHT_ORIENTATION_WORLD_ENABLED(wpd)) {
- float view_matrix_inverse[4][4];
- float rot_matrix[4][4];
- float matrix[4][4];
- axis_angle_to_mat4_single(rot_matrix, 'Z', -wpd->shading.studiolight_rot_z);
- DRW_viewport_matrix_get(view_matrix_inverse, DRW_MAT_VIEWINV);
- mul_m4_m4m4(matrix, rot_matrix, view_matrix_inverse);
- copy_m3_m4(persistent_matrix, matrix);
- DRW_shgroup_uniform_mat3(grp, "normalWorldMatrix", persistent_matrix);
- }
+ /* NOTE: change MAX_PREPASS_SHADERS accordingly when modifying this function. */
+ int index = 0;
+ SET_FLAG_FROM_TEST(index, is_hair, 1 << 0);
+ SET_FLAG_FROM_TEST(index, MATDATA_PASS_ENABLED(wpd), 1 << 1);
+ SET_FLAG_FROM_TEST(index, OBJECT_ID_PASS_ENABLED(wpd), 1 << 2);
+ SET_FLAG_FROM_TEST(index, NORMAL_VIEWPORT_PASS_ENABLED(wpd), 1 << 3);
+ SET_FLAG_FROM_TEST(index, MATCAP_ENABLED(wpd), 1 << 4);
+ SET_FLAG_FROM_TEST(index, use_textures, 1 << 5);
+ return index;
+}
+
+int workbench_material_get_accum_shader_index(WORKBENCH_PrivateData *wpd, bool use_textures, bool is_hair)
+{
+ /* NOTE: change MAX_ACCUM_SHADERS accordingly when modifying this function. */
+ int index = 0;
+ /* 2 bits FLAT/STUDIO/MATCAP + Specular highlight */
+ index = SPECULAR_HIGHLIGHT_ENABLED(wpd) ? 3 : wpd->shading.light;
+ SET_FLAG_FROM_TEST(index, use_textures, 1 << 2);
+ SET_FLAG_FROM_TEST(index, is_hair, 1 << 3);
+ return index;
}
int workbench_material_determine_color_type(WORKBENCH_PrivateData *wpd, Image *ima, Object *ob)
@@ -174,18 +183,32 @@ int workbench_material_determine_color_type(WORKBENCH_PrivateData *wpd, Image *i
}
void workbench_material_shgroup_uniform(
- WORKBENCH_PrivateData *wpd, DRWShadingGroup *grp, WORKBENCH_MaterialData *material, Object *ob)
+ WORKBENCH_PrivateData *wpd, DRWShadingGroup *grp, WORKBENCH_MaterialData *material, Object *ob,
+ const bool use_metallic, const bool deferred)
{
+ if (deferred && !MATDATA_PASS_ENABLED(wpd)) {
+ return;
+ }
+
if (workbench_material_determine_color_type(wpd, material->ima, ob) == V3D_SHADING_TEXTURE_COLOR) {
+ ImBuf *ibuf = BKE_image_acquire_ibuf(material->ima, NULL, NULL);
+ const bool do_color_correction = (ibuf && (ibuf->colormanage_flag & IMB_COLORMANAGE_IS_DATA) == 0);
+ BKE_image_release_ibuf(material->ima, ibuf, NULL);
GPUTexture *tex = GPU_texture_from_blender(material->ima, NULL, GL_TEXTURE_2D, false, 0.0f);
DRW_shgroup_uniform_texture(grp, "image", tex);
+ DRW_shgroup_uniform_bool_copy(grp, "imageSrgb", do_color_correction);
}
else {
- DRW_shgroup_uniform_vec4(grp, "materialDiffuseColor", material->diffuse_color, 1);
+ DRW_shgroup_uniform_vec3(grp, "materialDiffuseColor", (use_metallic) ? material->base_color : material->diffuse_color, 1);
}
if (SPECULAR_HIGHLIGHT_ENABLED(wpd)) {
- DRW_shgroup_uniform_vec4(grp, "materialSpecularColor", material->specular_color, 1);
+ if (use_metallic) {
+ DRW_shgroup_uniform_float(grp, "materialMetallic", &material->metallic, 1);
+ }
+ else {
+ DRW_shgroup_uniform_vec3(grp, "materialSpecularColor", material->specular_color, 1);
+ }
DRW_shgroup_uniform_float(grp, "materialRoughness", &material->roughness, 1);
}
}
@@ -193,8 +216,10 @@ void workbench_material_shgroup_uniform(
void workbench_material_copy(WORKBENCH_MaterialData *dest_material, const WORKBENCH_MaterialData *source_material)
{
dest_material->object_id = source_material->object_id;
- copy_v4_v4(dest_material->diffuse_color, source_material->diffuse_color);
- copy_v4_v4(dest_material->specular_color, source_material->specular_color);
+ copy_v3_v3(dest_material->base_color, source_material->base_color);
+ copy_v3_v3(dest_material->diffuse_color, source_material->diffuse_color);
+ copy_v3_v3(dest_material->specular_color, source_material->specular_color);
+ dest_material->metallic = source_material->metallic;
dest_material->roughness = source_material->roughness;
dest_material->ima = source_material->ima;
}
diff --git a/source/blender/draw/engines/workbench/workbench_private.h b/source/blender/draw/engines/workbench/workbench_private.h
index 93b3bddfb72..080817c7f53 100644
--- a/source/blender/draw/engines/workbench/workbench_private.h
+++ b/source/blender/draw/engines/workbench/workbench_private.h
@@ -40,16 +40,22 @@
#define WORKBENCH_ENGINE "BLENDER_WORKBENCH"
#define M_GOLDEN_RATION_CONJUGATE 0.618033988749895
-#define MAX_SHADERS (1 << 10)
+#define MAX_COMPOSITE_SHADERS (1 << 6)
+#define MAX_PREPASS_SHADERS (1 << 6)
+#define MAX_ACCUM_SHADERS (1 << 4)
+#define MAX_CAVITY_SHADERS (1 << 3)
#define TEXTURE_DRAWING_ENABLED(wpd) (wpd->shading.color_type & V3D_SHADING_TEXTURE_COLOR)
#define FLAT_ENABLED(wpd) (wpd->shading.light == V3D_LIGHTING_FLAT)
#define STUDIOLIGHT_ENABLED(wpd) (wpd->shading.light == V3D_LIGHTING_STUDIO)
#define MATCAP_ENABLED(wpd) (wpd->shading.light == V3D_LIGHTING_MATCAP)
-#define STUDIOLIGHT_ORIENTATION_WORLD_ENABLED(wpd) (STUDIOLIGHT_ENABLED(wpd) && (wpd->studio_light->flag & STUDIOLIGHT_ORIENTATION_WORLD))
-#define STUDIOLIGHT_ORIENTATION_CAMERA_ENABLED(wpd) (STUDIOLIGHT_ENABLED(wpd) && (wpd->studio_light->flag & STUDIOLIGHT_ORIENTATION_CAMERA))
-#define STUDIOLIGHT_ORIENTATION_VIEWNORMAL_ENABLED(wpd) (MATCAP_ENABLED(wpd) && (wpd->studio_light->flag & STUDIOLIGHT_ORIENTATION_VIEWNORMAL))
-#define CAVITY_ENABLED(wpd) (wpd->shading.flag & V3D_SHADING_CAVITY)
+#define USE_WORLD_ORIENTATION(wpd) ((wpd->shading.flag & V3D_SHADING_WORLD_ORIENTATION) != 0)
+#define STUDIOLIGHT_TYPE_WORLD_ENABLED(wpd) (STUDIOLIGHT_ENABLED(wpd) && (wpd->studio_light->flag & STUDIOLIGHT_TYPE_WORLD))
+#define STUDIOLIGHT_TYPE_STUDIO_ENABLED(wpd) (STUDIOLIGHT_ENABLED(wpd) && (wpd->studio_light->flag & STUDIOLIGHT_TYPE_STUDIO))
+#define STUDIOLIGHT_TYPE_MATCAP_ENABLED(wpd) (MATCAP_ENABLED(wpd) && (wpd->studio_light->flag & STUDIOLIGHT_TYPE_MATCAP))
+#define SSAO_ENABLED(wpd) ((wpd->shading.flag & V3D_SHADING_CAVITY) && ((wpd->shading.cavity_type == V3D_SHADING_CAVITY_SSAO) || (wpd->shading.cavity_type == V3D_SHADING_CAVITY_BOTH)))
+#define CURVATURE_ENABLED(wpd) ((wpd->shading.flag & V3D_SHADING_CAVITY) && ((wpd->shading.cavity_type == V3D_SHADING_CAVITY_CURVATURE) || (wpd->shading.cavity_type == V3D_SHADING_CAVITY_BOTH)))
+#define CAVITY_ENABLED(wpd) (CURVATURE_ENABLED(wpd) || SSAO_ENABLED(wpd))
#define SHADOW_ENABLED(wpd) (wpd->shading.flag & V3D_SHADING_SHADOW)
#define GHOST_ENABLED(psl) (!DRW_pass_is_empty(psl->ghost_prepass_pass) || !DRW_pass_is_empty(psl->ghost_prepass_hair_pass))
@@ -58,10 +64,12 @@
(IN_RANGE(wpd->user_preferences->gpu_viewport_quality, GPU_VIEWPORT_QUALITY_FXAA, GPU_VIEWPORT_QUALITY_TAA8) || \
((IS_NAVIGATING(wpd) || wpd->is_playback) && (wpd->user_preferences->gpu_viewport_quality >= GPU_VIEWPORT_QUALITY_TAA8))))
#define TAA_ENABLED(wpd) (DRW_state_is_image_render() || (wpd->user_preferences->gpu_viewport_quality >= GPU_VIEWPORT_QUALITY_TAA8 && !IS_NAVIGATING(wpd) && !wpd->is_playback))
-#define SPECULAR_HIGHLIGHT_ENABLED(wpd) ((wpd->shading.flag & V3D_SHADING_SPECULAR_HIGHLIGHT) && (!STUDIOLIGHT_ORIENTATION_VIEWNORMAL_ENABLED(wpd)))
-#define OBJECT_ID_PASS_ENABLED(wpd) (wpd->shading.flag & V3D_SHADING_OBJECT_OUTLINE)
-#define NORMAL_VIEWPORT_COMP_PASS_ENABLED(wpd) (MATCAP_ENABLED(wpd) || STUDIOLIGHT_ENABLED(wpd) || SHADOW_ENABLED(wpd) || SPECULAR_HIGHLIGHT_ENABLED(wpd))
-#define NORMAL_VIEWPORT_PASS_ENABLED(wpd) (NORMAL_VIEWPORT_COMP_PASS_ENABLED(wpd) || CAVITY_ENABLED(wpd))
+#define SPECULAR_HIGHLIGHT_ENABLED(wpd) (STUDIOLIGHT_ENABLED(wpd) && (wpd->shading.flag & V3D_SHADING_SPECULAR_HIGHLIGHT) && (!STUDIOLIGHT_TYPE_MATCAP_ENABLED(wpd)))
+#define OBJECT_OUTLINE_ENABLED(wpd) (wpd->shading.flag & V3D_SHADING_OBJECT_OUTLINE)
+#define OBJECT_ID_PASS_ENABLED(wpd) (OBJECT_OUTLINE_ENABLED(wpd) || CURVATURE_ENABLED(wpd))
+#define MATDATA_PASS_ENABLED(wpd) (wpd->shading.color_type != V3D_SHADING_SINGLE_COLOR || MATCAP_ENABLED(wpd))
+#define NORMAL_VIEWPORT_COMP_PASS_ENABLED(wpd) (MATCAP_ENABLED(wpd) || STUDIOLIGHT_ENABLED(wpd) || SHADOW_ENABLED(wpd))
+#define NORMAL_VIEWPORT_PASS_ENABLED(wpd) (NORMAL_VIEWPORT_COMP_PASS_ENABLED(wpd) || SSAO_ENABLED(wpd) || CURVATURE_ENABLED(wpd))
#define NORMAL_ENCODING_ENABLED() (true)
@@ -76,6 +84,7 @@ typedef struct WORKBENCH_FramebufferList {
struct GPUFrameBuffer *ghost_prepass_fb;
struct GPUFrameBuffer *cavity_fb;
struct GPUFrameBuffer *composite_fb;
+ struct GPUFrameBuffer *id_clear_fb;
struct GPUFrameBuffer *effect_fb;
struct GPUFrameBuffer *effect_taa_fb;
@@ -113,6 +122,7 @@ typedef struct WORKBENCH_PassList {
struct DRWPass *shadow_depth_fail_caps_mani_pass;
struct DRWPass *composite_pass;
struct DRWPass *composite_shadow_pass;
+ struct DRWPass *background_pass;
struct DRWPass *ghost_resolve_pass;
struct DRWPass *effect_aa_pass;
struct DRWPass *volume_pass;
@@ -133,24 +143,24 @@ typedef struct WORKBENCH_Data {
} WORKBENCH_Data;
typedef struct WORKBENCH_UBO_Light {
- float light_direction_vs[4];
- float specular_color[3];
- float energy;
+ float light_direction[4];
+ float specular_color[3], pad;
+ float diffuse_color[3], wrapped;
} WORKBENCH_UBO_Light;
-#define WORKBENCH_SH_DATA_LEN ((STUDIOLIGHT_SH_BANDS == 2) ? 6 : STUDIOLIGHT_SH_EFFECTIVE_COEFS_LEN)
-
typedef struct WORKBENCH_UBO_World {
- float spherical_harmonics_coefs[WORKBENCH_SH_DATA_LEN][4];
float background_color_low[4];
float background_color_high[4];
float object_outline_color[4];
float shadow_direction_vs[4];
- WORKBENCH_UBO_Light lights[3];
+ WORKBENCH_UBO_Light lights[4];
+ float ambient_color[4];
int num_lights;
int matcap_orientation;
float background_alpha;
- int pad[1];
+ float curvature_ridge;
+ float curvature_valley;
+ int pad[3];
} WORKBENCH_UBO_World;
BLI_STATIC_ASSERT_ALIGN(WORKBENCH_UBO_World, 16)
@@ -162,6 +172,7 @@ typedef struct WORKBENCH_PrivateData {
struct GPUShader *prepass_texture_sh;
struct GPUShader *prepass_texture_hair_sh;
struct GPUShader *composite_sh;
+ struct GPUShader *background_sh;
struct GPUShader *transparent_accum_sh;
struct GPUShader *transparent_accum_hair_sh;
struct GPUShader *transparent_accum_texture_sh;
@@ -212,8 +223,10 @@ typedef struct WORKBENCH_EffectInfo {
} WORKBENCH_EffectInfo;
typedef struct WORKBENCH_MaterialData {
- float diffuse_color[4];
- float specular_color[4];
+ float base_color[3];
+ float diffuse_color[3];
+ float specular_color[3];
+ float metallic;
float roughness;
int object_id;
int color_type;
@@ -288,15 +301,16 @@ int workbench_material_determine_color_type(WORKBENCH_PrivateData *wpd, Image *i
char *workbench_material_build_defines(WORKBENCH_PrivateData *wpd, bool use_textures, bool is_hair);
void workbench_material_update_data(WORKBENCH_PrivateData *wpd, Object *ob, Material *mat, WORKBENCH_MaterialData *data);
uint workbench_material_get_hash(WORKBENCH_MaterialData *material_template, bool is_ghost);
-int workbench_material_get_shader_index(WORKBENCH_PrivateData *wpd, bool use_textures, bool is_hair);
-void workbench_material_set_normal_world_matrix(
- DRWShadingGroup *grp, WORKBENCH_PrivateData *wpd, float persistent_matrix[3][3]);
+int workbench_material_get_composite_shader_index(WORKBENCH_PrivateData *wpd);
+int workbench_material_get_prepass_shader_index(WORKBENCH_PrivateData *wpd, bool use_textures, bool is_hair);
+int workbench_material_get_accum_shader_index(WORKBENCH_PrivateData *wpd, bool use_textures, bool is_hair);
void workbench_material_shgroup_uniform(
- WORKBENCH_PrivateData *wpd, DRWShadingGroup *grp, WORKBENCH_MaterialData *material, Object *ob);
+ WORKBENCH_PrivateData *wpd, DRWShadingGroup *grp, WORKBENCH_MaterialData *material, Object *ob,
+ const bool use_metallic, const bool deferred);
void workbench_material_copy(WORKBENCH_MaterialData *dest_material, const WORKBENCH_MaterialData *source_material);
/* workbench_studiolight.c */
-void studiolight_update_world(StudioLight *sl, WORKBENCH_UBO_World *wd);
+void studiolight_update_world(WORKBENCH_PrivateData *wpd, StudioLight *sl, WORKBENCH_UBO_World *wd);
void studiolight_update_light(WORKBENCH_PrivateData *wpd, const float light_direction[3]);
bool studiolight_object_cast_visible_shadow(WORKBENCH_PrivateData *wpd, Object *ob, WORKBENCH_ObjectData *oed);
float studiolight_object_shadow_distance(WORKBENCH_PrivateData *wpd, Object *ob, WORKBENCH_ObjectData *oed);
diff --git a/source/blender/draw/engines/workbench/workbench_studiolight.c b/source/blender/draw/engines/workbench/workbench_studiolight.c
index 901260d0660..52a0e6045c6 100644
--- a/source/blender/draw/engines/workbench/workbench_studiolight.c
+++ b/source/blender/draw/engines/workbench/workbench_studiolight.c
@@ -32,8 +32,48 @@
#include "BLI_math.h"
#include "BKE_global.h"
-void studiolight_update_world(StudioLight *sl, WORKBENCH_UBO_World *wd)
+void studiolight_update_world(WORKBENCH_PrivateData *wpd, StudioLight *studiolight, WORKBENCH_UBO_World *wd)
{
+ float view_matrix[4][4], rot_matrix[4][4];
+ DRW_viewport_matrix_get(view_matrix, DRW_MAT_VIEW);
+
+ if (USE_WORLD_ORIENTATION(wpd)) {
+ axis_angle_to_mat4_single(rot_matrix, 'Z', -wpd->shading.studiolight_rot_z);
+ mul_m4_m4m4(rot_matrix, view_matrix, rot_matrix);
+ swap_v3_v3(rot_matrix[2], rot_matrix[1]);
+ negate_v3(rot_matrix[2]);
+ }
+ else {
+ unit_m4(rot_matrix);
+ }
+
+ if (U.edit_studio_light) {
+ studiolight = BKE_studiolight_studio_edit_get();
+ }
+
+ /* Studio Lights. */
+ for (int i = 0; i < 4; i++) {
+ WORKBENCH_UBO_Light *light = &wd->lights[i];
+
+ SolidLight *sl = &studiolight->light[i];
+ if (sl->flag) {
+ copy_v3_v3(light->light_direction, sl->vec);
+ mul_mat3_m4_v3(rot_matrix, light->light_direction);
+ /* We should predivide the power by PI but that makes the lights really dim. */
+ copy_v3_v3(light->specular_color, sl->spec);
+ copy_v3_v3(light->diffuse_color, sl->col);
+ light->wrapped = sl->smooth;
+ }
+ else {
+ copy_v3_fl3(light->light_direction, 1.0f, 0.0f, 0.0f);
+ copy_v3_fl(light->specular_color, 0.0f);
+ copy_v3_fl(light->diffuse_color, 0.0f);
+ }
+ }
+
+ copy_v3_v3(wd->ambient_color, studiolight->light_ambient);
+
+#if 0
BKE_studiolight_ensure_flag(sl, STUDIOLIGHT_SPHERICAL_HARMONICS_COEFFICIENTS_CALCULATED);
#if STUDIOLIGHT_SH_BANDS == 2
@@ -87,6 +127,7 @@ void studiolight_update_world(StudioLight *sl, WORKBENCH_UBO_World *wd)
copy_v3_v3(wd->spherical_harmonics_coefs[i], sl->spherical_harmonics_coefs[i]);
}
#endif
+#endif
}
static void compute_parallel_lines_nor_and_dist(const float v1[2], const float v2[2], const float v3[2], float r_line[2])
diff --git a/source/blender/draw/intern/DRW_render.h b/source/blender/draw/intern/DRW_render.h
index faba85c9b46..89aa55c56b2 100644
--- a/source/blender/draw/intern/DRW_render.h
+++ b/source/blender/draw/intern/DRW_render.h
@@ -283,9 +283,9 @@ typedef enum {
DRW_STATE_CULL_FRONT = (1 << 9),
DRW_STATE_WIRE = (1 << 10),
DRW_STATE_POINT = (1 << 11),
- DRW_STATE_STIPPLE_2 = (1 << 12),
- DRW_STATE_STIPPLE_3 = (1 << 13),
- DRW_STATE_STIPPLE_4 = (1 << 14),
+ DRW_STATE_OFFSET_POSITIVE = (1 << 12), /* Polygon offset. Does not work with lines and points. */
+ DRW_STATE_OFFSET_NEGATIVE = (1 << 13), /* Polygon offset. Does not work with lines and points. */
+ /* DRW_STATE_STIPPLE_4 = (1 << 14), */ /* Not used */
DRW_STATE_BLEND = (1 << 15),
DRW_STATE_ADDITIVE = (1 << 16),
DRW_STATE_MULTIPLY = (1 << 17),
@@ -296,6 +296,7 @@ typedef enum {
DRW_STATE_WIRE_SMOOTH = (1 << 22),
DRW_STATE_TRANS_FEEDBACK = (1 << 23),
DRW_STATE_BLEND_OIT = (1 << 24),
+ DRW_STATE_FIRST_VERTEX_CONVENTION = (1 << 25),
DRW_STATE_WRITE_STENCIL = (1 << 27),
DRW_STATE_WRITE_STENCIL_SHADOW_PASS = (1 << 28),
@@ -512,9 +513,13 @@ DrawData *DRW_drawdata_ensure(
bool DRW_object_is_renderable(const struct Object *ob);
bool DRW_object_is_visible_in_active_context(const struct Object *ob);
bool DRW_object_is_flat_normal(const struct Object *ob);
+bool DRW_object_use_hide_faces(const struct Object *ob);
bool DRW_object_is_visible_psys_in_active_context(const struct Object *object, const struct ParticleSystem *psys);
+struct Object *DRW_object_get_dupli_parent(const struct Object *ob);
+struct DupliObject *DRW_object_get_dupli(const struct Object *ob);
+
/* Draw commands */
void DRW_draw_pass(DRWPass *pass);
void DRW_draw_pass_subset(DRWPass *pass, DRWShadingGroup *start_group, DRWShadingGroup *end_group);
@@ -552,6 +557,7 @@ bool DRW_state_is_depth(void);
bool DRW_state_is_image_render(void);
bool DRW_state_is_scene_render(void);
bool DRW_state_is_opengl_render(void);
+bool DRW_state_is_playback(void);
bool DRW_state_show_text(void);
bool DRW_state_draw_support(void);
bool DRW_state_draw_background(void);
diff --git a/source/blender/draw/intern/draw_armature.c b/source/blender/draw/intern/draw_armature.c
index aec25274ab1..b8b53fbbb78 100644
--- a/source/blender/draw/intern/draw_armature.c
+++ b/source/blender/draw/intern/draw_armature.c
@@ -940,7 +940,7 @@ static void edbo_compute_bbone_child(bArmature *arm)
}
}
-/* A version of b_bone_spline_setup() for previewing editmode curve settings. */
+/* A version of BKE_pchan_bbone_spline_setup() for previewing editmode curve settings. */
static void ebone_spline_preview(EditBone *ebone, float result_array[MAX_BBONE_SUBDIV][4][4])
{
BBoneSplineParameters param;
@@ -1043,7 +1043,7 @@ static void ebone_spline_preview(EditBone *ebone, float result_array[MAX_BBONE_S
param.curveOutX = ebone->curveOutX;
param.curveOutY = ebone->curveOutY;
- ebone->segments = BKE_compute_b_bone_spline(&param, (Mat4 *)result_array);
+ ebone->segments = BKE_pchan_bbone_spline_compute(&param, (Mat4 *)result_array);
}
static void draw_bone_update_disp_matrix_bbone(EditBone *eBone, bPoseChannel *pchan)
@@ -1086,7 +1086,7 @@ static void draw_bone_update_disp_matrix_bbone(EditBone *eBone, bPoseChannel *pc
memcpy(bbones_mat, pchan->runtime.bbone_pose_mats, sizeof(Mat4) * bbone_segments);
}
else {
- b_bone_spline_setup(pchan, false, bbones_mat);
+ BKE_pchan_bbone_spline_setup(pchan, false, bbones_mat);
}
for (int i = bbone_segments; i--; bbones_mat++) {
diff --git a/source/blender/draw/intern/draw_cache.c b/source/blender/draw/intern/draw_cache.c
index 4857f4c0bb2..c9be2cb4b31 100644
--- a/source/blender/draw/intern/draw_cache.c
+++ b/source/blender/draw/intern/draw_cache.c
@@ -39,6 +39,7 @@
#include "BLI_math.h"
#include "BLI_listbase.h"
+#include "BKE_object.h"
#include "BKE_object_deform.h"
#include "GPU_batch.h"
@@ -49,6 +50,7 @@
#include "draw_cache.h"
#include "draw_cache_impl.h"
+#include "draw_manager.h"
/* Batch's only (free'd as an array) */
static struct DRWShapeCache {
@@ -693,25 +695,21 @@ GPUBatch *DRW_cache_object_edge_detection_get(Object *ob, bool *r_is_manifold)
}
/* Returns a buffer texture. */
-void DRW_cache_object_face_wireframe_get(
- Object *ob, struct GPUTexture **r_vert_tx, struct GPUTexture **r_faceid_tx, int *r_tri_count)
+GPUBatch *DRW_cache_object_face_wireframe_get(Object *ob)
{
switch (ob->type) {
case OB_MESH:
- DRW_cache_mesh_face_wireframe_get(ob, r_vert_tx, r_faceid_tx, r_tri_count);
- break;
+ return DRW_cache_mesh_face_wireframe_get(ob);
case OB_CURVE:
- DRW_cache_curve_face_wireframe_get(ob, r_vert_tx, r_faceid_tx, r_tri_count);
- break;
+ return DRW_cache_curve_face_wireframe_get(ob);
case OB_SURF:
- DRW_cache_surf_face_wireframe_get(ob, r_vert_tx, r_faceid_tx, r_tri_count);
- break;
+ return DRW_cache_surf_face_wireframe_get(ob);
case OB_FONT:
- DRW_cache_text_face_wireframe_get(ob, r_vert_tx, r_faceid_tx, r_tri_count);
- break;
+ return DRW_cache_text_face_wireframe_get(ob);
case OB_MBALL:
- DRW_cache_mball_face_wireframe_get(ob, r_vert_tx, r_faceid_tx, r_tri_count);
- break;
+ return DRW_cache_mball_face_wireframe_get(ob);
+ default:
+ return NULL;
}
}
@@ -720,8 +718,14 @@ GPUBatch *DRW_cache_object_loose_edges_get(struct Object *ob)
switch (ob->type) {
case OB_MESH:
return DRW_cache_mesh_loose_edges_get(ob);
-
- /* TODO, should match 'DRW_cache_object_surface_get' */
+ case OB_CURVE:
+ return DRW_cache_curve_loose_edges_get(ob);
+ case OB_SURF:
+ return DRW_cache_surf_loose_edges_get(ob);
+ case OB_FONT:
+ return DRW_cache_text_loose_edges_get(ob);
+ case OB_MBALL:
+ /* Cannot have any loose edge */
default:
return NULL;
}
@@ -2988,51 +2992,6 @@ GPUBatch *DRW_cache_single_vert_get(void)
/** \name Meshes
* \{ */
-GPUBatch *DRW_cache_mesh_surface_overlay_get(Object *ob)
-{
- BLI_assert(ob->type == OB_MESH);
- Mesh *me = ob->data;
- return DRW_mesh_batch_cache_get_all_triangles(me);
-}
-
-void DRW_cache_mesh_wire_overlay_get(
- Object *ob,
- GPUBatch **r_tris, GPUBatch **r_ledges, GPUBatch **r_lverts,
- struct GPUTexture **r_data_tex)
-{
- BLI_assert(ob->type == OB_MESH);
-
- Mesh *me = ob->data;
-
- *r_tris = DRW_mesh_batch_cache_get_overlay_triangles(me);
- *r_ledges = DRW_mesh_batch_cache_get_overlay_loose_edges(me);
- *r_lverts = DRW_mesh_batch_cache_get_overlay_loose_verts(me);
- *r_data_tex = DRW_mesh_batch_cache_get_overlay_data_tex(me);
-}
-
-void DRW_cache_mesh_normals_overlay_get(
- Object *ob,
- GPUBatch **r_tris, GPUBatch **r_tris_lnor, GPUBatch **r_ledges, GPUBatch **r_lverts)
-{
- BLI_assert(ob->type == OB_MESH);
-
- Mesh *me = ob->data;
-
- *r_tris = DRW_mesh_batch_cache_get_overlay_triangles_nor(me);
- *r_tris_lnor = DRW_mesh_batch_cache_get_overlay_triangles_lnor(me);
- *r_ledges = DRW_mesh_batch_cache_get_overlay_loose_edges_nor(me);
- *r_lverts = DRW_mesh_batch_cache_get_overlay_loose_verts(me);
-}
-
-GPUBatch *DRW_cache_face_centers_get(Object *ob)
-{
- BLI_assert(ob->type == OB_MESH);
-
- Mesh *me = ob->data;
-
- return DRW_mesh_batch_cache_get_overlay_facedots(me);
-}
-
GPUBatch *DRW_cache_mesh_wire_outline_get(Object *ob)
{
BLI_assert(ob->type == OB_MESH);
@@ -3057,64 +3016,36 @@ GPUBatch *DRW_cache_mesh_surface_get(Object *ob)
return DRW_mesh_batch_cache_get_triangles_with_normals(me);
}
-void DRW_cache_mesh_face_wireframe_get(
- Object *ob, struct GPUTexture **r_vert_tx, struct GPUTexture **r_faceid_tx, int *r_tri_count)
+GPUBatch *DRW_cache_mesh_wire_get(Object *ob)
{
BLI_assert(ob->type == OB_MESH);
Mesh *me = ob->data;
- DRW_mesh_batch_cache_get_wireframes_face_texbuf(me, r_vert_tx, r_faceid_tx, r_tri_count);
+ return DRW_mesh_batch_cache_get_wire_loops(me);
}
-GPUBatch *DRW_cache_mesh_loose_edges_get(Object *ob)
+GPUBatch *DRW_cache_mesh_face_wireframe_get(Object *ob)
{
BLI_assert(ob->type == OB_MESH);
Mesh *me = ob->data;
- return DRW_mesh_batch_cache_get_loose_edges_with_normals(me);
+ return DRW_mesh_batch_cache_get_wireframes_face(me);
}
-GPUBatch *DRW_cache_mesh_surface_weights_get(Object *ob, ToolSettings *ts, bool paint_mode)
+GPUBatch *DRW_cache_mesh_loose_edges_get(Object *ob)
{
BLI_assert(ob->type == OB_MESH);
Mesh *me = ob->data;
+ return DRW_mesh_batch_cache_get_loose_edges_with_normals(me);
+}
- /* Extract complete vertex weight group selection state and mode flags. */
- struct DRW_MeshWeightState wstate;
- memset(&wstate, 0, sizeof(wstate));
-
- wstate.defgroup_active = ob->actdef - 1;
- wstate.defgroup_len = BLI_listbase_count(&ob->defbase);
-
- wstate.alert_mode = ts->weightuser;
-
- if (paint_mode && ts->multipaint) {
- /* Multipaint needs to know all selected bones, not just the active group.
- * This is actually a relatively expensive operation, but caching would be difficult. */
- wstate.defgroup_sel = BKE_object_defgroup_selected_get(ob, wstate.defgroup_len, &wstate.defgroup_sel_count);
-
- if (wstate.defgroup_sel_count > 1) {
- wstate.flags |= DRW_MESH_WEIGHT_STATE_MULTIPAINT | (ts->auto_normalize ? DRW_MESH_WEIGHT_STATE_AUTO_NORMALIZE : 0);
-
- if (me->editflag & ME_EDIT_MIRROR_X) {
- BKE_object_defgroup_mirror_selection(
- ob, wstate.defgroup_len, wstate.defgroup_sel, wstate.defgroup_sel, &wstate.defgroup_sel_count);
- }
- }
- /* With only one selected bone Multipaint reverts to regular mode. */
- else {
- wstate.defgroup_sel_count = 0;
- MEM_SAFE_FREE(wstate.defgroup_sel);
- }
- }
-
- /* Generate the weight data using the selection. */
- GPUBatch *batch = DRW_mesh_batch_cache_get_triangles_with_normals_and_weights(me, &wstate);
-
- DRW_mesh_weight_state_clear(&wstate);
+GPUBatch *DRW_cache_mesh_surface_weights_get(Object *ob)
+{
+ BLI_assert(ob->type == OB_MESH);
- return batch;
+ Mesh *me = ob->data;
+ return DRW_mesh_batch_cache_get_triangles_with_normals_and_weights(me);
}
GPUBatch *DRW_cache_mesh_surface_vert_colors_get(Object *ob)
@@ -3122,7 +3053,7 @@ GPUBatch *DRW_cache_mesh_surface_vert_colors_get(Object *ob)
BLI_assert(ob->type == OB_MESH);
Mesh *me = ob->data;
- return DRW_mesh_batch_cache_get_triangles_with_normals_and_vert_colors(me);
+ return DRW_mesh_batch_cache_get_surface_vertpaint(me);
}
/* Return list of batches */
@@ -3178,30 +3109,6 @@ GPUBatch *DRW_cache_mesh_verts_get(Object *ob)
return DRW_mesh_batch_cache_get_all_verts(me);
}
-GPUBatch *DRW_cache_mesh_edges_paint_overlay_get(Object *ob, bool use_wire, bool use_sel)
-{
- BLI_assert(ob->type == OB_MESH);
-
- Mesh *me = ob->data;
- return DRW_mesh_batch_cache_get_weight_overlay_edges(me, use_wire, use_sel);
-}
-
-GPUBatch *DRW_cache_mesh_faces_weight_overlay_get(Object *ob)
-{
- BLI_assert(ob->type == OB_MESH);
-
- Mesh *me = ob->data;
- return DRW_mesh_batch_cache_get_weight_overlay_faces(me);
-}
-
-GPUBatch *DRW_cache_mesh_verts_weight_overlay_get(Object *ob)
-{
- BLI_assert(ob->type == OB_MESH);
-
- Mesh *me = ob->data;
- return DRW_mesh_batch_cache_get_weight_overlay_verts(me);
-}
-
void DRW_cache_mesh_sculpt_coords_ensure(Object *ob)
{
BLI_assert(ob->type == OB_MESH);
@@ -3222,15 +3129,15 @@ GPUBatch *DRW_cache_curve_edge_wire_get(Object *ob)
BLI_assert(ob->type == OB_CURVE);
struct Curve *cu = ob->data;
- return DRW_curve_batch_cache_get_wire_edge(cu, ob->runtime.curve_cache);
+ return DRW_curve_batch_cache_get_wire_edge(cu);
}
-GPUBatch *DRW_cache_curve_edge_normal_get(Object *ob, float normal_size)
+GPUBatch *DRW_cache_curve_edge_normal_get(Object *ob)
{
BLI_assert(ob->type == OB_CURVE);
struct Curve *cu = ob->data;
- return DRW_curve_batch_cache_get_normal_edge(cu, ob->runtime.curve_cache, normal_size);
+ return DRW_curve_batch_cache_get_normal_edge(cu);
}
GPUBatch *DRW_cache_curve_edge_overlay_get(Object *ob)
@@ -3238,7 +3145,7 @@ GPUBatch *DRW_cache_curve_edge_overlay_get(Object *ob)
BLI_assert(ELEM(ob->type, OB_CURVE, OB_SURF));
struct Curve *cu = ob->data;
- return DRW_curve_batch_cache_get_overlay_edges(cu);
+ return DRW_curve_batch_cache_get_edit_edges(cu);
}
GPUBatch *DRW_cache_curve_vert_overlay_get(Object *ob, bool handles)
@@ -3246,7 +3153,7 @@ GPUBatch *DRW_cache_curve_vert_overlay_get(Object *ob, bool handles)
BLI_assert(ELEM(ob->type, OB_CURVE, OB_SURF));
struct Curve *cu = ob->data;
- return DRW_curve_batch_cache_get_overlay_verts(cu, handles);
+ return DRW_curve_batch_cache_get_edit_verts(cu, handles);
}
GPUBatch *DRW_cache_curve_surface_get(Object *ob)
@@ -3254,16 +3161,43 @@ GPUBatch *DRW_cache_curve_surface_get(Object *ob)
BLI_assert(ob->type == OB_CURVE);
struct Curve *cu = ob->data;
- return DRW_curve_batch_cache_get_triangles_with_normals(cu, ob->runtime.curve_cache);
+ struct Mesh *mesh_eval = ob->runtime.mesh_eval;
+ if (mesh_eval != NULL) {
+ return DRW_mesh_batch_cache_get_triangles_with_normals(mesh_eval);
+ }
+ else {
+ return DRW_curve_batch_cache_get_triangles_with_normals(cu);
+ }
+}
+
+GPUBatch *DRW_cache_curve_loose_edges_get(Object *ob)
+{
+ BLI_assert(ob->type == OB_CURVE);
+
+ struct Curve *cu = ob->data;
+ struct Mesh *mesh_eval = ob->runtime.mesh_eval;
+ if (mesh_eval != NULL) {
+ return DRW_mesh_batch_cache_get_loose_edges_with_normals(mesh_eval);
+ }
+ else {
+ /* TODO */
+ UNUSED_VARS(cu);
+ return NULL;
+ }
}
-void DRW_cache_curve_face_wireframe_get(
- Object *ob, struct GPUTexture **r_vert_tx, struct GPUTexture **r_faceid_tx, int *r_tri_count)
+GPUBatch *DRW_cache_curve_face_wireframe_get(Object *ob)
{
BLI_assert(ob->type == OB_CURVE);
struct Curve *cu = ob->data;
- DRW_curve_batch_cache_get_wireframes_face_texbuf(cu, ob->runtime.curve_cache, r_vert_tx, r_faceid_tx, r_tri_count);
+ struct Mesh *mesh_eval = ob->runtime.mesh_eval;
+ if (mesh_eval != NULL) {
+ return DRW_mesh_batch_cache_get_wireframes_face(mesh_eval);
+ }
+ else {
+ return DRW_curve_batch_cache_get_wireframes_face(cu);
+ }
}
/* Return list of batches */
@@ -3273,7 +3207,13 @@ GPUBatch **DRW_cache_curve_surface_shaded_get(
BLI_assert(ob->type == OB_CURVE);
struct Curve *cu = ob->data;
- return DRW_curve_batch_cache_get_surface_shaded(cu, ob->runtime.curve_cache, gpumat_array, gpumat_array_len);
+ struct Mesh *mesh_eval = ob->runtime.mesh_eval;
+ if (mesh_eval != NULL) {
+ return DRW_mesh_batch_cache_get_surface_shaded(mesh_eval, gpumat_array, gpumat_array_len, NULL, NULL, NULL);
+ }
+ else {
+ return DRW_curve_batch_cache_get_surface_shaded(cu, gpumat_array, gpumat_array_len);
+ }
}
/** \} */
@@ -3289,11 +3229,10 @@ GPUBatch *DRW_cache_mball_surface_get(Object *ob)
return DRW_metaball_batch_cache_get_triangles_with_normals(ob);
}
-void DRW_cache_mball_face_wireframe_get(
- Object *ob, struct GPUTexture **r_vert_tx, struct GPUTexture **r_faceid_tx, int *r_tri_count)
+GPUBatch *DRW_cache_mball_face_wireframe_get(Object *ob)
{
BLI_assert(ob->type == OB_MBALL);
- return DRW_metaball_batch_cache_get_wireframes_face_texbuf(ob, r_vert_tx, r_faceid_tx, r_tri_count);
+ return DRW_metaball_batch_cache_get_wireframes_face(ob);
}
GPUBatch **DRW_cache_mball_surface_shaded_get(
@@ -3316,57 +3255,73 @@ GPUBatch *DRW_cache_text_edge_wire_get(Object *ob)
BLI_assert(ob->type == OB_FONT);
struct Curve *cu = ob->data;
- return DRW_curve_batch_cache_get_wire_edge(cu, ob->runtime.curve_cache);
+ return DRW_curve_batch_cache_get_wire_edge(cu);
}
GPUBatch *DRW_cache_text_surface_get(Object *ob)
{
BLI_assert(ob->type == OB_FONT);
struct Curve *cu = ob->data;
+ struct Mesh *mesh_eval = ob->runtime.mesh_eval;
if (cu->editfont && (cu->flag & CU_FAST)) {
return NULL;
}
- return DRW_curve_batch_cache_get_triangles_with_normals(cu, ob->runtime.curve_cache);
+ if (mesh_eval != NULL) {
+ return DRW_mesh_batch_cache_get_triangles_with_normals(mesh_eval);
+ }
+ else {
+ return DRW_curve_batch_cache_get_triangles_with_normals(cu);
+ }
}
-void DRW_cache_text_face_wireframe_get(
- Object *ob,
- struct GPUTexture **r_vert_tx, struct GPUTexture **r_faceid_tx, int *r_tri_count)
+GPUBatch *DRW_cache_text_loose_edges_get(Object *ob)
{
BLI_assert(ob->type == OB_FONT);
struct Curve *cu = ob->data;
+ struct Mesh *mesh_eval = ob->runtime.mesh_eval;
if (cu->editfont && (cu->flag & CU_FAST)) {
- *r_vert_tx = NULL;
- *r_faceid_tx = NULL;
- *r_tri_count = 0;
- return;
+ return NULL;
+ }
+ if (mesh_eval != NULL) {
+ return DRW_mesh_batch_cache_get_loose_edges_with_normals(mesh_eval);
+ }
+ else {
+ /* TODO */
+ return NULL;
}
- DRW_curve_batch_cache_get_wireframes_face_texbuf(cu, ob->runtime.curve_cache, r_vert_tx, r_faceid_tx, r_tri_count);
}
-GPUBatch **DRW_cache_text_surface_shaded_get(
- Object *ob, struct GPUMaterial **gpumat_array, uint gpumat_array_len)
+GPUBatch *DRW_cache_text_face_wireframe_get(Object *ob)
{
BLI_assert(ob->type == OB_FONT);
struct Curve *cu = ob->data;
+ struct Mesh *mesh_eval = ob->runtime.mesh_eval;
if (cu->editfont && (cu->flag & CU_FAST)) {
return NULL;
}
- return DRW_curve_batch_cache_get_surface_shaded(cu, ob->runtime.curve_cache, gpumat_array, gpumat_array_len);
-}
-
-GPUBatch *DRW_cache_text_cursor_overlay_get(Object *ob)
-{
- BLI_assert(ob->type == OB_FONT);
- struct Curve *cu = ob->data;
- return DRW_curve_batch_cache_get_overlay_cursor(cu);
+ if (mesh_eval != NULL) {
+ return DRW_mesh_batch_cache_get_wireframes_face(mesh_eval);
+ }
+ else {
+ return DRW_curve_batch_cache_get_wireframes_face(cu);
+ }
}
-GPUBatch *DRW_cache_text_select_overlay_get(Object *ob)
+GPUBatch **DRW_cache_text_surface_shaded_get(
+ Object *ob, struct GPUMaterial **gpumat_array, uint gpumat_array_len)
{
BLI_assert(ob->type == OB_FONT);
struct Curve *cu = ob->data;
- return DRW_curve_batch_cache_get_overlay_select(cu);
+ struct Mesh *mesh_eval = ob->runtime.mesh_eval;
+ if (cu->editfont && (cu->flag & CU_FAST)) {
+ return NULL;
+ }
+ if (mesh_eval != NULL) {
+ return DRW_mesh_batch_cache_get_surface_shaded(mesh_eval, gpumat_array, gpumat_array_len, NULL, NULL, NULL);
+ }
+ else {
+ return DRW_curve_batch_cache_get_surface_shaded(cu, gpumat_array, gpumat_array_len);
+ }
}
/** \} */
@@ -3381,16 +3336,51 @@ GPUBatch *DRW_cache_surf_surface_get(Object *ob)
BLI_assert(ob->type == OB_SURF);
struct Curve *cu = ob->data;
- return DRW_curve_batch_cache_get_triangles_with_normals(cu, ob->runtime.curve_cache);
+ struct Mesh *mesh_eval = ob->runtime.mesh_eval;
+ if (mesh_eval != NULL) {
+ return DRW_mesh_batch_cache_get_triangles_with_normals(mesh_eval);
+ }
+ else {
+ return DRW_curve_batch_cache_get_triangles_with_normals(cu);
+ }
+}
+
+GPUBatch *DRW_cache_surf_edge_wire_get(Object *ob)
+{
+ BLI_assert(ob->type == OB_SURF);
+
+ struct Curve *cu = ob->data;
+ return DRW_curve_batch_cache_get_wire_edge(cu);
+}
+
+GPUBatch *DRW_cache_surf_face_wireframe_get(Object *ob)
+{
+ BLI_assert(ob->type == OB_SURF);
+
+ struct Curve *cu = ob->data;
+ struct Mesh *mesh_eval = ob->runtime.mesh_eval;
+ if (mesh_eval != NULL) {
+ return DRW_mesh_batch_cache_get_wireframes_face(mesh_eval);
+ }
+ else {
+ return DRW_curve_batch_cache_get_wireframes_face(cu);
+ }
}
-void DRW_cache_surf_face_wireframe_get(
- Object *ob, struct GPUTexture **r_vert_tx, struct GPUTexture **r_faceid_tx, int *r_tri_count)
+GPUBatch *DRW_cache_surf_loose_edges_get(Object *ob)
{
BLI_assert(ob->type == OB_SURF);
struct Curve *cu = ob->data;
- DRW_curve_batch_cache_get_wireframes_face_texbuf(cu, ob->runtime.curve_cache, r_vert_tx, r_faceid_tx, r_tri_count);
+ struct Mesh *mesh_eval = ob->runtime.mesh_eval;
+ if (mesh_eval != NULL) {
+ return DRW_mesh_batch_cache_get_loose_edges_with_normals(mesh_eval);
+ }
+ else {
+ /* TODO */
+ UNUSED_VARS(cu);
+ return NULL;
+ }
}
/* Return list of batches */
@@ -3400,7 +3390,13 @@ GPUBatch **DRW_cache_surf_surface_shaded_get(
BLI_assert(ob->type == OB_SURF);
struct Curve *cu = ob->data;
- return DRW_curve_batch_cache_get_surface_shaded(cu, ob->runtime.curve_cache, gpumat_array, gpumat_array_len);
+ struct Mesh *mesh_eval = ob->runtime.mesh_eval;
+ if (mesh_eval != NULL) {
+ return DRW_mesh_batch_cache_get_surface_shaded(mesh_eval, gpumat_array, gpumat_array_len, NULL, NULL, NULL);
+ }
+ else {
+ return DRW_curve_batch_cache_get_surface_shaded(cu, gpumat_array, gpumat_array_len);
+ }
}
/** \} */
@@ -3437,7 +3433,7 @@ GPUBatch *DRW_cache_lattice_vert_overlay_get(Object *ob)
BLI_assert(ob->type == OB_LATTICE);
struct Lattice *lt = ob->data;
- return DRW_lattice_batch_cache_get_overlay_verts(lt);
+ return DRW_lattice_batch_cache_get_edit_verts(lt);
}
/** \} */
@@ -3460,9 +3456,10 @@ GPUBatch *DRW_cache_particles_get_dots(Object *object, ParticleSystem *psys)
GPUBatch *DRW_cache_particles_get_edit_strands(
Object *object,
ParticleSystem *psys,
- struct PTCacheEdit *edit)
+ struct PTCacheEdit *edit,
+ bool use_weight)
{
- return DRW_particles_batch_cache_get_edit_strands(object, psys, edit);
+ return DRW_particles_batch_cache_get_edit_strands(object, psys, edit, use_weight);
}
GPUBatch *DRW_cache_particles_get_edit_inner_points(
@@ -3733,3 +3730,95 @@ GPUBatch *DRW_cache_cursor_get(bool crosshair_lines)
}
return *drw_cursor;
}
+
+/** \} */
+
+/* -------------------------------------------------------------------- */
+
+/** \name Batch Cache Impl. common
+ * \{ */
+
+GPUBatch *DRW_batch_request(GPUBatch **batch)
+{
+ /* XXX TODO(fclem): We are writting to batch cache here. Need to make this thread safe. */
+ if (*batch == NULL) {
+ *batch = MEM_callocN(sizeof(GPUBatch), "GPUBatch");
+ }
+ return *batch;
+}
+
+bool DRW_batch_requested(GPUBatch *batch, int prim_type)
+{
+ /* Batch has been requested if it has been created but not initialized. */
+ if (batch != NULL && batch->verts[0] == NULL) {
+ /* HACK. We init without a valid VBO and let the first vbo binding
+ * fill verts[0]. */
+ GPU_batch_init_ex(batch, prim_type, (GPUVertBuf *)1, NULL, 0);
+ batch->verts[0] = NULL;
+ return true;
+ }
+ return false;
+}
+
+void DRW_ibo_request(GPUBatch *batch, GPUIndexBuf **ibo)
+{
+ if (*ibo == NULL) {
+ *ibo = MEM_callocN(sizeof(GPUIndexBuf), "GPUIndexBuf");
+ }
+ GPU_batch_vao_cache_clear(batch);
+ batch->elem = *ibo;
+}
+
+bool DRW_ibo_requested(GPUIndexBuf *ibo)
+{
+ /* TODO do not rely on data uploaded. This prevents multithreading.
+ * (need access to a gl context) */
+ return (ibo != NULL && ibo->ibo_id == 0 && ibo->data == NULL);
+}
+
+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;
+ }
+}
+
+bool DRW_vbo_requested(GPUVertBuf *vbo)
+{
+ return (vbo != NULL && vbo->format.attr_len == 0);
+}
+
+void drw_batch_cache_generate_requested(Object *ob)
+{
+ struct Mesh *mesh_eval = ob->runtime.mesh_eval;
+ switch (ob->type) {
+ case OB_MESH:
+ DRW_mesh_batch_cache_create_requested(ob, (Mesh *)ob->data);
+ break;
+ case OB_CURVE:
+ case OB_FONT:
+ case OB_SURF:
+ if (mesh_eval) {
+ DRW_mesh_batch_cache_create_requested(ob, mesh_eval);
+ }
+ DRW_curve_batch_cache_create_requested(ob);
+ break;
+ /* TODO all cases */
+ default:
+ break;
+ }
+}
+
+/** \} */
diff --git a/source/blender/draw/intern/draw_cache.h b/source/blender/draw/intern/draw_cache.h
index f3f41e569ed..cbc4ef413ac 100644
--- a/source/blender/draw/intern/draw_cache.h
+++ b/source/blender/draw/intern/draw_cache.h
@@ -59,8 +59,7 @@ struct GPUBatch *DRW_cache_object_loose_edges_get(struct Object *ob);
struct GPUBatch **DRW_cache_object_surface_material_get(
struct Object *ob, struct GPUMaterial **gpumat_array, uint gpumat_array_len,
char **auto_layer_names, int **auto_layer_is_srgb, int *auto_layer_count);
-void DRW_cache_object_face_wireframe_get(
- Object *ob, struct GPUTexture **r_vert_tx, struct GPUTexture **r_faceid_tx, int *r_tri_count);
+struct GPUBatch *DRW_cache_object_face_wireframe_get(Object *ob);
/* Empties */
struct GPUBatch *DRW_cache_plain_axes_get(void);
@@ -127,35 +126,23 @@ struct GPUBatch *DRW_cache_bone_dof_sphere_get(void);
struct GPUBatch *DRW_cache_bone_dof_lines_get(void);
/* Meshes */
-struct GPUBatch *DRW_cache_mesh_surface_overlay_get(struct Object *ob);
-void DRW_cache_mesh_wire_overlay_get(
- struct Object *ob,
- struct GPUBatch **r_tris, struct GPUBatch **r_ledges, struct GPUBatch **r_lverts,
- struct GPUTexture **r_data_tex);
-void DRW_cache_mesh_normals_overlay_get(
- struct Object *ob,
- struct GPUBatch **r_tris, struct GPUBatch **r_tris_lnor,
- struct GPUBatch **r_ledges, struct GPUBatch **r_lverts);
-struct GPUBatch *DRW_cache_face_centers_get(struct Object *ob);
struct GPUBatch *DRW_cache_mesh_wire_outline_get(struct Object *ob);
struct GPUBatch *DRW_cache_mesh_edge_detection_get(struct Object *ob, bool *r_is_manifold);
struct GPUBatch *DRW_cache_mesh_surface_get(struct Object *ob);
+struct GPUBatch *DRW_cache_mesh_wire_get(struct Object *ob);
struct GPUBatch *DRW_cache_mesh_loose_edges_get(struct Object *ob);
-struct GPUBatch *DRW_cache_mesh_surface_weights_get(struct Object *ob, struct ToolSettings *ts, bool paint_mode);
+struct GPUBatch *DRW_cache_mesh_surface_weights_get(struct Object *ob);
struct GPUBatch *DRW_cache_mesh_surface_vert_colors_get(struct Object *ob);
struct GPUBatch *DRW_cache_mesh_surface_verts_get(struct Object *ob);
struct GPUBatch *DRW_cache_mesh_edges_get(struct Object *ob);
struct GPUBatch *DRW_cache_mesh_verts_get(struct Object *ob);
struct GPUBatch *DRW_cache_mesh_edges_paint_overlay_get(struct Object *ob, bool use_wire, bool use_sel);
-struct GPUBatch *DRW_cache_mesh_faces_weight_overlay_get(struct Object *ob);
-struct GPUBatch *DRW_cache_mesh_verts_weight_overlay_get(struct Object *ob);
struct GPUBatch **DRW_cache_mesh_surface_shaded_get(
struct Object *ob, struct GPUMaterial **gpumat_array, uint gpumat_array_len,
char **auto_layer_names, int **auto_layer_is_srgb, int *auto_layer_count);
struct GPUBatch **DRW_cache_mesh_surface_texpaint_get(struct Object *ob);
struct GPUBatch *DRW_cache_mesh_surface_texpaint_single_get(struct Object *ob);
-void DRW_cache_mesh_face_wireframe_get(
- Object *ob, struct GPUTexture **r_vert_tx, struct GPUTexture **r_faceid_tx, int *r_tri_count);
+struct GPUBatch *DRW_cache_mesh_face_wireframe_get(struct Object *ob);
void DRW_cache_mesh_sculpt_coords_ensure(struct Object *ob);
@@ -164,31 +151,32 @@ struct GPUBatch *DRW_cache_curve_surface_get(struct Object *ob);
struct GPUBatch **DRW_cache_curve_surface_shaded_get(
struct Object *ob, struct GPUMaterial **gpumat_array, uint gpumat_array_len);
struct GPUBatch *DRW_cache_curve_surface_verts_get(struct Object *ob);
+struct GPUBatch *DRW_cache_curve_loose_edges_get(struct Object *ob);
struct GPUBatch *DRW_cache_curve_edge_wire_get(struct Object *ob);
-void DRW_cache_curve_face_wireframe_get(
- Object *ob, struct GPUTexture **r_vert_tx, struct GPUTexture **r_faceid_tx, int *r_tri_count);
+struct GPUBatch *DRW_cache_curve_face_wireframe_get(Object *ob);
/* edit-mode */
-struct GPUBatch *DRW_cache_curve_edge_normal_get(struct Object *ob, float normal_size);
+struct GPUBatch *DRW_cache_curve_edge_normal_get(struct Object *ob);
struct GPUBatch *DRW_cache_curve_edge_overlay_get(struct Object *ob);
struct GPUBatch *DRW_cache_curve_vert_overlay_get(struct Object *ob, bool handles);
/* Font */
-struct GPUBatch *DRW_cache_text_edge_wire_get(struct Object *ob);
struct GPUBatch *DRW_cache_text_surface_get(struct Object *ob);
+struct GPUBatch *DRW_cache_text_loose_edges_get(struct Object *ob);
+struct GPUBatch *DRW_cache_text_edge_wire_get(struct Object *ob);
struct GPUBatch **DRW_cache_text_surface_shaded_get(
struct Object *ob, struct GPUMaterial **gpumat_array, uint gpumat_array_len);
-void DRW_cache_text_face_wireframe_get(
- Object *ob, struct GPUTexture **r_vert_tx, struct GPUTexture **r_faceid_tx, int *r_tri_count);
+struct GPUBatch *DRW_cache_text_face_wireframe_get(Object *ob);
/* edit-mode */
struct GPUBatch *DRW_cache_text_cursor_overlay_get(struct Object *ob);
struct GPUBatch *DRW_cache_text_select_overlay_get(struct Object *ob);
/* Surface */
struct GPUBatch *DRW_cache_surf_surface_get(struct Object *ob);
+struct GPUBatch *DRW_cache_surf_edge_wire_get(struct Object *ob);
+struct GPUBatch *DRW_cache_surf_loose_edges_get(struct Object *ob);
struct GPUBatch **DRW_cache_surf_surface_shaded_get(
struct Object *ob, struct GPUMaterial **gpumat_array, uint gpumat_array_len);
-void DRW_cache_surf_face_wireframe_get(
- Object *ob, struct GPUTexture **r_vert_tx, struct GPUTexture **r_faceid_tx, int *r_tri_count);
+struct GPUBatch *DRW_cache_surf_face_wireframe_get(Object *ob);
/* Lattice */
struct GPUBatch *DRW_cache_lattice_verts_get(struct Object *ob);
@@ -201,7 +189,7 @@ struct GPUBatch *DRW_cache_particles_get_hair(
struct GPUBatch *DRW_cache_particles_get_dots(
struct Object *object, struct ParticleSystem *psys);
struct GPUBatch *DRW_cache_particles_get_edit_strands(
- struct Object *object, struct ParticleSystem *psys, struct PTCacheEdit *edit);
+ struct Object *object, struct ParticleSystem *psys, struct PTCacheEdit *edit, bool use_weight);
struct GPUBatch *DRW_cache_particles_get_edit_inner_points(
struct Object *object, struct ParticleSystem *psys, struct PTCacheEdit *edit);
struct GPUBatch *DRW_cache_particles_get_edit_tip_points(
@@ -217,7 +205,6 @@ struct GPUBatch *DRW_cache_hair_get_edit_strands(struct Object *ob, struct HairS
/* Metaball */
struct GPUBatch *DRW_cache_mball_surface_get(struct Object *ob);
struct GPUBatch **DRW_cache_mball_surface_shaded_get(struct Object *ob, struct GPUMaterial **gpumat_array, uint gpumat_array_len);
-void DRW_cache_mball_face_wireframe_get(
- Object *ob, struct GPUTexture **r_vert_tx, struct GPUTexture **r_faceid_tx, int *r_tri_count);
+struct GPUBatch *DRW_cache_mball_face_wireframe_get(Object *ob);
#endif /* __DRAW_CACHE_H__ */
diff --git a/source/blender/draw/intern/draw_cache_impl.h b/source/blender/draw/intern/draw_cache_impl.h
index c25b7b74532..1a01184f760 100644
--- a/source/blender/draw/intern/draw_cache_impl.h
+++ b/source/blender/draw/intern/draw_cache_impl.h
@@ -69,82 +69,50 @@ void DRW_hair_batch_cache_dirty(struct HairSystem *hsys, int mode);
void DRW_hair_batch_cache_free(struct HairSystem *hsys);
/* Curve */
-struct GPUBatch *DRW_curve_batch_cache_get_wire_edge(struct Curve *cu, struct CurveCache *ob_curve_cache);
-struct GPUBatch *DRW_curve_batch_cache_get_normal_edge(
- struct Curve *cu, struct CurveCache *ob_curve_cache, float normal_size);
-struct GPUBatch *DRW_curve_batch_cache_get_overlay_edges(struct Curve *cu);
-struct GPUBatch *DRW_curve_batch_cache_get_overlay_verts(struct Curve *cu, bool handles);
-
-struct GPUBatch *DRW_curve_batch_cache_get_triangles_with_normals(
- struct Curve *cu, struct CurveCache *ob_curve_cache);
+void DRW_curve_batch_cache_create_requested(struct Object *ob);
+
+struct GPUBatch *DRW_curve_batch_cache_get_wire_edge(struct Curve *cu);
+struct GPUBatch *DRW_curve_batch_cache_get_normal_edge(struct Curve *cu);
+struct GPUBatch *DRW_curve_batch_cache_get_edit_edges(struct Curve *cu);
+struct GPUBatch *DRW_curve_batch_cache_get_edit_verts(struct Curve *cu, bool handles);
+
+struct GPUBatch *DRW_curve_batch_cache_get_triangles_with_normals(struct Curve *cu);
struct GPUBatch **DRW_curve_batch_cache_get_surface_shaded(
- struct Curve *cu, struct CurveCache *ob_curve_cache,
- struct GPUMaterial **gpumat_array, uint gpumat_array_len);
-void DRW_curve_batch_cache_get_wireframes_face_texbuf(
- struct Curve *cu, struct CurveCache *ob_curve_cache,
- struct GPUTexture **verts_data, struct GPUTexture **face_indices, int *tri_count);
+ struct Curve *cu, struct GPUMaterial **gpumat_array, uint gpumat_array_len);
+struct GPUBatch *DRW_curve_batch_cache_get_wireframes_face(struct Curve *cu);
/* Metaball */
struct GPUBatch *DRW_metaball_batch_cache_get_triangles_with_normals(struct Object *ob);
struct GPUBatch **DRW_metaball_batch_cache_get_surface_shaded(struct Object *ob, struct MetaBall *mb, struct GPUMaterial **gpumat_array, uint gpumat_array_len);
-void DRW_metaball_batch_cache_get_wireframes_face_texbuf(
- struct Object *ob, struct GPUTexture **verts_data, struct GPUTexture **face_indices, int *tri_count);
-
-/* Curve (Font) */
-struct GPUBatch *DRW_curve_batch_cache_get_overlay_cursor(struct Curve *cu);
-struct GPUBatch *DRW_curve_batch_cache_get_overlay_select(struct Curve *cu);
+struct GPUBatch *DRW_metaball_batch_cache_get_wireframes_face(struct Object *ob);
/* DispList */
-struct GPUVertBuf *DRW_displist_vertbuf_calc_pos_with_normals(struct ListBase *lb);
-struct GPUIndexBuf *DRW_displist_indexbuf_calc_triangles_in_order(struct ListBase *lb);
-struct GPUIndexBuf **DRW_displist_indexbuf_calc_triangles_in_order_split_by_material(
- struct ListBase *lb, uint gpumat_array_len);
-struct GPUBatch **DRW_displist_batch_calc_tri_pos_normals_and_uv_split_by_material(
- struct ListBase *lb, uint gpumat_array_len);
-struct GPUVertBuf *DRW_displist_create_edges_overlay_texture_buf(ListBase *lb);
+void DRW_displist_vertbuf_create_pos_and_nor(struct ListBase *lb, struct GPUVertBuf *vbo);
+void DRW_displist_vertbuf_create_pos_and_nor_and_uv_tess(
+ struct ListBase *lb, struct GPUVertBuf *vbo_pos_nor, struct GPUVertBuf *vbo_uv);
+void DRW_displist_vertbuf_create_wireframe_data_tess(struct ListBase *lb, struct GPUVertBuf *vbo);
+void DRW_displist_indexbuf_create_triangles_in_order(struct ListBase *lb, struct GPUIndexBuf *vbo);
+void DRW_displist_indexbuf_create_triangles_tess_split_by_material(
+ struct ListBase *lb, struct GPUIndexBuf **ibo_mat, uint mat_len);
/* Lattice */
struct GPUBatch *DRW_lattice_batch_cache_get_all_edges(struct Lattice *lt, bool use_weight, const int actdef);
struct GPUBatch *DRW_lattice_batch_cache_get_all_verts(struct Lattice *lt);
-struct GPUBatch *DRW_lattice_batch_cache_get_overlay_verts(struct Lattice *lt);
-
-/* Vertex Group Selection and display options */
-struct DRW_MeshWeightState {
- int defgroup_active;
- int defgroup_len;
-
- short flags;
- char alert_mode;
-
- /* Set of all selected bones for Multipaint. */
- bool *defgroup_sel; /* [defgroup_len] */
- int defgroup_sel_count;
-};
-
-/* DRW_MeshWeightState.flags */
-enum {
- DRW_MESH_WEIGHT_STATE_MULTIPAINT = (1 << 0),
- DRW_MESH_WEIGHT_STATE_AUTO_NORMALIZE = (1 << 1),
-};
-
-void DRW_mesh_weight_state_clear(struct DRW_MeshWeightState *wstate);
-void DRW_mesh_weight_state_copy(struct DRW_MeshWeightState *wstate_dst, const struct DRW_MeshWeightState *wstate_src);
-bool DRW_mesh_weight_state_compare(const struct DRW_MeshWeightState *a, const struct DRW_MeshWeightState *b);
+struct GPUBatch *DRW_lattice_batch_cache_get_edit_verts(struct Lattice *lt);
/* Mesh */
+void DRW_mesh_batch_cache_create_requested(struct Object *ob, struct Mesh *me);
+
struct GPUBatch **DRW_mesh_batch_cache_get_surface_shaded(
struct Mesh *me, struct GPUMaterial **gpumat_array, uint gpumat_array_len,
char **auto_layer_names, int **auto_layer_is_srgb, int *auto_layer_count);
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_weight_overlay_edges(struct Mesh *me, bool use_wire, bool use_sel);
-struct GPUBatch *DRW_mesh_batch_cache_get_weight_overlay_faces(struct Mesh *me);
-struct GPUBatch *DRW_mesh_batch_cache_get_weight_overlay_verts(struct Mesh *me);
+struct GPUBatch *DRW_mesh_batch_cache_get_surface_vertpaint(struct Mesh *me);
+struct GPUBatch *DRW_mesh_batch_cache_get_wire_loops(struct Mesh *me);
struct GPUBatch *DRW_mesh_batch_cache_get_all_edges(struct Mesh *me);
-struct GPUBatch *DRW_mesh_batch_cache_get_all_triangles(struct Mesh *me);
struct GPUBatch *DRW_mesh_batch_cache_get_triangles_with_normals(struct Mesh *me);
-struct GPUBatch *DRW_mesh_batch_cache_get_triangles_with_normals_and_weights(struct Mesh *me, const struct DRW_MeshWeightState *wstate);
-struct GPUBatch *DRW_mesh_batch_cache_get_triangles_with_normals_and_vert_colors(struct Mesh *me);
+struct GPUBatch *DRW_mesh_batch_cache_get_triangles_with_normals_and_weights(struct Mesh *me);
struct GPUBatch *DRW_mesh_batch_cache_get_triangles_with_select_id(struct Mesh *me, bool use_hide, uint select_id_offset);
struct GPUBatch *DRW_mesh_batch_cache_get_triangles_with_select_mask(struct Mesh *me, bool use_hide);
struct GPUBatch *DRW_mesh_batch_cache_get_loose_edges_with_normals(struct Mesh *me);
@@ -152,22 +120,20 @@ struct GPUBatch *DRW_mesh_batch_cache_get_points_with_normals(struct Mesh *me);
struct GPUBatch *DRW_mesh_batch_cache_get_all_verts(struct Mesh *me);
struct GPUBatch *DRW_mesh_batch_cache_get_fancy_edges(struct Mesh *me);
struct GPUBatch *DRW_mesh_batch_cache_get_edge_detection(struct Mesh *me, bool *r_is_manifold);
-struct GPUBatch *DRW_mesh_batch_cache_get_overlay_triangles(struct Mesh *me);
-struct GPUBatch *DRW_mesh_batch_cache_get_overlay_triangles_nor(struct Mesh *me);
-struct GPUBatch *DRW_mesh_batch_cache_get_overlay_triangles_lnor(struct Mesh *me);
-struct GPUBatch *DRW_mesh_batch_cache_get_overlay_verts(struct Mesh *me);
-struct GPUBatch *DRW_mesh_batch_cache_get_overlay_loose_edges(struct Mesh *me);
-struct GPUBatch *DRW_mesh_batch_cache_get_overlay_loose_edges_nor(struct Mesh *me);
-struct GPUBatch *DRW_mesh_batch_cache_get_overlay_loose_verts(struct Mesh *me);
-struct GPUBatch *DRW_mesh_batch_cache_get_overlay_facedots(struct Mesh *me);
-struct GPUTexture *DRW_mesh_batch_cache_get_overlay_data_tex(struct Mesh *me);
+struct GPUBatch *DRW_mesh_batch_cache_get_edit_triangles(struct Mesh *me);
+struct GPUBatch *DRW_mesh_batch_cache_get_edit_triangles_nor(struct Mesh *me);
+struct GPUBatch *DRW_mesh_batch_cache_get_edit_triangles_lnor(struct Mesh *me);
+struct GPUBatch *DRW_mesh_batch_cache_get_edit_vertices(struct Mesh *me);
+struct GPUBatch *DRW_mesh_batch_cache_get_edit_loose_edges(struct Mesh *me);
+struct GPUBatch *DRW_mesh_batch_cache_get_edit_loose_edges_nor(struct Mesh *me);
+struct GPUBatch *DRW_mesh_batch_cache_get_edit_loose_verts(struct Mesh *me);
+struct GPUBatch *DRW_mesh_batch_cache_get_edit_facedots(struct Mesh *me);
/* edit-mesh selection (use generic function for faces) */
struct GPUBatch *DRW_mesh_batch_cache_get_facedots_with_select_id(struct Mesh *me, uint select_id_offset);
struct GPUBatch *DRW_mesh_batch_cache_get_edges_with_select_id(struct Mesh *me, uint select_id_offset);
struct GPUBatch *DRW_mesh_batch_cache_get_verts_with_select_id(struct Mesh *me, uint select_id_offset);
/* Object mode Wireframe overlays */
-void DRW_mesh_batch_cache_get_wireframes_face_texbuf(
- struct Mesh *me, struct GPUTexture **verts_data, struct GPUTexture **face_indices, int *tri_count);
+struct GPUBatch *DRW_mesh_batch_cache_get_wireframes_face(struct Mesh *me);
void DRW_mesh_cache_sculpt_coords_ensure(struct Mesh *me);
@@ -217,7 +183,7 @@ struct GPUBatch *DRW_particles_batch_cache_get_hair(
struct GPUBatch *DRW_particles_batch_cache_get_dots(
struct Object *object, struct ParticleSystem *psys);
struct GPUBatch *DRW_particles_batch_cache_get_edit_strands(
- struct Object *object, struct ParticleSystem *psys, struct PTCacheEdit *edit);
+ struct Object *object, struct ParticleSystem *psys, struct PTCacheEdit *edit, bool use_weight);
struct GPUBatch *DRW_particles_batch_cache_get_edit_inner_points(
struct Object *object, struct ParticleSystem *psys, struct PTCacheEdit *edit);
struct GPUBatch *DRW_particles_batch_cache_get_edit_tip_points(
@@ -229,4 +195,19 @@ struct GPUBatch *DRW_hair_batch_cache_get_edit_follicle_normals(struct Object *o
struct GPUBatch *DRW_hair_batch_cache_get_edit_follicle_axes(struct Object *ob, struct HairSystem *hsys);
struct GPUBatch *DRW_hair_batch_cache_get_edit_strands(struct Object *ob, struct HairSystem *hsys);
+/* Common */
+#define DRW_ADD_FLAG_FROM_VBO_REQUEST(flag, vbo, value) (flag |= DRW_vbo_requested(vbo) ? value : 0)
+#define DRW_ADD_FLAG_FROM_IBO_REQUEST(flag, ibo, value) (flag |= DRW_ibo_requested(ibo) ? value : 0)
+
+/* Test and assign NULL if test fails */
+#define DRW_TEST_ASSIGN_VBO(v) (v = (DRW_vbo_requested(v) ? v : NULL))
+#define DRW_TEST_ASSIGN_IBO(v) (v = (DRW_ibo_requested(v) ? v : NULL))
+
+struct GPUBatch *DRW_batch_request(struct GPUBatch **batch);
+bool DRW_batch_requested(struct GPUBatch *batch, int prim_type);
+void DRW_ibo_request(struct GPUBatch *batch, struct GPUIndexBuf **ibo);
+bool DRW_ibo_requested(struct GPUIndexBuf *ibo);
+void DRW_vbo_request(struct GPUBatch *batch, struct GPUVertBuf **vbo);
+bool DRW_vbo_requested(struct GPUVertBuf *vbo);
+
#endif /* __DRAW_CACHE_IMPL_H__ */
diff --git a/source/blender/draw/intern/draw_cache_impl_curve.c b/source/blender/draw/intern/draw_cache_impl_curve.c
index f214f722c0b..ecdbdcf094f 100644
--- a/source/blender/draw/intern/draw_cache_impl_curve.c
+++ b/source/blender/draw/intern/draw_cache_impl_curve.c
@@ -35,11 +35,12 @@
#include "DNA_curve_types.h"
#include "BKE_curve.h"
-
+#include "BKE_displist.h"
#include "BKE_font.h"
#include "GPU_batch.h"
#include "GPU_texture.h"
+#include "GPU_material.h"
#include "UI_resources.h"
@@ -99,23 +100,27 @@ static void curve_render_overlay_verts_edges_len_get(
static void curve_render_wire_verts_edges_len_get(
const CurveCache *ob_curve_cache,
- int *r_vert_len, int *r_edge_len)
+ int *r_curve_len, int *r_vert_len, int *r_edge_len)
{
BLI_assert(r_vert_len || r_edge_len);
int vert_len = 0;
int edge_len = 0;
+ int curve_len = 0;
for (const BevList *bl = ob_curve_cache->bev.first; bl; bl = bl->next) {
if (bl->nr > 0) {
const bool is_cyclic = bl->poly != -1;
-
- /* verts */
+ edge_len += (is_cyclic) ? bl->nr : bl->nr - 1;
vert_len += bl->nr;
-
- /* edges */
- edge_len += bl->nr;
- if (!is_cyclic) {
- edge_len -= 1;
- }
+ curve_len += 1;
+ }
+ }
+ for (const DispList *dl = ob_curve_cache->disp.first; dl; dl = dl->next) {
+ if (ELEM(dl->type, DL_SEGM, DL_POLY)) {
+ BLI_assert(dl->parts == 1);
+ const bool is_cyclic = dl->type == DL_POLY;
+ edge_len += (is_cyclic) ? dl->nr : dl->nr - 1;
+ vert_len += dl->nr;
+ curve_len += 1;
}
}
if (r_vert_len) {
@@ -124,6 +129,9 @@ static void curve_render_wire_verts_edges_len_get(
if (r_edge_len) {
*r_edge_len = edge_len;
}
+ if (r_curve_len) {
+ *r_curve_len = curve_len;
+ }
}
static int curve_render_normal_len_get(const ListBase *lb, const CurveCache *ob_curve_cache)
@@ -159,6 +167,7 @@ typedef struct CurveRenderData {
} overlay;
struct {
+ int curve_len;
int vert_len;
int edge_len;
} wire;
@@ -216,7 +225,7 @@ static CurveRenderData *curve_render_data_create(Curve *cu, CurveCache *ob_curve
if (types & CU_DATATYPE_WIRE) {
curve_render_wire_verts_edges_len_get(
rdata->ob_curve_cache,
- &rdata->wire.vert_len, &rdata->wire.edge_len);
+ &rdata->wire.curve_len, &rdata->wire.vert_len, &rdata->wire.edge_len);
}
if (cu->editnurb) {
@@ -281,67 +290,112 @@ static int curve_render_data_wire_edges_len_get(const CurveRenderData *rdata)
return rdata->wire.edge_len;
}
+static int curve_render_data_wire_curve_len_get(const CurveRenderData *rdata)
+{
+ BLI_assert(rdata->types & CU_DATATYPE_WIRE);
+ return rdata->wire.curve_len;
+}
+
static int curve_render_data_normal_len_get(const CurveRenderData *rdata)
{
BLI_assert(rdata->types & CU_DATATYPE_NORMAL);
return rdata->normal.len;
}
+static void curve_cd_calc_used_gpu_layers(int *cd_layers, struct GPUMaterial **gpumat_array, int gpumat_array_len)
+{
+ GPUVertexAttribs gattribs = {{{0}}};
+ for (int i = 0; i < gpumat_array_len; i++) {
+ struct GPUMaterial *gpumat = gpumat_array[i];
+ if (gpumat == NULL) {
+ continue;
+ }
+ GPU_material_vertex_attributes(gpumat, &gattribs);
+ for (int j = 0; j < gattribs.totlayer; j++) {
+ const char *name = gattribs.layer[j].name;
+ int type = gattribs.layer[j].type;
+
+ /* Curves cannot have named layers.
+ * Note: We could relax this assumption later. */
+ if (name[0] != '\0') {
+ continue;
+ }
+
+ if (type == CD_AUTO_FROM_NAME) {
+ type = CD_MTFACE;
+ }
+
+ switch (type) {
+ case CD_MTFACE:
+ *cd_layers |= CD_MLOOPUV;
+ break;
+ case CD_TANGENT:
+ /* Currently unsupported */
+ // *cd_layers |= CD_TANGENT;
+ break;
+ case CD_MCOL:
+ /* Curve object don't have Color data. */
+ break;
+ case CD_ORCO:
+ *cd_layers |= CD_ORCO;
+ break;
+ }
+ }
+ }
+}
/* ---------------------------------------------------------------------- */
/* Curve GPUBatch Cache */
typedef struct CurveBatchCache {
- /* center-line */
struct {
- GPUVertBuf *verts;
- GPUVertBuf *edges;
- GPUBatch *batch;
- GPUIndexBuf *elem;
- } wire;
+ GPUVertBuf *pos_nor;
+ GPUVertBuf *curves_pos;
+ } ordered;
- /* normals */
struct {
- GPUVertBuf *verts;
- GPUVertBuf *edges;
- GPUBatch *batch;
- GPUIndexBuf *elem;
- } normal;
+ GPUVertBuf *pos_nor;
+ GPUVertBuf *uv;
- /* control handles and vertices */
- struct {
- GPUBatch *edges;
- GPUBatch *verts;
- GPUBatch *verts_no_handles;
- } overlay;
+ GPUVertBuf *wireframe_data;
+ } tess;
struct {
- GPUVertBuf *verts;
- GPUIndexBuf *triangles_in_order;
- GPUBatch **shaded_triangles;
- GPUBatch *batch;
- int mat_len;
- } surface;
-
- /* Wireframes */
+ /* Curve points. Aligned with ordered.pos_nor */
+ GPUVertBuf *curves_nor;
+ GPUVertBuf *curves_weight; /* TODO. */
+ /* Edit points (beztriples and bpoints) */
+ GPUVertBuf *pos;
+ GPUVertBuf *data;
+ } edit;
+
struct {
- GPUVertBuf *elem_vbo;
- GPUTexture *elem_tx;
- GPUTexture *verts_tx;
- uint tri_count;
- } face_wire;
+ GPUIndexBuf *surfaces_tris;
+ GPUIndexBuf *curves_lines;
+ /* Edit mode */
+ GPUIndexBuf *edit_verts_points; /* Only control points. Not handles. */
+ GPUIndexBuf *edit_lines;
+ } ibo;
- /* 3d text */
struct {
- GPUBatch *select;
- GPUBatch *cursor;
- } text;
+ GPUBatch *surfaces;
+ GPUBatch *curves;
+ /* control handles and vertices */
+ GPUBatch *edit_edges;
+ GPUBatch *edit_verts;
+ GPUBatch *edit_handles_verts;
+ GPUBatch *edit_normals;
+ /* Triangles for object mode wireframe. */
+ GPUBatch *wire_triangles;
+ } batch;
+
+ GPUIndexBuf **surf_per_mat_tris;
+ GPUBatch **surf_per_mat;
+ int mat_len;
+ int cd_used, cd_needed;
/* settings to determine if cache is invalid */
bool is_dirty;
-
- float normal_size;
-
bool is_editmode;
} CurveBatchCache;
@@ -355,6 +409,10 @@ static bool curve_batch_cache_valid(Curve *cu)
return false;
}
+ if (cache->mat_len != max_ii(1, cu->totcol)) {
+ return false;
+ }
+
if (cache->is_dirty) {
return false;
}
@@ -394,6 +452,17 @@ static void curve_batch_cache_init(Curve *cu)
}
#endif
+ cache->cd_used = 0;
+ cache->mat_len = max_ii(1, cu->totcol);
+ cache->surf_per_mat_tris = MEM_mallocN(sizeof(*cache->surf_per_mat_tris) * cache->mat_len, __func__);
+ cache->surf_per_mat = MEM_mallocN(sizeof(*cache->surf_per_mat) * cache->mat_len, __func__);
+
+ /* TODO Might be wiser to alloc in one chunck. */
+ for (int i = 0; i < cache->mat_len; ++i) {
+ cache->surf_per_mat_tris[i] = MEM_callocN(sizeof(GPUIndexBuf), "GPUIndexBuf");
+ cache->surf_per_mat[i] = MEM_callocN(sizeof(GPUBatch), "GPUBatch");
+ }
+
cache->is_editmode = (cu->editnurb != NULL) || (cu->editfont != NULL);
cache->is_dirty = false;
@@ -419,14 +488,11 @@ void DRW_curve_batch_cache_dirty_tag(Curve *cu, int mode)
cache->is_dirty = true;
break;
case BKE_CURVE_BATCH_DIRTY_SELECT:
- /* editnurb */
- GPU_BATCH_DISCARD_SAFE(cache->overlay.verts_no_handles);
- GPU_BATCH_DISCARD_SAFE(cache->overlay.verts);
- GPU_BATCH_DISCARD_SAFE(cache->overlay.edges);
-
- /* editfont */
- GPU_BATCH_DISCARD_SAFE(cache->text.select);
- GPU_BATCH_DISCARD_SAFE(cache->text.cursor);
+ GPU_VERTBUF_DISCARD_SAFE(cache->edit.data);
+
+ GPU_BATCH_DISCARD_SAFE(cache->batch.edit_edges);
+ GPU_BATCH_DISCARD_SAFE(cache->batch.edit_verts);
+ GPU_BATCH_DISCARD_SAFE(cache->batch.edit_handles_verts);
break;
default:
BLI_assert(0);
@@ -440,36 +506,35 @@ static void curve_batch_cache_clear(Curve *cu)
return;
}
- GPU_BATCH_DISCARD_SAFE(cache->overlay.verts_no_handles);
- GPU_BATCH_DISCARD_SAFE(cache->overlay.verts);
- GPU_BATCH_DISCARD_SAFE(cache->overlay.edges);
-
- GPU_VERTBUF_DISCARD_SAFE(cache->surface.verts);
- GPU_INDEXBUF_DISCARD_SAFE(cache->surface.triangles_in_order);
-
- GPU_BATCH_DISCARD_ARRAY_SAFE(cache->surface.shaded_triangles, cache->surface.mat_len);
- GPU_BATCH_DISCARD_SAFE(cache->surface.batch);
-
- GPU_VERTBUF_DISCARD_SAFE(cache->face_wire.elem_vbo);
- DRW_TEXTURE_FREE_SAFE(cache->face_wire.elem_tx);
- DRW_TEXTURE_FREE_SAFE(cache->face_wire.verts_tx);
- cache->face_wire.tri_count = 0;
-
- /* don't own vbo & elems */
- GPU_BATCH_DISCARD_SAFE(cache->wire.batch);
- GPU_VERTBUF_DISCARD_SAFE(cache->wire.verts);
- GPU_VERTBUF_DISCARD_SAFE(cache->wire.edges);
- GPU_INDEXBUF_DISCARD_SAFE(cache->wire.elem);
-
- /* don't own vbo & elems */
- GPU_BATCH_DISCARD_SAFE(cache->normal.batch);
- GPU_VERTBUF_DISCARD_SAFE(cache->normal.verts);
- GPU_VERTBUF_DISCARD_SAFE(cache->normal.edges);
- GPU_INDEXBUF_DISCARD_SAFE(cache->normal.elem);
+ for (int i = 0; i < sizeof(cache->ordered) / sizeof(void *); ++i) {
+ GPUVertBuf **vbo = (GPUVertBuf **)&cache->ordered;
+ GPU_VERTBUF_DISCARD_SAFE(vbo[i]);
+ }
+ for (int i = 0; i < sizeof(cache->tess) / sizeof(void *); ++i) {
+ GPUVertBuf **vbo = (GPUVertBuf **)&cache->tess;
+ GPU_VERTBUF_DISCARD_SAFE(vbo[i]);
+ }
+ for (int i = 0; i < sizeof(cache->edit) / sizeof(void *); ++i) {
+ GPUVertBuf **vbo = (GPUVertBuf **)&cache->edit;
+ GPU_VERTBUF_DISCARD_SAFE(vbo[i]);
+ }
+ for (int i = 0; i < sizeof(cache->ibo) / sizeof(void *); ++i) {
+ GPUIndexBuf **ibo = (GPUIndexBuf **)&cache->ibo;
+ GPU_INDEXBUF_DISCARD_SAFE(ibo[i]);
+ }
+ for (int i = 0; i < sizeof(cache->batch) / sizeof(void *); ++i) {
+ GPUBatch **batch = (GPUBatch **)&cache->batch;
+ GPU_BATCH_DISCARD_SAFE(batch[i]);
+ }
- /* 3d text */
- GPU_BATCH_DISCARD_SAFE(cache->text.cursor);
- GPU_BATCH_DISCARD_SAFE(cache->text.select);
+ for (int i = 0; i < cache->mat_len; ++i) {
+ GPU_INDEXBUF_DISCARD_SAFE(cache->surf_per_mat_tris[i]);
+ GPU_BATCH_DISCARD_SAFE(cache->surf_per_mat[i]);
+ }
+ MEM_SAFE_FREE(cache->surf_per_mat_tris);
+ MEM_SAFE_FREE(cache->surf_per_mat);
+ cache->mat_len = 0;
+ cache->cd_used = 0;
}
void DRW_curve_batch_cache_free(Curve *cu)
@@ -484,460 +549,277 @@ void DRW_curve_batch_cache_free(Curve *cu)
* \{ */
/* GPUBatch cache usage. */
-static GPUVertBuf *curve_batch_cache_get_wire_verts(CurveRenderData *rdata, CurveBatchCache *cache)
+static void curve_create_curves_pos(CurveRenderData *rdata, GPUVertBuf *vbo_curves_pos)
{
- BLI_assert(rdata->types & CU_DATATYPE_WIRE);
BLI_assert(rdata->ob_curve_cache != NULL);
- if (cache->wire.verts == NULL) {
- static GPUVertFormat format = { 0 };
- static struct { uint pos; } attr_id;
- if (format.attr_len == 0) {
- /* initialize vertex format */
- attr_id.pos = GPU_vertformat_attr_add(&format, "pos", GPU_COMP_F32, 3, GPU_FETCH_FLOAT);
- }
+ static GPUVertFormat format = { 0 };
+ static struct { uint pos; } attr_id;
+ if (format.attr_len == 0) {
+ attr_id.pos = GPU_vertformat_attr_add(&format, "pos", GPU_COMP_F32, 3, GPU_FETCH_FLOAT);
+ }
- const int vert_len = curve_render_data_wire_verts_len_get(rdata);
+ const int vert_len = curve_render_data_wire_verts_len_get(rdata);
+ GPU_vertbuf_init_with_format(vbo_curves_pos, &format);
+ GPU_vertbuf_data_alloc(vbo_curves_pos, vert_len);
- GPUVertBuf *vbo = cache->wire.verts = GPU_vertbuf_create_with_format(&format);
- GPU_vertbuf_data_alloc(vbo, vert_len);
- int vbo_len_used = 0;
- for (const BevList *bl = rdata->ob_curve_cache->bev.first; bl; bl = bl->next) {
- if (bl->nr > 0) {
- const int i_end = vbo_len_used + bl->nr;
- for (const BevPoint *bevp = bl->bevpoints; vbo_len_used < i_end; vbo_len_used++, bevp++) {
- GPU_vertbuf_attr_set(vbo, attr_id.pos, vbo_len_used, bevp->vec);
- }
+ int v_idx = 0;
+ for (const BevList *bl = rdata->ob_curve_cache->bev.first; bl; bl = bl->next) {
+ if (bl->nr <= 0) {
+ continue;
+ }
+ const int i_end = v_idx + bl->nr;
+ for (const BevPoint *bevp = bl->bevpoints; v_idx < i_end; v_idx++, bevp++) {
+ GPU_vertbuf_attr_set(vbo_curves_pos, attr_id.pos, v_idx, bevp->vec);
+ }
+ }
+ for (const DispList *dl = rdata->ob_curve_cache->disp.first; dl; dl = dl->next) {
+ if (ELEM(dl->type, DL_SEGM, DL_POLY)) {
+ for (int i = 0; i < dl->nr; v_idx++, i++) {
+ GPU_vertbuf_attr_set(vbo_curves_pos, attr_id.pos, v_idx, &((float(*)[3])dl->verts)[i]);
}
}
- BLI_assert(vbo_len_used == vert_len);
}
-
- return cache->wire.verts;
+ BLI_assert(v_idx == vert_len);
}
-static GPUIndexBuf *curve_batch_cache_get_wire_edges(CurveRenderData *rdata, CurveBatchCache *cache)
+static void curve_create_curves_lines(CurveRenderData *rdata, GPUIndexBuf *ibo_curve_lines)
{
- BLI_assert(rdata->types & CU_DATATYPE_WIRE);
BLI_assert(rdata->ob_curve_cache != NULL);
- if (cache->wire.edges == NULL) {
- const int vert_len = curve_render_data_wire_verts_len_get(rdata);
- const int edge_len = curve_render_data_wire_edges_len_get(rdata);
- int edge_len_used = 0;
-
- GPUIndexBufBuilder elb;
- GPU_indexbuf_init(&elb, GPU_PRIM_LINES, edge_len, vert_len);
-
- int i = 0;
- for (const BevList *bl = rdata->ob_curve_cache->bev.first; bl; bl = bl->next) {
- if (bl->nr > 0) {
- const bool is_cyclic = bl->poly != -1;
- const int i_end = i + (bl->nr);
- int i_prev;
- if (is_cyclic) {
- i_prev = i + (bl->nr - 1);
- }
- else {
- i_prev = i;
- i += 1;
- }
- for (; i < i_end; i_prev = i++) {
- GPU_indexbuf_add_line_verts(&elb, i_prev, i);
- edge_len_used += 1;
- }
+ const int vert_len = curve_render_data_wire_verts_len_get(rdata);
+ const int edge_len = curve_render_data_wire_edges_len_get(rdata);
+ const int curve_len = curve_render_data_wire_curve_len_get(rdata);
+ /* Count the last vertex or each strip and the primitive restart. */
+ const int index_len = edge_len + curve_len * 2;
+
+ GPUIndexBufBuilder elb;
+ GPU_indexbuf_init_ex(&elb, GPU_PRIM_LINE_STRIP, index_len, vert_len, true);
+
+ int v_idx = 0;
+ for (const BevList *bl = rdata->ob_curve_cache->bev.first; bl; bl = bl->next) {
+ if (bl->nr <= 0) {
+ continue;
+ }
+ const bool is_cyclic = bl->poly != -1;
+ if (is_cyclic) {
+ GPU_indexbuf_add_generic_vert(&elb, v_idx + (bl->nr - 1));
+ }
+ for (int i = 0; i < bl->nr; i++) {
+ GPU_indexbuf_add_generic_vert(&elb, v_idx + i);
+ }
+ GPU_indexbuf_add_primitive_restart(&elb);
+ v_idx += bl->nr;
+ }
+ for (const DispList *dl = rdata->ob_curve_cache->disp.first; dl; dl = dl->next) {
+ if (ELEM(dl->type, DL_SEGM, DL_POLY)) {
+ const bool is_cyclic = dl->type == DL_POLY;
+ if (is_cyclic) {
+ GPU_indexbuf_add_generic_vert(&elb, v_idx + (dl->nr - 1));
+ }
+ for (int i = 0; i < dl->nr; i++) {
+ GPU_indexbuf_add_generic_vert(&elb, v_idx + i);
}
+ GPU_indexbuf_add_primitive_restart(&elb);
+ v_idx += dl->nr;
}
- cache->wire.elem = GPU_indexbuf_build(&elb);
}
-
- return cache->wire.elem;
+ GPU_indexbuf_build_in_place(&elb, ibo_curve_lines);
}
-static GPUVertBuf *curve_batch_cache_get_normal_verts(CurveRenderData *rdata, CurveBatchCache *cache)
+static void curve_create_edit_curves_nor(CurveRenderData *rdata, GPUVertBuf *vbo_curves_nor)
{
- BLI_assert(rdata->types & CU_DATATYPE_NORMAL);
- BLI_assert(rdata->ob_curve_cache != NULL);
-
- if (cache->normal.verts == NULL) {
- static GPUVertFormat format = { 0 };
- static struct { uint pos; } attr_id;
- if (format.attr_len == 0) {
- /* initialize vertex format */
- attr_id.pos = GPU_vertformat_attr_add(&format, "pos", GPU_COMP_F32, 3, GPU_FETCH_FLOAT);
- }
-
- const int normal_len = curve_render_data_normal_len_get(rdata);
- const int vert_len = normal_len * 3;
-
- GPUVertBuf *vbo = cache->normal.verts = GPU_vertbuf_create_with_format(&format);
- GPU_vertbuf_data_alloc(vbo, vert_len);
- int vbo_len_used = 0;
+ static GPUVertFormat format = { 0 };
+ static struct { uint pos, nor, tan, rad; } attr_id;
+ if (format.attr_len == 0) {
+ /* initialize vertex formats */
+ attr_id.pos = GPU_vertformat_attr_add(&format, "pos", GPU_COMP_F32, 3, GPU_FETCH_FLOAT);
+ attr_id.rad = GPU_vertformat_attr_add(&format, "rad", GPU_COMP_F32, 1, GPU_FETCH_FLOAT);
+ attr_id.nor = GPU_vertformat_attr_add(&format, "nor", GPU_COMP_I10, 3, GPU_FETCH_INT_TO_FLOAT_UNIT);
+ attr_id.tan = GPU_vertformat_attr_add(&format, "tan", GPU_COMP_I10, 3, GPU_FETCH_INT_TO_FLOAT_UNIT);
+ }
- const BevList *bl;
- const Nurb *nu;
+ int verts_len_capacity = curve_render_data_normal_len_get(rdata) * 2;
+ int vbo_len_used = 0;
- for (bl = rdata->ob_curve_cache->bev.first, nu = rdata->nurbs->first;
- nu && bl;
- bl = bl->next, nu = nu->next)
- {
- const BevPoint *bevp = bl->bevpoints;
- int nr = bl->nr;
- int skip = nu->resolu / 16;
+ GPU_vertbuf_init_with_format(vbo_curves_nor, &format);
+ GPU_vertbuf_data_alloc(vbo_curves_nor, verts_len_capacity);
- while (nr-- > 0) { /* accounts for empty bevel lists */
- const float fac = bevp->radius * cache->normal_size;
- float vec_a[3]; /* Offset perpendicular to the curve */
- float vec_b[3]; /* Delta along the curve */
+ const BevList *bl;
+ const Nurb *nu;
- vec_a[0] = fac;
- vec_a[1] = 0.0f;
- vec_a[2] = 0.0f;
+ for (bl = rdata->ob_curve_cache->bev.first, nu = rdata->nurbs->first;
+ nu && bl;
+ bl = bl->next, nu = nu->next)
+ {
+ const BevPoint *bevp = bl->bevpoints;
+ int nr = bl->nr;
+ int skip = nu->resolu / 16;
- mul_qt_v3(bevp->quat, vec_a);
- madd_v3_v3fl(vec_a, bevp->dir, -fac);
+ while (nr-- > 0) { /* accounts for empty bevel lists */
+ float nor[3] = {1.0f, 0.0f, 0.0f};
+ mul_qt_v3(bevp->quat, nor);
- reflect_v3_v3v3(vec_b, vec_a, bevp->dir);
- negate_v3(vec_b);
+ GPUPackedNormal pnor = GPU_normal_convert_i10_v3(nor);
+ GPUPackedNormal ptan = GPU_normal_convert_i10_v3(bevp->dir);
- add_v3_v3(vec_a, bevp->vec);
- add_v3_v3(vec_b, bevp->vec);
+ /* Only set attribs for one vertex. */
+ GPU_vertbuf_attr_set(vbo_curves_nor, attr_id.pos, vbo_len_used, bevp->vec);
+ GPU_vertbuf_attr_set(vbo_curves_nor, attr_id.rad, vbo_len_used, &bevp->radius);
+ GPU_vertbuf_attr_set(vbo_curves_nor, attr_id.nor, vbo_len_used, &pnor);
+ GPU_vertbuf_attr_set(vbo_curves_nor, attr_id.tan, vbo_len_used, &ptan);
+ vbo_len_used++;
- GPU_vertbuf_attr_set(vbo, attr_id.pos, vbo_len_used++, vec_a);
- GPU_vertbuf_attr_set(vbo, attr_id.pos, vbo_len_used++, bevp->vec);
- GPU_vertbuf_attr_set(vbo, attr_id.pos, vbo_len_used++, vec_b);
+ /* Skip the other vertex (it does not need to be offseted). */
+ GPU_vertbuf_attr_set(vbo_curves_nor, attr_id.pos, vbo_len_used, bevp->vec);
+ vbo_len_used++;
- bevp += skip + 1;
- nr -= skip;
- }
+ bevp += skip + 1;
+ nr -= skip;
}
- BLI_assert(vbo_len_used == vert_len);
}
-
- return cache->normal.verts;
+ BLI_assert(vbo_len_used == verts_len_capacity);
}
-static GPUIndexBuf *curve_batch_cache_get_normal_edges(CurveRenderData *rdata, CurveBatchCache *cache)
+static char beztriple_vflag_get(CurveRenderData *rdata, char flag, char col_id, int v_idx, int nu_id)
{
- BLI_assert(rdata->types & CU_DATATYPE_NORMAL);
- BLI_assert(rdata->ob_curve_cache != NULL);
-
- if (cache->normal.edges == NULL) {
- const int normal_len = curve_render_data_normal_len_get(rdata);
- const int vert_len = normal_len * 3;
- const int edge_len = normal_len * 2;
-
- GPUIndexBufBuilder elb;
- GPU_indexbuf_init(&elb, GPU_PRIM_LINES, edge_len, vert_len);
-
- int vbo_len_used = 0;
- for (int i = 0; i < normal_len; i++) {
- GPU_indexbuf_add_line_verts(&elb, vbo_len_used + 0, vbo_len_used + 1);
- GPU_indexbuf_add_line_verts(&elb, vbo_len_used + 1, vbo_len_used + 2);
- vbo_len_used += 3;
- }
+ char vflag = 0;
+ SET_FLAG_FROM_TEST(vflag, (flag & SELECT), VFLAG_VERTEX_SELECTED);
+ SET_FLAG_FROM_TEST(vflag, (v_idx == rdata->actvert), VFLAG_VERTEX_ACTIVE);
+ SET_FLAG_FROM_TEST(vflag, (nu_id == rdata->actnu), ACTIVE_NURB);
+ /* handle color id */
+ vflag |= col_id << 4; /* << 4 because of EVEN_U_BIT */
+ return vflag;
+}
- BLI_assert(vbo_len_used == vert_len);
+static char bpoint_vflag_get(CurveRenderData *rdata, char flag, int v_idx, int nu_id, int u)
+{
+ char vflag = 0;
+ SET_FLAG_FROM_TEST(vflag, (flag & SELECT), VFLAG_VERTEX_SELECTED);
+ SET_FLAG_FROM_TEST(vflag, (v_idx == rdata->actvert), VFLAG_VERTEX_ACTIVE);
+ SET_FLAG_FROM_TEST(vflag, (nu_id == rdata->actnu), ACTIVE_NURB);
+ SET_FLAG_FROM_TEST(vflag, ((u % 2) == 0), EVEN_U_BIT);
+ vflag |= COLOR_NURB_ULINE_ID << 4; /* << 4 because of EVEN_U_BIT */
+ return vflag;
+}
- cache->normal.elem = GPU_indexbuf_build(&elb);
+static void curve_create_edit_data_and_handles(
+ CurveRenderData *rdata,
+ GPUVertBuf *vbo_pos, GPUVertBuf *vbo_data, GPUIndexBuf *ibo_edit_verts_points, GPUIndexBuf *ibo_edit_lines)
+{
+ static GPUVertFormat format_pos = { 0 };
+ static GPUVertFormat format_data = { 0 };
+ static struct { uint pos, data; } attr_id;
+ if (format_pos.attr_len == 0) {
+ /* initialize vertex formats */
+ attr_id.pos = GPU_vertformat_attr_add(&format_pos, "pos", GPU_COMP_F32, 3, GPU_FETCH_FLOAT);
+ attr_id.data = GPU_vertformat_attr_add(&format_data, "data", GPU_COMP_U8, 1, GPU_FETCH_INT);
}
- return cache->normal.elem;
-}
+ int verts_len_capacity = curve_render_data_overlay_verts_len_get(rdata);
+ int edges_len_capacity = curve_render_data_overlay_edges_len_get(rdata) * 2;
+ int vbo_len_used = 0;
-static void curve_batch_cache_create_overlay_batches(Curve *cu)
-{
- /* Since CU_DATATYPE_OVERLAY is slow to generate, generate them all at once */
- int options = CU_DATATYPE_OVERLAY;
+ if (DRW_TEST_ASSIGN_VBO(vbo_pos)) {
+ GPU_vertbuf_init_with_format(vbo_pos, &format_pos);
+ GPU_vertbuf_data_alloc(vbo_pos, verts_len_capacity);
+ }
+ if (DRW_TEST_ASSIGN_VBO(vbo_data)) {
+ GPU_vertbuf_init_with_format(vbo_data, &format_data);
+ GPU_vertbuf_data_alloc(vbo_data, verts_len_capacity);
+ }
- CurveBatchCache *cache = curve_batch_cache_get(cu);
- CurveRenderData *rdata = curve_render_data_create(cu, NULL, options);
-
- if (cache->overlay.verts == NULL) {
- static GPUVertFormat format = { 0 };
- static struct { uint pos, data; } attr_id;
- if (format.attr_len == 0) {
- /* initialize vertex format */
- attr_id.pos = GPU_vertformat_attr_add(&format, "pos", GPU_COMP_F32, 3, GPU_FETCH_FLOAT);
- attr_id.data = GPU_vertformat_attr_add(&format, "data", GPU_COMP_U8, 1, GPU_FETCH_INT);
- }
+ GPUIndexBufBuilder elb_verts, *elbp_verts = NULL;
+ GPUIndexBufBuilder elb_lines, *elbp_lines = NULL;
+ if (DRW_TEST_ASSIGN_IBO(ibo_edit_verts_points)) {
+ elbp_verts = &elb_verts;
+ GPU_indexbuf_init(elbp_verts, GPU_PRIM_POINTS, verts_len_capacity, verts_len_capacity);
+ }
+ if (DRW_TEST_ASSIGN_IBO(ibo_edit_lines)) {
+ elbp_lines = &elb_lines;
+ GPU_indexbuf_init(elbp_lines, GPU_PRIM_LINES, edges_len_capacity, verts_len_capacity);
+ }
- GPUVertBuf *vbo = GPU_vertbuf_create_with_format(&format);
- const int vbo_len_capacity = curve_render_data_overlay_verts_len_get(rdata);
- GPUIndexBufBuilder elb;
- GPU_indexbuf_init(&elb, GPU_PRIM_POINTS, vbo_len_capacity, vbo_len_capacity);
- int vbo_len_used = 0;
- GPU_vertbuf_data_alloc(vbo, vbo_len_capacity);
- int i = 0, nu_id = 0;
- for (Nurb *nu = rdata->nurbs->first; nu; nu = nu->next, nu_id++) {
- const bool is_active_nurb = (nu_id == cu->actnu);
- if (nu->bezt) {
- int a = 0;
- for (const BezTriple *bezt = nu->bezt; a < nu->pntsu; a++, bezt++) {
- if (bezt->hide == false) {
- const bool is_active = (i == rdata->actvert);
- GPU_indexbuf_add_point_vert(&elb, vbo_len_used + 1);
- for (int j = 0; j < 3; j++) {
- char vflag = ((&bezt->f1)[j] & SELECT) ? VFLAG_VERTEX_SELECTED : 0;
- vflag |= (is_active) ? VFLAG_VERTEX_ACTIVE : 0;
- vflag |= (is_active_nurb) ? ACTIVE_NURB : 0;
- /* handle color id */
- char col_id = (&bezt->h1)[j / 2];
- vflag |= col_id << 4; /* << 4 because of EVEN_U_BIT */
- GPU_vertbuf_attr_set(vbo, attr_id.pos, vbo_len_used, bezt->vec[j]);
- GPU_vertbuf_attr_set(vbo, attr_id.data, vbo_len_used, &vflag);
- vbo_len_used += 1;
- }
- }
- i += 1;
+ int v_idx = 0, nu_id = 0;
+ for (Nurb *nu = rdata->nurbs->first; nu; nu = nu->next, nu_id++) {
+ const BezTriple *bezt = nu->bezt;
+ const BPoint *bp = nu->bp;
+ if (bezt && bezt->hide == false) {
+ for (int a = 0; a < nu->pntsu; a++, bezt++) {
+ if (elbp_verts) {
+ GPU_indexbuf_add_point_vert(elbp_verts, vbo_len_used + 1);
}
- }
- else if (nu->bp) {
- int a = 0;
- int pt_len = nu->pntsu * nu->pntsv;
- for (const BPoint *bp = nu->bp; a < pt_len; a++, bp++) {
- if (bp->hide == false) {
- const bool is_active = (i == rdata->actvert);
- char vflag = (bp->f1 & SELECT) ? VFLAG_VERTEX_SELECTED : 0;
- vflag |= (is_active) ? VFLAG_VERTEX_ACTIVE : 0;
- vflag |= (is_active_nurb) ? ACTIVE_NURB : 0;
- vflag |= (((a % nu->pntsu) % 2) == 0) ? EVEN_U_BIT : 0;
- vflag |= COLOR_NURB_ULINE_ID << 4; /* << 4 because of EVEN_U_BIT */
- GPU_indexbuf_add_point_vert(&elb, vbo_len_used);
- GPU_vertbuf_attr_set(vbo, attr_id.pos, vbo_len_used, bp->vec);
- GPU_vertbuf_attr_set(vbo, attr_id.data, vbo_len_used, &vflag);
- vbo_len_used += 1;
+ if (elbp_lines) {
+ GPU_indexbuf_add_line_verts(elbp_lines, vbo_len_used + 1, vbo_len_used + 0);
+ GPU_indexbuf_add_line_verts(elbp_lines, vbo_len_used + 1, vbo_len_used + 2);
+ }
+ if (vbo_data) {
+ char vflag[3] = {
+ beztriple_vflag_get(rdata, bezt->f1, bezt->h1, v_idx, nu_id),
+ beztriple_vflag_get(rdata, bezt->f2, bezt->h1, v_idx, nu_id),
+ beztriple_vflag_get(rdata, bezt->f3, bezt->h2, v_idx, nu_id)
+ };
+ for (int j = 0; j < 3; j++) {
+ GPU_vertbuf_attr_set(vbo_data, attr_id.data, vbo_len_used + j, &vflag[j]);
}
- i += 1;
}
- }
- i += nu->pntsu;
- }
- if (vbo_len_capacity != vbo_len_used) {
- GPU_vertbuf_data_resize(vbo, vbo_len_used);
- }
-
- GPUIndexBuf *ibo = GPU_indexbuf_build(&elb);
-
- cache->overlay.verts = GPU_batch_create_ex(GPU_PRIM_POINTS, vbo, NULL, GPU_BATCH_OWNS_VBO);
- cache->overlay.verts_no_handles = GPU_batch_create_ex(GPU_PRIM_POINTS, vbo, ibo, GPU_BATCH_OWNS_INDEX);
- }
-
- if (cache->overlay.edges == NULL) {
- GPUVertBuf *vbo = cache->overlay.verts->verts[0];
-
- const int edge_len = curve_render_data_overlay_edges_len_get(rdata);
- const int vbo_len_capacity = edge_len * 2;
-
- GPUIndexBufBuilder elb;
- GPU_indexbuf_init(&elb, GPU_PRIM_LINES, vbo_len_capacity, vbo->vertex_len);
-
- int curr_index = 0;
- int i = 0;
- for (Nurb *nu = rdata->nurbs->first; nu; nu = nu->next, i++) {
- if (nu->bezt) {
- int a = 0;
- for (const BezTriple *bezt = nu->bezt; a < nu->pntsu; a++, bezt++) {
- if (bezt->hide == false) {
- GPU_indexbuf_add_line_verts(&elb, curr_index + 1, curr_index + 0);
- GPU_indexbuf_add_line_verts(&elb, curr_index + 1, curr_index + 2);
- curr_index += 3;
+ if (vbo_pos) {
+ for (int j = 0; j < 3; j++) {
+ GPU_vertbuf_attr_set(vbo_pos, attr_id.pos, vbo_len_used + j, bezt->vec[j]);
}
}
+ vbo_len_used += 3;
+ v_idx += 1;
}
- else if (nu->bp) {
- int a = 0;
- int next_v_index = curr_index;
- for (const BPoint *bp = nu->bp; a < nu->pntsu; a++, bp++) {
- if (bp->hide == false) {
- next_v_index += 1;
- }
+ }
+ else if (bp) {
+ int pt_len = nu->pntsu * nu->pntsv;
+ for (int a = 0; a < pt_len; a++, bp++) {
+ int u = (a % nu->pntsu);
+ int v = (a / nu->pntsu);
+ /* Use indexed rendering for bezier.
+ * Specify all points and use indices to hide/show. */
+ if (elbp_verts && bp->hide == false) {
+ GPU_indexbuf_add_point_vert(elbp_verts, vbo_len_used);
}
-
- int pt_len = nu->pntsu * nu->pntsv;
- for (a = 0; a < pt_len; a++) {
- const BPoint *bp_curr = &nu->bp[a];
- const BPoint *bp_next_u = ((a % nu->pntsu) < (nu->pntsu - 1)) ? &nu->bp[a + 1] : NULL;
- const BPoint *bp_next_v = (a < (pt_len - nu->pntsu)) ? &nu->bp[a + nu->pntsu] : NULL;
- if (bp_curr->hide == false) {
- if (bp_next_u && (bp_next_u->hide == false)) {
- GPU_indexbuf_add_line_verts(&elb, curr_index, curr_index + 1);
- }
- if (bp_next_v && (bp_next_v->hide == false)) {
- GPU_indexbuf_add_line_verts(&elb, curr_index, next_v_index);
- }
- curr_index += 1;
+ if (elbp_lines && bp->hide == false) {
+ const BPoint *bp_next_u = (u < (nu->pntsu - 1)) ? &nu->bp[a + 1] : NULL;
+ const BPoint *bp_next_v = (v < (nu->pntsv - 1)) ? &nu->bp[a + nu->pntsu] : NULL;
+ if (bp_next_u && (bp_next_u->hide == false)) {
+ GPU_indexbuf_add_line_verts(elbp_lines, vbo_len_used, vbo_len_used + 1);
}
if (bp_next_v && (bp_next_v->hide == false)) {
- next_v_index += 1;
+ GPU_indexbuf_add_line_verts(elbp_lines, vbo_len_used, vbo_len_used + nu->pntsu);
}
}
+ if (vbo_data) {
+ char vflag = bpoint_vflag_get(rdata, bp->f1, v_idx, nu_id, u);
+ GPU_vertbuf_attr_set(vbo_data, attr_id.data, vbo_len_used, &vflag);
+ }
+ if (vbo_pos) {
+ GPU_vertbuf_attr_set(vbo_pos, attr_id.pos, vbo_len_used, bp->vec);
+ }
+ vbo_len_used += 1;
+ v_idx += 1;
}
}
-
- GPUIndexBuf *ibo = GPU_indexbuf_build(&elb);
- cache->overlay.edges = GPU_batch_create_ex(GPU_PRIM_LINES, vbo, ibo, GPU_BATCH_OWNS_INDEX);
- }
-
- curve_render_data_free(rdata);
-}
-
-static GPUBatch *curve_batch_cache_get_pos_and_normals(CurveRenderData *rdata, CurveBatchCache *cache)
-{
- BLI_assert(rdata->types & CU_DATATYPE_SURFACE);
- if (cache->surface.batch == NULL) {
- ListBase *lb = &rdata->ob_curve_cache->disp;
-
- if (cache->surface.verts == NULL) {
- cache->surface.verts = DRW_displist_vertbuf_calc_pos_with_normals(lb);
- }
- if (cache->surface.triangles_in_order == NULL) {
- cache->surface.triangles_in_order = DRW_displist_indexbuf_calc_triangles_in_order(lb);
- }
- cache->surface.batch = GPU_batch_create(
- GPU_PRIM_TRIS, cache->surface.verts, cache->surface.triangles_in_order);
}
- return cache->surface.batch;
-}
-
-static GPUTexture *curve_batch_cache_get_edges_overlay_texture_buf(CurveRenderData *rdata, CurveBatchCache *cache)
-{
- BLI_assert(rdata->types & CU_DATATYPE_SURFACE);
-
- if (cache->face_wire.elem_tx != NULL) {
- return cache->face_wire.elem_tx;
+ /* Resize & Finish */
+ if (elbp_verts != NULL) {
+ GPU_indexbuf_build_in_place(elbp_verts, ibo_edit_verts_points);
}
-
- ListBase *lb = &rdata->ob_curve_cache->disp;
-
- /* We need a special index buffer. */
- GPUVertBuf *vbo = cache->face_wire.elem_vbo = DRW_displist_create_edges_overlay_texture_buf(lb);
-
- /* Upload data early because we need to create the texture for it. */
- GPU_vertbuf_use(vbo);
- cache->face_wire.elem_tx = GPU_texture_create_from_vertbuf(vbo);
- cache->face_wire.tri_count = vbo->vertex_alloc / 3;
-
- return cache->face_wire.elem_tx;
-}
-
-static GPUTexture *curve_batch_cache_get_vert_pos_and_nor_in_order_buf(CurveRenderData *rdata, CurveBatchCache *cache)
-{
- BLI_assert(rdata->types & CU_DATATYPE_SURFACE);
-
- if (cache->face_wire.verts_tx == NULL) {
- curve_batch_cache_get_pos_and_normals(rdata, cache);
- GPU_vertbuf_use(cache->surface.verts); /* Upload early for buffer texture creation. */
- cache->face_wire.verts_tx = GPU_texture_create_buffer(GPU_R32F, cache->surface.verts->vbo_id);
- }
-
- return cache->face_wire.verts_tx;
-}
-
-/** \} */
-
-
-/* -------------------------------------------------------------------- */
-
-/** \name Private Object/Font Cache API
- * \{ */
-
-
-static GPUBatch *curve_batch_cache_get_overlay_select(CurveRenderData *rdata, CurveBatchCache *cache)
-{
- BLI_assert(rdata->types & CU_DATATYPE_TEXT_SELECT);
- if (cache->text.select == NULL) {
- EditFont *ef = rdata->text.edit_font;
- static GPUVertFormat format = { 0 };
- static struct { uint pos; } attr_id;
- if (format.attr_len == 0) {
- attr_id.pos = GPU_vertformat_attr_add(&format, "pos", GPU_COMP_F32, 3, GPU_FETCH_FLOAT);
- }
-
- GPUVertBuf *vbo = GPU_vertbuf_create_with_format(&format);
- const int vbo_len_capacity = ef->selboxes_len * 6;
- int vbo_len_used = 0;
- GPU_vertbuf_data_alloc(vbo, vbo_len_capacity);
-
- float box[4][3];
-
- /* fill in xy below */
- box[0][2] = box[1][2] = box[2][2] = box[3][2] = 0.001;
-
- for (int i = 0; i < ef->selboxes_len; i++) {
- EditFontSelBox *sb = &ef->selboxes[i];
-
- float selboxw;
- if (i + 1 != ef->selboxes_len) {
- if (ef->selboxes[i + 1].y == sb->y)
- selboxw = ef->selboxes[i + 1].x - sb->x;
- else
- selboxw = sb->w;
- }
- else {
- selboxw = sb->w;
- }
-
- if (sb->rot == 0.0f) {
- copy_v2_fl2(box[0], sb->x, sb->y);
- copy_v2_fl2(box[1], sb->x + selboxw, sb->y);
- copy_v2_fl2(box[2], sb->x + selboxw, sb->y + sb->h);
- copy_v2_fl2(box[3], sb->x, sb->y + sb->h);
- }
- else {
- float mat[2][2];
-
- angle_to_mat2(mat, sb->rot);
-
- copy_v2_fl2(box[0], sb->x, sb->y);
-
- copy_v2_fl2(box[1], selboxw, 0.0f);
- mul_m2v2(mat, box[1]);
- add_v2_v2(box[1], &sb->x);
-
- copy_v2_fl2(box[2], selboxw, sb->h);
- mul_m2v2(mat, box[2]);
- add_v2_v2(box[2], &sb->x);
-
- copy_v2_fl2(box[3], 0.0f, sb->h);
- mul_m2v2(mat, box[3]);
- add_v2_v2(box[3], &sb->x);
- }
-
- GPU_vertbuf_attr_set(vbo, attr_id.pos, vbo_len_used++, box[0]);
- GPU_vertbuf_attr_set(vbo, attr_id.pos, vbo_len_used++, box[1]);
- GPU_vertbuf_attr_set(vbo, attr_id.pos, vbo_len_used++, box[2]);
-
- GPU_vertbuf_attr_set(vbo, attr_id.pos, vbo_len_used++, box[0]);
- GPU_vertbuf_attr_set(vbo, attr_id.pos, vbo_len_used++, box[2]);
- GPU_vertbuf_attr_set(vbo, attr_id.pos, vbo_len_used++, box[3]);
- }
- BLI_assert(vbo_len_used == vbo_len_capacity);
- cache->text.select = GPU_batch_create_ex(GPU_PRIM_TRIS, vbo, NULL, GPU_BATCH_OWNS_VBO);
+ if (elbp_lines != NULL) {
+ GPU_indexbuf_build_in_place(elbp_lines, ibo_edit_lines);
}
- return cache->text.select;
-}
-
-static GPUBatch *curve_batch_cache_get_overlay_cursor(CurveRenderData *rdata, CurveBatchCache *cache)
-{
- BLI_assert(rdata->types & CU_DATATYPE_TEXT_SELECT);
- if (cache->text.cursor == NULL) {
- static GPUVertFormat format = { 0 };
- static struct { uint pos; } attr_id;
- if (format.attr_len == 0) {
- attr_id.pos = GPU_vertformat_attr_add(&format, "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
+ if (vbo_len_used != verts_len_capacity) {
+ if (vbo_pos != NULL) {
+ GPU_vertbuf_data_resize(vbo_pos, vbo_len_used);
}
-
- GPUVertBuf *vbo = GPU_vertbuf_create_with_format(&format);
- const int vbo_len_capacity = 4;
- GPU_vertbuf_data_alloc(vbo, vbo_len_capacity);
- for (int i = 0; i < 4; i++) {
- GPU_vertbuf_attr_set(vbo, attr_id.pos, i, rdata->text.edit_font->textcurs[i]);
+ if (vbo_data != NULL) {
+ GPU_vertbuf_data_resize(vbo_data, vbo_len_used);
}
- cache->text.cursor = GPU_batch_create_ex(GPU_PRIM_TRI_FAN, vbo, NULL, GPU_BATCH_OWNS_VBO);
}
- return cache->text.cursor;
}
/** \} */
@@ -947,186 +829,209 @@ static GPUBatch *curve_batch_cache_get_overlay_cursor(CurveRenderData *rdata, Cu
/** \name Public Object/Curve API
* \{ */
-GPUBatch *DRW_curve_batch_cache_get_wire_edge(Curve *cu, CurveCache *ob_curve_cache)
+GPUBatch *DRW_curve_batch_cache_get_wire_edge(Curve *cu)
{
CurveBatchCache *cache = curve_batch_cache_get(cu);
-
- if (cache->wire.batch == NULL) {
- /* create batch from Curve */
- CurveRenderData *rdata = curve_render_data_create(cu, ob_curve_cache, CU_DATATYPE_WIRE);
-
- cache->wire.batch = GPU_batch_create(
- GPU_PRIM_LINES,
- curve_batch_cache_get_wire_verts(rdata, cache),
- curve_batch_cache_get_wire_edges(rdata, cache));
-
- curve_render_data_free(rdata);
- }
- return cache->wire.batch;
+ return DRW_batch_request(&cache->batch.curves);
}
-GPUBatch *DRW_curve_batch_cache_get_normal_edge(Curve *cu, CurveCache *ob_curve_cache, float normal_size)
+GPUBatch *DRW_curve_batch_cache_get_normal_edge(Curve *cu)
{
CurveBatchCache *cache = curve_batch_cache_get(cu);
-
- if (cache->normal.batch != NULL) {
- cache->normal_size = normal_size;
- if (cache->normal_size != normal_size) {
- GPU_BATCH_DISCARD_SAFE(cache->normal.batch);
- GPU_VERTBUF_DISCARD_SAFE(cache->normal.edges);
- }
- }
- cache->normal_size = normal_size;
-
- if (cache->normal.batch == NULL) {
- /* create batch from Curve */
- CurveRenderData *rdata = curve_render_data_create(cu, ob_curve_cache, CU_DATATYPE_NORMAL);
-
- cache->normal.batch = GPU_batch_create(
- GPU_PRIM_LINES,
- curve_batch_cache_get_normal_verts(rdata, cache),
- curve_batch_cache_get_normal_edges(rdata, cache));
-
- curve_render_data_free(rdata);
- cache->normal_size = normal_size;
- }
- return cache->normal.batch;
+ return DRW_batch_request(&cache->batch.edit_normals);
}
-GPUBatch *DRW_curve_batch_cache_get_overlay_edges(Curve *cu)
+GPUBatch *DRW_curve_batch_cache_get_edit_edges(Curve *cu)
{
CurveBatchCache *cache = curve_batch_cache_get(cu);
-
- if (cache->overlay.edges == NULL) {
- curve_batch_cache_create_overlay_batches(cu);
- }
-
- return cache->overlay.edges;
+ return DRW_batch_request(&cache->batch.edit_edges);
}
-GPUBatch *DRW_curve_batch_cache_get_overlay_verts(Curve *cu, bool handles)
+GPUBatch *DRW_curve_batch_cache_get_edit_verts(Curve *cu, bool handles)
{
CurveBatchCache *cache = curve_batch_cache_get(cu);
-
- if (cache->overlay.verts == NULL || cache->overlay.verts_no_handles == NULL) {
- curve_batch_cache_create_overlay_batches(cu);
+ if (handles) {
+ return DRW_batch_request(&cache->batch.edit_handles_verts);
+ }
+ else {
+ return DRW_batch_request(&cache->batch.edit_verts);
}
-
- return (handles) ? cache->overlay.verts : cache->overlay.verts_no_handles;
}
-GPUBatch *DRW_curve_batch_cache_get_triangles_with_normals(
- struct Curve *cu, struct CurveCache *ob_curve_cache)
+GPUBatch *DRW_curve_batch_cache_get_triangles_with_normals(struct Curve *cu)
{
CurveBatchCache *cache = curve_batch_cache_get(cu);
-
- if (cache->surface.batch == NULL) {
- CurveRenderData *rdata = curve_render_data_create(cu, ob_curve_cache, CU_DATATYPE_SURFACE);
-
- curve_batch_cache_get_pos_and_normals(rdata, cache);
-
- curve_render_data_free(rdata);
- }
-
- return cache->surface.batch;
+ return DRW_batch_request(&cache->batch.surfaces);
}
GPUBatch **DRW_curve_batch_cache_get_surface_shaded(
- struct Curve *cu, struct CurveCache *ob_curve_cache,
- struct GPUMaterial **UNUSED(gpumat_array), uint gpumat_array_len)
+ struct Curve *cu,
+ struct GPUMaterial **gpumat_array, uint gpumat_array_len)
{
CurveBatchCache *cache = curve_batch_cache_get(cu);
- if (cache->surface.mat_len != gpumat_array_len) {
- GPU_BATCH_DISCARD_ARRAY_SAFE(cache->surface.shaded_triangles, cache->surface.mat_len);
- }
+ BLI_assert(gpumat_array_len == cache->mat_len);
- if (cache->surface.shaded_triangles == NULL) {
- CurveRenderData *rdata = curve_render_data_create(cu, ob_curve_cache, CU_DATATYPE_SURFACE);
- ListBase *lb = &rdata->ob_curve_cache->disp;
+ curve_cd_calc_used_gpu_layers(&cache->cd_needed, gpumat_array, gpumat_array_len);
- cache->surface.mat_len = gpumat_array_len;
- if (cu->flag & CU_UV_ORCO) {
- cache->surface.shaded_triangles = DRW_displist_batch_calc_tri_pos_normals_and_uv_split_by_material(
- lb, gpumat_array_len);
- }
- else {
- cache->surface.shaded_triangles = MEM_mallocN(
- sizeof(*cache->surface.shaded_triangles) * gpumat_array_len, __func__);
- GPUIndexBuf **el = DRW_displist_indexbuf_calc_triangles_in_order_split_by_material(
- lb, gpumat_array_len);
-
- if (cache->surface.verts == NULL) {
- cache->surface.verts = DRW_displist_vertbuf_calc_pos_with_normals(lb);
- }
-
- for (int i = 0; i < gpumat_array_len; ++i) {
- cache->surface.shaded_triangles[i] = GPU_batch_create_ex(
- GPU_PRIM_TRIS, cache->surface.verts, el[i], GPU_BATCH_OWNS_INDEX);
- }
-
- MEM_freeN(el); /* Save `el` in cache? */
- }
-
- curve_render_data_free(rdata);
+ for (int i = 0; i < cache->mat_len; ++i) {
+ DRW_batch_request(&cache->surf_per_mat[i]);
}
-
- return cache->surface.shaded_triangles;
+ return cache->surf_per_mat;
}
-void DRW_curve_batch_cache_get_wireframes_face_texbuf(
- Curve *cu, CurveCache *ob_curve_cache,
- GPUTexture **verts_data, GPUTexture **face_indices, int *tri_count)
+GPUBatch *DRW_curve_batch_cache_get_wireframes_face(Curve *cu)
{
CurveBatchCache *cache = curve_batch_cache_get(cu);
+ return DRW_batch_request(&cache->batch.wire_triangles);
+}
- if (cache->face_wire.elem_tx == NULL || cache->face_wire.verts_tx == NULL) {
- CurveRenderData *rdata = curve_render_data_create(cu, ob_curve_cache, CU_DATATYPE_SURFACE);
+/** \} */
- curve_batch_cache_get_edges_overlay_texture_buf(rdata, cache);
- curve_batch_cache_get_vert_pos_and_nor_in_order_buf(rdata, cache);
+/* -------------------------------------------------------------------- */
+/** \name Grouped batch generation
+ * \{ */
- curve_render_data_free(rdata);
+void DRW_curve_batch_cache_create_requested(Object *ob)
+{
+ BLI_assert(ELEM(ob->type, OB_CURVE, OB_SURF, OB_FONT));
+
+ Curve *me = (Curve *)ob->data;
+ CurveBatchCache *cache = curve_batch_cache_get(me);
+
+ /* Verify that all surface batches have needed attrib layers. */
+ /* TODO(fclem): We could be a bit smarter here and only do it per material. */
+ for (int i = 0; i < cache->mat_len; ++i) {
+ if ((cache->cd_used & cache->cd_needed) != cache->cd_needed) {
+ /* We can't discard batches at this point as they have been
+ * referenced for drawing. Just clear them in place. */
+ GPU_batch_clear(cache->surf_per_mat[i]);
+ memset(cache->surf_per_mat[i], 0, sizeof(*cache->surf_per_mat[i]));
+ }
+ }
+ if ((cache->cd_used & cache->cd_needed) != cache->cd_needed) {
+ cache->cd_used |= cache->cd_needed;
+ cache->cd_needed = 0;
}
- *tri_count = cache->face_wire.tri_count;
- *face_indices = cache->face_wire.elem_tx;
- *verts_data = cache->face_wire.verts_tx;
-}
+ /* Init batches and request VBOs & IBOs */
+ if (DRW_batch_requested(cache->batch.surfaces, GPU_PRIM_TRIS)) {
+ DRW_ibo_request(cache->batch.surfaces, &cache->ibo.surfaces_tris);
+ DRW_vbo_request(cache->batch.surfaces, &cache->ordered.pos_nor);
+ }
+ if (DRW_batch_requested(cache->batch.curves, GPU_PRIM_LINE_STRIP)) {
+ DRW_ibo_request(cache->batch.curves, &cache->ibo.curves_lines);
+ DRW_vbo_request(cache->batch.curves, &cache->ordered.curves_pos);
+ }
+ if (DRW_batch_requested(cache->batch.wire_triangles, GPU_PRIM_TRIS)) {
+ DRW_vbo_request(cache->batch.wire_triangles, &cache->tess.pos_nor);
+ DRW_vbo_request(cache->batch.wire_triangles, &cache->tess.wireframe_data);
+ }
-/* -------------------------------------------------------------------- */
+ /* Edit mode */
+ if (DRW_batch_requested(cache->batch.edit_edges, GPU_PRIM_LINES)) {
+ DRW_ibo_request(cache->batch.edit_edges, &cache->ibo.edit_lines);
+ DRW_vbo_request(cache->batch.edit_edges, &cache->edit.pos);
+ DRW_vbo_request(cache->batch.edit_edges, &cache->edit.data);
+ }
+ if (DRW_batch_requested(cache->batch.edit_verts, GPU_PRIM_POINTS)) {
+ DRW_ibo_request(cache->batch.edit_verts, &cache->ibo.edit_verts_points);
+ DRW_vbo_request(cache->batch.edit_verts, &cache->edit.pos);
+ DRW_vbo_request(cache->batch.edit_verts, &cache->edit.data);
+ }
+ if (DRW_batch_requested(cache->batch.edit_handles_verts, GPU_PRIM_POINTS)) {
+ DRW_vbo_request(cache->batch.edit_handles_verts, &cache->edit.pos);
+ DRW_vbo_request(cache->batch.edit_handles_verts, &cache->edit.data);
+ }
+ if (DRW_batch_requested(cache->batch.edit_normals, GPU_PRIM_LINES)) {
+ DRW_vbo_request(cache->batch.edit_normals, &cache->edit.curves_nor);
+ }
+ for (int i = 0; i < cache->mat_len; ++i) {
+ if (DRW_batch_requested(cache->surf_per_mat[i], GPU_PRIM_TRIS)) {
+ if (cache->mat_len > 1) {
+ DRW_ibo_request(cache->surf_per_mat[i], &cache->surf_per_mat_tris[i]);
+ }
+ if (cache->cd_used & CD_MLOOPUV) {
+ DRW_vbo_request(cache->surf_per_mat[i], &cache->tess.uv);
+ }
+ DRW_vbo_request(cache->surf_per_mat[i], &cache->tess.pos_nor);
+ }
+ }
-/** \name Public Object/Font API
- * \{ */
+ /* Generate MeshRenderData flags */
+ int mr_flag = 0;
+ DRW_ADD_FLAG_FROM_VBO_REQUEST(mr_flag, cache->ordered.pos_nor, CU_DATATYPE_SURFACE);
+ DRW_ADD_FLAG_FROM_VBO_REQUEST(mr_flag, cache->ordered.curves_pos, CU_DATATYPE_WIRE);
+ DRW_ADD_FLAG_FROM_VBO_REQUEST(mr_flag, cache->tess.pos_nor, CU_DATATYPE_SURFACE);
+ DRW_ADD_FLAG_FROM_VBO_REQUEST(mr_flag, cache->tess.uv, CU_DATATYPE_SURFACE);
+ DRW_ADD_FLAG_FROM_VBO_REQUEST(mr_flag, cache->tess.wireframe_data, CU_DATATYPE_SURFACE);
+ DRW_ADD_FLAG_FROM_IBO_REQUEST(mr_flag, cache->ibo.surfaces_tris, CU_DATATYPE_SURFACE);
+ DRW_ADD_FLAG_FROM_IBO_REQUEST(mr_flag, cache->ibo.curves_lines, CU_DATATYPE_WIRE);
+
+ DRW_ADD_FLAG_FROM_VBO_REQUEST(mr_flag, cache->edit.pos, CU_DATATYPE_OVERLAY);
+ DRW_ADD_FLAG_FROM_VBO_REQUEST(mr_flag, cache->edit.data, CU_DATATYPE_OVERLAY);
+ DRW_ADD_FLAG_FROM_VBO_REQUEST(mr_flag, cache->edit.curves_nor, CU_DATATYPE_NORMAL);
+ DRW_ADD_FLAG_FROM_VBO_REQUEST(mr_flag, cache->edit.curves_weight, CU_DATATYPE_OVERLAY);
+ DRW_ADD_FLAG_FROM_IBO_REQUEST(mr_flag, cache->ibo.edit_verts_points, CU_DATATYPE_OVERLAY);
+ DRW_ADD_FLAG_FROM_IBO_REQUEST(mr_flag, cache->ibo.edit_lines, CU_DATATYPE_OVERLAY);
+
+ for (int i = 0; i < cache->mat_len; ++i) {
+ DRW_ADD_FLAG_FROM_IBO_REQUEST(mr_flag, cache->surf_per_mat_tris[i], CU_DATATYPE_SURFACE);
+ }
-GPUBatch *DRW_curve_batch_cache_get_overlay_select(Curve *cu)
-{
- CurveBatchCache *cache = curve_batch_cache_get(cu);
+ CurveRenderData *rdata = curve_render_data_create(me, ob->runtime.curve_cache, mr_flag);
- if (cache->text.select == NULL) {
- CurveRenderData *rdata = curve_render_data_create(cu, NULL, CU_DATATYPE_TEXT_SELECT);
+ /* DispLists */
+ ListBase *lb = &rdata->ob_curve_cache->disp;
- curve_batch_cache_get_overlay_select(rdata, cache);
+ /* Generate VBOs */
+ if (DRW_vbo_requested(cache->ordered.pos_nor)) {
+ DRW_displist_vertbuf_create_pos_and_nor(lb, cache->ordered.pos_nor);
+ }
+ if (DRW_vbo_requested(cache->ordered.curves_pos)) {
+ curve_create_curves_pos(rdata, cache->ordered.curves_pos);
+ }
- curve_render_data_free(rdata);
+ if (DRW_vbo_requested(cache->tess.pos_nor) ||
+ DRW_vbo_requested(cache->tess.uv))
+ {
+ DRW_displist_vertbuf_create_pos_and_nor_and_uv_tess(lb, cache->tess.pos_nor, cache->tess.uv);
+ }
+ if (DRW_vbo_requested(cache->tess.wireframe_data)) {
+ DRW_displist_vertbuf_create_wireframe_data_tess(lb, cache->tess.wireframe_data);
}
- return cache->text.select;
-}
+ if (DRW_ibo_requested(cache->surf_per_mat_tris[0])) {
+ DRW_displist_indexbuf_create_triangles_tess_split_by_material(lb, cache->surf_per_mat_tris, cache->mat_len);
+ }
-GPUBatch *DRW_curve_batch_cache_get_overlay_cursor(Curve *cu)
-{
- CurveBatchCache *cache = curve_batch_cache_get(cu);
+ if (DRW_ibo_requested(cache->ibo.curves_lines)) {
+ curve_create_curves_lines(rdata, cache->ibo.curves_lines);
+ }
+ if (DRW_ibo_requested(cache->ibo.surfaces_tris)) {
+ DRW_displist_indexbuf_create_triangles_in_order(lb, cache->ibo.surfaces_tris);
+ }
- if (cache->text.cursor == NULL) {
- CurveRenderData *rdata = curve_render_data_create(cu, NULL, CU_DATATYPE_TEXT_SELECT);
+ if (DRW_vbo_requested(cache->edit.pos) ||
+ DRW_vbo_requested(cache->edit.data) ||
+ DRW_ibo_requested(cache->ibo.edit_verts_points) ||
+ DRW_ibo_requested(cache->ibo.edit_lines))
+ {
+ curve_create_edit_data_and_handles(rdata, cache->edit.pos, cache->edit.data,
+ cache->ibo.edit_verts_points, cache->ibo.edit_lines);
+ }
+ if (DRW_vbo_requested(cache->edit.curves_nor)) {
+ curve_create_edit_curves_nor(rdata, cache->edit.curves_nor);
+ }
- curve_batch_cache_get_overlay_cursor(rdata, cache);
+ curve_render_data_free(rdata);
- curve_render_data_free(rdata);
+#ifdef DEBUG
+ /* Make sure all requested batches have been setup. */
+ for (int i = 0; i < sizeof(cache->batch) / sizeof(void *); ++i) {
+ BLI_assert(!DRW_batch_requested(((GPUBatch **)&cache->batch)[i], 0));
}
-
- return cache->text.cursor;
+#endif
}
/** \} */
diff --git a/source/blender/draw/intern/draw_cache_impl_displist.c b/source/blender/draw/intern/draw_cache_impl_displist.c
index d6a57676a8d..9724b1a47a2 100644
--- a/source/blender/draw/intern/draw_cache_impl_displist.c
+++ b/source/blender/draw/intern/draw_cache_impl_displist.c
@@ -125,7 +125,52 @@ static void displist_indexbufbuilder_set(
}
}
-GPUVertBuf *DRW_displist_vertbuf_calc_pos_with_normals(ListBase *lb)
+static int displist_indexbufbuilder_tess_set(
+ setTriIndicesFn *set_tri_indices,
+ setTriIndicesFn *set_quad_tri_indices, /* meh, find a better solution. */
+ void *thunk, const DispList *dl, const int ofs)
+{
+ int v_idx = ofs;
+ if (ELEM(dl->type, DL_INDEX3, DL_INDEX4, DL_SURF)) {
+ if (dl->type == DL_INDEX3) {
+ for (int i = 0; i < dl->parts; i++) {
+ set_tri_indices(thunk, v_idx + 0, v_idx + 1, v_idx + 2);
+ v_idx += 3;
+ }
+ }
+ else if (dl->type == DL_SURF) {
+ for (int a = 0; a < dl->parts; a++) {
+ if ((dl->flag & DL_CYCL_V) == 0 && a == dl->parts - 1) {
+ break;
+ }
+ int b = (dl->flag & DL_CYCL_U) ? 0 : 1;
+ for (; b < dl->nr; b++) {
+ set_quad_tri_indices(thunk, v_idx + 0, v_idx + 1, v_idx + 2);
+ set_quad_tri_indices(thunk, v_idx + 3, v_idx + 4, v_idx + 5);
+ v_idx += 6;
+ }
+ }
+ }
+ else {
+ BLI_assert(dl->type == DL_INDEX4);
+ const int *idx = dl->index;
+ for (int i = 0; i < dl->parts; i++, idx += 4) {
+ if (idx[2] != idx[3]) {
+ set_quad_tri_indices(thunk, v_idx + 0, v_idx + 1, v_idx + 2);
+ set_quad_tri_indices(thunk, v_idx + 3, v_idx + 4, v_idx + 5);
+ v_idx += 6;
+ }
+ else {
+ set_tri_indices(thunk, v_idx + 0, v_idx + 1, v_idx + 2);
+ v_idx += 3;
+ }
+ }
+ }
+ }
+ return v_idx;
+}
+
+void DRW_displist_vertbuf_create_pos_and_nor(ListBase *lb, GPUVertBuf *vbo)
{
static GPUVertFormat format = { 0 };
static struct { uint pos, nor; } attr_id;
@@ -135,7 +180,7 @@ GPUVertBuf *DRW_displist_vertbuf_calc_pos_with_normals(ListBase *lb)
attr_id.nor = GPU_vertformat_attr_add(&format, "nor", GPU_COMP_I16, 4, GPU_FETCH_INT_TO_FLOAT_UNIT);
}
- GPUVertBuf *vbo = GPU_vertbuf_create_with_format(&format);
+ GPU_vertbuf_init_with_format(vbo, &format);
GPU_vertbuf_data_alloc(vbo, curve_render_surface_vert_len_get(lb));
BKE_displist_normals_add(lb);
@@ -162,11 +207,9 @@ GPUVertBuf *DRW_displist_vertbuf_calc_pos_with_normals(ListBase *lb)
}
}
}
-
- return vbo;
}
-GPUIndexBuf *DRW_displist_indexbuf_calc_triangles_in_order(ListBase *lb)
+void DRW_displist_indexbuf_create_triangles_in_order(ListBase *lb, GPUIndexBuf *ibo)
{
const int tri_len = curve_render_surface_tri_len_get(lb);
const int vert_len = curve_render_surface_vert_len_get(lb);
@@ -182,159 +225,197 @@ GPUIndexBuf *DRW_displist_indexbuf_calc_triangles_in_order(ListBase *lb)
ofs += dl_vert_len(dl);
}
- return GPU_indexbuf_build(&elb);
+ GPU_indexbuf_build_in_place(&elb, ibo);
}
-GPUIndexBuf **DRW_displist_indexbuf_calc_triangles_in_order_split_by_material(ListBase *lb, uint gpumat_array_len)
+void DRW_displist_indexbuf_create_triangles_tess_split_by_material(
+ ListBase *lb,
+ GPUIndexBuf **ibo_mats, uint mat_len)
{
- GPUIndexBuf **shaded_triangles_in_order = MEM_callocN(
- sizeof(*shaded_triangles_in_order) * gpumat_array_len, __func__);
- GPUIndexBufBuilder *elb = BLI_array_alloca(elb, gpumat_array_len);
+ GPUIndexBufBuilder *elb = BLI_array_alloca(elb, mat_len);
const int tri_len = curve_render_surface_tri_len_get(lb);
- const int vert_len = curve_render_surface_vert_len_get(lb);
- int i;
/* Init each index buffer builder */
- for (i = 0; i < gpumat_array_len; i++) {
- GPU_indexbuf_init(&elb[i], GPU_PRIM_TRIS, tri_len, vert_len);
+ for (int i = 0; i < mat_len; i++) {
+ GPU_indexbuf_init(&elb[i], GPU_PRIM_TRIS, tri_len * 3, tri_len * 3);
}
/* calc each index buffer builder */
- int ofs = 0;
+ uint v_idx = 0;
for (const DispList *dl = lb->first; dl; dl = dl->next) {
- displist_indexbufbuilder_set((setTriIndicesFn *)GPU_indexbuf_add_tri_verts,
- (setTriIndicesFn *)GPU_indexbuf_add_tri_verts,
- &elb[dl->col], dl, ofs);
- ofs += dl_vert_len(dl);
+ v_idx = displist_indexbufbuilder_tess_set((setTriIndicesFn *)GPU_indexbuf_add_tri_verts,
+ (setTriIndicesFn *)GPU_indexbuf_add_tri_verts,
+ &elb[dl->col], dl, v_idx);
}
/* build each indexbuf */
- for (i = 0; i < gpumat_array_len; i++) {
- shaded_triangles_in_order[i] = GPU_indexbuf_build(&elb[i]);
+ for (int i = 0; i < mat_len; i++) {
+ GPU_indexbuf_build_in_place(&elb[i], ibo_mats[i]);
}
-
- return shaded_triangles_in_order;
}
typedef struct DRWDisplistWireThunk {
- uint index_id, vidx;
- short dl_type;
+ uint wd_id, ofs;
+ const DispList *dl;
GPUVertBuf *vbo;
} DRWDisplistWireThunk;
static void set_overlay_wires_tri_indices(void *thunk, uint v1, uint v2, uint v3)
{
DRWDisplistWireThunk *dwt = (DRWDisplistWireThunk *)thunk;
- /* Tag real edges. */
- v1 |= (1 << 30);
- v2 |= (1 << 30);
- v3 |= (1 << 30);
- GPU_vertbuf_attr_set(dwt->vbo, dwt->index_id, dwt->vidx++, &v1);
- GPU_vertbuf_attr_set(dwt->vbo, dwt->index_id, dwt->vidx++, &v2);
- GPU_vertbuf_attr_set(dwt->vbo, dwt->index_id, dwt->vidx++, &v3);
+ uint indices[3] = {v1, v2, v3};
+
+ for (int i = 0; i < 3; ++i) {
+ /* TODO: Compute sharpness. For now, only tag real egdes. */
+ uchar sharpness = 0xFF;
+ GPU_vertbuf_attr_set(dwt->vbo, dwt->wd_id, indices[i], &sharpness);
+ }
}
static void set_overlay_wires_quad_tri_indices(void *thunk, uint v1, uint v2, uint v3)
{
DRWDisplistWireThunk *dwt = (DRWDisplistWireThunk *)thunk;
- /* Tag real edges. */
- v2 |= (1 << 30);
- v3 |= (1 << 30);
- GPU_vertbuf_attr_set(dwt->vbo, dwt->index_id, dwt->vidx++, &v1);
- GPU_vertbuf_attr_set(dwt->vbo, dwt->index_id, dwt->vidx++, &v2);
- GPU_vertbuf_attr_set(dwt->vbo, dwt->index_id, dwt->vidx++, &v3);
+ uint indices[3] = {v1, v2, v3};
+
+ for (int i = 0; i < 3; ++i) {
+ /* TODO: Compute sharpness. For now, only tag real egdes. */
+ uchar sharpness = (i == 0) ? 0x00 : 0xFF;
+ GPU_vertbuf_attr_set(dwt->vbo, dwt->wd_id, indices[i], &sharpness);
+ }
}
-GPUVertBuf *DRW_displist_create_edges_overlay_texture_buf(ListBase *lb)
+/* TODO reuse the position and normals from other tesselation vertbuf. */
+void DRW_displist_vertbuf_create_wireframe_data_tess(ListBase *lb, GPUVertBuf *vbo)
{
- GPUVertFormat format = {0};
- uint index_id = GPU_vertformat_attr_add(&format, "index", GPU_COMP_U32, 1, GPU_FETCH_INT);
- GPUVertBuf *vbo = GPU_vertbuf_create_with_format(&format);
+ static DRWDisplistWireThunk thunk;
+ static GPUVertFormat format = {0};
+ if (format.attr_len == 0) {
+ thunk.wd_id = GPU_vertformat_attr_add(&format, "wd", GPU_COMP_U8, 1, GPU_FETCH_INT_TO_FLOAT_UNIT);
+ GPU_vertformat_triple_load(&format);
+ }
- GPU_vertbuf_data_alloc(vbo, curve_render_surface_tri_len_get(lb) * 3);
+ GPU_vertbuf_init_with_format(vbo, &format);
+ thunk.vbo = vbo;
- DRWDisplistWireThunk thunk = {.index_id = index_id, .vbo = vbo, .vidx = 0};
+ int vert_len = curve_render_surface_tri_len_get(lb) * 3;
+ GPU_vertbuf_data_alloc(thunk.vbo, vert_len);
- int ofs = 0;
+ thunk.ofs = 0;
for (const DispList *dl = lb->first; dl; dl = dl->next) {
- thunk.dl_type = dl->type;
+ thunk.dl = dl;
/* TODO consider non-manifold edges correctly. */
- displist_indexbufbuilder_set(set_overlay_wires_tri_indices,
- set_overlay_wires_quad_tri_indices,
- &thunk, dl, ofs);
- ofs += dl_vert_len(dl);
+ thunk.ofs = displist_indexbufbuilder_tess_set(set_overlay_wires_tri_indices,
+ set_overlay_wires_quad_tri_indices,
+ &thunk, dl, thunk.ofs);
}
- return vbo;
+ if (thunk.ofs < vert_len) {
+ GPU_vertbuf_data_resize(thunk.vbo, thunk.ofs);
+ }
}
+static void surf_uv_quad(const DispList *dl, const uint quad[4], float r_uv[4][2])
+{
+ int orco_sizeu = dl->nr - 1;
+ int orco_sizev = dl->parts - 1;
+
+ /* exception as handled in convertblender.c too */
+ if (dl->flag & DL_CYCL_U) {
+ orco_sizeu++;
+ }
+ if (dl->flag & DL_CYCL_V) {
+ orco_sizev++;
+ }
+
+ for (int i = 0; i < 4; i++) {
+ /* find uv based on vertex index into grid array */
+ r_uv[i][0] = (quad[i] / dl->nr) / (float)orco_sizev;
+ r_uv[i][1] = (quad[i] % dl->nr) / (float)orco_sizeu;
-static void displist_vertbuf_attr_set_tri_pos_normals_and_uv(
+ /* cyclic correction */
+ if ((i == 1 || i == 2) && r_uv[i][0] == 0.0f) {
+ r_uv[i][0] = 1.0f;
+ }
+ if ((i == 0 || i == 1) && r_uv[i][1] == 0.0f) {
+ r_uv[i][1] = 1.0f;
+ }
+ }
+}
+
+static void displist_vertbuf_attr_set_tri_pos_nor_uv(
GPUVertBufRaw *pos_step, GPUVertBufRaw *nor_step, GPUVertBufRaw *uv_step,
const float v1[3], const float v2[3], const float v3[3],
const float n1[3], const float n2[3], const float n3[3],
- const float uv1[2], const float uv2[2], const float uv3[2])
+ const float uv1[2], const float uv2[2], const float uv3[2],
+ const bool invert_normal)
{
- copy_v3_v3(GPU_vertbuf_raw_step(pos_step), v1);
- copy_v3_v3(GPU_vertbuf_raw_step(nor_step), n1);
- copy_v2_v2(GPU_vertbuf_raw_step(uv_step), uv1);
-
- copy_v3_v3(GPU_vertbuf_raw_step(pos_step), v2);
- copy_v3_v3(GPU_vertbuf_raw_step(nor_step), n2);
- copy_v2_v2(GPU_vertbuf_raw_step(uv_step), uv2);
+ if (pos_step->size != 0) {
+ copy_v3_v3(GPU_vertbuf_raw_step(pos_step), v1);
+ copy_v3_v3(GPU_vertbuf_raw_step(pos_step), v2);
+ copy_v3_v3(GPU_vertbuf_raw_step(pos_step), v3);
+
+ if (invert_normal) {
+ float neg_n1[3], neg_n2[3], neg_n3[3];
+ negate_v3_v3(neg_n1, n1);
+ negate_v3_v3(neg_n2, n2);
+ negate_v3_v3(neg_n3, n3);
+ *(GPUPackedNormal *)GPU_vertbuf_raw_step(nor_step) = GPU_normal_convert_i10_v3(neg_n1);
+ *(GPUPackedNormal *)GPU_vertbuf_raw_step(nor_step) = GPU_normal_convert_i10_v3(neg_n2);
+ *(GPUPackedNormal *)GPU_vertbuf_raw_step(nor_step) = GPU_normal_convert_i10_v3(neg_n3);
+ }
+ else {
+ *(GPUPackedNormal *)GPU_vertbuf_raw_step(nor_step) = GPU_normal_convert_i10_v3(n1);
+ *(GPUPackedNormal *)GPU_vertbuf_raw_step(nor_step) = GPU_normal_convert_i10_v3(n2);
+ *(GPUPackedNormal *)GPU_vertbuf_raw_step(nor_step) = GPU_normal_convert_i10_v3(n3);
+ }
+ }
- copy_v3_v3(GPU_vertbuf_raw_step(pos_step), v3);
- copy_v3_v3(GPU_vertbuf_raw_step(nor_step), n3);
- copy_v2_v2(GPU_vertbuf_raw_step(uv_step), uv3);
+ if (uv_step->size != 0) {
+ normal_float_to_short_v2(GPU_vertbuf_raw_step(uv_step), uv1);
+ normal_float_to_short_v2(GPU_vertbuf_raw_step(uv_step), uv2);
+ normal_float_to_short_v2(GPU_vertbuf_raw_step(uv_step), uv3);
+ }
}
-GPUBatch **DRW_displist_batch_calc_tri_pos_normals_and_uv_split_by_material(ListBase *lb, uint gpumat_array_len)
+void DRW_displist_vertbuf_create_pos_and_nor_and_uv_tess(
+ ListBase *lb,
+ GPUVertBuf *vbo_pos_nor, GPUVertBuf *vbo_uv)
{
- static GPUVertFormat shaded_triangles_format = { 0 };
+ static GPUVertFormat format_pos_nor = { 0 };
+ static GPUVertFormat format_uv = { 0 };
static struct { uint pos, nor, uv; } attr_id;
-
- if (shaded_triangles_format.attr_len == 0) {
+ if (format_pos_nor.attr_len == 0) {
/* initialize vertex format */
- attr_id.pos = GPU_vertformat_attr_add(&shaded_triangles_format, "pos", GPU_COMP_F32, 3, GPU_FETCH_FLOAT);
- attr_id.nor = GPU_vertformat_attr_add(&shaded_triangles_format, "nor", GPU_COMP_F32, 3, GPU_FETCH_FLOAT);
- attr_id.uv = GPU_vertformat_attr_add(&shaded_triangles_format, "u", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
+ attr_id.pos = GPU_vertformat_attr_add(&format_pos_nor, "pos", GPU_COMP_F32, 3, GPU_FETCH_FLOAT);
+ attr_id.nor = GPU_vertformat_attr_add(&format_pos_nor, "nor", GPU_COMP_I10, 3, GPU_FETCH_INT_TO_FLOAT_UNIT);
+ GPU_vertformat_triple_load(&format_pos_nor);
+ /* UVs are in [0..1] range. We can compress them. */
+ attr_id.uv = GPU_vertformat_attr_add(&format_uv, "u", GPU_COMP_I16, 2, GPU_FETCH_INT_TO_FLOAT_UNIT);
}
- GPUBatch **shaded_triangles = MEM_mallocN(sizeof(*shaded_triangles) * gpumat_array_len, __func__);
+ int vbo_len_capacity = curve_render_surface_tri_len_get(lb) * 3;
- GPUVertBuf **vbo = BLI_array_alloca(vbo, gpumat_array_len);
- uint *vbo_len_capacity = BLI_array_alloca(vbo_len_capacity, gpumat_array_len);
+ GPUVertBufRaw pos_step = {0};
+ GPUVertBufRaw nor_step = {0};
+ GPUVertBufRaw uv_step = {0};
- GPUVertBufRaw *pos_step, *nor_step, *uv_step;
- pos_step = BLI_array_alloca(pos_step, gpumat_array_len);
- nor_step = BLI_array_alloca(nor_step, gpumat_array_len);
- uv_step = BLI_array_alloca(uv_step, gpumat_array_len);
-
- /* Create each vertex buffer */
- for (int i = 0; i < gpumat_array_len; i++) {
- vbo[i] = GPU_vertbuf_create_with_format(&shaded_triangles_format);
- vbo_len_capacity[i] = 0;
+ if (DRW_TEST_ASSIGN_VBO(vbo_pos_nor)) {
+ GPU_vertbuf_init_with_format(vbo_pos_nor, &format_pos_nor);
+ GPU_vertbuf_data_alloc(vbo_pos_nor, vbo_len_capacity);
+ GPU_vertbuf_attr_get_raw_data(vbo_pos_nor, attr_id.pos, &pos_step);
+ GPU_vertbuf_attr_get_raw_data(vbo_pos_nor, attr_id.nor, &nor_step);
}
-
- /* Calc `vbo_len_capacity` */
- for (const DispList *dl = lb->first; dl; dl = dl->next) {
- vbo_len_capacity[dl->col] += dl_tri_len(dl) * 3;
- }
-
- /* Alloc each vertex buffer and get each raw data */
- for (int i = 0; i < gpumat_array_len; i++) {
- GPU_vertbuf_data_alloc(vbo[i], vbo_len_capacity[i]);
- GPU_vertbuf_attr_get_raw_data(vbo[i], attr_id.pos, &pos_step[i]);
- GPU_vertbuf_attr_get_raw_data(vbo[i], attr_id.nor, &nor_step[i]);
- GPU_vertbuf_attr_get_raw_data(vbo[i], attr_id.uv, &uv_step[i]);
+ if (DRW_TEST_ASSIGN_VBO(vbo_uv)) {
+ GPU_vertbuf_init_with_format(vbo_uv, &format_uv);
+ GPU_vertbuf_data_alloc(vbo_uv, vbo_len_capacity);
+ GPU_vertbuf_attr_get_raw_data(vbo_uv, attr_id.uv, &uv_step);
}
BKE_displist_normals_add(lb);
for (const DispList *dl = lb->first; dl; dl = dl->next) {
if (ELEM(dl->type, DL_INDEX3, DL_INDEX4, DL_SURF)) {
- const int col = dl->col;
const float(*verts)[3] = (float(*)[3])dl->verts;
const float(*nors)[3] = (float(*)[3])dl->nors;
const int *idx = dl->index;
@@ -345,15 +426,17 @@ GPUBatch **DRW_displist_batch_calc_tri_pos_normals_and_uv_split_by_material(List
uv[0][1] = uv[1][1] = uv[2][1] = 0.0f;
const int i_end = dl->parts;
for (int i = 0; i < i_end; i++, idx += 3) {
- uv[0][0] = idx[0] / x_max;
- uv[1][0] = idx[2] / x_max;
- uv[2][0] = idx[1] / x_max;
+ if (vbo_uv) {
+ uv[0][0] = idx[0] / x_max;
+ uv[1][0] = idx[1] / x_max;
+ uv[2][0] = idx[2] / x_max;
+ }
- displist_vertbuf_attr_set_tri_pos_normals_and_uv(
- &pos_step[col], &nor_step[col], &uv_step[col],
+ displist_vertbuf_attr_set_tri_pos_nor_uv(
+ &pos_step, &nor_step, &uv_step,
verts[idx[0]], verts[idx[2]], verts[idx[1]],
dl->nors, dl->nors, dl->nors,
- uv[0], uv[1], uv[2]);
+ uv[0], uv[2], uv[1], false);
}
}
else if (dl->type == DL_SURF) {
@@ -384,42 +467,21 @@ GPUBatch **DRW_displist_batch_calc_tri_pos_normals_and_uv_split_by_material(List
}
for (; b < dl->nr; b++) {
- int orco_sizeu = dl->nr - 1;
- int orco_sizev = dl->parts - 1;
-
- /* exception as handled in convertblender.c too */
- if (dl->flag & DL_CYCL_U) {
- orco_sizeu++;
- }
- if (dl->flag & DL_CYCL_V) {
- orco_sizev++;
+ if (vbo_uv) {
+ surf_uv_quad(dl, quad, uv);
}
- for (int i = 0; i < 4; i++) {
- /* find uv based on vertex index into grid array */
- uv[i][0] = (quad[i] / dl->nr) / (float)orco_sizev;
- uv[i][1] = (quad[i] % dl->nr) / (float)orco_sizeu;
-
- /* cyclic correction */
- if ((i == 1 || i == 2) && uv[i][0] == 0.0f) {
- uv[i][0] = 1.0f;
- }
- if ((i == 0 || i == 1) && uv[i][1] == 0.0f) {
- uv[i][1] = 1.0f;
- }
- }
+ displist_vertbuf_attr_set_tri_pos_nor_uv(
+ &pos_step, &nor_step, &uv_step,
+ verts[quad[2]], verts[quad[0]], verts[quad[1]],
+ nors[quad[2]], nors[quad[0]], nors[quad[1]],
+ uv[2], uv[0], uv[1], false);
- displist_vertbuf_attr_set_tri_pos_normals_and_uv(
- &pos_step[col], &nor_step[col], &uv_step[col],
- verts[quad[0]], verts[quad[1]], verts[quad[2]],
- nors[quad[0]], nors[quad[1]], nors[quad[2]],
- uv[0], uv[1], uv[2]);
-
- displist_vertbuf_attr_set_tri_pos_normals_and_uv(
- &pos_step[col], &nor_step[col], &uv_step[col],
+ displist_vertbuf_attr_set_tri_pos_nor_uv(
+ &pos_step, &nor_step, &uv_step,
verts[quad[0]], verts[quad[2]], verts[quad[3]],
nors[quad[0]], nors[quad[2]], nors[quad[3]],
- uv[0], uv[2], uv[3]);
+ uv[0], uv[2], uv[3], false);
quad[2] = quad[1];
quad[1]++;
@@ -435,31 +497,34 @@ GPUBatch **DRW_displist_batch_calc_tri_pos_normals_and_uv_split_by_material(List
const int i_end = dl->parts;
for (int i = 0; i < i_end; i++, idx += 4) {
- displist_vertbuf_attr_set_tri_pos_normals_and_uv(
- &pos_step[col], &nor_step[col], &uv_step[col],
- verts[idx[0]], verts[idx[1]], verts[idx[2]],
- nors[idx[0]], nors[idx[1]], nors[idx[2]],
- uv[0], uv[1], uv[2]);
+ displist_vertbuf_attr_set_tri_pos_nor_uv(
+ &pos_step, &nor_step, &uv_step,
+ verts[idx[0]], verts[idx[2]], verts[idx[1]],
+ nors[idx[0]], nors[idx[2]], nors[idx[1]],
+ uv[0], uv[2], uv[1], true);
if (idx[2] != idx[3]) {
- displist_vertbuf_attr_set_tri_pos_normals_and_uv(
- &pos_step[col], &nor_step[col], &uv_step[col],
- verts[idx[0]], verts[idx[2]], verts[idx[3]],
- nors[idx[0]], nors[idx[2]], nors[idx[3]],
- uv[0], uv[2], uv[3]);
+ displist_vertbuf_attr_set_tri_pos_nor_uv(
+ &pos_step, &nor_step, &uv_step,
+ verts[idx[2]], verts[idx[0]], verts[idx[3]],
+ nors[idx[2]], nors[idx[0]], nors[idx[3]],
+ uv[2], uv[0], uv[3], true);
}
}
}
}
}
-
- for (int i = 0; i < gpumat_array_len; i++) {
- uint vbo_len_used = GPU_vertbuf_raw_used(&pos_step[i]);
- if (vbo_len_capacity[i] != vbo_len_used) {
- GPU_vertbuf_data_resize(vbo[i], vbo_len_used);
+ /* Resize and finish. */
+ if (pos_step.size != 0) {
+ int vbo_len_used = GPU_vertbuf_raw_used(&pos_step);
+ if (vbo_len_used < vbo_len_capacity) {
+ GPU_vertbuf_data_resize(vbo_pos_nor, vbo_len_used);
+ }
+ }
+ if (uv_step.size != 0) {
+ int vbo_len_used = GPU_vertbuf_raw_used(&uv_step);
+ if (vbo_len_used < vbo_len_capacity) {
+ GPU_vertbuf_data_resize(vbo_uv, vbo_len_used);
}
- shaded_triangles[i] = GPU_batch_create_ex(GPU_PRIM_TRIS, vbo[i], NULL, GPU_BATCH_OWNS_VBO);
}
-
- return shaded_triangles;
}
diff --git a/source/blender/draw/intern/draw_cache_impl_lattice.c b/source/blender/draw/intern/draw_cache_impl_lattice.c
index b077162b41d..12f80c4e8e9 100644
--- a/source/blender/draw/intern/draw_cache_impl_lattice.c
+++ b/source/blender/draw/intern/draw_cache_impl_lattice.c
@@ -567,7 +567,7 @@ GPUBatch *DRW_lattice_batch_cache_get_all_verts(Lattice *lt)
return cache->all_verts;
}
-GPUBatch *DRW_lattice_batch_cache_get_overlay_verts(Lattice *lt)
+GPUBatch *DRW_lattice_batch_cache_get_edit_verts(Lattice *lt)
{
LatticeBatchCache *cache = lattice_batch_cache_get(lt);
diff --git a/source/blender/draw/intern/draw_cache_impl_mesh.c b/source/blender/draw/intern/draw_cache_impl_mesh.c
index a24702368de..b0080c70a0d 100644
--- a/source/blender/draw/intern/draw_cache_impl_mesh.c
+++ b/source/blender/draw/intern/draw_cache_impl_mesh.c
@@ -44,6 +44,7 @@
#include "DNA_meshdata_types.h"
#include "DNA_object_types.h"
#include "DNA_space_types.h"
+#include "DNA_scene_types.h"
#include "BKE_customdata.h"
#include "BKE_deform.h"
@@ -53,16 +54,19 @@
#include "BKE_mesh.h"
#include "BKE_mesh_tangent.h"
#include "BKE_mesh_runtime.h"
+#include "BKE_object.h"
+#include "BKE_object_deform.h"
#include "BKE_colorband.h"
#include "BKE_cdderivedmesh.h"
+#include "DEG_depsgraph_query.h"
+
#include "bmesh.h"
#include "GPU_batch.h"
#include "GPU_batch_presets.h"
#include "GPU_draw.h"
#include "GPU_material.h"
-#include "GPU_texture.h"
#include "DRW_render.h"
@@ -72,8 +76,28 @@
#include "draw_cache_impl.h" /* own include */
+
static void mesh_batch_cache_clear(Mesh *me);
+/* Vertex Group Selection and display options */
+typedef struct DRW_MeshWeightState {
+ int defgroup_active;
+ int defgroup_len;
+
+ short flags;
+ char alert_mode;
+
+ /* Set of all selected bones for Multipaint. */
+ bool *defgroup_sel; /* [defgroup_len] */
+ int defgroup_sel_count;
+} DRW_MeshWeightState;
+
+/* DRW_MeshWeightState.flags */
+enum {
+ DRW_MESH_WEIGHT_STATE_MULTIPAINT = (1 << 0),
+ DRW_MESH_WEIGHT_STATE_AUTO_NORMALIZE = (1 << 1),
+};
+
/* ---------------------------------------------------------------------- */
/** \name Mesh/BMesh Interface (direct access to basic data).
@@ -175,6 +199,8 @@ typedef struct MeshRenderData {
BMEditMesh *edit_bmesh;
struct EditMeshData *edit_data;
+ Mesh *me;
+
MVert *mvert;
const MEdge *medge;
const MLoop *mloop;
@@ -247,6 +273,7 @@ typedef struct MeshRenderData {
GPUPackedNormal *poly_normals_pack;
GPUPackedNormal *vert_normals_pack;
bool *edge_select_bool;
+ bool *edge_visible_bool;
} MeshRenderData;
enum {
@@ -260,6 +287,8 @@ enum {
MR_DATATYPE_DVERT = 1 << 7,
MR_DATATYPE_LOOPCOL = 1 << 8,
MR_DATATYPE_LOOPUV = 1 << 9,
+ MR_DATATYPE_LOOSE_VERT = 1 << 10,
+ MR_DATATYPE_LOOSE_EDGE = 1 << 11,
};
/**
@@ -291,12 +320,60 @@ static bool bm_edge_has_visible_face(const BMEdge *e)
return false;
}
+/* Return true is all layers in _b_ are inside _a_. */
+static bool mesh_cd_layers_type_overlap(
+ const uchar av[CD_NUMTYPES], const ushort al[CD_NUMTYPES],
+ const uchar bv[CD_NUMTYPES], const ushort bl[CD_NUMTYPES])
+{
+ for (int i = 0; i < CD_NUMTYPES; ++i) {
+ if ((av[i] & bv[i]) != bv[i]) {
+ return false;
+ }
+ if ((al[i] & bl[i]) != bl[i]) {
+ return false;
+ }
+ }
+ return true;
+}
+
+static void mesh_cd_layers_type_merge(
+ uchar av[CD_NUMTYPES], ushort al[CD_NUMTYPES],
+ uchar bv[CD_NUMTYPES], ushort bl[CD_NUMTYPES])
+{
+ for (int i = 0; i < CD_NUMTYPES; ++i) {
+ av[i] |= bv[i];
+ al[i] |= bl[i];
+ }
+}
+
+static void mesh_cd_calc_active_uv_layer(
+ const Mesh *me, ushort cd_lused[CD_NUMTYPES])
+{
+ const CustomData *cd_ldata = (me->edit_btmesh) ? &me->edit_btmesh->bm->ldata : &me->ldata;
+
+ int layer = CustomData_get_active_layer(cd_ldata, CD_MLOOPUV);
+ if (layer != -1) {
+ cd_lused[CD_MLOOPUV] |= (1 << layer);
+ }
+}
+
+static void mesh_cd_calc_active_vcol_layer(
+ const Mesh *me, ushort cd_lused[CD_NUMTYPES])
+{
+ const CustomData *cd_ldata = (me->edit_btmesh) ? &me->edit_btmesh->bm->ldata : &me->ldata;
+
+ int layer = CustomData_get_active_layer(cd_ldata, CD_MLOOPCOL);
+ if (layer != -1) {
+ cd_lused[CD_MLOOPCOL] |= (1 << layer);
+ }
+}
static void mesh_cd_calc_used_gpu_layers(
- CustomData *UNUSED(cd_vdata), uchar cd_vused[CD_NUMTYPES],
- CustomData *cd_ldata, ushort cd_lused[CD_NUMTYPES],
+ const Mesh *me, uchar cd_vused[CD_NUMTYPES], ushort cd_lused[CD_NUMTYPES],
struct GPUMaterial **gpumat_array, int gpumat_array_len)
{
+ const CustomData *cd_ldata = (me->edit_btmesh) ? &me->edit_btmesh->bm->ldata : &me->ldata;
+
/* See: DM_vertex_attributes_from_gpu for similar logic */
GPUVertexAttribs gattribs = {{{0}}};
@@ -417,6 +494,54 @@ static void mesh_render_calc_normals_loop_and_poly(const Mesh *me, const float s
rdata->poly_normals = poly_normals;
}
+static void mesh_cd_extract_auto_layers_names_and_srgb(
+ Mesh *me, const ushort cd_lused[CD_NUMTYPES],
+ char **r_auto_layers_names, int **r_auto_layers_srgb, int *r_auto_layers_len)
+{
+ const CustomData *cd_ldata = (me->edit_btmesh) ? &me->edit_btmesh->bm->ldata : &me->ldata;
+
+ int uv_len_used = count_bits_i(cd_lused[CD_MLOOPUV]);
+ int vcol_len_used = count_bits_i(cd_lused[CD_MLOOPCOL]);
+ int uv_len = CustomData_number_of_layers(cd_ldata, CD_MLOOPUV);
+ int vcol_len = CustomData_number_of_layers(cd_ldata, CD_MLOOPCOL);
+
+ uint auto_names_len = 32 * (uv_len_used + vcol_len_used);
+ uint auto_ofs = 0;
+ /* Allocate max, resize later. */
+ char *auto_names = MEM_callocN(sizeof(char) * auto_names_len, __func__);
+ int *auto_is_srgb = MEM_callocN(sizeof(int) * (uv_len_used + vcol_len_used), __func__);
+
+ for (int i = 0; i < uv_len; i++) {
+ if ((cd_lused[CD_MLOOPUV] & (1 << i)) != 0) {
+ const char *name = CustomData_get_layer_name(cd_ldata, CD_MLOOPUV, i);
+ uint hash = BLI_ghashutil_strhash_p(name);
+ /* +1 to include '\0' terminator. */
+ auto_ofs += 1 + BLI_snprintf_rlen(auto_names + auto_ofs, auto_names_len - auto_ofs, "ba%u", hash);
+ }
+ }
+
+ uint auto_is_srgb_ofs = uv_len_used;
+ for (int i = 0; i < vcol_len; i++) {
+ if ((cd_lused[CD_MLOOPCOL] & (1 << i)) != 0) {
+ const char *name = CustomData_get_layer_name(cd_ldata, CD_MLOOPCOL, i);
+ /* We only do vcols that are not overridden by a uv layer with same name. */
+ if (CustomData_get_named_layer_index(cd_ldata, CD_MLOOPUV, name) == -1) {
+ uint hash = BLI_ghashutil_strhash_p(name);
+ /* +1 to include '\0' terminator. */
+ auto_ofs += 1 + BLI_snprintf_rlen(auto_names + auto_ofs, auto_names_len - auto_ofs, "ba%u", hash);
+ auto_is_srgb[auto_is_srgb_ofs] = true;
+ auto_is_srgb_ofs++;
+ }
+ }
+ }
+
+ auto_names = MEM_reallocN(auto_names, sizeof(char) * auto_ofs);
+ auto_is_srgb = MEM_reallocN(auto_is_srgb, sizeof(int) * auto_is_srgb_ofs);
+
+ *r_auto_layers_names = auto_names;
+ *r_auto_layers_srgb = auto_is_srgb;
+ *r_auto_layers_len = auto_is_srgb_ofs;
+}
/**
* TODO(campbell): 'gpumat_array' may include materials linked to the object.
@@ -424,8 +549,7 @@ static void mesh_render_calc_normals_loop_and_poly(const Mesh *me, const float s
* Although this only impacts the data that's generated, not the materials that display.
*/
static MeshRenderData *mesh_render_data_create_ex(
- Mesh *me, const int types,
- struct GPUMaterial **gpumat_array, uint gpumat_array_len)
+ Mesh *me, const int types, const uchar cd_vused[CD_NUMTYPES], const ushort cd_lused[CD_NUMTYPES])
{
MeshRenderData *rdata = MEM_callocN(sizeof(*rdata), __func__);
rdata->types = types;
@@ -539,8 +663,9 @@ static MeshRenderData *mesh_render_data_create_ex(
rdata->tri_len = tottri;
}
- if (types & MR_DATATYPE_OVERLAY) {
- rdata->loose_vert_len = rdata->loose_edge_len = 0;
+ if (types & MR_DATATYPE_LOOSE_VERT) {
+ BLI_assert(types & MR_DATATYPE_VERT);
+ rdata->loose_vert_len = 0;
{
int *lverts = MEM_mallocN(rdata->vert_len * sizeof(int), __func__);
@@ -557,24 +682,9 @@ static MeshRenderData *mesh_render_data_create_ex(
rdata->loose_verts = MEM_reallocN(lverts, rdata->loose_vert_len * sizeof(int));
}
- {
- int *ledges = MEM_mallocN(rdata->edge_len * sizeof(int), __func__);
- BLI_assert((bm->elem_table_dirty & BM_EDGE) == 0);
- for (int i = 0; i < bm->totedge; i++) {
- const BMEdge *eed = BM_edge_at_index(bm, i);
- if (!BM_elem_flag_test(eed, BM_ELEM_HIDDEN)) {
- /* Loose edge */
- if (eed->l == NULL || !bm_edge_has_visible_face(eed)) {
- ledges[rdata->loose_edge_len++] = i;
- }
- }
- }
- rdata->loose_edges = MEM_reallocN(ledges, rdata->loose_edge_len * sizeof(int));
- }
-
if (rdata->mapped.supported) {
Mesh *me_cage = embm->mesh_eval_cage;
- rdata->mapped.loose_vert_len = rdata->mapped.loose_edge_len = 0;
+ rdata->mapped.loose_vert_len = 0;
if (rdata->loose_vert_len) {
int *lverts = MEM_mallocN(me_cage->totvert * sizeof(int), __func__);
@@ -593,6 +703,31 @@ static MeshRenderData *mesh_render_data_create_ex(
}
rdata->mapped.loose_verts = MEM_reallocN(lverts, rdata->mapped.loose_vert_len * sizeof(int));
}
+ }
+ }
+
+ if (types & MR_DATATYPE_LOOSE_EDGE) {
+ BLI_assert(types & MR_DATATYPE_EDGE);
+ rdata->loose_edge_len = 0;
+
+ {
+ int *ledges = MEM_mallocN(rdata->edge_len * sizeof(int), __func__);
+ BLI_assert((bm->elem_table_dirty & BM_EDGE) == 0);
+ for (int i = 0; i < bm->totedge; i++) {
+ const BMEdge *eed = BM_edge_at_index(bm, i);
+ if (!BM_elem_flag_test(eed, BM_ELEM_HIDDEN)) {
+ /* Loose edge */
+ if (eed->l == NULL || !bm_edge_has_visible_face(eed)) {
+ ledges[rdata->loose_edge_len++] = i;
+ }
+ }
+ }
+ rdata->loose_edges = MEM_reallocN(ledges, rdata->loose_edge_len * sizeof(int));
+ }
+
+ if (rdata->mapped.supported) {
+ Mesh *me_cage = embm->mesh_eval_cage;
+ rdata->mapped.loose_edge_len = 0;
if (rdata->loose_edge_len) {
int *ledges = MEM_mallocN(me_cage->totedge * sizeof(int), __func__);
@@ -615,6 +750,8 @@ static MeshRenderData *mesh_render_data_create_ex(
}
}
else {
+ rdata->me = me;
+
if (types & (MR_DATATYPE_VERT)) {
rdata->vert_len = me->totvert;
rdata->mvert = CustomData_get_layer(&me->vdata, CD_MVERT);
@@ -658,6 +795,8 @@ static MeshRenderData *mesh_render_data_create_ex(
if (types & MR_DATATYPE_SHADING) {
CustomData *cd_vdata, *cd_ldata;
+ BLI_assert(cd_vused != NULL && cd_lused != NULL);
+
if (me->edit_btmesh) {
BMesh *bm = me->edit_btmesh->bm;
cd_vdata = &bm->vdata;
@@ -668,16 +807,6 @@ static MeshRenderData *mesh_render_data_create_ex(
cd_ldata = &me->ldata;
}
- /* Add edge/poly if we need them */
- uchar cd_vused[CD_NUMTYPES] = {0};
- ushort cd_lused[CD_NUMTYPES] = {0};
-
- mesh_cd_calc_used_gpu_layers(
- cd_vdata, cd_vused,
- cd_ldata, cd_lused,
- gpumat_array, gpumat_array_len);
-
-
rdata->cd.layers.uv_active = CustomData_get_active_layer(cd_ldata, CD_MLOOPUV);
rdata->cd.layers.vcol_active = CustomData_get_active_layer(cd_ldata, CD_MLOOPCOL);
rdata->cd.layers.tangent_active = rdata->cd.layers.uv_active;
@@ -942,6 +1071,21 @@ static MeshRenderData *mesh_render_data_create_ex(
return rdata;
}
+/* Warning replace mesh pointer. */
+#define MBC_GET_FINAL_MESH(me) \
+ /* Hack to show the final result. */ \
+ const bool _use_em_final = ( \
+ (me)->edit_btmesh && \
+ (me)->edit_btmesh->mesh_eval_final && \
+ ((me)->edit_btmesh->mesh_eval_final->runtime.is_original == false)); \
+ Mesh _me_fake; \
+ if (_use_em_final) { \
+ _me_fake = *(me)->edit_btmesh->mesh_eval_final; \
+ _me_fake.mat = (me)->mat; \
+ _me_fake.totcol = (me)->totcol; \
+ (me) = &_me_fake; \
+ } ((void)0)
+
static void mesh_render_data_free(MeshRenderData *rdata)
{
if (rdata->is_orco_allocated) {
@@ -967,6 +1111,7 @@ static void mesh_render_data_free(MeshRenderData *rdata)
MEM_SAFE_FREE(rdata->vert_normals_pack);
MEM_SAFE_FREE(rdata->vert_weight);
MEM_SAFE_FREE(rdata->edge_select_bool);
+ MEM_SAFE_FREE(rdata->edge_visible_bool);
MEM_SAFE_FREE(rdata->vert_color);
MEM_SAFE_FREE(rdata->mapped.loose_verts);
@@ -979,12 +1124,11 @@ static void mesh_render_data_free(MeshRenderData *rdata)
static MeshRenderData *mesh_render_data_create(Mesh *me, const int types)
{
- return mesh_render_data_create_ex(me, types, NULL, 0);
+ return mesh_render_data_create_ex(me, types, NULL, NULL);
}
/** \} */
-
/* ---------------------------------------------------------------------- */
/** \name Accessor Functions
@@ -1075,7 +1219,7 @@ static int mesh_render_data_looptri_len_get_maybe_mapped(const MeshRenderData *r
return ((rdata->mapped.use == false) ? rdata->tri_len : rdata->mapped.tri_len);
}
-static int mesh_render_data_mat_len_get(const MeshRenderData *rdata)
+static int UNUSED_FUNCTION(mesh_render_data_mat_len_get)(const MeshRenderData *rdata)
{
BLI_assert(rdata->types & MR_DATATYPE_POLY);
return rdata->mat_len;
@@ -1103,6 +1247,9 @@ static int mesh_render_data_polys_len_get_maybe_mapped(const MeshRenderData *rda
/* ---------------------------------------------------------------------- */
+/* TODO remove prototype. */
+static void mesh_create_edit_facedots(MeshRenderData *rdata, GPUVertBuf *vbo_pos_nor_data_facedots);
+
/** \name Internal Cache (Lazy Initialization)
* \{ */
@@ -1174,7 +1321,7 @@ static void mesh_render_data_ensure_vert_normals_pack(MeshRenderData *rdata)
/** Ensure #MeshRenderData.vert_color */
-static void mesh_render_data_ensure_vert_color(MeshRenderData *rdata)
+static void UNUSED_FUNCTION(mesh_render_data_ensure_vert_color)(MeshRenderData *rdata)
{
char (*vcol)[3] = rdata->vert_color;
if (vcol == NULL) {
@@ -1230,7 +1377,7 @@ fallback:
}
}
-static float evaluate_vertex_weight(const MDeformVert *dvert, const struct DRW_MeshWeightState *wstate)
+static float evaluate_vertex_weight(const MDeformVert *dvert, const DRW_MeshWeightState *wstate)
{
float input = 0.0f;
bool show_alert_color = false;
@@ -1322,34 +1469,6 @@ fallback:
}
}
-
-/** Ensure #MeshRenderData.edge_select_bool */
-static void mesh_render_data_ensure_edge_select_bool(MeshRenderData *rdata, bool use_wire)
-{
- bool *edge_select_bool = rdata->edge_select_bool;
- if (edge_select_bool == NULL) {
- edge_select_bool = rdata->edge_select_bool =
- MEM_callocN(sizeof(*edge_select_bool) * rdata->edge_len, __func__);
-
- for (int i = 0; i < rdata->poly_len; i++) {
- const MPoly *poly = &rdata->mpoly[i];
-
- if (poly->flag & ME_FACE_SEL) {
- for (int j = 0; j < poly->totloop; j++) {
- const MLoop *loop = &rdata->mloop[poly->loopstart + j];
- if (use_wire) {
- edge_select_bool[loop->e] = true;
- }
- else {
- /* Not totally correct, will cause problems for edges with 3x faces. */
- edge_select_bool[loop->e] = !edge_select_bool[loop->e];
- }
- }
- }
- }
- }
-}
-
/** \} */
/* ---------------------------------------------------------------------- */
@@ -1357,75 +1476,6 @@ static void mesh_render_data_ensure_edge_select_bool(MeshRenderData *rdata, bool
/** \name Internal Cache Generation
* \{ */
-static bool mesh_render_data_pnors_pcenter_select_get(
- MeshRenderData *rdata, const int poly,
- float r_pnors[3], float r_center[3], bool *r_selected)
-{
- BLI_assert(rdata->types & (MR_DATATYPE_VERT | MR_DATATYPE_LOOP | MR_DATATYPE_POLY));
-
- if (rdata->edit_bmesh) {
- const BMFace *efa = BM_face_at_index(rdata->edit_bmesh->bm, poly);
- if (BM_elem_flag_test(efa, BM_ELEM_HIDDEN)) {
- return false;
- }
- if (rdata->edit_data && rdata->edit_data->vertexCos) {
- copy_v3_v3(r_center, rdata->edit_data->polyCos[poly]);
- copy_v3_v3(r_pnors, rdata->edit_data->polyNos[poly]);
- }
- else {
- BM_face_calc_center_mean(efa, r_center);
- copy_v3_v3(r_pnors, efa->no);
- }
- *r_selected = (BM_elem_flag_test(efa, BM_ELEM_SELECT) != 0) ? true : false;
- }
- else {
- MVert *mvert = rdata->mvert;
- const MPoly *mpoly = rdata->mpoly + poly;
- const MLoop *mloop = rdata->mloop + mpoly->loopstart;
-
- BKE_mesh_calc_poly_center(mpoly, mloop, mvert, r_center);
- BKE_mesh_calc_poly_normal(mpoly, mloop, mvert, r_pnors);
-
- *r_selected = false; /* No selection if not in edit mode */
- }
-
- return true;
-}
-static bool mesh_render_data_pnors_pcenter_select_get_mapped(
- MeshRenderData *rdata, const int poly,
- float r_pnors[3], float r_center[3], bool *r_selected)
-{
- BLI_assert(rdata->types & (MR_DATATYPE_VERT | MR_DATATYPE_LOOP | MR_DATATYPE_POLY));
- const int *p_origindex = rdata->mapped.p_origindex;
- const int p_orig = p_origindex[poly];
- if (p_orig == ORIGINDEX_NONE) {
- return false;
- }
- BMEditMesh *em = rdata->edit_bmesh;
- const BMFace *efa = BM_face_at_index(rdata->edit_bmesh->bm, p_orig);
- if (BM_elem_flag_test(efa, BM_ELEM_HIDDEN)) {
- return false;
- }
-
- Mesh *me_cage = em->mesh_eval_cage;
- const MVert *mvert = me_cage->mvert;
-#if 0
- const MEdge *medge = me_cage->medge;
-#endif
- const MLoop *mloop = me_cage->mloop;
- const MPoly *mpoly = me_cage->mpoly;
-
- const MPoly *mp = mpoly + poly;
- const MLoop *ml = mloop + mp->loopstart;
-
- BKE_mesh_calc_poly_center(mp, ml, mvert, r_center);
- BKE_mesh_calc_poly_normal(mp, ml, mvert, r_pnors);
-
- *r_selected = (BM_elem_flag_test(efa, BM_ELEM_SELECT) != 0) ? true : false;
-
- return true;
-}
-
static bool mesh_render_data_edge_vcos_manifold_pnors(
MeshRenderData *rdata, const int edge_index,
float **r_vco1, float **r_vco2, float **r_pnor1, float **r_pnor2, bool *r_is_manifold)
@@ -1613,46 +1663,52 @@ static uchar mesh_render_data_vertex_flag(MeshRenderData *rdata, const BMVert *e
return vflag;
}
-static void add_overlay_tri(
- MeshRenderData *rdata, GPUVertBuf *vbo_pos, GPUVertBuf *vbo_nor, GPUVertBuf *vbo_data, GPUIndexBufBuilder *elb,
+static void add_edit_tri(
+ MeshRenderData *rdata, GPUVertBuf *vbo_pos_nor, GPUVertBuf *vbo_lnor, GPUVertBuf *vbo_data, GPUIndexBufBuilder *elb,
const uint pos_id, const uint vnor_id, const uint lnor_id, const uint data_id,
const BMLoop **bm_looptri, const int base_vert_idx)
{
uchar fflag;
uchar vflag;
- for (int i = 0; i < 3; ++i) {
- if (!BM_elem_flag_test(bm_looptri[i]->v, BM_ELEM_TAG)) {
- BM_elem_flag_enable(bm_looptri[i]->v, BM_ELEM_TAG);
- GPU_indexbuf_add_generic_vert(elb, base_vert_idx + i);
+ /* Only draw vertices once. */
+ if (elb) {
+ for (int i = 0; i < 3; ++i) {
+ if (!BM_elem_flag_test(bm_looptri[i]->v, BM_ELEM_TAG)) {
+ BM_elem_flag_enable(bm_looptri[i]->v, BM_ELEM_TAG);
+ GPU_indexbuf_add_generic_vert(elb, base_vert_idx + i);
+ }
}
}
- if (vbo_pos) {
+ if (vbo_pos_nor) {
/* TODO(sybren): deduplicate this and all the other places it's pasted to in this file. */
if (rdata->edit_data && rdata->edit_data->vertexCos) {
for (uint i = 0; i < 3; i++) {
int vidx = BM_elem_index_get(bm_looptri[i]->v);
const float *pos = rdata->edit_data->vertexCos[vidx];
- GPU_vertbuf_attr_set(vbo_pos, pos_id, base_vert_idx + i, pos);
+ GPU_vertbuf_attr_set(vbo_pos_nor, pos_id, base_vert_idx + i, pos);
}
}
else {
for (uint i = 0; i < 3; i++) {
const float *pos = bm_looptri[i]->v->co;
- GPU_vertbuf_attr_set(vbo_pos, pos_id, base_vert_idx + i, pos);
+ GPU_vertbuf_attr_set(vbo_pos_nor, pos_id, base_vert_idx + i, pos);
}
}
+
+ for (uint i = 0; i < 3; i++) {
+ GPUPackedNormal vnor = GPU_normal_convert_i10_v3(bm_looptri[i]->v->no);
+ GPU_vertbuf_attr_set(vbo_pos_nor, vnor_id, base_vert_idx + i, &vnor);
+ }
}
- if (vbo_nor) {
+ if (vbo_lnor) {
float (*lnors)[3] = rdata->loop_normals;
for (uint i = 0; i < 3; i++) {
const float *nor = (lnors) ? lnors[BM_elem_index_get(bm_looptri[i])] : bm_looptri[0]->f->no;
GPUPackedNormal lnor = GPU_normal_convert_i10_v3(nor);
- GPU_vertbuf_attr_set(vbo_nor, lnor_id, base_vert_idx + i, &lnor);
- GPUPackedNormal vnor = GPU_normal_convert_i10_v3(bm_looptri[i]->v->no);
- GPU_vertbuf_attr_set(vbo_nor, vnor_id, base_vert_idx + i, &vnor);
+ GPU_vertbuf_attr_set(vbo_lnor, lnor_id, base_vert_idx + i, &lnor);
}
}
@@ -1673,11 +1729,15 @@ static void add_overlay_tri(
}
}
}
-static void add_overlay_tri_mapped(
- MeshRenderData *rdata, GPUVertBuf *vbo_pos, GPUVertBuf *vbo_nor, GPUVertBuf *vbo_data, GPUIndexBufBuilder *elb,
+static bool add_edit_tri_mapped(
+ MeshRenderData *rdata, GPUVertBuf *vbo_pos_nor, GPUVertBuf *vbo_lnor, GPUVertBuf *vbo_data, GPUIndexBufBuilder *elb,
const uint pos_id, const uint vnor_id, const uint lnor_id, const uint data_id,
- BMFace *efa, const MLoopTri *mlt, const float poly_normal[3], const int base_vert_idx)
+ BMFace *efa, const MLoopTri *mlt, const float (*poly_normals)[3], const float (*loop_normals)[3], const int base_vert_idx)
{
+ if (BM_elem_flag_test(efa, BM_ELEM_HIDDEN)) {
+ return false;
+ }
+
BMEditMesh *embm = rdata->edit_bmesh;
BMesh *bm = embm->bm;
Mesh *me_cage = embm->mesh_eval_cage;
@@ -1685,19 +1745,9 @@ static void add_overlay_tri_mapped(
const MVert *mvert = me_cage->mvert;
const MEdge *medge = me_cage->medge;
const MLoop *mloop = me_cage->mloop;
-#if 0
- const MPoly *mpoly = me_cage->mpoly;
-#endif
const int *v_origindex = rdata->mapped.v_origindex;
const int *e_origindex = rdata->mapped.e_origindex;
-#if 0
- const int *l_origindex = rdata->mapped.l_origindex;
- const int *p_origindex = rdata->mapped.p_origindex;
-#endif
-
- uchar fflag;
- uchar vflag;
if (elb) {
for (int i = 0; i < 3; ++i) {
@@ -1713,40 +1763,35 @@ static void add_overlay_tri_mapped(
}
}
- if (vbo_pos) {
+ if (vbo_pos_nor) {
for (uint i = 0; i < 3; i++) {
const float *pos = mvert[mloop[mlt->tri[i]].v].co;
- GPU_vertbuf_attr_set(vbo_pos, pos_id, base_vert_idx + i, pos);
+ GPUPackedNormal vnor = GPU_normal_convert_i10_s3(mvert[mloop[mlt->tri[i]].v].no);
+ GPU_vertbuf_attr_set(vbo_pos_nor, pos_id, base_vert_idx + i, pos);
+ GPU_vertbuf_attr_set(vbo_pos_nor, vnor_id, base_vert_idx + i, &vnor);
}
}
- if (vbo_nor) {
- float (*lnors)[3] = rdata->loop_normals;
+ if (vbo_lnor) {
for (uint i = 0; i < 3; i++) {
- const float *nor = (lnors) ? lnors[mlt->tri[i]] : poly_normal;
+ const float *nor = loop_normals ? loop_normals[mlt->tri[i]] : poly_normals[mlt->poly];
GPUPackedNormal lnor = GPU_normal_convert_i10_v3(nor);
- GPU_vertbuf_attr_set(vbo_nor, lnor_id, base_vert_idx + i, &lnor);
- GPUPackedNormal vnor = GPU_normal_convert_i10_s3(mvert[mloop[mlt->tri[i]].v].no);
- GPU_vertbuf_attr_set(vbo_nor, vnor_id, base_vert_idx + i, &vnor);
+ GPU_vertbuf_attr_set(vbo_lnor, lnor_id, base_vert_idx + i, &lnor);
}
}
if (vbo_data) {
- fflag = mesh_render_data_looptri_flag(rdata, efa);
+ EdgeDrawAttr eattr[3] = {{0}}; /* Importantly VFLAG_VERTEX_EXISTS is not set. */
+ uchar fflag = mesh_render_data_looptri_flag(rdata, efa);
for (uint i = 0; i < 3; i++) {
const int i_next = (i + 1) % 3;
const int i_prev = (i + 2) % 3;
const int v_orig = v_origindex[mloop[mlt->tri[i]].v];
if (v_orig != ORIGINDEX_NONE) {
BMVert *v = BM_vert_at_index(bm, v_orig);
- vflag = mesh_render_data_vertex_flag(rdata, v);
- }
- else {
- /* Importantly VFLAG_VERTEX_EXISTS is not set. */
- vflag = 0;
+ eattr[i].v_flag |= mesh_render_data_vertex_flag(rdata, v);
}
/* Opposite edge to the vertex at 'i'. */
- EdgeDrawAttr eattr = {0};
const int e_idx = mloop[mlt->tri[i_next]].e;
const int e_orig = e_origindex[e_idx];
if (e_orig != ORIGINDEX_NONE) {
@@ -1757,41 +1802,50 @@ static void add_overlay_tri_mapped(
((ed->v1 == tri_edge[1]) && (ed->v2 == tri_edge[0])));
if (is_edge_real) {
BMEdge *eed = BM_edge_at_index(bm, e_orig);
- mesh_render_data_edge_flag(rdata, eed, &eattr);
+ mesh_render_data_edge_flag(rdata, eed, &eattr[i]);
+ /* Set vertex selected if both original verts are selected. */
+ if (BM_elem_flag_test(eed->v1, BM_ELEM_SELECT) &&
+ BM_elem_flag_test(eed->v2, BM_ELEM_SELECT))
+ {
+ eattr[i_next].v_flag |= VFLAG_VERTEX_SELECTED;
+ eattr[i_prev].v_flag |= VFLAG_VERTEX_SELECTED;
+ }
}
}
- eattr.v_flag = fflag | vflag;
- GPU_vertbuf_attr_set(vbo_data, data_id, base_vert_idx + i, &eattr);
+ }
+ for (uint i = 0; i < 3; i++) {
+ eattr[i].v_flag |= fflag;
+ GPU_vertbuf_attr_set(vbo_data, data_id, base_vert_idx + i, &eattr[i]);
}
}
+
+ return true;
}
-static void add_overlay_loose_edge(
- MeshRenderData *rdata, GPUVertBuf *vbo_pos, GPUVertBuf *vbo_nor, GPUVertBuf *vbo_data,
+static void add_edit_loose_edge(
+ MeshRenderData *rdata, GPUVertBuf *vbo_pos_nor, GPUVertBuf *vbo_data,
const uint pos_id, const uint vnor_id, const uint data_id,
const BMEdge *eed, const int base_vert_idx)
{
- if (vbo_pos) {
+ if (vbo_pos_nor) {
/* TODO(sybren): deduplicate this and all the other places it's pasted to in this file. */
if (rdata->edit_data && rdata->edit_data->vertexCos) {
for (uint i = 0; i < 2; i++) {
int vidx = BM_elem_index_get((&eed->v1)[i]);
const float *pos = rdata->edit_data->vertexCos[vidx];
- GPU_vertbuf_attr_set(vbo_pos, pos_id, base_vert_idx + i, pos);
+ GPU_vertbuf_attr_set(vbo_pos_nor, pos_id, base_vert_idx + i, pos);
}
}
else {
for (int i = 0; i < 2; i++) {
const float *pos = (&eed->v1)[i]->co;
- GPU_vertbuf_attr_set(vbo_pos, pos_id, base_vert_idx + i, pos);
+ GPU_vertbuf_attr_set(vbo_pos_nor, pos_id, base_vert_idx + i, pos);
}
}
- }
- if (vbo_nor) {
for (int i = 0; i < 2; i++) {
GPUPackedNormal vnor = GPU_normal_convert_i10_v3((&eed->v1)[i]->no);
- GPU_vertbuf_attr_set(vbo_nor, vnor_id, base_vert_idx + i, &vnor);
+ GPU_vertbuf_attr_set(vbo_pos_nor, vnor_id, base_vert_idx + i, &vnor);
}
}
@@ -1804,23 +1858,19 @@ static void add_overlay_loose_edge(
}
}
}
-static void add_overlay_loose_edge_mapped(
- MeshRenderData *rdata, GPUVertBuf *vbo_pos, GPUVertBuf *vbo_nor, GPUVertBuf *vbo_data,
+static void add_edit_loose_edge_mapped(
+ MeshRenderData *rdata, GPUVertBuf *vbo_pos_nor, GPUVertBuf *vbo_data,
const uint pos_id, const uint vnor_id, const uint data_id,
BMEdge *eed, const MVert *mvert, const MEdge *ed, const int base_vert_idx)
{
- if (vbo_pos) {
+ if (vbo_pos_nor) {
/* TODO(sybren): deduplicate this and all the other places it's pasted to in this file. */
for (int i = 0; i < 2; i++) {
const float *pos = mvert[*(&ed->v1 + i)].co;
- GPU_vertbuf_attr_set(vbo_pos, pos_id, base_vert_idx + i, pos);
- }
- }
+ GPU_vertbuf_attr_set(vbo_pos_nor, pos_id, base_vert_idx + i, pos);
- if (vbo_nor) {
- for (int i = 0; i < 2; i++) {
GPUPackedNormal vnor = GPU_normal_convert_i10_s3(mvert[*(&ed->v1 + i)].no);
- GPU_vertbuf_attr_set(vbo_nor, vnor_id, base_vert_idx + i, &vnor);
+ GPU_vertbuf_attr_set(vbo_pos_nor, vnor_id, base_vert_idx + i, &vnor);
}
}
@@ -1835,27 +1885,25 @@ static void add_overlay_loose_edge_mapped(
}
}
-static void add_overlay_loose_vert(
- MeshRenderData *rdata, GPUVertBuf *vbo_pos, GPUVertBuf *vbo_nor, GPUVertBuf *vbo_data,
+static void add_edit_loose_vert(
+ MeshRenderData *rdata, GPUVertBuf *vbo_pos_nor, GPUVertBuf *vbo_data,
const uint pos_id, const uint vnor_id, const uint data_id,
const BMVert *eve, const int base_vert_idx)
{
- if (vbo_pos) {
+ if (vbo_pos_nor) {
/* TODO(sybren): deduplicate this and all the other places it's pasted to in this file. */
if (rdata->edit_data && rdata->edit_data->vertexCos) {
int vidx = BM_elem_index_get(eve);
const float *pos = rdata->edit_data->vertexCos[vidx];
- GPU_vertbuf_attr_set(vbo_pos, pos_id, base_vert_idx, pos);
+ GPU_vertbuf_attr_set(vbo_pos_nor, pos_id, base_vert_idx, pos);
}
else {
const float *pos = eve->co;
- GPU_vertbuf_attr_set(vbo_pos, pos_id, base_vert_idx, pos);
+ GPU_vertbuf_attr_set(vbo_pos_nor, pos_id, base_vert_idx, pos);
}
- }
- if (vbo_nor) {
GPUPackedNormal vnor = GPU_normal_convert_i10_v3(eve->no);
- GPU_vertbuf_attr_set(vbo_nor, vnor_id, base_vert_idx, &vnor);
+ GPU_vertbuf_attr_set(vbo_pos_nor, vnor_id, base_vert_idx, &vnor);
}
if (vbo_data) {
@@ -1864,19 +1912,17 @@ static void add_overlay_loose_vert(
GPU_vertbuf_attr_set(vbo_data, data_id, base_vert_idx, vflag);
}
}
-static void add_overlay_loose_vert_mapped(
- MeshRenderData *rdata, GPUVertBuf *vbo_pos, GPUVertBuf *vbo_nor, GPUVertBuf *vbo_data,
+static void add_edit_loose_vert_mapped(
+ MeshRenderData *rdata, GPUVertBuf *vbo_pos_nor, GPUVertBuf *vbo_data,
const uint pos_id, const uint vnor_id, const uint data_id,
const BMVert *eve, const MVert *mv, const int base_vert_idx)
{
- if (vbo_pos) {
+ if (vbo_pos_nor) {
const float *pos = mv->co;
- GPU_vertbuf_attr_set(vbo_pos, pos_id, base_vert_idx, pos);
- }
+ GPU_vertbuf_attr_set(vbo_pos_nor, pos_id, base_vert_idx, pos);
- if (vbo_nor) {
GPUPackedNormal vnor = GPU_normal_convert_i10_s3(mv->no);
- GPU_vertbuf_attr_set(vbo_nor, vnor_id, base_vert_idx, &vnor);
+ GPU_vertbuf_attr_set(vbo_pos_nor, vnor_id, base_vert_idx, &vnor);
}
if (vbo_data) {
@@ -1886,6 +1932,84 @@ static void add_overlay_loose_vert_mapped(
}
}
+static bool add_edit_facedot(
+ MeshRenderData *rdata, GPUVertBuf *vbo,
+ const uint fdot_pos_id, const uint fdot_nor_flag_id,
+ const int poly, const int base_vert_idx)
+{
+ BLI_assert(rdata->types & (MR_DATATYPE_VERT | MR_DATATYPE_LOOP | MR_DATATYPE_POLY));
+ float pnor[3], center[3];
+ bool selected;
+ if (rdata->edit_bmesh) {
+ const BMFace *efa = BM_face_at_index(rdata->edit_bmesh->bm, poly);
+ if (BM_elem_flag_test(efa, BM_ELEM_HIDDEN)) {
+ return false;
+ }
+ if (rdata->edit_data && rdata->edit_data->vertexCos) {
+ copy_v3_v3(center, rdata->edit_data->polyCos[poly]);
+ copy_v3_v3(pnor, rdata->edit_data->polyNos[poly]);
+ }
+ else {
+ BM_face_calc_center_median(efa, center);
+ copy_v3_v3(pnor, efa->no);
+ }
+ selected = (BM_elem_flag_test(efa, BM_ELEM_SELECT) != 0) ? true : false;
+ }
+ else {
+ MVert *mvert = rdata->mvert;
+ const MPoly *mpoly = rdata->mpoly + poly;
+ const MLoop *mloop = rdata->mloop + mpoly->loopstart;
+
+ BKE_mesh_calc_poly_center(mpoly, mloop, mvert, center);
+ BKE_mesh_calc_poly_normal(mpoly, mloop, mvert, pnor);
+
+ selected = false; /* No selection if not in edit mode */
+ }
+
+ GPUPackedNormal nor = GPU_normal_convert_i10_v3(pnor);
+ nor.w = (selected) ? 1 : 0;
+ GPU_vertbuf_attr_set(vbo, fdot_nor_flag_id, base_vert_idx, &nor);
+ GPU_vertbuf_attr_set(vbo, fdot_pos_id, base_vert_idx, center);
+
+ return true;
+}
+static bool add_edit_facedot_mapped(
+ MeshRenderData *rdata, GPUVertBuf *vbo,
+ const uint fdot_pos_id, const uint fdot_nor_flag_id,
+ const int poly, const int base_vert_idx)
+{
+ BLI_assert(rdata->types & (MR_DATATYPE_VERT | MR_DATATYPE_LOOP | MR_DATATYPE_POLY));
+ float pnor[3], center[3];
+ const int *p_origindex = rdata->mapped.p_origindex;
+ const int p_orig = p_origindex[poly];
+ if (p_orig == ORIGINDEX_NONE) {
+ return false;
+ }
+ BMEditMesh *em = rdata->edit_bmesh;
+ const BMFace *efa = BM_face_at_index(rdata->edit_bmesh->bm, p_orig);
+ if (BM_elem_flag_test(efa, BM_ELEM_HIDDEN)) {
+ return false;
+ }
+
+ Mesh *me_cage = em->mesh_eval_cage;
+ const MVert *mvert = me_cage->mvert;
+ const MLoop *mloop = me_cage->mloop;
+ const MPoly *mpoly = me_cage->mpoly;
+
+ const MPoly *mp = mpoly + poly;
+ const MLoop *ml = mloop + mp->loopstart;
+
+ BKE_mesh_calc_poly_center(mp, ml, mvert, center);
+ BKE_mesh_calc_poly_normal(mp, ml, mvert, pnor);
+
+ GPUPackedNormal nor = GPU_normal_convert_i10_v3(pnor);
+ nor.w = (BM_elem_flag_test(efa, BM_ELEM_SELECT) != 0) ? 1 : 0;
+ GPU_vertbuf_attr_set(vbo, fdot_nor_flag_id, base_vert_idx, &nor);
+ GPU_vertbuf_attr_set(vbo, fdot_pos_id, base_vert_idx, center);
+
+ return true;
+}
+
/** \} */
/* ---------------------------------------------------------------------- */
@@ -1894,7 +2018,7 @@ static void add_overlay_loose_vert_mapped(
* \{ */
/** Reset the selection structure, deallocating heap memory as appropriate. */
-void DRW_mesh_weight_state_clear(struct DRW_MeshWeightState *wstate)
+static void drw_mesh_weight_state_clear(struct DRW_MeshWeightState *wstate)
{
MEM_SAFE_FREE(wstate->defgroup_sel);
@@ -1904,7 +2028,8 @@ void DRW_mesh_weight_state_clear(struct DRW_MeshWeightState *wstate)
}
/** Copy selection data from one structure to another, including heap memory. */
-void DRW_mesh_weight_state_copy(struct DRW_MeshWeightState *wstate_dst, const struct DRW_MeshWeightState *wstate_src)
+static void drw_mesh_weight_state_copy(
+ struct DRW_MeshWeightState *wstate_dst, const struct DRW_MeshWeightState *wstate_src)
{
MEM_SAFE_FREE(wstate_dst->defgroup_sel);
@@ -1916,7 +2041,7 @@ void DRW_mesh_weight_state_copy(struct DRW_MeshWeightState *wstate_dst, const st
}
/** Compare two selection structures. */
-bool DRW_mesh_weight_state_compare(const struct DRW_MeshWeightState *a, const struct DRW_MeshWeightState *b)
+static bool drw_mesh_weight_state_compare(const struct DRW_MeshWeightState *a, const struct DRW_MeshWeightState *b)
{
return a->defgroup_active == b->defgroup_active &&
a->defgroup_len == b->defgroup_len &&
@@ -1928,6 +2053,39 @@ bool DRW_mesh_weight_state_compare(const struct DRW_MeshWeightState *a, const st
memcmp(a->defgroup_sel, b->defgroup_sel, a->defgroup_len * sizeof(bool)) == 0));
}
+static void drw_mesh_weight_state_extract(
+ Object *ob, Mesh *me, ToolSettings *ts, bool paint_mode,
+ struct DRW_MeshWeightState *wstate)
+{
+ /* Extract complete vertex weight group selection state and mode flags. */
+ memset(wstate, 0, sizeof(*wstate));
+
+ wstate->defgroup_active = ob->actdef - 1;
+ wstate->defgroup_len = BLI_listbase_count(&ob->defbase);
+
+ wstate->alert_mode = ts->weightuser;
+
+ if (paint_mode && ts->multipaint) {
+ /* Multipaint needs to know all selected bones, not just the active group.
+ * This is actually a relatively expensive operation, but caching would be difficult. */
+ wstate->defgroup_sel = BKE_object_defgroup_selected_get(ob, wstate->defgroup_len, &wstate->defgroup_sel_count);
+
+ if (wstate->defgroup_sel_count > 1) {
+ wstate->flags |= DRW_MESH_WEIGHT_STATE_MULTIPAINT | (ts->auto_normalize ? DRW_MESH_WEIGHT_STATE_AUTO_NORMALIZE : 0);
+
+ if (me->editflag & ME_EDIT_MIRROR_X) {
+ BKE_object_defgroup_mirror_selection(
+ ob, wstate->defgroup_len, wstate->defgroup_sel, wstate->defgroup_sel, &wstate->defgroup_sel_count);
+ }
+ }
+ /* With only one selected bone Multipaint reverts to regular mode. */
+ else {
+ wstate->defgroup_sel_count = 0;
+ MEM_SAFE_FREE(wstate->defgroup_sel);
+ }
+ }
+}
+
/** \} */
/* ---------------------------------------------------------------------- */
@@ -1936,19 +2094,89 @@ bool DRW_mesh_weight_state_compare(const struct DRW_MeshWeightState *a, const st
* \{ */
typedef struct MeshBatchCache {
- GPUVertBuf *pos_in_order;
+ /* In order buffers: All verts only specified once.
+ * To be used with a GPUIndexBuf. */
+ struct {
+ /* Vertex data. */
+ GPUVertBuf *pos_nor;
+ GPUVertBuf *weights;
+ /* Loop data. */
+ GPUVertBuf *loop_pos_nor;
+ GPUVertBuf *loop_uv_tan;
+ GPUVertBuf *loop_vcol;
+ } ordered;
+
+ /* Tesselated: (all verts specified for each triangles).
+ * Indices does not match the CPU data structure's. */
+ struct {
+ GPUVertBuf *pos_nor;
+
+ GPUVertBuf *wireframe_data;
+ } tess;
+
+ /* Edit Mesh Data:
+ * Data is also tesselated because of barycentric wireframe rendering. */
+ struct {
+ GPUVertBuf *pos_nor;
+ GPUVertBuf *pos_nor_ledges;
+ GPUVertBuf *pos_nor_lverts;
+ GPUVertBuf *pos_nor_data_facedots;
+ GPUVertBuf *data;
+ GPUVertBuf *data_ledges;
+ GPUVertBuf *data_lverts;
+ GPUVertBuf *lnor;
+ } edit;
+
+ /* Index Buffers:
+ * Only need to be updated when topology changes. */
+ struct {
+ /* Indices to verts. */
+ GPUIndexBuf *surf_tris;
+ /* Indices to vloops. */
+ GPUIndexBuf *loops_tris;
+ GPUIndexBuf *loops_lines;
+ /* Contains indices to unique edit vertices to not
+ * draw the same vert multiple times (because of tesselation). */
+ GPUIndexBuf *edit_verts_points;
+ } ibo;
+
+ struct {
+ /* Surfaces / Render */
+ GPUBatch *surface;
+ GPUBatch *surface_weights;
+ /* Edit mode */
+ GPUBatch *edit_triangles;
+ GPUBatch *edit_vertices;
+ GPUBatch *edit_loose_edges;
+ GPUBatch *edit_loose_verts;
+ GPUBatch *edit_triangles_nor;
+ GPUBatch *edit_triangles_lnor;
+ GPUBatch *edit_loose_edges_nor;
+ GPUBatch *edit_facedots;
+ /* Common display / Other */
+ GPUBatch *all_verts;
+ GPUBatch *wire_loops; /* Loops around faces. */
+ GPUBatch *wire_triangles; /* Triangles for object mode wireframe. */
+ } batch;
+
+ GPUIndexBuf **surf_per_mat_tris;
+ GPUBatch **surf_per_mat;
+
+ /* OLD BATCH METHOD, thoses needs to be ported and added in the structs above. */
+
+ /* Indices buffers. */
GPUIndexBuf *edges_in_order;
GPUIndexBuf *edges_adjacency; /* Store edges with adjacent vertices. */
GPUIndexBuf *triangles_in_order;
GPUIndexBuf *ledges_in_order;
- GPUTexture *pos_in_order_tx; /* Depending on pos_in_order */
-
- GPUBatch *all_verts;
GPUBatch *all_edges;
GPUBatch *all_triangles;
GPUVertBuf *pos_with_normals;
+ GPUVertBuf *pos_with_normals_visible_only;
+ GPUVertBuf *pos_with_normals_edit;
+ GPUVertBuf *pos_with_normals_visible_only_edit;
GPUVertBuf *tri_aligned_uv; /* Active UV layer (mloopuv) */
/**
@@ -1970,7 +2198,7 @@ typedef struct MeshBatchCache {
GPUBatch *triangles_with_select_id;
uint triangles_with_select_id_offset;
- GPUBatch *facedot_with_select_id; /* shares vbo with 'overlay_facedots' */
+ GPUBatch *facedot_with_select_id; /* shares vbo with 'edit_facedots' */
GPUBatch *edges_with_select_id;
GPUBatch *verts_with_select_id;
@@ -1983,45 +2211,11 @@ typedef struct MeshBatchCache {
GPUBatch *edge_detection;
- GPUVertBuf *edges_face_overlay;
- GPUTexture *edges_face_overlay_tx;
- int edges_face_overlay_tri_count; /* Number of tri in edges_face_overlay(_adj)_tx */
-
- /* Maybe have shaded_triangles_data split into pos_nor and uv_tangent
- * to minimize data transfer for skinned mesh. */
- GPUVertFormat shaded_triangles_format;
- GPUVertBuf *shaded_triangles_data;
- GPUIndexBuf **shaded_triangles_in_order;
- GPUBatch **shaded_triangles;
-
/* Texture Paint.*/
/* per-texture batch */
GPUBatch **texpaint_triangles;
GPUBatch *texpaint_triangles_single;
- /* Edit Cage Mesh buffers */
- GPUVertBuf *ed_tri_pos;
- GPUVertBuf *ed_tri_nor; /* LoopNor, VertNor */
- GPUVertBuf *ed_tri_data;
- GPUTexture *ed_tri_data_tx;
- GPUIndexBuf *ed_tri_verts;
-
- GPUVertBuf *ed_ledge_pos;
- GPUVertBuf *ed_ledge_nor; /* VertNor */
- GPUVertBuf *ed_ledge_data;
-
- GPUVertBuf *ed_lvert_pos;
- GPUVertBuf *ed_lvert_nor; /* VertNor */
- GPUVertBuf *ed_lvert_data;
-
- GPUBatch *overlay_triangles;
- GPUBatch *overlay_triangles_nor; /* GPU_PRIM_POINTS */
- GPUBatch *overlay_triangles_lnor; /* GPU_PRIM_POINTS */
- GPUBatch *overlay_loose_edges;
- GPUBatch *overlay_loose_edges_nor; /* GPU_PRIM_POINTS */
- GPUBatch *overlay_loose_verts;
- GPUBatch *overlay_facedots;
-
GPUBatch *overlay_weight_faces;
GPUBatch *overlay_weight_verts;
GPUBatch *overlay_paint_edges;
@@ -2064,6 +2258,11 @@ typedef struct MeshBatchCache {
struct DRW_MeshWeightState weight_state;
+ uchar cd_vused[CD_NUMTYPES];
+ uchar cd_vneeded[CD_NUMTYPES];
+ ushort cd_lused[CD_NUMTYPES];
+ ushort cd_lneeded[CD_NUMTYPES];
+
/* XXX, only keep for as long as sculpt mode uses shaded drawing. */
bool is_sculpt_points_tag;
@@ -2081,9 +2280,8 @@ static bool mesh_batch_cache_valid(Mesh *me)
return false;
}
- /* XXX find another place for this */
if (cache->mat_len != mesh_render_mat_len_get(me)) {
- cache->is_maybe_dirty = true;
+ return false;
}
if (cache->is_editmode != (me->edit_btmesh != NULL)) {
@@ -2135,11 +2333,19 @@ static void mesh_batch_cache_init(Mesh *me)
}
cache->mat_len = mesh_render_mat_len_get(me);
+ cache->surf_per_mat_tris = MEM_callocN(sizeof(*cache->surf_per_mat_tris) * cache->mat_len, __func__);
+ cache->surf_per_mat = MEM_callocN(sizeof(*cache->surf_per_mat) * cache->mat_len, __func__);
+
+ /* TODO Might be wiser to alloc in one chunck. */
+ for (int i = 0; i < cache->mat_len; ++i) {
+ cache->surf_per_mat_tris[i] = MEM_callocN(sizeof(GPUIndexBuf), "GPUIndexBuf");
+ cache->surf_per_mat[i] = MEM_callocN(sizeof(GPUBatch), "GPUBatch");
+ }
cache->is_maybe_dirty = false;
cache->is_dirty = false;
- DRW_mesh_weight_state_clear(&cache->weight_state);
+ drw_mesh_weight_state_clear(&cache->weight_state);
}
static MeshBatchCache *mesh_batch_cache_get(Mesh *me)
@@ -2153,38 +2359,41 @@ static MeshBatchCache *mesh_batch_cache_get(Mesh *me)
static void mesh_batch_cache_check_vertex_group(MeshBatchCache *cache, const struct DRW_MeshWeightState *wstate)
{
- if (!DRW_mesh_weight_state_compare(&cache->weight_state, wstate)) {
- GPU_BATCH_DISCARD_SAFE(cache->triangles_with_weights);
+ if (!drw_mesh_weight_state_compare(&cache->weight_state, wstate)) {
+ GPU_BATCH_CLEAR_SAFE(cache->batch.surface_weights);
+ GPU_VERTBUF_DISCARD_SAFE(cache->ordered.weights);
- DRW_mesh_weight_state_clear(&cache->weight_state);
+ drw_mesh_weight_state_clear(&cache->weight_state);
}
}
static void mesh_batch_cache_discard_shaded_tri(MeshBatchCache *cache)
{
- GPU_VERTBUF_DISCARD_SAFE(cache->shaded_triangles_data);
- if (cache->shaded_triangles_in_order) {
- for (int i = 0; i < cache->mat_len; i++) {
- GPU_INDEXBUF_DISCARD_SAFE(cache->shaded_triangles_in_order[i]);
- }
- }
- if (cache->shaded_triangles) {
+ GPU_VERTBUF_DISCARD_SAFE(cache->ordered.loop_pos_nor);
+ GPU_VERTBUF_DISCARD_SAFE(cache->ordered.loop_uv_tan);
+ GPU_VERTBUF_DISCARD_SAFE(cache->ordered.loop_vcol);
+ /* TODO */
+ // GPU_VERTBUF_DISCARD_SAFE(cache->ordered.loop_orco);
+
+ if (cache->surf_per_mat_tris) {
for (int i = 0; i < cache->mat_len; i++) {
- GPU_BATCH_DISCARD_SAFE(cache->shaded_triangles[i]);
+ GPU_INDEXBUF_DISCARD_SAFE(cache->surf_per_mat_tris[i]);
}
}
- if (cache->texpaint_triangles) {
+ MEM_SAFE_FREE(cache->surf_per_mat_tris);
+ if (cache->surf_per_mat) {
for (int i = 0; i < cache->mat_len; i++) {
- /* They use shaded_triangles_in_order */
- GPU_BATCH_DISCARD_SAFE(cache->texpaint_triangles[i]);
+ GPU_BATCH_DISCARD_SAFE(cache->surf_per_mat[i]);
}
}
- MEM_SAFE_FREE(cache->shaded_triangles_in_order);
- MEM_SAFE_FREE(cache->shaded_triangles);
+ MEM_SAFE_FREE(cache->surf_per_mat);
+
MEM_SAFE_FREE(cache->texpaint_triangles);
MEM_SAFE_FREE(cache->auto_layer_names);
MEM_SAFE_FREE(cache->auto_layer_is_srgb);
+
+ cache->mat_len = 0;
}
static void mesh_batch_cache_discard_uvedit(MeshBatchCache *cache)
@@ -2241,26 +2450,34 @@ void DRW_mesh_batch_cache_dirty_tag(Mesh *me, int mode)
cache->is_maybe_dirty = true;
break;
case BKE_MESH_BATCH_DIRTY_SELECT:
- GPU_VERTBUF_DISCARD_SAFE(cache->ed_tri_data);
- GPU_VERTBUF_DISCARD_SAFE(cache->ed_ledge_data);
- GPU_VERTBUF_DISCARD_SAFE(cache->ed_lvert_data);
- GPU_VERTBUF_DISCARD_SAFE(cache->ed_fcenter_pos_with_nor_and_sel); /* Contains select flag */
+ GPU_VERTBUF_DISCARD_SAFE(cache->edit.data);
+ GPU_VERTBUF_DISCARD_SAFE(cache->edit.data_ledges);
+ GPU_VERTBUF_DISCARD_SAFE(cache->edit.data_lverts);
+ GPU_VERTBUF_DISCARD_SAFE(cache->edit.pos_nor_data_facedots);
+ GPU_BATCH_DISCARD_SAFE(cache->batch.edit_triangles);
+ GPU_BATCH_DISCARD_SAFE(cache->batch.edit_vertices);
+ GPU_BATCH_DISCARD_SAFE(cache->batch.edit_loose_verts);
+ GPU_BATCH_DISCARD_SAFE(cache->batch.edit_loose_edges);
+ GPU_BATCH_DISCARD_SAFE(cache->batch.edit_facedots);
GPU_VERTBUF_DISCARD_SAFE(cache->ed_edge_pos);
GPU_VERTBUF_DISCARD_SAFE(cache->ed_vert_pos);
- GPU_INDEXBUF_DISCARD_SAFE(cache->ed_tri_verts);
- DRW_TEXTURE_FREE_SAFE(cache->ed_tri_data_tx);
-
- GPU_BATCH_DISCARD_SAFE(cache->overlay_triangles);
- GPU_BATCH_DISCARD_SAFE(cache->overlay_loose_verts);
- GPU_BATCH_DISCARD_SAFE(cache->overlay_loose_edges);
- GPU_BATCH_DISCARD_SAFE(cache->overlay_facedots);
- GPU_BATCH_DISCARD_SAFE(cache->overlay_triangles_nor);
- GPU_BATCH_DISCARD_SAFE(cache->overlay_triangles_lnor);
- GPU_BATCH_DISCARD_SAFE(cache->overlay_loose_edges_nor);
/* Edit mode selection. */
GPU_BATCH_DISCARD_SAFE(cache->facedot_with_select_id);
GPU_BATCH_DISCARD_SAFE(cache->edges_with_select_id);
GPU_BATCH_DISCARD_SAFE(cache->verts_with_select_id);
+ /* Paint mode selection */
+ /* TODO only do that in paint mode. */
+ GPU_VERTBUF_DISCARD_SAFE(cache->ordered.loop_pos_nor);
+ GPU_BATCH_DISCARD_SAFE(cache->batch.surface);
+ GPU_BATCH_DISCARD_SAFE(cache->batch.wire_loops);
+ if (cache->surf_per_mat) {
+ for (int i = 0; i < cache->mat_len; i++) {
+ GPU_BATCH_DISCARD_SAFE(cache->surf_per_mat[i]);
+ }
+ }
+ GPU_BATCH_DISCARD_SAFE(cache->overlay_paint_edges);
+ GPU_BATCH_DISCARD_SAFE(cache->overlay_weight_faces);
+ GPU_BATCH_DISCARD_SAFE(cache->overlay_weight_verts);
/* Because visible UVs depends on edit mode selection, discard everything. */
mesh_batch_cache_discard_uvedit(cache);
break;
@@ -2298,7 +2515,9 @@ static void mesh_batch_cache_clear_selective(Mesh *me, GPUVertBuf *vert)
BLI_assert(vert != NULL);
- if (cache->pos_with_normals == vert) {
+ if (ELEM(vert, cache->pos_with_normals, cache->pos_with_normals_visible_only,
+ cache->pos_with_normals_edit, cache->pos_with_normals_visible_only_edit))
+ {
GPU_BATCH_DISCARD_SAFE(cache->triangles_with_normals);
GPU_BATCH_DISCARD_SAFE(cache->triangles_with_weights);
GPU_BATCH_DISCARD_SAFE(cache->triangles_with_vert_colors);
@@ -2306,17 +2525,17 @@ static void mesh_batch_cache_clear_selective(Mesh *me, GPUVertBuf *vert)
GPU_BATCH_DISCARD_SAFE(cache->triangles_with_select_mask);
GPU_BATCH_DISCARD_SAFE(cache->points_with_normals);
GPU_BATCH_DISCARD_SAFE(cache->ledges_with_normals);
- if (cache->shaded_triangles) {
- for (int i = 0; i < cache->mat_len; i++) {
- GPU_BATCH_DISCARD_SAFE(cache->shaded_triangles[i]);
- }
- }
- MEM_SAFE_FREE(cache->shaded_triangles);
- if (cache->texpaint_triangles) {
- for (int i = 0; i < cache->mat_len; i++) {
- GPU_BATCH_DISCARD_SAFE(cache->texpaint_triangles[i]);
- }
- }
+ // if (cache->shaded_triangles) {
+ // for (int i = 0; i < cache->mat_len; i++) {
+ // GPU_BATCH_DISCARD_SAFE(cache->shaded_triangles[i]);
+ // }
+ // }
+ // MEM_SAFE_FREE(cache->shaded_triangles);
+ // if (cache->texpaint_triangles) {
+ // for (int i = 0; i < cache->mat_len; i++) {
+ // GPU_BATCH_DISCARD_SAFE(cache->texpaint_triangles[i]);
+ // }
+ // }
MEM_SAFE_FREE(cache->texpaint_triangles);
GPU_BATCH_DISCARD_SAFE(cache->texpaint_triangles_single);
}
@@ -2334,43 +2553,45 @@ static void mesh_batch_cache_clear(Mesh *me)
return;
}
- GPU_BATCH_DISCARD_SAFE(cache->all_verts);
+ for (int i = 0; i < sizeof(cache->ordered) / sizeof(void *); ++i) {
+ GPUVertBuf **vbo = (GPUVertBuf **)&cache->ordered;
+ GPU_VERTBUF_DISCARD_SAFE(vbo[i]);
+ }
+ for (int i = 0; i < sizeof(cache->tess) / sizeof(void *); ++i) {
+ GPUVertBuf **vbo = (GPUVertBuf **)&cache->tess;
+ GPU_VERTBUF_DISCARD_SAFE(vbo[i]);
+ }
+ for (int i = 0; i < sizeof(cache->edit) / sizeof(void *); ++i) {
+ GPUVertBuf **vbo = (GPUVertBuf **)&cache->edit;
+ GPU_VERTBUF_DISCARD_SAFE(vbo[i]);
+ }
+ for (int i = 0; i < sizeof(cache->ibo) / sizeof(void *); ++i) {
+ GPUIndexBuf **ibo = (GPUIndexBuf **)&cache->ibo;
+ GPU_INDEXBUF_DISCARD_SAFE(ibo[i]);
+ }
+ for (int i = 0; i < sizeof(cache->batch) / sizeof(void *); ++i) {
+ GPUBatch **batch = (GPUBatch **)&cache->batch;
+ GPU_BATCH_DISCARD_SAFE(batch[i]);
+ }
+
GPU_BATCH_DISCARD_SAFE(cache->all_edges);
GPU_BATCH_DISCARD_SAFE(cache->all_triangles);
- GPU_VERTBUF_DISCARD_SAFE(cache->pos_in_order);
- DRW_TEXTURE_FREE_SAFE(cache->pos_in_order_tx);
GPU_INDEXBUF_DISCARD_SAFE(cache->edges_in_order);
GPU_INDEXBUF_DISCARD_SAFE(cache->triangles_in_order);
GPU_INDEXBUF_DISCARD_SAFE(cache->ledges_in_order);
- GPU_VERTBUF_DISCARD_SAFE(cache->ed_tri_pos);
- GPU_VERTBUF_DISCARD_SAFE(cache->ed_tri_nor);
- GPU_VERTBUF_DISCARD_SAFE(cache->ed_tri_data);
- GPU_VERTBUF_DISCARD_SAFE(cache->ed_ledge_pos);
- GPU_VERTBUF_DISCARD_SAFE(cache->ed_ledge_nor);
- GPU_VERTBUF_DISCARD_SAFE(cache->ed_ledge_data);
- GPU_VERTBUF_DISCARD_SAFE(cache->ed_lvert_pos);
- GPU_VERTBUF_DISCARD_SAFE(cache->ed_lvert_nor);
- GPU_VERTBUF_DISCARD_SAFE(cache->ed_lvert_data);
- GPU_INDEXBUF_DISCARD_SAFE(cache->ed_tri_verts);
- GPU_BATCH_DISCARD_SAFE(cache->overlay_triangles);
- GPU_BATCH_DISCARD_SAFE(cache->overlay_triangles_nor);
- GPU_BATCH_DISCARD_SAFE(cache->overlay_triangles_lnor);
- GPU_BATCH_DISCARD_SAFE(cache->overlay_loose_verts);
- GPU_BATCH_DISCARD_SAFE(cache->overlay_loose_edges);
- GPU_BATCH_DISCARD_SAFE(cache->overlay_loose_edges_nor);
- DRW_TEXTURE_FREE_SAFE(cache->ed_tri_data_tx);
-
GPU_BATCH_DISCARD_SAFE(cache->overlay_weight_faces);
GPU_BATCH_DISCARD_SAFE(cache->overlay_weight_verts);
GPU_BATCH_DISCARD_SAFE(cache->overlay_paint_edges);
- GPU_BATCH_DISCARD_SAFE(cache->overlay_facedots);
GPU_BATCH_DISCARD_SAFE(cache->triangles_with_normals);
GPU_BATCH_DISCARD_SAFE(cache->points_with_normals);
GPU_BATCH_DISCARD_SAFE(cache->ledges_with_normals);
GPU_VERTBUF_DISCARD_SAFE(cache->pos_with_normals);
+ GPU_VERTBUF_DISCARD_SAFE(cache->pos_with_normals_visible_only);
+ GPU_VERTBUF_DISCARD_SAFE(cache->pos_with_normals_edit);
+ GPU_VERTBUF_DISCARD_SAFE(cache->pos_with_normals_visible_only_edit);
GPU_BATCH_DISCARD_SAFE(cache->triangles_with_weights);
GPU_BATCH_DISCARD_SAFE(cache->triangles_with_vert_colors);
GPU_VERTBUF_DISCARD_SAFE(cache->tri_aligned_uv);
@@ -2388,9 +2609,6 @@ static void mesh_batch_cache_clear(Mesh *me)
GPU_INDEXBUF_DISCARD_SAFE(cache->edges_adjacency);
GPU_BATCH_DISCARD_SAFE(cache->edge_detection);
- GPU_VERTBUF_DISCARD_SAFE(cache->edges_face_overlay);
- DRW_TEXTURE_FREE_SAFE(cache->edges_face_overlay_tx);
-
mesh_batch_cache_discard_shaded_tri(cache);
mesh_batch_cache_discard_uvedit(cache);
@@ -2402,9 +2620,7 @@ static void mesh_batch_cache_clear(Mesh *me)
}
MEM_SAFE_FREE(cache->texpaint_triangles);
- GPU_BATCH_DISCARD_SAFE(cache->texpaint_triangles_single);
-
- DRW_mesh_weight_state_clear(&cache->weight_state);
+ drw_mesh_weight_state_clear(&cache->weight_state);
}
void DRW_mesh_batch_cache_free(Mesh *me)
@@ -2415,408 +2631,164 @@ void DRW_mesh_batch_cache_free(Mesh *me)
/* GPUBatch cache usage. */
-static GPUVertBuf *mesh_batch_cache_get_tri_shading_data(MeshRenderData *rdata, MeshBatchCache *cache)
+static void mesh_create_pos_and_nor_tess(MeshRenderData *rdata, GPUVertBuf *vbo, bool use_hide)
{
- BLI_assert(rdata->types & (MR_DATATYPE_VERT | MR_DATATYPE_LOOPTRI | MR_DATATYPE_LOOP | MR_DATATYPE_POLY));
-
- if (cache->shaded_triangles_data == NULL) {
- const uint uv_len = rdata->cd.layers.uv_len;
- const uint tangent_len = rdata->cd.layers.tangent_len;
- const uint vcol_len = rdata->cd.layers.vcol_len;
- const uint layers_combined_len = uv_len + vcol_len + tangent_len;
- cache->auto_layer_len = 0;
-
- if (layers_combined_len == 0) {
- return NULL;
- }
-
- GPUVertFormat *format = &cache->shaded_triangles_format;
-
- GPU_vertformat_clear(format);
-
- /* initialize vertex format */
- uint *layers_combined_id = BLI_array_alloca(layers_combined_id, layers_combined_len);
- uint *uv_id = layers_combined_id;
- uint *tangent_id = uv_id + uv_len;
- uint *vcol_id = tangent_id + tangent_len;
-
- /* Not needed, just for sanity. */
- if (uv_len == 0) { uv_id = NULL; }
- if (tangent_len == 0) { tangent_id = NULL; }
- if (vcol_len == 0) { vcol_id = NULL; }
-
- /* Count number of auto layer and allocate big enough name buffer. */
- uint auto_names_len = 0;
- uint auto_ofs = 0;
- uint auto_id = 0;
- for (uint i = 0; i < uv_len; i++) {
- const char *attrib_name = mesh_render_data_uv_auto_layer_uuid_get(rdata, i);
- auto_names_len += strlen(attrib_name) + 2; /* include null terminator and b prefix. */
- cache->auto_layer_len++;
- }
- for (uint i = 0; i < vcol_len; i++) {
- if (rdata->cd.layers.auto_vcol[i]) {
- const char *attrib_name = mesh_render_data_vcol_auto_layer_uuid_get(rdata, i);
- auto_names_len += strlen(attrib_name) + 2; /* include null terminator and b prefix. */
- cache->auto_layer_len++;
- }
- }
- auto_names_len += 1; /* add an ultimate '\0' terminator */
- cache->auto_layer_names = MEM_callocN(auto_names_len * sizeof(char), "Auto layer name buf");
- cache->auto_layer_is_srgb = MEM_mallocN(cache->auto_layer_len * sizeof(int), "Auto layer value buf");
-
-#define USE_COMP_MESH_DATA
-
- for (uint i = 0; i < uv_len; i++) {
- /* UV */
- const char *attrib_name = mesh_render_data_uv_layer_uuid_get(rdata, i);
-#if defined(USE_COMP_MESH_DATA) && 0 /* these are clamped. Maybe use them as an option in the future */
- uv_id[i] = GPU_vertformat_attr_add(format, attrib_name, GPU_COMP_I16, 2, GPU_FETCH_INT_TO_FLOAT_UNIT);
-#else
- uv_id[i] = GPU_vertformat_attr_add(format, attrib_name, GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
-#endif
-
- /* Auto Name */
- attrib_name = mesh_render_data_uv_auto_layer_uuid_get(rdata, i);
- GPU_vertformat_alias_add(format, attrib_name);
-
- /* +1 include null terminator. */
- auto_ofs += 1 + BLI_snprintf_rlen(
- cache->auto_layer_names + auto_ofs, auto_names_len - auto_ofs, "b%s", attrib_name);
- cache->auto_layer_is_srgb[auto_id++] = 0; /* tag as not srgb */
-
- if (i == rdata->cd.layers.uv_active) {
- GPU_vertformat_alias_add(format, "u");
- }
- }
-
- for (uint i = 0; i < tangent_len; i++) {
- const char *attrib_name = mesh_render_data_tangent_layer_uuid_get(rdata, i);
-#ifdef USE_COMP_MESH_DATA
- /* Tangents need more precision than 10_10_10 */
- tangent_id[i] = GPU_vertformat_attr_add(format, attrib_name, GPU_COMP_I16, 4, GPU_FETCH_INT_TO_FLOAT_UNIT);
-#else
- tangent_id[i] = GPU_vertformat_attr_add(format, attrib_name, GPU_COMP_F32, 4, GPU_FETCH_FLOAT);
-#endif
+ static GPUVertFormat format = { 0 };
+ static struct { uint pos, nor; } attr_id;
+ if (format.attr_len == 0) {
+ attr_id.pos = GPU_vertformat_attr_add(&format, "pos", GPU_COMP_F32, 3, GPU_FETCH_FLOAT);
+ attr_id.nor = GPU_vertformat_attr_add(&format, "nor", GPU_COMP_I10, 3, GPU_FETCH_INT_TO_FLOAT_UNIT);
+ GPU_vertformat_triple_load(&format);
+ }
- if (i == rdata->cd.layers.tangent_active) {
- GPU_vertformat_alias_add(format, "t");
- }
- }
+ GPU_vertbuf_init_with_format(vbo, &format);
- for (uint i = 0; i < vcol_len; i++) {
- const char *attrib_name = mesh_render_data_vcol_layer_uuid_get(rdata, i);
- vcol_id[i] = GPU_vertformat_attr_add(format, attrib_name, GPU_COMP_U8, 3, GPU_FETCH_INT_TO_FLOAT_UNIT);
+ const int tri_len = mesh_render_data_looptri_len_get_maybe_mapped(rdata);
+ const int vbo_len_capacity = tri_len * 3;
+ int vbo_len_used = 0;
+ GPU_vertbuf_data_alloc(vbo, vbo_len_capacity);
- /* Auto layer */
- if (rdata->cd.layers.auto_vcol[i]) {
- attrib_name = mesh_render_data_vcol_auto_layer_uuid_get(rdata, i);
+ GPUVertBufRaw pos_step, nor_step;
+ GPU_vertbuf_attr_get_raw_data(vbo, attr_id.pos, &pos_step);
+ GPU_vertbuf_attr_get_raw_data(vbo, attr_id.nor, &nor_step);
- GPU_vertformat_alias_add(format, attrib_name);
+ if (rdata->mapped.use == false) {
+ float (*lnors)[3] = rdata->loop_normals;
+ if (rdata->edit_bmesh) {
+ GPUPackedNormal *pnors_pack, *vnors_pack;
- /* +1 include null terminator. */
- auto_ofs += 1 + BLI_snprintf_rlen(
- cache->auto_layer_names + auto_ofs, auto_names_len - auto_ofs, "b%s", attrib_name);
- cache->auto_layer_is_srgb[auto_id++] = 1; /* tag as srgb */
- }
+ if (lnors == NULL) {
+ mesh_render_data_ensure_poly_normals_pack(rdata);
+ mesh_render_data_ensure_vert_normals_pack(rdata);
- if (i == rdata->cd.layers.vcol_active) {
- GPU_vertformat_alias_add(format, "c");
+ pnors_pack = rdata->poly_normals_pack;
+ vnors_pack = rdata->vert_normals_pack;
}
- }
-
- const uint tri_len = mesh_render_data_looptri_len_get(rdata);
- GPUVertBuf *vbo = cache->shaded_triangles_data = GPU_vertbuf_create_with_format(format);
-
- const int vbo_len_capacity = tri_len * 3;
- int vbo_len_used = 0;
- GPU_vertbuf_data_alloc(vbo, vbo_len_capacity);
-
- GPUVertBufRaw *layers_combined_step = BLI_array_alloca(layers_combined_step, layers_combined_len);
-
- GPUVertBufRaw *uv_step = layers_combined_step;
- GPUVertBufRaw *tangent_step = uv_step + uv_len;
- GPUVertBufRaw *vcol_step = tangent_step + tangent_len;
-
- /* Not needed, just for sanity. */
- if (uv_len == 0) { uv_step = NULL; }
- if (tangent_len == 0) { tangent_step = NULL; }
- if (vcol_len == 0) { vcol_step = NULL; }
-
- for (uint i = 0; i < uv_len; i++) {
- GPU_vertbuf_attr_get_raw_data(vbo, uv_id[i], &uv_step[i]);
- }
- for (uint i = 0; i < tangent_len; i++) {
- GPU_vertbuf_attr_get_raw_data(vbo, tangent_id[i], &tangent_step[i]);
- }
- for (uint i = 0; i < vcol_len; i++) {
- GPU_vertbuf_attr_get_raw_data(vbo, vcol_id[i], &vcol_step[i]);
- }
-
- /* TODO deduplicate all verts and make use of GPUIndexBuf in
- * mesh_batch_cache_get_triangles_in_order_split_by_material. */
- if (rdata->edit_bmesh) {
- for (uint i = 0; i < tri_len; i++) {
+ for (int i = 0; i < tri_len; i++) {
const BMLoop **bm_looptri = (const BMLoop **)rdata->edit_bmesh->looptris[i];
- if (BM_elem_flag_test(bm_looptri[0]->f, BM_ELEM_HIDDEN)) {
+ const BMFace *bm_face = bm_looptri[0]->f;
+
+ /* use_hide always for edit-mode */
+ if (BM_elem_flag_test(bm_face, BM_ELEM_HIDDEN)) {
continue;
}
- /* UVs */
- for (uint j = 0; j < uv_len; j++) {
- const uint layer_offset = rdata->cd.offset.uv[j];
+
+ if (lnors) {
for (uint t = 0; t < 3; t++) {
- const float *elem = ((MLoopUV *)BM_ELEM_CD_GET_VOID_P(bm_looptri[t], layer_offset))->uv;
- copy_v2_v2(GPU_vertbuf_raw_step(&uv_step[j]), elem);
+ const float *nor = lnors[BM_elem_index_get(bm_looptri[t])];
+ *((GPUPackedNormal *)GPU_vertbuf_raw_step(&nor_step)) = GPU_normal_convert_i10_v3(nor);
}
}
- /* TANGENTs */
- for (uint j = 0; j < tangent_len; j++) {
- float (*layer_data)[4] = rdata->cd.layers.tangent[j];
+ else if (BM_elem_flag_test(bm_face, BM_ELEM_SMOOTH)) {
for (uint t = 0; t < 3; t++) {
- const float *elem = layer_data[BM_elem_index_get(bm_looptri[t])];
-#ifdef USE_COMP_MESH_DATA
- normal_float_to_short_v4(GPU_vertbuf_raw_step(&tangent_step[j]), elem);
-#else
- copy_v4_v4(GPU_vertbuf_raw_step(&tangent_step[j]), elem);
-#endif
+ *((GPUPackedNormal *)GPU_vertbuf_raw_step(&nor_step)) = vnors_pack[BM_elem_index_get(bm_looptri[t]->v)];
}
}
- /* VCOLs */
- for (uint j = 0; j < vcol_len; j++) {
- const uint layer_offset = rdata->cd.offset.vcol[j];
+ else {
+ const GPUPackedNormal *snor_pack = &pnors_pack[BM_elem_index_get(bm_face)];
for (uint t = 0; t < 3; t++) {
- const uchar *elem = &((MLoopCol *)BM_ELEM_CD_GET_VOID_P(bm_looptri[t], layer_offset))->r;
- copy_v3_v3_uchar(GPU_vertbuf_raw_step(&vcol_step[j]), elem);
+ *((GPUPackedNormal *)GPU_vertbuf_raw_step(&nor_step)) = *snor_pack;
}
}
- }
- }
- else {
- for (uint i = 0; i < tri_len; i++) {
- const MLoopTri *mlt = &rdata->mlooptri[i];
- /* UVs */
- for (uint j = 0; j < uv_len; j++) {
- const MLoopUV *layer_data = rdata->cd.layers.uv[j];
+ /* TODO(sybren): deduplicate this and all the other places it's pasted to in this file. */
+ if (rdata->edit_data && rdata->edit_data->vertexCos) {
for (uint t = 0; t < 3; t++) {
- const float *elem = layer_data[mlt->tri[t]].uv;
- copy_v2_v2(GPU_vertbuf_raw_step(&uv_step[j]), elem);
+ int vidx = BM_elem_index_get(bm_looptri[t]->v);
+ const float *pos = rdata->edit_data->vertexCos[vidx];
+ copy_v3_v3(GPU_vertbuf_raw_step(&pos_step), pos);
}
}
- /* TANGENTs */
- for (uint j = 0; j < tangent_len; j++) {
- float (*layer_data)[4] = rdata->cd.layers.tangent[j];
- for (uint t = 0; t < 3; t++) {
- const float *elem = layer_data[mlt->tri[t]];
-#ifdef USE_COMP_MESH_DATA
- normal_float_to_short_v4(GPU_vertbuf_raw_step(&tangent_step[j]), elem);
-#else
- copy_v4_v4(GPU_vertbuf_raw_step(&tangent_step[j]), elem);
-#endif
- }
- }
- /* VCOLs */
- for (uint j = 0; j < vcol_len; j++) {
- const MLoopCol *layer_data = rdata->cd.layers.vcol[j];
+ else {
for (uint t = 0; t < 3; t++) {
- const uchar *elem = &layer_data[mlt->tri[t]].r;
- copy_v3_v3_uchar(GPU_vertbuf_raw_step(&vcol_step[j]), elem);
+ copy_v3_v3(GPU_vertbuf_raw_step(&pos_step), bm_looptri[t]->v->co);
}
}
}
}
-
- vbo_len_used = GPU_vertbuf_raw_used(&layers_combined_step[0]);
-
-#ifndef NDEBUG
- /* Check all layers are write aligned. */
- if (layers_combined_len > 1) {
- for (uint i = 1; i < layers_combined_len; i++) {
- BLI_assert(vbo_len_used == GPU_vertbuf_raw_used(&layers_combined_step[i]));
+ else {
+ if (lnors == NULL) {
+ /* Use normals from vertex. */
+ mesh_render_data_ensure_poly_normals_pack(rdata);
}
- }
-#endif
- if (vbo_len_capacity != vbo_len_used) {
- GPU_vertbuf_data_resize(vbo, vbo_len_used);
- }
- }
-
-#undef USE_COMP_MESH_DATA
-
- return cache->shaded_triangles_data;
-}
-
-static GPUVertBuf *mesh_batch_cache_get_tri_uv_active(
- MeshRenderData *rdata, MeshBatchCache *cache)
-{
- BLI_assert(rdata->types & (MR_DATATYPE_VERT | MR_DATATYPE_LOOPTRI | MR_DATATYPE_LOOP | MR_DATATYPE_LOOPUV));
-
-
- if (cache->tri_aligned_uv == NULL) {
- const MLoopUV *mloopuv = rdata->mloopuv;
- if (mloopuv == NULL) {
- return NULL;
- }
-
- uint vidx = 0;
-
- static GPUVertFormat format = { 0 };
- static struct { uint uv; } attr_id;
- if (format.attr_len == 0) {
- attr_id.uv = GPU_vertformat_attr_add(&format, "uv", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
- }
-
- const int tri_len = mesh_render_data_looptri_len_get(rdata);
-
- GPUVertBuf *vbo = cache->tri_aligned_uv = GPU_vertbuf_create_with_format(&format);
-
- const int vbo_len_capacity = tri_len * 3;
- int vbo_len_used = 0;
- GPU_vertbuf_data_alloc(vbo, vbo_len_capacity);
-
-
- BMEditMesh *embm = rdata->edit_bmesh;
- /* get uv's from active UVMap */
- if (rdata->edit_bmesh) {
- /* edit mode */
- BMesh *bm = embm->bm;
-
- const int layer_offset = CustomData_get_offset(&bm->ldata, CD_MLOOPUV);
- for (uint i = 0; i < tri_len; i++) {
- const BMLoop **bm_looptri = (const BMLoop **)embm->looptris[i];
- if (BM_elem_flag_test(bm_looptri[0]->f, BM_ELEM_HIDDEN)) {
- continue;
- }
- for (uint t = 0; t < 3; t++) {
- const BMLoop *loop = bm_looptri[t];
- const int index = BM_elem_index_get(loop);
- if (index != -1) {
- const float *elem = ((MLoopUV *)BM_ELEM_CD_GET_VOID_P(loop, layer_offset))->uv;
- GPU_vertbuf_attr_set(vbo, attr_id.uv, vidx++, elem);
- }
- }
- }
- }
- else {
- /* object mode */
for (int i = 0; i < tri_len; i++) {
const MLoopTri *mlt = &rdata->mlooptri[i];
- GPU_vertbuf_attr_set(vbo, attr_id.uv, vidx++, mloopuv[mlt->tri[0]].uv);
- GPU_vertbuf_attr_set(vbo, attr_id.uv, vidx++, mloopuv[mlt->tri[1]].uv);
- GPU_vertbuf_attr_set(vbo, attr_id.uv, vidx++, mloopuv[mlt->tri[2]].uv);
- }
- }
+ const MPoly *mp = &rdata->mpoly[mlt->poly];
- vbo_len_used = vidx;
-
- BLI_assert(vbo_len_capacity == vbo_len_used);
- UNUSED_VARS_NDEBUG(vbo_len_used);
- }
-
- return cache->tri_aligned_uv;
-}
-
-static GPUVertBuf *mesh_batch_cache_get_tri_pos_and_normals_ex(
- MeshRenderData *rdata, const bool use_hide,
- GPUVertBuf **r_vbo)
-{
- BLI_assert(rdata->types & (MR_DATATYPE_VERT | MR_DATATYPE_LOOPTRI | MR_DATATYPE_LOOP | MR_DATATYPE_POLY));
-
- if (*r_vbo == NULL) {
- static GPUVertFormat format = { 0 };
- static struct { uint pos, nor; } attr_id;
- if (format.attr_len == 0) {
- attr_id.pos = GPU_vertformat_attr_add(&format, "pos", GPU_COMP_F32, 3, GPU_FETCH_FLOAT);
- attr_id.nor = GPU_vertformat_attr_add(&format, "nor", GPU_COMP_I10, 3, GPU_FETCH_INT_TO_FLOAT_UNIT);
- }
-
- const int tri_len = mesh_render_data_looptri_len_get_maybe_mapped(rdata);
-
- GPUVertBuf *vbo = *r_vbo = GPU_vertbuf_create_with_format(&format);
-
- const int vbo_len_capacity = tri_len * 3;
- int vbo_len_used = 0;
- GPU_vertbuf_data_alloc(vbo, vbo_len_capacity);
-
- GPUVertBufRaw pos_step, nor_step;
- GPU_vertbuf_attr_get_raw_data(vbo, attr_id.pos, &pos_step);
- GPU_vertbuf_attr_get_raw_data(vbo, attr_id.nor, &nor_step);
-
- if (rdata->mapped.use == false) {
- float (*lnors)[3] = rdata->loop_normals;
- if (rdata->edit_bmesh) {
- GPUPackedNormal *pnors_pack, *vnors_pack;
-
- if (lnors == NULL) {
- mesh_render_data_ensure_poly_normals_pack(rdata);
- mesh_render_data_ensure_vert_normals_pack(rdata);
-
- pnors_pack = rdata->poly_normals_pack;
- vnors_pack = rdata->vert_normals_pack;
+ if (use_hide && (mp->flag & ME_HIDE)) {
+ continue;
}
- for (int i = 0; i < tri_len; i++) {
- const BMLoop **bm_looptri = (const BMLoop **)rdata->edit_bmesh->looptris[i];
- const BMFace *bm_face = bm_looptri[0]->f;
-
- /* use_hide always for edit-mode */
- if (BM_elem_flag_test(bm_face, BM_ELEM_HIDDEN)) {
- continue;
- }
+ const uint vtri[3] = {
+ rdata->mloop[mlt->tri[0]].v,
+ rdata->mloop[mlt->tri[1]].v,
+ rdata->mloop[mlt->tri[2]].v,
+ };
- if (lnors) {
- for (uint t = 0; t < 3; t++) {
- const float *nor = lnors[BM_elem_index_get(bm_looptri[t])];
- *((GPUPackedNormal *)GPU_vertbuf_raw_step(&nor_step)) = GPU_normal_convert_i10_v3(nor);
- }
+ if (lnors) {
+ for (uint t = 0; t < 3; t++) {
+ const float *nor = lnors[mlt->tri[t]];
+ *((GPUPackedNormal *)GPU_vertbuf_raw_step(&nor_step)) = GPU_normal_convert_i10_v3(nor);
}
- else if (BM_elem_flag_test(bm_face, BM_ELEM_SMOOTH)) {
- for (uint t = 0; t < 3; t++) {
- *((GPUPackedNormal *)GPU_vertbuf_raw_step(&nor_step)) = vnors_pack[BM_elem_index_get(bm_looptri[t]->v)];
- }
+ }
+ else if (mp->flag & ME_SMOOTH) {
+ for (uint t = 0; t < 3; t++) {
+ const MVert *mv = &rdata->mvert[vtri[t]];
+ *((GPUPackedNormal *)GPU_vertbuf_raw_step(&nor_step)) = GPU_normal_convert_i10_s3(mv->no);
}
- else {
- const GPUPackedNormal *snor_pack = &pnors_pack[BM_elem_index_get(bm_face)];
- for (uint t = 0; t < 3; t++) {
- *((GPUPackedNormal *)GPU_vertbuf_raw_step(&nor_step)) = *snor_pack;
- }
+ }
+ else {
+ const GPUPackedNormal *pnors_pack = &rdata->poly_normals_pack[mlt->poly];
+ for (uint t = 0; t < 3; t++) {
+ *((GPUPackedNormal *)GPU_vertbuf_raw_step(&nor_step)) = *pnors_pack;
}
+ }
- /* TODO(sybren): deduplicate this and all the other places it's pasted to in this file. */
- if (rdata->edit_data && rdata->edit_data->vertexCos) {
- for (uint t = 0; t < 3; t++) {
- int vidx = BM_elem_index_get(bm_looptri[t]->v);
- const float *pos = rdata->edit_data->vertexCos[vidx];
- copy_v3_v3(GPU_vertbuf_raw_step(&pos_step), pos);
- }
- }
- else {
- for (uint t = 0; t < 3; t++) {
- copy_v3_v3(GPU_vertbuf_raw_step(&pos_step), bm_looptri[t]->v->co);
- }
- }
+ for (uint t = 0; t < 3; t++) {
+ const MVert *mv = &rdata->mvert[vtri[t]];
+ copy_v3_v3(GPU_vertbuf_raw_step(&pos_step), mv->co);
}
}
- else {
- if (lnors == NULL) {
- /* Use normals from vertex. */
- mesh_render_data_ensure_poly_normals_pack(rdata);
- }
+ }
+ }
+ else {
+ /* Note: mapped doesn't support lnors yet. */
+ BMesh *bm = rdata->edit_bmesh->bm;
+ Mesh *me_cage = rdata->mapped.me_cage;
- for (int i = 0; i < tri_len; i++) {
- const MLoopTri *mlt = &rdata->mlooptri[i];
- const MPoly *mp = &rdata->mpoly[mlt->poly];
+ /* TODO(campbell): unlike non-mapped modes we don't generate these on demand, just use if they exist.
+ * this seems like a low priority TODO since mapped meshes typically
+ * use the final mesh evaluated mesh for showing faces. */
+ const float (*lnors)[3] = CustomData_get_layer(&me_cage->ldata, CD_NORMAL);
- if (use_hide && (mp->flag & ME_HIDE)) {
- continue;
- }
+ /* TODO(campbell): this is quite an expensive operation for something
+ * that's not used unless 'normal' display option is enabled. */
+ if (!CustomData_has_layer(&me_cage->pdata, CD_NORMAL)) {
+ /* TODO(campbell): this is quite an expensive operation for something
+ * that's not used unless 'normal' display option is enabled. */
+ BKE_mesh_ensure_normals_for_display(me_cage);
+ }
+ const float (*polynors)[3] = CustomData_get_layer(&me_cage->pdata, CD_NORMAL);
+
+ const MVert *mvert = rdata->mapped.me_cage->mvert;
+ const MLoop *mloop = rdata->mapped.me_cage->mloop;
+ const MPoly *mpoly = rdata->mapped.me_cage->mpoly;
+ const MLoopTri *mlooptri = BKE_mesh_runtime_looptri_ensure(me_cage);
+ for (int i = 0; i < tri_len; i++) {
+ const MLoopTri *mlt = &mlooptri[i];
+ const int p_orig = rdata->mapped.p_origindex[mlt->poly];
+ if (p_orig != ORIGINDEX_NONE) {
+ /* Assume 'use_hide' */
+ BMFace *efa = BM_face_at_index(bm, p_orig);
+ if (!BM_elem_flag_test(efa, BM_ELEM_HIDDEN)) {
+ const MPoly *mp = &mpoly[mlt->poly];
const uint vtri[3] = {
- rdata->mloop[mlt->tri[0]].v,
- rdata->mloop[mlt->tri[1]].v,
- rdata->mloop[mlt->tri[2]].v,
+ mloop[mlt->tri[0]].v,
+ mloop[mlt->tri[1]].v,
+ mloop[mlt->tri[2]].v,
};
if (lnors) {
@@ -2827,176 +2799,68 @@ static GPUVertBuf *mesh_batch_cache_get_tri_pos_and_normals_ex(
}
else if (mp->flag & ME_SMOOTH) {
for (uint t = 0; t < 3; t++) {
- const MVert *mv = &rdata->mvert[vtri[t]];
+ const MVert *mv = &mvert[vtri[t]];
*((GPUPackedNormal *)GPU_vertbuf_raw_step(&nor_step)) = GPU_normal_convert_i10_s3(mv->no);
}
}
else {
- const GPUPackedNormal *pnors_pack = &rdata->poly_normals_pack[mlt->poly];
+ /* we don't have cached 'rdata->poly_normals_pack'. */
+ const GPUPackedNormal pnor = GPU_normal_convert_i10_v3(polynors[mlt->poly]);
for (uint t = 0; t < 3; t++) {
- *((GPUPackedNormal *)GPU_vertbuf_raw_step(&nor_step)) = *pnors_pack;
+ *((GPUPackedNormal *)GPU_vertbuf_raw_step(&nor_step)) = pnor;
}
}
for (uint t = 0; t < 3; t++) {
- const MVert *mv = &rdata->mvert[vtri[t]];
+ const MVert *mv = &mvert[vtri[t]];
copy_v3_v3(GPU_vertbuf_raw_step(&pos_step), mv->co);
}
}
}
}
- else {
- /* Note: mapped doesn't support lnors yet. */
- BMesh *bm = rdata->edit_bmesh->bm;
- Mesh *me_cage = rdata->mapped.me_cage;
-
- /* TODO(campbell): unlike non-mapped modes we don't generate these on demand, just use if they exist.
- * this seems like a low priority TODO since mapped meshes typically
- * use the final mesh evaluated mesh for showing faces. */
- const float (*lnors)[3] = CustomData_get_layer(&me_cage->ldata, CD_NORMAL);
-
- /* TODO(campbell): this is quite an expensive operation for something
- * that's not used unless 'normal' display option is enabled. */
- if (!CustomData_has_layer(&me_cage->pdata, CD_NORMAL)) {
- /* TODO(campbell): this is quite an expensive operation for something
- * that's not used unless 'normal' display option is enabled. */
- BKE_mesh_ensure_normals_for_display(me_cage);
- }
- const float (*polynors)[3] = CustomData_get_layer(&me_cage->pdata, CD_NORMAL);
-
- const MVert *mvert = rdata->mapped.me_cage->mvert;
- const MLoop *mloop = rdata->mapped.me_cage->mloop;
- const MPoly *mpoly = rdata->mapped.me_cage->mpoly;
+ }
- const MLoopTri *mlooptri = BKE_mesh_runtime_looptri_ensure(me_cage);
- for (int i = 0; i < tri_len; i++) {
- const MLoopTri *mlt = &mlooptri[i];
- const int p_orig = rdata->mapped.p_origindex[mlt->poly];
- if (p_orig != ORIGINDEX_NONE) {
- /* Assume 'use_hide' */
- BMFace *efa = BM_face_at_index(bm, p_orig);
- if (!BM_elem_flag_test(efa, BM_ELEM_HIDDEN)) {
- const MPoly *mp = &mpoly[mlt->poly];
- const uint vtri[3] = {
- mloop[mlt->tri[0]].v,
- mloop[mlt->tri[1]].v,
- mloop[mlt->tri[2]].v,
- };
-
- if (lnors) {
- for (uint t = 0; t < 3; t++) {
- const float *nor = lnors[mlt->tri[t]];
- *((GPUPackedNormal *)GPU_vertbuf_raw_step(&nor_step)) = GPU_normal_convert_i10_v3(nor);
- }
- }
- else if (mp->flag & ME_SMOOTH) {
- for (uint t = 0; t < 3; t++) {
- const MVert *mv = &mvert[vtri[t]];
- *((GPUPackedNormal *)GPU_vertbuf_raw_step(&nor_step)) = GPU_normal_convert_i10_s3(mv->no);
- }
- }
- else {
- /* we don't have cached 'rdata->poly_normals_pack'. */
- const GPUPackedNormal pnor = GPU_normal_convert_i10_v3(polynors[mlt->poly]);
- for (uint t = 0; t < 3; t++) {
- *((GPUPackedNormal *)GPU_vertbuf_raw_step(&nor_step)) = pnor;
- }
- }
+ vbo_len_used = GPU_vertbuf_raw_used(&pos_step);
+ BLI_assert(vbo_len_used == GPU_vertbuf_raw_used(&nor_step));
- for (uint t = 0; t < 3; t++) {
- const MVert *mv = &mvert[vtri[t]];
- copy_v3_v3(GPU_vertbuf_raw_step(&pos_step), mv->co);
- }
- }
- }
- }
- }
+ if (vbo_len_capacity != vbo_len_used) {
+ GPU_vertbuf_data_resize(vbo, vbo_len_used);
+ }
+}
- vbo_len_used = GPU_vertbuf_raw_used(&pos_step);
- BLI_assert(vbo_len_used == GPU_vertbuf_raw_used(&nor_step));
+static GPUVertBuf *mesh_batch_cache_get_tri_pos_and_normals_ex(
+ MeshRenderData *rdata, const bool use_hide,
+ GPUVertBuf **r_vbo)
+{
+ BLI_assert(rdata->types & (MR_DATATYPE_VERT | MR_DATATYPE_LOOPTRI | MR_DATATYPE_LOOP | MR_DATATYPE_POLY));
- if (vbo_len_capacity != vbo_len_used) {
- GPU_vertbuf_data_resize(vbo, vbo_len_used);
- }
+ if (*r_vbo == NULL) {
+ *r_vbo = GPU_vertbuf_create(GPU_USAGE_STATIC);
+ mesh_create_pos_and_nor_tess(rdata, *r_vbo, use_hide);
}
return *r_vbo;
}
-static GPUVertBuf *mesh_batch_cache_get_tri_pos_and_normals(
- MeshRenderData *rdata, MeshBatchCache *cache)
-{
- return mesh_batch_cache_get_tri_pos_and_normals_ex(
- rdata, false,
- &cache->pos_with_normals);
-}
-static GPUVertBuf *mesh_create_tri_pos_and_normals_visible_only(
- MeshRenderData *rdata)
+static GPUVertBuf *mesh_batch_cache_get_tri_pos_and_normals_edit(
+ MeshRenderData *rdata, MeshBatchCache *cache, bool use_hide)
{
- GPUVertBuf *vbo_dummy = NULL;
return mesh_batch_cache_get_tri_pos_and_normals_ex(
- rdata, true,
- &vbo_dummy);
+ rdata, use_hide,
+ use_hide ? &cache->pos_with_normals_visible_only_edit : &cache->pos_with_normals_edit);
}
+/* DEPRECATED Need to be ported */
static GPUVertBuf *mesh_batch_cache_get_facedot_pos_with_normals_and_flag(
MeshRenderData *rdata, MeshBatchCache *cache)
{
BLI_assert(rdata->types & (MR_DATATYPE_VERT | MR_DATATYPE_LOOP | MR_DATATYPE_POLY));
- if (cache->ed_fcenter_pos_with_nor_and_sel == NULL) {
- static GPUVertFormat format = { 0 };
- static struct { uint pos, data; } attr_id;
- if (format.attr_len == 0) {
- attr_id.pos = GPU_vertformat_attr_add(&format, "pos", GPU_COMP_F32, 3, GPU_FETCH_FLOAT);
- attr_id.data = GPU_vertformat_attr_add(&format, "norAndFlag", GPU_COMP_I10, 4, GPU_FETCH_INT_TO_FLOAT_UNIT);
- }
- const int vbo_len_capacity = mesh_render_data_polys_len_get_maybe_mapped(rdata);
- int vidx = 0;
-
- GPUVertBuf *vbo = cache->ed_fcenter_pos_with_nor_and_sel = GPU_vertbuf_create_with_format(&format);
- GPU_vertbuf_data_alloc(vbo, vbo_len_capacity);
-
- if (rdata->edit_bmesh) {
- if (rdata->edit_data && rdata->edit_data->vertexCos != NULL) {
- BKE_editmesh_cache_ensure_poly_normals(rdata->edit_bmesh, rdata->edit_data);
- BKE_editmesh_cache_ensure_poly_centers(rdata->edit_bmesh, rdata->edit_data);
- }
- }
-
- if (rdata->mapped.use == false) {
- for (int i = 0; i < vbo_len_capacity; i++) {
- float pcenter[3], pnor[3];
- bool selected = false;
- if (mesh_render_data_pnors_pcenter_select_get(rdata, i, pnor, pcenter, &selected)) {
- GPUPackedNormal nor = GPU_normal_convert_i10_v3(pnor);
- nor.w = selected ? 1 : 0;
- GPU_vertbuf_attr_set(vbo, attr_id.data, vidx, &nor);
- GPU_vertbuf_attr_set(vbo, attr_id.pos, vidx, pcenter);
- vidx += 1;
- }
- }
- }
- else {
- for (int i = 0; i < vbo_len_capacity; i++) {
- float pcenter[3], pnor[3];
- bool selected = false;
- if (mesh_render_data_pnors_pcenter_select_get_mapped(rdata, i, pnor, pcenter, &selected)) {
- GPUPackedNormal nor = GPU_normal_convert_i10_v3(pnor);
- nor.w = selected ? 1 : 0;
- GPU_vertbuf_attr_set(vbo, attr_id.data, vidx, &nor);
- GPU_vertbuf_attr_set(vbo, attr_id.pos, vidx, pcenter);
- vidx += 1;
- }
- }
- }
- const int vbo_len_used = vidx;
- BLI_assert(vbo_len_used <= vbo_len_capacity);
- if (vbo_len_used != vbo_len_capacity) {
- GPU_vertbuf_data_resize(vbo, vbo_len_used);
- }
+ if (cache->edit.pos_nor_data_facedots == NULL) {
+ cache->edit.pos_nor_data_facedots = GPU_vertbuf_create(GPU_USAGE_STATIC);
+ mesh_create_edit_facedots(rdata, cache->edit.pos_nor_data_facedots);
}
- return cache->ed_fcenter_pos_with_nor_and_sel;
+ return cache->edit.pos_nor_data_facedots;
}
static GPUVertBuf *mesh_batch_cache_get_edges_visible(
@@ -3327,126 +3191,6 @@ static GPUVertBuf *mesh_create_verts_select_id(
return vbo;
}
-static GPUVertBuf *mesh_create_tri_weights(
- MeshRenderData *rdata, bool use_hide, const struct DRW_MeshWeightState *wstate)
-{
- BLI_assert(
- rdata->types &
- (MR_DATATYPE_VERT | MR_DATATYPE_LOOPTRI | MR_DATATYPE_LOOP | MR_DATATYPE_POLY | MR_DATATYPE_DVERT));
-
- GPUVertBuf *vbo;
- {
- uint cidx = 0;
-
- static GPUVertFormat format = { 0 };
- static struct { uint weight; } attr_id;
- if (format.attr_len == 0) {
- attr_id.weight = GPU_vertformat_attr_add(&format, "weight", GPU_COMP_F32, 1, GPU_FETCH_FLOAT);
- }
-
- vbo = GPU_vertbuf_create_with_format(&format);
-
- const int tri_len = mesh_render_data_looptri_len_get(rdata);
- const int vbo_len_capacity = tri_len * 3;
- int vbo_len_used = 0;
- GPU_vertbuf_data_alloc(vbo, vbo_len_capacity);
-
- mesh_render_data_ensure_vert_weight(rdata, wstate);
- const float (*vert_weight) = rdata->vert_weight;
-
- if (rdata->edit_bmesh) {
- for (int i = 0; i < tri_len; i++) {
- const BMLoop **ltri = (const BMLoop **)rdata->edit_bmesh->looptris[i];
- /* Assume 'use_hide' */
- if (!BM_elem_flag_test(ltri[0]->f, BM_ELEM_HIDDEN)) {
- for (uint tri_corner = 0; tri_corner < 3; tri_corner++) {
- const int v_index = BM_elem_index_get(ltri[tri_corner]->v);
- GPU_vertbuf_attr_set(vbo, attr_id.weight, cidx++, &vert_weight[v_index]);
- }
- }
- }
- }
- else {
- for (int i = 0; i < tri_len; i++) {
- const MLoopTri *mlt = &rdata->mlooptri[i];
- if (!(use_hide && (rdata->mpoly[mlt->poly].flag & ME_HIDE))) {
- for (uint tri_corner = 0; tri_corner < 3; tri_corner++) {
- const uint v_index = rdata->mloop[mlt->tri[tri_corner]].v;
- GPU_vertbuf_attr_set(vbo, attr_id.weight, cidx++, &vert_weight[v_index]);
- }
- }
- }
- }
- vbo_len_used = cidx;
-
- if (vbo_len_capacity != vbo_len_used) {
- GPU_vertbuf_data_resize(vbo, vbo_len_used);
- }
- }
-
- return vbo;
-}
-
-static GPUVertBuf *mesh_create_tri_vert_colors(
- MeshRenderData *rdata, bool use_hide)
-{
- BLI_assert(
- rdata->types &
- (MR_DATATYPE_VERT | MR_DATATYPE_LOOPTRI | MR_DATATYPE_LOOP | MR_DATATYPE_POLY | MR_DATATYPE_LOOPCOL));
-
- GPUVertBuf *vbo;
- {
- uint cidx = 0;
-
- static GPUVertFormat format = { 0 };
- static struct { uint col; } attr_id;
- if (format.attr_len == 0) {
- attr_id.col = GPU_vertformat_attr_add(&format, "color", GPU_COMP_U8, 3, GPU_FETCH_INT_TO_FLOAT_UNIT);
- }
-
- const int tri_len = mesh_render_data_looptri_len_get(rdata);
-
- vbo = GPU_vertbuf_create_with_format(&format);
-
- const uint vbo_len_capacity = tri_len * 3;
- GPU_vertbuf_data_alloc(vbo, vbo_len_capacity);
-
- mesh_render_data_ensure_vert_color(rdata);
- const char (*vert_color)[3] = rdata->vert_color;
-
- if (rdata->edit_bmesh) {
- for (int i = 0; i < tri_len; i++) {
- const BMLoop **ltri = (const BMLoop **)rdata->edit_bmesh->looptris[i];
- /* Assume 'use_hide' */
- if (!BM_elem_flag_test(ltri[0]->f, BM_ELEM_HIDDEN)) {
- for (uint tri_corner = 0; tri_corner < 3; tri_corner++) {
- const int l_index = BM_elem_index_get(ltri[tri_corner]);
- GPU_vertbuf_attr_set(vbo, attr_id.col, cidx++, vert_color[l_index]);
- }
- }
- }
- }
- else {
- for (int i = 0; i < tri_len; i++) {
- const MLoopTri *mlt = &rdata->mlooptri[i];
- if (!(use_hide && (rdata->mpoly[mlt->poly].flag & ME_HIDE))) {
- for (uint tri_corner = 0; tri_corner < 3; tri_corner++) {
- const uint l_index = mlt->tri[tri_corner];
- GPU_vertbuf_attr_set(vbo, attr_id.col, cidx++, vert_color[l_index]);
- }
- }
- }
- }
- const uint vbo_len_used = cidx;
-
- if (vbo_len_capacity != vbo_len_used) {
- GPU_vertbuf_data_resize(vbo, vbo_len_used);
- }
- }
-
- return vbo;
-}
-
static GPUVertBuf *mesh_create_tri_select_id(
MeshRenderData *rdata, bool use_hide, uint select_id_offset)
{
@@ -3489,14 +3233,22 @@ static GPUVertBuf *mesh_create_tri_select_id(
}
}
else {
+ const int *p_origindex = NULL;
+ if (rdata->me != NULL) {
+ p_origindex = CustomData_get_layer(&rdata->me->pdata, CD_ORIGINDEX);
+ }
+
for (int i = 0; i < tri_len; i++) {
const MLoopTri *mlt = &rdata->mlooptri[i];
const int poly_index = mlt->poly;
if (!(use_hide && (rdata->mpoly[poly_index].flag & ME_HIDE))) {
- int select_id;
- GPU_select_index_get(poly_index + select_id_offset, &select_id);
- for (uint tri_corner = 0; tri_corner < 3; tri_corner++) {
- GPU_vertbuf_attr_set(vbo, attr_id.col, cidx++, &select_id);
+ int orig_index = p_origindex ? p_origindex[poly_index] : poly_index;
+ if (orig_index != ORIGINDEX_NONE) {
+ int select_id;
+ GPU_select_index_get(orig_index + select_id_offset, &select_id);
+ for (uint tri_corner = 0; tri_corner < 3; tri_corner++) {
+ GPU_vertbuf_attr_set(vbo, attr_id.col, cidx++, &select_id);
+ }
}
}
}
@@ -3531,519 +3283,719 @@ static GPUVertBuf *mesh_create_tri_select_id(
return vbo;
}
-static GPUVertBuf *mesh_batch_cache_get_vert_pos_and_nor_in_order(
- MeshRenderData *rdata, MeshBatchCache *cache)
+static void mesh_create_pos_and_nor(MeshRenderData *rdata, GPUVertBuf *vbo)
{
- BLI_assert(rdata->types & MR_DATATYPE_VERT);
+ static GPUVertFormat format = { 0 };
+ static struct { uint pos, nor; } attr_id;
+ if (format.attr_len == 0) {
+ attr_id.pos = GPU_vertformat_attr_add(&format, "pos", GPU_COMP_F32, 3, GPU_FETCH_FLOAT);
+ attr_id.nor = GPU_vertformat_attr_add(&format, "nor", GPU_COMP_I10, 4, GPU_FETCH_INT_TO_FLOAT_UNIT);
+ }
- if (cache->pos_in_order == NULL) {
- static GPUVertFormat format = { 0 };
- static struct { uint pos, nor; } attr_id;
- if (format.attr_len == 0) {
- /* Normal is padded so that the vbo can be used as a buffer texture */
- attr_id.pos = GPU_vertformat_attr_add(&format, "pos", GPU_COMP_F32, 3, GPU_FETCH_FLOAT);
- attr_id.nor = GPU_vertformat_attr_add(&format, "nor", GPU_COMP_I16, 4, GPU_FETCH_INT_TO_FLOAT_UNIT);
+ GPU_vertbuf_init_with_format(vbo, &format);
+ const int vbo_len_capacity = mesh_render_data_verts_len_get_maybe_mapped(rdata);
+ GPU_vertbuf_data_alloc(vbo, vbo_len_capacity);
+
+ if (rdata->mapped.use == false) {
+ if (rdata->edit_bmesh) {
+ BMesh *bm = rdata->edit_bmesh->bm;
+ BMIter iter;
+ BMVert *eve;
+ uint i;
+
+ mesh_render_data_ensure_vert_normals_pack(rdata);
+ GPUPackedNormal *vnor = rdata->vert_normals_pack;
+
+ BM_ITER_MESH_INDEX (eve, &iter, bm, BM_VERTS_OF_MESH, i) {
+ GPU_vertbuf_attr_set(vbo, attr_id.pos, i, eve->co);
+ GPU_vertbuf_attr_set(vbo, attr_id.nor, i, &vnor[i]);
+ }
+ BLI_assert(i == vbo_len_capacity);
+ }
+ else {
+ for (int i = 0; i < vbo_len_capacity; i++) {
+ const MVert *mv = &rdata->mvert[i];
+ GPUPackedNormal vnor_pack = GPU_normal_convert_i10_s3(mv->no);
+ vnor_pack.w = (mv->flag & ME_HIDE) ? -1 : ((mv->flag & SELECT) ? 1 : 0);
+ GPU_vertbuf_attr_set(vbo, attr_id.pos, i, rdata->mvert[i].co);
+ GPU_vertbuf_attr_set(vbo, attr_id.nor, i, &vnor_pack);
+ }
+ }
+ }
+ else {
+ const MVert *mvert = rdata->mapped.me_cage->mvert;
+ const int *v_origindex = rdata->mapped.v_origindex;
+ for (int i = 0; i < vbo_len_capacity; i++) {
+ const int v_orig = v_origindex[i];
+ if (v_orig != ORIGINDEX_NONE) {
+ const MVert *mv = &mvert[i];
+ GPUPackedNormal vnor_pack = GPU_normal_convert_i10_s3(mv->no);
+ vnor_pack.w = (mv->flag & ME_HIDE) ? -1 : ((mv->flag & SELECT) ? 1 : 0);
+ GPU_vertbuf_attr_set(vbo, attr_id.pos, i, mv->co);
+ GPU_vertbuf_attr_set(vbo, attr_id.nor, i, &vnor_pack);
+ }
}
+ }
+}
- GPUVertBuf *vbo = cache->pos_in_order = GPU_vertbuf_create_with_format(&format);
- const int vbo_len_capacity = mesh_render_data_verts_len_get_maybe_mapped(rdata);
- GPU_vertbuf_data_alloc(vbo, vbo_len_capacity);
+static void mesh_create_weights(MeshRenderData *rdata, GPUVertBuf *vbo, DRW_MeshWeightState *wstate)
+{
+ static GPUVertFormat format = { 0 };
+ static struct { uint weight; } attr_id;
+ if (format.attr_len == 0) {
+ attr_id.weight = GPU_vertformat_attr_add(&format, "weight", GPU_COMP_F32, 1, GPU_FETCH_FLOAT);
+ }
- if (rdata->mapped.use == false) {
- if (rdata->edit_bmesh) {
- BMesh *bm = rdata->edit_bmesh->bm;
- BMIter iter;
- BMVert *eve;
- uint i;
+ const int vbo_len_capacity = mesh_render_data_verts_len_get_maybe_mapped(rdata);
- BM_ITER_MESH_INDEX (eve, &iter, bm, BM_VERTS_OF_MESH, i) {
- static short no_short[4];
- normal_float_to_short_v3(no_short, eve->no);
+ mesh_render_data_ensure_vert_weight(rdata, wstate);
+ const float (*vert_weight) = rdata->vert_weight;
- GPU_vertbuf_attr_set(vbo, attr_id.pos, i, eve->co);
- GPU_vertbuf_attr_set(vbo, attr_id.nor, i, no_short);
- }
- BLI_assert(i == vbo_len_capacity);
+ GPU_vertbuf_init_with_format(vbo, &format);
+ /* Meh, another allocation / copy for no benefit.
+ * Needed because rdata->vert_weight is freed afterwards and
+ * GPU module don't have a GPU_vertbuf_data_from_memory or similar. */
+ /* TODO get rid of the extra allocation/copy. */
+ GPU_vertbuf_data_alloc(vbo, vbo_len_capacity);
+ GPU_vertbuf_attr_fill(vbo, attr_id.weight, vert_weight);
+}
+
+static void mesh_create_loop_pos_and_nor(MeshRenderData *rdata, GPUVertBuf *vbo, const bool use_face_sel)
+{
+ /* TODO deduplicate format creation*/
+ static GPUVertFormat format = { 0 };
+ static struct { uint pos, nor; } attr_id;
+ if (format.attr_len == 0) {
+ attr_id.pos = GPU_vertformat_attr_add(&format, "pos", GPU_COMP_F32, 3, GPU_FETCH_FLOAT);
+ attr_id.nor = GPU_vertformat_attr_add(&format, "nor", GPU_COMP_I10, 4, GPU_FETCH_INT_TO_FLOAT_UNIT);
+ }
+ const int poly_len = mesh_render_data_polys_len_get(rdata);
+ const int loop_len = mesh_render_data_loops_len_get(rdata);
+
+ GPU_vertbuf_init_with_format(vbo, &format);
+ GPU_vertbuf_data_alloc(vbo, loop_len);
+
+ GPUVertBufRaw pos_step, nor_step;
+ GPU_vertbuf_attr_get_raw_data(vbo, attr_id.pos, &pos_step);
+ GPU_vertbuf_attr_get_raw_data(vbo, attr_id.nor, &nor_step);
+
+ if (rdata->mapped.use == false) {
+ if (rdata->edit_bmesh) {
+ const GPUPackedNormal *vnor, *pnor;
+ const float (*lnors)[3] = rdata->loop_normals;
+ BMesh *bm = rdata->edit_bmesh->bm;
+ BMIter iter_efa, iter_loop;
+ BMFace *efa;
+ BMLoop *loop;
+ uint f;
+
+ if (rdata->loop_normals == NULL) {
+ mesh_render_data_ensure_poly_normals_pack(rdata);
+ mesh_render_data_ensure_vert_normals_pack(rdata);
+ vnor = rdata->vert_normals_pack;
+ pnor = rdata->poly_normals_pack;
}
- else {
- for (int i = 0; i < vbo_len_capacity; i++) {
- GPU_vertbuf_attr_set(vbo, attr_id.pos, i, rdata->mvert[i].co);
- GPU_vertbuf_attr_set(vbo, attr_id.nor, i, rdata->mvert[i].no); /* XXX actually reading 4 shorts */
+
+ BM_ITER_MESH_INDEX (efa, &iter_efa, bm, BM_FACES_OF_MESH, f) {
+ const bool face_smooth = BM_elem_flag_test(efa, BM_ELEM_SMOOTH);
+
+ BM_ITER_ELEM (loop, &iter_loop, efa, BM_LOOPS_OF_FACE) {
+ BLI_assert(GPU_vertbuf_raw_used(&pos_step) == BM_elem_index_get(loop));
+ copy_v3_v3(GPU_vertbuf_raw_step(&pos_step), loop->v->co);
+
+ if (lnors) {
+ GPUPackedNormal plnor = GPU_normal_convert_i10_v3(lnors[BM_elem_index_get(loop)]);
+ *((GPUPackedNormal *)GPU_vertbuf_raw_step(&nor_step)) = plnor;
+ }
+ else if (!face_smooth) {
+ *((GPUPackedNormal *)GPU_vertbuf_raw_step(&nor_step)) = pnor[f];
+ }
+ else {
+ *((GPUPackedNormal *)GPU_vertbuf_raw_step(&nor_step)) = vnor[BM_elem_index_get(loop->v)];
+ }
}
}
+ BLI_assert(GPU_vertbuf_raw_used(&pos_step) == loop_len);
}
else {
- const MVert *mvert = rdata->mapped.me_cage->mvert;
- const int *v_origindex = rdata->mapped.v_origindex;
- for (int i = 0; i < vbo_len_capacity; i++) {
- const int v_orig = v_origindex[i];
- if (v_orig != ORIGINDEX_NONE) {
- const MVert *mv = &mvert[i];
- GPU_vertbuf_attr_set(vbo, attr_id.pos, i, mv->co);
- GPU_vertbuf_attr_set(vbo, attr_id.nor, i, mv->no); /* XXX actually reading 4 shorts */
+ const MVert *mvert = rdata->mvert;
+ const MPoly *mpoly = rdata->mpoly;
+
+ if (rdata->loop_normals == NULL) {
+ mesh_render_data_ensure_poly_normals_pack(rdata);
+ }
+
+ for (int a = 0; a < poly_len; a++, mpoly++) {
+ const MLoop *mloop = rdata->mloop + mpoly->loopstart;
+ const float *lnors = (rdata->loop_normals) ? rdata->loop_normals[mpoly->loopstart] : NULL;
+ const GPUPackedNormal *fnor = (mpoly->flag & ME_SMOOTH) ? NULL : &rdata->poly_normals_pack[a];
+ for (int b = 0; b < mpoly->totloop; b++, mloop++) {
+ copy_v3_v3(GPU_vertbuf_raw_step(&pos_step), mvert[mloop->v].co);
+ GPUPackedNormal *pnor = (GPUPackedNormal *)GPU_vertbuf_raw_step(&nor_step);
+ if (lnors) {
+ *pnor = GPU_normal_convert_i10_v3(lnors);
+ }
+ else if (fnor) {
+ *pnor = *fnor;
+ }
+ else {
+ *pnor = GPU_normal_convert_i10_s3(mvert[mloop->v].no);
+ }
+ if (use_face_sel) {
+ pnor->w = (mpoly->flag & ME_HIDE) ? -1 : ((mpoly->flag & ME_FACE_SEL) ? 1 : 0);
+ }
}
}
+
+ BLI_assert(loop_len == GPU_vertbuf_raw_used(&pos_step));
}
}
+ else {
+ const int *p_origindex = rdata->mapped.p_origindex;
+ const MVert *mvert = rdata->mvert;
+ const MPoly *mpoly = rdata->mpoly;
+
+ if (rdata->loop_normals == NULL) {
+ mesh_render_data_ensure_poly_normals_pack(rdata);
+ }
- return cache->pos_in_order;
+ for (int a = 0; a < poly_len; a++, mpoly++) {
+ const MLoop *mloop = rdata->mloop + mpoly->loopstart;
+ const float *lnors = (rdata->loop_normals) ? rdata->loop_normals[mpoly->loopstart] : NULL;
+ const GPUPackedNormal *fnor = (mpoly->flag & ME_SMOOTH) ? NULL : &rdata->poly_normals_pack[a];
+ if (p_origindex[a] == ORIGINDEX_NONE) {
+ continue;
+ }
+ for (int b = 0; b < mpoly->totloop; b++, mloop++) {
+ copy_v3_v3(GPU_vertbuf_raw_step(&pos_step), mvert[mloop->v].co);
+ GPUPackedNormal *pnor = (GPUPackedNormal *)GPU_vertbuf_raw_step(&nor_step);
+ if (lnors) {
+ *pnor = GPU_normal_convert_i10_v3(lnors);
+ }
+ else if (fnor) {
+ *pnor = *fnor;
+ }
+ else {
+ *pnor = GPU_normal_convert_i10_s3(mvert[mloop->v].no);
+ }
+ }
+ }
+ }
+
+ int vbo_len_used = GPU_vertbuf_raw_used(&pos_step);
+ if (vbo_len_used < loop_len) {
+ GPU_vertbuf_data_resize(vbo, vbo_len_used);
+ }
}
-static GPUVertFormat *edit_mesh_overlay_pos_format(uint *r_pos_id)
+static void mesh_create_loop_uv_and_tan(MeshRenderData *rdata, GPUVertBuf *vbo)
{
- static GPUVertFormat format_pos = { 0 };
- static uint pos_id;
- if (format_pos.attr_len == 0) {
- pos_id = GPU_vertformat_attr_add(&format_pos, "pos", GPU_COMP_F32, 3, GPU_FETCH_FLOAT);
+ const uint loops_len = mesh_render_data_loops_len_get(rdata);
+ const uint uv_len = rdata->cd.layers.uv_len;
+ const uint tangent_len = rdata->cd.layers.tangent_len;
+ const uint layers_combined_len = uv_len + tangent_len;
+
+ GPUVertBufRaw *layers_combined_step = BLI_array_alloca(layers_combined_step, layers_combined_len);
+ GPUVertBufRaw *uv_step = layers_combined_step;
+ GPUVertBufRaw *tangent_step = uv_step + uv_len;
+
+ uint *layers_combined_id = BLI_array_alloca(layers_combined_id, layers_combined_len);
+ uint *uv_id = layers_combined_id;
+ uint *tangent_id = uv_id + uv_len;
+
+ /* initialize vertex format */
+ GPUVertFormat format = { 0 };
+
+ for (uint i = 0; i < uv_len; i++) {
+ const char *attrib_name = mesh_render_data_uv_layer_uuid_get(rdata, i);
+#if 0 /* these are clamped. Maybe use them as an option in the future */
+ uv_id[i] = GPU_vertformat_attr_add(&format, attrib_name, GPU_COMP_I16, 2, GPU_FETCH_INT_TO_FLOAT_UNIT);
+#else
+ uv_id[i] = GPU_vertformat_attr_add(&format, attrib_name, GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
+#endif
+ /* Auto Name */
+ attrib_name = mesh_render_data_uv_auto_layer_uuid_get(rdata, i);
+ GPU_vertformat_alias_add(&format, attrib_name);
+
+ if (i == rdata->cd.layers.uv_active) {
+ GPU_vertformat_alias_add(&format, "u");
+ }
}
- *r_pos_id = pos_id;
- return &format_pos;
+
+ for (uint i = 0; i < tangent_len; i++) {
+ const char *attrib_name = mesh_render_data_tangent_layer_uuid_get(rdata, i);
+#ifdef USE_COMP_MESH_DATA
+ tangent_id[i] = GPU_vertformat_attr_add(&format, attrib_name, GPU_COMP_I16, 4, GPU_FETCH_INT_TO_FLOAT_UNIT);
+#else
+ tangent_id[i] = GPU_vertformat_attr_add(&format, attrib_name, GPU_COMP_F32, 4, GPU_FETCH_FLOAT);
+#endif
+ if (i == rdata->cd.layers.tangent_active) {
+ GPU_vertformat_alias_add(&format, "t");
+ }
+ }
+
+ GPU_vertbuf_init_with_format(vbo, &format);
+ GPU_vertbuf_data_alloc(vbo, loops_len);
+
+ for (uint i = 0; i < uv_len; i++) {
+ GPU_vertbuf_attr_get_raw_data(vbo, uv_id[i], &uv_step[i]);
+ }
+ for (uint i = 0; i < tangent_len; i++) {
+ GPU_vertbuf_attr_get_raw_data(vbo, tangent_id[i], &tangent_step[i]);
+ }
+
+ if (rdata->edit_bmesh) {
+ BMesh *bm = rdata->edit_bmesh->bm;
+ BMIter iter_efa, iter_loop;
+ BMFace *efa;
+ BMLoop *loop;
+
+ BM_ITER_MESH (efa, &iter_efa, bm, BM_FACES_OF_MESH) {
+ BM_ITER_ELEM (loop, &iter_loop, efa, BM_LOOPS_OF_FACE) {
+ /* UVs */
+ for (uint j = 0; j < uv_len; j++) {
+ const uint layer_offset = rdata->cd.offset.uv[j];
+ const float *elem = ((MLoopUV *)BM_ELEM_CD_GET_VOID_P(loop, layer_offset))->uv;
+ copy_v2_v2(GPU_vertbuf_raw_step(&uv_step[j]), elem);
+ }
+ /* TANGENTs */
+ for (uint j = 0; j < tangent_len; j++) {
+ float (*layer_data)[4] = rdata->cd.layers.tangent[j];
+ const float *elem = layer_data[BM_elem_index_get(loop)];
+#ifdef USE_COMP_MESH_DATA
+ normal_float_to_short_v4(GPU_vertbuf_raw_step(&tangent_step[j]), elem);
+#else
+ copy_v4_v4(GPU_vertbuf_raw_step(&tangent_step[j]), elem);
+#endif
+ }
+ }
+ }
+ }
+ else {
+ for (uint loop = 0; loop < loops_len; loop++) {
+ /* UVs */
+ for (uint j = 0; j < uv_len; j++) {
+ const MLoopUV *layer_data = rdata->cd.layers.uv[j];
+ const float *elem = layer_data[loop].uv;
+ copy_v2_v2(GPU_vertbuf_raw_step(&uv_step[j]), elem);
+ }
+ /* TANGENTs */
+ for (uint j = 0; j < tangent_len; j++) {
+ float (*layer_data)[4] = rdata->cd.layers.tangent[j];
+ const float *elem = layer_data[loop];
+#ifdef USE_COMP_MESH_DATA
+ normal_float_to_short_v4(GPU_vertbuf_raw_step(&tangent_step[j]), elem);
+#else
+ copy_v4_v4(GPU_vertbuf_raw_step(&tangent_step[j]), elem);
+#endif
+ }
+ }
+ }
+
+#ifndef NDEBUG
+ /* Check all layers are write aligned. */
+ if (layers_combined_len > 0) {
+ int vbo_len_used = GPU_vertbuf_raw_used(&layers_combined_step[0]);
+ for (uint i = 0; i < layers_combined_len; i++) {
+ BLI_assert(vbo_len_used == GPU_vertbuf_raw_used(&layers_combined_step[i]));
+ }
+ }
+#endif
+
+#undef USE_COMP_MESH_DATA
}
-static GPUVertFormat *edit_mesh_overlay_nor_format(uint *r_vnor_id, uint *r_lnor_id)
+static void mesh_create_loop_vcol(MeshRenderData *rdata, GPUVertBuf *vbo)
{
- static GPUVertFormat format_nor = { 0 };
- static GPUVertFormat format_nor_loop = { 0 };
- static uint vnor_id, vnor_loop_id, lnor_id;
- if (format_nor.attr_len == 0) {
- vnor_id = GPU_vertformat_attr_add(&format_nor, "vnor", GPU_COMP_I10, 3, GPU_FETCH_INT_TO_FLOAT_UNIT);
- vnor_loop_id = GPU_vertformat_attr_add(&format_nor_loop, "vnor", GPU_COMP_I10, 3, GPU_FETCH_INT_TO_FLOAT_UNIT);
- lnor_id = GPU_vertformat_attr_add(&format_nor_loop, "lnor", GPU_COMP_I10, 3, GPU_FETCH_INT_TO_FLOAT_UNIT);
+ const uint loops_len = mesh_render_data_loops_len_get(rdata);
+ const uint vcol_len = rdata->cd.layers.vcol_len;
+
+ GPUVertBufRaw *vcol_step = BLI_array_alloca(vcol_step, vcol_len);
+ uint *vcol_id = BLI_array_alloca(vcol_id, vcol_len);
+
+ /* initialize vertex format */
+ GPUVertFormat format = { 0 };
+
+ for (uint i = 0; i < vcol_len; i++) {
+ const char *attrib_name = mesh_render_data_vcol_layer_uuid_get(rdata, i);
+ vcol_id[i] = GPU_vertformat_attr_add(&format, attrib_name, GPU_COMP_U8, 3, GPU_FETCH_INT_TO_FLOAT_UNIT);
+ /* Auto layer */
+ if (rdata->cd.layers.auto_vcol[i]) {
+ attrib_name = mesh_render_data_vcol_auto_layer_uuid_get(rdata, i);
+ GPU_vertformat_alias_add(&format, attrib_name);
+ }
+ if (i == rdata->cd.layers.vcol_active) {
+ GPU_vertformat_alias_add(&format, "c");
+ }
+ }
+
+ GPU_vertbuf_init_with_format(vbo, &format);
+ GPU_vertbuf_data_alloc(vbo, loops_len);
+
+ for (uint i = 0; i < vcol_len; i++) {
+ GPU_vertbuf_attr_get_raw_data(vbo, vcol_id[i], &vcol_step[i]);
}
- if (r_lnor_id) {
- *r_vnor_id = vnor_loop_id;
- *r_lnor_id = lnor_id;
- return &format_nor_loop;
+
+ if (rdata->edit_bmesh) {
+ BMesh *bm = rdata->edit_bmesh->bm;
+ BMIter iter_efa, iter_loop;
+ BMFace *efa;
+ BMLoop *loop;
+
+ BM_ITER_MESH (efa, &iter_efa, bm, BM_FACES_OF_MESH) {
+ BM_ITER_ELEM (loop, &iter_loop, efa, BM_LOOPS_OF_FACE) {
+ for (uint j = 0; j < vcol_len; j++) {
+ const uint layer_offset = rdata->cd.offset.vcol[j];
+ const uchar *elem = &((MLoopCol *)BM_ELEM_CD_GET_VOID_P(loop, layer_offset))->r;
+ copy_v3_v3_uchar(GPU_vertbuf_raw_step(&vcol_step[j]), elem);
+ }
+ }
+ }
}
else {
- *r_vnor_id = vnor_id;
- return &format_nor;
+ for (uint loop = 0; loop < loops_len; loop++) {
+ for (uint j = 0; j < vcol_len; j++) {
+ const MLoopCol *layer_data = rdata->cd.layers.vcol[j];
+ const uchar *elem = &layer_data[loop].r;
+ copy_v3_v3_uchar(GPU_vertbuf_raw_step(&vcol_step[j]), elem);
+ }
+ }
+ }
+
+#ifndef NDEBUG
+ /* Check all layers are write aligned. */
+ if (vcol_len > 0) {
+ int vbo_len_used = GPU_vertbuf_raw_used(&vcol_step[0]);
+ for (uint i = 0; i < vcol_len; i++) {
+ BLI_assert(vbo_len_used == GPU_vertbuf_raw_used(&vcol_step[i]));
+ }
+ }
+#endif
+
+#undef USE_COMP_MESH_DATA
+}
+
+static GPUVertBuf *mesh_batch_cache_get_vert_pos_and_nor_in_order(
+ MeshRenderData *rdata, MeshBatchCache *cache)
+{
+ BLI_assert(rdata->types & MR_DATATYPE_VERT);
+
+ if (cache->ordered.pos_nor == NULL) {
+ cache->ordered.pos_nor = GPU_vertbuf_create(GPU_USAGE_STATIC);
+ mesh_create_pos_and_nor(rdata, cache->ordered.pos_nor);
}
+
+ return cache->ordered.pos_nor;
}
-static GPUVertFormat *edit_mesh_overlay_data_format(uint *r_data_id)
+static GPUVertFormat *edit_mesh_pos_nor_format(uint *r_pos_id, uint *r_nor_id)
+{
+ static GPUVertFormat format_pos_nor = { 0 };
+ static uint pos_id, nor_id;
+ if (format_pos_nor.attr_len == 0) {
+ pos_id = GPU_vertformat_attr_add(&format_pos_nor, "pos", GPU_COMP_F32, 3, GPU_FETCH_FLOAT);
+ nor_id = GPU_vertformat_attr_add(&format_pos_nor, "vnor", GPU_COMP_I10, 3, GPU_FETCH_INT_TO_FLOAT_UNIT);
+ }
+ *r_pos_id = pos_id;
+ *r_nor_id = nor_id;
+ return &format_pos_nor;
+}
+
+static GPUVertFormat *edit_mesh_lnor_format(uint *r_lnor_id)
+{
+ static GPUVertFormat format_lnor = { 0 };
+ static uint lnor_id;
+ if (format_lnor.attr_len == 0) {
+ lnor_id = GPU_vertformat_attr_add(&format_lnor, "lnor", GPU_COMP_I10, 3, GPU_FETCH_INT_TO_FLOAT_UNIT);
+ }
+ *r_lnor_id = lnor_id;
+ return &format_lnor;
+}
+
+static GPUVertFormat *edit_mesh_data_format(uint *r_data_id)
{
static GPUVertFormat format_flag = { 0 };
static uint data_id;
if (format_flag.attr_len == 0) {
data_id = GPU_vertformat_attr_add(&format_flag, "data", GPU_COMP_U8, 4, GPU_FETCH_INT);
+ GPU_vertformat_triple_load(&format_flag);
}
*r_data_id = data_id;
return &format_flag;
}
-static void mesh_batch_cache_create_overlay_tri_buffers(
- MeshRenderData *rdata, MeshBatchCache *cache)
+static GPUVertFormat *edit_mesh_facedot_format(uint *r_pos_id, uint *r_nor_flag_id)
+{
+ static GPUVertFormat format_facedots = { 0 };
+ static uint pos_id, nor_flag_id;
+ if (format_facedots.attr_len == 0) {
+ pos_id = GPU_vertformat_attr_add(&format_facedots, "pos", GPU_COMP_F32, 3, GPU_FETCH_FLOAT);
+ nor_flag_id = GPU_vertformat_attr_add(&format_facedots, "norAndFlag", GPU_COMP_I10, 4, GPU_FETCH_INT_TO_FLOAT_UNIT);
+ }
+ *r_pos_id = pos_id;
+ *r_nor_flag_id = nor_flag_id;
+ return &format_facedots;
+}
+
+static void mesh_create_edit_tris_and_verts(
+ MeshRenderData *rdata,
+ GPUVertBuf *vbo_data, GPUVertBuf *vbo_pos_nor, GPUVertBuf *vbo_lnor, GPUIndexBuf *ibo_verts)
{
- BLI_assert(rdata->types & (MR_DATATYPE_VERT | MR_DATATYPE_LOOPTRI));
BMesh *bm = rdata->edit_bmesh->bm;
BMIter iter;
BMVert *ev;
const int tri_len = mesh_render_data_looptri_len_get_maybe_mapped(rdata);
-
- const int vbo_len_capacity = tri_len * 3;
- int vbo_len_used = 0;
+ int tri_len_used = 0;
int points_len = bm->totvert;
-
- /* Positions */
- GPUVertBuf *vbo_pos = NULL;
- static struct { uint pos, vnor, lnor, data; } attr_id;
- if (cache->ed_tri_pos == NULL) {
- vbo_pos = cache->ed_tri_pos =
- GPU_vertbuf_create_with_format(edit_mesh_overlay_pos_format(&attr_id.pos));
- GPU_vertbuf_data_alloc(vbo_pos, vbo_len_capacity);
- }
-
- /* Normals */
- GPUVertBuf *vbo_nor = NULL;
- if (cache->ed_tri_nor == NULL) {
- vbo_nor = cache->ed_tri_nor =
- GPU_vertbuf_create_with_format(edit_mesh_overlay_nor_format(&attr_id.vnor, &attr_id.lnor));
- GPU_vertbuf_data_alloc(vbo_nor, vbo_len_capacity);
- }
-
- /* Data */
- GPUVertBuf *vbo_data = NULL;
- if (cache->ed_tri_data == NULL) {
- vbo_data = cache->ed_tri_data =
- GPU_vertbuf_create_with_format(edit_mesh_overlay_data_format(&attr_id.data));
- GPU_vertbuf_data_alloc(vbo_data, vbo_len_capacity);
+ int verts_tri_len = tri_len * 3;
+ struct { uint pos, vnor, lnor, data; } attr_id;
+ GPUVertFormat *pos_nor_format = edit_mesh_pos_nor_format(&attr_id.pos, &attr_id.vnor);
+ GPUVertFormat *data_format = edit_mesh_data_format(&attr_id.data);
+ GPUVertFormat *lnor_format = edit_mesh_lnor_format(&attr_id.lnor);
+
+ /* Positions & Vert Normals */
+ if (DRW_TEST_ASSIGN_VBO(vbo_pos_nor)) {
+ GPU_vertbuf_init_with_format(vbo_pos_nor, pos_nor_format);
+ GPU_vertbuf_data_alloc(vbo_pos_nor, verts_tri_len);
+ }
+ /* Overlay data */
+ if (DRW_TEST_ASSIGN_VBO(vbo_data)) {
+ GPU_vertbuf_init_with_format(vbo_data, data_format);
+ GPU_vertbuf_data_alloc(vbo_data, verts_tri_len);
+ }
+ /* Loop Normals */
+ if (DRW_TEST_ASSIGN_VBO(vbo_lnor)) {
+ GPU_vertbuf_init_with_format(vbo_lnor, lnor_format);
+ GPU_vertbuf_data_alloc(vbo_lnor, verts_tri_len);
}
-
/* Verts IBO */
GPUIndexBufBuilder elb, *elbp = NULL;
- if (cache->ed_tri_verts == NULL) {
+ if (DRW_TEST_ASSIGN_IBO(ibo_verts)) {
elbp = &elb;
- GPU_indexbuf_init(elbp, GPU_PRIM_POINTS, points_len, vbo_len_capacity);
- }
-
- /* Clear tag */
- BM_ITER_MESH(ev, &iter, bm, BM_VERTS_OF_MESH) {
- BM_elem_flag_disable(ev, BM_ELEM_TAG);
+ GPU_indexbuf_init(elbp, GPU_PRIM_POINTS, points_len, verts_tri_len);
+ /* Clear tag */
+ BM_ITER_MESH(ev, &iter, bm, BM_VERTS_OF_MESH) {
+ BM_elem_flag_disable(ev, BM_ELEM_TAG);
+ }
}
if (rdata->mapped.use == false) {
for (int i = 0; i < tri_len; i++) {
const BMLoop **bm_looptri = (const BMLoop **)rdata->edit_bmesh->looptris[i];
if (!BM_elem_flag_test(bm_looptri[0]->f, BM_ELEM_HIDDEN)) {
- add_overlay_tri(
- rdata, vbo_pos, vbo_nor, vbo_data, elbp,
- attr_id.pos, attr_id.vnor, attr_id.lnor, attr_id.data,
- bm_looptri, vbo_len_used);
- vbo_len_used += 3;
+ add_edit_tri(rdata, vbo_pos_nor, vbo_lnor, vbo_data, elbp,
+ attr_id.pos, attr_id.vnor, attr_id.lnor, attr_id.data,
+ bm_looptri, tri_len_used);
+ tri_len_used += 3;
}
}
}
else {
Mesh *me_cage = rdata->mapped.me_cage;
+
+ /* TODO(fclem): Maybe move data generation to mesh_render_data_create() */
const MLoopTri *mlooptri = BKE_mesh_runtime_looptri_ensure(me_cage);
- if (!CustomData_has_layer(&me_cage->pdata, CD_NORMAL)) {
- /* TODO(campbell): this is quite an expensive operation for something
- * that's not used unless 'normal' display option is enabled. */
+ if (vbo_lnor && !CustomData_has_layer(&me_cage->pdata, CD_NORMAL)) {
BKE_mesh_ensure_normals_for_display(me_cage);
}
const float (*polynors)[3] = CustomData_get_layer(&me_cage->pdata, CD_NORMAL);
+ const float (*loopnors)[3] = CustomData_get_layer(&me_cage->ldata, CD_NORMAL);
+
for (int i = 0; i < tri_len; i++) {
const MLoopTri *mlt = &mlooptri[i];
const int p_orig = rdata->mapped.p_origindex[mlt->poly];
if (p_orig != ORIGINDEX_NONE) {
BMFace *efa = BM_face_at_index(bm, p_orig);
- if (!BM_elem_flag_test(efa, BM_ELEM_HIDDEN)) {
- add_overlay_tri_mapped(
- rdata, vbo_pos, vbo_nor, vbo_data, elbp,
- attr_id.pos, attr_id.vnor, attr_id.lnor, attr_id.data,
- efa, mlt, polynors[mlt->poly], vbo_len_used);
- vbo_len_used += 3;
+ if (add_edit_tri_mapped(rdata, vbo_pos_nor, vbo_lnor, vbo_data, elbp,
+ attr_id.pos, attr_id.vnor, attr_id.lnor, attr_id.data,
+ efa, mlt, polynors, loopnors, tri_len_used))
+ {
+ tri_len_used += 3;
}
}
}
}
+ /* Resize & Finish */
if (elbp != NULL) {
- cache->ed_tri_verts = GPU_indexbuf_build(elbp);
+ GPU_indexbuf_build_in_place(elbp, ibo_verts);
}
-
- /* Finish */
- if (vbo_len_used != vbo_len_capacity) {
- if (vbo_pos != NULL) {
- GPU_vertbuf_data_resize(vbo_pos, vbo_len_used);
+ if (tri_len_used != verts_tri_len) {
+ if (vbo_pos_nor != NULL) {
+ GPU_vertbuf_data_resize(vbo_pos_nor, tri_len_used);
}
- if (vbo_nor != NULL) {
- GPU_vertbuf_data_resize(vbo_nor, vbo_len_used);
+ if (vbo_lnor != NULL) {
+ GPU_vertbuf_data_resize(vbo_lnor, tri_len_used);
}
if (vbo_data != NULL) {
- GPU_vertbuf_data_resize(vbo_data, vbo_len_used);
+ GPU_vertbuf_data_resize(vbo_data, tri_len_used);
}
}
-
- /* Upload data early because we need to create the texture for it. */
- GPU_vertbuf_use(vbo_data);
- cache->ed_tri_data_tx = GPU_texture_create_from_vertbuf(vbo_data);
}
-static void mesh_batch_cache_create_overlay_ledge_buffers(
- MeshRenderData *rdata, MeshBatchCache *cache)
+static void mesh_create_edit_loose_edges(
+ MeshRenderData *rdata,
+ GPUVertBuf *vbo_data_ledges, GPUVertBuf *vbo_pos_nor_ledges)
{
- BLI_assert(rdata->types & (MR_DATATYPE_VERT | MR_DATATYPE_LOOPTRI));
-
- const int ledge_len = mesh_render_data_loose_edges_len_get_maybe_mapped(rdata);
+ BMesh *bm = rdata->edit_bmesh->bm;
+ const int loose_edge_len = mesh_render_data_loose_edges_len_get_maybe_mapped(rdata);
+ const int verts_ledges_len = loose_edge_len * 2;
+ int ledges_len_used = 0;
- const int vbo_len_capacity = ledge_len * 2;
- int vbo_len_used = 0;
+ struct { uint pos, vnor, data; } attr_id;
+ GPUVertFormat *pos_nor_format = edit_mesh_pos_nor_format(&attr_id.pos, &attr_id.vnor);
+ GPUVertFormat *data_format = edit_mesh_data_format(&attr_id.data);
- /* Positions */
- GPUVertBuf *vbo_pos = NULL;
- static struct { uint pos, vnor, data; } attr_id;
- if (cache->ed_ledge_pos == NULL) {
- vbo_pos = cache->ed_ledge_pos =
- GPU_vertbuf_create_with_format(edit_mesh_overlay_pos_format(&attr_id.pos));
- GPU_vertbuf_data_alloc(vbo_pos, vbo_len_capacity);
+ /* Positions & Vert Normals */
+ if (DRW_TEST_ASSIGN_VBO(vbo_pos_nor_ledges)) {
+ GPU_vertbuf_init_with_format(vbo_pos_nor_ledges, pos_nor_format);
+ GPU_vertbuf_data_alloc(vbo_pos_nor_ledges, verts_ledges_len);
}
-
- /* Normals */
- GPUVertBuf *vbo_nor = NULL;
- if (cache->ed_ledge_nor == NULL) {
- vbo_nor = cache->ed_ledge_nor =
- GPU_vertbuf_create_with_format(edit_mesh_overlay_nor_format(&attr_id.vnor, NULL));
- GPU_vertbuf_data_alloc(vbo_nor, vbo_len_capacity);
- }
-
- /* Data */
- GPUVertBuf *vbo_data = NULL;
- if (cache->ed_ledge_data == NULL) {
- vbo_data = cache->ed_ledge_data =
- GPU_vertbuf_create_with_format(edit_mesh_overlay_data_format(&attr_id.data));
- GPU_vertbuf_data_alloc(vbo_data, vbo_len_capacity);
+ /* Overlay data */
+ if (DRW_TEST_ASSIGN_VBO(vbo_data_ledges)) {
+ GPU_vertbuf_init_with_format(vbo_data_ledges, data_format);
+ GPU_vertbuf_data_alloc(vbo_data_ledges, verts_ledges_len);
}
if (rdata->mapped.use == false) {
- if (rdata->edit_bmesh) {
- BMesh *bm = rdata->edit_bmesh->bm;
- for (uint i = 0; i < ledge_len; i++) {
- const BMEdge *eed = BM_edge_at_index(bm, rdata->loose_edges[i]);
- add_overlay_loose_edge(
- rdata, vbo_pos, vbo_nor, vbo_data,
- attr_id.pos, attr_id.vnor, attr_id.data,
- eed, vbo_len_used);
- vbo_len_used += 2;
- }
+ for (uint i = 0; i < loose_edge_len; i++) {
+ const BMEdge *eed = BM_edge_at_index(bm, rdata->loose_edges[i]);
+ add_edit_loose_edge(rdata, vbo_pos_nor_ledges, vbo_data_ledges,
+ attr_id.pos, attr_id.vnor, attr_id.data,
+ eed, ledges_len_used);
+ ledges_len_used += 2;
}
}
else {
- BMesh *bm = rdata->edit_bmesh->bm;
Mesh *me_cage = rdata->mapped.me_cage;
const MVert *mvert = me_cage->mvert;
const MEdge *medge = me_cage->medge;
const int *e_origindex = rdata->mapped.e_origindex;
- for (uint i_iter = 0; i_iter < ledge_len; i_iter++) {
+
+ for (uint i_iter = 0; i_iter < loose_edge_len; i_iter++) {
const int i = rdata->mapped.loose_edges[i_iter];
const int e_orig = e_origindex[i];
- const MEdge *ed = &medge[i];
BMEdge *eed = BM_edge_at_index(bm, e_orig);
- add_overlay_loose_edge_mapped(
- rdata, vbo_pos, vbo_nor, vbo_data,
- attr_id.pos, attr_id.vnor, attr_id.data,
- eed, mvert, ed, vbo_len_used);
- vbo_len_used += 2;
- }
- }
-
- /* Finish */
- if (vbo_len_used != vbo_len_capacity) {
- if (vbo_pos != NULL) {
- GPU_vertbuf_data_resize(vbo_pos, vbo_len_used);
- }
- if (vbo_nor != NULL) {
- GPU_vertbuf_data_resize(vbo_nor, vbo_len_used);
- }
- if (vbo_data != NULL) {
- GPU_vertbuf_data_resize(vbo_data, vbo_len_used);
+ add_edit_loose_edge_mapped(rdata, vbo_pos_nor_ledges, vbo_data_ledges,
+ attr_id.pos, attr_id.vnor, attr_id.data,
+ eed, mvert, &medge[i], ledges_len_used);
+ ledges_len_used += 2;
}
}
+ BLI_assert(ledges_len_used == verts_ledges_len);
}
-static void mesh_batch_cache_create_overlay_lvert_buffers(
- MeshRenderData *rdata, MeshBatchCache *cache)
+static void mesh_create_edit_loose_verts(
+ MeshRenderData *rdata,
+ GPUVertBuf *vbo_data_lverts, GPUVertBuf *vbo_pos_nor_lverts)
{
- BLI_assert(rdata->types & (MR_DATATYPE_VERT | MR_DATATYPE_LOOPTRI));
-
BMesh *bm = rdata->edit_bmesh->bm;
- const int lvert_len = mesh_render_data_loose_verts_len_get_maybe_mapped(rdata);
-
- const int vbo_len_capacity = lvert_len;
- int vbo_len_used = 0;
+ const int loose_verts_len = mesh_render_data_loose_verts_len_get_maybe_mapped(rdata);
+ const int verts_lverts_len = loose_verts_len;
+ int lverts_len_used = 0;
- static struct { uint pos, vnor, data; } attr_id;
+ struct { uint pos, vnor, data; } attr_id;
+ GPUVertFormat *pos_nor_format = edit_mesh_pos_nor_format(&attr_id.pos, &attr_id.vnor);
+ GPUVertFormat *data_format = edit_mesh_data_format(&attr_id.data);
- /* Positions */
- GPUVertBuf *vbo_pos = NULL;
- if (cache->ed_lvert_pos == NULL) {
- vbo_pos = cache->ed_lvert_pos =
- GPU_vertbuf_create_with_format(edit_mesh_overlay_pos_format(&attr_id.pos));
- GPU_vertbuf_data_alloc(vbo_pos, vbo_len_capacity);
+ /* Positions & Vert Normals */
+ if (DRW_TEST_ASSIGN_VBO(vbo_pos_nor_lverts)) {
+ GPU_vertbuf_init_with_format(vbo_pos_nor_lverts, pos_nor_format);
+ GPU_vertbuf_data_alloc(vbo_pos_nor_lverts, verts_lverts_len);
}
-
- /* Normals */
- GPUVertBuf *vbo_nor = NULL;
- if (cache->ed_lvert_nor == NULL) {
- vbo_nor = cache->ed_lvert_nor =
- GPU_vertbuf_create_with_format(edit_mesh_overlay_nor_format(&attr_id.vnor, NULL));
- GPU_vertbuf_data_alloc(vbo_nor, vbo_len_capacity);
- }
-
- /* Data */
- GPUVertBuf *vbo_data = NULL;
- if (cache->ed_lvert_data == NULL) {
- vbo_data = cache->ed_lvert_data =
- GPU_vertbuf_create_with_format(edit_mesh_overlay_data_format(&attr_id.data));
- GPU_vertbuf_data_alloc(vbo_data, vbo_len_capacity);
+ /* Overlay data */
+ if (DRW_TEST_ASSIGN_VBO(vbo_data_lverts)) {
+ GPU_vertbuf_init_with_format(vbo_data_lverts, data_format);
+ GPU_vertbuf_data_alloc(vbo_data_lverts, verts_lverts_len);
}
if (rdata->mapped.use == false) {
- for (uint i = 0; i < lvert_len; i++) {
+ for (uint i = 0; i < loose_verts_len; i++) {
BMVert *eve = BM_vert_at_index(bm, rdata->loose_verts[i]);
- add_overlay_loose_vert(
- rdata, vbo_pos, vbo_nor, vbo_data,
- attr_id.pos, attr_id.vnor, attr_id.data,
- eve, vbo_len_used);
- vbo_len_used += 1;
+ add_edit_loose_vert(rdata, vbo_pos_nor_lverts, vbo_data_lverts,
+ attr_id.pos, attr_id.vnor, attr_id.data,
+ eve, lverts_len_used);
+ lverts_len_used += 1;
}
}
else {
Mesh *me_cage = rdata->mapped.me_cage;
const MVert *mvert = me_cage->mvert;
const int *v_origindex = rdata->mapped.v_origindex;
- for (uint i_iter = 0; i_iter < lvert_len; i_iter++) {
+
+ for (uint i_iter = 0; i_iter < loose_verts_len; i_iter++) {
const int i = rdata->mapped.loose_verts[i_iter];
const int v_orig = v_origindex[i];
- const MVert *mv = &mvert[i];
BMVert *eve = BM_vert_at_index(bm, v_orig);
- add_overlay_loose_vert_mapped(
- rdata, vbo_pos, vbo_nor, vbo_data,
- attr_id.pos, attr_id.vnor, attr_id.data,
- eve, mv, vbo_len_used);
- vbo_len_used += 1;
- }
- }
-
- /* Finish */
- if (vbo_len_used != vbo_len_capacity) {
- if (vbo_pos != NULL) {
- GPU_vertbuf_data_resize(vbo_pos, vbo_len_used);
- }
- if (vbo_nor != NULL) {
- GPU_vertbuf_data_resize(vbo_nor, vbo_len_used);
+ add_edit_loose_vert_mapped(rdata, vbo_pos_nor_lverts, vbo_data_lverts,
+ attr_id.pos, attr_id.vnor, attr_id.data,
+ eve, &mvert[i], lverts_len_used);
+ lverts_len_used += 1;
}
- if (vbo_data != NULL) {
- GPU_vertbuf_data_resize(vbo_data, vbo_len_used);
- }
- }
-}
-
-/* Position */
-static GPUVertBuf *mesh_batch_cache_get_edit_tri_pos(
- MeshRenderData *rdata, MeshBatchCache *cache)
-{
- BLI_assert(rdata->types & MR_DATATYPE_VERT);
-
- if (cache->ed_tri_pos == NULL) {
- mesh_batch_cache_create_overlay_tri_buffers(rdata, cache);
}
-
- return cache->ed_tri_pos;
+ BLI_assert(lverts_len_used == verts_lverts_len);
}
-static GPUVertBuf *mesh_batch_cache_get_edit_ledge_pos(
- MeshRenderData *rdata, MeshBatchCache *cache)
+static void mesh_create_edit_facedots(
+ MeshRenderData *rdata,
+ GPUVertBuf *vbo_pos_nor_data_facedots)
{
- BLI_assert(rdata->types & MR_DATATYPE_VERT);
+ const int poly_len = mesh_render_data_polys_len_get_maybe_mapped(rdata);
+ const int verts_facedot_len = poly_len;
+ int facedot_len_used = 0;
- if (cache->ed_ledge_pos == NULL) {
- if (rdata->mapped.supported) {
- rdata->mapped.use = true;
- }
- mesh_batch_cache_create_overlay_ledge_buffers(rdata, cache);
- }
-
- return cache->ed_ledge_pos;
-}
+ struct { uint fdot_pos, fdot_nor_flag; } attr_id;
+ GPUVertFormat *facedot_format = edit_mesh_facedot_format(&attr_id.fdot_pos, &attr_id.fdot_nor_flag);
-static GPUVertBuf *mesh_batch_cache_get_edit_lvert_pos(
- MeshRenderData *rdata, MeshBatchCache *cache)
-{
- BLI_assert(rdata->types & MR_DATATYPE_VERT);
-
- if (cache->ed_lvert_pos == NULL) {
- if (rdata->mapped.supported) {
- rdata->mapped.use = true;
- }
- mesh_batch_cache_create_overlay_lvert_buffers(rdata, cache);
- }
-
- return cache->ed_lvert_pos;
-}
-
-/* Indices */
-static GPUIndexBuf *mesh_batch_cache_get_edit_tri_indices(
- MeshRenderData *rdata, MeshBatchCache *cache)
-{
- BLI_assert(rdata->types & MR_DATATYPE_VERT);
-
- if (cache->ed_tri_verts == NULL) {
- mesh_batch_cache_create_overlay_tri_buffers(rdata, cache);
- }
-
- return cache->ed_tri_verts;
-}
-
-/* Normal */
-static GPUVertBuf *mesh_batch_cache_get_edit_tri_nor(
- MeshRenderData *rdata, MeshBatchCache *cache)
-{
- BLI_assert(rdata->types & MR_DATATYPE_VERT);
-
- if (cache->ed_tri_nor == NULL) {
- if (rdata->mapped.supported) {
- rdata->mapped.use = true;
+ if (DRW_TEST_ASSIGN_VBO(vbo_pos_nor_data_facedots)) {
+ GPU_vertbuf_init_with_format(vbo_pos_nor_data_facedots, facedot_format);
+ GPU_vertbuf_data_alloc(vbo_pos_nor_data_facedots, verts_facedot_len);
+ /* TODO(fclem): Maybe move data generation to mesh_render_data_create() */
+ if (rdata->edit_bmesh) {
+ if (rdata->edit_data && rdata->edit_data->vertexCos != NULL) {
+ BKE_editmesh_cache_ensure_poly_normals(rdata->edit_bmesh, rdata->edit_data);
+ BKE_editmesh_cache_ensure_poly_centers(rdata->edit_bmesh, rdata->edit_data);
+ }
}
- mesh_batch_cache_create_overlay_tri_buffers(rdata, cache);
}
- return cache->ed_tri_nor;
-}
-
-static GPUVertBuf *mesh_batch_cache_get_edit_ledge_nor(
- MeshRenderData *rdata, MeshBatchCache *cache)
-{
- BLI_assert(rdata->types & MR_DATATYPE_VERT);
-
- if (cache->ed_ledge_nor == NULL) {
- if (rdata->mapped.supported) {
- rdata->mapped.use = true;
+ if (rdata->mapped.use == false) {
+ for (int i = 0; i < poly_len; i++) {
+ if (add_edit_facedot(rdata, vbo_pos_nor_data_facedots,
+ attr_id.fdot_pos, attr_id.fdot_nor_flag,
+ i, facedot_len_used))
+ {
+ facedot_len_used += 1;
+ }
}
- mesh_batch_cache_create_overlay_ledge_buffers(rdata, cache);
}
-
- return cache->ed_ledge_nor;
-}
-
-static GPUVertBuf *mesh_batch_cache_get_edit_lvert_nor(
- MeshRenderData *rdata, MeshBatchCache *cache)
-{
- BLI_assert(rdata->types & MR_DATATYPE_VERT);
-
- if (cache->ed_lvert_nor == NULL) {
- if (rdata->mapped.supported) {
- rdata->mapped.use = true;
+ else {
+#if 0 /* TODO(fclem): Mapped facedots are not following the original face. */
+ Mesh *me_cage = rdata->mapped.me_cage;
+ const MVert *mvert = me_cage->mvert;
+ const MEdge *medge = me_cage->medge;
+ const int *e_origindex = rdata->mapped.e_origindex;
+ const int *v_origindex = rdata->mapped.v_origindex;
+#endif
+ for (int i = 0; i < poly_len; i++) {
+ if (add_edit_facedot_mapped(rdata, vbo_pos_nor_data_facedots,
+ attr_id.fdot_pos, attr_id.fdot_nor_flag,
+ i, facedot_len_used))
+ {
+ facedot_len_used += 1;
+ }
}
- mesh_batch_cache_create_overlay_lvert_buffers(rdata, cache);
}
- return cache->ed_lvert_nor;
-}
-
-/* Data */
-static GPUVertBuf *mesh_batch_cache_get_edit_tri_data(
- MeshRenderData *rdata, MeshBatchCache *cache)
-{
- BLI_assert(rdata->types & MR_DATATYPE_VERT);
-
- if (cache->ed_tri_data == NULL) {
- mesh_batch_cache_create_overlay_tri_buffers(rdata, cache);
- }
-
- return cache->ed_tri_data;
-}
-
-static GPUVertBuf *mesh_batch_cache_get_edit_ledge_data(
- MeshRenderData *rdata, MeshBatchCache *cache)
-{
- BLI_assert(rdata->types & MR_DATATYPE_VERT);
-
- if (cache->ed_ledge_data == NULL) {
- if (rdata->mapped.supported) {
- rdata->mapped.use = true;
+ /* Resize & Finish */
+ if (facedot_len_used != verts_facedot_len) {
+ if (vbo_pos_nor_data_facedots != NULL) {
+ GPU_vertbuf_data_resize(vbo_pos_nor_data_facedots, facedot_len_used);
}
- mesh_batch_cache_create_overlay_ledge_buffers(rdata, cache);
}
-
- return cache->ed_ledge_data;
}
-static GPUVertBuf *mesh_batch_cache_get_edit_lvert_data(
- MeshRenderData *rdata, MeshBatchCache *cache)
-{
- BLI_assert(rdata->types & MR_DATATYPE_VERT);
-
- if (cache->ed_lvert_data == NULL) {
- if (rdata->mapped.supported) {
- rdata->mapped.use = true;
- }
- mesh_batch_cache_create_overlay_lvert_buffers(rdata, cache);
- }
-
- return cache->ed_lvert_data;
-}
+/* Indices */
static GPUIndexBuf *mesh_batch_cache_get_edges_in_order(MeshRenderData *rdata, MeshBatchCache *cache)
{
@@ -4173,11 +4125,14 @@ static GPUIndexBuf *mesh_batch_cache_get_edges_adjacency(MeshRenderData *rdata,
}
#undef NO_EDGE
-static EdgeHash *create_looptri_edge_adjacency_hash(MeshRenderData *rdata)
+static EdgeHash *create_looptri_edge_adjacency_hash(MeshRenderData *rdata, EdgeAdjacentVerts **r_adj_data)
{
const int tri_len = mesh_render_data_looptri_len_get(rdata);
/* Create adjacency info in looptri */
EdgeHash *eh = BLI_edgehash_new_ex(__func__, tri_len * 3);
+ /* TODO allocate less memory (based on edge count) */
+ EdgeAdjacentVerts *adj_data = MEM_mallocN(tri_len * 3 * sizeof(EdgeAdjacentVerts), __func__);
+ *r_adj_data = adj_data;
/* Create edges for each pair of triangles sharing an edge. */
for (int i = 0; i < tri_len; i++) {
for (int e = 0; e < 3; e++) {
@@ -4202,7 +4157,7 @@ static EdgeHash *create_looptri_edge_adjacency_hash(MeshRenderData *rdata)
EdgeAdjacentVerts **eav;
bool value_is_init = BLI_edgehash_ensure_p(eh, v1, v2, (void ***)&eav);
if (!value_is_init) {
- *eav = MEM_mallocN(sizeof(**eav), "EdgeAdjacentVerts");
+ *eav = adj_data++;
(*eav)->vert_index[0] = v0;
(*eav)->vert_index[1] = -1;
}
@@ -4219,24 +4174,30 @@ static EdgeHash *create_looptri_edge_adjacency_hash(MeshRenderData *rdata)
return eh;
}
-static GPUVertBuf *mesh_batch_cache_create_edges_overlay_texture_buf(MeshRenderData *rdata)
+static void mesh_create_wireframe_data_tess(MeshRenderData *rdata, GPUVertBuf *vbo)
{
- const int tri_len = mesh_render_data_looptri_len_get(rdata);
+ static uint data_id;
+ static GPUVertFormat format = {0};
+ if (format.attr_len == 0) {
+ data_id = GPU_vertformat_attr_add(&format, "wd", GPU_COMP_U8, 1, GPU_FETCH_INT_TO_FLOAT_UNIT);
+ GPU_vertformat_triple_load(&format);
+ }
- GPUVertFormat format = {0};
- uint index_id = GPU_vertformat_attr_add(&format, "index", GPU_COMP_U32, 1, GPU_FETCH_INT);
- GPUVertBuf *vbo = GPU_vertbuf_create_with_format(&format);
+ GPU_vertbuf_init_with_format(vbo, &format);
+ const int tri_len = mesh_render_data_looptri_len_get(rdata);
int vbo_len_capacity = tri_len * 3;
GPU_vertbuf_data_alloc(vbo, vbo_len_capacity);
int vidx = 0;
EdgeHash *eh = NULL;
- eh = create_looptri_edge_adjacency_hash(rdata);
+ EdgeAdjacentVerts *adj_data = NULL;
+ eh = create_looptri_edge_adjacency_hash(rdata, &adj_data);
for (int i = 0; i < tri_len; i++) {
- bool edge_is_real[3];
+ uchar vdata[3] = {0, 0, 0};
+ const MVert *mvert = rdata->mvert;
const MEdge *medge = rdata->medge;
const MLoop *mloop = rdata->mloop;
const MLoopTri *mlt = rdata->mlooptri + i;
@@ -4244,110 +4205,69 @@ static GPUVertBuf *mesh_batch_cache_create_edges_overlay_texture_buf(MeshRenderD
int j, j_next;
for (j = 2, j_next = 0; j_next < 3; j = j_next++) {
const MEdge *ed = &medge[mloop[mlt->tri[j]].e];
- const uint tri_edge[2] = {mloop[mlt->tri[j]].v, mloop[mlt->tri[j_next]].v};
- const bool is_edge_real = (
- ((ed->v1 == tri_edge[0]) && (ed->v2 == tri_edge[1])) ||
- ((ed->v1 == tri_edge[1]) && (ed->v2 == tri_edge[0])));
- edge_is_real[j] = is_edge_real;
- }
+ const uint tri_edge[2] = {mloop[mlt->tri[j]].v, mloop[mlt->tri[j_next]].v};
- for (int e = 0; e < 3; e++) {
- int v0 = mloop[mlt->tri[e]].v;
- int v1 = mloop[mlt->tri[(e + 1) % 3]].v;
- EdgeAdjacentVerts *eav = BLI_edgehash_lookup(eh, v0, v1);
- uint value = (uint)v0;
- /* Real edge */
- if (edge_is_real[e]) {
- value |= (1 << 30);
- }
- /* Non-manifold edge */
- if (eav->vert_index[1] == -1) {
- value |= (1u << 31);
+ if ((((ed->v1 == tri_edge[0]) && (ed->v2 == tri_edge[1])) ||
+ ((ed->v1 == tri_edge[1]) && (ed->v2 == tri_edge[0]))))
+ {
+ /* Real edge. */
+ /* Temp Workaround. If a mesh has a subdiv mod we should not
+ * compute the edge sharpness. Instead, we just mix both for now. */
+ vdata[j] = ((ed->flag & ME_EDGERENDER) != 0) ? 0xFD : 0xFE;
}
- GPU_vertbuf_attr_set(vbo, index_id, vidx++, &value);
}
- }
-
- BLI_edgehash_free(eh, MEM_freeN);
- int vbo_len_used = vidx;
+ /* If at least one edge is real. */
+ if (vdata[0] || vdata[1] || vdata[2]) {
+ float fnor[3];
+ normal_tri_v3(fnor,
+ mvert[mloop[mlt->tri[0]].v].co,
+ mvert[mloop[mlt->tri[1]].v].co,
+ mvert[mloop[mlt->tri[2]].v].co);
- if (vbo_len_capacity != vbo_len_used) {
- GPU_vertbuf_data_resize(vbo, vbo_len_used);
- }
-
- return vbo;
-}
-
-static GPUTexture *mesh_batch_cache_get_edges_overlay_texture_buf(MeshRenderData *rdata, MeshBatchCache *cache)
-{
- BLI_assert(rdata->types & (MR_DATATYPE_VERT | MR_DATATYPE_EDGE | MR_DATATYPE_LOOP | MR_DATATYPE_LOOPTRI));
-
- BLI_assert(rdata->edit_bmesh == NULL); /* Not supported in edit mode */
-
- if (cache->edges_face_overlay_tx != NULL) {
- return cache->edges_face_overlay_tx;
- }
-
- GPUVertBuf *vbo = cache->edges_face_overlay = mesh_batch_cache_create_edges_overlay_texture_buf(rdata);
-
- /* Upload data early because we need to create the texture for it. */
- GPU_vertbuf_use(vbo);
- cache->edges_face_overlay_tx = GPU_texture_create_from_vertbuf(vbo);
- cache->edges_face_overlay_tri_count = vbo->vertex_alloc / 3;
-
- return cache->edges_face_overlay_tx;
-}
-
-static GPUTexture *mesh_batch_cache_get_vert_pos_and_nor_in_order_buf(MeshRenderData *rdata, MeshBatchCache *cache)
-{
- BLI_assert(rdata->types & (MR_DATATYPE_VERT | MR_DATATYPE_EDGE | MR_DATATYPE_LOOP | MR_DATATYPE_LOOPTRI));
-
- if (cache->pos_in_order_tx == NULL) {
- GPUVertBuf *pos_in_order = mesh_batch_cache_get_vert_pos_and_nor_in_order(rdata, cache);
- GPU_vertbuf_use(pos_in_order); /* Upload early for buffer texture creation. */
- cache->pos_in_order_tx = GPU_texture_create_buffer(GPU_R32F, pos_in_order->vbo_id);
- }
-
- return cache->pos_in_order_tx;
-}
-
-static GPUIndexBuf *mesh_batch_cache_get_triangles_in_order(MeshRenderData *rdata, MeshBatchCache *cache)
-{
- BLI_assert(rdata->types & (MR_DATATYPE_VERT | MR_DATATYPE_LOOPTRI));
-
- if (cache->triangles_in_order == NULL) {
- const int vert_len = mesh_render_data_verts_len_get(rdata);
- const int tri_len = mesh_render_data_looptri_len_get(rdata);
-
- GPUIndexBufBuilder elb;
- GPU_indexbuf_init(&elb, GPU_PRIM_TRIS, tri_len, vert_len);
-
- if (rdata->edit_bmesh) {
- for (int i = 0; i < tri_len; i++) {
- const BMLoop **ltri = (const BMLoop **)rdata->edit_bmesh->looptris[i];
- if (!BM_elem_flag_test(ltri[0]->f, BM_ELEM_HIDDEN)) {
- for (uint tri_corner = 0; tri_corner < 3; tri_corner++) {
- GPU_indexbuf_add_generic_vert(&elb, BM_elem_index_get(ltri[tri_corner]->v));
+ for (int e = 0; e < 3; e++) {
+ /* Non-real edge. */
+ if (vdata[e] == 0) {
+ continue;
+ }
+ int v0 = mloop[mlt->tri[e]].v;
+ int v1 = mloop[mlt->tri[(e + 1) % 3]].v;
+ EdgeAdjacentVerts *eav = BLI_edgehash_lookup(eh, v0, v1);
+ /* If Non Manifold. */
+ if (eav->vert_index[1] == -1) {
+ vdata[e] = 0xFF;
+ }
+ else if (vdata[e] == 0xFD) {
+ int v2 = mloop[mlt->tri[(e + 2) % 3]].v;
+ /* Select the right opposite vertex */
+ v2 = (eav->vert_index[1] == v2) ? eav->vert_index[0] : eav->vert_index[1];
+ float fnor_adj[3];
+ normal_tri_v3(fnor_adj,
+ mvert[v1].co,
+ mvert[v0].co,
+ mvert[v2].co);
+ float fac = dot_v3v3(fnor_adj, fnor);
+ fac = fac * fac * 50.0f - 49.0f;
+ CLAMP(fac, 0.0f, 0.999f);
+ /* Shorten the range to make the non-ME_EDGERENDER fade first.
+ * Add one because 0x0 is no edges. */
+ vdata[e] = (uchar)(0xDF * fac) + 1;
+ if (vdata[e] < 0.999f) {
+ /* TODO construct fast face wire index buffer. */
}
}
}
}
- else {
- for (int i = 0; i < tri_len; i++) {
- const MLoopTri *mlt = &rdata->mlooptri[i];
- for (uint tri_corner = 0; tri_corner < 3; tri_corner++) {
- GPU_indexbuf_add_generic_vert(&elb, mlt->tri[tri_corner]);
- }
- }
+
+ for (int e = 0; e < 3; e++) {
+ GPU_vertbuf_attr_set(vbo, data_id, vidx++, &vdata[e]);
}
- cache->triangles_in_order = GPU_indexbuf_build(&elb);
}
- return cache->triangles_in_order;
+ BLI_edgehash_free(eh, NULL);
+ MEM_freeN(adj_data);
}
-
static GPUIndexBuf *mesh_batch_cache_get_loose_edges(MeshRenderData *rdata, MeshBatchCache *cache)
{
BLI_assert(rdata->types & (MR_DATATYPE_VERT | MR_DATATYPE_LOOPTRI));
@@ -4399,244 +4319,179 @@ static GPUIndexBuf *mesh_batch_cache_get_loose_edges(MeshRenderData *rdata, Mesh
return cache->ledges_in_order;
}
-static GPUIndexBuf **mesh_batch_cache_get_triangles_in_order_split_by_material(
- MeshRenderData *rdata, MeshBatchCache *cache,
- /* Special case when drawing final evaluated mesh in editmode, so hidden faces are ignored. */
- BMesh *bm_mapped, const int *p_origindex_mapped)
+static void mesh_create_surf_tris(MeshRenderData *rdata, GPUIndexBuf *ibo, const bool use_hide)
{
- BLI_assert(rdata->types & (MR_DATATYPE_VERT | MR_DATATYPE_POLY));
-
- if (cache->shaded_triangles_in_order == NULL) {
- const int poly_len = mesh_render_data_polys_len_get(rdata);
- const int tri_len = mesh_render_data_looptri_len_get(rdata);
- const int mat_len = mesh_render_data_mat_len_get(rdata);
+ const int vert_len = mesh_render_data_verts_len_get_maybe_mapped(rdata);
+ const int tri_len = mesh_render_data_looptri_len_get(rdata);
- int *mat_tri_len = MEM_callocN(sizeof(*mat_tri_len) * mat_len, __func__);
- cache->shaded_triangles_in_order = MEM_callocN(sizeof(*cache->shaded_triangles) * mat_len, __func__);
- GPUIndexBufBuilder *elb = MEM_callocN(sizeof(*elb) * mat_len, __func__);
+ GPUIndexBufBuilder elb;
+ GPU_indexbuf_init(&elb, GPU_PRIM_TRIS, tri_len, vert_len * 3);
- /* Note that polygons (not triangles) are used here.
- * This OK because result is _guaranteed_ to be the same. */
+ if (rdata->mapped.use == false) {
if (rdata->edit_bmesh) {
- BMesh *bm = rdata->edit_bmesh->bm;
- BMIter fiter;
- BMFace *efa;
-
- BM_ITER_MESH(efa, &fiter, bm, BM_FACES_OF_MESH) {
- if (!BM_elem_flag_test(efa, BM_ELEM_HIDDEN)) {
- const short ma_id = efa->mat_nr < mat_len ? efa->mat_nr : 0;
- mat_tri_len[ma_id] += (efa->len - 2);
+ for (int i = 0; i < tri_len; i++) {
+ const BMLoop **bm_looptri = (const BMLoop **)rdata->edit_bmesh->looptris[i];
+ const BMFace *bm_face = bm_looptri[0]->f;
+ /* use_hide always for edit-mode */
+ if (BM_elem_flag_test(bm_face, BM_ELEM_HIDDEN)) {
+ continue;
}
- }
- }
- else if (bm_mapped == NULL) {
- for (uint i = 0; i < poly_len; i++) {
- const MPoly *mp = &rdata->mpoly[i]; ;
- const short ma_id = mp->mat_nr < mat_len ? mp->mat_nr : 0;
- mat_tri_len[ma_id] += (mp->totloop - 2);
+ GPU_indexbuf_add_tri_verts(&elb, BM_elem_index_get(bm_looptri[0]->v),
+ BM_elem_index_get(bm_looptri[1]->v),
+ BM_elem_index_get(bm_looptri[2]->v));
}
}
else {
- BM_mesh_elem_table_ensure(bm_mapped, BM_FACE);
- for (uint i = 0; i < poly_len; i++) {
- const int p_orig = p_origindex_mapped[i];
- if ((p_orig == ORIGINDEX_NONE) ||
- !BM_elem_flag_test(BM_face_at_index(bm_mapped, p_orig), BM_ELEM_HIDDEN))
- {
- const MPoly *mp = &rdata->mpoly[i]; ;
- const short ma_id = mp->mat_nr < mat_len ? mp->mat_nr : 0;
- mat_tri_len[ma_id] += (mp->totloop - 2);
+ const MLoop *loops = rdata->mloop;
+ for (int i = 0; i < tri_len; i++) {
+ const MLoopTri *mlt = &rdata->mlooptri[i];
+ const MPoly *mp = &rdata->mpoly[mlt->poly];
+ if (use_hide && (mp->flag & ME_HIDE)) {
+ continue;
}
+ GPU_indexbuf_add_tri_verts(&elb, loops[mlt->tri[0]].v, loops[mlt->tri[1]].v, loops[mlt->tri[2]].v);
}
-
}
+ }
+ else {
+ /* Note: mapped doesn't support lnors yet. */
+ BMesh *bm = rdata->edit_bmesh->bm;
+ Mesh *me_cage = rdata->mapped.me_cage;
- /* Init ELBs. */
- for (int i = 0; i < mat_len; i++) {
- GPU_indexbuf_init(&elb[i], GPU_PRIM_TRIS, mat_tri_len[i], tri_len * 3);
+ const MLoop *loops = rdata->mloop;
+ const MLoopTri *mlooptri = BKE_mesh_runtime_looptri_ensure(me_cage);
+ for (int i = 0; i < tri_len; i++) {
+ const MLoopTri *mlt = &mlooptri[i];
+ const int p_orig = rdata->mapped.p_origindex[mlt->poly];
+ if (p_orig != ORIGINDEX_NONE) {
+ /* Assume 'use_hide' */
+ BMFace *efa = BM_face_at_index(bm, p_orig);
+ if (!BM_elem_flag_test(efa, BM_ELEM_HIDDEN)) {
+ GPU_indexbuf_add_tri_verts(&elb, loops[mlt->tri[0]].v, loops[mlt->tri[1]].v, loops[mlt->tri[2]].v);
+ }
+ }
}
+ }
- /* Populate ELBs. */
- uint nidx = 0;
+ GPU_indexbuf_build_in_place(&elb, ibo);
+}
+
+static void mesh_create_loops_lines(
+ MeshRenderData *rdata, GPUIndexBuf *ibo, const bool use_hide)
+{
+ const int loop_len = mesh_render_data_loops_len_get(rdata);
+ const int poly_len = mesh_render_data_polys_len_get(rdata);
+
+ GPUIndexBufBuilder elb;
+ GPU_indexbuf_init_ex(&elb, GPU_PRIM_LINE_STRIP, loop_len + poly_len * 2, loop_len, true);
+
+ uint v_index = 0;
+ if (rdata->mapped.use == false) {
if (rdata->edit_bmesh) {
BMesh *bm = rdata->edit_bmesh->bm;
- BMIter fiter;
- BMFace *efa;
+ BMIter iter;
+ BMFace *bm_face;
- BM_ITER_MESH(efa, &fiter, bm, BM_FACES_OF_MESH) {
- if (!BM_elem_flag_test(efa, BM_ELEM_HIDDEN)) {
- const short ma_id = efa->mat_nr < mat_len ? efa->mat_nr : 0;
- for (int j = 2; j < efa->len; j++) {
- GPU_indexbuf_add_tri_verts(&elb[ma_id], nidx + 0, nidx + 1, nidx + 2);
- nidx += 3;
+ BM_ITER_MESH (bm_face, &iter, bm, BM_FACES_OF_MESH) {
+ /* use_hide always for edit-mode */
+ if (!BM_elem_flag_test(bm_face, BM_ELEM_HIDDEN)) {
+ for (int i; i < bm_face->len; i++) {
+ GPU_indexbuf_add_generic_vert(&elb, v_index + i);
}
+ /* Finish loop and restart primitive. */
+ GPU_indexbuf_add_generic_vert(&elb, v_index);
+ GPU_indexbuf_add_primitive_restart(&elb);
}
- }
- }
- else if (bm_mapped == NULL) {
- for (uint i = 0; i < poly_len; i++) {
- const MPoly *mp = &rdata->mpoly[i]; ;
- const short ma_id = mp->mat_nr < mat_len ? mp->mat_nr : 0;
- for (int j = 2; j < mp->totloop; j++) {
- GPU_indexbuf_add_tri_verts(&elb[ma_id], nidx + 0, nidx + 1, nidx + 2);
- nidx += 3;
- }
+ v_index += bm_face->len;
}
}
else {
- for (uint i = 0; i < poly_len; i++) {
- const int p_orig = p_origindex_mapped[i];
- const MPoly *mp = &rdata->mpoly[i];
- if ((p_orig == ORIGINDEX_NONE) ||
- !BM_elem_flag_test(BM_face_at_index(bm_mapped, p_orig), BM_ELEM_HIDDEN))
- {
- const short ma_id = mp->mat_nr < mat_len ? mp->mat_nr : 0;
- for (int j = 2; j < mp->totloop; j++) {
- GPU_indexbuf_add_tri_verts(&elb[ma_id], nidx + 0, nidx + 1, nidx + 2);
- nidx += 3;
+ for (int poly = 0; poly < poly_len; poly++) {
+ const MPoly *mp = &rdata->mpoly[poly];
+ if (!(use_hide && (mp->flag & ME_HIDE))) {
+ const int loopend = mp->loopstart + mp->totloop;
+ for (int j = mp->loopstart; j < loopend; j++) {
+ GPU_indexbuf_add_generic_vert(&elb, j);
}
+ /* Finish loop and restart primitive. */
+ GPU_indexbuf_add_generic_vert(&elb, mp->loopstart);
+ GPU_indexbuf_add_primitive_restart(&elb);
}
- else {
- nidx += (mp->totloop - 2) * 3;
- }
+ v_index += mp->totloop;
}
}
-
- /* Build ELBs. */
- for (int i = 0; i < mat_len; i++) {
- cache->shaded_triangles_in_order[i] = GPU_indexbuf_build(&elb[i]);
- }
-
- MEM_freeN(mat_tri_len);
- MEM_freeN(elb);
+ }
+ else {
+ /* Implement ... eventually if needed. */
+ BLI_assert(0);
}
- return cache->shaded_triangles_in_order;
+ GPU_indexbuf_build_in_place(&elb, ibo);
}
-static GPUVertBuf *mesh_create_edge_pos_with_sel(
- MeshRenderData *rdata, bool use_wire, bool use_select_bool)
+static void mesh_create_loops_tris(
+ MeshRenderData *rdata, GPUIndexBuf **ibo, int ibo_len, const bool use_hide)
{
- BLI_assert(rdata->types & (MR_DATATYPE_VERT | MR_DATATYPE_EDGE | MR_DATATYPE_POLY | MR_DATATYPE_LOOP));
- BLI_assert(rdata->edit_bmesh == NULL);
-
- GPUVertBuf *vbo;
- {
- uint vidx = 0, cidx = 0;
-
- static GPUVertFormat format = { 0 };
- static struct { uint pos, sel; } attr_id;
- if (format.attr_len == 0) {
- attr_id.pos = GPU_vertformat_attr_add(&format, "pos", GPU_COMP_F32, 3, GPU_FETCH_FLOAT);
- attr_id.sel = GPU_vertformat_attr_add(&format, "select", GPU_COMP_U8, 1, GPU_FETCH_INT);
- }
-
- const int edge_len = mesh_render_data_edges_len_get(rdata);
-
- vbo = GPU_vertbuf_create_with_format(&format);
-
- const int vbo_len_capacity = edge_len * 2;
- int vbo_len_used = 0;
- GPU_vertbuf_data_alloc(vbo, vbo_len_capacity);
+ const int loop_len = mesh_render_data_loops_len_get(rdata);
+ const int tri_len = mesh_render_data_looptri_len_get(rdata);
- if (use_select_bool) {
- mesh_render_data_ensure_edge_select_bool(rdata, use_wire);
- }
- bool *edge_select_bool = use_select_bool ? rdata->edge_select_bool : NULL;
+ GPUIndexBufBuilder *elb = BLI_array_alloca(elb, ibo_len);
- for (int i = 0; i < edge_len; i++) {
- const MEdge *ed = &rdata->medge[i];
+ for (int i = 0; i < ibo_len; ++i) {
+ /* TODO alloc minmum necessary. */
+ GPU_indexbuf_init(&elb[i], GPU_PRIM_TRIS, tri_len, loop_len * 3);
+ }
- uchar edge_vert_sel;
- if (use_select_bool && edge_select_bool[i]) {
- edge_vert_sel = true;
- }
- else if (use_wire) {
- edge_vert_sel = false;
- }
- else {
- continue;
+ if (rdata->mapped.use == false) {
+ if (rdata->edit_bmesh) {
+ for (int i = 0; i < tri_len; i++) {
+ const BMLoop **bm_looptri = (const BMLoop **)rdata->edit_bmesh->looptris[i];
+ const BMFace *bm_face = bm_looptri[0]->f;
+ /* use_hide always for edit-mode */
+ if (BM_elem_flag_test(bm_face, BM_ELEM_HIDDEN)) {
+ continue;
+ }
+ int mat = (ibo_len > 1) ? bm_face->mat_nr : 0;
+ GPU_indexbuf_add_tri_verts(&elb[mat], BM_elem_index_get(bm_looptri[0]),
+ BM_elem_index_get(bm_looptri[1]),
+ BM_elem_index_get(bm_looptri[2]));
}
-
- GPU_vertbuf_attr_set(vbo, attr_id.sel, cidx++, &edge_vert_sel);
- GPU_vertbuf_attr_set(vbo, attr_id.sel, cidx++, &edge_vert_sel);
-
- GPU_vertbuf_attr_set(vbo, attr_id.pos, vidx++, rdata->mvert[ed->v1].co);
- GPU_vertbuf_attr_set(vbo, attr_id.pos, vidx++, rdata->mvert[ed->v2].co);
}
- vbo_len_used = vidx;
-
- if (vbo_len_capacity != vbo_len_used) {
- GPU_vertbuf_data_resize(vbo, vbo_len_used);
+ else {
+ for (int i = 0; i < tri_len; i++) {
+ const MLoopTri *mlt = &rdata->mlooptri[i];
+ const MPoly *mp = &rdata->mpoly[mlt->poly];
+ if (use_hide && (mp->flag & ME_HIDE)) {
+ continue;
+ }
+ int mat = (ibo_len > 1) ? mp->mat_nr : 0;
+ GPU_indexbuf_add_tri_verts(&elb[mat], mlt->tri[0], mlt->tri[1], mlt->tri[2]);
+ }
}
}
+ else {
+ /* Note: mapped doesn't support lnors yet. */
+ BMesh *bm = rdata->edit_bmesh->bm;
+ Mesh *me_cage = rdata->mapped.me_cage;
- return vbo;
-}
-
-static GPUIndexBuf *mesh_create_tri_overlay_weight_faces(
- MeshRenderData *rdata)
-{
- BLI_assert(rdata->types & (MR_DATATYPE_VERT | MR_DATATYPE_LOOPTRI));
-
- {
- const int vert_len = mesh_render_data_verts_len_get(rdata);
- const int tri_len = mesh_render_data_looptri_len_get(rdata);
-
- GPUIndexBufBuilder elb;
- GPU_indexbuf_init(&elb, GPU_PRIM_TRIS, tri_len, vert_len);
-
+ const MLoopTri *mlooptri = BKE_mesh_runtime_looptri_ensure(me_cage);
for (int i = 0; i < tri_len; i++) {
- const MLoopTri *mlt = &rdata->mlooptri[i];
- if (!(rdata->mpoly[mlt->poly].flag & (ME_FACE_SEL | ME_HIDE))) {
- for (uint tri_corner = 0; tri_corner < 3; tri_corner++) {
- GPU_indexbuf_add_generic_vert(&elb, rdata->mloop[mlt->tri[tri_corner]].v);
+ const MLoopTri *mlt = &mlooptri[i];
+ const int p_orig = rdata->mapped.p_origindex[mlt->poly];
+ if (p_orig != ORIGINDEX_NONE) {
+ /* Assume 'use_hide' */
+ BMFace *efa = BM_face_at_index(bm, p_orig);
+ if (!BM_elem_flag_test(efa, BM_ELEM_HIDDEN)) {
+ int mat = (ibo_len > 1) ? efa->mat_nr : 0;
+ GPU_indexbuf_add_tri_verts(&elb[mat], mlt->tri[0], mlt->tri[1], mlt->tri[2]);
}
}
}
- return GPU_indexbuf_build(&elb);
}
-}
-/**
- * Non-edit mode vertices (only used for weight-paint mode).
- */
-static GPUVertBuf *mesh_create_vert_pos_with_overlay_data(
- MeshRenderData *rdata)
-{
- BLI_assert(rdata->types & (MR_DATATYPE_VERT));
- BLI_assert(rdata->edit_bmesh == NULL);
-
- GPUVertBuf *vbo;
- {
- uint cidx = 0;
-
- static GPUVertFormat format = { 0 };
- static struct { uint data; } attr_id;
- if (format.attr_len == 0) {
- attr_id.data = GPU_vertformat_attr_add(&format, "data", GPU_COMP_I8, 1, GPU_FETCH_INT);
- }
-
- const int vert_len = mesh_render_data_verts_len_get(rdata);
-
- vbo = GPU_vertbuf_create_with_format(&format);
-
- const int vbo_len_capacity = vert_len;
- int vbo_len_used = 0;
- GPU_vertbuf_data_alloc(vbo, vbo_len_capacity);
-
- for (int i = 0; i < vert_len; i++) {
- const MVert *mv = &rdata->mvert[i];
- const char data = mv->flag & (SELECT | ME_HIDE);
- GPU_vertbuf_attr_set(vbo, attr_id.data, cidx++, &data);
- }
- vbo_len_used = cidx;
-
- if (vbo_len_capacity != vbo_len_used) {
- GPU_vertbuf_data_resize(vbo, vbo_len_used);
- }
+ for (int i = 0; i < ibo_len; ++i) {
+ GPU_indexbuf_build_in_place(&elb[i], ibo[i]);
}
- return vbo;
}
/** \} */
@@ -4647,6 +4502,12 @@ static GPUVertBuf *mesh_create_vert_pos_with_overlay_data(
/** \name Public API
* \{ */
+GPUBatch *DRW_mesh_batch_cache_get_all_verts(Mesh *me)
+{
+ MeshBatchCache *cache = mesh_batch_cache_get(me);
+ return DRW_batch_request(&cache->batch.all_verts);
+}
+
GPUBatch *DRW_mesh_batch_cache_get_all_edges(Mesh *me)
{
MeshBatchCache *cache = mesh_batch_cache_get(me);
@@ -4666,40 +4527,10 @@ GPUBatch *DRW_mesh_batch_cache_get_all_edges(Mesh *me)
return cache->all_edges;
}
-GPUBatch *DRW_mesh_batch_cache_get_all_triangles(Mesh *me)
-{
- MeshBatchCache *cache = mesh_batch_cache_get(me);
-
- if (cache->all_triangles == NULL) {
- /* create batch from DM */
- const int datatype = MR_DATATYPE_VERT | MR_DATATYPE_LOOPTRI;
- MeshRenderData *rdata = mesh_render_data_create(me, datatype);
-
- cache->all_triangles = GPU_batch_create(
- GPU_PRIM_TRIS, mesh_batch_cache_get_vert_pos_and_nor_in_order(rdata, cache),
- mesh_batch_cache_get_triangles_in_order(rdata, cache));
-
- mesh_render_data_free(rdata);
- }
-
- return cache->all_triangles;
-}
-
GPUBatch *DRW_mesh_batch_cache_get_triangles_with_normals(Mesh *me)
{
MeshBatchCache *cache = mesh_batch_cache_get(me);
-
- if (cache->triangles_with_normals == NULL) {
- const int datatype = MR_DATATYPE_VERT | MR_DATATYPE_LOOPTRI | MR_DATATYPE_LOOP | MR_DATATYPE_POLY;
- MeshRenderData *rdata = mesh_render_data_create(me, datatype);
-
- cache->triangles_with_normals = GPU_batch_create(
- GPU_PRIM_TRIS, mesh_batch_cache_get_tri_pos_and_normals(rdata, cache), NULL);
-
- mesh_render_data_free(rdata);
- }
-
- return cache->triangles_with_normals;
+ return DRW_batch_request(&cache->batch.surface);
}
GPUBatch *DRW_mesh_batch_cache_get_loose_edges_with_normals(Mesh *me)
@@ -4723,61 +4554,12 @@ GPUBatch *DRW_mesh_batch_cache_get_loose_edges_with_normals(Mesh *me)
return cache->ledges_with_normals;
}
-GPUBatch *DRW_mesh_batch_cache_get_triangles_with_normals_and_weights(
- Mesh *me, const struct DRW_MeshWeightState *wstate)
+GPUBatch *DRW_mesh_batch_cache_get_triangles_with_normals_and_weights(Mesh *me)
{
MeshBatchCache *cache = mesh_batch_cache_get(me);
-
- mesh_batch_cache_check_vertex_group(cache, wstate);
-
- if (cache->triangles_with_weights == NULL) {
- const bool use_hide = (me->editflag & (ME_EDIT_PAINT_VERT_SEL | ME_EDIT_PAINT_FACE_SEL)) != 0;
- const int datatype =
- MR_DATATYPE_VERT | MR_DATATYPE_LOOPTRI | MR_DATATYPE_LOOP | MR_DATATYPE_POLY | MR_DATATYPE_DVERT;
- MeshRenderData *rdata = mesh_render_data_create(me, datatype);
-
- cache->triangles_with_weights = GPU_batch_create_ex(
- GPU_PRIM_TRIS, mesh_create_tri_weights(rdata, use_hide, wstate), NULL, GPU_BATCH_OWNS_VBO);
-
- DRW_mesh_weight_state_copy(&cache->weight_state, wstate);
-
- GPUVertBuf *vbo_tris = use_hide ?
- mesh_create_tri_pos_and_normals_visible_only(rdata) :
- mesh_batch_cache_get_tri_pos_and_normals(rdata, cache);
-
- GPU_batch_vertbuf_add_ex(cache->triangles_with_weights, vbo_tris, use_hide);
-
- mesh_render_data_free(rdata);
- }
-
- return cache->triangles_with_weights;
-}
-
-GPUBatch *DRW_mesh_batch_cache_get_triangles_with_normals_and_vert_colors(Mesh *me)
-{
- MeshBatchCache *cache = mesh_batch_cache_get(me);
-
- if (cache->triangles_with_vert_colors == NULL) {
- const bool use_hide = (me->editflag & (ME_EDIT_PAINT_VERT_SEL | ME_EDIT_PAINT_FACE_SEL)) != 0;
- const int datatype =
- MR_DATATYPE_VERT | MR_DATATYPE_LOOPTRI | MR_DATATYPE_LOOP | MR_DATATYPE_POLY | MR_DATATYPE_LOOPCOL;
- MeshRenderData *rdata = mesh_render_data_create(me, datatype);
-
- cache->triangles_with_vert_colors = GPU_batch_create_ex(
- GPU_PRIM_TRIS, mesh_create_tri_vert_colors(rdata, use_hide), NULL, GPU_BATCH_OWNS_VBO);
-
- GPUVertBuf *vbo_tris = use_hide ?
- mesh_create_tri_pos_and_normals_visible_only(rdata) :
- mesh_batch_cache_get_tri_pos_and_normals(rdata, cache);
- GPU_batch_vertbuf_add_ex(cache->triangles_with_vert_colors, vbo_tris, use_hide);
-
- mesh_render_data_free(rdata);
- }
-
- return cache->triangles_with_vert_colors;
+ return DRW_batch_request(&cache->batch.surface_weights);
}
-
struct GPUBatch *DRW_mesh_batch_cache_get_triangles_with_select_id(
struct Mesh *me, bool use_hide, uint select_id_offset)
{
@@ -4799,10 +4581,8 @@ struct GPUBatch *DRW_mesh_batch_cache_get_triangles_with_select_id(
cache->triangles_with_select_id = GPU_batch_create_ex(
GPU_PRIM_TRIS, mesh_create_tri_select_id(rdata, use_hide, select_id_offset), NULL, GPU_BATCH_OWNS_VBO);
- GPUVertBuf *vbo_tris = use_hide ?
- mesh_create_tri_pos_and_normals_visible_only(rdata) :
- mesh_batch_cache_get_tri_pos_and_normals(rdata, cache);
- GPU_batch_vertbuf_add_ex(cache->triangles_with_select_id, vbo_tris, use_hide);
+ GPUVertBuf *vbo_tris = mesh_batch_cache_get_tri_pos_and_normals_edit(rdata, cache, use_hide);
+ GPU_batch_vertbuf_add(cache->triangles_with_select_id, vbo_tris);
mesh_render_data_free(rdata);
}
@@ -4825,12 +4605,10 @@ struct GPUBatch *DRW_mesh_batch_cache_get_triangles_with_select_mask(struct Mesh
rdata->mapped.use = true;
}
- GPUVertBuf *vbo_tris = use_hide ?
- mesh_create_tri_pos_and_normals_visible_only(rdata) :
- mesh_batch_cache_get_tri_pos_and_normals(rdata, cache);
+ GPUVertBuf *vbo_tris = mesh_batch_cache_get_tri_pos_and_normals_edit(rdata, cache, use_hide);
- cache->triangles_with_select_mask = GPU_batch_create_ex(
- GPU_PRIM_TRIS, vbo_tris, NULL, use_hide ? GPU_BATCH_OWNS_VBO : 0);
+ cache->triangles_with_select_mask = GPU_batch_create(
+ GPU_PRIM_TRIS, vbo_tris, NULL);
mesh_render_data_free(rdata);
}
@@ -4847,7 +4625,7 @@ GPUBatch *DRW_mesh_batch_cache_get_points_with_normals(Mesh *me)
MeshRenderData *rdata = mesh_render_data_create(me, datatype);
cache->points_with_normals = GPU_batch_create(
- GPU_PRIM_POINTS, mesh_batch_cache_get_tri_pos_and_normals(rdata, cache), NULL);
+ GPU_PRIM_POINTS, mesh_batch_cache_get_tri_pos_and_normals_edit(rdata, cache, false), NULL);
mesh_render_data_free(rdata);
}
@@ -4855,23 +4633,6 @@ GPUBatch *DRW_mesh_batch_cache_get_points_with_normals(Mesh *me)
return cache->points_with_normals;
}
-GPUBatch *DRW_mesh_batch_cache_get_all_verts(Mesh *me)
-{
- MeshBatchCache *cache = mesh_batch_cache_get(me);
-
- if (cache->all_verts == NULL) {
- /* create batch from DM */
- MeshRenderData *rdata = mesh_render_data_create(me, MR_DATATYPE_VERT);
-
- cache->all_verts = GPU_batch_create(
- GPU_PRIM_POINTS, mesh_batch_cache_get_vert_pos_and_nor_in_order(rdata, cache), NULL);
-
- mesh_render_data_free(rdata);
- }
-
- return cache->all_verts;
-}
-
GPUBatch *DRW_mesh_batch_cache_get_fancy_edges(Mesh *me)
{
MeshBatchCache *cache = mesh_batch_cache_get(me);
@@ -4960,183 +4721,61 @@ GPUBatch *DRW_mesh_batch_cache_get_edge_detection(Mesh *me, bool *r_is_manifold)
return cache->edge_detection;
}
-void DRW_mesh_batch_cache_get_wireframes_face_texbuf(
- Mesh *me, GPUTexture **verts_data, GPUTexture **face_indices, int *tri_count)
-{
- MeshBatchCache *cache = mesh_batch_cache_get(me);
-
- if (cache->edges_face_overlay_tx == NULL || cache->pos_in_order_tx == NULL) {
- const int options = MR_DATATYPE_VERT | MR_DATATYPE_EDGE | MR_DATATYPE_LOOP | MR_DATATYPE_LOOPTRI;
-
- MeshRenderData *rdata = mesh_render_data_create(me, options);
-
- mesh_batch_cache_get_edges_overlay_texture_buf(rdata, cache);
- mesh_batch_cache_get_vert_pos_and_nor_in_order_buf(rdata, cache);
-
- mesh_render_data_free(rdata);
- }
-
- *tri_count = cache->edges_face_overlay_tri_count;
- *face_indices = cache->edges_face_overlay_tx;
- *verts_data = cache->pos_in_order_tx;
-}
-
-static void mesh_batch_cache_create_overlay_batches(Mesh *me)
+GPUBatch *DRW_mesh_batch_cache_get_wireframes_face(Mesh *me)
{
- BLI_assert(me->edit_btmesh != NULL);
-
- /* Since MR_DATATYPE_OVERLAY is slow to generate, generate them all at once */
- const int options =
- MR_DATATYPE_VERT | MR_DATATYPE_EDGE | MR_DATATYPE_LOOP | MR_DATATYPE_POLY |
- MR_DATATYPE_LOOPTRI | MR_DATATYPE_OVERLAY;
-
MeshBatchCache *cache = mesh_batch_cache_get(me);
- MeshRenderData *rdata = mesh_render_data_create(me, options);
-
- if (rdata->mapped.supported) {
- rdata->mapped.use = true;
- }
-
- if (cache->overlay_triangles == NULL) {
- cache->overlay_triangles = GPU_batch_create(
- GPU_PRIM_TRIS, mesh_batch_cache_get_edit_tri_pos(rdata, cache), NULL);
- GPU_batch_vertbuf_add(cache->overlay_triangles, mesh_batch_cache_get_edit_tri_nor(rdata, cache));
- GPU_batch_vertbuf_add(cache->overlay_triangles, mesh_batch_cache_get_edit_tri_data(rdata, cache));
- }
-
- if (cache->overlay_loose_edges == NULL) {
- cache->overlay_loose_edges = GPU_batch_create(
- GPU_PRIM_LINES, mesh_batch_cache_get_edit_ledge_pos(rdata, cache), NULL);
- GPU_batch_vertbuf_add(cache->overlay_loose_edges, mesh_batch_cache_get_edit_ledge_nor(rdata, cache));
- GPU_batch_vertbuf_add(cache->overlay_loose_edges, mesh_batch_cache_get_edit_ledge_data(rdata, cache));
- }
-
- if (cache->overlay_loose_verts == NULL) {
- cache->overlay_loose_verts = GPU_batch_create(
- GPU_PRIM_POINTS, mesh_batch_cache_get_edit_lvert_pos(rdata, cache), NULL);
- GPU_batch_vertbuf_add(cache->overlay_loose_verts, mesh_batch_cache_get_edit_lvert_nor(rdata, cache));
- GPU_batch_vertbuf_add(cache->overlay_loose_verts, mesh_batch_cache_get_edit_lvert_data(rdata, cache));
- }
-
- /* Also used for vertices display */
- if (cache->overlay_triangles_nor == NULL) {
- cache->overlay_triangles_nor = GPU_batch_create(
- GPU_PRIM_POINTS, mesh_batch_cache_get_edit_tri_pos(rdata, cache),
- mesh_batch_cache_get_edit_tri_indices(rdata, cache));
- GPU_batch_vertbuf_add(cache->overlay_triangles_nor, mesh_batch_cache_get_edit_tri_nor(rdata, cache));
- GPU_batch_vertbuf_add(cache->overlay_triangles_nor, mesh_batch_cache_get_edit_tri_data(rdata, cache));
- }
-
- if (cache->overlay_triangles_lnor == NULL) {
- cache->overlay_triangles_lnor = GPU_batch_create(
- GPU_PRIM_POINTS, mesh_batch_cache_get_edit_tri_pos(rdata, cache), NULL);
- GPU_batch_vertbuf_add(cache->overlay_triangles_lnor, mesh_batch_cache_get_edit_tri_nor(rdata, cache));
- GPU_batch_vertbuf_add(cache->overlay_triangles_lnor, mesh_batch_cache_get_edit_tri_data(rdata, cache));
- }
-
- if (cache->overlay_loose_edges_nor == NULL) {
- cache->overlay_loose_edges_nor = GPU_batch_create(
- GPU_PRIM_POINTS, mesh_batch_cache_get_edit_ledge_pos(rdata, cache), NULL);
- GPU_batch_vertbuf_add(cache->overlay_loose_edges_nor, mesh_batch_cache_get_edit_ledge_nor(rdata, cache));
- GPU_batch_vertbuf_add(cache->overlay_loose_edges_nor, mesh_batch_cache_get_edit_ledge_data(rdata, cache));
- }
-
- mesh_render_data_free(rdata);
+ return DRW_batch_request(&cache->batch.wire_triangles);
}
-GPUBatch *DRW_mesh_batch_cache_get_overlay_triangles(Mesh *me)
+GPUBatch *DRW_mesh_batch_cache_get_edit_triangles(Mesh *me)
{
MeshBatchCache *cache = mesh_batch_cache_get(me);
-
- if (cache->overlay_triangles == NULL) {
- mesh_batch_cache_create_overlay_batches(me);
- }
-
- return cache->overlay_triangles;
+ return DRW_batch_request(&cache->batch.edit_triangles);
}
-GPUTexture *DRW_mesh_batch_cache_get_overlay_data_tex(Mesh *me)
+GPUBatch *DRW_mesh_batch_cache_get_edit_vertices(Mesh *me)
{
MeshBatchCache *cache = mesh_batch_cache_get(me);
-
- if (cache->ed_tri_data_tx == NULL) {
- mesh_batch_cache_create_overlay_batches(me);
- }
-
- return cache->ed_tri_data_tx;
+ return DRW_batch_request(&cache->batch.edit_vertices);
}
-GPUBatch *DRW_mesh_batch_cache_get_overlay_loose_edges(Mesh *me)
+GPUBatch *DRW_mesh_batch_cache_get_edit_loose_edges(Mesh *me)
{
MeshBatchCache *cache = mesh_batch_cache_get(me);
-
- if (cache->overlay_loose_edges == NULL) {
- mesh_batch_cache_create_overlay_batches(me);
- }
-
- return cache->overlay_loose_edges;
+ return DRW_batch_request(&cache->batch.edit_loose_edges);
}
-GPUBatch *DRW_mesh_batch_cache_get_overlay_loose_verts(Mesh *me)
+GPUBatch *DRW_mesh_batch_cache_get_edit_loose_verts(Mesh *me)
{
MeshBatchCache *cache = mesh_batch_cache_get(me);
-
- if (cache->overlay_loose_verts == NULL) {
- mesh_batch_cache_create_overlay_batches(me);
- }
-
- return cache->overlay_loose_verts;
+ return DRW_batch_request(&cache->batch.edit_loose_verts);
}
-GPUBatch *DRW_mesh_batch_cache_get_overlay_triangles_nor(Mesh *me)
+GPUBatch *DRW_mesh_batch_cache_get_edit_triangles_nor(Mesh *me)
{
MeshBatchCache *cache = mesh_batch_cache_get(me);
-
- if (cache->overlay_triangles_nor == NULL) {
- mesh_batch_cache_create_overlay_batches(me);
- }
-
- return cache->overlay_triangles_nor;
+ return DRW_batch_request(&cache->batch.edit_triangles_nor);
}
-GPUBatch *DRW_mesh_batch_cache_get_overlay_triangles_lnor(Mesh *me)
+GPUBatch *DRW_mesh_batch_cache_get_edit_triangles_lnor(Mesh *me)
{
MeshBatchCache *cache = mesh_batch_cache_get(me);
-
- if (cache->overlay_triangles_lnor == NULL) {
- mesh_batch_cache_create_overlay_batches(me);
- }
-
- return cache->overlay_triangles_lnor;
+ return DRW_batch_request(&cache->batch.edit_triangles_lnor);
}
-GPUBatch *DRW_mesh_batch_cache_get_overlay_loose_edges_nor(Mesh *me)
+GPUBatch *DRW_mesh_batch_cache_get_edit_loose_edges_nor(Mesh *me)
{
MeshBatchCache *cache = mesh_batch_cache_get(me);
-
- if (cache->overlay_loose_edges_nor == NULL) {
- mesh_batch_cache_create_overlay_batches(me);
- }
-
- return cache->overlay_loose_edges_nor;
+ return DRW_batch_request(&cache->batch.edit_loose_edges_nor);
}
-GPUBatch *DRW_mesh_batch_cache_get_overlay_facedots(Mesh *me)
+GPUBatch *DRW_mesh_batch_cache_get_edit_facedots(Mesh *me)
{
MeshBatchCache *cache = mesh_batch_cache_get(me);
-
- if (cache->overlay_facedots == NULL) {
- MeshRenderData *rdata = mesh_render_data_create(me, MR_DATATYPE_VERT | MR_DATATYPE_LOOP | MR_DATATYPE_POLY);
-
- cache->overlay_facedots = GPU_batch_create(
- GPU_PRIM_POINTS, mesh_batch_cache_get_facedot_pos_with_normals_and_flag(rdata, cache), NULL);
-
- mesh_render_data_free(rdata);
- }
-
- return cache->overlay_facedots;
+ return DRW_batch_request(&cache->batch.edit_facedots);
}
+/* Need to be ported to new getter style. */
GPUBatch *DRW_mesh_batch_cache_get_facedots_with_select_id(Mesh *me, uint select_id_offset)
{
MeshBatchCache *cache = mesh_batch_cache_get(me);
@@ -5225,122 +4864,97 @@ GPUBatch **DRW_mesh_batch_cache_get_surface_shaded(
char **auto_layer_names, int **auto_layer_is_srgb, int *auto_layer_count)
{
MeshBatchCache *cache = mesh_batch_cache_get(me);
+ uchar cd_vneeded[CD_NUMTYPES] = {0};
+ ushort cd_lneeded[CD_NUMTYPES] = {0};
+ mesh_cd_calc_used_gpu_layers(me, cd_vneeded, cd_lneeded, gpumat_array, gpumat_array_len);
- if (cache->shaded_triangles == NULL) {
+ BLI_assert(gpumat_array_len == cache->mat_len);
- /* Hack to show the final result. */
- BMesh *bm_mapped = NULL;
- const int *p_origindex = NULL;
- const bool use_em_final = (
- me->edit_btmesh &&
- me->edit_btmesh->mesh_eval_final &&
- (me->edit_btmesh->mesh_eval_final->runtime.is_original == false));
- Mesh me_fake;
- if (use_em_final) {
- /* Pass in mapped args. */
- bm_mapped = me->edit_btmesh->bm;
- p_origindex = CustomData_get_layer(&me->edit_btmesh->mesh_eval_final->pdata, CD_ORIGINDEX);
- if (p_origindex == NULL) {
- bm_mapped = NULL;
- }
+ bool cd_overlap = mesh_cd_layers_type_overlap(cache->cd_vused, cache->cd_lused,
+ cd_vneeded, cd_lneeded);
+ if (cd_overlap == false) {
+ /* XXX TODO(fclem): We are writting to batch cache here. Need to make this thread safe. */
+ mesh_cd_layers_type_merge(cache->cd_vneeded, cache->cd_lneeded,
+ cd_vneeded, cd_lneeded);
- me_fake = *me->edit_btmesh->mesh_eval_final;
- me_fake.mat = me->mat;
- me_fake.totcol = me->totcol;
- me = &me_fake;
- }
-
- /* create batch from DM */
- const int datatype =
- MR_DATATYPE_VERT | MR_DATATYPE_LOOP | MR_DATATYPE_LOOPTRI |
- MR_DATATYPE_POLY | MR_DATATYPE_SHADING;
- MeshRenderData *rdata = mesh_render_data_create_ex(me, datatype, gpumat_array, gpumat_array_len);
-
- const int mat_len = mesh_render_data_mat_len_get(rdata);
-
- cache->shaded_triangles = MEM_callocN(sizeof(*cache->shaded_triangles) * mat_len, __func__);
-
- GPUIndexBuf **el = mesh_batch_cache_get_triangles_in_order_split_by_material(
- rdata, cache,
- bm_mapped, p_origindex);
-
- GPUVertBuf *vbo = mesh_batch_cache_get_tri_pos_and_normals(rdata, cache);
- GPUVertBuf *vbo_shading = mesh_batch_cache_get_tri_shading_data(rdata, cache);
-
- for (int i = 0; i < mat_len; i++) {
- cache->shaded_triangles[i] = GPU_batch_create(
- GPU_PRIM_TRIS, vbo, el[i]);
- if (vbo_shading) {
- GPU_batch_vertbuf_add(cache->shaded_triangles[i], vbo_shading);
- }
- }
-
- mesh_render_data_free(rdata);
+ mesh_cd_extract_auto_layers_names_and_srgb(me,
+ cache->cd_lneeded,
+ &cache->auto_layer_names,
+ &cache->auto_layer_is_srgb,
+ &cache->auto_layer_len);
}
-
if (auto_layer_names) {
*auto_layer_names = cache->auto_layer_names;
*auto_layer_is_srgb = cache->auto_layer_is_srgb;
*auto_layer_count = cache->auto_layer_len;
}
+ for (int i = 0; i < cache->mat_len; ++i) {
+ DRW_batch_request(&cache->surf_per_mat[i]);
+ }
+ return cache->surf_per_mat;
+}
- return cache->shaded_triangles;
+static void texpaint_request_active_uv(MeshBatchCache *cache, Mesh *me)
+{
+ uchar cd_vneeded[CD_NUMTYPES] = {0};
+ ushort cd_lneeded[CD_NUMTYPES] = {0};
+ mesh_cd_calc_active_uv_layer(me, cd_lneeded);
+ if (cd_lneeded[CD_MLOOPUV] == 0) {
+ /* This should not happen. */
+ BLI_assert(!"No uv layer available in texpaint, but batches requested anyway!");
+ }
+ bool cd_overlap = mesh_cd_layers_type_overlap(cache->cd_vused, cache->cd_lused,
+ cd_vneeded, cd_lneeded);
+ if (cd_overlap == false) {
+ /* XXX TODO(fclem): We are writting to batch cache here. Need to make this thread safe. */
+ mesh_cd_layers_type_merge(cache->cd_vneeded, cache->cd_lneeded,
+ cd_vneeded, cd_lneeded);
+ }
}
GPUBatch **DRW_mesh_batch_cache_get_surface_texpaint(Mesh *me)
{
MeshBatchCache *cache = mesh_batch_cache_get(me);
-
- if (cache->texpaint_triangles == NULL) {
- /* create batch from DM */
- const int datatype =
- MR_DATATYPE_VERT | MR_DATATYPE_LOOP | MR_DATATYPE_POLY | MR_DATATYPE_LOOPTRI | MR_DATATYPE_LOOPUV;
- MeshRenderData *rdata = mesh_render_data_create(me, datatype);
-
- const int mat_len = mesh_render_data_mat_len_get(rdata);
-
- cache->texpaint_triangles = MEM_callocN(sizeof(*cache->texpaint_triangles) * mat_len, __func__);
-
- GPUIndexBuf **el = mesh_batch_cache_get_triangles_in_order_split_by_material(rdata, cache, NULL, NULL);
-
- GPUVertBuf *vbo = mesh_batch_cache_get_tri_pos_and_normals(rdata, cache);
- for (int i = 0; i < mat_len; i++) {
- cache->texpaint_triangles[i] = GPU_batch_create(
- GPU_PRIM_TRIS, vbo, el[i]);
- GPUVertBuf *vbo_uv = mesh_batch_cache_get_tri_uv_active(rdata, cache);
- if (vbo_uv) {
- GPU_batch_vertbuf_add(cache->texpaint_triangles[i], vbo_uv);
- }
- }
- mesh_render_data_free(rdata);
+ texpaint_request_active_uv(cache, me);
+ for (int i = 0; i < cache->mat_len; ++i) {
+ DRW_batch_request(&cache->surf_per_mat[i]);
}
-
- return cache->texpaint_triangles;
+ return cache->surf_per_mat;
}
GPUBatch *DRW_mesh_batch_cache_get_surface_texpaint_single(Mesh *me)
{
MeshBatchCache *cache = mesh_batch_cache_get(me);
+ texpaint_request_active_uv(cache, me);
+ return DRW_batch_request(&cache->batch.surface);
+}
- if (cache->texpaint_triangles_single == NULL) {
- /* create batch from DM */
- const int datatype =
- MR_DATATYPE_VERT | MR_DATATYPE_LOOP | MR_DATATYPE_POLY | MR_DATATYPE_LOOPTRI | MR_DATATYPE_LOOPUV;
- MeshRenderData *rdata = mesh_render_data_create(me, datatype);
-
- GPUVertBuf *vbo = mesh_batch_cache_get_tri_pos_and_normals(rdata, cache);
-
- cache->texpaint_triangles_single = GPU_batch_create(
- GPU_PRIM_TRIS, vbo, NULL);
- GPUVertBuf *vbo_uv = mesh_batch_cache_get_tri_uv_active(rdata, cache);
- if (vbo_uv) {
- GPU_batch_vertbuf_add(cache->texpaint_triangles_single, vbo_uv);
- }
- mesh_render_data_free(rdata);
+static void texpaint_request_active_vcol(MeshBatchCache *cache, Mesh *me)
+{
+ uchar cd_vneeded[CD_NUMTYPES] = {0};
+ ushort cd_lneeded[CD_NUMTYPES] = {0};
+ mesh_cd_calc_active_vcol_layer(me, cd_lneeded);
+ if (cd_lneeded[CD_MLOOPCOL] == 0) {
+ /* This should not happen. */
+ BLI_assert(!"No vcol layer available in vertpaint, but batches requested anyway!");
}
- return cache->texpaint_triangles_single;
+ bool cd_overlap = mesh_cd_layers_type_overlap(cache->cd_vused, cache->cd_lused,
+ cd_vneeded, cd_lneeded);
+ if (cd_overlap == false) {
+ /* XXX TODO(fclem): We are writting to batch cache here. Need to make this thread safe. */
+ mesh_cd_layers_type_merge(cache->cd_vneeded, cache->cd_lneeded,
+ cd_vneeded, cd_lneeded);
+ }
+}
+
+GPUBatch *DRW_mesh_batch_cache_get_surface_vertpaint(Mesh *me)
+{
+ MeshBatchCache *cache = mesh_batch_cache_get(me);
+ texpaint_request_active_vcol(cache, me);
+ return DRW_batch_request(&cache->batch.surface);
}
+/* TODO port to batch request. Is basically batch.wire_loops. */
GPUBatch *DRW_mesh_batch_cache_get_texpaint_loop_wire(Mesh *me)
{
MeshBatchCache *cache = mesh_batch_cache_get(me);
@@ -5392,61 +5006,10 @@ GPUBatch *DRW_mesh_batch_cache_get_texpaint_loop_wire(Mesh *me)
return cache->texpaint_uv_loops;
}
-GPUBatch *DRW_mesh_batch_cache_get_weight_overlay_edges(Mesh *me, bool use_wire, bool use_sel)
+GPUBatch *DRW_mesh_batch_cache_get_wire_loops(Mesh *me)
{
MeshBatchCache *cache = mesh_batch_cache_get(me);
-
- if (cache->overlay_paint_edges == NULL) {
- /* create batch from Mesh */
- const int datatype = MR_DATATYPE_VERT | MR_DATATYPE_EDGE | MR_DATATYPE_POLY | MR_DATATYPE_LOOP;
- MeshRenderData *rdata = mesh_render_data_create(me, datatype);
-
- cache->overlay_paint_edges = GPU_batch_create_ex(
- GPU_PRIM_LINES, mesh_create_edge_pos_with_sel(rdata, use_wire, use_sel), NULL, GPU_BATCH_OWNS_VBO);
-
- mesh_render_data_free(rdata);
- }
-
- return cache->overlay_paint_edges;
-}
-
-GPUBatch *DRW_mesh_batch_cache_get_weight_overlay_faces(Mesh *me)
-{
- MeshBatchCache *cache = mesh_batch_cache_get(me);
-
- if (cache->overlay_weight_faces == NULL) {
- /* create batch from Mesh */
- const int datatype = MR_DATATYPE_VERT | MR_DATATYPE_POLY | MR_DATATYPE_LOOP | MR_DATATYPE_LOOPTRI;
- MeshRenderData *rdata = mesh_render_data_create(me, datatype);
-
- cache->overlay_weight_faces = GPU_batch_create_ex(
- GPU_PRIM_TRIS, mesh_batch_cache_get_vert_pos_and_nor_in_order(rdata, cache),
- mesh_create_tri_overlay_weight_faces(rdata), GPU_BATCH_OWNS_INDEX);
-
- mesh_render_data_free(rdata);
- }
-
- return cache->overlay_weight_faces;
-}
-
-GPUBatch *DRW_mesh_batch_cache_get_weight_overlay_verts(Mesh *me)
-{
- MeshBatchCache *cache = mesh_batch_cache_get(me);
-
- if (cache->overlay_weight_verts == NULL) {
- /* create batch from Mesh */
- MeshRenderData *rdata = mesh_render_data_create(me, MR_DATATYPE_VERT);
-
- cache->overlay_weight_verts = GPU_batch_create(
- GPU_PRIM_POINTS, mesh_batch_cache_get_vert_pos_and_nor_in_order(rdata, cache), NULL);
-
- GPU_batch_vertbuf_add_ex(
- cache->overlay_weight_verts,
- mesh_create_vert_pos_with_overlay_data(rdata), true);
- mesh_render_data_free(rdata);
- }
-
- return cache->overlay_weight_verts;
+ return DRW_batch_request(&cache->batch.wire_loops);
}
/**
@@ -5885,3 +5448,269 @@ void DRW_mesh_cache_uvedit(
}
/** \} */
+
+
+/* ---------------------------------------------------------------------- */
+
+/** \name Grouped batch generation
+ * \{ */
+
+/* Can be called for any surface type. Mesh *me is the final mesh. */
+void DRW_mesh_batch_cache_create_requested(Object *ob, Mesh *me)
+{
+ const DRWContextState *draw_ctx = DRW_context_state_get();
+ const int mode = CTX_data_mode_enum_ex(draw_ctx->object_edit, draw_ctx->obact, draw_ctx->object_mode);
+ const bool is_paint_mode = ELEM(mode, CTX_MODE_PAINT_TEXTURE, CTX_MODE_PAINT_VERTEX, CTX_MODE_PAINT_WEIGHT);
+ const bool use_hide = (ob->type == OB_MESH) && ((is_paint_mode && (ob == draw_ctx->obact)) ||
+ ((mode == CTX_MODE_EDIT_MESH) && BKE_object_is_in_editmode(ob)));
+ bool use_face_sel = false;
+
+ /* Tex paint face select */
+ if (is_paint_mode && (ob->type == OB_MESH) && (draw_ctx->obact == ob)) {
+ const Mesh *me_orig = DEG_get_original_object(ob)->data;
+ use_face_sel = (me_orig->editflag & ME_EDIT_PAINT_FACE_SEL) != 0;
+ }
+
+ MeshBatchCache *cache = mesh_batch_cache_get(me);
+
+ /* Check vertex weights. */
+ if (cache->batch.surface_weights != 0) {
+ struct DRW_MeshWeightState wstate;
+ BLI_assert(ob->type == OB_MESH);
+ drw_mesh_weight_state_extract(ob, me, draw_ctx->scene->toolsettings, is_paint_mode, &wstate);
+ mesh_batch_cache_check_vertex_group(cache, &wstate);
+ drw_mesh_weight_state_copy(&cache->weight_state, &wstate);
+ drw_mesh_weight_state_clear(&wstate);
+ }
+
+ /* Verify that all surface batches have needed attrib layers. */
+ /* TODO(fclem): We could be a bit smarter here and only do it per material. */
+ bool cd_overlap = mesh_cd_layers_type_overlap(cache->cd_vused, cache->cd_lused,
+ cache->cd_vneeded, cache->cd_lneeded);
+ if (cd_overlap == false) {
+ for (int type = 0; type < CD_NUMTYPES; ++type) {
+ if ((cache->cd_vused[type] & cache->cd_vneeded[type]) != cache->cd_vneeded[type]) {
+ switch (type) {
+ case CD_MLOOPUV:
+ case CD_TANGENT:
+ GPU_VERTBUF_DISCARD_SAFE(cache->ordered.loop_uv_tan);
+ break;
+ case CD_MLOOPCOL:
+ GPU_VERTBUF_DISCARD_SAFE(cache->ordered.loop_vcol);
+ break;
+ case CD_ORCO:
+ /* TODO */
+ // GPU_VERTBUF_DISCARD_SAFE(cache->ordered.loop_orco);
+ break;
+ }
+ }
+ }
+ /* We can't discard batches at this point as they have been
+ * referenced for drawing. Just clear them in place. */
+ for (int i = 0; i < cache->mat_len; ++i) {
+ GPU_BATCH_CLEAR_SAFE(cache->surf_per_mat[i]);
+ }
+ GPU_BATCH_CLEAR_SAFE(cache->batch.surface);
+
+ mesh_cd_layers_type_merge(cache->cd_vused, cache->cd_lused,
+ cache->cd_vneeded, cache->cd_lneeded);
+
+ }
+
+ memset(cache->cd_lneeded, 0, sizeof(cache->cd_lneeded));
+ memset(cache->cd_vneeded, 0, sizeof(cache->cd_vneeded));
+
+ /* Init batches and request VBOs & IBOs */
+ if (DRW_batch_requested(cache->batch.surface, GPU_PRIM_TRIS)) {
+ DRW_ibo_request(cache->batch.surface, &cache->ibo.loops_tris);
+ DRW_vbo_request(cache->batch.surface, &cache->ordered.loop_pos_nor);
+ /* For paint overlay. Active layer should have been queried. */
+ if (cache->cd_lused[CD_MLOOPUV] != 0) {
+ DRW_vbo_request(cache->batch.surface, &cache->ordered.loop_uv_tan);
+ }
+ if (cache->cd_lused[CD_MLOOPCOL] != 0) {
+ DRW_vbo_request(cache->batch.surface, &cache->ordered.loop_vcol);
+ }
+ }
+ if (DRW_batch_requested(cache->batch.all_verts, GPU_PRIM_POINTS)) {
+ DRW_vbo_request(cache->batch.all_verts, &cache->ordered.pos_nor);
+ }
+ if (DRW_batch_requested(cache->batch.surface_weights, GPU_PRIM_TRIS)) {
+ DRW_ibo_request(cache->batch.surface_weights, &cache->ibo.surf_tris);
+ DRW_vbo_request(cache->batch.surface_weights, &cache->ordered.pos_nor);
+ DRW_vbo_request(cache->batch.surface_weights, &cache->ordered.weights);
+ }
+ if (DRW_batch_requested(cache->batch.wire_loops, GPU_PRIM_LINE_STRIP)) {
+ DRW_ibo_request(cache->batch.wire_loops, &cache->ibo.loops_lines);
+ DRW_vbo_request(cache->batch.wire_loops, &cache->ordered.loop_pos_nor);
+ }
+ if (DRW_batch_requested(cache->batch.wire_triangles, GPU_PRIM_TRIS)) {
+ DRW_vbo_request(cache->batch.wire_triangles, &cache->tess.pos_nor);
+ DRW_vbo_request(cache->batch.wire_triangles, &cache->tess.wireframe_data);
+ }
+
+ if (DRW_batch_requested(cache->batch.edit_triangles, GPU_PRIM_TRIS)) {
+ DRW_vbo_request(cache->batch.edit_triangles, &cache->edit.pos_nor);
+ DRW_vbo_request(cache->batch.edit_triangles, &cache->edit.data);
+ }
+ if (DRW_batch_requested(cache->batch.edit_vertices, GPU_PRIM_POINTS)) {
+ DRW_ibo_request(cache->batch.edit_vertices, &cache->ibo.edit_verts_points);
+ DRW_vbo_request(cache->batch.edit_vertices, &cache->edit.pos_nor);
+ DRW_vbo_request(cache->batch.edit_vertices, &cache->edit.data);
+ }
+ if (DRW_batch_requested(cache->batch.edit_loose_edges, GPU_PRIM_LINES)) {
+ DRW_vbo_request(cache->batch.edit_loose_edges, &cache->edit.pos_nor_ledges);
+ DRW_vbo_request(cache->batch.edit_loose_edges, &cache->edit.data_ledges);
+ }
+ if (DRW_batch_requested(cache->batch.edit_loose_verts, GPU_PRIM_POINTS)) {
+ DRW_vbo_request(cache->batch.edit_loose_verts, &cache->edit.pos_nor_lverts);
+ DRW_vbo_request(cache->batch.edit_loose_verts, &cache->edit.data_lverts);
+ }
+ if (DRW_batch_requested(cache->batch.edit_triangles_nor, GPU_PRIM_POINTS)) {
+ DRW_ibo_request(cache->batch.edit_triangles_nor, &cache->ibo.edit_verts_points);
+ DRW_vbo_request(cache->batch.edit_triangles_nor, &cache->edit.pos_nor);
+ }
+ if (DRW_batch_requested(cache->batch.edit_triangles_lnor, GPU_PRIM_POINTS)) {
+ DRW_vbo_request(cache->batch.edit_triangles_lnor, &cache->edit.pos_nor);
+ DRW_vbo_request(cache->batch.edit_triangles_lnor, &cache->edit.lnor);
+ }
+ if (DRW_batch_requested(cache->batch.edit_loose_edges_nor, GPU_PRIM_POINTS)) {
+ DRW_vbo_request(cache->batch.edit_loose_edges_nor, &cache->edit.pos_nor_ledges);
+ }
+ if (DRW_batch_requested(cache->batch.edit_facedots, GPU_PRIM_POINTS)) {
+ DRW_vbo_request(cache->batch.edit_facedots, &cache->edit.pos_nor_data_facedots);
+ }
+
+ for (int i = 0; i < cache->mat_len; ++i) {
+ if (DRW_batch_requested(cache->surf_per_mat[i], GPU_PRIM_TRIS)) {
+ if (cache->mat_len > 1) {
+ DRW_ibo_request(cache->surf_per_mat[i], &cache->surf_per_mat_tris[i]);
+ }
+ else {
+ DRW_ibo_request(cache->surf_per_mat[i], &cache->ibo.loops_tris);
+ }
+ DRW_vbo_request(cache->surf_per_mat[i], &cache->ordered.loop_pos_nor);
+ if ((cache->cd_lused[CD_MLOOPUV] != 0) ||
+ (cache->cd_lused[CD_TANGENT] != 0))
+ {
+ DRW_vbo_request(cache->surf_per_mat[i], &cache->ordered.loop_uv_tan);
+ }
+ if (cache->cd_lused[CD_MLOOPCOL] != 0) {
+ DRW_vbo_request(cache->surf_per_mat[i], &cache->ordered.loop_vcol);
+ }
+ /* TODO */
+ // if (cache->cd_vused[CD_ORCO] != 0) {
+ // DRW_vbo_request(cache->surf_per_mat[i], &cache->ordered.loop_orco);
+ // }
+ }
+ }
+
+ /* Generate MeshRenderData flags */
+ int mr_flag = 0, mr_edit_flag = 0;
+ DRW_ADD_FLAG_FROM_VBO_REQUEST(mr_flag, cache->ordered.pos_nor, MR_DATATYPE_VERT);
+ DRW_ADD_FLAG_FROM_VBO_REQUEST(mr_flag, cache->ordered.weights, MR_DATATYPE_VERT | MR_DATATYPE_DVERT);
+ DRW_ADD_FLAG_FROM_VBO_REQUEST(mr_flag, cache->ordered.loop_pos_nor, MR_DATATYPE_VERT | MR_DATATYPE_POLY | MR_DATATYPE_LOOP);
+ DRW_ADD_FLAG_FROM_VBO_REQUEST(mr_flag, cache->ordered.loop_uv_tan, MR_DATATYPE_VERT | MR_DATATYPE_POLY | MR_DATATYPE_LOOP | MR_DATATYPE_SHADING);
+ DRW_ADD_FLAG_FROM_VBO_REQUEST(mr_flag, cache->ordered.loop_vcol, MR_DATATYPE_VERT | MR_DATATYPE_POLY | MR_DATATYPE_LOOP | MR_DATATYPE_SHADING);
+ DRW_ADD_FLAG_FROM_VBO_REQUEST(mr_flag, cache->tess.pos_nor, MR_DATATYPE_VERT | MR_DATATYPE_LOOP | MR_DATATYPE_LOOPTRI | MR_DATATYPE_POLY);
+ DRW_ADD_FLAG_FROM_VBO_REQUEST(mr_flag, cache->tess.wireframe_data, MR_DATATYPE_VERT | MR_DATATYPE_EDGE | MR_DATATYPE_LOOP | MR_DATATYPE_LOOPTRI);
+ DRW_ADD_FLAG_FROM_IBO_REQUEST(mr_flag, cache->ibo.surf_tris, MR_DATATYPE_VERT | MR_DATATYPE_LOOPTRI);
+ DRW_ADD_FLAG_FROM_IBO_REQUEST(mr_flag, cache->ibo.loops_tris, MR_DATATYPE_LOOP | MR_DATATYPE_LOOPTRI);
+ DRW_ADD_FLAG_FROM_IBO_REQUEST(mr_flag, cache->ibo.loops_lines, MR_DATATYPE_LOOP | MR_DATATYPE_POLY);
+ for (int i = 0; i < cache->mat_len; ++i) {
+ DRW_ADD_FLAG_FROM_IBO_REQUEST(mr_flag, cache->surf_per_mat_tris[i], MR_DATATYPE_LOOP | MR_DATATYPE_LOOPTRI);
+ }
+
+ DRW_ADD_FLAG_FROM_VBO_REQUEST(mr_edit_flag, cache->edit.data, MR_DATATYPE_VERT | MR_DATATYPE_EDGE | MR_DATATYPE_LOOP | MR_DATATYPE_LOOPTRI | MR_DATATYPE_POLY | MR_DATATYPE_OVERLAY);
+ DRW_ADD_FLAG_FROM_VBO_REQUEST(mr_edit_flag, cache->edit.data_ledges, MR_DATATYPE_LOOSE_EDGE | MR_DATATYPE_VERT | MR_DATATYPE_EDGE | MR_DATATYPE_LOOP | MR_DATATYPE_OVERLAY);
+ DRW_ADD_FLAG_FROM_VBO_REQUEST(mr_edit_flag, cache->edit.data_lverts, MR_DATATYPE_LOOSE_VERT | MR_DATATYPE_VERT | MR_DATATYPE_LOOP | MR_DATATYPE_OVERLAY);
+ DRW_ADD_FLAG_FROM_VBO_REQUEST(mr_edit_flag, cache->edit.pos_nor, MR_DATATYPE_VERT | MR_DATATYPE_EDGE | MR_DATATYPE_LOOP | MR_DATATYPE_LOOPTRI | MR_DATATYPE_POLY | MR_DATATYPE_OVERLAY);
+ DRW_ADD_FLAG_FROM_VBO_REQUEST(mr_edit_flag, cache->edit.pos_nor_ledges, MR_DATATYPE_VERT | MR_DATATYPE_EDGE | MR_DATATYPE_LOOSE_EDGE | MR_DATATYPE_LOOP | MR_DATATYPE_OVERLAY);
+ DRW_ADD_FLAG_FROM_VBO_REQUEST(mr_edit_flag, cache->edit.pos_nor_lverts, MR_DATATYPE_VERT | MR_DATATYPE_LOOSE_VERT | MR_DATATYPE_OVERLAY);
+ DRW_ADD_FLAG_FROM_VBO_REQUEST(mr_edit_flag, cache->edit.pos_nor_data_facedots, MR_DATATYPE_VERT | MR_DATATYPE_LOOP | MR_DATATYPE_POLY | MR_DATATYPE_OVERLAY);
+ DRW_ADD_FLAG_FROM_VBO_REQUEST(mr_edit_flag, cache->edit.lnor, MR_DATATYPE_VERT | MR_DATATYPE_LOOP | MR_DATATYPE_LOOPTRI | MR_DATATYPE_OVERLAY);
+ DRW_ADD_FLAG_FROM_IBO_REQUEST(mr_edit_flag, cache->ibo.edit_verts_points, MR_DATATYPE_VERT | MR_DATATYPE_POLY | MR_DATATYPE_LOOPTRI);
+
+ Mesh *me_original = me;
+ MBC_GET_FINAL_MESH(me);
+
+ if (me_original == me) {
+ mr_flag |= mr_edit_flag;
+ }
+
+ MeshRenderData *rdata = mesh_render_data_create_ex(me, mr_flag, cache->cd_vused, cache->cd_lused);
+
+ /* Generate VBOs */
+ if (DRW_vbo_requested(cache->ordered.pos_nor)) {
+ mesh_create_pos_and_nor(rdata, cache->ordered.pos_nor);
+ }
+ if (DRW_vbo_requested(cache->ordered.weights)) {
+ mesh_create_weights(rdata, cache->ordered.weights, &cache->weight_state);
+ }
+ if (DRW_vbo_requested(cache->ordered.loop_pos_nor)) {
+ mesh_create_loop_pos_and_nor(rdata, cache->ordered.loop_pos_nor, use_face_sel);
+ }
+ if (DRW_vbo_requested(cache->ordered.loop_uv_tan)) {
+ mesh_create_loop_uv_and_tan(rdata, cache->ordered.loop_uv_tan);
+ }
+ if (DRW_vbo_requested(cache->ordered.loop_vcol)) {
+ mesh_create_loop_vcol(rdata, cache->ordered.loop_vcol);
+ }
+ if (DRW_vbo_requested(cache->tess.wireframe_data)) {
+ mesh_create_wireframe_data_tess(rdata, cache->tess.wireframe_data);
+ }
+ if (DRW_vbo_requested(cache->tess.pos_nor)) {
+ mesh_create_pos_and_nor_tess(rdata, cache->tess.pos_nor, use_hide);
+ }
+ if (DRW_ibo_requested(cache->ibo.surf_tris)) {
+ mesh_create_surf_tris(rdata, cache->ibo.surf_tris, use_hide);
+ }
+ if (DRW_ibo_requested(cache->ibo.loops_lines)) {
+ mesh_create_loops_lines(rdata, cache->ibo.loops_lines, use_hide);
+ }
+ if (DRW_ibo_requested(cache->ibo.loops_tris)) {
+ mesh_create_loops_tris(rdata, &cache->ibo.loops_tris, 1, use_hide);
+ }
+ if (DRW_ibo_requested(cache->surf_per_mat_tris[0])) {
+ mesh_create_loops_tris(rdata, cache->surf_per_mat_tris, cache->mat_len, use_hide);
+ }
+
+ /* Use original Mesh* to have the correct edit cage. */
+ if (me_original != me) {
+ mesh_render_data_free(rdata);
+ rdata = mesh_render_data_create(me_original, mr_edit_flag);
+ }
+
+ if (rdata->mapped.supported) {
+ rdata->mapped.use = true;
+ }
+
+ if (DRW_vbo_requested(cache->edit.data) ||
+ DRW_vbo_requested(cache->edit.pos_nor) ||
+ DRW_vbo_requested(cache->edit.lnor) ||
+ DRW_ibo_requested(cache->ibo.edit_verts_points))
+ {
+ mesh_create_edit_tris_and_verts(rdata, cache->edit.data, cache->edit.pos_nor,
+ cache->edit.lnor, cache->ibo.edit_verts_points);
+ }
+ if (DRW_vbo_requested(cache->edit.data_ledges) || DRW_vbo_requested(cache->edit.pos_nor_ledges)) {
+ mesh_create_edit_loose_edges(rdata, cache->edit.data_ledges, cache->edit.pos_nor_ledges);
+ }
+ if (DRW_vbo_requested(cache->edit.data_lverts) || DRW_vbo_requested(cache->edit.pos_nor_lverts)) {
+ mesh_create_edit_loose_verts(rdata, cache->edit.data_lverts, cache->edit.pos_nor_lverts);
+ }
+ if (DRW_vbo_requested(cache->edit.pos_nor_data_facedots)) {
+ mesh_create_edit_facedots(rdata, cache->edit.pos_nor_data_facedots);
+ }
+
+ mesh_render_data_free(rdata);
+
+#ifdef DEBUG
+ /* Make sure all requested batches have been setup. */
+ for (int i = 0; i < sizeof(cache->batch) / sizeof(void *); ++i) {
+ BLI_assert(!DRW_batch_requested(((GPUBatch **)&cache->batch)[i], 0));
+ }
+#endif
+}
+
+/** \} */
diff --git a/source/blender/draw/intern/draw_cache_impl_metaball.c b/source/blender/draw/intern/draw_cache_impl_metaball.c
index 841cb73d9c7..b77268fb0a7 100644
--- a/source/blender/draw/intern/draw_cache_impl_metaball.c
+++ b/source/blender/draw/intern/draw_cache_impl_metaball.c
@@ -59,10 +59,7 @@ typedef struct MetaBallBatchCache {
/* Wireframe */
struct {
- GPUVertBuf *elem_vbo;
- GPUTexture *elem_tx;
- GPUTexture *verts_tx;
- int tri_count;
+ GPUBatch *batch;
} face_wire;
/* settings to determine if cache is invalid */
@@ -94,10 +91,7 @@ static void metaball_batch_cache_init(MetaBall *mb)
cache->shaded_triangles = NULL;
cache->is_dirty = false;
cache->pos_nor_in_order = NULL;
- cache->face_wire.elem_vbo = NULL;
- cache->face_wire.elem_tx = NULL;
- cache->face_wire.verts_tx = NULL;
- cache->face_wire.tri_count = 0;
+ cache->face_wire.batch = NULL;
}
static MetaBallBatchCache *metaball_batch_cache_get(MetaBall *mb)
@@ -131,10 +125,7 @@ static void metaball_batch_cache_clear(MetaBall *mb)
return;
}
- GPU_VERTBUF_DISCARD_SAFE(cache->face_wire.elem_vbo);
- DRW_TEXTURE_FREE_SAFE(cache->face_wire.elem_tx);
- DRW_TEXTURE_FREE_SAFE(cache->face_wire.verts_tx);
-
+ GPU_BATCH_DISCARD_SAFE(cache->face_wire.batch);
GPU_BATCH_DISCARD_SAFE(cache->batch);
GPU_VERTBUF_DISCARD_SAFE(cache->pos_nor_in_order);
/* Note: shaded_triangles[0] is already freed by cache->batch */
@@ -152,41 +143,12 @@ static GPUVertBuf *mball_batch_cache_get_pos_and_normals(Object *ob, MetaBallBat
{
if (cache->pos_nor_in_order == NULL) {
ListBase *lb = &ob->runtime.curve_cache->disp;
- cache->pos_nor_in_order = DRW_displist_vertbuf_calc_pos_with_normals(lb);
+ cache->pos_nor_in_order = MEM_callocN(sizeof(GPUVertBuf), __func__);
+ DRW_displist_vertbuf_create_pos_and_nor(lb, cache->pos_nor_in_order);
}
return cache->pos_nor_in_order;
}
-static GPUTexture *mball_batch_cache_get_edges_overlay_texture_buf(Object *ob, MetaBallBatchCache *cache)
-{
- if (cache->face_wire.elem_tx != NULL) {
- return cache->face_wire.elem_tx;
- }
-
- ListBase *lb = &ob->runtime.curve_cache->disp;
-
- /* We need a special index buffer. */
- GPUVertBuf *vbo = cache->face_wire.elem_vbo = DRW_displist_create_edges_overlay_texture_buf(lb);
-
- /* Upload data early because we need to create the texture for it. */
- GPU_vertbuf_use(vbo);
- cache->face_wire.elem_tx = GPU_texture_create_from_vertbuf(vbo);
- cache->face_wire.tri_count = vbo->vertex_alloc / 3;
-
- return cache->face_wire.elem_tx;
-}
-
-static GPUTexture *mball_batch_cache_get_vert_pos_and_nor_in_order_buf(Object *ob, MetaBallBatchCache *cache)
-{
- if (cache->face_wire.verts_tx == NULL) {
- GPUVertBuf *vbo = mball_batch_cache_get_pos_and_normals(ob, cache);
- GPU_vertbuf_use(vbo); /* Upload early for buffer texture creation. */
- cache->face_wire.verts_tx = GPU_texture_create_buffer(GPU_R32F, vbo->vbo_id);
- }
-
- return cache->face_wire.verts_tx;
-}
-
/* -------------------------------------------------------------------- */
/** \name Public Object/MetaBall API
@@ -203,10 +165,12 @@ GPUBatch *DRW_metaball_batch_cache_get_triangles_with_normals(Object *ob)
if (cache->batch == NULL) {
ListBase *lb = &ob->runtime.curve_cache->disp;
+ GPUIndexBuf *ibo = MEM_callocN(sizeof(GPUIndexBuf), __func__);
+ DRW_displist_indexbuf_create_triangles_in_order(lb, ibo);
cache->batch = GPU_batch_create_ex(
GPU_PRIM_TRIS,
mball_batch_cache_get_pos_and_normals(ob, cache),
- DRW_displist_indexbuf_calc_triangles_in_order(lb),
+ ibo,
GPU_BATCH_OWNS_INDEX);
}
@@ -232,26 +196,27 @@ GPUBatch **DRW_metaball_batch_cache_get_surface_shaded(Object *ob, MetaBall *mb,
}
-void DRW_metaball_batch_cache_get_wireframes_face_texbuf(
- Object *ob, struct GPUTexture **verts_data, struct GPUTexture **face_indices, int *tri_count)
+GPUBatch *DRW_metaball_batch_cache_get_wireframes_face(Object *ob)
{
if (!BKE_mball_is_basis(ob)) {
- *verts_data = NULL;
- *face_indices = NULL;
- *tri_count = 0;
- return;
+ return NULL;
}
MetaBall *mb = ob->data;
MetaBallBatchCache *cache = metaball_batch_cache_get(mb);
- if (cache->face_wire.verts_tx == NULL) {
- *verts_data = mball_batch_cache_get_vert_pos_and_nor_in_order_buf(ob, cache);
- *face_indices = mball_batch_cache_get_edges_overlay_texture_buf(ob, cache);
- }
- else {
- *verts_data = cache->face_wire.verts_tx;
- *face_indices = cache->face_wire.elem_tx;
+ if (cache->face_wire.batch == NULL) {
+ ListBase *lb = &ob->runtime.curve_cache->disp;
+
+ GPUVertBuf *vbo_pos_nor = MEM_callocN(sizeof(GPUVertBuf), __func__);
+ GPUVertBuf *vbo_wireframe_data = MEM_callocN(sizeof(GPUVertBuf), __func__);
+
+ DRW_displist_vertbuf_create_pos_and_nor_and_uv_tess(lb, vbo_pos_nor, NULL);
+ DRW_displist_vertbuf_create_wireframe_data_tess(lb, vbo_wireframe_data);
+
+ cache->face_wire.batch = GPU_batch_create_ex(GPU_PRIM_TRIS, vbo_pos_nor, NULL, GPU_BATCH_OWNS_VBO);
+ GPU_batch_vertbuf_add_ex(cache->face_wire.batch, vbo_wireframe_data, true);
}
- *tri_count = cache->face_wire.tri_count;
+
+ return cache->face_wire.batch;
}
diff --git a/source/blender/draw/intern/draw_cache_impl_particles.c b/source/blender/draw/intern/draw_cache_impl_particles.c
index 2eec85807b6..b6c0fa42331 100644
--- a/source/blender/draw/intern/draw_cache_impl_particles.c
+++ b/source/blender/draw/intern/draw_cache_impl_particles.c
@@ -80,6 +80,9 @@ typedef struct ParticleBatchCache {
/* Control points when in edit mode. */
ParticleHairCache edit_hair;
+ GPUVertBuf *edit_pos;
+ GPUBatch *edit_strands;
+
GPUVertBuf *edit_inner_pos;
GPUBatch *edit_inner_points;
int edit_inner_point_len;
@@ -90,6 +93,7 @@ typedef struct ParticleBatchCache {
/* Settings to determine if cache is invalid. */
bool is_dirty;
+ bool edit_is_weight;
} ParticleBatchCache;
/* GPUBatch cache management. */
@@ -100,6 +104,25 @@ typedef struct HairAttributeID {
uint ind;
} HairAttributeID;
+typedef struct EditStrandData {
+ float pos[3];
+ uchar color;
+} EditStrandData;
+
+static GPUVertFormat *edit_points_vert_format_get(uint *r_pos_id, uint *r_color_id)
+{
+ static GPUVertFormat edit_point_format = { 0 };
+ static uint pos_id, color_id;
+ if (edit_point_format.attr_len == 0) {
+ /* Keep in sync with EditStrandData */
+ pos_id = GPU_vertformat_attr_add(&edit_point_format, "pos", GPU_COMP_F32, 3, GPU_FETCH_FLOAT);
+ color_id = GPU_vertformat_attr_add(&edit_point_format, "color", GPU_COMP_U8, 1, GPU_FETCH_INT_TO_FLOAT_UNIT);
+ }
+ *r_pos_id = pos_id;
+ *r_color_id = color_id;
+ return &edit_point_format;
+}
+
static bool particle_batch_cache_valid(ParticleSystem *psys)
{
ParticleBatchCache *cache = psys->batch_cache;
@@ -622,6 +645,78 @@ static void particle_batch_cache_fill_segments_proc_pos(
}
}
+static float particle_key_select_ratio(const PTCacheEdit *edit, int strand, float t)
+{
+ const PTCacheEditPoint *point = &edit->points[strand];
+ float edit_key_seg_t = 1.0f / (point->totkey - 1);
+ if (t == 1.0) {
+ return (point->keys[point->totkey - 1].flag & PEK_SELECT) ? 1.0f : 0.0;
+ }
+ else {
+ float interp = t / edit_key_seg_t;
+ int index = (int)interp;
+ interp -= floorf(interp); /* Time between 2 edit key */
+ float s1 = (point->keys[index].flag & PEK_SELECT) ? 1.0f : 0.0;
+ float s2 = (point->keys[index + 1].flag & PEK_SELECT) ? 1.0f : 0.0;
+ return s1 + interp * (s2 - s1);
+ }
+}
+
+static float particle_key_weight(const ParticleData *particle, int strand, float t)
+{
+ const ParticleData *part = particle + strand;
+ const HairKey *hkeys = part->hair;
+ float edit_key_seg_t = 1.0f / (part->totkey - 1);
+ if (t == 1.0) {
+ return hkeys[part->totkey - 1].weight;
+ }
+ else {
+ float interp = t / edit_key_seg_t;
+ int index = (int)interp;
+ interp -= floorf(interp); /* Time between 2 edit key */
+ float s1 = hkeys[index].weight;
+ float s2 = hkeys[index + 1].weight;
+ return s1 + interp * (s2 - s1);
+ }
+}
+
+static int particle_batch_cache_fill_segments_edit(
+ const PTCacheEdit *edit, /* NULL for weight data */
+ const ParticleData *particle, /* NULL for select data */
+ ParticleCacheKey **path_cache,
+ const int start_index,
+ const int num_path_keys,
+ GPUIndexBufBuilder *elb,
+ GPUVertBufRaw *attr_step)
+{
+ int curr_point = start_index;
+ for (int i = 0; i < num_path_keys; i++) {
+ ParticleCacheKey *path = path_cache[i];
+ if (path->segments <= 0) {
+ continue;
+ }
+ for (int j = 0; j <= path->segments; j++) {
+ EditStrandData *seg_data = (EditStrandData *)GPU_vertbuf_raw_step(attr_step);
+ copy_v3_v3(seg_data->pos, path[j].co);
+ float strand_t = (float)(j) / path->segments;
+ if (particle) {
+ float weight = particle_key_weight(particle, i, strand_t);
+ /* NaN or unclamped become 0xFF */
+ seg_data->color = (uchar)((weight <= 1.0f) ? 0xFE * weight : 0xFF);
+ }
+ else {
+ float selected = particle_key_select_ratio(edit, i, strand_t);
+ seg_data->color = (uchar)(0xFF * selected);
+ }
+ GPU_indexbuf_add_generic_vert(elb, curr_point);
+ curr_point++;
+ }
+ /* Finish the segment and add restart primitive. */
+ GPU_indexbuf_add_primitive_restart(elb);
+ }
+ return curr_point;
+}
+
static int particle_batch_cache_fill_segments_indices(
const ParticleSystem *psys,
ParticleCacheKey **path_cache,
@@ -1409,22 +1504,71 @@ GPUBatch *DRW_particles_batch_cache_get_dots(Object *object, ParticleSystem *psy
return cache->point.points;
}
+static void particle_batch_cache_ensure_edit_pos_and_seg(
+ PTCacheEdit *edit,
+ ParticleSystem *psys,
+ ModifierData *UNUSED(md),
+ ParticleHairCache *hair_cache,
+ bool use_weight)
+{
+ if (hair_cache->pos != NULL && hair_cache->indices != NULL) {
+ return;
+ }
+
+ ParticleData *particle = (use_weight) ? psys->particles : NULL;
+
+ GPU_VERTBUF_DISCARD_SAFE(hair_cache->pos);
+ GPU_INDEXBUF_DISCARD_SAFE(hair_cache->indices);
+
+ GPUVertBufRaw data_step;
+ GPUIndexBufBuilder elb;
+ uint pos_id, color_id;
+ GPUVertFormat *edit_point_format = edit_points_vert_format_get(&pos_id, &color_id);
+
+ hair_cache->pos = GPU_vertbuf_create_with_format(edit_point_format);
+ GPU_vertbuf_data_alloc(hair_cache->pos, hair_cache->point_len);
+ GPU_vertbuf_attr_get_raw_data(hair_cache->pos, pos_id, &data_step);
+
+ GPU_indexbuf_init_ex(
+ &elb,
+ GPU_PRIM_LINE_STRIP,
+ hair_cache->elems_len, hair_cache->point_len,
+ true);
+
+ if (edit != NULL && edit->pathcache != NULL) {
+ particle_batch_cache_fill_segments_edit(
+ edit, particle, edit->pathcache,
+ 0, edit->totcached,
+ &elb, &data_step);
+ }
+ else {
+ BLI_assert(!"Hairs are not in edit mode!");
+ }
+ hair_cache->indices = GPU_indexbuf_build(&elb);
+}
+
GPUBatch *DRW_particles_batch_cache_get_edit_strands(
Object *object,
ParticleSystem *psys,
- PTCacheEdit *edit)
+ PTCacheEdit *edit,
+ bool use_weight)
{
ParticleBatchCache *cache = particle_batch_cache_get(psys);
+ if (cache->edit_is_weight != use_weight) {
+ GPU_VERTBUF_DISCARD_SAFE(cache->edit_hair.pos);
+ GPU_BATCH_DISCARD_SAFE(cache->edit_hair.hairs);
+ }
if (cache->edit_hair.hairs != NULL) {
return cache->edit_hair.hairs;
}
drw_particle_update_ptcache_edit(object, psys, edit);
ensure_seg_pt_count(edit, psys, &cache->edit_hair);
- particle_batch_cache_ensure_pos_and_seg(edit, psys, NULL, &cache->edit_hair);
+ particle_batch_cache_ensure_edit_pos_and_seg(edit, psys, NULL, &cache->edit_hair, use_weight);
cache->edit_hair.hairs = GPU_batch_create(
GPU_PRIM_LINE_STRIP,
cache->edit_hair.pos,
cache->edit_hair.indices);
+ cache->edit_is_weight = use_weight;
return cache->edit_hair.hairs;
}
@@ -1443,17 +1587,6 @@ static void ensure_edit_inner_points_count(
}
}
-static void edit_colors_get(
- PTCacheEdit *edit,
- float selected_color[4],
- float normal_color[4])
-{
- rgb_uchar_to_float(selected_color, edit->sel_col);
- rgb_uchar_to_float(normal_color, edit->nosel_col);
- selected_color[3] = 1.0f;
- normal_color[3] = 1.0f;
-}
-
static void particle_batch_cache_ensure_edit_inner_pos(
PTCacheEdit *edit,
ParticleBatchCache *cache)
@@ -1462,35 +1595,20 @@ static void particle_batch_cache_ensure_edit_inner_pos(
return;
}
- static GPUVertFormat format = { 0 };
- static uint pos_id, color_id;
+ uint pos_id, color_id;
+ GPUVertFormat *edit_point_format = edit_points_vert_format_get(&pos_id, &color_id);
- GPU_VERTBUF_DISCARD_SAFE(cache->edit_inner_pos);
-
- if (format.attr_len == 0) {
- /* initialize vertex format */
- pos_id = GPU_vertformat_attr_add(&format, "pos", GPU_COMP_F32, 3, GPU_FETCH_FLOAT);
- color_id = GPU_vertformat_attr_add(&format, "color", GPU_COMP_F32, 4, GPU_FETCH_FLOAT);
- }
-
- cache->edit_inner_pos = GPU_vertbuf_create_with_format(&format);
+ cache->edit_inner_pos = GPU_vertbuf_create_with_format(edit_point_format);
GPU_vertbuf_data_alloc(cache->edit_inner_pos, cache->edit_inner_point_len);
- float selected_color[4], normal_color[4];
- edit_colors_get(edit, selected_color, normal_color);
-
int global_key_index = 0;
for (int point_index = 0; point_index < edit->totpoint; point_index++) {
const PTCacheEditPoint *point = &edit->points[point_index];
for (int key_index = 0; key_index < point->totkey - 1; key_index++) {
PTCacheEditKey *key = &point->keys[key_index];
+ uchar color = (key->flag & PEK_SELECT) ? 0xFF : 0x00;
GPU_vertbuf_attr_set(cache->edit_inner_pos, pos_id, global_key_index, key->world_co);
- if (key->flag & PEK_SELECT) {
- GPU_vertbuf_attr_set(cache->edit_inner_pos, color_id, global_key_index, selected_color);
- }
- else {
- GPU_vertbuf_attr_set(cache->edit_inner_pos, color_id, global_key_index, normal_color);
- }
+ GPU_vertbuf_attr_set(cache->edit_inner_pos, color_id, global_key_index, &color);
global_key_index++;
}
}
@@ -1533,33 +1651,18 @@ static void particle_batch_cache_ensure_edit_tip_pos(
return;
}
- static GPUVertFormat format = { 0 };
- static uint pos_id, color_id;
-
- GPU_VERTBUF_DISCARD_SAFE(cache->edit_tip_pos);
+ uint pos_id, color_id;
+ GPUVertFormat *edit_point_format = edit_points_vert_format_get(&pos_id, &color_id);
- if (format.attr_len == 0) {
- /* initialize vertex format */
- pos_id = GPU_vertformat_attr_add(&format, "pos", GPU_COMP_F32, 3, GPU_FETCH_FLOAT);
- color_id = GPU_vertformat_attr_add(&format, "color", GPU_COMP_F32, 4, GPU_FETCH_FLOAT);
- }
-
- cache->edit_tip_pos = GPU_vertbuf_create_with_format(&format);
+ cache->edit_tip_pos = GPU_vertbuf_create_with_format(edit_point_format);
GPU_vertbuf_data_alloc(cache->edit_tip_pos, cache->edit_tip_point_len);
- float selected_color[4], normal_color[4];
- edit_colors_get(edit, selected_color, normal_color);
-
for (int point_index = 0; point_index < edit->totpoint; point_index++) {
const PTCacheEditPoint *point = &edit->points[point_index];
PTCacheEditKey *key = &point->keys[point->totkey - 1];
+ uchar color = (key->flag & PEK_SELECT) ? 0xFF : 0x00;
GPU_vertbuf_attr_set(cache->edit_tip_pos, pos_id, point_index, key->world_co);
- if (key->flag & PEK_SELECT) {
- GPU_vertbuf_attr_set(cache->edit_tip_pos, color_id, point_index, selected_color);
- }
- else {
- GPU_vertbuf_attr_set(cache->edit_tip_pos, color_id, point_index, normal_color);
- }
+ GPU_vertbuf_attr_set(cache->edit_tip_pos, color_id, point_index, &color);
}
}
@@ -1624,6 +1727,5 @@ bool particles_ensure_procedural_data(
particle_batch_cache_ensure_procedural_indices(source.edit, source.psys, &cache->hair, thickness_res, subdiv);
}
-
return need_ft_update;
}
diff --git a/source/blender/draw/intern/draw_common.c b/source/blender/draw/intern/draw_common.c
index 4d33e6ed802..837b6e5d051 100644
--- a/source/blender/draw/intern/draw_common.c
+++ b/source/blender/draw/intern/draw_common.c
@@ -87,6 +87,10 @@ void DRW_globals_update(void)
UI_GetThemeColor4fv(TH_FACE_DOT, ts.colorFaceDot);
UI_GetThemeColor4fv(TH_BACK, ts.colorBackground);
+ /* Custom median color to slightly affect the edit mesh colors. */
+ interp_v4_v4v4(ts.colorEditMeshMiddle, ts.colorVertexSelect, ts.colorWireEdit, 0.35f);
+ copy_v3_fl(ts.colorEditMeshMiddle, dot_v3v3(ts.colorEditMeshMiddle, (float[3]){0.3333f, 0.3333f, 0.3333f})); /* Desaturate */
+
#ifdef WITH_FREESTYLE
UI_GetThemeColor4fv(TH_FREESTYLE_EDGE_MARK, ts.colorEdgeFreestyle);
UI_GetThemeColor4fv(TH_FREESTYLE_FACE_MARK, ts.colorFaceFreestyle);
@@ -159,29 +163,28 @@ void DRW_globals_update(void)
DRW_uniformbuffer_update(globals_ubo, &ts);
- ColorBand ramp = {0};
- float *colors;
- int col_size;
+ if (!globals_ramp) {
+ ColorBand ramp = {0};
+ float *colors;
+ int col_size;
- ramp.tot = 3;
- ramp.data[0].a = 1.0f;
- ramp.data[0].b = 1.0f;
- ramp.data[0].pos = 0.0f;
- ramp.data[1].a = 1.0f;
- ramp.data[1].g = 1.0f;
- ramp.data[1].pos = 0.5f;
- ramp.data[2].a = 1.0f;
- ramp.data[2].r = 1.0f;
- ramp.data[2].pos = 1.0f;
+ ramp.tot = 3;
+ ramp.data[0].a = 1.0f;
+ ramp.data[0].b = 1.0f;
+ ramp.data[0].pos = 0.0f;
+ ramp.data[1].a = 1.0f;
+ ramp.data[1].g = 1.0f;
+ ramp.data[1].pos = 0.5f;
+ ramp.data[2].a = 1.0f;
+ ramp.data[2].r = 1.0f;
+ ramp.data[2].pos = 1.0f;
- BKE_colorband_evaluate_table_rgba(&ramp, &colors, &col_size);
+ BKE_colorband_evaluate_table_rgba(&ramp, &colors, &col_size);
- if (globals_ramp) {
- GPU_texture_free(globals_ramp);
- }
- globals_ramp = GPU_texture_create_1D(col_size, GPU_RGBA8, colors, NULL);
+ globals_ramp = GPU_texture_create_1D(col_size, GPU_RGBA8, colors, NULL);
- MEM_freeN(colors);
+ MEM_freeN(colors);
+ }
/* Weight Painting color ramp texture */
bool user_weight_ramp = (U.flag & USER_CUSTOM_RANGE) != 0;
@@ -366,7 +369,6 @@ DRWShadingGroup *shgroup_instance_screenspace(DRWPass *pass, struct GPUBatch *ge
DRW_shgroup_uniform_float(grp, "size", size, 1);
DRW_shgroup_uniform_float(grp, "pixel_size", DRW_viewport_pixelsize_get(), 1);
DRW_shgroup_uniform_vec3(grp, "screen_vecs[0]", DRW_viewport_screenvecs_get(), 2);
- DRW_shgroup_state_enable(grp, DRW_STATE_STIPPLE_3);
return grp;
}
@@ -876,9 +878,11 @@ int DRW_object_wire_theme_get(Object *ob, ViewLayer *view_layer, float **r_color
* note: no theme yet for 'colindex' */
int theme_id = is_edit ? TH_WIRE_EDIT : TH_WIRE;
- if (//(scene->obedit == NULL) &&
- ((G.moving & G_TRANSFORM_OBJ) != 0) &&
- ((ob->base_flag & BASE_SELECTED) != 0))
+ if (is_edit) {
+ /* fallback to TH_WIRE */
+ }
+ else if (((G.moving & G_TRANSFORM_OBJ) != 0) &&
+ ((ob->base_flag & BASE_SELECTED) != 0))
{
theme_id = TH_TRANSFORM;
}
diff --git a/source/blender/draw/intern/draw_common.h b/source/blender/draw/intern/draw_common.h
index 90097a6415f..ff276c0e08b 100644
--- a/source/blender/draw/intern/draw_common.h
+++ b/source/blender/draw/intern/draw_common.h
@@ -84,6 +84,7 @@ typedef struct GlobalsUboStorage {
float colorLampNoAlpha[4];
float colorBackground[4];
+ float colorEditMeshMiddle[4];
float colorHandleFree[4];
float colorHandleAuto[4];
diff --git a/source/blender/draw/intern/draw_hair.c b/source/blender/draw/intern/draw_hair.c
index 51943b2f102..9c6b057e1cb 100644
--- a/source/blender/draw/intern/draw_hair.c
+++ b/source/blender/draw/intern/draw_hair.c
@@ -41,6 +41,7 @@
#include "DNA_particle_types.h"
#include "DNA_customdata_types.h"
+#include "BKE_anim.h"
#include "BKE_hair.h"
#include "BKE_mesh.h"
#include "BKE_particle.h"
@@ -87,6 +88,12 @@ void DRW_hair_init(void)
g_tf_pass = DRW_pass_create("Update Hair Pass", DRW_STATE_TRANS_FEEDBACK);
}
+typedef struct DRWHairInstanceData {
+ DrawData dd;
+
+ float mat[4][4];
+} DRWHairInstanceData;
+
void particle_batch_cache_clear_hair(ParticleHairCache *hair_cache)
{
/* TODO more granular update tagging. */
@@ -126,6 +133,15 @@ static DRWShadingGroup *drw_shgroup_create_particle_hair_procedural_ex(
/* TODO(fclem): Pass the scene as parameter */
const DRWContextState *draw_ctx = DRW_context_state_get();
Scene *scene = draw_ctx->scene;
+ static float unit_mat[4][4] = {
+ {1, 0, 0, 0},
+ {0, 1, 0, 0},
+ {0, 0, 1, 0},
+ {0, 0, 0, 1},
+ };
+ float (*dupli_mat)[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;
@@ -158,10 +174,29 @@ static DRWShadingGroup *drw_shgroup_create_particle_hair_procedural_ex(
}
}
+ if (dupli_parent) {
+ DRWHairInstanceData *hair_inst_data = (DRWHairInstanceData *)DRW_drawdata_ensure(
+ &object->id, (DrawEngineType *)&drw_shgroup_create_particle_hair_procedural_ex,
+ sizeof(DRWHairInstanceData), NULL, NULL);
+ dupli_mat = hair_inst_data->mat;
+ 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 {
+ dupli_mat = unit_mat;
+ }
+
DRW_shgroup_uniform_texture(shgrp, "hairPointBuffer", hair_cache->final[subdiv].proc_tex);
DRW_shgroup_uniform_texture(shgrp, "hairIndexBuffer", hair_cache->final[subdiv].hair_index_tex);
DRW_shgroup_uniform_int_copy(shgrp, "hairThicknessRes", thickness_res);
DRW_shgroup_uniform_float(shgrp, "hairRadShape", &part->shape, 1);
+ DRW_shgroup_uniform_mat4(shgrp, "hairDupliMatrix", dupli_mat);
DRW_shgroup_uniform_float_copy(shgrp, "hairRadRoot", part->rad_root * part->rad_scale * 0.5f);
DRW_shgroup_uniform_float_copy(shgrp, "hairRadTip", part->rad_tip * part->rad_scale * 0.5f);
DRW_shgroup_uniform_bool_copy(shgrp, "hairCloseTip", (part->shape_flag & PART_SHAPE_CLOSE_TIP) != 0);
diff --git a/source/blender/draw/intern/draw_manager.c b/source/blender/draw/intern/draw_manager.c
index 54693bd95e7..049f58cb509 100644
--- a/source/blender/draw/intern/draw_manager.c
+++ b/source/blender/draw/intern/draw_manager.c
@@ -33,6 +33,7 @@
#include "BLF_api.h"
+#include "BKE_colortools.h"
#include "BKE_global.h"
#include "BKE_mesh.h"
#include "BKE_object.h"
@@ -189,6 +190,24 @@ bool DRW_object_is_flat_normal(const Object *ob)
return true;
}
+bool DRW_object_use_hide_faces(const struct Object *ob)
+{
+ if (ob->type == OB_MESH) {
+ const Mesh *me = DEG_get_original_object((Object *)ob)->data;
+
+ switch (ob->mode) {
+ case OB_MODE_TEXTURE_PAINT:
+ case OB_MODE_VERTEX_PAINT:
+ return (me->editflag & ME_EDIT_PAINT_FACE_SEL) != 0;
+
+ case OB_MODE_WEIGHT_PAINT:
+ return (me->editflag & (ME_EDIT_PAINT_FACE_SEL | ME_EDIT_PAINT_VERT_SEL)) != 0;
+ }
+ }
+
+ return false;
+}
+
bool DRW_object_is_visible_psys_in_active_context(
const Object *object,
const ParticleSystem *psys)
@@ -216,6 +235,16 @@ bool DRW_object_is_visible_psys_in_active_context(
return true;
}
+struct Object *DRW_object_get_dupli_parent(const Object *UNUSED(ob))
+{
+ return DST.dupli_parent;
+}
+
+struct DupliObject *DRW_object_get_dupli(const Object *UNUSED(ob))
+{
+ return DST.dupli_source;
+}
+
/** \} */
@@ -241,10 +270,19 @@ void DRW_transform_to_display(GPUTexture *tex, bool use_view_settings)
if (!(DST.options.is_image_render && !DST.options.is_scene_render)) {
Scene *scene = DST.draw_ctx.scene;
ColorManagedDisplaySettings *display_settings = &scene->display_settings;
- ColorManagedViewSettings *view_settings = (use_view_settings) ? &scene->view_settings : NULL;
-
+ ColorManagedViewSettings *active_view_settings;
+ ColorManagedViewSettings default_view_settings;
+ if (use_view_settings) {
+ active_view_settings = &scene->view_settings;
+ }
+ else {
+ BKE_color_managed_view_settings_init_render(
+ &default_view_settings,
+ display_settings);
+ active_view_settings = &default_view_settings;
+ }
use_ocio = IMB_colormanagement_setup_glsl_draw_from_space(
- view_settings, display_settings, NULL, dither, false);
+ active_view_settings, display_settings, NULL, dither, false);
}
if (!use_ocio) {
@@ -980,6 +1018,10 @@ static void drw_engines_cache_populate(Object *ob)
}
}
+ /* TODO: in the future it would be nice to generate once for all viewports.
+ * But we need threaded DRW manager first. */
+ drw_batch_cache_generate_requested(ob);
+
/* ... and clearing it here too because theses draw data are
* from a mempool and must not be free individually by depsgraph. */
drw_drawdata_unlink_dupli((ID *)ob);
@@ -1216,10 +1258,10 @@ static void drw_engines_enable_from_mode(int mode)
case CTX_MODE_PAINT_VERTEX:
case CTX_MODE_PAINT_TEXTURE:
case CTX_MODE_OBJECT:
- case CTX_MODE_GPENCIL_PAINT:
- case CTX_MODE_GPENCIL_EDIT:
- case CTX_MODE_GPENCIL_SCULPT:
- case CTX_MODE_GPENCIL_WEIGHT:
+ case CTX_MODE_PAINT_GPENCIL:
+ case CTX_MODE_EDIT_GPENCIL:
+ case CTX_MODE_SCULPT_GPENCIL:
+ case CTX_MODE_WEIGHT_GPENCIL:
break;
default:
BLI_assert(!"Draw mode invalid");
@@ -1427,13 +1469,23 @@ void DRW_draw_render_loop_ex(
drw_engines_world_update(scene);
const int object_type_exclude_viewport = v3d->object_type_exclude_viewport;
- DEG_OBJECT_ITER_FOR_RENDER_ENGINE_BEGIN(depsgraph, ob)
+ DEG_OBJECT_ITER_BEGIN(depsgraph, ob,
+ DEG_ITER_OBJECT_FLAG_LINKED_DIRECTLY |
+ DEG_ITER_OBJECT_FLAG_LINKED_VIA_SET |
+ DEG_ITER_OBJECT_FLAG_VISIBLE |
+ DEG_ITER_OBJECT_FLAG_DUPLI)
{
- if ((object_type_exclude_viewport & (1 << ob->type)) == 0) {
- drw_engines_cache_populate(ob);
+ if ((object_type_exclude_viewport & (1 << ob->type)) != 0) {
+ continue;
}
+ if (v3d->localvd && ((v3d->local_view_uuid & ob->base_local_view_bits) == 0)) {
+ continue;
+ }
+ DST.dupli_parent = data_.dupli_parent;
+ DST.dupli_source = data_.dupli_object_current;
+ drw_engines_cache_populate(ob);
}
- DEG_OBJECT_ITER_FOR_RENDER_ENGINE_END;
+ DEG_OBJECT_ITER_END;
drw_engines_cache_finish();
@@ -1481,6 +1533,11 @@ void DRW_draw_render_loop_ex(
drw_engines_draw_scene();
+#ifdef __APPLE__
+ /* Fix 3D view being "laggy" on macos. (See T56996) */
+ GPU_flush();
+#endif
+
/* annotations - temporary drawing buffer (3d space) */
/* XXX: Or should we use a proper draw/overlay engine for this case? */
if (do_annotations) {
@@ -1852,14 +1909,22 @@ void DRW_render_object_iter(
DRW_hair_init();
const int object_type_exclude_viewport = draw_ctx->v3d ? draw_ctx->v3d->object_type_exclude_viewport : 0;
- DEG_OBJECT_ITER_FOR_RENDER_ENGINE_BEGIN(depsgraph, ob)
+ DEG_OBJECT_ITER_BEGIN(depsgraph, ob,
+ DEG_ITER_OBJECT_FLAG_LINKED_DIRECTLY |
+ DEG_ITER_OBJECT_FLAG_LINKED_VIA_SET |
+ DEG_ITER_OBJECT_FLAG_VISIBLE |
+ DEG_ITER_OBJECT_FLAG_DUPLI)
{
if ((object_type_exclude_viewport & (1 << ob->type)) == 0) {
+ DST.dupli_parent = data_.dupli_parent;
+ DST.dupli_source = data_.dupli_object_current;
DST.ob_state = NULL;
callback(vedata, ob, engine, depsgraph);
+
+ drw_batch_cache_generate_requested(ob);
}
}
- DEG_OBJECT_ITER_FOR_RENDER_ENGINE_END
+ DEG_OBJECT_ITER_END
}
/* Assume a valid gl context is bound (and that the gl_context_mutex has been acquired).
@@ -2046,7 +2111,7 @@ void DRW_draw_select_loop(
#if 0
drw_engines_cache_populate(obact);
#else
- FOREACH_OBJECT_IN_MODE_BEGIN (view_layer, obact->mode, ob_iter) {
+ FOREACH_OBJECT_IN_MODE_BEGIN (view_layer, v3d, obact->type, obact->mode, ob_iter) {
drw_engines_cache_populate(ob_iter);
}
FOREACH_OBJECT_IN_MODE_END;
@@ -2057,12 +2122,16 @@ void DRW_draw_select_loop(
v3d->object_type_exclude_viewport | v3d->object_type_exclude_select
);
bool filter_exclude = false;
- DEG_OBJECT_ITER_BEGIN(
- depsgraph, ob,
+ DEG_OBJECT_ITER_BEGIN(depsgraph, ob,
DEG_ITER_OBJECT_FLAG_LINKED_DIRECTLY |
+ DEG_ITER_OBJECT_FLAG_LINKED_VIA_SET |
DEG_ITER_OBJECT_FLAG_VISIBLE |
DEG_ITER_OBJECT_FLAG_DUPLI)
{
+ if (v3d->localvd && ((v3d->local_view_uuid & ob->base_local_view_bits) == 0)) {
+ continue;
+ }
+
if ((ob->base_flag & BASE_SELECTABLE) &&
(object_type_exclude_select & (1 << ob->type)) == 0)
{
@@ -2083,6 +2152,8 @@ void DRW_draw_select_loop(
Object *ob_orig = DEG_get_original_object(ob);
DRW_select_load_id(ob_orig->select_color);
}
+ DST.dupli_parent = data_.dupli_parent;
+ DST.dupli_source = data_.dupli_object_current;
drw_engines_cache_populate(ob);
}
}
@@ -2211,7 +2282,9 @@ void DRW_draw_depth_loop(
/* Get list of enabled engines */
{
drw_engines_enable_basic();
- drw_engines_enable_from_object_mode();
+ if (DRW_state_draw_support()) {
+ drw_engines_enable_from_object_mode();
+ }
}
/* Setup viewport */
@@ -2238,13 +2311,25 @@ void DRW_draw_depth_loop(
drw_engines_world_update(scene);
const int object_type_exclude_viewport = v3d->object_type_exclude_viewport;
- DEG_OBJECT_ITER_FOR_RENDER_ENGINE_BEGIN(depsgraph, ob)
+ DEG_OBJECT_ITER_BEGIN(depsgraph, ob,
+ DEG_ITER_OBJECT_FLAG_LINKED_DIRECTLY |
+ DEG_ITER_OBJECT_FLAG_LINKED_VIA_SET |
+ DEG_ITER_OBJECT_FLAG_VISIBLE |
+ DEG_ITER_OBJECT_FLAG_DUPLI)
{
- if ((object_type_exclude_viewport & (1 << ob->type)) == 0) {
- drw_engines_cache_populate(ob);
+ if ((object_type_exclude_viewport & (1 << ob->type)) != 0) {
+ continue;
+ }
+
+ if (v3d->localvd && ((v3d->local_view_uuid & ob->base_local_view_bits) == 0)) {
+ continue;
}
+
+ DST.dupli_parent = data_.dupli_parent;
+ DST.dupli_source = data_.dupli_object_current;
+ drw_engines_cache_populate(ob);
}
- DEG_OBJECT_ITER_FOR_RENDER_ENGINE_END;
+ DEG_OBJECT_ITER_END;
drw_engines_cache_finish();
@@ -2355,6 +2440,16 @@ bool DRW_state_is_opengl_render(void)
return DST.options.is_image_render && !DST.options.is_scene_render;
}
+bool DRW_state_is_playback(void)
+{
+ if (DST.draw_ctx.evil_C != NULL) {
+ struct wmWindowManager *wm = CTX_wm_manager(DST.draw_ctx.evil_C);
+ return ED_screen_animation_playing(wm) != NULL;
+ }
+ return false;
+}
+
+
/**
* Should text draw in this mode?
*/
@@ -2423,7 +2518,7 @@ void DRW_engine_register(DrawEngineType *draw_engine_type)
void DRW_engines_register(void)
{
RE_engines_register(&DRW_engine_viewport_eevee_type);
- RE_engines_register(&DRW_engine_viewport_opengl_type);
+ RE_engines_register(&DRW_engine_viewport_workbench_type);
DRW_engine_register(&draw_engine_workbench_solid);
DRW_engine_register(&draw_engine_workbench_transparent);
@@ -2601,7 +2696,7 @@ void DRW_opengl_context_disable_ex(bool restore)
#ifdef __APPLE__
/* Need to flush before disabling draw context, otherwise it does not
* always finish drawing and viewport can be empty or partially drawn */
- glFlush();
+ GPU_flush();
#endif
if (BLI_thread_is_main() && restore) {
@@ -2638,7 +2733,7 @@ void DRW_opengl_render_context_enable(void *re_gl_context)
void DRW_opengl_render_context_disable(void *re_gl_context)
{
- glFlush();
+ GPU_flush();
WM_opengl_context_release(re_gl_context);
/* TODO get rid of the blocking. */
BLI_ticket_mutex_unlock(DST.gl_context_mutex);
diff --git a/source/blender/draw/intern/draw_manager.h b/source/blender/draw/intern/draw_manager.h
index c8a7816c402..9ff34fe79aa 100644
--- a/source/blender/draw/intern/draw_manager.h
+++ b/source/blender/draw/intern/draw_manager.h
@@ -319,6 +319,8 @@ typedef struct DRWManager {
/* State of the object being evaluated if already allocated. */
DRWCallState *ob_state;
uchar state_cache_id; /* Could be larger but 254 view changes is already a lot! */
+ struct DupliObject *dupli_source;
+ struct Object *dupli_parent;
/* Rendering state */
GPUShader *shader;
@@ -418,4 +420,6 @@ void drw_state_set(DRWState state);
void drw_debug_draw(void);
void drw_debug_init(void);
+void drw_batch_cache_generate_requested(struct Object *ob);
+
#endif /* __DRAW_MANAGER_H__ */
diff --git a/source/blender/draw/intern/draw_manager_data.c b/source/blender/draw/intern/draw_manager_data.c
index e9d874bd1ee..5863eb57745 100644
--- a/source/blender/draw/intern/draw_manager_data.c
+++ b/source/blender/draw/intern/draw_manager_data.c
@@ -122,8 +122,8 @@ static void drw_shgroup_uniform(DRWShadingGroup *shgroup, const char *name,
}
if (location == -1) {
- if (G.debug & G_DEBUG)
- fprintf(stderr, "Pass : %s, Uniform '%s' not found!\n", shgroup->pass_parent->name, name);
+ if (G.debug & G_DEBUG_GPU)
+ fprintf(stderr, "Warning: Pass : %s, Uniform '%s' not found!\n", shgroup->pass_parent->name, name);
/* Nice to enable eventually, for now eevee uses uniforms that might not exist. */
// BLI_assert(0);
return;
@@ -1040,7 +1040,7 @@ DRWShadingGroup *DRW_shgroup_create_sub(DRWShadingGroup *shgroup)
DRWShadingGroup *shgroup_new = BLI_mempool_alloc(DST.vmempool->shgroups);
*shgroup_new = *shgroup;
- shgroup_new->uniforms = NULL; /* Not sure about that.. Should we copy them instead? */
+ shgroup_new->uniforms = NULL;
shgroup_new->calls.first = NULL;
shgroup_new->calls.last = NULL;
diff --git a/source/blender/draw/intern/draw_manager_exec.c b/source/blender/draw/intern/draw_manager_exec.c
index 2d56c7e0cfe..88db0f07267 100644
--- a/source/blender/draw/intern/draw_manager_exec.c
+++ b/source/blender/draw/intern/draw_manager_exec.c
@@ -282,33 +282,6 @@ void drw_state_set(DRWState state)
}
}
- /* Line Stipple */
- {
- int test;
- if (CHANGED_ANY_STORE_VAR(
- DRW_STATE_STIPPLE_2 | DRW_STATE_STIPPLE_3 | DRW_STATE_STIPPLE_4,
- test))
- {
- if (test) {
- if ((state & DRW_STATE_STIPPLE_2) != 0) {
- setlinestyle(2);
- }
- else if ((state & DRW_STATE_STIPPLE_3) != 0) {
- setlinestyle(3);
- }
- else if ((state & DRW_STATE_STIPPLE_4) != 0) {
- setlinestyle(4);
- }
- else {
- BLI_assert(0);
- }
- }
- else {
- setlinestyle(0);
- }
- }
- }
-
/* Stencil */
{
DRWState test;
@@ -356,6 +329,50 @@ void drw_state_set(DRWState state)
}
}
+ /* Provoking Vertex */
+ {
+ int test;
+ if ((test = CHANGED_TO(DRW_STATE_FIRST_VERTEX_CONVENTION))) {
+ if (test == 1) {
+ glProvokingVertex(GL_FIRST_VERTEX_CONVENTION);
+ }
+ else {
+ glProvokingVertex(GL_LAST_VERTEX_CONVENTION);
+ }
+ }
+ }
+
+ /* Polygon Offset */
+ {
+ int test;
+ if (CHANGED_ANY_STORE_VAR(
+ DRW_STATE_OFFSET_POSITIVE |
+ DRW_STATE_OFFSET_NEGATIVE,
+ test))
+ {
+ if (test) {
+ glEnable(GL_POLYGON_OFFSET_FILL);
+ glEnable(GL_POLYGON_OFFSET_LINE);
+ glEnable(GL_POLYGON_OFFSET_POINT);
+ /* Stencil Write */
+ if ((state & DRW_STATE_OFFSET_POSITIVE) != 0) {
+ glPolygonOffset(1.0f, 1.0f);
+ }
+ else if ((state & DRW_STATE_OFFSET_NEGATIVE) != 0) {
+ glPolygonOffset(-1.0f, -1.0f);
+ }
+ else {
+ BLI_assert(0);
+ }
+ }
+ else {
+ glDisable(GL_POLYGON_OFFSET_FILL);
+ glDisable(GL_POLYGON_OFFSET_LINE);
+ glDisable(GL_POLYGON_OFFSET_POINT);
+ }
+ }
+ }
+
#undef CHANGED_TO
#undef CHANGED_ANY
#undef CHANGED_ANY_STORE_VAR
diff --git a/source/blender/draw/intern/draw_manager_shader.c b/source/blender/draw/intern/draw_manager_shader.c
index bb580695865..e8d693aa7c0 100644
--- a/source/blender/draw/intern/draw_manager_shader.c
+++ b/source/blender/draw/intern/draw_manager_shader.c
@@ -47,6 +47,7 @@
extern char datatoc_gpu_shader_2D_vert_glsl[];
extern char datatoc_gpu_shader_3D_vert_glsl[];
+extern char datatoc_gpu_shader_depth_only_frag_glsl[];
extern char datatoc_common_fullscreen_vert_glsl[];
#define USE_DEFERRED_COMPILATION 1
@@ -131,7 +132,7 @@ static void drw_deferred_shader_compilation_exec(void *custom_data, short *stop,
*progress = (float)comp->shaders_done / (float)total;
*do_update = true;
- glFlush();
+ GPU_flush();
BLI_mutex_unlock(&comp->compilation_lock);
BLI_spin_lock(&comp->list_lock);
@@ -295,7 +296,9 @@ GPUShader *DRW_shader_create_with_transform_feedback(
const char *vert, const char *geom, const char *defines,
const GPUShaderTFBType prim_type, const char **varying_names, const int varying_count)
{
- return GPU_shader_create_ex(vert, NULL, geom, NULL, defines,
+ return GPU_shader_create_ex(vert,
+ datatoc_gpu_shader_depth_only_frag_glsl,
+ geom, NULL, defines,
prim_type, varying_names, varying_count, __func__);
}
diff --git a/source/blender/draw/intern/draw_manager_texture.c b/source/blender/draw/intern/draw_manager_texture.c
index 607b5e19745..be6e66c339f 100644
--- a/source/blender/draw/intern/draw_manager_texture.c
+++ b/source/blender/draw/intern/draw_manager_texture.c
@@ -33,9 +33,12 @@ static bool drw_texture_format_supports_framebuffer(GPUTextureFormat format)
switch (format) {
/* Only add formats that are COMPATIBLE with FB.
* Generally they are multiple of 16bit. */
+ case GPU_R8:
+ case GPU_R8UI:
case GPU_R16F:
case GPU_R16I:
case GPU_R16UI:
+ case GPU_R16:
case GPU_R32F:
case GPU_R32UI:
case GPU_RG8:
diff --git a/source/blender/draw/intern/draw_view.c b/source/blender/draw/intern/draw_view.c
index 70049a5c345..4c53049e772 100644
--- a/source/blender/draw/intern/draw_view.c
+++ b/source/blender/draw/intern/draw_view.c
@@ -154,7 +154,7 @@ static bool is_cursor_visible(const DRWContextState *draw_ctx, Scene *scene, Vie
/* no exception met? then don't draw cursor! */
return false;
}
- else if (draw_ctx->object_mode & OB_MODE_GPENCIL_WEIGHT) {
+ else if (draw_ctx->object_mode & OB_MODE_WEIGHT_GPENCIL) {
/* grease pencil hide always in some modes */
return false;
}
@@ -165,7 +165,6 @@ static bool is_cursor_visible(const DRWContextState *draw_ctx, Scene *scene, Vie
void DRW_draw_cursor(void)
{
const DRWContextState *draw_ctx = DRW_context_state_get();
- View3D *v3d = draw_ctx->v3d;
ARegion *ar = draw_ctx->ar;
Scene *scene = draw_ctx->scene;
ViewLayer *view_layer = draw_ctx->view_layer;
@@ -176,14 +175,14 @@ void DRW_draw_cursor(void)
if (is_cursor_visible(draw_ctx, scene, view_layer)) {
int co[2];
- const View3DCursor *cursor = ED_view3d_cursor3d_get(scene, v3d);
+ const View3DCursor *cursor = &scene->cursor;
if (ED_view3d_project_int_global(
ar, cursor->location, co, V3D_PROJ_TEST_NOP | V3D_PROJ_TEST_CLIP_NEAR) == V3D_PROJ_RET_OK)
{
RegionView3D *rv3d = ar->regiondata;
/* Draw nice Anti Aliased cursor. */
- glLineWidth(1.0f);
+ GPU_line_width(1.0f);
glEnable(GL_BLEND);
glEnable(GL_LINE_SMOOTH);
@@ -228,6 +227,9 @@ void DRW_draw_cursor(void)
immUnbindProgram();
}
+ float original_proj[4][4];
+ GPU_matrix_projection_get(original_proj);
+ GPU_matrix_push();
ED_region_pixelspace(ar);
GPU_matrix_translate_2f(co[0] + 0.5f, co[1] + 0.5f);
GPU_matrix_scale_2f(U.widget_unit, U.widget_unit);
@@ -240,6 +242,8 @@ void DRW_draw_cursor(void)
glDisable(GL_BLEND);
glDisable(GL_LINE_SMOOTH);
+ GPU_matrix_pop();
+ GPU_matrix_projection_set(original_proj);
}
}
}
diff --git a/source/blender/draw/modes/edit_curve_mode.c b/source/blender/draw/modes/edit_curve_mode.c
index e5fd199b69a..b3cb2cb3d80 100644
--- a/source/blender/draw/modes/edit_curve_mode.c
+++ b/source/blender/draw/modes/edit_curve_mode.c
@@ -47,11 +47,13 @@ extern struct GlobalsUboStorage ts; /* draw_common.c */
extern char datatoc_common_globals_lib_glsl[];
extern char datatoc_edit_curve_overlay_loosevert_vert_glsl[];
+extern char datatoc_edit_curve_overlay_normals_vert_glsl[];
extern char datatoc_edit_curve_overlay_handle_vert_glsl[];
extern char datatoc_edit_curve_overlay_handle_geom_glsl[];
extern char datatoc_gpu_shader_point_varying_color_frag_glsl[];
extern char datatoc_gpu_shader_3D_smooth_color_frag_glsl[];
+extern char datatoc_gpu_shader_uniform_color_frag_glsl[];
/* *********** LISTS *********** */
/* All lists are per viewport specific datas.
@@ -83,6 +85,7 @@ typedef struct EDIT_CURVE_Data {
static struct {
GPUShader *wire_sh;
+ GPUShader *wire_normals_sh;
GPUShader *overlay_edge_sh; /* handles and nurbs control cage */
GPUShader *overlay_vert_sh;
} e_data = {NULL}; /* Engine data */
@@ -90,6 +93,7 @@ static struct {
typedef struct EDIT_CURVE_PrivateData {
/* resulting curve as 'wire' for curves (and optionally normals) */
DRWShadingGroup *wire_shgrp;
+ DRWShadingGroup *wire_normals_shgrp;
DRWShadingGroup *overlay_edge_shgrp;
DRWShadingGroup *overlay_vert_shgrp;
@@ -108,6 +112,12 @@ static void EDIT_CURVE_engine_init(void *UNUSED(vedata))
e_data.wire_sh = GPU_shader_get_builtin_shader(GPU_SHADER_3D_UNIFORM_COLOR);
}
+ if (!e_data.wire_normals_sh) {
+ e_data.wire_normals_sh = DRW_shader_create(
+ datatoc_edit_curve_overlay_normals_vert_glsl, NULL,
+ datatoc_gpu_shader_uniform_color_frag_glsl, NULL);
+ }
+
if (!e_data.overlay_edge_sh) {
e_data.overlay_edge_sh = DRW_shader_create_with_lib(
datatoc_edit_curve_overlay_handle_vert_glsl,
@@ -152,6 +162,12 @@ static void EDIT_CURVE_cache_init(void *vedata)
DRW_shgroup_uniform_vec4(grp, "color", ts.colorWireEdit, 1);
stl->g_data->wire_shgrp = grp;
+
+ grp = DRW_shgroup_create(e_data.wire_normals_sh, psl->wire_pass);
+ DRW_shgroup_uniform_vec4(grp, "color", ts.colorWireEdit, 1);
+ DRW_shgroup_uniform_float_copy(grp, "normalSize", v3d->overlay.normals_length);
+ stl->g_data->wire_normals_shgrp = grp;
+
psl->overlay_edge_pass = DRW_pass_create(
"Curve Handle Overlay",
DRW_STATE_WRITE_COLOR | DRW_STATE_BLEND);
@@ -169,7 +185,6 @@ static void EDIT_CURVE_cache_init(void *vedata)
grp = DRW_shgroup_create(e_data.overlay_vert_sh, psl->overlay_vert_pass);
DRW_shgroup_uniform_block(grp, "globalsBlock", globals_ubo);
- DRW_shgroup_uniform_vec2(grp, "viewportSize", DRW_viewport_size_get(), 1);
stl->g_data->overlay_vert_shgrp = grp;
}
}
@@ -191,8 +206,9 @@ static void EDIT_CURVE_cache_populate(void *vedata, Object *ob)
DRW_shgroup_call_add(stl->g_data->wire_shgrp, geom, ob->obmat);
if ((cu->flag & CU_3D) && (v3d->overlay.edit_flag & V3D_OVERLAY_EDIT_CU_NORMALS) != 0) {
- geom = DRW_cache_curve_edge_normal_get(ob, v3d->overlay.normals_length);
- DRW_shgroup_call_add(stl->g_data->wire_shgrp, geom, ob->obmat);
+ static uint instance_len = 2;
+ geom = DRW_cache_curve_edge_normal_get(ob);
+ DRW_shgroup_call_instances_add(stl->g_data->wire_normals_shgrp, geom, ob->obmat, &instance_len);
}
geom = DRW_cache_curve_edge_overlay_get(ob);
@@ -243,6 +259,7 @@ static void EDIT_CURVE_draw_scene(void *vedata)
* Mostly used for freeing shaders */
static void EDIT_CURVE_engine_free(void)
{
+ DRW_SHADER_FREE_SAFE(e_data.wire_normals_sh);
DRW_SHADER_FREE_SAFE(e_data.overlay_edge_sh);
DRW_SHADER_FREE_SAFE(e_data.overlay_vert_sh);
}
diff --git a/source/blender/draw/modes/edit_mesh_mode.c b/source/blender/draw/modes/edit_mesh_mode.c
index fabff950c60..569ec59c93d 100644
--- a/source/blender/draw/modes/edit_mesh_mode.c
+++ b/source/blender/draw/modes/edit_mesh_mode.c
@@ -38,6 +38,7 @@
#include "edit_mesh_mode_intern.h" /* own include */
+#include "BKE_editmesh.h"
#include "BKE_object.h"
#include "BLI_dynstr.h"
@@ -59,7 +60,6 @@ extern char datatoc_edit_mesh_overlay_geom_edge_glsl[];
extern char datatoc_edit_mesh_overlay_points_vert_glsl[];
extern char datatoc_edit_mesh_overlay_facedot_frag_glsl[];
extern char datatoc_edit_mesh_overlay_facedot_vert_glsl[];
-extern char datatoc_edit_mesh_overlay_ghost_clear_vert_glsl[];
extern char datatoc_edit_mesh_overlay_mix_frag_glsl[];
extern char datatoc_edit_mesh_overlay_facefill_vert_glsl[];
extern char datatoc_edit_mesh_overlay_facefill_frag_glsl[];
@@ -70,6 +70,7 @@ extern char datatoc_common_globals_lib_glsl[];
extern char datatoc_gpu_shader_uniform_color_frag_glsl[];
extern char datatoc_gpu_shader_flat_color_frag_glsl[];
extern char datatoc_gpu_shader_point_varying_color_frag_glsl[];
+extern char datatoc_gpu_shader_depth_only_frag_glsl[];
/* *********** LISTS *********** */
typedef struct EDIT_MESH_PassList {
@@ -135,17 +136,14 @@ typedef struct EDIT_MESH_PrivateData {
DRWShadingGroup *vnormals_shgrp;
DRWShadingGroup *lnormals_shgrp;
- DRWShadingGroup *face_overlay_shgrp;
- DRWShadingGroup *verts_overlay_shgrp;
- DRWShadingGroup *ledges_overlay_shgrp;
- DRWShadingGroup *lverts_overlay_shgrp;
- DRWShadingGroup *facedot_overlay_shgrp;
-
- DRWShadingGroup *face_occluded_shgrp;
- DRWShadingGroup *verts_occluded_shgrp;
- DRWShadingGroup *ledges_occluded_shgrp;
- DRWShadingGroup *lverts_occluded_shgrp;
- DRWShadingGroup *facedot_occluded_shgrp;
+ DRWShadingGroup *face_shgrp;
+ DRWShadingGroup *face_cage_shgrp;
+
+ DRWShadingGroup *verts_shgrp;
+ DRWShadingGroup *ledges_shgrp;
+ DRWShadingGroup *lverts_shgrp;
+ DRWShadingGroup *facedot_shgrp;
+
DRWShadingGroup *facefill_occluded_shgrp;
int data_mask[4];
@@ -329,8 +327,7 @@ static void EDIT_MESH_engine_init(void *vedata)
e_data.depth_sh = DRW_shader_create_3D_depth_only();
}
if (!e_data.ghost_clear_depth_sh) {
- e_data.ghost_clear_depth_sh = DRW_shader_create(datatoc_edit_mesh_overlay_ghost_clear_vert_glsl,
- NULL, NULL, NULL);
+ e_data.ghost_clear_depth_sh = DRW_shader_create_fullscreen(datatoc_gpu_shader_depth_only_frag_glsl, NULL);
}
}
@@ -338,7 +335,8 @@ static void EDIT_MESH_engine_init(void *vedata)
static DRWPass *edit_mesh_create_overlay_pass(
float *face_alpha, float *edge_width_scale, int *data_mask, bool do_edges, bool xray,
DRWState statemod,
- DRWShadingGroup **r_face_shgrp, DRWShadingGroup **r_verts_shgrp, DRWShadingGroup **r_ledges_shgrp,
+ DRWShadingGroup **r_face_shgrp, DRWShadingGroup **r_face_cage_shgrp,
+ DRWShadingGroup **r_verts_shgrp, DRWShadingGroup **r_ledges_shgrp,
DRWShadingGroup **r_lverts_shgrp, DRWShadingGroup **r_facedot_shgrp)
{
GPUShader *tri_sh, *ledge_sh;
@@ -361,12 +359,14 @@ static DRWPass *edit_mesh_create_overlay_pass(
DRW_shgroup_uniform_vec2(*r_lverts_shgrp, "viewportSize", DRW_viewport_size_get(), 1);
DRW_shgroup_uniform_float(*r_lverts_shgrp, "edgeScale", edge_width_scale, 1);
DRW_shgroup_state_enable(*r_lverts_shgrp, DRW_STATE_WRITE_DEPTH);
+ DRW_shgroup_state_disable(*r_lverts_shgrp, DRW_STATE_BLEND);
*r_verts_shgrp = DRW_shgroup_create(e_data.overlay_vert_sh, pass);
DRW_shgroup_uniform_block(*r_verts_shgrp, "globalsBlock", globals_ubo);
DRW_shgroup_uniform_vec2(*r_verts_shgrp, "viewportSize", DRW_viewport_size_get(), 1);
DRW_shgroup_uniform_float(*r_verts_shgrp, "edgeScale", edge_width_scale, 1);
DRW_shgroup_state_enable(*r_verts_shgrp, DRW_STATE_WRITE_DEPTH);
+ DRW_shgroup_state_disable(*r_verts_shgrp, DRW_STATE_BLEND);
}
if ((tsettings->selectmode & SCE_SELECT_FACE) != 0) {
@@ -386,6 +386,13 @@ static DRWPass *edit_mesh_create_overlay_pass(
if (!fast_mode) {
DRW_shgroup_uniform_bool_copy(*r_face_shgrp, "isXray", xray);
}
+ else {
+ /* To be able to use triple load. */
+ DRW_shgroup_state_enable(*r_face_shgrp, DRW_STATE_FIRST_VERTEX_CONVENTION);
+ }
+ /* Cage geom needs to be offseted to avoid Z-fighting. */
+ *r_face_cage_shgrp = DRW_shgroup_create_sub(*r_face_shgrp);
+ DRW_shgroup_state_enable(*r_face_cage_shgrp, DRW_STATE_OFFSET_NEGATIVE);
*r_ledges_shgrp = DRW_shgroup_create(ledge_sh, pass);
DRW_shgroup_uniform_block(*r_ledges_shgrp, "globalsBlock", globals_ubo);
@@ -521,22 +528,24 @@ static void EDIT_MESH_cache_init(void *vedata)
psl->edit_face_overlay = edit_mesh_create_overlay_pass(
&face_mod, &stl->g_data->edge_width_scale, stl->g_data->data_mask, stl->g_data->do_edges, false,
DRW_STATE_DEPTH_LESS_EQUAL | DRW_STATE_BLEND,
- &stl->g_data->face_overlay_shgrp,
- &stl->g_data->verts_overlay_shgrp,
- &stl->g_data->ledges_overlay_shgrp,
- &stl->g_data->lverts_overlay_shgrp,
- &stl->g_data->facedot_overlay_shgrp);
+ &stl->g_data->face_shgrp,
+ &stl->g_data->face_cage_shgrp,
+ &stl->g_data->verts_shgrp,
+ &stl->g_data->ledges_shgrp,
+ &stl->g_data->lverts_shgrp,
+ &stl->g_data->facedot_shgrp);
}
else {
/* We render all wires with depth and opaque to a new fbo and blend the result based on depth values */
psl->edit_face_occluded = edit_mesh_create_overlay_pass(
&zero, &stl->g_data->edge_width_scale, stl->g_data->data_mask, stl->g_data->do_edges, true,
DRW_STATE_DEPTH_LESS_EQUAL | DRW_STATE_WRITE_DEPTH,
- &stl->g_data->face_occluded_shgrp,
- &stl->g_data->verts_occluded_shgrp,
- &stl->g_data->ledges_occluded_shgrp,
- &stl->g_data->lverts_occluded_shgrp,
- &stl->g_data->facedot_occluded_shgrp);
+ &stl->g_data->face_shgrp,
+ &stl->g_data->face_cage_shgrp,
+ &stl->g_data->verts_shgrp,
+ &stl->g_data->ledges_shgrp,
+ &stl->g_data->lverts_shgrp,
+ &stl->g_data->facedot_shgrp);
/* however we loose the front faces value (because we need the depth of occluded wires and
* faces are alpha blended ) so we recover them in a new pass. */
@@ -564,40 +573,48 @@ static void EDIT_MESH_cache_init(void *vedata)
static void edit_mesh_add_ob_to_pass(
Scene *scene, Object *ob,
- DRWShadingGroup *face_shgrp,
- DRWShadingGroup *verts_shgrp,
- DRWShadingGroup *ledges_shgrp,
- DRWShadingGroup *lverts_shgrp,
+ EDIT_MESH_PrivateData *g_data,
DRWShadingGroup *facedot_shgrp,
DRWShadingGroup *facefill_shgrp)
{
- struct GPUBatch *geo_ovl_tris, *geo_ovl_verts, *geo_ovl_lnor, *geo_ovl_ledges, *geo_ovl_lverts, *geo_ovl_fcenter;
- struct GPUTexture *data_texture;
+ struct GPUBatch *geom_tris, *geom_verts, *geom_ledges, *geom_ledges_nor, *geom_lverts, *geom_fcenter;
ToolSettings *tsettings = scene->toolsettings;
- DRW_cache_mesh_wire_overlay_get(ob, &geo_ovl_tris, &geo_ovl_ledges, &geo_ovl_lverts, &data_texture);
+ bool has_edit_mesh_cage = false;
+ /* TODO: Should be its own function. */
+ Mesh *me = (Mesh *)ob->data;
+ BMEditMesh *embm = me->edit_btmesh;
+ if (embm) {
+ has_edit_mesh_cage = embm->mesh_eval_cage && (embm->mesh_eval_cage != embm->mesh_eval_final);
+ }
- face_shgrp = DRW_shgroup_create_sub(face_shgrp);
- DRW_shgroup_uniform_texture(face_shgrp, "dataBuffer", data_texture);
- DRW_shgroup_call_add(face_shgrp, geo_ovl_tris, ob->obmat);
+ DRWShadingGroup *face_shgrp = (has_edit_mesh_cage) ? g_data->face_cage_shgrp : g_data->face_shgrp;
+ DRWShadingGroup *verts_shgrp = g_data->verts_shgrp;
+ DRWShadingGroup *ledges_shgrp = g_data->ledges_shgrp;
+ DRWShadingGroup *lverts_shgrp = g_data->lverts_shgrp;
- DRW_shgroup_call_add(ledges_shgrp, geo_ovl_ledges, ob->obmat);
+ geom_tris = DRW_mesh_batch_cache_get_edit_triangles(ob->data);
+ geom_ledges = DRW_mesh_batch_cache_get_edit_loose_edges(ob->data);
+ DRW_shgroup_call_add(face_shgrp, geom_tris, ob->obmat);
+ DRW_shgroup_call_add(ledges_shgrp, geom_ledges, ob->obmat);
if (facefill_shgrp) {
- DRW_shgroup_call_add(facefill_shgrp, geo_ovl_tris, ob->obmat);
+ DRW_shgroup_call_add(facefill_shgrp, geom_tris, ob->obmat);
}
if ((tsettings->selectmode & SCE_SELECT_VERTEX) != 0) {
/* Thoses are point batches. */
- DRW_cache_mesh_normals_overlay_get(ob, &geo_ovl_verts, &geo_ovl_lnor, &geo_ovl_ledges, &geo_ovl_lverts);
- DRW_shgroup_call_add(verts_shgrp, geo_ovl_verts, ob->obmat);
- DRW_shgroup_call_add(lverts_shgrp, geo_ovl_ledges, ob->obmat);
- DRW_shgroup_call_add(lverts_shgrp, geo_ovl_lverts, ob->obmat);
+ geom_verts = DRW_mesh_batch_cache_get_edit_vertices(ob->data);
+ geom_ledges_nor = DRW_mesh_batch_cache_get_edit_loose_edges_nor(ob->data);
+ geom_lverts = DRW_mesh_batch_cache_get_edit_loose_verts(ob->data);
+ DRW_shgroup_call_add(verts_shgrp, geom_verts, ob->obmat);
+ DRW_shgroup_call_add(lverts_shgrp, geom_ledges_nor, ob->obmat);
+ DRW_shgroup_call_add(lverts_shgrp, geom_lverts, ob->obmat);
}
if (facedot_shgrp && (tsettings->selectmode & SCE_SELECT_FACE) != 0 ) {
- geo_ovl_fcenter = DRW_cache_face_centers_get(ob);
- DRW_shgroup_call_add(facedot_shgrp, geo_ovl_fcenter, ob->obmat);
+ geom_fcenter = DRW_mesh_batch_cache_get_edit_facedots(ob->data);
+ DRW_shgroup_call_add(facedot_shgrp, geom_fcenter, ob->obmat);
}
}
@@ -640,7 +657,7 @@ static void EDIT_MESH_cache_populate(void *vedata, Object *ob)
}
if (do_show_weight) {
- geom = DRW_cache_mesh_surface_weights_get(ob, tsettings, false);
+ geom = DRW_cache_mesh_surface_weights_get(ob);
DRW_shgroup_call_add(stl->g_data->fweights_shgrp, geom, ob->obmat);
}
@@ -649,44 +666,33 @@ static void EDIT_MESH_cache_populate(void *vedata, Object *ob)
DRW_shgroup_call_add(stl->g_data->depth_shgrp_hidden_wire, geom, ob->obmat);
}
+ if (vnormals_do) {
+ geom = DRW_mesh_batch_cache_get_edit_triangles_nor(ob->data);
+ DRW_shgroup_call_add(stl->g_data->vnormals_shgrp, geom, ob->obmat);
+ geom = DRW_mesh_batch_cache_get_edit_loose_verts(ob->data);
+ DRW_shgroup_call_add(stl->g_data->vnormals_shgrp, geom, ob->obmat);
+ geom = DRW_mesh_batch_cache_get_edit_loose_edges_nor(ob->data);
+ DRW_shgroup_call_add(stl->g_data->vnormals_shgrp, geom, ob->obmat);
+ }
+ if (lnormals_do) {
+ geom = DRW_mesh_batch_cache_get_edit_triangles_lnor(ob->data);
+ DRW_shgroup_call_add(stl->g_data->lnormals_shgrp, geom, ob->obmat);
+ }
if (fnormals_do) {
- geom = DRW_cache_face_centers_get(ob);
+ geom = DRW_mesh_batch_cache_get_edit_facedots(ob->data);
DRW_shgroup_call_add(stl->g_data->fnormals_shgrp, geom, ob->obmat);
}
- if (vnormals_do || lnormals_do) {
- struct GPUBatch *geo_ovl_tris, *geo_ovl_lnor, *geo_ovl_ledges, *geo_ovl_lverts;
- DRW_cache_mesh_normals_overlay_get(ob, &geo_ovl_tris, &geo_ovl_lnor, &geo_ovl_ledges, &geo_ovl_lverts);
-
- if (vnormals_do) {
- DRW_shgroup_call_add(stl->g_data->vnormals_shgrp, geo_ovl_tris, ob->obmat);
- DRW_shgroup_call_add(stl->g_data->vnormals_shgrp, geo_ovl_ledges, ob->obmat);
- DRW_shgroup_call_add(stl->g_data->vnormals_shgrp, geo_ovl_lverts, ob->obmat);
- }
-
- if (lnormals_do) {
- DRW_shgroup_call_add(stl->g_data->lnormals_shgrp, geo_ovl_lnor, ob->obmat);
- }
- }
-
if (stl->g_data->do_zbufclip) {
edit_mesh_add_ob_to_pass(
- scene, ob,
- stl->g_data->face_occluded_shgrp,
- stl->g_data->verts_occluded_shgrp,
- stl->g_data->ledges_occluded_shgrp,
- stl->g_data->lverts_occluded_shgrp,
- stl->g_data->facedot_occluded_shgrp,
+ scene, ob, stl->g_data,
+ stl->g_data->facedot_shgrp,
(stl->g_data->do_faces) ? stl->g_data->facefill_occluded_shgrp : NULL);
}
else {
edit_mesh_add_ob_to_pass(
- scene, ob,
- stl->g_data->face_overlay_shgrp,
- stl->g_data->verts_overlay_shgrp,
- stl->g_data->ledges_overlay_shgrp,
- stl->g_data->lverts_overlay_shgrp,
- (show_face_dots) ? stl->g_data->facedot_overlay_shgrp : NULL,
+ scene, ob, stl->g_data,
+ (show_face_dots) ? stl->g_data->facedot_shgrp : NULL,
NULL);
}
diff --git a/source/blender/draw/modes/edit_mesh_mode_text.c b/source/blender/draw/modes/edit_mesh_mode_text.c
index d2bfc75a2bf..0498998b69a 100644
--- a/source/blender/draw/modes/edit_mesh_mode_text.c
+++ b/source/blender/draw/modes/edit_mesh_mode_text.c
@@ -345,7 +345,7 @@ void DRW_edit_mesh_mode_text_measure_stats(
BM_ITER_MESH_INDEX(f, &iter, em->bm, BM_FACES_OF_MESH, i) {
if (BM_elem_flag_test(f, BM_ELEM_SELECT)) {
- BM_face_calc_center_mean(f, v1);
+ BM_face_calc_center_median(f, v1);
mul_m4_v3(ob->obmat, v1);
numstr_len = BLI_snprintf_rlen(numstr, sizeof(numstr), "%d", i);
diff --git a/source/blender/draw/modes/edit_text_mode.c b/source/blender/draw/modes/edit_text_mode.c
index d186ee967e5..cb87a015717 100644
--- a/source/blender/draw/modes/edit_text_mode.c
+++ b/source/blender/draw/modes/edit_text_mode.c
@@ -30,6 +30,8 @@
#include "BIF_glutil.h"
+#include "BKE_font.h"
+
/* If builtin shaders are needed */
#include "GPU_shader.h"
#include "GPU_batch.h"
@@ -193,6 +195,78 @@ static void EDIT_TEXT_cache_init(void *vedata)
}
}
+/* Use 2D quad corners to create a matrix that set
+ * a [-1..1] quad at the right position. */
+static void v2_quad_corners_to_mat4(float corners[4][2], float r_mat[4][4])
+{
+ unit_m4(r_mat);
+ sub_v2_v2v2(r_mat[0], corners[1], corners[0]);
+ sub_v2_v2v2(r_mat[1], corners[3], corners[0]);
+ mul_v2_fl(r_mat[0], 0.5f);
+ mul_v2_fl(r_mat[1], 0.5f);
+ copy_v2_v2(r_mat[3], corners[0]);
+ add_v2_v2(r_mat[3], r_mat[0]);
+ add_v2_v2(r_mat[3], r_mat[1]);
+}
+
+static void edit_text_cache_populate_select(void *vedata, Object *ob)
+{
+ EDIT_TEXT_StorageList *stl = ((EDIT_TEXT_Data *)vedata)->stl;
+ const Curve *cu = ob->data;
+ EditFont *ef = cu->editfont;
+ float final_mat[4][4], box[4][2];
+ struct GPUBatch *geom = DRW_cache_quad_get();
+
+ for (int i = 0; i < ef->selboxes_len; i++) {
+ EditFontSelBox *sb = &ef->selboxes[i];
+
+ float selboxw;
+ if (i + 1 != ef->selboxes_len) {
+ if (ef->selboxes[i + 1].y == sb->y)
+ selboxw = ef->selboxes[i + 1].x - sb->x;
+ else
+ selboxw = sb->w;
+ }
+ else {
+ selboxw = sb->w;
+ }
+ /* NOTE: v2_quad_corners_to_mat4 don't need the 3rd corner. */
+ if (sb->rot == 0.0f) {
+ copy_v2_fl2(box[0], sb->x, sb->y);
+ copy_v2_fl2(box[1], sb->x + selboxw, sb->y);
+ copy_v2_fl2(box[3], sb->x, sb->y + sb->h);
+ }
+ else {
+ float mat[2][2];
+ angle_to_mat2(mat, sb->rot);
+ copy_v2_fl2(box[0], sb->x, sb->y);
+ mul_v2_v2fl(box[1], mat[0], selboxw);
+ add_v2_v2(box[1], &sb->x);
+ mul_v2_v2fl(box[3], mat[1], sb->h);
+ add_v2_v2(box[3], &sb->x);
+ }
+ v2_quad_corners_to_mat4(box, final_mat);
+ mul_m4_m4m4(final_mat, ob->obmat, final_mat);
+
+ DRW_shgroup_call_add(stl->g_data->overlay_select_shgrp, geom, final_mat);
+ }
+}
+
+static void edit_text_cache_populate_cursor(void *vedata, Object *ob)
+{
+ EDIT_TEXT_StorageList *stl = ((EDIT_TEXT_Data *)vedata)->stl;
+ const Curve *cu = ob->data;
+ EditFont *edit_font = cu->editfont;
+ float (*cursor)[2] = edit_font->textcurs;
+ float mat[4][4];
+
+ v2_quad_corners_to_mat4(cursor, mat);
+ mul_m4_m4m4(mat, ob->obmat, mat);
+
+ struct GPUBatch *geom = DRW_cache_quad_get();
+ DRW_shgroup_call_add(stl->g_data->overlay_cursor_shgrp, geom, mat);
+}
+
static void edit_text_cache_populate_boxes(void *vedata, Object *ob)
{
EDIT_TEXT_StorageList *stl = ((EDIT_TEXT_Data *)vedata)->stl;
@@ -215,7 +289,7 @@ static void edit_text_cache_populate_boxes(void *vedata, Object *ob)
DRWShadingGroup *shading_group = shading_groups[is_active ? 0 : 1];
vec[0] = cu->xof + tb->x;
- vec[1] = cu->yof + tb->y + cu->fsize;
+ vec[1] = cu->yof + tb->y + cu->fsize_realtime;
vec[2] = 0.001;
mul_v3_m4v3(vec1, ob->obmat, vec);
@@ -273,16 +347,8 @@ static void EDIT_TEXT_cache_populate(void *vedata, Object *ob)
/* object mode draws */
}
- geom = DRW_cache_text_select_overlay_get(ob);
- if (geom) {
- DRW_shgroup_call_add(stl->g_data->overlay_select_shgrp, geom, ob->obmat);
- }
-
- geom = DRW_cache_text_cursor_overlay_get(ob);
- if (geom) {
- DRW_shgroup_call_add(stl->g_data->overlay_cursor_shgrp, geom, ob->obmat);
- }
-
+ edit_text_cache_populate_select(vedata, ob);
+ edit_text_cache_populate_cursor(vedata, ob);
edit_text_cache_populate_boxes(vedata, ob);
}
}
diff --git a/source/blender/draw/modes/object_mode.c b/source/blender/draw/modes/object_mode.c
index 144609ddb10..b466333fd13 100644
--- a/source/blender/draw/modes/object_mode.c
+++ b/source/blender/draw/modes/object_mode.c
@@ -95,6 +95,7 @@ extern char datatoc_object_grid_vert_glsl[];
extern char datatoc_object_empty_image_frag_glsl[];
extern char datatoc_object_empty_image_vert_glsl[];
extern char datatoc_object_lightprobe_grid_vert_glsl[];
+extern char datatoc_object_loose_points_frag_glsl[];
extern char datatoc_object_particle_prim_vert_glsl[];
extern char datatoc_object_particle_dot_vert_glsl[];
extern char datatoc_object_particle_dot_frag_glsl[];
@@ -312,6 +313,7 @@ static struct {
GPUShader *part_prim_sh;
GPUShader *part_axis_sh;
GPUShader *lightprobe_grid_sh;
+ GPUShader *loose_points_sh;
float camera_pos[3];
float screenvecs[3][4];
float grid_settings[5];
@@ -463,6 +465,9 @@ static void OBJECT_engine_init(void *vedata)
/* Lightprobes */
e_data.lightprobe_grid_sh = DRW_shader_create(
datatoc_object_lightprobe_grid_vert_glsl, NULL, datatoc_gpu_shader_flat_id_frag_glsl, NULL);
+
+ /* Loose Points */
+ e_data.loose_points_sh = DRW_shader_create_3D(datatoc_object_loose_points_frag_glsl, NULL);
}
{
@@ -692,6 +697,7 @@ static void OBJECT_engine_free(void)
DRW_SHADER_FREE_SAFE(e_data.part_axis_sh);
DRW_SHADER_FREE_SAFE(e_data.part_dot_sh);
DRW_SHADER_FREE_SAFE(e_data.lightprobe_grid_sh);
+ DRW_SHADER_FREE_SAFE(e_data.loose_points_sh);
}
static DRWShadingGroup *shgroup_outline(DRWPass *pass, const int *ofs, GPUShader *sh)
@@ -716,6 +722,7 @@ static DRWShadingGroup *shgroup_points(DRWPass *pass, const float col[4], GPUSha
{
DRWShadingGroup *grp = DRW_shgroup_create(sh, pass);
DRW_shgroup_uniform_vec4(grp, "color", col, 1);
+ DRW_shgroup_uniform_vec4(grp, "innerColor", ts.colorEditMeshMiddle, 1);
return grp;
}
@@ -826,14 +833,12 @@ static DRWShadingGroup *shgroup_theme_id_to_point_or(
}
}
-static void image_calc_aspect(Image *ima, ImageUser *iuser, float r_image_aspect[2])
+static void image_calc_aspect(Image *ima, const int size[2], float r_image_aspect[2])
{
float ima_x, ima_y;
if (ima) {
- int w, h;
- BKE_image_get_size(ima, iuser, &w, &h);
- ima_x = w;
- ima_y = h;
+ ima_x = size[0];
+ ima_y = size[1];
}
else {
/* if no image, make it a 1x1 empty square, honor scale & offset */
@@ -867,15 +872,27 @@ static void DRW_shgroup_empty_image(
{
/* TODO: 'StereoViews', see draw_empty_image. */
- if (!BKE_image_empty_visible_in_view3d(ob, rv3d))
+ if (!BKE_object_empty_image_is_visible_in_view3d(ob, rv3d))
return;
- GPUTexture *tex = ob->data ?
- GPU_texture_from_blender(ob->data, ob->iuser, GL_TEXTURE_2D, false, 0.0f) :
- NULL;
+ /* Calling 'BKE_image_get_size' may free the texture. Get the size from 'tex' instead, see: T59347 */
+ int size[2] = {0};
+
+ GPUTexture *tex = NULL;
+
+ if (ob->data != NULL) {
+ tex = GPU_texture_from_blender(ob->data, ob->iuser, GL_TEXTURE_2D, false, 0.0f);
+ if (tex) {
+ size[0] = GPU_texture_width(tex);
+ size[1] = GPU_texture_height(tex);
+ }
+ }
+
+ CLAMP_MIN(size[0], 1);
+ CLAMP_MIN(size[1], 1);
float image_aspect[2];
- image_calc_aspect(ob->data, ob->iuser, image_aspect);
+ image_calc_aspect(ob->data, size, image_aspect);
/* OPTI(fclem) We need sorting only for transparent images. If an image as no alpha channel and
* ob->col[3] == 1.0f, we could remove it from the sorting pass. */
@@ -901,7 +918,7 @@ static void DRW_shgroup_empty_image(
DRW_shgroup_uniform_int_copy(grp, "depthMode", ob->empty_image_depth);
DRW_shgroup_uniform_float(grp, "size", &ob->empty_drawsize, 1);
DRW_shgroup_uniform_vec2(grp, "offset", ob->ima_ofs, 1);
- DRW_shgroup_uniform_vec4(grp, "color", color, 1);
+ DRW_shgroup_uniform_vec3(grp, "color", color, 1);
DRW_shgroup_call_add(grp, DRW_cache_image_plane_wire_get(), ob->obmat);
}
}
@@ -1198,11 +1215,15 @@ static void OBJECT_cache_init(void *vedata)
sgl->wire_active = shgroup_wire(sgl->non_meshes, ts.colorActive, sh);
/* Points (loose points) */
- sh = GPU_shader_get_builtin_shader(GPU_SHADER_3D_POINT_FIXED_SIZE_UNIFORM_COLOR);
+ sh = e_data.loose_points_sh;
sgl->points = shgroup_points(sgl->non_meshes, ts.colorWire, sh);
sgl->points_select = shgroup_points(sgl->non_meshes, ts.colorSelect, sh);
sgl->points_transform = shgroup_points(sgl->non_meshes, ts.colorTransform, sh);
sgl->points_active = shgroup_points(sgl->non_meshes, ts.colorActive, sh);
+ DRW_shgroup_state_disable(sgl->points, DRW_STATE_BLEND);
+ DRW_shgroup_state_disable(sgl->points_select, DRW_STATE_BLEND);
+ DRW_shgroup_state_disable(sgl->points_transform, DRW_STATE_BLEND);
+ DRW_shgroup_state_disable(sgl->points_active, DRW_STATE_BLEND);
/* Metaballs Handles */
sgl->mball_handle = shgroup_instance_mball_handles(sgl->non_meshes);
@@ -2270,7 +2291,7 @@ static void DRW_shgroup_relationship_lines(
Object *ob)
{
if (ob->parent && DRW_object_is_visible_in_active_context(ob->parent)) {
- DRW_shgroup_call_dynamic_add(sgl->relationship_lines, ob->parent->obmat[3]);
+ DRW_shgroup_call_dynamic_add(sgl->relationship_lines, ob->orig);
DRW_shgroup_call_dynamic_add(sgl->relationship_lines, ob->obmat[3]);
}
@@ -2399,31 +2420,30 @@ static void DRW_shgroup_texture_space(OBJECT_ShadingGroupList *sgl, Object *ob,
ID *ob_data = ob->data;
float *texcoloc = NULL;
float *texcosize = NULL;
- if (ob->data != NULL) {
- switch (GS(ob_data->name)) {
- case ID_ME:
- BKE_mesh_texspace_get_reference((Mesh *)ob_data, NULL, &texcoloc, NULL, &texcosize);
- break;
- case ID_CU:
- {
- Curve *cu = (Curve *)ob_data;
- if (cu->bb == NULL || (cu->bb->flag & BOUNDBOX_DIRTY)) {
- BKE_curve_texspace_calc(cu);
- }
- texcoloc = cu->loc;
- texcosize = cu->size;
- break;
- }
- case ID_MB:
- {
- MetaBall *mb = (MetaBall *)ob_data;
- texcoloc = mb->loc;
- texcosize = mb->size;
- break;
+
+ switch (GS(ob_data->name)) {
+ case ID_ME:
+ BKE_mesh_texspace_get_reference((Mesh *)ob_data, NULL, &texcoloc, NULL, &texcosize);
+ break;
+ case ID_CU:
+ {
+ Curve *cu = (Curve *)ob_data;
+ if (cu->bb == NULL || (cu->bb->flag & BOUNDBOX_DIRTY)) {
+ BKE_curve_texspace_calc(cu);
}
- default:
- BLI_assert(0);
+ texcoloc = cu->loc;
+ texcosize = cu->size;
+ break;
}
+ case ID_MB:
+ {
+ MetaBall *mb = (MetaBall *)ob_data;
+ texcoloc = mb->loc;
+ texcosize = mb->size;
+ break;
+ }
+ default:
+ BLI_assert(0);
}
float tmp[4][4] = {{0.0f}}, one = 1.0f;
@@ -2682,7 +2702,21 @@ static void OBJECT_cache_populate(void *vedata, Object *ob)
break;
}
case OB_SURF:
+ {
+ if (hide_object_extra) {
+ break;
+ }
+ struct GPUBatch *geom = DRW_cache_surf_edge_wire_get(ob);
+ if (geom == NULL) {
+ break;
+ }
+ if (theme_id == TH_UNDEFINED) {
+ theme_id = DRW_object_wire_theme_get(ob, view_layer, NULL);
+ }
+ DRWShadingGroup *shgroup = shgroup_theme_id_to_wire_or(sgl, theme_id, sgl->wire);
+ DRW_shgroup_call_object_add(shgroup, geom, ob);
break;
+ }
case OB_LATTICE:
{
if (ob != draw_ctx->object_edit && !BKE_object_is_in_editmode(ob)) {
@@ -2774,7 +2808,9 @@ static void OBJECT_cache_populate(void *vedata, Object *ob)
break;
case OB_ARMATURE:
{
- if (v3d->overlay.flag & V3D_OVERLAY_HIDE_BONES) {
+ if ((v3d->flag2 & V3D_RENDER_OVERRIDE) ||
+ (v3d->overlay.flag & V3D_OVERLAY_HIDE_BONES))
+ {
break;
}
bArmature *arm = ob->data;
@@ -2894,18 +2930,18 @@ static void OBJECT_draw_scene(void *vedata)
MULTISAMPLE_SYNC_ENABLE(dfbl, dtxl);
- /* This needs to be drawn after the oultine */
DRW_draw_pass(stl->g_data->sgl.spot_shapes);
DRW_draw_pass(stl->g_data->sgl.bone_solid);
DRW_draw_pass(stl->g_data->sgl.bone_wire);
DRW_draw_pass(stl->g_data->sgl.bone_outline);
DRW_draw_pass(stl->g_data->sgl.non_meshes);
DRW_draw_pass(psl->particle);
- DRW_draw_pass(stl->g_data->sgl.image_empties);
DRW_draw_pass(stl->g_data->sgl.bone_axes);
MULTISAMPLE_SYNC_DISABLE(dfbl, dtxl)
+ DRW_draw_pass(stl->g_data->sgl.image_empties);
+
if (DRW_state_is_fbo() && outline_calls > 0) {
DRW_stats_group_start("Outlines");
diff --git a/source/blender/draw/modes/overlay_mode.c b/source/blender/draw/modes/overlay_mode.c
index 460b3d4240a..0c67263bd4f 100644
--- a/source/blender/draw/modes/overlay_mode.c
+++ b/source/blender/draw/modes/overlay_mode.c
@@ -23,8 +23,10 @@
* \ingroup draw_engine
*/
+#include "DNA_mesh_types.h"
#include "DNA_view3d_types.h"
+#include "BKE_editmesh.h"
#include "BKE_object.h"
#include "GPU_shader.h"
@@ -40,9 +42,7 @@ typedef struct OVERLAY_StorageList {
typedef struct OVERLAY_PassList {
struct DRWPass *face_orientation_pass;
- struct DRWPass *flat_wireframe_pass;
struct DRWPass *face_wireframe_pass;
- struct DRWPass *face_wireframe_full_pass;
} OVERLAY_PassList;
typedef struct OVERLAY_Data {
@@ -55,7 +55,8 @@ typedef struct OVERLAY_Data {
typedef struct OVERLAY_PrivateData {
DRWShadingGroup *face_orientation_shgrp;
- DRWShadingGroup *sculpt_wires_full;
+ DRWShadingGroup *face_wires;
+ DRWShadingGroup *flat_wires;
DRWShadingGroup *sculpt_wires;
View3DOverlay overlay;
float wire_step_param[2];
@@ -70,9 +71,7 @@ static struct {
/* Wireframe shader */
struct GPUShader *select_wireframe_sh;
struct GPUShader *face_wireframe_sh;
- struct GPUShader *face_wireframe_pretty_sh;
struct GPUShader *face_wireframe_sculpt_sh;
- struct GPUShader *face_wireframe_sculpt_pretty_sh;
} e_data = {NULL};
/* Shaders */
@@ -82,6 +81,7 @@ extern char datatoc_overlay_face_orientation_vert_glsl[];
extern char datatoc_overlay_face_wireframe_vert_glsl[];
extern char datatoc_overlay_face_wireframe_geom_glsl[];
extern char datatoc_overlay_face_wireframe_frag_glsl[];
+extern char datatoc_gpu_shader_depth_only_frag_glsl[];
extern struct GlobalsUboStorage ts; /* draw_common.c */
@@ -105,45 +105,23 @@ static void overlay_engine_init(void *vedata)
}
if (!e_data.face_wireframe_sh) {
- bool use_geom = GPU_type_matches(GPU_DEVICE_INTEL, GPU_OS_ANY, GPU_DRIVER_ANY);
-
e_data.select_wireframe_sh = DRW_shader_create(
datatoc_overlay_face_wireframe_vert_glsl,
datatoc_overlay_face_wireframe_geom_glsl,
- datatoc_overlay_face_wireframe_frag_glsl,
- "#define SELECT_EDGES\n"
- "#define LIGHT_EDGES\n"
- "#define USE_GEOM_SHADER\n");
+ datatoc_gpu_shader_depth_only_frag_glsl,
+ "#define SELECT_EDGES\n");
e_data.face_wireframe_sh = DRW_shader_create(
datatoc_overlay_face_wireframe_vert_glsl,
- use_geom ? datatoc_overlay_face_wireframe_geom_glsl : NULL,
- datatoc_overlay_face_wireframe_frag_glsl,
- use_geom ? "#define USE_GEOM_SHADER\n"
- : NULL);
-
- e_data.face_wireframe_pretty_sh = DRW_shader_create(
- datatoc_overlay_face_wireframe_vert_glsl,
- use_geom ? datatoc_overlay_face_wireframe_geom_glsl : NULL,
+ NULL,
datatoc_overlay_face_wireframe_frag_glsl,
- use_geom ? "#define USE_GEOM_SHADER\n"
- "#define LIGHT_EDGES\n"
- : "#define LIGHT_EDGES\n");
+ NULL);
e_data.face_wireframe_sculpt_sh = DRW_shader_create(
datatoc_overlay_face_wireframe_vert_glsl,
datatoc_overlay_face_wireframe_geom_glsl,
datatoc_overlay_face_wireframe_frag_glsl,
- "#define USE_SCULPT\n"
- "#define USE_GEOM_SHADER\n");
-
- e_data.face_wireframe_sculpt_pretty_sh = DRW_shader_create(
- datatoc_overlay_face_wireframe_vert_glsl,
- datatoc_overlay_face_wireframe_geom_glsl,
- datatoc_overlay_face_wireframe_frag_glsl,
- "#define USE_SCULPT\n"
- "#define USE_GEOM_SHADER\n"
- "#define LIGHT_EDGES\n");
+ "#define USE_SCULPT\n");
}
}
@@ -152,73 +130,68 @@ static void overlay_cache_init(void *vedata)
OVERLAY_Data *data = vedata;
OVERLAY_PassList *psl = data->psl;
OVERLAY_StorageList *stl = data->stl;
+ OVERLAY_PrivateData *g_data = stl->g_data;
const DRWContextState *DCS = DRW_context_state_get();
View3D *v3d = DCS->v3d;
if (v3d) {
- stl->g_data->overlay = v3d->overlay;
- stl->g_data->show_overlays = (v3d->flag2 & V3D_RENDER_OVERRIDE) == 0;
+ g_data->overlay = v3d->overlay;
+ g_data->show_overlays = (v3d->flag2 & V3D_RENDER_OVERRIDE) == 0;
}
else {
- memset(&stl->g_data->overlay, 0, sizeof(stl->g_data->overlay));
- stl->g_data->show_overlays = false;
+ memset(&g_data->overlay, 0, sizeof(g_data->overlay));
+ g_data->show_overlays = false;
}
- if (stl->g_data->show_overlays == false) {
- stl->g_data->overlay.flag = 0;
+ if (g_data->show_overlays == false) {
+ g_data->overlay.flag = 0;
}
if (v3d->shading.type == OB_WIRE) {
- stl->g_data->overlay.flag |= V3D_OVERLAY_WIREFRAMES;
- stl->g_data->show_overlays = true;
+ g_data->overlay.flag |= V3D_OVERLAY_WIREFRAMES;
+ g_data->show_overlays = true;
}
{
/* Face Orientation Pass */
DRWState state = DRW_STATE_WRITE_COLOR | DRW_STATE_DEPTH_EQUAL | DRW_STATE_BLEND;
psl->face_orientation_pass = DRW_pass_create("Face Orientation", state);
- stl->g_data->face_orientation_shgrp = DRW_shgroup_create(
+ g_data->face_orientation_shgrp = DRW_shgroup_create(
e_data.face_orientation_sh, psl->face_orientation_pass);
}
{
/* Wireframe */
- DRWState state = DRW_STATE_WRITE_COLOR | DRW_STATE_DEPTH_LESS_EQUAL | DRW_STATE_BLEND;
+ DRWState state = DRW_STATE_WRITE_COLOR | DRW_STATE_DEPTH_LESS_EQUAL | DRW_STATE_BLEND | DRW_STATE_FIRST_VERTEX_CONVENTION;
float wire_size = max_ff(0.0f, U.pixelsize - 1.0f) * 0.5f;
- psl->flat_wireframe_pass = DRW_pass_create("Flat Object Wires", state | DRW_STATE_WRITE_DEPTH);
+ const bool use_select = (DRW_state_is_select() || DRW_state_is_depth());
+ GPUShader *sculpt_wire_sh = use_select ? e_data.select_wireframe_sh : e_data.face_wireframe_sculpt_sh;
+ GPUShader *face_wires_sh = use_select ? e_data.select_wireframe_sh : e_data.face_wireframe_sh;
+ GPUShader *flat_wires_sh = GPU_shader_get_builtin_shader(GPU_SHADER_3D_UNIFORM_COLOR);
+
+ psl->face_wireframe_pass = DRW_pass_create("Face Wires", state);
- psl->face_wireframe_full_pass = DRW_pass_create("All Face Wires", state);
+ g_data->flat_wires = DRW_shgroup_create(flat_wires_sh, psl->face_wireframe_pass);
+ DRW_shgroup_uniform_vec4(g_data->flat_wires, "color", ts.colorWire, 1);
- stl->g_data->sculpt_wires_full = DRW_shgroup_create(e_data.face_wireframe_sculpt_sh, psl->face_wireframe_full_pass);
- DRW_shgroup_uniform_float_copy(stl->g_data->sculpt_wires_full, "wireSize", wire_size);
+ g_data->sculpt_wires = DRW_shgroup_create(sculpt_wire_sh, psl->face_wireframe_pass);
- DRWShadingGroup *shgrp = DRW_shgroup_create(e_data.face_wireframe_sh, psl->face_wireframe_full_pass);
- DRW_shgroup_uniform_float_copy(shgrp, "wireSize", wire_size);
+ g_data->face_wires = DRW_shgroup_create(face_wires_sh, psl->face_wireframe_pass);
+ DRW_shgroup_uniform_vec2(g_data->face_wires, "wireStepParam", g_data->wire_step_param, 1);
- psl->face_wireframe_pass = DRW_pass_create("Face Wires", state);
+ if (!use_select) {
+ DRW_shgroup_uniform_float_copy(g_data->sculpt_wires, "wireSize", wire_size);
+ DRW_shgroup_uniform_float_copy(g_data->face_wires, "wireSize", wire_size);
+ }
- stl->g_data->sculpt_wires = DRW_shgroup_create(e_data.face_wireframe_sculpt_pretty_sh, psl->face_wireframe_pass);
- DRW_shgroup_uniform_vec2(stl->g_data->sculpt_wires, "wireStepParam", stl->g_data->wire_step_param, 1);
- DRW_shgroup_uniform_float_copy(stl->g_data->sculpt_wires, "wireSize", wire_size);
-
- shgrp = DRW_shgroup_create(e_data.face_wireframe_pretty_sh, psl->face_wireframe_pass);
- DRW_shgroup_uniform_vec2(shgrp, "wireStepParam", stl->g_data->wire_step_param, 1);
- DRW_shgroup_uniform_float_copy(shgrp, "wireSize", wire_size);
-
- /**
- * The wireframe threshold ranges from 0.0 to 1.0
- * When 1.0 we show all the edges, when 0.5 we show as many as 2.7.
- *
- * If we wanted 0.0 to match 2.7, factor would need to be 0.003f.
- * The range controls the falloff effect. If range was 0.0f we would get a hard cut (as in 2.7).
- * That said we are using a different algorithm so the results will always differ.
- */
- const float factor = 0.0045f;
- const float range = 0.00125f;
- stl->g_data->wire_step_param[1] = (1.0f - factor) + stl->g_data->overlay.wireframe_threshold * factor;
- stl->g_data->wire_step_param[0] = stl->g_data->wire_step_param[1] + range;
+ /* Control aspect of the falloff. */
+ const float sharpness = 4.0f;
+ /* Scale and bias: Adjust with wiredata encoding. (see mesh_batch_cache_create_edges_wireframe_data) */
+ const float decompress = (0xFF / (float)(0xFF - 0x20));
+ g_data->wire_step_param[0] = -sharpness * decompress;
+ g_data->wire_step_param[1] = decompress + sharpness * stl->g_data->overlay.wireframe_threshold;
}
}
@@ -227,35 +200,47 @@ static void overlay_cache_populate(void *vedata, Object *ob)
OVERLAY_Data *data = vedata;
OVERLAY_StorageList *stl = data->stl;
OVERLAY_PrivateData *pd = stl->g_data;
- OVERLAY_PassList *psl = data->psl;
const DRWContextState *draw_ctx = DRW_context_state_get();
RegionView3D *rv3d = draw_ctx->rv3d;
View3D *v3d = draw_ctx->v3d;
- if ((!stl->g_data->show_overlays) ||
+ if ((!pd->show_overlays) ||
(ob->dt < OB_WIRE) ||
(!DRW_object_is_renderable(ob) && (ob->dt != OB_WIRE)))
{
return;
}
- if (DRW_object_is_renderable(ob) && stl->g_data->overlay.flag & V3D_OVERLAY_FACE_ORIENTATION) {
+ if (DRW_object_is_renderable(ob) && pd->overlay.flag & V3D_OVERLAY_FACE_ORIENTATION) {
struct GPUBatch *geom = DRW_cache_object_surface_get(ob);
if (geom) {
DRW_shgroup_call_add(pd->face_orientation_shgrp, geom, ob->obmat);
}
}
- if ((stl->g_data->overlay.flag & V3D_OVERLAY_WIREFRAMES) ||
+ if ((pd->overlay.flag & V3D_OVERLAY_WIREFRAMES) ||
(v3d->shading.type == OB_WIRE) ||
(ob->dtx & OB_DRAWWIRE) ||
(ob->dt == OB_WIRE))
{
- /* Don't do that in edit Mesh mode. */
- if (((ob != draw_ctx->object_edit) && !BKE_object_is_in_editmode(ob)) || ob->type != OB_MESH) {
+ const bool is_edit_mode = BKE_object_is_in_editmode(ob);
+ bool has_edit_mesh_cage = false;
+ if (ob->type == OB_MESH) {
+ /* TODO: Should be its own function. */
+ Mesh *me = (Mesh *)ob->data;
+ BMEditMesh *embm = me->edit_btmesh;
+ if (embm) {
+ has_edit_mesh_cage = embm->mesh_eval_cage && (embm->mesh_eval_cage != embm->mesh_eval_final);
+ }
+ }
+
+ /* Don't do that in edit Mesh mode, unless there is a modifier preview. */
+ if ((((ob != draw_ctx->object_edit) && !is_edit_mode) || has_edit_mesh_cage) ||
+ ob->type != OB_MESH)
+ {
const bool is_active = (ob == draw_ctx->obact);
const bool is_sculpt_mode = is_active && (draw_ctx->object_mode & OB_MODE_SCULPT) != 0;
- const bool all_wires = (stl->g_data->overlay.wireframe_threshold == 1.0f) ||
+ const bool all_wires = (pd->overlay.wireframe_threshold == 1.0f) ||
(ob->dtx & OB_DRAW_ALL_EDGES);
const bool is_wire = (ob->dt < OB_SOLID);
const int stencil_mask = (ob->dtx & OB_DRAWXRAY) ? 0x00 : 0xFF;
@@ -267,62 +252,47 @@ static void overlay_cache_populate(void *vedata, Object *ob)
DRW_object_is_flat(ob, &flat_axis) &&
DRW_object_axis_orthogonal_to_view(ob, flat_axis);
- if (is_sculpt_mode) {
- shgrp = (all_wires || DRW_object_is_flat_normal(ob))
- ? stl->g_data->sculpt_wires_full
- : stl->g_data->sculpt_wires;
- if (is_wire) {
- shgrp = DRW_shgroup_create_sub(shgrp);
- }
- DRW_shgroup_call_sculpt_add(shgrp, ob, ob->obmat);
- }
- else if (is_flat_object_viewed_from_side) {
+ if (is_flat_object_viewed_from_side && !is_sculpt_mode) {
/* Avoid losing flat objects when in ortho views (see T56549) */
struct GPUBatch *geom = DRW_cache_object_wire_outline_get(ob);
if (geom) {
- GPUShader *sh = GPU_shader_get_builtin_shader(GPU_SHADER_3D_UNIFORM_COLOR);
- shgrp = DRW_shgroup_create(sh, psl->flat_wireframe_pass);
+ shgrp = pd->flat_wires;
+ shgrp = DRW_shgroup_create_sub(shgrp);
DRW_shgroup_stencil_mask(shgrp, stencil_mask);
- DRW_shgroup_uniform_vec4(shgrp, "color", ts.colorWire, 1);
DRW_shgroup_call_object_add(shgrp, geom, ob);
}
}
else {
- int tri_count;
- GPUTexture *verts = NULL, *faceids;
- DRW_cache_object_face_wireframe_get(ob, &verts, &faceids, &tri_count);
- if (verts) {
+ struct GPUBatch *geom = DRW_cache_object_face_wireframe_get(ob);
+ if (geom || is_sculpt_mode) {
float *rim_col = ts.colorWire;
- if ((ob->base_flag & BASE_SELECTED) != 0) {
+ if (!is_edit_mode && !is_sculpt_mode && !has_edit_mesh_cage &&
+ ((ob->base_flag & BASE_SELECTED) != 0))
+ {
rim_col = (ob == draw_ctx->obact) ? ts.colorActive : ts.colorSelect;
}
- DRWPass *pass = (all_wires) ? psl->face_wireframe_full_pass : psl->face_wireframe_pass;
- GPUShader *sh = (all_wires) ? e_data.face_wireframe_sh : e_data.face_wireframe_pretty_sh;
-
- if ((DRW_state_is_select() || DRW_state_is_depth())) {
- static float params[2] = {1.2f, 1.0f}; /* Parameters for all wires */
-
- sh = e_data.select_wireframe_sh;
- shgrp = DRW_shgroup_create(sh, pass);
- DRW_shgroup_uniform_vec2(shgrp, "wireStepParam", (all_wires)
- ? params
- : stl->g_data->wire_step_param, 1);
- DRW_shgroup_uniform_texture(shgrp, "vertData", verts);
- DRW_shgroup_uniform_texture(shgrp, "faceIds", faceids);
- DRW_shgroup_call_object_procedural_triangles_culled_add(shgrp, tri_count, ob);
- }
- else {
- shgrp = DRW_shgroup_create(sh, pass);
+ shgrp = (is_sculpt_mode) ? pd->sculpt_wires : pd->face_wires;
+ shgrp = DRW_shgroup_create_sub(shgrp);
+
+ static float all_wires_params[2] = {0.0f, 10.0f}; /* Parameters for all wires */
+ DRW_shgroup_uniform_vec2(shgrp, "wireStepParam", (all_wires)
+ ? all_wires_params
+ : pd->wire_step_param, 1);
+
+ if (!(DRW_state_is_select() || DRW_state_is_depth())) {
DRW_shgroup_stencil_mask(shgrp, stencil_mask);
- DRW_shgroup_uniform_texture(shgrp, "vertData", verts);
- DRW_shgroup_uniform_texture(shgrp, "faceIds", faceids);
DRW_shgroup_uniform_vec3(shgrp, "wireColor", ts.colorWire, 1);
DRW_shgroup_uniform_vec3(shgrp, "rimColor", rim_col, 1);
- DRW_shgroup_call_object_procedural_triangles_culled_add(shgrp, tri_count, ob);
+ }
+
+ if (is_sculpt_mode) {
+ DRW_shgroup_call_sculpt_add(shgrp, ob, ob->obmat);
+ }
+ else {
+ DRW_shgroup_call_add(shgrp, geom, ob->obmat);
}
}
}
-
if (is_wire && shgrp != NULL) {
/* If object is wireframe, don't try to use stencil test. */
DRW_shgroup_state_disable(shgrp, DRW_STATE_STENCIL_EQUAL);
@@ -332,7 +302,7 @@ static void overlay_cache_populate(void *vedata, Object *ob)
}
}
else if ((ob->dtx & OB_DRAWXRAY) && shgrp != NULL) {
- stl->g_data->ghost_stencil_test = true;
+ pd->ghost_stencil_test = true;
}
}
}
@@ -351,7 +321,6 @@ static void overlay_cache_finish(void *vedata)
if (v3d->shading.type == OB_SOLID && (v3d->shading.flag & XRAY_FLAG(v3d)) == 0) {
if (stl->g_data->ghost_stencil_test) {
DRW_pass_state_add(psl->face_wireframe_pass, DRW_STATE_STENCIL_EQUAL);
- DRW_pass_state_add(psl->face_wireframe_full_pass, DRW_STATE_STENCIL_EQUAL);
}
}
}
@@ -366,9 +335,7 @@ static void overlay_draw_scene(void *vedata)
GPU_framebuffer_bind(dfbl->default_fb);
}
DRW_draw_pass(psl->face_orientation_pass);
- DRW_draw_pass(psl->flat_wireframe_pass);
DRW_draw_pass(psl->face_wireframe_pass);
- DRW_draw_pass(psl->face_wireframe_full_pass);
}
static void overlay_engine_free(void)
@@ -376,9 +343,7 @@ static void overlay_engine_free(void)
DRW_SHADER_FREE_SAFE(e_data.face_orientation_sh);
DRW_SHADER_FREE_SAFE(e_data.select_wireframe_sh);
DRW_SHADER_FREE_SAFE(e_data.face_wireframe_sh);
- DRW_SHADER_FREE_SAFE(e_data.face_wireframe_pretty_sh);
DRW_SHADER_FREE_SAFE(e_data.face_wireframe_sculpt_sh);
- DRW_SHADER_FREE_SAFE(e_data.face_wireframe_sculpt_pretty_sh);
}
static const DrawEngineDataSize overlay_data_size = DRW_VIEWPORT_DATA_SIZE(OVERLAY_Data);
diff --git a/source/blender/draw/modes/paint_texture_mode.c b/source/blender/draw/modes/paint_texture_mode.c
index 2792c59b805..3386c797765 100644
--- a/source/blender/draw/modes/paint_texture_mode.c
+++ b/source/blender/draw/modes/paint_texture_mode.c
@@ -38,11 +38,16 @@
#include "DNA_mesh_types.h"
+#include "DEG_depsgraph_query.h"
+
extern char datatoc_common_globals_lib_glsl[];
extern char datatoc_paint_texture_vert_glsl[];
extern char datatoc_paint_texture_frag_glsl[];
extern char datatoc_paint_wire_vert_glsl[];
extern char datatoc_paint_wire_frag_glsl[];
+extern char datatoc_paint_face_vert_glsl[];
+
+extern char datatoc_gpu_shader_uniform_color_frag_glsl[];
/* If needed, contains all global/Theme colors
* Add needed theme colors / values to DRW_globals_update() and update UBO
@@ -128,35 +133,12 @@ typedef struct PAINT_TEXTURE_PrivateData {
/* *********** FUNCTIONS *********** */
/* Init Textures, Framebuffers, Storage and Shaders.
- * It is called for every frames.
- * (Optional) */
-static void PAINT_TEXTURE_engine_init(void *vedata)
+ * It is called for every frames. */
+static void PAINT_TEXTURE_engine_init(void *UNUSED(vedata))
{
- PAINT_TEXTURE_TextureList *txl = ((PAINT_TEXTURE_Data *)vedata)->txl;
- PAINT_TEXTURE_FramebufferList *fbl = ((PAINT_TEXTURE_Data *)vedata)->fbl;
- PAINT_TEXTURE_StorageList *stl = ((PAINT_TEXTURE_Data *)vedata)->stl;
-
- UNUSED_VARS(txl, fbl, stl);
-
- /* Init Framebuffers like this: order is attachment order (for color texs) */
- /*
- * DRWFboTexture tex[2] = {{&txl->depth, GPU_DEPTH_COMPONENT24, 0},
- * {&txl->color, GPU_RGBA8, DRW_TEX_FILTER}};
- */
-
- /* DRW_framebuffer_init takes care of checking if
- * the framebuffer is valid and has the right size*/
- /*
- * float *viewport_size = DRW_viewport_size_get();
- * DRW_framebuffer_init(&fbl->occlude_wire_fb,
- * (int)viewport_size[0], (int)viewport_size[1],
- * tex, 2);
- */
-
if (!e_data.fallback_sh) {
e_data.fallback_sh = GPU_shader_get_builtin_shader(GPU_SHADER_3D_UNIFORM_COLOR);
- }
- if (!e_data.image_sh) {
+
e_data.image_sh = GPU_shader_get_builtin_shader(GPU_SHADER_3D_UNIFORM_COLOR);
e_data.image_sh = DRW_shader_create_with_lib(
@@ -164,18 +146,15 @@ static void PAINT_TEXTURE_engine_init(void *vedata)
datatoc_paint_texture_frag_glsl,
datatoc_common_globals_lib_glsl, NULL);
- }
-
- if (!e_data.wire_overlay_shader) {
e_data.wire_overlay_shader = DRW_shader_create_with_lib(
datatoc_paint_wire_vert_glsl, NULL,
datatoc_paint_wire_frag_glsl,
datatoc_common_globals_lib_glsl,
"#define VERTEX_MODE\n");
- }
- if (!e_data.face_overlay_shader) {
- e_data.face_overlay_shader = GPU_shader_get_builtin_shader(GPU_SHADER_3D_UNIFORM_COLOR);
+ e_data.face_overlay_shader = DRW_shader_create(
+ datatoc_paint_face_vert_glsl, NULL,
+ datatoc_gpu_shader_uniform_color_frag_glsl, NULL);
}
}
@@ -258,7 +237,7 @@ static void PAINT_TEXTURE_cache_init(void *vedata)
{
psl->wire_overlay = DRW_pass_create(
"Wire Pass",
- DRW_STATE_WRITE_COLOR | DRW_STATE_WRITE_DEPTH | DRW_STATE_DEPTH_LESS_EQUAL);
+ DRW_STATE_WRITE_COLOR | DRW_STATE_WRITE_DEPTH | DRW_STATE_DEPTH_LESS_EQUAL | DRW_STATE_OFFSET_NEGATIVE);
stl->g_data->lwire_shgrp = DRW_shgroup_create(e_data.wire_overlay_shader, psl->wire_overlay);
DRW_shgroup_uniform_block(stl->g_data->lwire_shgrp, "globalsBlock", globals_ubo);
@@ -288,57 +267,48 @@ static void PAINT_TEXTURE_cache_populate(void *vedata, Object *ob)
if ((ob->type == OB_MESH) && (draw_ctx->obact == ob)) {
/* Get geometry cache */
const Mesh *me = ob->data;
+ const Mesh *me_orig = DEG_get_original_object(ob)->data;
Scene *scene = draw_ctx->scene;
const bool use_surface = draw_ctx->v3d->overlay.texture_paint_mode_opacity != 0.0; //DRW_object_is_mode_shade(ob) == true;
const bool use_material_slots = (scene->toolsettings->imapaint.mode == IMAGEPAINT_MODE_MATERIAL);
- bool ok = false;
+ const bool use_face_sel = (me_orig->editflag & ME_EDIT_PAINT_FACE_SEL) != 0;
if (use_surface) {
if (me->mloopuv != NULL) {
if (use_material_slots) {
- struct GPUBatch **geom_array = me->totcol ? DRW_cache_mesh_surface_texpaint_get(ob) : NULL;
- if ((me->totcol == 0) || (geom_array == NULL)) {
- struct GPUBatch *geom = DRW_cache_mesh_surface_get(ob);
- DRW_shgroup_call_add(stl->g_data->shgroup_fallback, geom, ob->obmat);
- ok = true;
- }
- else {
- for (int i = 0; i < me->totcol; i++) {
- if (stl->g_data->shgroup_image_array[i]) {
- DRW_shgroup_call_add(stl->g_data->shgroup_image_array[i], geom_array[i], ob->obmat);
- }
- else {
- DRW_shgroup_call_add(stl->g_data->shgroup_fallback, geom_array[i], ob->obmat);
- }
- ok = true;
+ int mat_nr = max_ii(1, me->totcol);
+ struct GPUBatch **geom_array = DRW_cache_mesh_surface_texpaint_get(ob);
+
+ for (int i = 0; i < mat_nr; i++) {
+ const int index = use_material_slots ? i : 0;
+ if (stl->g_data->shgroup_image_array[index]) {
+ DRW_shgroup_call_add(stl->g_data->shgroup_image_array[index], geom_array[i], ob->obmat);
+ }
+ else {
+ DRW_shgroup_call_add(stl->g_data->shgroup_fallback, geom_array[i], ob->obmat);
}
}
}
else {
- struct GPUBatch *geom = DRW_cache_mesh_surface_texpaint_single_get(ob);
- if (geom && stl->g_data->shgroup_image_array[0]) {
+ if (stl->g_data->shgroup_image_array[0]) {
+ struct GPUBatch *geom = DRW_cache_mesh_surface_texpaint_single_get(ob);
DRW_shgroup_call_add(stl->g_data->shgroup_image_array[0], geom, ob->obmat);
- ok = true;
}
}
}
-
- if (!ok) {
+ else {
struct GPUBatch *geom = DRW_cache_mesh_surface_get(ob);
DRW_shgroup_call_add(stl->g_data->shgroup_fallback, geom, ob->obmat);
}
}
/* Face Mask */
- const bool use_face_sel = (me->editflag & ME_EDIT_PAINT_FACE_SEL) != 0;
if (use_face_sel) {
struct GPUBatch *geom;
- /* Note: ideally selected faces wouldn't show interior wire. */
- const bool use_wire = true;
- geom = DRW_cache_mesh_edges_paint_overlay_get(ob, use_wire, use_face_sel);
+ geom = DRW_cache_mesh_wire_get(ob);
DRW_shgroup_call_add(stl->g_data->lwire_shgrp, geom, ob->obmat);
- geom = DRW_cache_mesh_faces_weight_overlay_get(ob);
+ geom = DRW_cache_mesh_surface_get(ob);
DRW_shgroup_call_add(stl->g_data->face_shgrp, geom, ob->obmat);
}
}
@@ -381,6 +351,7 @@ static void PAINT_TEXTURE_engine_free(void)
{
DRW_SHADER_FREE_SAFE(e_data.image_sh);
DRW_SHADER_FREE_SAFE(e_data.wire_overlay_shader);
+ DRW_SHADER_FREE_SAFE(e_data.face_overlay_shader);
}
static const DrawEngineDataSize PAINT_TEXTURE_data_size = DRW_VIEWPORT_DATA_SIZE(PAINT_TEXTURE_Data);
diff --git a/source/blender/draw/modes/paint_vertex_mode.c b/source/blender/draw/modes/paint_vertex_mode.c
index d026e7a7924..7d3aa0f0b20 100644
--- a/source/blender/draw/modes/paint_vertex_mode.c
+++ b/source/blender/draw/modes/paint_vertex_mode.c
@@ -45,8 +45,11 @@ extern char datatoc_paint_vertex_vert_glsl[];
extern char datatoc_paint_vertex_frag_glsl[];
extern char datatoc_paint_wire_vert_glsl[];
extern char datatoc_paint_wire_frag_glsl[];
+extern char datatoc_paint_face_vert_glsl[];
extern char datatoc_common_globals_lib_glsl[];
+extern char datatoc_gpu_shader_uniform_color_frag_glsl[];
+
/* *********** LISTS *********** */
typedef struct PAINT_VERTEX_PassList {
@@ -95,7 +98,9 @@ static void PAINT_VERTEX_engine_init(void *UNUSED(vedata))
datatoc_paint_wire_frag_glsl,
datatoc_common_globals_lib_glsl, "#define VERTEX_MODE\n");
- e_data.face_overlay_shader = GPU_shader_get_builtin_shader(GPU_SHADER_3D_UNIFORM_COLOR);
+ e_data.face_overlay_shader = DRW_shader_create(
+ datatoc_paint_face_vert_glsl, NULL,
+ datatoc_gpu_shader_uniform_color_frag_glsl, NULL);
}
}
@@ -124,7 +129,7 @@ static void PAINT_VERTEX_cache_init(void *vedata)
{
psl->wire_overlay = DRW_pass_create(
"Wire Pass",
- DRW_STATE_WRITE_COLOR | DRW_STATE_WRITE_DEPTH | DRW_STATE_DEPTH_LESS_EQUAL);
+ DRW_STATE_WRITE_COLOR | DRW_STATE_WRITE_DEPTH | DRW_STATE_DEPTH_LESS_EQUAL | DRW_STATE_OFFSET_NEGATIVE);
stl->g_data->lwire_shgrp = DRW_shgroup_create(e_data.wire_overlay_shader, psl->wire_overlay);
DRW_shgroup_uniform_block(stl->g_data->lwire_shgrp, "globalsBlock", globals_ubo);
@@ -149,26 +154,28 @@ static void PAINT_VERTEX_cache_populate(void *vedata, Object *ob)
const View3D *v3d = draw_ctx->v3d;
if ((ob->type == OB_MESH) && (ob == draw_ctx->obact)) {
- /* We're always painting on original, display original data. */
- ob = DEG_get_original_object(ob);
const Mesh *me = ob->data;
const bool use_wire = (v3d->overlay.paint_flag & V3D_OVERLAY_PAINT_WIRE) != 0;
const bool use_surface = v3d->overlay.vertex_paint_mode_opacity != 0.0f;
const bool use_face_sel = (me->editflag & ME_EDIT_PAINT_FACE_SEL) != 0;
struct GPUBatch *geom;
+ if (me->mloopcol == NULL) {
+ return;
+ }
+
if (use_surface) {
geom = DRW_cache_mesh_surface_vert_colors_get(ob);
DRW_shgroup_call_add(stl->g_data->fvcolor_shgrp, geom, ob->obmat);
}
if (use_face_sel || use_wire) {
- geom = DRW_cache_mesh_edges_paint_overlay_get(ob, use_wire, use_face_sel);
+ geom = DRW_cache_mesh_wire_get(ob);
DRW_shgroup_call_add(stl->g_data->lwire_shgrp, geom, ob->obmat);
}
if (use_face_sel) {
- geom = DRW_cache_mesh_faces_weight_overlay_get(ob);
+ geom = DRW_cache_mesh_surface_get(ob);
DRW_shgroup_call_add(stl->g_data->face_shgrp, geom, ob->obmat);
}
}
@@ -187,6 +194,7 @@ static void PAINT_VERTEX_engine_free(void)
{
DRW_SHADER_FREE_SAFE(e_data.vcolor_face_shader);
DRW_SHADER_FREE_SAFE(e_data.wire_overlay_shader);
+ DRW_SHADER_FREE_SAFE(e_data.face_overlay_shader);
}
static const DrawEngineDataSize PAINT_VERTEX_data_size = DRW_VIEWPORT_DATA_SIZE(PAINT_VERTEX_Data);
diff --git a/source/blender/draw/modes/paint_weight_mode.c b/source/blender/draw/modes/paint_weight_mode.c
index 9060a97f412..e3993ee177a 100644
--- a/source/blender/draw/modes/paint_weight_mode.c
+++ b/source/blender/draw/modes/paint_weight_mode.c
@@ -45,6 +45,7 @@ extern struct GlobalsUboStorage ts; /* draw_common.c */
extern struct GPUTexture *globals_weight_ramp; /* draw_common.c */
+extern char datatoc_paint_face_vert_glsl[];
extern char datatoc_paint_weight_vert_glsl[];
extern char datatoc_paint_weight_frag_glsl[];
extern char datatoc_paint_wire_vert_glsl[];
@@ -52,6 +53,8 @@ extern char datatoc_paint_wire_frag_glsl[];
extern char datatoc_paint_vert_frag_glsl[];
extern char datatoc_common_globals_lib_glsl[];
+extern char datatoc_gpu_shader_uniform_color_frag_glsl[];
+
/* *********** LISTS *********** */
typedef struct PAINT_WEIGHT_PassList {
@@ -99,20 +102,16 @@ static void PAINT_WEIGHT_engine_init(void *UNUSED(vedata))
datatoc_paint_weight_vert_glsl, NULL,
datatoc_paint_weight_frag_glsl,
datatoc_common_globals_lib_glsl, NULL);
- }
- if (!e_data.wire_overlay_shader) {
e_data.wire_overlay_shader = DRW_shader_create_with_lib(
datatoc_paint_wire_vert_glsl, NULL,
datatoc_paint_wire_frag_glsl,
datatoc_common_globals_lib_glsl, "#define WEIGHT_MODE\n");
- }
- if (!e_data.face_overlay_shader) {
- e_data.face_overlay_shader = GPU_shader_get_builtin_shader(GPU_SHADER_3D_UNIFORM_COLOR);
- }
+ e_data.face_overlay_shader = DRW_shader_create(
+ datatoc_paint_face_vert_glsl, NULL,
+ datatoc_gpu_shader_uniform_color_frag_glsl, NULL);
- if (!e_data.vert_overlay_shader) {
e_data.vert_overlay_shader = DRW_shader_create_with_lib(
datatoc_paint_wire_vert_glsl, NULL,
datatoc_paint_vert_frag_glsl,
@@ -150,7 +149,7 @@ static void PAINT_WEIGHT_cache_init(void *vedata)
{
psl->wire_overlay = DRW_pass_create(
"Wire Pass",
- DRW_STATE_WRITE_COLOR | DRW_STATE_WRITE_DEPTH | DRW_STATE_DEPTH_LESS_EQUAL);
+ DRW_STATE_WRITE_COLOR | DRW_STATE_WRITE_DEPTH | DRW_STATE_DEPTH_LESS_EQUAL | DRW_STATE_OFFSET_NEGATIVE);
stl->g_data->lwire_shgrp = DRW_shgroup_create(e_data.wire_overlay_shader, psl->wire_overlay);
DRW_shgroup_uniform_block(stl->g_data->lwire_shgrp, "globalsBlock", globals_ubo);
@@ -170,7 +169,7 @@ static void PAINT_WEIGHT_cache_init(void *vedata)
{
psl->vert_overlay = DRW_pass_create(
"Vert Mask Pass",
- DRW_STATE_WRITE_COLOR | DRW_STATE_WRITE_DEPTH | DRW_STATE_DEPTH_LESS_EQUAL);
+ DRW_STATE_WRITE_COLOR | DRW_STATE_WRITE_DEPTH | DRW_STATE_DEPTH_LESS_EQUAL | DRW_STATE_OFFSET_NEGATIVE);
stl->g_data->vert_shgrp = DRW_shgroup_create(e_data.vert_overlay_shader, psl->vert_overlay);
DRW_shgroup_uniform_block(stl->g_data->vert_shgrp, "globalsBlock", globals_ubo);
@@ -184,30 +183,30 @@ static void PAINT_WEIGHT_cache_populate(void *vedata, Object *ob)
const View3D *v3d = draw_ctx->v3d;
if ((ob->type == OB_MESH) && (ob == draw_ctx->obact)) {
- const Mesh *me = ob->data;
+ const Mesh *me_orig = DEG_get_original_object(ob)->data;
const bool use_wire = (v3d->overlay.paint_flag & V3D_OVERLAY_PAINT_WIRE) != 0;
const bool use_surface = v3d->overlay.weight_paint_mode_opacity != 0.0f;
- const bool use_face_sel = (me->editflag & ME_EDIT_PAINT_FACE_SEL) != 0;
- const bool use_vert_sel = (me->editflag & ME_EDIT_PAINT_VERT_SEL) != 0;
+ const bool use_face_sel = (me_orig->editflag & ME_EDIT_PAINT_FACE_SEL) != 0;
+ const bool use_vert_sel = (me_orig->editflag & ME_EDIT_PAINT_VERT_SEL) != 0;
struct GPUBatch *geom;
if (use_surface) {
- geom = DRW_cache_mesh_surface_weights_get(ob, draw_ctx->scene->toolsettings, true);
+ geom = DRW_cache_mesh_surface_weights_get(ob);
DRW_shgroup_call_add(stl->g_data->fweights_shgrp, geom, ob->obmat);
}
if (use_face_sel || use_wire) {
- geom = DRW_cache_mesh_edges_paint_overlay_get(ob, use_wire, use_face_sel);
+ geom = DRW_cache_mesh_wire_get(ob);
DRW_shgroup_call_add(stl->g_data->lwire_shgrp, geom, ob->obmat);
}
if (use_face_sel) {
- geom = DRW_cache_mesh_faces_weight_overlay_get(ob);
+ geom = DRW_cache_mesh_surface_get(ob);
DRW_shgroup_call_add(stl->g_data->face_shgrp, geom, ob->obmat);
}
if (use_vert_sel) {
- geom = DRW_cache_mesh_verts_weight_overlay_get(ob);
+ geom = DRW_cache_mesh_verts_get(ob);
DRW_shgroup_call_add(stl->g_data->vert_shgrp, geom, ob->obmat);
}
}
@@ -228,6 +227,7 @@ static void PAINT_WEIGHT_engine_free(void)
DRW_SHADER_FREE_SAFE(e_data.weight_face_shader);
DRW_SHADER_FREE_SAFE(e_data.wire_overlay_shader);
DRW_SHADER_FREE_SAFE(e_data.vert_overlay_shader);
+ DRW_SHADER_FREE_SAFE(e_data.face_overlay_shader);
}
static const DrawEngineDataSize PAINT_WEIGHT_data_size = DRW_VIEWPORT_DATA_SIZE(PAINT_WEIGHT_Data);
diff --git a/source/blender/draw/modes/particle_mode.c b/source/blender/draw/modes/particle_mode.c
index f4879483540..758218fe329 100644
--- a/source/blender/draw/modes/particle_mode.c
+++ b/source/blender/draw/modes/particle_mode.c
@@ -48,6 +48,9 @@
extern char datatoc_particle_strand_vert_glsl[];
extern char datatoc_particle_strand_frag_glsl[];
+extern char datatoc_common_globals_lib_glsl[];
+
+extern struct GPUUniformBuffer *globals_ubo; /* draw_common.c */
/* *********** LISTS *********** */
@@ -80,6 +83,7 @@ typedef struct PARTICLE_Data {
static struct {
struct GPUShader *strands_shader;
+ struct GPUShader *strands_weight_shader;
struct GPUShader *points_shader;
} e_data = {NULL}; /* Engine data */
@@ -94,15 +98,26 @@ typedef struct PARTICLE_PrivateData {
static void particle_engine_init(void *UNUSED(vedata))
{
if (!e_data.strands_shader) {
- e_data.strands_shader = DRW_shader_create(
+ e_data.strands_shader = DRW_shader_create_with_lib(
datatoc_particle_strand_vert_glsl,
NULL,
datatoc_particle_strand_frag_glsl,
+ datatoc_common_globals_lib_glsl,
"");
- }
- if (!e_data.points_shader) {
- e_data.points_shader = GPU_shader_get_builtin_shader(
- GPU_SHADER_3D_POINT_FIXED_SIZE_VARYING_COLOR);
+
+ e_data.strands_weight_shader = DRW_shader_create_with_lib(
+ datatoc_particle_strand_vert_glsl,
+ NULL,
+ datatoc_particle_strand_frag_glsl,
+ datatoc_common_globals_lib_glsl,
+ "#define USE_WEIGHT");
+
+ e_data.points_shader = DRW_shader_create_with_lib(
+ datatoc_particle_strand_vert_glsl,
+ NULL,
+ datatoc_particle_strand_frag_glsl,
+ datatoc_common_globals_lib_glsl,
+ "#define USE_POINTS");
}
}
@@ -110,6 +125,9 @@ static void particle_cache_init(void *vedata)
{
PARTICLE_PassList *psl = ((PARTICLE_Data *)vedata)->psl;
PARTICLE_StorageList *stl = ((PARTICLE_Data *)vedata)->stl;
+ const DRWContextState *draw_ctx = DRW_context_state_get();
+ ParticleEditSettings *pset = PE_settings(draw_ctx->scene);
+ const bool use_weight = (pset->brushtype == PE_BRUSH_WEIGHT);
if (!stl->g_data) {
/* Alloc transient pointers */
@@ -124,19 +142,14 @@ static void particle_cache_init(void *vedata)
DRW_STATE_WIRE |
DRW_STATE_POINT));
- stl->g_data->strands_group = DRW_shgroup_create(
- e_data.strands_shader, psl->psys_edit_pass);
- stl->g_data->inner_points_group = DRW_shgroup_create(
- e_data.points_shader, psl->psys_edit_pass);
- stl->g_data->tip_points_group = DRW_shgroup_create(
- e_data.points_shader, psl->psys_edit_pass);
-
- static float size = 5.0f;
- static float outline_width = 1.0f;
- DRW_shgroup_uniform_float(stl->g_data->inner_points_group, "size", &size, 1);
- DRW_shgroup_uniform_float(stl->g_data->inner_points_group, "outlineWidth", &outline_width, 1);
- DRW_shgroup_uniform_float(stl->g_data->tip_points_group, "size", &size, 1);
- DRW_shgroup_uniform_float(stl->g_data->tip_points_group, "outlineWidth", &outline_width, 1);
+ GPUShader *strand_shader = (use_weight) ? e_data.strands_weight_shader : e_data.strands_shader;
+ stl->g_data->strands_group = DRW_shgroup_create(strand_shader, psl->psys_edit_pass);
+ stl->g_data->inner_points_group = DRW_shgroup_create(e_data.points_shader, psl->psys_edit_pass);
+ stl->g_data->tip_points_group = DRW_shgroup_create(e_data.points_shader, psl->psys_edit_pass);
+
+ DRW_shgroup_uniform_block(stl->g_data->strands_group, "globalsBlock", globals_ubo);
+ DRW_shgroup_uniform_block(stl->g_data->inner_points_group, "globalsBlock", globals_ubo);
+ DRW_shgroup_uniform_block(stl->g_data->tip_points_group, "globalsBlock", globals_ubo);
}
static void particle_edit_cache_populate(void *vedata,
@@ -147,9 +160,10 @@ static void particle_edit_cache_populate(void *vedata,
PARTICLE_StorageList *stl = ((PARTICLE_Data *)vedata)->stl;
const DRWContextState *draw_ctx = DRW_context_state_get();
ParticleEditSettings *pset = PE_settings(draw_ctx->scene);
+ const bool use_weight = (pset->brushtype == PE_BRUSH_WEIGHT);
{
struct GPUBatch *strands =
- DRW_cache_particles_get_edit_strands(object, psys, edit);
+ DRW_cache_particles_get_edit_strands(object, psys, edit, use_weight);
DRW_shgroup_call_add(stl->g_data->strands_group, strands, NULL);
}
if (pset->selectmode == SCE_SELECT_POINT) {
@@ -225,6 +239,8 @@ static void particle_draw_scene(void *vedata)
static void particle_engine_free(void)
{
DRW_SHADER_FREE_SAFE(e_data.strands_shader);
+ DRW_SHADER_FREE_SAFE(e_data.strands_weight_shader);
+ DRW_SHADER_FREE_SAFE(e_data.points_shader);
}
static const DrawEngineDataSize particle_data_size =
diff --git a/source/blender/draw/modes/pose_mode.c b/source/blender/draw/modes/pose_mode.c
index 3c0a8048c9e..6ee6f59e5fa 100644
--- a/source/blender/draw/modes/pose_mode.c
+++ b/source/blender/draw/modes/pose_mode.c
@@ -195,7 +195,9 @@ static void POSE_cache_populate(void *vedata, Object *ob)
* and similar functionalities. For now we handle only pose bones. */
if (ob->type == OB_ARMATURE) {
- if (draw_ctx->v3d->overlay.flag & V3D_OVERLAY_HIDE_BONES) {
+ if ((draw_ctx->v3d->flag2 & V3D_RENDER_OVERRIDE) ||
+ (draw_ctx->v3d->overlay.flag & V3D_OVERLAY_HIDE_BONES))
+ {
return;
}
if (DRW_pose_mode_armature(ob, draw_ctx->obact)) {
diff --git a/source/blender/draw/modes/shaders/common_fullscreen_vert.glsl b/source/blender/draw/modes/shaders/common_fullscreen_vert.glsl
index fc5cc1cdcc3..e5c5ccc97bf 100644
--- a/source/blender/draw/modes/shaders/common_fullscreen_vert.glsl
+++ b/source/blender/draw/modes/shaders/common_fullscreen_vert.glsl
@@ -6,5 +6,5 @@ out vec4 uvcoordsvar;
void main()
{
uvcoordsvar = vec4(uvs, 0.0, 0.0);
- gl_Position = vec4(pos, 0.0, 1.0);
+ gl_Position = vec4(pos, 1.0, 1.0);
}
diff --git a/source/blender/draw/modes/shaders/common_globals_lib.glsl b/source/blender/draw/modes/shaders/common_globals_lib.glsl
index 69ba304ca24..520b368bbc2 100644
--- a/source/blender/draw/modes/shaders/common_globals_lib.glsl
+++ b/source/blender/draw/modes/shaders/common_globals_lib.glsl
@@ -36,6 +36,7 @@ layout(std140) uniform globalsBlock {
vec4 colorLampNoAlpha;
vec4 colorBackground;
+ vec4 colorEditMeshMiddle;
vec4 colorHandleFree;
vec4 colorHandleAuto;
diff --git a/source/blender/draw/modes/shaders/common_hair_lib.glsl b/source/blender/draw/modes/shaders/common_hair_lib.glsl
index ab4ccad9342..a7fe2a23ed0 100644
--- a/source/blender/draw/modes/shaders/common_hair_lib.glsl
+++ b/source/blender/draw/modes/shaders/common_hair_lib.glsl
@@ -19,6 +19,8 @@ uniform float hairRadTip = 0.0;
uniform float hairRadShape = 0.5;
uniform bool hairCloseTip = true;
+uniform mat4 hairDupliMatrix;
+
/* -- Per control points -- */
uniform samplerBuffer hairPointBuffer; /* RGBA32F */
#define point_position xyz
@@ -146,6 +148,9 @@ void hair_get_pos_tan_binor_time(
wtan = wpos - texelFetch(hairPointBuffer, id - 1).point_position;
}
+ wpos = (hairDupliMatrix * vec4(wpos, 1.0)).xyz;
+ wtan = mat3(hairDupliMatrix) * wtan;
+
vec3 camera_vec = (is_persp) ? wpos - camera_pos : -camera_z;
wbinor = normalize(cross(camera_vec, wtan));
diff --git a/source/blender/draw/modes/shaders/edit_curve_overlay_normals_vert.glsl b/source/blender/draw/modes/shaders/edit_curve_overlay_normals_vert.glsl
new file mode 100644
index 00000000000..06be402d737
--- /dev/null
+++ b/source/blender/draw/modes/shaders/edit_curve_overlay_normals_vert.glsl
@@ -0,0 +1,23 @@
+
+/* Draw Curve Normals */
+
+uniform mat4 ModelViewProjectionMatrix;
+uniform float normalSize;
+
+in vec3 pos;
+in vec3 nor;
+in vec3 tan;
+in float rad;
+
+void main()
+{
+ vec3 final_pos = pos;
+
+ float flip = (gl_InstanceID != 0) ? -1.0 : 1.0;
+
+ if (gl_VertexID % 2 == 0) {
+ final_pos += normalSize * rad * (flip * nor - tan);
+ }
+
+ gl_Position = ModelViewProjectionMatrix * vec4(final_pos, 1.0);
+}
diff --git a/source/blender/draw/modes/shaders/edit_mesh_overlay_frag.glsl b/source/blender/draw/modes/shaders/edit_mesh_overlay_frag.glsl
index 8d7a653c2fe..0d5c76ad790 100644
--- a/source/blender/draw/modes/shaders/edit_mesh_overlay_frag.glsl
+++ b/source/blender/draw/modes/shaders/edit_mesh_overlay_frag.glsl
@@ -144,7 +144,7 @@ void main()
#endif
#ifdef VERTEX_FACING
- FragColor.a *= 1.0 - abs(facing) * 0.4;
+ FragColor.rgb = mix(colorEditMeshMiddle.rgb, FragColor.rgb, 1.0 - abs(facing) * 0.4);
#endif
/* don't write depth if not opaque */
diff --git a/source/blender/draw/modes/shaders/edit_mesh_overlay_geom_tri.glsl b/source/blender/draw/modes/shaders/edit_mesh_overlay_geom_tri.glsl
index a04494d2ec4..fa2063a40a6 100644
--- a/source/blender/draw/modes/shaders/edit_mesh_overlay_geom_tri.glsl
+++ b/source/blender/draw/modes/shaders/edit_mesh_overlay_geom_tri.glsl
@@ -9,7 +9,7 @@ layout(triangles) in;
* triangle. Order is important.
* TODO diagram
*/
-layout(triangle_strip, max_vertices=12) out;
+layout(triangle_strip, max_vertices=11) out;
uniform mat4 ProjectionMatrix;
uniform vec2 viewportSize;
@@ -92,7 +92,7 @@ void mask_edge_flag(int v, ivec3 eflag)
/* Only shade the edge that we are currently drawing.
* (fix corner bleeding) */
- flag = eflag & ~EDGE_VERTEX_EXISTS;
+ flag = eflag;
flag[vaf] &= ~EDGE_EXISTS;
flag[v] &= ~EDGE_EXISTS;
}
diff --git a/source/blender/draw/modes/shaders/edit_mesh_overlay_points_vert.glsl b/source/blender/draw/modes/shaders/edit_mesh_overlay_points_vert.glsl
index 3886213ce49..245cbab92d5 100644
--- a/source/blender/draw/modes/shaders/edit_mesh_overlay_points_vert.glsl
+++ b/source/blender/draw/modes/shaders/edit_mesh_overlay_points_vert.glsl
@@ -38,8 +38,10 @@ void main()
? normalize(vPos.xyz)
: vec3(0.0, 0.0, 1.0);
float facing = dot(view_vec, view_normal);
+ facing = 1.0 - abs(facing) * 0.4;
- finalColor.a *= 1.0 - abs(facing) * 0.4;
+ finalColor = mix(colorEditMeshMiddle, finalColor, facing);
+ finalColor.a = 1.0;
#endif
if ((data.x & VERTEX_EXISTS) == 0) {
diff --git a/source/blender/draw/modes/shaders/edit_mesh_overlay_vert.glsl b/source/blender/draw/modes/shaders/edit_mesh_overlay_vert.glsl
index e4268188e09..b78c7a7a476 100644
--- a/source/blender/draw/modes/shaders/edit_mesh_overlay_vert.glsl
+++ b/source/blender/draw/modes/shaders/edit_mesh_overlay_vert.glsl
@@ -8,10 +8,6 @@ uniform mat4 ModelViewMatrix;
uniform mat4 ModelViewProjectionMatrix;
uniform ivec4 dataMask = ivec4(0xFF);
-uniform float ofs = 1e-5;
-
-uniform isamplerBuffer dataBuffer;
-
in vec3 pos;
#ifdef VERTEX_FACING
in vec3 vnor;
@@ -29,7 +25,6 @@ out float vFacing;
void main()
{
pPos = ModelViewProjectionMatrix * vec4(pos, 1.0);
- pPos.z -= ofs * ((ProjectionMatrix[3][3] == 0.0) ? 1.0 : 0.0);
vData = data & dataMask;
# ifdef VERTEX_FACING
vec4 vpos = ModelViewMatrix * vec4(pos, 1.0);
@@ -43,6 +38,13 @@ void main()
#else /* EDGE_FIX */
+/* Consecutive data of the nth vertex.
+ * Only valid for first vertex in the triangle.
+ * Assuming GL_FRIST_VERTEX_CONVENTION. */
+in ivec4 data0;
+in ivec4 data1;
+in ivec4 data2;
+
flat out vec3 edgesCrease;
flat out vec3 edgesBweight;
flat out vec4 faceColor;
@@ -59,18 +61,16 @@ out vec3 barycentric;
void main()
{
gl_Position = ModelViewProjectionMatrix * vec4(pos, 1.0);
- gl_Position.z -= ofs * ((ProjectionMatrix[3][3] == 0.0) ? 1.0 : 0.0);
int v_0 = (gl_VertexID / 3) * 3;
int vidx = gl_VertexID % 3;
barycentric = vec3(equal(ivec3(0, 1, 2), ivec3(vidx)));
/* Edge */
- ivec4 vData[3], data = ivec4(0);
+ ivec4 vData[3] = ivec4[3](data0, data1, data2);
ivec3 eflag;
for (int v = 0; v < 3; ++v) {
- data = texelFetch(dataBuffer, v_0 + v);
- vData[v] = data & dataMask;
+ vData[v] = vData[v] & dataMask;
flag[v] = eflag[v] = vData[v].y | (vData[v].x << 8);
edgesCrease[v] = vData[v].z / 255.0;
edgesBweight[v] = vData[v].w / 255.0;
@@ -87,7 +87,7 @@ void main()
faceColor = colorFace;
# ifdef VERTEX_SELECTION
- vertexColor = EDIT_MESH_vertex_color(vData[vidx].x).rgb;
+ vertexColor = EDIT_MESH_vertex_color(data0.x).rgb;
# endif
# ifdef VERTEX_FACING
vec4 vPos = ModelViewMatrix * vec4(pos, 1.0);
diff --git a/source/blender/draw/modes/shaders/object_empty_image_vert.glsl b/source/blender/draw/modes/shaders/object_empty_image_vert.glsl
index 3469e37358e..1c1525696fb 100644
--- a/source/blender/draw/modes/shaders/object_empty_image_vert.glsl
+++ b/source/blender/draw/modes/shaders/object_empty_image_vert.glsl
@@ -24,6 +24,7 @@ void main()
(pos + offset) * (size * vec2(aspectX, aspectY)),
0.0, 1.0);
#ifdef USE_WIRE
+ gl_Position.z -= 1e-5;
finalColor = vec4(color, 1.0);
#else
texCoord_interp = texCoord;
diff --git a/source/blender/draw/modes/shaders/object_grid_vert.glsl b/source/blender/draw/modes/shaders/object_grid_vert.glsl
index a346973a597..15b37bb289d 100644
--- a/source/blender/draw/modes/shaders/object_grid_vert.glsl
+++ b/source/blender/draw/modes/shaders/object_grid_vert.glsl
@@ -53,10 +53,10 @@ void main()
/* Used for additional Z axis */
if ((gridFlag & CLIP_Z_POS) != 0) {
- realPos.z = max(realPos.z, 0.0);
+ realPos.z = clamp(realPos.z, 0.0, 1e30);
}
if ((gridFlag & CLIP_Z_NEG) != 0) {
- realPos.z = min(-realPos.z, 0.0);
+ realPos.z = clamp(realPos.z, -1e30, 0.0);
}
gl_Position = ViewProjectionMatrix * vec4(realPos, 1.0);
diff --git a/source/blender/draw/modes/shaders/object_loose_points_frag.glsl b/source/blender/draw/modes/shaders/object_loose_points_frag.glsl
new file mode 100644
index 00000000000..66b3091a41c
--- /dev/null
+++ b/source/blender/draw/modes/shaders/object_loose_points_frag.glsl
@@ -0,0 +1,19 @@
+
+uniform vec4 color;
+uniform vec4 innerColor;
+
+out vec4 fragColor;
+
+void main()
+{
+ vec2 centered = abs(gl_PointCoord - vec2(0.5));
+ float dist = max(centered.x, centered.y);
+
+ float fac = dist * dist * 4.0;
+ fragColor = mix(innerColor, color, 0.45 + fac * 0.65);
+
+ /* Make the effect more like a fresnel by offsetting
+ * the depth and creating mini-spheres.
+ * Disabled as it has performance impact. */
+ // gl_FragDepth = gl_FragCoord.z + 1e-6 * fac;
+}
diff --git a/source/blender/draw/modes/shaders/overlay_face_wireframe_frag.glsl b/source/blender/draw/modes/shaders/overlay_face_wireframe_frag.glsl
index 69af4858a48..cefd4eab2e3 100644
--- a/source/blender/draw/modes/shaders/overlay_face_wireframe_frag.glsl
+++ b/source/blender/draw/modes/shaders/overlay_face_wireframe_frag.glsl
@@ -1,18 +1,12 @@
-#ifndef SELECT_EDGES
uniform vec3 wireColor;
uniform vec3 rimColor;
in float facing;
in vec3 barycentric;
-
-# ifdef LIGHT_EDGES
flat in vec3 edgeSharpness;
-# endif
out vec4 fragColor;
-#endif
-float min_v3(vec3 v) { return min(v.x, min(v.y, v.z)); }
float max_v3(vec3 v) { return max(v.x, max(v.y, v.z)); }
/* In pixels */
@@ -25,7 +19,6 @@ const float rim_alpha = 0.75;
void main()
{
-#ifndef SELECT_EDGES
vec3 dx = dFdx(barycentric);
vec3 dy = dFdy(barycentric);
vec3 d = vec3(
@@ -35,11 +28,7 @@ void main()
);
vec3 dist_to_edge = barycentric / d;
-# ifdef LIGHT_EDGES
vec3 fac = abs(dist_to_edge);
-# else
- float fac = min_v3(abs(dist_to_edge));
-# endif
fac = smoothstep(wireSize + wire_smooth, wireSize, fac);
@@ -48,10 +37,5 @@ void main()
vec3 final_front_col = mix(rimColor, wireColor, 0.05);
fragColor = mix(vec4(rimColor, rim_alpha), vec4(final_front_col, front_alpha), facing_clamped);
-# ifdef LIGHT_EDGES
fragColor.a *= max_v3(fac * edgeSharpness);
-# else
- fragColor.a *= fac;
-# endif
-#endif
}
diff --git a/source/blender/draw/modes/shaders/overlay_face_wireframe_geom.glsl b/source/blender/draw/modes/shaders/overlay_face_wireframe_geom.glsl
index 8abb6ecc737..7a40dd59571 100644
--- a/source/blender/draw/modes/shaders/overlay_face_wireframe_geom.glsl
+++ b/source/blender/draw/modes/shaders/overlay_face_wireframe_geom.glsl
@@ -1,6 +1,5 @@
-/* This shader is only used for intel GPU where the Geom shader is faster
- * than doing everything thrice in the vertex shader. */
+/* This shader is only used for edge selection & sculpt mode wires (because of indexed drawing). */
layout(triangles) in;
#ifdef SELECT_EDGES
@@ -9,119 +8,53 @@ layout(line_strip, max_vertices = 6) out;
layout(triangle_strip, max_vertices = 3) out;
#endif
-uniform vec2 wireStepParam;
-
-in vec2 ssPos[];
-in float facingOut[];
+in float facing_g[];
+in float edgeSharpness_g[];
#ifndef SELECT_EDGES
-out vec3 barycentric;
out float facing;
-#endif
-
-#ifdef LIGHT_EDGES
-in vec3 obPos[];
-in vec3 vNor[];
-in float forceEdge[];
-
-# ifndef SELECT_EDGES
+out vec3 barycentric;
flat out vec3 edgeSharpness;
-# endif
#endif
-#define NO_EDGE vec3(10000.0);
-
-vec3 get_edge_normal(vec3 n1, vec3 n2, vec3 edge)
-{
- edge = normalize(edge);
- vec3 n = n1 + n2;
- float p = dot(edge, n);
- return normalize(n - p * edge);
-}
-
-float get_edge_sharpness(vec3 fnor, vec3 vnor)
-{
- float sharpness = abs(dot(fnor, vnor));
- return smoothstep(wireStepParam.x, wireStepParam.y, sharpness);
-}
-
-vec3 get_barycentric(bvec3 do_edge, const int v)
-{
- int v_n = v;
- int v_n1 = (v + 1) % 3;
- int v_n2 = (v + 2) % 3;
- vec3 bary;
- bary[v_n] = do_edge[v_n] ? 0.0 : 1.0;
- bary[v_n1] = 1.0;
- bary[v_n2] = do_edge[v_n2] ? 0.0 : 1.0;
- return bary;
-}
-
void main(void)
{
- vec3 facings = vec3(facingOut[0], facingOut[1], facingOut[2]);
- bvec3 do_edge = greaterThan(abs(facings), vec3(1.0));
- facings = fract(facings) - clamp(-sign(facings), 0.0, 1.0);
-
-#ifdef SELECT_EDGES
- vec3 edgeSharpness;
-#endif
-
-#ifdef LIGHT_EDGES
- vec3 edges[3];
- edges[0] = obPos[1] - obPos[0];
- edges[1] = obPos[2] - obPos[1];
- edges[2] = obPos[0] - obPos[2];
- vec3 fnor = normalize(cross(edges[0], -edges[2]));
-
- edgeSharpness.x = get_edge_sharpness(fnor, get_edge_normal(vNor[0], vNor[1], edges[0]));
- edgeSharpness.y = get_edge_sharpness(fnor, get_edge_normal(vNor[1], vNor[2], edges[1]));
- edgeSharpness.z = get_edge_sharpness(fnor, get_edge_normal(vNor[2], vNor[0], edges[2]));
- edgeSharpness.x = (forceEdge[0] == 1.0) ? 1.0 : edgeSharpness.x;
- edgeSharpness.y = (forceEdge[1] == 1.0) ? 1.0 : edgeSharpness.y;
- edgeSharpness.z = (forceEdge[2] == 1.0) ? 1.0 : edgeSharpness.z;
-#endif
-
#ifdef SELECT_EDGES
const float edge_select_threshold = 0.3;
- if (edgeSharpness.x > edge_select_threshold) {
- gl_Position = gl_in[0].gl_Position;
- EmitVertex();
- gl_Position = gl_in[1].gl_Position;
- EmitVertex();
+ if (edgeSharpness_g[0] > edge_select_threshold) {
+ gl_Position = gl_in[0].gl_Position; EmitVertex();
+ gl_Position = gl_in[1].gl_Position; EmitVertex();
EndPrimitive();
}
- if (edgeSharpness.y > edge_select_threshold) {
- gl_Position = gl_in[1].gl_Position;
- EmitVertex();
- gl_Position = gl_in[2].gl_Position;
- EmitVertex();
+ if (edgeSharpness_g[1] > edge_select_threshold) {
+ gl_Position = gl_in[1].gl_Position; EmitVertex();
+ gl_Position = gl_in[2].gl_Position; EmitVertex();
EndPrimitive();
}
- if (edgeSharpness.z > edge_select_threshold) {
- gl_Position = gl_in[2].gl_Position;
- EmitVertex();
- gl_Position = gl_in[0].gl_Position;
- EmitVertex();
+ if (edgeSharpness_g[2] > edge_select_threshold) {
+ gl_Position = gl_in[2].gl_Position; EmitVertex();
+ gl_Position = gl_in[0].gl_Position; EmitVertex();
EndPrimitive();
}
#else
- barycentric = get_barycentric(do_edge, 0);
+ edgeSharpness = vec3(edgeSharpness_g[0], edgeSharpness_g[1], edgeSharpness_g[2]);
+
+ barycentric = vec3(1.0, 0.0, 0.0);
gl_Position = gl_in[0].gl_Position;
- facing = facings.x;
+ facing = facing_g[0];
EmitVertex();
- barycentric = get_barycentric(do_edge, 1);
+ barycentric = vec3(0.0, 1.0, 0.0);
gl_Position = gl_in[1].gl_Position;
- facing = facings.y;
+ facing = facing_g[1];
EmitVertex();
- barycentric = get_barycentric(do_edge, 2);
+ barycentric = vec3(0.0, 0.0, 1.0);
gl_Position = gl_in[2].gl_Position;
- facing = facings.z;
+ facing = facing_g[2];
EmitVertex();
EndPrimitive();
-#endif
+#endif /* SELECT_EDGES */
}
diff --git a/source/blender/draw/modes/shaders/overlay_face_wireframe_vert.glsl b/source/blender/draw/modes/shaders/overlay_face_wireframe_vert.glsl
index 828bc551cad..d5c2bdeefea 100644
--- a/source/blender/draw/modes/shaders/overlay_face_wireframe_vert.glsl
+++ b/source/blender/draw/modes/shaders/overlay_face_wireframe_vert.glsl
@@ -1,177 +1,81 @@
uniform mat4 ModelViewProjectionMatrix;
-uniform mat4 ModelViewMatrix;
-uniform mat4 ProjectionMatrix;
uniform mat3 NormalMatrix;
uniform vec2 wireStepParam;
-uniform float nearDist;
-uniform samplerBuffer vertData;
-uniform usamplerBuffer faceIds;
-
-#ifdef USE_SCULPT
-in vec3 pos;
-in vec3 nor;
-#endif
-
-float short_to_unit_float(uint s)
+vec3 get_edge_sharpness(vec3 wd)
{
- int value = int(s) & 0x7FFF;
- if ((s & 0x8000u) != 0u) {
- value |= ~0x7FFF;
- }
- return float(value) / float(0x7FFF);
+ bvec3 do_edge = greaterThan(wd, vec3(0.0));
+ bvec3 force_edge = equal(wd, vec3(1.0));
+ wd = clamp(wireStepParam.x * wd + wireStepParam.y, 0.0, 1.0);
+ return clamp(wd * vec3(do_edge) + vec3(force_edge), 0.0, 1.0);
}
-vec3 get_vertex_nor(uint id)
+float get_edge_sharpness(float wd)
{
- int v_id = int(id) * 5; /* See vertex format for explanation. */
- /* Fetch compressed normal as float and unpack them. */
- vec2 data;
- data.x = texelFetch(vertData, v_id + 3).r;
- data.y = texelFetch(vertData, v_id + 4).r;
-
- uvec2 udata = floatBitsToUint(data);
-
- vec3 nor;
- nor.x = short_to_unit_float(udata.x & 0xFFFFu);
- nor.y = short_to_unit_float(udata.x >> 16u);
- nor.z = short_to_unit_float(udata.y & 0xFFFFu);
- return nor;
+ bool do_edge = (wd > 0.0);
+ bool force_edge = (wd == 1.0);
+ wd = (wireStepParam.x * wd + wireStepParam.y);
+ return clamp(wd * float(do_edge) + float(force_edge), 0.0, 1.0);
}
-vec3 get_vertex_pos(uint id)
-{
- int v_id = int(id) * 5; /* See vertex format for explanation. */
- vec3 pos;
- pos.x = texelFetch(vertData, v_id).r;
- pos.y = texelFetch(vertData, v_id + 1).r;
- pos.z = texelFetch(vertData, v_id + 2).r;
- return pos;
-}
+/* Geometry shader version */
+#if defined(SELECT_EDGES) || defined(USE_SCULPT)
-vec3 get_edge_normal(vec3 n1, vec3 n2, vec3 edge)
-{
- edge = normalize(edge);
- vec3 n = n1 + n2;
- float p = dot(edge, n);
- return normalize(n - p * edge);
-}
-
-float get_edge_sharpness(vec3 fnor, vec3 vnor)
-{
- float sharpness = abs(dot(fnor, vnor));
- return smoothstep(wireStepParam.x, wireStepParam.y, sharpness);
-}
-
-#ifdef USE_GEOM_SHADER
+in vec3 pos;
+in vec3 nor;
+in float wd; /* wiredata */
-# ifdef LIGHT_EDGES
-out vec3 obPos;
-out vec3 vNor;
-out float forceEdge;
-# endif
-out float facingOut; /* abs(facing) > 1.0 if we do edge */
+out float facing_g;
+out float edgeSharpness_g;
void main()
{
# ifndef USE_SCULPT
- uint v_id = texelFetch(faceIds, gl_VertexID).r;
-
- bool do_edge = (v_id & (1u << 30u)) != 0u;
- bool force_edge = (v_id & (1u << 31u)) != 0u;
- v_id = (v_id << 2u) >> 2u;
-
- vec3 pos = get_vertex_pos(v_id);
- vec3 nor = get_vertex_nor(v_id);
+ edgeSharpness_g = get_edge_sharpness(wd);
# else
- const bool do_edge = true;
- const bool force_edge = false;
+ /* TODO approximation using normals. */
+ edgeSharpness_g = 1.0;
# endif
- facingOut = normalize(NormalMatrix * nor).z;
- facingOut += (do_edge) ? ((facingOut > 0.0) ? 2.0 : -2.0) : 0.0;
-
gl_Position = ModelViewProjectionMatrix * vec4(pos, 1.0);
-# ifdef LIGHT_EDGES
- obPos = pos;
- vNor = nor;
- forceEdge = float(force_edge); /* meh, could try to also encode it in facingOut */
-# endif
+ facing_g = normalize(NormalMatrix * nor).z;
}
-#else /* USE_GEOM_SHADER */
+#else /* SELECT_EDGES */
+
+/* Consecutive pos of the nth vertex
+ * Only valid for first vertex in the triangle.
+ * Assuming GL_FRIST_VERTEX_CONVENTION. */
+in vec3 pos0;
+in vec3 pos1;
+in vec3 pos2;
+in float wd0; /* wiredata */
+in float wd1;
+in float wd2;
+in vec3 nor;
-# ifdef LIGHT_EDGES
-flat out vec3 edgeSharpness;
-# endif
out float facing;
out vec3 barycentric;
+flat out vec3 edgeSharpness;
void main()
{
- int v_0 = (gl_VertexID / 3) * 3;
int v_n = gl_VertexID % 3;
- int v_n1 = (gl_VertexID + 1) % 3;
- int v_n2 = (gl_VertexID + 2) % 3;
-
- /* Getting the same positions for each of the 3 verts. */
- uvec3 v_id;
- v_id.x = texelFetch(faceIds, v_0).r;
- v_id.y = texelFetch(faceIds, v_0 + 1).r;
- v_id.z = texelFetch(faceIds, v_0 + 2).r;
-
- bvec3 do_edge, force_edge;
- do_edge.x = (v_id.x & (1u << 30u)) != 0u;
- do_edge.y = (v_id.y & (1u << 30u)) != 0u;
- do_edge.z = (v_id.z & (1u << 30u)) != 0u;
- force_edge.x = (v_id.x & (1u << 31u)) != 0u;
- force_edge.y = (v_id.y & (1u << 31u)) != 0u;
- force_edge.z = (v_id.z & (1u << 31u)) != 0u;
- v_id = (v_id << 2u) >> 2u;
-
- vec3 pos[3];
- vec4 p_pos[3];
-
- pos[v_n] = get_vertex_pos(v_id[v_n]);
- gl_Position = p_pos[v_n] = ModelViewProjectionMatrix * vec4(pos[v_n], 1.0);
-
- bvec3 bary = equal(ivec3(0, 1, 2), ivec3(v_n1));
- /* This is equivalent to component wise : (do_edge ? bary : 1.0) */
- barycentric = vec3(lessThanEqual(ivec3(do_edge), ivec3(bary)));
-
-# ifndef LIGHT_EDGES
- vec3 nor = get_vertex_nor(v_id[v_n]);
-# else
- p_pos[v_n1] = ModelViewProjectionMatrix * vec4(pos[v_n1], 1.0);
- p_pos[v_n2] = ModelViewProjectionMatrix * vec4(pos[v_n2], 1.0);
-
- pos[v_n1] = get_vertex_pos(v_id[v_n1]);
- pos[v_n2] = get_vertex_pos(v_id[v_n2]);
-
- vec3 edges[3];
- edges[0] = pos[1] - pos[0];
- edges[1] = pos[2] - pos[1];
- edges[2] = pos[0] - pos[2];
- vec3 fnor = normalize(cross(edges[0], -edges[2]));
-
- vec3 nors[3];
- nors[0] = get_vertex_nor(v_id.x);
- nors[1] = get_vertex_nor(v_id.y);
- nors[2] = get_vertex_nor(v_id.z);
- edgeSharpness.x = get_edge_sharpness(fnor, get_edge_normal(nors[0], nors[1], edges[0]));
- edgeSharpness.y = get_edge_sharpness(fnor, get_edge_normal(nors[1], nors[2], edges[1]));
- edgeSharpness.z = get_edge_sharpness(fnor, get_edge_normal(nors[2], nors[0], edges[2]));
- edgeSharpness.x = force_edge.x ? 1.0 : edgeSharpness.x;
- edgeSharpness.y = force_edge.y ? 1.0 : edgeSharpness.y;
- edgeSharpness.z = force_edge.z ? 1.0 : edgeSharpness.z;
-
- vec3 nor = nors[v_n];
-# endif
+
+ barycentric = vec3(equal(ivec3(2, 0, 1), ivec3(v_n)));
+
+ vec3 wb = vec3(wd0, wd1, wd2);
+ edgeSharpness = get_edge_sharpness(wb);
+
+ /* Don't generate any fragment if there is no edge to draw. */
+ vec3 pos = (!any(greaterThan(edgeSharpness, vec3(0.04))) && (v_n == 0)) ? pos1 : pos0;
+
+ gl_Position = ModelViewProjectionMatrix * vec4(pos, 1.0);
facing = normalize(NormalMatrix * nor).z;
}
-#endif /* USE_GEOM_SHADER */
+#endif /* SELECT_EDGES */
diff --git a/source/blender/draw/modes/shaders/paint_face_vert.glsl b/source/blender/draw/modes/shaders/paint_face_vert.glsl
new file mode 100644
index 00000000000..437eeb28118
--- /dev/null
+++ b/source/blender/draw/modes/shaders/paint_face_vert.glsl
@@ -0,0 +1,14 @@
+
+uniform mat4 ModelViewProjectionMatrix;
+
+in vec3 pos;
+in vec4 nor; /* select flag on the 4th component */
+
+void main()
+{
+ gl_Position = ModelViewProjectionMatrix * vec4(pos, 1.0);
+ /* Don't draw faces that are selected. */
+ if (nor.w > 0.0) {
+ gl_Position = vec4(0.0, 0.0, 0.0, 1.0);
+ }
+}
diff --git a/source/blender/draw/modes/shaders/paint_texture_vert.glsl b/source/blender/draw/modes/shaders/paint_texture_vert.glsl
index 4ce12e048fa..8eae494cc35 100644
--- a/source/blender/draw/modes/shaders/paint_texture_vert.glsl
+++ b/source/blender/draw/modes/shaders/paint_texture_vert.glsl
@@ -1,7 +1,7 @@
uniform mat4 ModelViewProjectionMatrix;
-in vec2 uv;
+in vec2 u; /* active uv map */
in vec3 pos;
out vec2 uv_interp;
@@ -10,6 +10,5 @@ void main()
{
gl_Position = ModelViewProjectionMatrix * vec4(pos, 1.0);
- uv_interp = uv;
-
+ uv_interp = u;
}
diff --git a/source/blender/draw/modes/shaders/paint_vert_frag.glsl b/source/blender/draw/modes/shaders/paint_vert_frag.glsl
index 5ea8c11ff9a..d7f604d5c2c 100644
--- a/source/blender/draw/modes/shaders/paint_vert_frag.glsl
+++ b/source/blender/draw/modes/shaders/paint_vert_frag.glsl
@@ -1,5 +1,5 @@
-flat in int finalFlag;
+flat in vec4 finalColor;
out vec4 fragColor;
#define VERTEX_SELECTED (1 << 0)
@@ -7,10 +7,6 @@ out vec4 fragColor;
void main()
{
- if (bool(finalFlag & VERTEX_HIDE)) {
- discard;
- }
-
vec2 centered = gl_PointCoord - vec2(0.5);
float dist_squared = dot(centered, centered);
const float rad_squared = 0.25;
@@ -22,5 +18,5 @@ void main()
discard;
}
- fragColor = bool(finalFlag & VERTEX_SELECTED) ? colSel : colUnsel;
+ fragColor = finalColor;
}
diff --git a/source/blender/draw/modes/shaders/paint_vertex_vert.glsl b/source/blender/draw/modes/shaders/paint_vertex_vert.glsl
index 178f77c6b9c..e52c17e52d5 100644
--- a/source/blender/draw/modes/shaders/paint_vertex_vert.glsl
+++ b/source/blender/draw/modes/shaders/paint_vertex_vert.glsl
@@ -2,7 +2,7 @@
uniform mat4 ModelViewProjectionMatrix;
in vec3 pos;
-in vec3 color;
+in vec3 c; /* active color */
out vec3 finalColor;
@@ -17,5 +17,5 @@ void main()
{
gl_Position = ModelViewProjectionMatrix * vec4(pos, 1.0);
- finalColor = srgb_to_linear_attrib(color);
+ finalColor = srgb_to_linear_attrib(c);
}
diff --git a/source/blender/draw/modes/shaders/paint_wire_frag.glsl b/source/blender/draw/modes/shaders/paint_wire_frag.glsl
index b6637fea308..d738ed5ddb2 100644
--- a/source/blender/draw/modes/shaders/paint_wire_frag.glsl
+++ b/source/blender/draw/modes/shaders/paint_wire_frag.glsl
@@ -1,22 +1,8 @@
-flat in int finalFlag;
+flat in vec4 finalColor;
out vec4 fragColor;
-#define VERTEX_SELECTED (1 << 0)
-#define VERTEX_HIDE (1 << 4)
-
void main()
{
- if (bool(finalFlag & VERTEX_HIDE)) {
- discard;
- }
-
-#ifdef VERTEX_MODE
- vec4 colSel = colorEdgeSelect;
- colSel.rgb = clamp(colSel.rgb - 0.2, 0.0, 1.0);
-#else
- const vec4 colSel = vec4(1.0, 1.0, 1.0, 1.0);
-#endif
-
- fragColor = bool(finalFlag & VERTEX_SELECTED) ? colSel : colorWire;
+ fragColor = finalColor;
}
diff --git a/source/blender/draw/modes/shaders/paint_wire_vert.glsl b/source/blender/draw/modes/shaders/paint_wire_vert.glsl
index 6a800e56d94..a92591b957d 100644
--- a/source/blender/draw/modes/shaders/paint_wire_vert.glsl
+++ b/source/blender/draw/modes/shaders/paint_wire_vert.glsl
@@ -2,16 +2,30 @@
uniform mat4 ModelViewProjectionMatrix;
in vec3 pos;
-in int data;
+in vec4 nor; /* flag stored in w */
-flat out int finalFlag;
+flat out vec4 finalColor;
void main()
{
+ bool is_select = (nor.w > 0.0);
+ bool is_hidden = (nor.w < 0.0);
gl_Position = ModelViewProjectionMatrix * vec4(pos, 1.0);
+ /* Add offset in Z to avoid zfighting and render selected wires on top. */
+ /* TODO scale this bias using znear and zfar range. */
+ gl_Position.zw -= exp2(-20) * (is_select ? 2.0 : 1.0);
- /* Temp hack for william to start using blender 2.8 for icons. Will be removed by T54910 */
- gl_Position.z -= 0.0001;
+ if (is_hidden) {
+ gl_Position = vec4(-2.0, -2.0, -2.0, 1.0);
+ }
- finalFlag = data;
+#ifdef VERTEX_MODE
+ vec4 colSel = colorEdgeSelect;
+ colSel.rgb = clamp(colSel.rgb - 0.2, 0.0, 1.0);
+#else
+ const vec4 colSel = vec4(1.0, 1.0, 1.0, 1.0);
+#endif
+
+ finalColor = (is_select) ? colSel : colorWire;
+ finalColor.a = nor.w;
}
diff --git a/source/blender/draw/modes/shaders/particle_strand_frag.glsl b/source/blender/draw/modes/shaders/particle_strand_frag.glsl
index 7053ca43ae7..8bb213dbd30 100644
--- a/source/blender/draw/modes/shaders/particle_strand_frag.glsl
+++ b/source/blender/draw/modes/shaders/particle_strand_frag.glsl
@@ -1,12 +1,23 @@
-uniform mat4 ProjectionMatrix;
+uniform mat4 ModelViewProjectionMatrix;
+
+in vec4 finalColor;
+#ifdef USE_POINTS
+in vec2 radii;
+#endif
-in vec3 tangent;
-in vec3 viewPosition;
-flat in float colRand;
out vec4 fragColor;
void main()
{
- fragColor.rgb = tangent;
- fragColor.a = 1.0;
+ fragColor = finalColor;
+
+#ifdef USE_POINTS
+ float dist = length(gl_PointCoord - vec2(0.5));
+
+ fragColor.a = mix(finalColor.a, 0.0, smoothstep(radii[1], radii[0], dist));
+
+ if (fragColor.a == 0.0) {
+ discard;
+ }
+#endif
}
diff --git a/source/blender/draw/modes/shaders/particle_strand_vert.glsl b/source/blender/draw/modes/shaders/particle_strand_vert.glsl
index d4c35d14182..9db62a581cb 100644
--- a/source/blender/draw/modes/shaders/particle_strand_vert.glsl
+++ b/source/blender/draw/modes/shaders/particle_strand_vert.glsl
@@ -1,34 +1,73 @@
uniform mat4 ModelViewProjectionMatrix;
-uniform mat3 NormalMatrix;
-uniform mat4 ModelViewMatrix;
in vec3 pos;
-in vec3 nor;
-in int ind;
-out vec3 tangent;
-out vec3 viewPosition;
-flat out float colRand;
+in float color;
-float rand(int s)
+out vec4 finalColor;
+#ifdef USE_POINTS
+out vec2 radii;
+#endif
+
+vec3 weight_to_rgb(float weight)
{
- int seed = s * 1023423;
+ vec3 r_rgb;
+ float blend = ((weight / 2.0) + 0.5);
- seed = (seed ^ 61) ^ (seed >> 16);
- seed *= 9;
- seed = seed ^ (seed >> 4);
- seed *= 0x27d4eb2d;
- seed = seed ^ (seed >> 15);
+ if (weight <= 0.25) { /* blue->cyan */
+ r_rgb[0] = 0.0;
+ r_rgb[1] = blend * weight * 4.0;
+ r_rgb[2] = blend;
+ }
+ else if (weight <= 0.50) { /* cyan->green */
+ r_rgb[0] = 0.0;
+ r_rgb[1] = blend;
+ r_rgb[2] = blend * (1.0 - ((weight - 0.25) * 4.0));
+ }
+ else if (weight <= 0.75) { /* green->yellow */
+ r_rgb[0] = blend * ((weight - 0.50) * 4.0);
+ r_rgb[1] = blend;
+ r_rgb[2] = 0.0;
+ }
+ else if (weight <= 1.0) { /* yellow->red */
+ r_rgb[0] = blend;
+ r_rgb[1] = blend * (1.0 - ((weight - 0.75) * 4.0));
+ r_rgb[2] = 0.0;
+ }
+ else {
+ /* exceptional value, unclamped or nan,
+ * avoid uninitialized memory use */
+ r_rgb[0] = 1.0;
+ r_rgb[1] = 0.0;
+ r_rgb[2] = 1.0;
+ }
- float value = float(seed);
- value *= 1.0 / 42596.0;
- return fract(value);
+ return r_rgb;
}
+#define DECOMPRESS_RANGE 1.0039
+
void main()
{
gl_Position = ModelViewProjectionMatrix * vec4(pos, 1.0);
- tangent = normalize(NormalMatrix * nor);
- viewPosition = (ModelViewMatrix * vec4(pos, 1.0)).xyz;
- colRand = rand(ind);
+
+#ifdef USE_WEIGHT
+ finalColor = vec4(weight_to_rgb(color * DECOMPRESS_RANGE), 1.0);
+#else
+ finalColor = mix(colorWire, colorEdgeSelect, color);
+#endif
+
+#ifdef USE_POINTS
+ gl_PointSize = sizeVertex;
+
+ /* calculate concentric radii in pixels */
+ float radius = 0.5 * sizeVertex;
+
+ /* start at the outside and progress toward the center */
+ radii[0] = radius;
+ radii[1] = radius - 1.0;
+
+ /* convert to PointCoord units */
+ radii /= sizeVertex;
+#endif
}