# HG changeset patch # User sam # Date 1734005863 -25200 # Node ID 9ca552dad5fcd09def18adb7bc4d15ca003699d4 # Parent ca3299ea1bdf4e5daa5f0edb57bd5353e0a80d87 did: continue working on new glyph-renderer diff -r ca3299ea1bdf -r 9ca552dad5fc semicongine/rendering/renderer.nim --- 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 diff -r ca3299ea1bdf -r 9ca552dad5fc semicongine/rendering/shaders.nim --- 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): diff -r ca3299ea1bdf -r 9ca552dad5fc semicongine/text.nim --- 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.} diff -r ca3299ea1bdf -r 9ca552dad5fc tests/test_text.nim --- 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)