Add SamplerDescriptor to Texture (#399) (#747)

GLTF loader now grabs (some) sampler information from the respective
GLTF sampler struct.
This commit is contained in:
Alex Hirsch 2020-10-29 22:22:45 +01:00 committed by GitHub
parent fb2b19def5
commit 1b051d3353
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 56 additions and 24 deletions

View File

@ -7,14 +7,18 @@ use bevy_render::{
mesh::{Indices, Mesh, VertexAttribute}, mesh::{Indices, Mesh, VertexAttribute},
pipeline::PrimitiveTopology, pipeline::PrimitiveTopology,
prelude::{Color, Texture}, prelude::{Color, Texture},
texture::TextureFormat, texture::{AddressMode, FilterMode, SamplerDescriptor, TextureFormat},
}; };
use bevy_scene::Scene; use bevy_scene::Scene;
use bevy_transform::{ use bevy_transform::{
hierarchy::{BuildWorldChildren, WorldChildBuilder}, hierarchy::{BuildWorldChildren, WorldChildBuilder},
prelude::{GlobalTransform, Transform}, prelude::{GlobalTransform, Transform},
}; };
use gltf::{mesh::Mode, Primitive}; use gltf::{
mesh::Mode,
texture::{MagFilter, MinFilter, WrappingMode},
Primitive,
};
use image::{GenericImageView, ImageFormat}; use image::{GenericImageView, ImageFormat};
use std::path::Path; use std::path::Path;
use thiserror::Error; use thiserror::Error;
@ -24,6 +28,8 @@ use thiserror::Error;
pub enum GltfError { pub enum GltfError {
#[error("Unsupported primitive mode.")] #[error("Unsupported primitive mode.")]
UnsupportedPrimitive { mode: Mode }, UnsupportedPrimitive { mode: Mode },
#[error("Unsupported min filter.")]
UnsupportedMinFilter { filter: MinFilter },
#[error("Invalid GLTF file.")] #[error("Invalid GLTF file.")]
Gltf(#[from] gltf::Error), Gltf(#[from] gltf::Error),
#[error("Binary blob is missing.")] #[error("Binary blob is missing.")]
@ -133,6 +139,7 @@ async fn load_gltf<'a, 'b>(
data: image.clone().into_vec(), data: image.clone().into_vec(),
size: bevy_math::f32::vec2(size.0 as f32, size.1 as f32), size: bevy_math::f32::vec2(size.0 as f32, size.1 as f32),
format: TextureFormat::Rgba8Unorm, format: TextureFormat::Rgba8Unorm,
sampler: texture_sampler(&texture)?,
}), }),
); );
} }
@ -263,6 +270,43 @@ fn texture_label(texture: &gltf::Texture) -> String {
format!("Texture{}", texture.index()) format!("Texture{}", texture.index())
} }
fn texture_sampler(texture: &gltf::Texture) -> Result<SamplerDescriptor, GltfError> {
let gltf_sampler = texture.sampler();
Ok(SamplerDescriptor {
address_mode_u: texture_address_mode(&gltf_sampler.wrap_s()),
address_mode_v: texture_address_mode(&gltf_sampler.wrap_t()),
mag_filter: gltf_sampler
.mag_filter()
.map(|mf| match mf {
MagFilter::Nearest => FilterMode::Nearest,
MagFilter::Linear => FilterMode::Linear,
})
.unwrap_or(SamplerDescriptor::default().mag_filter),
min_filter: gltf_sampler
.min_filter()
.map(|mf| match mf {
MinFilter::Nearest => Ok(FilterMode::Nearest),
MinFilter::Linear => Ok(FilterMode::Linear),
filter => Err(GltfError::UnsupportedMinFilter { filter }),
})
.transpose()?
.unwrap_or(SamplerDescriptor::default().min_filter),
..Default::default()
})
}
fn texture_address_mode(gltf_address_mode: &gltf::texture::WrappingMode) -> AddressMode {
match gltf_address_mode {
WrappingMode::ClampToEdge => AddressMode::ClampToEdge,
WrappingMode::Repeat => AddressMode::Repeat,
WrappingMode::MirroredRepeat => AddressMode::MirrorRepeat,
}
}
fn get_primitive_topology(mode: Mode) -> Result<PrimitiveTopology, GltfError> { fn get_primitive_topology(mode: Mode) -> Result<PrimitiveTopology, GltfError> {
match mode { match mode {
Mode::Points => Ok(PrimitiveTopology::PointList), Mode::Points => Ok(PrimitiveTopology::PointList),

View File

@ -1,9 +1,8 @@
use super::Texture;
use crate::pipeline::CompareFunction; use crate::pipeline::CompareFunction;
use std::num::NonZeroU8; use std::num::NonZeroU8;
/// Describes a sampler /// Describes a sampler
#[derive(Copy, Clone)] #[derive(Debug, Copy, Clone)]
pub struct SamplerDescriptor { pub struct SamplerDescriptor {
pub address_mode_u: AddressMode, pub address_mode_u: AddressMode,
pub address_mode_v: AddressMode, pub address_mode_v: AddressMode,
@ -34,23 +33,6 @@ impl Default for SamplerDescriptor {
} }
} }
impl From<&Texture> for SamplerDescriptor {
fn from(_texture: &Texture) -> Self {
SamplerDescriptor {
address_mode_u: AddressMode::ClampToEdge,
address_mode_v: AddressMode::ClampToEdge,
address_mode_w: AddressMode::ClampToEdge,
mag_filter: FilterMode::Nearest,
min_filter: FilterMode::Linear,
mipmap_filter: FilterMode::Nearest,
lod_min_clamp: 0.0,
lod_max_clamp: std::f32::MAX,
compare_function: None,
anisotropy_clamp: None,
}
}
}
/// How edges should be handled in texture addressing. /// How edges should be handled in texture addressing.
#[derive(Copy, Clone, Debug, Hash, Eq, PartialEq)] #[derive(Copy, Clone, Debug, Hash, Eq, PartialEq)]
pub enum AddressMode { pub enum AddressMode {

View File

@ -18,6 +18,7 @@ pub struct Texture {
pub data: Vec<u8>, pub data: Vec<u8>,
pub size: Vec2, pub size: Vec2,
pub format: TextureFormat, pub format: TextureFormat,
pub sampler: SamplerDescriptor,
} }
impl Default for Texture { impl Default for Texture {
@ -26,6 +27,7 @@ impl Default for Texture {
data: Default::default(), data: Default::default(),
size: Default::default(), size: Default::default(),
format: TextureFormat::Rgba8UnormSrgb, format: TextureFormat::Rgba8UnormSrgb,
sampler: Default::default(),
} }
} }
} }
@ -37,7 +39,12 @@ impl Texture {
data.len(), data.len(),
"Pixel data, size and format have to match", "Pixel data, size and format have to match",
); );
Self { data, size, format } Self {
data,
size,
format,
..Default::default()
}
} }
pub fn new_fill(size: Vec2, pixel: &[u8], format: TextureFormat) -> Self { pub fn new_fill(size: Vec2, pixel: &[u8], format: TextureFormat) -> Self {
@ -104,8 +111,7 @@ impl Texture {
let texture_descriptor: TextureDescriptor = texture.into(); let texture_descriptor: TextureDescriptor = texture.into();
let texture_resource = render_resource_context.create_texture(texture_descriptor); let texture_resource = render_resource_context.create_texture(texture_descriptor);
let sampler_descriptor: SamplerDescriptor = texture.into(); let sampler_resource = render_resource_context.create_sampler(&texture.sampler);
let sampler_resource = render_resource_context.create_sampler(&sampler_descriptor);
render_resource_context.set_asset_resource( render_resource_context.set_asset_resource(
texture_handle, texture_handle,