我正在关注本教程(链接),它说您必须在链接程序后将着色器从程序中分离出来,并且之后您必须删除它们。
与编译 C++ 相比,直观地说,我认为“链接”是实际创建程序的行为(例如,制作可执行文件),-分离意味着以某种方式删除指向着色器对象的指针(我想这是相似的到.o
),在程序中(这仍然不是很清楚 - 此时程序不是已编译的可执行文件吗?它如何仍然持有指向某物的指针?) - 删除就像实际上.o
从文件夹。
但这些都是猜测,那么那里实际发生了什么?
从glDeleteShader上的 OpenGL 文档:
如果要删除的着色器对象附加到程序对象,它将被标记为删除,但在它不再附加到任何程序对象之前不会被删除,对于任何渲染上下文(即,它必须从在它被删除之前附加的任何地方)
因此,它更像是减少引用计数器而不是实际删除。
如果您了解多个程序可以共享同一个着色器,这可能会有所帮助。如果仅仅是将它从程序中分离出来就导致它被删除,那么像OpenGL 4.1 中的分离着色器对象之类的东西就会更快地实现。
您还应该知道,链接真正指的是或多或少的验证。当着色器链接在一起以创建程序时,输入/输出变量都被连接起来,并且使用的制服被分配了标识符。当程序运行时,它会使用着色器填充图形管道的每个阶段。所以实际上,程序所做的只是封装多个着色器阶段。
如果您研究ARB_separate_shader_objects
引入了程序管道对象概念的扩展规范,这一点会更清楚。您可以为每个阶段设置一个程序,而不是为每个阶段使用一个带有着色器的程序。整个 GLSL 程序方案总是有点迟钝,在大多数其他 API 中,每个阶段都有单独的着色器,并且没有一个程序链接无意义。
用你的可执行程序类比。GLSL 着色器是实际的可执行文件,GLSL 程序是有效的作业控制脚本。您的程序负责让您的每个着色器在各自的管道阶段运行,并充当传递变量(制服)的接口。