--------------------------------------------------- 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; }" }