我应该在哪里保存我的着色器代码?
Where should I keep my shader code?
这是一个哲学问题。
我想知道是否有任何优雅的方法可以在标准 QtCreator 项目中包含着色器代码。我知道的唯一两种方式是:
着色器代码在单独的文件中,例如"fragmentshader.frag",此文件在运行时读取,着色器代码被编译和链接。
着色器代码是项目中包含的源文件之一中的硬编码字符串。
这两种方式对我来说都有点烦人。第一种可能性要求硬盘驱动器上的文件必须与可执行文件位于同一目录中(因此我必须将它们放在每个 debug/release 目录中并最终得到我的着色器文件的多个副本)或在我驱动器上的特定硬编码目录,这似乎不利于便携性。
第二种可能性让我很困扰,因为你必须在你的着色器代码中包含像 \n
这样的东西,这使得格式有点难看。
"right" 如何做到这一点?如果它有任何意义,我正在使用 c/c++、OpenGL 和 GLSL 进行编码。
编辑:
我一直在谷歌搜索这个......我注意到例如一个图标文件可以保存在项目的一个特殊资源文件夹中。这样它就是一个文件并且可以这样编辑但仍然没有在运行时加载。有没有办法用着色器做到这一点?
我觉得这不是一个正确的答案,但它也太长了,不适合发表评论。
粗略地说,您是对的 - 您可以在编译时使用着色器并进行硬编码,或者在 运行 时加载。我将详细说明实现此目标的各种方法。请注意,所说的一切都可以应用于您的程序需要的任何其他类型的数据资源 运行。
硬编码可以以更优雅的方式完成:将资源保存在单独的文件中,但设置您的构建系统,使其自动生成 带有硬编码的源文件编码资源(例如,作为 std::uint8_t
或 char
的静态或动态数组),并将这些生成的文件编译到您的程序中。在这里,您可能需要一个从二进制数据生成 C++ 源文件的实用程序。我不知道有这样好的、有特色的节目;当我需要的时候,我自己写了一个,因为它很简单。
为了运行时间加载更便携,您可以使用大量选项,但似乎最重要的是使资源在文件系统上的位置可配置;在 运行 时间或编译时间,由您决定。它可以是编译标志(f.e。由构建系统设置的宏RUNTIME_RESOURCE_PATH
)。它可以是具有一些合理默认值的命令行选项。
我不知道right
是哪条路。应根据用例选择一个。
硬编码数据简化了部署(更少的文件、更少的显式 io、更少的错误),而单独文件中的资源使您能够在不触及程序本身的情况下更新它们,包括用户修改。
你可以做的另一件事是使用原始字符串文字,如果你有 C++11:
const char shaderSource[] = R"glsl(
#version 450 core
...
void main() {
...
}
)glsl";
看不到 \n
:)
这是一个哲学问题。
我想知道是否有任何优雅的方法可以在标准 QtCreator 项目中包含着色器代码。我知道的唯一两种方式是:
着色器代码在单独的文件中,例如"fragmentshader.frag",此文件在运行时读取,着色器代码被编译和链接。
着色器代码是项目中包含的源文件之一中的硬编码字符串。
这两种方式对我来说都有点烦人。第一种可能性要求硬盘驱动器上的文件必须与可执行文件位于同一目录中(因此我必须将它们放在每个 debug/release 目录中并最终得到我的着色器文件的多个副本)或在我驱动器上的特定硬编码目录,这似乎不利于便携性。
第二种可能性让我很困扰,因为你必须在你的着色器代码中包含像 \n
这样的东西,这使得格式有点难看。
"right" 如何做到这一点?如果它有任何意义,我正在使用 c/c++、OpenGL 和 GLSL 进行编码。
编辑: 我一直在谷歌搜索这个......我注意到例如一个图标文件可以保存在项目的一个特殊资源文件夹中。这样它就是一个文件并且可以这样编辑但仍然没有在运行时加载。有没有办法用着色器做到这一点?
我觉得这不是一个正确的答案,但它也太长了,不适合发表评论。
粗略地说,您是对的 - 您可以在编译时使用着色器并进行硬编码,或者在 运行 时加载。我将详细说明实现此目标的各种方法。请注意,所说的一切都可以应用于您的程序需要的任何其他类型的数据资源 运行。
硬编码可以以更优雅的方式完成:将资源保存在单独的文件中,但设置您的构建系统,使其自动生成 带有硬编码的源文件编码资源(例如,作为 std::uint8_t
或 char
的静态或动态数组),并将这些生成的文件编译到您的程序中。在这里,您可能需要一个从二进制数据生成 C++ 源文件的实用程序。我不知道有这样好的、有特色的节目;当我需要的时候,我自己写了一个,因为它很简单。
为了运行时间加载更便携,您可以使用大量选项,但似乎最重要的是使资源在文件系统上的位置可配置;在 运行 时间或编译时间,由您决定。它可以是编译标志(f.e。由构建系统设置的宏RUNTIME_RESOURCE_PATH
)。它可以是具有一些合理默认值的命令行选项。
我不知道right
是哪条路。应根据用例选择一个。
硬编码数据简化了部署(更少的文件、更少的显式 io、更少的错误),而单独文件中的资源使您能够在不触及程序本身的情况下更新它们,包括用户修改。
你可以做的另一件事是使用原始字符串文字,如果你有 C++11:
const char shaderSource[] = R"glsl(
#version 450 core
...
void main() {
...
}
)glsl";
看不到 \n
:)