summaryrefslogtreecommitdiffstats
path: root/doc/src/07-file-formats/5-custom-material-reference.qdoc
blob: 4d3d93b75627850ca912e441f4a52d423c5e5e20 (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
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
/****************************************************************************
**
** Copyright (C) 2018 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of Qt 3D Studio.
**
** $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 https://www.qt.io/terms-conditions. For further
** information use the contact form at https://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: https://www.gnu.org/licenses/fdl-1.3.html.
** $QT_END_LICENSE$
**
****************************************************************************/

/*!
\title Custom Material Reference
\page custom-material-reference.html
\ingroup qt3dstudio-file-formats

This page explains how to write custom \l {The .shader Format}{materials}.

\section1 Overview

The material specification allows writing custom materials and
connect those to the studio lighting system. A fragment shader must be written
for the material, which must implement all the functions studio uses to calculate
the shaded color. The material system also offers ready-made functions to help
implementing the material. These functions can be accessed by the shader
using \c #include directive with the name of the function.

The material system supports dielectric and transparent materials, point lights,
area lights, ambient occlusion, shadowing, two-sided polygons,
index-of-refraction and fragment cutoff(masking).

It is also possible to write custom material without using the boilerplate code,
in which case the main function must be implemented in the shader.

\note The Qt 3D Studio 2.0 runtime does not support multiple render passes for
custom materials.

\section1 Required Functions

These are the functions each fragment shader must implement.

\badcode
bool evalTwoSided()
\endcode

This function controls two-sided lighting. Return true to enable two-sided
lighting and false to disable it. When two-sided lighting is disabled, only
the front-facing material functions are called.

\badcode
float computeIOR()
\endcode

This function is called to compute the index of refraction for the material.
Return material index of refraction.

\badcode
float evalCutout()
\endcode

This function is called when evaluating fragment cutoff(masking) value.
The fragment will be discarded if the value
returned by this function is less or equal to zero.

\badcode
vec3 computeNormal()
\endcode

This function is used to calculate the normal for the fragment. Return the
normal of the fragment.

\badcode
void computeTemporaries()
\endcode

This function is called to allow the material to calculate any temporary values
it needs. It gets called before any other function.

\badcode
void initializeLayerVariables()
\endcode

This function is called to allow the material to initialize layer parameters.
User should initialize variables to store the lighting values to be computed
in the \e computeFrontLayerColor, \e computeFrontAreaColor, \e computeFrontLayerEnvironment,
\e computeBackLayerColor, \e computeBackAreaColor and \e computeBackLayerEnvironment.

\badcode
void initializeLayerVariablesWithLightmap()
\endcode

This function is called to allow the material to initialize layer parameters.
\note This function is optional and gets called only if the material uses lightmaps.

\badcode
vec3 computeFrontMaterialEmissive()
\endcode

This function is called when the material calculates the Emissive component
of the material for the front-facing polygon.
Return vec3 RGB emissive value.

\badcode
vec3 computeBackMaterialEmissive()
\endcode

This function is called when the material calculates the Emissive component
of the material for the back-facing polygon.
Return vec3 RGB emissive value.

\badcode
void computeFrontLayerColor( in vec3 normal, in vec3 lightDir, in vec3 viewDir,
                             in vec3 lightDiffuse, in vec3 lightSpecular,
                             in float materialIOR, in float aoFactor )
\endcode

This function gets called for every light(excluding area lights) for the
front-facing polygon. The material can write their own lighting model or use
the provided functions. The functions available for use are \e microfacetBSDF,
\e physGlossyBSDF and \e simpleGlossyBSDF. The \a normal is the fragment normal.
The \a lightDir is the normalized vector from fragment to light in world space.

\badcode
void computeFrontAreaColor( in int lightIdx, in vec4 lightDiffuse, in vec4 lightSpecular )
\endcode

This function gets called for every area light for the front-facing polygon.

\badcode
void computeFrontLayerEnvironment( in vec3 normal, in vec3 viewDir, in float aoFactor )
\endcode

This function gets called once to calculate the environmental light for the front-facing polygon.

\badcode
void computeBackLayerColor( in vec3 normal, in vec3 lightDir, in vec3 viewDir,
                            in vec3 lightDiffuse, in vec3 lightSpecular,
                            in float materialIOR, in float aoFactor )
\endcode

This function gets called for every light(excluding area lights) for the
back-facing polygon. The material can write their own lighting model or use
the provided functions. The functions available for use are \e microfacetBSDF,
\e physGlossyBSDF and \e simpleGlossyBSDF. The \a normal is the fragment normal.
The \a lightDir is the normalized vector from fragment to light in world space.

\badcode
void computeBackAreaColor( in int lightIdx, in vec4 lightDiffuse, in vec4 lightSpecular )
\endcode

This function gets called for every area light for the back-facing polygon.

\badcode
void computeBackLayerEnvironment( in vec3 normal, in vec3 viewDir, in float aoFactor )
\endcode

This function gets called once to calculate the environmental light for the back-facing polygon.

\badcode
vec4 computeLayerWeights( in float alpha )
\endcode

This function gets called after all lighting have been processed to calculate
the final lighting value for the fragment.

\badcode
vec4 computeGlass( in vec3 normal, in float materialIOR, in float alpha, in vec4 color )
\endcode

This function gets called only if the material is transparent and non-transmissive
after \e computeLayerWeights has been called.
\note This function is optional and gets called only if the material
is transparent and non-transmissive.

\badcode
vec4 computeOpacity( in vec4 color )
\endcode

This function gets called only if the material is transmissive after
\e computeLayerWeights has been called.
\note This function is optional and gets called only if the material
is transmissive.

\section1 Mandatory Includes

\badcode
#include "vertexFragmentBase.glsllib"
#include "SSAOCustomMaterial.glsllib"
#include "sampleLight.glsllib"
#include "sampleProbe.glsllib"
#include "sampleArea.glsllib"
\endcode

These are required includes for all materials.

\section1 Global Variables

These variables are available to the material, but should not be written to.

\badcode
vec3 normal;
vec3 surfNormal;
vec3 texCoord0;
vec3 tangent;
vec3 binormal;
vec3 viewDir;
\endcode

These are the fragment shader input variables and can only be read.

\badcode
vec3 varTexCoord0;
vec3 varTexCoord1;
vec3 varNormal;
vec3 varTangent;
vec3 varBinormal;
vec3 varObjTangent;
vec3 varObjBinormal;
vec3 varWorldPos;
vec3 varObjPos;
\endcode

\section1 Configuration Flags

These are configuration flags, which can be used to enable certain features for the material.

\badcode
#define QT3DS_ENABLE_UV0 1/0
#define QT3DS_ENABLE_WORLD_POSITION 1/0
#define QT3DS_ENABLE_TEXTAN 1/0
#define QT3DS_ENABLE_BINORMAL 1/0
\endcode

\list
\li \e QT3DS_ENABLE_UV0 flag enables texture coordinate 0 variable.
\li \e QT3DS_ENABLE_WORLD_POSITION flag enables world position variable.
\li \e QT3DS_ENABLE_TEXTAN flag enables tangent variable.
\li \e QT3DS_ENABLE_BINORMAL flag enables binormal variable.
\endlist

\section1 Configured Features

These flags are conditionally enabled by the material system when the material
is being compiled. The custom shader can use them to enable different code
paths for compilation.

\badcode
#define QT3DS_ENABLE_CG_LIGHTING
#define QT3DS_ENABLE_LIGHT_PROBE
#define QT3DS_ENABLE_SSAO
#define QT3DS_ENABLE_SSDO
#define QT3DS_ENABLE_SSM
#define QT3DS_ENABLE_RNM
\endcode

\list
\li \e QT3DS_ENABLE_CG_LIGHTING flag is enabled when lighting is enabled.
\li \e QT3DS_ENABLE_LIGHT_PROBE flag is enabled when light probe is enabled.
\li \e QT3DS_ENABLE_SSAO flag is enabled when screen space ambient occlusion is enabled.
\li \e QT3DS_ENABLE_SSDO flag is enabled when screen space direct occlusion is enabled.
\li \e QT3DS_ENABLE_SSM flag is enabled when shadow mapping is enabled.
\li \e QT3DS_ENABLE_RNM flag is enabled when normal-mapped radiosity is enabled.
\note Normal-mapped radiosity is not currently supported.
\endlist

\section1 Using Includes to Add Functionality from Shader Library

The material can import functions from the shader library using the
\c #include directive. Some functionality requires the user to define the
constant and structures of the functionality. For example, to use the
blendColorLayers function the user must specify the mono_xxx constants
and the texture_return and color_layer structure (at least once) before
including them in their material.

\badcode
#define mono_alpha 0
#define mono_average 1
#define mono_luminance 2
#define mono_maximum 3

struct texture_return
{
    vec3 tint;
    float mono;
};

struct color_layer
{
    vec3 layer_color;
    float weight;
    int mode;
};

#include "blendColorLayers.glsllib"

texture_return blendColorLayers( in color_layer colorLayer[1], in vec3 base, in int monoSource );
\endcode

Some includes require additional includes to work correctly. For example
fileBumpTexture requires these additional includes and defines:
\badcode
#include "luminance.glsllib"
#include "monoChannel.glsllib"
#define wrap_clamp 0
#define wrap_repeat 1
#define wrap_mirrored_repeat 2
#include "rotationTranslationScale.glsllib"
#include "transformCoordinate.glsllib"
\endcode

\section1 Includable Functions

\section2 microfacetBSDF

\badcode

#define scatter_reflect 0
#define scatter_transmit 1
#define scatter_reflect_transmit 2

#include "calculateRoughness.glsllib"
#include "microfacetBSDF.glsllib"

vec4 microfacetBSDF( in mat3 tanFrame, in vec3 L, in vec3 V, in vec3 lightSpecular, in float ior,
                     in float roughnessU, in float roughnessV, in int mode )
\endcode

This function calculates light value for rough surface using microfacet BSDF lighting model.
The \a tanFrame parameter is the tangent-space matrix of the fragment, \a L and \a V are the
light vector and view vector, \a lightSpecular is the light specular value, \a ior specifies
the index-of-refraction of the surface, the \a roughnessU and \a roughnessV
are the roughness factors relative to the texture U and V coordinates and the \a mode parameter
specifies how the scattering is calculated. The return value is 4-component rgba vector.

\badcode
vec4 microfacetSampledBSDF( in mat3 tanFrame, in vec3 viewDir, in float roughnessU,
                            in float roughnessV, in int mode )
\endcode

This function calculates light value for rough surface using microfacet BSDF lighting model based
on environment map. The environment map is specified with the uEnvironmentMap property.
The \a tanFrame parameter is the tangent-space matrix of the fragment, \a viewDir is the view
vector, \a roughnessU and \a roughnessV are the roughness factors relative to the texture U and V
coordinates and the \a mode parameter specifies how the scattering is calculated.
The return value is 4-component rgba vector.

\section2 physGlossyBSDF

\badcode

#define scatter_reflect 0
#define scatter_transmit 1
#define scatter_reflect_transmit 2

#include "physGlossyBSDF.glsllib"

vec4 kggxGlossyBSDF( in mat3 tanFrame, in vec3 L, in vec3 V, in vec3 lightSpecular, in float ior,
                     in float roughnessU, in float roughnessV, in int mode )
\endcode

This function calculates light value for glossy surface using the GGX BSDF.
The \a tanFrame parameter is the tangent-space matrix of the fragment, \a L and \a V are the
light vector and view vector, \a lightSpecular is the light specular value, \a ior specifies
the index-of-refraction of the surface, the \a roughnessU and \a roughnessV are the roughness
factors relative to the texture U and V coordinates and the \a mode parameter specifies how
the scattering is calculated. The return value is 4-component rgba vector.

\badcode
vec4 wardGlossyBSDF( in mat3 tanFrame, in vec3 L, in vec3 V, in vec3 lightSpecular, in float ior,
                     in float roughnessU, in float roughnessV, in int mode )
\endcode

This function calculates light value for glossy surface using the Ward BSDF.
The \a tanFrame parameter is the tangent-space matrix of the fragment, \a L and \a V are the
light vector and view vector, \a lightSpecular is the light specular value, \a ior specifies
the index-of-refraction of the surface, the \a roughnessU and \a roughnessV are the roughness
factors relative to the texture U and V coordinates and the \a mode parameter specifies how
the scattering is calculated. The return value is 4-component rgba vector.

\section2 simpleGlossyBSDF

\badcode

#define scatter_reflect 0
#define scatter_transmit 1
#define scatter_reflect_transmit 2

#include "calculateRoughness.glsllib"
#include "simpleGlossyBSDF.glsllib"

vec4 simpleGlossyBSDF( in mat3 tanFrame, in vec3 L, vec3 V, in vec3 lightSpecular, in float ior,
                       in float roughnessU, in float roughnessV, in int mode )
\endcode

This function calculates light value for glossy surface using the simple BSDF.
The \a tanFrame parameter is the tangent-space matrix of the fragment, \a L and \a V are the light
vector and view vector, \a lightSpecular is the light specular value, \a ior specifies the
index-of-refraction of the surface, the \a roughnessU and \a roughnessV are the roughness factors
relative to the texture U and V coordinates and the \a mode parameter specifies how
the scattering is calculated. The return value is 4-component rgba vector.

\badcode
vec4 simpleGlossyBSDFEnvironment( in mat3 tanFrame, in vec3 viewDir, in float roughnessU,
                                  in float roughnessV, in int mode )
\endcode

This function calculates light value for glossy surface using simple BSDF lighting model based on
environment map. The environment map is specified with the uEnvironmentMap property.
The \a tanFrame parameter is the tangent-space matrix of the fragment, \a viewDir is the view
vector, \a roughnessU and \a roughnessV are the roughness factors relative to the texture U and V
coordinates and the \a mode parameter specifies how the scattering is calculated.
The return value is 4-component rgba vector.


\section2 sampleProbe

\badcode
#include "sampleProbe.glsllib"

vec4 sampleGlossyAniso( mat3 tanFrame, vec3 viewDir, float roughnessU, float roughnessV )
\endcode

Calculates specular sample for the light probe. The \a tanFrame parameter is the tangent-space
matrix of the fragment, \a viewDir is the view vector and \a roughnessU and \a roughnessV are
the roughness factors relative to the texture U and V coordinates.

\note QT3DS_ENABLE_LIGHT_PROBE must be enabled to use this function.

\badcode
vec4 sampleDiffuse( mat3 tanFrame )
\endcode

Calculates diffuse sample for the light probe. The \a tanFrame parameter is the tangent-space
matrix of the fragment.

\note QT3DS_ENABLE_LIGHT_PROBE must be enabled to use this function.

\section2 sampleArea

\badcode
#include "sampleArea.glsllib"

vec4 sampleAreaGlossy( in mat3 tanFrame, in vec3 pos, in int lightIdx, in vec3 viewDir,
                       in float roughnessU, in float roughnessV )
\endcode

Computes specular sample for an area light. The \a tanFrame parameter is the tangent-space matrix
of the fragment, \a pos is the fragmentworld position, \a lightIdx is the index of the light,
\a viewDir is the view vector and \a roughnessU and \a roughnessV are the roughness
factors relative to the texture U and V coordinates.

\badcode
vec4 sampleAreaDiffuse( in mat3 tanFrame, in vec3 pos, in int lightIdx )
\endcode

Computes diffuse sample for an area light. The \a tanFrame parameter is the tangent-space matrix
of the fragment, \a pos is the fragmentworld position and \a lightIdx is the index of the light,

\section1 Custom Material with Main Function

It is also possible to write the custom material without the rest of the material system.
In this case it is not necessary to write all the functions described above. Each pass only has to
contain main function.

\badcode
out vec4 fragColor;
void main()
{
    fragColor = ...
}
\endcode

\note Previous versions stated that the closing parenthesis should not be added to the main function.
This is no longer the case and the main function should add the closing parenthesis.

\section2 Simple Custom Material Example

\badcode
<Material name="simplecustom" version="1.0">
    <MetaData >
        <Property formalName="Red" name="red_weight" type="Float" default="1.0" min="0" max="1.0" category="Material"/>
        <Property formalName="Green" name="green_weight" type="Float" default="1.0" min="0" max="1.0" category="Material"/>
        <Property formalName="Blue" name="blue_weight" type="Float" default="1.0" min="0" max="1.0" category="Material"/>
        <Property formalName="Base Color" name="basecolor" type="Texture" filter="linear" minfilter="linearMipmapLinear" clamp="repeat" category="Material"/>
    </MetaData>
    <Shaders type="GLSL" version="330">
    <Shader>
        <Shared></Shared>
        <VertexShader>
        </VertexShader>
        <FragmentShader>
#define UIC_ENABLE_UV0 1
#define UIC_ENABLE_WORLD_POSITION 1
#define UIC_ENABLE_TEXTAN 0
#define UIC_ENABLE_BINORMAL 0

#include "vertexFragmentBase.glsllib"
#include "SSAOCustomMaterial.glsllib"
#include "sampleLight.glsllib"
#include "sampleProbe.glsllib"
#include "sampleArea.glsllib"

// Set shader output.
out vec4 fragColor;

    void main()
    {
        vec4 c = texture(basecolor, varTexCoord0.xy);
        c.rgb *= vec3(red_weight, green_weight, blue_weight);
        fragColor = c;
    }
        </FragmentShader>
    </Shader>
    </Shaders>
    <Passes >
        <ShaderKey value="7"/>
        <LayerKey count="1"/>
    <Pass >
    </Pass>
</Passes>
</Material>
\endcode

\section1 ShaderKey

ShaderKey-element is a magic number specifying how the material gets compiled. The value is
the sum of the properties the material needs to enable. Supported properties are:

\value 1 Dielectric
\value 2 Specular
\value 4 Glossy
\value 8 Cutout
\value 16 Refraction
\value 32 Transparent
\value 256 Transmissive

LayerKey-element specifies how many layers the material has. This is currently ignored.

*/