版权声明:如果对您有帮助,跪求点赞!本文为博主原创作品,转载请声明出处! https://blog.csdn.net/u011086209/article/details/90764408
---------------------------------------------------
Qt quick 2d shader effect
---------------------------------------------------
概念
着色器和普通的图像处理程序不同,它只针对一个点做运算,它包括:
vertext shader: 顶点着色器,主要用于处理位置,要求输出当前点的新位置。
fragment shader(pixel shader):片段着色器(像素着色器),主要用于处理色彩。要求输出当前点的新色彩。
系统会自动处理循环,并行运算多个点,自动处理图像边界
主要有两类Shader程序: GLSL(OpenGL提供), HLSL(DirectX提供)
注:好像时 5.6 版本后才支持directx,所以事情复杂了。现在Qt3D的shader就复杂无比.
GLSL(OpenGL Shader Language)
参数修饰词
uniform : 表示每次运算时参数值不变的
varying : 表示每次运算时参数值时变动的。如当前点的纹理坐标
lowp : 表示低精度
highp : 表示高精度
预定义参数
uniform mat4 qt_Matrix : 变形矩阵- combined transformation matrix, the product of the matrices from the root item to this ShaderEffect, and an orthogonal projection.
uniform float qt_Opacity : 透明度- combined opacity, the product of the opacities from the root item to this ShaderEffect.
attribute vec4 qt_Vertex : 当前计算点的坐标
attribute vec2 qt_MultiTexCoord0 : 纹理坐标(输入的图片/item等)
输入参数类型映射
在ShaderEffect中定义的参数会自动映射到Shader里面去
bool, int, qreal -> bool, int, float
QColor -> vec4 : 注意色彩输入shader时会先做半透明预处理,如Qt.rgba(0.2, 0.6, 1.0, 0.5) 会转化为 vec4(0.1, 0.3, 0.5, 0.5)
QRect, QRectF -> vec4(x, y, w, h)
QPoint, QPointF, QSize, QSizeF -> vec2(x, y)
QVector3D -> vec3(x, y, z)
QVector4D -> vec4(x, y, w, w)
QTransform -> mat3
QMatrix4x4 -> mat4
QQuaternion -> vec4, scalar value is w.
Image -> sampler2D
ShaderEffectSource -> sampler2D
输出
vertext shader: 顶点着色器,主要用于处理位置,要求输出gl_Position参数。
fragment shader(pixel shader):片段着色器(像素着色器),主要用于处理色彩。要求输出gl_FragColor参数。
常用方法
lowp vect4 text = texture2D(src, qt_TexCoord0); // 取纹理色彩
abs/min/max/....
示例
ShaderEffect {
width: 200
height: 200
mesh: GridMesh { resolution: Qt.size(20, 20) }
property var source: Image {
source: "qt-logo.png"
sourceSize { width: 200; height: 200 }
}
vertexShader: "
uniform highp mat4 qt_Matrix;
attribute highp vec4 qt_Vertex;
attribute highp vec2 qt_MultiTexCoord0;
varying highp vec2 qt_TexCoord0;
uniform highp float width;
void main() {
highp vec4 pos = qt_Vertex;
highp float d = .5 * smoothstep(0., 1., qt_MultiTexCoord0.y);
pos.x = width * mix(d, 1.0 - d, qt_MultiTexCoord0.x);
gl_Position = qt_Matrix * pos;
qt_TexCoord0 = qt_MultiTexCoord0;
}"
}
HLSL(Direct3D)
blablabla,有很多不同,
示例
Image { id: img; sourceSize { width: 100; height: 100 } source: "qt-logo.png" }
ShaderEffect {
width: 100; height: 100
property variant src: img
fragmentShader: "qrc:/effect_ps.cso"
}
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;
}
跨平台的Shader写法
方法1(根据 GraphicsInfo.shaderType 判断):
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;
}"
: ""
}
方法2(自动选择):
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" // 系统会自动选择 shaders/effect.frag 或 shaders/+hlsl/effect.frag
}
示例
// 去色
ShaderEffect {
fragmentShader: "
uniform lowp sampler2D source; // this item
uniform lowp float qt_Opacity; // inherited opacity of this item
varying highp vec2 qt_TexCoord0;
void main() {
lowp vec4 p = texture2D(source, qt_TexCoord0);
lowp float g = dot(p.xyz, vec3(0.344, 0.5, 0.156));
gl_FragColor = vec4(g, g, g, p.a) * qt_Opacity;
}"
}
// 图层混合
ShaderEffect {
property var colorSource: gradientRect;
fragmentShader: "
uniform lowp sampler2D colorSource;
uniform lowp sampler2D maskSource;
uniform lowp float qt_Opacity;
varying highp vec2 qt_TexCoord0;
void main() {
gl_FragColor =
texture2D(colorSource, qt_TexCoord0)
* texture2D(maskSource, qt_TexCoord0).a
* qt_Opacity;
}
"
}
// 上下两边虚化
Flickable{
....
}
ShaderEffectSource {
id: flickableAreaSource
sourceItem: flickableArea
hideSource: true
visible: false
}
ShaderEffect {
property variant src: flickableAreaSource
anchors.fill: flickableArea
fragmentShader: "
varying highp vec2 qt_TexCoord0;
uniform lowp float qt_Opacity;
uniform sampler2D src;
void main() {
lowp vec4 tex = texture2D(src, qt_TexCoord0);
lowp float dist = abs(qt_TexCoord0.y-0.5)*4.0;
tex*= min(1.0, (2.0 - dist));
gl_FragColor = tex * qt_Opacity;
}"
}