Что не так с моим glOrtho? Отрицательный ноль вместо нуля - PullRequest
0 голосов
/ 29 марта 2012

Я реализую свою собственную матричную математику для приложения OpenGL.Пока все в основном хорошо, хотя и сложно.Моя самая последняя проблема, которую мне не очень повезло, когда я получил объяснение или указала конкретную проблему, связана с моей реализацией glOrtho ().

В частности, моя версия приводит кэлемент матрицы [14], являющийся отрицательным нулем.(-0.000000) в то время как версия, которую я glGet () из OpenGL после использования устаревшего glOrtho (), является нормальным нулем.(0.000000)

Я не знаю, влияет ли это на что-либо, но меня беспокоит, что моя математика не соответствует.

Спецификация OpenGL glOrtho, для справки, которой, я считаю, я следуюи правильно выполнять математику для: http://www.opengl.org/sdk/docs/man/xhtml/glOrtho.xml

Моя собственная функция glOrtho:

vec_t* Utils::OrthoMatrix(vec_t* out_matrix, const vec_t& left, const vec_t& right, const vec_t& bottom, const vec_t& top, const vec_t& znear, const vec_t& zfar)
{
    memcpy(out_matrix, zeroMatrix, 16*sizeof(vec_t));

    out_matrix[0] = 2.0f / (right - left);
    out_matrix[5] = 2.0f / (top - bottom);
    out_matrix[10] = -2.0f / (zfar - znear);
    out_matrix[12] = -((right + left) / (right - left));
    out_matrix[13] = -((top + bottom) / (top - bottom));
    out_matrix[14] = -((zfar + znear) / (zfar - znear));
    out_matrix[15] = 1.0f;

    return out_matrix;
}

Моя функция изменения размера (значительно уменьшена для удобства чтения):

void GameLogic::OnResize(int width, int height) // For purposes of this test, width = 640, height = 480.
{
    if(height == 0) // Avoid potential divide-by-zero
        height = 1;

    glViewport(0, 0, width, height);

    Utils::OrthoMatrix(m_orthoMatrix, 0.0f, (GLfloat)width, (GLfloat)height, 0.0f, -100.0f, 100.0f);

    // Setup fixed function OpenGL to compare against.
    glMatrixMode(GL_PROJECTION);
    glLoadIdentity();
    glOrtho(0.0f, (GLfloat)width, (GLfloat)height, 0.0f, -100.0f, 100.0f);

    glMatrixMode(GL_MODELVIEW);
    glLoadIdentity();
}
void GameLogic::Render() // Drastically cut down to illustrate issue.
{
    vec_t modelviewmatrix[16], projectionmatrix[16];
    glGetFloatv(GL_MODELVIEW_MATRIX, modelviewmatrix);

    glGetFloatv(GL_PROJECTION_MATRIX, projectionmatrix);
/*
    At this point, projectionmatrix and m_orthoMatrix are identical, 
    except in the matrix[14] element, which is 0.000000 for projectionmatrix, 
    and -0.000000 for m_orthoMatrix.
*/
}

Я не могу понять, почему это может быть, или как это повлияет?Насколько я могу судить, математика проверяется на правильность, поэтому она должна быть отрицательным нулем, но OpenGL возвращает положительный ноль.Мое лучшее предположение на данный момент - это какая-то причуда водителя, когда водитель выдумывает числа, чтобы избежать отрицательного нуля?Я тестировал этот код на двух отдельных графических процессорах nVidia и получил тот же результат.У меня нет доступа к чему-то ATI или аналогичному для тестирования.

Отказ от ответственности: я несколько не понимаю, как работают близкие и дальние значения glOrtho, хотя в спецификации указано, что отрицательные значения допустимы.

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

Есть какие-нибудь идеи, кто-нибудь, о том, что я делаю неправильно или неправильно?Или если я действительно нашел какую-то странную причуду?Было бы хорошо также объяснить, что, если вообще что-либо, использование отрицательного нуля может дать эффект, если посоветовать, что лучше всего просто пойти с ним, а не пытаться настроить значения по сравнению с тем, что я получаю в настоящее время?

Ответы [ 3 ]

3 голосов
/ 29 марта 2012

Точность с плавающей запятой внутри ЦП и ГП не обязательно одинакова, поэтому следует ожидать незначительных расхождений.

1 голос
/ 29 марта 2012

Не пытайтесь «исправить» это - ваш код работает правильно.Я думаю, что «нечетная причуда» прекрасно подходит для этого.

Добавление нуля к чему-либо, кроме нуля (что и делает умножение матриц), дает точно такой же результат;это даже не считается существенным расхождением.

И, фактически, вы должны ожидать, что столкнется с расхождениями при сравнении двух разных процедур с плавающей запятой, которые вычисляют один и тот же номинальный результат.Плавающая точка не является точной, поэтому все, что вы делаете по-другому (например, изменяя порядок добавления), скорее всего, даст немного другой результат.Следовательно, всякий раз, когда вы сравниваете результаты с плавающей запятой, вам нужно указать допуск.

0 голосов
/ 29 марта 2012

Отрицательный ноль и положительный ноль - математически идентичные значения с плавающей точкой. Они не равны , но вы получите то же самое в соответствии с IEEE-754.

Вы вообще не должны пытаться сопоставить равенство с различными вычислениями с плавающей точкой. Если вам нужно проверить свою матричную математику, то, по крайней мере, проверьте ее по диапазону (плюс или минус небольшое число).

...