Mercurial > games > semicongine
changeset 1406:aeb15aa9768c
did: continue text layout, improve vector api
author | sam <sam@basx.dev> |
---|---|
date | Sat, 21 Dec 2024 19:32:59 +0700 |
parents | 46bac138ad6c |
children | 56f927b89716 |
files | semicongine/core/vector.nim semicongine/text.nim tests/test_text.nim |
diffstat | 3 files changed, 62 insertions(+), 63 deletions(-) [+] |
line wrap: on
line diff
--- a/semicongine/core/vector.nim Sat Dec 21 00:19:11 2024 +0700 +++ b/semicongine/core/vector.nim Sat Dec 21 19:32:59 2024 +0700 @@ -450,30 +450,30 @@ TVec4[T]([vec[0] / l, vec[1] / l, vec[2] / l, vec[3] / l]) # scalar operations -func `+`*(a: TVec1, b: SomeNumber): auto = - TVec1([a[0] + b]) -func `+`*(a: TVec2, b: SomeNumber): auto = - TVec2([a[0] + b, a[1] + b]) -func `+`*(a: TVec3, b: SomeNumber): auto = - TVec3([a[0] + b, a[1] + b, a[2] + b]) -func `+`*(a: TVec4, b: SomeNumber): auto = - TVec4([a[0] + b, a[1] + b, a[2] + b, a[3] + b]) -func `-`*(a: TVec1, b: SomeNumber): auto = - TVec1([a[0] - b]) -func `-`*(a: TVec2, b: SomeNumber): auto = - TVec2([a[0] - b, a[1] - b]) -func `-`*(a: TVec3, b: SomeNumber): auto = - TVec3([a[0] - b, a[1] - b, a[2] - b]) -func `-`*(a: TVec4, b: SomeNumber): auto = - TVec4([a[0] - b, a[1] - b, a[2] - b, a[3] - b]) -func `*`*(a: TVec1, b: SomeNumber): auto = - TVec1([a[0] * b]) -func `*`*(a: TVec2, b: SomeNumber): auto = - TVec2([a[0] * b, a[1] * b]) -func `*`*(a: TVec3, b: SomeNumber): auto = - TVec3([a[0] * b, a[1] * b, a[2] * b]) -func `*`*(a: TVec4, b: SomeNumber): auto = - TVec4([a[0] * b, a[1] * b, a[2] * b, a[3] * b]) +func `+`*[T](a: TVec1[T], b: SomeNumber): auto = + TVec1([a[0] + T(b)]) +func `+`*[T](a: TVec2[T], b: SomeNumber): auto = + TVec2([a[0] + T(b), a[1] + T(b)]) +func `+`*[T](a: TVec3[T], b: SomeNumber): auto = + TVec3([a[0] + T(b), a[1] + T(b), a[2] + T(b)]) +func `+`*[T](a: TVec4[T], b: SomeNumber): auto = + TVec4([a[0] + T(b), a[1] + T(b), a[2] + T(b), a[3] + T(b)]) +func `-`*[T](a: TVec1[T], b: SomeNumber): auto = + TVec1([a[0] - T(b)]) +func `-`*[T](a: TVec2[T], b: SomeNumber): auto = + TVec2([a[0] - T(b), a[1] - T(b)]) +func `-`*[T](a: TVec3[T], b: SomeNumber): auto = + TVec3([a[0] - T(b), a[1] - T(b), a[2] - T(b)]) +func `-`*[T](a: TVec4[T], b: SomeNumber): auto = + TVec4([a[0] - T(b), a[1] - T(b), a[2] - T(b), a[3] - T(b)]) +func `*`*[T](a: TVec1[T], b: SomeNumber): auto = + TVec1([a[0] * T(b)]) +func `*`*[T](a: TVec2[T], b: SomeNumber): auto = + TVec2([a[0] * T(b), a[1] * T(b)]) +func `*`*[T](a: TVec3[T], b: SomeNumber): auto = + TVec3([a[0] * T(b), a[1] * T(b), a[2] * T(b)]) +func `*`*[T](a: TVec4[T], b: SomeNumber): auto = + TVec4([a[0] * T(b), a[1] * T(b), a[2] * T(b), a[3] * T(b)]) func `div`*[T, S: SomeInteger](a: TVec1[T], b: S): auto = TVec1[T]([a[0] div T(b)]) func `/`*[T, S: SomeFloat](a: TVec1[T], b: S): auto =
--- a/semicongine/text.nim Sat Dec 21 00:19:11 2024 +0700 +++ b/semicongine/text.nim Sat Dec 21 19:32:59 2024 +0700 @@ -79,17 +79,12 @@ void main() { int vertexI = indices[gl_VertexIndex]; - vec3 pos = vec3( + vec3 vertexPos = vec3( glyphquads.pos[glyphIndex][i_x[vertexI]] * scale / textRendering.aspectRatio, glyphquads.pos[glyphIndex][i_y[vertexI]] * scale, 1 - (gl_InstanceIndex + 1) * epsilon // allows overlapping glyphs to make proper depth test ); - vec3 offset = vec3( - (position.x - textRendering.aspectRatio + 1) / textRendering.aspectRatio, - position.y, - position.z - ); - gl_Position = vec4(pos + offset, 1.0); + gl_Position = vec4(vertexPos + position, 1.0); vec2 uv = vec2(glyphquads.uv[glyphIndex][i_x[vertexI]], glyphquads.uv[glyphIndex][i_y[vertexI]]); fragmentUv = uv; fragmentColor = color; @@ -135,11 +130,11 @@ result += font.advance[font.fallbackCharacter] * scale if i < text.len - 1: result += font.kerning.getOrDefault((text[i], text[i + 1]), 0) * scale - return result * 0.5 / getAspectRatio() + return result proc textDimension*(font: Font, text: seq[Rune], scale: float32): Vec2f = let nLines = text.countIt(it == Rune('\n')).float32 - let h = (nLines * font.lineAdvance * scale + font.lineHeight * scale) * 0.5 + let h = (nLines * font.lineAdvance * scale + font.lineHeight * scale) let w = max(splitLines(text).toSeq.mapIt(width(font, it, scale))) return vec2(w, h) @@ -149,7 +144,7 @@ text: seq[Rune], position: Vec3f, alignment: TextAlignment = Left, - anchor: Vec2f = vec2(0, 1), + anchor: Vec2f = vec2(-1, 1), scale: float32 = 1'f32, color: Vec4f = vec4(1, 1, 1, 1), ) = @@ -165,17 +160,16 @@ let globalScale = scale * glyphs.baseScale dim = textDimension(glyphs.font, text, globalScale) - baselineStart = vec2(0, glyphs.font.ascent * globalScale * 0.5) + baselineStart = vec2(0, glyphs.font.ascent * globalScale) pos = position.xy - anchor * dim + baselineStart # lineWidths need to be converted to NDC lineWidths = splitLines(text).toSeq.mapIt(width(glyphs.font, it, globalScale)) # also dimension must be in NDC maxWidth = dim.x + aratio = getAspectRatio() var - origin = vec3( - pos.x * getAspectRatio() * 2'f32 - 1'f32, -(pos.y * 2'f32 - 1'f32), position.z - ) + origin = vec3(pos.x, pos.y, position.z) cursorPos = origin lineI = 0 @@ -185,7 +179,7 @@ of Center: cursorPos.x = origin.x + ((maxWidth - lineWidths[lineI]) / 2) of Right: - cursorPos.x = origin.x + (maxWidth - lineWidths[lineI]) * getAspectRatio() * 2 + cursorPos.x = origin.x + (maxWidth - lineWidths[lineI]) * aratio * 2 for i in 0 ..< text.len: if text[i] == Rune('\n'): @@ -196,7 +190,7 @@ of Center: cursorPos.x = origin.x + ((maxWidth - lineWidths[lineI]) / 2) of Right: - cursorPos.x = origin.x + (maxWidth - lineWidths[lineI]) * getAspectRatio() * 2 + cursorPos.x = origin.x + (maxWidth - lineWidths[lineI]) * aratio * 2 cursorPos.y = cursorPos.y - glyphs.font.lineAdvance * globalScale else: if not text[i].isWhitespace(): @@ -211,15 +205,17 @@ inc glyphs.cursor if text[i] in glyphs.font.advance: - cursorPos.x = cursorPos.x + glyphs.font.advance[text[i]] * globalScale + cursorPos.x = cursorPos.x + glyphs.font.advance[text[i]] * globalScale / aratio else: cursorPos.x = - cursorPos.x + glyphs.font.advance[glyphs.font.fallbackCharacter] * globalScale + cursorPos.x + + glyphs.font.advance[glyphs.font.fallbackCharacter] * globalScale / aratio if i < text.len - 1: cursorPos.x = cursorPos.x + - glyphs.font.kerning.getOrDefault((text[i], text[i + 1]), 0) * globalScale + glyphs.font.kerning.getOrDefault((text[i], text[i + 1]), 0) * globalScale / + aratio proc add*( glyphs: var Glyphs,
--- a/tests/test_text.nim Sat Dec 21 00:19:11 2024 +0700 +++ b/tests/test_text.nim Sat Dec 21 19:32:59 2024 +0700 @@ -123,15 +123,13 @@ destroyRenderData(renderdata) proc test_03_layouting(time: float32) = - var font = loadFont[MAX_CODEPOINTS]("DejaVuSans.ttf", lineHeightPixels = 40) + var font = loadFont[MAX_CODEPOINTS]("DejaVuSans.ttf", lineHeightPixels = 160) var renderdata = initRenderData() var pipeline = createPipeline[GlyphShader[MAX_CODEPOINTS]]( renderPass = vulkan.swapchain.renderPass ) - var ds = asDescriptorSetData(FontDS(fontAtlas: font.fontAtlas.copy())) - assignBuffers(renderdata, font.descriptorSet) uploadImages(renderdata, font.descriptorSet) initDescriptorSet(renderdata, pipeline.layout(0), font.descriptorSet) @@ -139,23 +137,28 @@ var glyphs = font.initGlyphs(1000, baseScale = 0.1) assignBuffers(renderdata, glyphs) - for horizontal in HorizontalAlignment: - glyphs.add $horizontal & " aligned" - for vertical in VerticalAlignment: - glyphs.add $vertical & " aligned" - - glyphs.add( - """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! :)""", - verticalAlignment = Top, - horizontalAlignment = Left, - ) - var start = getMonoTime() while ((getMonoTime() - start).inMilliseconds().int / 1000) < time: let progress = ((getMonoTime() - start).inMilliseconds().int / 1000) / time + + glyphs.reset() + glyphs.add("Anchor Center", vec3(0, 0), anchor = vec2(0, 0)) + glyphs.add("Anchor top left", vec3(0, 0), anchor = vec2(-1, 1)) + glyphs.add("Anchor top right", vec3(0, 0), anchor = vec2(1, 1)) + glyphs.add("Anchor bottom left", vec3(0, 0), anchor = vec2(-1, -1)) + glyphs.add("Anchor bottom right", vec3(0, 0), anchor = vec2(1, -1)) + + glyphs.add( + """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! :)""", + vec3(0.5, 0.5), + anchor = vec2(0, 0), + alignment = Center, + ) + glyphs.updateAllGPUBuffers(flush = true) + withNextFrame(framebuffer, commandbuffer): bindDescriptorSet(commandbuffer, font.descriptorSet, 0, pipeline) withRenderPass( @@ -225,7 +228,7 @@ ]# when isMainModule: - var time = 1'f32 + var time = 100'f32 initVulkan() for depthBuffer in [true, false]: @@ -233,8 +236,8 @@ setupSwapchain(renderpass = renderpass) # tests a simple triangle with minimalistic shader and vertex format - test_01_static_label(time) - test_02_multi_counter(time) + # test_01_static_label(time) + # test_02_multi_counter(time) test_03_layouting(time) # test_04_lots_of_texts(time)