【问题标题】:#include with custom IO for GLSL/C?#include 与 GLSL/C 的自定义 IO?
【发布时间】:2018-10-20 13:12:23
【问题描述】:

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

  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. 函数的可重用性。

预期用途的一个例子:

ColourGradient.glsl

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

Gradient.frag

#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,并可选择返回 GLSL (或 HLSL) 如果使用的后端不是 Vulkan。由于我不知道如何在反编译回 GLSL 之前将多个 SPIR-V 二进制文件拼接在一起,因此我认为每个着色器模块只有一个二进制文件很重要,因此需要#include 而不是使用多个二进制文件。

【问题讨论】:

  • 为什么要能够#include,给出编码示例来说明想要达到的效果

标签: c glsl c-preprocessor preprocessor physfs


【解决方案1】:

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

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

综上所述,我认为支持这些添加是一种不好的做法:

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

总而言之,这些不存在的事实主要是因为从一开始就精心设计的 GLSL 不需要这些。所以在明目张胆地给某样东西添加“功能”之前,必须先问问这些添加是必要的,还是可以通过其他方式实现的。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2012-10-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-02-11
    • 2017-05-05
    • 2016-01-29
    相关资源
    最近更新 更多