Skip to content
/ bevy Public
forked from bevyengine/bevy

Commit

Permalink
Add support for KHR_texture_transform
Browse files Browse the repository at this point in the history
  • Loading branch information
yrns committed Mar 30, 2023
1 parent 1319661 commit 462b6fb
Show file tree
Hide file tree
Showing 5 changed files with 46 additions and 12 deletions.
1 change: 1 addition & 0 deletions crates/bevy_gltf/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ bevy_utils = { path = "../bevy_utils", version = "0.11.0-dev" }
gltf = { version = "1.0.0", default-features = false, features = [
"KHR_lights_punctual",
"KHR_materials_unlit",
"KHR_texture_transform",
"extras",
"names",
"utils",
Expand Down
39 changes: 31 additions & 8 deletions crates/bevy_gltf/src/loader.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ use bevy_core_pipeline::prelude::Camera3dBundle;
use bevy_ecs::{entity::Entity, prelude::FromWorld, world::World};
use bevy_hierarchy::{BuildWorldChildren, WorldChildBuilder};
use bevy_log::warn;
use bevy_math::{Mat4, Vec3};
use bevy_math::{Mat3, Mat4, Vec3};
use bevy_pbr::{
AlphaMode, DirectionalLight, DirectionalLightBundle, PbrBundle, PointLight, PointLightBundle,
SpotLight, SpotLightBundle, StandardMaterial,
Expand All @@ -33,7 +33,7 @@ use bevy_transform::components::Transform;
use bevy_utils::{HashMap, HashSet};
use gltf::{
mesh::Mode,
texture::{MagFilter, MinFilter, WrappingMode},
texture::{MagFilter, MinFilter, TextureTransform, WrappingMode},
Material, Node, Primitive,
};
use std::{collections::VecDeque, path::Path};
Expand Down Expand Up @@ -627,19 +627,35 @@ async fn load_texture<'a>(
Ok((texture, texture_label(&gltf_texture)))
}

/// Converts [`TextureTransform`] to [`Mat3`].
fn texture_transform_mat3(texture_transform: TextureTransform) -> Mat3 {
Mat3::from_scale_angle_translation(
texture_transform.scale().into(),
-texture_transform.rotation(),
texture_transform.offset().into(),
)
}

/// Loads a glTF material as a bevy [`StandardMaterial`] and returns it.
fn load_material(material: &Material, load_context: &mut LoadContext) -> Handle<StandardMaterial> {
let material_label = material_label(material);

let pbr = material.pbr_metallic_roughness();

let color = pbr.base_color_factor();
let base_color_texture = pbr.base_color_texture().map(|info| {
// TODO: handle info.tex_coord() (the *set* index for the right texcoords)
let label = texture_label(&info.texture());
let path = AssetPath::new_ref(load_context.path(), Some(&label));
load_context.get_handle(path)
});
let (base_color_texture, uv_transform) = pbr
.base_color_texture()
.map(|info| {
// TODO: handle info.tex_coord() (the *set* index for the right texcoords)
let label = texture_label(&info.texture());
let path = AssetPath::new_ref(load_context.path(), Some(&label));
(
load_context.get_handle(path),
info.texture_transform().map(texture_transform_mat3),
)
})
.unzip();
let uv_transform = uv_transform.flatten().unwrap_or_default();

let normal_map_texture: Option<Handle<Image>> =
material.normal_texture().map(|normal_texture| {
Expand All @@ -654,6 +670,9 @@ fn load_material(material: &Material, load_context: &mut LoadContext) -> Handle<
// TODO: handle info.tex_coord() (the *set* index for the right texcoords)
let label = texture_label(&info.texture());
let path = AssetPath::new_ref(load_context.path(), Some(&label));
if info.texture_transform().map(texture_transform_mat3) != Some(uv_transform) {
warn!("Only one texture transform is supported");
}
load_context.get_handle(path)
});

Expand All @@ -671,6 +690,9 @@ fn load_material(material: &Material, load_context: &mut LoadContext) -> Handle<
// TODO: handle occlusion_texture.strength() (a scalar multiplier for occlusion strength)
let label = texture_label(&info.texture());
let path = AssetPath::new_ref(load_context.path(), Some(&label));
if info.texture_transform().map(texture_transform_mat3) != Some(uv_transform) {
warn!("Only one texture transform is supported");
}
load_context.get_handle(path)
});

Expand All @@ -694,6 +716,7 @@ fn load_material(material: &Material, load_context: &mut LoadContext) -> Handle<
emissive_texture,
unlit: material.unlit(),
alpha_mode: alpha_mode(material),
uv_transform,
..Default::default()
}),
)
Expand Down
9 changes: 8 additions & 1 deletion crates/bevy_pbr/src/pbr_material.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ use crate::{
PBR_SHADER_HANDLE,
};
use bevy_asset::Handle;
use bevy_math::Vec4;
use bevy_math::{Mat3, Vec4};
use bevy_reflect::{std_traits::ReflectDefault, FromReflect, Reflect, TypeUuid};
use bevy_render::{
color::Color, mesh::MeshVertexBufferLayout, render_asset::RenderAssets, render_resource::*,
Expand Down Expand Up @@ -231,6 +231,9 @@ pub struct StandardMaterial {
///
/// [z-fighting]: https://en.wikipedia.org/wiki/Z-fighting
pub depth_bias: f32,

/// Texture UV transform.
pub uv_transform: Mat3,
}

impl Default for StandardMaterial {
Expand Down Expand Up @@ -260,6 +263,7 @@ impl Default for StandardMaterial {
fog_enabled: true,
alpha_mode: AlphaMode::Opaque,
depth_bias: 0.0,
uv_transform: Mat3::IDENTITY,
}
}
}
Expand Down Expand Up @@ -341,6 +345,8 @@ pub struct StandardMaterialUniform {
/// When the alpha mode mask flag is set, any base color alpha above this cutoff means fully opaque,
/// and any below means fully transparent.
pub alpha_cutoff: f32,
/// Texture UV transform.
pub uv_transform: Mat3,
}

impl AsBindGroupShaderType<StandardMaterialUniform> for StandardMaterial {
Expand Down Expand Up @@ -407,6 +413,7 @@ impl AsBindGroupShaderType<StandardMaterialUniform> for StandardMaterial {
reflectance: self.reflectance,
flags: flags.bits(),
alpha_cutoff,
uv_transform: self.uv_transform,
}
}
}
Expand Down
7 changes: 4 additions & 3 deletions crates/bevy_pbr/src/render/pbr.wgsl
Original file line number Diff line number Diff line change
Expand Up @@ -23,8 +23,9 @@ fn fragment(in: FragmentInput) -> @location(0) vec4<f32> {
output_color = output_color * in.color;
#endif
#ifdef VERTEX_UVS
var uv = (material.uv_transform * vec3(in.uv, 1.0)).xy;
if ((material.flags & STANDARD_MATERIAL_FLAGS_BASE_COLOR_TEXTURE_BIT) != 0u) {
output_color = output_color * textureSample(base_color_texture, base_color_sampler, in.uv);
output_color = output_color * textureSample(base_color_texture, base_color_sampler, uv);
}
#endif

Expand All @@ -43,7 +44,7 @@ fn fragment(in: FragmentInput) -> @location(0) vec4<f32> {
var emissive: vec4<f32> = material.emissive;
#ifdef VERTEX_UVS
if ((material.flags & STANDARD_MATERIAL_FLAGS_EMISSIVE_TEXTURE_BIT) != 0u) {
emissive = vec4<f32>(emissive.rgb * textureSample(emissive_texture, emissive_sampler, in.uv).rgb, 1.0);
emissive = vec4<f32>(emissive.rgb * textureSample(emissive_texture, emissive_sampler, uv).rgb, 1.0);
}
#endif
pbr_input.material.emissive = emissive;
Expand All @@ -52,7 +53,7 @@ fn fragment(in: FragmentInput) -> @location(0) vec4<f32> {
var perceptual_roughness: f32 = material.perceptual_roughness;
#ifdef VERTEX_UVS
if ((material.flags & STANDARD_MATERIAL_FLAGS_METALLIC_ROUGHNESS_TEXTURE_BIT) != 0u) {
let metallic_roughness = textureSample(metallic_roughness_texture, metallic_roughness_sampler, in.uv);
let metallic_roughness = textureSample(metallic_roughness_texture, metallic_roughness_sampler, uv);
// Sampling from GLTF standard channels for now
metallic = metallic * metallic_roughness.b;
perceptual_roughness = perceptual_roughness * metallic_roughness.g;
Expand Down
2 changes: 2 additions & 0 deletions crates/bevy_pbr/src/render/pbr_types.wgsl
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ struct StandardMaterial {
// 'flags' is a bit field indicating various options. u32 is 32 bits so we have up to 32 options.
flags: u32,
alpha_cutoff: f32,
uv_transform: mat3x3<f32>,
};

const STANDARD_MATERIAL_FLAGS_BASE_COLOR_TEXTURE_BIT: u32 = 1u;
Expand Down Expand Up @@ -42,6 +43,7 @@ fn standard_material_new() -> StandardMaterial {
material.reflectance = 0.5;
material.flags = STANDARD_MATERIAL_FLAGS_ALPHA_MODE_OPAQUE;
material.alpha_cutoff = 0.5;
material.uv_transform = mat3x3<f32>(1.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 1.0);

return material;
}

0 comments on commit 462b6fb

Please sign in to comment.