Math 在3D(DirectX)中绘制线条?

Math 在3D(DirectX)中绘制线条?,math,matrix,directx,projection,Math,Matrix,Directx,Projection,我正在向我的3D世界添加线条,就像我们在3D studio max中看到的那样。要绘制线条,我使用圆柱体网格并简单地适当拉伸/旋转它。这一切都很好,但我的问题是规模。由于它的三维几何渲染在透视图中,它的大小会发生变化,从一个小的距离到不可见的距离,近距离看它是巨大的 我想使线几何体的大小保持不变。我试着玩弄正交投影,但什么也没想到。有什么想法吗?你可以很容易地编写一个着色器来解决这个问题。基本上,您需要按生成的w值的比例将其推出。即如果圆柱体的宽度为r。然后您可以通过将透视图推出(r*w)来取消

我正在向我的3D世界添加线条,就像我们在3D studio max中看到的那样。要绘制线条,我使用圆柱体网格并简单地适当拉伸/旋转它。这一切都很好,但我的问题是规模。由于它的三维几何渲染在透视图中,它的大小会发生变化,从一个小的距离到不可见的距离,近距离看它是巨大的


我想使线几何体的大小保持不变。我试着玩弄正交投影,但什么也没想到。有什么想法吗?

你可以很容易地编写一个着色器来解决这个问题。基本上,您需要按生成的w值的比例将其推出。即如果圆柱体的宽度为r。然后您可以通过将透视图推出(r*w)来取消透视图。这样,当w除法出现时,它总是给你r

不过,圆柱体可能有点过分,你可以通过画一条广告牌上的线并对其应用纹理来获得类似的效果

很多年前,我在DX8中编写了一个着色器来实现这一点(请注意,这是透视图)。基本上,我定义顶点数据如下:

struct BillboardLineVertex
{
    D3DXVECTOR3  position;
    D3DXVECTOR3  otherPosition;
    DWORD        colour;
    D3DXVECTOR2  UV;
};
假设直线从A到B,则前两个顶点的位置为A,其他位置为B。此外,我编码到UV的V(或y)中,要么是-1,要么是1。这告诉了我,我会在屏幕上排成一行还是排成一行。最后,三角形的第三个坐标将A和B放置到位,而其他位置则相反(我将让您思考如何构建另一个三角形。请注意,U纹理坐标(或x)是可设置的,以允许沿直线重复纹理

然后我用下面的着色器组合来构建线条…这有一个额外的好处,那就是只需要2个三角形就可以完成一条线条…然后我可以将它们全部打包到一个大顶点缓冲区中,并在一次绘制调用中渲染几百个

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

这样的设置很容易修改,无论距离相机有多远,都可以得到相同的大小。

你可以很容易地编写一个着色器来解决这个问题。基本上,你需要按生成的w值成比例地将其推出。例如,如果圆柱体的宽度为r,那么你可以通过按下i来取消透视t out to(r*w)。这样,当w除法出现时,它总是给你r

不过,圆柱体可能有点过分,你可以通过画一条广告牌上的线并对其应用纹理来获得类似的效果

多年前,我在DX8中编写了一个着色器来实现这一点(请注意,这是透视图)。基本上,我定义了顶点数据,如下所示:

struct BillboardLineVertex
{
    D3DXVECTOR3  position;
    D3DXVECTOR3  otherPosition;
    DWORD        colour;
    D3DXVECTOR2  UV;
};
假设直线从A到B,那么前两个顶点的位置是A,其他位置是BUV的a-1或1。这告诉我是从屏幕上的线条向上还是向下推出。最后,三角形的第三个坐标将a&B放置到位,而其他坐标则反过来放置(我将让您思考如何构建另一个三角形。请注意,U纹理坐标(或x)可设置为允许沿线条重复纹理

然后我用下面的着色器组合来构建线条…这有一个额外的好处,那就是只需要2个三角形就可以完成一条线条…然后我可以将它们全部打包到一个大顶点缓冲区中,并在一次绘制调用中渲染几百个

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

这样的设置很容易修改,无论离相机有多远,都可以给你相同的大小。

Brillant..看到il asm代码很有趣!我做了同样的事情,但使用了几何体着色器。它避免了复制其他位置的成本。还支持任意线宽和线型ala
GllineStiple
@Stringer:I D我在2001年写了这段代码;)我同意如果你能瞄准DX10几何体着色器是你的朋友:)Brillant。。看到il asm代码很有趣!我做了同样的事情,但使用了几何体着色器。它避免了重复其他位置的成本。还支持任意线宽和线型(ala
glLineStipple
@Stringer:2001年我写过这段代码;)我同意,如果您可以将DX10几何体着色器作为目标,那么您的朋友:)