Foramatting
This commit is contained in:
@@ -58,8 +58,8 @@ Rectangle :: struct {
|
|||||||
|
|
||||||
Sub_Batch_Kind :: enum u8 {
|
Sub_Batch_Kind :: enum u8 {
|
||||||
Shapes, // non-indexed, white texture, mode 0
|
Shapes, // non-indexed, white texture, mode 0
|
||||||
Text, // indexed, atlas texture, mode 0
|
Text, // indexed, atlas texture, mode 0
|
||||||
SDF, // instanced unit quad, white texture, mode 1
|
SDF, // instanced unit quad, white texture, mode 1
|
||||||
}
|
}
|
||||||
|
|
||||||
Sub_Batch :: struct {
|
Sub_Batch :: struct {
|
||||||
@@ -89,34 +89,34 @@ Scissor :: struct {
|
|||||||
GLOB: Global
|
GLOB: Global
|
||||||
|
|
||||||
Global :: struct {
|
Global :: struct {
|
||||||
odin_context: runtime.Context,
|
odin_context: runtime.Context,
|
||||||
pipeline_2d_base: Pipeline_2D_Base,
|
pipeline_2d_base: Pipeline_2D_Base,
|
||||||
text_cache: Text_Cache,
|
text_cache: Text_Cache,
|
||||||
layers: [dynamic]Layer,
|
layers: [dynamic]Layer,
|
||||||
scissors: [dynamic]Scissor,
|
scissors: [dynamic]Scissor,
|
||||||
tmp_shape_verts: [dynamic]Vertex,
|
tmp_shape_verts: [dynamic]Vertex,
|
||||||
tmp_text_verts: [dynamic]Vertex,
|
tmp_text_verts: [dynamic]Vertex,
|
||||||
tmp_text_indices: [dynamic]c.int,
|
tmp_text_indices: [dynamic]c.int,
|
||||||
tmp_text_batches: [dynamic]TextBatch,
|
tmp_text_batches: [dynamic]TextBatch,
|
||||||
tmp_primitives: [dynamic]Primitive,
|
tmp_primitives: [dynamic]Primitive,
|
||||||
tmp_sub_batches: [dynamic]Sub_Batch,
|
tmp_sub_batches: [dynamic]Sub_Batch,
|
||||||
clay_mem: [^]u8,
|
clay_mem: [^]u8,
|
||||||
msaa_texture: ^sdl.GPUTexture,
|
msaa_texture: ^sdl.GPUTexture,
|
||||||
curr_layer_index: uint,
|
curr_layer_index: uint,
|
||||||
max_layers: int,
|
max_layers: int,
|
||||||
max_scissors: int,
|
max_scissors: int,
|
||||||
max_shape_verts: int,
|
max_shape_verts: int,
|
||||||
max_text_verts: int,
|
max_text_verts: int,
|
||||||
max_text_indices: int,
|
max_text_indices: int,
|
||||||
max_text_batches: int,
|
max_text_batches: int,
|
||||||
max_primitives: int,
|
max_primitives: int,
|
||||||
max_sub_batches: int,
|
max_sub_batches: int,
|
||||||
dpi_scaling: f32,
|
dpi_scaling: f32,
|
||||||
msaa_w: u32,
|
msaa_w: u32,
|
||||||
msaa_h: u32,
|
msaa_h: u32,
|
||||||
sample_count: sdl.GPUSampleCount,
|
sample_count: sdl.GPUSampleCount,
|
||||||
clay_z_index: i16,
|
clay_z_index: i16,
|
||||||
cleared: bool,
|
cleared: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
Init_Options :: struct {
|
Init_Options :: struct {
|
||||||
@@ -186,8 +186,8 @@ init :: proc(
|
|||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO every x frames nuke max values in case of edge cases where max gets set very high
|
// TODO Either every x frames nuke max values in case of edge cases where max gets set very high
|
||||||
// Called at the end of every frame
|
// or leave to application code to decide the right time for resize
|
||||||
resize_global :: proc() {
|
resize_global :: proc() {
|
||||||
if len(GLOB.layers) > GLOB.max_layers do GLOB.max_layers = len(GLOB.layers)
|
if len(GLOB.layers) > GLOB.max_layers do GLOB.max_layers = len(GLOB.layers)
|
||||||
shrink(&GLOB.layers, GLOB.max_layers)
|
shrink(&GLOB.layers, GLOB.max_layers)
|
||||||
@@ -546,11 +546,7 @@ prepare_clay_batch :: proc(
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Render primitives. clear_color is the background fill before any layers are drawn.
|
// Render primitives. clear_color is the background fill before any layers are drawn.
|
||||||
end :: proc(
|
end :: proc(device: ^sdl.GPUDevice, window: ^sdl.Window, clear_color: Color = BLACK) {
|
||||||
device: ^sdl.GPUDevice,
|
|
||||||
window: ^sdl.Window,
|
|
||||||
clear_color: Color = BLACK,
|
|
||||||
) {
|
|
||||||
cmd_buffer := sdl.AcquireGPUCommandBuffer(device)
|
cmd_buffer := sdl.AcquireGPUCommandBuffer(device)
|
||||||
if cmd_buffer == nil {
|
if cmd_buffer == nil {
|
||||||
log.panicf("Failed to acquire GPU command buffer: %s", sdl.GetError())
|
log.panicf("Failed to acquire GPU command buffer: %s", sdl.GetError())
|
||||||
@@ -561,10 +557,6 @@ end :: proc(
|
|||||||
upload(device, copy_pass)
|
upload(device, copy_pass)
|
||||||
sdl.EndGPUCopyPass(copy_pass)
|
sdl.EndGPUCopyPass(copy_pass)
|
||||||
|
|
||||||
// Resize dynamic arrays
|
|
||||||
// TODO: This should only be called occasionally, not every frame.
|
|
||||||
resize_global()
|
|
||||||
|
|
||||||
swapchain_texture: ^sdl.GPUTexture
|
swapchain_texture: ^sdl.GPUTexture
|
||||||
w, h: u32
|
w, h: u32
|
||||||
if !sdl.WaitAndAcquireGPUSwapchainTexture(cmd_buffer, window, &swapchain_texture, &w, &h) {
|
if !sdl.WaitAndAcquireGPUSwapchainTexture(cmd_buffer, window, &swapchain_texture, &w, &h) {
|
||||||
|
|||||||
@@ -100,11 +100,11 @@ Shape_Params :: struct #raw_union {
|
|||||||
|
|
||||||
// GPU layout: 64 bytes, std430-compatible. The shader declares this as a storage buffer struct.
|
// GPU layout: 64 bytes, std430-compatible. The shader declares this as a storage buffer struct.
|
||||||
Primitive :: struct {
|
Primitive :: struct {
|
||||||
bounds: [4]f32, // 0: min_x, min_y, max_x, max_y (world-space, pre-DPI)
|
bounds: [4]f32, // 0: min_x, min_y, max_x, max_y (world-space, pre-DPI)
|
||||||
color: Color, // 16: u8x4, unpacked in shader via unpackUnorm4x8
|
color: Color, // 16: u8x4, unpacked in shader via unpackUnorm4x8
|
||||||
kind_flags: u32, // 20: (kind as u32) | (flags as u32 << 8)
|
kind_flags: u32, // 20: (kind as u32) | (flags as u32 << 8)
|
||||||
_pad: [2]f32, // 24: alignment to vec4 boundary
|
_pad: [2]f32, // 24: alignment to vec4 boundary
|
||||||
params: Shape_Params, // 32: two vec4s of shape params
|
params: Shape_Params, // 32: two vec4s of shape params
|
||||||
}
|
}
|
||||||
|
|
||||||
#assert(size_of(Primitive) == 64)
|
#assert(size_of(Primitive) == 64)
|
||||||
@@ -279,14 +279,14 @@ create_pipeline_2d_base :: proc(
|
|||||||
pipeline.white_texture = sdl.CreateGPUTexture(
|
pipeline.white_texture = sdl.CreateGPUTexture(
|
||||||
device,
|
device,
|
||||||
sdl.GPUTextureCreateInfo {
|
sdl.GPUTextureCreateInfo {
|
||||||
type = .D2,
|
type = .D2,
|
||||||
format = .R8G8B8A8_UNORM,
|
format = .R8G8B8A8_UNORM,
|
||||||
usage = {.SAMPLER},
|
usage = {.SAMPLER},
|
||||||
width = 1,
|
width = 1,
|
||||||
height = 1,
|
height = 1,
|
||||||
layer_count_or_depth = 1,
|
layer_count_or_depth = 1,
|
||||||
num_levels = 1,
|
num_levels = 1,
|
||||||
sample_count = ._1,
|
sample_count = ._1,
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
if pipeline.white_texture == nil {
|
if pipeline.white_texture == nil {
|
||||||
@@ -314,9 +314,13 @@ create_pipeline_2d_base :: proc(
|
|||||||
mem.copy(white_ptr, &white_pixel, size_of(white_pixel))
|
mem.copy(white_ptr, &white_pixel, size_of(white_pixel))
|
||||||
sdl.UnmapGPUTransferBuffer(device, white_transfer)
|
sdl.UnmapGPUTransferBuffer(device, white_transfer)
|
||||||
|
|
||||||
quad_verts := [6]Vertex{
|
quad_verts := [6]Vertex {
|
||||||
{position = {0, 0}}, {position = {1, 0}}, {position = {0, 1}},
|
{position = {0, 0}},
|
||||||
{position = {0, 1}}, {position = {1, 0}}, {position = {1, 1}},
|
{position = {1, 0}},
|
||||||
|
{position = {0, 1}},
|
||||||
|
{position = {0, 1}},
|
||||||
|
{position = {1, 0}},
|
||||||
|
{position = {1, 1}},
|
||||||
}
|
}
|
||||||
quad_transfer := sdl.CreateGPUTransferBuffer(
|
quad_transfer := sdl.CreateGPUTransferBuffer(
|
||||||
device,
|
device,
|
||||||
@@ -353,11 +357,7 @@ create_pipeline_2d_base :: proc(
|
|||||||
sdl.UploadToGPUBuffer(
|
sdl.UploadToGPUBuffer(
|
||||||
upload_pass,
|
upload_pass,
|
||||||
sdl.GPUTransferBufferLocation{transfer_buffer = quad_transfer},
|
sdl.GPUTransferBufferLocation{transfer_buffer = quad_transfer},
|
||||||
sdl.GPUBufferRegion{
|
sdl.GPUBufferRegion{buffer = pipeline.unit_quad_buffer, offset = 0, size = size_of(quad_verts)},
|
||||||
buffer = pipeline.unit_quad_buffer,
|
|
||||||
offset = 0,
|
|
||||||
size = size_of(quad_verts),
|
|
||||||
},
|
|
||||||
false,
|
false,
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -373,9 +373,9 @@ create_pipeline_2d_base :: proc(
|
|||||||
pipeline.sampler = sdl.CreateGPUSampler(
|
pipeline.sampler = sdl.CreateGPUSampler(
|
||||||
device,
|
device,
|
||||||
sdl.GPUSamplerCreateInfo {
|
sdl.GPUSamplerCreateInfo {
|
||||||
min_filter = .LINEAR,
|
min_filter = .LINEAR,
|
||||||
mag_filter = .LINEAR,
|
mag_filter = .LINEAR,
|
||||||
mipmap_mode = .LINEAR,
|
mipmap_mode = .LINEAR,
|
||||||
address_mode_u = .CLAMP_TO_EDGE,
|
address_mode_u = .CLAMP_TO_EDGE,
|
||||||
address_mode_v = .CLAMP_TO_EDGE,
|
address_mode_v = .CLAMP_TO_EDGE,
|
||||||
address_mode_w = .CLAMP_TO_EDGE,
|
address_mode_w = .CLAMP_TO_EDGE,
|
||||||
@@ -428,11 +428,7 @@ upload :: proc(device: ^sdl.GPUDevice, pass: ^sdl.GPUCopyPass) {
|
|||||||
sdl.UploadToGPUBuffer(
|
sdl.UploadToGPUBuffer(
|
||||||
pass,
|
pass,
|
||||||
sdl.GPUTransferBufferLocation{transfer_buffer = GLOB.pipeline_2d_base.vertex_buffer.transfer},
|
sdl.GPUTransferBufferLocation{transfer_buffer = GLOB.pipeline_2d_base.vertex_buffer.transfer},
|
||||||
sdl.GPUBufferRegion{
|
sdl.GPUBufferRegion{buffer = GLOB.pipeline_2d_base.vertex_buffer.gpu, offset = 0, size = total_vert_size},
|
||||||
buffer = GLOB.pipeline_2d_base.vertex_buffer.gpu,
|
|
||||||
offset = 0,
|
|
||||||
size = total_vert_size,
|
|
||||||
},
|
|
||||||
false,
|
false,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@@ -459,11 +455,7 @@ upload :: proc(device: ^sdl.GPUDevice, pass: ^sdl.GPUCopyPass) {
|
|||||||
sdl.UploadToGPUBuffer(
|
sdl.UploadToGPUBuffer(
|
||||||
pass,
|
pass,
|
||||||
sdl.GPUTransferBufferLocation{transfer_buffer = GLOB.pipeline_2d_base.index_buffer.transfer},
|
sdl.GPUTransferBufferLocation{transfer_buffer = GLOB.pipeline_2d_base.index_buffer.transfer},
|
||||||
sdl.GPUBufferRegion{
|
sdl.GPUBufferRegion{buffer = GLOB.pipeline_2d_base.index_buffer.gpu, offset = 0, size = index_size},
|
||||||
buffer = GLOB.pipeline_2d_base.index_buffer.gpu,
|
|
||||||
offset = 0,
|
|
||||||
size = index_size,
|
|
||||||
},
|
|
||||||
false,
|
false,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@@ -480,9 +472,7 @@ upload :: proc(device: ^sdl.GPUDevice, pass: ^sdl.GPUCopyPass) {
|
|||||||
sdl.GPUBufferUsageFlags{.GRAPHICS_STORAGE_READ},
|
sdl.GPUBufferUsageFlags{.GRAPHICS_STORAGE_READ},
|
||||||
)
|
)
|
||||||
|
|
||||||
p_array := sdl.MapGPUTransferBuffer(
|
p_array := sdl.MapGPUTransferBuffer(device, GLOB.pipeline_2d_base.primitive_buffer.transfer, false)
|
||||||
device, GLOB.pipeline_2d_base.primitive_buffer.transfer, false,
|
|
||||||
)
|
|
||||||
if p_array == nil {
|
if p_array == nil {
|
||||||
log.panicf("Failed to map primitive transfer buffer: %s", sdl.GetError())
|
log.panicf("Failed to map primitive transfer buffer: %s", sdl.GetError())
|
||||||
}
|
}
|
||||||
@@ -491,14 +481,8 @@ upload :: proc(device: ^sdl.GPUDevice, pass: ^sdl.GPUCopyPass) {
|
|||||||
|
|
||||||
sdl.UploadToGPUBuffer(
|
sdl.UploadToGPUBuffer(
|
||||||
pass,
|
pass,
|
||||||
sdl.GPUTransferBufferLocation{
|
sdl.GPUTransferBufferLocation{transfer_buffer = GLOB.pipeline_2d_base.primitive_buffer.transfer},
|
||||||
transfer_buffer = GLOB.pipeline_2d_base.primitive_buffer.transfer,
|
sdl.GPUBufferRegion{buffer = GLOB.pipeline_2d_base.primitive_buffer.gpu, offset = 0, size = prim_size},
|
||||||
},
|
|
||||||
sdl.GPUBufferRegion{
|
|
||||||
buffer = GLOB.pipeline_2d_base.primitive_buffer.gpu,
|
|
||||||
offset = 0,
|
|
||||||
size = prim_size,
|
|
||||||
},
|
|
||||||
false,
|
false,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@@ -521,10 +505,8 @@ draw_layer :: proc(
|
|||||||
cmd_buffer,
|
cmd_buffer,
|
||||||
&sdl.GPUColorTargetInfo {
|
&sdl.GPUColorTargetInfo {
|
||||||
texture = render_texture,
|
texture = render_texture,
|
||||||
clear_color = sdl.FColor {
|
clear_color = sdl.FColor{clear_color[0], clear_color[1], clear_color[2], clear_color[3]},
|
||||||
clear_color[0], clear_color[1], clear_color[2], clear_color[3],
|
load_op = .CLEAR,
|
||||||
},
|
|
||||||
load_op = .CLEAR,
|
|
||||||
store_op = .STORE,
|
store_op = .STORE,
|
||||||
},
|
},
|
||||||
1,
|
1,
|
||||||
@@ -540,10 +522,8 @@ draw_layer :: proc(
|
|||||||
cmd_buffer,
|
cmd_buffer,
|
||||||
&sdl.GPUColorTargetInfo {
|
&sdl.GPUColorTargetInfo {
|
||||||
texture = render_texture,
|
texture = render_texture,
|
||||||
clear_color = sdl.FColor {
|
clear_color = sdl.FColor{clear_color[0], clear_color[1], clear_color[2], clear_color[3]},
|
||||||
clear_color[0], clear_color[1], clear_color[2], clear_color[3],
|
load_op = GLOB.cleared ? .LOAD : .CLEAR,
|
||||||
},
|
|
||||||
load_op = GLOB.cleared ? .LOAD : .CLEAR,
|
|
||||||
store_op = .STORE,
|
store_op = .STORE,
|
||||||
},
|
},
|
||||||
1,
|
1,
|
||||||
@@ -571,16 +551,14 @@ draw_layer :: proc(
|
|||||||
// Shorthand aliases for frequently-used pipeline resources
|
// Shorthand aliases for frequently-used pipeline resources
|
||||||
main_vbuf := GLOB.pipeline_2d_base.vertex_buffer.gpu
|
main_vbuf := GLOB.pipeline_2d_base.vertex_buffer.gpu
|
||||||
unit_quad := GLOB.pipeline_2d_base.unit_quad_buffer
|
unit_quad := GLOB.pipeline_2d_base.unit_quad_buffer
|
||||||
white := GLOB.pipeline_2d_base.white_texture
|
white := GLOB.pipeline_2d_base.white_texture
|
||||||
sampler := GLOB.pipeline_2d_base.sampler
|
sampler := GLOB.pipeline_2d_base.sampler
|
||||||
w := f32(swapchain_w)
|
w := f32(swapchain_w)
|
||||||
h := f32(swapchain_h)
|
h := f32(swapchain_h)
|
||||||
|
|
||||||
// Initial GPU state: tessellated mode, main vertex buffer, no atlas bound yet
|
// Initial GPU state: tessellated mode, main vertex buffer, no atlas bound yet
|
||||||
push_globals(cmd_buffer, w, h, .Tessellated)
|
push_globals(cmd_buffer, w, h, .Tessellated)
|
||||||
sdl.BindGPUVertexBuffers(
|
sdl.BindGPUVertexBuffers(render_pass, 0, &sdl.GPUBufferBinding{buffer = main_vbuf, offset = 0}, 1)
|
||||||
render_pass, 0, &sdl.GPUBufferBinding{buffer = main_vbuf, offset = 0}, 1,
|
|
||||||
)
|
|
||||||
|
|
||||||
current_mode: Draw_Mode = .Tessellated
|
current_mode: Draw_Mode = .Tessellated
|
||||||
current_vbuf := main_vbuf
|
current_vbuf := main_vbuf
|
||||||
@@ -600,16 +578,15 @@ draw_layer :: proc(
|
|||||||
current_mode = .Tessellated
|
current_mode = .Tessellated
|
||||||
}
|
}
|
||||||
if current_vbuf != main_vbuf {
|
if current_vbuf != main_vbuf {
|
||||||
sdl.BindGPUVertexBuffers(
|
sdl.BindGPUVertexBuffers(render_pass, 0, &sdl.GPUBufferBinding{buffer = main_vbuf, offset = 0}, 1)
|
||||||
render_pass, 0,
|
|
||||||
&sdl.GPUBufferBinding{buffer = main_vbuf, offset = 0}, 1,
|
|
||||||
)
|
|
||||||
current_vbuf = main_vbuf
|
current_vbuf = main_vbuf
|
||||||
}
|
}
|
||||||
if current_atlas != white {
|
if current_atlas != white {
|
||||||
sdl.BindGPUFragmentSamplers(
|
sdl.BindGPUFragmentSamplers(
|
||||||
render_pass, 0,
|
render_pass,
|
||||||
&sdl.GPUTextureSamplerBinding{texture = white, sampler = sampler}, 1,
|
0,
|
||||||
|
&sdl.GPUTextureSamplerBinding{texture = white, sampler = sampler},
|
||||||
|
1,
|
||||||
)
|
)
|
||||||
current_atlas = white
|
current_atlas = white
|
||||||
}
|
}
|
||||||
@@ -621,20 +598,15 @@ draw_layer :: proc(
|
|||||||
current_mode = .Tessellated
|
current_mode = .Tessellated
|
||||||
}
|
}
|
||||||
if current_vbuf != main_vbuf {
|
if current_vbuf != main_vbuf {
|
||||||
sdl.BindGPUVertexBuffers(
|
sdl.BindGPUVertexBuffers(render_pass, 0, &sdl.GPUBufferBinding{buffer = main_vbuf, offset = 0}, 1)
|
||||||
render_pass, 0,
|
|
||||||
&sdl.GPUBufferBinding{buffer = main_vbuf, offset = 0}, 1,
|
|
||||||
)
|
|
||||||
current_vbuf = main_vbuf
|
current_vbuf = main_vbuf
|
||||||
}
|
}
|
||||||
chunk := &GLOB.tmp_text_batches[batch.offset]
|
chunk := &GLOB.tmp_text_batches[batch.offset]
|
||||||
if current_atlas != chunk.atlas_texture {
|
if current_atlas != chunk.atlas_texture {
|
||||||
sdl.BindGPUFragmentSamplers(
|
sdl.BindGPUFragmentSamplers(
|
||||||
render_pass, 0,
|
render_pass,
|
||||||
&sdl.GPUTextureSamplerBinding {
|
0,
|
||||||
texture = chunk.atlas_texture,
|
&sdl.GPUTextureSamplerBinding{texture = chunk.atlas_texture, sampler = sampler},
|
||||||
sampler = sampler,
|
|
||||||
},
|
|
||||||
1,
|
1,
|
||||||
)
|
)
|
||||||
current_atlas = chunk.atlas_texture
|
current_atlas = chunk.atlas_texture
|
||||||
@@ -654,16 +626,15 @@ draw_layer :: proc(
|
|||||||
current_mode = .SDF
|
current_mode = .SDF
|
||||||
}
|
}
|
||||||
if current_vbuf != unit_quad {
|
if current_vbuf != unit_quad {
|
||||||
sdl.BindGPUVertexBuffers(
|
sdl.BindGPUVertexBuffers(render_pass, 0, &sdl.GPUBufferBinding{buffer = unit_quad, offset = 0}, 1)
|
||||||
render_pass, 0,
|
|
||||||
&sdl.GPUBufferBinding{buffer = unit_quad, offset = 0}, 1,
|
|
||||||
)
|
|
||||||
current_vbuf = unit_quad
|
current_vbuf = unit_quad
|
||||||
}
|
}
|
||||||
if current_atlas != white {
|
if current_atlas != white {
|
||||||
sdl.BindGPUFragmentSamplers(
|
sdl.BindGPUFragmentSamplers(
|
||||||
render_pass, 0,
|
render_pass,
|
||||||
&sdl.GPUTextureSamplerBinding{texture = white, sampler = sampler}, 1,
|
0,
|
||||||
|
&sdl.GPUTextureSamplerBinding{texture = white, sampler = sampler},
|
||||||
|
1,
|
||||||
)
|
)
|
||||||
current_atlas = white
|
current_atlas = white
|
||||||
}
|
}
|
||||||
|
|||||||
142
draw/shapes.odin
142
draw/shapes.odin
@@ -324,13 +324,7 @@ triangle_strip :: proc(
|
|||||||
// ----- SDF drawing functions ----
|
// ----- SDF drawing functions ----
|
||||||
|
|
||||||
// Draw a rectangle with per-corner rounding radii via SDF.
|
// Draw a rectangle with per-corner rounding radii via SDF.
|
||||||
rectangle_corners :: proc(
|
rectangle_corners :: proc(layer: ^Layer, rect: Rectangle, radii: [4]f32, color: Color, soft_px: f32 = 1.0) {
|
||||||
layer: ^Layer,
|
|
||||||
rect: Rectangle,
|
|
||||||
radii: [4]f32,
|
|
||||||
color: Color,
|
|
||||||
soft_px: f32 = 1.0,
|
|
||||||
) {
|
|
||||||
max_radius := min(rect.w, rect.h) * 0.5
|
max_radius := min(rect.w, rect.h) * 0.5
|
||||||
tl := clamp(radii[0], 0, max_radius)
|
tl := clamp(radii[0], 0, max_radius)
|
||||||
tr := clamp(radii[1], 0, max_radius)
|
tr := clamp(radii[1], 0, max_radius)
|
||||||
@@ -387,13 +381,7 @@ rectangle_corners_lines :: proc(
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Draw a rectangle with uniform corner rounding via SDF.
|
// Draw a rectangle with uniform corner rounding via SDF.
|
||||||
rectangle_rounded :: proc(
|
rectangle_rounded :: proc(layer: ^Layer, rect: Rectangle, roundness: f32, color: Color, soft_px: f32 = 1.0) {
|
||||||
layer: ^Layer,
|
|
||||||
rect: Rectangle,
|
|
||||||
roundness: f32,
|
|
||||||
color: Color,
|
|
||||||
soft_px: f32 = 1.0,
|
|
||||||
) {
|
|
||||||
cr := min(rect.w, rect.h) * clamp(roundness, 0, 1) * 0.5
|
cr := min(rect.w, rect.h) * clamp(roundness, 0, 1) * 0.5
|
||||||
if cr < 1 {
|
if cr < 1 {
|
||||||
rectangle(layer, rect, color)
|
rectangle(layer, rect, color)
|
||||||
@@ -425,12 +413,19 @@ circle :: proc(layer: ^Layer, center: [2]f32, radius: f32, color: Color, soft_px
|
|||||||
dpi := GLOB.dpi_scaling
|
dpi := GLOB.dpi_scaling
|
||||||
|
|
||||||
prim := Primitive {
|
prim := Primitive {
|
||||||
bounds = {center.x - radius - pad, center.y - radius - pad,
|
bounds = {
|
||||||
center.x + radius + pad, center.y + radius + pad},
|
center.x - radius - pad,
|
||||||
|
center.y - radius - pad,
|
||||||
|
center.x + radius + pad,
|
||||||
|
center.y + radius + pad,
|
||||||
|
},
|
||||||
color = color,
|
color = color,
|
||||||
kind_flags = pack_kind_flags(.Circle, {}),
|
kind_flags = pack_kind_flags(.Circle, {}),
|
||||||
}
|
}
|
||||||
prim.params.circle = Circle_Params{radius = radius * dpi, soft_px = soft_px}
|
prim.params.circle = Circle_Params {
|
||||||
|
radius = radius * dpi,
|
||||||
|
soft_px = soft_px,
|
||||||
|
}
|
||||||
prepare_sdf_primitive(layer, prim)
|
prepare_sdf_primitive(layer, prim)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -447,35 +442,42 @@ circle_lines :: proc(
|
|||||||
dpi := GLOB.dpi_scaling
|
dpi := GLOB.dpi_scaling
|
||||||
|
|
||||||
prim := Primitive {
|
prim := Primitive {
|
||||||
bounds = {center.x - radius - pad, center.y - radius - pad,
|
bounds = {
|
||||||
center.x + radius + pad, center.y + radius + pad},
|
center.x - radius - pad,
|
||||||
|
center.y - radius - pad,
|
||||||
|
center.x + radius + pad,
|
||||||
|
center.y + radius + pad,
|
||||||
|
},
|
||||||
color = color,
|
color = color,
|
||||||
kind_flags = pack_kind_flags(.Circle, {.Stroke}),
|
kind_flags = pack_kind_flags(.Circle, {.Stroke}),
|
||||||
}
|
}
|
||||||
prim.params.circle = Circle_Params{
|
prim.params.circle = Circle_Params {
|
||||||
radius = radius * dpi, soft_px = soft_px, stroke_px = thick * dpi,
|
radius = radius * dpi,
|
||||||
|
soft_px = soft_px,
|
||||||
|
stroke_px = thick * dpi,
|
||||||
}
|
}
|
||||||
prepare_sdf_primitive(layer, prim)
|
prepare_sdf_primitive(layer, prim)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Draw a filled ellipse via SDF.
|
// Draw a filled ellipse via SDF.
|
||||||
ellipse :: proc(
|
ellipse :: proc(layer: ^Layer, center: [2]f32, radius_h, radius_v: f32, color: Color, soft_px: f32 = 1.0) {
|
||||||
layer: ^Layer,
|
|
||||||
center: [2]f32,
|
|
||||||
radius_h, radius_v: f32,
|
|
||||||
color: Color,
|
|
||||||
soft_px: f32 = 1.0,
|
|
||||||
) {
|
|
||||||
pad := soft_px / GLOB.dpi_scaling
|
pad := soft_px / GLOB.dpi_scaling
|
||||||
dpi := GLOB.dpi_scaling
|
dpi := GLOB.dpi_scaling
|
||||||
|
|
||||||
prim := Primitive {
|
prim := Primitive {
|
||||||
bounds = {center.x - radius_h - pad, center.y - radius_v - pad,
|
bounds = {
|
||||||
center.x + radius_h + pad, center.y + radius_v + pad},
|
center.x - radius_h - pad,
|
||||||
|
center.y - radius_v - pad,
|
||||||
|
center.x + radius_h + pad,
|
||||||
|
center.y + radius_v + pad,
|
||||||
|
},
|
||||||
color = color,
|
color = color,
|
||||||
kind_flags = pack_kind_flags(.Ellipse, {}),
|
kind_flags = pack_kind_flags(.Ellipse, {}),
|
||||||
}
|
}
|
||||||
prim.params.ellipse = Ellipse_Params{radii = {radius_h * dpi, radius_v * dpi}, soft_px = soft_px}
|
prim.params.ellipse = Ellipse_Params {
|
||||||
|
radii = {radius_h * dpi, radius_v * dpi},
|
||||||
|
soft_px = soft_px,
|
||||||
|
}
|
||||||
prepare_sdf_primitive(layer, prim)
|
prepare_sdf_primitive(layer, prim)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -494,13 +496,19 @@ ellipse_lines :: proc(
|
|||||||
dpi := GLOB.dpi_scaling
|
dpi := GLOB.dpi_scaling
|
||||||
|
|
||||||
prim := Primitive {
|
prim := Primitive {
|
||||||
bounds = {center.x - radius_h - pad, center.y - radius_v - pad,
|
bounds = {
|
||||||
center.x + radius_h + pad, center.y + radius_v + pad},
|
center.x - radius_h - pad,
|
||||||
|
center.y - radius_v - pad,
|
||||||
|
center.x + radius_h + pad,
|
||||||
|
center.y + radius_v + pad,
|
||||||
|
},
|
||||||
color = color,
|
color = color,
|
||||||
kind_flags = pack_kind_flags(.Ellipse, {.Stroke}),
|
kind_flags = pack_kind_flags(.Ellipse, {.Stroke}),
|
||||||
}
|
}
|
||||||
prim.params.ellipse = Ellipse_Params{
|
prim.params.ellipse = Ellipse_Params {
|
||||||
radii = {radius_h * dpi, radius_v * dpi}, soft_px = soft_px, stroke_px = thick * dpi,
|
radii = {radius_h * dpi, radius_v * dpi},
|
||||||
|
soft_px = soft_px,
|
||||||
|
stroke_px = thick * dpi,
|
||||||
}
|
}
|
||||||
prepare_sdf_primitive(layer, prim)
|
prepare_sdf_primitive(layer, prim)
|
||||||
}
|
}
|
||||||
@@ -518,8 +526,12 @@ ring :: proc(
|
|||||||
dpi := GLOB.dpi_scaling
|
dpi := GLOB.dpi_scaling
|
||||||
|
|
||||||
prim := Primitive {
|
prim := Primitive {
|
||||||
bounds = {center.x - outer_radius - pad, center.y - outer_radius - pad,
|
bounds = {
|
||||||
center.x + outer_radius + pad, center.y + outer_radius + pad},
|
center.x - outer_radius - pad,
|
||||||
|
center.y - outer_radius - pad,
|
||||||
|
center.x + outer_radius + pad,
|
||||||
|
center.y + outer_radius + pad,
|
||||||
|
},
|
||||||
color = color,
|
color = color,
|
||||||
kind_flags = pack_kind_flags(.Ring_Arc, {}),
|
kind_flags = pack_kind_flags(.Ring_Arc, {}),
|
||||||
}
|
}
|
||||||
@@ -544,11 +556,27 @@ ring_lines :: proc(
|
|||||||
soft_px: f32 = 1.0,
|
soft_px: f32 = 1.0,
|
||||||
) {
|
) {
|
||||||
// Inner arc outline
|
// Inner arc outline
|
||||||
ring(layer, center, max(0, inner_radius - thick * 0.5), inner_radius + thick * 0.5,
|
ring(
|
||||||
start_angle, end_angle, color, soft_px)
|
layer,
|
||||||
|
center,
|
||||||
|
max(0, inner_radius - thick * 0.5),
|
||||||
|
inner_radius + thick * 0.5,
|
||||||
|
start_angle,
|
||||||
|
end_angle,
|
||||||
|
color,
|
||||||
|
soft_px,
|
||||||
|
)
|
||||||
// Outer arc outline
|
// Outer arc outline
|
||||||
ring(layer, center, max(0, outer_radius - thick * 0.5), outer_radius + thick * 0.5,
|
ring(
|
||||||
start_angle, end_angle, color, soft_px)
|
layer,
|
||||||
|
center,
|
||||||
|
max(0, outer_radius - thick * 0.5),
|
||||||
|
outer_radius + thick * 0.5,
|
||||||
|
start_angle,
|
||||||
|
end_angle,
|
||||||
|
color,
|
||||||
|
soft_px,
|
||||||
|
)
|
||||||
// Start cap
|
// Start cap
|
||||||
start_rad := math.to_radians(start_angle)
|
start_rad := math.to_radians(start_angle)
|
||||||
end_rad := math.to_radians(end_angle)
|
end_rad := math.to_radians(end_angle)
|
||||||
@@ -562,13 +590,7 @@ ring_lines :: proc(
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Draw a line segment via SDF.
|
// Draw a line segment via SDF.
|
||||||
line :: proc(
|
line :: proc(layer: ^Layer, start, end_pos: [2]f32, color: Color, thick: f32 = 1, soft_px: f32 = 1.0) {
|
||||||
layer: ^Layer,
|
|
||||||
start, end_pos: [2]f32,
|
|
||||||
color: Color,
|
|
||||||
thick: f32 = 1,
|
|
||||||
soft_px: f32 = 1.0,
|
|
||||||
) {
|
|
||||||
cap := thick * 0.5 + soft_px / GLOB.dpi_scaling
|
cap := thick * 0.5 + soft_px / GLOB.dpi_scaling
|
||||||
min_x := min(start.x, end_pos.x) - cap
|
min_x := min(start.x, end_pos.x) - cap
|
||||||
max_x := max(start.x, end_pos.x) + cap
|
max_x := max(start.x, end_pos.x) + cap
|
||||||
@@ -595,13 +617,7 @@ line :: proc(
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Draw a line strip via decomposed SDF segments.
|
// Draw a line strip via decomposed SDF segments.
|
||||||
line_strip :: proc(
|
line_strip :: proc(layer: ^Layer, points: [][2]f32, color: Color, thick: f32 = 1, soft_px: f32 = 1.0) {
|
||||||
layer: ^Layer,
|
|
||||||
points: [][2]f32,
|
|
||||||
color: Color,
|
|
||||||
thick: f32 = 1,
|
|
||||||
soft_px: f32 = 1.0,
|
|
||||||
) {
|
|
||||||
if len(points) < 2 do return
|
if len(points) < 2 do return
|
||||||
for i in 0 ..< len(points) - 1 {
|
for i in 0 ..< len(points) - 1 {
|
||||||
line(layer, points[i], points[i + 1], color, thick, soft_px)
|
line(layer, points[i], points[i + 1], color, thick, soft_px)
|
||||||
@@ -623,8 +639,12 @@ poly :: proc(
|
|||||||
dpi := GLOB.dpi_scaling
|
dpi := GLOB.dpi_scaling
|
||||||
|
|
||||||
prim := Primitive {
|
prim := Primitive {
|
||||||
bounds = {center.x - radius - pad, center.y - radius - pad,
|
bounds = {
|
||||||
center.x + radius + pad, center.y + radius + pad},
|
center.x - radius - pad,
|
||||||
|
center.y - radius - pad,
|
||||||
|
center.x + radius + pad,
|
||||||
|
center.y + radius + pad,
|
||||||
|
},
|
||||||
color = color,
|
color = color,
|
||||||
kind_flags = pack_kind_flags(.NGon, {}),
|
kind_flags = pack_kind_flags(.NGon, {}),
|
||||||
}
|
}
|
||||||
@@ -653,8 +673,12 @@ poly_lines :: proc(
|
|||||||
dpi := GLOB.dpi_scaling
|
dpi := GLOB.dpi_scaling
|
||||||
|
|
||||||
prim := Primitive {
|
prim := Primitive {
|
||||||
bounds = {center.x - radius - pad, center.y - radius - pad,
|
bounds = {
|
||||||
center.x + radius + pad, center.y + radius + pad},
|
center.x - radius - pad,
|
||||||
|
center.y - radius - pad,
|
||||||
|
center.x + radius + pad,
|
||||||
|
center.y + radius + pad,
|
||||||
|
},
|
||||||
color = color,
|
color = color,
|
||||||
kind_flags = pack_kind_flags(.NGon, {.Stroke}),
|
kind_flags = pack_kind_flags(.NGon, {.Stroke}),
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user