ShaderEffect 是 QML 中用于实现自定义着色器效果的组件,允许开发者使用 GLSL 着色器语言创建图形效果。
核心属性
基本属性
属性 | 类型 | 默认值 | 说明 |
---|---|---|---|
fragmentShader | string | "" | 片段着色器代码 |
vertexShader | string | "" | 顶点着色器代码 |
blending | bool | true | 是否启用混合 |
mesh | variant | Qt.size(1, 1) | 网格分辨率或自定义网格 |
cullMode | enumeration | ShaderEffect.NoCulling | 面剔除模式 |
log | string | "" | 只读,着色器编译日志 |
着色器参数属性
属性 | 类型 | 说明 |
---|---|---|
property var <name> | variant | 声明着色器参数 |
property real <name> | real | 声明实数参数 |
property vector2d <name> | vector2d | 声明2D向量参数 |
property vector3d <name> | vector3d | 声明3D向量参数 |
property vector4d <name> | vector4d | 声明4D向量参数 |
property color <name> | color | 声明颜色参数 |
property rect <name> | rect | 声明矩形参数 |
property point <name> | point | 声明点参数 |
property size <name> | size | 声明尺寸参数 |
property matrix4x4 <name> | matrix4x4 | 声明4x4矩阵参数 |
CullMode 枚举值
值 | 说明 |
---|---|
ShaderEffect.NoCulling | 不剔除 |
ShaderEffect.BackFaceCulling | 剔除背面 |
ShaderEffect.FrontFaceCulling | 剔除正面 |
常用方法
方法 | 参数 | 返回值 | 说明 |
---|---|---|---|
setUniformValue(name, value) | name: string value: variant | - | 设置着色器参数值 |
update() | - | - | 强制更新效果 |
常用信号
信号 | 参数 | 说明 |
---|---|---|
logChanged() | - | 着色器日志改变时触发 |
着色器特殊变量
顶点着色器可用变量
变量 | 类型 | 说明 |
---|---|---|
qt_Vertex | vec4 | 顶点位置 |
qt_MultiTexCoord0 | vec4 | 纹理坐标 |
qt_ModelViewProjectionMatrix | mat4 | 模型视图投影矩阵 |
varying vec2 qt_TexCoord0 | vec2 | 传递给片段着色器的纹理坐标 |
片段着色器可用变量
变量 | 类型 | 说明 |
---|---|---|
varying vec2 qt_TexCoord0 | vec2 | 来自顶点着色器的纹理坐标 |
uniform sampler2D source | sampler2D | 源纹理 |
uniform float qt_Opacity | float | 不透明度 |
基本使用示例
1. 简单着色器效果
qml
import QtQuick 2.15
ShaderEffect {
width: 200; height: 200
property color uColor: "red"
fragmentShader: "
uniform lowp vec4 uColor;
void main() {
gl_FragColor = uColor;
}
"
}
2. 纹理处理
qml
ShaderEffect {
width: 200; height: 200
property variant source
property real uAmount: 0.5
fragmentShader: "
uniform sampler2D source;
uniform float uAmount;
varying vec2 qt_TexCoord0;
void main() {
vec4 color = texture2D(source, qt_TexCoord0);
gl_FragColor = vec4(color.rgb * uAmount, color.a);
}
"
}
高级用法
1. 自定义网格
qml
ShaderEffect {
width: 200; height: 200
mesh: GridMesh {
resolution: Qt.size(10, 10)
}
// 着色器代码...
}
2. 多纹理输入
qml
ShaderEffect {
width: 200; height: 200
property variant source1
property variant source2
property real uMixFactor: 0.5
fragmentShader: "
uniform sampler2D source1;
uniform sampler2D source2;
uniform float uMixFactor;
varying vec2 qt_TexCoord0;
void main() {
vec4 color1 = texture2D(source1, qt_TexCoord0);
vec4 color2 = texture2D(source2, qt_TexCoord0);
gl_FragColor = mix(color1, color2, uMixFactor);
}
"
}
3. 动画效果
qml
ShaderEffect {
width: 200; height: 200
property variant source
property real uTime: 0
NumberAnimation on uTime {
from: 0; to: 1
duration: 1000
loops: Animation.Infinite
}
fragmentShader: "
uniform sampler2D source;
uniform float uTime;
varying vec2 qt_TexCoord0;
void main() {
vec2 uv = qt_TexCoord0;
uv.x += sin(uTime * 10.0 + uv.y * 5.0) * 0.1;
gl_FragColor = texture2D(source, uv);
}
"
}
性能优化技巧
-
减少uniform更新:避免频繁更新着色器参数
-
简化着色器:复杂着色器会影响性能
-
合理使用mesh:增加网格分辨率会降低性能
-
避免动态编译:预编译着色器
-
使用mipmap:对于缩小的纹理
常见着色器效果实现
1. 灰度效果
qml
fragmentShader: "
uniform sampler2D source;
varying vec2 qt_TexCoord0;
void main() {
vec4 color = texture2D(source, qt_TexCoord0);
float gray = dot(color.rgb, vec3(0.299, 0.587, 0.114));
gl_FragColor = vec4(vec3(gray), color.a);
}
"
2. 边缘检测
qml
fragmentShader: "
uniform sampler2D source;
uniform float qt_Opacity;
varying vec2 qt_TexCoord0;
void main() {
vec2 uv = qt_TexCoord0;
vec2 step = vec2(1.0/width, 1.0/height);
float gx = -1.0 * texture2D(source, uv + vec2(-step.x, -step.y)).r +
-2.0 * texture2D(source, uv + vec2(-step.x, 0.0)).r +
-1.0 * texture2D(source, uv + vec2(-step.x, step.y)).r +
1.0 * texture2D(source, uv + vec2(step.x, -step.y)).r +
2.0 * texture2D(source, uv + vec2(step.x, 0.0)).r +
1.0 * texture2D(source, uv + vec2(step.x, step.y)).r;
float gy = -1.0 * texture2D(source, uv + vec2(-step.x, -step.y)).r +
-2.0 * texture2D(source, uv + vec2(0.0, -step.y)).r +
-1.0 * texture2D(source, uv + vec2(step.x, -step.y)).r +
1.0 * texture2D(source, uv + vec2(-step.x, step.y)).r +
2.0 * texture2D(source, uv + vec2(0.0, step.y)).r +
1.0 * texture2D(source, uv + vec2(step.x, step.y)).r;
float edge = sqrt(gx*gx + gy*gy);
gl_FragColor = vec4(vec3(edge), qt_Opacity);
}
"
注意事项
-
着色器代码必须符合目标平台的GLSL版本
-
不同平台可能有不同的着色器限制
-
复杂的着色器可能在某些设备上不工作
-
调试着色器可以使用log属性查看编译错误
-
确保所有uniform变量都有对应的property声明