Путаница с трансформацией пространства в OpenGL

В книге 3D-графики для игрового программирования, написанной JungHyun Han, на странице 38-39 говорится, что

матрица базового преобразования из e_1, e_2, e_3 в u,v,n введите описание изображения здесь

Однако это противоречит тому, что я знаю по линейной алгебре. Я имею в виду, не должна ли матрица базисного преобразования быть транспонированной этой матрицей?

Обратите внимание, что автор ведет свое происхождение, но я не смог найти пропущенную точку между тем, что я знаю, и тем, что делает автор.

Код: вершинный шейдер:

#version 330
layout(location = 0) in vec4 position;
layout(location = 1) in vec4 color;

uniform vec3 cameraPosition;
uniform vec3 AT;
uniform vec3 UP;
uniform mat4 worldTrans;

vec3 ep_1 = ( cameraPosition - AT )/ length(cameraPosition - AT);
vec3 ep_2 = ( cross(UP, ep_1) )/length( cross(UP, ep_1 )); 
vec3 ep_3 = cross(ep_1, ep_2);

vec4 t_ep_1 = vec4(ep_1, -1.0f);
vec4 t_ep_2 = vec4(ep_2, cameraPosition.y);
vec4 t_ep_3 = vec4(ep_3, cameraPosition.z);
mat4 viewTransform = mat4(t_ep_1, t_ep_2, t_ep_3, vec4(0.0f, 0.0f, 0.0f, 1.0f));

smooth out vec4 fragColor;
void main()
{
    gl_Position = transpose(viewTransform) * position;
    fragColor = color;
}
)glsl";

Входы:

GLuint transMat = glGetUniformLocation(m_Program.m_shaderProgram, "worldTrans");
    GLfloat dArray[16] = {0.0};
    dArray[0] = 1;
    dArray[3] = 0.5;
    dArray[5] = 1;
    dArray[7] = 0.5;
    dArray[10] = 1;
    dArray[11] = 0;
    dArray[15] = 1;
    glUniformMatrix4fv(transMat, 1, GL_TRUE, &dArray[0]);
    GLuint cameraPosId = glGetUniformLocation(m_Program.m_shaderProgram, "cameraPosition");
    GLuint ATId = glGetUniformLocation(m_Program.m_shaderProgram, "AT");
    GLuint UPId = glGetUniformLocation(m_Program.m_shaderProgram, "UP");
    const float cameraPosition[4] = {2.0f, 0.0f, 0.0f};
    const float AT[4] = {1.0f, 0.0f, 0.0f};
    const float UP[4] = {0.0f, 0.0f, 1.0f};
    glUniform3fv(cameraPosId, 1, cameraPosition);
    glUniform3fv(ATId, 1, AT);
    glUniform3fv(UPId, 1, UP);

2 ответа

Решение

По-видимому, смена базиса в векторном пространстве действительно изменяет векторы в этом векторном пространстве, и это не то, что мы хотим здесь.

Поэтому математика, которую я применял, здесь недействительна.

Чтобы понять, почему мы используем матрицу, которую я дал в этом вопросе, просмотрите этот вопрос.

Хотя верно, что вращение, масштабирование или деформация могут быть выражены матрицей 4x4 в виде введите описание изображения здесь

то, о чем вы читаете, это так называемая "трансформация вида"

Для достижения этой матрицы нам нужно два преобразования: сначала перевести в положение камеры, а затем повернуть камеру.

Данные для этих преобразований:

  • Положение камеры C (Cx,Cy,Cz)
  • Целевая позиция T (Тх, Ту, Тг)
  • Камера нормализована UP (Ux, Uy, Uz)

Перевод может быть выражен

введите описание изображения здесь

Для вращения мы определяем:
F = T – C и после нормализации мы получаем f = F / ||T-C|| также выражается f= normalize(F)
s = normalize(cross (f, UP))
u = normalize(cross(s, f))

s, u, -f являются новой осью, выраженной в старой системе координат.

Таким образом, мы можем построить матрицу вращения для этого преобразования как введите описание изображения здесь

Объединяя два преобразования в единственную матрицу, мы получаем: введите описание изображения здесь введите описание изображения здесь

Обратите внимание, что система осей является той, что используется OpenGL, где -f= cross(s,u),

Теперь, сравнивая с вашим кодом GLSL, я вижу:

  1. Ваш f (ep_1) вектор идет в противоположном направлении.
  2. s (ep_2) вектор рассчитывается как cross(UP, f) вместо cross(f, UP), Это правильно, из-за 1).
  3. То же самое для u (Ep_3).
  4. Здание V ячейка (0,0) неверна. Он пытается установить правильное направление с помощью этого -1.0f,
  5. Для других ячеек (компоненты t_ep_J) используется положение камеры. Но вы забыли использовать скалярное произведение с s,u,f,
  6. Инициализатор GLSL mat4(c1,c2,c3,c4) требует вектор-столбца в качестве параметров. Вы прошли ряды-столбцы. Но после main использование transpose исправляет это.

Кстати, вы не собираетесь вычислять матрицу для каждой вершины, времени, времени и времени... верно? Лучше рассчитать его на стороне процессора и передать if (в порядке столбцов) как униформу.

Другие вопросы по тегам