diff 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
line wrap: on
line diff
--- a/tests/test_text.nim	Sat Aug 17 11:34:15 2024 +0700
+++ b/tests/test_text.nim	Sat Aug 17 13:54:22 2024 +0700
@@ -9,28 +9,39 @@
 
 import ../semicongine
 
+type
+  FontDS = object
+    fontAtlas: Image[Gray]
+
 proc test_01_static_label(time: float32) =
+  var font = loadFont("Overhaul.ttf", lineHeightPixels = 160)
   var renderdata = initRenderData()
+  var pipeline = createPipeline[DefaultFontShader[FontDS]](renderPass = vulkan.swapchain.renderPass)
 
-  var pipeline = createPipeline[DefaultFontShader](renderPass = vulkan.swapchain.renderPass)
+  var ds = asDescriptorSetData(FontDS(fontAtlas: font.fontAtlas))
+  uploadImages(renderdata, ds)
+  initDescriptorSet(
+    renderdata,
+    pipeline.layout(0),
+    ds,
+  )
 
-  var font = loadFont("Overhaul.ttf", lineHeightPixels = 160)
   var label1 = initTextbox(
     renderdata,
     pipeline.layout(0),
     font,
+    0.0005,
     "Hello semicongine!",
-    color = vec4(1, 1, 1, 1),
-    scale = 0.0005,
   )
 
   var start = getMonoTime()
   while ((getMonoTime() - start).inMilliseconds().int / 1000) < time:
     label1.refresh()
     withNextFrame(framebuffer, commandbuffer):
+      bindDescriptorSet(commandbuffer, ds, 0, pipeline)
       withRenderPass(vulkan.swapchain.renderPass, framebuffer, commandbuffer, vulkan.swapchain.width, vulkan.swapchain.height, vec4(0, 0, 0, 0)):
         withPipeline(commandbuffer, pipeline):
-          render(commandbuffer, pipeline, label1)
+          render(commandbuffer, pipeline, label1, vec3(), vec4(1, 1, 1, 1))
 
         # cleanup
   checkVkResult vkDeviceWaitIdle(vulkan.device)
@@ -38,40 +49,46 @@
   destroyRenderData(renderdata)
 
 proc test_02_multiple_animated(time: float32) =
-  var renderdata = initRenderData()
-
-  var pipeline = createPipeline[DefaultFontShader](renderPass = vulkan.swapchain.renderPass)
-
   var font1 = loadFont("Overhaul.ttf", lineHeightPixels = 40)
   var font2 = loadFont("Overhaul.ttf", lineHeightPixels = 160)
   var font3 = loadFont("DejaVuSans.ttf", lineHeightPixels = 160)
+  var renderdata = initRenderData()
+
+  var pipeline = createPipeline[DefaultFontShader[FontDS]](renderPass = vulkan.swapchain.renderPass)
+
+  var ds1 = asDescriptorSetData(FontDS(fontAtlas: font1.fontAtlas))
+  uploadImages(renderdata, ds1)
+  initDescriptorSet(renderdata, pipeline.layout(0), ds1)
+
+  var ds2 = asDescriptorSetData(FontDS(fontAtlas: font2.fontAtlas))
+  uploadImages(renderdata, ds2)
+  initDescriptorSet(renderdata, pipeline.layout(0), ds2)
+
+  var ds3 = asDescriptorSetData(FontDS(fontAtlas: font3.fontAtlas))
+  uploadImages(renderdata, ds3)
+  initDescriptorSet(renderdata, pipeline.layout(0), ds3)
+
   var labels = [
     initTextbox(
       renderdata,
       pipeline.layout(0),
       font1,
+      0.004,
       "  0",
-      color = vec4(0, 1, 1, 1),
-      scale = 0.004,
-      position = vec3(-0.3, 0.5)
     ),
     initTextbox(
       renderdata,
       pipeline.layout(0),
       font2,
+      0.001,
       "  1",
-      color = vec4(1, 0, 1, 1),
-      scale = 0.001,
-      position = vec3(0, 0)
     ),
     initTextbox(
       renderdata,
       pipeline.layout(0),
       font3,
+      0.001,
       "  2",
-      color = vec4(1, 1, 0, 1),
-      scale = 0.001,
-      position = vec3(0.3, -0.5)
     )
   ]
 
@@ -80,19 +97,36 @@
   while ((getMonoTime() - start).inMilliseconds().int / 1000) < time:
     let progress = ((getMonoTime() - start).inMilliseconds().int / 1000) / time
     for i in 0 ..< labels.len:
-      var c = labels[i].color
-      c[i] = progress
-      labels[i].color = c
-      labels[i].scale = labels[i].scale * (1.0 + (i + 1).float * 0.001)
-      labels[i].position = labels[i].position + vec3(0.001 * (i.float - 1'f))
       labels[i].text = $(p + i)
       labels[i].refresh()
     inc p
     withNextFrame(framebuffer, commandbuffer):
       withRenderPass(vulkan.swapchain.renderPass, framebuffer, commandbuffer, vulkan.swapchain.width, vulkan.swapchain.height, vec4(0, 0, 0, 0)):
         withPipeline(commandbuffer, pipeline):
-          for label in labels.litems:
-            render(commandbuffer, pipeline, label)
+          bindDescriptorSet(commandbuffer, ds1, 0, pipeline)
+          render(
+            commandbuffer,
+            pipeline,
+            labels[0],
+            position=vec3(0 / labels.len, 0.1 + progress * 0.5),
+            color=vec4(1, 1, 1, 1),
+          )
+          bindDescriptorSet(commandbuffer, ds2, 0, pipeline)
+          render(
+            commandbuffer,
+            pipeline,
+            labels[1],
+            position=vec3(1 / labels.len, 0.1 + progress * 0.5),
+            color=vec4(1, 1, 1, 1),
+          )
+          bindDescriptorSet(commandbuffer, ds3, 0, pipeline)
+          render(
+            commandbuffer,
+            pipeline,
+            labels[2],
+            position=vec3(2 / labels.len, 0.1 + progress * 0.5),
+            color=vec4(1, 1, 1, 1),
+          )
 
       # cleanup
   checkVkResult vkDeviceWaitIdle(vulkan.device)
@@ -100,11 +134,19 @@
   destroyRenderData(renderdata)
 
 proc test_03_layouting(time: float32) =
+  var font = loadFont("DejaVuSans.ttf", lineHeightPixels = 40)
   var renderdata = initRenderData()
 
-  var pipeline = createPipeline[DefaultFontShader](renderPass = vulkan.swapchain.renderPass)
+  var pipeline = createPipeline[DefaultFontShader[FontDS]](renderPass = vulkan.swapchain.renderPass)
 
-  var font = loadFont("DejaVuSans.ttf", lineHeightPixels = 40)
+  var ds = asDescriptorSetData(FontDS(fontAtlas: font.fontAtlas))
+  uploadImages(renderdata, ds)
+  initDescriptorSet(
+    renderdata,
+    pipeline.layout(0),
+    ds,
+  )
+
   var labels: seq[Textbox]
 
   for horizontal in HorizontalAlignment:
@@ -112,10 +154,8 @@
       renderdata,
       pipeline.layout(0),
       font,
+      0.001,
       $horizontal & " aligned",
-      color = vec4(1, 1, 1, 1),
-      scale = 0.001,
-      position = vec3(0, 0.9 - (horizontal.float * 0.15)),
       horizontalAlignment = horizontal,
     )
   for vertical in VerticalAlignment:
@@ -123,37 +163,33 @@
       renderdata,
       pipeline.layout(0),
       font,
+      0.001,
       $vertical & " aligned",
-      color = vec4(1, 1, 1, 1),
-      scale = 0.001,
-      position = vec3(-0.35 + (vertical.float * 0.35), 0.3),
       verticalAlignment = vertical,
     )
   labels.add initTextbox(
     renderdata,
     pipeline.layout(0),
     font,
+    0.001,
     """Paragraph
 This is a somewhat longer paragraph with a few newlines and a maximum width of 0.2.
 
 It should display with some space above and have a pleasing appearance overall! :)""",
     maxWidth = 0.6,
-    color = vec4(1, 1, 1, 1),
-    scale = 0.001,
-    position = vec3(-0.9, 0.1),
     verticalAlignment = Top,
     horizontalAlignment = Left,
   )
 
-
   var start = getMonoTime()
   while ((getMonoTime() - start).inMilliseconds().int / 1000) < time:
     let progress = ((getMonoTime() - start).inMilliseconds().int / 1000) / time
     withNextFrame(framebuffer, commandbuffer):
+      bindDescriptorSet(commandbuffer, ds, 0, pipeline)
       withRenderPass(vulkan.swapchain.renderPass, framebuffer, commandbuffer, vulkan.swapchain.width, vulkan.swapchain.height, vec4(0, 0, 0, 0)):
         withPipeline(commandbuffer, pipeline):
-          for label in labels:
-            render(commandbuffer, pipeline, label)
+          for i in 0 ..< labels.len:
+            render(commandbuffer, pipeline, labels[i], vec3(0.5 - i.float32 * 0.1, 0.5 - i.float32 * 0.1), vec4(1, 1, 1, 1))
 
       # cleanup
   checkVkResult vkDeviceWaitIdle(vulkan.device)
@@ -161,33 +197,45 @@
   destroyRenderData(renderdata)
 
 proc test_04_lots_of_texts(time: float32) =
+  var font = loadFont("DejaVuSans.ttf", lineHeightPixels = 160)
   var renderdata = initRenderData()
 
-  var pipeline = createPipeline[DefaultFontShader](renderPass = vulkan.swapchain.renderPass)
+  var pipeline = createPipeline[DefaultFontShader[FontDS]](renderPass = vulkan.swapchain.renderPass)
 
-  var font = loadFont("DejaVuSans.ttf", lineHeightPixels = 160)
+  var ds = asDescriptorSetData(FontDS(fontAtlas: font.fontAtlas))
+  uploadImages(renderdata, ds)
+  initDescriptorSet(
+    renderdata,
+    pipeline.layout(0),
+    ds,
+  )
+
   var labels: seq[Textbox]
+  var positions = newSeq[Vec3f](100)
+  var colors = newSeq[Vec4f](100)
+  var scales = newSeq[float32](100)
   for i in 0 ..< 100:
+    positions[i] = vec3(rand(-0.5 .. 0.5), rand(-0.5 .. 0.5), rand(-0.1 .. 0.1))
+    colors[i] = vec4(rand(0.5 .. 1.0), rand(0.5 .. 1.0), rand(0.5 .. 1.0), rand(0.5 .. 1.0))
+    scales[i] = rand(0.5'f32 .. 1.5'f32)
     labels.add initTextbox(
       renderdata,
       pipeline.layout(0),
       font,
+      0.001,
       $i,
-      color = vec4(rand(0.5 .. 1.0), rand(0.5 .. 1.0), rand(0.5 .. 1.0), rand(0.5 .. 1.0)),
-      scale = rand(0.0002 .. 0.002),
-      position = vec3(rand(-0.5 .. 0.5), rand(-0.5 .. 0.5), rand(-0.1 .. 0.1))
     )
-  labels.sort(proc(x, y: Textbox): int = cmp(x.position.z, y.position.z), Ascending)
 
   var start = getMonoTime()
   while ((getMonoTime() - start).inMilliseconds().int / 1000) < time:
     for l in labels.mitems:
       l.refresh()
     withNextFrame(framebuffer, commandbuffer):
+      bindDescriptorSet(commandbuffer, ds, 0, pipeline)
       withRenderPass(vulkan.swapchain.renderPass, framebuffer, commandbuffer, vulkan.swapchain.width, vulkan.swapchain.height, vec4(0, 0, 0, 0)):
         withPipeline(commandbuffer, pipeline):
-          for l in labels:
-            render(commandbuffer, pipeline, l)
+          for i in 0 ..< labels.len:
+            render(commandbuffer, pipeline, labels[i], positions[i], colors[i], scales[i])
 
         # cleanup
   checkVkResult vkDeviceWaitIdle(vulkan.device)