1. 程式人生 > >Qt QML 2D shader

Qt QML 2D shader

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