# 着色器元素

对于着色器编程,Qt Quick提供了两个元素:ShaderEffectSource(着色器效果源)和ShaderEffect(着色器效果)。 着色器效果,应用自定义的着色器;着色器效果源,将QML项目渲染到纹理中并渲染此纹理。 由于着色器效果可以将自定义着色器应用于其矩形形状,并且可以使用着色器操作的源(As shader effect can apply custom shaders to its rectangular shape and can use sources for the shader operation)。 源可以是图像,它被用于纹理或着色器效果源。

默认着色器使用源并不加修改地渲染它。 下面,首先看这带有两个ShaderEffect元素的QML文件。 一种没有指定任何着色器,另一种显式指定了默认的顶点着色器和片段着色器。 将很快了解着色器。

import QtQuick

Rectangle {
    width: 480; height: 240
    color: '#1e1e1e'

    Row {
        anchors.centerIn: parent
        spacing: 20
        Image {
            id: sourceImage
            width: 80; height: width
            source: '../assets/tulips.jpg'
        }
        ShaderEffect {
            id: effect
            width: 80; height: width
            property variant source: sourceImage
        }
        ShaderEffect {
            id: effect2
            width: 80; height: width
            property variant source: sourceImage
            vertexShader: "default.vert.qsb"
            fragmentShader: "default.frag.qsb"
        }
    }
}

image

在上面的示例中,有一行3张图像。 第一张是真实的图像,第二张使用了默认着色器进行渲染,第三张使用了片段和顶点着色器代码进行渲染,如下所示。 看一下这些着色器。

顶点着色器获取纹理坐标qt_MultiTexCoord0,并将其传递到qt_TexCoord0变量。 它还获取qt_Vertex位置,并将其与Qt的变换矩阵ubuf.qt_Matrix相乘,并通过gl_Position变量返回它。 这使屏幕上的纹理和顶点位置保持不变。

#version 440

layout(location=0) in vec4 qt_Vertex;
layout(location=1) in vec2 qt_MultiTexCoord0;

layout(location=0) out vec2 qt_TexCoord0;

layout(std140, binding=0) uniform buf {
    mat4 qt_Matrix;
    float qt_Opacity;
} ubuf;

out gl_PerVertex { 
    vec4 gl_Position;
};

void main() {
    qt_TexCoord0 = qt_MultiTexCoord0;
    gl_Position = ubuf.qt_Matrix * qt_Vertex;
}

片段着色器从source2D采样器中获取纹理,纹理位于坐标qt_TexCoord0处,并将其与Qt不透明度ubuf.qt_Opacity相乘以计算fragColor,它是像素要使用的颜色。

#version 440

layout(location=0) in vec2 qt_TexCoord0;

layout(location=0) out vec4 fragColor;

layout(std140, binding=0) uniform buf {
    mat4 qt_Matrix;
    float qt_Opacity;
} ubuf;

layout(binding=1) uniform sampler2D source;

void main() {
    fragColor = texture(source, qt_TexCoord0) * ubuf.qt_Opacity;
}

请注意,这两个着色器可以用作自己的着色器的样板代码。 这些变量、位置和绑定都是Qt中所期望的。可以在着色器效果文档(Shader Effect Documentation) (opens new window)阅读更多与此相关的确切细节.

在可以使用着色器之前,它们需要被烘焙。 如果着色器是较大Qt项目的一部分并将其作为资源包含在内,则可以自动执行此操作。 但是,当使用着色器和qml文件时,需要手动显式烘焙它们。 这是使用以下两个命令完成的:

qsb --glsl 100es,120,150 --hlsl 50 --msl 12    -o default.frag.qsb default.frag 
qsb --glsl 100es,120,150 --hlsl 50 --msl 12 -b -o default.vert.qsb default.vert

qsb工具位于Qt 6安装目录下的bin目录中。

提示

如果不想看到源图像而只想看到效果图像,可以将Image设置为不可见(visible: false)。 着色器效果仍将使用图像数据,只是Image元素不会被渲染。

在接下来的示例中将使用一些简单的着色器机制。 首先,专注于分析片段着色器,然后将回到分析顶点着色器上。

最后更新: 1/9/2022, 5:58:27 PM