![]() |
Qt 6.x
The Qt SDK
|
#include "qquick3dcustommaterial_p.h"#include <QtQuick3DRuntimeRender/private/qssgrendercustommaterial_p.h>#include <QtQuick3DRuntimeRender/private/qssgrendercontextcore_p.h>#include <QtQuick3DRuntimeRender/private/qssgshadermaterialadapter_p.h>#include <QtQuick/QQuickWindow>#include "qquick3dobject_p.h"#include "qquick3dviewport_p.h"#include "qquick3dscenemanager_p.h"
Include dependency graph for qquick3dcustommaterial.cpp:Go to the source code of this file.
Functions | |
| static QT_BEGIN_NAMESPACE QRhiGraphicsPipeline::BlendFactor | toRhiBlendFactor (QQuick3DCustomMaterial::BlendMode mode) |
| \qmlproperty url CustomMaterial::vertexShader | |
| static void | setCustomMaterialFlagsFromShader (QSSGRenderCustomMaterial *material, const QSSGCustomShaderMetaData &meta) |
|
static |
Definition at line 1427 of file qquick3dcustommaterial.cpp.
References QSSGRenderCustomMaterial::AoTexture, QSSGRenderCustomMaterial::DepthTexture, QSSGCustomShaderMetaData::flags, QSSGRenderCustomMaterial::IblOrientation, QSSGRenderCustomMaterial::InverseProjectionMatrix, QSSGRenderCustomMaterial::Lightmap, QSSGRenderCustomMaterial::m_renderFlags, QSSGRenderCustomMaterial::Morphing, QSSGRenderCustomMaterial::ProjectionMatrix, QSSGRenderCustomMaterial::ScreenMipTexture, QSSGRenderCustomMaterial::ScreenTexture, QSSGRenderCustomMaterial::Skinning, QSSGCustomShaderMetaData::UsesAoTexture, QSSGCustomShaderMetaData::UsesDepthTexture, QSSGCustomShaderMetaData::UsesIblOrientation, QSSGCustomShaderMetaData::UsesInverseProjectionMatrix, QSSGCustomShaderMetaData::UsesLightmap, QSSGCustomShaderMetaData::UsesMorphing, QSSGCustomShaderMetaData::UsesProjectionMatrix, QSSGCustomShaderMetaData::UsesScreenMipTexture, QSSGCustomShaderMetaData::UsesScreenTexture, QSSGCustomShaderMetaData::UsesSkinning, QSSGCustomShaderMetaData::UsesVarColor, and QSSGRenderCustomMaterial::VarColor.
Referenced by QQuick3DCustomMaterial::updateSpatialNode().
Here is the caller graph for this function:
|
inlinestatic |
\qmlproperty url CustomMaterial::vertexShader
\qmltype CustomMaterial
\inherits Material
\inqmlmodule QtQuick3D
\brief Base component for creating custom materials used to shade models.
The custom material allows using custom shader code for a material, enabling
programmability on graphics shader level. A vertex, fragment, or both
shaders can be provided. The \l vertexShader and \l fragmentShader
properties are URLs, referencing files containing shader snippets, and work
very similarly to ShaderEffect or \l{Image::source}{Image.source}. Only the
\c file and \c qrc schemes are supported with custom materials. It is also
possible to omit the \c file scheme, allowing to specify a relative path in
a convenient way. Such a path is resolved relative to the component's (the
\c{.qml} file's) location.
For a getting started guide to custom materials, see the page \l{Programmable
Materials, Effects, Geometry, and Texture data}.
\section1 Introduction
Consider the following versions of the same scene. On the left, the cylinder
is using a built-in, non-programmable material. Such materials are
configurable through a wide range of properties, but there is no further
control given over the shaders that are generated under the hood. On the
right, the same cylinder is now associated with a CustomMaterial referencing
application-provided vertex and fragment shader snippets. This allows
inserting custom, application-specific logic into the vertex shader to
transform the geometry, and to determine certain color properties in a
custom manner in the fragment shader. As this is a
\l{shadingMode}{shaded} custom material, the cylinder still
participates in the scene lighting normally.
\table 70%
\row
\li \qml
View3D {
anchors.fill: parent
PerspectiveCamera {
id: camera
position: Qt.vector3d(0, 0, 600)
}
camera: camera
DirectionalLight {
position: Qt.vector3d(-500, 500, -100)
color: Qt.rgba(0.2, 0.2, 0.2, 1.0)
ambientColor: Qt.rgba(0.1, 0.1, 0.1, 1.0)
}
Model {
source: "#Cylinder"
eulerRotation: Qt.vector3d(30, 30, 0)
scale: Qt.vector3d(1.5, 1.5, 1.5)
materials: [
DefaultMaterial {
diffuseColor: Qt.rgba(0, 1, 0, 1)
}
]
}
}
\endqml
\li \qml
View3D {
anchors.fill: parent
PerspectiveCamera {
id: camera
position: Qt.vector3d(0, 0, 600)
}
camera: camera
DirectionalLight {
position: Qt.vector3d(-500, 500, -100)
color: Qt.rgba(0.2, 0.2, 0.2, 1.0)
ambientColor: Qt.rgba(0.1, 0.1, 0.1, 1.0)
}
Model {
source: "#Cylinder"
eulerRotation: Qt.vector3d(30, 30, 0)
scale: Qt.vector3d(1.5, 1.5, 1.5)
materials: [
CustomMaterial {
vertexShader: "material.vert"
fragmentShader: "material.frag"
property real uTime
property real uAmplitude: 50
NumberAnimation on uTime { from: 0; to: 100; duration: 10000; loops: -1 }
}
]
}
}
\endqml
\endtable
Let's assume that the shader snippets in \c{material.vert} and \c{material.frag} are
the following:
\table 70%
\row
\li \badcode
void MAIN()
{
VERTEX.x += sin(uTime + VERTEX.y) * uAmplitude;
}
\endcode
\li \badcode
void MAIN()
{
BASE_COLOR = vec4(0.0, 1.0, 0.0, 1.0);
}
\endcode
\endtable
Notice how \c uTime and \c uAmplitude are properties of the CustomMaterial
element. They can change values and get animated normally, the values will
be exposed to the shaders automatically without any further action from the
developer.
The result is a cylinder that animates its vertices:
\image custommaterial_cylinder.png
\section1 Two flavors of custom materials
There are two main types of custom materials. This is specified by the \l
shadingMode property. In \l{CustomMaterial::shadingMode}{unshaded} custom
materials the fragment shader outputs a single \c vec4 color, ignoring
lights, light probes, shadowing in the scene. In
\l{CustomMaterial::shadingMode}{shaded} materials the shader is expected to
implement certain functions and work with built-in variables to take
lighting and shadow contribution into account.
The default choice is typically a shaded material, this is reflected in the
default value of the \l shadingMode property. This fits materials that needs
to transform vertices or other incoming data from the geometry, or determine
values like \c BASE_COLOR or \c EMISSIVE_COLOR in a custom manner, perhaps
by sampling \c SCREEN_TEXTURE or \c DEPTH_TEXTURE, while still reciving
light and shadow contributions from the scene. Additionally, such materials
can also override and reimplement the equations used to calculate the
contributions from directional, point, and other lights. The
application-provided shader snippets are heavily amended by the Qt Quick 3D
engine under the hood, in order to provide the features, such as lighting,
the standard materials have.
Unshaded materials are useful when the object's appearance is determined
completely by the custom shader code. The shaders for such materials
receive minimal additions by the engine, and therefore it is completely up
to the shader to determine the final fragment color. This gives more
freedom, but also limits possiblities to integrate with other elements of
the scene, such as lights.
\note Shader code is always provided using Vulkan-style GLSL, regardless of
the graphics API used by Qt at run time.
\note The vertex and fragment shader code provided by the material are not
full, complete GLSL shaders on their own. Rather, they provide a set of
functions, which are then amended with further shader code by the engine.
\section1 Exposing data to the shaders
The dynamic properties of the CustomMaterial can be changed and animated
using QML and Qt Quick facilities, and the values are exposed to the
shaders automatically. This in practice is very similar ShaderEffect. The
following list shows how properties are mapped:
\list
\li bool, int, real -> bool, int, float
\li QColor, \l{QtQml::Qt::rgba()}{color} -> vec4, and the color gets
converted to linear, assuming sRGB space for the color value specified in
QML. The built-in Qt colors, such as \c{"green"} are in sRGB color space as
well, and the same conversion is performed for all color properties of
DefaultMaterial and PrincipledMaterial, so this behavior of CustomMaterial
matches those. Unlike Qt Quick, for Qt Quick 3D linearizing is essential as
there will typically be tonemapping performed on the 3D scene.
\li QRect, QRectF, \l{QtQml::Qt::rect()}{rect} -> vec4
\li QPoint, QPointF, \l{QtQml::Qt::point()}{point}, QSize, QSizeF, \l{QtQml::Qt::size()}{size} -> vec2
\li QVector2D, \l{QtQml::Qt::vector2d()}{vector2d} -> vec2
\li QVector3D, \l{QtQml::Qt::vector3d()}{vector3d} -> vec3
\li QVector4D, \l{QtQml::Qt::vector4d()}{vector4d} -> vec4
\li QMatrix4x4, \l{QtQml::Qt::matrix4x4()}{matrix4x4} -> mat4
\li QQuaternion, \l{QtQml::Qt::quaternion()}{quaternion} -> vec4, scalar value is \c w
\li TextureInput -> sampler2D or samplerCube, depending on whether \l
Texture or \l CubeMapTexture is used in the texture property of the
TextureInput. Setting the \l{TextureInput::enabled}{enabled} property to
false leads to exposing a dummy texture to the shader, meaning the shaders
are still functional but will sample a texture with opaque black image
content. Pay attention to the fact that properties for samplers must always
reference a \l TextureInput object, not a \l Texture directly. When it
comes to the \l Texture properties, the source, tiling, and filtering
related ones are the only ones that are taken into account implicitly with
custom materials, as the rest (such as, UV transformations) is up to the
custom shaders to implement as they see fit.
\endlist
\note When a uniform referenced in the shader code does not have a
corresponding property, it will cause a shader compilation error when
processing the material at run time. There are some exceptions to this,
such as, sampler uniforms, that get a dummy texture bound when no
corresponding QML property is present, but as a general rule, all uniforms
and samplers must have a corresponding property declared in the
CustomMaterial object.
\section1 Unshaded custom materials
The following is an example of an \l{CustomMaterial::shadingMode}{unshaded}
custom material.
\qml
CustomMaterial {
These properties are automatically exposed to the shaders property real time: 0.0 property real amplitude: 5.0 property real alpha: 1.0 property TextureInput tex: TextureInput { enabled: true texture: Texture { source: "image.png" } }
shadingMode: CustomMaterial.Unshaded sourceBlend: alpha < 1.0 ? CustomMaterial.SrcAlpha : CustomMaterial.NoBlend destinationBlend: alpha < 1.0 ? CustomMaterial.OneMinusSrcAlpha : CustomMaterial.NoBlend cullMode: CustomMaterial.BackFaceCulling
vertexShader: "customshader.vert" fragmentShader: "customshader.frag" } \endqml
With the above example, the \l{CustomMaterial::shadingMode}{unshaded} vertex and fragment shaders snippets could look like the following. Note how the shaders do not, and must not, declare uniforms or vertex inputs as that is taken care of by Qt when assembling the final shader code.
\badcode VARYING vec3 pos; VARYING vec2 texcoord;
void MAIN() { pos = VERTEX; pos.x += sin(time * 4.0 + pos.y) * amplitude; texcoord = UV0; POSITION = MODELVIEWPROJECTION_MATRIX * vec4(pos, 1.0); }
\badcode VARYING vec3 pos; VARYING vec2 texcoord;
void MAIN() { vec4 c = texture(tex, texcoord); FRAGCOLOR = vec4(pos.x * 0.02, pos.y * 0.02, pos.z * 0.02, alpha) * c; }
The following special, uppercase keywords are available:
\list
MAIN. Providing this function is mandatory in shader snippets for unshaded custom materials.\endlist
Definition at line 1264 of file qquick3dcustommaterial.cpp.
References QRhiGraphicsPipeline::ConstantAlpha, QQuick3DCustomMaterial::ConstantAlpha, QRhiGraphicsPipeline::ConstantColor, QQuick3DCustomMaterial::ConstantColor, QRhiGraphicsPipeline::DstAlpha, QQuick3DCustomMaterial::DstAlpha, QRhiGraphicsPipeline::DstColor, QQuick3DCustomMaterial::DstColor, QRhiGraphicsPipeline::One, QQuick3DCustomMaterial::One, QRhiGraphicsPipeline::OneMinusConstantAlpha, QQuick3DCustomMaterial::OneMinusConstantAlpha, QRhiGraphicsPipeline::OneMinusConstantColor, QQuick3DCustomMaterial::OneMinusConstantColor, QRhiGraphicsPipeline::OneMinusDstAlpha, QQuick3DCustomMaterial::OneMinusDstAlpha, QRhiGraphicsPipeline::OneMinusDstColor, QQuick3DCustomMaterial::OneMinusDstColor, QRhiGraphicsPipeline::OneMinusSrcAlpha, QQuick3DCustomMaterial::OneMinusSrcAlpha, QRhiGraphicsPipeline::OneMinusSrcColor, QQuick3DCustomMaterial::OneMinusSrcColor, QRhiGraphicsPipeline::SrcAlpha, QQuick3DCustomMaterial::SrcAlpha, QRhiGraphicsPipeline::SrcAlphaSaturate, QQuick3DCustomMaterial::SrcAlphaSaturate, QRhiGraphicsPipeline::SrcColor, QQuick3DCustomMaterial::SrcColor, QRhiGraphicsPipeline::Zero, and QQuick3DCustomMaterial::Zero.