Geometry Nodes: Dashed lines for function flow
Use dashes to represent the function flow (while keeping continuous lines for the data-flow). It is important to tell both flows apart (the data and the function flow). The sockets help with that, the noodles help this further. The "data flow" is evaluated at every single node. A user can inspect the output sockets of those nodes and have a glimpse at their values. The "function flow" (nodes) however is only evaluated in the geometry nodes. The noodles are not transporting data in the same sense of the "data flow". All that can be inspected are the attributes the functions depend on. Having this clearly communicated should help users to inspect the nodetrees, read and understand the different flows in the same tree. --- Known limitations: At the moment the dash lines are not equidistant: * It would be nice to get the "uv.x" to be resampled for the bezier curve so the dashes are equally distributed in the curve. * Using distance between the P3 and P0 instead of the real bezier curve length seems to be fine. --- Full disclaimer: Changes with that much of a visual impact tend to be controversial. So far the main feedback is that dashed lines can be associated to broken link, and that there are better ways to represent the flows (or different information that should be visually represented). I'm fully aware of that. However dashed lines are already used in the viewport and outliner to indicate (hierarchical) relation. Besides, other approaches (double-lines, having the data flow to be more distinct, ...) didn't pan out in the end (or didn't look as good as this). --- Impact in other editors: The compositor uses mostly a "data flow" nodetree, so no change is expected there. The shader nodetree is one that could but doesn't have to change its visual language. The shader nodetree uses mostly "function flow" with some "data flow" nodes. One can argue that it should be adapted to follow the same pattern as geometry nodes (with the new noodles and the diamond sockets). Oh the other hand, a shader nodetree has a single context. When a node depends on the "UV", there is only one UV at a time for the entire nodetree. So it can also be treated as a psedo "data flow" nodetree if we want to avoid too many changes in other parts of Blender. Differential Revision: https://developer.blender.org/D12602
This commit is contained in:
parent
728ae33f37
commit
ff7e67afd5
|
@ -3934,10 +3934,12 @@ static struct {
|
|||
uint colid_id, muted_id;
|
||||
uint dim_factor_id;
|
||||
uint thickness_id;
|
||||
uint dash_factor_id;
|
||||
GPUVertBufRaw p0_step, p1_step, p2_step, p3_step;
|
||||
GPUVertBufRaw colid_step, muted_step;
|
||||
GPUVertBufRaw dim_factor_step;
|
||||
GPUVertBufRaw thickness_step;
|
||||
GPUVertBufRaw dash_factor_step;
|
||||
uint count;
|
||||
bool enabled;
|
||||
} g_batch_link;
|
||||
|
@ -3956,6 +3958,8 @@ static void nodelink_batch_reset()
|
|||
g_batch_link.inst_vbo, g_batch_link.dim_factor_id, &g_batch_link.dim_factor_step);
|
||||
GPU_vertbuf_attr_get_raw_data(
|
||||
g_batch_link.inst_vbo, g_batch_link.thickness_id, &g_batch_link.thickness_step);
|
||||
GPU_vertbuf_attr_get_raw_data(
|
||||
g_batch_link.inst_vbo, g_batch_link.dash_factor_id, &g_batch_link.dash_factor_step);
|
||||
g_batch_link.count = 0;
|
||||
}
|
||||
|
||||
|
@ -4077,6 +4081,8 @@ static void nodelink_batch_init()
|
|||
&format_inst, "dim_factor", GPU_COMP_F32, 1, GPU_FETCH_FLOAT);
|
||||
g_batch_link.thickness_id = GPU_vertformat_attr_add(
|
||||
&format_inst, "thickness", GPU_COMP_F32, 1, GPU_FETCH_FLOAT);
|
||||
g_batch_link.dash_factor_id = GPU_vertformat_attr_add(
|
||||
&format_inst, "dash_factor", GPU_COMP_F32, 1, GPU_FETCH_FLOAT);
|
||||
g_batch_link.inst_vbo = GPU_vertbuf_create_with_format_ex(&format_inst, GPU_USAGE_STREAM);
|
||||
/* Alloc max count but only draw the range we need. */
|
||||
GPU_vertbuf_data_alloc(g_batch_link.inst_vbo, NODELINK_GROUP_SIZE);
|
||||
|
@ -4154,7 +4160,8 @@ static void nodelink_batch_add_link(const SpaceNode *snode,
|
|||
bool drawarrow,
|
||||
bool drawmuted,
|
||||
float dim_factor,
|
||||
float thickness)
|
||||
float thickness,
|
||||
float dash_factor)
|
||||
{
|
||||
/* Only allow these colors. If more is needed, you need to modify the shader accordingly. */
|
||||
BLI_assert(ELEM(th_col1, TH_WIRE_INNER, TH_WIRE, TH_ACTIVE, TH_EDGE_SELECT, TH_REDALERT));
|
||||
|
@ -4175,6 +4182,7 @@ static void nodelink_batch_add_link(const SpaceNode *snode,
|
|||
muted[0] = drawmuted;
|
||||
*(float *)GPU_vertbuf_raw_step(&g_batch_link.dim_factor_step) = dim_factor;
|
||||
*(float *)GPU_vertbuf_raw_step(&g_batch_link.thickness_step) = thickness;
|
||||
*(float *)GPU_vertbuf_raw_step(&g_batch_link.dash_factor_step) = dash_factor;
|
||||
|
||||
if (g_batch_link.count == NODELINK_GROUP_SIZE) {
|
||||
nodelink_batch_draw(snode);
|
||||
|
@ -4191,10 +4199,13 @@ void node_draw_link_bezier(const View2D *v2d,
|
|||
{
|
||||
const float dim_factor = node_link_dim_factor(v2d, link);
|
||||
float thickness = 1.5f;
|
||||
float dash_factor = 1.0f;
|
||||
if (snode->edittree->type == NTREE_GEOMETRY) {
|
||||
if (link->fromsock && link->fromsock->display_shape == SOCK_DISPLAY_SHAPE_DIAMOND) {
|
||||
/* Make field links a bit thinner. */
|
||||
thickness = 1.0f;
|
||||
/* Draw field as dashes. */
|
||||
dash_factor = 0.75f;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -4221,7 +4232,8 @@ void node_draw_link_bezier(const View2D *v2d,
|
|||
drawarrow,
|
||||
drawmuted,
|
||||
dim_factor,
|
||||
thickness);
|
||||
thickness,
|
||||
dash_factor);
|
||||
}
|
||||
else {
|
||||
/* Draw single link. */
|
||||
|
@ -4248,6 +4260,7 @@ void node_draw_link_bezier(const View2D *v2d,
|
|||
GPU_batch_uniform_1i(batch, "doMuted", drawmuted);
|
||||
GPU_batch_uniform_1f(batch, "dim_factor", dim_factor);
|
||||
GPU_batch_uniform_1f(batch, "thickness", thickness);
|
||||
GPU_batch_uniform_1f(batch, "dash_factor", dash_factor);
|
||||
GPU_batch_draw(batch);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,11 +1,41 @@
|
|||
|
||||
in float colorGradient;
|
||||
in vec4 finalColor;
|
||||
in float lineU;
|
||||
flat in float lineLength;
|
||||
flat in float dashFactor;
|
||||
flat in int isMainLine;
|
||||
|
||||
out vec4 fragColor;
|
||||
|
||||
#define DASH_WIDTH 20.0
|
||||
#define ANTIALIAS 1.0
|
||||
|
||||
void main()
|
||||
{
|
||||
fragColor = finalColor;
|
||||
|
||||
if ((isMainLine != 0) && (dashFactor < 1.0)) {
|
||||
float distance_along_line = lineLength * lineU;
|
||||
float normalized_distance = fract(distance_along_line / DASH_WIDTH);
|
||||
|
||||
/* Checking if `normalized_distance <= dashFactor` is already enough for a basic
|
||||
* dash, however we want to handle a nice antialias. */
|
||||
|
||||
float dash_center = DASH_WIDTH * dashFactor * 0.5;
|
||||
float normalized_distance_triangle =
|
||||
1.0 - abs((fract((distance_along_line - dash_center) / DASH_WIDTH)) * 2.0 - 1.0);
|
||||
float t = ANTIALIAS / DASH_WIDTH;
|
||||
float slope = 1.0 / (2.0 * t);
|
||||
|
||||
float alpha = min(1.0, max(0.0, slope * (normalized_distance_triangle - dashFactor + t)));
|
||||
|
||||
if (alpha < 0.0) {
|
||||
discard;
|
||||
}
|
||||
|
||||
fragColor.a *= 1.0 - alpha;
|
||||
}
|
||||
|
||||
fragColor.a *= smoothstep(1.0, 0.1, abs(colorGradient));
|
||||
}
|
||||
|
|
|
@ -20,6 +20,7 @@ in ivec4 colid_doarrow;
|
|||
in ivec2 domuted;
|
||||
in float dim_factor;
|
||||
in float thickness;
|
||||
in float dash_factor;
|
||||
|
||||
uniform vec4 colors[6];
|
||||
|
||||
|
@ -43,6 +44,7 @@ uniform bool doArrow;
|
|||
uniform bool doMuted;
|
||||
uniform float dim_factor;
|
||||
uniform float thickness;
|
||||
uniform float dash_factor;
|
||||
|
||||
# define colShadow colors[0]
|
||||
# define colStart colors[1]
|
||||
|
@ -56,9 +58,21 @@ uniform mat4 ModelViewProjectionMatrix;
|
|||
|
||||
out float colorGradient;
|
||||
out vec4 finalColor;
|
||||
out float lineU;
|
||||
flat out float lineLength;
|
||||
flat out float dashFactor;
|
||||
flat out int isMainLine;
|
||||
|
||||
void main(void)
|
||||
{
|
||||
/* Parameters for the dashed line. */
|
||||
isMainLine = expand.y != 1.0 ? 0 : 1;
|
||||
dashFactor = dash_factor;
|
||||
/* Approximate line length, no need for real bezier length calculation. */
|
||||
lineLength = distance(P0, P3);
|
||||
/* TODO: Incorrect U, this leads to non-uniform dash distribution. */
|
||||
lineU = uv.x;
|
||||
|
||||
float t = uv.x;
|
||||
float t2 = t * t;
|
||||
float t2_3 = 3.0 * t2;
|
||||
|
|
Loading…
Reference in New Issue