diff --git a/.ignore b/.ignore index a6ae5ac..578b033 100644 --- a/.ignore +++ b/.ignore @@ -2,3 +2,4 @@ src/VulkanRenderer/vma src/DLibs/external build +assets diff --git a/assets/gui.frag.spv b/assets/gui.frag.spv index 2c93105..7bf5ca3 100644 Binary files a/assets/gui.frag.spv and b/assets/gui.frag.spv differ diff --git a/assets/gui.vert.spv b/assets/gui.vert.spv index b52986e..a8a2e35 100644 Binary files a/assets/gui.vert.spv and b/assets/gui.vert.spv differ diff --git a/dub.json b/dub.json index affcfd2..32ef420 100644 --- a/dub.json +++ b/dub.json @@ -16,7 +16,7 @@ "versions": ["VK_DEBUG_PRINTF"], "preGenerateCommands-linux": ["./build.sh"], "preGenerateCommands-windows": [], - "dflags": ["-Xcc=-mno-sse", "-P-I/usr/include/freetype2", "-Jbuild"], + "dflags": ["-Xcc=-mno-sse", "-P-I/usr/include/freetype2", "-Jbuild", "-Jassets"], "dflags-dmd": ["-P=-DSTBI_NO_SIMD"] }, ] diff --git a/src/VulkanRenderer b/src/VulkanRenderer index e5f4777..5c2a3ab 160000 --- a/src/VulkanRenderer +++ b/src/VulkanRenderer @@ -1 +1 @@ -Subproject commit e5f47772a5d879f3cd5848108761271876bbef0e +Subproject commit 5c2a3ab5efa1aaa15ca6f3144655550dd024823a diff --git a/src/dlib b/src/dlib index f8d1707..f211a29 160000 --- a/src/dlib +++ b/src/dlib @@ -1 +1 @@ -Subproject commit f8d1707450d92bd147a3283527043c86312b3872 +Subproject commit f211a29857111a6be26b9cb0e9799ffcb7631df6 diff --git a/src/editor/editor.d b/src/editor/editor.d index c80d801..130a45f 100644 --- a/src/editor/editor.d +++ b/src/editor/editor.d @@ -10,6 +10,10 @@ import buffer; import std.stdio; import std.exception; +const u8[] FONT_BYTES = import("pc-9800.ttf"); +const u8[] VERTEX_BYTES = import("gui.vert.spv"); +const u8[] FRAGMENT_BYTES = import("gui.frag.spv"); + const UI_COUNT = 50000; struct Editor @@ -52,7 +56,7 @@ struct PushConst struct Vertex { - Vec4 col; + Vec4[4] cols; Vec2 dst_start; Vec2 dst_end; Vec2 src_start; @@ -76,7 +80,8 @@ Cycle(Editor* ed) //DrawRect(ed, 200.0, 200.0, 300.0, 300.0, 0.0, 0.0, 0.0, Vec4(0.2, 0.4, 0.8, 1.0)); //DrawRect(ed, 330.0, 330.0, 430.0, 430.0, 0.0, 0.0, 0.0, Vec4(0.2, 0.4, 0.8, 1.0)); - DrawRect(ed, 450.0, 450.0, 550.0, 550.0, 0.0, 1.0, 0.0, Vec4(1.0)); + DrawRect(ed, 450.0, 450.0, 550.0, 550.0, 0.0, 5.0, 1.0, 20.0, [Vec4(0.2, 0.5, 0.9, 1.0), Vec4(Vec3(0.8), 1.0), Vec4(Vec3(0.8), 1.0), Vec4(Vec3(0.6), 1.0)]); + DrawRect(ed, 450.0, 450.0, 550.0, 550.0, 2.0, 5.0, 1.0, 20.0, [Vec4(Vec3(0.0), 1.0), Vec4(Vec3(0.0), 1.0), Vec4(Vec3(0.0), 1.0), Vec4(Vec3(0.0), 1.0)]); BeginFrame(&ed.rd); @@ -142,8 +147,7 @@ CreateEditor(PlatformWindow* window, u8[] buffer_data, u8[] buffer_name) Arena arena = CreateArena(MB(32)); - u8[] font_data = LoadFile(&arena, "assets/pc-9800.ttf"); - FontFace font = OpenFont(font_data); + FontFace font = OpenFont(cast(u8[])FONT_BYTES); FontAtlasBuf atlas_buf = CreateAtlas(&arena, font, 14.0, 256); Editor editor = { @@ -151,7 +155,7 @@ CreateEditor(PlatformWindow* window, u8[] buffer_data, u8[] buffer_name) arena: arena, temp_arena: CreateArena(MB(8)), rd: InitRenderer(handles, MB(32), MB(16)), - font_data: font_data, + font_data: cast(u8[])FONT_BYTES, font: font, atlas_buf: atlas_buf, buffers: MAllocArray!(FlatBuffer)(32), @@ -182,21 +186,24 @@ CreateEditor(PlatformWindow* window, u8[] buffer_data, u8[] buffer_name) editor.desc_set = AllocDescSet(&editor.rd, editor.desc_set_layout); editor.pipeline_layout = CreatePipelineLayout(&editor.rd, editor.desc_set_layout, PushConst.sizeof); - Attribute[9] attributes = [ - { binding: 0, location: 0, format: FMT.RGBA_F32, offset: Vertex.col.offsetof }, - { binding: 0, location: 1, format: FMT.RG_F32, offset: Vertex.dst_start.offsetof }, - { binding: 0, location: 2, format: FMT.RG_F32, offset: Vertex.dst_end.offsetof }, - { binding: 0, location: 3, format: FMT.RG_F32, offset: Vertex.src_start.offsetof }, - { binding: 0, location: 4, format: FMT.RG_F32, offset: Vertex.src_end.offsetof }, - { binding: 0, location: 5, format: FMT.R_F32, offset: Vertex.border_thickness.offsetof }, - { binding: 0, location: 6, format: FMT.R_F32, offset: Vertex.corner_radius.offsetof }, - { binding: 0, location: 7, format: FMT.R_F32, offset: Vertex.edge_softness.offsetof }, - { binding: 0, location: 8, format: FMT.R_F32, offset: Vertex.raised.offsetof }, + Attribute[12] attributes = [ + { binding: 0, location: 0, format: FMT.RGBA_F32, offset: Vertex.cols.offsetof + Vec4.sizeof * 0}, + { binding: 0, location: 1, format: FMT.RGBA_F32, offset: Vertex.cols.offsetof + Vec4.sizeof * 1}, + { binding: 0, location: 2, format: FMT.RGBA_F32, offset: Vertex.cols.offsetof + Vec4.sizeof * 2}, + { binding: 0, location: 3, format: FMT.RGBA_F32, offset: Vertex.cols.offsetof + Vec4.sizeof * 3}, + { binding: 0, location: 4, format: FMT.RG_F32, offset: Vertex.dst_start.offsetof }, + { binding: 0, location: 5, format: FMT.RG_F32, offset: Vertex.dst_end.offsetof }, + { binding: 0, location: 6, format: FMT.RG_F32, offset: Vertex.src_start.offsetof }, + { binding: 0, location: 7, format: FMT.RG_F32, offset: Vertex.src_end.offsetof }, + { binding: 0, location: 8, format: FMT.R_F32, offset: Vertex.border_thickness.offsetof }, + { binding: 0, location: 9, format: FMT.R_F32, offset: Vertex.corner_radius.offsetof }, + { binding: 0, location: 10, format: FMT.R_F32, offset: Vertex.edge_softness.offsetof }, + { binding: 0, location: 11, format: FMT.R_F32, offset: Vertex.raised.offsetof }, ]; GfxPipelineInfo ui_info = { - vertex_shader: LoadFile(&editor.temp_arena, "assets/gui.vert.spv"), - frag_shader: LoadFile(&editor.temp_arena, "assets/gui.frag.spv"), + vertex_shader: cast(u8[])VERTEX_BYTES, + frag_shader: cast(u8[])FRAGMENT_BYTES, input_rate: IR.Instance, input_rate_stride: Vertex.sizeof, layout: editor.pipeline_layout, @@ -220,6 +227,8 @@ CreateEditor(PlatformWindow* window, u8[] buffer_data, u8[] buffer_name) Write(&editor.rd, editor.desc_set, &editor.font_atlas, 0, DT.Image); + SetClearColors(&editor.rd, [0.149, 0.607, 0.768, 1.0], [0.0, 0.0, 0.0, 0.0]); + Reset(&editor.temp_arena); return editor; @@ -351,7 +360,10 @@ DrawGlyph(Editor* ed, Glyph* glyph, f32 scale, f32* x_pos, f32 y, Vec4 col = Vec v.src_end.x = glyph.atlas_right; v.src_end.y = glyph.atlas_bottom; - v.col = col; + v.cols[0] = col; + v.cols[1] = col; + v.cols[2] = col; + v.cols[3] = col; AddUIIndices(ed); } @@ -360,7 +372,7 @@ DrawGlyph(Editor* ed, Glyph* glyph, f32 scale, f32* x_pos, f32 y, Vec4 col = Vec } void -DrawRect(Editor* ed, f32 p0_x, f32 p0_y, f32 p1_x, f32 p1_y, f32 border, f32 corner, f32 softness, Vec4 col) +DrawRect(Editor* ed, f32 p0_x, f32 p0_y, f32 p1_x, f32 p1_y, f32 border, f32 corner, f32 softness, f32 raised, Vec4[4] cols) { // Y reversed Vertex* v = ed.vertices.ptr + ed.ui_count; @@ -368,10 +380,11 @@ DrawRect(Editor* ed, f32 p0_x, f32 p0_y, f32 p1_x, f32 p1_y, f32 border, f32 cor v.dst_start.y = p0_y; v.dst_end.x = p1_x; v.dst_end.y = p1_y; - v.col = col; + v.cols = cols; v.border_thickness = border; v.corner_radius = corner; v.edge_softness = softness; + v.raised = raised; AddUIIndices(ed); } diff --git a/src/shaders/gui.frag.glsl b/src/shaders/gui.frag.glsl index 1637234..d86d166 100644 --- a/src/shaders/gui.frag.glsl +++ b/src/shaders/gui.frag.glsl @@ -25,9 +25,19 @@ float RoundedRectSDF(vec2 pos, vec2 center, vec2 half_size, float radius) return min(max(dist.x, dist.y), 0.0) + length(max(dist, 0.0)) - radius; } -float RoundedRectSDF2(vec2 pos, vec2 center, vec2 size, float radius) +float ToSRGB(float col) { - return length(max(abs(pos - center) - size + radius, 0.0)) - radius; + return pow(col, 1.0/2.2); +} + +vec4 ToSRGB(vec4 col) +{ + return vec4(ToSRGB(col.r), ToSRGB(col.g), ToSRGB(col.b), col.a); +} + +vec4 ToLinear(vec4 col) +{ + return pow(col, vec4(vec3(2.2), 1.0)); } void main() @@ -35,15 +45,29 @@ void main() float softness = FD.softness; vec2 softness_padding = vec2(max(0, softness*2-1), max(0, softness*2-1)); - //float dist = RoundedRectSDF(FD.dst_pos, FD.dst_center, FD.dst_half_size-softness_padding, FD.corner_radius); - float dist = RoundedRectSDF2(FD.dst_pos, FD.dst_center, vec2(1.0), FD.corner_radius); + float dist = RoundedRectSDF(FD.dst_pos, FD.dst_center, FD.dst_half_size-softness_padding, FD.corner_radius); + //float dist = RoundedRectSDF2(FD.dst_pos, FD.dst_center, vec2(1.0), FD.corner_radius); float sdf_factor = 1.0 - smoothstep(0, 2*softness, dist); - debugPrintfEXT("%v2f %v2f %v2f %f", FD.dst_pos, FD.dst_center, FD.dst_half_size, sdf_factor); + float border_factor = 1.0; + if (FD.border_thickness != 0.0) + { + vec2 interior_half_size = FD.dst_half_size - vec2(FD.border_thickness); + + float interior_radius_reduce_f = min(interior_half_size.x/FD.dst_half_size.x, interior_half_size.y/FD.dst_half_size.y); + + float interior_corner_radius = FD.corner_radius * interior_radius_reduce_f * interior_radius_reduce_f; + + float inside_d = RoundedRectSDF(FD.dst_pos, FD.dst_center, interior_half_size-softness_padding, interior_corner_radius); + + float inside_f = smoothstep(0, 2*softness, inside_d); + border_factor = inside_f; + } vec4 tex_color = texture(sampler2D(SpriteAtlas, SamplerNearest), FD.uv); - vec4 out_color = FD.color * tex_color * sdf_factor; + debugPrintfEXT("tex_color %v4f", tex_color); + vec4 out_color = FD.color * tex_color * sdf_factor * border_factor; FragColor = out_color; } diff --git a/src/shaders/gui.vert.glsl b/src/shaders/gui.vert.glsl index dfb7c43..5d76729 100644 --- a/src/shaders/gui.vert.glsl +++ b/src/shaders/gui.vert.glsl @@ -4,15 +4,18 @@ #include "gui.layout" -layout (location = 0) in vec4 in_col; -layout (location = 1) in vec2 in_dst_start; -layout (location = 2) in vec2 in_dst_end; -layout (location = 3) in vec2 in_src_start; -layout (location = 4) in vec2 in_src_end; -layout (location = 5) in float border_thickness; -layout (location = 6) in float corner_radius; -layout (location = 7) in float edge_softness; -layout (location = 8) in float raised; +layout (location = 0) in vec4 in_col_1; +layout (location = 1) in vec4 in_col_2; +layout (location = 2) in vec4 in_col_3; +layout (location = 3) in vec4 in_col_4; +layout (location = 4) in vec2 in_dst_start; +layout (location = 5) in vec2 in_dst_end; +layout (location = 6) in vec2 in_src_start; +layout (location = 7) in vec2 in_src_end; +layout (location = 8) in float border_thickness; +layout (location = 9) in float corner_radius; +layout (location = 10) in float edge_softness; +layout (location = 11) in float raised; layout (location = 0) out struct FragDataOut { vec4 color; @@ -42,8 +45,8 @@ void main() { ivec2 tex_size = textureSize(sampler2D(SpriteAtlas, SamplerNearest), 0); - vec4 pos_start = PC.projection * vec4(in_dst_start.x, in_dst_start.y, 0.0, 1.0); - vec4 pos_end = PC.projection * vec4(in_dst_end.x, in_dst_end.y, 0.0, 1.0); + vec4 pos_start = vec4(in_dst_start.x, in_dst_start.y - raised, 0.0, 1.0); + vec4 pos_end = vec4(in_dst_end.x, in_dst_end.y, 0.0, 1.0); vec2 half_size = ((pos_end.xy - pos_start.xy) / 2); vec2 center = ((pos_end.xy + pos_start.xy) / 2); @@ -60,7 +63,14 @@ void main() vec2(in_src_end.x, in_src_end.y) ); - FragData.color = in_col; + vec4 cols[4] = vec4[4]( + in_col_1, + in_col_2, + in_col_3, + in_col_4 + ); + + FragData.color = cols[gl_VertexIndex]; FragData.uv = uvs[gl_VertexIndex] / tex_size; FragData.dst_pos = pos; FragData.dst_center = center; @@ -70,5 +80,6 @@ void main() FragData.raised = raised; FragData.border_thickness = border_thickness; - gl_Position = vec4(pos.x, pos.y, 0, 1); + vec4 v_pos = PC.projection * vec4(pos.x, pos.y, 0, 1); + gl_Position = vec4(v_pos.x, v_pos.y, 0, 1); }