Qt 6.x
The Qt SDK
Loading...
Searching...
No Matches
qssgrendereffect.cpp
Go to the documentation of this file.
1// Copyright (C) 2020 The Qt Company Ltd.
2// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
3
4#include <QtQuick3DRuntimeRender/private/qssgrendereffect_p.h>
5#include <QtQuick3DRuntimeRender/private/qssgrenderlayer_p.h>
6#include <QtQuick3DRuntimeRender/private/qssgrendercommands_p.h>
7#include <QtQuick3DRuntimeRender/private/qssgrendercontextcore_p.h>
8
9#include <QtGui/QVector2D>
10#include <QtGui/QVector3D>
11
13
15
17{
19}
20
22{
23 flags |= FlagT(Flags::Dirty);
24}
25
27{
28 flags &= ~FlagT(Flags::Dirty);
29}
30
31// Suffix snippets added to the end of the shader strings. These are appended
32// after processing so it must be valid GLSL as-is, no more magic keywords.
33
34static const char *effect_vertex_main_pre =
35 "void main()\n"
36 "{\n"
37 " qt_inputUV = attr_uv;\n"
38 " qt_textureUV = qt_effectTextureMapUV(attr_uv);\n"
39 " vec4 qt_vertPosition = vec4(attr_pos, 1.0);\n"
40 " qt_customMain(qt_vertPosition.xyz);\n";
41
42static const char *effect_vertex_main_position =
43 " gl_Position = qt_modelViewProjection * qt_vertPosition;\n";
44
45static const char *effect_vertex_main_post =
46 "}\n";
47
48static const char *effect_fragment_main =
49 "void main()\n"
50 "{\n"
51 " qt_customMain();\n"
52 "}\n";
53
55 "#include \"tonemapping.glsllib\"\n"
56 "void main()\n"
57 "{\n"
58 " qt_customMain();\n"
59 " fragOutput = qt_tonemap(fragOutput);\n"
60 "}\n";
61
63{
65
66 // this is called on every frame, so do nothing if there are no changes
67 if (!shaderPrepData.valid)
68 return;
69
70 QRhi *rhi = renderContext->rhiContext()->rhi();
71
72 for (int i = 0, ie = shaderPrepData.passes.size(); i != ie; ++i) {
73 const ShaderPrepPassData &pass(shaderPrepData.passes[i]);
74
75 // The fragment shader of the last pass of the last effect may need to
76 // perform the built-in tonemapping.
77 const bool isLastEffect = m_nextEffect == nullptr;
78 const bool isLastPass = i == ie - 1;
79 const bool shouldTonemapIfEnabled = isLastEffect && isLastPass;
80
81 QSSGShaderFeatures features;
82 QByteArray completeVertexShader;
83 QByteArray completeFragmentShader;
84 QByteArray sourceCodeForHash;
85 if (!pass.vertexShaderCode.isEmpty()) {
86 QByteArray code = pass.vertexShaderCode;
87 // add the real main(), with or without assigning gl_Position at the end
92 completeVertexShader = code;
93 sourceCodeForHash += code;
94 }
95 if (!pass.fragmentShaderCode.isEmpty()) {
97 if (shouldTonemapIfEnabled)
99 else
101 completeFragmentShader = code;
102 sourceCodeForHash += code;
103 }
104
105 QByteArray shaderPathKey = pass.shaderPathKeyPrefix;
106 shaderPathKey.append(':' + QCryptographicHash::hash(sourceCodeForHash, QCryptographicHash::Algorithm::Sha1).toHex());
107
108 // QSSGRhiEffectSystem will vary the vertex shader code based on this
109 // flag from the QRhi. It is therefore important to capture this in the
110 // cache key as well.
111 shaderPathKey.append(':' + QByteArray::number(rhi->isYUpInFramebuffer() ? 1 : 0));
112
113 if (shouldTonemapIfEnabled) {
114 // This does not always mean there will be tonemapping: if the mode
115 // is TonemapModeNone, then no extra feature defines are set, and
116 // so qt_tonemap() in the shader will not alter the color.
117 const QSSGRenderLayer::TonemapMode tonemapMode = layer.tonemapMode;
118 shaderPathKey.append(':' + QByteArray::number(int(tonemapMode)));
119 QSSGRenderer::setTonemapFeatures(features, tonemapMode);
120 }
121
122 // Now that the final shaderPathKey is known, store the source and
123 // related data; it will be retrieved later by the QSSGRhiEffectSystem.
124 if (!completeVertexShader.isEmpty()) {
125 renderContext->shaderLibraryManager()->setShaderSource(shaderPathKey,
127 completeVertexShader,
128 pass.vertexMetaData);
129 }
130 if (!completeFragmentShader.isEmpty()) {
132 metaData.features = features;
133 renderContext->shaderLibraryManager()->setShaderSource(shaderPathKey,
135 completeFragmentShader,
136 metaData);
137 }
138
139 // and update the command
140 delete commands[pass.bindShaderCmdIndex].command;
141 commands[pass.bindShaderCmdIndex] = { new QSSGBindShader(shaderPathKey), true };
142 }
143
144 shaderPrepData.valid = false;
145}
146
148{
149 for (const Command &cmd : commands) {
150 if (cmd.own)
151 delete cmd.command;
152 }
153 commands.clear();
154 shaderPrepData.passes.clear();
155}
156
\inmodule QtCore
Definition qbytearray.h:57
bool isEmpty() const noexcept
Returns true if the byte array has size 0; otherwise returns false.
Definition qbytearray.h:106
static QByteArray number(int, int base=10)
Returns a byte-array representing the whole number n as text.
QByteArray & append(char c)
This is an overloaded member function, provided for convenience. It differs from the above function o...
static QByteArray hash(QByteArrayView data, Algorithm method)
Returns the hash of data using method.
\inmodule QtGui
Definition qrhi.h:1767
bool isYUpInFramebuffer() const
Definition qrhi.cpp:9601
const std::unique_ptr< QSSGRhiContext > & rhiContext() const
const std::shared_ptr< QSSGShaderLibraryManager > & shaderLibraryManager() const
static void setTonemapFeatures(QSSGShaderFeatures &features, QSSGRenderLayer::TonemapMode tonemapMode)
QString & append(QChar c)
Definition qstring.cpp:3227
Combined button and popup list for selecting options.
EGLOutputLayerEXT layer
GLsizei const GLubyte * commands
GLbitfield flags
static const char * effect_vertex_main_pre
static const char * effect_vertex_main_post
static const char * effect_fragment_main_with_tonemapping
static const char * effect_fragment_main
static const char * effect_vertex_main_position
#define Q_UNUSED(x)
QSSGCustomShaderMetaData fragmentMetaData
struct QSSGRenderEffect::@750 shaderPrepData
QVector< Command > commands
void finalizeShaders(const QSSGRenderLayer &layer, QSSGRenderContextInterface *renderContext)
QSSGRenderEffect * m_nextEffect
std::underlying_type_t< Flags > FlagT
Definition moc.h:24