Qt QML 2D shader

---------------------------------------------------
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;
            }"
    }    
相關文章
相關標籤/搜索