用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);
}
);
} }
我认为这不会导致exe文件太大而且会加快加载时间;除非我误认为有多少着色器用于典型的图形应用程序。我意识到你可能想在编译时更新着色器,但这确实发生了吗?
我有什么理由不想这样做吗?
答案 0 :(得分:3)
有几个原因:
答案 1 :(得分:1)
你怎么认为它会加快加载时间?它没有!
如果您从使用fopen
(或std::ifstream
或CreateFile
或其他)打开的常规文件中读取数据并从中读取数据,或者您正在访问过程映像的某些部分。哎呀,在大多数情况下,访问过程映像中的一些大页面的页面可能会表现得更糟,因为大多数操作系统都是在不可执行的,只读数据的段中延迟填充页面;未填充页面上的mmaped读取访问实际上比简单读取更慢,因为它涉及故障页面表和随后的I / O读取以使用数据填充页面。
强制性阅读:http://lkml.iu.edu/hypermail/linux/kernel/0004.0/0728.html
OpenGL API指定GLSL源代码是实际加载着色器的唯一方法。有一个缓存API(glShaderBinary,glProgramBinary),但是通过它加载的二进制文件是一种未指定的格式,可能随时改变,并且它是一个有效的错误条件,驱动程序因任何原因拒绝二进制文件强制加载原始的GLSL源。要实际获得这样的着色器二进制文件,首先要加载一个常规的GLSL着色器源,编译它,然后从OpenGL中检索二进制blob。
答案 2 :(得分:-1)
着色器编译过程是OpenGL的glsl编译器的一部分,而您可以将着色器作为字符串硬化到内存中,每次对着色器进行任何编辑时都需要重新编译。
在游戏编程中,当您对代码,着色器,库等的数百个部分进行小的调整时,通常不希望重新编译整个项目。这是所有大型游戏引擎都有脚本编写的主要原因之一引擎,编写额外的样板代码以将脚本集成到引擎中通常比编译程序10次只是为了使对象的颜色/光泽/位置恰到好处更好。尝试对所有着色器进行硬编码,以便它们在运行时在内存中进行编译,您将看到它在一天之后变得多么乏味!