我应该把我的着色器代码保存在哪里?

10

这有点像是一个哲学问题。

我在想,是否有任何优雅的方法可以将着色器代码包含在标准 QtCreator 项目中。我所知道的只有两种方法:

  1. 着色器代码位于单独的文件中,例如 "fragmentshader.frag",此文件在运行时被读取,着色器代码被编译和链接。

  2. 着色器代码是项目中包含的源文件中的硬编码字符串。

这两种方法都让我感到有些烦人。第一种可能性需要硬盘上的文件,这些文件必须与可执行文件位于同一目录中(因此我必须将它们放在每个调试/发布目录中,并最终得到我的着色器文件的多个副本),或者位于硬编码指定的特定目录中,这似乎不利于可移植性。

第二种可能性让我感到困扰,因为您必须在着色器代码中包含换行符 \ n,这使得格式有点丑陋。

什么是“正确”的方法?如果有任何意义的话,我正在使用 c / c ++、OpenGL 和 GLSL 进行编码。

编辑: 我继续搜索了相关信息... 我注意到,例如图标文件可以保存在项目中的特殊资源文件夹中。这样它就是一个文件,可以像文件一样进行编辑,但仍然不必在运行时加载。是否有一种方法可以对着色器做到这一点?

2个回答

11

另一件事是,如果您使用的是C++11,则可以使用原始字符串字面值:

const char shaderSource[] = R"glsl(
#version 450 core

...    

void main() {
    ...
}
)glsl";

没有\n出现 :)


这很有趣!我一定会尝试的! - Martin Hennig
是不是每行开头都要加 " 呢?我刚刚设置了我的 .pro 文件使用 c++11,在字符数组中,如果我按下回车键,它会自动给我加上一个引号。(此外,测试着色器并没有像你在这里发布的那样工作) - Martin Hennig
它可以工作,但是需要在每行前后加上引号,而不使用 glsl() - Martin Hennig
1
您可以在此处阅读有关字符串字面值的更多信息:http://en.cppreference.com/w/cpp/language/string_literal。开头和结尾括号旁边的“glsl”是可选的。它们只是使结束序列变长,以便您的字符串可以包含“)”而不会结束。 - Jagoly
我现在已经使用它有一段时间了,我非常喜欢它。谢谢! - Martin Hennig
1
我强烈推荐这个。 - Krythic

4

我认为这不是一个恰当的回答,但也过长不能作为评论。

粗略地说,你是正确的——要么在编译时硬编码使用着色器资源,要么在运行时加载。我将详细阐述您可以实现此目标的各种方法。请注意,所有内容都适用于程序运行所需的任何其他数据资源。

硬编码可能以更优雅的方式完成:将资源保留在单独的文件中,但设置构建系统以使其“自动生成”具有硬编码资源的源文件(例如,作为std::uint8_tchar的静态或动态数组),并将这些生成的文件编译到您的程序中。在这里,您可能需要一个实用程序,该实用程序从二进制数据生成C++源文件。我不知道像这样的好的、功能齐全的程序;当我需要一个时,我自己编写了一个,因为它非常简单。

为了使运行时加载更加可移植,您可以使用大量选项,但似乎最重要的是使文件系统上的资源位置可配置;在运行时或编译时,由您决定。它可以是编译标志(例如,通过构建系统设置的宏RUNTIME_RESOURCE_PATH)。它可以是带有一些合理默认值的命令行选项。

我没有关于哪种方式是“正确”的答案。应根据使用情况选择一种方法。

硬编码数据简化了部署(文件更少,显式io更少,错误更少),而单独的资源文件使您可以在不触及程序本身的情况下更新它们,包括用户的修改。


尽管将资源放在单独的文件中使您能够更新它们而无需触及程序本身,但着色器代码也是一个程序...我们在此进行即时编译。 - Alexis Wilke

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