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

Qt5.15着色器适配Qt6.6后无输出问题求助

Qt 6.6着色器转换后无可见输出问题修复

问题背景

适配Qt 5.15的着色器代码转换为Qt 6.6版本后,无可见输出。已通过QShaderTool将着色器转为.qsb文件并集成到QML资源中。

原Qt 5.15着色器代码(MainShader.frag)

uniform lowp float qt_Opacity;
uniform lowp vec4 editColor;
float interval = 12.0;
float a = step(mod(gl_FragCoord.x + gl_FragCoord.y, interval) / (interval - 1.0), 0.5);
void main() {
    gl_FragColor = editColor * a;
}

转换后Qt 6.6错误着色器代码(MainShader.frag)

#version 440
layout(location = 0) in vec2 qt_TexCoord0;
layout(location = 0) out vec4 fragColor;

layout(std140, binding = 0) uniform buf {
   mat4 qt_Matrix;
   float qt_Opacity;
};


void main(void)
{
   float interval = 12.0;
   float a = step(mod(qt_TexCoord0.x + qt_TexCoord0.y, interval) / (interval - 1.0), 0.5);
   fragColor = fragColor * a;
}

测试用QML代码(Test.qml)

import QtQuick.Controls
import Qt5Compat.GraphicalEffects
import QtWebEngine
import QtQml

Rectangle {
    id: root

    property bool editMode: false
    property string editModeName: ""
    property string url: ""
    property int borderWidth: 20
    property color editColor: "yellow"
    property color editTextColor: "black"
    property bool isVisible: true

    visible: isVisible
    anchors.fill: parent
    color: "transparent"

    // WebEngineView加载URL
    WebEngineView {
        id: web
        anchors.fill: parent
        anchors.margins: root.borderWidth
        backgroundColor: "transparent"
        url: "url"
    }

    // 编辑模式管理
    Rectangle {
        id: editModeContent
        z: web.z + 1
        visible: root.editMode
        anchors.fill: parent
        color: "transparent"

        Loader {
            id: loader
            active: true
            anchors.fill: parent
            sourceComponent: border
        }

        Component {
            id: border
            Item {
                ShaderEffect {
                    property color editColor: root.editColor

                    id: borderFill
                    anchors.fill: parent
                    visible: true
                    fragmentShader: "qrc:/qml/MainShader.frag.qsb"
                }

                Rectangle {
                    id: mask
                    border.width: root.borderWidth
                    anchors.fill: parent
                    color: 'transparent'
                    visible: false
                }

                OpacityMask {
                    id: opM
                    anchors.fill: parent
                    source: borderFill
                    maskSource: mask
                }
            }
        }

        Rectangle {
            color: root.editColor
            anchors.top: parent.top
            anchors.horizontalCenter: parent.horizontalCenter
            width: editModeName.width + 40
            radius: 5
            height: root.borderWidth
        }

        Text {
            id: editModeName
            height: root.borderWidth
            color: root.editTextColor
            anchors.top: parent.top
            anchors.horizontalCenter: parent.horizontalCenter
            font.family: "Helvetica"
            font.pointSize: 12
            text: root.editModeName
        }
    }
}

预期效果

显示带有黄色斜向网格图案的边框,仅在控件边缘区域显示该网格(通过OpacityMask裁剪)。


问题分析

  1. 缺失自定义Uniform变量:原Qt5代码中的editColor变量未在Qt6着色器中声明,导致着色器无法获取传入的颜色参数。
  2. 未初始化输出变量:fragColor = fragColor * a中fragColor初始值未定义,计算结果为无效颜色值。
  3. 坐标系统不匹配:Qt6中qt_TexCoord0是[0,1]范围的纹理坐标,而原代码使用的gl_FragCoord是像素坐标,直接替换后网格尺寸会异常放大,无法显示预期图案。

修复方案

修复后的Qt 6.6着色器代码

#version 440
layout(location = 0) in vec2 qt_TexCoord0;
layout(location = 0) out vec4 fragColor;

// Qt内置Uniform块
layout(std140, binding = 0) uniform buf {
   mat4 qt_Matrix;
   float qt_Opacity;
};

// 自定义Uniform块,对应QML中ShaderEffect的属性
layout(std140, binding = 1) uniform customBuf {
    vec4 editColor;
    vec2 size; // 控件的像素尺寸
};

void main(void)
{
    float interval = 12.0;
    // 将纹理坐标转换为像素坐标
    vec2 fragCoord = qt_TexCoord0 * size;
    // 保留原逻辑计算网格透明度
    float a = step(mod(fragCoord.x + fragCoord.y, interval) / (interval - 1.0), 0.5);
    // 正确计算输出颜色,叠加透明度
    fragColor = editColor * a * qt_Opacity;
}

QML代码修改

在ShaderEffect中添加size属性,传递控件的像素尺寸给着色器:

ShaderEffect {
    property color editColor: root.editColor
    // 传递控件尺寸到着色器
    property variant size: Qt.size(width, height)

    id: borderFill
    anchors.fill: parent
    visible: true
    fragmentShader: "qrc:/qml/MainShader.frag.qsb"
}

编译.qsb文件

使用QShaderTool重新编译修复后的着色器代码:

qshadertool --glsl "440,440" --output MainShader.frag.qsb MainShader.frag

将生成的.qsb文件替换资源中的原文件。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.03 15:07:35