This page explains how to write custom material using the QtQuick3D.Materials material library interface.
The material specification lets you write custom materials and connect those to the lighting system. Each material must have a fragment shader that implements all the functions the library needs to calculate the shaded color. The material system also offers readymade functions to help implementing the material. These functions can be accessed by the shader using #include
directive with the name of the function.
The material system supports dielectric and transparent materials, point lights, area lights, ambient occlusion, shadowing, twosided polygons, indexofrefraction, 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.
These are the functions each fragment shader must implement.
bool evalTwoSided()
This function controls twosided lighting. Return true
to enable twosided lighting and false
to disable it. When twosided lighting is disabled, only the frontfacing material functions are called.
float computeIOR()
This function is called to compute the index of refraction for the material. Return material index of refraction.
float evalCutout()
This function is called when evaluating fragment cutoff (masking) value. The fragment is discarded if the value returned by this function is less than or equal to zero.
vec3 computeNormal()
This function is used to calculate the normal for the fragment. Return the normal of the fragment.
void computeTemporaries()
This function is called to calculate any temporary values needed by the material and it is called before any other function.
void initializeLayerVariables()
This function is called to initialize layer parameters for the material. User should initialize variables to store the lighting values to be computed in the computeFrontLayerColor
, computeFrontAreaColor
, computeFrontLayerEnvironment
, computeBackLayerColor
, computeBackAreaColor
, and computeBackLayerEnvironment
.
void initializeLayerVariablesWithLightmap()
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.
vec3 computeFrontMaterialEmissive()
This function is called when the material calculates the Emissive component of the material for the frontfacing polygon. Return vec3 RGB emissive value.
vec3 computeBackMaterialEmissive()
This function is called when the material calculates the Emissive component of the material for the backfacing polygon. Return vec3 RGB emissive value.
void computeFrontLayerColor( in vec3 normal, in vec3 lightDir, in vec3 viewDir, in vec3 lightDiffuse, in vec3 lightSpecular, in float materialIOR, in float aoFactor )
This function is called for every light (excluding area lights) for the frontfacing polygon. The material can write its own lighting model or use the provided functions. The functions available for use are microfacetBSDF
, physGlossyBSDF
, and simpleGlossyBSDF
. The normal
is the fragment normal. The lightDir
is the normalized vector from fragment to light in world space.
void computeFrontAreaColor( in int lightIdx, in vec4 lightDiffuse, in vec4 lightSpecular )
This function is called for every area light for the frontfacing polygon.
void computeFrontLayerEnvironment( in vec3 normal, in vec3 viewDir, in float aoFactor )
This function is called once to calculate the environmental light for the frontfacing polygon.
void computeBackLayerColor( in vec3 normal, in vec3 lightDir, in vec3 viewDir, in vec3 lightDiffuse, in vec3 lightSpecular, in float materialIOR, in float aoFactor )
This function is called for every light (excluding area lights) for the backfacing polygon. The material can write its own lighting model or use the provided functions. The functions available for use are microfacetBSDF
, physGlossyBSDF
and simpleGlossyBSDF
. The normal
is the fragment normal. The lightDir
is the normalized vector from fragment to light in world space.
void computeBackAreaColor( in int lightIdx, in vec4 lightDiffuse, in vec4 lightSpecular )
This function is called for every area light for the backfacing polygon.
void computeBackLayerEnvironment( in vec3 normal, in vec3 viewDir, in float aoFactor )
This function is called once to calculate the environmental light for the backfacing polygon.
vec4 computeLayerWeights( in float alpha )
This function is called after all lighting have been processed to calculate the final lighting value for the fragment.
vec4 computeGlass( in vec3 normal, in float materialIOR, in float alpha, in vec4 color )
This function is called only if the material is transparent and nontransmissive after computeLayerWeights
has been called.
vec4 computeOpacity( in vec4 color )
This function is called only if the material is transmissive after computeLayerWeights
has been called.
#include "vertexFragmentBase.glsllib" #include "SSAOCustomMaterial.glsllib" #include "sampleLight.glsllib" #include "sampleProbe.glsllib" #include "sampleArea.glsllib"
These includes are required for all materials.
These variables are available to the material, but should not be modified:
vec3 normal; vec3 surfNormal; vec3 texCoord0; vec3 tangent; vec3 binormal; vec3 viewDir;
These are readonly the fragment shader input variables.
vec3 varTexCoord0; vec3 varTexCoord1; vec3 varNormal; vec3 varTangent; vec3 varBinormal; vec3 varObjTangent; vec3 varObjBinormal; vec3 varWorldPos; vec3 varObjPos;
These configuration flags can be used to enable certain features for the material.
#define QSSG_ENABLE_UV0 1/0 #define QSSG_ENABLE_WORLD_POSITION 1/0 #define QSSG_ENABLE_TEXTAN 1/0 #define QSSG_ENABLE_BINORMAL 1/0
Flag  Desctiption 

QSSG_ENABLE_UV0 
Enables texture coordinate 0 variable. 
QSSG_ENABLE_WORLD_POSITION 
Enables world position variable. 
QSSG_ENABLE_TEXTAN 
Enables tangent variable. 
QSSG_ENABLE_BINORMAL 
Enables binormal variable. 
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.
#define QSSG_ENABLE_CG_LIGHTING #define QSSG_ENABLE_LIGHT_PROBE #define QSSG_ENABLE_SSAO #define QSSG_ENABLE_SSDO #define QSSG_ENABLE_SSM #define QSSG_ENABLE_RNM
Note: Normalmapped radiosity is not currently supported.
Flag  Desctiption 

QSSG_ENABLE_CG_LIGHTING 
Enabled when lighting is enabled. 
QSSG_ENABLE_LIGHT_PROBE 
Enabled when light probe is enabled. 
QSSG_ENABLE_SSAO 
Enabled when screen space ambient occlusion is enabled. 
QSSG_ENABLE_SSDO 
Enabled when screen space direct occlusion is enabled. 
QSSG_ENABLE_SSM 
Enabled when shadow mapping is enabled. 
QSSG_ENABLE_RNM 
Enabled when normalmapped radiosity is enabled. 
The material can import functions from the shader library using the #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.
#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 );
Some includes require additional functionality to work correctly. For example fileBumpTexture
requires these additional includes and defines:
#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"
#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 )
This function calculates light value for rough surface using microfacet BSDF lighting model. The return value is 4component rgba vector.
Parameter  Description 

tanFrame 
Tangentspace matrix of the fragment. 
L 
Light vector. 
V 
View vector. 
ior 
Indexofrefraction. 
roughtnessU roughnessV

Roughness factors relative to the texture U and Vcoordinates. 
mode 
The mode of scattering calculations. 
vec4 microfacetSampledBSDF( in mat3 tanFrame, in vec3 viewDir, in float roughnessU, in float roughnessV, in int mode )
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 return value is 4component rgba vector.
Parameter  Description 

tanFrame 
Tangentspace matrix of the fragment. 
viewDir 
View direction vector. 
roughtnessU roughnessV

Roughness factors relative to the texture U and Vcoordinates. 
mode 
The mode of scattering calculations. 
#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 )
This function calculates light value for glossy surface using the GGX BSDF. The return value is 4component rgba vector.
Parameter  Description 

tanFrame 
Tangentspace matrix of the fragment. 
L 
Light vector. 
V 
View vector. 
lightSpecular 
Light specular value. 
ior 
Indexofrefraction. 
roughtnessU roughnessV

Roughness factors relative to the texture U and Vcoordinates. 
mode 
The mode of scattering calculations. 
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 )
This function calculates light value for glossy surface using the Ward BSDF. The return value is 4component rgba vector.
Parameter  Description 

tanFrame 
Tangentspace matrix of the fragment. 
L 
Light vector. 
V 
View vector. 
lightSpecular 
Light specular value. 
ior 
Indexofrefraction. 
roughtnessU roughnessV

Roughness factors relative to the texture U and Vcoordinates. 
mode 
The mode of scattering calculations. 
#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 )
This function calculates light value for glossy surface using the simple BSDF. The return value is 4component rgba vector.
Parameter  Description 

tanFrame 
Tangentspace matrix of the fragment. 
L 
Light vector. 
V 
View vector. 
lightSpecular 
Light specular value. 
ior 
Indexofrefraction. 
roughtnessU roughnessV

Roughness factors relative to the texture U and Vcoordinates. 
mode 
The mode of scattering calculations. 
vec4 simpleGlossyBSDFEnvironment( in mat3 tanFrame, in vec3 viewDir, in float roughnessU, in float roughnessV, in int mode )
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 return value is 4component rgba vector.
Parameter  Description 

tanFrame 
Tangentspace matrix of the fragment. 
viewDir 
View vector. 
roughtnessU roughnessV

Roughness factors relative to the texture U and Vcoordinates. 
mode 
The mode of scattering calculations. 
#include "sampleProbe.glsllib" vec4 sampleGlossy( mat3 tanFrame, vec3 viewDir, float roughness )
Calculates specular sample for the light probe. The return value is 4component rgba vector.
Parameter  Description 

tanFrame 
Tangentspace matrix of the fragment. 
viewDir 
View direction vector. 
roughtnessU roughnessV

Roughness factors relative to the texture U and Vcoordinates. 
Note: QT3DS_ENABLE_LIGHT_PROBE must be enabled to use this function.
vec4 sampleDiffuse( mat3 tanFrame )
Calculates diffuse sample for the light probe. The return value is 4component rgba vector.
Parameter  Description 

tanFrame 
Tangentspace matrix of the fragment. 
Note: QT3DS_ENABLE_LIGHT_PROBE must be enabled to use this function.
#include "sampleArea.glsllib" vec4 sampleAreaGlossy( in mat3 tanFrame, in vec3 pos, in int lightIdx, in vec3 viewDir, in float roughnessU, in float roughnessV )
Computes specular sample for an area light. The return value is 4component rgba vector.
Parameter  Description 

tanFrame 
Tangentspace matrix of the fragment. 
pos 
Fragment world position. 
lightIdx 
Index of the light to sample. 
viewDir 
View direction vector. 
roughtnessU roughnessV

Roughness factors relative to the texture U and Vcoordinates. 
vec4 sampleAreaDiffuse( in mat3 tanFrame, in vec3 pos, in int lightIdx )
Computes diffuse sample for an area light. The return value is 4component rgba vector.
Parameter  Description 

tanFrame 
Tangentspace matrix of the fragment. 
pos 
Fragment world position. 
lightIdx 
Index of the light to sample. 
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 needs a main function only.
out vec4 fragColor; void main() { fragColor = ... }
#define QSSG_ENABLE_UV0 1 #define QSSG_ENABLE_WORLD_POSITION 1 #define QSSG_ENABLE_TEXTAN 0 #define QSSG_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; }
Default vertex shader generation can be overridden with a custom vertex shader.
in vec3 attr_pos; uniform mat4 modelViewProjection; out vec3 pos; void main() { pos = attr_pos; pos.x += sin(time * 4.0 + pos.y) * amplitude; gl_Position = modelViewProjection * vec4(pos, 1.0); }
The vertex attributes provided as inputs to the vertex shaders are defined by the mesh files. The following vertex attributes are used by default.
in vec3 attr_pos; in vec3 attr_norm; in vec2 attr_uv0; in vec3 attr_textan; in vec3 attr_binormal;
The following uniforms are provided to shaders.
uniform mat4 modelMatrix; uniform mat4 modelViewProjection; uniform mat4 viewMatrix; uniform mat3 normalMatrix; uniform mat4 viewProjectionMatrix; uniform mat4 viewportMatrix; uniform vec3 cameraPosition; uniform vec2 cameraProperties; uniform sampler2D depthTexture; uniform sampler2D aoTexture; uniform sampler2D lightProbe; uniform vec4 lightProbeProperties; uniform vec4 lightProbeOptions; uniform vec4 lightProbeRotation; uniform vec4 lightProbeOffset; uniform sampler2D lightProbe2; uniform vec4 lightProbe2Properties; uniform int lightCount; uniform int areaLightCount; uniform int shadowMapCount; uniform int shadowCubeCount; uniform float objectOpacity; uniform sampler2D shadowMaps[8]; uniform samplerCube shadowCubes[8];
© The Qt Company Ltd
Licensed under the GNU Free Documentation License, Version 1.3.
https://doc.qt.io/qt5.15/custommaterialreference.html