Some gltf improvements #4
|
@ -93,21 +93,21 @@ async fn main() {
|
||||||
//let diffuse_texture = resman.request::<Texture>("assets/happy-tree.png").unwrap();
|
//let diffuse_texture = resman.request::<Texture>("assets/happy-tree.png").unwrap();
|
||||||
//let antique_camera_model = resman.request::<Model>("assets/AntiqueCamera.glb").unwrap();
|
//let antique_camera_model = resman.request::<Model>("assets/AntiqueCamera.glb").unwrap();
|
||||||
//let cube_model = resman.request::<Model>("assets/cube-texture-bin.glb").unwrap();
|
//let cube_model = resman.request::<Model>("assets/cube-texture-bin.glb").unwrap();
|
||||||
let cube_gltf = resman.request::<Gltf>("assets/texture-sep/texture-sep.gltf").unwrap();
|
/* let cube_gltf = resman.request::<Gltf>("assets/texture-sep/texture-sep.gltf").unwrap();
|
||||||
let crate_gltf = resman.request::<Gltf>("assets/crate/crate.gltf").unwrap();
|
let crate_gltf = resman.request::<Gltf>("assets/crate/crate.gltf").unwrap();
|
||||||
|
|
||||||
let separate_gltf = resman.request::<Gltf>("assets/pos-testing/separate-nodes-two-cubes.glb").unwrap();
|
let separate_gltf = resman.request::<Gltf>("assets/pos-testing/child-node-cubes.glb").unwrap(); */
|
||||||
drop(resman);
|
//drop(resman);
|
||||||
|
|
||||||
let cube_mesh = &cube_gltf.data_ref()
|
/* let cube_mesh = &cube_gltf.data_ref()
|
||||||
.unwrap().meshes[0];
|
.unwrap().meshes[0];
|
||||||
let crate_mesh = &crate_gltf.data_ref()
|
let crate_mesh = &crate_gltf.data_ref()
|
||||||
.unwrap().meshes[0];
|
.unwrap().meshes[0];
|
||||||
|
|
||||||
let separate_scene = &separate_gltf.data_ref()
|
let separate_scene = &separate_gltf.data_ref()
|
||||||
.unwrap().scenes[0];
|
.unwrap().scenes[0]; */
|
||||||
|
|
||||||
/* let sponza_model = resman.request::<Gltf>("assets/sponza/Sponza.gltf").unwrap();
|
let sponza_model = resman.request::<Gltf>("assets/sponza/Sponza.gltf").unwrap();
|
||||||
drop(resman);
|
drop(resman);
|
||||||
|
|
||||||
let sponza_scene = &sponza_model.data_ref()
|
let sponza_scene = &sponza_model.data_ref()
|
||||||
|
@ -116,12 +116,12 @@ async fn main() {
|
||||||
world.spawn((
|
world.spawn((
|
||||||
sponza_scene.clone(),
|
sponza_scene.clone(),
|
||||||
Transform::from_xyz(0.0, 0.0, 0.0),
|
Transform::from_xyz(0.0, 0.0, 0.0),
|
||||||
)); */
|
));
|
||||||
|
|
||||||
world.spawn((
|
/* world.spawn((
|
||||||
separate_scene.clone(),
|
separate_scene.clone(),
|
||||||
Transform::from_xyz(0.0, -5.0, -10.0),
|
Transform::from_xyz(0.0, -5.0, -10.0),
|
||||||
));
|
)); */
|
||||||
|
|
||||||
/* {
|
/* {
|
||||||
let cube_tran = Transform::from_xyz(-5.9026427, -1.8953488, -10.0);
|
let cube_tran = Transform::from_xyz(-5.9026427, -1.8953488, -10.0);
|
||||||
|
@ -146,7 +146,7 @@ async fn main() {
|
||||||
specular: 1.3,
|
specular: 1.3,
|
||||||
},
|
},
|
||||||
light_tran,
|
light_tran,
|
||||||
cube_mesh.clone(),
|
//cube_mesh.clone(),
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,7 @@
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
|
|
||||||
|
use lyra_resource::{ResHandle, Texture};
|
||||||
|
|
||||||
use super::texture::RenderTexture;
|
use super::texture::RenderTexture;
|
||||||
|
|
||||||
pub struct MaterialSpecular {
|
pub struct MaterialSpecular {
|
||||||
|
@ -9,13 +11,18 @@ pub struct MaterialSpecular {
|
||||||
pub color_texture: Option<RenderTexture>,
|
pub color_texture: Option<RenderTexture>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn texture_to_render(device: &wgpu::Device, queue: &wgpu::Queue, bg_layout: &Arc<wgpu::BindGroupLayout>, i: &Option<ResHandle<Texture>>) -> Option<RenderTexture> {
|
||||||
|
if let Some(tex) = i {
|
||||||
|
RenderTexture::from_resource(device, queue, bg_layout.clone(), tex, None).ok()
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl MaterialSpecular {
|
impl MaterialSpecular {
|
||||||
pub fn from_resource(device: &wgpu::Device, queue: &wgpu::Queue, bg_layout: Arc<wgpu::BindGroupLayout>, value: &lyra_resource::gltf::Specular) -> Self {
|
pub fn from_resource(device: &wgpu::Device, queue: &wgpu::Queue, bg_layout: Arc<wgpu::BindGroupLayout>, value: &lyra_resource::gltf::Specular) -> Self {
|
||||||
let tex = value.texture.as_ref().and_then(|t| t.data_ref())
|
let tex = texture_to_render(device, queue, &bg_layout, &value.texture);
|
||||||
.map(|i| RenderTexture::from_image(device, queue, bg_layout.clone(), &i.image, None).unwrap());
|
let color_tex = texture_to_render(device, queue, &bg_layout, &value.color_texture);
|
||||||
|
|
||||||
let color_tex = value.color_texture.as_ref().and_then(|t| t.data_ref())
|
|
||||||
.map(|i| RenderTexture::from_image(device, queue, bg_layout, &i.image, None).unwrap());
|
|
||||||
|
|
||||||
Self {
|
Self {
|
||||||
factor: value.factor,
|
factor: value.factor,
|
||||||
|
@ -39,8 +46,7 @@ pub struct Material {
|
||||||
|
|
||||||
impl Material {
|
impl Material {
|
||||||
pub fn from_resource(device: &wgpu::Device, queue: &wgpu::Queue, bg_layout: Arc<wgpu::BindGroupLayout>, value: &lyra_resource::gltf::Material) -> Self {
|
pub fn from_resource(device: &wgpu::Device, queue: &wgpu::Queue, bg_layout: Arc<wgpu::BindGroupLayout>, value: &lyra_resource::gltf::Material) -> Self {
|
||||||
let diffuse_texture = value.base_color_texture.as_ref().and_then(|t| t.data_ref())
|
let diffuse_texture = texture_to_render(device, queue, &bg_layout, &value.base_color_texture);
|
||||||
.map(|i| RenderTexture::from_image(device, queue, bg_layout.clone(), &i.image, None).unwrap());
|
|
||||||
|
|
||||||
let specular = value.specular.as_ref().map(|s| MaterialSpecular::from_resource(device, queue, bg_layout.clone(), s));
|
let specular = value.specular.as_ref().map(|s| MaterialSpecular::from_resource(device, queue, bg_layout.clone(), s));
|
||||||
|
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
|
|
||||||
use image::GenericImageView;
|
use image::GenericImageView;
|
||||||
use lyra_resource::{ResHandle, Texture};
|
use lyra_resource::{FilterMode, ResHandle, Texture, WrappingMode};
|
||||||
|
|
||||||
use super::render_buffer::BindGroupPair;
|
use super::render_buffer::BindGroupPair;
|
||||||
|
|
||||||
|
@ -134,12 +134,101 @@ impl RenderTexture {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn from_resource(device: &wgpu::Device, queue: &wgpu::Queue, bg_layout: Arc<wgpu::BindGroupLayout>, texture_res: &ResHandle<Texture>, label: Option<&str>) -> anyhow::Result<Self> {
|
||||||
|
let texture_ref = texture_res.data_ref().unwrap();
|
||||||
|
let img = texture_ref.image.data_ref().unwrap();
|
||||||
|
|
||||||
|
let rgba = img.to_rgba8();
|
||||||
|
let dimensions = img.dimensions();
|
||||||
|
|
||||||
|
let size = wgpu::Extent3d {
|
||||||
|
width: dimensions.0,
|
||||||
|
height: dimensions.1,
|
||||||
|
depth_or_array_layers: 1,
|
||||||
|
};
|
||||||
|
let texture = device.create_texture(
|
||||||
|
&wgpu::TextureDescriptor {
|
||||||
|
label,
|
||||||
|
size,
|
||||||
|
mip_level_count: 1,
|
||||||
|
sample_count: 1,
|
||||||
|
dimension: wgpu::TextureDimension::D2,
|
||||||
|
format: wgpu::TextureFormat::Rgba8UnormSrgb,
|
||||||
|
usage: wgpu::TextureUsages::TEXTURE_BINDING | wgpu::TextureUsages::COPY_DST,
|
||||||
|
view_formats: &[],
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
queue.write_texture(
|
||||||
|
wgpu::ImageCopyTexture {
|
||||||
|
aspect: wgpu::TextureAspect::All,
|
||||||
|
texture: &texture,
|
||||||
|
mip_level: 0,
|
||||||
|
origin: wgpu::Origin3d::ZERO,
|
||||||
|
},
|
||||||
|
&rgba,
|
||||||
|
wgpu::ImageDataLayout {
|
||||||
|
offset: 0,
|
||||||
|
bytes_per_row: std::num::NonZeroU32::new(4 * dimensions.0),
|
||||||
|
rows_per_image: std::num::NonZeroU32::new(dimensions.1),
|
||||||
|
},
|
||||||
|
size,
|
||||||
|
);
|
||||||
|
|
||||||
|
// convert resource sampler into wgpu sampler
|
||||||
|
let sampler_desc = match &texture_ref.sampler {
|
||||||
|
Some(sampler) => {
|
||||||
|
let magf = res_filter_to_wgpu(sampler.mag_filter.unwrap_or(FilterMode::Linear));
|
||||||
|
let minf = res_filter_to_wgpu(sampler.min_filter.unwrap_or(FilterMode::Nearest));
|
||||||
|
let mipf = res_filter_to_wgpu(sampler.mipmap_filter.unwrap_or(FilterMode::Nearest));
|
||||||
|
|
||||||
|
let wrap_u = res_wrap_to_wgpu(sampler.wrap_u);
|
||||||
|
let wrap_v = res_wrap_to_wgpu(sampler.wrap_v);
|
||||||
|
let wrap_w = res_wrap_to_wgpu(sampler.wrap_w);
|
||||||
|
|
||||||
|
wgpu::SamplerDescriptor {
|
||||||
|
address_mode_u: wrap_u,
|
||||||
|
address_mode_v: wrap_v,
|
||||||
|
address_mode_w: wrap_w,
|
||||||
|
mag_filter: magf,
|
||||||
|
min_filter: minf,
|
||||||
|
mipmap_filter: mipf,
|
||||||
|
..Default::default()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
None => wgpu::SamplerDescriptor {
|
||||||
|
address_mode_u: wgpu::AddressMode::ClampToEdge,
|
||||||
|
address_mode_v: wgpu::AddressMode::ClampToEdge,
|
||||||
|
address_mode_w: wgpu::AddressMode::ClampToEdge,
|
||||||
|
mag_filter: wgpu::FilterMode::Linear,
|
||||||
|
min_filter: wgpu::FilterMode::Nearest,
|
||||||
|
mipmap_filter: wgpu::FilterMode::Nearest,
|
||||||
|
..Default::default()
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
let view = texture.create_view(&wgpu::TextureViewDescriptor::default());
|
||||||
|
let sampler = device.create_sampler(
|
||||||
|
&sampler_desc
|
||||||
|
);
|
||||||
|
|
||||||
|
let bgp = Self::create_bind_group_pair(device, bg_layout, &view, &sampler);
|
||||||
|
|
||||||
|
Ok(Self {
|
||||||
|
inner_texture: texture,
|
||||||
|
view,
|
||||||
|
sampler,
|
||||||
|
bindgroup_pair: Some(bgp),
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
/// Updates the texture on the gpu with the provided texture.
|
/// Updates the texture on the gpu with the provided texture.
|
||||||
///
|
///
|
||||||
/// # Panics
|
/// # Panics
|
||||||
/// Panics if `texture` is not loaded
|
/// Panics if `texture` is not loaded
|
||||||
pub fn update_texture(&mut self, _device: &wgpu::Device, queue: &wgpu::Queue, texture: &ResHandle<Texture>) {
|
pub fn update_texture(&mut self, _device: &wgpu::Device, queue: &wgpu::Queue, texture: &ResHandle<Texture>) {
|
||||||
let texture = &texture.data_ref().unwrap().image;
|
let texture = &texture.data_ref().unwrap().image;
|
||||||
|
let texture = &texture.data_ref().unwrap();
|
||||||
let rgba = texture.to_rgba8();
|
let rgba = texture.to_rgba8();
|
||||||
let dimensions = texture.dimensions();
|
let dimensions = texture.dimensions();
|
||||||
let size = wgpu::Extent3d {
|
let size = wgpu::Extent3d {
|
||||||
|
@ -216,3 +305,20 @@ impl RenderTexture {
|
||||||
&self.bindgroup_pair.as_ref().unwrap().bindgroup
|
&self.bindgroup_pair.as_ref().unwrap().bindgroup
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Convert [`lyra_resource::WrappingMode`] to [`wgpu::AddressMode`]
|
||||||
|
fn res_wrap_to_wgpu(wmode: WrappingMode) -> wgpu::AddressMode {
|
||||||
|
match wmode {
|
||||||
|
WrappingMode::ClampToEdge => wgpu::AddressMode::ClampToEdge,
|
||||||
|
WrappingMode::MirroredRepeat => wgpu::AddressMode::MirrorRepeat,
|
||||||
|
WrappingMode::Repeat => wgpu::AddressMode::Repeat,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Convert [`lyra_resource::FilterMode`] to [`wgpu::FilterMode`]
|
||||||
|
fn res_filter_to_wgpu(fmode: FilterMode) -> wgpu::FilterMode {
|
||||||
|
match fmode {
|
||||||
|
FilterMode::Nearest => wgpu::FilterMode::Nearest,
|
||||||
|
FilterMode::Linear => wgpu::FilterMode::Linear,
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,6 +1,8 @@
|
||||||
use std::{collections::hash_map::DefaultHasher, hash::{Hash, Hasher}};
|
use std::{collections::hash_map::DefaultHasher, hash::{Hash, Hasher}};
|
||||||
|
|
||||||
use crate::{Texture, ResHandle, util};
|
use gltf::texture::{MagFilter, MinFilter};
|
||||||
|
|
||||||
|
use crate::{util, FilterMode, Image, ResHandle, Texture, TextureSampler, WrappingMode};
|
||||||
use super::loader::GltfLoadContext;
|
use super::loader::GltfLoadContext;
|
||||||
|
|
||||||
/// PBR metallic roughness
|
/// PBR metallic roughness
|
||||||
|
@ -248,15 +250,33 @@ impl Material {
|
||||||
fn load_texture(context: &mut GltfLoadContext, texture_info: gltf::texture::Info<'_>) -> ResHandle<Texture> {
|
fn load_texture(context: &mut GltfLoadContext, texture_info: gltf::texture::Info<'_>) -> ResHandle<Texture> {
|
||||||
// TODO: texture_info.tex_coord()
|
// TODO: texture_info.tex_coord()
|
||||||
let tex = texture_info.texture();
|
let tex = texture_info.texture();
|
||||||
|
// TODO: tex.sampler()
|
||||||
let img = tex.source();
|
let img = tex.source();
|
||||||
let src = img.source();
|
let src = img.source();
|
||||||
|
|
||||||
let buf = Material::read_source(context, src).unwrap();
|
let buf = Material::read_source(context, src).unwrap();
|
||||||
let buflen = buf.len();
|
let buflen = buf.len();
|
||||||
let mime_type = infer::get(&buf).expect("Failed to get file type").mime_type();
|
let mime_type = infer::get(&buf).expect("Failed to get image type").mime_type();
|
||||||
|
|
||||||
context.resource_manager.load_bytes::<Texture>(&uuid::Uuid::new_v4().to_string(), mime_type,
|
let tex_img = context.resource_manager.load_bytes::<Image>(&uuid::Uuid::new_v4().to_string(), mime_type,
|
||||||
buf, 0, buflen).unwrap()
|
buf, 0, buflen).unwrap();
|
||||||
|
|
||||||
|
let samp = tex.sampler();
|
||||||
|
let samp = TextureSampler {
|
||||||
|
mag_filter: samp.mag_filter().map(FilterMode::from_mag_filter),
|
||||||
|
min_filter: samp.min_filter().map(FilterMode::from_min_filter),
|
||||||
|
mipmap_filter: samp.min_filter().and_then(FilterMode::mipmap_filter),
|
||||||
|
wrap_u: samp.wrap_s().into(),
|
||||||
|
wrap_v: samp.wrap_t().into(),
|
||||||
|
wrap_w: WrappingMode::ClampToEdge,
|
||||||
|
};
|
||||||
|
|
||||||
|
let handler = ResHandle::with_data("", Texture {
|
||||||
|
image: tex_img,
|
||||||
|
sampler: Some(samp),
|
||||||
|
});
|
||||||
|
context.resource_manager.store_uuid(handler.clone());
|
||||||
|
handler
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Load the Material from a gltf::Material.
|
/// Load the Material from a gltf::Material.
|
||||||
|
@ -297,3 +317,54 @@ impl Material {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl From<gltf::texture::MagFilter> for FilterMode {
|
||||||
|
fn from(value: gltf::texture::MagFilter) -> Self {
|
||||||
|
match value {
|
||||||
|
gltf::texture::MagFilter::Nearest => Self::Nearest,
|
||||||
|
gltf::texture::MagFilter::Linear => Self::Linear,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl FilterMode {
|
||||||
|
/// Get the MinFilter mode and the mipmap filter mode from gltf MinFilter
|
||||||
|
pub fn from_min_filter(minf: MinFilter) -> FilterMode {
|
||||||
|
match minf {
|
||||||
|
MinFilter::Nearest => FilterMode::Nearest,
|
||||||
|
MinFilter::Linear => FilterMode::Linear,
|
||||||
|
MinFilter::NearestMipmapNearest => FilterMode::Nearest,
|
||||||
|
MinFilter::LinearMipmapNearest => FilterMode::Linear,
|
||||||
|
MinFilter::NearestMipmapLinear => FilterMode::Nearest,
|
||||||
|
MinFilter::LinearMipmapLinear => FilterMode::Linear,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn from_mag_filter(magf: MagFilter) -> FilterMode {
|
||||||
|
match magf {
|
||||||
|
MagFilter::Nearest => FilterMode::Nearest,
|
||||||
|
MagFilter::Linear => FilterMode::Linear,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn mipmap_filter(minf: MinFilter) -> Option<FilterMode> {
|
||||||
|
match minf {
|
||||||
|
MinFilter::Nearest => None,
|
||||||
|
MinFilter::Linear => None,
|
||||||
|
MinFilter::NearestMipmapNearest => Some(FilterMode::Nearest),
|
||||||
|
MinFilter::LinearMipmapNearest => Some(FilterMode::Nearest),
|
||||||
|
MinFilter::NearestMipmapLinear => Some(FilterMode::Linear),
|
||||||
|
MinFilter::LinearMipmapLinear => Some(FilterMode::Linear),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<gltf::texture::WrappingMode> for WrappingMode {
|
||||||
|
fn from(value: gltf::texture::WrappingMode) -> Self {
|
||||||
|
match value {
|
||||||
|
gltf::texture::WrappingMode::ClampToEdge => Self::ClampToEdge,
|
||||||
|
gltf::texture::WrappingMode::MirroredRepeat => Self::MirroredRepeat,
|
||||||
|
gltf::texture::WrappingMode::Repeat => Self::Repeat,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -3,7 +3,7 @@ use std::{fs::File, sync::Arc, io::Read};
|
||||||
use image::ImageError;
|
use image::ImageError;
|
||||||
use tracing::{debug, trace};
|
use tracing::{debug, trace};
|
||||||
|
|
||||||
use crate::{resource_manager::ResourceStorage, texture::Texture, resource::ResHandle, ResourceManager};
|
use crate::{resource::ResHandle, resource_manager::ResourceStorage, Image, ResourceManager};
|
||||||
|
|
||||||
use super::{LoaderError, ResourceLoader};
|
use super::{LoaderError, ResourceLoader};
|
||||||
|
|
||||||
|
@ -13,7 +13,7 @@ impl From<ImageError> for LoaderError {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// A struct that implements the `ResourceLoader` trait used for loading textures.
|
/// A struct that implements the `ResourceLoader` trait used for loading images.
|
||||||
#[derive(Default)]
|
#[derive(Default)]
|
||||||
pub struct ImageLoader;
|
pub struct ImageLoader;
|
||||||
|
|
||||||
|
@ -60,10 +60,8 @@ impl ResourceLoader for ImageLoader {
|
||||||
ImageError::IoError(e) => LoaderError::IoError(e),
|
ImageError::IoError(e) => LoaderError::IoError(e),
|
||||||
_ => LoaderError::DecodingError(e.into()),
|
_ => LoaderError::DecodingError(e.into()),
|
||||||
})?;
|
})?;
|
||||||
let texture = Texture {
|
let image = Image::from(image);
|
||||||
image,
|
let res = ResHandle::with_data(path, image);
|
||||||
};
|
|
||||||
let res = ResHandle::with_data(path, texture);
|
|
||||||
|
|
||||||
Ok(Arc::new(res))
|
Ok(Arc::new(res))
|
||||||
}
|
}
|
||||||
|
@ -76,10 +74,8 @@ impl ResourceLoader for ImageLoader {
|
||||||
ImageError::IoError(e) => LoaderError::IoError(e),
|
ImageError::IoError(e) => LoaderError::IoError(e),
|
||||||
_ => LoaderError::DecodingError(e.into()),
|
_ => LoaderError::DecodingError(e.into()),
|
||||||
})?;
|
})?;
|
||||||
let texture = Texture {
|
let image = Image::from(image);
|
||||||
image,
|
let res = ResHandle::with_data(&uuid::Uuid::new_v4().to_string(), image);
|
||||||
};
|
|
||||||
let res = ResHandle::with_data(&uuid::Uuid::new_v4().to_string(), texture);
|
|
||||||
|
|
||||||
debug!("Finished loading image of {} bytes", length);
|
debug!("Finished loading image of {} bytes", length);
|
||||||
|
|
||||||
|
|
|
@ -1,10 +1,73 @@
|
||||||
|
use std::ops::{Deref, DerefMut};
|
||||||
|
|
||||||
|
//pub use gltf::texture::{MagFilter, MinFilter, WrappingMode};
|
||||||
use image::DynamicImage;
|
use image::DynamicImage;
|
||||||
|
|
||||||
|
use crate::ResHandle;
|
||||||
|
|
||||||
|
/// The filter mode of the sampler.
|
||||||
|
///
|
||||||
|
/// This is used for minification, magnification, and mipmap filters
|
||||||
|
#[derive(Clone, Copy, PartialEq, Eq)]
|
||||||
|
pub enum FilterMode {
|
||||||
|
Nearest,
|
||||||
|
Linear,
|
||||||
|
}
|
||||||
|
|
||||||
|
/// The wrapping mode of the Texture coordinates
|
||||||
|
#[derive(Clone, Copy, PartialEq, Eq)]
|
||||||
|
pub enum WrappingMode {
|
||||||
|
ClampToEdge,
|
||||||
|
MirroredRepeat,
|
||||||
|
Repeat,
|
||||||
|
}
|
||||||
|
|
||||||
|
/// The descriptor of the sampler for a Texture.
|
||||||
|
#[derive(Clone)]
|
||||||
|
pub struct TextureSampler {
|
||||||
|
pub mag_filter: Option<FilterMode>,
|
||||||
|
pub min_filter: Option<FilterMode>,
|
||||||
|
pub mipmap_filter: Option<FilterMode>,
|
||||||
|
pub wrap_u: WrappingMode,
|
||||||
|
pub wrap_v: WrappingMode,
|
||||||
|
pub wrap_w: WrappingMode,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Clone)]
|
||||||
|
pub struct Image(DynamicImage);
|
||||||
|
|
||||||
|
impl Deref for Image {
|
||||||
|
type Target = DynamicImage;
|
||||||
|
|
||||||
|
fn deref(&self) -> &Self::Target {
|
||||||
|
&self.0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl DerefMut for Image {
|
||||||
|
fn deref_mut(&mut self) -> &mut Self::Target {
|
||||||
|
&mut self.0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<DynamicImage> for Image {
|
||||||
|
fn from(value: DynamicImage) -> Self {
|
||||||
|
Self(value)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
pub struct Texture {
|
pub struct Texture {
|
||||||
pub image: DynamicImage,
|
pub image: ResHandle<Image>,
|
||||||
|
pub sampler: Option<TextureSampler>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Texture {
|
impl Texture {
|
||||||
|
/// Create a texture from an image.
|
||||||
|
pub fn from_image(image: ResHandle<Image>) -> Self {
|
||||||
|
Self {
|
||||||
|
image,
|
||||||
|
sampler: None,
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
Loading…
Reference in New Issue