Skip to content
Snippets Groups Projects
Commit 5f41b5ff authored by StarArawn's avatar StarArawn
Browse files

Working SDF? I guess..

parent af1fe271
No related branches found
No related tags found
No related merge requests found
Showing
with 2174 additions and 226 deletions
This diff is collapsed.
......@@ -17,5 +17,5 @@ kayak_components = { path = "kayak_components" }
kayak_core = { path = "kayak_core" }
[dev-dependencies]
bevy = { git = "https://github.com/StarArawn/bevy", rev = "b26f563b13c267ffe1ee801bd71fd40b98a256e7" }
bevy = { git = "https://github.com/StarArawn/bevy", rev = "146ddbe5f839d5d635fe350a535155231d4050c2" }
bevy_kayak_ui = { path = "bevy_kayak_ui" }
assets/fullsheet.png

88.9 KiB

This diff is collapsed.
This diff is collapsed.
assets/roboto.png

43.9 KiB

File added
......@@ -5,9 +5,12 @@ edition = "2021"
[dependencies]
bytemuck = "1.7.2"
bevy = { git = "https://github.com/StarArawn/bevy", rev = "b26f563b13c267ffe1ee801bd71fd40b98a256e7" }
bevy = { git = "https://github.com/StarArawn/bevy", rev = "146ddbe5f839d5d635fe350a535155231d4050c2" }
kayak_core = { path = "../kayak_core" }
kayak_components = { path = "../kayak_components" }
kayak_render_macros = { path = "../kayak_render_macros" }
kayak_font = { path = "../kayak_font" }
crevice = { git = "https://github.com/StarArawn/bevy", rev = "b26f563b13c267ffe1ee801bd71fd40b98a256e7" }
crevice = { git = "https://github.com/StarArawn/bevy", rev = "146ddbe5f839d5d635fe350a535155231d4050c2" }
serde = "1.0"
serde_json = "1.0"
serde_path_to_error = "0.1"
use bevy::ecs::reflect::ReflectComponent;
use bevy::prelude::Component;
use bevy::{
math::Mat4,
reflect::Reflect,
render2::camera::{CameraProjection, DepthCalculation, ScalingMode, WindowOrigin},
};
#[derive(Debug, Clone, Reflect)]
#[derive(Debug, Clone, Component, Reflect)]
#[reflect(Component)]
pub struct UIOrthographicProjection {
pub left: f32,
......
......@@ -57,28 +57,91 @@ pub fn extract_texts(
}
}
let font = fonts.get(font_handle.clone()).unwrap();
let char_layouts = font.font.get_layout(content, font_size);
let max_glyph_size = font
.sdf
.as_ref()
.and_then(|sdf| Some(sdf.max_glyph_size()))
.unwrap_or_default();
// let char_layouts = font.font.get_layout(
// content,
// font_size,
// font.sdf.as_ref().unwrap().atlas.size,
// (max_glyph_size.x, max_glyph_size.y),
// );
// let font_scale = font_size / font.font.units_per_em() as f32;
// for (c, (x, y), (width, height)) in char_layouts {
// // let size = font.font.get_size(c, font_size);
// let position_x = layout.posx + x;
// let position_y = layout.posy + y;
// extracted_texts.push(ExtractQuadBundle {
// extracted_quad: ExtractedQuad {
// font_handle: Some(font_handle.clone()),
// rect: Rect {
// min: Vec2::new(position_x, position_y),
// max: Vec2::new(position_x + width, position_y + height),
// },
// color: to_bevy_color(background_color),
// vertex_index: 0,
// char_id: font.font.get_char_id(c),
// z_index: layout.z_index,
// quad_type: UIQuadType::Text,
// type_index: 0,
// border_radius: (0.0, 0.0, 0.0, 0.0),
// },
// });
// }
for (c, (x, y), (width, height)) in char_layouts {
// let size = font.font.get_size(c, font_size);
let position_x = layout.posx + x;
let position_y = layout.posy + y;
extracted_texts.push(ExtractQuadBundle {
extracted_quad: ExtractedQuad {
font_handle: Some(font_handle.clone()),
rect: Rect {
min: Vec2::new(position_x, position_y),
max: Vec2::new(position_x + width, position_y + height),
let mut x = 0.0;
for c in content.chars() {
if let Some(glyph) = font
.sdf
.as_ref()
.unwrap()
.glyphs
.iter()
.find(|glyph| glyph.unicode == c)
{
let plane_bounds = glyph.plane_bounds.as_ref();
let (left, top, width, height) = match plane_bounds {
Some(val) => (
val.left,
val.top,
val.size().x * font_size,
val.size().y * font_size,
),
None => (0.0, 0.0, 0.0, 0.0),
};
let font_ratio = font_size / font.sdf.as_ref().unwrap().atlas.size;
let resized_max_glyph_size =
(max_glyph_size.x * font_ratio, max_glyph_size.y * font_ratio);
let shift_y = resized_max_glyph_size.1 - height;
let position_x = layout.posx + x + left * font_size;
let position_y = (layout.posy + (-top * font_size)) + font_size;
extracted_texts.push(ExtractQuadBundle {
extracted_quad: ExtractedQuad {
font_handle: Some(font_handle.clone()),
rect: Rect {
min: Vec2::new(position_x, position_y),
max: Vec2::new(
position_x + resized_max_glyph_size.0,
position_y + resized_max_glyph_size.1,
),
},
color: to_bevy_color(background_color),
vertex_index: 0,
char_id: font.font.get_char_id(c),
z_index: layout.z_index,
quad_type: UIQuadType::Text,
type_index: 0,
border_radius: (0.0, 0.0, 0.0, 0.0),
},
color: to_bevy_color(background_color),
vertex_index: 0,
char_id: font.font.get_char_id(c),
z_index: layout.z_index,
quad_type: UIQuadType::Text,
type_index: 0,
border_radius: (0.0, 0.0, 0.0, 0.0),
},
});
});
x += glyph.advance * font_size;
}
}
}
commands.spawn_batch(extracted_texts);
......
use bevy::reflect::TypeUuid;
use bevy::{prelude::Handle, reflect::TypeUuid, render2::texture::Image};
use kayak_font::Font;
use super::sdf::Sdf;
#[derive(Debug, Clone, TypeUuid)]
#[uuid = "4fe4732c-6731-49bb-bafc-4690d636b848"]
pub struct KayakFont {
pub sdf: Option<Sdf>,
pub atlas_image: Option<Handle<Image>>,
pub font: Font,
}
// impl KayakFont {
// pub fn from_atlas(atlas: Texture, )
// }
use bevy::{prelude::Handle, render2::{render_resource::{AddressMode, BindGroup, BindGroupDescriptor, BindGroupEntry, BindGroupLayout, BindingResource, Extent3d, FilterMode, ImageCopyTexture, ImageDataLayout, Origin3d, SamplerDescriptor, TextureAspect, TextureDescriptor, TextureDimension, TextureFormat, TextureUsages, TextureViewDescriptor, TextureViewDimension}, renderer::{RenderDevice, RenderQueue}, texture::{GpuImage, TextureFormatPixelInfo}}, utils::HashMap};
use bevy::{
math::Vec2,
prelude::{Assets, Handle, Res},
render2::{
render_asset::RenderAssets,
render_resource::{
AddressMode, BindGroup, BindGroupDescriptor, BindGroupEntry, BindGroupLayout,
BindingResource, CommandEncoderDescriptor, Extent3d, FilterMode, ImageCopyTexture,
ImageDataLayout, Origin3d, SamplerDescriptor, TextureAspect, TextureDescriptor,
TextureDimension, TextureFormat, TextureUsages, TextureViewDescriptor,
TextureViewDimension,
},
renderer::{RenderDevice, RenderQueue},
texture::{GpuImage, Image, TextureFormatPixelInfo},
},
utils::HashMap,
};
use crate::render::unified::pipeline::UnifiedPipeline;
use super::font::KayakFont;
use super::{font::KayakFont, sdf::Sdf};
pub const MAX_CHARACTERS: u32 = 100;
......@@ -43,36 +59,67 @@ impl FontTextureCache {
}
}
pub fn process_new(&mut self, device: &RenderDevice, pipeline: &UnifiedPipeline) {
let new_fonts = self.new_fonts.drain(..);
pub fn process_new(
&mut self,
device: &RenderDevice,
queue: &RenderQueue,
pipeline: &UnifiedPipeline,
render_images: &Res<RenderAssets<Image>>,
) {
let new_fonts: Vec<_> = self.new_fonts.drain(..).collect();
for kayak_font_handle in new_fonts {
let mut was_processed = true;
if let Some(font) = self.fonts.get(&kayak_font_handle) {
Self::create_texture(
&mut self.images,
kayak_font_handle.clone_weak(),
font,
device,
);
if let Some(sdf) = &font.sdf {
let atlas_handle = font.atlas_image.as_ref().unwrap();
if let Some(atlas_texture) = render_images.get(atlas_handle) {
Self::create_from_atlas(
&mut self.images,
&mut self.bind_groups,
sdf,
kayak_font_handle.clone_weak(),
device,
queue,
pipeline,
atlas_texture,
sdf.max_glyph_size(),
);
} else {
was_processed = false;
}
} else {
Self::create_texture(
&mut self.images,
kayak_font_handle.clone_weak(),
(font.font.cache.dimensions.0, font.font.cache.dimensions.1),
device,
TextureFormat::Rgba32Float,
);
let gpu_image = self.images.get(&kayak_font_handle).unwrap();
let gpu_image = self.images.get(&kayak_font_handle).unwrap();
// create bind group
let binding = device.create_bind_group(&BindGroupDescriptor {
label: Some("text_image_bind_group"),
entries: &[
BindGroupEntry {
binding: 0,
resource: BindingResource::TextureView(&gpu_image.texture_view),
},
BindGroupEntry {
binding: 1,
resource: BindingResource::Sampler(&gpu_image.sampler),
},
],
layout: &pipeline.image_layout,
});
// create bind group
let binding = device.create_bind_group(&BindGroupDescriptor {
label: Some("text_image_bind_group"),
entries: &[
BindGroupEntry {
binding: 0,
resource: BindingResource::TextureView(&gpu_image.texture_view),
},
BindGroupEntry {
binding: 1,
resource: BindingResource::Sampler(&gpu_image.sampler),
},
],
layout: &pipeline.image_layout,
});
self.bind_groups.insert(kayak_font_handle, binding);
self.bind_groups
.insert(kayak_font_handle.clone_weak(), binding);
}
}
if !was_processed {
self.new_fonts.push(kayak_font_handle.clone_weak());
}
}
}
......@@ -94,20 +141,21 @@ impl FontTextureCache {
fn create_texture(
images: &mut HashMap<Handle<KayakFont>, GpuImage>,
font_handle: Handle<KayakFont>,
font: &KayakFont,
size: (u32, u32),
device: &RenderDevice,
format: TextureFormat,
) {
let texture_descriptor = TextureDescriptor {
label: Some("font_texture_array"),
size: Extent3d {
width: font.font.cache.dimensions,
height: font.font.cache.dimensions,
width: size.0,
height: size.1,
depth_or_array_layers: MAX_CHARACTERS,
},
mip_level_count: 1,
sample_count: 1,
dimension: TextureDimension::D2,
format: TextureFormat::Rgba32Float,
format,
usage: TextureUsages::TEXTURE_BINDING | TextureUsages::COPY_DST,
};
......@@ -174,13 +222,13 @@ impl FontTextureCache {
ImageDataLayout {
offset: 0,
bytes_per_row: Some(
std::num::NonZeroU32::new(size * format_size as u32).unwrap(),
std::num::NonZeroU32::new(size.0 * format_size as u32).unwrap(),
),
rows_per_image: None,
},
Extent3d {
width: size,
height: size,
width: size.0,
height: size.1,
depth_or_array_layers: 1,
},
);
......@@ -245,4 +293,90 @@ impl FontTextureCache {
(image, binding)
}
pub fn create_from_atlas(
images: &mut HashMap<Handle<KayakFont>, GpuImage>,
bind_groups: &mut HashMap<Handle<KayakFont>, BindGroup>,
sdf: &Sdf,
font_handle: Handle<KayakFont>,
device: &RenderDevice,
queue: &RenderQueue,
pipeline: &UnifiedPipeline,
atlas_texture: &GpuImage,
size: Vec2,
) {
dbg!(size);
Self::create_texture(
images,
font_handle.clone_weak(),
(size.x as u32, size.y as u32),
device,
TextureFormat::Rgba8Unorm,
);
let mut command_encoder = device.create_command_encoder(&CommandEncoderDescriptor {
label: Some("create_sdf_from_atlas_encoder"),
});
let gpu_image = images.get(&font_handle).unwrap();
// create bind group
let binding = device.create_bind_group(&BindGroupDescriptor {
label: Some("text_image_bind_group"),
entries: &[
BindGroupEntry {
binding: 0,
resource: BindingResource::TextureView(&gpu_image.texture_view),
},
BindGroupEntry {
binding: 1,
resource: BindingResource::Sampler(&gpu_image.sampler),
},
],
layout: &pipeline.image_layout,
});
bind_groups.insert(font_handle.clone_weak(), binding);
// Now fill the texture data.
let atlas_width = sdf.atlas.width;
let atlas_height = sdf.atlas.height;
for (i, glyph) in sdf.glyphs.iter().enumerate() {
if let Some(atlas_bounds) = glyph.atlas_bounds {
let glyph_size = atlas_bounds.size();
command_encoder.copy_texture_to_texture(
ImageCopyTexture {
texture: &atlas_texture.texture,
mip_level: 0,
origin: Origin3d {
x: atlas_bounds.left as u32,
y: atlas_height - atlas_bounds.top as u32,
z: 0,
},
aspect: TextureAspect::All,
},
ImageCopyTexture {
texture: &gpu_image.texture,
mip_level: 0,
origin: Origin3d {
x: 0,
y: 0,
z: i as u32,
},
aspect: TextureAspect::All,
},
Extent3d {
width: glyph_size.x as u32,
height: glyph_size.y as u32,
depth_or_array_layers: 1,
},
);
}
}
let command_buffer = command_encoder.finish();
queue.submit(vec![command_buffer]);
}
}
use bevy::{
prelude::{AddAsset, AssetEvent, Assets, Commands, EventReader, Handle, Plugin, Res, ResMut},
prelude::{
AddAsset, AssetEvent, AssetServer, Assets, Commands, EventReader, Handle, Local, Plugin,
Res, ResMut,
},
render2::{
render_asset::RenderAssets,
render_resource::{FilterMode, TextureFormat, TextureUsages},
renderer::{RenderDevice, RenderQueue},
texture::Image,
RenderApp, RenderStage,
},
utils::HashSet,
};
use self::extract::extract_texts;
use self::{extract::extract_texts, sdf::Sdf};
use super::pipeline::UnifiedPipeline;
......@@ -15,6 +21,7 @@ mod extract;
mod font;
mod font_mapping;
mod font_texture_cache;
mod sdf;
pub use font::*;
pub use font_mapping::*;
......@@ -27,7 +34,8 @@ impl Plugin for TextRendererPlugin {
fn build(&self, app: &mut bevy::prelude::App) {
app.add_asset::<KayakFont>()
.init_resource::<FontMapping>()
.add_startup_system(load_fonts);
.add_startup_system(load_fonts)
.add_system(set_font_texture);
let render_app = app.sub_app(RenderApp);
render_app.add_system_to_stage(RenderStage::Extract, extract_texts);
......@@ -46,18 +54,70 @@ pub struct ExtractedFonts {
pub fonts: Vec<(Handle<KayakFont>, KayakFont)>,
}
fn load_fonts(mut font_assets: ResMut<Assets<KayakFont>>, mut font_mapping: ResMut<FontMapping>) {
fn load_fonts(
mut font_assets: ResMut<Assets<KayakFont>>,
mut font_mapping: ResMut<FontMapping>,
asset_server: Res<AssetServer>,
) {
let font_bytes = include_bytes!("../../../../../resources/Roboto-Regular.ttf");
let font = kayak_font::Font::new(font_bytes, 128);
let sdf = Sdf::from_string(include_str!("../../../../../assets/roboto.json").to_string());
let max_glyph_size = sdf.max_glyph_size();
let mut font = kayak_font::Font::new(
font_bytes,
(max_glyph_size.x as u32, max_glyph_size.y as u32),
);
let atlas_image: Handle<Image> = asset_server.load("roboto.png");
for glyph in sdf.glyphs.iter() {
if !font.cache.has_character(glyph.unicode) {
font.cache.add_character(glyph.unicode);
}
}
let handle = font_assets.add(KayakFont { font });
let handle = font_assets.add(KayakFont {
font,
atlas_image: Some(atlas_image),
sdf: Some(sdf),
});
font_mapping.add(handle);
}
pub fn set_font_texture(
mut texture_events: EventReader<AssetEvent<Image>>,
mut textures: ResMut<Assets<Image>>,
asset_server: Res<AssetServer>,
) {
// quick and dirty, run this for all textures anytime a texture is created.
for event in texture_events.iter() {
dbg!(&event);
match event {
AssetEvent::Created { handle } => {
let handle_path = asset_server.get_handle_path(handle).unwrap();
dbg!(&handle_path);
if handle_path.path().to_str().unwrap().contains("roboto") {
if let Some(mut texture) = textures.get_mut(handle) {
dbg!("Setting font texture!");
texture.texture_descriptor.format = TextureFormat::Rgba8Unorm;
texture.sampler_descriptor.min_filter = FilterMode::Linear;
texture.sampler_descriptor.mipmap_filter = FilterMode::Linear;
texture.sampler_descriptor.mag_filter = FilterMode::Linear;
texture.texture_descriptor.usage =
TextureUsages::COPY_DST | TextureUsages::COPY_SRC;
}
}
}
_ => (),
}
}
}
fn extract_fonts(
mut not_processed: Local<Vec<Handle<KayakFont>>>,
mut commands: Commands,
font_assets: Res<Assets<KayakFont>>,
mut events: EventReader<AssetEvent<KayakFont>>,
mut textures: ResMut<Assets<Image>>,
) {
let mut extracted_fonts = ExtractedFonts { fonts: Vec::new() };
let mut changed_assets = HashSet::default();
......@@ -65,10 +125,10 @@ fn extract_fonts(
for event in events.iter() {
match event {
AssetEvent::Created { handle } => {
changed_assets.insert(handle);
changed_assets.insert(handle.clone_weak());
}
AssetEvent::Modified { handle } => {
changed_assets.insert(handle);
changed_assets.insert(handle.clone_weak());
}
AssetEvent::Removed { handle } => {
if !changed_assets.remove(handle) {
......@@ -78,11 +138,30 @@ fn extract_fonts(
}
}
for handle in not_processed.drain(..) {
changed_assets.insert(handle);
}
for handle in changed_assets {
let font_asset = font_assets.get(handle).unwrap();
let font = font_asset.clone();
let font_asset = font_assets.get(&handle).unwrap();
if let Some(image) = font_asset.atlas_image.as_ref() {
if let Some(image) = textures.get(image) {
if !image
.texture_descriptor
.usage
.contains(TextureUsages::COPY_SRC)
{
not_processed.push(handle);
continue;
}
} else {
not_processed.push(handle);
continue;
}
}
extracted_fonts.fonts.push((handle.clone_weak(), font));
let font = font_asset.clone();
extracted_fonts.fonts.push((handle, font));
}
commands.insert_resource(extracted_fonts);
......@@ -92,7 +171,8 @@ fn prepare_fonts(
mut extracted_fonts: ResMut<ExtractedFonts>,
mut font_texture_cache: ResMut<FontTextureCache>,
) {
for (handle, font) in extracted_fonts.fonts.drain(..) {
let fonts: Vec<_> = extracted_fonts.fonts.drain(..).collect();
for (handle, font) in fonts {
font_texture_cache.add(handle, font);
}
}
......@@ -102,7 +182,8 @@ fn create_and_update_font_cache_texture(
queue: Res<RenderQueue>,
pipeline: Res<UnifiedPipeline>,
mut font_texture_cache: ResMut<FontTextureCache>,
images: Res<RenderAssets<Image>>,
) {
font_texture_cache.process_new(&device, &pipeline);
font_texture_cache.process_new(&device, &queue, &pipeline, &images);
font_texture_cache.process_updated(&queue);
}
use serde::Deserialize;
#[derive(Deserialize, Debug, Copy, Clone)]
pub enum SDFType {
#[serde(alias = "msdf")]
Msdf,
}
#[derive(Deserialize, Debug, Copy, Clone)]
pub enum Origin {
#[serde(alias = "bottom")]
Bottom,
#[serde(alias = "left")]
Left,
#[serde(alias = "right")]
Right,
#[serde(alias = "top")]
Top,
}
#[derive(Deserialize, Debug, Copy, Clone)]
pub struct Atlas {
#[serde(alias = "type")]
pub sdf_type: SDFType,
#[serde(alias = "distanceRange")]
pub distance_range: f32,
pub size: f32,
pub width: u32,
pub height: u32,
#[serde(alias = "yOrigin")]
pub y_origin: Origin,
}
use bevy::math::Vec2;
use serde::{Deserialize, Deserializer};
fn from_u32<'de, D>(deserializer: D) -> Result<char, D::Error>
where
D: Deserializer<'de>,
{
let number: u32 = Deserialize::deserialize(deserializer)?;
match char::from_u32(number) {
Some(c) => Ok(c),
None => Err(serde::de::Error::custom("Can't deserialize char from u32!")),
}
}
#[derive(Deserialize, Debug, Clone, Copy)]
pub struct Glyph {
#[serde(deserialize_with = "from_u32")]
pub unicode: char,
pub advance: f32,
#[serde(alias = "atlasBounds")]
pub atlas_bounds: Option<Rect>,
#[serde(alias = "planeBounds")]
pub plane_bounds: Option<Rect>,
}
#[derive(Deserialize, Default, Clone, Copy, Debug)]
pub struct Rect {
pub left: f32,
pub bottom: f32,
pub right: f32,
pub top: f32,
}
impl Rect {
pub fn width(&self) -> f32 {
self.right - self.left
}
pub fn height(&self) -> f32 {
self.top - self.bottom
}
pub fn size(&self) -> Vec2 {
Vec2::new(self.width(), self.height())
}
}
use serde::Deserialize;
#[derive(Deserialize, Debug, Copy, Clone)]
pub struct Metrics {
#[serde(alias = "emSize")]
em_size: f32,
#[serde(alias = "lineHeight")]
line_height: f32,
ascender: f32,
descender: f32,
#[serde(alias = "underlineY")]
underline_y: f32,
#[serde(alias = "underlineThickness")]
underline_thickness: f32,
}
use crate::render::unified::pipeline::UnifiedPipeline;
use self::{
atlas::Atlas,
glyph::{Glyph, Rect},
metrics::Metrics,
};
use bevy::{
math::Vec2,
prelude::Handle,
render2::{
renderer::{RenderDevice, RenderQueue},
texture::GpuImage,
},
};
use serde::Deserialize;
use super::{FontTextureCache, KayakFont};
mod atlas;
mod glyph;
mod metrics;
#[derive(Deserialize, Debug, Clone)]
pub struct Sdf {
pub atlas: Atlas,
metrics: Metrics,
pub glyphs: Vec<Glyph>,
kerning: Vec<KerningData>,
}
#[derive(serde::Deserialize, Debug, Clone, Copy)]
pub struct KerningData {
pub unicode1: u32,
pub unicode2: u32,
pub advance: f32,
}
impl Sdf {
pub fn from_string(data: String) -> Sdf {
let value: Sdf = match serde_path_to_error::deserialize(
&mut serde_json::Deserializer::from_str(&data),
) {
Ok(v) => v,
Err(err) => {
let path = err.path().to_string();
dbg!(err);
panic!("failed to deserialize json! path: {}", path);
}
};
value
}
pub fn max_glyph_size(&self) -> Vec2 {
let mut size = Vec2::new(0.0, 0.0);
self.glyphs.iter().for_each(|glyph| {
if let Some(atlas_bounds) = glyph.atlas_bounds {
let atlas_size = atlas_bounds.size();
if atlas_size.x > size.x {
size.x = atlas_size.x;
}
if atlas_size.y > size.y {
size.y = atlas_size.y;
}
}
});
size
}
}
#[test]
fn test_sdf_loader() {
let sdf = Sdf::from_string(include_str!("../../../../../../msdfgen/test.json").to_string());
dbg!(sdf.max_glyph_size());
}
......@@ -5,7 +5,7 @@ use bevy::{
SystemState,
},
math::{const_vec3, Mat4, Quat, Vec3, Vec4},
prelude::{Bundle, Entity, FromWorld, Handle, Query, Res, ResMut, World},
prelude::{Bundle, Component, Entity, FromWorld, Handle, Query, Res, ResMut, World},
render2::{
color::Color,
render_phase::{Draw, DrawFunctions, RenderPhase, TrackedRenderPass},
......@@ -213,6 +213,7 @@ pub enum UIQuadType {
Text,
}
#[derive(Component)]
pub struct ExtractedQuad {
pub rect: Rect,
pub color: Color,
......
......@@ -48,7 +48,7 @@ var sprite_texture: texture_2d_array<f32>;
[[group(1), binding(1)]]
var sprite_sampler: sampler;
let RADIUS: f32 = 0.5;
let RADIUS: f32 = 0.1;
fn sd_box_rounded(
......@@ -71,6 +71,9 @@ fn sd_box_rounded(
[[stage(fragment)]]
fn fragment(in: VertexOutput) -> [[location(0)]] vec4<f32> {
var pxRange = 2.5;
var tex_dimensions = textureDimensions(sprite_texture);
var msdfUnit = vec2<f32>(pxRange, pxRange) / vec2<f32>(f32(tex_dimensions.x), f32(tex_dimensions.y));
if (quad_type.t == 0) {
var dist = sd_box_rounded(
in.position.xy,
......@@ -86,12 +89,22 @@ fn fragment(in: VertexOutput) -> [[location(0)]] vec4<f32> {
return vec4<f32>(in.color.rgb, dist);
}
if (quad_type.t == 1) {
var x = textureSample(sprite_texture, sprite_sampler, in.uv.xy, i32(in.uv.z));
var x = textureSample(sprite_texture, sprite_sampler, vec2<f32>(in.uv.x, 1.0 - in.uv.y), i32(in.uv.z));
var v = max(min(x.r, x.g), min(max(x.r, x.g), x.b));
var c = v; //remap(v);
var v2 = c / fwidth( c );
var a = v2 + RADIUS; //clamp( v2 + RADIUS, 0.0, 1.0 );
// var v2 = c / fwidth( c );
// var a = clamp( v2 + RADIUS, 0.0, 1.0 );
// var a = smoothStep(
// max(RADIUS - 0.5, 0.0),
// RADIUS + 0.5,
// c);
// var w = fwidth(c);
// var a = smoothStep(0.5 - w, 0.5 + w, c);
var sigDist = (c - 0.5) * dot(msdfUnit, 0.5 / fwidth(in.uv.xy));
var a = clamp(sigDist + 0.5, 0.0, 1.0);
return vec4<f32>(in.color.rgb, a);
}
......
......@@ -47,7 +47,7 @@ pub fn Window(
};
let title_text_styles = Style {
height: StyleProp::Value(Units::Pixels(16.0)),
height: StyleProp::Value(Units::Pixels(22.0)),
..Style::default()
};
......@@ -56,7 +56,7 @@ pub fn Window(
<Fragment>
<Clip>
<Background styles={Some(title_background_styles)}>
<Text styles={Some(title_text_styles)} size={14.0} content={title}>{}</Text>
<Text styles={Some(title_text_styles)} size={16.0} content={title}>{}</Text>
</Background>
</Clip>
<Clip>
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment