...
 
Commits (2)
use renderer::*;
use native::{ Event, Window, take_event };
use ui::{ Font, FontRenderer };
use ui::{ UiRenderer, Position2D };
use render::Texture;
fn main() {
native::init();
let mut win = Window::new(None);
let mut font = Font::from_ttf(include_bytes!("Quicksand.ttf"));
let mut renderer = FontRenderer::new();
let mut ui = UiRenderer::new();
ui.load_font("Quicksand", include_bytes!("Quicksand.ttf"));
ui.load_font("WorkSans", include_bytes!("WorkSans.ttf"));
ui.load_font("IndieFlower", include_bytes!("IndieFlower.ttf"));
let texture = Texture::from(include_bytes!("scout.jpg"), None).unwrap();
'main: loop {
while let Some(event) = take_event() {
......@@ -26,11 +32,39 @@ fn main() {
win.enable();
win.clear();
renderer.render();
renderer.set_colour(&glm::vec3(1.0, 1.0, 1.0));
font.render("ah yes, very epic and cool beans".to_string(), 72, 120.0, 300.0);
renderer.set_colour(&glm::vec3(0.05, 0.68, 0.89));
font.render("this text is a nice shade of blue".to_string(), 48, 120.0, 420.0);
ui.begin();
ui.set_text_colour(&glm::vec3(1.0, 1.0, 1.0));
ui.draw_text("Quicksand", "ah yes, very epic and cool beans",
Position2D::new().set_pos(120.0, 300.0).set_height(72.0));
ui.draw_text("WorkSans", "sans font",
Position2D::new().set_pos(40.0, 10.0).set_height(280.0));
ui.draw_text("IndieFlower", "\"gamer\" - sans from sans undertale",
Position2D::new().set_pos(40.0, 540.0).set_height(80.0));
ui.set_text_colour(&glm::vec3(0.05, 0.68, 0.89));
ui.draw_text("WorkSans", "this text is a nice shade of blue",
Position2D::new().set_pos(120.0, 420.0).set_height(48.0));
ui.draw_rect(Position2D::new().set_pos(0.0, 0.0).set_size(100.0, 100.0),
&glm::vec4(1.0, 0.0, 0.0, 1.0));
ui.draw_rect(Position2D::new().set_pos(100.0, 0.0).set_size(100.0, 100.0),
&glm::vec4(0.0, 1.0, 0.0, 1.0));
ui.draw_rect(Position2D::new().set_pos(200.0, 0.0).set_size(100.0, 100.0),
&glm::vec4(0.0, 0.0, 1.0, 1.0));
ui.draw_rect(Position2D::new().set_pos(50.0, 50.0).set_size(300.0, 100.0),
&glm::vec4(0.0, 0.0, 0.0, 0.3));
ui.draw_image(Position2D::new().set_pos(1080.0, 0.0).set_size(200.0,200.0), &texture);
ui.end();
win.swap();
}
......
......@@ -172,6 +172,14 @@ impl Program {
}
}
pub fn upload_vec4(&mut self, name: &str, vec: &glm::Vec4) {
if let Ok(location) = self.get_uniform_location(&name) {
unsafe { gl::Uniform4fv(location, 1, vec.as_ptr()); }
} else {
println!("Could not find location, {}. [{}]", name, self.id);
}
}
pub fn upload_mat4(&mut self, name: &str, mat: &glm::Mat4) {
if let Ok(location) = self.get_uniform_location(&name) {
unsafe { gl::UniformMatrix4fv(location, 1, gl::FALSE, mat.as_ptr()); }
......
use crate::native::get_active_viewport;
#[derive(Clone, Copy)]
pub enum Alignment {
TOP_LEFT,
TOP_CENTRE,
TOP_RIGHT,
MID_LEFT,
MID_CENTRE,
MID_RIGHT,
BOT_LEFT,
BOT_CENTRE,
BOT_RIGHT,
}
pub struct Position2D {
pub alignment: Alignment,
pub x: f32,
pub y: f32,
pub w: f32,
pub h: f32,
}
impl Position2D {
pub fn new() -> Position2D {
Position2D {
alignment: Alignment::TOP_LEFT,
x: 0.0,
y: 0.0,
w: 0.0,
h: 0.0,
}
}
pub fn set_alignment(self, alignment: Alignment) -> Position2D {
Position2D {
alignment,
..self
}
}
pub fn set_pos(self, x: f32, y: f32) -> Position2D {
Position2D {
x,
y,
..self
}
}
pub fn set_size(self, w: f32, h: f32) -> Position2D {
Position2D {
w,
h,
..self
}
}
pub fn set_height(self, h: f32) -> Position2D {
Position2D {
h,
..self
}
}
pub fn generate(&self) -> glm::Mat4 {
let vp = get_active_viewport().unwrap();
let proj = glm::ortho(0.0, vp.w as f32, vp.h as f32, 0.0, -1.0, 1.0);
let mut model = glm::identity();
model = glm::translate(&model, &glm::vec3(self.x, self.y, 0.0));
model = glm::scale(&model, &glm::vec3(self.w, self.h, 0.0));
proj * model
}
}
......@@ -8,6 +8,8 @@ use crate::native::get_active_viewport;
use crate::shaders::get_active_program;
use hashbrown::{ HashMap, HashSet };
use super::Position2D;
#[derive(PartialEq, Eq, Hash)]
pub struct Key ( usize, char );
......@@ -63,7 +65,7 @@ impl<'a> Font<'a> {
}
}
pub fn render(&mut self, text: String, pixel_height: usize, X: f32, Y: f32) {
pub fn render(&mut self, text: &str, pixel_height: usize, position: Position2D) {
let mut set = HashSet::<char>::new();
for c in text.chars() {
set.insert(c);
......@@ -91,8 +93,6 @@ impl<'a> Font<'a> {
let v_metrics = self.font.v_metrics(scale);
let offset = point(0.0, v_metrics.ascent);
let vp = get_active_viewport().unwrap();
let proj = glm::ortho(0.0, vp.w as f32, 0.0, vp.h as f32, -1.0, 1.0);
let shader = get_active_program().expect("No active program.");
let glyphs: Vec<PositionedGlyph<'_>> = self.font.layout(&text, scale, offset).collect();
......@@ -100,14 +100,15 @@ impl<'a> Font<'a> {
if let Some(bb) = g.pixel_bounding_box() {
let c = text[i..].chars().next().unwrap();
if let Some(texture) = self.glyphs.get(&Key ( pixel_height, c )) {
let pos = g.position();
let mut model = glm::identity();
model = glm::translate(&model, &glm::vec3(pos.x.floor() + X, vp.h as f32 - pos.y.floor() as f32 - height / 2.0 - Y, 0.0));
model = glm::scale(&model, &glm::vec3((bb.max.x - bb.min.x) as f32, (bb.max.y - bb.min.y) as f32, 0.0));
let mp = proj * model;
shader.upload_mat4("projection", &mp);
shader.upload_mat4("projection",
&Position2D {
x: bb.min.x as f32 + position.x,
y: bb.min.y as f32 + position.y,
w: (bb.max.x - bb.min.x) as f32,
h: (bb.max.y - bb.min.y) as f32,
..position
}.generate()
);
texture.enable(0);
Mesh::draw_anonymous(6);
......
pub mod font;
pub mod render;
pub mod common;
pub use font::*;
pub use render::*;
pub use common::*;
use crate::shaders::{ Program, Shader };
use crate::mesh::{ Mesh, MeshData, Render };
use crate::render::Texture;
pub struct FontRenderer {
program: Program,
mesh: Mesh,
use super::{ Font, Position2D };
use hashbrown::HashMap;
pub struct UiRenderer<'a> {
default_program: Program,
text_program: Program,
texture_program: Program,
//colour_program: Program,
default_mesh: Mesh,
//texture_mesh: Mesh,
//colour_mesh: Mesh,
fonts: HashMap<&'a str, Font<'a>>,
}
impl FontRenderer {
pub fn new() -> FontRenderer {
let mut program = Program::from_shaders(
&[
Shader::from_vert_string(include_str!("text_vert.glsl")).unwrap(),
Shader::from_frag_string(include_str!("text_frag.glsl")).unwrap(),
]
).unwrap();
impl<'a> UiRenderer<'a> {
pub fn new() -> UiRenderer<'a> {
let default_program = Program::from_shaders(&[
Shader::from_vert_string(include_str!("shaders/default_vert.glsl")).unwrap(),
Shader::from_frag_string(include_str!("shaders/default_frag.glsl")).unwrap(),
])
.unwrap();
let text_program = Program::from_shaders(&[
Shader::from_vert_string(include_str!("shaders/text_vert.glsl")).unwrap(),
Shader::from_frag_string(include_str!("shaders/text_frag.glsl")).unwrap(),
])
.unwrap();
program.upload_i32("text", 0);
program.upload_vec3("textColour", &glm::vec3(1.0, 1.0, 1.0));
let texture_program = Program::from_shaders(&[
Shader::from_vert_string(include_str!("shaders/texture_vert.glsl")).unwrap(),
Shader::from_frag_string(include_str!("shaders/texture_frag.glsl")).unwrap(),
])
.unwrap();
let mesh = MeshData::new()
let default_mesh = MeshData::new()
.vertex(vec![
0.0, 0.0, 0.0,
1.0, 1.0, 0.0,
0.0, 1.0, 0.0,
0.0, 0.0, 0.0,
1.0, 0.0, 0.0,
1.0, 1.0, 0.0,
0.0, 0.0, 0.0,
1.0, 1.0, 0.0,
0.0, 1.0, 0.0,
0.0, 0.0, 0.0,
1.0, 0.0, 0.0,
1.0, 1.0, 0.0,
])
.render(
Render::UV(vec![
0.0, 1.0,
1.0, 0.0,
0.0, 0.0,
0.0, 1.0,
1.0, 1.0,
0.0, 1.0,
0.0, 0.0,
1.0, 0.0,
1.0, 1.0,
])
)
.create();
FontRenderer {
program,
mesh,
UiRenderer {
default_program,
text_program,
texture_program,
default_mesh,
fonts: HashMap::new(),
}
}
pub fn render(&self) {
pub fn add_font(&mut self, name: &'a str, font: Font<'a>) {
self.fonts.insert(name, font);
}
pub fn load_font(&mut self, name: &'a str, buf: &'a [u8]) {
self.add_font(name, Font::from_ttf(&buf));
}
pub fn set_text_colour(&mut self, colour: &glm::Vec3) {
self.text_program.enable();
self.text_program.upload_vec3("textColour", &colour);
}
pub fn begin(&self) {
unsafe {
gl::Enable(gl::BLEND);
gl::BlendFunc(gl::SRC_ALPHA, gl::ONE_MINUS_SRC_ALPHA);
gl::BlendFunc(gl::SRC_ALPHA, gl::ONE_MINUS_SRC_ALPHA);
}
}
pub fn end(&self) {
unsafe {
gl::Disable(gl::BLEND);
}
}
pub fn draw_text(&mut self, font: &'a str, text: &str, position: Position2D) {
let pixel_height = position.h.ceil() as usize;
let font = self.fonts.get_mut(&font).unwrap();
self.text_program.enable();
self.default_mesh.bind_only();
font.render(text, pixel_height, position);
}
pub fn draw_rect(&mut self, position: Position2D, colour: &glm::Vec4) {
self.default_program.enable();
self.default_program.upload_vec4("colour", &colour);
self.default_program.upload_mat4("projection", &position.generate());
self.default_mesh.draw();
}
self.program.enable();
self.mesh.bind_only();
pub fn draw_image(&mut self, position: Position2D, texture: &Texture) {
self.texture_program.enable();
texture.enable(0);
self.texture_program.upload_i32("tex", 0);
self.texture_program.upload_mat4("projection", &position.generate());
self.default_mesh.draw();
}
pub fn set_colour(&mut self, colour: &glm::Vec3) {
self.program.upload_vec3("textColour", &colour);
pub fn draw_attachment(&mut self, position: Position2D, attachment: i32) {
self.texture_program.enable();
self.texture_program.upload_i32("tex", attachment);
self.texture_program.upload_mat4("projection", &position.generate());
self.default_mesh.draw();
}
}
#version 330 core
out vec4 color;
uniform vec4 colour;
void main() {
color = colour;
}
#version 330 core
layout (location = 0) in vec3 vPos;
uniform mat4 projection;
void main() {
gl_Position = projection * vec4(vPos, 1.0);
}
#version 330 core
in vec2 TexCoords;
in vec2 fUV;
out vec4 color;
uniform sampler2D text;
uniform vec3 textColour;
void main() {
vec4 sampled = vec4(1.0, 1.0, 1.0, texture(text, TexCoords).r);
vec4 sampled = vec4(1.0, 1.0, 1.0, texture(text, fUV).r);
color = vec4(textColour, 1.0) * sampled;
}
#version 330 core
layout (location = 0) in vec3 vPos;
layout (location = 1) in vec2 vUV;
out vec2 fUV;
uniform mat4 projection;
void main() {
gl_Position = projection * vec4(vPos, 1.0);
fUV = vUV;
}
#version 330 core
in vec2 fUV;
out vec4 color;
uniform sampler2D tex;
void main() {
color = texture(tex, fUV);
}
#version 330 core
layout (location = 0) in vec3 vPos;
layout (location = 1) in vec2 vUV;
out vec2 fUV;
uniform mat4 projection;
void main() {
gl_Position = projection * vec4(vPos, 1.0);
fUV = vUV;
}
#version 330 core
layout (location = 0) in vec3 vertex;
layout (location = 1) in vec2 uv;
out vec2 TexCoords;
uniform mat4 projection;
void main() {
gl_Position = projection * vec4(vertex, 1.0);
TexCoords = uv;
}