Make compatible with GLES 2.0 (GLSL 1.20)

This commit is contained in:
Olivier 'reivilibre' 2021-06-26 19:15:19 +01:00
parent 2f47858662
commit 6472746bd2
5 changed files with 86 additions and 98 deletions

View File

@ -1,13 +1,14 @@
[package] [package]
name = "glow_glyph" name = "glow_glyph"
version = "0.4.0" version = "0.4.0"
authors = ["Héctor Ramón Jiménez <hector0193@gmail.com>"] # Héctor is the author of glow_glyph and is otherwise unaffiliated
authors = ["Olivier 'reivilibre' <olivier@librepush.net>", "Héctor Ramón Jiménez <hector0193@gmail.com>"]
edition = "2018" edition = "2018"
description = "A fast text renderer for glow, powered by glyph_brush" description = "A fork (supporting old GLES 2.0) of a fast text renderer for glow, powered by glyph_brush"
license = "MIT" license = "MIT"
keywords = ["font", "ttf", "truetype", "glow", "text"] keywords = ["font", "ttf", "truetype", "glow", "text"]
repository = "https://github.com/hecrj/glow_glyph" repository = "https://bics.ga/reivilibre/glow_glyph_compat"
documentation = "https://docs.rs/glow_glyph" documentation = "https://docs.rs/glow_glyph_compat"
readme = "README.md" readme = "README.md"
[dependencies] [dependencies]

View File

@ -9,7 +9,7 @@ mod region;
pub use region::Region; pub use region::Region;
use pipeline::{Instance, Pipeline}; use pipeline::{Vertex, Pipeline};
pub use builder::GlyphBrushBuilder; pub use builder::GlyphBrushBuilder;
pub use glyph_brush::ab_glyph; pub use glyph_brush::ab_glyph;
@ -26,6 +26,7 @@ use std::borrow::Cow;
use glyph_brush::{BrushAction, BrushError, DefaultSectionHasher}; use glyph_brush::{BrushAction, BrushError, DefaultSectionHasher};
use log::{log_enabled, warn}; use log::{log_enabled, warn};
use crate::pipeline::VertexGroup;
/// Object allowing glyph drawing, containing cache state. Manages glyph positioning cacheing, /// Object allowing glyph drawing, containing cache state. Manages glyph positioning cacheing,
/// glyph draw caching & efficient GPU texture cache updating and re-sizing on demand. /// glyph draw caching & efficient GPU texture cache updating and re-sizing on demand.
@ -33,7 +34,7 @@ use log::{log_enabled, warn};
/// Build using a [`GlyphBrushBuilder`](struct.GlyphBrushBuilder.html). /// Build using a [`GlyphBrushBuilder`](struct.GlyphBrushBuilder.html).
pub struct GlyphBrush<F = FontArc, H = DefaultSectionHasher> { pub struct GlyphBrush<F = FontArc, H = DefaultSectionHasher> {
pipeline: Pipeline, pipeline: Pipeline,
glyph_brush: glyph_brush::GlyphBrush<Instance, Extra, F, H>, glyph_brush: glyph_brush::GlyphBrush<VertexGroup, Extra, F, H>,
} }
impl<F: Font, H: BuildHasher> GlyphBrush<F, H> { impl<F: Font, H: BuildHasher> GlyphBrush<F, H> {
@ -209,7 +210,7 @@ impl<F: Font + Sync, H: BuildHasher> GlyphBrush<F, H> {
pipeline.update_cache(context, offset, size, tex_data); pipeline.update_cache(context, offset, size, tex_data);
}, },
Instance::from_vertex, Vertex::from_vertex,
); );
match brush_action { match brush_action {

View File

@ -39,7 +39,7 @@ impl Pipeline {
}; };
let (vertex_array, instances) = let (vertex_array, instances) =
unsafe { create_instance_buffer(gl, Instance::INITIAL_AMOUNT) }; unsafe { create_instance_buffer(gl, Vertex::INITIAL_AMOUNT) };
let transform = unsafe { let transform = unsafe {
gl.get_uniform_location(program, "transform") gl.get_uniform_location(program, "transform")
@ -72,7 +72,7 @@ impl Pipeline {
instances, instances,
transform, transform,
current_instances: 0, current_instances: 0,
supported_instances: Instance::INITIAL_AMOUNT, supported_instances: Vertex::INITIAL_AMOUNT,
current_transform: IDENTITY_MATRIX, current_transform: IDENTITY_MATRIX,
} }
} }
@ -115,12 +115,20 @@ impl Pipeline {
gl.bind_vertex_array(Some(self.vertex_array)); gl.bind_vertex_array(Some(self.vertex_array));
gl.draw_arrays_instanced( // gl.draw_arrays_instanced(
glow::TRIANGLE_STRIP, // glow::TRIANGLE_STRIP,
0, // 0,
4, // 4,
self.current_instances as i32, // self.current_instances as i32,
); // );
let num = self.current_instances as i32;
for i in 0..num {
gl.draw_arrays(glow::TRIANGLE_STRIP,
i * 4,
4);
}
gl.bind_vertex_array(None); gl.bind_vertex_array(None);
gl.bind_texture(glow::TEXTURE_2D, None); gl.bind_texture(glow::TEXTURE_2D, None);
@ -154,7 +162,7 @@ impl Pipeline {
} }
} }
pub fn upload(&mut self, gl: &glow::Context, instances: &[Instance]) { pub fn upload(&mut self, gl: &glow::Context, instances: &[VertexGroup]) {
if instances.is_empty() { if instances.is_empty() {
self.current_instances = 0; self.current_instances = 0;
return; return;
@ -199,18 +207,23 @@ const IDENTITY_MATRIX: [f32; 16] = [
#[derive(Debug, Clone, Copy)] #[derive(Debug, Clone, Copy)]
#[repr(C)] #[repr(C)]
pub struct Instance { pub struct Vertex {
left_top: [f32; 3], tex_pos: [f32; 2],
right_bottom: [f32; 2], pos: [f32; 3],
tex_left_top: [f32; 2],
tex_right_bottom: [f32; 2],
color: [f32; 4], color: [f32; 4],
} }
unsafe impl bytemuck::Zeroable for Instance {} #[derive(Debug, Clone, Copy)]
unsafe impl bytemuck::Pod for Instance {} #[repr(C)]
pub struct VertexGroup(Vertex, Vertex, Vertex, Vertex);
impl Instance { unsafe impl bytemuck::Zeroable for Vertex {}
unsafe impl bytemuck::Pod for Vertex {}
unsafe impl bytemuck::Zeroable for VertexGroup {}
unsafe impl bytemuck::Pod for VertexGroup {}
impl Vertex {
const INITIAL_AMOUNT: usize = 50_000; const INITIAL_AMOUNT: usize = 50_000;
pub fn from_vertex( pub fn from_vertex(
@ -220,7 +233,7 @@ impl Instance {
bounds, bounds,
extra, extra,
}: glyph_brush::GlyphVertex, }: glyph_brush::GlyphVertex,
) -> Instance { ) -> VertexGroup {
let gl_bounds = bounds; let gl_bounds = bounds;
let mut gl_rect = Rect { let mut gl_rect = Rect {
@ -257,13 +270,33 @@ impl Instance {
- tex_coords.height() * gl_rect.height() / old_height; - tex_coords.height() * gl_rect.height() / old_height;
} }
Instance { let left = gl_rect.min.x;
left_top: [gl_rect.min.x, gl_rect.max.y, extra.z], let right = gl_rect.max.x;
right_bottom: [gl_rect.max.x, gl_rect.min.y], let top = gl_rect.max.y;
tex_left_top: [tex_coords.min.x, tex_coords.max.y], let bottom = gl_rect.min.y;
tex_right_bottom: [tex_coords.max.x, tex_coords.min.y],
color: extra.color, let vert0 = Vertex {
} tex_pos: [tex_coords.min.x, tex_coords.max.y],
pos: [left, top, extra.z],
color: extra.color
};
let vert1 = Vertex {
tex_pos: [tex_coords.max.x, tex_coords.max.y],
pos: [right, top, extra.z],
color: extra.color
};
let vert2 = Vertex {
tex_pos: [tex_coords.min.x, tex_coords.min.y],
pos: [left, bottom, extra.z],
color: extra.color
};
let vert3 = Vertex {
tex_pos: [tex_coords.max.x, tex_coords.min.y],
pos: [right, bottom, extra.z],
color: extra.color
};
VertexGroup(vert0, vert1, vert2, vert3)
} }
} }
@ -284,7 +317,7 @@ unsafe fn create_program(
gl.compile_shader(shader); gl.compile_shader(shader);
if !gl.get_shader_compile_status(shader) { if !gl.get_shader_compile_status(shader) {
panic!(gl.get_shader_info_log(shader)); panic!("{}", gl.get_shader_info_log(shader));
} }
gl.attach_shader(program, shader); gl.attach_shader(program, shader);
@ -294,7 +327,7 @@ unsafe fn create_program(
gl.link_program(program); gl.link_program(program);
if !gl.get_program_link_status(program) { if !gl.get_program_link_status(program) {
panic!(gl.get_program_info_log(program)); panic!("{}", gl.get_program_info_log(program));
} }
for shader in shaders { for shader in shaders {
@ -319,45 +352,27 @@ unsafe fn create_instance_buffer(
gl.bind_buffer(glow::ARRAY_BUFFER, Some(buffer)); gl.bind_buffer(glow::ARRAY_BUFFER, Some(buffer));
gl.buffer_data_size( gl.buffer_data_size(
glow::ARRAY_BUFFER, glow::ARRAY_BUFFER,
(size * std::mem::size_of::<Instance>()) as i32, (size * std::mem::size_of::<Vertex>()) as i32,
glow::DYNAMIC_DRAW, glow::DYNAMIC_DRAW,
); );
let stride = std::mem::size_of::<Instance>() as i32; let stride = std::mem::size_of::<Vertex>() as i32;
gl.enable_vertex_attrib_array(0); gl.enable_vertex_attrib_array(0);
gl.vertex_attrib_pointer_f32(0, 3, glow::FLOAT, false, stride, 0); gl.vertex_attrib_pointer_f32(0, 2, glow::FLOAT, false, stride, 0);
gl.vertex_attrib_divisor(0, 1);
gl.enable_vertex_attrib_array(1); gl.enable_vertex_attrib_array(1);
gl.vertex_attrib_pointer_f32(1, 2, glow::FLOAT, false, stride, 4 * 3); gl.vertex_attrib_pointer_f32(1, 3, glow::FLOAT, false, stride, 4 * 2);
gl.vertex_attrib_divisor(1, 1);
gl.enable_vertex_attrib_array(2); 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( gl.vertex_attrib_pointer_f32(
3,
2, 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, 4,
glow::FLOAT, glow::FLOAT,
false, false,
stride, stride,
4 * (3 + 2 + 2 + 2), 4 * (2 + 3),
); );
gl.vertex_attrib_divisor(4, 1);
gl.bind_vertex_array(None); gl.bind_vertex_array(None);
gl.bind_buffer(glow::ARRAY_BUFFER, None); gl.bind_buffer(glow::ARRAY_BUFFER, None);

View File

@ -1,14 +1,14 @@
#version 330 #version 120
uniform sampler2D font_sampler; uniform sampler2D font_sampler;
in vec2 f_tex_pos; in vec2 f_tex_pos;
in vec4 f_color; in vec4 f_color;
out vec4 Target0; varying out vec4 Target0;
void main() { void main() {
float alpha = texture(font_sampler, f_tex_pos).r; float alpha = texture2D(font_sampler, f_tex_pos).r;
if (alpha <= 0.0) { if (alpha <= 0.0) {
discard; discard;

View File

@ -1,46 +1,17 @@
#version 330 #version 120
uniform mat4 transform; uniform mat4 transform;
layout(location = 0) in vec3 left_top; in vec2 tex_pos;
layout(location = 1) in vec2 right_bottom; in vec3 pos;
layout(location = 2) in vec2 tex_left_top; in vec4 color;
layout(location = 3) in vec2 tex_right_bottom;
layout(location = 4) in vec4 color;
out vec2 f_tex_pos; varying out vec2 f_tex_pos;
out vec4 f_color; varying out vec4 f_color;
// generate positional data based on vertex ID // pass through positional data based
void main() { 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_VertexID) {
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; f_color = color;
gl_Position = transform * vec4(pos, left_top.z, 1.0); f_tex_pos = tex_pos;
gl_Position = transform * vec4(pos, 1.0);
} }