【问题标题】:Precision loss with unprojecting and reprojecting不投影和重投影的精度损失
【发布时间】:2011-08-26 00:36:48
【问题描述】:

我正在实施阴影映射技术的变体,但我(认为)正在遭受精度损失。

这是我的工作:

  • 我从眼睛位置绘制场景以填充深度缓冲区
  • 我使用 gluUnproject 取消投影这些点
  • 我使用 gluProject 将光源中的这些点重新投影为视点
  • 然后我遍历所有三角形,将它们从我的光源投射为视点

-> 对于与三角形重叠的点(从第一步开始),我比较深度。我将三角形像素处的插值深度与我在步骤 2 中重新投影的深度进行比较,如果三角形更接近,则将其映射到阴影中。

我使用重心坐标在不规则位置插入深度。这意味着将三个浮点值与零进行比较,比较两个浮点值以查看哪个更小,.. 我对所有比较都使用了偏差,没有任何大的影响(eps = 0.00001)

该算法运行良好,但我仍然有一些伪影,我认为这些可以归因于联合国和重新投影。可以吗?

我正在使用透视投影,近 = 1.0,远 = 20.0。 我可以做些什么来改善这一点?

我很乐意展示一些代码,但数量很多。那么让我们先看看有哪些建议。

Artifact http://img849.imageshack.us/img849/4420/artifactk.png

我以这种方式读取像素并取消投影:

//Get the original pixels
glBindBufferARB(GL_PIXEL_PACK_BUFFER_ARB, pboIds[0]);
glReadPixels( 0, 0,800, 300, GL_DEPTH_COMPONENT,GL_FLOAT, BUFFER_OFFSET(0));

glBindBufferARB(GL_PIXEL_PACK_BUFFER_ARB, pboIds[1]);
glReadPixels( 0, 300, 800, 300, GL_DEPTH_COMPONENT,GL_FLOAT, BUFFER_OFFSET(0));

//Process the first batch of pixels
glBindBufferARB(GL_PIXEL_PACK_BUFFER_ARB, pboIds[0]);   
GLfloat *pixels1 = (GLfloat*)glMapBufferARB(GL_PIXEL_PACK_BUFFER, GL_READ_ONLY);
processPixels( pixels1, lightPoints, modelview, projection, viewport, 0);

//Process the second batch of pixels
glBindBufferARB(GL_PIXEL_PACK_BUFFER_ARB, pboIds[1]);
GLfloat *pixels2 = (GLfloat*)glMapBufferARB(GL_PIXEL_PACK_BUFFER, GL_READ_ONLY);
processPixels( pixels2, lightPoints, modelview, projection, viewport, 1);

//Unamp buffers and restore default buffer
glBindBufferARB(GL_PIXEL_PACK_BUFFER_EXT, pboIds[0]);
glUnmapBuffer(GL_PIXEL_PACK_BUFFER);

glBindBufferARB(GL_PIXEL_PACK_BUFFER_EXT, pboIds[1]);
glUnmapBufferARB(GL_PIXEL_PACK_BUFFER);

glBindBufferARB(GL_PIXEL_PACK_BUFFER_ARB, 0);

//Projecting the original points to lightspace
glLoadIdentity();   
gluLookAt( light_position[0], light_position[1], light_position[2], 0.0,0.0,0.0,0.0,1.0,0.0);

//We get the new modelview matrix - Lightspace
glGetDoublev( GL_MODELVIEW_MATRIX, modelview );

//std::cout <<"Reprojecting" << std::endl;
GLdouble winX, winY, winZ;
Vertex temp;
//Projecting the points into lightspace and saving the sample points
for(vector<Vertex>::iterator vertex = lightPoints.begin(); vertex != lightPoints.end(); ++vertex){
    gluProject( vertex->x, vertex->y, vertex->z,modelview, projection, viewport, &winX, &winY, &winZ );
    temp.x = winX;
    temp.y = winY;
    temp.z = winZ;
//  std::cout << winX << " " << winY << " " << winZ << std::endl;
    samplePoints.push_back(temp);
}

我的深度缓冲区是 24 位,我无法更改 afaik(ATI Radeon HD4570,我正在使用 GLUT)。

我比较我的深度:

if(rasterizer.interpolateDepth(A, B, C, baryc) < sample->z - 0.00001*sample->z){
                stencilBits[(((int)sample->y*800 +(int)sample->x )) ] = 1;

两者都是花车。

floats 应该足够精确,顺便说一句,在我的论文中,我基于他们也使用 floats。 }

【问题讨论】:

  • 你如何比较你的花车?
  • 你能打印出反投影前后矩阵中的值吗?应该可以看出它们丢失了多少精度。
  • 让我确定我理解你的算法。你渲染场景。然后,您将深度缓冲区读回 CPU。然后,对于每个像素,调用 gluUnproject。然后,您使用不同的投影矩阵调用 gluProject。如果那是您的算法(我希望不是),那么我们需要看看您是如何读取深度缓冲区的。但最终,我看不出这实际上是如何工作的。
  • 为什么不呢?它实际上是一些学术论文的主题。它被称为不规则 Z 缓冲。稍后我将发布编辑,提供更多信息。我正在使用 PBO 和 readpixels 读取我的深度缓冲区。我把它们读成花车。是的,我可以将它们读取为 int,但我必须稍后将它们转换回浮点数,所以我认为这并不重要。

标签: c++ opengl 3d


【解决方案1】:

试着把远方飞机放在更远的地方:http://www.codermind.com/files/small_wnear.gif

【讨论】:

    【解决方案2】:

    几个建议: - 首先实现没有 cpu 的常规阴影映射 - 非常非常仔细地阅读 opengl 管道数学并确保一切正确,包括四舍五入 - 你说插值深度。这听起来很错误 - 你不能按原样线性插值深度(你可以深度平方,但我认为你没有这样做)

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2018-08-06
      • 2019-02-11
      • 2012-08-03
      • 2012-05-20
      • 2020-08-30
      • 2016-10-20
      • 2013-11-26
      • 2021-06-19
      相关资源
      最近更新 更多