gpt4 book ai didi

c++ - 在着色器上计算标准化设备坐标会显示与在 cpu 上计算不同的结果

转载 作者:行者123 更新时间:2023-12-01 17:57:28 29 4
gpt4 key购买 nike

我创建了一个正交投影相机,用于我的简单 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 是一个变换矩阵,在本例中是一个简单的单位矩阵,a_Position 是顶点位置。

使用上述值会产生以下渲染结果: Image of render showing triangle

现在,如果我使用以下代码在 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 。不幸的是,他们在这里显示的图像暗示它是列主,而实际上是行主,请参见下面的屏幕截图: screenshot

最佳答案

您必须转置矩阵,因为 OpenGL 矩阵按列优先顺序存储。

参见The OpenGL Shading Language 4.6, 5.4.2 Vector and Matrix Constructors ,第 108 页:

To initialize a matrix by specifying vectors or scalars, the components are assigned to the matrix elements in column-major order:

mat4(float, float, float, float,  // first column
float, float, float, float, // second column
float, float, float, float, // third column
float, float, float, float); // fourth column

4*4 OpenGL矩阵的内存图像

  c0  c1  c2  c3            c0  c1  c2  c3
[ Xx Yx Zx Tx ] [ 0 4 8 12 ]
[ Xy Yy Zy Ty ] [ 1 5 9 13 ]
[ Xz Yz Zz Tz ] [ 2 6 10 14 ]
[ 0 0 0 1 ] [ 3 7 11 15 ]

看起来像这样:

[ Xx, Xy, Xz, 0, Yx, Yy, Yz, 0, Zx, Zy, Zz, 0, Tx, Ty, Tz, 1 ]

所以 View 矩阵必须是

2 / (right - left), 0,                  0,                   0,
0, 2 / (top - bottom), 0, 0,
0, 0, -2 / (zFar - zNear), 0,
-((right + left) / (right - left)), -((top + bottom) / (top - bottom)), -((zFar + zNear) / (zFar - zNear)), 1
<小时/>

另一个选项是反转顶点着色器中的乘法顺序:

gl_Position = vec4(a_Position, 1.0) * u_Transform * u_ViewProjection;

参见GLSL Programming/Vector and Matrix Operations :

If a vector is multiplied to a matrix from the left, the result corresponds to multiplying a row vector from the left to the matrix. This corresponds to multiplying a column vector to the transposed matrix from the right:

关于c++ - 在着色器上计算标准化设备坐标会显示与在 cpu 上计算不同的结果,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59555952/

29 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com