1/*
2 * This file is part of KQuickCharts
3 * SPDX-FileCopyrightText: 2019 Arjen Hiemstra <ahiemstra@heimr.nl>
4 *
5 * SPDX-License-Identifier: LGPL-2.1-only OR LGPL-3.0-only OR LicenseRef-KDE-Accepted-LGPL
6 */
7
8#ifndef SDF_SHADER_H
9#define SDF_SHADER_H
10
11#include <QSGMaterialShader>
12
13struct UniformDataStream {
14 inline UniformDataStream(QSGMaterialShader::RenderState &state) noexcept
15 : bytes(state.uniformData()->data())
16 {
17 }
18
19 ~UniformDataStream()
20 {
21 }
22
23 template<typename Data>
24 friend inline UniformDataStream &operator<<(UniformDataStream &stream, const Data &data)
25 {
26 constexpr uint dataSize = sizeof(Data);
27 stream.align(size: dataSize);
28 memcpy(stream.bytes, &data, dataSize);
29 stream.bytes += dataSize;
30 stream.offset += dataSize;
31 return stream;
32 }
33
34 template<typename Data>
35 inline void skip(const Data &data = {})
36 {
37 constexpr uint dataSize = sizeof(Data);
38
39 align(size: dataSize);
40 Q_UNUSED(data);
41 bytes += dataSize;
42 offset += dataSize;
43 }
44
45 inline void skipComponents(uint count)
46 {
47 const uint skipCount = count * 4;
48 align(size: 4);
49 bytes += skipCount;
50 offset += skipCount;
51 }
52
53 friend inline UniformDataStream &operator<<(UniformDataStream &stream, const QMatrix4x4 &m)
54 {
55 constexpr uint Matrix4x4Size = 4 * 4 * 4;
56
57 stream.align(size: Matrix4x4Size);
58 memcpy(dest: stream.bytes, src: m.constData(), n: Matrix4x4Size);
59 stream.bytes += Matrix4x4Size;
60 stream.offset += Matrix4x4Size;
61 return stream;
62 }
63
64 friend inline UniformDataStream &operator<<(UniformDataStream &stream, const QColor &color)
65 {
66 constexpr uint ColorSize = 4 * 4;
67
68 stream.align(size: ColorSize);
69 std::array<float, 4> colorArray;
70 color.getRgbF(r: &colorArray[0], g: &colorArray[1], b: &colorArray[2], a: &colorArray[3]);
71 memcpy(dest: stream.bytes, src: colorArray.data(), n: ColorSize);
72 stream.bytes += ColorSize;
73 stream.offset += ColorSize;
74 return stream;
75 }
76
77 template<typename T>
78 friend inline UniformDataStream &operator<<(UniformDataStream &stream, const QList<T> &v)
79 {
80 for (const auto &item : v) {
81 stream << item;
82 // Using std140, array elements are padded to a size of 16 bytes per element.
83 stream.align(size: 16);
84 }
85 return stream;
86 }
87
88 char *bytes;
89 size_t padding = 16;
90 size_t offset = 0;
91
92private:
93 // Encode alignment rules for std140.
94 // Minimum alignment is 4 bytes.
95 // Vec2 alignment is 8 bytes.
96 // Vec3 and Vec4 alignment is 16 bytes.
97 inline void align(uint size)
98 {
99 if (size <= 4) {
100 const auto padding = offset % 4 > 0 ? 4 - offset % 4 : 0;
101 offset += padding;
102 bytes += padding;
103 } else if (size <= 8) {
104 auto padding = offset % 8 > 0 ? 8 - offset % 8 : 0;
105 offset += padding;
106 bytes += padding;
107 } else {
108 auto padding = offset % 16 > 0 ? 16 - offset % 16 : 0;
109 offset += padding;
110 bytes += padding;
111 }
112 }
113};
114
115class SDFShader : public QSGMaterialShader
116{
117public:
118 SDFShader();
119 virtual ~SDFShader();
120
121 void setShaders(const QString &vertex, const QString &fragment);
122};
123
124#endif // SDF_SHADER_H
125

source code of kquickcharts/src/scenegraph/SDFShader.h