#include "constants.glsl"
+#include "rect.vert.glsl"
#ifndef _CLIP_
#define _CLIP_
}
#ifdef CLIP_ROUNDED_RECT
-vec4 clip(vec4 rect)
+
+vec4
+clip(vec4 rect)
{
/* rounded corner clipping is done in fragment shader */
return intersect(rect, push.clip_bounds);
}
+
+Rect
+clip_rect (vec4 xywh)
+{
+ /* rounded corner clipping is done in fragment shader */
+ return rect_intersect (rect_from_gsk (xywh), rect_to_int (rect_from_gsk (push.clip_bounds)));
+}
+
#elif defined(CLIP_RECT)
-vec4 clip(vec4 rect)
+
+vec4
+clip(vec4 rect)
{
return intersect(rect, push.clip_bounds);
}
+
+Rect
+clip_rect (vec4 xywh)
+{
+ return rect_intersect (rect_from_gsk (xywh), rect_to_int (rect_from_gsk (push.clip_bounds)));
+}
+
#elif defined(CLIP_NONE)
vec4 clip(vec4 rect)
{
return rect;
}
+
+Rect
+clip_rect (vec4 xywh)
+{
+ return rect_from_gsk (xywh);
+}
+
#else
#error "No clipping define given. Need CLIP_NONE, CLIP_RECT or CLIP_ROUNDED_RECT"
#endif
#version 420 core
#include "clip.frag.glsl"
+#include "rect.frag.glsl"
layout(location = 0) in vec2 inPos;
-layout(location = 1) in vec4 inColor;
+layout(location = 1) in Rect inRect;
+layout(location = 2) in vec4 inColor;
layout(location = 0) out vec4 color;
void main()
{
- color = clip (inPos, vec4(inColor.rgb * inColor.a, inColor.a));
+ float alpha = inColor.a * rect_coverage (inRect, inPos);
+ color = clip (inPos, vec4(inColor.rgb, 1) * alpha);
}
#version 420 core
#include "clip.vert.glsl"
+#include "rect.vert.glsl"
layout(location = 0) in vec4 inRect;
layout(location = 1) in vec4 inColor;
layout(location = 0) out vec2 outPos;
-layout(location = 1) out flat vec4 outColor;
+layout(location = 1) out flat Rect outRect;
+layout(location = 2) out flat vec4 outColor;
vec2 offsets[6] = { vec2(0.0, 0.0),
vec2(1.0, 0.0),
vec2(1.0, 1.0) };
void main() {
- vec4 rect = clip (inRect);
+ Rect rect = rect_to_int (clip_rect (inRect));
- vec2 pos = rect.xy + rect.zw * offsets[gl_VertexIndex];
+ vec2 pos = mix (rect.bounds.xy, rect.bounds.zw, offsets[gl_VertexIndex]);
gl_Position = push.mvp * vec4 (pos, 0.0, 1.0);
outPos = pos;
+ outRect = rect_from_gsk (inRect);
outColor = inColor;
}
'clip.frag.glsl',
'clip.vert.glsl',
'constants.glsl',
+ 'rect.glsl',
+ 'rect.frag.glsl',
+ 'rect.vert.glsl',
'rounded-rect.glsl',
]
--- /dev/null
+#ifndef _RECT_FRAG_
+#define _RECT_FRAG_
+
+#include "rect.glsl"
+
+float
+rect_coverage (Rect r, vec2 p)
+{
+ vec2 dFdp = abs(fwidth (p));
+ Rect prect = Rect(vec4(p - 0.5 * dFdp, p + 0.5 * dFdp));
+ Rect coverect = rect_intersect (r, prect);
+ vec2 coverage = rect_size(coverect) / dFdp;
+ return coverage.x * coverage.y;
+}
+
+#endif
--- /dev/null
+#ifndef _RECT_
+#define _RECT_
+
+struct Rect
+{
+ /* x,y and y,w make up the 2 points of this rect,
+ note that this is not containing width or height */
+ vec4 bounds;
+};
+
+Rect
+rect_from_gsk (vec4 xywh)
+{
+ return Rect(xywh.xyxy + vec4(0,0,xywh.zw));
+}
+
+float
+rect_distance (Rect r, vec2 p)
+{
+ vec4 distance = (r.bounds - p.xyxy) * vec4(1.0, 1.0, -1.0, -1.0);
+ vec2 max2 = max (distance.xy, distance.zw);
+ return length (max (max2, 0)) + min (max(max2.x, max2.y), 0);
+}
+
+vec2
+rect_size (Rect r)
+{
+ return r.bounds.zw - r.bounds.xy;
+}
+
+Rect
+rect_to_int (Rect r)
+{
+ return Rect (vec4 (floor(r.bounds.xy), ceil (r.bounds.zw)));
+}
+
+Rect
+rect_intersect (Rect a, Rect b)
+{
+ vec4 result = vec4(max(a.bounds.xy, b.bounds.xy), min(a.bounds.zw, b.bounds.zw));
+ if (any (greaterThanEqual (result.xy, result.zw)))
+ return Rect (vec4(0.0));
+ return Rect(result);
+}
+
+#endif
--- /dev/null
+#ifndef _RECT_VERT_
+#define _RECT_VERT_
+
+#include "rect.glsl"
+
+#endif