diff --git a/Cargo.lock b/Cargo.lock index 8605000b24..2dbbf6fd5f 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1,5 +1,21 @@ # This file is automatically @generated by Cargo. # It is not intended for manual editing. +[[package]] +name = "ab_glyph" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "89080d12ceb15b6e4c748e1e0ec048bf97ef28fa20c285dd411738a9d648b08a" +dependencies = [ + "ab_glyph_rasterizer", + "owned_ttf_parser", +] + +[[package]] +name = "ab_glyph_rasterizer" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2b7e4e8cf778db814365e46839949ca74df4efb10e87ba4913e6ec5967ef0285" + [[package]] name = "adler32" version = "1.0.4" @@ -431,6 +447,16 @@ dependencies = [ "itertools", ] +[[package]] +name = "crossbeam-channel" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cced8691919c02aac3cb0a1bc2e9b73d89e832bf9a06fc579d4e71b68a2da061" +dependencies = [ + "crossbeam-utils", + "maybe-uninit", +] + [[package]] name = "crossbeam-deque" version = "0.7.3" @@ -764,6 +790,45 @@ dependencies = [ "tempfile", ] +[[package]] +name = "glyph_brush" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "afd3e2cfd503a5218dd56172a8bf7c8655a4a7cf745737c606a6edfeea1b343f" +dependencies = [ + "glyph_brush_draw_cache", + "glyph_brush_layout", + "log", + "ordered-float", + "rustc-hash", + "twox-hash", +] + +[[package]] +name = "glyph_brush_draw_cache" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "588662439c80d2784e6bb1274e2a6378ffcc74f8006b02e67e905039e200764d" +dependencies = [ + "ab_glyph", + "crossbeam-channel", + "crossbeam-deque", + "linked-hash-map", + "rayon", + "rustc-hash", +] + +[[package]] +name = "glyph_brush_layout" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9aa49abf7dcf7bfe68f42c1c8ab7473505aaba14de84afb8899a0109b6c61717" +dependencies = [ + "ab_glyph", + "approx", + "xi-unicode", +] + [[package]] name = "heck" version = "0.3.1" @@ -995,6 +1060,12 @@ dependencies = [ "num-traits", ] +[[package]] +name = "linked-hash-map" +version = "0.5.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8dd5a6d5999d9907cda8ed67bbd137d3af8085216c2ac62de5be860bd41f304a" + [[package]] name = "llvm-sys" version = "100.0.1" @@ -1293,6 +1364,15 @@ dependencies = [ "num-traits", ] +[[package]] +name = "owned_ttf_parser" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9f923fb806c46266c02ab4a5b239735c144bdeda724a50ed058e5226f594cde3" +dependencies = [ + "ttf-parser", +] + [[package]] name = "parking_lot" version = "0.10.2" @@ -1830,6 +1910,7 @@ dependencies = [ "gfx-backend-vulkan", "gfx-hal", "glsl-to-spirv", + "glyph_brush", "im", "im-rc", "image", @@ -2120,6 +2201,12 @@ dependencies = [ "roc_types", ] +[[package]] +name = "rustc-hash" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "08d43f7aa6b08d49f382cde6a7982047c3426db949b1424bc4b7ec9ae12c6ce2" + [[package]] name = "rustc_version" version = "0.2.3" @@ -2450,6 +2537,21 @@ dependencies = [ "winapi 0.3.8", ] +[[package]] +name = "ttf-parser" +version = "0.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "52fbe7769f5af5d7d25aea74b9443b64e544a5ffb4d2b2968295ddea934f1a06" + +[[package]] +name = "twox-hash" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3bfd5b7557925ce778ff9b9ef90e3ade34c524b5ff10e239c69a42d546d2af56" +dependencies = [ + "rand 0.7.3", +] + [[package]] name = "typed-arena" version = "2.0.1" @@ -2796,6 +2898,12 @@ version = "2.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d089681aa106a86fade1b0128fb5daf07d5867a509ab036d99988dec80429a57" +[[package]] +name = "xi-unicode" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7395cdb9d0a6219fa0ea77d08c946adf9c1984c72fcd443ace30365f3daadef7" + [[package]] name = "xml-rs" version = "0.8.3" diff --git a/editor/Cargo.toml b/editor/Cargo.toml index fdaea372ed..5a331ea6b3 100644 --- a/editor/Cargo.toml +++ b/editor/Cargo.toml @@ -50,6 +50,7 @@ inkwell = { git = "https://github.com/rtfeldman/inkwell", tag = "llvm10-0.releas target-lexicon = "0.10" winit = "0.22" image = "0.23" +glyph_brush="0.7" gfx-hal = "0.5" glsl-to-spirv = "0.1" bincode = "1.2" diff --git a/editor/shaders/text.frag b/editor/shaders/text.frag new file mode 100644 index 0000000000..5492b796fa --- /dev/null +++ b/editor/shaders/text.frag @@ -0,0 +1,17 @@ +#version 450 +#extension GL_ARB_separate_shader_objects : enable + +uniform sampler2D font_tex; + +layout(location = 0) in vec2 f_tex_pos; +layout(location = 1) in vec4 f_color; + +layout(location = 0) out vec4 out_color; + +void main() { + float alpha = texture(font_tex, f_tex_pos).r; + if (alpha <= 0.0) { + discard; + } + out_color = f_color * vec4(1.0, 1.0, 1.0, alpha); +} diff --git a/editor/shaders/text.vert b/editor/shaders/text.vert new file mode 100644 index 0000000000..8aaf383746 --- /dev/null +++ b/editor/shaders/text.vert @@ -0,0 +1,53 @@ +#version 450 +#extension GL_ARB_separate_shader_objects : enable + +const mat4 INVERT_Y_AXIS = mat4( + vec4(1.0, 0.0, 0.0, 0.0), + vec4(0.0, -1.0, 0.0, 0.0), + vec4(0.0, 0.0, 1.0, 0.0), + vec4(0.0, 0.0, 0.0, 1.0) +); + +/* layout(push_constant) uniform Transform { */ +/* mat4 matrix; */ +/* } transform; */ + +layout(location = 0) in vec3 left_top; +layout(location = 1) in vec2 right_bottom; +layout(location = 2) in vec2 tex_left_top; +layout(location = 3) in vec2 tex_right_bottom; +layout(location = 4) in vec4 color; + +layout(location = 0) out vec2 f_tex_pos; +layout(location = 1) out vec4 f_color; + +// generate positional data based on vertex ID +void main() { + vec2 pos = vec2(0.0); + float left = left_top.x; + float right = right_bottom.x; + float top = left_top.y; + float bottom = right_bottom.y; + + switch (gl_VertexIndex) { + case 0: + pos = vec2(left, top); + f_tex_pos = tex_left_top; + break; + case 1: + pos = vec2(right, top); + f_tex_pos = vec2(tex_right_bottom.x, tex_left_top.y); + break; + case 2: + pos = vec2(left, bottom); + f_tex_pos = vec2(tex_left_top.x, tex_right_bottom.y); + break; + case 3: + pos = vec2(right, bottom); + f_tex_pos = tex_right_bottom; + break; + } + + f_color = color; + gl_Position = INVERT_Y_AXIS * /*transform.matrix * */ vec4(pos, left_top.z, 1.0); +} diff --git a/editor/src/lib.rs b/editor/src/lib.rs index cff7fe34e6..9cd830c04b 100644 --- a/editor/src/lib.rs +++ b/editor/src/lib.rs @@ -70,10 +70,29 @@ impl Drop for ResourceHolder { #[repr(C)] #[derive(Debug, Clone, Copy)] -struct PushConstants { - color: [f32; 4], - pos: [f32; 2], - scale: [f32; 2], +struct Transform { + matrix: Mat4, +} + +#[repr(C)] +#[derive(Debug, Clone, Copy)] +struct Mat4 { + m11: f32, + m21: f32, + m31: f32, + m41: f32, + m12: f32, + m22: f32, + m32: f32, + m42: f32, + m13: f32, + m23: f32, + m33: f32, + m43: f32, + m14: f32, + m24: f32, + m34: f32, + m44: f32, } fn run_event_loop() { @@ -201,15 +220,16 @@ fn run_event_loop() { let pipeline_layout = unsafe { use gfx_hal::pso::ShaderStageFlags; - let push_constant_bytes = std::mem::size_of::() as u32; + let push_constant_bytes = std::mem::size_of::() as u32; device .create_pipeline_layout(&[], &[(ShaderStageFlags::VERTEX, 0..push_constant_bytes)]) .expect("Out of memory") }; - let vertex_shader = include_str!("../shaders/triangle.vert"); - let fragment_shader = include_str!("../shaders/triangle.frag"); + // Vertex and fragment shaders for text + let text_vs = include_str!("../shaders/text.vert"); + let text_fs = include_str!("../shaders/text.frag"); /// Create a pipeline with the given layout and shaders. unsafe fn make_pipeline( @@ -284,13 +304,7 @@ fn run_event_loop() { }; let pipeline = unsafe { - make_pipeline::( - &device, - &render_pass, - &pipeline_layout, - vertex_shader, - fragment_shader, - ) + make_pipeline::(&device, &render_pass, &pipeline_layout, text_vs, text_fs) }; let submission_complete_fence = device.create_fence(true).expect("Out of memory"); @@ -368,18 +382,48 @@ fn run_event_loop() { let pipeline_layout = &res.pipeline_layouts[0]; let pipeline = &res.pipelines[0]; - let triangles = text_state.chars().enumerate().map(|(index, char)| { + let triangles = text_state.chars().enumerate().map(|(_index, char)| { if char == ' ' { - PushConstants { - color: [0.0, 0.0, 0.0, 0.0], - pos: [0.0, 0.0], - scale: [0.00, 0.00], + Transform { + matrix: Mat4 { + m11: 0.0, + m21: 0.0, + m31: 0.0, + m41: 0.0, + m12: 0.0, + m22: 0.0, + m32: 0.0, + m42: 0.0, + m13: 0.0, + m23: 0.0, + m33: 0.0, + m43: 0.0, + m14: 0.0, + m24: 0.0, + m34: 0.0, + m44: 0.0, + }, } } else { - PushConstants { - color: [1.0, 1.0, 1.0, 1.0], - pos: [0.06 * index as f32, 0.0], - scale: [0.05, 0.05], + Transform { + matrix: Mat4 { + m11: 0.0, + m21: 0.0, + m31: 0.0, + m41: 0.0, + m12: 0.0, + m22: 0.0, + m32: 0.0, + m42: 0.0, + m13: 0.0, + m23: 0.0, + m33: 0.0, + m43: 0.0, + m14: 0.0, + m24: 0.0, + m34: 0.0, + m44: 0.0, + }, } } });