fix corrupted text bug

This commit is contained in:
griffi-gh 2024-03-06 21:14:40 +01:00
parent cd6d421909
commit d4151e6c76
2 changed files with 38 additions and 0 deletions

View file

@ -97,6 +97,32 @@ impl UiDrawCall {
pub(crate) fn build(draw_commands: &UiDrawCommandList, atlas: &mut TextureAtlasManager, text_renderer: &mut TextRenderer) -> Self { pub(crate) fn build(draw_commands: &UiDrawCommandList, atlas: &mut TextureAtlasManager, text_renderer: &mut TextRenderer) -> Self {
let mut trans_stack = Vec::new(); let mut trans_stack = Vec::new();
let mut draw_call = UiDrawCall::default(); let mut draw_call = UiDrawCall::default();
//HACK: atlas may get resized while creating new glyphs,
//which invalidates all uvs, causing corrupted-looking texture
//so we need to pregenerate font textures before generating any vertices
//we are doing *a lot* of double work here, but it's the easiest way to avoid the issue
for comamnd in &draw_commands.commands {
if let UiDrawCommand::Text { text, font: font_handle, size, .. } = comamnd {
let mut layout = Layout::new(CoordinateSystem::PositiveYDown);
layout.append(
&[text_renderer.internal_font(*font_handle)],
&TextStyle::new(text, *size as f32, 0)
);
let glyphs = layout.glyphs();
for layout_glyph in glyphs {
if !layout_glyph.char_data.rasterize() { continue }
text_renderer.glyph(atlas, *font_handle, layout_glyph.parent, layout_glyph.key.px as u8);
}
}
}
//note to future self:
//RESIZING OR ADDING STUFF TO ATLAS AFTER THIS POINT IS A BIG NO-NO,
//DON'T DO IT EVER AGAIN UNLESS YOU WANT TO SPEND HOURS DEBUGGING
atlas.lock_atlas = true;
for command in &draw_commands.commands { for command in &draw_commands.commands {
match command { match command {
UiDrawCommand::PushTransform(trans) => { UiDrawCommand::PushTransform(trans) => {
@ -328,10 +354,14 @@ impl UiDrawCall {
} }
} }
} }
atlas.lock_atlas = false;
#[cfg(feature = "pixel_perfect")] #[cfg(feature = "pixel_perfect")]
draw_call.vertices.iter_mut().for_each(|v| { draw_call.vertices.iter_mut().for_each(|v| {
v.position = v.position.round() v.position = v.position.round()
}); });
draw_call draw_call
} }
} }

View file

@ -59,6 +59,10 @@ pub(crate) struct TextureAtlasManager {
/// True if the atlas has been modified in a way which requires a texture reupload /// True if the atlas has been modified in a way which requires a texture reupload
/// since the beginning of the current frame /// since the beginning of the current frame
modified: bool, modified: bool,
/// If true, attempting to modify the atlas in a way which invalidates UVs will cause a panic\
/// Used internally to ensure that the UVs do not become invalidated mid-render
pub(crate) lock_atlas: bool,
} }
impl TextureAtlasManager { impl TextureAtlasManager {
@ -73,11 +77,15 @@ impl TextureAtlasManager {
allocations: HashMap::default(), allocations: HashMap::default(),
remove_queue: Vec::new(), remove_queue: Vec::new(),
modified: true, modified: true,
lock_atlas: false,
} }
} }
/// Resize the texture atlas to the new size in-place, preserving the existing data /// Resize the texture atlas to the new size in-place, preserving the existing data
pub fn resize(&mut self, new_size: UVec2) { pub fn resize(&mut self, new_size: UVec2) {
if self.lock_atlas {
panic!("Attempted to resize the texture atlas while the atlas is locked");
}
log::trace!("resizing texture atlas to {:?}", new_size); log::trace!("resizing texture atlas to {:?}", new_size);
if self.size == new_size { if self.size == new_size {
log::warn!("Texture atlas is already the requested size"); log::warn!("Texture atlas is already the requested size");