使用OpenGL ES为图形引擎编写动态着色器管道
Writing a dynamic Shader Pipe using OpenGL ES for a graphics engine
我不确定这是否是正确的术语,但我相信我要做的是为OpenGL ES 2.0上的GLSL着色器编写各种"管道"。这个想法是,如果你愿意的话,这将是一个方便的组件,它将进入我的引擎的图形管道。我的目标平台是安卓。我想对我背后的设计方法提出一些批评。简而言之,我似乎面临着要么创建一个动态处理管道,我只能简单地指定一些设置并添加值,要么具有最少的自动化程度,并且仍然在编写多少代码方面保持相对较低的水平,以及代码正在做什么。
详情
到目前为止,我的设计方法如下:
- 着色器文件存储在资产文件夹中
- Java充当前端,获取所有着色器文件,并将每个文件存储在Shader对象中,该对象包含有关着色器类型和原始着色器源的信息。
- 然后,Java 将着色器数据发送到这些自定义着色器对象数组中的C++(即,还不是 OpenGL 着色器对象(,然后由 JNI 解析。
- 之后,JNI 将通过 Java 获得的着色器源发送到 ShaderHandler 类单例,该类为每种类型的着色器保存一个多维
std::vector< std::vector< GLuint > >
(一个用于顶点,一个用于片段,一个用于纹理等(。- ShaderHandler 类将着色器对象编译并链接到可编程接口中,一旦完成此操作,它就会通过将其功能扩展到充当 ShaderVariable 处理程序的组件类来引导大部分繁重的工作,方法是动态地为它们赋值。例如,once可以简单地指定一个值/向量/矩阵/任何内容以及要修改的索引数量,并将其传递给ShaderVariable处理程序。一旦SVH得到,它就会将其存储在一个
std::map
中,使用变量的名称作为其标识符。
- ShaderHandler 类将着色器对象编译并链接到可编程接口中,一旦完成此操作,它就会通过将其功能扩展到充当 ShaderVariable 处理程序的组件类来引导大部分繁重的工作,方法是动态地为它们赋值。例如,once可以简单地指定一个值/向量/矩阵/任何内容以及要修改的索引数量,并将其传递给ShaderVariable处理程序。一旦SVH得到,它就会将其存储在一个
- 当出现提示时,这些 SVH 对象(存储在驻留在 ShaderHandler 类中的向量中(实质上动态绑定其 std::maps 中存在的任何值的属性和统一。
分配的一些内存是通过指针完成的,但不可否认,其中大部分由堆栈组成。我想知道我是否应该为此研究更多的动态内存分配,因为在 Android 手机上,我会想象堆栈溢出可以通过这样的方法非常非常容易实现,对于一个有点雄心勃勃的游戏,具有良好的图形等。
思潮?
,所以我对我工作的图形引擎做了一些非常相似的事情。 主要区别在于我在C++端做所有事情,而在 Java 端什么都不做(不是一件事(,这消除了 JNI 障碍。
此外,当我为OpenGL和DX9做同样的事情时,我已经抽象了一些东西。
一些提示:
- 顶点着色器和片段着色器是链接到着色器"程序"中的单独文件。 按文件夹指定程序,然后在文件夹中搜索"gles2.vert"和"gles2.frag"。 将来搜索"gles3.vert"/"gles3.frag"或"dx11.vert"/"dx11.frag"等。
- 在源代码中嵌入"默认"着色器。 这允许您将缺少的顶点/碎片着色器替换为默认值。 你不会相信顶点着色器是默认着色器的次数
- 在链接之前,请绑定属性位置。 具有属性的预定义名称/类型列表。 如果着色器不使用属性也没关系。
- 链接后,获取统一位置并将其存储在 SVH 中。 std::map 将允许您指定一个使其不区分大小写的函子。 此外,在运行时很容易推断出统一类型,以便在设置值时进行简单的类型检查。
- 此外,在链接后使用 glUniform1i 来设置采样器位置。 这是为了使 [0..N] 制服指向正确的采样器
texN
。 - SVH 将具有默认值,或者您需要一个标志来确定用户是否已设置值。
- 保留程序的状态。 该程序可能具有 std::map,但您需要具有用户设置制服的用户状态。 这种状态使得您可以使用具有不同统一值的相同着色器程序。 用户状态不需要统一位置,因为它们将由程序 svh 映射解析。 这使您无需绘制调用即可聚合统一值。
绘图
- 显式绑定和取消绑定采样器,不要自动执行此操作。 能够在采样器[1]上加载color_lut并将采样器[0]作为多个不同调用的纹理运行,这真是太好了。
- 绑定程序之后,但在绘制之前,使用程序状态中的位置从用户状态解析和设置制服。
保持着色器程序、采样器和几何体彼此不知情。 这种不可知的方法可以让你执行一些很酷的效果,例如我之前提到的color_lut着色器有效,因为几何体没有显式设置着色器,也不会清除采样器状态。这是一个可堆叠的材料系统。
我执行了一项检查,即在绑定着色器程序之前查看是否设置了 sampler0,如果是(并且没有显式设置着色器(,那么我将设置默认的纹理着色器。 如果不存在纹理(并且如果设置为默认纹理着色器(,我将回退到简单的颜色着色器。 如果着色器程序不是 [null, defaultTex],那么我不会搞砸它。
不要害怕问任何其他问题。
- std::向量与传递值的动态数组
- 在c++中用vector填充一个简单的动态数组
- C++中的动态铸造故障
- 如果C++类在类方法中具有动态分配,但没有构造函数/析构函数或任何非静态成员,那么它仍然是POD类型吗
- 在进程中对同一管道进行读取和写入时C++管道出现问题
- 内联映射初始化的动态atexit析构函数崩溃
- IPC使用多个管道和分支进程来运行Python程序
- 使用动态分配的数组会导致代码分析发出虚假的C6386缓冲区溢出警告
- 控制允许动态运行c++的并发操作数
- 如何将这个C++哈希表转换为动态扩展和收缩,而不是使用硬设置的最大值
- 在调用FreeLibrary后,释放动态链接到具有相同版本的CRT堆的DLL的内存
- 输出没有重复元素的动态数组(收缩数组)C++
- C++为线程工作动态地分割例程
- 正在插入动态数组
- 在c++中使用动态分配的问题
- C++中的动态对象与非动态对象
- 如何在动态数组上使用搜索函数
- 动态替换播放gstreamer管道中的元素
- 如何使用管道发送动态分配的字符串
- 使用OpenGL ES为图形引擎编写动态着色器管道