OpenGL着色语言向后兼容性
我注意到,当GLSL版本低于130时,我的GLSL着色器不可编译 拥有向后兼容的着色器源最关键的元素是什么?我不想完全向后兼容,但我想了解在GLSL低于130的GPU上运行简单(向前兼容)着色器的主要指导原则 当然,这个问题可以通过预处理器解决OpenGL着色语言向后兼容性,opengl,backwards-compatibility,glsl,shader,Opengl,Backwards Compatibility,Glsl,Shader,我注意到,当GLSL版本低于130时,我的GLSL着色器不可编译 拥有向后兼容的着色器源最关键的元素是什么?我不想完全向后兼容,但我想了解在GLSL低于130的GPU上运行简单(向前兼容)着色器的主要指导原则 当然,这个问题可以通过预处理器解决 #if __VERSION__ < 130 #define VERTEX_IN attribute #else #define VERTER_IN in #endif 如果版本1.0不推荐) 当然,着色器基础结构可以定义最低要求。一旦着色器需要G
#if __VERSION__ < 130
#define VERTEX_IN attribute
#else
#define VERTER_IN in
#endif
如果版本<130
#在属性中定义顶点
#否则
#在中定义VERTER_
#恩迪夫
但我可能忽略了很多问题。- 将#version 110或#version 120作为着色器的第一行
- 在ATI的ShaderAnalyst中测试它们
- 在来自不同供应商的大量实际图形卡上测试您的代码 阅读。为了支持GLSL-140、130和120版本,您可能需要向应用程序中添加以下代码:
#version 150 compatibility
从着色器中取出#version行,在许多具有不同GPU功能的不同计算机上测试代码。您将看到着色器兼容性将提高。#version指令有时会导致着色器失败,即使该计算机中的GPU在没有给定版本号的情况下可以执行所有着色器代码。最近的活动提出了这个老问题,我意识到我解决了这个问题。这并不容易,但它是一个成功的解决方案,许多基于它的着色器和编译着色器源的驱动程序的数量都证明了这一点 本质上,我使用了扩展(我还为那些没有实现它的系统实现了一个源预处理器),最后定义了以下着色器include source:
// 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
//版权所有(C)2011-2013卢卡·皮奇奥尼
//
//此程序是免费软件:您可以重新发布和/或修改它
//它是根据GNU通用公共许可证的条款发布的
//自由软件基金会,或者许可证的第3版,或者
//(由您选择)任何更高版本。
//
//这个节目的发布是希望它会有用,
//但无任何保证;甚至没有任何关于
//适销性或适合某一特定目的。见
//有关更多详细信息,请参阅GNU通用公共许可证。
//
//您应该已经收到GNU通用公共许可证的副本
//和这个节目一起。如果没有,请参阅。
//@BeginInterface
//着色器渲染器
//在NVIDIA渲染器上运行时定义的符号。
#定义DS_供应商_NVIDIA 1
//在ATI/AMD渲染器上运行时定义的符号。
#定义DS\U供应商\U AMD 2
//在英特尔渲染器上运行时定义的符号
#定义DS\u供应商\u英特尔3
//着色器输入和输出关键字
//
//-属性:用于标记顶点着色器输入
//-着色器_IN:用于标记非顶点着色器输入
//-SHADER_OUT:用于标记非片段着色器输出
//-OUT:用于标记片段着色器输出
#如果版本=130
#在中定义属性
#在中定义着色器_
#定义着色器输出
#界定
#否则
#定义属性
#以不同的方式定义着色器_
#定义着色器_OUT变量
#界定
#恩迪夫
//支持数组属性
#如果版本=130
#定义数组_属性(名称、大小)名称[大小]
#否则
#定义数组_属性(名称、大小)名称[大小]
#恩迪夫
//均匀块
#如果版本=130
#定义开始\u统一\u块(名称)统一名称{
#定义END_UNIFORM_BLOCK()};
#否则
#定义开始统一块(名称)
#定义结束统一块()
#恩迪夫
//输入和输出块
#如果版本=150
#在名称中定义开始输入块(名称){
#定义END_INPUT_BLOCK()};
#定义开始\输出\块(名称)输出名称{
#定义END_OUTPUT_BLOCK()};
#否则
#定义开始输入块(名称)
#定义结束输入块()
#定义开始输出块(名称)
#定义结束输出块()
#恩迪夫
//纹理功能
#如果版本=130
#定义纹理\u二维纹理
#定义纹理\u 3D纹理
#定义纹理-直接纹理
#定义纹理\u立方体纹理
#如果版本=150
#定义纹理大小(采样器)纹理大小(采样器)
#否则
#定义纹理大小(采样器)采样器大小
#恩迪夫
#否则
#定义纹理\u 2D纹理2D
#定义纹理\u 3D纹理3D
#定义纹理直接纹理2删除
#定义纹理\u立方体纹理
#恩迪夫
//不变性
#如果版本=120
#定义不变量
#否则
#定义不变量
#恩迪夫
//属性位置
#如果已定义(GL\U ARB\U显式\U属性位置)
#定义位置(loc)布局(位置=loc)
#否则
#定义位置(loc)
#恩迪夫
//几何体着色器布局
#如果版本=150
#在中定义几何图形布局
#定义几何体布局(到,最大)布局(到,最大顶点=最大)输出
#否则
#在中定义几何图形\u布局\u(从)
#定义几何图形和布局(到,最大)
#恩迪夫
//@EndInterface
实际上,在着色器源代码之前包含着色器include,框架可以在各种编译器上编译。当然,框架必须检测实际的系统功能并定义编译器参数,以便正确完成任务(考虑行着色器,因为行宽度>1.0不推荐)
当然,着色器基础结构可以定义最低要求。一旦着色器需要GLSL 1.50或更高版本的核心配置文件,就不再需要包含上述着色器了。谢谢,但我尝试的是通过仅使用预处理器为不同版本编译着色器源代码来避免兼容性标志。是的,#version指令在运行时插入,这取决于从一开始的系统功能。必须有一个可伸缩的引擎;但是,大多数系统支持高级GLSL功能。省略#版本默认为GLSL 1.1