changeset 1379:9ca552dad5fc

did: continue working on new glyph-renderer
author sam <sam@basx.dev>
date Thu, 12 Dec 2024 19:17:43 +0700
parents ca3299ea1bdf
children 4aa9e703af48
files semicongine/rendering/renderer.nim semicongine/rendering/shaders.nim semicongine/text.nim tests/test_text.nim
diffstat 4 files changed, 59 insertions(+), 39 deletions(-) [+]
line wrap: on
line diff
--- a/semicongine/rendering/renderer.nim	Sat Dec 07 21:34:24 2024 +0700
+++ b/semicongine/rendering/renderer.nim	Thu Dec 12 19:17:43 2024 +0700
@@ -87,7 +87,8 @@
   # santization checks
   for theName, value in descriptorSet.data.fieldPairs:
     when typeof(value) is GPUValue:
-      assert value.buffer.vk.Valid
+      assert value.buffer.vk.Valid,
+        "Invalid buffer, did you call 'assignBuffers' for this buffer?"
     elif typeof(value) is ImageObject:
       assert value.vk.Valid
       assert value.imageview.Valid
--- a/semicongine/rendering/shaders.nim	Sat Dec 07 21:34:24 2024 +0700
+++ b/semicongine/rendering/shaders.nim	Thu Dec 12 19:17:43 2024 +0700
@@ -80,7 +80,7 @@
     {.error: "Unsupported data type on GPU: " & n.}
 
 func glslType[T: SupportedGPUType](value: openArray[T]): string =
-  return glslType(default(T)) & "[]"
+  return glslType(default(T)) & "[" & $len(value) & "]"
 
 func vkType[T: SupportedGPUType](value: T): VkFormat =
   when T is float32:
@@ -323,7 +323,11 @@
             uniforms.add "} " & descriptorName & "[" & $descriptorValue.len & "];"
             descriptorBinding.inc
           else:
-            {.error: "Unsupported shader descriptor field " & descriptorName.}
+            {.
+              error:
+                "Unsupported shader descriptor field " & descriptorName & ": " &
+                $(typeof(descriptorValue))
+            .}
     elif fieldname in ["vertexCode", "fragmentCode"]:
       discard
     elif hasCustomPragma(value, PushConstant):
--- a/semicongine/text.nim	Sat Dec 07 21:34:24 2024 +0700
+++ b/semicongine/text.nim	Thu Dec 12 19:17:43 2024 +0700
@@ -69,12 +69,19 @@
     color = vec4(textbox.color.rgb, textbox.color.a * v);
 }"""
 
-  GlyphDescriptors[N: static int] = object
-    fontAtlas: Image[Gray]
-    uvs1: array[N, Vec2f]
-    uvs2: array[N, Vec2f]
-    vertexPos1: array[N, Vec2f]
-    vertexPos2: array[N, Vec2f]
+  Glyphs* = object
+    position*: GPUArray[Vec3f, VertexBufferMapped]
+    color*: GPUArray[Vec4f, VertexBufferMapped]
+    scale*: GPUArray[float32, VertexBufferMapped]
+    glyphIndex*: GPUArray[uint16, VertexBufferMapped]
+
+  GlyphData[N: static int] = object
+    pos: array[N, Vec2f] # [left, bottom, right, top]
+    uv: array[N, Vec4f] # [left, bottom, right, top]
+
+  GlyphDescriptorSet*[N: static int] = object
+    fontAtlas*: Image[Gray]
+    glyphData*: GPUValue[GlyphData[N], StorageBuffer]
 
   GlyphShader*[N: static int] = object
     position {.InstanceAttribute.}: Vec3f
@@ -85,27 +92,32 @@
     fragmentUv {.Pass.}: Vec2f
     fragmentColor {.PassFlat.}: Vec4f
     outColor {.ShaderOutput.}: Vec4f
-    glyphData {.DescriptorSet: 0.}: GlyphDescriptors[N]
+    glyphData {.DescriptorSet: 0.}: GlyphDescriptorSet[N]
     vertexCode* =
-      """void main() {
-  vec2 uv1 = uvs1[glyphIndex];
-  vec2 uv2 = uvs2[glyphIndex];
-  vec2 p1 = vertexPos1[glyphIndex];
-  vec2 p2 = vertexPos2[glyphIndex];
-  uv1[gl_VertexIndex % ]
+      """
+const int[6] indices = int[](0, 1, 2, 2, 3, 0);
+const int[4] i_x = int[](0, 0, 2, 2);
+const int[4] i_y = int[](1, 3, 3, 1);
+const vec2[4] pp = vec2[](vec2(-0.1, -0.1), vec2(-0.1, 0.1), vec2(0.1, 0.1), vec2(0.1, -0.1));
 
-  gl_Position = vec4(position * vec3(textbox.scale, 1) + textbox.position, 1.0);
-  fragmentUv = uv;
-  fragmentColor = color;
+void main() {
+  // int vertexI = indices[gl_VertexIndex];
+  // vec3 pos = vec3(glyphData.pos[glyphIndex][i_x[vertexI]], glyphData.pos[glyphIndex][i_y[vertexI]], 0);
+  // vec2 uv = vec2(glyphData.uv[glyphIndex][i_x[vertexI]], glyphData.uv[glyphIndex][i_y[vertexI]]);
+  // gl_Position = vec4(pos * scale + position, 1.0);
+  // fragmentUv = uv;
+  // fragmentColor = color;
+  gl_Position = vec4(pp[indices[gl_VertexIndex]] + glyphIndex * 0.1, 0, 1);
 }  """
     fragmentCode* =
       """void main() {
-    float v = texture(fontAtlas, fragmentUv).r;
+    // float v = texture(fontAtlas, fragmentUv).r;
     // CARFULL: This can lead to rough edges at times
-    if(v == 0) {
-      discard;
-    }
-    outColor = vec4(fragmentColor.rgb, fragmentColor.a * v);
+    // if(v == 0) {
+      // discard;
+    // }
+    // outColor = vec4(fragmentColor.rgb, fragmentColor.a * v);
+    outColor = vec4(1, 0, 1, 1);
 }"""
 
 proc `=copy`(dest: var FontObj, source: FontObj) {.error.}
--- a/tests/test_text.nim	Sat Dec 07 21:34:24 2024 +0700
+++ b/tests/test_text.nim	Thu Dec 12 19:17:43 2024 +0700
@@ -12,13 +12,24 @@
 type FontDS = object
   fontAtlas: Image[Gray]
 
+type EMPTY = object
+
 proc test_01_static_label_new(time: float32) =
   var font = loadFont("Overhaul.ttf", lineHeightPixels = 160)
   var renderdata = initRenderData()
   var pipeline =
     createPipeline[GlyphShader[200]](renderPass = vulkan.swapchain.renderPass)
+  var glyphs = Glyphs(
+    position: asGPUArray([vec3()], VertexBufferMapped),
+    scale: asGPUArray([1'f32], VertexBufferMapped),
+    color: asGPUArray([vec4(1, 1, 1, 1)], VertexBufferMapped),
+    glyphIndex: asGPUArray([0'u16], VertexBufferMapped),
+  )
 
-  var ds = asDescriptorSetData(GlyphDescriptors[200](fontAtlas: font.fontAtlas.copy()))
+  var ds =
+    asDescriptorSetData(GlyphDescriptorSet[200](fontAtlas: font.fontAtlas.copy()))
+  assignBuffers(renderdata, glyphs)
+  assignBuffers(renderdata, ds)
   uploadImages(renderdata, ds)
   initDescriptorSet(renderdata, pipeline.layout(0), ds)
 
@@ -35,7 +46,7 @@
         vec4(0, 0, 0, 0),
       ):
         withPipeline(commandbuffer, pipeline):
-          render(commandbuffer, pipeline, label1, vec3(), vec4(1, 1, 1, 1))
+          render(commandbuffer, pipeline, EMPTY(), glyphs, fixedVertexCount = 6)
 
         # cleanup
   checkVkResult vkDeviceWaitIdle(vulkan.device)
@@ -69,15 +80,7 @@
         vec4(0, 0, 0, 0),
       ):
         withPipeline(commandbuffer, pipeline):
-          proc render(
-            commandBuffer = commandbuffer,
-            pipeline = pipeline,
-            mesh: TMesh,
-            instances: TInstance,
-            fixedVertexCount = -1,
-            fixedInstanceCount = -1,
-          )
-
+          render(commandbuffer, pipeline, label1, vec3(), vec4(1, 1, 1, 1))
         # cleanup
   checkVkResult vkDeviceWaitIdle(vulkan.device)
   destroyPipeline(pipeline)
@@ -288,10 +291,10 @@
 
     # tests a simple triangle with minimalistic shader and vertex format
     test_01_static_label_new(time)
-    test_01_static_label(time)
-    test_02_multiple_animated(time)
-    test_03_layouting(time)
-    test_04_lots_of_texts(time)
+    # test_01_static_label(time)
+    # test_02_multiple_animated(time)
+    # test_03_layouting(time)
+    # test_04_lots_of_texts(time)
 
     checkVkResult vkDeviceWaitIdle(vulkan.device)
     vkDestroyRenderPass(vulkan.device, renderpass.vk, nil)