OpenTK-Matrixtransformationen

Hier ist der Vertex-Shader:

uniform mat4 projection;
uniform mat4 view;
uniform mat4 model;

void main(void)
{
    gl_Position = projection * view * model * gl_Vertex;
    gl_TexCoord[0] = gl_MultiTexCoord0;
}

Meines Wissens nach wird der Modellraum mithilfe verschiedener Transformationen schließlich in Clip-Raum umgewandelt. Dabei handelt es sich um einen Rahmen, der von jeder Einheit in jeder Achse direkt auf das Ansichtsfenster gezeichnet wird, dh etwas bei (-1, 1,0) befindet sich oben links vom Ansichtsfenster. Wenn ich alle Matrixtransformationen aus dem Shader entferne,

gl_Position = gl_Vertex;

und als Modell ein einfaches Quad übergeben

public Vector3[] verts = new Vector3[] {
    new Vector3(-1f, -1f, 0),
    new Vector3(1f, -1f, 0),
    new Vector3(1f, 1f, 0),
    new Vector3(-1f, 1f, 0),
};

public Vector2[] coords = new Vector2[] {
    new Vector2(0, 1f),
    new Vector2(1f, 1f),
    new Vector2(1f, 0f),
    new Vector2(0f, 0f),
};

public uint[] indices = new uint[] {
    0,1,2,
    0,2,3,
};

Ich erhalte das erwartete Vollbild. Wenn ich die Transformationen anwende, wird das Bild wie erwartet als kleines Quadrat in der Mitte des Bildschirms angezeigt. Das Problem tritt auf, wenn ich versuche, die Position eines Scheitelpunkts des Modells in Clip-Koordinaten auf der CPU zu berechnen:

public Vector4 testMult(Vector4 v, Matrix4 m)
{
    return new Vector4(
        m.M11 * v.X + m.M12 * v.Y + m.M13 * v.Z + m.M14 * v.W,
        m.M21 * v.X + m.M22 * v.Y + m.M23 * v.Z + m.M24 * v.W,
        m.M31 * v.X + m.M32 * v.Y + m.M33 * v.Z + m.M34 * v.W,
        m.M41 * v.X + m.M42 * v.Y + m.M43 * v.Z + m.M44 * v.W);
}

Matrix4 test = (GlobalDrawer.projectionMatrix * GlobalDrawer.viewMatrix) * modelMatrix;

Vector4 testv = (new Vector4(1f, 1f, 0, 1));
Console.WriteLine("Test Input: " + testv);
Console.WriteLine("Test Output: " + Vector4.Transform(testv, test));
Vector4 testv2 = testMult(testv, test);
Console.WriteLine("Test Output: " + testv2);
Console.WriteLine("Test Output division: " + testv2 / testv2.W);

(Die übergebenen Matrizen sind identisch mit denen, die an den Shader übergeben wurden.)

Das Programm gibt dann eine Ausgabe außerhalb des Clip-Bereichs aus, und die Division durch W führt zu einer Division durch 0:

Test Input: (1, 1, 0, 1)
Test Output: (0.9053301, 1.207107, -2.031746, 0)
Test Output: (0.9053301, 1.207107, -1, 0)
Test Output division: (Infinity, Infinity, -Infinity, NaN)

Die Matrizen werden wie folgt erstellt:

projectionMatrix = Matrix4.CreatePerspectiveFieldOfView((float)Math.PI / 4, window.Width / (float)window.Height, 1.0f, 64.0f);
projectionMatrix =
(1.81066, 0, 0, 0)
(0, 2.414213, 0, 0)
(0, 0, -1.031746, -1)
(0, 0, -2.031746, 0)

viewMatrix = Matrix4.LookAt(new Vector3(0,0,4), -Vector3.UnitZ, Vector3.UnitY);
viewMatrix = 
(1, 0, 0, 0)
(0, 1, 0, 0)
(0, 0, 1, 0)
(0, 0, -4, 1)

modelMatrix = 
(0.5, 0  , 0  , 0)
(0  , 0.5, 0  , 0)
(0  , 0  , 1  , 0)
(0  , 0  , 0  , 1)

Die Frage ist also warum; Was mache ich falsch?

Antworten auf die Frage(1)

Ihre Antwort auf die Frage