Skip to content

Commit

Permalink
prototyping
Browse files Browse the repository at this point in the history
  • Loading branch information
ffreyer committed Jan 16, 2024
1 parent 3917891 commit 0c2441a
Show file tree
Hide file tree
Showing 6 changed files with 452 additions and 786 deletions.
91 changes: 91 additions & 0 deletions GLMakie/assets/shader/line_segments.frag
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
{{GLSL_VERSION}}
{{GLSL_EXTENSIONS}}
{{SUPPORTED_EXTENSIONS}}

struct Nothing{ //Nothing type, to encode if some variable doesn't contain any data
bool _; //empty structs are not allowed
};

in vec4 f_color;
in vec2 f_uv;
in float f_thickness;
flat in uvec2 f_id;
flat in vec2 f_uv_minmax;
{{pattern_type}} pattern;

uniform float pattern_length;
uniform bool fxaa;

// Half width of antialiasing smoothstep
#define ANTIALIAS_RADIUS 0.8

float aastep(float threshold1, float dist) {
return smoothstep(threshold1-ANTIALIAS_RADIUS, threshold1+ANTIALIAS_RADIUS, dist);
}

float aastep(float threshold1, float threshold2, float dist) {
// We use 2x pixel space in the geometry shaders which passes through
// in uv.y, so we need to treat it here by using 2 * ANTIALIAS_RADIUS
float AA = 2 * ANTIALIAS_RADIUS;
return smoothstep(threshold1 - AA, threshold1 + AA, dist) -
smoothstep(threshold2 - AA, threshold2 + AA, dist);
}

float aastep_scaled(float threshold1, float threshold2, float dist) {
float AA = ANTIALIAS_RADIUS / pattern_length;
return smoothstep(threshold1 - AA, threshold1 + AA, dist) -
smoothstep(threshold2 - AA, threshold2 + AA, dist);
}


void write2framebuffer(vec4 color, uvec2 id);

// Signed distance fields for lines
// x/y pattern
float get_sd(sampler2D pattern, vec2 uv){
return texture(pattern, uv).x;
}

// x pattern
vec2 get_sd(sampler1D pattern, vec2 uv){
return vec2(texture(pattern, uv.x).x, uv.y);
}

// normal line type
// Note that this just returns uv, so get full manual control in geom shader
vec2 get_sd(Nothing _, vec2 uv){
return uv;
}

void main(){
vec4 color = vec4(f_color.rgb, 0.0);
vec2 xy = get_sd(pattern, f_uv);

float alpha, alpha2, alpha3;
if (!fxaa) {
alpha = aastep(0.0, xy.x);
alpha2 = aastep(-f_thickness, f_thickness, xy.y);
alpha3 = aastep_scaled(f_uv_minmax.x, f_uv_minmax.y, f_uv.x);
} else {
alpha = step(0.0, xy.x);
alpha2 = step(-f_thickness, xy.y) - step(f_thickness, xy.y);
alpha3 = step(f_uv_minmax.x, f_uv.x) - step(f_uv_minmax.y, f_uv.x);
}

color = vec4(f_color.rgb, f_color.a * alpha * alpha2 * alpha3);

// Debug: Show uv values in line direction (repeating)
// color = vec4(mod(f_uv.x, 1.0), 0, 0, 1);

// Debug: Show uv values in line direction with pattern
// color.r = 0.5;
// color.g = mod(f_uv.x, 1.0);
// color.b = mod(f_uv.x, 1.0);
// color.a = 0.2 + 0.8 * color.a;

// Debug: Show AA padding in red
// color.r = 1 - color.a;
// color.a = 0.5 + 0.5 * color.a;

write2framebuffer(color, f_id);
}
188 changes: 137 additions & 51 deletions GLMakie/assets/shader/lines.frag
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,17 @@ struct Nothing{ //Nothing type, to encode if some variable doesn't contain any d
};

in vec4 f_color;
in vec2 f_uv;
in float f_thickness;
in vec3 f_quad_sdf;
in vec2 f_joint_cutoff;
in float f_line_width;
in float f_cumulative_length;
flat in uvec2 f_id;
flat in vec2 f_uv_minmax;

// in vec2 f_rect_sdf;
// in vec2 f_joint_smooth;
// flat in float f_line_length;
// flat in float f_line_offset;

{{pattern_type}} pattern;

uniform float pattern_length;
Expand All @@ -23,69 +30,148 @@ float aastep(float threshold1, float dist) {
return smoothstep(threshold1-ANTIALIAS_RADIUS, threshold1+ANTIALIAS_RADIUS, dist);
}

float aastep(float threshold1, float threshold2, float dist) {
// We use 2x pixel space in the geometry shaders which passes through
// in uv.y, so we need to treat it here by using 2 * ANTIALIAS_RADIUS
float AA = 2 * ANTIALIAS_RADIUS;
return smoothstep(threshold1 - AA, threshold1 + AA, dist) -
smoothstep(threshold2 - AA, threshold2 + AA, dist);
// Pattern sampling
float get_pattern_sdf(sampler2D pattern, vec2 uv){
// make this texture repeating
// TODO
// vec2 uv2 = vec2((uv.x + f_line_offset) / pattern_length, 0.5 * uv.y / f_line_width);
return texture(pattern, uv).x;
}

float aastep_scaled(float threshold1, float threshold2, float dist) {
float AA = ANTIALIAS_RADIUS / pattern_length;
return smoothstep(threshold1 - AA, threshold1 + AA, dist) -
smoothstep(threshold2 - AA, threshold2 + AA, dist);
float get_pattern_sdf(sampler1D pattern, vec2 uv){
// make this texture repeating
return texture(pattern, uv.x / pattern_length).x;
}
float get_pattern_sdf(Nothing _, vec2 uv){
return -10.0;
}


void write2framebuffer(vec4 color, uvec2 id);

// Signed distance fields for lines
// x/y pattern
float get_sd(sampler2D pattern, vec2 uv){
return texture(pattern, uv).x;
}

// x pattern
vec2 get_sd(sampler1D pattern, vec2 uv){
return vec2(texture(pattern, uv.x).x, uv.y);
}

// normal line type
// Note that this just returns uv, so get full manual control in geom shader
vec2 get_sd(Nothing _, vec2 uv){
return uv;
}
#define DEBUG

void main(){
vec4 color = vec4(f_color.rgb, 0.0);
vec2 xy = get_sd(pattern, f_uv);
// Metrics we need:
// line length for pattern
// line width sdf w/ AA
// line start/end/truncation sdf w/ AA
// hard join edge sdf


// New version

#ifndef DEBUG
// We effectively start with a rectangle that's fully drawn, i.e. sdf < 0

// Remove overlap of rects at joint
// things that need to be cut have sdf >= 0
if (max(f_joint_cutoff.x, f_joint_cutoff.y) >= 0.0)
discard;

// smoothly cut out line start, end and edge of truncated joint (if applicable)
float sdf = max(f_quad_sdf.x, f_quad_sdf.y);

// smoothly cut out edges at +- 0.5 * line width
sdf = max(sdf, abs(f_quad_sdf.z) - f_line_width);

// draw
vec4 color = f_color;

float alpha, alpha2, alpha3;
if (!fxaa) {
alpha = aastep(0.0, xy.x);
alpha2 = aastep(-f_thickness, f_thickness, xy.y);
alpha3 = aastep_scaled(f_uv_minmax.x, f_uv_minmax.y, f_uv.x);
color.a *= aastep(0.0, -sdf);
} else {
alpha = step(0.0, xy.x);
alpha2 = step(-f_thickness, xy.y) - step(f_thickness, xy.y);
alpha3 = step(f_uv_minmax.x, f_uv.x) - step(f_uv_minmax.y, f_uv.x);
color.a *= step(0.0, -sdf);
}

// float aa = aastep(0.0, sdf);
// vec4 color = vec4(0.0, 0.7, 0.1, 1);
// color.rgb = mix(color.rgb, vec3(1,0,0), aa);

#endif


// 1. and 2. probably not mergeable because 2 needs to be an actual sdf that
// can be cut off smoothly

// discard join edge
// seems like a vert/geom shader thing
// if (f_joint_cutoff.x > 0.0 || f_joint_cutoff.y > 0.0) {
// // discard;
// }

// signed distance to edge of rect (line without join)
// - start/end need rect_sdf to be 0 at p1/p2 (could be done with f_joint_smooth)
// - pattern needs rect_sdf to be 0 at p1
// - joins need rect_sdf to extend/ignore x
// ^- probably possible by merging sdfs correctly?
// - max(min(rect.x, smooth.x), min(rect.x, smooth.y))?
// - yea but necessitates smooth >= 0.0 outside of rect sdf
// float sdf = max(abs(f_rect_sdf.x) - f_line_length, abs(f_rect_sdf.y) - f_line_width);

// smooth out truncated join
// sdf = max(sdf, dot(gl_Position.xy - P1, miter_n_a) - miter_a_offset);
// sdf = max(sdf, max(f_joint_smooth.x, f_joint_smooth.y));

// fix up line pattern fetch
// float pattern_sdf = texture(pattern, mod(f_rect_sdf.x + line_length_offset, pattern_length) / pattern_length );
// sdf = max(sdf, get_pattern_sdf(pattern, f_rect_sdf));

// draw
// vec4 color = f_color;

// if (fxaa)
// color.a *= aastep(0.0, sdf);
// else
// color.a *= step(0.0, sdf);




#ifdef DEBUG
// show geom in white
vec4 color = vec4(1, 1, 1, 0.5);

// show line smooth clipping from quad_sdf
float sdf_width = abs(f_quad_sdf.z) - f_line_width;
color.r = 0.9 - 0.5 * aastep(0.0, sdf_width);
color.b = 0.9 - 0.5 * aastep(0.0, f_quad_sdf.y);
color.g = 0.9 - 0.5 * aastep(0.0, f_quad_sdf.x);

// show how the joint overlap is cut off
if (max(f_joint_cutoff.x, f_joint_cutoff.y) > 0.0) {
color.r += 0.3;
color.gb -= vec2(0.3);
}
#endif

color = vec4(f_color.rgb, f_color.a * alpha * alpha2 * alpha3);

// Debug: Show uv values in line direction (repeating)
// color = vec4(mod(f_uv.x, 1.0), 0, 0, 1);
/*
// show geom in black
vec4 color = vec4(0,0,0,0.6);
// Debug: Show uv values in line direction with pattern
// color.r = 0.5;
// color.g = mod(f_uv.x, 1.0);
// color.b = mod(f_uv.x, 1.0);
// color.a = 0.2 + 0.8 * color.a;
// show rect sdf in red
float rect = max(abs(f_rect_sdf.x) - f_line_length, abs(f_rect_sdf.y) - f_line_width);
color.r = 0.5 * aastep(0.0, -rect);
// Debug: Show AA padding in red
// color.r = 1 - color.a;
// color.a = 0.5 + 0.5 * color.a;
// sharp join cutoff - color yellow
// if (max(f_joint_cutoff.x, f_joint_cutoff.y) > 0.0) {
// color.rg += vec2(0.7);
// }
// smooth cutoff - mark in blue what's considered outside
color.b = aastep(0.0, min(f_joint_smooth.x, f_joint_smooth.y));
// what's inside that wasn't before?
// rect > 0 and smooth < 0
// color.b = aastep(0.0, f_joint_smooth.x);
// color.b = aastep(0.0, f_joint_smooth.y);
// color.g = 0.5 * aastep(0.0, f_joint_smooth.x);
// color.b = 0.5 * aastep(0.0, f_joint_smooth.y);
// float smooth_join = max(min(rect.x, f_joint_smooth.x), min(rect.x, f_joint_smooth.y));
// color.rg = vec2(0.5, 0.5) * aastep(0.0, smooth_join);
*/

write2framebuffer(color, f_id);
}
}
Loading

0 comments on commit 0c2441a

Please sign in to comment.