我正在使用 GLSL 着色器编写一个小型渲染引擎:
每个网格(嗯,子网格)都有许多顶点流(例如位置、法线、纹理、切线等)到一个大 VBO 和一个 MaterialID。
每个材质都有一组纹理和属性(例如镜面反射颜色、漫反射颜色、颜色纹理、法线贴图等)
然后我有一个 GLSL 着色器,带有它的制服和属性。比方说:
uniform vec3 DiffuseColor;
uniform sampler2D NormalMapTexture;
attribute vec3 Position;
attribute vec2 TexCoord;
我有点卡在尝试为 GLSL 着色器设计一种方法来定义属性和制服的流映射(语义),然后将顶点流绑定到适当的属性。
对网格说的话:“将您的位置流放在属性“Position”中,将您的tex坐标放在“TexCoord”中。还将材质的漫反射颜色放在“DiffuseColor”中,将材质的第二个纹理放在“NormalMapTexture”中
目前我正在使用硬编码的属性名称(即顶点位置始终是“位置”等)并检查每个统一和属性名称以了解着色器使用它的目的。
我想我正在寻找某种创建“顶点声明”的方法,但也包括制服和纹理。
所以我只是想知道人们如何在大型渲染引擎中做到这一点。
编辑:
回顾建议的方法:
1. 属性/统一语义由变量的名称给出 (我现在正在做的)为每个可能的属性使用预定义的名称。GLSL 绑定器将查询每个属性的名称并根据变量名:
//global static variable
semantics (name,normalize,offset) = {"Position",false,0} {"Normal",true,1},{"TextureUV,false,2}
...when linking
for (int index=0;index<allAttribs;index++)
{
glGetActiveAttrib(program,index,bufSize,length,size[index],type[index],name);
semantics[index]= GetSemanticsFromGlobalHardCodedList(name);
}
... when binding vertex arrays for render
for (int index=0;index<allAttribs;index++)
{
glVertexAttribPointer(index,size[index],type[index],semantics[index]->normalized,bufferStride,semantics[index]->offset);
}
2. 每个语义的预定义位置
GLSL binder 将始终将顶点数组绑定到相同的位置。由着色器使用适当的名称进行匹配。(这似乎与方法 1 非常相似,但除非我误解了,这意味着绑定所有可用的顶点数据,即使着色器不使用它)
.. when linking the program...
glBindAttribLocation(prog, 0, "mg_Position");
glBindAttribLocation(prog, 1, "mg_Color");
glBindAttribLocation(prog, 2, "mg_Normal");
3. 材质、引擎全局、渲染器和网格的可用属性字典
维护由活动材质、引擎全局变量、当前渲染器和当前场景节点发布的可用属性列表。
例如:
Material has (uniformName,value) = {"ambientColor", (1.0,1.0,1.0)}, {"diffuseColor",(0.2,0.2,0.2)}
Mesh has (attributeName,offset) = {"Position",0,},{"Normals",1},{"BumpBlendUV",2}
然后在着色器中:
uniform vec3 ambientColor,diffuseColo;
attribute vec3 Position;
将顶点数据绑定到着色器时,GLSL 绑定器将遍历属性并绑定到字典中找到(或未找到?)的属性:
for (int index=0;index<allAttribs;index++)
{
glGetActiveAttrib(program,index,bufSize,length,size[index],type[index],name);
semantics[index] = Mesh->GetAttributeSemantics(name);
}
和制服一样,只查询活动材质和全局。