Introduce ColorMode
for Atlas
This commit is contained in:
parent
80e8465af6
commit
9f82af4f7d
3 changed files with 83 additions and 13 deletions
|
@ -3,7 +3,7 @@ mod text_atlas;
|
||||||
mod text_render;
|
mod text_render;
|
||||||
|
|
||||||
pub use error::{PrepareError, RenderError};
|
pub use error::{PrepareError, RenderError};
|
||||||
pub use text_atlas::TextAtlas;
|
pub use text_atlas::{ColorMode, TextAtlas};
|
||||||
use text_render::ContentType;
|
use text_render::ContentType;
|
||||||
pub use text_render::TextRenderer;
|
pub use text_render::TextRenderer;
|
||||||
|
|
||||||
|
|
|
@ -15,17 +15,17 @@ use wgpu::{
|
||||||
|
|
||||||
#[allow(dead_code)]
|
#[allow(dead_code)]
|
||||||
pub(crate) struct InnerAtlas {
|
pub(crate) struct InnerAtlas {
|
||||||
|
pub kind: Kind,
|
||||||
pub texture: Texture,
|
pub texture: Texture,
|
||||||
pub texture_view: TextureView,
|
pub texture_view: TextureView,
|
||||||
pub packer: BucketedAtlasAllocator,
|
pub packer: BucketedAtlasAllocator,
|
||||||
pub width: u32,
|
pub width: u32,
|
||||||
pub height: u32,
|
pub height: u32,
|
||||||
pub glyph_cache: LruCache<CacheKey, GlyphDetails>,
|
pub glyph_cache: LruCache<CacheKey, GlyphDetails>,
|
||||||
pub num_atlas_channels: usize,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl InnerAtlas {
|
impl InnerAtlas {
|
||||||
fn new(device: &Device, _queue: &Queue, num_atlas_channels: usize) -> Self {
|
fn new(device: &Device, _queue: &Queue, kind: Kind) -> Self {
|
||||||
let max_texture_dimension_2d = device.limits().max_texture_dimension_2d;
|
let max_texture_dimension_2d = device.limits().max_texture_dimension_2d;
|
||||||
let width = max_texture_dimension_2d;
|
let width = max_texture_dimension_2d;
|
||||||
let height = max_texture_dimension_2d;
|
let height = max_texture_dimension_2d;
|
||||||
|
@ -43,11 +43,7 @@ impl InnerAtlas {
|
||||||
mip_level_count: 1,
|
mip_level_count: 1,
|
||||||
sample_count: 1,
|
sample_count: 1,
|
||||||
dimension: TextureDimension::D2,
|
dimension: TextureDimension::D2,
|
||||||
format: match num_atlas_channels {
|
format: kind.texture_format(),
|
||||||
1 => TextureFormat::R8Unorm,
|
|
||||||
4 => TextureFormat::Rgba8UnormSrgb,
|
|
||||||
_ => panic!("unexpected number of channels"),
|
|
||||||
},
|
|
||||||
usage: TextureUsages::TEXTURE_BINDING | TextureUsages::COPY_DST,
|
usage: TextureUsages::TEXTURE_BINDING | TextureUsages::COPY_DST,
|
||||||
view_formats: &[],
|
view_formats: &[],
|
||||||
});
|
});
|
||||||
|
@ -57,13 +53,13 @@ impl InnerAtlas {
|
||||||
let glyph_cache = LruCache::unbounded();
|
let glyph_cache = LruCache::unbounded();
|
||||||
|
|
||||||
Self {
|
Self {
|
||||||
|
kind,
|
||||||
texture,
|
texture,
|
||||||
texture_view,
|
texture_view,
|
||||||
packer,
|
packer,
|
||||||
width,
|
width,
|
||||||
height,
|
height,
|
||||||
glyph_cache,
|
glyph_cache,
|
||||||
num_atlas_channels,
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -82,6 +78,61 @@ impl InnerAtlas {
|
||||||
.deallocate(value.atlas_id.expect("cache corrupt"));
|
.deallocate(value.atlas_id.expect("cache corrupt"));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn num_channels(&self) -> usize {
|
||||||
|
self.kind.num_channels()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
||||||
|
pub(crate) enum Kind {
|
||||||
|
Mask,
|
||||||
|
Color { srgb: bool },
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Kind {
|
||||||
|
fn num_channels(self) -> usize {
|
||||||
|
match self {
|
||||||
|
Kind::Mask => 1,
|
||||||
|
Kind::Color { .. } => 4,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn texture_format(self) -> wgpu::TextureFormat {
|
||||||
|
match self {
|
||||||
|
Kind::Mask => TextureFormat::R8Unorm,
|
||||||
|
Kind::Color { srgb } => {
|
||||||
|
if srgb {
|
||||||
|
TextureFormat::Rgba8UnormSrgb
|
||||||
|
} else {
|
||||||
|
TextureFormat::Rgba8Unorm
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// The color mode of an [`Atlas`].
|
||||||
|
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
||||||
|
pub enum ColorMode {
|
||||||
|
/// Accurate color management.
|
||||||
|
///
|
||||||
|
/// This mode will use a proper sRGB texture for colored glyphs. This will
|
||||||
|
/// produce physically accurate color blending when rendering.
|
||||||
|
Accurate,
|
||||||
|
|
||||||
|
/// Web color management.
|
||||||
|
///
|
||||||
|
/// This mode reproduces the color management strategy used in the Web and
|
||||||
|
/// implemented by browsers.
|
||||||
|
///
|
||||||
|
/// This entails storing glyphs colored using the sRGB color space in a
|
||||||
|
/// linear RGB texture. Blending will not be physically accurate, but will
|
||||||
|
/// produce the same results as most UI toolkits.
|
||||||
|
///
|
||||||
|
/// This mode should be used to render to a linear RGB texture containing
|
||||||
|
/// sRGB colors.
|
||||||
|
Web,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// An atlas containing a cache of rasterized glyphs that can be rendered.
|
/// An atlas containing a cache of rasterized glyphs that can be rendered.
|
||||||
|
@ -103,8 +154,18 @@ pub struct TextAtlas {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl TextAtlas {
|
impl TextAtlas {
|
||||||
/// Creates a new `TextAtlas`.
|
/// Creates a new [`TextAtlas`].
|
||||||
pub fn new(device: &Device, queue: &Queue, format: TextureFormat) -> Self {
|
pub fn new(device: &Device, queue: &Queue, format: TextureFormat) -> Self {
|
||||||
|
Self::with_color_mode(device, queue, format, ColorMode::Accurate)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Creates a new [`TextAtlas`] with the given [`ColorMode`].
|
||||||
|
pub fn with_color_mode(
|
||||||
|
device: &Device,
|
||||||
|
queue: &Queue,
|
||||||
|
format: TextureFormat,
|
||||||
|
color_mode: ColorMode,
|
||||||
|
) -> Self {
|
||||||
let sampler = device.create_sampler(&SamplerDescriptor {
|
let sampler = device.create_sampler(&SamplerDescriptor {
|
||||||
label: Some("glyphon sampler"),
|
label: Some("glyphon sampler"),
|
||||||
min_filter: FilterMode::Nearest,
|
min_filter: FilterMode::Nearest,
|
||||||
|
@ -215,8 +276,17 @@ impl TextAtlas {
|
||||||
mapped_at_creation: false,
|
mapped_at_creation: false,
|
||||||
});
|
});
|
||||||
|
|
||||||
let color_atlas = InnerAtlas::new(device, queue, 4);
|
let color_atlas = InnerAtlas::new(
|
||||||
let mask_atlas = InnerAtlas::new(device, queue, 1);
|
device,
|
||||||
|
queue,
|
||||||
|
Kind::Color {
|
||||||
|
srgb: match color_mode {
|
||||||
|
ColorMode::Accurate => true,
|
||||||
|
ColorMode::Web => false,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
);
|
||||||
|
let mask_atlas = InnerAtlas::new(device, queue, Kind::Mask);
|
||||||
|
|
||||||
let bind_group = Arc::new(device.create_bind_group(&BindGroupDescriptor {
|
let bind_group = Arc::new(device.create_bind_group(&BindGroupDescriptor {
|
||||||
layout: &bind_group_layout,
|
layout: &bind_group_layout,
|
||||||
|
|
|
@ -147,7 +147,7 @@ impl TextRenderer {
|
||||||
&image.data,
|
&image.data,
|
||||||
ImageDataLayout {
|
ImageDataLayout {
|
||||||
offset: 0,
|
offset: 0,
|
||||||
bytes_per_row: Some(width as u32 * inner.num_atlas_channels as u32),
|
bytes_per_row: Some(width as u32 * inner.num_channels() as u32),
|
||||||
rows_per_image: None,
|
rows_per_image: None,
|
||||||
},
|
},
|
||||||
Extent3d {
|
Extent3d {
|
||||||
|
|
Loading…
Reference in a new issue