D3D11: How to draw a simple pixel aligned line?

后端 未结 3 1286
醉梦人生
醉梦人生 2021-01-05 07:50

I tried to draw a line between two vertices with D3D11. I have some experiences in D3D9 and D3D11, but it seems to be a problem in D3D11 to draw a line, which starts in one

相关标签:
3条回答
  • 2021-01-05 08:29

    According to the rasterisation rules (link in the question above) I might have found a solution that should work:

    1. sort the vertices StartX < EndX and StartY < EndY
    2. add (0.5/0.5) to the start vertex (as i did before) to move the vertex to the center of the pixel
    3. add (1.0/1.0) to the end vertex to move the vertex to the lower right corner

    This is needed to tell the rasterizer that the last pixel of the line should be drawn.

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

    If you know a better solution, please let me know.

    0 讨论(0)
  • 2021-01-05 08:40

    I encountered the exact same issue, and i fixed thank to this discussion.

    My vertices are stored into a D3D11_PRIMITIVE_TOPOLOGY_LINELIST vertex buffer.

    Thank for this usefull post, you made me fix this bug today. It was REALLY trickier than i thought at start.

    Here a few line of my code.

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

    I tested Several DrawLine2D calls, and it seems to work well.

    0 讨论(0)
  • 2021-01-05 08:48

    I don't know D3D11, but your problem sounds a lot like the D3DRS_LASTPIXEL render state from D3D9 - maybe there's an equal for D3D11 you need to look into.

    0 讨论(0)
提交回复
热议问题