在OpenGL中管理着色器的正确方法

时间:2013-07-31 13:40:42

标签: opengl architecture glsl shader

我正在用C ++编写代码来处理通常的3D东西 - 模型,材料,灯光等等。但是,我发现无论什么工作,都需要了解着色器。 EG,要为材质设置统一变量,您需要从着色器中知道它们的句柄;要将网格加载到内存中,您需要知道不同in位置的句柄。

我最终拥有模型,材料等,每个都有一个着色器的句柄,所以他们可以做像glUniform1f(shader->getKdLocation(),kd)这样的事情,但这种烫手山芋对我来说似乎是糟糕的设计。我已经看过教程,其中制服和ins和out在着色器中硬编码(例如layout = 0),然后只与glUniform1f(0,kd)绑定。但是,这意味着我的其余代码只能使用我特别设计的着色器,因此看起来像是一个次优的解决方案。另外,我认为你不能为子程序做这个,这使得这个选项不一致。

它似乎是所有获取着色器引用的所有内容之间的选择,并且在某些情况下甚至无法在没有一个(例如网格)的情况下进行正确实例化或在更多地方硬编码数字并且必须处理硬编码后面的问题。

坚实的方式来做到这一点。我的底线问题是处理着色器的最佳实践是什么?我没关系,如果它不能解决我的所有问题,我只想知道一个好的设计决定是什么, 为什么

2 个答案:

答案 0 :(得分:1)

问题在于您的引擎架构,或者它缺乏。在许多游戏引擎中,游戏对象被分为几个类别,如Mesh对象,它负责几何(顶点缓冲等),Material对象(负责网格对象的外观)在这样的设计中,材料通常是一个实体,其中包含在渲染过程中传递到着色器的制服的信息。这样的设计允许大量的灵活性,因为您可以重复使用,在不同的可渲染对象之间重新分配不同的材料。所以您可以将特定着色器程序设置为特定材质类型,因此每次绘制网格时,其材质都会与着色器程序进行交互,并传递所有需要的制服。

我建议你看看开源OpenGL引擎,了解它是如何工作的。

答案 1 :(得分:0)

对于客户端上的统一规范与着色器中规定的实际统一位置之间的松散关联,我有同样的担忧。

您可以采取的一种方法是使用glGetUniformLocation根据名称确定统一变量的位置。它可能仍然不完美,但它可能是你能做的最好的。

示例:

// Old way:
GLfloat myfloat = ...;
glUniform1f(0, myfloat);   // Hope that myfloat was supposed to go at location 0...

VS

// Slightly better...
GLfloat myfloat = ...;
GLint location = glGetUniformLocation(myprogram, "myfloat");
glUniform1f(location, myfloat);   // We know that a uniform with name "myfloat" goes at this location

glGetActiveUniform的一些额外工作也可以让你确保“myfloat”具有你所期望的类型/大小/等。