diff --git a/assets/gui.frag.spv b/assets/gui.frag.spv index 6568e89..9535953 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 fb83d4f..b52986e 100644 Binary files a/assets/gui.vert.spv and b/assets/gui.vert.spv differ diff --git a/dub.json b/dub.json index 118cea4..affcfd2 100644 --- a/dub.json +++ b/dub.json @@ -13,6 +13,7 @@ "sourcePaths": ["src/editor", "src/dlib", "src/dlib/external/xxhash", "src/VulkanRenderer"], "libs-linux": ["xcb", "X11", "X11-xcb", "vulkan", "stdc++", "xcb-xfixes", "freetype"], "libs-windows": [], + "versions": ["VK_DEBUG_PRINTF"], "preGenerateCommands-linux": ["./build.sh"], "preGenerateCommands-windows": [], "dflags": ["-Xcc=-mno-sse", "-P-I/usr/include/freetype2", "-Jbuild"], diff --git a/src/VulkanRenderer b/src/VulkanRenderer index f3b7536..b0d96f2 160000 --- a/src/VulkanRenderer +++ b/src/VulkanRenderer @@ -1 +1 @@ -Subproject commit f3b7536c8e4edea80d3b7ef3e4265e521a050c03 +Subproject commit b0d96f26fe727d297c441ce989f3fec45095e3c3 diff --git a/src/dlib b/src/dlib index 98701be..f8d1707 160000 --- a/src/dlib +++ b/src/dlib @@ -1 +1 @@ -Subproject commit 98701be20c223d1130a1f423c8ca3b520c9d4a95 +Subproject commit f8d1707450d92bd147a3283527043c86312b3872 diff --git a/src/editor/editor.d b/src/editor/editor.d index 43a8100..c80d801 100644 --- a/src/editor/editor.d +++ b/src/editor/editor.d @@ -41,20 +41,26 @@ struct Editor u8[] font_data; FontFace font; FontAtlasBuf atlas_buf; + + UVec2 res; } struct PushConst { - Vec2 res; + Mat4 projection; } struct Vertex { + Vec4 col; Vec2 dst_start; Vec2 dst_end; Vec2 src_start; Vec2 src_end; - Vec4 col; + f32 border_thickness; + f32 corner_radius; + f32 edge_softness; + f32 raised; } void @@ -68,11 +74,18 @@ Cycle(Editor* ed) f32 h = ed.atlas_buf.atlas.size; DrawBuffer(ed, 0.0, 0.0, h, ed.active_buffer); + //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)); + BeginFrame(&ed.rd); UVec2 ext = UVec2(GetExtent(&ed.rd)); - ed.pc.res.x = cast(f32)ext.x; - ed.pc.res.y = cast(f32)ext.y; + if (ext != ed.res) + { + ed.res = ext; + Ortho(&ed.pc.projection, 0.0, 0.0, cast(f32)(ext.x), cast(f32)(ext.y), 1000.0, 0.1); + } BeginRendering(&ed.rd); @@ -169,12 +182,16 @@ 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[5] attributes = [ - { binding: 0, location: 0, format: FMT.RG_F32, offset: Vertex.dst_start.offsetof }, - { binding: 0, location: 1, format: FMT.RG_F32, offset: Vertex.dst_end.offsetof }, - { binding: 0, location: 2, format: FMT.RG_F32, offset: Vertex.src_start.offsetof }, - { binding: 0, location: 3, format: FMT.RG_F32, offset: Vertex.src_end.offsetof }, - { binding: 0, location: 4, format: FMT.RGBA_F32, offset: Vertex.col.offsetof }, + 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 }, ]; GfxPipelineInfo ui_info = { @@ -184,6 +201,12 @@ CreateEditor(PlatformWindow* window, u8[] buffer_data, u8[] buffer_name) input_rate_stride: Vertex.sizeof, layout: editor.pipeline_layout, vertex_attributes: attributes, + src_color: BF.SrcAlpha, + dst_color: BF.OneMinusSrcAlpha, + color_op: BO.Add, + src_alpha: BF.One, + dst_alpha: BF.Zero, + alpha_op: BO.Add, }; assert(CreateGraphicsPipeline(&editor.rd, &editor.pipeline, &ui_info), "Unable to build UI pipeline"); @@ -319,9 +342,9 @@ DrawGlyph(Editor* ed, Glyph* glyph, f32 scale, f32* x_pos, f32 y, Vec4 col = Vec f32 y_pos = glyph.plane_top * scale; v.dst_start.x = *x_pos + l; - v.dst_start.y = y + h - y_pos; + v.dst_start.y = y - y_pos; v.dst_end.x = *x_pos + w + l; - v.dst_end.y = y - y_pos; + v.dst_end.y = y + h - y_pos; v.src_start.x = glyph.atlas_left; v.src_start.y = glyph.atlas_top; @@ -336,6 +359,23 @@ DrawGlyph(Editor* ed, Glyph* glyph, f32 scale, f32* x_pos, f32 y, Vec4 col = Vec *x_pos += glyph.advance * scale; } +void +DrawRect(Editor* ed, f32 p0_x, f32 p0_y, f32 p1_x, f32 p1_y, f32 border, f32 corner, f32 softness, Vec4 col) +{ + // Y reversed + Vertex* v = ed.vertices.ptr + ed.ui_count; + v.dst_start.x = p0_x; + v.dst_start.y = p0_y; + v.dst_end.x = p1_x; + v.dst_end.y = p1_y; + v.col = col; + v.border_thickness = border; + v.corner_radius = corner; + v.edge_softness = softness; + + AddUIIndices(ed); +} + void AddUIIndices(Editor* ed) { diff --git a/src/shaders/gui.frag.glsl b/src/shaders/gui.frag.glsl index 60666e9..49ef7bd 100644 --- a/src/shaders/gui.frag.glsl +++ b/src/shaders/gui.frag.glsl @@ -1,18 +1,49 @@ #version 460 #extension GL_GOOGLE_include_directive : require +#extension GL_EXT_debug_printf : require #include "gui.layout" layout (location = 0) in struct FragDataIn { vec4 color; vec2 uv; -} FragData; + vec2 dst_pos; + vec2 dst_center; + vec2 dst_half_size; + float corner_radius; + float softness; + float raised; + float border_thickness; +} FD; layout (location = 0) out vec4 FragColor; +float RoundedRectSDF(vec2 pos, vec2 center, vec2 half_size, float radius) +{ + vec2 dist = (abs(center - pos) - half_size + vec2(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) +{ + return length(max(abs(pos - center) - size + radius, 0.0)) - radius; +} + void main() { - vec4 tex_color = texture(sampler2D(SpriteAtlas, SamplerNearest), FragData.uv); - FragColor = FragData.color * tex_color; + 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 sdf_factor = 1.0 - smoothstep(0, 2*softness, dist); + + debugPrintfEXT("%v2f %v2f %v2f", FD.dst_pos, FD.dst_center, FD.dst_half_size); + + vec4 tex_color = texture(sampler2D(SpriteAtlas, SamplerNearest), FD.uv); + vec4 out_color = FD.color * tex_color * sdf_factor; + + FragColor = out_color; } diff --git a/src/shaders/gui.layout b/src/shaders/gui.layout index 543f030..cb24155 100644 --- a/src/shaders/gui.layout +++ b/src/shaders/gui.layout @@ -5,5 +5,5 @@ layout (set = 0, binding = 1) uniform sampler SamplerNearest; layout (set = 1, binding = 0) uniform texture2D SpriteAtlas; layout (push_constant) uniform Constants { - vec2 res; + mat4 projection; } PC; diff --git a/src/shaders/gui.vert.glsl b/src/shaders/gui.vert.glsl index ea2b1bc..dfb7c43 100644 --- a/src/shaders/gui.vert.glsl +++ b/src/shaders/gui.vert.glsl @@ -4,22 +4,33 @@ #include "gui.layout" -layout (location = 0) in vec2 in_dst_start; -layout (location = 1) in vec2 in_dst_end; -layout (location = 2) in vec2 in_src_start; -layout (location = 3) in vec2 in_src_end; -layout (location = 4) in vec4 in_col; +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) out struct FragDataOut { vec4 color; vec2 uv; + vec2 dst_pos; + vec2 dst_center; + vec2 dst_half_size; + float corner_radius; + float softness; + float raised; + float border_thickness; } FragData; vec2 Vertices[4] = vec2[4]( - vec2(-1.0, +1.0), vec2(-1.0, -1.0), - vec2(+1.0, +1.0), - vec2(+1.0, -1.0) + vec2(-1.0, +1.0), + vec2(+1.0, -1.0), + vec2(+1.0, +1.0) ); vec2 rotate(vec2 coords, float theta) @@ -31,9 +42,12 @@ void main() { ivec2 tex_size = textureSize(sampler2D(SpriteAtlas, SamplerNearest), 0); - vec2 dst_half_size = (in_dst_end - in_dst_start) / 2; - vec2 dst_center = (in_dst_end + in_dst_start) / 2; - vec2 dst_pos = (Vertices[gl_VertexIndex] * dst_half_size + dst_center); + 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); + + vec2 half_size = ((pos_end.xy - pos_start.xy) / 2); + vec2 center = ((pos_end.xy + pos_start.xy) / 2); + vec2 pos = (Vertices[gl_VertexIndex] * half_size + center); vec2 src_half_size = (in_src_end - in_src_start) / 2; vec2 src_center = (in_src_end + in_src_start) / 2; @@ -48,9 +62,13 @@ void main() FragData.color = in_col; FragData.uv = uvs[gl_VertexIndex] / tex_size; + FragData.dst_pos = pos; + FragData.dst_center = center; + FragData.dst_half_size = half_size; + FragData.corner_radius = corner_radius; + FragData.softness = edge_softness; + FragData.raised = raised; + FragData.border_thickness = border_thickness; - gl_Position = vec4(2 * dst_pos.x / PC.res.x - 1, - 2 * dst_pos.y / PC.res.y - 1, - 0, - 1); + gl_Position = vec4(pos.x, pos.y, 0, 1); }