2016-11-30 73 views
0

据我所知的屏幕空间,在OpenGL多边形通常被限幅在裁剪空间和仅那些三角形(或三角形的部分,如果限幅处理拆分它们)存活与+的比较 - 瓦特然后这需要实施诸如Sutherland-Hodgman的多边形裁剪算法。裁剪三角形每像素

我实现我自己的CPU光栅化现在想避免这样做。我有可用顶点的NDC坐标(不是真的归一化了,因为我没有剪取任何东西,所以位置可能不在范围[-1,1]中)。我想为所有像素插值这些值,并且只绘制NDC坐标在x,y和z维度中落入[-1,1]范围内的像素。然后我会另外进行深度测试。

会这样吗?如果是,插值看起来像什么?我可以如here所述使用OpenGl spec(p。429 14.9)属性插值公式吗?或者,我应该使用公式14.10,它用于所有3个坐标的深度(z)插值(我不明白为什么在那里使用不同的坐标)?

更新: 我试图通过两种方法插每个像素的NDC值:

w0, w1, w2是顶点的重心权重。

1)float x_ndc = w0 * v0_NDC.x + w1 * v1_NDC.x + w2 * v2_NDC.x; float y_ndc = w0 * v0_NDC.y + w1 * v1_NDC.y + w2 * v2_NDC.y; float z_ndc = w0 * v0_NDC.z + w1 * v1_NDC.z + w2 * v2_NDC.z;

2) float x_ndc = (w0*v0_NDC.x/v0_NDC.w + w1*v1_NDC.x/v1_NDC.w + w2*v2_NDC.x/v2_NDC.w)/ (w0/v0_NDC.w + w1/v1_NDC.w + w2/v2_NDC.w); float y_ndc = (w0*v0_NDC.y/v0_NDC.w + w1*v1_NDC.y/v1_NDC.w + w2*v2_NDC.y/v2_NDC.w)/ (w0/v0_NDC.w + w1/w1_NDC.w + w2/v2_NDC.w); float z_ndc = w0 * v0_NDC.z + w1 * v1_NDC.z + w2 * v2_NDC.z;

的修剪+深度测试总是看起来像这样:

if (-1.0f < z_ndc && z_ndc < 1.0f && z_ndc < currentDepth && 1.0f < y_ndc && y_ndc < 1.0f && -1.0f < x_ndc && x_ndc < 1.0f)

情况1)对应于利用方程14.10为其内插。情况2)对应于使用等式14.9进行插值。

结果documented in gifs on imgur. 1)奇怪的事情发生在第二个立方体在相机后面或者当我进入立方体时。 2)奇怪的工件不可见,但随着相机接近顶点,它们开始消失。并且由于这是perspective correct interpolation of attributes顶点(靠近摄像机?)具有更大的权重,所以一旦顶点被剪切,该信息就会以强大的权重插入到三角形像素中。

是这一切的预期或有我做错了什么?

+1

我不知道你在这里执行什么。正如Nicol Bolas已经指出的那样,如果任何基元与'z_eye = 0'平面相交,剪切就非常重要。并且对这些基元的插值将变得完全没有意义(对于某些顶点,在'z_eye = 0'时,甚至最终会以零除除)。在NDC中检查'-1 <= x,y,z <= 1'不等于剪辑空间中的-w <= x,y,z <= w',因为符合'w <= x, y,z,<= -w'(在相机后面)也可以实现。我不知道'NDC.w'是什么意思,因为在NDC中,没有w(或者它是1)。 – derhass

+1

总结:在我看来,剪切屏幕空间并没有丝毫的意义(你可以在同质坐标系下进行光栅化)(http://www.cs.unc.edu/~olano/papers/2dh-tri /)),它会慢很多。所以我不知道你在这里获得了什么。 – derhass

+0

感谢澄清derhass。我没有正确理解尼科尔的回答(我认为他的意思是即使在裁剪z_eye = 0的情况下,数学也可以工作)。在我的代码中,我使用NDC.w作为顶点的相机空间z。无可否认,这在透视分裂后没有意义。 – pseudomarvin

回答

2

除非三角形在摄像机空间Z中达到或超过0,否则不要紧靠近平面进行剪切。一旦出现这种情况,齐次坐标数学就会变得很奇怪。

如果在剪辑空间外延伸的屏幕宽度超过屏幕宽度,或者如果它们穿过零相机Z,大多数硬件只会困扰剪裁三角形。这种剪辑称为“保护带剪辑”,因为剪辑不便宜,所以可以节省大量性能。

所以,数学可以正常工作。在设置扫描线时,你需要做的主要事情是弄清楚它们每个在屏幕上的开始/结束位置。插值数学是相同的任何方式。

+0

我使用边缘函数来测试一个像素是否在三角形内,所以在我的情况下,“设置扫描线”可能等同于在屏幕空间中夹紧到范围[0,宽度 - 1],[0,height - 1],对吗? – pseudomarvin

2

我看不出有任何理由,这是行不通的。但它会比传统裁剪慢。请注意,您可能会遇到靠近投影中心的三角形,因为它们会很小,并且可能会在重心坐标计算中导致问题。方程14.9和14.10之间的区别在于,该深度基本上是z/w(并重新映射为[0,1])。由于角度差已经发生,所以在插值期间必须将其留下。