为什么这些带符号的字节被LWJGL读作无符号字节?

时间:2014-01-06 08:52:16

标签: java opengl lwjgl

当您使用LJWGL函数glBufferData()上传存储带符号字节的ByteBuffer(java lang对象)时,事实证明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等的积分值放入这个bytebuffer中,大概是带符号的字节,因为这是java处理的。因此,大概在使用带符号的解释时这些字节存储12345。那么为什么openGL读取带有无符号解释的12345而不是带符号的解释就是问题。

请注意,数据的重要性是索引缓冲区。

2 个答案:

答案 0 :(得分:1)

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

要解决此问题中的实际问题,您使用GL_UNSIGNED_BYTE来解释顶点索引,在这种情况下,数据类型的范围与值<无关紧要。 128. GL_UNSIGNED_BYTEGL_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的语言绑定将负责确定这些枚举的含义以及如何处理它们。

答案 1 :(得分:0)

有符号和无符号字节之间的主要区别在于您如何解释这些位:负值具有与超过127的值相同的位模式。您不需要两种不同类型的存储和转换(这实际上是a no-op)使用二进制补码系统自动工作。