Render: сплошной глиф и заливка прямоугольников для оверлеев
This commit is contained in:
parent
300a6c6d98
commit
70ee8d9ece
2 changed files with 63 additions and 3 deletions
|
|
@ -30,7 +30,7 @@ use font8x8::UnicodeFonts;
|
|||
/// Строит атлас глифов ASCII 32..127 (R8, альфа).
|
||||
pub fn build_atlas() -> Vec<u8> {
|
||||
let mut atlas = vec![0u8; (ATLAS_W * ATLAS_H) as usize];
|
||||
for code in 32u8..127 {
|
||||
for code in 32u8..=127 {
|
||||
let glyph = font8x8::BASIC_FONTS
|
||||
.get(char::from(code))
|
||||
.unwrap_or([0u8; 8]);
|
||||
|
|
@ -47,14 +47,39 @@ pub fn build_atlas() -> Vec<u8> {
|
|||
}
|
||||
}
|
||||
}
|
||||
// 127 — служебный «белый квадрат»: им заливаются прямоугольники (фон
|
||||
// меню/затемнение), у шрифта такого символа нет.
|
||||
let index = 127u32 - 32;
|
||||
let gx = (index % 16) * 8;
|
||||
let gy = (index / 16) * 8;
|
||||
for row in 0..8u32 {
|
||||
for col in 0..8u32 {
|
||||
atlas[((gy + row) * ATLAS_W + gx + col) as usize] = 255;
|
||||
}
|
||||
}
|
||||
atlas
|
||||
}
|
||||
|
||||
/// UV-прямоугольник глифа в атласе.
|
||||
pub fn glyph_uv(code: u8) -> ([f32; 2], [f32; 2]) {
|
||||
let index = code.clamp(32, 126) as u32 - 32;
|
||||
let index = code.clamp(32, 127) as u32 - 32;
|
||||
let gx = (index % 16) * 8;
|
||||
let gy = (index / 16) * 8;
|
||||
// Сплошной глиф растягивается на весь экран: берём UV с отступом в
|
||||
// полтексела, иначе линейная фильтрация подмешивает соседний глиф и на
|
||||
// границе заливки появляется полоса.
|
||||
if code == 127 {
|
||||
return (
|
||||
[
|
||||
(gx as f32 + 0.5) / ATLAS_W as f32,
|
||||
(gy as f32 + 0.5) / ATLAS_H as f32,
|
||||
],
|
||||
[
|
||||
(gx as f32 + 7.5) / ATLAS_W as f32,
|
||||
(gy as f32 + 7.5) / ATLAS_H as f32,
|
||||
],
|
||||
);
|
||||
}
|
||||
(
|
||||
[gx as f32 / ATLAS_W as f32, gy as f32 / ATLAS_H as f32],
|
||||
[
|
||||
|
|
@ -110,6 +135,22 @@ mod tests {
|
|||
assert!(lit > 100, "атлас пуст: {lit}");
|
||||
}
|
||||
|
||||
/// Служебный глиф 127 — сплошной белый квадрат для заливки фона.
|
||||
#[test]
|
||||
fn atlas_has_solid_glyph() {
|
||||
let atlas = build_atlas();
|
||||
let (uv0, uv1) = glyph_uv(127);
|
||||
let x0 = (uv0[0] * ATLAS_W as f32) as u32;
|
||||
let y0 = (uv0[1] * ATLAS_H as f32) as u32;
|
||||
let x1 = (uv1[0] * ATLAS_W as f32) as u32;
|
||||
let y1 = (uv1[1] * ATLAS_H as f32) as u32;
|
||||
for y in y0..y1 {
|
||||
for x in x0..x1 {
|
||||
assert_eq!(atlas[(y * ATLAS_W + x) as usize], 255, "пиксель {x},{y}");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn vertices_for_text() {
|
||||
let items = vec![TextItem {
|
||||
|
|
|
|||
|
|
@ -1278,7 +1278,7 @@ impl WorldRenderer {
|
|||
resource: screen_buffer.as_entire_binding(),
|
||||
}],
|
||||
});
|
||||
let capacity = 16384;
|
||||
let capacity = 65536;
|
||||
let vertex_buffer = device.create_buffer(&wgpu::BufferDescriptor {
|
||||
label: Some("text vertices"),
|
||||
size: (capacity * std::mem::size_of::<TextVertex>()) as u64,
|
||||
|
|
@ -1465,6 +1465,25 @@ impl WorldRenderer {
|
|||
self.text.items.clear();
|
||||
}
|
||||
|
||||
/// Заливает прямоугольник цветом (затемнение под меню).
|
||||
///
|
||||
/// Панелей у HUD пока нет, поэтому берём служебный сплошной глиф 127 из
|
||||
/// атласа и растягиваем его сеткой. Годится только для прямоугольников,
|
||||
/// залитых одним цветом, — ровно это нужно модальному оверлею.
|
||||
pub fn push_rect(&mut self, x: f32, y: f32, width: f32, height: f32, color: [f32; 4]) {
|
||||
if width <= 0.0 || height <= 0.0 {
|
||||
return;
|
||||
}
|
||||
let scale = (height / 8.0).max(1.0);
|
||||
let step = 8.0 * scale;
|
||||
let cols = (width / step).ceil().max(1.0) as usize;
|
||||
let rows = (height / step).ceil().max(1.0) as usize;
|
||||
let line: String = std::iter::repeat_n('\u{7f}', cols).collect();
|
||||
for row in 0..rows {
|
||||
self.push_text(x, y + row as f32 * step, scale, color, line.clone());
|
||||
}
|
||||
}
|
||||
|
||||
/// Загружает оверлей на GPU (размер экрана + вершины).
|
||||
fn upload_text(&self, queue: &wgpu::Queue, width: u32, height: u32) {
|
||||
let screen: [f32; 4] = [width as f32, height as f32, 0.0, 0.0];
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue