为什么这个图像不是水平渐变?

Why this image is not an horizontal gradient?

这个问题不是我的问题,而是我们为什么会得到这个结果的问题。 此图像生成渲染两个立方体,使用此着色器:

片段:


uniform mat4 u_ModelMatrix;
uniform mat4 u_ViewMatrix;
uniform mat4 u_ProjectionMatrix;

in FS {
    vec4 pos;
} fs;

out vec4 out_Color;

void main()
{
    out_Color.rgb = vec3(u_ProjectionMatrix * u_ViewMatrix * fs.pos).xxx;
}

顶点:

layout (location = 0) in vec4 in_Pos;

uniform mat4 u_ModelMatrix;
uniform mat4 u_ViewMatrix;
uniform mat4 u_ProjectionMatrix;

out FS {
    vec4 pos;
} fs;

void main()
{
    fs.pos = u_ModelMatrix * in_Pos;
    gl_Position = u_ProjectionMatrix * u_ViewMatrix * worldPos;
}

我的理解是,当我们通过乘以 MVP 得到 projected 片段坐标时,我们应该 vec3(u_ProjectionMatrix * u_ViewMatrix * fs.pos) 等于到 X 和 Y 的 window 屏幕,等于 Z 的深度。因此,使用 xxx 作为 rgb 应该显示绘制模型的水平渐变,中心全黑window(右边是负 X)和右边的全白。这是全局结果,但颜色不仅仅取决于 X,因为我们可以看到图像中的垂直线具有不同颜色的像素。为什么会这样?

投影矩阵将输入转换为剪辑 space。 Clip space 是齐次 space(实际上是射影 P^3 space),并且不保证轴上有任何边界。对于剪辑 space 中可见的任何点,x、y、z 轴必须小于 w 分量。

如果您需要 space 中的点,其中所有坐标都在 [-1,1] 范围内,您必须通过将剪辑 space 坐标除以 w 坐标来均化剪辑坐标。

... we should have vec3(u_ProjectionMatrix * u_ViewMatrix * fs.pos) equals to the window screen in X and Y and equals to the depth in Z:

NDC = clipSpace.xyz / clipSpace.w;

这既不适用于剪辑 space 也不适用于 NDC space true,要获得屏幕坐标,必须执行视口变换,基本上变换 [-1, 1] space 到 [0, 宽度](或 [0, 高度])space。为此,您必须执行以下计算:

windowSpace = (NDC.xy + 1.0) * ([width, height] / 2.0)