面向对象架构,用于简单的基于着色器的GL程序

OO architecture for simple shader-based GL program

本文关键字:于着色 GL 程序 简单 用于 面向对象      更新时间:2023-10-16

我正在设计一个OO程序(用C++),它处理用OpenGL实现的中等简单的图形。我已经为我的Drawable对象编写了几个顶点着色器程序。此外,我还在Shader类中封装了着色器管理(编译、链接和使用)。

我的问题是,由于我的所有类都将使用这一小组着色器渲染视觉对象,并且它们都有一个指向Shader对象的指针,因此为所有类提供公共引用是否有意义,这样可以避免多次编译"同一"着色器代码?

如果是,为什么?防止着色器代码的重复真的很重要吗?(我的程序可能会有数千个独立的视觉元素,需要一起渲染)。我是OpenGL的新手,性能/效率问题对我来说仍然很模糊…

编辑:此外,我想知道我的着色器制服会发生什么;它们也会被分享吗?这应该如何允许我,例如以不同的速率旋转我的元素?每次我想绘制每个元素时,编写元素统一(即模型矩阵)是否比复制着色器代码更好?

我敢打赌,在大多数(如果不是所有的话)OpenGL实现中,多次编译和链接同一着色器会导致着色器二进制文件的多个副本和统一空间等。调用glUseProgram在重复副本之间切换仍然会导致状态更改,尽管在调用前后GPU内核上运行相同的代码。有了足够复杂的场景,你可能也会切换纹理,所以无论如何都会有状态变化。

这可能不是你的瓶颈,但肯定是浪费。对于着色器和纹理等静态内容,一个好的模式是拥有一个或多个Manager类(AssetManagerTextureManager等),这些类将延迟加载(或预加载)所有资产,并在您请求时为您提供共享指针(或其他内存管理策略),通常是通过一些字符串ID。

关于编辑:

是的,您的制服将被共享,并且在您解除绑定后仍将被装载。这是首选的方法,因为更新统一比绑定新着色器快一个数量级以上。您只需为每个新对象设置模型矩阵统一,但保持相同的着色器。

统一格式存储在着色器中,因此切换着色器意味着加载所有统一格式。