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裁剪)。
问题分析
- 缺失自定义Uniform变量:原Qt5代码中的
editColor变量未在Qt6着色器中声明,导致着色器无法获取传入的颜色参数。 - 未初始化输出变量:
fragColor = fragColor * a中fragColor初始值未定义,计算结果为无效颜色值。 - 坐标系统不匹配: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
相关产品推荐
相关产品推荐

