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

View File

@ -9,6 +9,7 @@ use glyph_brush::rusttype::{point, Rect};
pub struct Pipeline {
sampler: <glow::Context as HasContext>::Sampler,
program: <glow::Context as HasContext>::Program,
vertex_array: <glow::Context as HasContext>::VertexArray,
instances: <glow::Context as HasContext>::Buffer,
cache: Cache,
current_instances: usize,
@ -25,7 +26,7 @@ impl Pipeline {
let 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 {
create_program(
@ -40,17 +41,18 @@ impl Pipeline {
)
};
let instances =
unsafe { gl.create_buffer().expect("Create instance buffer") };
let (vertex_array, instances) =
unsafe { create_instance_buffer(gl, Instance::INITIAL_AMOUNT) };
Pipeline {
sampler,
program,
cache,
vertex_array,
instances,
current_instances: 0,
supported_instances: Instance::INITIAL_AMOUNT,
current_transform: [0.0; 16],
current_transform: IDENTITY_MATRIX,
}
}
@ -60,6 +62,36 @@ impl Pipeline {
transform: [f32; 16],
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(
@ -69,7 +101,9 @@ impl Pipeline {
size: [u16; 2],
data: &[u8],
) {
self.cache.update(gl, offset, size, data);
unsafe {
self.cache.update(gl, offset, size, data);
}
}
pub fn increase_cache_size(
@ -78,7 +112,11 @@ impl Pipeline {
width: u32,
height: u32,
) {
self.cache = Cache::new(gl, width, height);
unsafe {
self.cache.destroy(gl);
self.cache = Cache::new(gl, width, height);
}
}
pub fn upload(&mut self, gl: &glow::Context, instances: &[Instance]) {
@ -88,12 +126,28 @@ impl Pipeline {
}
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();
}
// 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();
}
@ -219,3 +273,63 @@ unsafe fn create_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;
pub struct Cache {
texture: <glow::Context as HasContext>::Texture,
pub(crate) texture: <glow::Context as HasContext>::Texture,
}
impl Cache {
pub fn new(gl: &glow::Context, width: u32, height: u32) -> Cache {
let texture = unsafe {
let handle = gl.create_texture().expect("Create glyph cache texture");
pub unsafe fn new(gl: &glow::Context, width: u32, height: u32) -> Cache {
gl.pixel_store_i32(glow::UNPACK_ALIGNMENT, 1);
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
};
@ -17,7 +57,34 @@ impl Cache {
Cache { texture }
}
pub fn update(&self, gl: &glow::Context, offset: [u16; 2], size: [u16; 2], data: &[u8]) {
// TODO
pub unsafe fn update(
&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;
in vec3 left_top;
in vec2 right_bottom;
in vec2 tex_left_top;
in vec2 tex_right_bottom;
in vec4 color;
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;
out vec2 f_tex_pos;
out vec4 f_color;