视图和投影矩阵不起作用
View & Projection Matrices are not working
我正在尝试在我的引擎中实施 MVP 矩阵。
我的模型矩阵工作正常,但我的视图和投影矩阵不起作用。
这是两者的创建:
public void calculateProjectionMatrix() {
final float aspect = Display.getDisplayWidth() / Display.getDisplayHeight();
final float y_scale = (float) ((1f / Math.tan(Math.toRadians(FOV / 2f))) * aspect);
final float x_scale = y_scale / aspect;
final float frustum_length = FAR_PLANE - NEAR_PLANE;
proj.identity();
proj._m00(x_scale);
proj._m11(y_scale);
proj._m22(-((FAR_PLANE + NEAR_PLANE) / frustum_length));
proj._m23(-1);
proj._m32(-((2 * NEAR_PLANE * FAR_PLANE) / frustum_length));
proj._m33(0);
}
public void calculateViewMatrix() {
view.identity();
view.rotate((float) Math.toRadians(rot.x), Mathf.xRot);
view.rotate((float) Math.toRadians(rot.y), Mathf.yRot);
view.rotate((float) Math.toRadians(rot.z), Mathf.zRot);
view.translate(new Vector3f(pos).mul(-1));
System.out.println(view);
}
我要渲染的顶点是:
-0.5f, 0.5f, -1.0f,
-0.5f, -0.5f, -1.0f,
0.5f, -0.5f, -1.0f,
0.5f, 0.5f, -1.0f
我在上传到着色器之前测试了视图矩阵,它是正确的。
我是这样渲染的:
ss.bind();
glEnableVertexAttribArray(0);
glEnableVertexAttribArray(1);
glEnableVertexAttribArray(2);
ss.loadViewProjection(cam);
ss.loadModelMatrix(Mathf.transformation(new Vector3f(0, 0, 0), new Vector3f(), new Vector3f(1)));
ss.connectTextureUnits();
glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0);
glDisableVertexAttribArray(0);
glDisableVertexAttribArray(1);
glDisableVertexAttribArray(2);
ss.unbind();
顶点着色器:
#version 330 core
layout(location = 0) in vec3 i_position;
layout(location = 1) in vec2 i_texCoord;
layout(location = 2) in vec3 i_normal;
out vec2 p_texCoord;
uniform mat4 u_proj;
uniform mat4 u_view;
uniform mat4 u_model;
void main() {
gl_Position = u_proj * u_view * u_model * vec4(i_position, 1.0);
p_texCoord = i_texCoord;
}
几何必须放在 Viewing frustum 中。视锥之外的所有几何体都被剪裁为非 "visible".
几何图形必须位于 NEAR_PLANE
和 FAR_PLANE
之间。注意,透视投影 NEAR_PLANE
和 FAR_PLANE
必须大于 0:
0 < NEAR_PLANE < FAR_PLANE
请注意,在视图 space 中,z 轴指向视口之外。查看对象的初始视图矩阵可以定义为:
pos = new Vector3f(0, 0, (NEAR_PLANE + FAR_PLANE)/2f );
rot = new Vector3f(0, 0, 0);
注意,如果到FAR_PLANE
的距离很远,那么物体可能很小,几乎看不见。在这种情况下更改初始值:
pos = new Vector3f(0, 0, NEAR_PLANE * 0.99f + FAR_PLANE * 0.01f );
rot = new Vector3f(0, 0, 0);
虽然@Rabbid76 的回答在一般情况下当然是完全正确的,但在这种情况下的实际问题是糟糕的 API 设计(在 JOML 的情况下)和不阅读 Java使用方法的文档。
特别是 Matrix4f._mNN() 方法仅设置相应的矩阵字段,但省略了重新评估内部存储的矩阵属性,以便 accelerate/route 进一步矩阵运算(最显着的是乘法)到更优化的方法时知道关于矩阵的属性,例如 "is it identity"、"does it only represent translation"、"is it a perspective projection"、"is it affine"、"is it orthonormal" 等...
这是 JOML 在大多数情况下应用的优化,可显着提高矩阵乘法的性能。
至于糟糕的 API 设计:这些方法只是 public 以便 class org.joml.internal.MemUtil
访问它们以设置从 NIO 缓冲区读取的矩阵元素。由于 Java 还没有朋友 classes,因此这些 _mNN() 方法一定是 public。然而,它们不适合 public/client 使用。
I've changed this now 和下一个 JOML 版本 1.9.21 将不再公开它们。
为了仍然显式地设置矩阵字段(在大多数情况下不需要像这里这样)仍然可以使用 mNN() 方法,它执行 reevaluate/weaken 矩阵属性以使所有进一步的操作仍然正确,尽管可能非最优。
所以这种情况下的问题实际上是:JOML 仍然认为手动创建的透视投影矩阵是单位矩阵,并且假设是这样会缩短进一步的矩阵乘法。
所以我尝试了一切,发现你不应该将统一位置初始化为 0。
在扩展 ShaderProgram class 的 class 中,我有:
private int l_TextureSampler = 0;
private int l_ProjectionMatrix = 0;
private int l_ViewMatrix = 0;
private int l_ModelMatrix = 0;
改成这样:
private int l_TextureSampler;
private int l_ProjectionMatrix;
private int l_ViewMatrix;
private int l_ModelMatrix;
对我有用。
我正在尝试在我的引擎中实施 MVP 矩阵。 我的模型矩阵工作正常,但我的视图和投影矩阵不起作用。 这是两者的创建:
public void calculateProjectionMatrix() {
final float aspect = Display.getDisplayWidth() / Display.getDisplayHeight();
final float y_scale = (float) ((1f / Math.tan(Math.toRadians(FOV / 2f))) * aspect);
final float x_scale = y_scale / aspect;
final float frustum_length = FAR_PLANE - NEAR_PLANE;
proj.identity();
proj._m00(x_scale);
proj._m11(y_scale);
proj._m22(-((FAR_PLANE + NEAR_PLANE) / frustum_length));
proj._m23(-1);
proj._m32(-((2 * NEAR_PLANE * FAR_PLANE) / frustum_length));
proj._m33(0);
}
public void calculateViewMatrix() {
view.identity();
view.rotate((float) Math.toRadians(rot.x), Mathf.xRot);
view.rotate((float) Math.toRadians(rot.y), Mathf.yRot);
view.rotate((float) Math.toRadians(rot.z), Mathf.zRot);
view.translate(new Vector3f(pos).mul(-1));
System.out.println(view);
}
我要渲染的顶点是: -0.5f, 0.5f, -1.0f, -0.5f, -0.5f, -1.0f, 0.5f, -0.5f, -1.0f, 0.5f, 0.5f, -1.0f
我在上传到着色器之前测试了视图矩阵,它是正确的。
我是这样渲染的:
ss.bind();
glEnableVertexAttribArray(0);
glEnableVertexAttribArray(1);
glEnableVertexAttribArray(2);
ss.loadViewProjection(cam);
ss.loadModelMatrix(Mathf.transformation(new Vector3f(0, 0, 0), new Vector3f(), new Vector3f(1)));
ss.connectTextureUnits();
glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0);
glDisableVertexAttribArray(0);
glDisableVertexAttribArray(1);
glDisableVertexAttribArray(2);
ss.unbind();
顶点着色器:
#version 330 core
layout(location = 0) in vec3 i_position;
layout(location = 1) in vec2 i_texCoord;
layout(location = 2) in vec3 i_normal;
out vec2 p_texCoord;
uniform mat4 u_proj;
uniform mat4 u_view;
uniform mat4 u_model;
void main() {
gl_Position = u_proj * u_view * u_model * vec4(i_position, 1.0);
p_texCoord = i_texCoord;
}
几何必须放在 Viewing frustum 中。视锥之外的所有几何体都被剪裁为非 "visible".
几何图形必须位于 NEAR_PLANE
和 FAR_PLANE
之间。注意,透视投影 NEAR_PLANE
和 FAR_PLANE
必须大于 0:
0 < NEAR_PLANE < FAR_PLANE
请注意,在视图 space 中,z 轴指向视口之外。查看对象的初始视图矩阵可以定义为:
pos = new Vector3f(0, 0, (NEAR_PLANE + FAR_PLANE)/2f );
rot = new Vector3f(0, 0, 0);
注意,如果到FAR_PLANE
的距离很远,那么物体可能很小,几乎看不见。在这种情况下更改初始值:
pos = new Vector3f(0, 0, NEAR_PLANE * 0.99f + FAR_PLANE * 0.01f );
rot = new Vector3f(0, 0, 0);
虽然@Rabbid76 的回答在一般情况下当然是完全正确的,但在这种情况下的实际问题是糟糕的 API 设计(在 JOML 的情况下)和不阅读 Java使用方法的文档。
特别是 Matrix4f._mNN() 方法仅设置相应的矩阵字段,但省略了重新评估内部存储的矩阵属性,以便 accelerate/route 进一步矩阵运算(最显着的是乘法)到更优化的方法时知道关于矩阵的属性,例如 "is it identity"、"does it only represent translation"、"is it a perspective projection"、"is it affine"、"is it orthonormal" 等... 这是 JOML 在大多数情况下应用的优化,可显着提高矩阵乘法的性能。
至于糟糕的 API 设计:这些方法只是 public 以便 class org.joml.internal.MemUtil
访问它们以设置从 NIO 缓冲区读取的矩阵元素。由于 Java 还没有朋友 classes,因此这些 _mNN() 方法一定是 public。然而,它们不适合 public/client 使用。
I've changed this now 和下一个 JOML 版本 1.9.21 将不再公开它们。 为了仍然显式地设置矩阵字段(在大多数情况下不需要像这里这样)仍然可以使用 mNN() 方法,它执行 reevaluate/weaken 矩阵属性以使所有进一步的操作仍然正确,尽管可能非最优。
所以这种情况下的问题实际上是:JOML 仍然认为手动创建的透视投影矩阵是单位矩阵,并且假设是这样会缩短进一步的矩阵乘法。
所以我尝试了一切,发现你不应该将统一位置初始化为 0。 在扩展 ShaderProgram class 的 class 中,我有:
private int l_TextureSampler = 0;
private int l_ProjectionMatrix = 0;
private int l_ViewMatrix = 0;
private int l_ModelMatrix = 0;
改成这样:
private int l_TextureSampler;
private int l_ProjectionMatrix;
private int l_ViewMatrix;
private int l_ModelMatrix;
对我有用。