【问题标题】:SlimDX DirectX11 and Text SpritesSlimDX DirectX11 和文本精灵
【发布时间】:2014-10-06 15:26:12
【问题描述】:

我有一个 SlimDX RenderForm(它继承了 System.Windows.Forms.Form),其中我有一个面板,可以在上面渲染地图。我想在地图上画出城市的名字。当用户放大和缩小地图时,文本不应该改变大小,而只是分散得更远更近。我已经想到了 5 种方法来做到这一点,但每种方法都存在问题:

  1. 使用精灵来绘制文本。问题:DirectX11 和 Sprite 无法混合。

  2. 等待 DirectX11 完成绘制,然后自己使用 GDI 手动将文本绘制到面板上。问题:处理尽可能多的文本需要一点时间,而且每次重绘时文本都会出现令人讨厌的闪光。

  3. 创建一个基于标签的自定义类,设置类以允许透明背景,将要绘制的面板设置为其父级,并在用户缩放时移动这些标签。问题:给标签一个透明的背景实际上并不能使它变得透明。这只是意味着它借用了正在绘制的 Panel DirectX 的背景颜色并将自定义类的背景设置为该颜色。我也试过重写 OnPaintBackground 函数什么都不做,但这只是给标签一个黑色背景。

  4. 给窗体一个 TransparencyKey,并给面板一个该颜色的背景。然后,在这些面板后面,制作全新的 RenderForms,在其上进行 DirectX 绘图,并将文本放置在现在透明面板上的标签中。问题:单击地图空间会使 RenderForms 在后面的焦点中,这意味着当单击该空间时,文本会消失在这些 Forms 后面。我可以提供主窗体 AlwaysOnTop,但我真的不想这样做,因为用户可能想在我的应用程序运行时做其他事情。另外,如果我打开另一个窗口,然后返回我的应用程序,这些表单将不再显示在我的主表单后面。

  5. 执行类似于 3 的操作,并操作 Region 属性以匹配文本的 GraphicsPath。问题:当我四处移动它们时,它有时不尊重我创建的区域,并返回黑色背景。

有什么我错过的解决方案,或者有什么方法可以使这些工作中的任何一个工作吗?

编辑:

根据给出的答案的建议,我现在正在尝试使用 GeometryShader 来制作精灵生成器。但是当我只有 6 个不同的精灵时,绘制时间太长了。只有 1 个精灵是可以接受的,但是当我尝试添加更多时,它变得太多了。

【问题讨论】:

  • 虽然我自己没有使用过 SlimDX,但 SlimDX.Toolkit 包中似乎支持 Sprite 和字体渲染:code.google.com/p/slimdx/source/browse/branches/lite/…
  • 是的,但我很确定这些不适用于 DirectX-11,但仅适用于 DirectX-9,或者可能适用于 DirectX-10
  • 查看源代码,它们是用 D3D11 对象编写的,所以我不确定为什么它们不起作用。精灵只是在屏幕空间中定义的两个纹理三角形,没有透视投影。 D3D11 中没有像 D3DX9 那样的内置精灵批处理。
  • 如果没有精灵批处理,那么考虑到我可以同时显示几十个城市,这不是问题吗?一次发送一个到设备会影响我的表现,不是吗?
  • 抱歉,我的意思是基本 D3D11 api 中没有内置精灵批处理类,但它并没有阻止人们编写像 SlimDX 在 Toolkit 包中具有的精灵批处理类。他们基本上只是在顶点缓冲区中收集成对的三角形,然后对它们进行排序以尽可能少地绘制。

标签: windows forms text directx-11 slimdx


【解决方案1】:

我已经在自己的引擎中解决了这个问题。我基本上创建了一个粒子系统,其中粒子顶点包含世界位置、颜色、字符索引、大小和大小模式。然后这个点粒子在几何着色器中被转换为一个精灵。这两种模式是固定世界尺寸(精灵在世界坐标中是固定尺寸)或固定屏幕尺寸(精灵在屏幕坐标中是固定尺寸)。然后,您需要编写一个方法,该方法接受一个字符串并为每个顶点输出这个粒子列表。如果操作正确,几何着色器会为您完成所有工作,即使在相机移动时,您也无需执行任何顶点缓冲区更新来定位文本。

就精灵批处理而言,无需担心绘制顺序。丢弃每个像素周围的透明像素以防止深度写入。

尝试将透明的 .Net 控件放置在要绘制的面板上时要小心。这将需要控件在您每次呈现场景时重绘,这会导致 .Net 限制您的帧速率(真的很糟糕!)。如果需要,我会在我的 d3d 面板上放置控件,但它们是不透明的,这不需要持续绘制。

希望对您有所帮助。如果您需要更多详细信息,请告诉我。

-- 更新--

让我定义两个术语。 “角色精灵”是包含单个角色图像的小精灵。 “字符串精灵”是角色精灵的集合,这些角色精灵移动并表现为一个具有多个字符外观的大型精灵。

用户定义字符串精灵在世界空间中的位置。字符串中的每个字符都用于定义字符精灵。具体来说,每个字符精灵都被赋予了相对于字符串精灵位置的屏幕空间偏移量。这允许所有精灵定位在 3d 空间中,而所有角色在屏幕空间中不会相互重叠。

每个角色精灵都是一个点顶点,带有“位置”(float3)、“纹理坐标”(float2)、“纹理编号”(int)、“屏幕空间偏移”(float2)和“颜色”(float4)。 “位置”对于字符串精灵中的所有字符精灵都是相同的。”每个字符的纹理可以在单个图像中定义,其中每个字符精灵都被赋予正确的纹理坐标(我所做的)或在纹理数组中。

-- 更新--

这是我用于文本的图像(低质量)。

这是根据角色分配给角色精灵的纹理坐标表。

Char    ASCII   StrtPix EndPix  PixWdth StartUTexCoord  EndUTexCoord

    32  0   0   40  0   0
!   33  16  34  18  0.002222222 0.004722222
"   34  56  97  41  0.007777778 0.013472222
#   35  113 197 84  0.015694444 0.027361111
$   36  212 279 67  0.029444444 0.03875
%   37  290 412 122 0.040277778 0.057222222
&   38  423 512 89  0.058750000 0.071111111
\   39  512 567 55  0.071111111 0.07875
(   40  572 611 39  0.079444444 0.084861111
)   41  625 664 39  0.086805556 0.092222222
*   42  681 743 62  0.094583333 0.103194444
+   43  761 842 81  0.105694444 0.116944444
,   44  859 888 29  0.119305556 0.123333333
-   45  902 945 43  0.125277778 0.13125
.   46  981 997 16  0.136250000 0.138472222
/   47  991 1048    57  0.137638889 0.145555556
0   48  1122    1188    66  0.155833333 0.165
1   49  1142    1194    52  0.158611111 0.165833333
2   50  1214    1278    64  0.168611111 0.1775
3   51  1292    1355    63  0.179444444 0.188194444
4   52  1365    1436    71  0.189583333 0.199444444
5   53  1450    1511    61  0.201388889 0.209861111
6   54  1524    1591    67  0.211666667 0.220972222
7   55  1602    1668    66  0.222500000 0.231666667
8   56  1680    1748    68  0.233333333 0.242777778
9   57  1756    1824    68  0.243888889 0.253333333
:   58  1849    1866    17  0.256805556 0.259166667
;   59  1896    1925    29  0.263333333 0.267361111
<   60  1954    2027    73  0.271388889 0.281527778
=   61  2054    2129    75  0.285277778 0.295694444
>   62  2156    2229    73  0.299444444 0.309583333
?   63  2250    2305    55  0.312500000 0.320138889
@   64  2319    2425    106 0.322083333 0.336805556
A   65  2434    2518    84  0.338055556 0.349722222
B   66  2528    2599    71  0.351111111 0.360972222
C   67  2607    2685    78  0.362083333 0.372916667
D   68  2698    2779    81  0.374722222 0.385972222
E   69  2792    2856    64  0.387777778 0.396666667
F   70  2871    2932    61  0.398750000 0.407222222
G   71  2936    3020    84  0.407777778 0.419444444
H   72  3036    3109    73  0.421666667 0.431805556
I   73  3126    3165    39  0.434166667 0.439583333
J   74  3172    3217    45  0.440555556 0.446805556
K   75  3236    3312    76  0.449444444 0.46
L   76  3321    3381    60  0.461250000 0.469583333
M   77  3389    3473    84  0.470694444 0.482361111
N   78  3492    3565    73  0.485000000 0.495138889
O   79  3579    3667    88  0.497083333 0.509305556
P   80  3682    3744    62  0.511388889 0.52
Q   81  3751    3841    90  0.520972222 0.533472222
R   82  3853    3932    79  0.535138889 0.546111111
S   83  3935    4008    73  0.546527778 0.556666667
T   84  4011    4091    80  0.557083333 0.568194444
U   85  4097    4170    73  0.569027778 0.579166667
V   86  4178    4264    86  0.580277778 0.592222222
W   87  4266    4383    117 0.592500000 0.60875
X   88  4389    4468    79  0.609583333 0.620555556
Y   89  4469    4547    78  0.620694444 0.631527778
Z   90  4552    4625    73  0.632222222 0.642361111
[   91  4642    4677    35  0.644722222 0.649583333
\   92  4687    4744    57  0.650972222 0.658888889
]   93  4749    4793    44  0.659583333 0.665694444
^   94  4805    4886    81  0.667361111 0.678611111
_   95  4893    4975    82  0.679583333 0.690972222
'   96  4982    4998    16  0.691944444 0.694166667
a   97  5010    5071    61  0.695833333 0.704305556
b   98  5089    5152    63  0.706805556 0.715555556
c   99  5161    5219    58  0.716805556 0.724861111
d   100 5226    5287    61  0.725833333 0.734305556
e   101 5303    5367    64  0.736527778 0.745416667
f   102 5373    5418    45  0.746250000 0.7525
g   103 5418    5479    61  0.752500000 0.760972222
h   104 5499    5559    60  0.763750000 0.772083333
i   105 5577    5597    13  0.774583333 0.776378888
j   106 5595    5634    39  0.777083333 0.7825
k   107 5652    5715    63  0.785000000 0.79375
l   108 5725    5738    13  0.795138889 0.796944444
m   109 5757    5860    103 0.799583333 0.813888889
n   110 5878    5937    59  0.816388889 0.824583333
o   111 5952    6016    64  0.826666667 0.835555556
p   112 6030    6093    63  0.837500000 0.84625
q   113 6103    6165    62  0.847638889 0.85625
r   114 6184    6229    45  0.858888889 0.865138889
s   115 6232    6287    55  0.865555556 0.873194444
t   116 6293    6338    45  0.874027778 0.880277778
u   117 6348    6407    59  0.881666667 0.889861111
v   118 6419    6488    69  0.891527778 0.901111111
w   119 6493    6588    95  0.901805556 0.915
x   120 6593    6661    68  0.915694444 0.925138889
y   121 6666    6735    69  0.925833333 0.935416667
z   122 6742    6798    56  0.936388889 0.944166667
{   123 6810    6869    59  0.945833333 0.954027778
|   124 6900    6913    13  0.958333333 0.960138889
}   125 6944    7003    59  0.964444444 0.972638889
~   126 7022    7104    82  0.975277778 0.986666667

这是我使用的 HLSL 几何着色器的 sn-p。使用这个着色器,以及适当的顶点和像素着色器,我可以渲染整个文本段落,几乎影响性能。 >1,000 个字符是不引人注意的。

struct VertexOutput
{
    float4 Pos  : SV_Position;
    float4 Color    : COLOR;
    float2 TexCoords    : TEXCOORD;
    float4 Size : TEXCOORD1;
};

struct GeometryOutput
{
    float4 Pos  : SV_Position;
    float4 Color    : COLOR;
    float2 TexCoords    : TEXCOORDS;
};

struct Camera
{
    float4x4 ViewProjection;
    float4x4 Projection;
    float4x4 View;
    float4 Position;
    float4 LookAt;
};

texture2D <float> TextTextures : register(t6);

[maxvertexcount(4)]
void GShader( point VertexOutput Input[1], inout TriangleStream<GeometryOutput> OutputStream )
{
    if(Input[0].TexCoords.x != Input[0].TexCoords.y)
    {
        GeometryOutput Output1 = (GeometryOutput)0;
        GeometryOutput Output2 = (GeometryOutput)0;
        GeometryOutput Output3 = (GeometryOutput)0;
        GeometryOutput Output4 = (GeometryOutput)0;

        if(Input[0].Pos.w == 1)
            Output1.Pos = mul(Input[0].Pos, Cameras[0].ViewProjection);
        else
        {
            Input[0].Pos.w = 1;
            Output1.Pos = mul(Input[0].Pos, Cameras[0].ViewProjection);
            Output1.Pos.xyz /= Output1.Pos.w;
            Output1.Pos.w = 1;
        }
        Output2.Pos = Output1.Pos;
        Output3.Pos = Output1.Pos;
        Output4.Pos = Output1.Pos;

        Output1.Pos.x += (Input[0].Size.z - Input[0].Size.x) / Resolution.x/2;
        Output2.Pos.x += (Input[0].Size.z + Input[0].Size.x) / Resolution.x/2;
        Output3.Pos.x += (Input[0].Size.z - Input[0].Size.x) / Resolution.x/2;
        Output4.Pos.x += (Input[0].Size.z + Input[0].Size.x) / Resolution.x/2;

        Output1.Pos.y += (Input[0].Size.w - Input[0].Size.y)  / Resolution.y/2;
        Output2.Pos.y += (Input[0].Size.w - Input[0].Size.y)  / Resolution.y/2;
        Output3.Pos.y += (Input[0].Size.w + Input[0].Size.y)  / Resolution.y/2;
        Output4.Pos.y += (Input[0].Size.w + Input[0].Size.y)  / Resolution.y/2;

        Output1.Color = Input[0].Color;
        Output2.Color = Input[0].Color;
        Output3.Color = Input[0].Color;
        Output4.Color = Input[0].Color;

        Output1.TexCoords = float2(Input[0].TexCoords.x,1);
        Output2.TexCoords = float2(Input[0].TexCoords.y,1);
        Output3.TexCoords = float2(Input[0].TexCoords.x,0);
        Output4.TexCoords = float2(Input[0].TexCoords.y,0);

        OutputStream.Append( Output1 );
        OutputStream.Append( Output3 );
        OutputStream.Append( Output2 );
        OutputStream.Append( Output4 );
    }
}

【讨论】:

  • 有趣。我一定会研究这个解决方案。我必须承认我以前从未做过粒子系统。我需要一些时间来弄清楚它们,但如果我这样做了,我肯定会将此标记为答案。谢谢。
  • 我开始回到这个话题。我一直忙于其他项目。我正在考虑这个问题,我想知道您的解决方案的参数是什么?您是否拥有每个精灵都是不同图像的地方?因为那是我需要的。一次有大约 250 张不同的图像,性能还可以吗?
  • 如果你有空,你能看看我的编辑吗?
  • 好的。我得到了它的工作(谢谢!实际上我在你上次更新之前就知道了,很抱歉我在最后一次上浪费了你的时间)但是还有一个问题:你知道我是否可以做一些碰撞检测在 HLSL 代码中?如果你放大得太远,我的很多城市都会重叠,我需要消除人口较少的城市。
  • 我对 SlimDX 和着色器图形非常陌生,是否可以看到一些有关如何使用此技术的示例代码?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-06-24
  • 1970-01-01
  • 2015-05-22
相关资源
最近更新 更多