comparison tests/test_text.nim @ 1407:56f927b89716

did: finally got typography right, still improving text-rendering API to cache text parts
author sam <sam@basx.dev>
date Sun, 22 Dec 2024 00:31:29 +0700
parents aeb15aa9768c
children 17d960ff6a24
comparison
equal deleted inserted replaced
1406:aeb15aa9768c 1407:56f927b89716
19 var font = loadFont[MAX_CODEPOINTS](FONTNAME, lineHeightPixels = 200) 19 var font = loadFont[MAX_CODEPOINTS](FONTNAME, lineHeightPixels = 200)
20 var renderdata = initRenderData() 20 var renderdata = initRenderData()
21 var pipeline = createPipeline[GlyphShader[MAX_CODEPOINTS]]( 21 var pipeline = createPipeline[GlyphShader[MAX_CODEPOINTS]](
22 renderPass = vulkan.swapchain.renderPass 22 renderPass = vulkan.swapchain.renderPass
23 ) 23 )
24 var glyphs = font.initGlyphs(1000, baseScale = 0.1) 24 var textbuffer = font.initTextBuffer(1000, baseScale = 0.1)
25 25
26 assignBuffers(renderdata, glyphs) 26 assignBuffers(renderdata, textbuffer)
27 assignBuffers(renderdata, font.descriptorSet) 27 assignBuffers(renderdata, font.descriptorSet)
28 uploadImages(renderdata, font.descriptorSet) 28 uploadImages(renderdata, font.descriptorSet)
29 initDescriptorSet(renderdata, pipeline.layout(0), font.descriptorSet) 29 initDescriptorSet(renderdata, pipeline.layout(0), font.descriptorSet)
30 30
31 var start = getMonoTime() 31 var start = getMonoTime()
32 while ((getMonoTime() - start).inMilliseconds().int / 1000) < time: 32 while ((getMonoTime() - start).inMilliseconds().int / 1000) < time:
33 let t = getMonoTime() 33 let t = getMonoTime()
34 glyphs.reset() 34 textbuffer.reset()
35 glyphs.add("Hello semicongine!", vec3(0.5, 0.5), anchor = vec2(0.5, 0.5)) 35 textbuffer.add("Hello semicongine!", vec3(0.5, 0.5), anchor = vec2(0.5, 0.5))
36 glyphs.updateAllGPUBuffers(flush = true) 36 textbuffer.updateAllGPUBuffers(flush = true)
37 37
38 withNextFrame(framebuffer, commandbuffer): 38 withNextFrame(framebuffer, commandbuffer):
39 bindDescriptorSet(commandbuffer, font.descriptorSet, 0, pipeline) 39 bindDescriptorSet(commandbuffer, font.descriptorSet, 0, pipeline)
40 withRenderPass( 40 withRenderPass(
41 vulkan.swapchain.renderPass, 41 vulkan.swapchain.renderPass,
44 vulkan.swapchain.width, 44 vulkan.swapchain.width,
45 vulkan.swapchain.height, 45 vulkan.swapchain.height,
46 vec4(0, 0, 0, 0), 46 vec4(0, 0, 0, 0),
47 ): 47 ):
48 withPipeline(commandbuffer, pipeline): 48 withPipeline(commandbuffer, pipeline):
49 renderGlyphs(commandbuffer, pipeline, glyphs) 49 renderTextBuffer(commandbuffer, pipeline, textbuffer)
50 50
51 # cleanup 51 # cleanup
52 checkVkResult vkDeviceWaitIdle(vulkan.device) 52 checkVkResult vkDeviceWaitIdle(vulkan.device)
53 destroyPipeline(pipeline) 53 destroyPipeline(pipeline)
54 destroyRenderData(renderdata) 54 destroyRenderData(renderdata)
71 uploadImages(renderdata, font3.descriptorSet) 71 uploadImages(renderdata, font3.descriptorSet)
72 initDescriptorSet(renderdata, pipeline.layout(0), font1.descriptorSet) 72 initDescriptorSet(renderdata, pipeline.layout(0), font1.descriptorSet)
73 initDescriptorSet(renderdata, pipeline.layout(0), font2.descriptorSet) 73 initDescriptorSet(renderdata, pipeline.layout(0), font2.descriptorSet)
74 initDescriptorSet(renderdata, pipeline.layout(0), font3.descriptorSet) 74 initDescriptorSet(renderdata, pipeline.layout(0), font3.descriptorSet)
75 75
76 var glyphs1 = font1.initGlyphs(10, baseScale = 0.1) 76 var textbuffer1 = font1.initTextBuffer(10, baseScale = 0.1)
77 var glyphs2 = font2.initGlyphs(10, baseScale = 0.1) 77 var textbuffer2 = font2.initTextBuffer(10, baseScale = 0.1)
78 var glyphs3 = font3.initGlyphs(10, baseScale = 0.1) 78 var textbuffer3 = font3.initTextBuffer(10, baseScale = 0.1)
79 79
80 assignBuffers(renderdata, glyphs1) 80 assignBuffers(renderdata, textbuffer1)
81 assignBuffers(renderdata, glyphs2) 81 assignBuffers(renderdata, textbuffer2)
82 assignBuffers(renderdata, glyphs3) 82 assignBuffers(renderdata, textbuffer3)
83 83
84 var labels = [" 0", " 1", " 2"] 84 var labels = [" 0", " 1", " 2"]
85 85
86 var start = getMonoTime() 86 var start = getMonoTime()
87 var p = 0 87 var p = 0
88 while ((getMonoTime() - start).inMilliseconds().int / 1000) < time: 88 while ((getMonoTime() - start).inMilliseconds().int / 1000) < time:
89 let progress = ((getMonoTime() - start).inMilliseconds().int / 1000) / time 89 let progress = ((getMonoTime() - start).inMilliseconds().int / 1000) / time
90 glyphs1.reset() 90 textbuffer1.reset()
91 glyphs2.reset() 91 textbuffer2.reset()
92 glyphs3.reset() 92 textbuffer3.reset()
93 93
94 glyphs1.add($(p + 0), vec3(0.3, 0.5)) 94 textbuffer1.add($(p + 0), vec3(0.3, 0.5))
95 glyphs2.add($(p + 1), vec3(0.5, 0.5)) 95 textbuffer2.add($(p + 1), vec3(0.5, 0.5))
96 glyphs3.add($(p + 2), vec3(0.7, 0.5)) 96 textbuffer3.add($(p + 2), vec3(0.7, 0.5))
97 97
98 glyphs1.updateAllGPUBuffers(flush = true) 98 textbuffer1.updateAllGPUBuffers(flush = true)
99 glyphs2.updateAllGPUBuffers(flush = true) 99 textbuffer2.updateAllGPUBuffers(flush = true)
100 glyphs3.updateAllGPUBuffers(flush = true) 100 textbuffer3.updateAllGPUBuffers(flush = true)
101 101
102 inc p 102 inc p
103 withNextFrame(framebuffer, commandbuffer): 103 withNextFrame(framebuffer, commandbuffer):
104 withRenderPass( 104 withRenderPass(
105 vulkan.swapchain.renderPass, 105 vulkan.swapchain.renderPass,
109 vulkan.swapchain.height, 109 vulkan.swapchain.height,
110 vec4(0, 0, 0, 0), 110 vec4(0, 0, 0, 0),
111 ): 111 ):
112 withPipeline(commandbuffer, pipeline): 112 withPipeline(commandbuffer, pipeline):
113 bindDescriptorSet(commandbuffer, font1.descriptorSet, 0, pipeline) 113 bindDescriptorSet(commandbuffer, font1.descriptorSet, 0, pipeline)
114 renderGlyphs(commandbuffer, pipeline, glyphs1) 114 renderTextBuffer(commandbuffer, pipeline, textbuffer1)
115 bindDescriptorSet(commandbuffer, font2.descriptorSet, 0, pipeline) 115 bindDescriptorSet(commandbuffer, font2.descriptorSet, 0, pipeline)
116 renderGlyphs(commandbuffer, pipeline, glyphs2) 116 renderTextBuffer(commandbuffer, pipeline, textbuffer2)
117 bindDescriptorSet(commandbuffer, font3.descriptorSet, 0, pipeline) 117 bindDescriptorSet(commandbuffer, font3.descriptorSet, 0, pipeline)
118 renderGlyphs(commandbuffer, pipeline, glyphs3) 118 renderTextBuffer(commandbuffer, pipeline, textbuffer3)
119 119
120 # cleanup 120 # cleanup
121 checkVkResult vkDeviceWaitIdle(vulkan.device) 121 checkVkResult vkDeviceWaitIdle(vulkan.device)
122 destroyPipeline(pipeline) 122 destroyPipeline(pipeline)
123 destroyRenderData(renderdata) 123 destroyRenderData(renderdata)
132 132
133 assignBuffers(renderdata, font.descriptorSet) 133 assignBuffers(renderdata, font.descriptorSet)
134 uploadImages(renderdata, font.descriptorSet) 134 uploadImages(renderdata, font.descriptorSet)
135 initDescriptorSet(renderdata, pipeline.layout(0), font.descriptorSet) 135 initDescriptorSet(renderdata, pipeline.layout(0), font.descriptorSet)
136 136
137 var glyphs = font.initGlyphs(1000, baseScale = 0.1) 137 var textbuffer = font.initTextBuffer(1000, baseScale = 0.1)
138 assignBuffers(renderdata, glyphs) 138 assignBuffers(renderdata, textbuffer)
139 139
140 var start = getMonoTime() 140 var start = getMonoTime()
141 while ((getMonoTime() - start).inMilliseconds().int / 1000) < time: 141 while ((getMonoTime() - start).inMilliseconds().int / 1000) < time:
142 let progress = ((getMonoTime() - start).inMilliseconds().int / 1000) / time 142 let progress = ((getMonoTime() - start).inMilliseconds().int / 1000) / time
143 143
144 glyphs.reset() 144 textbuffer.reset()
145 glyphs.add("Anchor Center", vec3(0, 0), anchor = vec2(0, 0)) 145 textbuffer.add("Anchor at center", vec3(0, 0), anchor = vec2(0, 0))
146 glyphs.add("Anchor top left", vec3(0, 0), anchor = vec2(-1, 1)) 146 textbuffer.add("Anchor at top left`", vec3(-1, 1), anchor = vec2(-1, 1))
147 glyphs.add("Anchor top right", vec3(0, 0), anchor = vec2(1, 1)) 147 textbuffer.add("Anchor at top right", vec3(1, 1), anchor = vec2(1, 1))
148 glyphs.add("Anchor bottom left", vec3(0, 0), anchor = vec2(-1, -1)) 148 textbuffer.add("Anchor at bottom left", vec3(-1, -1), anchor = vec2(-1, -1))
149 glyphs.add("Anchor bottom right", vec3(0, 0), anchor = vec2(1, -1)) 149 textbuffer.add("Anchor at bottom right", vec3(1, -1), anchor = vec2(1, -1))
150 150
151 glyphs.add( 151 textbuffer.add(
152 """Paragraph 152 "Mutiline text\nLeft aligned\nCool!", vec3(-0.5, -0.5), alignment = Left
153 This is a somewhat longer paragraph with a few newlines and a maximum width of 0.2.
154
155 It should display with some space above and have a pleasing appearance overall! :)""",
156 vec3(0.5, 0.5),
157 anchor = vec2(0, 0),
158 alignment = Center,
159 ) 153 )
160 glyphs.updateAllGPUBuffers(flush = true) 154 textbuffer.add(
155 "Mutiline text\nCenter aligned\nCool!!", vec3(0, -0.5), alignment = Center
156 )
157 textbuffer.add(
158 "Mutiline text\nRight aligned\nCool!!!", vec3(0.5, -0.5), alignment = Right
159 )
160
161 textbuffer.updateAllGPUBuffers(flush = true)
161 162
162 withNextFrame(framebuffer, commandbuffer): 163 withNextFrame(framebuffer, commandbuffer):
163 bindDescriptorSet(commandbuffer, font.descriptorSet, 0, pipeline) 164 bindDescriptorSet(commandbuffer, font.descriptorSet, 0, pipeline)
164 withRenderPass( 165 withRenderPass(
165 vulkan.swapchain.renderPass, 166 vulkan.swapchain.renderPass,
168 vulkan.swapchain.width, 169 vulkan.swapchain.width,
169 vulkan.swapchain.height, 170 vulkan.swapchain.height,
170 vec4(0, 0, 0, 0), 171 vec4(0, 0, 0, 0),
171 ): 172 ):
172 withPipeline(commandbuffer, pipeline): 173 withPipeline(commandbuffer, pipeline):
173 renderGlyphs(commandbuffer, pipeline, glyphs) 174 renderTextBuffer(commandbuffer, pipeline, textbuffer)
174 175
175 # cleanup 176 # cleanup
176 checkVkResult vkDeviceWaitIdle(vulkan.device) 177 checkVkResult vkDeviceWaitIdle(vulkan.device)
177 destroyPipeline(pipeline) 178 destroyPipeline(pipeline)
178 destroyRenderData(renderdata) 179 destroyRenderData(renderdata)
179 180
180 #[
181 proc test_04_lots_of_texts(time: float32) = 181 proc test_04_lots_of_texts(time: float32) =
182 var font = loadFont[MAX_CODEPOINTS]("DejaVuSans.ttf", lineHeightPixels = 160) 182 var font = loadFont[MAX_CODEPOINTS]("DejaVuSans.ttf", lineHeightPixels = 160)
183 var renderdata = initRenderData() 183 var renderdata = initRenderData()
184 184
185 var pipeline = createPipeline[GlyphShader[MAX_CODEPOINTS]]( 185 var pipeline = createPipeline[GlyphShader[MAX_CODEPOINTS]](
186 renderPass = vulkan.swapchain.renderPass 186 renderPass = vulkan.swapchain.renderPass
187 ) 187 )
188 188
189 var ds = asDescriptorSetData(FontDS(fontAtlas: font.fontAtlas.copy())) 189 assignBuffers(renderdata, font.descriptorSet)
190 uploadImages(renderdata, ds) 190 uploadImages(renderdata, font.descriptorSet)
191 initDescriptorSet(renderdata, pipeline.layout(0), ds) 191 initDescriptorSet(renderdata, pipeline.layout(0), font.descriptorSet)
192
193 var textbuffer = font.initTextBuffer(1000, baseScale = 0.1)
194 assignBuffers(renderdata, textbuffer)
192 195
193 var labels: seq[Textbox] 196 var labels: seq[Textbox]
194 var positions = newSeq[Vec3f](100) 197 var positions = newSeq[Vec3f](100)
195 var colors = newSeq[Vec4f](100) 198 var colors = newSeq[Vec4f](100)
196 var scales = newSeq[Vec2f](100) 199 var scales = newSeq[Vec2f](100)
201 scales[i] = vec2(rand(0.5'f32 .. 1.5'f32), rand(0.5'f32 .. 1.5'f32)) 204 scales[i] = vec2(rand(0.5'f32 .. 1.5'f32), rand(0.5'f32 .. 1.5'f32))
202 labels.add initTextbox(renderdata, pipeline.layout(0), font, 0.001, $i) 205 labels.add initTextbox(renderdata, pipeline.layout(0), font, 0.001, $i)
203 206
204 var start = getMonoTime() 207 var start = getMonoTime()
205 while ((getMonoTime() - start).inMilliseconds().int / 1000) < time: 208 while ((getMonoTime() - start).inMilliseconds().int / 1000) < time:
206 for l in labels.mitems: 209 textbuffer.reset()
207 l.refresh() 210 withNextFrame(framebuffer, commandbuffer):
208 withNextFrame(framebuffer, commandbuffer): 211 bindDescriptorSet(commandbuffer, font.descriptorSet, 0, pipeline)
209 bindDescriptorSet(commandbuffer, ds, 0, pipeline) 212 withRenderPass(
210 withRenderPass( 213 vulkan.swapchain.renderPass,
211 vulkan.swapchain.renderPass, 214 framebuffer,
212 framebuffer, 215 commandbuffer,
213 commandbuffer, 216 vulkan.swapchain.width,
214 vulkan.swapchain.width, 217 vulkan.swapchain.height,
215 vulkan.swapchain.height, 218 vec4(0, 0, 0, 0),
216 vec4(0, 0, 0, 0), 219 ):
217 ): 220 withPipeline(commandbuffer, pipeline):
218 withPipeline(commandbuffer, pipeline): 221 renderTextBuffer(commandbuffer, pipeline, textbuffer)
219 for i in 0 ..< labels.len:
220 render(
221 commandbuffer, pipeline, labels[i], positions[i], colors[i], scales[i]
222 )
223 222
224 # cleanup 223 # cleanup
225 checkVkResult vkDeviceWaitIdle(vulkan.device) 224 checkVkResult vkDeviceWaitIdle(vulkan.device)
226 destroyPipeline(pipeline) 225 destroyPipeline(pipeline)
227 destroyRenderData(renderdata) 226 destroyRenderData(renderdata)
228 ]#
229 227
230 when isMainModule: 228 when isMainModule:
231 var time = 100'f32 229 var time = 100'f32
232 initVulkan() 230 initVulkan()
233 231