简体   繁体   English

我的glOrtho怎么了? 负零而不是零

[英]What's wrong with my glOrtho? Negative zero instead of zero

I'm implementing my own matrix math for an OpenGL application. 我正在为OpenGL应用程序实现自己的矩阵数学。 So far, things are largely fine, although difficult. 到目前为止,虽然困难,但情况基本上还不错。 My most recent issue, one I've not had much luck on getting an explanation or a specific problem pointed out to me, is to do with my implementation of glOrtho(). 我最近的问题是我对glOrtho()的实现,我对得到一种解释或向我指出的具体问题没有多大的运气。

Specifically, my version results in the matrix[14] element being negative zero. 具体来说,我的版本导致matrix [14]元素为负零。 (-0.000000) while the version that I glGet() from OpenGL after using the deprecated glOrtho() is a normal zero. (-0.000000),而我使用弃用的glOrtho()后来自OpenGL的glGet()版本是正常零。 (0.000000) (0.000000)

I don't know if this affects things any, but I am disturbed by my math not matching. 我不知道这是否会影响任何事情,但是我对数学不匹配感到不安。

glOrtho's OpenGL specification, for reference, which I believe I'm following properly, and doing the math correctly for: http://www.opengl.org/sdk/docs/man/xhtml/glOrtho.xml glOrtho的OpenGL规范,以供参考,我相信我已经正确地遵循了它,并且为以下内容正确地进行了数学运算: http : //www.opengl.org/sdk/docs/man/xhtml/glOrtho.xml

My own glOrtho function: 我自己的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;
}

My resizing function(stripped down considerably for readability): 我的调整大小功能(为便于阅读而大幅缩减):

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.
*/
}

I can't quite figure out why this could be, or what it effects? 我不太清楚为什么会这样,或者它会产生什么影响? The math checks out as correct as far as I can see, so it should be negative zero, yet OpenGL is returning positive zero. 据我所知,该数学运算正确无误,因此它应为负零,而OpenGL返回正零。 My best guess so far is some sort of driver quirk where the driver is fudging the numbers to avoid negative zero? 到目前为止,我最好的猜测是某种驾驶员怪癖,其中驾驶员正在伪造数字以避免负零? I've tested this code on two separate nVidia GPUs and gotten the same result. 我已经在两个独立的nVidia GPU上测试了此代码,并获得了相同的结果。 Don't have access to something ATI or similar to test with too. 也无权使用ATI或类似产品进行测试。

Disclaimer: I'm somewhat clueless as to how glOrtho's near and far values work, although the specification does specify that negative values are allowed. 免责声明:尽管规范确实规定允许使用负值,但我对glOrtho的近和远值如何工作一无所知。

Should I be initializing my projection matrix with an identity matrix, or multiplying an identity matrix into the perspective matrix? 我应该使用单位矩阵来初始化投影矩阵,还是将单位矩阵乘以透视矩阵? I don't...think I need to do that, and my glFrustum implementation appears to have been working okay without doing that, but maybe that's it? 我不需要...认为我需要这样做,而我的glFrustum实现似乎在不这样做的情况下就可以正常工作,但是也许就是这样吗? I don't understand the math well enough to know if that should be done for correctness or not. 我对数学不太了解,无法知道是否应该这样做以确保正确性。

Any ideas, anyone, on what I'm doing wrong or misunderstanding? 关于我做错或误解的任何想法,有人吗? Or if I've indeed found some sort of odd quirk? 或者,如果我确实发现了某种奇怪的怪癖? An explanation of what, if anything, using negative zero might effect would be good, as well, if it's advised that the best course is to just go with it, rather than try to adjust the values from what I'm currently getting? 如果建议最好的方法是仅使用它,而不是尝试根据我目前所获得的值进行调整,那么对使用负零的影响(如果有的话)的解释也是有好处的。

CPU和GPU内部的浮点精度不一定相同,因此可以预期会有很小的差异。

Don't try to "fix" it -- your code is working correctly. 不要尝试“修复”它-您的代码可以正常工作。 "Odd quirk" covers it nicely, I think. 我认为“奇怪的怪癖”很好地涵盖了它。

Adding either zero to anything other than zero (which is what matrix multiplication does) yields exactly the same result; 将零加到除零以外的任何值上(这是矩阵乘法的结果),得出的结果完全相同; this doesn't even count as a significant discrepancy. 这甚至不算是重大差异。

And, practically speaking, you should expect to encounter discrepancies when comparing two different floating point procedures that compute the same nominal result. 而且,实际上,您应该期望在比较两个计算相同标称结果的不同浮点过程时会遇到差异。 Floating point is not exact, so anything you do differently (changing the order of addition, for example) will likely yield a slightly different result. 浮点数并不精确,因此您做任何不同的操作(例如,更改加法顺序)都可能会产生稍微不同的结果。 Consequently, whenever you compare floating point results, you need to specify a tolerance. 因此,每当比较浮点结果时,都需要指定一个公差。

Negative zero and positive zero are mathematically identical floating-point values. 负零和正零在数学上是相同的浮点值。 They're not equal , but you'll get same thing according to IEEE-754. 它们不相等 ,但是根据IEEE-754,您会得到相同的结果。

You shouldn't be trying to match equality with different floating-point computations at all. 您根本不应该尝试将相等性与其他浮点计算进行匹配。 If you need to check your matrix math, then at least test it against a range (plus or minus some small number). 如果需要检查矩阵数学,则至少要针对一个范围(正负一些小数)进行测试。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM