actually, auto-group textures into groups based on size. too tedious otherwise.

This commit is contained in:
Dustin Carlino 2019-11-24 07:21:30 -08:00
parent f89bdbab86
commit 888e405146
2 changed files with 43 additions and 29 deletions

View File

@ -4,8 +4,10 @@ use crate::{
};
use abstutil::{elapsed_seconds, Timer, TimerSink};
use geom::Angle;
use glium::texture::{RawImage2d, Texture2dArray};
use glium_glyph::glyph_brush::rusttype::Font;
use glium_glyph::GlyphBrush;
use std::collections::BTreeMap;
use std::collections::VecDeque;
use std::time::Instant;
@ -47,9 +49,7 @@ impl<'a> EventCtx<'a> {
pub fn set_textures(
&mut self,
skip_textures: Vec<(&str, Color)>,
// Each group must have the same dimensions, because they're getting grouped in a texture
// array.
texture_groups: Vec<Vec<(&str, TextureType)>>,
textures: Vec<(&str, TextureType)>,
timer: &mut Timer,
) {
self.canvas.texture_arrays.clear();
@ -61,25 +61,40 @@ impl<'a> EventCtx<'a> {
.insert(filename.to_string(), fallback);
}
// Group textures with the same dimensions and create a texture array. Videocards have a
// limit on the number of textures that can be uploaded.
let mut dims_to_textures: BTreeMap<(u32, u32), Vec<(String, Vec<u8>, TextureType)>> =
BTreeMap::new();
let num_textures = textures.len();
timer.start_iter("upload textures", num_textures);
for (filename, tex_type) in textures {
timer.next();
let img = image::open(filename).unwrap().to_rgba();
let dims = img.dimensions();
//let raw = RawImage2d::from_raw_rgba_reversed(&img.into_raw(), dims);
dims_to_textures.entry(dims).or_insert_with(Vec::new).push((
filename.to_string(),
img.into_raw(),
tex_type,
));
}
timer.note(format!(
"{} textures grouped into {} arrays (with the same dimensions)",
num_textures,
dims_to_textures.len()
));
// The limit depends on videocard and drivers -- I can't find a reasonable minimum
// documented online. But in practice, some Mac users hit a limit of 16. :)
if texture_groups.len() > 15 {
panic!("Due to lovely hacks, only 15 texture groups supported");
if dims_to_textures.len() > 15 {
panic!("Only 15 texture arrays supported by some videocards. Group more textures by using the same image dimensions.");
}
timer.start_iter("upload textures", texture_groups.len());
for (group_idx, group) in texture_groups.into_iter().enumerate() {
timer.next();
for (group_idx, (dims, list)) in dims_to_textures.into_iter().enumerate() {
let mut raw_data = Vec::new();
for (tex_idx, (filename, tex_type)) in group.into_iter().enumerate() {
let img = image::open(filename).unwrap().to_rgba();
let dims = img.dimensions();
raw_data.push(glium::texture::RawImage2d::from_raw_rgba_reversed(
&img.into_raw(),
dims,
));
for (tex_idx, (filename, raw, tex_type)) in list.into_iter().enumerate() {
let tex_id = (group_idx as f32, tex_idx as f32);
self.canvas.texture_lookups.insert(
filename.to_string(),
filename,
match tex_type {
TextureType::Stretch => Color::StretchTexture(tex_id, Angle::ZERO),
TextureType::Tile => {
@ -88,12 +103,11 @@ impl<'a> EventCtx<'a> {
TextureType::CustomUV => Color::CustomUVTexture(tex_id),
},
);
raw_data.push(RawImage2d::from_raw_rgba_reversed(&raw, dims));
}
// TODO When the "Varying dimensions were found" error happens, print a friendlier
// error that has the list of files in the group with mismatched sizes.
self.canvas.texture_arrays.push(
glium::texture::Texture2dArray::new(self.prerender.display, raw_data).unwrap(),
);
self.canvas
.texture_arrays
.push(Texture2dArray::new(self.prerender.display, raw_data).unwrap());
}
}
}

View File

@ -24,7 +24,7 @@ impl UI {
let cs = ColorScheme::load().unwrap();
let (primary, prebaked) = ctx.loading_screen("load map", |ctx, mut timer| {
// Always load some small icons.
let mut texture_groups = vec![vec![
let mut textures = vec![
("assets/ui/edit_bike.png", TextureType::Stretch),
("assets/ui/edit_bus.png", TextureType::Stretch),
("assets/ui/edit_construction.png", TextureType::Stretch),
@ -44,13 +44,13 @@ impl UI {
("assets/ui/slow_down.png", TextureType::Stretch),
("assets/ui/small_step.png", TextureType::Stretch),
("assets/ui/speed_up.png", TextureType::Stretch),
]];
];
let skip_textures = if flags.textures {
texture_groups.extend(vec![
vec![("assets/water_texture.png", TextureType::Tile)],
vec![("assets/grass_texture.png", TextureType::Tile)],
vec![("assets/pedestrian.png", TextureType::Stretch)],
vec![("assets/car.png", TextureType::CustomUV)],
textures.extend(vec![
("assets/water_texture.png", TextureType::Tile),
("assets/grass_texture.png", TextureType::Tile),
("assets/pedestrian.png", TextureType::Stretch),
("assets/car.png", TextureType::CustomUV),
]);
Vec::new()
} else {
@ -68,7 +68,7 @@ impl UI {
]
};
ctx.set_textures(skip_textures, texture_groups, &mut timer);
ctx.set_textures(skip_textures, textures, &mut timer);
let primary = PerMapUI::new(flags, &cs, ctx, &mut timer);
let prebaked: Analytics = abstutil::read_binary(