直角视图中未显示三角形拓扑

Triangle topology not displayed in orthographic view

本文关键字:三角形 显示 视图      更新时间:2023-10-16

我正在尝试使用DirectX(在WP8上)在正射影视图中绘制原语,为了使事情更容易,我正在尝试使用DirectXTK。

然而,由于某种原因,我无法自己弄清楚,只有线条带/列表拓扑有效,而任何基于三角形的都没有(视觉)效果。

场景是正字的,PrimitiveBatch是用BasicEffect输入的,代码是基于示例并在物理WP8设备上测试的。

projection = XMMatrixOrthographicOffCenterLH(-1, 1, -1, 1, 0, 1);
...
VertexPositionColor A, B, C, D; 
A.position.x = -0.5;
A.position.y = -0.5;
A.position.z = 0;B.position.x = 0.5;
B.position.x = 0.5;
B.position.y = -0.5;
B.position.z = 0;
C.position.x = 0.5;
C.position.y = 0.5;
C.position.z = 0;
D.position.x = -0.5;
D.position.y = 0.5;
D.position.z = 0;
//and so on, centered rectangle with width/height of half of screen
...    
// only DrawLine produces effect
m_batch->DrawLine(A, B);
m_batch->DrawQuad(A, B, C, D);
m_batch->DrawTriangle(A, B, C);
// even more direct approach produces no effect (for line topology it works fine)
m_batch->Draw(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST, mappedVertices, n);

我所需要的是大量的2D原语(带有厚度和/或填充的线条/矩形)和文本(spritefont?),它们目前是在。net (XAML)前端执行的(通过textblock编写文本的速度非常快…),我想摆脱它们,但第一次与DirectX发生冲突就杀了我(上次我在Commodore 64上为如此低级的图形内容感到困扰,似乎事情已经改变了…)

也许有另一个库可以更好地满足我对性能和本机代码的需求,但不需要学习新的邪恶技术?

经过一番学习,我能够回答自己的问题了。

正如Zdd和Roger在评论中提到的,问题是由背面剔除引起的,或者说是不正确的顶点顺序使得三角形可以被剔除。Back-Side Culling是用一种非常简单的方式来测试三角形的可见性:三角形的顶点必须顺时针地围绕图形的中心放置,才能被认为是可见的。

有两种可能的解决方案。

  • 更改剔除模式以接受不正确的顶点顺序,但是这会导致性能下降。
  • 将需要在绘制前准备的顶点顺序更改为合适的顺序

要检查顶点是否按顺时针顺序,做一点数学运算就足够了,如果结果是False,只需翻转a和C。结果取决于Z轴方向

bool TestTriangle(VertexPositionColor A, VertexPositionColor B, VertexPositionColor C)
{
    float crossz = (B.position.x - A.position.x) * (C.position.y - B.position.y) - (B.position.y - A.position.y) * (C.position.x - B.position.x);
    // for Left Hand z axis
    return !(crossz > 0.0f);
    // for Right Hand z axis
    return (crossz > 0.0f);
}

对于轴对齐的矩形,可以从开始

开始以正确的顺序创建顶点
void DrawRect(int x, int y, int h, int w, XMFLOAT4 brush)
{
    VertexPositionColor A, B, C, D;
    // set color
    D.color = C.color = B.color = A.color = brush;
    //Z index manipulation can be used to position figure above/below other drawings
    D.position.z = C.position.z = B.position.z = A.position.z = 0;
    // clockwise aligned vertices
    A.position.x = x; B.position.x = x + w;
    D.position.x = x; C.position.x = x + w;
    // DirectX Y axis starts from bottom left corner (as in cartesian coordinates system and in opposite to WinApi Top/Left coord system)
    A.position.y = y + h; B.position.y = y + h;
    D.position.y = y;     C.position.y = y;
    //m_batch is PrimitveBatch from Directx Toolkit
    m_batch->DrawQuad(A, B, C, D);
}