Compare commits

..

7 Commits

5 changed files with 90 additions and 20 deletions

View File

@@ -321,6 +321,10 @@ layout :: proc(layer: ^renderer.Layer) {
border_color = {0, 0, 0, 1},
border_width = 10,
)
renderer.prepare_quad(layer, test_quad)
text_ok, text := renderer.text(0, "Raw Text", {bounds.x + 80, bounds.y + 80})
if text_ok {
renderer.prepare_text(layer, text)
}
}

View File

@@ -13,8 +13,8 @@ fi
# Convert GLSL to SPIRV
echo "Converting GLSL shaders to SPIRV..."
mkdir -p renderer/res/shaders/compiled
cd renderer/res/shaders/raw || exit
mkdir -p res/shaders/compiled
cd res/shaders/raw || exit
glslangValidator -V quad.vert -o ../compiled/quad.vert.spv
glslangValidator -V quad.frag -o ../compiled/quad.frag.spv
glslangValidator -V text.vert -o ../compiled/text.vert.spv

View File

@@ -211,7 +211,7 @@ draw_quads :: proc(
) {
using global
if layer.quad_len == 0 {
if layer.quad_instance_len == 0 {
return
}

View File

@@ -33,6 +33,7 @@ Global :: struct {
tmp_quads: [dynamic]Quad,
max_tmp_quads: int,
clay_mem: [^]u8,
clay_z_index: i16,
odin_context: runtime.Context,
quad_pipeline: QuadPipeline,
text_pipeline: TextPipeline,
@@ -68,6 +69,7 @@ clear_global :: proc() {
using global
curr_layer_index = 0
clay_z_index = 0
clear(&layers)
clear(&scissors)
clear(&tmp_text)
@@ -86,7 +88,7 @@ Rectangle :: struct {
Layer :: struct {
bounds: Rectangle,
quad_instance_start: u32,
quad_len: u32,
quad_instance_len: u32,
text_instance_start: u32,
text_instance_len: u32,
text_vertex_start: u32,
@@ -184,19 +186,20 @@ begin_prepare :: proc(bounds: Rectangle) -> ^Layer {
}
/// Creates a new layer
new_layer :: proc(old_layer: ^Layer, bounds: Rectangle) -> ^Layer {
new_layer :: proc(prev_layer: ^Layer, bounds: Rectangle) -> ^Layer {
using global
layer := Layer {
bounds = bounds,
quad_instance_start = old_layer.quad_instance_start + old_layer.quad_len,
text_instance_start = old_layer.text_instance_start + old_layer.text_instance_len,
text_vertex_start = old_layer.text_vertex_start + old_layer.text_vertex_len,
text_index_start = old_layer.text_index_start + old_layer.text_instance_len,
scissor_start = old_layer.scissor_start + old_layer.scissor_len,
quad_instance_start = prev_layer.quad_instance_start + prev_layer.quad_instance_len,
text_instance_start = prev_layer.text_instance_start + prev_layer.text_instance_len,
text_vertex_start = prev_layer.text_vertex_start + prev_layer.text_vertex_len,
text_index_start = prev_layer.text_index_start + prev_layer.text_index_len,
scissor_start = prev_layer.scissor_start + prev_layer.scissor_len,
scissor_len = 1,
}
append(&layers, layer)
curr_layer_index += 1
log.debug("Added new layer; curr index", curr_layer_index)
scissor := Scissor {
bounds = sdl.Rect {
@@ -227,10 +230,26 @@ prepare_quad :: proc(layer: ^Layer, quad: Quad) {
using global
append(&tmp_quads, quad)
layer.quad_len += 1
layer.quad_instance_len += 1
scissors[layer.scissor_start + layer.scissor_len - 1].quad_len += 1
}
// TODO need to make sure no overlap with clay render command IDs
prepare_text :: proc(layer: ^Layer, text: Text) {
using global
data := sdl_ttf.GetGPUTextDrawData(text.ref)
if data == nil {
log.error("Failed to find GPUTextDrawData for sdl_text")
}
append(&tmp_text, text)
layer.text_instance_len += 1
layer.text_vertex_len += u32(data.num_vertices)
layer.text_index_len += u32(data.num_indices)
scissors[layer.scissor_start + layer.scissor_len - 1].text_len += 1
}
// ====== Clay-specific processing ======
ClayBatch :: struct {
bounds: Rectangle,
@@ -239,7 +258,7 @@ ClayBatch :: struct {
/// Upload data to the GPU
prepare_clay_batch :: proc(
layer: ^Layer,
base_layer: ^Layer,
mouse_pos: [2]f32,
mouse_flags: sdl.MouseButtonFlags,
mouse_wheel_delta: [2]f32,
@@ -250,14 +269,17 @@ prepare_clay_batch :: proc(
// Update clay internals
clay.SetPointerState(
clay.Vector2{mouse_pos.x - layer.bounds.x, mouse_pos.y - layer.bounds.y},
clay.Vector2{mouse_pos.x - base_layer.bounds.x, mouse_pos.y - base_layer.bounds.y},
.LEFT in mouse_flags,
)
clay.UpdateScrollContainers(true, transmute(clay.Vector2)mouse_wheel_delta, frame_time)
layer := base_layer
// Parse render commands
for i in 0 ..< int(batch.cmds.length) {
render_command := clay.RenderCommandArray_Get(&batch.cmds, cast(i32)i)
// Translate bounding box of the primitive by the layer position
bounds := Rectangle {
x = render_command.boundingBox.x + layer.bounds.x,
@@ -266,6 +288,18 @@ prepare_clay_batch :: proc(
h = render_command.boundingBox.height,
}
if render_command.zIndex > clay_z_index {
log.debug(
"Higher zIndex found, creating new layer & setting z_index to",
render_command.zIndex,
)
layer = new_layer(layer, bounds)
// Update bounds to new layer offset
bounds.x = render_command.boundingBox.x + layer.bounds.x
bounds.y = render_command.boundingBox.y + layer.bounds.y
clay_z_index = render_command.zIndex
}
switch (render_command.commandType) {
case clay.RenderCommandType.None:
case clay.RenderCommandType.Text:
@@ -347,7 +381,7 @@ prepare_clay_batch :: proc(
}
append(&tmp_quads, quad)
layer.quad_len += 1
layer.quad_instance_len += 1
scissors[layer.scissor_start + layer.scissor_len - 1].quad_len += 1
case clay.RenderCommandType.Border:
render_data := render_command.renderData.border
@@ -363,7 +397,7 @@ prepare_clay_batch :: proc(
// Technically these should be drawn on top of everything else including children, but
// for our use case we can just chuck these in with the quad pipeline
append(&tmp_quads, quad)
layer.quad_len += 1
layer.quad_instance_len += 1
scissors[layer.scissor_start + layer.scissor_len - 1].quad_len += 1
case clay.RenderCommandType.Custom:
}
@@ -386,6 +420,7 @@ draw :: proc(device: ^sdl.GPUDevice, window: ^sdl.Window, cmd_buffer: ^sdl.GPUCo
}
for &layer, index in layers {
log.debug("Drawing layer", index)
draw_quads(
device,
window,

View File

@@ -61,6 +61,38 @@ Text :: struct {
color: [4]f32,
}
text :: proc(
id: u32,
txt: cstring,
pos: [2]f32,
color: [4]f32 = {0.0, 0.0, 0.0, 1.0},
font_id: u16 = JETBRAINS_MONO_REGULAR,
font_size: u16 = 44,
) -> (bool, Text) {
using global
sdl_text := text_pipeline.cache[id]
if sdl_text == nil {
sdl_text = sdl_ttf.CreateText(text_pipeline.engine, get_font(font_id, font_size), txt, 0)
text_pipeline.cache[id] = sdl_text
} else {
//TODO if IDs are always unique and never change the underlying text
// can get rid of this
_ = sdl_ttf.SetTextString(sdl_text, txt, 0)
}
if sdl_text == nil {
log.error("Could not create SDL text:", sdl.GetError())
return false, Text {}
} else {
return true, Text {
sdl_text,
pos,
color,
}
}
}
// For upload
TextVert :: struct {
pos_uv: [4]f32,
@@ -383,9 +415,8 @@ draw_text :: proc(
atlas: ^sdl.GPUTexture
layer_text := tmp_text[layer.text_instance_start:layer.text_instance_start +
layer.text_instance_len]
index_offset: u32 = layer.text_instance_start
layer_text := tmp_text[layer.text_instance_start:][:layer.text_instance_len]
index_offset: u32 = layer.text_index_start
vertex_offset: i32 = i32(layer.text_vertex_start)
instance_offset: u32 = layer.text_instance_start
@@ -396,7 +427,7 @@ draw_text :: proc(
sdl.SetGPUScissor(render_pass, scissor.bounds)
for &text in layer_text[scissor.text_start:scissor.text_start + scissor.text_len] {
for &text in layer_text[scissor.text_start:][:scissor.text_len] {
data := sdl_ttf.GetGPUTextDrawData(text.ref)
for data != nil {