comparison tests/test_text.nim @ 1327:373a4888f6ac

did: rework font-rendering
author sam <sam@basx.dev>
date Sat, 17 Aug 2024 13:54:22 +0700
parents 385dbd68a947
children ad09d41abd1e
comparison
equal deleted inserted replaced
1326:41f3612ef38d 1327:373a4888f6ac
7 import std/options 7 import std/options
8 import std/random 8 import std/random
9 9
10 import ../semicongine 10 import ../semicongine
11 11
12 type
13 FontDS = object
14 fontAtlas: Image[Gray]
15
12 proc test_01_static_label(time: float32) = 16 proc test_01_static_label(time: float32) =
13 var renderdata = initRenderData()
14
15 var pipeline = createPipeline[DefaultFontShader](renderPass = vulkan.swapchain.renderPass)
16
17 var font = loadFont("Overhaul.ttf", lineHeightPixels = 160) 17 var font = loadFont("Overhaul.ttf", lineHeightPixels = 160)
18 var renderdata = initRenderData()
19 var pipeline = createPipeline[DefaultFontShader[FontDS]](renderPass = vulkan.swapchain.renderPass)
20
21 var ds = asDescriptorSetData(FontDS(fontAtlas: font.fontAtlas))
22 uploadImages(renderdata, ds)
23 initDescriptorSet(
24 renderdata,
25 pipeline.layout(0),
26 ds,
27 )
28
18 var label1 = initTextbox( 29 var label1 = initTextbox(
19 renderdata, 30 renderdata,
20 pipeline.layout(0), 31 pipeline.layout(0),
21 font, 32 font,
33 0.0005,
22 "Hello semicongine!", 34 "Hello semicongine!",
23 color = vec4(1, 1, 1, 1),
24 scale = 0.0005,
25 ) 35 )
26 36
27 var start = getMonoTime() 37 var start = getMonoTime()
28 while ((getMonoTime() - start).inMilliseconds().int / 1000) < time: 38 while ((getMonoTime() - start).inMilliseconds().int / 1000) < time:
29 label1.refresh() 39 label1.refresh()
30 withNextFrame(framebuffer, commandbuffer): 40 withNextFrame(framebuffer, commandbuffer):
31 withRenderPass(vulkan.swapchain.renderPass, framebuffer, commandbuffer, vulkan.swapchain.width, vulkan.swapchain.height, vec4(0, 0, 0, 0)): 41 bindDescriptorSet(commandbuffer, ds, 0, pipeline)
32 withPipeline(commandbuffer, pipeline): 42 withRenderPass(vulkan.swapchain.renderPass, framebuffer, commandbuffer, vulkan.swapchain.width, vulkan.swapchain.height, vec4(0, 0, 0, 0)):
33 render(commandbuffer, pipeline, label1) 43 withPipeline(commandbuffer, pipeline):
44 render(commandbuffer, pipeline, label1, vec3(), vec4(1, 1, 1, 1))
34 45
35 # cleanup 46 # cleanup
36 checkVkResult vkDeviceWaitIdle(vulkan.device) 47 checkVkResult vkDeviceWaitIdle(vulkan.device)
37 destroyPipeline(pipeline) 48 destroyPipeline(pipeline)
38 destroyRenderData(renderdata) 49 destroyRenderData(renderdata)
39 50
40 proc test_02_multiple_animated(time: float32) = 51 proc test_02_multiple_animated(time: float32) =
41 var renderdata = initRenderData()
42
43 var pipeline = createPipeline[DefaultFontShader](renderPass = vulkan.swapchain.renderPass)
44
45 var font1 = loadFont("Overhaul.ttf", lineHeightPixels = 40) 52 var font1 = loadFont("Overhaul.ttf", lineHeightPixels = 40)
46 var font2 = loadFont("Overhaul.ttf", lineHeightPixels = 160) 53 var font2 = loadFont("Overhaul.ttf", lineHeightPixels = 160)
47 var font3 = loadFont("DejaVuSans.ttf", lineHeightPixels = 160) 54 var font3 = loadFont("DejaVuSans.ttf", lineHeightPixels = 160)
55 var renderdata = initRenderData()
56
57 var pipeline = createPipeline[DefaultFontShader[FontDS]](renderPass = vulkan.swapchain.renderPass)
58
59 var ds1 = asDescriptorSetData(FontDS(fontAtlas: font1.fontAtlas))
60 uploadImages(renderdata, ds1)
61 initDescriptorSet(renderdata, pipeline.layout(0), ds1)
62
63 var ds2 = asDescriptorSetData(FontDS(fontAtlas: font2.fontAtlas))
64 uploadImages(renderdata, ds2)
65 initDescriptorSet(renderdata, pipeline.layout(0), ds2)
66
67 var ds3 = asDescriptorSetData(FontDS(fontAtlas: font3.fontAtlas))
68 uploadImages(renderdata, ds3)
69 initDescriptorSet(renderdata, pipeline.layout(0), ds3)
70
48 var labels = [ 71 var labels = [
49 initTextbox( 72 initTextbox(
50 renderdata, 73 renderdata,
51 pipeline.layout(0), 74 pipeline.layout(0),
52 font1, 75 font1,
76 0.004,
53 " 0", 77 " 0",
54 color = vec4(0, 1, 1, 1),
55 scale = 0.004,
56 position = vec3(-0.3, 0.5)
57 ), 78 ),
58 initTextbox( 79 initTextbox(
59 renderdata, 80 renderdata,
60 pipeline.layout(0), 81 pipeline.layout(0),
61 font2, 82 font2,
83 0.001,
62 " 1", 84 " 1",
63 color = vec4(1, 0, 1, 1),
64 scale = 0.001,
65 position = vec3(0, 0)
66 ), 85 ),
67 initTextbox( 86 initTextbox(
68 renderdata, 87 renderdata,
69 pipeline.layout(0), 88 pipeline.layout(0),
70 font3, 89 font3,
90 0.001,
71 " 2", 91 " 2",
72 color = vec4(1, 1, 0, 1),
73 scale = 0.001,
74 position = vec3(0.3, -0.5)
75 ) 92 )
76 ] 93 ]
77 94
78 var start = getMonoTime() 95 var start = getMonoTime()
79 var p = 0 96 var p = 0
80 while ((getMonoTime() - start).inMilliseconds().int / 1000) < time: 97 while ((getMonoTime() - start).inMilliseconds().int / 1000) < time:
81 let progress = ((getMonoTime() - start).inMilliseconds().int / 1000) / time 98 let progress = ((getMonoTime() - start).inMilliseconds().int / 1000) / time
82 for i in 0 ..< labels.len: 99 for i in 0 ..< labels.len:
83 var c = labels[i].color
84 c[i] = progress
85 labels[i].color = c
86 labels[i].scale = labels[i].scale * (1.0 + (i + 1).float * 0.001)
87 labels[i].position = labels[i].position + vec3(0.001 * (i.float - 1'f))
88 labels[i].text = $(p + i) 100 labels[i].text = $(p + i)
89 labels[i].refresh() 101 labels[i].refresh()
90 inc p 102 inc p
91 withNextFrame(framebuffer, commandbuffer): 103 withNextFrame(framebuffer, commandbuffer):
92 withRenderPass(vulkan.swapchain.renderPass, framebuffer, commandbuffer, vulkan.swapchain.width, vulkan.swapchain.height, vec4(0, 0, 0, 0)): 104 withRenderPass(vulkan.swapchain.renderPass, framebuffer, commandbuffer, vulkan.swapchain.width, vulkan.swapchain.height, vec4(0, 0, 0, 0)):
93 withPipeline(commandbuffer, pipeline): 105 withPipeline(commandbuffer, pipeline):
94 for label in labels.litems: 106 bindDescriptorSet(commandbuffer, ds1, 0, pipeline)
95 render(commandbuffer, pipeline, label) 107 render(
108 commandbuffer,
109 pipeline,
110 labels[0],
111 position=vec3(0 / labels.len, 0.1 + progress * 0.5),
112 color=vec4(1, 1, 1, 1),
113 )
114 bindDescriptorSet(commandbuffer, ds2, 0, pipeline)
115 render(
116 commandbuffer,
117 pipeline,
118 labels[1],
119 position=vec3(1 / labels.len, 0.1 + progress * 0.5),
120 color=vec4(1, 1, 1, 1),
121 )
122 bindDescriptorSet(commandbuffer, ds3, 0, pipeline)
123 render(
124 commandbuffer,
125 pipeline,
126 labels[2],
127 position=vec3(2 / labels.len, 0.1 + progress * 0.5),
128 color=vec4(1, 1, 1, 1),
129 )
96 130
97 # cleanup 131 # cleanup
98 checkVkResult vkDeviceWaitIdle(vulkan.device) 132 checkVkResult vkDeviceWaitIdle(vulkan.device)
99 destroyPipeline(pipeline) 133 destroyPipeline(pipeline)
100 destroyRenderData(renderdata) 134 destroyRenderData(renderdata)
101 135
102 proc test_03_layouting(time: float32) = 136 proc test_03_layouting(time: float32) =
103 var renderdata = initRenderData()
104
105 var pipeline = createPipeline[DefaultFontShader](renderPass = vulkan.swapchain.renderPass)
106
107 var font = loadFont("DejaVuSans.ttf", lineHeightPixels = 40) 137 var font = loadFont("DejaVuSans.ttf", lineHeightPixels = 40)
138 var renderdata = initRenderData()
139
140 var pipeline = createPipeline[DefaultFontShader[FontDS]](renderPass = vulkan.swapchain.renderPass)
141
142 var ds = asDescriptorSetData(FontDS(fontAtlas: font.fontAtlas))
143 uploadImages(renderdata, ds)
144 initDescriptorSet(
145 renderdata,
146 pipeline.layout(0),
147 ds,
148 )
149
108 var labels: seq[Textbox] 150 var labels: seq[Textbox]
109 151
110 for horizontal in HorizontalAlignment: 152 for horizontal in HorizontalAlignment:
111 labels.add initTextbox( 153 labels.add initTextbox(
112 renderdata, 154 renderdata,
113 pipeline.layout(0), 155 pipeline.layout(0),
114 font, 156 font,
157 0.001,
115 $horizontal & " aligned", 158 $horizontal & " aligned",
116 color = vec4(1, 1, 1, 1),
117 scale = 0.001,
118 position = vec3(0, 0.9 - (horizontal.float * 0.15)),
119 horizontalAlignment = horizontal, 159 horizontalAlignment = horizontal,
120 ) 160 )
121 for vertical in VerticalAlignment: 161 for vertical in VerticalAlignment:
122 labels.add initTextbox( 162 labels.add initTextbox(
123 renderdata, 163 renderdata,
124 pipeline.layout(0), 164 pipeline.layout(0),
125 font, 165 font,
166 0.001,
126 $vertical & " aligned", 167 $vertical & " aligned",
127 color = vec4(1, 1, 1, 1),
128 scale = 0.001,
129 position = vec3(-0.35 + (vertical.float * 0.35), 0.3),
130 verticalAlignment = vertical, 168 verticalAlignment = vertical,
131 ) 169 )
132 labels.add initTextbox( 170 labels.add initTextbox(
133 renderdata, 171 renderdata,
134 pipeline.layout(0), 172 pipeline.layout(0),
135 font, 173 font,
174 0.001,
136 """Paragraph 175 """Paragraph
137 This is a somewhat longer paragraph with a few newlines and a maximum width of 0.2. 176 This is a somewhat longer paragraph with a few newlines and a maximum width of 0.2.
138 177
139 It should display with some space above and have a pleasing appearance overall! :)""", 178 It should display with some space above and have a pleasing appearance overall! :)""",
140 maxWidth = 0.6, 179 maxWidth = 0.6,
141 color = vec4(1, 1, 1, 1),
142 scale = 0.001,
143 position = vec3(-0.9, 0.1),
144 verticalAlignment = Top, 180 verticalAlignment = Top,
145 horizontalAlignment = Left, 181 horizontalAlignment = Left,
146 ) 182 )
147 183
148
149 var start = getMonoTime() 184 var start = getMonoTime()
150 while ((getMonoTime() - start).inMilliseconds().int / 1000) < time: 185 while ((getMonoTime() - start).inMilliseconds().int / 1000) < time:
151 let progress = ((getMonoTime() - start).inMilliseconds().int / 1000) / time 186 let progress = ((getMonoTime() - start).inMilliseconds().int / 1000) / time
152 withNextFrame(framebuffer, commandbuffer): 187 withNextFrame(framebuffer, commandbuffer):
153 withRenderPass(vulkan.swapchain.renderPass, framebuffer, commandbuffer, vulkan.swapchain.width, vulkan.swapchain.height, vec4(0, 0, 0, 0)): 188 bindDescriptorSet(commandbuffer, ds, 0, pipeline)
154 withPipeline(commandbuffer, pipeline): 189 withRenderPass(vulkan.swapchain.renderPass, framebuffer, commandbuffer, vulkan.swapchain.width, vulkan.swapchain.height, vec4(0, 0, 0, 0)):
155 for label in labels: 190 withPipeline(commandbuffer, pipeline):
156 render(commandbuffer, pipeline, label) 191 for i in 0 ..< labels.len:
192 render(commandbuffer, pipeline, labels[i], vec3(0.5 - i.float32 * 0.1, 0.5 - i.float32 * 0.1), vec4(1, 1, 1, 1))
157 193
158 # cleanup 194 # cleanup
159 checkVkResult vkDeviceWaitIdle(vulkan.device) 195 checkVkResult vkDeviceWaitIdle(vulkan.device)
160 destroyPipeline(pipeline) 196 destroyPipeline(pipeline)
161 destroyRenderData(renderdata) 197 destroyRenderData(renderdata)
162 198
163 proc test_04_lots_of_texts(time: float32) = 199 proc test_04_lots_of_texts(time: float32) =
164 var renderdata = initRenderData()
165
166 var pipeline = createPipeline[DefaultFontShader](renderPass = vulkan.swapchain.renderPass)
167
168 var font = loadFont("DejaVuSans.ttf", lineHeightPixels = 160) 200 var font = loadFont("DejaVuSans.ttf", lineHeightPixels = 160)
201 var renderdata = initRenderData()
202
203 var pipeline = createPipeline[DefaultFontShader[FontDS]](renderPass = vulkan.swapchain.renderPass)
204
205 var ds = asDescriptorSetData(FontDS(fontAtlas: font.fontAtlas))
206 uploadImages(renderdata, ds)
207 initDescriptorSet(
208 renderdata,
209 pipeline.layout(0),
210 ds,
211 )
212
169 var labels: seq[Textbox] 213 var labels: seq[Textbox]
214 var positions = newSeq[Vec3f](100)
215 var colors = newSeq[Vec4f](100)
216 var scales = newSeq[float32](100)
170 for i in 0 ..< 100: 217 for i in 0 ..< 100:
218 positions[i] = vec3(rand(-0.5 .. 0.5), rand(-0.5 .. 0.5), rand(-0.1 .. 0.1))
219 colors[i] = vec4(rand(0.5 .. 1.0), rand(0.5 .. 1.0), rand(0.5 .. 1.0), rand(0.5 .. 1.0))
220 scales[i] = rand(0.5'f32 .. 1.5'f32)
171 labels.add initTextbox( 221 labels.add initTextbox(
172 renderdata, 222 renderdata,
173 pipeline.layout(0), 223 pipeline.layout(0),
174 font, 224 font,
225 0.001,
175 $i, 226 $i,
176 color = vec4(rand(0.5 .. 1.0), rand(0.5 .. 1.0), rand(0.5 .. 1.0), rand(0.5 .. 1.0)), 227 )
177 scale = rand(0.0002 .. 0.002),
178 position = vec3(rand(-0.5 .. 0.5), rand(-0.5 .. 0.5), rand(-0.1 .. 0.1))
179 )
180 labels.sort(proc(x, y: Textbox): int = cmp(x.position.z, y.position.z), Ascending)
181 228
182 var start = getMonoTime() 229 var start = getMonoTime()
183 while ((getMonoTime() - start).inMilliseconds().int / 1000) < time: 230 while ((getMonoTime() - start).inMilliseconds().int / 1000) < time:
184 for l in labels.mitems: 231 for l in labels.mitems:
185 l.refresh() 232 l.refresh()
186 withNextFrame(framebuffer, commandbuffer): 233 withNextFrame(framebuffer, commandbuffer):
187 withRenderPass(vulkan.swapchain.renderPass, framebuffer, commandbuffer, vulkan.swapchain.width, vulkan.swapchain.height, vec4(0, 0, 0, 0)): 234 bindDescriptorSet(commandbuffer, ds, 0, pipeline)
188 withPipeline(commandbuffer, pipeline): 235 withRenderPass(vulkan.swapchain.renderPass, framebuffer, commandbuffer, vulkan.swapchain.width, vulkan.swapchain.height, vec4(0, 0, 0, 0)):
189 for l in labels: 236 withPipeline(commandbuffer, pipeline):
190 render(commandbuffer, pipeline, l) 237 for i in 0 ..< labels.len:
238 render(commandbuffer, pipeline, labels[i], positions[i], colors[i], scales[i])
191 239
192 # cleanup 240 # cleanup
193 checkVkResult vkDeviceWaitIdle(vulkan.device) 241 checkVkResult vkDeviceWaitIdle(vulkan.device)
194 destroyPipeline(pipeline) 242 destroyPipeline(pipeline)
195 destroyRenderData(renderdata) 243 destroyRenderData(renderdata)