我的 glOrtho 有什么问题?负零而不是零
What's wrong with my glOrtho? Negative zero instead of zero
我正在为OpenGL应用程序实现我自己的矩阵数学。到目前为止,情况基本上是好的,尽管很困难。我最近的一个问题是关于glOrtho()的实现,我很难得到解释或具体的问题。
具体来说,我的版本导致矩阵[14]元素为负零。(-0.000000),而在使用不推荐使用的glOrtho()之后,我从OpenGL获得的glGet()版本是正常的零。(0.00000)
我不知道这是否会影响事情,但我对我的数学不匹配感到不安。
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实现似乎在没有这样做的情况下运行良好,但也许就是这样?我对数学理解不够好,不知道是否应该这样做以确保正确性。
有人认为我做错了什么或误解了什么吗?或者,如果我真的发现了某种奇怪的怪癖?如果有人建议最好的方法是使用负零,而不是试图根据我目前得到的值来调整值,那么解释使用负零可能会产生什么效果也会很好?
CPU和GPU内部的浮点精度不一定相同,因此可能会出现微小差异。
不要试图"修复"它——您的代码工作正常。我觉得"怪癖"很好地掩盖了这一点。
将零与除零之外的任何东西相加(这就是矩阵乘法的作用)会产生完全相同的结果;这甚至不算是一个显著的差异。
而且,实际上,当比较计算相同标称结果的两个不同浮点过程时,您应该预计会遇到差异。浮点是不精确的,所以任何不同的操作(例如,更改加法顺序)都可能产生稍微不同的结果。因此,无论何时比较浮点结果,都需要指定公差。
负零和正零在数学上是相同的浮点值。它们不等于,但根据IEEE-754,你们会得到同样的结果。
您根本不应该试图将等式与不同的浮点计算进行匹配。如果你需要检查你的矩阵数学,那么至少要根据一个范围(加上或减去一些小数字)来测试它。
- 为不同配置设置MSVC_RUNTIME_LIBRARY的正确方法是什么
- 警告处理为错误这里有什么问题
- 什么时候调用组成单元对象的析构函数
- #定义c-预处理器常量..我做错了什么
- 努力将整数转换为链表。不知道我在这里做错了什么
- C++我的数学有什么问题,为什么我的代码不能正确循环
- 什么时候在C++中返回常量引用是个好主意
- 当在同一名称空间中有两个具有相同签名的函数时,会发生什么
- C++避免重复声明的语法是什么
- c++库的公共头文件中应该包含什么
- 问题:什么是QAbstractItemView::NoEditTriggers的反面
- 有什么方法可以遍历结构吗
- 当类在C++中定义时,有什么方法可以"register"类吗?
- ifstream什么都没读
- 在C++中,将大的无符号浮点数四舍五入为整数的最佳方法是什么
- 实现无开销push_back的最佳方法是什么
- C++从另一个类访问公共静态向量的正确方法是什么
- "throw expression code" 1e7 >返回 d 是什么?投掷标准::overflow_error( "too big" ) : d;意味 着?
- 我应该使用什么来代替void作为变体中的替代类型之一
- 我的 glOrtho 有什么问题?负零而不是零