在OpenGL规范中,某些参数采用from GL_OBJECTENUMERATIONi
的一组值,其中i范围从0到某个数字,如GL_MAX_OBJECT
所示。 (作为一个例子,灯是一个'对象'。)很明显,指示的数字是要通过glGet函数传递的上限,提供一些间接。
然而,根据OpenGL规范的字面解释,glActiveTexture must be one of GL_TEXTUREi, where i ranges from 0 (GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS - 1)
的“纹理”参数表示接受的常量必须 be GL_TEXTURE0
到GL_TEXTURE35660
因为常量是值35661的常量。
除了语言律师之外,这种设置意味着子类型不仅可以不相交,而且也可以不按顺序排列,以便以下C-ish映射有效:
#define GL_TEXTURE0 0x84C0
#define GL_TEXTURE1 0x84C1
#define GL_TEXTURE2 0x84C2
#define GL_TEXTURE3 0x84A0
#define GL_TEXTURE4 0x84A4
#define GL_TEXTURE5 0x84A5
#define GL_TEXTURE6 0x84A8
#define GL_TEXTURE7 0x84A2
首先,这是一个问题实际上是一个问题,还是常量总是布局好像GL_OBJECTi
= GL_OBJECTi-1
+ 1?
如果该关系成立,则可以使用Ada的子类型功能来避免传入无效参数...
理想情况下,如:
-- This is an old [and incorrect] declaration using constants.
-- It's just here for an example.
SubType Texture_Number is Enum Range
GL_TEXTURE0..Enum'Max(
GL_MAX_TEXTURE_COORDS - 1,
GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS - 1);
但是,如果最大值是动态确定的,那么我们必须做一些关于:
的工作With GL_Constants;
Generic
GL_MAX_TEXTURE : Integer;
-- ...and one of those for EACH maximum for the ranges.
Package Types is
Use GL_Constants;
SubType Texture_Number is Enum Range
GL_TEXTURE0..GL_MAX_TEXTURE;
End Types;
实例化Package GL_TYPES is new Types( GL_MAX_TEXTURE => glGet(GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS) );
,然后使用这个新的GL_TYPES
包...多做一点工作,比直接子类型更麻烦。
其中大部分来自于对OpenGL完全不熟悉并且不完全了解/理解它;但它确实引发了一些有趣的问题,即建立良好,厚实的Ada绑定的最佳方式。
答案 0 :(得分:4)
表示接受的常量集必须是GL_TEXTURE0到GL_TEXTURE35660,因为常量是值35661的常量。
不,这并不意味着这一点。 GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS是依赖于实现的值,将在运行时使用glGetIntegerv(GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS, out)
关于其余部分:OpenGL规范声明GL_TEXTURE = GL_TEXTURE0 + i,并且对于所有其他对象类型都是类似的,i < n
其中 n 是一个合理的数字。
答案 1 :(得分:3)
这是其中一种情况,我不认为这些类型会让你变得更加性感。
如果您只是为GL_TEXTURE(type GL_TEXTURE is 16#84C0# .. 16#8B4C#;
)创建一个特殊的整数类型,并将该类型用于寻找GL纹理的所有参数,编译器将阻止用户在这些和其他整数对象之间进行数学运算。那可能会很多。它比那些可怜的C / C ++编码员更好的方式更好!
然后,我再也没有成为超厚Ada绑定的支持者。 Ada绑定应该用于使类型更像Ada,并将C错误代码转换为异常。如果还有其他方法可以为用户节省一些工作,请继续操作。但是,不要抽象掉API的任何功能!
关于我选择使用单独的数字类型而不是整数子类型的评论中有多个问题。
事实上,当integer
子类型执行时,开始制作自己的自定义数字类型是一个常见的Ada noob错误,然后对您必须执行的所有类型转换感到恼火。经典的例子是某人制作速度类型,然后是另一种类型的距离,然后是另一种类型的力量,然后发现他们必须对每一个该死的数学运算进行类型转换。
但是,有时会调用自定义数字类型。特别是,只要该类型的对象应该存在于与普通整数不同的类型Universe中,就要使用自定义数字类型。最常见的情况发生在API绑定中,其中所讨论的数字实际上是某些资源的C-ish指定。这是我们在这里的确切情况。你想要在GL_Texture
上做的唯一数学是与类型的界限进行比较,以及用文字量进行简单的加法和减法。 (最有可能GL_Texture'next()
就足够了。)
作为一个巨大的奖励,使其成为自定义类型将防止将GL_Texture值插入API调用中的错误参数的常见错误。 C API调用确实喜欢他们的int
...
事实上,如果坐下来输入它们是合理的,我怀疑你很想让这个东西成为枚举。如果没有转换,那与Integer
的兼容性就更低了,但是没有人在这里会三思而后行。
答案 2 :(得分:2)
好的,首先需要了解OpenGL的规则:每当你看到的东西都说“从X到Y”,其中一个值是GL_THINGY
,是不谈论GL_THINGY
的数值。他们讨论的是依赖于实现的值,您使用 GL_THINGY
查询。这通常是一个整数,因此您可以使用某种形式的glGetIntegerv
来查询它。
下一步:
此设置意味着子类型不仅可以不相交,而且也可以不按顺序排列,以便以下C-ish映射有效:
不,它不会。
ARB中的每个实际枚举器都由ARB分配一个特定值。 ARB为指定的GL_TEXTURE''i''枚举器指定的值为:
#define GL_TEXTURE0 0x84C0
#define GL_TEXTURE1 0x84C1
#define GL_TEXTURE2 0x84C2
#define GL_TEXTURE3 0x84C3
#define GL_TEXTURE4 0x84C4
#define GL_TEXTURE5 0x84C5
#define GL_TEXTURE6 0x84C6
#define GL_TEXTURE7 0x84C7
#define GL_TEXTURE8 0x84C8
注意它们是如何按顺序排列的。
至于其余部分,让我引用一下glActiveTexture
上的OpenGL 4.3规范:
如果指定了无效纹理,则会生成INVALID_ENUM错误。纹理是TEXTURE''i'形式的符号常量,表示要修改纹理单元“i”。常量遵循TEXTURE''i''= TEXTURE0 +''i'',其中''i'在0到''k'' - 1的范围内,''k''是MAX_COMBINED_TEXTURE_IMAGE_UNITS的值)。
如果你用某种语言创建一个绑定,一般的想法是:''不要强烈键入某些值''。特别是这一个。只需拿走用户提供的任何内容并传递给它。如果用户收到错误,则会收到错误。
更好的是,公开一个更合理的glActiveTexture
版本,它取一个'整数'而不是一个枚举器,然后自己做这个加法。