summaryrefslogtreecommitdiffstats
path: root/examples/qt3d/shadow-map-qml/doc/src/shadow-map-qml.qdoc
blob: 5d47a4d3e51def7d7a4694a2a98aa380394c20ed (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
/****************************************************************************
**
** Copyright (C) 2015 Klaralvdalens Datakonsult AB (KDAB).
** Contact: http://www.qt.io/licensing/
**
** This file is part of the documentation of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:FDL$
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and The Qt Company. For licensing terms
** and conditions see http://www.qt.io/terms-conditions. For further
** information use the contact form at http://www.qt.io/contact-us.
**
** GNU Free Documentation License Usage
** Alternatively, this file may be used under the terms of the GNU Free
** Documentation License version 1.3 as published by the Free Software
** Foundation and appearing in the file included in the packaging of
** this file. Please review the following information to ensure
** the GNU Free Documentation License version 1.3 requirements
** will be met: http://www.gnu.org/copyleft/fdl.html.
** $QT_END_LICENSE$
**
****************************************************************************/

/*!
    \example shadow-map-qml
    \title Qt 3D: Shadow Map QML Example
    \ingroup qt3d-examples-qml

    \brief A Qt 3D QML application that illustrates how to render a scene in Qt 3D
    with shadows.

    \image shadowmapping-qt3d.png

    \e {Qt 3D Shadow Map} illustrates how to configure the renderer in order to
    accommodate custom rendering techniques. The example application displays a
    self-shadowed plane and trefoil knot.

    We implement \l{Shadow Mapping}{shadow mapping} using a two pass rendering.
    In the first pass, we generate the shadow information. In the second pass,
    we generate the scene using the forward rendering technique with Phong
    shading, while at the same time using the information gathered in the first
    pass to draw the shadows.

    The entire rendering is configured using QML, but it is possible to use C++
    to achieve the very same result.

    \include examples-run.qdocinc

    \section1 Setting Up the Scene

    We set up the entire scene in the \e main.qml file.

    To be able to use the types in the Q3D and Q3D Renderer modules, we must
    import the modules:

    \quotefromfile shadow-map-qml/main.qml
    \skipto import Qt3D
    \printuntil Render

    The first entities we create are a \l Camera, which represents the camera
    used for the final rendering, and a \l Configuration, which allows us to
    control this camera using the keyboard or the mouse:

    \printuntil }
    \printuntil }

    We then create a Light custom entity, which represents our light. It is a
    directional spotlight, placed somewhere above the plane and looking down at
    the scene’s origin:

    \printuntil }

    This light entity is used by our custom framegraph, ShadowMapFrameGraph,
    and our rendering effect, AdsEffect, whose instances are created just after
    the light:

    \printuntil ]
    \printuntil }

    Last, we create three entities for the meshes in the scene: a trefoil knot,
    a toy plane, and a ground plane. They aggregate a mesh, a transformation,
    and a material that uses the AdsEffect. The toy plane and the trefoil knot
    transformations are animated:

    \printuntil /^\}/

    \section1 Specifying the Light

    We specify the Light custom entity in \e Light.qml.

    Again, we import the necessary modules:

    \quotefromfile shadow-map-qml/Light.qml
    \skipto import Qt3D
    \printuntil Qt3D.Render

    We then use an \l Entity type as the root element of the custom QML type.
    The light is a directional spotlight that exposes as properties a position,
    intensity, and a 4×4 transformation matrix:

    \printuntil matrix4x4

    In the first rendering pass, we use the light as a camera, and therefore we
    use a \l Camera entity within the light and expose it as a property:

    \printuntil /^\}/

    \section1 Configuring the Framegraph

    In Qt3D, the framegraph is the data-driven configuration for the rendering.
    We implement the framegraph in the \e ShadowMapFrameGraph.qml file.

    In addition to the Qt3D and Qt3D Renderer modules, we also import the
    Qt Quick module:

    \quotefromfile shadow-map-qml/ShadowMapFrameGraph.qml
    \skipto import Qt3D
    \printuntil QtQuick

    The code defines a \l FrameGraph entity that has a tree of entities as the
    active framegraph:

    \printuntil clearColor

    Any path from the leaves of this tree to the root is a viable framegraph
    configuration. Filter entities can enable or disable such paths, and
    selector entities can alter the configuration.

    In our case, the tree looks like this:

    \badcode
    Viewport
        RenderPassFilter
            RenderTargetSelector
                ClearBuffer
                    CameraSelector
        RenderPassFilter
            ClearBuffer
                CameraSelector
    \endcode

    So we have two paths from the topmost \l Viewport entity. Each path
    corresponds to a pass of the shadow map technique. The paths are enabled and
    disabled using a RenderPassFilter, an entity that can filter depending on
    arbitrary values defined in a given render pass. In this example, it is a
    string:

    \printuntil ]

    The actual passes are not defined here. The framegraph simply modifies its
    configuration when a given pass is rendered.

    \section1 Generating the Shadow Map

    In the shadow map generation pass, we must render to an offscreen surface
    (Framebuffer Object) which has a depth texture attachment. In Qt3D, it is
    represented by the RenderTarget entity, which has a number of attachments.

    In this example, we need only a depth attachment. We define it as a
    RenderAttachment entity using the RenderAttachment.DepthAttachment \c type
    that stores the depth and a Texture2D entity that actually configures the
    exture storage used to store the depth information:

    \printuntil ]
    \printuntil }

    Moreover, in this first pass, we must render using the light’s camera.
    Therefore, we have a CameraSelector entity that sets the camera to the one
    exported by the Light:

    \skipto CameraSelector
    \printuntil }

    The second pass is more straightforward, because we simply render to the
    screen using the main camera.

    \section1 Using Effects

    The bulk of the magic happens in the \e AdsEffect.qml file, where our main
    \l Effect entity is defined. It implements the Ambient, Diffuse and Specular
    (ADS) Lightning Model Phong shading with the addition of shadow mapped
    generated shadows.

    An effect contains the implementation of a particular rendering strategy. In
    this example, shadow mapping using two passes:

    \quotefromfile shadow-map-qml/AdsEffect.qml
    \skipto Effect
    \printuntil Light

    The \c parameters list defines some default values for the effect. The
    values will get mapped to OpenGL shader program uniforms, so that in the
    shaders we can access them. In this example, we expose some information from
    the Light entity (position, intensity, view or projection matrix defined by
    the internal camera) and the shadow map texture exposed by the framegraph:

    \skipto parameters:
    \printuntil ]

    It is possible to put such parameters all the way down, from a \l Material,
    to its \l Effect, to one of the effect’s \l Techniques. This allows a
    \l Material instance to override defaults in an \l Effect or \l Technique.
    The bindings array provides the same thing, except that it also allows us to
    rename some parameters. In this example, it renames the \c ambient,
    \c diffuse, and \c specular values defined in the material to the actual
    uniform names used by the shader programs:

    \skipto bindings:
    \printuntil ]

    To adapt the implementation to different hardware or OpenGL versions, we
    could use one or more \l Technique elements. In this example, only one
    technique is provided, targeting OpenGL 3.2 Core, or later:

    \quotefromfile shadow-map-qml/AdsEffect.qml
    \skipto techniques:
    \printuntil }

    Inside the technique, we finally have the definition of our two rendering
    passes. We \e tag each pass with an \l Annotation entity, matching the ones
    we specified in the framegraph configuration, so that each pass will have
    different rendering settings:

    \printuntil ]

    The first pass is the shadow map generation. We load a suitable set of GLSL
    shaders, which are actually extremely simple. They do only MVP (Model, View,
    Projection) to bring meshes from their model space into clip space (and,
    remember, in this first pass, the light is the camera). The fragment shader
    is totally empty, because there is no color to be generated, and the depth
    will be automatically captured for us by OpenGL:

    \printuntil }

    In this first pass, we also set some custom OpenGL state in the form of a
    polygon offset and depth testing mode:

    \printuntil ]

    \section1 Rendering Using Phong Shading

    The second pass is a normal forward rendering using Phong shading. The code
    in the effect entity is extremely simple. We simply configure some
    parameters and load a pair of shaders which will be used when drawing.

    The first part of the shadow mapping happens in the vertex shader defined in
    \e ads.vert file, where we output towards the fragment shader the
    coordinates of each vertex in light space:

    \quotefromfile shadow-map-qml/shaders/ads.vert
    \skipto mat4(
    \skipto positionInLightSpace
    \printuntil ;

    Actually, the coordinates get adjusted a little to allow us to easily sample
    the shadow map texture.

    The second part happens in the fragment shader defined in the \e ads.frag
    file, where we sample the shadow map. If the currently processed fragment is
    behind the one closest to the light, then the current fragment is in shadow
    (and only gets ambient contribution). Otherwise, it gets full Phong shading:

    \quotefromfile shadow-map-qml/shaders/ads.frag
    \skipto main
    \printuntil }
*/