在图形应用程序中,为什么着色器在运行时加载到应用程序中?

Kei*_*ker 7 c++ opengl performance shader glsl

用 GLSL 等编写的着色器通常在运行时加载到图形应用程序中。我想知道为什么不直接使用着色器编译应用程序,这样以后就不必加载它们了。像这样:

#define glsl(version, glsl) "#version " #version "\n" #glsl

namespace glsl { namespace vs {
//VERTEX SHADERS
//=========================
// simple VS
//=========================
constexpr GLchar * const simple = glsl(450 core, 
    layout(location = 0) in vec3 position;

    void main() {
        gl_Position = vec4(position, 1.0f);
    }
    );

} namespace fs {
//FRAGMENT SHADERS
//=========================
// simple FS
//=========================
constexpr GLchar * const simple = glsl(450 core,
    out vec4 color;

    void main() {
        color = vec4(1.0f, 0.0f, 0.0f, 1.0f);
    }       
    );

} }
Run Code Online (Sandbox Code Playgroud)

我不认为这会导致 exe 文件太大并且会加快加载时间;除非我错误地理解了典型图形应用程序使用了多少个着色器。我知道您可能想在编译后更新着色器,但这真的会发生吗?

我有什么理由不想这样做吗?

mat*_*ort 5

有几个原因:

  • 在开发过程中,“热加载”着色器非常方便,无需重新启动应用程序,因此您可以在调试或性能调整时进行更改并立即查看结果。当着色器存储为单独的文件时,这会更简单。
  • 正如评论中提到的,根据您的平台,通常将着色器从高级着色语言预编译为中间字节代码表示或实际的最终 GPU 代码(例如,在 GPU 硬件是固定目标的控制台的情况下) 。着色器编译可能非常耗时,因此最好尽可能离线完成,而不是在运行时完成。
  • 您采取的方法实际上在小型/简单的应用程序中并不罕见,您的应用程序越大并且您必须管理的着色器越多,它就会变得更加痛苦。就我个人而言,我喜欢即使在小型个人项目中也能够热加载着色器。
  • 这实际上是一个比着色器更普遍的问题。在任何项目中,您都可以选择何时将资源嵌入到可执行文件中(直接嵌入源代码或通过 Windows 资源等单独的构建步骤)或将它们存储为单独的文件。两种方法都有优点和缺点,但嵌入的主要优点是应用程序可能需要的所有资源都直接嵌入到可执行文件中,因此您不必担心/处理可能丢失的资源。缺点是,如果将所有内容都塞进可执行文件中(特别是对于具有许多大型资产(例如游戏)的项目),则会增加构建时间,使热加载变得困难,并使资产组织问题变得更加困难。