【发布时间】:2020-04-20 16:22:43
【问题描述】:
我创建了一个正交投影相机,用于我的简单 opengl 2d 渲染器。 目前我遇到的问题是,当我在着色器上计算它们时,计算出的标准化设备坐标是错误的,但是当我在 cpu 上计算它们时,我得到了想要的结果。
我使用以下公式创建了一个正交投影矩阵:
2 / (right - left), 0, 0, -((right + left) / (right - left)),
0, 2 / (top - bottom), 0, -((top + bottom) / (top - bottom)),
0, 0, -2 / (zFar - zNear), -((zFar + zNear) / (zFar - zNear)),
0, 0, 0, 1
其中右 = 1280,左 = 0,上 = 0,下 = 720,zFar = 1.0 和 zNear = -1.0。
如果我要使用以下顶点位置创建一个矩形:
float vertices[5 * 4] = {
//vertex pos tex pos
0.0f, 720.0f, 0.0f, 0.0f, 0.0f, //bottom left
1280.0f, 720.0f, 0.0f, 1.0f, 0.0f, //bottom right
1280.0f, 0.0f, 0.0f, 1.0f, 1.0f, //top right
0.0f, 0.0f, 0.0f, 0.0f, 1.0f // top left
};
它应该会导致一个矩形填满整个屏幕。
要计算标准化设备坐标,我使用以下公式:
ViewProjectionMatrix * Transform * Position
在顶点着色器中是这样的:
layout(location = 0) in vec3 a_Position;
layout(location = 1) in vec2 a_TexCoord;
uniform mat4 u_ViewProjection;
uniform mat4 u_Transform;
uniform vec4 position;
out vec2 v_TexCoord;
void main()
{
v_TexCoord = a_TexCoord;
gl_Position = u_ViewProjection * u_Transform * vec4(a_Position, 1.0);
}
u_ViewProjection 是上面提到的 ViewProjection 矩阵,u_Transform 是一个变换矩阵,在这种情况下是一个简单的 Identity 矩阵,a_Position 是顶点位置。
现在,如果我使用以下代码在 cpu 上进行计算:
Mat4x4f transform = Mat4x4f::translate(Mat4x4f(1.0f), Vector3f(0.0f, 0.0f, 0.0f)) *
Mat4x4f::scale(Vector3f(1.0f, 1.0f, 1.0f));
// ViewProjectionMatrix * Transform * Position
Vector4f tl = camera.getViewProjectionMatrix() * transform * Vector4f(0.0f, 0.0f, 0.0f, 1.0f);
该变换与传递给 u_Transform 的变换相同,并且与传递给 u_ViewProjection 的 camera.getViewProjectionMatrix 相同。
这里我得到了想要的结果:x = -1.0, y = 1.0 这应该是屏幕的左上角。
所以我的问题... 我在着色器中做错了什么还是其他原因导致了这种情况?
编辑 1 正如在接受的答案中所说,需要转置投影矩阵,我使用以下来源来到这个矩阵:https://www.scratchapixel.com/lessons/3d-basic-rendering/perspective-and-orthographic-projection-matrix/orthographic-projection-matrix。 不幸的是,他们在这里显示的图像暗示它是列专业的,而实际上是行专业的,请参见下面的屏幕截图:
【问题讨论】:
-
您没有提供足够的信息,但可能您必须转置矩阵。请注意,OpenGL 矩阵按列主要顺序存储。
-
您对 CPU 实现的看法分歧在哪里?
标签: c++ opengl matrix glsl shader