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