我正在为OpenGL应用程序实现自己的矩阵数学。到目前为止,事情基本上很好,虽然很难。我最近的一个问题,就是我得到解释或特定问题并没有太多运气,这与我的glOrtho()的实现有关。
具体来说,我的版本导致矩阵[14]元素为负零。 (-0.000000)虽然使用不推荐的glOrtho()后来自OpenGL的glGet()版本是正常零。 (0.000000)
我不知道这是否会影响到任何事情,但我对数学不匹配感到不安。
glOrtho的OpenGL规范,供参考,我相信我已经正确遵循,并正确地进行数学运算: 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 GPU上测试了这段代码并获得了相同的结果。无法访问ATI或类似的内容以进行测试。
免责声明:尽管规范确实指明允许使用负值,但我对glOrtho的近端值和远值的工作原理有点无能为力。
我应该使用单位矩阵初始化我的投影矩阵,还是将单位矩阵乘以透视矩阵?我不......认为我需要这样做,而且我的glFrustum实现似乎没有这样做,但也许就是这样吗?我不太了解数学,不知道是否应该为了正确性而做。
任何想法,任何人,我做错了什么或误解?或者,如果我确实发现了某种奇怪的怪癖?如果使用负零可能会产生什么影响的解释可能会很好,如果建议最好的方法就是采用它,而不是试图调整我目前得到的值? / p>
答案 0 :(得分:3)
CPU和GPU内部的浮点精度并不一定相同,因此预计会出现很小的差异。
答案 1 :(得分:1)
不要试图“修复”它 - 你的代码工作正常。我想,“奇怪的怪癖”很好地涵盖了它。
将零添加到零以外的任何值(这是矩阵乘法所做的)会产生完全相同的结果;这甚至不算是一个显着的差异。
而且,实际上,在比较计算相同标称结果的两个不同浮点过程时,您应该期望遇到差异。浮点不精确,所以你做的不同(例如改变加法顺序)可能会产生略微不同的结果。因此,无论何时比较浮点结果,都需要指定容差。
答案 2 :(得分:0)
负零和正零在数学上是相同的浮点值。他们不是相等,但根据IEEE-754,你会得到同样的东西。
您根本不应该尝试使用不同的浮点计算来匹配相等性。如果你需要检查矩阵数学,那么至少要测试一个范围(加上或减去一些小数字)。