Curves: smooth handles
Adds antialiasing to curve's handles and thickness to active ones. Also handles now react to `Preferences > Interface > Display > Resolution Scale` and `Preferences > Themes > 3D Viewport > Edge Width` as they do in legacy curves. Pull Request: https://projects.blender.org/blender/blender/pulls/122910
This commit is contained in:
committed by
Clément Foucault
parent
12ef319a49
commit
84dedfaf4b
@@ -678,8 +678,10 @@ set(GLSL_SRC
|
||||
engines/overlay/shaders/overlay_edit_curve_handle_vert.glsl
|
||||
engines/overlay/shaders/overlay_edit_curve_handle_vert_no_geom.glsl
|
||||
engines/overlay/shaders/overlay_edit_curve_point_vert.glsl
|
||||
engines/overlay/shaders/overlay_edit_curves_handle_frag.glsl
|
||||
engines/overlay/shaders/overlay_edit_curves_handle_geom.glsl
|
||||
engines/overlay/shaders/overlay_edit_curves_handle_next_vert.glsl
|
||||
engines/overlay/shaders/overlay_edit_curves_handle_vert.glsl
|
||||
engines/overlay/shaders/overlay_edit_curves_handle_vert_no_geom.glsl
|
||||
engines/overlay/shaders/overlay_edit_curve_wire_vert.glsl
|
||||
engines/overlay/shaders/overlay_edit_curve_wire_next_vert.glsl
|
||||
engines/overlay/shaders/overlay_edit_gpencil_canvas_vert.glsl
|
||||
|
||||
@@ -71,6 +71,7 @@ void OVERLAY_edit_curves_cache_init(OVERLAY_Data *vedata)
|
||||
sh = OVERLAY_shader_edit_curves_handle();
|
||||
grp = pd->edit_curves_handles_grp = DRW_shgroup_create(sh, psl->edit_curves_handles_ps);
|
||||
DRW_shgroup_uniform_block(grp, "globalsBlock", G_draw.block_ubo);
|
||||
DRW_shgroup_state_enable(grp, DRW_STATE_BLEND_ALPHA);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -86,14 +87,10 @@ static void overlay_edit_curves_add_ob_to_pass(OVERLAY_PrivateData *pd, Object *
|
||||
}
|
||||
|
||||
DRWShadingGroup *handles_shgrp = pd->edit_curves_handles_grp;
|
||||
DRW_shgroup_uniform_block(
|
||||
handles_shgrp, "curvesInfoBlock", DRW_curves_batch_cache_ubo_storage(curves));
|
||||
blender::gpu::Batch *geom_handles = DRW_curves_batch_cache_get_edit_curves_handles(curves);
|
||||
DRW_shgroup_call_no_cull(handles_shgrp, geom_handles, ob);
|
||||
|
||||
DRWShadingGroup *lines_shgrp = pd->edit_curves_lines_grp[in_front];
|
||||
DRW_shgroup_uniform_block(
|
||||
lines_shgrp, "curvesInfoBlock", DRW_curves_batch_cache_ubo_storage(curves));
|
||||
blender::gpu::Batch *geom_lines = DRW_curves_batch_cache_get_edit_curves_lines(curves);
|
||||
DRW_shgroup_call_no_cull(lines_shgrp, geom_lines, ob);
|
||||
}
|
||||
|
||||
@@ -55,18 +55,6 @@ class Curves {
|
||||
{
|
||||
auto &pass = edit_curves_ps_;
|
||||
pass.init();
|
||||
{
|
||||
auto &sub = pass.sub("Points");
|
||||
sub.state_set(DRW_STATE_WRITE_COLOR | DRW_STATE_DEPTH_LESS_EQUAL | DRW_STATE_BLEND_ALPHA |
|
||||
DRW_STATE_WRITE_DEPTH,
|
||||
state.clipping_plane_count);
|
||||
sub.shader_set(res.shaders.curve_edit_points.get());
|
||||
sub.bind_ubo("globalsBlock", &res.globals_buf);
|
||||
sub.bind_texture("weightTex", &res.weight_ramp_tx);
|
||||
sub.push_constant("useWeight", false);
|
||||
sub.push_constant("useGreasePencil", false);
|
||||
edit_curves_points_ = ⊂
|
||||
}
|
||||
{
|
||||
auto &sub = pass.sub("Lines");
|
||||
sub.state_set(DRW_STATE_WRITE_COLOR | DRW_STATE_DEPTH_LESS_EQUAL | DRW_STATE_BLEND_ALPHA |
|
||||
@@ -81,11 +69,25 @@ class Curves {
|
||||
}
|
||||
{
|
||||
auto &sub = pass.sub("Handles");
|
||||
sub.state_set(DRW_STATE_WRITE_COLOR, state.clipping_plane_count);
|
||||
sub.state_set(DRW_STATE_WRITE_COLOR | DRW_STATE_BLEND_ALPHA, state.clipping_plane_count);
|
||||
sub.shader_set(res.shaders.curve_edit_handles.get());
|
||||
sub.bind_ubo("globalsBlock", &res.globals_buf);
|
||||
sub.push_constant("showCurveHandles", state.overlay.handle_display != CURVE_HANDLE_NONE);
|
||||
sub.push_constant("curveHandleDisplay", int(state.overlay.handle_display));
|
||||
edit_curves_handles_ = ⊂
|
||||
}
|
||||
{
|
||||
auto &sub = pass.sub("Points");
|
||||
sub.state_set(DRW_STATE_WRITE_COLOR | DRW_STATE_DEPTH_LESS_EQUAL | DRW_STATE_BLEND_ALPHA |
|
||||
DRW_STATE_WRITE_DEPTH,
|
||||
state.clipping_plane_count);
|
||||
sub.shader_set(res.shaders.curve_edit_points.get());
|
||||
sub.bind_ubo("globalsBlock", &res.globals_buf);
|
||||
sub.bind_texture("weightTex", &res.weight_ramp_tx);
|
||||
sub.push_constant("useWeight", false);
|
||||
sub.push_constant("useGreasePencil", false);
|
||||
edit_curves_points_ = ⊂
|
||||
}
|
||||
}
|
||||
|
||||
const bool show_normals = (state.overlay.edit_flag & V3D_OVERLAY_EDIT_CU_NORMALS);
|
||||
@@ -149,16 +151,13 @@ class Curves {
|
||||
::Curves &curves = *static_cast<::Curves *>(ob->data);
|
||||
const bool show_points = bke::AttrDomain(curves.selection_domain) == bke::AttrDomain::Point;
|
||||
|
||||
GPUUniformBuf *ubo_storage = DRW_curves_batch_cache_ubo_storage(&curves);
|
||||
|
||||
if (show_points) {
|
||||
gpu::Batch *geom = DRW_curves_batch_cache_get_edit_points(&curves);
|
||||
edit_curves_points_->draw(geom, manager.unique_handle(ob_ref));
|
||||
}
|
||||
{
|
||||
gpu::Batch *geom = DRW_curves_batch_cache_get_edit_curves_handles(&curves);
|
||||
edit_curves_handles_->bind_ubo("curvesInfoBlock", ubo_storage);
|
||||
edit_curves_handles_->draw(geom, manager.unique_handle(ob_ref));
|
||||
edit_curves_handles_->draw_expand(geom, GPU_PRIM_TRIS, 8, 1, manager.unique_handle(ob_ref));
|
||||
}
|
||||
{
|
||||
gpu::Batch *geom = DRW_curves_batch_cache_get_edit_curves_lines(&curves);
|
||||
|
||||
@@ -207,7 +207,7 @@ class ShaderModule {
|
||||
ShaderPtr background_clip_bound = shader("overlay_clipbound");
|
||||
ShaderPtr curve_edit_points;
|
||||
ShaderPtr curve_edit_line;
|
||||
ShaderPtr curve_edit_handles;
|
||||
ShaderPtr curve_edit_handles = shader("overlay_edit_curves_handle_next");
|
||||
ShaderPtr extra_point;
|
||||
ShaderPtr facing;
|
||||
ShaderPtr grid = shader("overlay_grid");
|
||||
|
||||
@@ -138,9 +138,6 @@ ShaderModule::ShaderModule(const SelectionType selection_type, const bool clippi
|
||||
[](gpu::shader::ShaderCreateInfo &info) { shader_patch_common(info); });
|
||||
curve_edit_line = shader("overlay_edit_particle_strand",
|
||||
[](gpu::shader::ShaderCreateInfo &info) { shader_patch_common(info); });
|
||||
curve_edit_handles = shader(
|
||||
"overlay_edit_curves_handle",
|
||||
[](gpu::shader::ShaderCreateInfo &info) { shader_patch_common(info); });
|
||||
|
||||
extra_point = shader("overlay_extra_point", [](gpu::shader::ShaderCreateInfo &info) {
|
||||
info.additional_infos_.clear();
|
||||
|
||||
@@ -69,8 +69,8 @@ BLI_STATIC_ASSERT_ALIGN(OVERLAY_GridData, 16)
|
||||
/* Keep the same values as in `draw_cache_impl_curves.cc` */
|
||||
# define EDIT_CURVES_NURBS_CONTROL_POINT (1u)
|
||||
# define EDIT_CURVES_BEZIER_HANDLE (1u << 1)
|
||||
# define EDIT_CURVES_LEFT_HANDLE_TYPES_SHIFT (6u)
|
||||
# define EDIT_CURVES_RIGHT_HANDLE_TYPES_SHIFT (4u)
|
||||
# define EDIT_CURVES_ACTIVE_HANDLE (1u << 2)
|
||||
# define EDIT_CURVES_HANDLE_TYPES_SHIFT (4u)
|
||||
/* Keep the same values as in `draw_cache_imp_curve.c` */
|
||||
# define ACTIVE_NURB (1u << 2)
|
||||
# define BEZIER_HANDLE (1u << 3)
|
||||
|
||||
@@ -562,6 +562,27 @@ GPU_SHADER_CREATE_INFO(overlay_edit_curve_handle_next)
|
||||
"gpu_index_load",
|
||||
"draw_globals");
|
||||
|
||||
GPU_SHADER_CREATE_INFO(overlay_edit_curves_handle_next)
|
||||
.do_static_compilation(true)
|
||||
.typedef_source("overlay_shader_shared.h")
|
||||
.storage_buf(0, Qualifier::READ, "float", "pos[]", Frequency::GEOMETRY)
|
||||
.storage_buf(1, Qualifier::READ, "uint", "data[]", Frequency::GEOMETRY)
|
||||
.storage_buf(2, Qualifier::READ, "float", "selection[]", Frequency::GEOMETRY)
|
||||
.push_constant(Type::IVEC2, "gpu_attr_0")
|
||||
.push_constant(Type::IVEC2, "gpu_attr_1")
|
||||
.push_constant(Type::IVEC2, "gpu_attr_2")
|
||||
.vertex_out(overlay_edit_smooth_color_iface)
|
||||
.push_constant(Type::BOOL, "showCurveHandles")
|
||||
.push_constant(Type::INT, "curveHandleDisplay")
|
||||
.fragment_out(0, Type::VEC4, "fragColor")
|
||||
.vertex_source("overlay_edit_curves_handle_next_vert.glsl")
|
||||
.fragment_source("overlay_varying_color.glsl")
|
||||
.additional_info("draw_view",
|
||||
"draw_modelmat_new",
|
||||
"draw_resource_handle_new",
|
||||
"gpu_index_load",
|
||||
"draw_globals");
|
||||
|
||||
GPU_SHADER_CREATE_INFO(overlay_edit_curve_handle_clipped)
|
||||
.do_static_compilation(true)
|
||||
.additional_info("overlay_edit_curve_handle", "drw_clipped");
|
||||
@@ -635,9 +656,9 @@ GPU_SHADER_CREATE_INFO(overlay_edit_curve_normals)
|
||||
/** \name Edit Curves
|
||||
* \{ */
|
||||
|
||||
GPU_SHADER_INTERFACE_INFO(overlay_edit_curves_handle_iface, "")
|
||||
.smooth(Type::VEC4, "finalColor")
|
||||
.smooth(Type::VEC4, "leftColor");
|
||||
GPU_SHADER_INTERFACE_INFO(overlay_edit_curves_handle_iface, "vert")
|
||||
.flat(Type::UINT, "flag")
|
||||
.flat(Type::FLOAT, "selection");
|
||||
|
||||
GPU_SHADER_CREATE_INFO(overlay_edit_curves_handle)
|
||||
.do_static_compilation(true)
|
||||
@@ -646,16 +667,38 @@ GPU_SHADER_CREATE_INFO(overlay_edit_curves_handle)
|
||||
.vertex_in(1, Type::UINT, "data")
|
||||
.vertex_in(2, Type::FLOAT, "selection")
|
||||
.vertex_out(overlay_edit_curves_handle_iface)
|
||||
.uniform_buf(0, "int", "curvesInfoBlock[4]")
|
||||
.geometry_layout(PrimitiveIn::LINES, PrimitiveOut::TRIANGLE_STRIP, 10)
|
||||
.geometry_out(overlay_edit_smooth_color_iface)
|
||||
.fragment_out(0, Type::VEC4, "fragColor")
|
||||
.vertex_source("overlay_edit_curves_handle_vert.glsl")
|
||||
.fragment_source("overlay_edit_curves_handle_frag.glsl")
|
||||
.geometry_source("overlay_edit_curves_handle_geom.glsl")
|
||||
.fragment_source("overlay_varying_color.glsl")
|
||||
.additional_info("draw_mesh", "draw_globals");
|
||||
|
||||
GPU_SHADER_CREATE_INFO(overlay_edit_curves_handle_clipped)
|
||||
.do_static_compilation(true)
|
||||
.additional_info("overlay_edit_curves_handle", "drw_clipped");
|
||||
|
||||
#ifdef WITH_METAL_BACKEND
|
||||
GPU_SHADER_CREATE_INFO(overlay_edit_curves_handle_no_geom)
|
||||
.metal_backend_only(true)
|
||||
.do_static_compilation(true)
|
||||
.typedef_source("overlay_shader_shared.h")
|
||||
.vertex_in(0, Type::VEC3, "pos")
|
||||
.vertex_in(1, Type::UINT, "data")
|
||||
.vertex_in(2, Type::FLOAT, "selection")
|
||||
.vertex_out(overlay_edit_smooth_color_iface)
|
||||
.fragment_out(0, Type::VEC4, "fragColor")
|
||||
.vertex_source("overlay_edit_curves_handle_vert_no_geom.glsl")
|
||||
.fragment_source("overlay_varying_color.glsl")
|
||||
.additional_info("draw_mesh", "draw_globals");
|
||||
|
||||
GPU_SHADER_CREATE_INFO(overlay_edit_curves_handle_clipped_no_geom)
|
||||
.metal_backend_only(true)
|
||||
.do_static_compilation(true)
|
||||
.additional_info("overlay_edit_curves_handle_no_geom", "drw_clipped");
|
||||
#endif
|
||||
|
||||
/** \} */
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
|
||||
@@ -1,14 +0,0 @@
|
||||
/* SPDX-FileCopyrightText: 2024 Blender Authors
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-2.0-or-later */
|
||||
|
||||
void main()
|
||||
{
|
||||
/* In the layout of index buffer for curves handles is:
|
||||
* [ left bezier handles, right bezier handles, NURBS handles].
|
||||
* So first bezier_point_count lines will use leftColor. All other will be using finalColor as
|
||||
* vertex shader stores right handles color in finalColor variable.
|
||||
*/
|
||||
int bezier_point_count = curvesInfoBlock[0];
|
||||
fragColor = gl_PrimitiveID < bezier_point_count ? leftColor : finalColor;
|
||||
}
|
||||
@@ -0,0 +1,140 @@
|
||||
/* SPDX-FileCopyrightText: 2018-2023 Blender Authors
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-2.0-or-later */
|
||||
|
||||
#pragma BLENDER_REQUIRE(common_math_lib.glsl)
|
||||
#pragma BLENDER_REQUIRE(common_view_clipping_lib.glsl)
|
||||
#pragma BLENDER_REQUIRE(common_view_lib.glsl)
|
||||
|
||||
#define M_TAN_PI_BY_8 tan(M_PI / 8)
|
||||
#define M_TAN_3_PI_BY_8 tan(3 * M_PI / 8)
|
||||
#define M_SQRT2_BY_2 (M_SQRT2 / 2)
|
||||
|
||||
float4 get_bezier_handle_color(uint color_id, float sel)
|
||||
{
|
||||
switch (color_id) {
|
||||
case 0u: /* BEZIER_HANDLE_FREE */
|
||||
return mix(globalsBlock.color_handle_free, globalsBlock.color_handle_sel_free, sel);
|
||||
case 1u: /* BEZIER_HANDLE_AUTO */
|
||||
return mix(globalsBlock.color_handle_auto, globalsBlock.color_handle_sel_auto, sel);
|
||||
case 2u: /* BEZIER_HANDLE_VECTOR */
|
||||
return mix(globalsBlock.color_handle_vect, globalsBlock.color_handle_sel_vect, sel);
|
||||
case 3u: /* BEZIER_HANDLE_ALIGN */
|
||||
return mix(globalsBlock.color_handle_align, globalsBlock.color_handle_sel_align, sel);
|
||||
}
|
||||
return mix(globalsBlock.color_handle_autoclamp, globalsBlock.color_handle_sel_autoclamp, sel);
|
||||
}
|
||||
|
||||
void output_line(vec2 offset, vec4 color_start, vec4 color_end)
|
||||
{
|
||||
finalColor = color_start;
|
||||
|
||||
gl_Position = gl_in[0].gl_Position;
|
||||
gl_Position.xy += offset * gl_in[0].gl_Position.w;
|
||||
view_clipping_distances_set(gl_in[0]);
|
||||
gpu_EmitVertex();
|
||||
|
||||
finalColor = color_end;
|
||||
|
||||
gl_Position = gl_in[1].gl_Position;
|
||||
gl_Position.xy += offset * gl_in[1].gl_Position.w;
|
||||
view_clipping_distances_set(gl_in[1]);
|
||||
gpu_EmitVertex();
|
||||
}
|
||||
|
||||
void main()
|
||||
{
|
||||
bool showCurveHandles = true;
|
||||
uint curveHandleDisplay = CURVE_HANDLE_ALL;
|
||||
|
||||
vec4 v1 = gl_in[0].gl_Position;
|
||||
vec4 v2 = gl_in[1].gl_Position;
|
||||
|
||||
bool is_active_nurb = (vert[0].flag & EDIT_CURVES_ACTIVE_HANDLE) != 0u;
|
||||
uint color_id = (vert[0].flag >> EDIT_CURVES_HANDLE_TYPES_SHIFT) & 3;
|
||||
|
||||
/* Don't output any edges if we don't show handles */
|
||||
if (!showCurveHandles && (color_id < 5u)) {
|
||||
return;
|
||||
}
|
||||
|
||||
bool handle_selected = (showCurveHandles &&
|
||||
((vert[0].flag &
|
||||
(EDIT_CURVES_ACTIVE_HANDLE | EDIT_CURVES_BEZIER_HANDLE)) != 0u));
|
||||
|
||||
/* If handle type is only selected and the edge is not selected, don't show. */
|
||||
if ((uint(curveHandleDisplay) != CURVE_HANDLE_ALL) && (!handle_selected)) {
|
||||
/* Nurbs must show the handles always. */
|
||||
bool is_nurbs = (vert[0].flag & EDIT_CURVES_NURBS_CONTROL_POINT) != 0u;
|
||||
if ((!is_nurbs) && (color_id <= 4u)) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
vec4 inner_color[2];
|
||||
if ((vert[0].flag & EDIT_CURVES_BEZIER_HANDLE) != 0u) {
|
||||
inner_color[0] = get_bezier_handle_color(color_id, vert[0].selection);
|
||||
inner_color[1] = get_bezier_handle_color(color_id, vert[1].selection);
|
||||
}
|
||||
else if ((vert[0].flag & EDIT_CURVES_NURBS_CONTROL_POINT) != 0u) {
|
||||
inner_color[0] = mix(
|
||||
globalsBlock.color_nurb_uline, globalsBlock.color_nurb_sel_uline, vert[0].selection);
|
||||
inner_color[1] = mix(
|
||||
globalsBlock.color_nurb_uline, globalsBlock.color_nurb_sel_uline, vert[1].selection);
|
||||
}
|
||||
else {
|
||||
inner_color[0] = mix(
|
||||
globalsBlock.color_wire, globalsBlock.color_vertex_select, vert[0].selection);
|
||||
inner_color[1] = mix(
|
||||
globalsBlock.color_wire, globalsBlock.color_vertex_select, vert[1].selection);
|
||||
}
|
||||
|
||||
vec4 outer_color[2];
|
||||
if (is_active_nurb) {
|
||||
outer_color[0] = mix(colorActiveSpline,
|
||||
inner_color[0],
|
||||
0.25); /* Minimize active color bleeding on inner_color. */
|
||||
outer_color[1] = mix(colorActiveSpline,
|
||||
inner_color[1],
|
||||
0.25); /* Minimize active color bleeding on inner_color. */
|
||||
}
|
||||
else {
|
||||
outer_color[0] = vec4(inner_color[0].rgb, 0.0);
|
||||
outer_color[1] = vec4(inner_color[1].rgb, 0.0);
|
||||
}
|
||||
|
||||
vec2 v1_2 = (v2.xy / v2.w - v1.xy / v1.w) * sizeViewport;
|
||||
vec2 offset = sizeEdge * 4.0 * sizeViewportInv; /* 4.0 is eyeballed */
|
||||
|
||||
if (abs(v1_2.x) <= M_TAN_PI_BY_8 * abs(v1_2.y)) {
|
||||
offset.y = 0.0;
|
||||
}
|
||||
else if (abs(v1_2.x) <= M_TAN_3_PI_BY_8 * abs(v1_2.y)) {
|
||||
offset = offset * vec2(-M_SQRT2_BY_2 * sign(v1_2.x), M_SQRT2_BY_2 * sign(v1_2.y));
|
||||
}
|
||||
else {
|
||||
offset.x = 0.0;
|
||||
}
|
||||
|
||||
/* draw the transparent border (AA). */
|
||||
if (is_active_nurb) {
|
||||
offset *= 0.75; /* Don't make the active "halo" appear very thick. */
|
||||
output_line(offset * 2.0, vec4(colorActiveSpline.rgb, 0.0), vec4(colorActiveSpline.rgb, 0.0));
|
||||
}
|
||||
|
||||
/* draw the outline. */
|
||||
output_line(offset, outer_color[0], outer_color[1]);
|
||||
|
||||
/* draw the core of the line. */
|
||||
output_line(vec2(0.0), inner_color[0], inner_color[1]);
|
||||
|
||||
/* draw the outline. */
|
||||
output_line(-offset, outer_color[0], outer_color[1]);
|
||||
|
||||
/* draw the transparent border (AA). */
|
||||
if (is_active_nurb) {
|
||||
output_line(offset * -2.0, vec4(colorActiveSpline.rgb, 0.0), vec4(colorActiveSpline.rgb, 0.0));
|
||||
}
|
||||
|
||||
EndPrimitive();
|
||||
}
|
||||
@@ -0,0 +1,234 @@
|
||||
/* SPDX-FileCopyrightText: 2018-2024 Blender Authors
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-2.0-or-later */
|
||||
|
||||
#pragma BLENDER_REQUIRE(common_view_clipping_lib.glsl)
|
||||
#pragma BLENDER_REQUIRE(common_view_lib.glsl)
|
||||
#pragma BLENDER_REQUIRE(gpu_shader_utildefines_lib.glsl)
|
||||
#pragma BLENDER_REQUIRE(gpu_shader_attribute_load_lib.glsl)
|
||||
#pragma BLENDER_REQUIRE(gpu_shader_index_load_lib.glsl)
|
||||
#pragma BLENDER_REQUIRE(gpu_shader_math_base_lib.glsl)
|
||||
|
||||
#define M_TAN_PI_BY_8 tan(M_PI / 8)
|
||||
#define M_TAN_3_PI_BY_8 tan(3 * M_PI / 8)
|
||||
#define M_SQRT2_BY_2 (M_SQRT2 / 2)
|
||||
|
||||
struct VertIn {
|
||||
/* Local Position. */
|
||||
vec3 ls_P;
|
||||
/* Edit Flags and Data. */
|
||||
uint e_data;
|
||||
float sel;
|
||||
};
|
||||
|
||||
VertIn input_assembly(uint in_vertex_id)
|
||||
{
|
||||
uint v_i = gpu_index_load(in_vertex_id);
|
||||
|
||||
VertIn vert_in;
|
||||
vert_in.ls_P = gpu_attr_load_float3(pos, gpu_attr_0, v_i);
|
||||
vert_in.e_data = data[gpu_attr_load_index(v_i, gpu_attr_1)];
|
||||
vert_in.sel = selection[gpu_attr_load_index(v_i, gpu_attr_2)];
|
||||
return vert_in;
|
||||
}
|
||||
|
||||
struct VertOut {
|
||||
vec3 ws_P;
|
||||
vec4 gpu_position;
|
||||
uint flag;
|
||||
float sel;
|
||||
};
|
||||
|
||||
VertOut vertex_main(VertIn vert_in)
|
||||
{
|
||||
VertOut vert;
|
||||
vert.flag = vert_in.e_data;
|
||||
vert.ws_P = point_object_to_world(vert_in.ls_P);
|
||||
vert.gpu_position = point_world_to_ndc(vert.ws_P);
|
||||
vert.sel = vert_in.sel;
|
||||
return vert;
|
||||
}
|
||||
|
||||
struct GeomOut {
|
||||
vec4 gpu_position;
|
||||
vec3 ws_P;
|
||||
vec2 offset;
|
||||
vec4 color;
|
||||
};
|
||||
|
||||
void export_vertex(GeomOut geom_out)
|
||||
{
|
||||
finalColor = geom_out.color;
|
||||
gl_Position = geom_out.gpu_position;
|
||||
gl_Position.xy += geom_out.offset * geom_out.gpu_position.w;
|
||||
view_clipping_distances(geom_out.ws_P);
|
||||
}
|
||||
|
||||
void strip_EmitVertex(const uint strip_index,
|
||||
uint out_vertex_id,
|
||||
uint out_primitive_id,
|
||||
GeomOut geom_out)
|
||||
{
|
||||
bool is_odd_primitive = (out_primitive_id & 1u) != 0u;
|
||||
/* Maps triangle list primitives to triangle strip indices. */
|
||||
uint out_strip_index = (is_odd_primitive ? (2u - out_vertex_id) : out_vertex_id) +
|
||||
out_primitive_id;
|
||||
|
||||
if (out_strip_index == strip_index) {
|
||||
export_vertex(geom_out);
|
||||
}
|
||||
}
|
||||
|
||||
void output_vertex_pair(const uint line_id,
|
||||
uint out_vertex_id,
|
||||
uint out_primitive_id,
|
||||
VertOut geom_in[2],
|
||||
vec2 offset,
|
||||
vec4 color)
|
||||
{
|
||||
GeomOut geom_out;
|
||||
geom_out.color = color;
|
||||
geom_out.offset = offset;
|
||||
|
||||
geom_out.gpu_position = geom_in[0].gpu_position;
|
||||
geom_out.ws_P = geom_in[0].ws_P;
|
||||
strip_EmitVertex(line_id * 2 + 0, out_vertex_id, out_primitive_id, geom_out);
|
||||
|
||||
geom_out.gpu_position = geom_in[1].gpu_position;
|
||||
geom_out.ws_P = geom_in[1].ws_P;
|
||||
strip_EmitVertex(line_id * 2 + 1, out_vertex_id, out_primitive_id, geom_out);
|
||||
}
|
||||
|
||||
float4 get_bezier_handle_color(uint color_id, float sel)
|
||||
{
|
||||
switch (color_id) {
|
||||
case 0u: /* BEZIER_HANDLE_FREE */
|
||||
return mix(globalsBlock.color_handle_free, globalsBlock.color_handle_sel_free, sel);
|
||||
case 1u: /* BEZIER_HANDLE_AUTO */
|
||||
return mix(globalsBlock.color_handle_auto, globalsBlock.color_handle_sel_auto, sel);
|
||||
case 2u: /* BEZIER_HANDLE_VECTOR */
|
||||
return mix(globalsBlock.color_handle_vect, globalsBlock.color_handle_sel_vect, sel);
|
||||
case 3u: /* BEZIER_HANDLE_ALIGN */
|
||||
return mix(globalsBlock.color_handle_align, globalsBlock.color_handle_sel_align, sel);
|
||||
}
|
||||
return mix(globalsBlock.color_handle_autoclamp, globalsBlock.color_handle_sel_autoclamp, sel);
|
||||
}
|
||||
|
||||
void geometry_main(VertOut geom_in[2],
|
||||
uint out_vertex_id,
|
||||
uint out_primitive_id,
|
||||
uint out_invocation_id)
|
||||
{
|
||||
vec4 v1 = geom_in[0].gpu_position;
|
||||
vec4 v2 = geom_in[1].gpu_position;
|
||||
|
||||
uint is_active_nurb = (geom_in[0].flag & EDIT_CURVES_ACTIVE_HANDLE);
|
||||
uint color_id = (geom_in[0].flag >> EDIT_CURVES_HANDLE_TYPES_SHIFT) & 3u;
|
||||
|
||||
/* Don't output any edges if we don't show handles */
|
||||
if (!showCurveHandles && (color_id < 5u)) {
|
||||
return;
|
||||
}
|
||||
|
||||
bool edge_selected = (((geom_in[1].flag | geom_in[0].flag) & VERT_SELECTED) != 0u);
|
||||
bool handle_selected = (showCurveHandles &&
|
||||
(((geom_in[0].flag) &
|
||||
(EDIT_CURVES_ACTIVE_HANDLE | EDIT_CURVES_BEZIER_HANDLE)) != 0u));
|
||||
|
||||
/* If handle type is only selected and the edge is not selected, don't show. */
|
||||
if ((uint(curveHandleDisplay) != CURVE_HANDLE_ALL) && (!handle_selected)) {
|
||||
/* Nurbs must show the handles always. */
|
||||
bool is_nurbs = (geom_in[0].flag & EDIT_CURVES_NURBS_CONTROL_POINT) != 0u;
|
||||
if ((!is_nurbs) && (color_id <= 4u)) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
bool is_odd_vertex = (out_vertex_id & 1u) != 0u;
|
||||
bool is_odd_primitive = (out_primitive_id & 1u) != 0u;
|
||||
uint line_end_point = (is_odd_primitive && !is_odd_vertex) ||
|
||||
(!is_odd_primitive && is_odd_vertex) ?
|
||||
1 :
|
||||
0;
|
||||
vec4 inner_color;
|
||||
if ((geom_in[line_end_point].flag & EDIT_CURVES_BEZIER_HANDLE) != 0u) {
|
||||
inner_color = get_bezier_handle_color(color_id, geom_in[line_end_point].sel);
|
||||
}
|
||||
else if ((geom_in[line_end_point].flag & EDIT_CURVES_NURBS_CONTROL_POINT) != 0u) {
|
||||
inner_color = mix(globalsBlock.color_nurb_uline,
|
||||
globalsBlock.color_nurb_sel_uline,
|
||||
geom_in[line_end_point].sel);
|
||||
}
|
||||
else {
|
||||
inner_color = mix(
|
||||
globalsBlock.color_wire, globalsBlock.color_vertex_select, geom_in[line_end_point].sel);
|
||||
}
|
||||
|
||||
/* Minimize active color bleeding on inner_color. */
|
||||
vec4 active_color = mix(colorActiveSpline, inner_color, 0.25);
|
||||
vec4 outer_color = (is_active_nurb != 0u) ? active_color : vec4(inner_color.rgb, 0.0);
|
||||
|
||||
vec2 v1_2 = (v2.xy / v2.w - v1.xy / v1.w);
|
||||
vec2 offset = sizeEdge * 4.0 * sizeViewportInv; /* 4.0 is eyeballed */
|
||||
|
||||
if (abs(v1_2.x) <= M_TAN_PI_BY_8 * abs(v1_2.y)) {
|
||||
offset.y = 0.0;
|
||||
}
|
||||
else if (abs(v1_2.x) <= M_TAN_3_PI_BY_8 * abs(v1_2.y)) {
|
||||
offset = offset * vec2(-M_SQRT2_BY_2 * sign(v1_2.x), M_SQRT2_BY_2 * sign(v1_2.y));
|
||||
}
|
||||
else {
|
||||
offset.x = 0.0;
|
||||
}
|
||||
|
||||
vec4 border_color = vec4(colorActiveSpline.rgb, 0.0);
|
||||
/* Draw the transparent border (AA). */
|
||||
if (is_active_nurb != 0u) {
|
||||
offset *= 0.75; /* Don't make the active "halo" appear very thick. */
|
||||
output_vertex_pair(0, out_vertex_id, out_primitive_id, geom_in, offset * 2.0, border_color);
|
||||
}
|
||||
/* Draw the outline. */
|
||||
output_vertex_pair(1, out_vertex_id, out_primitive_id, geom_in, offset, outer_color);
|
||||
/* Draw the core of the line. */
|
||||
output_vertex_pair(2, out_vertex_id, out_primitive_id, geom_in, vec2(0.0), inner_color);
|
||||
/* Draw the outline. */
|
||||
output_vertex_pair(3, out_vertex_id, out_primitive_id, geom_in, -offset, outer_color);
|
||||
/* Draw the transparent border (AA). */
|
||||
if (is_active_nurb != 0u) {
|
||||
output_vertex_pair(4, out_vertex_id, out_primitive_id, geom_in, -offset * 2.0, border_color);
|
||||
}
|
||||
}
|
||||
|
||||
void main()
|
||||
{
|
||||
/* Line list primitive. */
|
||||
const uint input_primitive_vertex_count = 2u;
|
||||
/* Triangle list primitive (emulating triangle strip). */
|
||||
const uint ouput_primitive_vertex_count = 3u;
|
||||
const uint ouput_primitive_count = 8u;
|
||||
const uint ouput_invocation_count = 1u;
|
||||
const uint output_vertex_count_per_invocation = ouput_primitive_count *
|
||||
ouput_primitive_vertex_count;
|
||||
const uint output_vertex_count_per_input_primitive = output_vertex_count_per_invocation *
|
||||
ouput_invocation_count;
|
||||
|
||||
uint in_primitive_id = uint(gl_VertexID) / output_vertex_count_per_input_primitive;
|
||||
uint in_primitive_first_vertex = in_primitive_id * input_primitive_vertex_count;
|
||||
|
||||
uint out_vertex_id = uint(gl_VertexID) % ouput_primitive_vertex_count;
|
||||
uint out_primitive_id = (uint(gl_VertexID) / ouput_primitive_vertex_count) %
|
||||
ouput_primitive_count;
|
||||
uint out_invocation_id = (uint(gl_VertexID) / output_vertex_count_per_invocation) %
|
||||
ouput_invocation_count;
|
||||
|
||||
VertIn vert_in[input_primitive_vertex_count];
|
||||
vert_in[0] = input_assembly(in_primitive_first_vertex + 0u);
|
||||
vert_in[1] = input_assembly(in_primitive_first_vertex + 1u);
|
||||
|
||||
VertOut vert_out[input_primitive_vertex_count];
|
||||
vert_out[0] = vertex_main(vert_in[0]);
|
||||
vert_out[1] = vertex_main(vert_in[1]);
|
||||
|
||||
/* Discard by default. */
|
||||
gl_Position = vec4(NAN_FLT);
|
||||
geometry_main(vert_out, out_vertex_id, out_primitive_id, out_invocation_id);
|
||||
}
|
||||
@@ -5,40 +5,14 @@
|
||||
#pragma BLENDER_REQUIRE(common_view_clipping_lib.glsl)
|
||||
#pragma BLENDER_REQUIRE(common_view_lib.glsl)
|
||||
|
||||
float4 get_bezier_handle_color(uint color_id, float sel)
|
||||
{
|
||||
switch (color_id) {
|
||||
case 0u: /* BEZIER_HANDLE_FREE */
|
||||
return mix(globalsBlock.color_handle_free, globalsBlock.color_handle_sel_free, sel);
|
||||
case 1u: /* BEZIER_HANDLE_AUTO */
|
||||
return mix(globalsBlock.color_handle_auto, globalsBlock.color_handle_sel_auto, sel);
|
||||
case 2u: /* BEZIER_HANDLE_VECTOR */
|
||||
return mix(globalsBlock.color_handle_vect, globalsBlock.color_handle_sel_vect, sel);
|
||||
case 3u: /* BEZIER_HANDLE_ALIGN */
|
||||
return mix(globalsBlock.color_handle_align, globalsBlock.color_handle_sel_align, sel);
|
||||
}
|
||||
return mix(globalsBlock.color_handle_autoclamp, globalsBlock.color_handle_sel_autoclamp, sel);
|
||||
}
|
||||
|
||||
void main()
|
||||
{
|
||||
GPU_INTEL_VERTEX_SHADER_WORKAROUND
|
||||
|
||||
vec3 world_pos = point_object_to_world(pos);
|
||||
gl_Position = point_world_to_ndc(world_pos);
|
||||
|
||||
if ((data & EDIT_CURVES_BEZIER_HANDLE) != 0u) {
|
||||
leftColor = get_bezier_handle_color((data >> EDIT_CURVES_LEFT_HANDLE_TYPES_SHIFT) & 3,
|
||||
selection);
|
||||
finalColor = get_bezier_handle_color((data >> EDIT_CURVES_RIGHT_HANDLE_TYPES_SHIFT) & 3,
|
||||
selection);
|
||||
}
|
||||
else if ((data & EDIT_CURVES_NURBS_CONTROL_POINT) != 0u) {
|
||||
finalColor = mix(globalsBlock.color_nurb_uline, globalsBlock.color_nurb_sel_uline, selection);
|
||||
}
|
||||
else {
|
||||
finalColor = mix(colorWire, colorVertexSelect, selection);
|
||||
}
|
||||
vert.flag = data;
|
||||
vert.selection = selection;
|
||||
|
||||
view_clipping_distances(world_pos);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,217 @@
|
||||
/* SPDX-FileCopyrightText: 2017-2023 Blender Authors
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-2.0-or-later */
|
||||
|
||||
#pragma BLENDER_REQUIRE(common_math_lib.glsl)
|
||||
#pragma BLENDER_REQUIRE(common_view_clipping_lib.glsl)
|
||||
#pragma BLENDER_REQUIRE(common_view_lib.glsl)
|
||||
#pragma USE_SSBO_VERTEX_FETCH(TriangleList, 24)
|
||||
|
||||
#define M_TAN_PI_BY_8 tan(M_PI / 8)
|
||||
#define M_TAN_3_PI_BY_8 tan(3 * M_PI / 8)
|
||||
#define M_SQRT2_BY_2 (M_SQRT2 / 2)
|
||||
|
||||
#define DISCARD_VERTEX \
|
||||
gl_Position = vec4(0.0); \
|
||||
finalColor = vec4(0.0); \
|
||||
return;
|
||||
|
||||
float4 get_bezier_handle_color(uint color_id, float sel)
|
||||
{
|
||||
switch (color_id) {
|
||||
case 0u: /* BEZIER_HANDLE_FREE */
|
||||
return mix(globalsBlock.color_handle_free, globalsBlock.color_handle_sel_free, sel);
|
||||
case 1u: /* BEZIER_HANDLE_AUTO */
|
||||
return mix(globalsBlock.color_handle_auto, globalsBlock.color_handle_sel_auto, sel);
|
||||
case 2u: /* BEZIER_HANDLE_VECTOR */
|
||||
return mix(globalsBlock.color_handle_vect, globalsBlock.color_handle_sel_vect, sel);
|
||||
case 3u: /* BEZIER_HANDLE_ALIGN */
|
||||
return mix(globalsBlock.color_handle_align, globalsBlock.color_handle_sel_align, sel);
|
||||
}
|
||||
return mix(globalsBlock.color_handle_autoclamp, globalsBlock.color_handle_sel_autoclamp, sel);
|
||||
}
|
||||
|
||||
void output_vert(vec2 offset, vec4 color, vec3 out_world_pos, vec4 out_ndc_pos)
|
||||
{
|
||||
finalColor = color;
|
||||
gl_Position = out_ndc_pos;
|
||||
gl_Position.xy += offset * out_ndc_pos.w;
|
||||
view_clipping_distances(out_world_pos);
|
||||
}
|
||||
|
||||
void main()
|
||||
{
|
||||
GPU_INTEL_VERTEX_SHADER_WORKAROUND
|
||||
|
||||
bool showCurveHandles = true;
|
||||
uint curveHandleDisplay = CURVE_HANDLE_ALL;
|
||||
|
||||
/* Perform vertex shader for each input primitive. */
|
||||
vec3 in_pos[2];
|
||||
vec3 world_pos[2];
|
||||
vec4 ndc_pos[2];
|
||||
uint vert_flag[2];
|
||||
float vert_selection[2];
|
||||
|
||||
/* Input prim is LineList. */
|
||||
/* Index of the input line primitive. */
|
||||
int input_line_id = gl_VertexID / 24;
|
||||
/* Index of output vertex set. Grouped into pairs as outputted by original "output_line" function
|
||||
* in overlay_edit_curve_handle_geom.glsl. */
|
||||
int output_quad_id = (gl_VertexID / 6) % 4;
|
||||
/* ID of vertex within generated line segment geometry. */
|
||||
int output_prim_vert_id = gl_VertexID % 24;
|
||||
int quotient = output_prim_vert_id / 3;
|
||||
int remainder = output_prim_vert_id % 3;
|
||||
int line_end_point = remainder == 0 || (quotient % 2 == 0 && remainder == 2) ? 0 : 1;
|
||||
|
||||
for (int i = 0; i < 2; i++) {
|
||||
in_pos[i] = vertex_fetch_attribute((input_line_id * 2) + i, pos, vec3).xyz;
|
||||
vert_flag[i] = (uint)vertex_fetch_attribute((input_line_id * 2) + i, data, uchar);
|
||||
vert_selection[i] = (float)vertex_fetch_attribute((input_line_id * 2) + i, selection, float);
|
||||
world_pos[i] = point_object_to_world(in_pos[i]);
|
||||
ndc_pos[i] = point_world_to_ndc(world_pos[i]);
|
||||
}
|
||||
|
||||
/* Perform Geometry shader equivalent calculation. */
|
||||
bool is_active_nurb = (vert_flag[0] & EDIT_CURVES_ACTIVE_HANDLE) != 0u;
|
||||
uint color_id = (vert_flag[0] >> EDIT_CURVES_HANDLE_TYPES_SHIFT) & 3;
|
||||
|
||||
/* Don't output any edges if we don't show handles */
|
||||
if (!showCurveHandles && (color_id < 5u)) {
|
||||
DISCARD_VERTEX
|
||||
return;
|
||||
}
|
||||
|
||||
bool handle_selected = (showCurveHandles &&
|
||||
((vert_flag[0] &
|
||||
(EDIT_CURVES_ACTIVE_HANDLE | EDIT_CURVES_BEZIER_HANDLE)) != 0u));
|
||||
|
||||
/* If handle type is only selected and the edge is not selected, don't show. */
|
||||
if ((uint(curveHandleDisplay) != CURVE_HANDLE_ALL) && (!handle_selected)) {
|
||||
/* Nurbs must show the handles always. */
|
||||
bool is_nurbs = (vert_flag[0] & EDIT_CURVES_NURBS_CONTROL_POINT) != 0u;
|
||||
if ((!is_nurbs) && (color_id <= 4u)) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
vec4 inner_color;
|
||||
if ((vert_flag[line_end_point] & EDIT_CURVES_BEZIER_HANDLE) != 0u) {
|
||||
inner_color = get_bezier_handle_color(color_id, vert_selection[line_end_point]);
|
||||
}
|
||||
else if ((vert_flag[line_end_point] & EDIT_CURVES_NURBS_CONTROL_POINT) != 0u) {
|
||||
inner_color = mix(globalsBlock.color_nurb_uline,
|
||||
globalsBlock.color_nurb_sel_uline,
|
||||
vert_selection[line_end_point]);
|
||||
}
|
||||
else {
|
||||
inner_color = mix(
|
||||
globalsBlock.color_wire, globalsBlock.color_vertex_select, vert_selection[line_end_point]);
|
||||
}
|
||||
|
||||
vec4 outer_color = (is_active_nurb != 0u) ?
|
||||
mix(colorActiveSpline,
|
||||
inner_color,
|
||||
0.25) /* Minimize active color bleeding on inner_color. */
|
||||
:
|
||||
vec4(inner_color.rgb, 0.0);
|
||||
|
||||
vec2 v1_2 = (ndc_pos[1].xy / ndc_pos[1].w - ndc_pos[0].xy / ndc_pos[0].w) * sizeViewport;
|
||||
vec2 offset = sizeEdge * 4.0 * sizeViewportInv; /* 4.0 is eyeballed */
|
||||
|
||||
if (abs(v1_2.x) <= M_TAN_PI_BY_8 * abs(v1_2.y)) {
|
||||
offset.y = 0.0;
|
||||
}
|
||||
else if (abs(v1_2.x) <= M_TAN_3_PI_BY_8 * abs(v1_2.y)) {
|
||||
offset = offset * vec2(-M_SQRT2_BY_2 * sign(v1_2.x), M_SQRT2_BY_2 * sign(v1_2.y));
|
||||
}
|
||||
else {
|
||||
offset.x = 0.0;
|
||||
}
|
||||
|
||||
/* Each output vertex falls into 10 possible positions to generate 8 output triangles between 5
|
||||
* lines. */
|
||||
/* Discard transparent border quads up-front. */
|
||||
if (!(is_active_nurb != 0u)) {
|
||||
if (output_quad_id == 0 || output_quad_id == 3) {
|
||||
DISCARD_VERTEX
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
switch (output_prim_vert_id) {
|
||||
/* Top transparent border left (AA). */
|
||||
case 0: {
|
||||
offset *= 0.75; /* Don't make the active "halo" appear very thick. */
|
||||
output_vert(offset * 2.0, vec4(colorActiveSpline.rgb, 0.0), world_pos[0], ndc_pos[0]);
|
||||
break;
|
||||
}
|
||||
/* Top transparent border right (AA). */
|
||||
case 1:
|
||||
case 4: {
|
||||
offset *= 0.75; /* Don't make the active "halo" appear very thick. */
|
||||
output_vert(offset * 2.0, vec4(colorActiveSpline.rgb, 0.0), world_pos[1], ndc_pos[1]);
|
||||
break;
|
||||
}
|
||||
/* Top Outline row left point. */
|
||||
case 2:
|
||||
case 3:
|
||||
case 6: {
|
||||
output_vert(offset, outer_color, world_pos[0], ndc_pos[0]);
|
||||
break;
|
||||
}
|
||||
/* Top Outline row right point. */
|
||||
case 5:
|
||||
case 7:
|
||||
case 10: {
|
||||
output_vert(offset, outer_color, world_pos[1], ndc_pos[1]);
|
||||
break;
|
||||
}
|
||||
/* Core line left point. */
|
||||
case 8:
|
||||
case 9:
|
||||
case 12: {
|
||||
output_vert(vec2(0.0), inner_color, world_pos[0], ndc_pos[0]);
|
||||
break;
|
||||
}
|
||||
/* Core line right point. */
|
||||
case 11:
|
||||
case 13:
|
||||
case 16: {
|
||||
output_vert(vec2(0.0), inner_color, world_pos[1], ndc_pos[1]);
|
||||
break;
|
||||
}
|
||||
/* Bottom outline left point. */
|
||||
case 14:
|
||||
case 15:
|
||||
case 18: {
|
||||
output_vert(-offset, outer_color, world_pos[0], ndc_pos[0]);
|
||||
break;
|
||||
}
|
||||
/* Bottom outline right point. */
|
||||
case 17:
|
||||
case 19:
|
||||
case 22: {
|
||||
output_vert(-offset, outer_color, world_pos[1], ndc_pos[1]);
|
||||
break;
|
||||
}
|
||||
/* Bottom transparent border left. */
|
||||
case 20:
|
||||
case 21: {
|
||||
offset *= 0.75; /* Don't make the active "halo" appear very thick. */
|
||||
output_vert(offset * -2.0, vec4(colorActiveSpline.rgb, 0.0), world_pos[0], ndc_pos[0]);
|
||||
break;
|
||||
}
|
||||
/* Bottom transparent border right. */
|
||||
case 23: {
|
||||
offset *= 0.75; /* Don't make the active "halo" appear very thick. */
|
||||
output_vert(offset * -2.0, vec4(colorActiveSpline.rgb, 0.0), world_pos[1], ndc_pos[1]);
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
DISCARD_VERTEX
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -140,7 +140,6 @@ gpu::VertBuf **DRW_curves_texture_for_evaluated_attribute(Curves *curves,
|
||||
const char *name,
|
||||
bool *r_is_point_domain);
|
||||
|
||||
GPUUniformBuf *DRW_curves_batch_cache_ubo_storage(Curves *curves);
|
||||
blender::gpu::Batch *DRW_curves_batch_cache_get_edit_points(Curves *curves);
|
||||
blender::gpu::Batch *DRW_curves_batch_cache_get_sculpt_curves_cage(Curves *curves);
|
||||
blender::gpu::Batch *DRW_curves_batch_cache_get_edit_curves_handles(Curves *curves);
|
||||
|
||||
@@ -50,14 +50,10 @@ namespace blender::draw {
|
||||
|
||||
#define EDIT_CURVES_NURBS_CONTROL_POINT (1u)
|
||||
#define EDIT_CURVES_BEZIER_HANDLE (1u << 1)
|
||||
#define EDIT_CURVES_LEFT_HANDLE_TYPES_SHIFT (6u)
|
||||
#define EDIT_CURVES_RIGHT_HANDLE_TYPES_SHIFT (4u)
|
||||
#define EDIT_CURVES_ACTIVE_HANDLE (1u << 2)
|
||||
#define EDIT_CURVES_HANDLE_TYPES_SHIFT (4u)
|
||||
|
||||
/* ---------------------------------------------------------------------- */
|
||||
struct CurvesUboStorage {
|
||||
int32_t bezier_point_count;
|
||||
float _pad1, _pad2, _pad3;
|
||||
};
|
||||
|
||||
struct CurvesBatchCache {
|
||||
CurvesEvalCache eval_cache;
|
||||
@@ -84,10 +80,6 @@ struct CurvesBatchCache {
|
||||
*/
|
||||
gpu::VertBuf *edit_points_data;
|
||||
|
||||
/* Buffer used to store CurvesUboStorage value. push_constant() could not be used for this
|
||||
* value, as it is not know in overlay_edit_curves.cc as other constants. */
|
||||
GPUUniformBuf *curves_ubo_storage;
|
||||
|
||||
/* Selection of original points. */
|
||||
gpu::VertBuf *edit_points_selection;
|
||||
|
||||
@@ -133,8 +125,6 @@ static void init_batch_cache(Curves &curves)
|
||||
|
||||
if (!cache) {
|
||||
cache = MEM_new<CurvesBatchCache>(__func__);
|
||||
cache->curves_ubo_storage = GPU_uniformbuf_create_ex(
|
||||
sizeof(CurvesUboStorage), nullptr, "CurvesUboStorage");
|
||||
curves.batch_cache = cache;
|
||||
}
|
||||
else {
|
||||
@@ -278,15 +268,10 @@ static void create_points_position_time_vbo(const bke::CurvesGeometry &curves,
|
||||
cache.proc_length_buf->data<float>());
|
||||
}
|
||||
|
||||
static uint32_t bezier_data_value(int8_t left_handle_type, int8_t right_handle_type)
|
||||
static uint32_t bezier_data_value(int8_t handle_type, bool is_active)
|
||||
{
|
||||
return (left_handle_type << EDIT_CURVES_LEFT_HANDLE_TYPES_SHIFT) |
|
||||
(right_handle_type << EDIT_CURVES_RIGHT_HANDLE_TYPES_SHIFT) | EDIT_CURVES_BEZIER_HANDLE;
|
||||
}
|
||||
|
||||
static uint32_t bezier_data_value(int8_t handle_type)
|
||||
{
|
||||
return bezier_data_value(handle_type, handle_type);
|
||||
return (handle_type << EDIT_CURVES_HANDLE_TYPES_SHIFT) | EDIT_CURVES_BEZIER_HANDLE |
|
||||
(is_active ? EDIT_CURVES_ACTIVE_HANDLE : 0);
|
||||
}
|
||||
|
||||
static void create_edit_points_position_and_data(
|
||||
@@ -328,11 +313,19 @@ static void create_edit_points_position_and_data(
|
||||
const VArray<int8_t> right_handle_types = curves.handle_types_right();
|
||||
const OffsetIndices<int> points_by_curve = curves.points_by_curve();
|
||||
|
||||
auto handle_other_curves = [&](const uint32_t fill_value) {
|
||||
return [&, fill_value](const IndexMask &selection) {
|
||||
const VArray<bool> selection_attr = *curves.attributes().lookup_or_default<bool>(
|
||||
".selection", bke::AttrDomain::Point, true);
|
||||
|
||||
auto handle_other_curves = [&](const uint32_t fill_value, const bool mark_active) {
|
||||
return [&, fill_value, mark_active](const IndexMask &selection) {
|
||||
selection.foreach_index(GrainSize(256), [&](const int curve_i) {
|
||||
const IndexRange points = points_by_curve[curve_i];
|
||||
data_dst.slice(points).fill(fill_value);
|
||||
bool is_active = false;
|
||||
if (mark_active) {
|
||||
is_active = array_utils::count_booleans(selection_attr, points) > 0;
|
||||
}
|
||||
uint32_t data_value = fill_value | (is_active ? EDIT_CURVES_ACTIVE_HANDLE : 0u);
|
||||
data_dst.slice(points).fill(data_value);
|
||||
});
|
||||
};
|
||||
};
|
||||
@@ -341,22 +334,28 @@ static void create_edit_points_position_and_data(
|
||||
curves.curve_types(),
|
||||
curves.curve_type_counts(),
|
||||
curves.curves_range(),
|
||||
handle_other_curves(0),
|
||||
handle_other_curves(0),
|
||||
handle_other_curves(0, false),
|
||||
handle_other_curves(0, false),
|
||||
[&](const IndexMask &selection) {
|
||||
const VArray<bool> selection_left = *curves.attributes().lookup_or_default<bool>(
|
||||
".selection_handle_left", bke::AttrDomain::Point, true);
|
||||
const VArray<bool> selection_right = *curves.attributes().lookup_or_default<bool>(
|
||||
".selection_handle_right", bke::AttrDomain::Point, true);
|
||||
|
||||
selection.foreach_index(GrainSize(256), [&](const int src_i, const int64_t dst_i) {
|
||||
for (const int point : points_by_curve[src_i]) {
|
||||
const int point_in_curve = point - points_by_curve[src_i].start();
|
||||
const int dst_index = bezier_dst_offsets[dst_i].start() + point_in_curve;
|
||||
|
||||
data_dst[point] = bezier_data_value(left_handle_types[point],
|
||||
right_handle_types[point]);
|
||||
handle_data_left[dst_index] = bezier_data_value(left_handle_types[point]);
|
||||
handle_data_right[dst_index] = bezier_data_value(right_handle_types[point]);
|
||||
data_dst[point] = EDIT_CURVES_BEZIER_HANDLE;
|
||||
bool is_active = selection_attr[point] || selection_left[point] ||
|
||||
selection_right[point];
|
||||
handle_data_left[dst_index] = bezier_data_value(left_handle_types[point], is_active);
|
||||
handle_data_right[dst_index] = bezier_data_value(right_handle_types[point], is_active);
|
||||
}
|
||||
});
|
||||
},
|
||||
handle_other_curves(EDIT_CURVES_NURBS_CONTROL_POINT));
|
||||
handle_other_curves(EDIT_CURVES_NURBS_CONTROL_POINT, true));
|
||||
|
||||
if (!bezier_point_count) {
|
||||
return;
|
||||
@@ -440,17 +439,22 @@ static void calc_edit_handles_ibo(const bke::CurvesGeometry &curves,
|
||||
const int bezier_point_count = bezier_offsets.total_size();
|
||||
/* Left and right handle will be appended for each Bezier point. */
|
||||
const int vert_len = curves.points_num() + 2 * bezier_point_count;
|
||||
/* For each point has 2 lines from 2 point and one restart entry. */
|
||||
const int index_len_for_bezier_handles = 6 * bezier_point_count;
|
||||
const int index_len = (curves.points_num() - bezier_point_count) +
|
||||
/* One restart entry and one possible cyclic for each non Bezier curve. */
|
||||
2 * (curves.curves_num() - bezier_curves.size()) +
|
||||
index_len_for_bezier_handles;
|
||||
/* For each point has 2 lines from 2 points. */
|
||||
const int index_len_for_bezier_handles = 4 * bezier_point_count;
|
||||
const VArray<bool> cyclic = curves.cyclic();
|
||||
/* For curves like NURBS each control point except last generates two point line.
|
||||
* If one point curves or two point cyclic curves are present, not all builder's buffer space
|
||||
* will be used. */
|
||||
const int index_len_for_other_handles = (curves.points_num() - bezier_point_count -
|
||||
other_curves.size()) *
|
||||
2 +
|
||||
array_utils::count_booleans(cyclic, other_curves) * 2;
|
||||
const int index_len = index_len_for_other_handles + index_len_for_bezier_handles;
|
||||
/* Use two index buffer builders for the same underlying memory. */
|
||||
GPUIndexBufBuilder elb, right_elb;
|
||||
GPU_indexbuf_init_ex(&elb, GPU_PRIM_LINE_STRIP, index_len, vert_len);
|
||||
GPU_indexbuf_init_ex(&elb, GPU_PRIM_LINES, index_len, vert_len);
|
||||
memcpy(&right_elb, &elb, sizeof(elb));
|
||||
right_elb.index_len = 3 * bezier_point_count;
|
||||
right_elb.index_len = 2 * bezier_point_count;
|
||||
|
||||
const OffsetIndices points_by_curve = curves.points_by_curve();
|
||||
|
||||
@@ -460,33 +464,24 @@ static void calc_edit_handles_ibo(const bke::CurvesGeometry &curves,
|
||||
bezier_offsets[dst_i].first();
|
||||
for (const int point : bezier_points) {
|
||||
const int point_left_i = index_shift + point;
|
||||
GPU_indexbuf_add_generic_vert(&elb, point_left_i);
|
||||
GPU_indexbuf_add_generic_vert(&elb, point);
|
||||
GPU_indexbuf_add_primitive_restart(&elb);
|
||||
GPU_indexbuf_add_generic_vert(&right_elb, point_left_i + bezier_point_count);
|
||||
GPU_indexbuf_add_generic_vert(&right_elb, point);
|
||||
GPU_indexbuf_add_primitive_restart(&right_elb);
|
||||
GPU_indexbuf_add_line_verts(&elb, point_left_i, point);
|
||||
GPU_indexbuf_add_line_verts(&right_elb, point_left_i + bezier_point_count, point);
|
||||
}
|
||||
});
|
||||
const VArray<bool> cyclic = curves.cyclic();
|
||||
other_curves.foreach_index([&](const int64_t src_i) {
|
||||
IndexRange curve_points = points_by_curve[src_i];
|
||||
if (curve_points.size() <= 1) {
|
||||
return;
|
||||
}
|
||||
for (const int point : curve_points) {
|
||||
GPU_indexbuf_add_generic_vert(&right_elb, point);
|
||||
for (const int point : curve_points.drop_back(1)) {
|
||||
GPU_indexbuf_add_line_verts(&right_elb, point, point + 1);
|
||||
}
|
||||
if (cyclic[src_i] && curve_points.size() > 2) {
|
||||
GPU_indexbuf_add_generic_vert(&right_elb, curve_points.first());
|
||||
GPU_indexbuf_add_line_verts(&right_elb, curve_points.first(), curve_points.last());
|
||||
}
|
||||
GPU_indexbuf_add_primitive_restart(&right_elb);
|
||||
});
|
||||
GPU_indexbuf_join(&elb, &right_elb);
|
||||
GPU_indexbuf_build_in_place(&elb, cache.edit_handles_ibo);
|
||||
|
||||
CurvesUboStorage ubo_storage{bezier_point_count};
|
||||
GPU_uniformbuf_update(cache.curves_ubo_storage, &ubo_storage);
|
||||
}
|
||||
|
||||
static void alloc_final_attribute_vbo(CurvesEvalCache &cache,
|
||||
@@ -917,7 +912,6 @@ void DRW_curves_batch_cache_free(Curves *curves)
|
||||
{
|
||||
clear_batch_cache(*curves);
|
||||
CurvesBatchCache *batch_cache = static_cast<CurvesBatchCache *>(curves->batch_cache);
|
||||
DRW_UBO_FREE_SAFE(batch_cache->curves_ubo_storage);
|
||||
MEM_delete(batch_cache);
|
||||
curves->batch_cache = nullptr;
|
||||
}
|
||||
@@ -953,12 +947,6 @@ int DRW_curves_material_count_get(const Curves *curves)
|
||||
return max_ii(1, curves->totcol);
|
||||
}
|
||||
|
||||
GPUUniformBuf *DRW_curves_batch_cache_ubo_storage(Curves *curves)
|
||||
{
|
||||
CurvesBatchCache &cache = get_batch_cache(*curves);
|
||||
return cache.curves_ubo_storage;
|
||||
}
|
||||
|
||||
gpu::Batch *DRW_curves_batch_cache_get_edit_points(Curves *curves)
|
||||
{
|
||||
CurvesBatchCache &cache = get_batch_cache(*curves);
|
||||
@@ -1097,7 +1085,7 @@ void DRW_curves_batch_cache_create_requested(Object *ob)
|
||||
DRW_vbo_request(cache.sculpt_cage, &cache.edit_points_data);
|
||||
DRW_vbo_request(cache.sculpt_cage, &cache.edit_points_selection);
|
||||
}
|
||||
if (DRW_batch_requested(cache.edit_handles, GPU_PRIM_LINE_STRIP)) {
|
||||
if (DRW_batch_requested(cache.edit_handles, GPU_PRIM_LINES)) {
|
||||
DRW_ibo_request(cache.edit_handles, &cache.edit_handles_ibo);
|
||||
DRW_vbo_request(cache.edit_handles, &cache.edit_points_pos);
|
||||
DRW_vbo_request(cache.edit_handles, &cache.edit_points_data);
|
||||
|
||||
@@ -501,8 +501,12 @@ void gpu_shader_create_info_init()
|
||||
overlay_edit_mesh_edge_flat = overlay_edit_mesh_edge_flat_no_geom;
|
||||
overlay_edit_mesh_edge_clipped = overlay_edit_mesh_edge_clipped_no_geom;
|
||||
overlay_edit_mesh_edge_flat_clipped = overlay_edit_mesh_edge_flat_clipped_no_geom;
|
||||
/* Overlay Edit Curve. */
|
||||
overlay_edit_curve_handle = overlay_edit_curve_handle_no_geom;
|
||||
overlay_edit_curve_handle_clipped = overlay_edit_curve_handle_clipped_no_geom;
|
||||
/* Overlay Edit Curves. */
|
||||
overlay_edit_curves_handle = overlay_edit_curves_handle_no_geom;
|
||||
overlay_edit_curves_handle_clipped = overlay_edit_curves_handle_clipped_no_geom;
|
||||
|
||||
/* Overlay Armature Shape outline. */
|
||||
overlay_armature_shape_outline = overlay_armature_shape_outline_no_geom;
|
||||
|
||||
Reference in New Issue
Block a user