我有一个小项目,它是用LWJGL2编写的,现在想转到版本3。我更改了主库,没有遇到更大的问题。但要循序渐进。所以我首先没有对Vector和Matrix类做任何更改。相反,在新项目中,我添加了旧的lwjgl_util.jar。我可以将所有内容渲染为正常。到目前为止,我唯一的损失是键盘和鼠标的输入,但这不是什么大问题。
下一步也是关键的一步是再次删除额外的.jar文件,并将所有导入更改为org.com.l.Vector2f、org.com.l.Vector2f和org.com.l.Matrix4f类,以及我的代码中所需的更改。Eclipse表示不再有错误,JVM也是如此。
如果我打印矢量或矩阵,代码就会运行。他们都有应该有的数据。
但是,它应该渲染的不是正常的世界,而是只有清晰的背景颜色(顺便说一句,正确的颜色(
我的想法是,我没有从Java获得任何数据到着色器,着色器将所有矩阵相乘为零,我看不到任何东西。
我在上找到了这条线https://github.com/JOML-CI/JOML/wiki/Migrating-from-LWJGL-2我知道这可能是我的问题,但我不明白它的确切含义:
一个重要的区别是从FloatBuffer获取值或将值写入FloatBuffer时对NIO Float缓冲区的处理。在LWJGL 2中,FloatBuffer的位置将通过加载和存储操作递增。在JOML中,位置不会改变!
所以我现在的问题是:
如何在不改变位置的情况下处理浮动缓冲器?
public abstract class ShaderProgram {
private static FloatBuffer matrixBuffer = BufferUtils.createFloatBuffer(16);
...
protected void loadMatrix(int location, Matrix4f matrix) {
matrix.get(matrixBuffer);
matrixBuffer.flip();
GL20.glUniformMatrix4fv(location, false, matrixBuffer);
}
}
tl;dr
删除对matrixBuffer.flip()
的调用
更长的解释
要知道你的代码为什么不起作用,你需要知道Buffer.flip()
(通过你的FloatBuffer.flip()
调用(到底做了什么:
翻转此缓冲区。限制设置为当前位置,然后位置设置为零。如果定义了标记,则会将其丢弃。
(我用粗体突出显示(。
你知道,NIO缓冲区有一个位置、标记、限制和容量。当您创建一个新的NIO缓冲区时,例如通过BufferUtils.createFloatBuffer(size)
,您将获得一个FloatBuffer
,它是底层直接ByteBuffer
的视图,其容量为size
,限制为size
,位置为0
,并且没有标记集。
通常,JDK中的relativeNIO Buffer put操作会增加缓冲区的位置。然而,JOML的Matrix/Vector.get(Buffer)
不会做到这一点,就像所有以NIO缓冲区为参数的LWJGL/OpenGL方法一样,比如GL15.glBufferData(...)
。
因此,当您调用Matrix4f.get(FloatBuffer)
时,所提供的缓冲区的位置将不会被修改,因此,之后在该缓冲区上调用.flip()
将把缓冲区的limit
设置为缓冲区位置所在的位置(可能是0
(。
接下来需要知道的是,采用NIO缓冲区的LWJGL方法将使用缓冲区的.remaining()
(即.limit() - .position()
(来确定底层本机OpenGL函数调用的任何大小/长度参数的参数值。在具有本机签名的glUniformMatrix4fv()
的情况下:
void glUniformMatrix4fv(GLint位置、GLsizei计数、GLboolean转置、常量GLfloat*值(;
LWJGL将根据提供的NIO缓冲区的.remaining() / 16
推断count
参数的值。由于您的缓冲区可能有.remaining()
对于0
(由于当所述缓冲器具有0
的位置时的.flip()
调用-由于Matrix4f.get(FloatBuffer)
没有增加该位置(,所提供的OpenGL函数自变量将是0
,这将在这种情况下引起noop。