1 /****************************************************************************
2 **
3 ** Copyright (C) 2020 The Qt Company Ltd.
4 ** Contact: https://www.qt.io/licensing/
5 **
6 ** This file is part of Qt Quick 3D.
7 **
8 ** $QT_BEGIN_LICENSE:GPL$
9 ** Commercial License Usage
10 ** Licensees holding valid commercial Qt licenses may use this file in
11 ** accordance with the commercial license agreement provided with the
12 ** Software or, alternatively, in accordance with the terms contained in
13 ** a written agreement between you and The Qt Company. For licensing terms
14 ** and conditions see https://www.qt.io/terms-conditions. For further
15 ** information use the contact form at https://www.qt.io/contact-us.
16 **
17 ** GNU General Public License Usage
18 ** Alternatively, this file may be used under the terms of the GNU
19 ** General Public License version 3 or (at your option) any later version
20 ** approved by the KDE Free Qt Foundation. The licenses are as published by
21 ** the Free Software Foundation and appearing in the file LICENSE.GPL3
22 ** included in the packaging of this file. Please review the following
23 ** information to ensure the GNU General Public License requirements will
24 ** be met: https://www.gnu.org/licenses/gpl-3.0.html.
25 **
26 ** $QT_END_LICENSE$
27 **
28 ****************************************************************************/
29 
30 #ifndef QQUICK3DSHADERUTILS_H
31 #define QQUICK3DSHADERUTILS_H
32 
33 //
34 //  W A R N I N G
35 //  -------------
36 //
37 // This file is not part of the Qt API.  It exists purely as an
38 // implementation detail.  This header file may change from version to
39 // version without notice, or even be removed.
40 //
41 // We mean it.
42 //
43 
44 #include <QtQuick3D/qtquick3dglobal.h>
45 #include <QtQuick3D/private/qquick3dobject_p.h>
46 #include <QtQuick3D/private/qquick3dtexture_p.h>
47 #include <QtQuick3D/private/qquick3dmaterial_p.h>
48 
49 #include <QtQuick3DRender/private/qssgrenderbasetypes_p.h>
50 
51 #include <QtQuick3DRuntimeRender/private/qssgrenderdynamicobjectsystemcommands_p.h>
52 
53 QT_BEGIN_NAMESPACE
54 
55 class QQuick3DShaderUtilsShader;
56 
57 namespace QSSGShaderUtils
58 {
59 void addSnapperSampler(const QByteArray &texName, QByteArray &shaderPrefix);
60 QByteArray resolveShader(const QByteArray &shader, QByteArray &shaderPath, const QObject *qmlObj);
61 QByteArray mergeShaderCode(const QByteArray &shared,
62                            const QByteArray &uniforms,
63                            const QByteArray &textures,
64                            const QByteArray &vertex,
65                            const QByteArray &geometry,
66                            const QByteArray &fragment);
67 }
68 
69 class Q_QUICK3D_EXPORT QQuick3DShaderUtilsTextureInput : public QObject
70 {
71     Q_OBJECT
72     Q_PROPERTY(QQuick3DTexture *texture READ texture WRITE setTexture)
73     Q_PROPERTY(bool enabled MEMBER enabled)
74 
75 public:
76     QQuick3DShaderUtilsTextureInput() = default;
77     virtual ~QQuick3DShaderUtilsTextureInput() = default;
78     QQuick3DTexture *m_texture = nullptr;
79     bool enabled = true;
80     QByteArray name;
texture()81     QQuick3DTexture *texture() const
82     {
83         return m_texture;
84     }
85 
86 public Q_SLOTS:
87     void setTexture(QQuick3DTexture *texture);
88 
89 Q_SIGNALS:
90     void textureDirty(QQuick3DShaderUtilsTextureInput *texture);
91 };
92 
93 class Q_QUICK3D_EXPORT QQuick3DShaderUtilsBuffer : public QObject
94 {
95     Q_OBJECT
96     Q_PROPERTY(TextureFormat format READ format WRITE setFormat)
97     Q_PROPERTY(TextureFilterOperation textureFilterOperation READ textureFilterOperation WRITE setTextureFilterOperation)
98     Q_PROPERTY(TextureCoordOperation textureCoordOperation READ textureCoordOperation WRITE setTextureCoordOperation)
99     Q_PROPERTY(float sizeMultiplier MEMBER sizeMultiplier)
100     Q_PROPERTY(AllocateBufferFlagValues bufferFlags READ bufferFlags WRITE setBufferFlags)
101     Q_PROPERTY(QByteArray name MEMBER name)
102 public:
103     QQuick3DShaderUtilsBuffer() = default;
104     ~QQuick3DShaderUtilsBuffer() override = default;
105 
106     enum class TextureFilterOperation
107     {
108         Unknown = 0,
109         Nearest,
110         Linear
111     };
112     Q_ENUM(TextureFilterOperation)
113 
114     enum class TextureCoordOperation
115     {
116         Unknown = 0,
117         ClampToEdge,
118         MirroredRepeat,
119         Repeat
120     };
121     Q_ENUM(TextureCoordOperation)
122 
123     enum class AllocateBufferFlagValues
124     {
125         None = 0,
126         SceneLifetime = 1
127     };
128     Q_ENUM(AllocateBufferFlagValues)
129 
130     enum class TextureFormat {
131         Unknown = 0,
132         R8,
133         R16,
134         R16F,
135         R32I,
136         R32UI,
137         R32F,
138         RG8,
139         RGBA8,
140         RGB8,
141         SRGB8,
142         SRGB8A8,
143         RGB565,
144         RGBA16F,
145         RG16F,
146         RG32F,
147         RGB32F,
148         RGBA32F,
149         R11G11B10,
150         RGB9E5,
151         Depth16,
152         Depth24,
153         Depth32,
154         Depth24Stencil8
155     };
Q_ENUM(TextureFormat)156     Q_ENUM(TextureFormat)
157 
158     dynamic::QSSGAllocateBuffer command {};
textureFilterOperation()159     TextureFilterOperation textureFilterOperation() const { return TextureFilterOperation(command.m_filterOp); }
setTextureFilterOperation(TextureFilterOperation op)160     void setTextureFilterOperation(TextureFilterOperation op) { command.m_filterOp = QSSGRenderTextureMagnifyingOp(op); }
161 
textureCoordOperation()162     TextureCoordOperation textureCoordOperation() const { return TextureCoordOperation(command.m_texCoordOp); }
setTextureCoordOperation(TextureCoordOperation texCoordOp)163     void setTextureCoordOperation(TextureCoordOperation texCoordOp) { command.m_texCoordOp = QSSGRenderTextureCoordOp(texCoordOp); }
164     float &sizeMultiplier = command.m_sizeMultiplier;
getCommand()165     dynamic::QSSGCommand *getCommand() { return &command; }
166 
167     TextureFormat format() const;
168     void setFormat(TextureFormat format);
169 
bufferFlags()170     AllocateBufferFlagValues bufferFlags() const { return AllocateBufferFlagValues(int(command.m_bufferFlags)); }
setBufferFlags(AllocateBufferFlagValues flag)171     void setBufferFlags(AllocateBufferFlagValues flag) { command.m_bufferFlags = quint32(flag);}
172 
173     QByteArray &name = command.m_name;
174 
175     static QSSGRenderTextureFormat::Format mapTextureFormat(QQuick3DShaderUtilsBuffer::TextureFormat fmt);
176     static QQuick3DShaderUtilsBuffer::TextureFormat mapRenderTextureFormat(QSSGRenderTextureFormat::Format fmt);
177 };
178 
179 class Q_QUICK3D_EXPORT QQuick3DShaderUtilsRenderCommand : public QObject
180 {
181     Q_OBJECT
182 public:
183     QQuick3DShaderUtilsRenderCommand() = default;
184     ~QQuick3DShaderUtilsRenderCommand() override = default;
getCommand()185     virtual dynamic::QSSGCommand *getCommand() { Q_ASSERT(0); return nullptr; }
bufferCount()186     virtual int bufferCount() const { return 0; }
bufferAt(int idx)187     virtual QQuick3DShaderUtilsBuffer *bufferAt(int idx) const { Q_UNUSED(idx) return nullptr; }
188 };
189 
190 class Q_QUICK3D_EXPORT QQuick3DShaderUtilsBufferInput : public QQuick3DShaderUtilsRenderCommand
191 {
192     Q_OBJECT
193     Q_PROPERTY(QQuick3DShaderUtilsBuffer *buffer READ buffer WRITE setBuffer)
194     Q_PROPERTY(QByteArray param MEMBER param)
195 public:
196     QQuick3DShaderUtilsBufferInput() = default;
197     ~QQuick3DShaderUtilsBufferInput() override = default;
198     dynamic::QSSGApplyBufferValue command { QByteArray(), QByteArray() };
199     QByteArray &param = command.m_paramName;
getCommand()200     dynamic::QSSGCommand *getCommand() override { return &command; }
201 
bufferCount()202     int bufferCount() const override { return (m_buffer != nullptr) ? 1 : 0; }
bufferAt(int idx)203     QQuick3DShaderUtilsBuffer *bufferAt(int idx) const override
204     {
205         Q_ASSERT(idx < 1 && idx >= 0);
206         return (m_buffer && idx == 0) ? m_buffer : nullptr;
207     }
208 
buffer()209     QQuick3DShaderUtilsBuffer *buffer() const { return m_buffer; }
setBuffer(QQuick3DShaderUtilsBuffer * buffer)210     void setBuffer(QQuick3DShaderUtilsBuffer *buffer) {
211         if (m_buffer == buffer)
212             return;
213 
214         if (buffer) {
215             Q_ASSERT(!buffer->name.isEmpty());
216             command.m_bufferName = buffer->name;
217         }
218         m_buffer = buffer;
219     }
220 
221     QQuick3DShaderUtilsBuffer *m_buffer = nullptr;
222 
223 };
224 
225 class Q_QUICK3D_EXPORT QQuick3DShaderUtilsBufferBlit : public QQuick3DShaderUtilsRenderCommand
226 {
227     Q_OBJECT
228     Q_PROPERTY(QQuick3DShaderUtilsBuffer *source READ source WRITE setSource)
229     Q_PROPERTY(QQuick3DShaderUtilsBuffer *destination READ destination WRITE setDestination)
230 public:
231     QQuick3DShaderUtilsBufferBlit() = default;
232     ~QQuick3DShaderUtilsBufferBlit() override = default;
233     dynamic::QSSGApplyBlitFramebuffer command { QByteArray(), QByteArray() };
getCommand()234     dynamic::QSSGCommand *getCommand() override { return &command; }
235 
bufferCount()236     int bufferCount() const override {
237         if (m_source != nullptr && m_destination != nullptr)
238             return 2;
239         if (m_source || m_destination)
240             return 1;
241 
242         return 0;
243     }
244 
bufferAt(int idx)245     QQuick3DShaderUtilsBuffer *bufferAt(int idx) const override
246     {
247         Q_ASSERT(idx < 2 && idx >= 0);
248         if (idx == 0)
249             return m_source ? m_source : m_destination;
250         if (idx == 1 && m_destination)
251             return m_destination;
252 
253         return nullptr;
254     }
255 
source()256     QQuick3DShaderUtilsBuffer *source() const { return m_source; }
setSource(QQuick3DShaderUtilsBuffer * src)257     void setSource(QQuick3DShaderUtilsBuffer *src)
258     {
259         if (src == m_source)
260             return;
261 
262         if (src) {
263             Q_ASSERT(!src->name.isEmpty());
264             command.m_sourceBufferName = src->name;
265         }
266         m_source = src;
267     }
268 
destination()269     QQuick3DShaderUtilsBuffer *destination() const { return m_destination; }
setDestination(QQuick3DShaderUtilsBuffer * dest)270     void setDestination(QQuick3DShaderUtilsBuffer *dest)
271     {
272         if (dest == m_destination)
273             return;
274 
275         if (dest) {
276             Q_ASSERT(!dest->name.isEmpty());
277             command.m_destBufferName = dest->name;
278         }
279         m_destination = dest;
280     }
281 
282     QQuick3DShaderUtilsBuffer *m_source = nullptr;
283     QQuick3DShaderUtilsBuffer *m_destination = nullptr;
284 };
285 
286 class Q_QUICK3D_EXPORT QQuick3DShaderUtilsBlending : public QQuick3DShaderUtilsRenderCommand
287 {
288     Q_OBJECT
289     Q_PROPERTY(SrcBlending srcBlending READ srcBlending WRITE setSrcBlending)
290     Q_PROPERTY(DestBlending destBlending READ destBlending WRITE setDestBlending)
291 
292 public:
293     enum class SrcBlending
294     {
295         Unknown = 0,
296         Zero,
297         One,
298         SrcColor,
299         OneMinusSrcColor,
300         DstColor,
301         OneMinusDstColor,
302         SrcAlpha,
303         OneMinusSrcAlpha,
304         DstAlpha,
305         OneMinusDstAlpha,
306         ConstantColor,
307         OneMinusConstantColor,
308         ConstantAlpha,
309         OneMinusConstantAlpha,
310         SrcAlphaSaturate
311     };
312     Q_ENUM(SrcBlending)
313 
314     enum class DestBlending
315     {
316         Unknown = 0,
317         Zero,
318         One,
319         SrcColor,
320         OneMinusSrcColor,
321         DstColor,
322         OneMinusDstColor,
323         SrcAlpha,
324         OneMinusSrcAlpha,
325         DstAlpha,
326         OneMinusDstAlpha,
327         ConstantColor,
328         OneMinusConstantColor,
329         ConstantAlpha,
330         OneMinusConstantAlpha
331     };
332     Q_ENUM(DestBlending)
333 
334     QQuick3DShaderUtilsBlending() = default;
335     ~QQuick3DShaderUtilsBlending() override = default;
336     dynamic::QSSGApplyBlending command { QSSGRenderSrcBlendFunc::Unknown, QSSGRenderDstBlendFunc::Unknown };
destBlending()337     DestBlending destBlending() const
338     {
339         return DestBlending(command.m_dstBlendFunc);
340     }
srcBlending()341     SrcBlending srcBlending() const
342     {
343         return SrcBlending(command.m_srcBlendFunc);
344     }
345 
getCommand()346     dynamic::QSSGCommand *getCommand() override { return &command; }
347 
348 public Q_SLOTS:
setDestBlending(DestBlending destBlending)349     void setDestBlending(DestBlending destBlending)
350     {
351         command.m_dstBlendFunc = QSSGRenderDstBlendFunc(destBlending);
352     }
setSrcBlending(SrcBlending srcBlending)353     void setSrcBlending(SrcBlending srcBlending)
354     {
355         command.m_srcBlendFunc= QSSGRenderSrcBlendFunc(srcBlending);
356     }
357 };
358 
359 class Q_QUICK3D_EXPORT QQuick3DShaderUtilsRenderState : public QQuick3DShaderUtilsRenderCommand
360 {
361     Q_OBJECT
362     Q_PROPERTY(RenderState renderState READ renderState WRITE setRenderState)
363     Q_PROPERTY(bool enabled MEMBER enabled)
364 
365 public:
366     enum class RenderState
367     {
368         Unknown = 0,
369         Blend,
370         CullFace,
371         DepthTest,
372         StencilTest,
373         ScissorTest,
374         DepthWrite,
375         Multisample
376     };
377     Q_ENUM(RenderState)
378 
379     QQuick3DShaderUtilsRenderState() = default;
380     ~QQuick3DShaderUtilsRenderState() override = default;
381     dynamic::QSSGApplyRenderState command { QSSGRenderState::Unknown, false };
382     bool &enabled = command.m_enabled;
renderState()383     RenderState renderState() const
384     {
385         return RenderState(command.m_renderState);
386     }
387 
getCommand()388     dynamic::QSSGCommand *getCommand() override { return &command; }
389 public Q_SLOTS:
setRenderState(RenderState renderState)390     void setRenderState(RenderState renderState)
391     {
392         command.m_renderState = QSSGRenderState(renderState);
393     }
394 };
395 
396 class Q_QUICK3D_EXPORT QQuick3DShaderUtilsCullMode : public QQuick3DShaderUtilsRenderCommand
397 {
398     Q_OBJECT
399     Q_PROPERTY(QQuick3DMaterial::CullMode cullMode READ cullMode WRITE setCullMode)
400 
401 public:
402     QQuick3DShaderUtilsCullMode() = default;
403     ~QQuick3DShaderUtilsCullMode() override = default;
404 
405     dynamic::QSSGApplyCullMode command { QSSGCullFaceMode::Back };
406 
cullMode()407     QQuick3DMaterial::CullMode cullMode() const
408     {
409         return QQuick3DMaterial::CullMode(command.m_cullMode);
410     }
getCommand()411     dynamic::QSSGCommand *getCommand() override { return &command; }
412 public Q_SLOTS:
setCullMode(QQuick3DMaterial::CullMode cullMode)413     void setCullMode(QQuick3DMaterial::CullMode cullMode)
414     {
415         command.m_cullMode = QSSGCullFaceMode(cullMode);
416     }
417 };
418 
419 class Q_QUICK3D_EXPORT QQuick3DShaderApplyDepthValue : public QQuick3DShaderUtilsRenderCommand
420 {
421     Q_OBJECT
422     Q_PROPERTY(QByteArray param MEMBER param)
423 
424 public:
425     QQuick3DShaderApplyDepthValue() = default;
426     ~QQuick3DShaderApplyDepthValue() override = default;
427 
428     dynamic::QSSGApplyDepthValue command { QByteArray() };
429 
getCommand()430     dynamic::QSSGCommand *getCommand() override { return &command; }
431     QByteArray &param = command.m_paramName;
432 };
433 
434 class Q_QUICK3D_EXPORT QQuick3DShaderUtilsApplyValue : public QQuick3DShaderUtilsRenderCommand
435 {
436     Q_OBJECT
437     Q_PROPERTY(QByteArray target MEMBER target)
438     Q_PROPERTY(QVariant value MEMBER value)
439 
440 public:
441     QQuick3DShaderUtilsApplyValue() = default;
442     ~QQuick3DShaderUtilsApplyValue() override = default;
getCommand()443     dynamic::QSSGCommand *getCommand() override { return &command; }
444     dynamic::QSSGApplyValue command { };
445     QVariant &value = command.m_value;
446     QByteArray &target = command.m_propertyName;
447 };
448 
449 class Q_QUICK3D_EXPORT QQuick3DShaderUtilsRenderPass : public QObject
450 {
451     Q_OBJECT
452     Q_PROPERTY(QQmlListProperty<QQuick3DShaderUtilsRenderCommand> commands READ commands)
453     Q_PROPERTY(QQuick3DShaderUtilsBuffer *output MEMBER outputBuffer)
454     Q_PROPERTY(QQmlListProperty<QQuick3DShaderUtilsShader> shaders READ shaders)
455 public:
456     QQuick3DShaderUtilsRenderPass() = default;
457     ~QQuick3DShaderUtilsRenderPass() override = default;
458 
459     static void qmlAppendCommand(QQmlListProperty<QQuick3DShaderUtilsRenderCommand> *list, QQuick3DShaderUtilsRenderCommand *command);
460     static QQuick3DShaderUtilsRenderCommand *qmlCommandAt(QQmlListProperty<QQuick3DShaderUtilsRenderCommand> *list, int index);
461     static int qmlCommandCount(QQmlListProperty<QQuick3DShaderUtilsRenderCommand> *list);
462     static void qmlCommandClear(QQmlListProperty<QQuick3DShaderUtilsRenderCommand> *list);
463 
464     static void qmlAppendShader(QQmlListProperty<QQuick3DShaderUtilsShader> *list, QQuick3DShaderUtilsShader *shader);
465     static QQuick3DShaderUtilsShader *qmlShaderAt(QQmlListProperty<QQuick3DShaderUtilsShader> *list, int index);
466     static int qmlShaderCount(QQmlListProperty<QQuick3DShaderUtilsShader> *list);
467     static void qmlShaderClear(QQmlListProperty<QQuick3DShaderUtilsShader> *list);
468 
469     QQmlListProperty<QQuick3DShaderUtilsRenderCommand> commands();
470     QVector<QQuick3DShaderUtilsRenderCommand *> m_commands;
471     QQuick3DShaderUtilsBuffer *outputBuffer = nullptr;
472     QQmlListProperty<QQuick3DShaderUtilsShader> shaders();
473     QVarLengthArray<QQuick3DShaderUtilsShader *, 5> m_shaders { nullptr, nullptr, nullptr, nullptr, nullptr };
474 };
475 
476 class Q_QUICK3D_EXPORT QQuick3DShaderUtilsShaderInfo : public QObject
477 {
478     Q_OBJECT
479     Q_PROPERTY(QByteArray version MEMBER version)
480     Q_PROPERTY(QByteArray type MEMBER type)
481     Q_PROPERTY(qint32 shaderKey MEMBER shaderKey)
482 public:
483     QQuick3DShaderUtilsShaderInfo() = default;
484     ~QQuick3DShaderUtilsShaderInfo() override = default;
485     QByteArray version;
486     QByteArray type; // I.e., GLSL
487 
488     enum class MaterialShaderKeyValues
489     {
490         Diffuse = 1 << 0,
491         Specular = 1 << 1,
492         Cutout = 1 << 2,
493         Refraction = 1 << 3,
494         Transparent = 1 << 4,
495         Displace = 1 << 5,
496         Transmissive = 1 << 6,
497         Glossy = Diffuse | Specular
498     };
499     Q_ENUM(MaterialShaderKeyValues)
Q_DECLARE_FLAGS(MaterialShaderKeyFlags,MaterialShaderKeyValues)500     Q_DECLARE_FLAGS(MaterialShaderKeyFlags, MaterialShaderKeyValues)
501 
502     qint32 shaderKey {0};
isValid()503     bool isValid() const { return !(version.isEmpty() && type.isEmpty()); }
504 };
505 
506 class Q_QUICK3D_EXPORT QQuick3DShaderUtilsShader : public QObject
507 {
508     Q_OBJECT
509     Q_PROPERTY(QByteArray shader MEMBER shader)
510     Q_PROPERTY(Stage stage MEMBER stage)
511 public:
512     QQuick3DShaderUtilsShader() = default;
513     virtual ~QQuick3DShaderUtilsShader() = default;
514     enum class Stage : quint8
515     {
516         Shared,
517         Vertex,
518         Fragment,
519         Geometry,
520         Compute
521     };
522     Q_ENUM(Stage)
523 
524     QByteArray shader;
525     Stage stage = Stage::Shared;
526 };
527 
528 QT_END_NAMESPACE
529 
530 #endif // QQUICK3DSHADERUTILS_H
531