Warning, /frameworks/kquickcharts/src/shaders/sdf.glsl is written in an unsupported language. File is not indexed.

0001 // SPDX-FileCopyrightText: 2019 Arjen Hiemstra <ahiemstra@heimr.nl>
0002 // SPDX-FileCopyrightText: 2017 Inigo Quilez
0003 //
0004 // SPDX-License-Identifier: MIT
0005 //
0006 // This file is based on
0007 // https://iquilezles.org/www/articles/distfunctions2d/distfunctions2d.htm
0008 
0009 // A maximum point count to be used for sdf_polygon input arrays.
0010 // Unfortunately even function inputs require a fixed size at declaration time
0011 // for arrays, unless we were to use OpenGL 4.5.
0012 // Since the polygon is most likely to be defined in a uniform, this should be
0013 // at least less than MAX_FRAGMENT_UNIFORM_COMPONENTS / 2 (since we need vec2).
0014 #define SDF_POLYGON_MAX_POINT_COUNT 400
0015 
0016 // A constant for pi
0017 const lowp float pi = 3.1415926535897932384626433832795;
0018 
0019 /*********************************
0020     Shapes
0021 *********************************/
0022 
0023 // Distance field for a circle.
0024 //
0025 // \param point A point on the distance field.
0026 // \param radius The radius of the circle.
0027 //
0028 // \return The signed distance from point to the circle. If negative, point is
0029 //         inside the circle.
0030 lowp float sdf_circle(in lowp vec2 point, in lowp float radius)
0031 {
0032     return length(point) - radius;
0033 }
0034 
0035 // Distance field for a triangle.
0036 //
0037 // \param point A point on the distance field.
0038 // \param p0 The first vertex of the triangle.
0039 // \param p0 The second vertex of the triangle.
0040 // \param p0 The third vertex of the triangle.
0041 //
0042 // \note The ordering of the three vertices does not matter.
0043 //
0044 // \return The signed distance from point to triangle. If negative, point is
0045 //         inside the triangle.
0046 lowp float sdf_triangle(in lowp vec2 point, in lowp vec2 p0, in lowp vec2 p1, in lowp vec2 p2)
0047 {
0048     lowp vec2 e0 = p1 - p0;
0049     lowp vec2 e1 = p2 - p1;
0050     lowp vec2 e2 = p0 - p2;
0051 
0052     lowp vec2 v0 = point - p0;
0053     lowp vec2 v1 = point - p1;
0054     lowp vec2 v2 = point - p2;
0055 
0056     lowp vec2 pq0 = v0 - e0 * clamp( dot(v0, e0) / dot(e0, e0), 0.0, 1.0 );
0057     lowp vec2 pq1 = v1 - e1 * clamp( dot(v1, e1) / dot(e1, e1), 0.0, 1.0 );
0058     lowp vec2 pq2 = v2 - e2 * clamp( dot(v2, e2) / dot(e2, e2), 0.0, 1.0 );
0059 
0060     lowp float s = sign( e0.x*e2.y - e0.y*e2.x );
0061     lowp vec2 d = min(min(vec2(dot(pq0,pq0), s*(v0.x*e0.y-v0.y*e0.x)),
0062                           vec2(dot(pq1,pq1), s*(v1.x*e1.y-v1.y*e1.x))),
0063                           vec2(dot(pq2,pq2), s*(v2.x*e2.y-v2.y*e2.x)));
0064 
0065     return -sqrt(d.x)*sign(d.y);
0066 }
0067 
0068 #ifndef API_ES2
0069 // Distance field for an arbitrary polygon.
0070 //
0071 // \param point A point on the distance field.
0072 // \param vertices An array of points that make up the polygon.
0073 // \param count The amount of points to use for the polygon.
0074 //
0075 // \note points should be an array of vec2 of size SDF_POLYGON_MAX_POINT_COUNT.
0076 //       Use count to indicate how many items of that array should be used.
0077 //
0078 // \return The signed distance from point to triangle. If negative, point is
0079 //         inside the triangle.
0080 lowp float sdf_polygon(in lowp vec2 point, in lowp vec2[SDF_POLYGON_MAX_POINT_COUNT] vertices, in lowp int count)
0081 {
0082     lowp float d = dot(point - vertices[0], point - vertices[0]);
0083     lowp float s = 1.0;
0084     for (int i = 0, j = count - 1; i < count && i < SDF_POLYGON_MAX_POINT_COUNT; j = i, i++)
0085     {
0086         lowp vec2 e = vertices[j] - vertices[i];
0087         lowp vec2 w = point - vertices[i];
0088         lowp float h = clamp( dot(w, e) / dot(e, e), 0.0, 1.0 );
0089         lowp vec2 b = w - e * h;
0090         d = min(d, dot(b, b));
0091 
0092         bvec3 c = bvec3(point.y >= vertices[i].y, point.y < vertices[j].y, e.x * w.y > e.y * w.x);
0093         if(all(c) || all(not(c))) s *= -1.0;
0094     }
0095     return s * sqrt(d);
0096 }
0097 #endif
0098 
0099 // Distance field for a rectangle.
0100 //
0101 // \param point A point on the distance field.
0102 // \param rect A vec2 with the size of the rectangle.
0103 //
0104 // \return The signed distance from point to rectangle. If negative, point is
0105 //         inside the rectangle.
0106 lowp float sdf_rectangle(in lowp vec2 point, in lowp vec2 rect)
0107 {
0108     lowp vec2 d = abs(point) - rect;
0109     return length(max(d, 0.0)) + min(max(d.x, d.y), 0.0);
0110 }
0111 
0112 // Distance field for a torus segment.
0113 //
0114 // \param point A point on the distance field.
0115 // \param start The start angle in radians of the segment.
0116 // \param end The end angle in radians of the segment.
0117 // \param inner_radius The inner radius of the torus.
0118 // \param outer_radius The outer radius of the torus.
0119 //
0120 // \return The signed distance from point to the torus segment. If negative,
0121 //         point is inside the segment.
0122 lowp float sdf_torus_segment(in lowp vec2 point, in lowp float start, in lowp float end, in lowp float inner_radius, in lowp float outer_radius)
0123 {
0124     start = clamp(start, end - 2.0 * pi, end);
0125     end = clamp(end, start, start + 2.0 * pi);
0126 
0127     lowp float angle = (end - start) / 2.0;
0128     lowp float rotation = (start + end) / 2.0;
0129 
0130     lowp vec2 rotated = point * mat2(cos(rotation), -sin(rotation), sin(rotation), cos(rotation));
0131     lowp vec2 c = vec2(sin(angle), cos(angle));
0132 
0133     rotated.x = abs(rotated.x);
0134 
0135     lowp float t = (outer_radius - inner_radius) / 2.0;
0136     lowp float l = abs(length(rotated) - (inner_radius + t)) - t;
0137 
0138     lowp float m = length(rotated - c * clamp(dot(rotated, c), inner_radius, outer_radius));
0139     return max(l, m * sign(c.y * rotated.x - c.x * rotated.y));
0140 }
0141 
0142 /*********************
0143     Operators
0144 *********************/
0145 
0146 // Convert a distance field to an annular (hollow) distance field.
0147 //
0148 // \param sdf The result of an sdf shape to convert.
0149 // \param thickness The thickness of the resulting shape.
0150 //
0151 // \return The value of sdf modified to an annular shape.
0152 lowp float sdf_annular(in lowp float sdf, in lowp float thickness)
0153 {
0154     return abs(sdf) - thickness;
0155 }
0156 
0157 // Union two sdf shapes together.
0158 //
0159 // \param sdf1 The first sdf shape.
0160 // \param sdf2 The second sdf shape.
0161 //
0162 // \return The union of sdf1 and sdf2, that is, the distance to both sdf1 and
0163 //         sdf2.
0164 lowp float sdf_union(in lowp float sdf1, in lowp float sdf2)
0165 {
0166     return min(sdf1, sdf2);
0167 }
0168 
0169 // Subtract two sdf shapes.
0170 //
0171 // \param sdf1 The first sdf shape.
0172 // \param sdf2 The second sdf shape.
0173 //
0174 // \return sdf1 with sdf2 subtracted from it.
0175 lowp float sdf_subtract(in lowp float sdf1, in lowp float sdf2)
0176 {
0177     return max(sdf1, -sdf2);
0178 }
0179 
0180 // Intersect two sdf shapes.
0181 //
0182 // \param sdf1 The first sdf shape.
0183 // \param sdf2 The second sdf shape.
0184 //
0185 // \return The intersection between sdf1 and sdf2, that is, the area where both
0186 //         sdf1 and sdf2 provide the same distance value.
0187 lowp float sdf_intersect(in lowp float sdf1, in lowp float sdf2)
0188 {
0189     return max(sdf1, sdf2);
0190 }
0191 
0192 // Smoothly intersect two sdf shapes.
0193 //
0194 // \param sdf1 The first sdf shape.
0195 // \param sdf2 The second sdf shape.
0196 // \param smoothing The amount of smoothing to apply.
0197 //
0198 // \return A smoothed version of the intersect operation.
0199 lowp float sdf_intersect_smooth(in lowp float sdf1, in lowp float sdf2, in lowp float smoothing)
0200 {
0201     lowp float h = clamp(0.5 - 0.5 * (sdf1 - sdf2) / smoothing, 0.0, 1.0);
0202     return mix(sdf1, sdf2, h) + smoothing * h * (1.0 - h);
0203 }
0204 
0205 // Round an sdf shape.
0206 //
0207 // \param sdf The sdf shape to round.
0208 // \param amount The amount of rounding to apply.
0209 //
0210 // \return The rounded shape of sdf.
0211 //         Note that rounding happens by basically selecting an isoline of sdf,
0212 //         therefore, the resulting shape may be larger than the input shape.
0213 lowp float sdf_round(in lowp float sdf, in lowp float amount)
0214 {
0215     return sdf - amount;
0216 }
0217 
0218 // Convert an sdf shape to an outline of its shape.
0219 //
0220 // \param sdf The sdf shape to turn into an outline.
0221 //
0222 // \return The outline of sdf.
0223 lowp float sdf_outline(in lowp float sdf)
0224 {
0225     return abs(sdf);
0226 }
0227 
0228 /********************
0229     Convenience
0230 ********************/
0231 
0232 // A constant to represent a "null" value of an sdf.
0233 // Since 0 is a point exactly on the outline of an sdf shape, and negative
0234 // values are inside the shape, this uses a very large positive constant to
0235 // indicate a value that is really far away from the actual sdf shape.
0236 const lowp float sdf_null = 99999.0;
0237 
0238 // A constant for a default level of smoothing when rendering an sdf.
0239 const lowp float sdf_default_smoothing = 0.625;
0240 
0241 // Render an sdf shape.
0242 //
0243 // This will render the sdf shape on top of whatever source color is input,
0244 // making sure to apply smoothing if desired.
0245 //
0246 // \param sdf The sdf shape to render.
0247 // \param sourceColor The source color to render on top of.
0248 // \param sdfColor The color to use for rendering the sdf shape.
0249 //
0250 // \return sourceColor with the sdf shape rendered on top.
0251 lowp vec4 sdf_render(in lowp float sdf, in lowp vec4 sourceColor, in lowp vec4 sdfColor)
0252 {
0253     lowp float g = fwidth(sdf);
0254     return mix(sourceColor, sdfColor, 1.0 - smoothstep(-sdf_default_smoothing * g, sdf_default_smoothing * g, sdf));
0255 }
0256 
0257 // Render an sdf shape.
0258 //
0259 // This is an overload of sdf_render(float, vec4, vec4) that allows specifying a
0260 // smoothing amount.
0261 //
0262 // \param smoothing The amount of smoothing to apply to the sdf.
0263 //
0264 lowp vec4 sdf_render(in lowp float sdf, in lowp vec4 sourceColor, in lowp vec4 sdfColor, in lowp float smoothing)
0265 {
0266     lowp float g = fwidth(sdf);
0267     return mix(sourceColor, sdfColor, 1.0 - smoothstep(-smoothing * g, smoothing * g, sdf));
0268 }
0269 
0270 // Render an sdf shape alpha-blended onto an existing color.
0271 //
0272 // This is an overload of sdf_render(float, vec4, vec4) that allows specifying a
0273 // blending amount and a smoothing amount.
0274 //
0275 // \param alpha The alpha to use for blending.
0276 // \param smoothing The amount of smoothing to apply to the sdf.
0277 //
0278 lowp vec4 sdf_render(in lowp float sdf, in lowp vec4 sourceColor, in lowp vec4 sdfColor, in lowp float alpha, in lowp float smoothing)
0279 {
0280     lowp float g = fwidth(sdf);
0281     return mix(sourceColor, sdfColor, alpha * (1.0 - smoothstep(-smoothing * g, smoothing * g, sdf)));
0282 }