三角形拓扑未在正交视图中显示

时间:2014-03-28 00:17:40

标签: c++ windows-phone-8 directx-11

我正在尝试使用DirectX(在WP8上)在正交视图中绘制基元,以便使我更容易使用DirectXTK。

但是,出于某种原因,我无法弄清楚,只有Line strip / list拓扑可以正常工作,而任何基于三角形的拓扑都没有(视觉)效果。

场景是正交的,PrimitiveBatch是BasicEffect,代码基于sample并在物理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上遇到如此低级别的图形内容,看起来情况发生了变化......)

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

1 个答案:

答案 0 :(得分:0)

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

正如Zdd和Roger在评论中提到的那样,问题是由背面剔除引起的,或者更确切地说是不正确的顶点顺序使得三角形可用于剔除。 Back-Side Culling以非常简单的方式测试三角形的可见性:三角形的顶点必须围绕图形的中心顺时针定位,以使其被视为可见。

有两种可能的解决方案。

  • 更改Culling mode以接受不正确的顶点顺序,但是 它会导致性能下降。
  • 将顶点的顺序更改为适当的顶点,这需要在绘制前进行准备

要检查顶点是否按顺时针顺序,只需要进行一些数学运算,如果结果为False,只需在A和C处翻转即可。 结果取决于Z axis direction

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);
}