首页 > 解决方案 > #include 与 GLSL/C 的自定义 IO?

问题描述

我有两个问题,两个非常重要的问题:

  1. 是否有 C 预处理器能够采用任何自定义函数来定位由 调用的文件#include?因为,比如说,我将我的代码存储在一个 ZIP 文件或其他东西中,并且依靠 PhysFS 来访问它们而不是解压缩它们。是否有可以使用的开源 C 预处理器,而不是仅限于普通的 fopen?
  2. 是否可以在 GLSL 代码上使用自定义或标准 C 预处理器?我知道 GLSL 已经有一个预处理器,但是它缺少这个#include功能,我想纠正它。
  3. 是否可以将上述两者结合起来,制作一个程序或视频游戏,其中 GLSL 源代码存储在 ZIP 或 PK3 文件中(因此可以使用 PhysFS 或任何自定义 IO 东西访问),并且自定义/修改过的 C 预处理器是用于处理#include 并获取包含的源?

我问这个是因为我不想为 GLSL 编写自己的 C 预处理器,除非绝对必要,并且更愿意利用现有的预处理器来实现带有自定义 IO 的#include。

几乎我需要 C 预处理器东西的唯一原因是因为我想要#include,并且我想要它与我的自定义 IO 东西。

我想实现的预处理器功能示例:

  1. #version 450使用、 或#version 310 es、 以及预先处理整个已预处理的源代码#extension GL_ARB_separate_shader_objects : enable
    1. 包括运行时常量。有人说制服可能更适合这个目的,但预定义的模棱两可的常量也可能没问题。
    2. 功能的可重用性。

预期用途的一个示例:

颜色渐变.glsl

#ifndef COLOURGRADIENT_GLSL
#define COLOURGRADIENT_GLSL
vec4 gradient(vec4 cl1, vec4 cl2, float distance)
{
    return cl1+((cl2-cl1)*distance);
}
#endif // COLOURGRADIENT_GLSL

渐变片段

#include <colours/ColourGradient.glsl>
layout(location = 0) in vec2 TexCoords;
layout(location = 0) out vec4 FragColor;

uniform vec4 colourA;
uniform vec4 colourB;
uniform bool colourCentering;
#define MAX_DISTANCE 1.4142135623731 // the square root of 2, basically

void main()
{
    float dist = length(TexCoords) / MAX_DISTANCE;
    if(colourCentering) 
    {
        FragColor = gradient(colourA,colourB,(abs(dist -0.5) * 2.0));
    }
    else FragColor = gradient(colourA,colourB,(diff * dist));
}

这显然是一个微不足道的例子,但主要目的是增加代码的可重用性,并减少非预处理着色器必须包含的不必要代码量。

我的最终意图是将GlSlangSPIR-V Cross集成以将Vulkan 兼容的 GLSL (使用自定义 C 预处理器扩展)编译到 SPIR-V,如果使用的后端不是 Vulkan ,则可以选择返回到 GLSL (或 HLSL) 。由于我不知道如何在反编译回 GLSL 之前将多个 SPIR-V 二进制文件拼接在一起,我认为每个着色器模块只有一个二进制文件很重要,因此有必要#include使用多个二进制文件来代替。

标签: cglslc-preprocessorpreprocessorphysfs

解决方案


#include指令只不过是将代码粘贴到某个位置,因此与“ #include <path>”或“ #include "path"”进行简单匹配就足够了。

如果需要更复杂的包含,还应该处理定义以方便保护(就像您在代码中所做的那样),但这些在开始时不是必需的。

尽管如此,我认为支持这些添加是一种不好的做法:

  1. 不应使用包含来访问其他单元中的代码,因为已经可以在相同着色器类型的其他单元中调用函数。您基本上强制“半内联”,这可能只会导致膨胀而不是提高速度。
  2. 还应避免使用常量进行定义,因为它们不是类型和上下文安全的。在这种情况下使用const float会更安全。

总而言之,这些不存在的事实主要是因为这些对于精心设计的 GLSL 来说并不是必需的。所以在明目张胆地为某件作品添加“功能”之前,必须先问问这些添加是否是必要的,或者可以通过其他方式实现。


推荐阅读