Draft a first working version 🎉

This commit is contained in:
Héctor Ramón Jiménez 2020-05-18 20:14:04 +02:00
parent 55275d7b05
commit 32c735ba36
4 changed files with 218 additions and 22 deletions

View File

@ -35,7 +35,13 @@ fn main() -> Result<(), String> {
context.window().request_redraw(); context.window().request_redraw();
unsafe { unsafe {
// Enable auto-conversion from/to sRGB
gl.enable(glow::FRAMEBUFFER_SRGB); gl.enable(glow::FRAMEBUFFER_SRGB);
// Enable alpha blending
gl.enable(glow::BLEND);
gl.blend_func(glow::SRC_ALPHA, glow::ONE_MINUS_SRC_ALPHA);
gl.clear_color(0.4, 0.4, 0.4, 1.0); gl.clear_color(0.4, 0.4, 0.4, 1.0);
} }
@ -51,13 +57,22 @@ fn main() -> Result<(), String> {
} => { } => {
context.resize(new_size); context.resize(new_size);
unsafe {
gl.viewport(
0,
0,
new_size.width as _,
new_size.height as _,
);
}
size = new_size; size = new_size;
} }
glutin::event::Event::RedrawRequested { .. } => { glutin::event::Event::RedrawRequested { .. } => {
unsafe { gl.clear(glow::COLOR_BUFFER_BIT) } unsafe { gl.clear(glow::COLOR_BUFFER_BIT) }
glyph_brush.queue(Section { glyph_brush.queue(Section {
text: "Hello wgpu_glyph!", text: "Hello glow_glyph!",
screen_position: (30.0, 30.0), screen_position: (30.0, 30.0),
color: [0.0, 0.0, 0.0, 1.0], color: [0.0, 0.0, 0.0, 1.0],
scale: Scale { x: 40.0, y: 40.0 }, scale: Scale { x: 40.0, y: 40.0 },
@ -66,7 +81,7 @@ fn main() -> Result<(), String> {
}); });
glyph_brush.queue(Section { glyph_brush.queue(Section {
text: "Hello wgpu_glyph!", text: "Hello glow_glyph!",
screen_position: (30.0, 90.0), screen_position: (30.0, 90.0),
color: [1.0, 1.0, 1.0, 1.0], color: [1.0, 1.0, 1.0, 1.0],
scale: Scale { x: 40.0, y: 40.0 }, scale: Scale { x: 40.0, y: 40.0 },

View File

@ -9,6 +9,7 @@ use glyph_brush::rusttype::{point, Rect};
pub struct Pipeline { pub struct Pipeline {
sampler: <glow::Context as HasContext>::Sampler, sampler: <glow::Context as HasContext>::Sampler,
program: <glow::Context as HasContext>::Program, program: <glow::Context as HasContext>::Program,
vertex_array: <glow::Context as HasContext>::VertexArray,
instances: <glow::Context as HasContext>::Buffer, instances: <glow::Context as HasContext>::Buffer,
cache: Cache, cache: Cache,
current_instances: usize, current_instances: usize,
@ -25,7 +26,7 @@ impl Pipeline {
let sampler = let sampler =
unsafe { gl.create_sampler().expect("Create glyph sampler") }; unsafe { gl.create_sampler().expect("Create glyph sampler") };
let cache = Cache::new(gl, cache_width, cache_height); let cache = unsafe { Cache::new(gl, cache_width, cache_height) };
let program = unsafe { let program = unsafe {
create_program( create_program(
@ -40,17 +41,18 @@ impl Pipeline {
) )
}; };
let instances = let (vertex_array, instances) =
unsafe { gl.create_buffer().expect("Create instance buffer") }; unsafe { create_instance_buffer(gl, Instance::INITIAL_AMOUNT) };
Pipeline { Pipeline {
sampler, sampler,
program, program,
cache, cache,
vertex_array,
instances, instances,
current_instances: 0, current_instances: 0,
supported_instances: Instance::INITIAL_AMOUNT, supported_instances: Instance::INITIAL_AMOUNT,
current_transform: [0.0; 16], current_transform: IDENTITY_MATRIX,
} }
} }
@ -60,6 +62,36 @@ impl Pipeline {
transform: [f32; 16], transform: [f32; 16],
region: Option<Region>, region: Option<Region>,
) { ) {
unsafe {
gl.use_program(Some(self.program));
}
if self.current_transform != transform {
unsafe {
gl.uniform_matrix_4_f32_slice(Some(0), false, &transform);
}
self.current_transform = transform;
}
unsafe {
gl.active_texture(glow::TEXTURE0);
gl.bind_texture(glow::TEXTURE_2D, Some(self.cache.texture));
gl.uniform_1_i32(Some(1), 0);
gl.bind_vertex_array(Some(self.vertex_array));
gl.draw_arrays_instanced(
glow::TRIANGLE_STRIP,
0,
4,
self.current_instances as i32,
);
gl.bind_vertex_array(None);
gl.bind_texture(glow::TEXTURE_2D, None);
gl.use_program(None);
}
} }
pub fn update_cache( pub fn update_cache(
@ -69,8 +101,10 @@ impl Pipeline {
size: [u16; 2], size: [u16; 2],
data: &[u8], data: &[u8],
) { ) {
unsafe {
self.cache.update(gl, offset, size, data); self.cache.update(gl, offset, size, data);
} }
}
pub fn increase_cache_size( pub fn increase_cache_size(
&mut self, &mut self,
@ -78,8 +112,12 @@ impl Pipeline {
width: u32, width: u32,
height: u32, height: u32,
) { ) {
unsafe {
self.cache.destroy(gl);
self.cache = Cache::new(gl, width, height); self.cache = Cache::new(gl, width, height);
} }
}
pub fn upload(&mut self, gl: &glow::Context, instances: &[Instance]) { pub fn upload(&mut self, gl: &glow::Context, instances: &[Instance]) {
if instances.is_empty() { if instances.is_empty() {
@ -88,12 +126,28 @@ impl Pipeline {
} }
if instances.len() > self.supported_instances { if instances.len() > self.supported_instances {
// TODO unsafe {
gl.delete_buffer(self.instances);
gl.delete_vertex_array(self.vertex_array);
}
let (new_vertex_array, new_instances) =
unsafe { create_instance_buffer(gl, instances.len()) };
self.vertex_array = new_vertex_array;
self.instances = new_instances;
self.supported_instances = instances.len(); self.supported_instances = instances.len();
} }
// TODO unsafe {
gl.bind_buffer(glow::ARRAY_BUFFER, Some(self.instances));
gl.buffer_sub_data_u8_slice(
glow::ARRAY_BUFFER,
0,
bytemuck::cast_slice(instances),
);
gl.bind_buffer(glow::ARRAY_BUFFER, None);
}
self.current_instances = instances.len(); self.current_instances = instances.len();
} }
@ -219,3 +273,63 @@ unsafe fn create_program(
program program
} }
unsafe fn create_instance_buffer(
gl: &glow::Context,
size: usize,
) -> (
<glow::Context as HasContext>::VertexArray,
<glow::Context as HasContext>::Buffer,
) {
let vertex_array = gl.create_vertex_array().expect("Create vertex array");
let buffer = gl.create_buffer().expect("Create instance buffer");
gl.bind_vertex_array(Some(vertex_array));
gl.bind_buffer(glow::ARRAY_BUFFER, Some(buffer));
gl.buffer_data_size(
glow::ARRAY_BUFFER,
(size * std::mem::size_of::<Instance>()) as i32,
glow::DYNAMIC_DRAW,
);
let stride = std::mem::size_of::<Instance>() as i32;
gl.enable_vertex_attrib_array(0);
gl.vertex_attrib_pointer_f32(0, 3, glow::FLOAT, false, stride, 0);
gl.vertex_attrib_divisor(0, 1);
gl.enable_vertex_attrib_array(1);
gl.vertex_attrib_pointer_f32(1, 2, glow::FLOAT, false, stride, 4 * 3);
gl.vertex_attrib_divisor(1, 1);
gl.enable_vertex_attrib_array(2);
gl.vertex_attrib_pointer_f32(2, 2, glow::FLOAT, false, stride, 4 * (3 + 2));
gl.vertex_attrib_divisor(2, 1);
gl.enable_vertex_attrib_array(3);
gl.vertex_attrib_pointer_f32(
3,
2,
glow::FLOAT,
false,
stride,
4 * (3 + 2 + 2),
);
gl.vertex_attrib_divisor(3, 1);
gl.enable_vertex_attrib_array(4);
gl.vertex_attrib_pointer_f32(
4,
4,
glow::FLOAT,
false,
stride,
4 * (3 + 2 + 2 + 2),
);
gl.vertex_attrib_divisor(4, 1);
gl.bind_vertex_array(None);
gl.bind_buffer(glow::ARRAY_BUFFER, None);
(vertex_array, buffer)
}

View File

@ -1,15 +1,55 @@
use glow::HasContext; use glow::HasContext;
pub struct Cache { pub struct Cache {
texture: <glow::Context as HasContext>::Texture, pub(crate) texture: <glow::Context as HasContext>::Texture,
} }
impl Cache { impl Cache {
pub fn new(gl: &glow::Context, width: u32, height: u32) -> Cache { pub unsafe fn new(gl: &glow::Context, width: u32, height: u32) -> Cache {
let texture = unsafe { gl.pixel_store_i32(glow::UNPACK_ALIGNMENT, 1);
let handle = gl.create_texture().expect("Create glyph cache texture");
gl.tex_storage_2d(handle, 1, glow::R8, width as i32, height as i32); let texture = {
let handle =
gl.create_texture().expect("Create glyph cache texture");
gl.bind_texture(glow::TEXTURE_2D, Some(handle));
#[cfg(debug_assertions)]
gl.object_label(glow::TEXTURE, handle, Some("Glyph cache"));
gl.tex_parameter_i32(
glow::TEXTURE_2D,
glow::TEXTURE_WRAP_S,
glow::CLAMP_TO_EDGE as i32,
);
gl.tex_parameter_i32(
glow::TEXTURE_2D,
glow::TEXTURE_WRAP_T,
glow::CLAMP_TO_EDGE as i32,
);
gl.tex_parameter_i32(
glow::TEXTURE_2D,
glow::TEXTURE_MIN_FILTER,
glow::LINEAR as i32,
);
gl.tex_parameter_i32(
glow::TEXTURE_2D,
glow::TEXTURE_MAG_FILTER,
glow::LINEAR as i32,
);
gl.tex_image_2d(
glow::TEXTURE_2D,
0,
glow::R8 as i32,
width as i32,
height as i32,
0,
glow::RED,
glow::UNSIGNED_BYTE,
None,
);
gl.bind_texture(glow::TEXTURE_2D, None);
handle handle
}; };
@ -17,7 +57,34 @@ impl Cache {
Cache { texture } Cache { texture }
} }
pub fn update(&self, gl: &glow::Context, offset: [u16; 2], size: [u16; 2], data: &[u8]) { pub unsafe fn update(
// TODO &self,
gl: &glow::Context,
offset: [u16; 2],
size: [u16; 2],
data: &[u8],
) {
let [offset_x, offset_y] = offset;
let [width, height] = size;
gl.bind_texture(glow::TEXTURE_2D, Some(self.texture));
gl.tex_sub_image_2d_u8_slice(
glow::TEXTURE_2D,
0,
i32::from(offset_x),
i32::from(offset_y),
i32::from(width),
i32::from(height),
glow::RED,
glow::UNSIGNED_BYTE,
Some(data),
);
gl.bind_texture(glow::TEXTURE_2D, None);
}
pub unsafe fn destroy(&self, gl: &glow::Context) {
gl.delete_texture(self.texture);
} }
} }

View File

@ -2,11 +2,11 @@
layout(location = 0) uniform mat4 transform; layout(location = 0) uniform mat4 transform;
in vec3 left_top; layout(location = 0) in vec3 left_top;
in vec2 right_bottom; layout(location = 1) in vec2 right_bottom;
in vec2 tex_left_top; layout(location = 2) in vec2 tex_left_top;
in vec2 tex_right_bottom; layout(location = 3) in vec2 tex_right_bottom;
in vec4 color; layout(location = 4) in vec4 color;
out vec2 f_tex_pos; out vec2 f_tex_pos;
out vec4 f_color; out vec4 f_color;