【问题标题】:OpenGL Shading Language backwards compatibilityOpenGL 着色语言向后兼容性
【发布时间】:2013-07-04 02:53:20
【问题描述】:

我注意到当 GLSL 版本低于 130 时,我的 GLSL 着色器无法编译。

拥有向后兼容的着色器源最关键的元素是什么?我不想完全向后兼容,但我想了解在 GLSL 低于 130 的 GPU 上运行简单(向前兼容)着色器的主要准则。

这个问题当然可以用预处理器解决

#if __VERSION__ < 130
#define VERTEX_IN attribute
#else
#define VERTER_IN in
#endif

但我可能忽略了很多问题。

【问题讨论】:

    标签: opengl backwards-compatibility glsl shader


    【解决方案1】:

    最近的活动提出了这个老问题,我意识到我解决了这个问题。这并不容易,但它是一个成功的解决方案,许多基于它的着色器和编译着色器源的驱动程序的数量都证明了这一点。

    基本上,我使用了GL_ARB_shading_language_include 扩展(我还为那些没有实现它的系统实现了源预处理器),最后我定义了以下着色器包含源:

    //  Copyright (C) 2011-2013 Luca Piccioni
    // 
    //  This program is free software: you can redistribute it and/or modify
    //  it under the terms of the GNU General Public License as published by
    //  the Free Software Foundation, either version 3 of the License, or
    //  (at your option) any later version.
    // 
    //  This program is distributed in the hope that it will be useful,
    //  but WITHOUT ANY WARRANTY; without even the implied warranty of
    //  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    //  GNU General Public License for more details.
    // 
    //  You should have received a copy of the GNU General Public License
    //  along with this program.  If not, see <http://www.gnu.org/licenses/>.
    
    // @BeginInterface
    
    // Shader renderer
    
    // Symbol defined if running on NVIDIA renderer.
    #define DS_VENDOR_NVIDIA            1
    // Symbol defined if running on ATI/AMD renderer.
    #define DS_VENDOR_AMD               2
    // Symbol defined if running on INTEL renderer
    #define DS_VENDOR_INTEL             3
    
    // Shader inputs and outputs keywords
    //
    // - ATTRIBUTE: used to mark a vertex shader inputs
    // - SHADER_IN: used to mark a non-vertex shader inputs
    // - SHADER_OUT: used to mark a non-fragment shader output
    // - OUT: used to mark a fragment shader output
    #if __VERSION__ >= 130
    
    #define ATTRIBUTE in
    #define SHADER_IN in
    #define SHADER_OUT out
    #define OUT out
    
    #else
    
    #define ATTRIBUTE attribute
    #define SHADER_IN varying
    #define SHADER_OUT varying
    #define OUT
    
    #endif
    
    // Support array attributes
    #if __VERSION__ >= 130
    
    #define ARRAY_ATTRIBUTE(name, size) name[size]
    
    #else
    
    #define ARRAY_ATTRIBUTE(name, size) name[size]
    
    #endif
    
    // Uniform blocks
    #if __VERSION__ >= 130
    
    #define BEGIN_UNIFORM_BLOCK(name)   uniform name {
    
    #define END_UNIFORM_BLOCK() };
    
    #else
    
    #define BEGIN_UNIFORM_BLOCK(name)
    
    #define END_UNIFORM_BLOCK()
    
    #endif
    
    // Input and output blocks
    #if __VERSION__ >= 150
    
    #define BEGIN_INPUT_BLOCK(name) in name {
    #define END_INPUT_BLOCK() };
    
    #define BEGIN_OUTPUT_BLOCK(name) out name {
    #define END_OUTPUT_BLOCK() };
    
    #else
    
    #define BEGIN_INPUT_BLOCK(name)
    #define END_INPUT_BLOCK()
    
    #define BEGIN_OUTPUT_BLOCK(name)
    #define END_OUTPUT_BLOCK()
    
    #endif
    
    // Texturing functions
    #if __VERSION__ >= 130
    
    #define TEXTURE_2D texture
    #define TEXTURE_3D texture
    #define TEXTURE_RECT texture
    #define TEXTURE_CUBE texture
    
    #if __VERSION__ >= 150
    #define TEXTURE_SIZE(sampler) textureSize(sampler)
    #else
    #define TEXTURE_SIZE(sampler) sampler ## _Size
    #endif
    
    #else
    
    #define TEXTURE_2D texture2D
    #define TEXTURE_3D texture3D
    #define TEXTURE_RECT texture2DRect
    #define TEXTURE_CUBE textureCube
    
    #endif
    
    // Invariance
    #if __VERSION__ >= 120
    #define INVARIANT invariant
    #else
    #define INVARIANT
    #endif
    
    // Attribute location
    #if defined(GL_ARB_explicit_attrib_location)
    #define LOCATION(loc)       layout(location = loc)
    #else
    #define LOCATION(loc)
    #endif
    
    // Geometry shader layout
    #if __VERSION__ >= 150
    #define GEOMETRY_LAYOUT_IN(from) layout (from) in
    #define GEOMETRY_LAYOUT(to, max) layout (to, max_vertices = max) out
    #else
    #define GEOMETRY_LAYOUT_IN(from)
    #define GEOMETRY_LAYOUT(to, max)
    #endif
    
    // @EndInterface
    

    确实,在着色器源代码之前包含着色器,框架可以在各种编译器上编译。当然,框架必须检测实际系统功能并定义编译器参数才能正确完成工作(考虑使用线着色器,因为不推荐使用线宽 > 1.0)。

    当然,着色器基础设施可以定义最低要求。一旦着色器需要 GLSL 1.50 或更高版本的核心配置文件,就不再需要上面包含的着色器。

    【讨论】:

      【解决方案2】:
      • 将#version 110 或#version 120 作为着色器的第一行
      • 在 ATI 的 ShaderAnalyst 中测试它们
      • 在大量来自不同供应商的实际显卡上测试您的代码

      【讨论】:

        【解决方案3】:

        阅读"OpenGL Shading Language, Bill Licea-Kane, AMD, SIGGRAPH 2009"。您可能需要将以下代码添加到您的应用程序以支持 GLSL-140、130 和 120 版本:

        #version 150 compatibility
        

        【讨论】:

        • 谢谢,但我试图通过仅使用预处理器使着色器源代码可编译为不同版本来避免兼容性标志。
        【解决方案4】:

        从您的着色器中取出 #version 行,并在具有不同 GPU 功能的许多不同计算机上测试您的代码。你会看到你的着色器兼容性会增加。 #version 指令有时会导致着色器失败,即使该机器中的 GPU 在未指定版本号时可以执行所有着色器代码。

        【讨论】:

        • 是的,#version 指令从一开始就根据系统功能在运行时插入。拥有一个可扩展的引擎是必不可少的;但是,大多数系统都支持高级 GLSL 功能。
        • 省略 #version 默认为 GLSL 1.1
        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2012-08-04
        • 2021-10-18
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多