render: is_transparent flag. draw transparent object back-to-front and opaque objects front-to-back

This commit is contained in:
Carter Anderson 2020-06-24 11:35:01 -07:00
parent 2b8fe144a8
commit 4ba2f72572
6 changed files with 53 additions and 12 deletions

View file

@ -2,6 +2,7 @@ use crate::bytes::AsBytes;
use std::{
cmp::Ordering,
hash::{Hash, Hasher},
ops::Neg,
};
// working around the famous "rust float ordering" problem
@ -39,3 +40,10 @@ impl Hash for FloatOrd {
state.write(self.0.as_bytes());
}
}
impl Neg for FloatOrd {
type Output = FloatOrd;
fn neg(self) -> Self::Output {
FloatOrd(-self.0)
}
}

View file

@ -35,6 +35,7 @@ pub fn visible_entities_system(
let camera_position = camera_transform.value.w_axis().truncate();
let mut no_transform_order = 0.0;
let mut transparent_entities = Vec::new();
for (entity, draw) in entities_query.iter_entities(world) {
if !draw.is_visible {
continue;
@ -49,14 +50,28 @@ pub fn visible_entities_system(
no_transform_order += 0.1;
order
};
visible_entities.value.push(VisibleEntity {
entity,
order,
})
if draw.is_transparent {
transparent_entities.push(VisibleEntity {
entity,
order,
})
} else {
visible_entities.value.push(VisibleEntity {
entity,
order,
})
}
}
// sort opaque entities front-to-back
visible_entities.value.sort_by_key(|e| e.order);
// sort transparent entities front-to-back
transparent_entities.sort_by_key(|e|-e.order);
visible_entities.value.extend(transparent_entities);
// TODO: check for big changes in visible entities len() vs capacity() (ex: 2x) and resize to prevent holding unneeded memory
}
}

View file

@ -51,6 +51,7 @@ pub enum RenderCommand {
#[derive(Properties)]
pub struct Draw {
pub is_visible: bool,
pub is_transparent: bool,
#[property(ignore)]
pub render_commands: Vec<RenderCommand>,
}
@ -59,6 +60,7 @@ impl Default for Draw {
fn default() -> Self {
Self {
is_visible: true,
is_transparent: false,
render_commands: Default::default(),
}
}

View file

@ -103,7 +103,7 @@ impl Node for PassNode {
};
let mut draw_state = DrawState::default();
for visible_entity in visible_entities.iter().rev() {
for visible_entity in visible_entities.iter() {
let draw = if let Some(draw) = world.get_component::<Draw>(visible_entity.entity) {
draw
} else {

View file

@ -46,9 +46,12 @@ impl Default for SpriteEntity {
..Default::default()
},
)]),
draw: Draw {
is_transparent: true,
..Default::default()
},
sprite: Default::default(),
material: Default::default(),
draw: Default::default(),
transform: Default::default(),
translation: Default::default(),
rotation: Default::default(),
@ -91,10 +94,13 @@ impl Default for SpriteSheetEntity {
..Default::default()
},
)]),
draw: Draw {
is_transparent: true,
..Default::default()
},
mesh: QUAD_HANDLE,
sprite: Default::default(),
texture_atlas: Default::default(),
draw: Default::default(),
transform: Default::default(),
translation: Default::default(),
rotation: Default::default(),

View file

@ -31,6 +31,7 @@ fn setup(
// this material renders the texture normally
let material_handle = materials.add(StandardMaterial {
albedo_texture: Some(texture_handle),
shaded: false,
..Default::default()
});
@ -38,6 +39,7 @@ fn setup(
let red_material_handle = materials.add(StandardMaterial {
albedo: Color::rgba(1.0, 0.0, 0.0, 0.5),
albedo_texture: Some(texture_handle),
shaded: false,
..Default::default()
});
@ -45,6 +47,7 @@ fn setup(
let blue_material_handle = materials.add(StandardMaterial {
albedo: Color::rgba(0.0, 0.0, 1.0, 0.5),
albedo_texture: Some(texture_handle),
shaded: false,
..Default::default()
});
@ -57,6 +60,10 @@ fn setup(
material: material_handle,
translation: Translation::new(0.0, -1.5, 0.0),
rotation: Rotation::from_euler_angles(0.0, std::f32::consts::PI / 3.0, 0.0),
draw: Draw {
is_transparent: true,
..Default::default()
},
..Default::default()
})
// textured quad - modulated
@ -65,6 +72,10 @@ fn setup(
material: red_material_handle,
translation: Translation::new(0.0, 0.0, 0.0),
rotation: Rotation::from_euler_angles(0.0, std::f32::consts::PI / 3.0, 0.0),
draw: Draw {
is_transparent: true,
..Default::default()
},
..Default::default()
})
// textured quad - modulated
@ -73,11 +84,10 @@ fn setup(
material: blue_material_handle,
translation: Translation::new(0.0, 1.5, 0.0),
rotation: Rotation::from_euler_angles(0.0, std::f32::consts::PI / 3.0, 0.0),
..Default::default()
})
// light
.add_entity(LightEntity {
translation: Translation::new(0.0, -5.0, 0.0),
draw: Draw {
is_transparent: true,
..Default::default()
},
..Default::default()
})
// camera