diff options
author | Laszlo Agocs <laszlo.agocs@qt.io> | 2016-06-28 16:33:42 +0200 |
---|---|---|
committer | Laszlo Agocs <laszlo.agocs@qt.io> | 2016-06-29 12:00:07 +0000 |
commit | f552d99f3d937ee9a8938673cd22246edbe70317 (patch) | |
tree | 36155668dac4b704c1c167b3cc8b8e5114d735fa /src/quick | |
parent | b87fd4752afd6b559d69ec2e08b2e3df69373b9e (diff) |
Update ShaderEffect docs
Change-Id: If20fa968fa596c82aa8eacbaedde9fa8ead5a8fd
Reviewed-by: Andy Nichols <andy.nichols@qt.io>
Diffstat (limited to 'src/quick')
-rw-r--r-- | src/quick/items/qquickshadereffect.cpp | 132 |
1 files changed, 117 insertions, 15 deletions
diff --git a/src/quick/items/qquickshadereffect.cpp b/src/quick/items/qquickshadereffect.cpp index f7c103a58f..57462219f9 100644 --- a/src/quick/items/qquickshadereffect.cpp +++ b/src/quick/items/qquickshadereffect.cpp @@ -169,7 +169,12 @@ QT_BEGIN_NAMESPACE \note Scene Graph textures have origin in the top-left corner rather than bottom-left which is common in OpenGL. - For information about the GLSL version being used, see \l QtQuick::OpenGLInfo. + For information about the GLSL version being used, see \l QtQuick::GraphicsInfo. + + Starting from Qt 5.8 ShaderEffect also supports reading the GLSL source + code from files. Whenever the fragmentShader or vertexShader property value + is a URL with the \c file or \c qrc schema, it is treated as a file + reference and the source code is read from the specified file. \section1 Direct3D and HLSL @@ -221,16 +226,17 @@ QT_BEGIN_NAMESPACE properties. Note that these are bitmasks, because some backends may support multiple approaches. - In case of Direct3D 12, both bytecode in files and HLSL source strings are - supported. If the vertexShader and fragmentShader properties form a valid - URL with the \c file or \c qrc schema, the bytecode is read from the - specified file. Otherwise, the string is treated as HLSL source code and is - compiled at runtime, assuming Shader Model 5.0 and an entry point of - \c{"main"}. This allows dynamically constructing shader strings. However, - whenever the shader source code is static, it is strongly recommended to - pre-compile to bytecode using the \c fxc tool and refer to these files from - QML. This will be a lot more efficient at runtime and allows catching - syntax errors in the shaders at compile time. + In case of Direct3D 12, all combinations are supported. If the vertexShader + and fragmentShader properties form a valid URL with the \c file or \c qrc + schema, the bytecode or HLSL source code is read from the specified file. + The type of the file contents is detected automatically. Otherwise, the + string is treated as HLSL source code and is compiled at runtime, assuming + Shader Model 5.0 and an entry point of \c{"main"}. This allows dynamically + constructing shader strings. However, whenever the shader source code is + static, it is strongly recommended to pre-compile to bytecode using the + \c fxc tool and refer to these files from QML. This will be a lot more + efficient at runtime and allows catching syntax errors in the shaders at + compile time. Unlike OpenGL, the Direct3D backend is able to perform runtime shader compilation on dedicated threads. This is managed transparently to the @@ -238,11 +244,14 @@ QT_BEGIN_NAMESPACE strings do not block the rendering or other parts of the application until the bytecode is ready. + Using files with bytecode is more flexible also when it comes to the entry + point name (it can be anything, not limited to \c main) and the shader + model (it can be something newer than 5.0, for instance 5.1). + \table 70% \row - \li \image declarative-shadereffectitem.png \li \qml - import QtQuick 2.8 + import QtQuick 2.0 Rectangle { width: 200; height: 100 @@ -282,6 +291,14 @@ QT_BEGIN_NAMESPACE in the constant buffer at offset 0, even though the pixel shader does not use the value. + If desired, the HLSL source code can be placed directly into the QML + source, similarly to how its done with GLSL. The only difference in this + case is the entry point name, which must be \c main when using inline + source strings. + + Alternatively, we could also have referred to a file containing the source + of the effect instead of the compiled bytecode version. + Some effects will want to provide a vertex shader as well. Below is a similar effect with both the vertex and fragment shader provided by the application. This time the colorization factor is provided by the QML item @@ -290,9 +307,8 @@ QT_BEGIN_NAMESPACE \table 70% \row - \li \image declarative-shadereffectitem.png \li \qml - import QtQuick 2.8 + import QtQuick 2.0 Rectangle { width: 200; height: 100 @@ -350,6 +366,92 @@ QT_BEGIN_NAMESPACE appropriate, meaning texture coordinates in HLSL version of the shaders will not need any adjustments compared to the equivalent GLSL code. + \section1 Cross-platform, Cross-API ShaderEffect Items + + Some applications will want to be functional with multiple accelerated + graphics backends. This has consequences for ShaderEffect items because the + supported shading languages may vary from backend to backend. + + There are two approaches to handle this: either write conditional property + values based on GraphicsInfo.shaderType, or use file selectors. In practice + the latter is strongly recommended as it leads to more concise and cleaner + application code. The only case it is not suitable is when the source + strings are constructed dynamically. + + \table 70% + \row + \li \qml + import QtQuick 2.8 // for GraphicsInfo + + Rectangle { + width: 200; height: 100 + Row { + Image { id: img; + sourceSize { width: 100; height: 100 } source: "qt-logo.png" } + ShaderEffect { + width: 100; height: 100 + property variant src: img + property variant color: Qt.vector3d(0.344, 0.5, 0.156) + fragmentShader: GraphicsInfo.shaderType === GraphicsInfo.GLSL ? + "varying highp vec2 coord; + uniform sampler2D src; + uniform lowp float qt_Opacity; + void main() { + lowp vec4 tex = texture2D(src, coord); + gl_FragColor = vec4(vec3(dot(tex.rgb, + vec3(0.344, 0.5, 0.156))), + tex.a) * qt_Opacity;" + : GraphicsInfo.shaderType === GraphicsInfo.HLSL ? + "cbuffer ConstantBuffer : register(b0) + { + float4x4 qt_Matrix; + float qt_Opacity; + }; + Texture2D src : register(t0); + SamplerState srcSampler : register(s0); + float4 ExamplePixelShader(float4 position : SV_POSITION, float2 coord : TEXCOORD0) : SV_TARGET + { + float4 tex = src.Sample(srcSampler, coord); + float3 col = dot(tex.rgb, float3(0.344, 0.5, 0.156)); + return float4(col, tex.a) * qt_Opacity; + }" + : "" + } + } + } + \endqml + \row + + \li This is the first approach based on GraphicsInfo. Note that the value + reported by GraphicsInfo is not up-to-date until the ShaderEffect item gets + associated with a QQuickWindow. Before that, the reported value is + GraphicsInfo.UnknownShadingLanguage. The alternative is to place the GLSL + source code and the compiled D3D bytecode into the files + \c{shaders/effect.frag} and \c{shaders/+hlsl/effect.frag}, include them in + the Qt resource system, and let the ShaderEffect's internal QFileSelector + do its job. The selector-less version is the GLSL source, while the \c hlsl + selector is used when running on the D3D12 backend. The file under + \c{+hlsl} can then contain either HLSL source code or compiled bytecode + from the \c fxc tool. + \qml + import QtQuick 2.8 // for GraphicsInfo + + Rectangle { + width: 200; height: 100 + Row { + Image { id: img; + sourceSize { width: 100; height: 100 } source: "qt-logo.png" } + ShaderEffect { + width: 100; height: 100 + property variant src: img + property variant color: Qt.vector3d(0.344, 0.5, 0.156) + fragmentShader: "qrc:shaders/effect.frag" // selects the correct variant automatically + } + } + } + \endqml + \endtable + \section1 ShaderEffect and Item Layers The ShaderEffect type can be combined with \l {Item Layers} {layered items}. |