【发布时间】:2014-12-24 19:40:30
【问题描述】:
注意:即使我的示例来自 OpenGL,这也不是 OpenGL 问题,而是一般 D 问题。
背景:在我的游戏项目中,我有一个着色器类来帮助连接到 GLSL 代码。设置制服效果很好:
uniform(string name, float value) --> glUniform1f(...)
uniform(string name, mat4 m) --> glUniformMatrix4fv( ...)
etc. etc.
也就是说,它根据参数的类型选择正确的函数,所以当我修改我的代码时,它会自动更改为使用正确的函数(假设我没有 D 和 GLSL 之间的类型冲突)。
我的麻烦是实现了一些类似的机制来绑定属性。我有 VERTEX 结构:
struct VERTEX { ...; vec3 pos; ... }
对于绑定属性,除了知道字段的类型,还需要偏移量,不需要值。我设法编写了笨拙的实现,其中调用看起来像:
vbo.attrib!(typeof(mesh.VERTEX.pos))("vert_pos", mesh.VERTEX.pos.offsetof);
而 VBO.attrib 是这样实现的:
void attrib(T: vec2)(string name, ulong offset) { /* 2 floats from offset */ }
void attrib(T: vec3)(string name, ulong offset) { /* 3 floats from offset */ }
问题:有没有办法让它更简单、更优雅?一般我不喜欢在调用时重复字段,即先提取类型选择正确的属性绑定函数,然后单独发送偏移量。我希望函数调用看起来像这样:
vbo.attrib("vert_pos", mesh.VERTEX.pos);
...以及从参数中提取类型和偏移量的模板。我已经阅读了 D 模板指南和教程,但我还没有弄清楚如何实现这样的模板。有可能吗?如何实现?
澄清:我感觉我已经很接近了,我只是没有足够的想象力(以及来自 D 模板和 mixins 的知识)来实现第一阶段:
XXX(name, field)
--> some unknown magic
--> vbo.attrib!(typeof(field))(name,field.offsetof)
--> void attrib(T: vec2)(string name, ulong offset) { /* arguments for GL call */ }
编辑:使用 mixins,我设法使它看起来像这样:
template attrib(string name, string field)
{
const char[] attrib =
"vbo.attrib!" ~
"(typeof(" ~ field ~ "))" ~
"(\"" ~ name ~ "\", " ~ field ~ ".offsetof);";
}
mixin(attrib!("vert_pos", "mesh.VERTEX.pos"));
mixin(attrib!("vert_uv", "mesh.VERTEX.uv"));
说实话,它(调用)看起来比我现在使用的更复杂,所以我保留当前的并寻找更好看的解决方案。
【问题讨论】:
-
您可以只将名称作为模板参数传递,然后使用 mixin 或 __traits(getMember) 从中获取偏移量和类型,然后将其转发给您的 attrib 函数调用。
-
或别名参数:
void attrib(alias field)(string name) { alias T = typeof(field); auto offset = field.offsetof; /* rest of your code */ }但我不确定 offsetof 是否真的适用于这样的别名。 -
blagh alias 选项可以让您获取数据,但实际上并未调用该函数,抱怨需要
this。 :( -
是的,我只是要写评论,别名假定您正在发送一些东西(我得到:“错误:模板实例属性!(pos)不能使用本地'pos'作为参数到非全局模板属性(别名字段)(字符串名称)” - 我尝试初始化,只需一秒钟。
标签: d