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:
Laurynas Duburas
2024-09-25 15:21:31 +02:00
committed by Clément Foucault
parent 12ef319a49
commit 84dedfaf4b
15 changed files with 716 additions and 136 deletions

View File

@@ -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

View File

@@ -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);
}

View File

@@ -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);

View File

@@ -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");

View File

@@ -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();

View File

@@ -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)

View File

@@ -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
/** \} */
/* -------------------------------------------------------------------- */

View File

@@ -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;
}

View File

@@ -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();
}

View File

@@ -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);
}

View File

@@ -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);
}

View File

@@ -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;
}
}
}

View File

@@ -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);

View File

@@ -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);

View File

@@ -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;