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

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'source/blender/draw/engines/overlay')
-rw-r--r--source/blender/draw/engines/overlay/overlay_antialiasing.c2
-rw-r--r--source/blender/draw/engines/overlay/overlay_armature.c2
-rw-r--r--source/blender/draw/engines/overlay/overlay_engine.c16
-rw-r--r--source/blender/draw/engines/overlay/overlay_extra.c14
-rw-r--r--source/blender/draw/engines/overlay/overlay_outline.c15
-rw-r--r--source/blender/draw/engines/overlay/overlay_private.h9
-rw-r--r--source/blender/draw/engines/overlay/overlay_sculpt_curves.cc96
-rw-r--r--source/blender/draw/engines/overlay/overlay_shader.c26
-rw-r--r--source/blender/draw/engines/overlay/shaders/infos/overlay_outline_info.hh10
-rw-r--r--source/blender/draw/engines/overlay/shaders/infos/overlay_sculpt_curves_info.hh21
-rw-r--r--source/blender/draw/engines/overlay/shaders/overlay_outline_prepass_curves_vert.glsl81
-rw-r--r--source/blender/draw/engines/overlay/shaders/overlay_sculpt_curves_selection_frag.glsl5
-rw-r--r--source/blender/draw/engines/overlay/shaders/overlay_sculpt_curves_selection_vert.glsl34
13 files changed, 323 insertions, 8 deletions
diff --git a/source/blender/draw/engines/overlay/overlay_antialiasing.c b/source/blender/draw/engines/overlay/overlay_antialiasing.c
index 27ee479cf36..780915b7fc4 100644
--- a/source/blender/draw/engines/overlay/overlay_antialiasing.c
+++ b/source/blender/draw/engines/overlay/overlay_antialiasing.c
@@ -52,7 +52,7 @@ void OVERLAY_antialiasing_init(OVERLAY_Data *vedata)
OVERLAY_PrivateData *pd = vedata->stl->pd;
DefaultTextureList *dtxl = DRW_viewport_texture_list_get();
- /* Small texture which will have very small impact on rendertime. */
+ /* Small texture which will have very small impact on render-time. */
if (txl->dummy_depth_tx == NULL) {
const float pixel[1] = {1.0f};
txl->dummy_depth_tx = DRW_texture_create_2d(1, 1, GPU_DEPTH_COMPONENT24, 0, pixel);
diff --git a/source/blender/draw/engines/overlay/overlay_armature.c b/source/blender/draw/engines/overlay/overlay_armature.c
index ea0c2f287a6..e38695c76ab 100644
--- a/source/blender/draw/engines/overlay/overlay_armature.c
+++ b/source/blender/draw/engines/overlay/overlay_armature.c
@@ -2102,7 +2102,7 @@ static void pchan_culling_calc_bsphere(const Object *ob,
{
float min[3], max[3];
INIT_MINMAX(min, max);
- BKE_pchan_minmax(ob, pchan, min, max);
+ BKE_pchan_minmax(ob, pchan, true, min, max);
mid_v3_v3v3(r_bsphere->center, min, max);
r_bsphere->radius = len_v3v3(min, r_bsphere->center);
}
diff --git a/source/blender/draw/engines/overlay/overlay_engine.c b/source/blender/draw/engines/overlay/overlay_engine.c
index f8c28394b16..5edd68bffff 100644
--- a/source/blender/draw/engines/overlay/overlay_engine.c
+++ b/source/blender/draw/engines/overlay/overlay_engine.c
@@ -192,6 +192,8 @@ static void OVERLAY_cache_init(void *vedata)
OVERLAY_edit_curves_cache_init(vedata);
break;
case CTX_MODE_SCULPT_CURVES:
+ OVERLAY_sculpt_curves_cache_init(vedata);
+ break;
case CTX_MODE_OBJECT:
break;
default:
@@ -308,8 +310,12 @@ static void OVERLAY_cache_populate(void *vedata, Object *ob)
(pd->ctx_mode == CTX_MODE_PARTICLE);
const bool in_paint_mode = (ob == draw_ctx->obact) &&
(draw_ctx->object_mode & OB_MODE_ALL_PAINT);
+ const bool in_sculpt_curve_mode = (ob == draw_ctx->obact) &&
+ (draw_ctx->object_mode & OB_MODE_SCULPT_CURVES);
const bool in_sculpt_mode = (ob == draw_ctx->obact) && (ob->sculpt != NULL) &&
(ob->sculpt->mode_type == OB_MODE_SCULPT);
+ const bool in_curves_sculpt_mode = (ob == draw_ctx->obact) &&
+ (ob->mode == OB_MODE_SCULPT_CURVES);
const bool has_surface = ELEM(ob->type,
OB_MESH,
OB_CURVES_LEGACY,
@@ -329,8 +335,8 @@ static void OVERLAY_cache_populate(void *vedata, Object *ob)
const bool draw_bones = (pd->overlay.flag & V3D_OVERLAY_HIDE_BONES) == 0;
const bool draw_wires = draw_surface && has_surface &&
(pd->wireframe_mode || !pd->hide_overlays);
- const bool draw_outlines = !in_edit_mode && !in_paint_mode && renderable && has_surface &&
- !instance_parent_in_edit_mode &&
+ const bool draw_outlines = !in_edit_mode && !in_paint_mode && !in_sculpt_curve_mode &&
+ renderable && has_surface && !instance_parent_in_edit_mode &&
(pd->v3d_flag & V3D_SELECT_OUTLINE) &&
(ob->base_flag & BASE_SELECTED);
const bool draw_bone_selection = (ob->type == OB_MESH) && pd->armature.do_pose_fade_geom &&
@@ -428,6 +434,9 @@ static void OVERLAY_cache_populate(void *vedata, Object *ob)
if (in_sculpt_mode) {
OVERLAY_sculpt_cache_populate(vedata, ob);
}
+ else if (in_curves_sculpt_mode) {
+ OVERLAY_sculpt_curves_cache_populate(vedata, ob);
+ }
if (draw_motion_paths) {
OVERLAY_motion_path_cache_populate(vedata, ob);
@@ -591,6 +600,9 @@ static void OVERLAY_draw_scene(void *vedata)
case CTX_MODE_SCULPT:
OVERLAY_sculpt_draw(vedata);
break;
+ case CTX_MODE_SCULPT_CURVES:
+ OVERLAY_sculpt_curves_draw(vedata);
+ break;
case CTX_MODE_EDIT_MESH:
case CTX_MODE_POSE:
case CTX_MODE_PAINT_WEIGHT:
diff --git a/source/blender/draw/engines/overlay/overlay_extra.c b/source/blender/draw/engines/overlay/overlay_extra.c
index f875254a685..4354777986c 100644
--- a/source/blender/draw/engines/overlay/overlay_extra.c
+++ b/source/blender/draw/engines/overlay/overlay_extra.c
@@ -1315,9 +1315,14 @@ static void OVERLAY_relationship_lines(OVERLAY_ExtraCallBuffers *cb,
if ((curcon->ui_expand_flag & (1 << 0)) && BKE_constraint_targets_get(curcon, &targets)) {
bConstraintTarget *ct;
+ BKE_constraint_custom_object_space_init(cob, curcon);
+
for (ct = targets.first; ct; ct = ct->next) {
/* calculate target's matrix */
- if (cti->get_target_matrix) {
+ if (ct->flag & CONSTRAINT_TAR_CUSTOM_SPACE) {
+ copy_m4_m4(ct->matrix, cob->space_obj_world_matrix);
+ }
+ else if (cti->get_target_matrix) {
cti->get_target_matrix(depsgraph, curcon, cob, ct, DEG_get_ctime(depsgraph));
}
else {
@@ -1353,7 +1358,7 @@ static void OVERLAY_volume_extra(OVERLAY_ExtraCallBuffers *cb,
/* Don't show smoke before simulation starts, this could be made an option in the future. */
const bool draw_velocity = (fds->draw_velocity && fds->fluid &&
- CFRA >= fds->point_cache[0]->startframe);
+ scene->r.cfra >= fds->point_cache[0]->startframe);
/* Show gridlines only for slices with no interpolation. */
const bool show_gridlines = (fds->show_gridlines && fds->fluid &&
@@ -1546,8 +1551,9 @@ void OVERLAY_extra_cache_populate(OVERLAY_Data *vedata, Object *ob)
(md = BKE_modifiers_findby_type(ob, eModifierType_Fluid)) &&
(BKE_modifier_is_enabled(scene, md, eModifierMode_Realtime)) &&
(((FluidModifierData *)md)->domain != NULL) &&
- (CFRA >= (((FluidModifierData *)md)->domain->cache_frame_start)) &&
- (CFRA <= (((FluidModifierData *)md)->domain->cache_frame_end));
+ (scene->r.cfra >=
+ (((FluidModifierData *)md)->domain->cache_frame_start)) &&
+ (scene->r.cfra <= (((FluidModifierData *)md)->domain->cache_frame_end));
float *color;
int theme_id = DRW_object_wire_theme_get(ob, view_layer, &color);
diff --git a/source/blender/draw/engines/overlay/overlay_outline.c b/source/blender/draw/engines/overlay/overlay_outline.c
index eea9a1a1bef..f2e2acc98a9 100644
--- a/source/blender/draw/engines/overlay/overlay_outline.c
+++ b/source/blender/draw/engines/overlay/overlay_outline.c
@@ -133,6 +133,10 @@ void OVERLAY_outline_cache_init(OVERLAY_Data *vedata)
pd->outlines_gpencil_grp = grp = DRW_shgroup_create(sh_gpencil, psl->outlines_prepass_ps);
DRW_shgroup_uniform_bool_copy(grp, "isTransform", (G.moving & G_TRANSFORM_OBJ) != 0);
DRW_shgroup_uniform_float_copy(grp, "gpStrokeIndexOffset", 0.0);
+
+ GPUShader *sh_curves = OVERLAY_shader_outline_prepass_curves();
+ pd->outlines_curves_grp = grp = DRW_shgroup_create(sh_curves, psl->outlines_prepass_ps);
+ DRW_shgroup_uniform_bool_copy(grp, "isTransform", (G.moving & G_TRANSFORM_OBJ) != 0);
}
/* outlines_prepass_ps is still needed for selection of probes. */
@@ -267,6 +271,12 @@ static void OVERLAY_outline_volume(OVERLAY_PrivateData *pd, Object *ob)
DRW_shgroup_call(shgroup, geom, ob);
}
+static void OVERLAY_outline_curves(OVERLAY_PrivateData *pd, Object *ob)
+{
+ DRWShadingGroup *shgroup = pd->outlines_curves_grp;
+ DRW_shgroup_curves_create_sub(ob, shgroup, NULL);
+}
+
void OVERLAY_outline_cache_populate(OVERLAY_Data *vedata,
Object *ob,
OVERLAY_DupliData *dupli,
@@ -293,6 +303,11 @@ void OVERLAY_outline_cache_populate(OVERLAY_Data *vedata,
return;
}
+ if (ob->type == OB_CURVES) {
+ OVERLAY_outline_curves(pd, ob);
+ return;
+ }
+
if (ob->type == OB_POINTCLOUD && pd->wireframe_mode) {
/* Looks bad in this case. Could be relaxed if we draw a
* wireframe of some sort in the future. */
diff --git a/source/blender/draw/engines/overlay/overlay_private.h b/source/blender/draw/engines/overlay/overlay_private.h
index 23c20a186a0..7d216ca54cf 100644
--- a/source/blender/draw/engines/overlay/overlay_private.h
+++ b/source/blender/draw/engines/overlay/overlay_private.h
@@ -116,6 +116,7 @@ typedef struct OVERLAY_PassList {
DRWPass *particle_ps;
DRWPass *pointcloud_ps;
DRWPass *sculpt_mask_ps;
+ DRWPass *sculpt_curves_selection_ps;
DRWPass *volume_ps;
DRWPass *wireframe_ps;
DRWPass *wireframe_xray_ps;
@@ -267,6 +268,7 @@ typedef struct OVERLAY_PrivateData {
DRWShadingGroup *motion_path_lines_grp;
DRWShadingGroup *motion_path_points_grp;
DRWShadingGroup *outlines_grp;
+ DRWShadingGroup *outlines_curves_grp;
DRWShadingGroup *outlines_ptcloud_grp;
DRWShadingGroup *outlines_gpencil_grp;
DRWShadingGroup *paint_depth_grp;
@@ -279,6 +281,7 @@ typedef struct OVERLAY_PrivateData {
DRWShadingGroup *particle_shapes_grp;
DRWShadingGroup *pointcloud_dots_grp;
DRWShadingGroup *sculpt_mask_grp;
+ DRWShadingGroup *sculpt_curves_selection_grp;
DRWShadingGroup *volume_selection_surface_grp;
DRWShadingGroup *wires_grp[2][2]; /* With and without coloring. */
DRWShadingGroup *wires_all_grp[2][2]; /* With and without coloring. */
@@ -669,6 +672,10 @@ void OVERLAY_sculpt_cache_init(OVERLAY_Data *vedata);
void OVERLAY_sculpt_cache_populate(OVERLAY_Data *vedata, Object *ob);
void OVERLAY_sculpt_draw(OVERLAY_Data *vedata);
+void OVERLAY_sculpt_curves_cache_init(OVERLAY_Data *vedata);
+void OVERLAY_sculpt_curves_cache_populate(OVERLAY_Data *vedata, Object *ob);
+void OVERLAY_sculpt_curves_draw(OVERLAY_Data *vedata);
+
void OVERLAY_wireframe_init(OVERLAY_Data *vedata);
void OVERLAY_wireframe_cache_init(OVERLAY_Data *vedata);
void OVERLAY_wireframe_cache_populate(OVERLAY_Data *vedata,
@@ -737,6 +744,7 @@ GPUShader *OVERLAY_shader_motion_path_line(void);
GPUShader *OVERLAY_shader_motion_path_vert(void);
GPUShader *OVERLAY_shader_uniform_color(void);
GPUShader *OVERLAY_shader_outline_prepass(bool use_wire);
+GPUShader *OVERLAY_shader_outline_prepass_curves(void);
GPUShader *OVERLAY_shader_outline_prepass_gpencil(void);
GPUShader *OVERLAY_shader_outline_prepass_pointcloud(void);
GPUShader *OVERLAY_shader_extra_grid(void);
@@ -750,6 +758,7 @@ GPUShader *OVERLAY_shader_paint_wire(void);
GPUShader *OVERLAY_shader_particle_dot(void);
GPUShader *OVERLAY_shader_particle_shape(void);
GPUShader *OVERLAY_shader_sculpt_mask(void);
+GPUShader *OVERLAY_shader_sculpt_curves_selection(void);
GPUShader *OVERLAY_shader_volume_velocity(bool use_needle, bool use_mac);
GPUShader *OVERLAY_shader_volume_gridlines(bool color_with_flags, bool color_range);
GPUShader *OVERLAY_shader_wireframe(bool custom_bias);
diff --git a/source/blender/draw/engines/overlay/overlay_sculpt_curves.cc b/source/blender/draw/engines/overlay/overlay_sculpt_curves.cc
new file mode 100644
index 00000000000..b8021124f27
--- /dev/null
+++ b/source/blender/draw/engines/overlay/overlay_sculpt_curves.cc
@@ -0,0 +1,96 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later
+ * Copyright 2022 Blender Foundation. */
+
+/** \file
+ * \ingroup draw_engine
+ */
+
+#include "DRW_render.h"
+
+#include "draw_cache_impl.h"
+#include "overlay_private.h"
+
+#include "BKE_curves.hh"
+
+void OVERLAY_sculpt_curves_cache_init(OVERLAY_Data *vedata)
+{
+ OVERLAY_PassList *psl = vedata->psl;
+ OVERLAY_PrivateData *pd = vedata->stl->pd;
+
+ const DRWState state = DRW_STATE_WRITE_COLOR | DRW_STATE_DEPTH_EQUAL | DRW_STATE_BLEND_ALPHA;
+ DRW_PASS_CREATE(psl->sculpt_curves_selection_ps, state | pd->clipping_state);
+
+ GPUShader *sh = OVERLAY_shader_sculpt_curves_selection();
+ pd->sculpt_curves_selection_grp = DRW_shgroup_create(sh, psl->sculpt_curves_selection_ps);
+ DRWShadingGroup *grp = pd->sculpt_curves_selection_grp;
+
+ /* Reuse the same mask opacity from sculpt mode, since it wasn't worth it to add a different
+ * property yet. */
+ DRW_shgroup_uniform_float_copy(grp, "selection_opacity", pd->overlay.sculpt_mode_mask_opacity);
+}
+
+static bool everything_selected(const Curves &curves_id)
+{
+ if (!(curves_id.flag & CV_SCULPT_SELECTION_ENABLED)) {
+ /* When the selection is disabled, conceptually everything is selected. */
+ return true;
+ }
+ const blender::bke::CurvesGeometry &curves = blender::bke::CurvesGeometry::wrap(
+ curves_id.geometry);
+ blender::VArray<float> selection;
+ switch (curves_id.selection_domain) {
+ case ATTR_DOMAIN_POINT:
+ selection = curves.selection_point_float();
+ break;
+ case ATTR_DOMAIN_CURVE:
+ selection = curves.selection_curve_float();
+ break;
+ }
+ return selection.is_single() && selection.get_internal_single() == 1.0f;
+}
+
+void OVERLAY_sculpt_curves_cache_populate(OVERLAY_Data *vedata, Object *object)
+{
+ OVERLAY_PrivateData *pd = vedata->stl->pd;
+ Curves *curves = static_cast<Curves *>(object->data);
+
+ /* As an optimization, return early if everything is selected. */
+ if (everything_selected(*curves)) {
+ return;
+ }
+
+ /* Retrieve the location of the texture. */
+ const char *name = curves->selection_domain == ATTR_DOMAIN_POINT ? ".selection_point_float" :
+ ".selection_curve_float";
+
+ bool is_point_domain;
+ GPUTexture **texture = DRW_curves_texture_for_evaluated_attribute(
+ curves, name, &is_point_domain);
+ if (texture == nullptr) {
+ return;
+ }
+
+ /* Evaluate curves and their attributes if necessary. */
+ DRWShadingGroup *grp = DRW_shgroup_curves_create_sub(
+ object, pd->sculpt_curves_selection_grp, nullptr);
+ if (*texture == nullptr) {
+ return;
+ }
+
+ DRW_shgroup_uniform_bool_copy(grp, "is_point_domain", is_point_domain);
+ DRW_shgroup_uniform_texture(grp, "selection_tx", *texture);
+}
+
+void OVERLAY_sculpt_curves_draw(OVERLAY_Data *vedata)
+{
+ OVERLAY_PassList *psl = vedata->psl;
+ OVERLAY_PrivateData *pd = vedata->stl->pd;
+ OVERLAY_FramebufferList *fbl = vedata->fbl;
+
+ if (DRW_state_is_fbo()) {
+ GPU_framebuffer_bind(pd->painting.in_front ? fbl->overlay_in_front_fb :
+ fbl->overlay_default_fb);
+ }
+
+ DRW_draw_pass(psl->sculpt_curves_selection_ps);
+}
diff --git a/source/blender/draw/engines/overlay/overlay_shader.c b/source/blender/draw/engines/overlay/overlay_shader.c
index 48146fbddfb..2373363ab9d 100644
--- a/source/blender/draw/engines/overlay/overlay_shader.c
+++ b/source/blender/draw/engines/overlay/overlay_shader.c
@@ -76,6 +76,7 @@ typedef struct OVERLAY_Shaders {
GPUShader *motion_path_line;
GPUShader *motion_path_vert;
GPUShader *outline_prepass;
+ GPUShader *outline_prepass_curves;
GPUShader *outline_prepass_gpencil;
GPUShader *outline_prepass_pointcloud;
GPUShader *outline_prepass_wire;
@@ -90,6 +91,7 @@ typedef struct OVERLAY_Shaders {
GPUShader *particle_shape;
GPUShader *pointcloud_dot;
GPUShader *sculpt_mask;
+ GPUShader *sculpt_curves_selection;
GPUShader *uniform_color;
GPUShader *volume_velocity_needle_sh;
GPUShader *volume_velocity_mac_sh;
@@ -650,6 +652,18 @@ GPUShader *OVERLAY_shader_outline_prepass(bool use_wire)
return use_wire ? sh_data->outline_prepass_wire : sh_data->outline_prepass;
}
+GPUShader *OVERLAY_shader_outline_prepass_curves()
+{
+ const DRWContextState *draw_ctx = DRW_context_state_get();
+ OVERLAY_Shaders *sh_data = &e_data.sh_data[draw_ctx->sh_cfg];
+ if (!sh_data->outline_prepass_curves) {
+ sh_data->outline_prepass_curves = GPU_shader_create_from_info_name(
+ draw_ctx->sh_cfg ? "overlay_outline_prepass_curves_clipped" :
+ "overlay_outline_prepass_curves");
+ }
+ return sh_data->outline_prepass_curves;
+}
+
GPUShader *OVERLAY_shader_outline_prepass_gpencil(void)
{
const DRWContextState *draw_ctx = DRW_context_state_get();
@@ -792,6 +806,18 @@ GPUShader *OVERLAY_shader_sculpt_mask(void)
return sh_data->sculpt_mask;
}
+GPUShader *OVERLAY_shader_sculpt_curves_selection(void)
+{
+ const DRWContextState *draw_ctx = DRW_context_state_get();
+ OVERLAY_Shaders *sh_data = &e_data.sh_data[draw_ctx->sh_cfg];
+ if (!sh_data->sculpt_curves_selection) {
+ sh_data->sculpt_curves_selection = GPU_shader_create_from_info_name(
+ draw_ctx->sh_cfg == GPU_SHADER_CFG_CLIPPED ? "overlay_sculpt_curves_selection_clipped" :
+ "overlay_sculpt_curves_selection");
+ }
+ return sh_data->sculpt_curves_selection;
+}
+
struct GPUShader *OVERLAY_shader_uniform_color(void)
{
const DRWContextState *draw_ctx = DRW_context_state_get();
diff --git a/source/blender/draw/engines/overlay/shaders/infos/overlay_outline_info.hh b/source/blender/draw/engines/overlay/shaders/infos/overlay_outline_info.hh
index 6f6a9c1622d..288fb3b3cbd 100644
--- a/source/blender/draw/engines/overlay/shaders/infos/overlay_outline_info.hh
+++ b/source/blender/draw/engines/overlay/shaders/infos/overlay_outline_info.hh
@@ -29,6 +29,16 @@ GPU_SHADER_CREATE_INFO(overlay_outline_prepass_mesh_clipped)
GPU_SHADER_INTERFACE_INFO(overlay_outline_prepass_wire_iface, "vert").flat(Type::VEC3, "pos");
+GPU_SHADER_CREATE_INFO(overlay_outline_prepass_curves)
+ .do_static_compilation(true)
+ .vertex_source("overlay_outline_prepass_curves_vert.glsl")
+ .additional_info("draw_hair", "overlay_outline_prepass")
+ .additional_info("draw_object_infos");
+
+GPU_SHADER_CREATE_INFO(overlay_outline_prepass_curves_clipped)
+ .do_static_compilation(true)
+ .additional_info("overlay_outline_prepass_curves", "drw_clipped");
+
GPU_SHADER_CREATE_INFO(overlay_outline_prepass_wire)
.do_static_compilation(true)
.define("USE_GEOM")
diff --git a/source/blender/draw/engines/overlay/shaders/infos/overlay_sculpt_curves_info.hh b/source/blender/draw/engines/overlay/shaders/infos/overlay_sculpt_curves_info.hh
new file mode 100644
index 00000000000..46e3943b293
--- /dev/null
+++ b/source/blender/draw/engines/overlay/shaders/infos/overlay_sculpt_curves_info.hh
@@ -0,0 +1,21 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+
+#include "gpu_shader_create_info.hh"
+
+GPU_SHADER_INTERFACE_INFO(overlay_sculpt_curves_selection_iface, "")
+ .smooth(Type::FLOAT, "mask_weight");
+
+GPU_SHADER_CREATE_INFO(overlay_sculpt_curves_selection)
+ .do_static_compilation(true)
+ .push_constant(Type::BOOL, "is_point_domain")
+ .push_constant(Type::FLOAT, "selection_opacity")
+ .sampler(0, ImageType::FLOAT_BUFFER, "selection_tx")
+ .vertex_out(overlay_sculpt_curves_selection_iface)
+ .vertex_source("overlay_sculpt_curves_selection_vert.glsl")
+ .fragment_source("overlay_sculpt_curves_selection_frag.glsl")
+ .fragment_out(0, Type::VEC4, "out_color")
+ .additional_info("draw_hair", "draw_globals");
+
+GPU_SHADER_CREATE_INFO(overlay_sculpt_curves_selection_clipped)
+ .do_static_compilation(true)
+ .additional_info("overlay_sculpt_curves_selection", "drw_clipped");
diff --git a/source/blender/draw/engines/overlay/shaders/overlay_outline_prepass_curves_vert.glsl b/source/blender/draw/engines/overlay/shaders/overlay_outline_prepass_curves_vert.glsl
new file mode 100644
index 00000000000..f9ec475d21f
--- /dev/null
+++ b/source/blender/draw/engines/overlay/shaders/overlay_outline_prepass_curves_vert.glsl
@@ -0,0 +1,81 @@
+
+#pragma BLENDER_REQUIRE(common_view_clipping_lib.glsl)
+#pragma BLENDER_REQUIRE(common_view_lib.glsl)
+#pragma BLENDER_REQUIRE(common_hair_lib.glsl)
+
+uint outline_colorid_get(void)
+{
+ int flag = int(abs(ObjectInfo.w));
+ bool is_active = (flag & DRW_BASE_ACTIVE) != 0;
+
+ if (isTransform) {
+ return 0u; /* colorTransform */
+ }
+ else if (is_active) {
+ return 3u; /* colorActive */
+ }
+ else {
+ return 1u; /* colorSelect */
+ }
+
+ return 0u;
+}
+
+/* Replace top 2 bits (of the 16bit output) by outlineId.
+ * This leaves 16K different IDs to create outlines between objects.
+ vec3 world_pos = point_object_to_world(pos);
+ * SHIFT = (32 - (16 - 2)) */
+#define SHIFT 18u
+
+void main()
+{
+ bool is_persp = (drw_view.winmat[3][3] == 0.0);
+ float time, thickness;
+ vec3 center_wpos, tan, binor;
+
+ hair_get_center_pos_tan_binor_time(is_persp,
+ ModelMatrixInverse,
+ drw_view.viewinv[3].xyz,
+ drw_view.viewinv[2].xyz,
+ center_wpos,
+ tan,
+ binor,
+ time,
+ thickness);
+ vec3 world_pos;
+ if (hairThicknessRes > 1) {
+ /* Calculate the thickness, thicktime, worldpos taken into account the outline. */
+ float outline_width = point_world_to_ndc(center_wpos).w * 1.25 *
+ drw_view.viewport_size_inverse.y * drw_view.wininv[1][1];
+ thickness += outline_width;
+ float thick_time = float(gl_VertexID % hairThicknessRes) / float(hairThicknessRes - 1);
+ thick_time = thickness * (thick_time * 2.0 - 1.0);
+ /* Take object scale into account.
+ * NOTE: This only works fine with uniform scaling. */
+ float scale = 1.0 / length(mat3(ModelMatrixInverse) * binor);
+ world_pos = center_wpos + binor * thick_time * scale;
+ }
+ else {
+ world_pos = center_wpos;
+ }
+
+ gl_Position = point_world_to_ndc(world_pos);
+
+#ifdef USE_GEOM
+ vert.pos = point_world_to_view(world_pos);
+#endif
+
+ /* Small bias to always be on top of the geom. */
+ gl_Position.z -= 1e-3;
+
+ /* ID 0 is nothing (background) */
+ interp.ob_id = uint(resource_handle + 1);
+
+ /* Should be 2 bits only [0..3]. */
+ uint outline_id = outline_colorid_get();
+
+ /* Combine for 16bit uint target. */
+ interp.ob_id = (outline_id << 14u) | ((interp.ob_id << SHIFT) >> SHIFT);
+
+ view_clipping_distances(world_pos);
+}
diff --git a/source/blender/draw/engines/overlay/shaders/overlay_sculpt_curves_selection_frag.glsl b/source/blender/draw/engines/overlay/shaders/overlay_sculpt_curves_selection_frag.glsl
new file mode 100644
index 00000000000..7af6bdb9fdb
--- /dev/null
+++ b/source/blender/draw/engines/overlay/shaders/overlay_sculpt_curves_selection_frag.glsl
@@ -0,0 +1,5 @@
+
+void main()
+{
+ out_color = vec4(vec3(0.0), 1.0 - mask_weight);
+}
diff --git a/source/blender/draw/engines/overlay/shaders/overlay_sculpt_curves_selection_vert.glsl b/source/blender/draw/engines/overlay/shaders/overlay_sculpt_curves_selection_vert.glsl
new file mode 100644
index 00000000000..7be3c8e6dfb
--- /dev/null
+++ b/source/blender/draw/engines/overlay/shaders/overlay_sculpt_curves_selection_vert.glsl
@@ -0,0 +1,34 @@
+#pragma BLENDER_REQUIRE(common_hair_lib.glsl)
+#pragma BLENDER_REQUIRE(common_view_clipping_lib.glsl)
+#pragma BLENDER_REQUIRE(common_view_lib.glsl)
+
+float retrieve_selection()
+{
+ if (is_point_domain) {
+ return texelFetch(selection_tx, hair_get_base_id()).r;
+ }
+ return texelFetch(selection_tx, hair_get_strand_id()).r;
+}
+
+void main()
+{
+ bool is_persp = (ProjectionMatrix[3][3] == 0.0);
+ float time, thick_time, thickness;
+ vec3 world_pos, tan, binor;
+ hair_get_pos_tan_binor_time(is_persp,
+ ModelMatrixInverse,
+ ViewMatrixInverse[3].xyz,
+ ViewMatrixInverse[2].xyz,
+ world_pos,
+ tan,
+ binor,
+ time,
+ thickness,
+ thick_time);
+
+ gl_Position = point_world_to_ndc(world_pos);
+
+ mask_weight = 1.0 - (selection_opacity - retrieve_selection() * selection_opacity);
+
+ view_clipping_distances(world_pos);
+}