diff options
Diffstat (limited to 'source/blender/draw/engines/overlay')
7 files changed, 187 insertions, 0 deletions
diff --git a/source/blender/draw/engines/overlay/overlay_engine.c b/source/blender/draw/engines/overlay/overlay_engine.c index f8c28394b16..9ec0398e5cb 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: @@ -310,6 +312,8 @@ static void OVERLAY_cache_populate(void *vedata, Object *ob) (draw_ctx->object_mode & OB_MODE_ALL_PAINT); 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, @@ -428,6 +432,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 +598,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_private.h b/source/blender/draw/engines/overlay/overlay_private.h index 23c20a186a0..667e443932c 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; @@ -279,6 +280,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 +671,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, @@ -750,6 +756,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..7b7e84c307b 100644 --- a/source/blender/draw/engines/overlay/overlay_shader.c +++ b/source/blender/draw/engines/overlay/overlay_shader.c @@ -90,6 +90,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; @@ -792,6 +793,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_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_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..9ed959b5ea1 --- /dev/null +++ b/source/blender/draw/engines/overlay/shaders/overlay_sculpt_curves_selection_vert.glsl @@ -0,0 +1,35 @@ +#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); +} |