use glume::gl;
use gl::types::*;
mod common;
use glenda::renderers::{
tilemap_renderer::{
TilemapRenderer, TilesetLayout
}, Renderer, Viewport
};
type Error = Box<dyn std::error::Error>;
fn main() -> Result<(), Error> {
common::run_example::<App>()
}
struct App {
renderer: TilemapRenderer,
texture: GLuint,
}
impl common::Application for App {
fn window_configuration() -> glume::window::WindowConfiguration {
glume::window::WindowConfiguration {
title: "Texture Renderer Example".to_string(),
size: (800, 600),
gl_version: (4, 5),
}
}
fn new() -> Result<Self, Error> {
let tileset_layout = TilesetLayout {
tile_count: [4, 4],
tile_size: [16, 16],
texture_size: [64, 64],
};
#[rustfmt::skip]
let tile_indices = &[
1, 12, 11, 10, 9,
2, 13, 14, 15, 8,
3, 4, 5, 6, 7,
];
let mut renderer = TilemapRenderer::new(
[5, 3],
tile_indices,
tileset_layout
)?;
renderer.set_map_tile_size([0.2, 0.2]);
renderer.set_map_offset([-1.0, 1.0]);
let texture = sample_texture()?;
unsafe {
gl::ActiveTexture(gl::TEXTURE0);
gl::BindTexture(gl::TEXTURE_2D, texture);
}
Ok(Self { renderer, texture })
}
}
impl Drop for App {
fn drop(&mut self) {
unsafe {
gl::DeleteTextures(1, &self.texture);
}
}
}
impl Renderer for App {
fn render(&self) {
self.renderer.render();
}
fn set_viewport(&mut self, viewport: Viewport) {
self.renderer.set_viewport(viewport);
}
}
fn sample_texture() -> Result<GLuint, Error> {
let size = [64, 64];
let mut pixels = vec![0u8; size[0] * size[1] * 4];
let mut set_pixel = |xy:[usize;2], color:[u8;4]| {
let index = (xy[1] * size[0] + xy[0]) * 4;
pixels[index] = color[0];
pixels[index + 1] = color[1];
pixels[index + 2] = color[2];
pixels[index + 3] = color[3];
};
let mut bkg_colors = [
[0, 128, 0, 255], [0, 255, 255, 255], [0, 255, 0, 255], [128, 128, 128, 255], [128, 0, 0, 255], [0, 0, 0, 255], [0, 0, 255, 255], [255, 0, 255, 255], [128, 128, 0, 255], [0, 128, 128, 255], [255, 0, 0, 255], [255, 165, 0, 255], [128, 0, 128, 255], [192, 192, 192, 255], [0, 0, 128, 255], [255, 255, 0, 255], ];
bkg_colors.iter_mut().for_each(|color| {
color[0] /= 3;
color[1] /= 3;
color[2] /= 3;
});
for ty in 0..4 {
for tx in 0..4 {
let px = tx * (size[0] / 4);
let py = ty * (size[1] / 4);
let index = ty * 4 + tx;
let bkg_color = bkg_colors[index % bkg_colors.len()];
for y in 0..(size[1] / 4) {
for x in 0..(size[0] / 4) {
set_pixel([px + x, py + y], bkg_color);
}
}
let grid_size = (index as f32).sqrt() as usize + 1;
let grid_color = [255, 255, 255, 255];
let mut n = 0;
for y in 0..grid_size {
for x in 0..grid_size {
if n >= index {
break;
}
let grid_x = px + 4 + 2 * x;
let grid_y = py + 4 + 2 * y;
set_pixel([grid_x, grid_y], grid_color);
n += 1;
}
}
}
}
let size = [size[0] as i32, size[1] as i32];
let texture = glh::create_texture_2d_rgba(size, &pixels)?;
unsafe {
gl::TexParameteri(gl::TEXTURE_2D, gl::TEXTURE_MIN_FILTER, gl::NEAREST as i32);
gl::TexParameteri(gl::TEXTURE_2D, gl::TEXTURE_MAG_FILTER, gl::NEAREST as i32);
}
Ok(texture)
}