2

在 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)的“纹理”参数意味着接受的常量集必须GL_TEXTURE0to,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 绑定的最佳方式。

4

3 回答 3

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是一个合理的数字。

于 2012-10-22T21:48:14.967 回答
3

这是其中一种情况,我不认为让这些类型变得特别性感会给你带来很多好处。

如果您只是为 GL_TEXTURE ( type GL_TEXTURE is 16#84C0# .. 16#8B4C#;) 创建一个特殊的整数类型,并将该类型用于查找 GL 纹理的所有参数,编译器将阻止用户在这些和其他整数对象之间进行数学运算。那可能就足够了。它肯定比那些可怜的 C/C++ 程序员所坚持的要好得多!

再说一次,我从来都不是超厚 Ada 绑定的支持者。应该使用 Ada 绑定来使类型更像 Ada,并将 C 错误代码转换为异常。如果有其他方法可以为用户节省一些工作,那就去做吧。但是,不要抽象出 API 的任何功能!


关于我选择使用单独的数字类型而不是整数子类型的评论中有多个问题。

实际上,当子类型可以使用时,开始为自己创建自定义数字类型integer,然后对必须进行的所有类型转换感到恼火,这是一个常见的 Ada 菜鸟错误。典型的例子是有人为速度创建了一种类型,然后为距离创建了另一种类型,然后为力创建了另一种类型,然后发现他们必须对每一个该死的数学运算进行类型转换。

但是,有时需要自定义数字类型。特别是,只要该类型的对象应该存在于与普通整数不同的类型域中,您就希望使用自定义数字类型。最常见的情况发生在 API 绑定中,其中有问题的数字实际上是某些资源的 C-ish 名称。这就是我们这里的确切情况。在 s 上你唯一想做的数学运算GL_Texture就是与类型的边界进行比较,以及按字面量进行简单的加减运算。(很可能GL_Texture'next()就足够了。)

作为一个巨大的好处,将其设为自定义类型将防止将 GL_Texture 值插入 API 调用中的错误参数的常见错误。C API 调用确实喜欢他们int的...

事实上,如果坐下来把它们全部输入是合理的,我怀疑你会很想把它作为一个枚举。如果没有转换,那将更不兼容Integer,但这里没有人会三思而后行。

于 2012-10-22T22:09:46.843 回答
2

好的,关于 OpenGL,您需要了解的第一条规则:每当您看到“从 X 到 Y”的内容,并且其中一个值是 aGL_THINGY时,它们并不是在谈论 的数值GL_THINGY。他们正在谈论您使用查询的依赖于实现的 GL_THINGY。这通常是一个整数,因此您可以使用某种形式的glGetIntegerv来查询它。

下一个:

这种设置意味着子类型不仅可以是不相交的,而且也可以是乱序的,因此以下 C-ish 映射将是有效的:

不,它不会。

OpenGL 中的每个实际枚举器都由 ARB 分配一个特定的值。命名 GL_TEXTURE''i'' 枚举器的 ARB 分配值为:

#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

注意它们是如何按顺序排列的。

至于其余的,让我从 OpenGL 4.3 规范中引用您的内容glActiveTexture

如果指定了无效纹理,则会生成 INVALID_ENUM 错误。texture 是 TEXTURE''i'' 形式的符号常量,表示要修改纹理单元 ''i''。常量服从 TEXTURE''i'' = TEXTURE0 + ''i'' 其中 ''i'' 在 0 到 ''k'' - 1 的范围内,而 ''k'' 是 MAX_COMBINED_TEXTURE_IMAGE_UNITS 的值)。

如果您要使用某种语言创建绑定,一般的想法是:“不要强类型化某些值”。尤其是这个。只要拿走用户给你的任何东西并传递它。如果用户得到一个错误,他们就会得到一个错误。

更好的是,公开一个更合理的版本,glActiveTexture它需要一个“整数”而不是一个枚举器,然后自己进行加法。

于 2012-10-22T23:15:22.493 回答