Direct2D/DirectX中线段的光栅化规则

3

我已经阅读了关于DirectX光栅化规则的在线文档,但我仍然不明白为什么这段代码在屏幕上没有显示出任何内容?

target->SetAntialiasMode(D2D1_ANTIALIAS_MODE_ALIASED);
target->DrawLine(D2D1::Point2F(0.f, 0.f), D2D1::Point2F(10.f, 0.f), redBrush, 1.f);

当然,如果我将y从0.0f更改为1.0f,两个线点都是这样的,我会在窗口客户区的左上方看到一条水平线,但我想理解这里涉及了哪些原则。我无法从可用的文档中弄清楚。

1个回答

2
您应该将线条“绘制在像素的中间”:
target->DrawLine(D2D1::Point2F(0.0f, 0.5f), D2D1::Point2F(10.f, 0.5f), redBrush, 1.f);

否则,如果你不使用抗锯齿,你的线条可能会绘制在0/0 ... 10/0线的任何一侧。 在你的情况下,它会被绘制在窗口画布外面。
请注意,屏幕上的像素实际上是一个坐标为D2D1 :: Point2F(0.0f,0.0f)到D2D1 :: Point2F(1.0f,1.0f)的矩形。
而D2D1 :: Point2F(0.5f,0.5f)则是该矩形的中心。 如果你在该坐标周围绘制1x1的矩形,则会完全覆盖该像素。

哦,看起来我正在阅读使用DirectX 10及更高版本中未使用的坐标系统的光栅化规则:https://learn.microsoft.com/en-us/windows/desktop/direct3d9/rasterization-rules - Tony
DirectX 10及更高版本中,所谓的钻石区域规则是否适用于别名线条? - Tony
这些是Direct2D、Skia、Cairo、GDI+等常用的“规则”。在锯齿状渲染中,如果像素的中心恰好位于轮廓内部,则会绘制该像素,因此这是计算精度的问题。在您的情况下,定义为一像素线的是从0,-0.5(包括)到10.0,+0.5(不包括)的矩形。因此,位于位图的零行中的像素不会被渲染。 - c-smile
我明白了,现在我不再将0,0作为最上方、最左侧的像素中心,就像在DirectX 9中一样。但是,你确定GDI+也是这样吗?换句话说,我感到困惑的另一个原因是,在GDI+中,类似于graph.DrawLine(pen, 0, 0, 10, 0); 这样的代码对于1.0宽度的笔确实会产生可见的线条,无论是在抗锯齿模式还是在非抗锯齿模式下。 - Tony
根据特定的约定,GDI+可能会将线段解释为从0,-0.5(不包括)开始,到10.0,+0.5(包括)结束的矩形。D2D在这方面显然更正确。一般来说,当您使用别名基元时,应该切换到FillRectangle()而不是使用DrawLine()。另一个选项是在绘制之前设置m_pRenderTarget->SetTransform(D2D1::Matrix3x2F::Translation(0.5, 0.5));,但如果考虑高于96 dpi的表面,则会很棘手。 - c-smile

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接