Skip to content

Commit

Permalink
update GLMakie lines
Browse files Browse the repository at this point in the history
  • Loading branch information
ffreyer committed Jun 16, 2024
1 parent 078f3ed commit a330d4f
Show file tree
Hide file tree
Showing 5 changed files with 57 additions and 28 deletions.
7 changes: 2 additions & 5 deletions GLMakie/assets/shader/line_segment.geom
Original file line number Diff line number Diff line change
Expand Up @@ -89,7 +89,6 @@ void main(void)
// get start and end point of line segment
// restrict to visible area (see lines.geom)
vec3 p1, p2;
vec2 clip_factor = vec2(0);
{
vec4 _p1 = gl_in[0].gl_Position, _p2 = gl_in[1].gl_Position;

Expand All @@ -106,12 +105,10 @@ void main(void)
vec4 v1 = _p2 - _p1;

if (_p1.w < 0.0) {
clip_factor.x = (-_p1.w - _p1.z) / (v1.z + v1.w);
_p1 = _p1 + clip_factor.x * v1;
_p1 = _p1 + (-_p1.w - _p1.z) / (v1.z + v1.w) * v1;
}
if (_p2.w < 0.0) {
clip_factor.y = (-_p2.w - _p2.z) / (v1.z + v1.w);
_p2 = _p2 + clip_factor.y * v1;
_p2 = _p2 + (-_p2.w - _p2.z) / (v1.z + v1.w) * v1;
}

// clip -> pixel/screen projection
Expand Down
45 changes: 44 additions & 1 deletion GLMakie/assets/shader/lines.geom
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,10 @@ uniform int linecap;
uniform int joinstyle;
uniform float miter_limit;

uniform mat4 view, projection, projectionview;
uniform int _num_clip_planes;
uniform vec4 clip_planes[8];

// Constants
const float AA_RADIUS = 0.8;
const float AA_THICKNESS = 4.0 * AA_RADIUS;
Expand Down Expand Up @@ -90,6 +94,35 @@ vec2 normal_vector(in vec2 v) { return vec2(-v.y, v.x); }
vec2 normal_vector(in vec3 v) { return vec2(-v.y, v.x); }
float sign_no_zero(float value) { return value >= 0.0 ? 1.0 : -1.0; }

bool process_clip_planes(inout vec4 p1, inout vec4 p2, inout bool[4] isvalid)
{
float d1, d2;
for(int i = 0; i < _num_clip_planes; i++)
{
// distance from clip planes with negative clipped
d1 = dot(p1.xyz, clip_planes[i].xyz) - clip_planes[i].w;
d2 = dot(p2.xyz, clip_planes[i].xyz) - clip_planes[i].w;

// both outside - clip everything
if (d1 < 0.0 && d2 < 0.0) {
p2 = p1;
isvalid[1] = false;
isvalid[2] = false;
return true;
// one outside - shorten segment
} else if (d1 < 0.0) {
// solve 0 = m * t + b = (d2 - d1) * t + d1 with t in (0, 1)
p1 = p1 - d1 * (p2 - p1) / (d2 - d1);
isvalid[0] = false;
} else if (d2 < 0.0) {
p2 = p2 - d2 * (p1 - p2) / (d1 - d2);
isvalid[3] = false;
}
}

return false;
}


////////////////////////////////////////////////////////////////////////////////
// Linestyle Support //
Expand Down Expand Up @@ -231,12 +264,22 @@ void main(void)
// moving them to the edge of the visible area.
vec3 p0, p1, p2, p3;
{
// All in clip space
// Not in clip space yet
vec4 clip_p0 = gl_in[0].gl_Position; // start of previous segment
vec4 clip_p1 = gl_in[1].gl_Position; // end of previous segment, start of current segment
vec4 clip_p2 = gl_in[2].gl_Position; // end of current segment, start of next segment
vec4 clip_p3 = gl_in[3].gl_Position; // end of next segment

// Shorten segments to fit clip planes
// returns true if segments are fully clipped
if (process_clip_planes(clip_p1, clip_p2, isvalid))
return;

clip_p0 = projectionview * clip_p0;
clip_p1 = projectionview * clip_p1;
clip_p2 = projectionview * clip_p2;
clip_p3 = projectionview * clip_p3;

vec4 v1 = clip_p2 - clip_p1;

// With our perspective projection matrix clip.w = -view.z with
Expand Down
24 changes: 3 additions & 21 deletions GLMakie/assets/shader/lines.vert
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ in float lastlen;
{{thickness_type}} thickness;
{{color_type}} color;

uniform mat4 projectionview, model;
uniform mat4 inverse_projectionview, model;
uniform uint objectid;
uniform int total_length;
uniform float px_per_unit;
Expand All @@ -34,22 +34,6 @@ int get_valid_vertex(Nothing se){return 1;}

uniform float depth_shift;

uniform int num_clip_planes;
uniform vec4 clip_planes[8];
out float g_clip_distance[8];

void process_clip_planes(vec3 world_pos)
{
// distance = dot(world_pos - plane.point, plane.normal)
// precalculated: dot(plane.point, plane.normal) -> plane.w
for (int i = 0; i < num_clip_planes; i++)
g_clip_distance[i] = dot(world_pos, clip_planes[i].xyz) - clip_planes[i].w;

// TODO: can be skipped?
for (int i = num_clip_planes; i < 8; i++)
g_clip_distance[i] = 1.0;
}

void main()
{
g_lastlen = lastlen;
Expand All @@ -59,12 +43,10 @@ void main()
g_thickness = px_per_unit * thickness;

g_color = color;
vec4 world_pos = model * to_vec4(vertex);
process_clip_planes(world_pos.xyz);
#ifdef FAST_PATH
gl_Position = projectionview * world_pos;
gl_Position = model * to_vec4(vertex);
#else
gl_Position = to_vec4(vertex);
gl_Position = inverse_projectionview * to_vec4(vertex);
#endif
gl_Position.z += gl_Position.w * depth_shift;
}
5 changes: 5 additions & 0 deletions GLMakie/src/drawing_primitives.jl
Original file line number Diff line number Diff line change
Expand Up @@ -474,6 +474,11 @@ function draw_atomic(screen::Screen, scene::Scene, @nospecialize(plot::Lines))
Vec2f(ppu * origin(viewport))
end

# Handled manually without using OpenGL clipping
data[:_num_clip_planes] = pop!(data, :num_clip_planes)
data[:num_clip_planes] = Observable(0)
data[:inverse_projectionview] = map(inv, data[:projectionview])

space = plot.space
if isnothing(to_value(linestyle))
data[:pattern] = nothing
Expand Down
4 changes: 3 additions & 1 deletion src/utilities/Plane.jl
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,9 @@ struct Plane{N, T}
distance::T
end

Plane(point::Point{N}, normal::Vec{N}) where N = Plane(normal, dot(point, normal))
function Plane(point::Point{N}, normal::Vec{N}) where N
Plane(normal, dot(point, normal))
end

const Plane2{T} = Plane{2, T}
const Plane3{T} = Plane{3, T}
Expand Down

0 comments on commit a330d4f

Please sign in to comment.