2012-07-12 3 views
2

Вот вершинный шейдер:OpenTK матричные преобразования

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

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

Я понимаю, что с помощью различных преобразований, модель пространства, в конечном счете превратилась в клип пространство, которое представляет собой коробку связаны каждую единицу в каждой оси обращается непосредственно окно просмотра, то есть что-то в (-1, 1,0) находится в верхнем левом углу окна просмотра. Когда я удаляю все матрицы переходит из шейдера,

gl_Position = gl_Vertex; 

и передать, как модель, простой квад

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, 
}; 

я получить ожидаемый полный экран изображение. Когда я применяю преобразования, изображение выглядит как небольшой квадрат в центре экрана, как и следовало ожидать. Проблема возникает при попытке вычислить положение вершины модели в формате координаты на CPU:

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); 

(Матрицы, передаваемые в идентичны тем, которые прошли в шейдер)

затем программа переходит, чтобы дать выход за пределы клипа пространства, и деление на W приводит к разделению на 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) 

матрицы создаются следующим образом:

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) 

Итак, вопрос в том, почему; Что я делаю не так?

+0

Не могли бы вы опубликовать, как вы создали три матрицы (проекцию, представление и модель), поскольку они очень важны при определении того, какое преобразование вы делаете. – Laar

+0

@ Laar - Я добавил это к вопросу, спасибо. – AStupidNoob

ответ

3

Редактировать (Добавление реального ответа от комментариев)

Ваших матриц OpenTK переставляются по умолчанию. Похоже, использовать векторы строк вместо векторов столбцов. Поэтому вам нужно сделать умножение как (model * view * proj), а не (proj * view * model). Либо это, либо транспонировать все матрицы перед их загрузкой.


На самом деле клип пространство не от -1 до 1, а от -W до W, где W является четвертым компонентом клипа пространственного вектора.

Что вы, вероятно, думаете о нормализованное устройство coodinates, которое колеблется от -1 до 1 на каждой оси. Вы получаете это значение, разделив координаты X, Y и Z вектора пространства клипа на W-компонент пространства клипа. Это деление называется перспективное подразделение.

Это делается за кулисами после того, как вы передадите координату пространства клипа в gl_Position.

Ваша координата пространства клипа равна 0, хотя это, по-видимому, не соответствует мне.

Здесь есть более подробная информация: OpenGL FAQ : Transformations.

+0

Спасибо. Я попробовал то, что вы предложили, и это приведет к делениям на 0, очевидно. Любые идеи, почему это может произойти?Я добавил пользовательскую матричную * векторную функцию, чтобы показать все, что я могу сделать неправильно. – AStupidNoob

+1

Можете ли вы просто пойти и опубликовать все классы Matrix4 и Vector4? Существует слишком много неизвестных функций. Также вы можете хорошо отформатировать и показать исходные значения ваших 3-х матриц (аналогично тому, как у вас есть для матрицы модели). @AStupidNoob – Tim

+0

Классы Matrix4 и Vector4 от OpenTK, поэтому они должны быть в порядке. Я добавил значения, спасибо за вашу помощь. Кроме того, я заметил, что когда я использую свою функцию для умножения матрицы и вектора, она дает тот же результат, что и встроенная функция «Vector4.Transform», когда матрица транспонирована ... – AStupidNoob