7
votes

D3D11: Comment dessiner une ligne alignée de pixels simple?

J'ai essayé de dessiner une ligne entre deux sommets avec D3D11. J'ai des expériences dans D3D9 et D3D11, mais cela semble être un problème dans D3D11 pour dessiner une ligne, qui commence dans un pixel donné et se termine dans un autre.

Qu'est-ce que j'ai fait:

  1. J'ai ajouté 0.5F aux coordonnées de pixels de chaque sommet pour adapter le système de coordonnées Texel / pixel (j'ai lu les pages Microsoft aux différents systèmes de coordonnées D3D9 et D3D11):

    F32 FOFF = 0.5F; NEWVERTICES DECORDERTEX [2] = { {D3DXVector3 (FSTARTX + FOFF, FSTARTY + FOFF, 0), VECCOLORRGB}, {D3DXVector3 (Fendx + FOFF, Fendy + FOFF, 0), VECCOLORRGB} };

  2. a généré une matrice de projection ortho pour adapter la cible de rendu:

    D3DXMATRIXORHOOFFCERLH (& Matrixortoproj, 0.0F, (F32) URTHIDTH, 0.0F, (F32) URTHEIGHT, 0.0F, 1.0F); D3DXMatrix Expose (& CBCONSTANT.M_MATORTHOPROJECTION ET MATRIXORTHOPROJ);

  3. Ensemble Rasterizattate, Blendstate, Viewport, ...

  4. Dessinez des sommets comme D3D11_PRIMITIVE_TOPOLOGIQUE_LINELIST

    problème: La ligne semble être un pixel à court. Cela commence dans la coordonnée de pixels donnée et il convient parfaitement. La direction de la ligne semble correcte, mais le pixel où je veux que la ligne se termine ne soit toujours pas colorée. On dirait que la ligne n'est qu'un pixel à court ...

    est le tutoriel qui explique ce problème ou que quelqu'un a-t-il le même problème? Comme je me souviens que ce n'était pas aussi difficile dans D3D9.

    S'il vous plaît demander si vous avez besoin d'informations supplémentaires.

    Merci, Stefan

    Edit: a trouvé les règles de rastralisation pour D3D10 (devrait être la même pour D3D11): http://msdn.microsoft.com /en-us/library/cc627092%28V=VS.85%29.aspx#line_1

    J'espère que cela va m'aider à comprendre ...


5 commentaires

Vous n'avez plus besoin d'ajuster les coordonnées PIXLE dans DX10 +, une des nombreuses améliorations (son non fait au niveau du conducteur IIRC). Ce problème me rappelle un ancien bogue OpenGL qui existait avec le dessin de la liste de lignes ...


Lorsque je n'ajoute pas 0.5F aux coordonnées, la ligne devient de 2px épaisseur, ce qui signifie pour moi, c'est exactement entre 2 pixels dans la cible de rendu


Render cible: 20x20px Line Soupices: (1,1) -> (18,1) sur la cible de rendu, la ligne remplit les pixels de (1,1) à (17,1) avec le réglage ajouté 0.5F


MSDN.MicRosoft.com/en-us/Library /bbb205073(v=vs.85).aspx Voir "Cartographie des texels aux pixels". utilisez-vous DX11 avec une interface DX9 par hasard (aka d3d_featu_level_9_x ?


J'utilise d3d_featu_level_11_0 avec le périphérique de rendu matériel (NVIDIA GEFORCE GTX 580). Le réglage est effectué avant que le Shader Vertex frappe le centre d'un pixel, de sorte que les coordonnées des sommets sont (1.5,1.5) et (18,5,1,5). Comme il n'y a pas de différence entre Texel et Pixel (de la cible de rendu), il n'y a plus d'ajustement après que cela


3 Réponses :


1
votes

Je ne sais pas D3D11, mais votre problème sonne beaucoup comme l'état du rendu D3DRS_LASTPIXEL de D3D9 - il y a peut-être un égal pour D3D11, vous devez examiner.


1 commentaires

À droite, on dirait que c'est ce dont j'ai besoin. Mais il n'y a plus de rendu dans D3D11. Je chercherai quelque chose d'égal. Merci :)



4
votes

Selon les règles de rasterisation (lien dans la question ci-dessus), j'ai peut-être trouvé une solution qui devrait fonctionner:

  1. Trier les sommets STARTX
  2. ajoutez (0,5 / 0,5) au sommet Vertex (comme je l'ai déjà fait) pour déplacer le sommet au centre du pixel li>
  3. Ajouter (1.0 / 1.0) au sommet d'extrémité pour déplacer le sommet dans le coin inférieur droit li> ol>

    Ceci est nécessaire pour dire au rasterizer que le dernier pixel de la ligne doit être dessiné. P>

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


3 commentaires

Erreur: il suffit de trier startx Fendy) Fyendoff = 0.0f;


Eh bien, vous ne pouvez pas simplement ajouter 0.5,0,5 supplément à la ligne ou vous modifiez la pente. Pour ce faire, vous devez ajouter 0,5 * pente (c'est-à-dire faire la ligne 0.5 pixels plus longtemps)


Vous avez raison, ma solution n'est pas aussi précise que je le souhaite, mais sur mes tests (plusieurs lignes sur une cible de rendu 20x20px), les résultats étaient corrects. Je vais essayer de tes suggestions. Merci :)



0
votes

J'ai rencontré exactement le même problème, et j'ai corrigé merci à cette discussion.

Mes sommets sont stockés dans un tampon D3D11_PRIMITID_TOPOLOPOLORE_PLINELIST_TOPOLOGIQUE. P>

Merci pour ce post utile, vous avez fait de me réparer ce bogue. aujourd'hui. C'était vraiment plus délicat que je pensais au début. P>

Voici quelques lignes de mon code. P>

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


1 commentaires

Vous voudrez peut-être jeter un coup d'œil à Kit d'outils DirectX et la classe Primitivatch .