pub mod aurora;
pub mod bloom;
pub mod colorblind;
pub mod crt;
pub mod glow_on_bell;
pub mod scanlines;
pub mod snow;
use engawa::{
BindingKind, Effect, Material, Node, RenderGraph, ResourceId, ResourceKind,
ShaderSource, UniformBinding,
};
use pleme_allvariants_derive::AllVariants;
pub const SCENE: &str = "scene";
pub const OUT: &str = "out";
pub const CATALOG_SAMPLER: &str = "catalog:sampler";
pub(crate) fn post_material(
name: &str,
wgsl: &str,
input: &ResourceId,
params_resource: &str,
) -> Material {
Material {
name: name.to_string(),
shader: ShaderSource::inline(wgsl),
bindings: vec![
UniformBinding {
binding: 0,
kind: BindingKind::Texture,
resource: input.clone(),
},
UniformBinding {
binding: 1,
kind: BindingKind::Sampler,
resource: CATALOG_SAMPLER.into(),
},
UniformBinding {
binding: 2,
kind: BindingKind::Uniform,
resource: params_resource.into(),
},
],
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, AllVariants)]
pub enum CatalogEffect {
Colorblind,
Crt,
Scanlines,
Bloom,
GlowOnBell,
Snow,
Aurora,
}
impl CatalogEffect {
#[must_use]
pub const fn name(self) -> &'static str {
match self {
Self::Colorblind => colorblind::EFFECT_NAME,
Self::Crt => crt::EFFECT_NAME,
Self::Scanlines => scanlines::EFFECT_NAME,
Self::Bloom => bloom::EFFECT_NAME,
Self::GlowOnBell => glow_on_bell::EFFECT_NAME,
Self::Snow => snow::EFFECT_NAME,
Self::Aurora => aurora::EFFECT_NAME,
}
}
#[must_use]
pub const fn priority(self) -> u16 {
match self {
Self::Colorblind => colorblind::PRIORITY,
Self::Crt => crt::PRIORITY,
Self::Scanlines => scanlines::PRIORITY,
Self::Bloom => bloom::PRIORITY,
Self::GlowOnBell => glow_on_bell::PRIORITY,
Self::Snow => snow::PRIORITY,
Self::Aurora => aurora::PRIORITY,
}
}
#[must_use]
pub const fn params_resource(self) -> &'static str {
match self {
Self::Colorblind => colorblind::PARAMS_RESOURCE,
Self::Crt => crt::PARAMS_RESOURCE,
Self::Scanlines => scanlines::PARAMS_RESOURCE,
Self::Bloom => bloom::PARAMS_RESOURCE,
Self::GlowOnBell => glow_on_bell::PARAMS_RESOURCE,
Self::Snow => snow::PARAMS_RESOURCE,
Self::Aurora => aurora::PARAMS_RESOURCE,
}
}
#[must_use]
pub const fn params_size(self) -> usize {
match self {
Self::Colorblind => size_of::<colorblind::ColorblindParams>(),
Self::Crt => size_of::<crt::CrtParams>(),
Self::Scanlines => size_of::<scanlines::ScanlinesParams>(),
Self::Bloom => size_of::<bloom::BloomParams>(),
Self::GlowOnBell => size_of::<glow_on_bell::GlowOnBellParams>(),
Self::Snow => size_of::<snow::SnowParams>(),
Self::Aurora => size_of::<aurora::AuroraParams>(),
}
}
#[must_use]
pub const fn tlisp_path(self) -> &'static str {
match self {
Self::Colorblind => "effects/colorblind.tlisp",
Self::Crt => "effects/crt.tlisp",
Self::Scanlines => "effects/scanlines.tlisp",
Self::Bloom => "effects/bloom.tlisp",
Self::GlowOnBell => "effects/glow_on_bell.tlisp",
Self::Snow => "effects/snow.tlisp",
Self::Aurora => "effects/aurora.tlisp",
}
}
#[must_use]
pub fn default_params_bytes(self) -> Vec<u8> {
match self {
Self::Colorblind => {
bytemuck::bytes_of(&colorblind::ColorblindParams::default()).to_vec()
}
Self::Crt => bytemuck::bytes_of(&crt::CrtParams::default()).to_vec(),
Self::Scanlines => {
bytemuck::bytes_of(&scanlines::ScanlinesParams::default()).to_vec()
}
Self::Bloom => bytemuck::bytes_of(&bloom::BloomParams::default()).to_vec(),
Self::GlowOnBell => {
bytemuck::bytes_of(&glow_on_bell::GlowOnBellParams::default()).to_vec()
}
Self::Snow => bytemuck::bytes_of(&snow::SnowParams::default()).to_vec(),
Self::Aurora => bytemuck::bytes_of(&aurora::AuroraParams::default()).to_vec(),
}
}
#[must_use]
pub fn effect(self) -> Effect {
match self {
Self::Colorblind => colorblind::effect(),
Self::Crt => crt::effect(),
Self::Scanlines => scanlines::effect(),
Self::Bloom => bloom::effect(),
Self::GlowOnBell => glow_on_bell::effect(),
Self::Snow => snow::effect(),
Self::Aurora => aurora::effect(),
}
}
#[must_use]
pub fn lower(self, input: &ResourceId, output: &ResourceId) -> Vec<Node> {
match self {
Self::Colorblind => colorblind::lower(input, output),
Self::Crt => crt::lower(input, output),
Self::Scanlines => scanlines::lower(input, output),
Self::Bloom => bloom::lower(input, output),
Self::GlowOnBell => glow_on_bell::lower(input, output),
Self::Snow => snow::lower(input, output),
Self::Aurora => aurora::lower(input, output),
}
}
#[must_use]
pub fn aux_resources(self) -> Vec<(&'static str, ResourceKind)> {
match self {
Self::Bloom => vec![
(
bloom::BRIGHT_RESOURCE,
ResourceKind::Texture { width: None, height: None },
),
(
bloom::BLUR_H_RESOURCE,
ResourceKind::Texture { width: None, height: None },
),
(
bloom::BLUR_V_RESOURCE,
ResourceKind::Texture { width: None, height: None },
),
],
Self::Colorblind
| Self::Crt
| Self::Scanlines
| Self::GlowOnBell
| Self::Snow
| Self::Aurora => Vec::new(),
}
}
#[must_use]
pub fn graph(self) -> RenderGraph {
let scene: ResourceId = SCENE.into();
let out: ResourceId = OUT.into();
let params_size =
u32::try_from(self.params_size()).expect("catalog params structs are tiny");
let mut g = RenderGraph::default()
.with_resource(SCENE, ResourceKind::Texture { width: None, height: None })
.with_resource(OUT, ResourceKind::Texture { width: None, height: None })
.with_resource(CATALOG_SAMPLER, ResourceKind::Sampler)
.with_resource(
self.params_resource(),
ResourceKind::Uniform { size_bytes: params_size },
)
.with_input(SCENE)
.with_input(CATALOG_SAMPLER)
.with_input(self.params_resource())
.with_output(OUT);
for (id, kind) in self.aux_resources() {
g = g.with_resource(id, kind);
}
for node in self.lower(&scene, &out) {
g = g.with_node(node);
}
g
}
}