2011-05-05 70 views
5

我試圖用D3D11在兩個頂點之間畫一條線。我在D3D9和D3D11中有一些經驗,但是在D3D11中繪製一條線開始於一個給定像素並以另一個像素結束似乎是個問題。D3D11:如何繪製一個簡單的像素對齊線?

我做了什麼:

  1. 我添加0.5F每個頂點的像素座標,以適應texel- /像素座標系(我讀D3D9的微軟網頁到differeces和D3D11座標系):

    f32 fOff = 0.5f; ColoredVertex newVertices [2] = { {D3DXVECTOR3(fStartX + FOFF,fStartY + FOFF,0),vecColorRGB},{ D3DXVECTOR3(fEndX + FOFF,fEndY + FOFF,0),vecColorRGB} };

  2. 產生的鄰投影矩陣,以適應渲染目標:

    D3DXMatrixOrthoOffCenterLH(& MatrixOrthoProj,0.0F,(F32)uRTWidth,0.0F,(F32)uRTHeight,0.0F,1.0F); D3DXMatrixTranspose(& cbConstant.m_matOrthoProjection,& MatrixOrthoProj);

  3. 集RasterizerState,BlendState,視口,...

  4. 繪製頂點作爲D3D11_PRIMITIVE_TOPOLOGY_LINELIST

問題: 行似乎是一個像素短。它從給定的像素座標開始,非常適合。線的方向看起來是正確的,但我想要線結束的像素仍然沒有着色。它看起來像線只是一個像素...

是任何教程解釋這個問題或有沒有人有同樣的問題?我記得在D3D9中並不難。

請詢問您是否需要更多信息。

感謝,斯特凡

編輯:發現D3D10光柵化規則(應該是D3D11相同): http://msdn.microsoft.com/en-us/library/cc627092%28v=vs.85%29.aspx#Line_1

我希望這將有助於我理解......

+0

您不再需要調整DX10 +中的像素座標,只是衆多改進中的一個(在驅動程序級iirc中沒有完成)。這個問題讓我想起了一箇舊的OpenGL bug列表繪圖... – Necrolis 2011-05-05 13:53:29

+0

當我不添加0.5f的座標,行變成2px厚,這意味着對我來說,它恰好在2像素之間渲染目標 – sandicz 2011-05-05 14:05:23

+0

渲染目標:20x20px 渲染目標上的線頂點:(1,1) - >(18,1) 該行將填充從(1,1)到(17,1)的像素並添加0.5 f調整 – sandicz 2011-05-05 14:10:00

回答

3

據光柵化規則(在上面的問題鏈接)我可能已經發現,應該工作的解決方案:

  1. 排序頂點startx的< EndX和StartY <恩迪
  2. 加(0.5/0.5 )到起始頂點(像我以前那樣)將頂點移動到像素的中心
  3. add(1.0/1。0)到結束頂點以將頂點移動到右下角

這是告訴光柵化設備應該繪製線條的最後一個像素所需要的。

f32 fXStartOff = 0.5f; 
f32 fYStartOff = 0.5f; 
f32 fXEndOff = 1.0f; 
f32 fYEndOff = 1.0f; 

ColoredVertex newVertices[2] = 
{ 
    { D3DXVECTOR3((f32)fStartX + fXStartOff, (f32)fStartY + fYStartOff,0), vecColorRGB }, 
    { D3DXVECTOR3((f32)fEndX + fXEndOff , (f32)fEndY + fYEndOff,0), vecColorRGB } 
}; 

如果您知道更好的解決方案,請告訴我。

+0

錯誤:僅對StartX fEndY)fYEndOff = 0.0f; – sandicz 2011-05-06 13:57:45

+0

好吧 - 你不能只在線上增加0.5,0.5的額外值,或者你正在改變斜率。要做到這一點,你需要添加0.5 *斜率(即使線條長0.5個像素) – Aaron 2011-05-06 16:00:08

+0

你是對的,我的解決方案並不像我想要的那樣精確,但是在我的測試中(20x20px上的幾行渲染目標)的結果是好的。我會試一試你的建議。謝謝:) – sandicz 2011-05-09 06:37:45

1

我不不知道D3D11,但是你的問題聽起來很像D3D9渲染狀態D3DRS_LASTPIXEL - 也許D3D11需要考慮。

+0

對,聽起來像這是什麼我需要。但是d3d11中沒有任何渲染器,我會尋找相同的東西。謝謝:) – sandicz 2011-05-06 06:39:30

0

我遇到了完全相同的問題,我解決了這個問題。

我的頂點存儲在D3D11_PRIMITIVE_TOPOLOGY_LINELIST頂點緩衝區中。

謝謝你這個有用的文章,你讓我今天修復這個bug。 這真的比我想象的更復雜。

這裏有幾行我的代碼。

// projection matrix code 
float width = 1024.0f; 
float height = 768.0f; 
DirectX::XMMATRIX offsetedProj = DirectX::XMMatrixOrthographicRH(width, height, 0.0f, 10.0f); 
DirectX::XMMATRIX proj = DirectX::XMMatrixMultiply(DirectX::XMMatrixTranslation(- width/2, height/2, 0), offsetedProj); 

// view matrix code 
// screen top left pixel is 0,0 and bottom right is 1023,767 
DirectX::XMMATRIX viewMirrored = DirectX::XMMatrixLookAtRH(eye, at, up); 
DirectX::XMMATRIX mirrorYZ = DirectX::XMMatrixScaling(1.0f, -1.0f, -1.0f); 
DirectX::XMMATRIX view = DirectX::XMMatrixMultiply(mirrorYZ, viewMirrored); 

// draw line code in my visual debug tool. 
void TVisualDebug::DrawLine2D(int2 const& parStart, 
           int2 const& parEnd, 
           TColor parColorStart, 
           TColor parColorEnd, 
           float parDepth) 

{ 
    FLine2DsDirty = true; 

    // D3D11_PRIMITIVE_TOPOLOGY_LINELIST 
    float2 const startFloat(parStart.x() + 0.5f, parStart.y() + 0.5f); 
    float2 const endFloat(parEnd.x() + 0.5f, parEnd.y() + 0.5f); 
    float2 const diff = endFloat - startFloat; 
    // return normalized difference or float2(1.0f, 1.0f) if distance between the points is null. Then multiplies the result by something a little bigger than 0.5f, 0.5f is not enough. 
    float2 const diffNormalized = diff.normalized_replace_if_null(float2(1.0f, 1.0f)) * 0.501f; 

    size_t const currentIndex = FLine2Ds.size(); 
    FLine2Ds.resize(currentIndex + 2); 
    render::vertex::TVertexColor* baseAddress = FLine2Ds.data() + currentIndex; 
    render::vertex::TVertexColor& v0 = baseAddress[0]; 
    render::vertex::TVertexColor& v1 = baseAddress[1]; 
    v0.FPosition = float3(startFloat.x(), startFloat.y(), parDepth); 
    v0.FColor = parColorStart; 
    v1.FPosition = float3(endFloat.x() + diffNormalized.x(), endFloat.y() + diffNormalized.y(), parDepth); 
    v1.FColor = parColorEnd; 
} 

我測試了幾個DrawLine2D調用,它似乎工作得很好。

+0

你可能想看看[DirectX Tool KIt](https://github.com/Microsoft/DirectXTK)和''PrimitiveBatch''類。 – 2015-10-02 05:19:53