This commit is contained in:
2025-01-12 10:29:11 -05:00
parent 470800af2a
commit 207fa94803
4 changed files with 105 additions and 86 deletions

View File

@@ -1,52 +1,68 @@
# Backend Guide
The end-user needs adapt this library for hookup into their own codebase. As an example they may see the [examples](../examples/) and [backend](../backend/) for working code of what this guide will go over.
The end-user needs to adapt this library to hook into their own codebase. For reference, they can check the [examples](../examples/) and [backend](../backend/) directories for working code that demonstrates what this guide covers.
When rendering text, the two products the user has to deal with: The text to draw and their "layering". Similar to UIs text should be drawn in layer batches, where each layer can represent a pass on some arbitrary set of distictions between the other layers.
When rendering text, users need to handle two main aspects: the text to draw and its "layering". Similar to UIs, text should be drawn in layer batches, where each layer can represent a pass with arbitrary distinctions from other layers.
The following are generally needed:
The following components are required:
* Vertex and Index Buffers for glyph meshes
* Glyph shader for rendering the glyph to the glyph buffer
* Atlas shader for blitting the upscaled glyph quads from the glyph buffer to an atlas region slot downsampled.
* Glyph shader for rendering glyphs to the glyph buffer
* Atlas shader for blitting upscaled glyph quads from the glyph buffer to an atlas region slot (downsampled)
* "Screen or Target" shader for blitting glyph quads from the atlas to a render target or swapchain
* The glyph, atlas, and some "target" image buffers
* The glyph, atlas, and target image buffers
Currently the library doesn't support sub-pixel AA so we're just rendering to R8 images.
Currently, the library doesn't support sub-pixel AA, so we're only rendering to R8 images.
## There are four passes that need to be handled when rendering a draw list
## Rendering Passes
There are four passes that need to be handled when rendering a draw list:
* Glyph: Rendering a glyph mesh to the glyph buffer
* Atlas: Blitting a glyph quad from the glyph buffer to an atlas slot
* Target: Blit from the atlas image to the target image
* Target_Uncached: Blit from the glyph buffer image to the target image
* Target: Blitting from the atlas image to the target image
* Target_Uncached: Blitting from the glyph buffer image to the target image
The Target & Target_Uncached passes can technically be handled in the same case. The user just needs to swap out using the atlas image with the glyph buffer image. This is how the backend_soko.odin's `render_text_layer` has those passes setup.
The Target & Target_Uncached passes can technically be handled in the same case. The user just needs to swap between using the atlas image and the glyph buffer image. This is how the backend_soko.odin's `render_text_layer` has these passes set up.
## The vertex buffer will have the following alyout for all passes
## Vertex Buffer Layout
`[2]f32` for positions
`[2]f32` for texture coords (Offset is naturally `[2]f32`)
With a total stride of `[4]f32`
The vertex buffer has the following layout for all passes:
* `[2]f32` for positions
* `[2]f32` for texture coords (Offset is naturally `[2]f32`)
* Total stride: `[4]f32`
---
The index buffer is just a u32 stream.
The index buffer is a simple u32 stream.
For how a quad mesh is laid out see `blit_quad` in [draw.odin](../vefontcache/draw.odin)
For quad mesh layout details, see `blit_quad` in [draw.odin](../vefontcache/draw.odin).
For how glyph shape triangulation meshes, the library currently only uses a triangle fanning technique so `fill_path_via_fan_triangulation` within [draw.odin](../vefontcache/draw.odin) is where that is being done. Eventually the libary will also support other modes on a per-font basis.
For glyph shape triangulation meshes, the library currently only uses a triangle fanning technique, implemented in `fill_path_via_fan_triangulation` within [draw.odin](../vefontcache/draw.odin). Eventually, the library will support other modes on a per-font basis.
## Keep in mind GLSL vs HLSL UV (texture) coordinate convention
## UV Coordinate Conventions (GLSL vs HLSL)
The UV coordinates used DirectX, Metal, and Vulkan all consider the top-left corner (0, 0), Where the Y axis increases downwards (traditional screenspace). This library follows the convention of (0, 0) being at the bottom-left (Y goes up) which is what OpenGL uses.
DirectX, Metal, and Vulkan consider the top-left corner as (0, 0), where the Y axis increases downward (traditional screenspace). This library follows OpenGL's convention, where (0, 0) is at the bottom-left (Y goes up).
In the shader the UV just has to be adjusted accordingly:
Adjust the UV coordinates in your shader accordingly:
```c
#if ! OpenGL
uv = vec2( v_texture.x, 1.0 - v_texture.y );
#if !OpenGL
uv = vec2(v_texture.x, 1.0 - v_texture.y);
#else
uv = vec2( v_texture.x, v_texture.y );
uv = vec2(v_texture.x, v_texture.y);
#endif
```
Eventually, the library will support both conventions as a comp-time conditional.
## Retrieving & Processing the layer
`get_draw_list_layer` will provide the layer's vertex, index, and draw call slices. Unless the default is overwritten, it will call `optimize_draw_list` before returning the slices (profile to see whats better for your use case).
Once those are retrived, call `flush_draw_list_layer` to update the layer offsets tracked by the library's `Context`.
The vertex and index slices just needed to be appended to your backend's vertex and index buffers.
The draw calls need to be iterated with a switch statement for the aforementioned pass types. Within the case you can construct the enqueue the passes.
---