separate albedo color and make it required

I worked really hard to make ColorSource work, but sadly we need color to be instanceable and making it optional would add too much complexity. Maybe at some point in the future we can add it back. On the plus side, albedo color now modulates the albedo texture
This commit is contained in:
Carter Anderson 2020-03-17 22:02:01 -07:00
parent ffa0bbe9ee
commit 04590de678
16 changed files with 146 additions and 76 deletions

View File

@ -138,7 +138,7 @@ pub fn derive_uniforms(input: TokenStream) -> TokenStream {
}).map(|(f, attrs)| { }).map(|(f, attrs)| {
let field_name = f.ident.as_ref().unwrap().to_string(); let field_name = f.ident.as_ref().unwrap().to_string();
let uniform = format!("{}_{}", struct_name, field_name); let uniform = format!("{}_{}", struct_name, field_name);
let texture = format!("{}_texture", uniform); let texture = format!("{}", uniform);
let sampler = format!("{}_sampler", uniform); let sampler = format!("{}_sampler", uniform);
uniform_name_strings.push(uniform.clone()); uniform_name_strings.push(uniform.clone());
texture_and_sampler_name_strings.push(texture.clone()); texture_and_sampler_name_strings.push(texture.clone());
@ -184,7 +184,6 @@ pub fn derive_uniforms(input: TokenStream) -> TokenStream {
}); });
impl bevy::render::shader::AsUniforms for #struct_name { impl bevy::render::shader::AsUniforms for #struct_name {
// TODO: max this an iterator that feeds on field_uniform_names_ident
fn get_field_infos(&self) -> &[bevy::render::shader::FieldInfo] { fn get_field_infos(&self) -> &[bevy::render::shader::FieldInfo] {
#field_infos_ident #field_infos_ident
} }
@ -192,7 +191,7 @@ pub fn derive_uniforms(input: TokenStream) -> TokenStream {
fn get_field_bind_type(&self, name: &str) -> Option<bevy::render::shader::FieldBindType> { fn get_field_bind_type(&self, name: &str) -> Option<bevy::render::shader::FieldBindType> {
use bevy::render::shader::AsFieldBindType; use bevy::render::shader::AsFieldBindType;
match name { match name {
#(#active_uniform_field_name_strings => Some(self.#active_uniform_field_names.get_field_bind_type()),)* #(#active_uniform_field_name_strings => self.#active_uniform_field_names.get_field_bind_type(),)*
_ => None, _ => None,
} }
} }

View File

@ -85,7 +85,7 @@ fn setup(world: &mut World, resources: &mut Resources) {
..Default::default() ..Default::default()
}, },
material: MyMaterial { material: MyMaterial {
color: Color::rgb(0.0, 0.8, 0.0).into(), color: Color::rgb(0.0, 0.8, 0.0),
always_red: false, always_red: false,
}, },
translation: Translation::new(-2.0, 0.0, 0.0), translation: Translation::new(-2.0, 0.0, 0.0),
@ -99,7 +99,7 @@ fn setup(world: &mut World, resources: &mut Resources) {
..Default::default() ..Default::default()
}, },
material: MyMaterial { material: MyMaterial {
color: Color::rgb(0.0, 0.0, 0.0).into(), color: Color::rgb(0.0, 0.0, 0.0),
always_red: true, always_red: true,
}, },
translation: Translation::new(2.0, 0.0, 0.0), translation: Translation::new(2.0, 0.0, 0.0),

View File

@ -16,7 +16,8 @@ fn create_entities_insert_vec(
vec![( vec![(
plane_handle, plane_handle,
StandardMaterial { StandardMaterial {
albedo: Color::rgb(0.1, 0.2, 0.1).into(), albedo: Color::rgb(0.1, 0.2, 0.1),
..Default::default()
}, },
LocalToWorld::identity(), LocalToWorld::identity(),
Translation::new(0.0, 0.0, 0.0), Translation::new(0.0, 0.0, 0.0),
@ -29,7 +30,8 @@ fn create_entities_insert_vec(
vec![( vec![(
cube_handle, cube_handle,
StandardMaterial { StandardMaterial {
albedo: Color::rgb(0.5, 0.3, 0.3).into(), albedo: Color::rgb(0.5, 0.3, 0.3),
..Default::default()
}, },
LocalToWorld::identity(), LocalToWorld::identity(),
Translation::new(0.0, 0.0, 1.0), Translation::new(0.0, 0.0, 1.0),
@ -79,7 +81,8 @@ fn create_entities_builder_add_component(
.build_entity() .build_entity()
.add(plane_handle) .add(plane_handle)
.add(StandardMaterial { .add(StandardMaterial {
albedo: Color::rgb(0.1, 0.2, 0.1).into(), albedo: Color::rgb(0.1, 0.2, 0.1),
..Default::default()
}) })
.add(LocalToWorld::identity()) .add(LocalToWorld::identity())
.add(Translation::new(0.0, 0.0, 0.0)) .add(Translation::new(0.0, 0.0, 0.0))
@ -87,7 +90,8 @@ fn create_entities_builder_add_component(
.build_entity() .build_entity()
.add(cube_handle) .add(cube_handle)
.add(StandardMaterial { .add(StandardMaterial {
albedo: Color::rgb(0.5, 0.3, 0.3).into(), albedo: Color::rgb(0.5, 0.3, 0.3),
..Default::default()
}) })
.add(LocalToWorld::identity()) .add(LocalToWorld::identity())
.add(Translation::new(0.0, 0.0, 1.0)) .add(Translation::new(0.0, 0.0, 1.0))
@ -167,10 +171,12 @@ fn setup(world: &mut World, resources: &mut Resources) {
let plane_handle = mesh_storage.add(Mesh::load(MeshType::Plane { size: 10.0 })); let plane_handle = mesh_storage.add(Mesh::load(MeshType::Plane { size: 10.0 }));
let cube_material_handle = material_storage.add(StandardMaterial { let cube_material_handle = material_storage.add(StandardMaterial {
albedo: Color::rgb(0.5, 0.3, 0.3).into(), albedo: Color::rgb(0.5, 0.3, 0.3),
..Default::default()
}); });
let plane_material_handle = material_storage.add(StandardMaterial { let plane_material_handle = material_storage.add(StandardMaterial {
albedo: Color::rgb(0.1, 0.2, 0.1).into(), albedo: Color::rgb(0.1, 0.2, 0.1),
..Default::default()
}); });
// no-archetype precompile: 1.24 sec // no-archetype precompile: 1.24 sec

View File

@ -19,11 +19,9 @@ fn build_move_system() -> Box<dyn Schedulable> {
for (mut translation, material_handle) in person_query.iter_mut(world) { for (mut translation, material_handle) in person_query.iter_mut(world) {
let material = material_storage.get_mut(&material_handle).unwrap(); let material = material_storage.get_mut(&material_handle).unwrap();
translation.0 += math::vec3(1.0, 0.0, 0.0) * time.delta_seconds; translation.0 += math::vec3(1.0, 0.0, 0.0) * time.delta_seconds;
if let ColorSource::Color(ref mut color) = material.albedo { material.albedo = material.albedo
*color = *color
+ Color::rgb(-time.delta_seconds, -time.delta_seconds, time.delta_seconds); + Color::rgb(-time.delta_seconds, -time.delta_seconds, time.delta_seconds);
} }
}
}) })
} }
@ -35,10 +33,12 @@ fn setup(world: &mut World, resources: &mut Resources) {
let cube_handle = mesh_storage.add(Mesh::load(MeshType::Cube)); let cube_handle = mesh_storage.add(Mesh::load(MeshType::Cube));
let plane_handle = mesh_storage.add(Mesh::load(MeshType::Plane { size: 10.0 })); let plane_handle = mesh_storage.add(Mesh::load(MeshType::Plane { size: 10.0 }));
let cube_material_handle = material_storage.add(StandardMaterial { let cube_material_handle = material_storage.add(StandardMaterial {
albedo: Color::rgb(0.5, 0.4, 0.3).into(), albedo: Color::rgb(0.5, 0.4, 0.3),
..Default::default()
}); });
let plane_material_handle = material_storage.add(StandardMaterial { let plane_material_handle = material_storage.add(StandardMaterial {
albedo: Color::rgb(0.1, 0.2, 0.1).into(), albedo: Color::rgb(0.1, 0.2, 0.1),
..Default::default()
}); });
let mut builder = world let mut builder = world
@ -84,8 +84,8 @@ fn setup(world: &mut World, resources: &mut Resources) {
rng.gen_range(0.0, 1.0), rng.gen_range(0.0, 1.0),
rng.gen_range(0.0, 1.0), rng.gen_range(0.0, 1.0),
rng.gen_range(0.0, 1.0), rng.gen_range(0.0, 1.0),
) ),
.into(), ..Default::default()
}); });
builder = builder.add_entity(MeshEntity { builder = builder.add_entity(MeshEntity {
mesh: cube_handle, mesh: cube_handle,

View File

@ -159,6 +159,7 @@ fn create_person(world: &mut World, mesh_handle: Handle<Mesh>, translation: Tran
}, },
StandardMaterial { StandardMaterial {
albedo: (math::vec4(0.5, 0.3, 0.3, 1.0) * random::<f32>()).into(), albedo: (math::vec4(0.5, 0.3, 0.3, 1.0) * random::<f32>()).into(),
..Default::default()
}, },
Renderable { Renderable {
instanced: true, instanced: true,

View File

@ -30,7 +30,8 @@ fn setup(world: &mut World, resources: &mut Resources) {
let cube_handle = mesh_storage.add(Mesh::load(MeshType::Cube)); let cube_handle = mesh_storage.add(Mesh::load(MeshType::Cube));
let cube_material_handle = material_storage.add(StandardMaterial { let cube_material_handle = material_storage.add(StandardMaterial {
albedo: Color::rgb(0.5, 0.4, 0.3).into(), albedo: Color::rgb(0.5, 0.4, 0.3),
..Default::default()
}); });
world world

View File

@ -24,7 +24,7 @@ pub fn setup(world: &mut World, resources: &mut Resources) {
.add_entity(MeshEntity { .add_entity(MeshEntity {
mesh: plane_handle, mesh: plane_handle,
material: StandardMaterial { material: StandardMaterial {
albedo: Color::rgb(0.1, 0.2, 0.1).into(), albedo: Color::rgb(0.1, 0.2, 0.1),
}, },
..Default::default() ..Default::default()
}) })
@ -32,7 +32,7 @@ pub fn setup(world: &mut World, resources: &mut Resources) {
.add_entity(MeshEntity { .add_entity(MeshEntity {
mesh: cube_handle, mesh: cube_handle,
material: StandardMaterial { material: StandardMaterial {
albedo: Color::rgb(0.5, 0.4, 0.3).into(), albedo: Color::rgb(0.5, 0.4, 0.3),
}, },
translation: Translation::new(0.0, 0.0, 1.0), translation: Translation::new(0.0, 0.0, 1.0),
..Default::default() ..Default::default()

View File

@ -12,10 +12,12 @@ fn setup(world: &mut World, resources: &mut Resources) {
let cube_handle = mesh_storage.add(Mesh::load(MeshType::Cube)); let cube_handle = mesh_storage.add(Mesh::load(MeshType::Cube));
let plane_handle = mesh_storage.add(Mesh::load(MeshType::Plane { size: 10.0 })); let plane_handle = mesh_storage.add(Mesh::load(MeshType::Plane { size: 10.0 }));
let cube_material_handle = material_storage.add(StandardMaterial { let cube_material_handle = material_storage.add(StandardMaterial {
albedo: Color::rgb(0.5, 0.4, 0.3).into(), albedo: Color::rgb(0.5, 0.4, 0.3),
..Default::default()
}); });
let plane_material_handle = material_storage.add(StandardMaterial { let plane_material_handle = material_storage.add(StandardMaterial {
albedo: Color::rgb(0.1, 0.2, 0.1).into(), albedo: Color::rgb(0.1, 0.2, 0.1),
..Default::default()
}); });
world world

View File

@ -19,11 +19,9 @@ fn build_move_system() -> Box<dyn Schedulable> {
for (mut translation, material_handle) in person_query.iter_mut(world) { for (mut translation, material_handle) in person_query.iter_mut(world) {
let material = material_storage.get_mut(&material_handle).unwrap(); let material = material_storage.get_mut(&material_handle).unwrap();
translation.0 += math::vec3(1.0, 0.0, 0.0) * time.delta_seconds; translation.0 += math::vec3(1.0, 0.0, 0.0) * time.delta_seconds;
if let ColorSource::Color(ref mut color) = material.albedo { material.albedo = material.albedo
*color = *color
+ Color::rgb(-time.delta_seconds, -time.delta_seconds, time.delta_seconds); + Color::rgb(-time.delta_seconds, -time.delta_seconds, time.delta_seconds);
} }
}
}) })
} }
@ -35,10 +33,12 @@ fn setup(world: &mut World, resources: &mut Resources) {
let cube_handle = mesh_storage.add(Mesh::load(MeshType::Cube)); let cube_handle = mesh_storage.add(Mesh::load(MeshType::Cube));
let plane_handle = mesh_storage.add(Mesh::load(MeshType::Plane { size: 10.0 })); let plane_handle = mesh_storage.add(Mesh::load(MeshType::Plane { size: 10.0 }));
let cube_material_handle = material_storage.add(StandardMaterial { let cube_material_handle = material_storage.add(StandardMaterial {
albedo: Color::rgb(0.5, 0.4, 0.3).into(), albedo: Color::rgb(0.5, 0.4, 0.3),
..Default::default()
}); });
let plane_material_handle = material_storage.add(StandardMaterial { let plane_material_handle = material_storage.add(StandardMaterial {
albedo: Color::rgb(0.1, 0.2, 0.1).into(), albedo: Color::rgb(0.1, 0.2, 0.1),
..Default::default()
}); });
let mut builder = world let mut builder = world
@ -84,8 +84,8 @@ fn setup(world: &mut World, resources: &mut Resources) {
rng.gen_range(0.0, 1.0), rng.gen_range(0.0, 1.0),
rng.gen_range(0.0, 1.0), rng.gen_range(0.0, 1.0),
rng.gen_range(0.0, 1.0), rng.gen_range(0.0, 1.0),
) ),
.into(), ..Default::default()
}); });
builder = builder.add_entity(MeshEntity { builder = builder.add_entity(MeshEntity {
mesh: cube_handle, mesh: cube_handle,

View File

@ -19,7 +19,14 @@ fn setup(world: &mut World, resources: &mut Resources) {
.unwrap(); .unwrap();
let cube_material_handle = material_storage.add(StandardMaterial { let cube_material_handle = material_storage.add(StandardMaterial {
albedo: texture_handle.into(), albedo_texture: Some(texture_handle),
..Default::default()
});
let modulated_cube_material_handle = material_storage.add(StandardMaterial {
albedo: Color::rgba(1.0, 0.0, 0.0, 0.5),
albedo_texture: Some(texture_handle),
..Default::default()
}); });
world world
@ -28,7 +35,14 @@ fn setup(world: &mut World, resources: &mut Resources) {
.add_entity(MeshEntity { .add_entity(MeshEntity {
mesh: cube_handle, mesh: cube_handle,
material: cube_material_handle, material: cube_material_handle,
translation: Translation::new(0.0, 0.0, 0.0), translation: Translation::new(1.0, 0.0, 0.0),
..Default::default()
})
// cube modulated
.add_entity(MeshEntity {
mesh: cube_handle,
material: modulated_cube_material_handle,
translation: Translation::new(-1.0, 0.0, 0.0),
..Default::default() ..Default::default()
}) })
// light // light

View File

@ -11,7 +11,8 @@ fn setup(world: &mut World, resources: &mut Resources) {
.unwrap(); .unwrap();
let cube_handle = mesh_storage.add(Mesh::load(MeshType::Cube)); let cube_handle = mesh_storage.add(Mesh::load(MeshType::Cube));
let cube_material_handle = material_storage.add(StandardMaterial { let cube_material_handle = material_storage.add(StandardMaterial {
albedo: Color::rgb(0.5, 0.3, 0.3).into(), albedo: Color::rgb(0.5, 0.3, 0.3),
..Default::default()
}); });
world world

View File

@ -23,19 +23,20 @@ layout(set = 0, binding = 1) uniform Lights {
Light SceneLights[MAX_LIGHTS]; Light SceneLights[MAX_LIGHTS];
}; };
# ifdef STANDARD_MATERIAL_ALBEDO_TEXTURE
layout(set = 2, binding = 1) uniform texture2D StandardMaterial_albedo_texture;
layout(set = 2, binding = 2) uniform sampler StandardMaterial_albedo_sampler;
# else
layout(set = 2, binding = 1) uniform StandardMaterial_albedo { layout(set = 2, binding = 1) uniform StandardMaterial_albedo {
vec4 Albedo; vec4 Albedo;
}; };
# ifdef STANDARD_MATERIAL_ALBEDO_TEXTURE
layout(set = 3, binding = 1) uniform texture2D StandardMaterial_albedo_texture;
layout(set = 3, binding = 2) uniform sampler StandardMaterial_albedo_texture_sampler;
# endif # endif
void main() { void main() {
vec4 albedo = Albedo;
# ifdef STANDARD_MATERIAL_ALBEDO_TEXTURE # ifdef STANDARD_MATERIAL_ALBEDO_TEXTURE
vec4 Albedo = texture( albedo *= texture(
sampler2D(StandardMaterial_albedo_texture, StandardMaterial_albedo_sampler), sampler2D(StandardMaterial_albedo_texture, StandardMaterial_albedo_texture_sampler),
v_Uv); v_Uv);
# endif # endif
vec3 normal = normalize(v_Normal); vec3 normal = normalize(v_Normal);
@ -51,5 +52,5 @@ void main() {
color += diffuse * light.color.xyz; color += diffuse * light.color.xyz;
} }
// multiply the light by material color // multiply the light by material color
o_Target = vec4(color, 1.0) * Albedo; o_Target = vec4(color, 1.0) * albedo;
} }

View File

@ -3,7 +3,7 @@ use crate::{
core::GetBytes, core::GetBytes,
render::{ render::{
color::ColorSource, color::ColorSource,
pipeline::{VertexBufferDescriptor, BindType}, pipeline::{BindType, VertexBufferDescriptor},
texture::{Texture, TextureViewDimension}, texture::{Texture, TextureViewDimension},
}, },
}; };
@ -72,16 +72,14 @@ where
bind_type: BindType::Sampler, bind_type: BindType::Sampler,
}) })
} else { } else {
if self.index == self.field_infos.len() { if self.index >= self.field_infos.len() {
None None
} else { } else {
let index = self.index; let index = self.index;
self.index += 1; self.index += 1;
let ref field_info = self.field_infos[index]; let ref field_info = self.field_infos[index];
let bind_type = self let bind_type = self.uniforms.get_field_bind_type(field_info.name);
.uniforms if let Some(bind_type) = bind_type {
.get_field_bind_type(field_info.name)
.unwrap();
Some(match bind_type { Some(match bind_type {
FieldBindType::Uniform => UniformInfo { FieldBindType::Uniform => UniformInfo {
bind_type: BindType::Uniform { bind_type: BindType::Uniform {
@ -101,6 +99,9 @@ where
} }
} }
}) })
} else {
self.next()
}
} }
} }
} }
@ -115,24 +116,39 @@ pub struct FieldInfo {
} }
pub trait AsFieldBindType { pub trait AsFieldBindType {
fn get_field_bind_type(&self) -> FieldBindType; fn get_field_bind_type(&self) -> Option<FieldBindType>;
} }
impl AsFieldBindType for ColorSource { impl AsFieldBindType for ColorSource {
fn get_field_bind_type(&self) -> FieldBindType { fn get_field_bind_type(&self) -> Option<FieldBindType> {
match *self { Some(match *self {
ColorSource::Texture(_) => FieldBindType::Texture, ColorSource::Texture(_) => FieldBindType::Texture,
ColorSource::Color(_) => FieldBindType::Uniform, ColorSource::Color(_) => FieldBindType::Uniform,
})
} }
} }
impl AsFieldBindType for Option<Handle<Texture>> {
fn get_field_bind_type(&self) -> Option<FieldBindType> {
match *self {
Some(_) => Some(FieldBindType::Texture),
None => None,
}
}
}
impl AsFieldBindType for Handle<Texture> {
fn get_field_bind_type(&self) -> Option<FieldBindType> {
Some(FieldBindType::Texture)
}
} }
impl<T> AsFieldBindType for T impl<T> AsFieldBindType for T
where where
T: GetBytes, T: GetBytes,
{ {
default fn get_field_bind_type(&self) -> FieldBindType { default fn get_field_bind_type(&self) -> Option<FieldBindType> {
FieldBindType::Uniform Some(FieldBindType::Uniform)
} }
} }
@ -157,6 +173,12 @@ impl GetTexture for Handle<Texture> {
} }
} }
impl GetTexture for Option<Handle<Texture>> {
fn get_texture(&self) -> Option<Handle<Texture>> {
*self
}
}
impl GetTexture for ColorSource { impl GetTexture for ColorSource {
fn get_texture(&self) -> Option<Handle<Texture>> { fn get_texture(&self) -> Option<Handle<Texture>> {
match self { match self {

View File

@ -1,18 +1,20 @@
use crate::render::{Color, ColorSource}; use crate::{asset::Handle, render::{Color, texture::Texture}};
use crate as bevy; // for macro imports use crate as bevy; // for macro imports
use bevy_derive::Uniforms; use bevy_derive::Uniforms;
#[derive(Uniforms)] #[derive(Uniforms)]
pub struct StandardMaterial { pub struct StandardMaterial {
pub albedo: Color,
#[uniform(shader_def)] #[uniform(shader_def)]
pub albedo: ColorSource, pub albedo_texture: Option<Handle<Texture>>,
} }
impl Default for StandardMaterial { impl Default for StandardMaterial {
fn default() -> Self { fn default() -> Self {
StandardMaterial { StandardMaterial {
albedo: Color::rgb(0.3, 0.3, 0.3).into(), albedo: Color::rgb(1.0, 1.0, 1.0),
albedo_texture: None,
} }
} }
} }

View File

@ -1,4 +1,8 @@
use crate::asset::Asset; use crate::{
asset::{Asset, Handle},
core::GetBytes,
render::shader::ShaderDefSuffixProvider,
};
use std::fs::File; use std::fs::File;
pub enum TextureType { pub enum TextureType {
@ -55,3 +59,22 @@ pub fn create_texels(size: usize) -> Vec<u8> {
}) })
.collect() .collect()
} }
impl ShaderDefSuffixProvider for Option<Handle<Texture>> {
fn get_shader_def(&self) -> Option<&'static str> {
match *self {
Some(_) => Some(""),
None => None,
}
}
}
impl GetBytes for Option<Handle<Texture>> {
fn get_bytes(&self) -> Vec<std::primitive::u8> {
Vec::new()
}
fn get_bytes_ref(&self) -> Option<&[std::primitive::u8]> {
None
}
}

View File

@ -5,8 +5,6 @@ run_example() {
timeout "$duration" cargo run --release --example $1 timeout "$duration" cargo run --release --example $1
} }
for entry in examples/* for entry in examples/*
do do
IFS='/' IFS='/'