Make compatible with GLES 2.0 (GLSL 1.20)
This commit is contained in:
parent
2f47858662
commit
6472746bd2
|
@ -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]
|
||||||
|
|
|
@ -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 {
|
||||||
|
|
115
src/pipeline.rs
115
src/pipeline.rs
|
@ -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);
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue