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)| {
let field_name = f.ident.as_ref().unwrap().to_string();
let uniform = format!("{}_{}", struct_name, field_name);
let texture = format!("{}_texture", uniform);
let texture = format!("{}", uniform);
let sampler = format!("{}_sampler", uniform);
uniform_name_strings.push(uniform.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 {
// TODO: max this an iterator that feeds on field_uniform_names_ident
fn get_field_infos(&self) -> &[bevy::render::shader::FieldInfo] {
#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> {
use bevy::render::shader::AsFieldBindType;
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,
}
}

View file

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

View file

@ -16,7 +16,8 @@ fn create_entities_insert_vec(
vec![(
plane_handle,
StandardMaterial {
albedo: Color::rgb(0.1, 0.2, 0.1).into(),
albedo: Color::rgb(0.1, 0.2, 0.1),
..Default::default()
},
LocalToWorld::identity(),
Translation::new(0.0, 0.0, 0.0),
@ -29,7 +30,8 @@ fn create_entities_insert_vec(
vec![(
cube_handle,
StandardMaterial {
albedo: Color::rgb(0.5, 0.3, 0.3).into(),
albedo: Color::rgb(0.5, 0.3, 0.3),
..Default::default()
},
LocalToWorld::identity(),
Translation::new(0.0, 0.0, 1.0),
@ -79,7 +81,8 @@ fn create_entities_builder_add_component(
.build_entity()
.add(plane_handle)
.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(Translation::new(0.0, 0.0, 0.0))
@ -87,7 +90,8 @@ fn create_entities_builder_add_component(
.build_entity()
.add(cube_handle)
.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(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 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 {
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

View file

@ -19,10 +19,8 @@ fn build_move_system() -> Box<dyn Schedulable> {
for (mut translation, material_handle) in person_query.iter_mut(world) {
let material = material_storage.get_mut(&material_handle).unwrap();
translation.0 += math::vec3(1.0, 0.0, 0.0) * time.delta_seconds;
if let ColorSource::Color(ref mut color) = material.albedo {
*color = *color
material.albedo = material.albedo
+ 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 plane_handle = mesh_storage.add(Mesh::load(MeshType::Plane { size: 10.0 }));
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 {
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
@ -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),
)
.into(),
),
..Default::default()
});
builder = builder.add_entity(MeshEntity {
mesh: cube_handle,

View file

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

View file

@ -24,7 +24,7 @@ pub fn setup(world: &mut World, resources: &mut Resources) {
.add_entity(MeshEntity {
mesh: plane_handle,
material: StandardMaterial {
albedo: Color::rgb(0.1, 0.2, 0.1).into(),
albedo: Color::rgb(0.1, 0.2, 0.1),
},
..Default::default()
})
@ -32,7 +32,7 @@ pub fn setup(world: &mut World, resources: &mut Resources) {
.add_entity(MeshEntity {
mesh: cube_handle,
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),
..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 plane_handle = mesh_storage.add(Mesh::load(MeshType::Plane { size: 10.0 }));
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 {
albedo: Color::rgb(0.1, 0.2, 0.1).into(),
albedo: Color::rgb(0.1, 0.2, 0.1),
..Default::default()
});
world

View file

@ -19,10 +19,8 @@ fn build_move_system() -> Box<dyn Schedulable> {
for (mut translation, material_handle) in person_query.iter_mut(world) {
let material = material_storage.get_mut(&material_handle).unwrap();
translation.0 += math::vec3(1.0, 0.0, 0.0) * time.delta_seconds;
if let ColorSource::Color(ref mut color) = material.albedo {
*color = *color
+ Color::rgb(-time.delta_seconds, -time.delta_seconds, time.delta_seconds);
}
material.albedo = material.albedo
+ 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 plane_handle = mesh_storage.add(Mesh::load(MeshType::Plane { size: 10.0 }));
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 {
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
@ -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),
)
.into(),
),
..Default::default()
});
builder = builder.add_entity(MeshEntity {
mesh: cube_handle,

View file

@ -19,7 +19,14 @@ fn setup(world: &mut World, resources: &mut Resources) {
.unwrap();
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
@ -28,7 +35,14 @@ fn setup(world: &mut World, resources: &mut Resources) {
.add_entity(MeshEntity {
mesh: cube_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()
})
// light

View file

@ -11,7 +11,8 @@ fn setup(world: &mut World, resources: &mut Resources) {
.unwrap();
let cube_handle = mesh_storage.add(Mesh::load(MeshType::Cube));
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

View file

@ -23,19 +23,20 @@ layout(set = 0, binding = 1) uniform 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 {
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
void main() {
vec4 albedo = Albedo;
# ifdef STANDARD_MATERIAL_ALBEDO_TEXTURE
vec4 Albedo = texture(
sampler2D(StandardMaterial_albedo_texture, StandardMaterial_albedo_sampler),
albedo *= texture(
sampler2D(StandardMaterial_albedo_texture, StandardMaterial_albedo_texture_sampler),
v_Uv);
# endif
vec3 normal = normalize(v_Normal);
@ -51,5 +52,5 @@ void main() {
color += diffuse * light.color.xyz;
}
// 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,
render::{
color::ColorSource,
pipeline::{VertexBufferDescriptor, BindType},
pipeline::{BindType, VertexBufferDescriptor},
texture::{Texture, TextureViewDimension},
},
};
@ -72,35 +72,36 @@ where
bind_type: BindType::Sampler,
})
} else {
if self.index == self.field_infos.len() {
if self.index >= self.field_infos.len() {
None
} else {
let index = self.index;
self.index += 1;
let ref field_info = self.field_infos[index];
let bind_type = self
.uniforms
.get_field_bind_type(field_info.name)
.unwrap();
Some(match bind_type {
FieldBindType::Uniform => UniformInfo {
bind_type: BindType::Uniform {
dynamic: false,
properties: Vec::new(),
},
name: field_info.uniform_name,
},
FieldBindType::Texture => {
self.add_sampler = true;
UniformInfo {
bind_type: BindType::SampledTexture {
dimension: TextureViewDimension::D2,
multisampled: false,
let bind_type = self.uniforms.get_field_bind_type(field_info.name);
if let Some(bind_type) = bind_type {
Some(match bind_type {
FieldBindType::Uniform => UniformInfo {
bind_type: BindType::Uniform {
dynamic: false,
properties: Vec::new(),
},
name: field_info.texture_name,
name: field_info.uniform_name,
},
FieldBindType::Texture => {
self.add_sampler = true;
UniformInfo {
bind_type: BindType::SampledTexture {
dimension: TextureViewDimension::D2,
multisampled: false,
},
name: field_info.texture_name,
}
}
}
})
})
} else {
self.next()
}
}
}
}
@ -111,28 +112,43 @@ pub struct FieldInfo {
pub uniform_name: &'static str,
pub texture_name: &'static str,
pub sampler_name: &'static str,
pub is_instanceable: bool,
pub is_instanceable: bool,
}
pub trait AsFieldBindType {
fn get_field_bind_type(&self) -> FieldBindType;
fn get_field_bind_type(&self) -> Option<FieldBindType>;
}
impl AsFieldBindType for ColorSource {
fn get_field_bind_type(&self) -> FieldBindType {
match *self {
fn get_field_bind_type(&self) -> Option<FieldBindType> {
Some(match *self {
ColorSource::Texture(_) => FieldBindType::Texture,
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
where
T: GetBytes,
{
default fn get_field_bind_type(&self) -> FieldBindType {
FieldBindType::Uniform
default fn get_field_bind_type(&self) -> Option<FieldBindType> {
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 {
fn get_texture(&self) -> Option<Handle<Texture>> {
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 bevy_derive::Uniforms;
#[derive(Uniforms)]
pub struct StandardMaterial {
pub albedo: Color,
#[uniform(shader_def)]
pub albedo: ColorSource,
pub albedo_texture: Option<Handle<Texture>>,
}
impl Default for StandardMaterial {
fn default() -> Self {
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;
pub enum TextureType {
@ -55,3 +59,22 @@ pub fn create_texels(size: usize) -> Vec<u8> {
})
.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
}
for entry in examples/*
do
IFS='/'