Java 两个相同的ByteBuffer行为不同

Java 两个相同的ByteBuffer行为不同,java,lwjgl,Java,Lwjgl,我有两个ByteBuffer,它们完全相同,但在GL11.glTexImage2D()中使用时,它们的行为有所不同方法 我的代码: IntBuffer width=BufferUtils.createIntBuffer(1); IntBuffer height=BufferUtils.createIntBuffer(1); IntBuffer comp=BufferUtils.createIntBuffer(1); ByteBuffer data=STBImage.stbi_载荷(“dsc8x1

我有两个ByteBuffer,它们完全相同,但在
GL11.glTexImage2D()中使用时,它们的行为有所不同方法

我的代码:

IntBuffer width=BufferUtils.createIntBuffer(1);
IntBuffer height=BufferUtils.createIntBuffer(1);
IntBuffer comp=BufferUtils.createIntBuffer(1);
ByteBuffer data=STBImage.stbi_载荷(“dsc8x12.bmp”,宽度、高度、成分,4);
byte[]bytes=新字节[data.limit()];
for(int i=0;i
控制台输出为
true

下面是当
GL11.glTexImage2D()中的最后一个参数
data
data2

使用
数据时

使用
data2
时:

使用两个不同的ByteBuffers会得到两个不同结果的原因是LWJGL仅适用于直接NIO缓冲区,即不受阵列支持的ByteBuffers

您获得此特定输出的原因有两个:

  • 您提供的非直接字节缓冲区(由
    .wrap(array)
    创建的字节缓冲区)的内部地址字段值为
    0
    。这就是LWJGL在实际调用本机OpenGL函数时所看到的。它读取该地址字段值,并期望它是要上载到纹理的客户端内存的虚拟内存地址

  • 现在,有一些OpenGL函数在给定无效指针(如零)时会出错。然而,在这种情况下,
    glTexImage2D
    函数实际上是语义过载的,因为当它接收到作为最后一个参数的零地址时,它将只分配请求大小的纹理内存(这里是ByteBuffer的
    剩余的
    大小),而不会将任何客户端内存移动到服务器(即GPU)

  • STBImage.stbi_load
    返回的ByteBuffer是直接的,因此,来自客户端虚拟内存地址空间的正确纹理内存将上载到OpenGL


    因此,本质上:当您使用LWJGL时,必须始终只使用直接NIO缓冲区,而不是数组的包装器

    当用
    STBImage.stbi\u load(…)
    初始化
    数据时,使用的是什么
    字节顺序
    ?请记住,
    ByteBuffer#wrap
    创建了一个带有
    字节顺序的
    ByteBuffer
    ,它可能与
    数据中使用的
    字节顺序不同。为什么字节顺序与此有关。字节缓冲不是单个字节的流吗?例如,如果您试图从缓冲区中读取整数,字节顺序不是就会出现这种情况吗?我不明白字节顺序如何影响比较两个ByteBuffer对象。阅读
    ByteBuffer.equals()
    的定义,它说:“剩余元素的两个序列,独立于它们的起始位置,是逐点相等的。”我想知道“剩余元素”是什么意思。这两个缓冲区可能是非常不同的,尽管它们的“剩余元素”是相同的吗?好像他们都没有“剩余元素”。我觉得这个想法不太可能,但我觉得把它扔出去也没什么坏处。我想不出还有什么其他原因。@Steve“如果您试图(例如)从缓冲区读取整数,字节顺序不会出现这种情况吗?”-确切地说,调用
    GL11.glTexImage2D
    时可能会发生这种情况。“我看不出字节顺序会如何影响比较两个ByteBuffer对象。”-它不会,因为
    ByteBuffer#equals
    在调用
    ByteBuffer#mismatch
    @JacobG之前不会比较两个缓冲区的
    ByteBuffer
    STBImage.stbi_load(…)
    提供字节缓冲带
    LITTLE_ENDIAN
    字节顺序,我如何克隆字节缓冲带?那么我应该如何复制纹理,以便它创建一个直接缓冲区,我可以提供给OpenGL?我只需要加载一部分位图,所以我认为只复制它的一部分就可以了,但事实证明它创建了一个非直接缓冲区,那么我如何才能将它的一部分复制到直接缓冲区呢?