【问题标题】:Why are these signed bytes being read as unsigned bytes with LWJGL?为什么这些有符号字节被 LWJGL 读取为无符号字节?
【发布时间】:2014-01-07 01:02:44
【问题描述】:

当您使用 LJWGL 函数 glBufferData() 上传存储有符号字节的 ByteBuffer(java 语言对象)时,openGL 解释相应缓冲区上的数据的正确方法是使用 GL_UNSIGNED_BYTE。

这是为什么? LWJGL 似乎没有将 ByteBuffer 转换为其他格式,这里是 glBUfferData() 函数的源代码。

public static void glBufferData(int target, ByteBuffer data, int usage) {
    ContextCapabilities caps = GLContext.getCapabilities();

    long function_pointer = caps.glBufferData;

    BufferChecks.checkFunctionAddress(function_pointer);
    BufferChecks.checkDirect(data);

    nglBufferData(target, data.remaining(), MemoryUtil.getAddress(data), usage, function_pointer);
}

知道为什么吗?

编辑:

我明白为什么你们可能认为不需要转换,因为无符号字节和字节的存储方式相同。但是让我澄清一下,我将 1 2 3 4 5 等的整数值放入这个字节缓冲区,大概是有符号字节,因为这是 java 处理的。因此,大概在使用有符号解释时,这些字节存储了 12345。那么为什么 openGL 用无符号解释而不是有符号解释来读取 12345,这就是问题所在。

注意数据的意义是一个索引缓冲区。

【问题讨论】:

  • 重要的是数据的含义。值 0 和值 255 是什么意思? -128 对您拥有的数据是否有意义?所以需要考虑的是你拥有的数据,而不是你在 Java 中存储它的类型(没有无符号类型)
  • 我在问题中添加了一个编辑以澄清
  • 0 到 127 的值无论是有符号字节还是无符号字节都没有区别。很可能 OpenGL 指定了无符号字节,但 Java 不支持它们,因此它使用有符号字节。

标签: java opengl lwjgl


【解决方案1】:

首先,不要将GL_UNSIGNED_BYTE 用于顶点缓冲区索引。 OpenGL 在 API 级别支持这一点,但过去约 14 年制造的桌面 GPU 硬件通常在硬件级别不支持它。驱动程序会将索引转换为 16 位以满足硬件限制,因此您实际上所做的只是增加驱动程序的工作量。如果您不想给驱动程序造成不必要的负担,GL_UNSIGNED_SHORT 确实是您应该使用的最小索引大小。归结为未对齐的内存访问,如果需要,您可以使用 8 位索引,但如果您使用 16/32 位,则会获得更好的顶点性能。

为了解决这个问题中的实际问题,您使用 GL_UNSIGNED_BYTE 来解释顶点索引,在这种情况下,数据类型的范围与 GL_UNSIGNED_BYTE 与 GL_SIGNED_BYTE 真的只有解释颜色值很重要,因为 GL 进行定点缩放以重新映射 [-128, 127] -> [-1.0, 1.0] 中的值(有符号)或 [0, 255] -> [0.0, 1.0](无符号)用于内部表示。

然而,在顶点索引的情况下,数字 5 在它之后是 仍然 5从无符号转换为有符号或相反。解释顶点索引不需要定点到浮点的转换,因此值的范围并不是特别重要(假设没有溢出)。

为此,您在使用顶点索引时别无选择。唯一有效的枚举是GL_UNSIGNED_BYTEGL_UNSIGNED_SHORTGL_UNSIGNED_INT。如果您的语言不能表示无符号值,那么 OpenGL 的语言绑定将负责弄清楚这些枚举的确切含义以及如何处理它们。

【讨论】:

    【解决方案2】:

    有符号字节和无符号字节之间的主要区别在于您对位的解释方式:负值与超过 127 的值具有相同的位模式。两者不需要不同类型的存储,并且转换(这真的是无操作)使用二进制补码系统自动工作。

    【讨论】:

    • 您能否根据我对问题的编辑来编辑您的答案?
    • 那么问题来了,为什么 1 2 3 4 5 的有符号和无符号二进制表示是相同的?这就是二进制补码系统的工作原理,正整数与无符号整数具有相同的表示,负整数与大的无符号正整数具有相同的表示。恐怕这已经被讨论到死了。
    • 虽然你说的是真的,但 OpenGL 中的 signedunsigned 在许多情况下比这更重要。无符号 8 位数 255 在使用二进制补码时与 -1 具有相同的位模式,但 OpenGL 将大量数据从定点整数转换为浮点数-点并且需要了解所表示的值的范围才能做到这一点......该数字可能旨在映射到浮点 1.0 或 ~ -0.0078 取决于数据类型应该是有符号还是无符号。
    猜你喜欢
    • 2011-10-21
    • 1970-01-01
    • 2017-10-01
    • 2015-01-12
    • 1970-01-01
    • 2018-04-07
    • 1970-01-01
    • 1970-01-01
    • 2014-12-06
    相关资源
    最近更新 更多