Primitive border drawing and rounded corners
This commit is contained in:
parent
b063d570b1
commit
9dec588ec1
@ -56,43 +56,28 @@ typedef enum Corner
|
||||
CORNER_COUNT,
|
||||
} Corner;
|
||||
|
||||
STRUCT(U32Vec2)
|
||||
{
|
||||
struct
|
||||
{
|
||||
u32 x;
|
||||
u32 y;
|
||||
};
|
||||
u32 v[2];
|
||||
};
|
||||
typedef float float2 __attribute__((ext_vector_type(2)));
|
||||
typedef float float3 __attribute__((ext_vector_type(3)));
|
||||
typedef float float4 __attribute__((ext_vector_type(4)));
|
||||
typedef float2 vec2;
|
||||
typedef float3 vec3;
|
||||
typedef float4 vec4;
|
||||
|
||||
STRUCT(F32Vec4)
|
||||
{
|
||||
f32 v[4];
|
||||
};
|
||||
typedef F32Vec4 Color;
|
||||
|
||||
UNION(F32Vec2)
|
||||
{
|
||||
struct
|
||||
{
|
||||
f32 x;
|
||||
f32 y;
|
||||
};
|
||||
f32 v[2];
|
||||
};
|
||||
typedef u32 uint2 __attribute__((ext_vector_type(2)));
|
||||
typedef u32 uint3 __attribute__((ext_vector_type(3)));
|
||||
typedef u32 uint4 __attribute__((ext_vector_type(4)));
|
||||
|
||||
UNION(F32Interval2)
|
||||
{
|
||||
struct
|
||||
{
|
||||
F32Vec2 min;
|
||||
F32Vec2 max;
|
||||
float2 min;
|
||||
float2 max;
|
||||
};
|
||||
struct
|
||||
{
|
||||
F32Vec2 p0;
|
||||
F32Vec2 p1;
|
||||
float2 p0;
|
||||
float2 p1;
|
||||
};
|
||||
struct
|
||||
{
|
||||
@ -101,9 +86,11 @@ UNION(F32Interval2)
|
||||
f32 x1;
|
||||
f32 y1;
|
||||
};
|
||||
F32Vec2 v[2];
|
||||
float2 v[2];
|
||||
};
|
||||
|
||||
static_assert(sizeof(F32Interval2) == 4 * sizeof(f32));
|
||||
|
||||
typedef enum Axis2
|
||||
{
|
||||
AXIS2_X,
|
||||
|
@ -37,4 +37,4 @@ STRUCT(TextureAtlasCreate)
|
||||
#include <std/render.h>
|
||||
|
||||
EXPORT TextureAtlas font_texture_atlas_create(Arena* arena, Renderer* renderer, TextureAtlasCreate create);
|
||||
EXPORT U32Vec2 texture_atlas_compute_string_rect(String string, const TextureAtlas* atlas);
|
||||
EXPORT uint2 texture_atlas_compute_string_rect(String string, const TextureAtlas* atlas);
|
||||
|
@ -1,6 +1,5 @@
|
||||
#pragma once
|
||||
|
||||
|
||||
#include <std/base.h>
|
||||
|
||||
typedef struct Renderer Renderer;
|
||||
@ -11,41 +10,18 @@ typedef struct Renderer Renderer;
|
||||
typedef struct RenderWindow RenderWindow;
|
||||
typedef struct Pipeline Pipeline;
|
||||
|
||||
STRUCT(RenderRect)
|
||||
{
|
||||
u32 x0;
|
||||
u32 y0;
|
||||
u32 x1;
|
||||
u32 y1;
|
||||
};
|
||||
|
||||
STRUCT(RectColors)
|
||||
{
|
||||
F32Vec4 v[4];
|
||||
};
|
||||
|
||||
STRUCT(RectDraw)
|
||||
{
|
||||
RenderRect vertex;
|
||||
RenderRect texture;
|
||||
RectColors colors;
|
||||
F32Interval2 vertex;
|
||||
F32Interval2 texture;
|
||||
vec4 colors[4];
|
||||
u32 texture_index;
|
||||
};
|
||||
|
||||
STRUCT(RectVertex)
|
||||
{
|
||||
f32 x;
|
||||
f32 y;
|
||||
f32 uv_x;
|
||||
f32 uv_y;
|
||||
RectColors colors;
|
||||
u32 texture_index;
|
||||
u32 reserved[3];
|
||||
};
|
||||
#include "../std/shaders/rect.inc"
|
||||
typedef struct RectVertex RectVertex;
|
||||
decl_vb(RectVertex);
|
||||
|
||||
#define Color4(r, g, b, a) ((F32Vec4){ .v = { r, g, b, a } })
|
||||
|
||||
typedef enum BBPipeline
|
||||
{
|
||||
BB_PIPELINE_RECT,
|
||||
@ -187,7 +163,7 @@ EXPORT PipelineLayoutIndex renderer_pipeline_get_layout(PipelineIndex pipeline);
|
||||
EXPORT void renderer_window_frame_begin(Renderer* renderer, RenderWindow* window);
|
||||
EXPORT void renderer_window_frame_end(Renderer* renderer, RenderWindow* window);
|
||||
EXPORT TextureIndex renderer_texture_create(Renderer* renderer, TextureMemory texture_memory);
|
||||
EXPORT U32Vec2 renderer_font_compute_string_rect(Renderer* renderer, RenderFontType type, String string);
|
||||
EXPORT uint2 renderer_font_compute_string_rect(Renderer* renderer, RenderFontType type, String string);
|
||||
EXPORT void window_command_begin(RenderWindow* window);
|
||||
EXPORT void window_command_end(RenderWindow* window);
|
||||
EXPORT void window_render_begin(RenderWindow* window);
|
||||
@ -203,4 +179,4 @@ EXPORT void window_rect_texture_update_end(Renderer* renderer, RenderWindow* win
|
||||
EXPORT u32 window_pipeline_add_vertices(RenderWindow* window, BBPipeline pipeline_index, String vertex_memory, u32 vertex_count);
|
||||
EXPORT void window_pipeline_add_indices(RenderWindow* window, BBPipeline pipeline_index, Slice(u32) indices);
|
||||
EXPORT void window_render_rect(RenderWindow* window, RectDraw draw);
|
||||
EXPORT void window_render_text(Renderer* renderer, RenderWindow* window, String string, Color color, RenderFontType font_type, u32 x_offset, u32 y_offset);
|
||||
EXPORT void window_render_text(Renderer* renderer, RenderWindow* window, String string, float4 color, RenderFontType font_type, u32 x_offset, u32 y_offset);
|
||||
|
@ -87,19 +87,19 @@ STRUCT(UI_Widget)
|
||||
UI_WidgetFlags flags;
|
||||
|
||||
// Data known after size determination happens
|
||||
F32Vec2 computed_size;
|
||||
F32Vec2 computed_relative_position;
|
||||
float2 computed_size;
|
||||
float2 computed_relative_position;
|
||||
|
||||
// Data known after layout computation happens
|
||||
F32Interval2 relative_rect;
|
||||
F32Interval2 rect;
|
||||
F32Vec2 relative_corner_delta[CORNER_COUNT];
|
||||
float2 relative_corner_delta[CORNER_COUNT];
|
||||
|
||||
// Persistent data across frames
|
||||
u64 last_build_touched;
|
||||
F32Vec2 view_offset;
|
||||
Color background_color;
|
||||
Color text_color;
|
||||
float2 view_offset;
|
||||
float4 background_color;
|
||||
float4 text_color;
|
||||
};
|
||||
decl_vbp(UI_Widget);
|
||||
|
||||
@ -111,7 +111,7 @@ STRUCT(UI_WidgetSlot)
|
||||
declare_slice(UI_WidgetSlot);
|
||||
|
||||
decl_vb(Axis2);
|
||||
decl_vb(Color);
|
||||
decl_vb(float4);
|
||||
|
||||
STRUCT(UI_StateStackAutoPops)
|
||||
{
|
||||
@ -131,8 +131,8 @@ STRUCT(UI_StateStackNulls)
|
||||
UI_Size pref_width;
|
||||
UI_Size pref_height;
|
||||
Axis2 child_layout_axis;
|
||||
Color text_color;
|
||||
Color background_color;
|
||||
float4 text_color;
|
||||
float4 background_color;
|
||||
f32 font_size;
|
||||
};
|
||||
|
||||
@ -142,8 +142,8 @@ STRUCT(UI_StateStacks)
|
||||
VirtualBuffer(UI_Size) pref_width;
|
||||
VirtualBuffer(UI_Size) pref_height;
|
||||
VirtualBuffer(Axis2) child_layout_axis;
|
||||
VirtualBuffer(Color) text_color;
|
||||
VirtualBuffer(Color) background_color;
|
||||
VirtualBuffer(float4) text_color;
|
||||
VirtualBuffer(float4) background_color;
|
||||
VirtualBuffer(f32) font_size;
|
||||
};
|
||||
|
||||
|
@ -1,21 +0,0 @@
|
||||
#version 450
|
||||
#extension GL_EXT_nonuniform_qualifier : require
|
||||
#extension GL_EXT_debug_printf : require
|
||||
#extension GL_GOOGLE_include_directive : require
|
||||
|
||||
#include "rect.h"
|
||||
|
||||
layout (location = 0) in flat uint texture_index;
|
||||
layout (location = 1) in FragmentShaderInput inputs;
|
||||
|
||||
layout (location = 0) out vec4 color;
|
||||
|
||||
layout(set = 0, binding = 0) uniform sampler2D textures[];
|
||||
|
||||
void main()
|
||||
{
|
||||
vec2 texture_size = textureSize(textures[nonuniformEXT(texture_index)], 0);
|
||||
vec2 uv = vec2(inputs.uv.x / texture_size.x, inputs.uv.y / texture_size.y);
|
||||
vec4 sampled = texture(textures[nonuniformEXT(texture_index)], uv);
|
||||
color = inputs.color * sampled;
|
||||
}
|
@ -1,5 +0,0 @@
|
||||
struct FragmentShaderInput
|
||||
{
|
||||
vec4 color;
|
||||
vec2 uv;
|
||||
};
|
@ -1,47 +0,0 @@
|
||||
#version 450
|
||||
#extension GL_EXT_buffer_reference : require
|
||||
#extension GL_EXT_debug_printf : require
|
||||
#extension GL_GOOGLE_include_directive : require
|
||||
|
||||
#include "rect.h"
|
||||
|
||||
layout (location = 0) out uint texture_index;
|
||||
layout (location = 1) out FragmentShaderInput outputs;
|
||||
|
||||
struct Vertex {
|
||||
float x;
|
||||
float y;
|
||||
float uv_x;
|
||||
float uv_y;
|
||||
vec4 colors[4];
|
||||
uint texture_index;
|
||||
uint r[3];
|
||||
};
|
||||
|
||||
layout(buffer_reference, std430) readonly buffer VertexBuffer{
|
||||
Vertex vertices[];
|
||||
};
|
||||
|
||||
//push constants block
|
||||
layout(push_constant) uniform constants
|
||||
{
|
||||
VertexBuffer vertex_buffer;
|
||||
float width;
|
||||
float height;
|
||||
} PushConstants;
|
||||
|
||||
void main()
|
||||
{
|
||||
Vertex v = PushConstants.vertex_buffer.vertices[gl_VertexIndex];
|
||||
float width = PushConstants.width;
|
||||
float height = PushConstants.height;
|
||||
|
||||
gl_Position = vec4(2 * v.x / width - 1, 2 * v.y / height - 1, 0, 1);
|
||||
|
||||
outputs.uv = vec2(v.uv_x, v.uv_y);
|
||||
outputs.color = v.colors[gl_VertexIndex % 4];
|
||||
texture_index = v.texture_index;
|
||||
|
||||
//debugPrintfEXT("Vertex index: (%u)\n", gl_VertexIndex);
|
||||
//debugPrintfEXT("UV: (%f, %f)\n", v.uv_x, v.uv_y);
|
||||
}
|
@ -108,7 +108,7 @@ TextureAtlas font_texture_atlas_create(Arena* arena, Renderer* renderer, Texture
|
||||
return result;
|
||||
}
|
||||
|
||||
U32Vec2 texture_atlas_compute_string_rect(String string, const TextureAtlas* atlas)
|
||||
uint2 texture_atlas_compute_string_rect(String string, const TextureAtlas* atlas)
|
||||
{
|
||||
auto height = atlas->ascent - atlas->descent;
|
||||
u32 x_offset = 0;
|
||||
@ -122,5 +122,5 @@ U32Vec2 texture_atlas_compute_string_rect(String string, const TextureAtlas* atl
|
||||
x_offset += character->advance + kerning;
|
||||
}
|
||||
|
||||
return (U32Vec2) { .x = x_offset, .y = y_offset };
|
||||
return (uint2) { x_offset, y_offset };
|
||||
}
|
||||
|
@ -7,7 +7,6 @@
|
||||
#include <stb_image.h>
|
||||
#pragma clang diagnostic pop
|
||||
|
||||
|
||||
EXPORT TextureMemory texture_load_from_file(Arena* arena, String path)
|
||||
{
|
||||
auto file = file_read(arena, path);
|
||||
|
@ -313,11 +313,15 @@ void buffer_copy_to_host(VulkanBuffer buffer, Slice(HostBufferCopy) regions)
|
||||
auto region = regions.pointer[i];
|
||||
auto* destination = buffer_pointer + region.destination_offset;
|
||||
assert(destination + region.source.length <= (u8*)buffer.address + buffer.size);
|
||||
#define USE_MEMCPY 1
|
||||
#if USE_MEMCPY
|
||||
memcpy(destination, region.source.pointer, region.source.length);
|
||||
#else
|
||||
for (u64 i = 0; i < region.source.length; i += 1)
|
||||
{
|
||||
destination[i] = region.source.pointer[i];
|
||||
}
|
||||
// memcpy(destination, region.source.pointer, region.source.length);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
@ -1095,8 +1099,8 @@ Renderer* renderer_initialize(Arena* arena)
|
||||
}
|
||||
|
||||
String shader_source_paths[] = {
|
||||
strlit("bootstrap/shaders/rect.vert"),
|
||||
strlit("bootstrap/shaders/rect.frag"),
|
||||
strlit("bootstrap/std/shaders/rect.vert"),
|
||||
strlit("bootstrap/std/shaders/rect.frag"),
|
||||
};
|
||||
|
||||
PipelineLayoutCreate pipeline_layouts[] = {
|
||||
@ -2201,38 +2205,53 @@ void window_pipeline_add_indices(RenderWindow* window, BBPipeline pipeline_index
|
||||
|
||||
void window_render_rect(RenderWindow* window, RectDraw draw)
|
||||
{
|
||||
auto p0 = draw.vertex.p0;
|
||||
auto uv0 = draw.texture.p0;
|
||||
if (draw.texture.p1.x != 0)
|
||||
{
|
||||
assert(draw.texture.p1.x - draw.texture.p0.x == draw.vertex.p1.x - draw.vertex.p0.x);
|
||||
assert(draw.texture.p1.y - draw.texture.p0.y == draw.vertex.p1.y - draw.vertex.p0.y);
|
||||
}
|
||||
|
||||
auto corner_radius = 10.0f;
|
||||
|
||||
auto extent = draw.vertex.p1 - p0;
|
||||
RectVertex vertices[] = {
|
||||
(RectVertex) {
|
||||
.x = draw.vertex.x0,
|
||||
.y = draw.vertex.y0,
|
||||
.uv_x = draw.texture.x0,
|
||||
.uv_y = draw.texture.y0,
|
||||
.colors = draw.colors,
|
||||
.p0 = p0,
|
||||
.uv0 = uv0,
|
||||
.extent = extent,
|
||||
.texture_index = draw.texture_index,
|
||||
.colors = { draw.colors[0], draw.colors[1], draw.colors[2], draw.colors[3] },
|
||||
.softness = 1.0,
|
||||
.corner_radius = corner_radius,
|
||||
},
|
||||
(RectVertex) {
|
||||
.x = draw.vertex.x1,
|
||||
.y = draw.vertex.y0,
|
||||
.uv_x = draw.texture.x1,
|
||||
.uv_y = draw.texture.y0,
|
||||
.colors = draw.colors,
|
||||
.p0 = p0,
|
||||
.uv0 = uv0,
|
||||
.extent = extent,
|
||||
.texture_index = draw.texture_index,
|
||||
.colors = { draw.colors[0], draw.colors[1], draw.colors[2], draw.colors[3] },
|
||||
.softness = 1.0,
|
||||
.corner_radius = corner_radius,
|
||||
},
|
||||
(RectVertex) {
|
||||
.x = draw.vertex.x0,
|
||||
.y = draw.vertex.y1,
|
||||
.uv_x = draw.texture.x0,
|
||||
.uv_y = draw.texture.y1,
|
||||
.colors = draw.colors,
|
||||
.p0 = p0,
|
||||
.uv0 = uv0,
|
||||
.extent = extent,
|
||||
.texture_index = draw.texture_index,
|
||||
.colors = { draw.colors[0], draw.colors[1], draw.colors[2], draw.colors[3] },
|
||||
.softness = 1.0,
|
||||
.corner_radius = corner_radius,
|
||||
},
|
||||
(RectVertex) {
|
||||
.x = draw.vertex.x1,
|
||||
.y = draw.vertex.y1,
|
||||
.uv_x = draw.texture.x1,
|
||||
.uv_y = draw.texture.y1,
|
||||
.colors = draw.colors,
|
||||
.p0 = p0,
|
||||
.uv0 = uv0,
|
||||
.extent = extent,
|
||||
.texture_index = draw.texture_index,
|
||||
.colors = { draw.colors[0], draw.colors[1], draw.colors[2], draw.colors[3] },
|
||||
.softness = 1.0,
|
||||
.corner_radius = corner_radius,
|
||||
},
|
||||
};
|
||||
|
||||
@ -2250,63 +2269,63 @@ void window_render_rect(RenderWindow* window, RectDraw draw)
|
||||
window_pipeline_add_indices(window, BB_PIPELINE_RECT, (Slice(u32))array_to_slice(indices));
|
||||
}
|
||||
|
||||
void window_render_text(Renderer* renderer, RenderWindow* window, String string, Color color, RenderFontType font_type, u32 x_offset, u32 y_offset)
|
||||
// TODO: support gradient
|
||||
void window_render_text(Renderer* renderer, RenderWindow* window, String string, float4 color, RenderFontType font_type, u32 x_offset, u32 y_offset)
|
||||
{
|
||||
auto* texture_atlas = &renderer->fonts[font_type];
|
||||
auto height = texture_atlas->ascent - texture_atlas->descent;
|
||||
auto texture_index = texture_atlas->texture.value;
|
||||
|
||||
// TODO: support gradient
|
||||
RectColors colors = {
|
||||
.v = { color, color, color, color }
|
||||
};
|
||||
|
||||
for (u64 i = 0; i < string.length; i += 1)
|
||||
{
|
||||
auto ch = string.pointer[i];
|
||||
auto* character = &texture_atlas->characters[ch];
|
||||
|
||||
auto pos_x = x_offset;
|
||||
auto pos_y = y_offset + character->y_offset + height + texture_atlas->descent; // Offset of the height to render the character from the bottom (y + height) up (y)
|
||||
//
|
||||
auto uv_x = character->x;
|
||||
auto uv_y = character->y;
|
||||
|
||||
auto uv_width = character->width;
|
||||
auto uv_height = character->height;
|
||||
auto char_width = character->width;
|
||||
auto char_height = character->height;
|
||||
|
||||
auto pos_x = x_offset;
|
||||
auto pos_y = y_offset + character->y_offset + height + texture_atlas->descent; // Offset of the height to render the character from the bottom (y + height) up (y)
|
||||
vec2 p0 = { pos_x, pos_y };
|
||||
vec2 uv0 = { uv_x, uv_y };
|
||||
vec2 extent = { char_width, char_height };
|
||||
// print("P0: ({u32}, {u32}). P1: ({u32}, {u32})\n", (u32)p0.x, (u32)p0.y, (u32)p1.x, (u32)p1.y);
|
||||
|
||||
RectVertex vertices[] = {
|
||||
(RectVertex) {
|
||||
.x = pos_x,
|
||||
.y = pos_y,
|
||||
.uv_x = (f32)uv_x,
|
||||
.uv_y = (f32)uv_y,
|
||||
.colors = colors,
|
||||
.p0 = p0,
|
||||
.uv0 = uv0,
|
||||
.extent = extent,
|
||||
.texture_index = texture_index,
|
||||
.colors = { color, color, color, color },
|
||||
.softness = 1.0,
|
||||
},
|
||||
(RectVertex) {
|
||||
.x = pos_x + character->width,
|
||||
.y = pos_y,
|
||||
.uv_x = (f32)(uv_x + uv_width),
|
||||
.uv_y = (f32)uv_y,
|
||||
.colors = colors,
|
||||
.p0 = p0,
|
||||
.uv0 = uv0,
|
||||
.extent = extent,
|
||||
.texture_index = texture_index,
|
||||
.colors = { color, color, color, color },
|
||||
.softness = 1.0,
|
||||
},
|
||||
(RectVertex) {
|
||||
.x = pos_x,
|
||||
.y = pos_y + character->height,
|
||||
.uv_x = (f32)uv_x,
|
||||
.uv_y = (f32)(uv_y + uv_height),
|
||||
.colors = colors,
|
||||
.p0 = p0,
|
||||
.uv0 = uv0,
|
||||
.extent = extent,
|
||||
.texture_index = texture_index,
|
||||
.colors = { color, color, color, color },
|
||||
.softness = 1.0,
|
||||
},
|
||||
(RectVertex) {
|
||||
.x = pos_x + character->width,
|
||||
.y = pos_y + character->height,
|
||||
.uv_x = (f32)(uv_x + uv_width),
|
||||
.uv_y = (f32)(uv_y + uv_height),
|
||||
.colors = colors,
|
||||
.p0 = p0,
|
||||
.uv0 = uv0,
|
||||
.extent = extent,
|
||||
.colors = { color, color, color, color },
|
||||
.texture_index = texture_index,
|
||||
.softness = 1.0,
|
||||
},
|
||||
};
|
||||
|
||||
@ -2328,7 +2347,7 @@ void window_render_text(Renderer* renderer, RenderWindow* window, String string,
|
||||
}
|
||||
}
|
||||
|
||||
U32Vec2 renderer_font_compute_string_rect(Renderer* renderer, RenderFontType type, String string)
|
||||
uint2 renderer_font_compute_string_rect(Renderer* renderer, RenderFontType type, String string)
|
||||
{
|
||||
auto* texture_atlas = &renderer->fonts[type];
|
||||
auto result = texture_atlas_compute_string_rect(string, texture_atlas);
|
||||
|
@ -89,7 +89,6 @@ fn SpirVBinary compileShaderToSPIRV_Vulkan(Arena* arena, glslang_stage_t stage,
|
||||
|
||||
String compile_shader(Arena* arena, String path, ShaderStage shader_stage)
|
||||
{
|
||||
print("Compile shader\n");
|
||||
#if SHADER_COMPILATION_USE_SOURCE
|
||||
auto file = file_read(arena, path);
|
||||
|
||||
|
35
bootstrap/std/shaders/rect.frag
Normal file
35
bootstrap/std/shaders/rect.frag
Normal file
@ -0,0 +1,35 @@
|
||||
#version 450
|
||||
#extension GL_EXT_nonuniform_qualifier : require
|
||||
#extension GL_EXT_debug_printf : require
|
||||
#extension GL_GOOGLE_include_directive : require
|
||||
|
||||
#include "rect.inc"
|
||||
|
||||
layout (location = 0) in flat uint texture_index;
|
||||
layout (location = 1) in RectFragmentShaderInput inputs;
|
||||
|
||||
layout (location = 0) out vec4 color;
|
||||
|
||||
layout(set = 0, binding = 0) uniform sampler2D textures[];
|
||||
|
||||
float rounded_rect_sdf(vec2 position, vec2 center, vec2 half_size, float radius)
|
||||
{
|
||||
vec2 d2 = abs(center - position) - half_size + vec2(radius, radius);
|
||||
float result = min(max(d2.x, d2.y), 0.0) + length(max(d2, 0.0)) - radius;
|
||||
return result;
|
||||
}
|
||||
|
||||
void main()
|
||||
{
|
||||
uint sampler_index = nonuniformEXT(texture_index);
|
||||
vec2 texture_size = textureSize(textures[sampler_index], 0);
|
||||
vec2 uv = vec2(inputs.uv.x / texture_size.x, inputs.uv.y / texture_size.y);
|
||||
vec4 sampled = texture(textures[sampler_index], uv);
|
||||
float softness = inputs.softness;
|
||||
float softness_padding_scalar = max(0, softness * 2 - 1);
|
||||
vec2 softness_padding = vec2(softness_padding_scalar, softness_padding_scalar);
|
||||
float distance = rounded_rect_sdf(inputs.position, inputs.center, inputs.half_size - softness_padding, inputs.corner_radius);
|
||||
|
||||
float sdf_factor = 1.0 - smoothstep(0, 2 * softness, distance);
|
||||
color = inputs.color * sampled * sdf_factor;
|
||||
}
|
22
bootstrap/std/shaders/rect.inc
Normal file
22
bootstrap/std/shaders/rect.inc
Normal file
@ -0,0 +1,22 @@
|
||||
struct RectVertex
|
||||
{
|
||||
vec2 p0;
|
||||
vec2 uv0;
|
||||
vec2 extent;
|
||||
float corner_radius;
|
||||
float softness;
|
||||
vec4 colors[4];
|
||||
uint texture_index;
|
||||
uint reserved[3];
|
||||
};
|
||||
|
||||
struct RectFragmentShaderInput
|
||||
{
|
||||
vec4 color;
|
||||
vec2 uv;
|
||||
vec2 position;
|
||||
vec2 center;
|
||||
vec2 half_size;
|
||||
float corner_radius;
|
||||
float softness;
|
||||
};
|
61
bootstrap/std/shaders/rect.vert
Normal file
61
bootstrap/std/shaders/rect.vert
Normal file
@ -0,0 +1,61 @@
|
||||
#version 450
|
||||
#extension GL_EXT_buffer_reference : require
|
||||
#extension GL_EXT_debug_printf : require
|
||||
#extension GL_GOOGLE_include_directive : require
|
||||
|
||||
#include "rect.inc"
|
||||
|
||||
layout (location = 0) out uint texture_index;
|
||||
layout (location = 1) out RectFragmentShaderInput outputs;
|
||||
|
||||
layout(buffer_reference, std430) readonly buffer VertexBuffer{
|
||||
RectVertex vertices[];
|
||||
};
|
||||
|
||||
layout(push_constant) uniform constants
|
||||
{
|
||||
VertexBuffer vertex_buffer;
|
||||
float width;
|
||||
float height;
|
||||
} PushConstants;
|
||||
|
||||
const vec2 vertices[] = {
|
||||
{ -1, -1 },
|
||||
{ +1, -1 },
|
||||
{ -1, +1 },
|
||||
{ +1, +1 },
|
||||
};
|
||||
|
||||
void main()
|
||||
{
|
||||
RectVertex v = PushConstants.vertex_buffer.vertices[gl_VertexIndex];
|
||||
uint vertex_id = gl_VertexIndex % 4;
|
||||
float width = PushConstants.width;
|
||||
float height = PushConstants.height;
|
||||
|
||||
vec2 extent = v.extent;
|
||||
|
||||
vec2 p0 = v.p0;
|
||||
vec2 p1 = p0 + extent;
|
||||
vec2 position_center = (p1 + p0) / 2;
|
||||
vec2 half_size = (p1 - p0) / 2;
|
||||
vec2 position = vertices[vertex_id] * half_size + position_center;
|
||||
//debugPrintfEXT("Vertex index: (%u). P0: (%f, %f). P1: (%f, %f). Center: (%f, %f). Half size: (%f, %f). Position: (%f, %f)\n", gl_VertexIndex, p0.x, p0.y, p1.x, p1.y, center.x, center.y, half_size.x, half_size.y, position.x, position.y);
|
||||
|
||||
gl_Position = vec4(2 * position.x / width - 1, 2 * position.y / height - 1, 0, 1);
|
||||
|
||||
vec2 uv0 = v.uv0;
|
||||
vec2 uv1 = uv0 + extent;
|
||||
vec2 texture_center = (uv1 + uv0) / 2;
|
||||
vec2 uv = vertices[vertex_id] * half_size + texture_center;
|
||||
|
||||
texture_index = v.texture_index;
|
||||
|
||||
outputs.color = v.colors[vertex_id];
|
||||
outputs.uv = uv;
|
||||
outputs.position = position;
|
||||
outputs.center = position_center;
|
||||
outputs.half_size = half_size;
|
||||
outputs.corner_radius = v.corner_radius;
|
||||
outputs.softness = v.softness;
|
||||
}
|
@ -248,8 +248,8 @@ UI_Widget* ui_widget_make_from_key(UI_WidgetFlags flags, UI_Key key)
|
||||
|
||||
auto color = count % 3 == 0;
|
||||
widget->key = key;
|
||||
widget->background_color = Color4(color, color, color, 1);
|
||||
widget->text_color = Color4(!color, !color, !color, 1);
|
||||
widget->background_color = (float4) { color, color, color, 1 };
|
||||
widget->text_color = (float4) { !color, !color, !color, 1 };
|
||||
widget->flags = flags;
|
||||
widget->first = 0;
|
||||
widget->last = 0;
|
||||
@ -462,8 +462,8 @@ u8 ui_build_begin(OSWindow os_window, f64 frame_time, OSEventQueue* event_queue)
|
||||
ui_push(parent, root);
|
||||
|
||||
ui_push(font_size, 12);
|
||||
ui_push(text_color, Color4(1, 1, 1, 1));
|
||||
ui_push(background_color, Color4(0, 0, 0, 1));
|
||||
ui_push(text_color, ((float4) { 1, 1, 1, 1 }));
|
||||
ui_push(background_color, ((float4) { 0, 0, 0, 1 }));
|
||||
ui_push(pref_width, ui_percentage(1.0, 0.0));
|
||||
ui_push(pref_height, ui_percentage(1.0, 0.0));
|
||||
// ui_push(pref_height, ui_em(1.8, 0.0));
|
||||
@ -482,7 +482,7 @@ fn void ui_compute_independent_sizes(UI_Widget* widget)
|
||||
default: break; case UI_SIZE_COUNT: unreachable();
|
||||
case UI_SIZE_PIXEL_COUNT:
|
||||
{
|
||||
widget->computed_size.v[axis] = floorf(widget->pref_size[axis].value);
|
||||
widget->computed_size[axis] = floorf(widget->pref_size[axis].value);
|
||||
} break;
|
||||
}
|
||||
}
|
||||
@ -508,7 +508,7 @@ fn void ui_compute_upward_dependent_sizes(UI_Widget* widget)
|
||||
{
|
||||
if (ancestor->pref_size[axis].kind != UI_SIZE_BY_CHILDREN)
|
||||
{
|
||||
widget->computed_size.v[axis] = floorf(ancestor->computed_size.v[axis] * widget->pref_size[axis].value);
|
||||
widget->computed_size[axis] = floorf(ancestor->computed_size[axis] * widget->pref_size[axis].value);
|
||||
break;
|
||||
}
|
||||
}
|
||||
@ -547,7 +547,7 @@ fn void ui_resolve_conflicts(UI_Widget* widget)
|
||||
{
|
||||
for (Axis2 axis = 0; axis < AXIS2_COUNT; axis += 1)
|
||||
{
|
||||
auto available_space = widget->computed_size.v[axis];
|
||||
auto available_space = widget->computed_size[axis];
|
||||
f32 taken_space = 0;
|
||||
f32 total_fixup_budget = 0;
|
||||
|
||||
@ -559,13 +559,13 @@ fn void ui_resolve_conflicts(UI_Widget* widget)
|
||||
{
|
||||
if (axis == widget->child_layout_axis)
|
||||
{
|
||||
taken_space += child_widget->computed_size.v[axis];
|
||||
taken_space += child_widget->computed_size[axis];
|
||||
}
|
||||
else
|
||||
{
|
||||
taken_space = MAX(taken_space, child_widget->computed_size.v[axis]);
|
||||
taken_space = MAX(taken_space, child_widget->computed_size[axis]);
|
||||
}
|
||||
auto fixup_budget_this_child = child_widget->computed_size.v[axis] * (1 - child_widget->pref_size[axis].strictness);
|
||||
auto fixup_budget_this_child = child_widget->computed_size[axis] * (1 - child_widget->pref_size[axis].strictness);
|
||||
total_fixup_budget += fixup_budget_this_child;
|
||||
}
|
||||
}
|
||||
@ -578,7 +578,7 @@ fn void ui_resolve_conflicts(UI_Widget* widget)
|
||||
{
|
||||
if (!(child_widget->flags.v & (UI_WIDGET_FLAG_FLOATING_X << axis)))
|
||||
{
|
||||
auto fixup_budget_this_child = child_widget->computed_size.v[axis] * (1 - child_widget->pref_size[axis].strictness);
|
||||
auto fixup_budget_this_child = child_widget->computed_size[axis] * (1 - child_widget->pref_size[axis].strictness);
|
||||
f32 fixup_size_this_child = 0;
|
||||
|
||||
if (axis == widget->child_layout_axis)
|
||||
@ -587,11 +587,11 @@ fn void ui_resolve_conflicts(UI_Widget* widget)
|
||||
}
|
||||
else
|
||||
{
|
||||
fixup_size_this_child = child_widget->computed_size.v[axis] - available_space;
|
||||
fixup_size_this_child = child_widget->computed_size[axis] - available_space;
|
||||
}
|
||||
|
||||
fixup_size_this_child = CLAMP(0, fixup_size_this_child, fixup_budget_this_child);
|
||||
child_widget->computed_size.v[axis] = floorf(child_widget->computed_size.v[axis] - fixup_size_this_child);
|
||||
child_widget->computed_size[axis] = floorf(child_widget->computed_size[axis] - fixup_size_this_child);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -605,8 +605,8 @@ fn void ui_resolve_conflicts(UI_Widget* widget)
|
||||
{
|
||||
if (!(child_widget->flags.v & (UI_WIDGET_FLAG_FLOATING_X << axis)))
|
||||
{
|
||||
child_widget->computed_relative_position.v[axis] = p;
|
||||
p += child_widget->computed_size.v[axis];
|
||||
child_widget->computed_relative_position[axis] = p;
|
||||
p += child_widget->computed_size[axis];
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -616,7 +616,7 @@ fn void ui_resolve_conflicts(UI_Widget* widget)
|
||||
{
|
||||
if (!(child_widget->flags.v & (UI_WIDGET_FLAG_FLOATING_X << axis)))
|
||||
{
|
||||
child_widget->computed_relative_position.v[axis] = 0;
|
||||
child_widget->computed_relative_position[axis] = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -624,26 +624,26 @@ fn void ui_resolve_conflicts(UI_Widget* widget)
|
||||
for (UI_Widget* child_widget = widget->first; child_widget; child_widget = child_widget->next)
|
||||
{
|
||||
auto last_relative_rect = child_widget->relative_rect;
|
||||
child_widget->relative_rect.p0.v[axis] = child_widget->computed_relative_position.v[axis];
|
||||
child_widget->relative_rect.p1.v[axis] = child_widget->relative_rect.p0.v[axis] + child_widget->computed_size.v[axis];
|
||||
child_widget->relative_rect.p0[axis] = child_widget->computed_relative_position[axis];
|
||||
child_widget->relative_rect.p1[axis] = child_widget->relative_rect.p0[axis] + child_widget->computed_size[axis];
|
||||
|
||||
F32Vec2 last_corner_01 = { .x = last_relative_rect.x0, .y = last_relative_rect.y1 };
|
||||
F32Vec2 last_corner_10 = { .x = last_relative_rect.x1, .y = last_relative_rect.y0 };
|
||||
F32Vec2 this_corner_01 = { .x = child_widget->relative_rect.x0, .y = child_widget->relative_rect.y1 };
|
||||
F32Vec2 this_corner_10 = { .x = child_widget->relative_rect.x1, .y = child_widget->relative_rect.y0 };
|
||||
float2 last_corner_01 = { last_relative_rect.x0, last_relative_rect.y1 };
|
||||
float2 last_corner_10 = { last_relative_rect.x1, last_relative_rect.y0 };
|
||||
float2 this_corner_01 = { child_widget->relative_rect.x0, child_widget->relative_rect.y1 };
|
||||
float2 this_corner_10 = { child_widget->relative_rect.x1, child_widget->relative_rect.y0 };
|
||||
|
||||
child_widget->relative_corner_delta[CORNER_00].v[axis] = child_widget->relative_rect.p0.v[axis] - last_relative_rect.p0.v[axis];
|
||||
child_widget->relative_corner_delta[CORNER_01].v[axis] = this_corner_01.v[axis] - last_corner_01.v[axis];
|
||||
child_widget->relative_corner_delta[CORNER_10].v[axis] = this_corner_10.v[axis] - last_corner_10.v[axis];
|
||||
child_widget->relative_corner_delta[CORNER_11].v[axis] = child_widget->relative_rect.p1.v[axis] - last_relative_rect.p1.v[axis];
|
||||
child_widget->relative_corner_delta[CORNER_00][axis] = child_widget->relative_rect.p0[axis] - last_relative_rect.p0[axis];
|
||||
child_widget->relative_corner_delta[CORNER_01][axis] = this_corner_01[axis] - last_corner_01[axis];
|
||||
child_widget->relative_corner_delta[CORNER_10][axis] = this_corner_10[axis] - last_corner_10[axis];
|
||||
child_widget->relative_corner_delta[CORNER_11][axis] = child_widget->relative_rect.p1[axis] - last_relative_rect.p1[axis];
|
||||
|
||||
child_widget->rect.p0.v[axis] = widget->rect.p0.v[axis] + child_widget->relative_rect.p0.v[axis] - widget->view_offset.v[axis];
|
||||
child_widget->rect.p1.v[axis] = child_widget->rect.p0.v[axis] + child_widget->computed_size.v[axis];
|
||||
child_widget->rect.p0[axis] = widget->rect.p0[axis] + child_widget->relative_rect.p0[axis] - widget->view_offset[axis];
|
||||
child_widget->rect.p1[axis] = child_widget->rect.p0[axis] + child_widget->computed_size[axis];
|
||||
|
||||
if (!(child_widget->flags.v & (UI_WIDGET_FLAG_FLOATING_X << axis)))
|
||||
{
|
||||
child_widget->rect.p0.v[axis] = floorf(child_widget->rect.p0.v[axis]);
|
||||
child_widget->rect.p1.v[axis] = floorf(child_widget->rect.p1.v[axis]);
|
||||
child_widget->rect.p0[axis] = floorf(child_widget->rect.p0[axis]);
|
||||
child_widget->rect.p1[axis] = floorf(child_widget->rect.p1[axis]);
|
||||
}
|
||||
}
|
||||
|
||||
@ -674,16 +674,6 @@ void ui_build_end()
|
||||
ui_resolve_conflicts(ui_state->root);
|
||||
}
|
||||
|
||||
fn RenderRect render_rect(F32Interval2 rect)
|
||||
{
|
||||
return (RenderRect) {
|
||||
.x0 = rect.x0,
|
||||
.y0 = rect.y0,
|
||||
.x1 = rect.x1,
|
||||
.y1 = rect.y1,
|
||||
};
|
||||
}
|
||||
|
||||
STRUCT(WidgetIterator)
|
||||
{
|
||||
UI_Widget* next;
|
||||
@ -734,8 +724,8 @@ void ui_draw()
|
||||
if (widget->flags.draw_background)
|
||||
{
|
||||
window_render_rect(window, (RectDraw) {
|
||||
.colors = (RectColors) { .v = { Color4(1, 1, 1, 1), Color4(1, 1, 1, 1), widget->background_color, widget->background_color } },
|
||||
.vertex = render_rect(widget->rect),
|
||||
.colors = { (float4) {1, 1, 1, 1 }, (float4) {1, 1, 1, 1}, widget->background_color, widget->background_color },
|
||||
.vertex = widget->rect,
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -105,6 +105,7 @@ cmake . \
|
||||
$CXX_COMPILER_OPT_ARG \
|
||||
$ASM_COMPILER_OPT_ARG
|
||||
|
||||
export VK_LAYER_PRINTF_BUFFER_SIZE=1000000
|
||||
cd $BUILD_DIR
|
||||
ninja -v
|
||||
cd $ORIGINAL_DIR/build
|
||||
|
Loading…
x
Reference in New Issue
Block a user