1 /****************************************************************************
2 **
3 ** Copyright (C) 2008-2012 NVIDIA Corporation.
4 ** Copyright (C) 2019 The Qt Company Ltd.
5 ** Contact: https://www.qt.io/licensing/
6 **
7 ** This file is part of Qt Quick 3D.
8 **
9 ** $QT_BEGIN_LICENSE:GPL$
10 ** Commercial License Usage
11 ** Licensees holding valid commercial Qt licenses may use this file in
12 ** accordance with the commercial license agreement provided with the
13 ** Software or, alternatively, in accordance with the terms contained in
14 ** a written agreement between you and The Qt Company. For licensing terms
15 ** and conditions see https://www.qt.io/terms-conditions. For further
16 ** information use the contact form at https://www.qt.io/contact-us.
17 **
18 ** GNU General Public License Usage
19 ** Alternatively, this file may be used under the terms of the GNU
20 ** General Public License version 3 or (at your option) any later version
21 ** approved by the KDE Free Qt Foundation. The licenses are as published by
22 ** the Free Software Foundation and appearing in the file LICENSE.GPL3
23 ** included in the packaging of this file. Please review the following
24 ** information to ensure the GNU General Public License requirements will
25 ** be met: https://www.gnu.org/licenses/gpl-3.0.html.
26 **
27 ** $QT_END_LICENSE$
28 **
29 ****************************************************************************/
30
31 #include <QtQuick3DRuntimeRender/private/qssgrenderlayer_p.h>
32 #include <QtQuick3DRuntimeRender/private/qssgrendershadowmap_p.h>
33 #include <QtQuick3DRuntimeRender/private/qssgrenderresourcemanager_p.h>
34 #include <QtQuick3DRuntimeRender/private/qssgrendererimpllayerrenderdata_p.h>
35 #include <QtQuick3DRender/private/qssgrendershaderconstant_p.h>
36 #include <QtQuick3DRender/private/qssgrendershaderprogram_p.h>
37
38 QT_BEGIN_NAMESPACE
39
QSSGRenderShadowMap(const QSSGRef<QSSGRenderContextInterface> & inContext)40 QSSGRenderShadowMap::QSSGRenderShadowMap(const QSSGRef<QSSGRenderContextInterface> &inContext)
41 : m_context(inContext)
42 {}
43
~QSSGRenderShadowMap()44 QSSGRenderShadowMap::~QSSGRenderShadowMap()
45 {
46 m_shadowMapList.clear();
47 }
48
49 //static bool isDepthFormat(QSSGRenderTextureFormat format)
50 //{
51 // switch (format.format) {
52 // case QSSGRenderTextureFormat::Depth16:
53 // case QSSGRenderTextureFormat::Depth24:
54 // case QSSGRenderTextureFormat::Depth32:
55 // case QSSGRenderTextureFormat::Depth24Stencil8:
56 // return true;
57 // default:
58 // return false;
59 // }
60 //}
61
addShadowMapEntry(qint32 index,qint32 width,qint32 height,QSSGRenderTextureFormat format,qint32 samples,ShadowMapModes mode,ShadowFilterValues filter)62 void QSSGRenderShadowMap::addShadowMapEntry(qint32 index,
63 qint32 width,
64 qint32 height,
65 QSSGRenderTextureFormat format,
66 qint32 samples,
67 ShadowMapModes mode,
68 ShadowFilterValues filter)
69 {
70 const QSSGRef<QSSGResourceManager> &theManager(m_context->resourceManager());
71 QSSGShadowMapEntry *pEntry = nullptr;
72
73 if (index < m_shadowMapList.size())
74 pEntry = &m_shadowMapList[index];
75
76 if (pEntry) {
77 if ((nullptr != pEntry->m_depthMap) && (mode == ShadowMapModes::CUBE)) {
78 theManager->release(pEntry->m_depthMap);
79 theManager->release(pEntry->m_depthCopy);
80 theManager->release(pEntry->m_depthRender);
81 pEntry->m_depthCube = theManager->allocateTextureCube(width, height, format, samples);
82 pEntry->m_cubeCopy = theManager->allocateTextureCube(width, height, format, samples);
83 pEntry->m_depthRender = theManager->allocateTexture2D(width, height, QSSGRenderTextureFormat::Depth24Stencil8, samples);
84 pEntry->m_depthMap = nullptr;
85 pEntry->m_depthCopy = nullptr;
86 } else if ((nullptr != pEntry->m_depthCube) && (mode != ShadowMapModes::CUBE)) {
87 theManager->release(pEntry->m_depthCube);
88 theManager->release(pEntry->m_cubeCopy);
89 theManager->release(pEntry->m_depthRender);
90 pEntry->m_depthMap = theManager->allocateTexture2D(width, height, format, samples);
91 pEntry->m_depthCopy = theManager->allocateTexture2D(width, height, format, samples);
92 pEntry->m_depthCube = nullptr;
93 pEntry->m_cubeCopy = nullptr;
94 pEntry->m_depthRender = theManager->allocateTexture2D(width, height, QSSGRenderTextureFormat::Depth24Stencil8, samples);
95 } else if (nullptr != pEntry->m_depthMap) {
96 QSSGTextureDetails theDetails(pEntry->m_depthMap->textureDetails());
97
98 // If anything differs about the map we're looking for, let's recreate it.
99 if (theDetails.format != format || theDetails.width != width || theDetails.height != height
100 || theDetails.sampleCount != samples) {
101 // release texture
102 theManager->release(pEntry->m_depthMap);
103 theManager->release(pEntry->m_depthCopy);
104 theManager->release(pEntry->m_depthRender);
105 pEntry->m_depthMap = theManager->allocateTexture2D(width, height, format, samples);
106 pEntry->m_depthCopy = theManager->allocateTexture2D(width, height, format, samples);
107 pEntry->m_depthCube = nullptr;
108 pEntry->m_cubeCopy = nullptr;
109 pEntry->m_depthRender = theManager->allocateTexture2D(width, height, QSSGRenderTextureFormat::Depth24Stencil8, samples);
110 }
111 } else {
112 QSSGTextureDetails theDetails(pEntry->m_depthCube->textureDetails());
113
114 // If anything differs about the map we're looking for, let's recreate it.
115 if (theDetails.format != format || theDetails.width != width || theDetails.height != height
116 || theDetails.sampleCount != samples) {
117 // release texture
118 theManager->release(pEntry->m_depthCube);
119 theManager->release(pEntry->m_cubeCopy);
120 theManager->release(pEntry->m_depthRender);
121 pEntry->m_depthCube = theManager->allocateTextureCube(width, height, format, samples);
122 pEntry->m_cubeCopy = theManager->allocateTextureCube(width, height, format, samples);
123 pEntry->m_depthRender = theManager->allocateTexture2D(width, height, QSSGRenderTextureFormat::Depth24Stencil8, samples);
124 pEntry->m_depthMap = nullptr;
125 pEntry->m_depthCopy = nullptr;
126 }
127 }
128
129 pEntry->m_shadowMapMode = mode;
130 pEntry->m_shadowFilterFlags = filter;
131 } else if (mode == ShadowMapModes::CUBE) {
132 QSSGRef<QSSGRenderTextureCube> theDepthTex = theManager->allocateTextureCube(width, height, format, samples);
133 QSSGRef<QSSGRenderTextureCube> theDepthCopy = theManager->allocateTextureCube(width, height, format, samples);
134 QSSGRef<QSSGRenderTexture2D> theDepthTemp = theManager->allocateTexture2D(width,
135 height,
136 QSSGRenderTextureFormat::Depth24Stencil8,
137 samples);
138 m_shadowMapList.push_back(QSSGShadowMapEntry(index, mode, filter, theDepthTex, theDepthCopy, theDepthTemp));
139
140 pEntry = &m_shadowMapList.back();
141 } else {
142 QSSGRef<QSSGRenderTexture2D> theDepthMap = theManager->allocateTexture2D(width, height, format, samples);
143 QSSGRef<QSSGRenderTexture2D> theDepthCopy = theManager->allocateTexture2D(width, height, format, samples);
144 QSSGRef<QSSGRenderTexture2D> theDepthTemp = theManager->allocateTexture2D(width,
145 height,
146 QSSGRenderTextureFormat::Depth24Stencil8,
147 samples);
148 m_shadowMapList.push_back(QSSGShadowMapEntry(index, mode, filter, theDepthMap, theDepthCopy, theDepthTemp));
149
150 pEntry = &m_shadowMapList.back();
151 }
152
153 if (pEntry) {
154 // setup some texture settings
155 if (pEntry->m_depthMap) {
156 pEntry->m_depthMap->setMinFilter(QSSGRenderTextureMinifyingOp::Linear);
157 pEntry->m_depthMap->setMagFilter(QSSGRenderTextureMagnifyingOp::Linear);
158 pEntry->m_depthMap->setTextureWrapS(QSSGRenderTextureCoordOp::ClampToEdge);
159 pEntry->m_depthMap->setTextureWrapT(QSSGRenderTextureCoordOp::ClampToEdge);
160
161 pEntry->m_depthCopy->setMinFilter(QSSGRenderTextureMinifyingOp::Linear);
162 pEntry->m_depthCopy->setMagFilter(QSSGRenderTextureMagnifyingOp::Linear);
163 pEntry->m_depthCopy->setTextureWrapS(QSSGRenderTextureCoordOp::ClampToEdge);
164 pEntry->m_depthCopy->setTextureWrapT(QSSGRenderTextureCoordOp::ClampToEdge);
165
166 pEntry->m_depthRender->setMinFilter(QSSGRenderTextureMinifyingOp::Linear);
167 pEntry->m_depthRender->setMagFilter(QSSGRenderTextureMagnifyingOp::Linear);
168 pEntry->m_depthRender->setTextureWrapS(QSSGRenderTextureCoordOp::ClampToEdge);
169 pEntry->m_depthRender->setTextureWrapT(QSSGRenderTextureCoordOp::ClampToEdge);
170 } else {
171 pEntry->m_depthCube->setMinFilter(QSSGRenderTextureMinifyingOp::Linear);
172 pEntry->m_depthCube->setMagFilter(QSSGRenderTextureMagnifyingOp::Linear);
173 pEntry->m_depthCube->setTextureWrapS(QSSGRenderTextureCoordOp::ClampToEdge);
174 pEntry->m_depthCube->setTextureWrapT(QSSGRenderTextureCoordOp::ClampToEdge);
175
176 pEntry->m_cubeCopy->setMinFilter(QSSGRenderTextureMinifyingOp::Linear);
177 pEntry->m_cubeCopy->setMagFilter(QSSGRenderTextureMagnifyingOp::Linear);
178 pEntry->m_cubeCopy->setTextureWrapS(QSSGRenderTextureCoordOp::ClampToEdge);
179 pEntry->m_cubeCopy->setTextureWrapT(QSSGRenderTextureCoordOp::ClampToEdge);
180
181 pEntry->m_depthRender->setMinFilter(QSSGRenderTextureMinifyingOp::Linear);
182 pEntry->m_depthRender->setMagFilter(QSSGRenderTextureMagnifyingOp::Linear);
183 pEntry->m_depthRender->setTextureWrapS(QSSGRenderTextureCoordOp::ClampToEdge);
184 pEntry->m_depthRender->setTextureWrapT(QSSGRenderTextureCoordOp::ClampToEdge);
185 }
186
187 pEntry->m_lightIndex = index;
188 }
189 }
190
getShadowMapEntry(int index)191 QSSGShadowMapEntry *QSSGRenderShadowMap::getShadowMapEntry(int index)
192 {
193 if (index < 0) {
194 Q_UNREACHABLE();
195 return nullptr;
196 }
197 QSSGShadowMapEntry *pEntry = nullptr;
198
199 for (int i = 0; i < m_shadowMapList.size(); i++) {
200 pEntry = &m_shadowMapList[i];
201 if (pEntry->m_lightIndex == quint32(index))
202 return pEntry;
203 }
204
205 return nullptr;
206 }
207
create(const QSSGRef<QSSGRenderContextInterface> & inContext)208 QSSGRef<QSSGRenderShadowMap> QSSGRenderShadowMap::create(const QSSGRef<QSSGRenderContextInterface> &inContext)
209 {
210 return QSSGRef<QSSGRenderShadowMap>(new QSSGRenderShadowMap(inContext));
211 }
212
213 QT_END_NAMESPACE
214