You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用QML ShaderEffect实现挖空效果时图片拉伸问题求解

问题原因

你当前代码出现拉伸的核心原因是使用了ShaderEffect自身的纹理坐标qt_MultiTexCoord0采样底层图像,该坐标的范围永远是[0,1]对应Shader组件自身的宽高,当Shader尺寸变化时,相当于把整张底层图像强制缩放匹配Shader尺寸,自然会出现变形。

解决方案

你不需要修改顶点着色器,只需要新增几个uniform参数传递坐标和尺寸信息,修改片段着色器的采样坐标计算逻辑即可,QML层的坐标转换可以直接用mapToItem完成后传入着色器,不需要在GLSL中处理坐标映射。

修改后的完整代码如下:

ShaderEffect {
    id: shader_element
    x: resizeable.x
    y: resizeable.y
    width: resizeable.width
    height: resizeable.height
    property Image src: global_image_reference // 底层原图全局引用

    // 新增传入着色器的参数,QML层完成计算
    property real srcWidth: src.width
    property real srcHeight: src.height
    // 计算当前Shader左上角相对于底层原图的坐标
    property real cutoutX: mapToItem(src, 0, 0).x
    property real cutoutY: mapToItem(src, 0, 0).y

    vertexShader: "
        uniform highp mat4 qt_Matrix;
        attribute highp vec4 qt_Vertex;
        attribute highp vec2 qt_MultiTexCoord0;
        varying highp vec2 coord;
        void main() {
            coord = qt_MultiTexCoord0;
            gl_Position = qt_Matrix * qt_Vertex;
        }"

    fragmentShader: "
        varying highp vec2 coord;
        uniform sampler2D src;
        uniform lowp float qt_Opacity;
        // 接收QML传入的参数,Shader自身的width/height会自动传入无需手动赋值
        uniform highp float srcWidth;
        uniform highp float srcHeight;
        uniform highp float cutoutX;
        uniform highp float cutoutY;
        uniform highp float width;
        uniform highp float height;

        void main() {
            // 计算当前像素对应底层原图的采样坐标
            highp vec2 srcSampleCoord = vec2(
                (cutoutX + coord.x * width) / srcWidth,
                (cutoutY + coord.y * height) / srcHeight
            );
            // 采样原图对应位置像素,避免拉伸
            gl_FragColor = texture2D(src, srcSampleCoord) * qt_Opacity;
        }"
}

逻辑说明

  • 坐标映射直接在QML层通过mapToItem完成,避免GLSL的复杂坐标计算,计算得到的cutoutX、cutoutY就是Shader组件左上角在底层原图坐标系下的绝对坐标
  • 片段着色器中先把Shader的局部坐标转换为相对于底层原图的绝对坐标,再归一化到[0,1]的纹理坐标范围采样,不管Shader尺寸怎么调整,采样的永远是和Shader区域位置完全对应的原图像素,不会出现拉伸变形
  • 如果需要实现部分区域挖空的效果,只需要在片段着色器中增加区域判断逻辑,非挖空区域返回上层内容的采样结果即可

内容的提问来源于stack exchange,提问作者comp1201

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.27 01:24:04