我在这里看到了有关此主题的堆栈溢出的许多问题和答案。从这些答案中,我想出了一个可能的解决方案,将 GLSL 属性绑定到用户定义的语义。我想获得一些关于它的意见和讨论,并检查它是否是一个有效的想法。
首先,假设我们有一些用户定义的语义列表:
enum VertexElementSemantic
{
POSITION, NORMAL, AMBIENT, DIFFUSE, SPECULAR,
TEX_COORD0, TEX_COORD1, TEX_COORD2, TEX_COORD3,
INDICES
};
以及封装设置顶点属性指针所需数据的结构。
struct VertexElement
{
unsigned int m_source;
unsigned int m_offset;
unsigned int m_stride;
}
现在,一些 RenderOperation 类将包含 VertexElementSemantics 到 VertexElements 的映射。VertexElement 的格式、大小以及是否归一化都可以由它的 Semantic 来确定。
为了设置这个指针,我们需要的最后一点信息是属性位置本身。这是我们想要将 VertexElementSemantic 绑定到特定位置的地方。
从这个问题的第一个答案中,我们了解到我们可以像这样明确地声明每个属性的期望位置:
layout(location = 0) in vec3 position;
所以我们可以将我们的语义映射到这些硬编码的位置,但是我们需要在每个着色器中对这个位置进行硬编码。对这些位置的任何更改都需要我们检查和编辑每个着色器。
但是,这个值根本不必由着色器源提供。从这个问题的答案中,我们了解到我们可以在外部将#defines 添加到我们的着色器中,如下所示:
char *sources[2] = { "#define FOO\n", sourceFromFile };
glShaderSourceARB(shader, 2, sources, NULL);
使用它,我们可以构建一个字符串,为每个语义的所需位置#defines 变量。例如,我们可以构建一个字符串,最终将以下内容插入到每个着色器的开头:
#define POSITION_LOCATION 0
#define NORMAL_LOCATION 1
#define AMBIENT_LOCATION 2
...
回到明确声明我们的属性位置,我们现在应该能够这样声明它们:
layout(location = POSITION_LOCATION) in vec3 position;
layout(location = NORMAL_LOCATION) in vec3 normal;
layout(location = AMBIENT_LOCATION) in vec4 ambient;
此方法允许我们在代码中设置每个语义的所需属性位置。它还为着色器本身提供了一种语义绑定感觉。像这样的系统是朝着正确方向迈出的一步来解决为属性位置提供意义的问题吗?