Qt QML 2D shader
阿新 • • 發佈:2017-06-08
coord con 表示 code 復雜 clas 輸入參數 from 程序
--------------------------------------------------- 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; }" }
Qt QML 2D shader