diff --git a/src/scenegraph/SDFShader.cpp b/src/scenegraph/SDFShader.cpp index 4afa75a..f4bbc1a 100644 --- a/src/scenegraph/SDFShader.cpp +++ b/src/scenegraph/SDFShader.cpp @@ -1,33 +1,33 @@ /* * This file is part of KQuickCharts * SPDX-FileCopyrightText: 2019 Arjen Hiemstra * * SPDX-License-Identifier: LGPL-2.1-only OR LGPL-3.0-only OR LicenseRef-KDE-Accepted-LGPL */ #include "SDFShader.h" #include static const char shaderRoot[] = ":/org.kde.quickcharts/"; SDFShader::SDFShader() { } SDFShader::~SDFShader() { } void SDFShader::setShaders(const QString &vertex, const QString &fragment) { - auto header = QOpenGLContext::currentContext()->isOpenGLES() ? QStringLiteral("es_header.glsl") : QStringLiteral("desktop_header.glsl"); + auto header = QStringLiteral("header_desktop.glsl"); setShaderSourceFiles(QOpenGLShader::Vertex, {QString::fromLatin1(shaderRoot) + header, QString::fromLatin1(shaderRoot) + vertex}); setShaderSourceFiles( QOpenGLShader::Fragment, {QString::fromLatin1(shaderRoot) + header, - QString::fromLatin1(shaderRoot) + QStringLiteral("sdf.frag"), + QString::fromLatin1(shaderRoot) + QStringLiteral("sdf.glsl"), QString::fromLatin1(shaderRoot) + fragment}); } diff --git a/src/shaders/desktop_header.glsl b/src/shaders/header_desktop.glsl similarity index 79% rename from src/shaders/desktop_header.glsl rename to src/shaders/header_desktop.glsl index 76c7f4b..f73ec8c 100644 --- a/src/shaders/desktop_header.glsl +++ b/src/shaders/header_desktop.glsl @@ -1,27 +1,18 @@ /* * This file is part of KQuickCharts * SPDX-FileCopyrightText: 2019 Arjen Hiemstra * * SPDX-License-Identifier: LGPL-2.1-only OR LGPL-3.0-only OR LicenseRef-KDE-Accepted-LGPL */ // This file contains common directives needed for the shaders to work. // It is included as the very first bit in the shader. // Important: If a specific GLSL version is needed, it should be set in this // file. // This file is intended for desktop OpenGL version 2.1 or greater. #version 120 -#ifndef lowp - #define lowp -#endif - -#ifndef mediump - #define mediump -#endif - -#ifndef highp - #define highp mediump -#endif +#define API_DESKTOP +#define LEGACY_STAGE_INOUT diff --git a/src/shaders/desktop_header_core.glsl b/src/shaders/header_desktop_core.glsl similarity index 96% rename from src/shaders/desktop_header_core.glsl rename to src/shaders/header_desktop_core.glsl index baa266c..f4664db 100644 --- a/src/shaders/desktop_header_core.glsl +++ b/src/shaders/header_desktop_core.glsl @@ -1,15 +1,17 @@ /* * This file is part of KQuickCharts * SPDX-FileCopyrightText: 2019 Arjen Hiemstra * * SPDX-License-Identifier: LGPL-2.1-only OR LGPL-3.0-only OR LicenseRef-KDE-Accepted-LGPL */ // This file contains common directives needed for the shaders to work. // It is included as the very first bit in the shader. // Important: If a specific GLSL version is needed, it should be set in this // file. // This file is intended for desktop OpenGL version 4.5 or greater. #version 450 + +#define API_CORE diff --git a/src/shaders/es_header.glsl b/src/shaders/header_es2.glsl similarity index 81% rename from src/shaders/es_header.glsl rename to src/shaders/header_es2.glsl index 8075b6b..905d7e7 100644 --- a/src/shaders/es_header.glsl +++ b/src/shaders/header_es2.glsl @@ -1,16 +1,19 @@ /* * This file is part of KQuickCharts * SPDX-FileCopyrightText: 2019 Arjen Hiemstra * * SPDX-License-Identifier: LGPL-2.1-only OR LGPL-3.0-only OR LicenseRef-KDE-Accepted-LGPL */ // This file contains common directives needed for the shaders to work. // It is included as the very first bit in the shader. // Important: If a specific GLSL version is needed, it should be set in this // file. // This file is intended for OpenGLES version 2.0 or greater. -#version 100 -#extension GL_OES_standard_derivatives : enable +// #version 100 +#extension GL_OES_standard_derivatives : require + +#define API_ES2 +#define LEGACY_STAGE_INOUT diff --git a/src/shaders/linechart_core.frag b/src/shaders/linechart_core.frag deleted file mode 100644 index ad64a3c..0000000 --- a/src/shaders/linechart_core.frag +++ /dev/null @@ -1,52 +0,0 @@ -/* - * This file is part of KQuickCharts - * SPDX-FileCopyrightText: 2019 Arjen Hiemstra - * - * SPDX-License-Identifier: LGPL-2.1-only OR LGPL-3.0-only OR LicenseRef-KDE-Accepted-LGPL - */ - -// This requires "sdf_core.frag" which is included through SDFShader. - -uniform float opacity; -uniform vec4 lineColor; -uniform vec4 fillColor; -uniform float lineWidth; -uniform lowp vec2 bounds; - -uniform vec2 points[SDF_POLYGON_MAX_POINT_COUNT]; -uniform int pointCount; - -in vec2 uv; - -out vec4 out_color; - -void main() -{ - vec2 point = uv; - - vec4 color = vec4(0.0, 0.0, 0.0, 0.0); - - // bounds.y contains the line segment's maximum value. If we are a bit above - // that, we will never render anything, so just discard the pixel. - if (point.y > bounds.y + 0.01) { - discard; - } - - // bounds.x contains the line segment's minimum value. If we are a bit below - // that, we know we will always be inside the polygon described by points. - // So just return a pixel with fillColor. - if (point.y < bounds.x - 0.01) { - out_color = fillColor * opacity; - return; - } - - float polygon = sdf_polygon(point, points, pointCount); - - color = sdf_render(polygon, color, fillColor, 0.001); - - if (lineWidth > 0.0) { - color = sdf_render(sdf_annular(sdf_outline(polygon), lineWidth), color, lineColor, 0.0002); - } - - out_color = color * opacity; -} diff --git a/src/shaders/linechart_core.vert b/src/shaders/linechart_core.vert deleted file mode 100644 index e2b7817..0000000 --- a/src/shaders/linechart_core.vert +++ /dev/null @@ -1,22 +0,0 @@ -/* - * This file is part of KQuickCharts - * SPDX-FileCopyrightText: 2019 Arjen Hiemstra - * - * SPDX-License-Identifier: LGPL-2.1-only OR LGPL-3.0-only OR LicenseRef-KDE-Accepted-LGPL - */ - -uniform mat4 matrix; -uniform float lineWidth; -uniform float aspect; - -in vec4 in_vertex; -in vec2 in_uv; - -out vec2 uv; - -void main() { - uv.x = in_uv.x; - uv.y = in_uv.y; - uv.y = (1.0 + -1.0 * uv.y) * aspect; - gl_Position = matrix * in_vertex; -} diff --git a/src/shaders/piechart_core.frag b/src/shaders/piechart_core.frag deleted file mode 100644 index ec83c1e..0000000 --- a/src/shaders/piechart_core.frag +++ /dev/null @@ -1,60 +0,0 @@ -/* - * This file is part of KQuickCharts - * SPDX-FileCopyrightText: 2019 Arjen Hiemstra - * - * SPDX-License-Identifier: LGPL-2.1-only OR LGPL-3.0-only OR LicenseRef-KDE-Accepted-LGPL - */ - -// This requires "sdf_core.frag" which is included through SDFShader. - -// The maximum number of segments we can support for a single pie. -// This is based on OpenGL's MAX_FRAGMENT_UNIFORM_COMPONENTS. -// MAX_FRAGMENT_UNIFORM_COMPONENTS is required to be at least 1024. -// Assuming a segment of size 1, each segment needs -// 2 (size of a vec2) * 2 (number of points) + 4 (size of vec4) + 1 (segment size) -// components. We also need to leave some room for the other uniforms. -#define MAX_SEGMENTS 100 - -uniform float opacity; -uniform float innerRadius; -uniform float outerRadius; -uniform vec4 backgroundColor; - -uniform vec2 triangles[MAX_SEGMENTS * 2]; -uniform vec4 colors[MAX_SEGMENTS]; -uniform int segments[MAX_SEGMENTS]; -uniform int segmentCount; - -in vec2 uv; - -out vec4 out_color; - -const vec2 origin = vec2(0.0, 0.0); -const float lineSmooth = 0.001; - -void main() -{ - vec2 point = uv * (1.0 + lineSmooth * 2.0); - - float thickness = (outerRadius - innerRadius) / 2.0; - float donut = sdf_annular(sdf_circle(point, innerRadius + thickness), thickness); - - vec4 color = vec4(0.0); - float totalSegments = sdf_null; - int index = 0; - - for (int i = 0; i < segmentCount && i < MAX_SEGMENTS; ++i) { - float segment = sdf_null; - for(int j = 0; j < segments[i] && j < MAX_SEGMENTS; j++) { - segment = sdf_union(segment, sdf_round(sdf_triangle(point, origin, triangles[index++], triangles[index++]), lineSmooth)); - } - totalSegments = sdf_union(totalSegments, segment); - color = sdf_render(sdf_intersect(donut, segment), color, colors[i], lineSmooth); - } - - // Finally, render an end segment with the background color. - float segment = sdf_subtract(sdf_round(donut, lineSmooth), totalSegments); - color = sdf_render(segment, color, backgroundColor, lineSmooth); - - out_color = color * opacity; -} diff --git a/src/shaders/piechart_core.vert b/src/shaders/piechart_core.vert deleted file mode 100644 index ba94d03..0000000 --- a/src/shaders/piechart_core.vert +++ /dev/null @@ -1,19 +0,0 @@ -/* - * This file is part of KQuickCharts - * SPDX-FileCopyrightText: 2019 Arjen Hiemstra - * - * SPDX-License-Identifier: LGPL-2.1-only OR LGPL-3.0-only OR LicenseRef-KDE-Accepted-LGPL - */ - -uniform mat4 matrix; -uniform vec2 aspect; - -in vec4 in_vertex; -in vec2 in_uv; - -out vec2 uv; - -void main() { - uv = (-1.0 + 2.0 * in_uv) * aspect; - gl_Position = matrix * in_vertex; -} diff --git a/src/shaders/sdf.frag b/src/shaders/sdf.glsl similarity index 74% rename from src/shaders/sdf.frag rename to src/shaders/sdf.glsl index e177f66..f5f532d 100644 --- a/src/shaders/sdf.frag +++ b/src/shaders/sdf.glsl @@ -1,228 +1,286 @@ // SPDX-FileCopyrightText: 2019 Arjen Hiemstra // SPDX-FileCopyrightText: 2017 Inigo Quilez // // SPDX-License-Identifier: MIT // // This file is based on // https://iquilezles.org/www/articles/distfunctions2d/distfunctions2d.htm -//if not GLES -// include "desktop_header.glsl" -//else -// include "es_header.glsl" - // A maximum point count to be used for sdf_polygon input arrays. // Unfortunately even function inputs require a fixed size at declaration time // for arrays, unless we were to use OpenGL 4.5. // Since the polygon is most likely to be defined in a uniform, this should be // at least less than MAX_FRAGMENT_UNIFORM_COMPONENTS / 2 (since we need vec2). #define SDF_POLYGON_MAX_POINT_COUNT 400 /********************************* Shapes *********************************/ // Distance field for a circle. // // \param point A point on the distance field. // \param radius The radius of the circle. // // \return The signed distance from point to the circle. If negative, point is // inside the circle. lowp float sdf_circle(in lowp vec2 point, in lowp float radius) { return length(point) - radius; } // Distance field for a triangle. // // \param point A point on the distance field. // \param p0 The first vertex of the triangle. // \param p0 The second vertex of the triangle. // \param p0 The third vertex of the triangle. // // \note The ordering of the three vertices does not matter. // // \return The signed distance from point to triangle. If negative, point is // inside the triangle. lowp float sdf_triangle(in lowp vec2 point, in lowp vec2 p0, in lowp vec2 p1, in lowp vec2 p2) { lowp vec2 e0 = p1 - p0; lowp vec2 e1 = p2 - p1; lowp vec2 e2 = p0 - p2; lowp vec2 v0 = point - p0; lowp vec2 v1 = point - p1; lowp vec2 v2 = point - p2; lowp vec2 pq0 = v0 - e0 * clamp( dot(v0, e0) / dot(e0, e0), 0.0, 1.0 ); lowp vec2 pq1 = v1 - e1 * clamp( dot(v1, e1) / dot(e1, e1), 0.0, 1.0 ); lowp vec2 pq2 = v2 - e2 * clamp( dot(v2, e2) / dot(e2, e2), 0.0, 1.0 ); lowp float s = sign( e0.x*e2.y - e0.y*e2.x ); lowp vec2 d = min(min(vec2(dot(pq0,pq0), s*(v0.x*e0.y-v0.y*e0.x)), vec2(dot(pq1,pq1), s*(v1.x*e1.y-v1.y*e1.x))), vec2(dot(pq2,pq2), s*(v2.x*e2.y-v2.y*e2.x))); return -sqrt(d.x)*sign(d.y); } +#if !defined(API_ES2) // Distance field for an arbitrary polygon. // // \param point A point on the distance field. // \param vertices An array of points that make up the polygon. // \param count The amount of points to use for the polygon. // // \note points should be an array of vec2 of size SDF_POLYGON_MAX_POINT_COUNT. // Use count to indicate how many items of that array should be used. // // \return The signed distance from point to triangle. If negative, point is // inside the triangle. - -// Strictly speaking, GLES 2.0 doesn't support function array arguments (apparently), so our validation fails here. -// But at least Mesa GLES 2.0 accepts it, so skip validation here instead. -#if !defined(GL_ES) || !defined(VALIDATING) lowp float sdf_polygon(in lowp vec2 point, in lowp vec2[SDF_POLYGON_MAX_POINT_COUNT] vertices, in lowp int count) { lowp float d = dot(point - vertices[0], point - vertices[0]); lowp float s = 1.0; for (int i = 0, j = count - 1; i < count && i < SDF_POLYGON_MAX_POINT_COUNT; j = i, i++) { lowp vec2 e = vertices[j] - vertices[i]; lowp vec2 w = point - vertices[i]; lowp float h = clamp( dot(w, e) / dot(e, e), 0.0, 1.0 ); lowp vec2 b = w - e * h; d = min(d, dot(b, b)); bvec3 c = bvec3(point.y >= vertices[i].y, point.y < vertices[j].y, e.x * w.y > e.y * w.x); if(all(c) || all(not(c))) s *= -1.0; } return s * sqrt(d); } #endif // Distance field for a rectangle. // // \param point A point on the distance field. // \param rect A vec2 with the size of the rectangle. // // \return The signed distance from point to rectangle. If negative, point is // inside the rectangle. lowp float sdf_rectangle(in lowp vec2 point, in lowp vec2 rect) { lowp vec2 d = abs(point) - rect; return length(max(d, 0.0)) + min(max(d.x, d.y), 0.0); } +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) +{ + start = clamp(start, 0.0, end); + end = clamp(end, start, 2.0 * pi); + + lowp float angle = (end - start) / 2.0; + lowp float rotation = (start + end) / 2.0; + + lowp vec2 rotated = point * mat2(cos(rotation), -sin(rotation), sin(rotation), cos(rotation)); + lowp vec2 c = vec2(sin(angle), cos(angle)); + + rotated.x = abs(rotated.x); + lowp float l = length(rotated) - outer_radius; + lowp float m = length(rotated - c * clamp(dot(rotated, c), 0.0, outer_radius)); + return max(l, m * sign(c.y * rotated.x - c.x * rotated.y)); +} + +// float pie( in vec2 p, in float start, in float end, in float r ) +// { +// start = clamp(start, 0.0, end); +// end = clamp(end, start, 2.0 * PI); +// +// float angle = (end - start) / 2.0; +// +// float rot = (start + end) / 2.0; +// +// vec2 rotated = p * mat2(cos(rot), -sin(rot), sin(rot), cos(rot)); +// vec2 c = vec2(sin(angle), cos(angle)); +// +// rotated.x = abs(rotated.x); +// float l = length(rotated) - r; +// float m = length(rotated - c * clamp(dot(rotated, c), 0.0, r)); +// return max(l, m * sign(c.y * rotated.x - c.x * rotated.y)); +// } + /********************* Operators *********************/ // Convert a distance field to an annular (hollow) distance field. // // \param sdf The result of an sdf shape to convert. // \param thickness The thickness of the resulting shape. // // \return The value of sdf modified to an annular shape. lowp float sdf_annular(in lowp float sdf, in lowp float thickness) { return abs(sdf) - thickness; } // Union two sdf shapes together. // // \param sdf1 The first sdf shape. // \param sdf2 The second sdf shape. // // \return The union of sdf1 and sdf2, that is, the distance to both sdf1 and // sdf2. lowp float sdf_union(in lowp float sdf1, in lowp float sdf2) { return min(sdf1, sdf2); } // Subtract two sdf shapes. // // \param sdf1 The first sdf shape. // \param sdf2 The second sdf shape. // // \return sdf1 with sdf2 subtracted from it. lowp float sdf_subtract(in lowp float sdf1, in lowp float sdf2) { return max(sdf1, -sdf2); } // Intersect two sdf shapes. // // \param sdf1 The first sdf shape. // \param sdf2 The second sdf shape. // // \return The intersection between sdf1 and sdf2, that is, the area where both // sdf1 and sdf2 provide the same distance value. lowp float sdf_intersect(in lowp float sdf1, in lowp float sdf2) { return max(sdf1, sdf2); } // Smoothly intersect two sdf shapes. // // \param sdf1 The first sdf shape. // \param sdf2 The second sdf shape. // \param smoothing The amount of smoothing to apply. // // \return A smoothed version of the intersect operation. lowp float sdf_intersect_smooth(in lowp float sdf1, in lowp float sdf2, in lowp float smoothing) { lowp float h = clamp(0.5 - 0.5 * (sdf1 - sdf2) / smoothing, 0.0, 1.0); return mix(sdf1, sdf2, h) + smoothing * h * (1.0 - h); } // Round an sdf shape. // // \param sdf The sdf shape to round. // \param amount The amount of rounding to apply. // // \return The rounded shape of sdf. // Note that rounding happens by basically selecting an isoline of sdf, // therefore, the resulting shape may be larger than the input shape. lowp float sdf_round(in lowp float sdf, in lowp float amount) { return sdf - amount; } // Convert an sdf shape to an outline of its shape. // // \param sdf The sdf shape to turn into an outline. // // \return The outline of sdf. lowp float sdf_outline(in lowp float sdf) { return abs(sdf); } /******************** Convenience ********************/ // A constant to represent a "null" value of an sdf. // Since 0 is a point exactly on the outline of an sdf shape, and negative // values are inside the shape, this uses a very large positive constant to // indicate a value that is really far away from the actual sdf shape. const lowp float sdf_null = 99999.0; +// A constant for a default level of smoothing when rendering an sdf. +const lowp float sdf_default_smoothing = 0.625; + +const lowp float pi = acos(-1.0); + // Render an sdf shape. // // This will render the sdf shape on top of whatever source color is input, // making sure to apply smoothing if desired. // // \param sdf The sdf shape to render. // \param sourceColor The source color to render on top of. // \param sdfColor The color to use for rendering the sdf shape. -// \param smoothing The amount of smoothing to apply to the sdf. // // \return sourceColor with the sdf shape rendered on top. +lowp vec4 sdf_render(in lowp float sdf, in lowp vec4 sourceColor, in lowp vec4 sdfColor) +{ + lowp float g = fwidth(sdf); + return mix(sourceColor, sdfColor, 1.0 - smoothstep(-sdf_default_smoothing * g, sdf_default_smoothing * g, sdf)); +} + +// Render an sdf shape. +// +// This is an overload of sdf_render(float, vec4, vec4) that allows specifying a +// smoothing amount. +// +// \param smoothing The amount of smoothing to apply to the sdf. +// lowp vec4 sdf_render(in lowp float sdf, in lowp vec4 sourceColor, in lowp vec4 sdfColor, in lowp float smoothing) { lowp float g = fwidth(sdf); - return mix(sourceColor, sdfColor, sdfColor.a * (1.0 - smoothstep(smoothing - g, smoothing + g, sdf))); + return mix(sourceColor, sdfColor, 1.0 - smoothstep(-smoothing * g, smoothing * g, sdf)); +} + +// Render an sdf shape alpha-blended onto an existing color. +// +// This is an overload of sdf_render(float, vec4, vec4) that allows specifying a +// blending amount and a smoothing amount. +// +// \param alpha The alpha to use for blending. +// \param smoothing The amount of smoothing to apply to the sdf. +// +lowp vec4 sdf_render(in lowp float sdf, in lowp vec4 sourceColor, in lowp vec4 sdfColor, in lowp float alpha, in lowp float smoothing) +{ + lowp float g = fwidth(sdf); + return mix(sourceColor, sdfColor, alpha * (1.0 - smoothstep(-smoothing * g, smoothing * g, sdf))); } diff --git a/src/shaders/sdf_core.frag b/src/shaders/sdf_core.frag deleted file mode 100644 index 7528d4f..0000000 --- a/src/shaders/sdf_core.frag +++ /dev/null @@ -1,195 +0,0 @@ -// SPDX-FileCopyrightText: 2019 Arjen Hiemstra -// SPDX-FileCopyrightText: 2017 Inigo Quilez -// -// SPDX-License-Identifier: MIT -// -// This file is based on -// https://iquilezles.org/www/articles/distfunctions2d/distfunctions2d.htm - -//include "desktop_header_core.glsl" - -// A maximum point count to be used for sdf_polygon input arrays. -// Unfortunately even function inputs require a fixed size at declaration time -// for arrays, unless we were to use OpenGL 4.5. -// Since the polygon is most likely to be defined in a uniform, this should be -// at least less than MAX_FRAGMENT_UNIFORM_COMPONENTS / 2 (since we need vec2). -#define SDF_POLYGON_MAX_POINT_COUNT 400 - -/********************************* - Shapes -*********************************/ - -// Distance field for a circle. -// -// \param point A point on the distance field. -// \param radius The radius of the circle. -// -// \return The signed distance from point to the circle. If negative, point is -// inside the circle. -float sdf_circle(in vec2 point, in float radius) -{ - return length(point) - radius; -} - -// Distance field for a triangle. -// -// \param point A point on the distance field. -// \param p0 The first vertex of the triangle. -// \param p0 The second vertex of the triangle. -// \param p0 The third vertex of the triangle. -// -// \note The ordering of the three vertices does not matter. -// -// \return The signed distance from point to triangle. If negative, point is -// inside the triangle. -float sdf_triangle(in vec2 point, in vec2 p0, in vec2 p1, in vec2 p2) -{ - vec2 e0 = p1 - p0; - vec2 e1 = p2 - p1; - vec2 e2 = p0 - p2; - - vec2 v0 = point - p0; - vec2 v1 = point - p1; - vec2 v2 = point - p2; - - vec2 pq0 = v0 - e0 * clamp( dot(v0, e0) / dot(e0, e0), 0.0, 1.0 ); - vec2 pq1 = v1 - e1 * clamp( dot(v1, e1) / dot(e1, e1), 0.0, 1.0 ); - vec2 pq2 = v2 - e2 * clamp( dot(v2, e2) / dot(e2, e2), 0.0, 1.0 ); - - float s = sign( e0.x*e2.y - e0.y*e2.x ); - vec2 d = min(min(vec2(dot(pq0,pq0), s*(v0.x*e0.y-v0.y*e0.x)), - vec2(dot(pq1,pq1), s*(v1.x*e1.y-v1.y*e1.x))), - vec2(dot(pq2,pq2), s*(v2.x*e2.y-v2.y*e2.x))); - - return -sqrt(d.x)*sign(d.y); -} - -// Distance field for an arbitrary polygon. -// -// \param point A point on the distance field. -// \param vertices An array of points that make up the polygon. -// \param count The amount of points to use for the polygon. -// -// \note points should be an array of vec2 of size SDF_POLYGON_MAX_POINT_COUNT. -// Use count to indicate how many items of that array should be used. -// -// \return The signed distance from point to triangle. If negative, point is -// inside the triangle. - -float sdf_polygon(in vec2 point, in vec2[SDF_POLYGON_MAX_POINT_COUNT] vertices, in int count) -{ - float d = dot(point - vertices[0], point - vertices[0]); - float s = 1.0; - for (int i = 0, j = count - 1; i < count && i < SDF_POLYGON_MAX_POINT_COUNT; j = i, i++) - { - vec2 e = vertices[j] - vertices[i]; - vec2 w = point - vertices[i]; - float h = clamp( dot(w, e) / dot(e, e), 0.0, 1.0 ); - vec2 b = w - e * h; - d = min(d, dot(b, b)); - - bvec3 c = bvec3(point.y >= vertices[i].y, point.y < vertices[j].y, e.x * w.y > e.y * w.x); - if(all(c) || all(not(c))) s *= -1.0; - } - return s * sqrt(d); -} - -/********************* - Operators -*********************/ - -// Convert a distance field to an annular (hollow) distance field. -// -// \param sdf The result of an sdf shape to convert. -// \param thickness The thickness of the resulting shape. -// -// \return The value of sdf modified to an annular shape. -float sdf_annular(in float sdf, in float thickness) -{ - return abs(sdf) - thickness; -} - -// Union two sdf shapes together. -// -// \param sdf1 The first sdf shape. -// \param sdf2 The second sdf shape. -// -// \return The union of sdf1 and sdf2, that is, the distance to both sdf1 and -// sdf2. -float sdf_union(in float sdf1, in float sdf2) -{ - return min(sdf1, sdf2); -} - -// Subtract two sdf shapes. -// -// \param sdf1 The first sdf shape. -// \param sdf2 The second sdf shape. -// -// \return sdf1 with sdf2 subtracted from it. -float sdf_subtract(in float sdf1, in float sdf2) -{ - return max(sdf1, -sdf2); -} - -// Intersect two sdf shapes. -// -// \param sdf1 The first sdf shape. -// \param sdf2 The second sdf shape. -// -// \return The intersection between sdf1 and sdf2, that is, the area where both -// sdf1 and sdf2 provide the same distance value. -float sdf_intersect(in float sdf1, in float sdf2) -{ - return max(sdf1, sdf2); -} - -// Round an sdf shape. -// -// \param sdf The sdf shape to round. -// \param amount The amount of rounding to apply. -// -// \return The rounded shape of sdf. -// Note that rounding happens by basically selecting an isoline of sdf, -// therefore, the resulting shape may be larger than the input shape. -float sdf_round(in float sdf, in float amount) -{ - return sdf - amount; -} - -// Convert an sdf shape to an outline of its shape. -// -// \param sdf The sdf shape to turn into an outline. -// -// \return The outline of sdf. -float sdf_outline(in float sdf) -{ - return abs(sdf); -} - -/******************** - Convenience -********************/ - -// A constant to represent a "null" value of an sdf. -// Since 0 is a point exactly on the outline of an sdf shape, and negative -// values are inside the shape, this uses a very large positive constant to -// indicate a value that is really far away from the actual sdf shape. -const float sdf_null = 99999.0; - -// Render an sdf shape. -// -// This will render the sdf shape on top of whatever source color is input, -// making sure to apply smoothing if desired. -// -// \param sdf The sdf shape to render. -// \param sourceColor The source color to render on top of. -// \param sdfColor The color to use for rendering the sdf shape. -// \param smoothing The amount of smoothing to apply to the sdf. -// -// \return sourceColor with the sdf shape rendered on top. -vec4 sdf_render(in float sdf, in vec4 sourceColor, in vec4 sdfColor, in float smoothing) -{ - float g = fwidth(sdf); - return mix(sourceColor, sdfColor, sdfColor.a * (1.0 - smoothstep(smoothing - g, smoothing + g, sdf))); -} diff --git a/src/shaders/shaders.qrc b/src/shaders/shaders.qrc index 97f64fe..5563f1c 100644 --- a/src/shaders/shaders.qrc +++ b/src/shaders/shaders.qrc @@ -1,19 +1,19 @@ - desktop_header.glsl - desktop_header_core.glsl - es_header.glsl - sdf.frag - sdf_core.frag - uv.vert + header_desktop.glsl + header_desktop_core.glsl + header_es2.glsl + header_es3.glsl + sdf.glsl + sdf.glsl piechart.frag - piechart_core.frag + piechart.frag piechart.vert - piechart_core.vert + piechart.vert linechart.frag - linechart_core.frag + linechart.frag linechart.vert - linechart_core.vert + linechart.vert diff --git a/src/shaders/uv.vert b/src/shaders/uv.vert deleted file mode 100644 index a7d1490..0000000 --- a/src/shaders/uv.vert +++ /dev/null @@ -1,18 +0,0 @@ -/* - * This file is part of KQuickCharts - * SPDX-FileCopyrightText: 2019 Arjen Hiemstra - * - * SPDX-License-Identifier: LGPL-2.1-only OR LGPL-3.0-only OR LicenseRef-KDE-Accepted-LGPL - */ - -uniform highp mat4 matrix; - -attribute highp vec4 in_vertex; -attribute mediump vec2 in_uv; - -varying mediump vec2 uv; - -void main() { - uv = in_uv; - gl_Position = matrix * in_vertex; -}