Qt 桌面着色器编译问题

Posted

技术标签:

【中文标题】Qt 桌面着色器编译问题【英文标题】:Qt desktop shader compilation issue 【发布时间】:2014-05-25 08:17:54 【问题描述】:

我正在使用 Qt 编写游戏,并且我已经实现了一些后处​​理着色器以使其看起来更有趣。在我升级到 linux mint 16 之前它工作正常,现在我总是收到一个需要精度说明符的错误,这只发生在编译片段着色器时。 因为代码在 android 版本上编译和工作正常,我认为这是因为 QGLShaderProgram 在桌面版本中编译着色器时将 mediump、highp 和 lowp 作为定义添加到着色器的开头。

所以我的问题是:有什么方法可以让 glsl 编译器停止要求精度说明符,或者我应该研究如何禁止添加这些定义?

代码:

    isOk = m_displaceShader.addShaderFromSourceCode(QGLShader::Vertex,
        "#version 100                                   \n"
        "attribute mediump vec4 in_verts;               \n"
        "varying mediump vec2 out_tex;                  \n"
        "void main(void)                                \n"
        "                                              \n"
        "   gl_Position = in_verts;                     \n"
        "   out_tex = (in_verts.xy + vec2(1.0)) * 0.5;  \n"
        "                                              \n");
    qDebug() << m_displaceShader.log();
    isOk &= m_displaceShader.addShaderFromSourceCode(   QGLShader::Fragment,
        "#version 100                                                               \n"
        "uniform sampler2D inCol;                                                   \n"
        "uniform sampler2D inDisplace;                                              \n"
        "varying mediump vec2 out_tex;                                              \n"
        "void main(void)                                                            \n"
        "                                                                          \n"
        "   mediump vec4 displaceCol = texture2D(inDisplace, out_tex);              \n"
        "   mediump float dispX = (displaceCol.r - 0.5) * 0.2;                      \n"
        "   mediump float dispY = (displaceCol.g - 0.5) * 0.2;                      \n"
        "   mediump vec2 texPlace = out_tex + vec2(dispX, dispY);                   \n"
        "   gl_FragColor = texture2D(inCol, texPlace);                              \n"
#ifdef DEBUG_SHADERS
        "   gl_FragColor = 0.5 * pow(texture2D(inCol, texPlace), vec4(1.0/2.2)) + 0.5 * displaceCol;            \n"
#endif
        "                                                                          \n"
    );

错误:

QGLShader::compile(Fragment): 0:7(16): error: no precision specified this scope for type `vec2'
0:10(9): error: no precision specified this scope for type `vec4'
0:11(10): error: no precision specified this scope for type `float'
0:12(10): error: no precision specified this scope for type `float'
0:13(9): error: no precision specified this scope for type `vec2'

【问题讨论】:

我很遗憾没有正确的答案。我刚刚遇到了同样的问题,我需要以 GLES SL 1.0 为目标,以使应用程序在 RDP 上运行。似乎唯一的解决方案是#undef mediump;呃。 【参考方案1】:

您正在使用#version 100,它不是有效的桌面 GLSL 版本指令。请参阅GLSL 4.40 spec(强调我的)的以下引用:

表示编译器不支持的语言版本的任何数字 支持将导致生成编译时错误。 1.10 版 语言不要求着色器包含此指令, 并且不包含#version 指令的着色器将被处理 作为目标版本 1.10。 指定#version 100 的着色器将是 视为面向 OpenGL ES 着色语言的 1.00 版。

这是为了与 GLES 兼容,而 GLES SL 需要这些精度说明符,因此您的编译器是正确的。

【讨论】:

谢谢,这确实是我猜我的驱动程序也随着系统更新的原因,现在弹出这个问题【参考方案2】:

如果您在 GLSL ES fragment 着色器中建立默认精度,问题将自行解决。

与顶点着色器不同,片段着色器没有默认值。如果您将precision mediump float; 添加到片段着色器的顶部(在#version 指令之后),这将解决您的问题。

您实际上也可以编译桌面 GL 着色器(例如 #version 110),但是您的精度限定符会产生解析错误,因此您需要将其删除。

【讨论】:

Qt 添加定义了将精度限定符映射到桌面构建上的空字符串,因此添加默认精度无济于事,原因与原始着色器无法编译相同,添加 #version 110 是解决方案从那时起就不再需要精度限定符 @RaduChivu 我对此表示怀疑,因为这会产生很多移植问题、错误的行号等。如果您真的认为会发生这种情况,可以从 GL glGetShaderSource (...) 查询着色器字符串。 在qglshaderprogram源码中可以看到qt.gitorious.org/qt/qt/source/…只要找#define mediump @RaduChivu 嗯,你是对的,它添加了这些东西而没有添加适当的 #line 指令来正确地重新编号 GLSL 编译器的错误日志中的行。您的代码生成有意义的行号真是个奇迹,它们每个都应该相差 3。实际上,没关系,我仔细查看了着色器日志,错误 are 相差 3;邪恶的 Qt :-/ @RaduChivu 为了避免 Qt 在您的 #version 指令之后静默添加这 3 行来避免将来为您创建的问题,我建议在 #version 之后立即添加 #line 1线。这样您就不必记住从 GLSL 编译器生成的任何行号中减去 3。如果 Qt 会像这样弄乱你的着色器源代码,这实际上是 Qt 自己应该做的事情。

以上是关于Qt 桌面着色器编译问题的主要内容,如果未能解决你的问题,请参考以下文章

Emscripten 无法编译着色器

运行时的 glsl 着色器编译问题

OpenGL着色器编译错误

在 PyQt 中编译着色器

着色器在 QML 中的插件安装

为啥在使用 OpenGL 编译顶点着色器时会出现着色器编译器错误 #143、#160 和 #216?