我有一个SlimDX RenderForm(它继承了System.Windows.Forms.Form),我在其中有一个我在其上渲染地图的Panel。我想在地图上绘制城市名称。当用户放大和缩小地图时,文本不应改变大小,而是简单地进一步分开和靠近在一起。我想到了5种方法,每种方法都存在问题:
使用精灵来绘制文本。问题:DirectX11和Sprites不能混合。
等待DirectX11完成绘图,然后使用GDI手动将文本绘制到面板上。问题:处理尽可能多的文本需要花费太长时间,文本在每次重绘时都会有一个恼人的闪光。
基于Label创建自定义类,将类设置为允许透明背景,将Panel绘制为其父级,然后在用户缩放时移动这些标签。问题:为标签提供透明背景实际上并不会使其透明。它只是意味着它借用了Panel DirectX正在绘制的背景颜色并将自定义类的背景设置为它。我也尝试重写OnPaintBackground函数什么都不做,但这只是给标签一个黑色背景。
为表单提供TransparencyKey,并为面板提供该颜色的背景。然后,在这些面板之后,制作全新的RenderForms,在其上进行DirectX绘图,并将文本放在现在透明面板上的标签中。问题:单击地图空间会在后焦点中显示RenderForms,这意味着当单击该空间时,文本会在这些表单后面消失。我可以给主要的Form AlwaysOnTop,但我真的不想这样做,因为用户可能想在我的应用程序运行时做一些其他事情。另外,如果我打开另一个窗口,然后回到我的应用程序,这些表格不再显示在我的主表格后面。
执行类似于3的操作,并操作Region属性以匹配文本的GraphicsPath。问题:当我移动它们时,它有时不会尊重我所制作的区域,并且会回到黑色背景。
是否有任何我错过的解决方案,或以任何方式完成这些工作?
修改
基于给出答案的建议,我现在尝试使用GeometryShader来实质上制作一个精灵生成器。但是当我只有6个不同的精灵时,画画需要很长时间。只有1个精灵可以接受,但是当我尝试添加更多精灵时,它会变得太多。
答案 0 :(得分:1)
我在自己的引擎中解决了这个问题。我基本上创建了一个粒子系统,其中粒子顶点包含世界位置,颜色,字符索引,大小和大小模式。然后,此点粒子将转换为几何着色器中的精灵。这两种模式是恒定的世界大小(精灵是世界坐标中的恒定大小)或恒定的屏幕大小(精灵在屏幕坐标中是恒定大小)。然后,您需要编写一个接收字符串的方法,并为每个顶点输出此粒子列表。如果操作正确,几何着色器会为您完成所有工作,即使相机移动,您也无需进行任何顶点缓冲区更新来定位文本。
就sprite批处理而言,无需担心绘制顺序。丢弃每个像素周围的透明像素以防止深度写入。
小心尝试在要绘制的面板上放置透明的.Net控件。这将需要控件在每次呈现场景时重绘,这会导致.Net限制帧速率(非常糟糕!)。如果需要,我将控件放在我的d3d面板上,但它们是不透明的,不需要不断绘画。
希望有所帮助。如果您需要更多详细信息,请与我们联系。
- 更新 -
我来定义2个术语。 “字符精灵”是一个包含单个字符图像的小精灵。 “字符串精灵”是角色精灵的集合,它们移动并表现为一个具有多个字符外观的大精灵。
用户在世界空间中定义字符串精灵的位置。字符串中的每个字符用于定义字符精灵。具体来说,每个字符精灵都被赋予一个与字符串精灵位置相对应的屏幕空间。这允许所有精灵定位在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几何着色器的片段。使用此着色器以及相应的顶点和像素着色器,我可以虚拟渲染整个文本段落以影响性能。 &gt; 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 );
}
}