2010-09-29 32 views
1

J'ajoute des lignes à mon monde 3D comme on le voit dans 3D studio max. Pour tracer des lignes, j'utilise une maille de cylindre et je l'étire/je la fais pivoter de manière appropriée. Tout fonctionne bien, mais mon problème est l'échelle. Comme le rendu de la géométrie 3D est en perspective, sa taille change, de loin elle est petite à invisible, de près elle est énorme.tracer des lignes en 3D (DirectX)?

Je veux faire en sorte que la taille de la géométrie de ligne reste la même. J'ai essayé de jouer avec la projection orthographique mais je n'ai rien trouvé. Des idées?

Répondre

1

Eh bien, vous pouvez facilement écrire un shader pour contourner ce problème. Fondamentalement, vous devez le pousser proportionnellement à la valeur w que vous générez. c'est-à-dire si le cylindre a une largeur de r. alors vous pouvez annuler la perspective en la poussant vers (r * w). De cette façon, lorsque la division w se produit, elle vous donnera TOUJOURS r. Un cylindre, cependant, pourrait être un peu excessif, vous pourriez obtenir un effet similaire en dessinant une ligne Billboarded et en appliquant une texture à elle.

J'ai écrit un shader dans DX8 il y a de nombreuses années pour le faire (attention c'est avec perspective). Fondamentalement, je défini les données de sommet de la manière suivante:

struct BillboardLineVertex 
{ 
    D3DXVECTOR3 position; 
    D3DXVECTOR3 otherPosition; 
    DWORD  colour; 
    D3DXVECTOR2 UV; 
}; 

En supposant que la ligne passe de A à B, puis position A et B est otherPosition pour les 2 premiers sommets. De plus, j'ai encodé dans le V (ou y) de l'UV soit -1 soit 1. Cela m'a indiqué si je pousserais hors de la ligne vers le haut ou le bas de l'écran. Finalement la 3ème coordonnée pour le triangle avait le A & B en position et l'autre Position l'inverse (je vais vous laisser imaginer comment construire l'autre triangle.) Notez que la coordonnée de texture U (ou x) était réglable pour permettre J'ai ensuite eu l'assemblage de shader suivant pour construire les lignes ... Cela a ajouté le bonus qu'il fallait exactement 2 triangles pour faire une ligne ... Je pouvais ensuite les emballer tous dans 1 grand tampon de sommet et de rendre plusieurs centaines dans un appel Draw.

asm 
{ 
    vs.1.1 

// Create line vector. 
    mov r1, v0 
    sub r3, r1, v4 

// Get eye to line vector 
    sub r6, v0, c20 

// Get Tangent to line vector lieing on screen plane. 
    mul r5, r6.yzxw, r3.zxyw 
    mad r5, -r3.yzxw, r6.zxyw, r5 

// Normalise tangent 
    dp3 r4.w, r5.xyz, r5.xyz 
    rsq r4.w, r4.w 
    mul r5.xyz, r5.xyz, r4.w 

// Multiply by 1 or -1 (y part of UV) 
    mul r5.xyz, r5.xyz, -v9.y 

// Push tangent out by "thickness" 
    mul r5.xyz, r5.xyz, c16.x 
    add r1.xyz, r1.xyz, r5.xyz 

// Transform position 
    m4x4 oPos, r1, c0 

// Work out UV (c16.y is assumed to contain 0.5, c16.z is assumed to contain 1) 
    mov r2.xy, v9.xy 
    mul r2.y, v9.y, v9.x 
    add r2.xy, r2.xy, c16.z 
    mul oT0.xy, r2.xy, c16.y 

// Move colour into diffuse output channel. 
    mov oD0, v3 
}; 

une telle configuration serait facilement modifiable pour vous donner la même taille quelle que soit la distance de la caméra.

+0

Brillant .. et amusant de voir le code asm! J'ai fait à peu près la même chose mais en utilisant Geometry Shaders. Il évite le coût de la duplication d'autresPosition. Également pris en charge la largeur de ligne arbitraire et les types de ligne ala 'glLineStipple'. – Stringer

+0

@Stringer: J'ai écrit ce code en 2001-ish;) Je suis d'accord si vous pouvez cibler les shaders de géométrie DX10 sont votre ami :) – Goz