OpenGL着色器语言的向后兼容性

6
我发现当GLSL版本低于130时,我的GLSL着色器无法编译。
在具有向后兼容的着色器源代码中,最关键的要素是什么?我不想完全向后兼容,但我想了解在GLSL版本低于130的GPU上运行简单(向前兼容)着色器的主要指南。
当然,可以通过预处理器解决问题。
#if __VERSION__ < 130
#define VERTEX_IN attribute
#else
#define VERTER_IN in
#endif

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

4个回答

3
最近的活动推动了这个老问题,我意识到我已经解决了这个问题。虽然不容易,但这是一个成功的解决方案,得到了许多基于它的着色器和编译着色器源代码的驱动程序的证明。
本质上,我使用了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或更高版本的核心配置文件,就不再需要上面的着色器包含了。


1
  • 将 #version 110 或 #version 120 放在你的着色器文件的第一行
  • 使用 ATI 的 ShaderAnalyst 对它们进行测试
  • 在许多不同供应商的实际图形卡上测试你的代码

0

谢谢,但是我尝试的是通过仅使用预处理器使着色器源代码可编译于不同版本,从而避免兼容性标志。 - Luca

0
从你的着色器中删除#version行,并在许多具有不同GPU功能的计算机上测试你的代码。你会发现你的着色器兼容性将会提高。#version指令有时会导致着色器失败,即使该计算机的GPU可以在没有给出版本号时执行所有着色器代码。

是的,#version指令从一开始就根据系统能力在运行时插入。拥有可扩展的引擎非常重要;然而,大多数系统都支持高级GLSL功能。 - Luca
省略 #version 将默认使用 GLSL 1.1。 - Luca

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接