2023-08-24 10:54:59 +10:00
|
|
|
/* SPDX-FileCopyrightText: 2019-2023 Blender Authors
|
|
|
|
|
*
|
|
|
|
|
* SPDX-License-Identifier: GPL-2.0-or-later */
|
|
|
|
|
|
2025-09-25 10:57:02 +02:00
|
|
|
#include "infos/overlay_wireframe_infos.hh"
|
2025-02-24 16:17:18 +01:00
|
|
|
|
|
|
|
|
VERTEX_SHADER_CREATE_INFO(overlay_wireframe)
|
|
|
|
|
|
2025-01-23 18:06:22 +01:00
|
|
|
#include "draw_model_lib.glsl"
|
2025-03-06 11:06:26 +01:00
|
|
|
#include "draw_object_infos_lib.glsl"
|
2025-02-19 17:46:04 +01:00
|
|
|
#include "draw_view_clipping_lib.glsl"
|
2025-01-23 18:06:22 +01:00
|
|
|
#include "draw_view_lib.glsl"
|
2025-09-15 12:07:26 +02:00
|
|
|
#include "gpu_shader_math_vector_safe_lib.glsl"
|
2024-10-04 15:48:22 +02:00
|
|
|
#include "gpu_shader_utildefines_lib.glsl"
|
2025-01-23 18:06:22 +01:00
|
|
|
#include "overlay_common_lib.glsl"
|
2024-10-04 15:48:22 +02:00
|
|
|
#include "select_lib.glsl"
|
2019-12-02 13:55:30 +01:00
|
|
|
|
2024-08-19 12:31:08 +02:00
|
|
|
#if !defined(POINTS) && !defined(CURVES)
|
|
|
|
|
bool is_edge_sharpness_visible(float wire_data)
|
2019-12-02 01:40:58 +01:00
|
|
|
{
|
2025-04-24 12:50:45 +02:00
|
|
|
return wire_data <= wire_step_param;
|
2019-12-02 01:40:58 +01:00
|
|
|
}
|
2024-08-19 12:31:08 +02:00
|
|
|
#endif
|
2019-12-02 01:40:58 +01:00
|
|
|
|
2025-04-14 13:46:41 +02:00
|
|
|
void wire_color_get(out float3 rim_col, out float3 wire_col)
|
2019-12-02 01:40:58 +01:00
|
|
|
{
|
2025-03-06 11:06:26 +01:00
|
|
|
eObjectInfoFlag ob_flag = drw_object_infos().flag;
|
2024-08-12 15:29:20 +02:00
|
|
|
bool is_selected = flag_test(ob_flag, OBJECT_SELECTED);
|
|
|
|
|
bool is_from_set = flag_test(ob_flag, OBJECT_FROM_SET);
|
|
|
|
|
bool is_active = flag_test(ob_flag, OBJECT_ACTIVE);
|
2019-12-02 01:40:58 +01:00
|
|
|
|
|
|
|
|
if (is_from_set) {
|
2025-04-26 11:28:24 +02:00
|
|
|
rim_col = theme.colors.wire.rgb;
|
|
|
|
|
wire_col = theme.colors.wire.rgb;
|
2019-12-02 01:40:58 +01:00
|
|
|
}
|
2025-04-24 12:50:45 +02:00
|
|
|
else if (is_selected && use_coloring) {
|
|
|
|
|
if (is_transform) {
|
2025-04-26 11:28:24 +02:00
|
|
|
rim_col = theme.colors.transform.rgb;
|
2019-12-02 01:40:58 +01:00
|
|
|
}
|
|
|
|
|
else if (is_active) {
|
2025-04-30 12:25:51 +02:00
|
|
|
rim_col = theme.colors.active_object.rgb;
|
2019-12-02 01:40:58 +01:00
|
|
|
}
|
|
|
|
|
else {
|
2025-05-06 19:42:09 +02:00
|
|
|
rim_col = theme.colors.object_select.rgb;
|
2019-12-02 01:40:58 +01:00
|
|
|
}
|
2025-04-26 11:28:24 +02:00
|
|
|
wire_col = theme.colors.wire.rgb;
|
2019-12-02 01:40:58 +01:00
|
|
|
}
|
|
|
|
|
else {
|
2025-04-26 11:28:24 +02:00
|
|
|
rim_col = theme.colors.wire.rgb;
|
|
|
|
|
wire_col = theme.colors.background.rgb;
|
2019-12-02 01:40:58 +01:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2025-04-14 13:46:41 +02:00
|
|
|
float3 hsv_to_rgb(float3 hsv)
|
2019-12-02 01:40:58 +01:00
|
|
|
{
|
2025-04-14 13:46:41 +02:00
|
|
|
float3 nrgb = abs(hsv.x * 6.0f - float3(3.0f, 2.0f, 4.0f)) * float3(1, -1, -1) +
|
|
|
|
|
float3(-1, 2, 2);
|
2025-04-11 18:28:45 +02:00
|
|
|
nrgb = clamp(nrgb, 0.0f, 1.0f);
|
|
|
|
|
return ((nrgb - 1.0f) * hsv.y + 1.0f) * hsv.z;
|
2019-12-02 01:40:58 +01:00
|
|
|
}
|
|
|
|
|
|
2025-04-14 13:46:41 +02:00
|
|
|
void wire_object_color_get(out float3 rim_col, out float3 wire_col)
|
2019-12-02 01:40:58 +01:00
|
|
|
{
|
2025-03-06 11:06:26 +01:00
|
|
|
ObjectInfos info = drw_object_infos();
|
|
|
|
|
bool is_selected = flag_test(info.flag, OBJECT_SELECTED);
|
2019-12-02 01:40:58 +01:00
|
|
|
|
2025-04-24 12:50:45 +02:00
|
|
|
if (color_type == V3D_SHADING_OBJECT_COLOR) {
|
2025-04-11 18:28:45 +02:00
|
|
|
rim_col = wire_col = drw_object_infos().ob_color.rgb * 0.5f;
|
2019-12-02 01:40:58 +01:00
|
|
|
}
|
|
|
|
|
else {
|
2025-03-06 11:06:26 +01:00
|
|
|
float hue = info.random;
|
2025-04-14 13:46:41 +02:00
|
|
|
float3 hsv = float3(hue, 0.75f, 0.8f);
|
2019-12-02 01:40:58 +01:00
|
|
|
rim_col = wire_col = hsv_to_rgb(hsv);
|
|
|
|
|
}
|
|
|
|
|
|
2025-04-24 12:50:45 +02:00
|
|
|
if (is_selected && use_coloring) {
|
2019-12-02 01:40:58 +01:00
|
|
|
/* "Normalize" color. */
|
2025-04-11 18:28:45 +02:00
|
|
|
wire_col += 1e-4f; /* Avoid division by 0. */
|
2019-12-02 01:40:58 +01:00
|
|
|
float brightness = max(wire_col.x, max(wire_col.y, wire_col.z));
|
2025-04-11 18:28:45 +02:00
|
|
|
wire_col *= 0.5f / brightness;
|
|
|
|
|
rim_col += 0.75f;
|
2019-12-02 01:40:58 +01:00
|
|
|
}
|
|
|
|
|
else {
|
2025-04-11 18:28:45 +02:00
|
|
|
rim_col *= 0.5f;
|
|
|
|
|
wire_col += 0.5f;
|
2019-12-02 01:40:58 +01:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void main()
|
|
|
|
|
{
|
2025-03-04 00:20:52 +01:00
|
|
|
select_id_set(drw_custom_id());
|
2024-08-19 12:31:08 +02:00
|
|
|
|
2025-02-05 14:13:51 +01:00
|
|
|
/* If no attribute is available, use a fixed facing value depending on the coloring mode.
|
|
|
|
|
* This allow to keep most of the contrast between unselected and selected color
|
|
|
|
|
* while keeping object coloring mode working (see #134011). */
|
2025-04-24 12:50:45 +02:00
|
|
|
float no_nor_facing = (color_type == V3D_SHADING_SINGLE_COLOR) ? 0.0f : 0.5f;
|
2025-02-05 14:13:51 +01:00
|
|
|
|
2025-04-14 13:46:41 +02:00
|
|
|
float3 wpos = drw_point_object_to_world(pos);
|
2024-08-19 12:31:08 +02:00
|
|
|
#if defined(POINTS)
|
2025-04-26 11:28:24 +02:00
|
|
|
gl_PointSize = theme.sizes.vert * 2.0f;
|
2024-08-19 12:31:08 +02:00
|
|
|
#elif defined(CURVES)
|
2025-02-05 14:13:51 +01:00
|
|
|
float facing = no_nor_facing;
|
2024-08-19 12:31:08 +02:00
|
|
|
#else
|
2025-04-14 13:46:41 +02:00
|
|
|
float3 wnor = safe_normalize(drw_normal_object_to_world(nor));
|
2019-12-03 01:51:57 +01:00
|
|
|
|
2025-04-24 12:50:45 +02:00
|
|
|
if (is_hair) {
|
|
|
|
|
float4x4 obmat = hair_dupli_matrix;
|
2025-04-14 13:46:41 +02:00
|
|
|
wpos = (obmat * float4(pos, 1.0f)).xyz;
|
2024-10-07 12:54:10 +02:00
|
|
|
wnor = -normalize(to_float3x3(obmat) * nor);
|
2020-05-20 21:47:42 +02:00
|
|
|
}
|
|
|
|
|
|
2025-04-11 18:28:45 +02:00
|
|
|
bool is_persp = (drw_view().winmat[3][3] == 0.0f);
|
2025-04-14 13:46:41 +02:00
|
|
|
float3 V = (is_persp) ? normalize(drw_view().viewinv[3].xyz - wpos) : drw_view().viewinv[2].xyz;
|
2019-12-03 01:51:57 +01:00
|
|
|
|
2025-04-14 13:46:41 +02:00
|
|
|
bool no_attr = all(equal(nor, float3(0)));
|
2025-02-05 14:13:51 +01:00
|
|
|
float facing = no_attr ? no_nor_facing : dot(wnor, V);
|
2024-08-19 12:31:08 +02:00
|
|
|
#endif
|
2020-03-26 15:36:15 +01:00
|
|
|
|
2025-01-23 18:06:22 +01:00
|
|
|
gl_Position = drw_point_world_to_homogenous(wpos);
|
2020-03-26 15:36:15 +01:00
|
|
|
|
2024-08-19 12:31:08 +02:00
|
|
|
#if !defined(POINTS) && !defined(CURVES)
|
|
|
|
|
if (!use_custom_depth_bias) {
|
2025-04-11 18:28:45 +02:00
|
|
|
float facing_ratio = clamp(1.0f - facing * facing, 0.0f, 1.0f);
|
|
|
|
|
float flip = sign(facing); /* Flip when not facing the normal (i.e.: back-facing). */
|
|
|
|
|
float curvature = (1.0f - wd * 0.75f); /* Avoid making things worse for curvy areas. */
|
2025-04-14 13:46:41 +02:00
|
|
|
float3 wofs = wnor * (facing_ratio * curvature * flip);
|
2025-01-23 18:06:22 +01:00
|
|
|
wofs = drw_normal_world_to_view(wofs);
|
2019-12-03 01:06:40 +01:00
|
|
|
|
2024-08-19 12:31:08 +02:00
|
|
|
/* Push vertex half a pixel (maximum) in normal direction. */
|
2025-04-26 11:28:24 +02:00
|
|
|
gl_Position.xy += wofs.xy * uniform_buf.size_viewport_inv * gl_Position.w;
|
2024-08-19 12:31:08 +02:00
|
|
|
|
|
|
|
|
/* Push the vertex towards the camera. Helps a bit. */
|
2025-04-11 18:28:45 +02:00
|
|
|
gl_Position.z -= facing_ratio * curvature * 1.0e-6f * gl_Position.w;
|
2024-08-19 12:31:08 +02:00
|
|
|
}
|
|
|
|
|
#endif
|
2019-12-02 01:40:58 +01:00
|
|
|
|
2025-02-03 14:24:57 +01:00
|
|
|
/* Curves do not need the offset since they *are* the curve geometry. */
|
|
|
|
|
#if !defined(CURVES)
|
2025-04-11 18:28:45 +02:00
|
|
|
gl_Position.z -= ndc_offset_factor * 0.5f;
|
2025-02-03 14:24:57 +01:00
|
|
|
#endif
|
2025-01-23 18:08:20 +01:00
|
|
|
|
2025-04-14 13:46:41 +02:00
|
|
|
float3 rim_col, wire_col;
|
2025-04-24 12:50:45 +02:00
|
|
|
if (color_type == V3D_SHADING_OBJECT_COLOR || color_type == V3D_SHADING_RANDOM_COLOR) {
|
2019-12-02 01:40:58 +01:00
|
|
|
wire_object_color_get(rim_col, wire_col);
|
|
|
|
|
}
|
|
|
|
|
else {
|
|
|
|
|
wire_color_get(rim_col, wire_col);
|
|
|
|
|
}
|
|
|
|
|
|
2024-08-19 12:31:08 +02:00
|
|
|
#if defined(POINTS)
|
2025-04-24 12:50:45 +02:00
|
|
|
final_color = wire_col.rgbb;
|
|
|
|
|
final_color_inner = rim_col.rgbb;
|
2019-12-02 01:40:58 +01:00
|
|
|
|
2024-08-19 12:31:08 +02:00
|
|
|
#else
|
|
|
|
|
/* Convert to screen position [0..sizeVp]. */
|
2025-04-26 11:28:24 +02:00
|
|
|
edge_start = ((gl_Position.xy / gl_Position.w) * 0.5f + 0.5f) * uniform_buf.size_viewport;
|
2025-04-24 12:50:45 +02:00
|
|
|
edge_pos = edge_start;
|
2024-08-19 12:31:08 +02:00
|
|
|
|
2025-02-05 14:13:51 +01:00
|
|
|
# if !defined(SELECT_ENABLE)
|
2025-04-11 18:28:45 +02:00
|
|
|
facing = clamp(abs(facing), 0.0f, 1.0f);
|
2020-02-23 14:32:34 +01:00
|
|
|
/* Do interpolation in a non-linear space to have a better visual result. */
|
2025-04-14 13:46:41 +02:00
|
|
|
rim_col = pow(rim_col, float3(1.0f / 2.2f));
|
|
|
|
|
wire_col = pow(wire_col, float3(1.0f / 2.2f));
|
|
|
|
|
float3 final_front_col = mix(rim_col, wire_col, 0.35f);
|
2025-04-24 12:50:45 +02:00
|
|
|
final_color.rgb = mix(rim_col, final_front_col, facing);
|
|
|
|
|
final_color.rgb = pow(final_color.rgb, float3(2.2f));
|
2024-08-19 12:31:08 +02:00
|
|
|
# endif
|
|
|
|
|
|
2025-04-24 12:50:45 +02:00
|
|
|
final_color.a = wire_opacity;
|
|
|
|
|
final_color.rgb *= wire_opacity;
|
2019-12-02 01:40:58 +01:00
|
|
|
|
2024-08-19 12:31:08 +02:00
|
|
|
# if !defined(CURVES)
|
2019-12-03 01:06:40 +01:00
|
|
|
/* Cull flat edges below threshold. */
|
2023-04-03 16:22:41 +02:00
|
|
|
if (!no_attr && !is_edge_sharpness_visible(wd)) {
|
2025-04-24 12:50:45 +02:00
|
|
|
edge_start = float2(-1.0f);
|
2019-12-03 01:06:40 +01:00
|
|
|
}
|
2024-08-19 12:31:08 +02:00
|
|
|
# endif
|
2019-12-03 01:06:40 +01:00
|
|
|
|
2024-12-12 23:05:00 +01:00
|
|
|
# if defined(SELECT_ENABLE)
|
2021-02-05 19:07:03 -08:00
|
|
|
/* HACK: to avoid losing sub-pixel object in selections, we add a bit of randomness to the
|
2020-02-04 15:19:28 +01:00
|
|
|
* wire to at least create one fragment that will pass the occlusion query. */
|
2025-04-26 11:28:24 +02:00
|
|
|
gl_Position.xy += uniform_buf.size_viewport_inv * gl_Position.w *
|
|
|
|
|
((gl_VertexID % 2 == 0) ? -1.0f : 1.0f);
|
2024-08-19 12:31:08 +02:00
|
|
|
# endif
|
2020-02-04 15:19:28 +01:00
|
|
|
#endif
|
|
|
|
|
|
2022-05-01 17:39:32 +02:00
|
|
|
view_clipping_distances(wpos);
|
2019-12-02 01:40:58 +01:00
|
|
|
}
|