主程序中有多个着色器程序
Multiple shader programs in main program
我在OpenGL中使用着色器进行编程。我知道每个着色器程序只能具有每种类型的着色器之一;例如顶点、片段、几何体等。因此,这是我的担忧以及我的解决方案:
在任何游戏中,都会有纹理和光照、环境映射、阴影和各种时髦的功能;但这些都放在一个着色器程序中吗?还是它们分布在各种着色器程序中?我的猜测是第二个,所以如果我有:
`ShaderProgram *TextLightProgram;
-> Compiles and links TextLight.vert
-> Compiles and links TextLight.frag`
-> Handles uniforms pertaining to said program
`ShaderProgram *SkyboxProgram;
-> Compiles and links Skybox.vert
-> Compiles and links Skybox.frag
-> Handles uniforms pertaining to said program`
那么,这是否适用于我的主C++程序?两组(着色器程序(的着色器,每个着色器都做自己的事情。
因为我不想明显地将这些放在 main.cpp(我正在做这种 OOP 风格(我会有两个继承自抽象 GLAbbrev 类的类(不要问我为什么这么称呼它;我想不出另一个名字了!其中将有两个实现的类,因此:
`GLAbbrev -> abstract class for handling ShaderPrograms
GLAbbrev_TextLight
-> Inherits from GLAbbrev
-> Implements functions and has ShaderProgram *TextLightProgram`
GLAbbrev_Skybox
-> Inherits from GLAbbrev
-> Implements functions and has ShaderProgram *Skybox`
因此,每个类处理一个着色器程序并相应地呈现结果。然后,在我的应用程序类中,我有一个指向GLAbbrev
的指针向量,用于管理 GLAbbrevs。(这不是一个好主意;它真的应该由另一个类管理,但请耐心等待(
Application::init()
{
glAbbrevs.push_back(new GLAbbrev_TextLight());
glAbbrevs.push_back(new GLAbbrev_Skybox());
}
然后我简单地将所有函数调用为一个,例如:
Application::render()
{
for (auto i : glAbbrevs)
i.render();
}
以及更新等。关于glViewport
和拥有相机,我认为在抽象类中已经实现这些是合乎逻辑的。因此,调整大小函数将在 GLAbbrev 中,并且该类也将具有指向Camera
的受保护指针,因为我有多个版本的相机。因此,我可以在应用程序中声明 Camera 并将其传递给 glAbbrevs,例如:
for (auto i : glAbbrevs)
i.setCamera(camera);
这可能是有问题的,但它现在会凑合着做。如您所见,这是我准备采用的一种设计方法,但不确定它是否是最有效的。其他图形程序员的意见是什么?着色器程序是否应该分布在各自的类中以执行一件事?或者应该有一个着色器程序,其顶点、碎片和几何着色器中包含所有代码;还是应该只有一个从 GLAbbrev 继承的类,但具有渲染所需输出所需的所有着色器程序?
如今,每个制作精良的游戏都使用多个着色器,每个着色器都有不同的目的和不同的实现。对于 exmaple,您可以为天空盒使用着色器,为树木使用另一个着色器,这效果很好,但它仍然不是最好的实现,在我们到达那里之前,我想澄清一下,使用这种方法有两种类型的着色器,一种绘制到屏幕(灯光等(和绘制到帧缓冲区(阴影贴图等(。
现在的完成方式是将阴影贴图和其他贴图渲染到帧缓冲区(基本上是内存中的可编辑纹理(之后,有一个大的着色器来处理光照和添加阴影贴图等等,但问题是着色器变得非常大,因此开发人员创建自定义着色器阅读器。他们从文件中读取着色器,并在读取文件时找到自己的自定义关键字(例如,他们可以有诸如"import"或"#include"之类的关键字,更像是"#include",它是一个预处理器。 并将它们替换为动作,因此可能有一个键"#include",然后是一个文件,所以它将是"#include res/shaders/lights.fs",然后他们将用 lights.fs 中的着色器代码替换该行, 当然,他们也会在 lights.fs 中检查关键字,所以在一天结束时,他们最终会得到一个由许多小着色器组成的大型着色器,并且使用这个大着色器,他们处理之前制作的所有帧缓冲区(这是通过简单地将它们作为 sampler2D 传入来完成的(以及所有的灯光和花哨的效果。
我建议在youtube上查看thebennybox,尤其是他的3D游戏引擎系列,它会对你有很大帮助,尽管前半部分是java,他后来切换到C ++,所有的C ++代码都可以在github上找到。
播放列表: https://www.youtube.com/playlist?list=PLEETnX-uPtBXP_B2yupUKlflXBznWIlL5
本尼盒:https://www.youtube.com/user/thebennybox/featured
Github:https://github.com/BennyQBD/3DEngineCpp
附言。调用 render 的更好方法是为呈现函数提供一个着色器参数,该参数被绑定,然后呈现,最后取消绑定。例如。
void render(Shader s) {
shader.bind();
this.mesh.render(); //Render here
shader.unbind();
}
如果你是老派的,你可以用一个笨重的大着色器做所有事情,是的。然而,许多人更喜欢所谓的deferred
渲染。这是一种策略,您可以通过该策略将最终帧划分为多个图层,然后以特定方式组合这些图层。在此处阅读更多相关信息。
我个人更喜欢延迟的方式,因为它提供了更简洁的方法,更少的意大利面条代码和干净的设计。
希望对您有所帮助!
- Mongodb c++驱动程序:如何查询元素的数组
- C++,系统无法执行指定的程序
- 在C++程序中输入的文本文件将不起作用,除非文本被复制和粘贴
- 在VS代码中交叉编译Windows与Linux上的MinGW的SDL程序
- C++ Windows 驱动程序MSB3030无法复制该文件,因为它找不到
- 重载操作程序时出错>>用于类中的字符串 memebr
- 获取日期异步信号安全吗?如果在信号处理程序中使用,它会导致死锁吗
- 试图在visual studio上用C++创建一个桌面应用程序
- 模板元程序查找相似的连续类型名称
- FFmpeg:制作一个应用程序比直接使用ffmepg更好吗
- 如何通过cpp程序运行shell脚本
- 有没有什么方法可以使用一个函数中定义的常量变量,也可以由c++中同一程序中的其他函数使用
- IPC使用多个管道和分支进程来运行Python程序
- 如何将c++程序的一些输出传递给shell,以便在shell中使用
- 使用C++程序合并排序没有得到正确的输出
- C++程序从主程序开始执行并在主程序结束?
- 当您的程序在进入主程序之前崩溃时该怎么办?
- 主程序中有多个着色器程序
- 获取一个主程序,在一个新线程中启动一个从程序
- OpenGL程序未到达主程序