drawing lines in 3D (DirectX)?
I'm adding lines to my 3D world like we see in 3D studio max. To draw lines I'm using a cylinder mesh and simply stretching/rotating it appropriately. That's all working fine but my problem is scale. Since it's 3D geometry rendering in perspective its size changes, from a distance it's small to invisible, up close it's h开发者_如何学编程uge.
I want to make it so the size of the line geometry stays the same. I tried toying around with orthographic projection but came up with nothing. Any ideas?
Well you could easily write a shader to get round that problem. Basically you need to push it out proportionally to the w value you generate. ie if the cylinder has a width of r. then you can cancel out the perspective by pushing it out to (r * w). This way when the w divide occurs it will ALWAYS give you r.
A cylinder, though, could be a tad excessive you could get a similar effect by drawing a billboarded line and applying a texture to it.
I wrote a shader in DX8 many years ago to do this (mind this is with perspective). Basically I defined the vertex data as follows:
struct BillboardLineVertex
{
D3DXVECTOR3 position;
D3DXVECTOR3 otherPosition;
DWORD colour;
D3DXVECTOR2 UV;
};
Assuming the line goes from A to B then position is A and otherPosition is B for the first 2 vertices. Furthermore I encoded into the V (or y) of the UV either a -1 or 1. This told me whether I would push out from the line up or down the screen. Finally the 3rd coordinate for the triangle had the A & B in position and otherPosition the other way round (I'll leave you to figure out how to build the other triangle. Note that the U texture coord (or x) was settable to allow for texture repeating along the line.
I then had the following bit of shader assembly to build the lines ... This had the added bonus that it took exactly 2 triangles to do one line... I could then pack them all into 1 big vertex buffer and render several hundred in one Draw call.
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
};
Such a setup would be easily modifiable to give you the same size regardless of distance from the camera.
精彩评论