Sdf2d
Sdf2d
is a std lib in Makepad use GLSL
(glsl|glslang)
#![allow(unused)] fn main() { /// Sdf2d结构体使用glsl /// Sdf2d struct use glsl Sdf2d = struct { // Fields of the Sdf2d struct field pos: vec2 // Current position 当前位置 field result: vec4 // Result color 最终的颜色 field last_pos: vec2 // Last position in path 路径中的最后一个位置 field start_pos: vec2 // Start position in path 路径中的初始的位置 field shape: float // Shape distance 形状 field clip: float // Clipping distance 裁剪长度 field has_clip: float // Clip flag 是否被裁剪(0.0 is false) field old_shape: float // Previous shape distance 上一个形状 field blur: float // Blur amount 模糊量 field aa: float // Anti-aliasing factor 抗锯齿因子 field scale_factor: float // Scaling factor 比例因子 field dist: float // Distance to shape 到形状的距离 // Calculate anti-aliasing factor based on the derivative of the position // 根据位置的导数计算抗锯齿因子 fn antialias(p: vec2) -> float { return 1.0 / length(vec2(length(dFdx(p)), length(dFdy(p)))); } // Initialize a new Sdf2d struct with the given position // 使用给定位置初始化新的Sdf2d结构 fn viewport(pos: vec2) -> Self { return Self { pos: pos result: vec4(0.) last_pos: vec2(0.) start_pos: vec2(0.) shape: 1e+20 clip: -1e+20 has_clip: 0.0 old_shape: 1e+20 blur: 0.00001 aa: antialias(pos) scale_factor: 1.0 dist: 0.0 }; } // Translate the current position by (x, y) // 将当前位置平移(x,y) fn translate(inout self, x: float, y: float) -> vec2 { self.pos -= vec2(x, y); return self.pos; } // Rotate the current position around (x, y) by angle a // 将当前位置绕(x,y)旋转角度a fn rotate(inout self, a: float, x: float, y: float) { let ca = cos(-a); let sa = sin(-a); let p = self.pos - vec2(x, y); self.pos = vec2(p.x * ca - p.y * sa, p.x * sa + p.y * ca) + vec2(x, y); } // Scale the current position relative to (x, y) by factor f // 按因子f相对于(x,y)缩放当前位置 fn scale(inout self, f: float, x: float, y: float) { self.scale_factor *= f; self.pos = (self.pos - vec2(x, y)) * f + vec2(x, y); } // Clear the result color with the given color // 使用给定的颜色清除结果颜色 fn clear(inout self, color: vec4) { self.result = vec4(color.rgb * color.a + self.result.rgb * (1.0 - color.a), color.a); } // Calculate blur based on width w // 根据宽度w计算模糊 fn calc_blur(inout self, w: float) -> float { let wa = clamp(-w * self.aa, 0.0, 1.0); let wb = 1.0; if self.blur > 0.001 { wb = clamp(-w / self.blur, 0.0, 1.0); } return wa * wb; } // Fill the current shape with premultiplied alpha, keeping the previous fill // 使用预乘的alpha填充当前形状,保持先前的填充 fn fill_keep_premul(inout self, source: vec4) -> vec4 { let f = self.calc_blur(self.shape); self.result = source * f + self.result * (1. - source.a * f); if self.has_clip > 0.5 { let f2 = 1.0 - self.calc_blur(-self.clip); self.result = source * f2 + self.result * (1. - source.a * f2); } return self.result; } // Fill the current shape with premultiplied alpha and reset the shape // 用预乘的alpha填充当前形状并重置形状 fn fill_premul(inout self, color: vec4) -> vec4 { self.fill_keep_premul(color); self.old_shape = self.shape = 1e+20; self.clip = -1e+20; self.has_clip = 0.; return self.result; } // Fill the current shape, keeping the previous fill // 填充当前形状,保留以前的填充 fn fill_keep(inout self, color: vec4) -> vec4 { return self.fill_keep_premul(vec4(color.rgb * color.a, color.a)); } // Fill the current shape and reset the shape // 填充当前形状并重置形状 fn fill(inout self, color: vec4) -> vec4 { return self.fill_premul(vec4(color.rgb * color.a, color.a)); } // Stroke the current shape, keeping the previous stroke // 笔划当前形状,保持上一个笔划 fn stroke_keep(inout self, color: vec4, width: float) -> vec4 { let f = self.calc_blur(abs(self.shape) - width / self.scale_factor); let source = vec4(color.rgb * color.a, color.a); let dest = self.result; self.result = source * f + dest * (1.0 - source.a * f); return self.result; } // Stroke the current shape and reset the shape // 笔划当前形状并重置形状 fn stroke(inout self, color: vec4, width: float) -> vec4 { self.stroke_keep(color, width); self.old_shape = self.shape = 1e+20; self.clip = -1e+20; self.has_clip = 0.; return self.result; } // Glow the current shape, keeping the previous glow fn glow_keep(inout self, color: vec4, width: float) -> vec4 { let f = self.calc_blur(abs(self.shape) - width / self.scale_factor); let source = vec4(color.rgb * color.a, color.a); let dest = self.result; self.result = vec4(source.rgb * f, 0.) + dest; return self.result; } // Glow the current shape and reset the shape fn glow(inout self, color: vec4, width: float) -> vec4 { self.glow_keep(color, width); self.old_shape = self.shape = 1e+20; self.clip = -1e+20; self.has_clip = 0.; return self.result; } // Union the current shape with the previous shape // 将当前形状与上一个形状合并 fn union(inout self) { self.old_shape = self.shape = min(self.dist, self.old_shape); } // Intersect the current shape with the previous shape fn intersect(inout self) { self.old_shape = self.shape = max(self.dist, self.old_shape); } // Subtract the current shape from the previous shape fn subtract(inout self) { self.old_shape = self.shape = max(-self.dist, self.old_shape); } // Apply a gloop effect to the current shape with factor k fn gloop(inout self, k: float) { let h = clamp(0.5 + 0.5 * (self.old_shape - self.dist) / k, 0.0, 1.0); self.old_shape = self.shape = mix(self.old_shape, self.dist, h) - k * h * (1.0 - h); } // Blend the current shape with the previous shape using factor k fn blend(inout self, k: float) { self.old_shape = self.shape = mix(self.old_shape, self.dist, k); } // Draw a circle at (x, y) with radius r fn circle(inout self, x: float, y: float, r: float) { let c = self.pos - vec2(x, y); let len = sqrt(c.x * c.x + c.y * c.y); self.dist = (len - r) / self.scale_factor; self.old_shape = self.shape; self.shape = min(self.shape, self.dist); } // Draw an arc at (x, y) with radius r from angle s to e fn arc2(inout self, x: float, y: float, r: float, s: float, e: float) -> vec4 { let c = self.pos - vec2(x, y); let pi = 3.141592653589793; // PI constant // Calculate angle let ang = (atan(c.y, c.x) + pi) / (2.0 * pi); let ces = (e - s) * 0.5; let ang2 = 1.0 - abs(ang - ces) + ces; return mix(vec4(0., 0., 0., 1.0), vec4(1.0), ang2); } // Draw a horizontal line at y with half height h fn hline(inout self, y: float, h: float) { let c = self.pos.y - y; self.dist = -h + abs(c) / self.scale_factor; self.old_shape = self.shape; self.shape = min(self.shape, self.dist); } // Draw a rounded box at (x, y) with width w, height h, and radius r // 在(x,y)处绘制一个宽度为w、高度为h、半径为r的圆角框 fn box(inout self, x: float, y: float, w: float, h: float, r: float) { let p = self.pos - vec2(x, y); let size = vec2(0.5 * w, 0.5 * h); let bp = max(abs(p - size.xy) - (size.xy - vec2(2. * r, 2. * r).xy), vec2(0., 0.)); self.dist = (length(bp) - 2. * r) / self.scale_factor; self.old_shape = self.shape; self.shape = min(self.shape, self.dist); } // Draw a box with different radii for top and bottom corners fn box_y(inout self, x: float, y: float, w: float, h: float, r_top: float, r_bottom: float) { let size = vec2(0.5 * w, 0.5 * h); let p_r = self.pos - vec2(x, y); let p = abs(p_r - size.xy) - size.xy; let bp_top = max(p + vec2(2. * r_top, 2. * r_top).xy, vec2(0., 0.)); let bp_bottom = max(p + vec2(2. * r_bottom, 2. * r_bottom).xy, vec2(0., 0.)); self.dist = mix( (length(bp_top) - 2. * r_top), (length(bp_bottom) - 2. * r_bottom), step(0.5 * h, p_r.y) ) / self.scale_factor; self.old_shape = self.shape; self.shape = min(self.shape, self.dist); } // Draw a box with different radii for left and right corners fn box_x(inout self, x: float, y: float, w: float, h: float, r_left: float, r_right: float) { let size = vec2(0.5 * w, 0.5 * h); let p_r = self.pos - vec2(x, y); let p = abs(p_r - size.xy) - size.xy; let bp_left = max(p + vec2(2. * r_left, 2. * r_left).xy, vec2(0., 0.)); let bp_right = max(p + vec2(2. * r_right, 2. * r_right).xy, vec2(0., 0.)); self.dist = mix( (length(bp_left) - 2. * r_left), (length(bp_right) - 2. * r_right), step(0.5 * w, p_r.x) ) / self.scale_factor; self.old_shape = self.shape; self.shape = min(self.shape, self.dist); } // Draw a box with different radii for each corner fn box_all( inout self, x: float, y: float, w: float, h: float, r_left_top: float, r_right_top: float, r_right_bottom: float, r_left_bottom: float ) { let size = vec2(0.5 * w, 0.5 * h); let p_r = self.pos - vec2(x, y); let p = abs(p_r - size.xy) - size.xy; let bp_lt = max(p + vec2(2. * r_left_top, 2. * r_left_top).xy, vec2(0., 0.)); let bp_rt = max(p + vec2(2. * r_right_top, 2. * r_right_top).xy, vec2(0., 0.)); let bp_rb = max(p + vec2(2. * r_right_bottom, 2. * r_right_bottom).xy, vec2(0., 0.)); let bp_lb = max(p + vec2(2. * r_left_bottom, 2. * r_left_bottom).xy, vec2(0., 0.)); self.dist = mix( mix( (length(bp_lt) - 2. * r_left_top), (length(bp_lb) - 2. * r_left_bottom), step(0.5 * h, p_r.y) ), mix( (length(bp_rt) - 2. * r_right_top), (length(bp_rb) - 2. * r_right_bottom), step(0.5 * h, p_r.y) ), step(0.5 * w, p_r.x) ) / self.scale_factor; self.old_shape = self.shape; self.shape = min(self.shape, self.dist); } // Draw a rectangle at (x, y) with width w and height h fn rect(inout self, x: float, y: float, w: float, h: float) { let s = vec2(w, h) * 0.5; let d = abs(vec2(x, y) - self.pos + s) - s; let dm = min(d, vec2(0., 0.)); self.dist = max(dm.x, dm.y) + length(max(d, vec2(0., 0.))); self.old_shape = self.shape; self.shape = min(self.shape, self.dist); } // Draw a hexagon at (x, y) with radius r fn hexagon(inout self, x: float, y: float, r: float) { let dx = abs(x - self.pos.x) * 1.15; let dy = abs(y - self.pos.y); self.dist = max(dy + cos(60.0 * TORAD) * dx - r, dx - r); self.old_shape = self.shape; self.shape = min(self.shape, self.dist); } // Move to position (x, y) without drawing fn move_to(inout self, x: float, y: float) { self.last_pos = self.start_pos = vec2(x, y); } // Draw a line to position (x, y) fn line_to(inout self, x: float, y: float) { let p = vec2(x, y); let pa = self.pos - self.last_pos; let ba = p - self.last_pos; let h = clamp(dot(pa, ba) / dot(ba, ba), 0.0, 1.0); let s = sign(pa.x * ba.y - pa.y * ba.x); self.dist = length(pa - ba * h) / self.scale_factor; self.old_shape = self.shape; self.shape = min(self.shape, self.dist); self.clip = max(self.clip, self.dist * s); self.has_clip = 1.0; self.last_pos = p; } // Close the current path fn close_path(inout self) { self.line_to(self.start_pos.x, self.start_pos.y); } } }