![]() |
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"
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().
|
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.