OpenGL левосторонняя система координат - PullRequest
0 голосов
/ 11 октября 2011

Я пишу 3D-приложение OpenGL, и у меня возникают проблемы с моей матрицей перевода вершин.

Вот мой вершинный шейдер:

attribute vec4     vInPos;

uniform mat4    kWorld;
uniform mat4    kProj;

void main( void )
{
    vec4 world_pos = kWorld * vInPos;
    gl_Position = kProj * world_pos;
}

Все мои матрицы хранятся в мажорной строке, и я использую левую перспективную матрицу в качестве матрицы проекции.

Проблема в том, что когда я перевожу вершину по моей матрице, она движется в неправильном направлении по осям X и Y и переворачивается. Таким образом, перевод на (100.0f,100.0f,100.0f) перемещает мою вершину в правильном направлении по оси Z (от камеры), но влево по оси X (назад) и вниз по оси Y (назад).

Вот как это выглядит в данный момент: screenshot

Счетчик FPS должен быть направлен вверх и вправо, а не вниз. Очевидно, что оно не должно отражаться. Исходя из того, что я прочитал, это происходит потому, что OpenGL по умолчанию использует правую систему координат, но я не уверен, что я могу сделать, чтобы это исправить.

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

EDIT: Для справки, мой код матрицы проекции основан на DirectX SDK .

EDIT: Согласно предложению Николя Боласа, я сейчас использую матрицу из gluPerspective , но я получаю те же результаты.


Вот код, который я использую для установки своих матриц:

/* Vertex data for reference
float vertices[] =
{
    {0.0f,0.0f,0.0f},
    {5.0f,0.0f,0.0f},
    {0.0f,5.0f,0.0f},
    {5.0f,5.0f,0.0f},
}; */    
float worldf[16];
float projf[16];
float fov       = 60.0f;
float aspect    = 1280.0f/720.0f;
float near      = 1.0f;
float far       = 1000.0f;
float f         = 1.0f/tanf( (fov*6.2831f/360.0f)/2.0f );

/* Build world matrix */
memset(worldf, 0, sizeof(worldf));
worldf[0] = worldf[5] = worldf[10] = worldf[15] = 1.0f;
worldf[12] = 100.0f;
worldf[13] = 100.0f;
worldf[14] = -100.0f;

/* Build perspective matrix */
memset(projf, 0, sizeof(projf));
projf[0] = f/aspect;
projf[5] = f;
projf[10] = (far+near)/(near-far);
projf[14] = (2.0f*far*near)/(near-far);
projf[11] = -1.0f;

glUniformMatrix4fv(proj_uniform, 1, GL_FALSE, projf);
glUniformMatrix4fv(world_uniform, 1, GL_FALSE, worldf);

При использовании этого кода мой текст вообще не отображается.

РЕДАКТИРОВАТЬ: Не уверен, что это актуально, но я использую OpenGL 2.0 на OS X Snow Leopard.

1 Ответ

1 голос
/ 11 октября 2011

Я использую левую матрицу перспективы

Хватит это делать.

Не менее важно, что вывод матрицы проекции (клип-пространство) отличается для OpenGL и D3D.Вы не можете просто взять матрицу проекции D3D, транспонировать ее и ожидать, что GLSL прекрасно примет вывод.

Итак, снова посмотрите gluPerspective и используйте эту матрицу.


Согласно предложению Николя Боласа, я сейчас использую матрицу из gluPerspective, но получаю те же результаты.

Вы, вероятно, также используетекуча других левосторонних матриц.Ваша матрица модель-к-камере должна быть правша.Кроме того, ваши данные вершин также должны быть правосторонними.В качестве альтернативы вы можете попытаться преобразовать левостороннее пространство в правостороннее, но я бы не советовал, если у вас не было другого выбора.


float f = 1.0f/tanf(fov/2.0f);

fov - это угол вградусов.tanf принимает угол в радиан .tanf из 30.0f - это отрицательное число, которое означает, что ваша шкала усечений в матрице перспективы отрицательна.Это эффективно инвертирует оси X и Y вашего взгляда.

Что вам действительно нужно, так это:

float f = 1.0f/tanf((fov * 6.2831f / 360.0f ) / 2.0f);
...