pub mod compositor;
use bevy::asset::embedded_asset;
use bevy::pbr::{ExtendedMaterial, MaterialExtension, MaterialPlugin};
use bevy::prelude::*;
use bevy::render::render_resource::{AsBindGroup, ShaderType};
use bevy::shader::ShaderRef;
pub use compositor::{LowResPixelArtCamera, PixelArtCompositor, PixelArtCompositorPlugin};
pub type PixelArtMaterial = ExtendedMaterial<StandardMaterial, PixelArtExtension>;
pub type HoldoutMaterial = ExtendedMaterial<StandardMaterial, HoldoutExtension>;
#[derive(Asset, AsBindGroup, TypePath, Debug, Clone)]
pub struct PixelArtExtension {
#[uniform(100)]
pub params: PixelArtShaderParams,
}
impl MaterialExtension for PixelArtExtension {
fn fragment_shader() -> ShaderRef {
"embedded://bevy_pixel_art_shader/pixel_art.wgsl".into()
}
fn prepass_fragment_shader() -> ShaderRef {
"embedded://bevy_pixel_art_shader/pixel_art_prepass.wgsl".into()
}
}
#[derive(Asset, AsBindGroup, TypePath, Debug, Clone)]
pub struct HoldoutExtension {}
impl MaterialExtension for HoldoutExtension {
fn fragment_shader() -> ShaderRef {
"embedded://bevy_pixel_art_shader/holdout.wgsl".into()
}
fn prepass_fragment_shader() -> ShaderRef {
"embedded://bevy_pixel_art_shader/holdout_prepass.wgsl".into()
}
}
#[derive(Clone, Debug, ShaderType)]
pub struct PixelArtShaderParams {
pub base_tint: Vec4,
pub toon_bands: f32,
pub toon_softness: f32,
pub toon_shadow_floor: f32,
pub dither_density: f32,
pub palette_count: u32,
pub palette_strength: f32,
pub dither_strength: f32,
pub debug_stage: u32,
pub palette_colors: [Vec4; 64],
}
impl Default for PixelArtShaderParams {
fn default() -> Self {
let (palette, count) = default_pixel_art_palette();
Self {
base_tint: Vec4::new(1.0, 1.0, 1.0, 1.0),
toon_bands: 10.0,
toon_softness: 0.0,
toon_shadow_floor: 0.1,
dither_density: 1.0,
palette_count: count,
palette_strength: 0.25,
dither_strength: 0.3,
debug_stage: 0,
palette_colors: palette,
}
}
}
pub struct PixelArtShaderPlugin;
impl Plugin for PixelArtShaderPlugin {
fn build(&self, app: &mut App) {
embedded_asset!(app, "pixel_art.wgsl");
embedded_asset!(app, "pixel_art_prepass.wgsl");
embedded_asset!(app, "holdout.wgsl");
embedded_asset!(app, "holdout_prepass.wgsl");
app.add_plugins(MaterialPlugin::<PixelArtMaterial>::default());
app.add_plugins(MaterialPlugin::<HoldoutMaterial>::default());
}
}
fn srgb_to_linear_vec4(r: u8, g: u8, b: u8) -> Vec4 {
let c = Color::srgb_u8(r, g, b).to_linear();
Vec4::new(c.red, c.green, c.blue, 1.0)
}
pub fn default_pixel_art_palette() -> ([Vec4; 64], u32) {
let mut colors = [Vec4::ZERO; 64];
colors[0] = srgb_to_linear_vec4(0, 0, 0); colors[1] = srgb_to_linear_vec4(29, 43, 83); colors[2] = srgb_to_linear_vec4(126, 37, 83); colors[3] = srgb_to_linear_vec4(0, 135, 81); colors[4] = srgb_to_linear_vec4(171, 82, 54); colors[5] = srgb_to_linear_vec4(95, 87, 79); colors[6] = srgb_to_linear_vec4(194, 195, 199); colors[7] = srgb_to_linear_vec4(255, 241, 232); colors[8] = srgb_to_linear_vec4(255, 0, 77); colors[9] = srgb_to_linear_vec4(255, 163, 0); colors[10] = srgb_to_linear_vec4(255, 236, 39); colors[11] = srgb_to_linear_vec4(0, 228, 54); colors[12] = srgb_to_linear_vec4(41, 173, 255); colors[13] = srgb_to_linear_vec4(131, 118, 156); colors[14] = srgb_to_linear_vec4(255, 119, 168); colors[15] = srgb_to_linear_vec4(255, 204, 170);
colors[16] = srgb_to_linear_vec4(41, 24, 20); colors[17] = srgb_to_linear_vec4(17, 29, 53); colors[18] = srgb_to_linear_vec4(66, 33, 54); colors[19] = srgb_to_linear_vec4(18, 83, 89); colors[20] = srgb_to_linear_vec4(116, 47, 41); colors[21] = srgb_to_linear_vec4(73, 51, 59); colors[22] = srgb_to_linear_vec4(162, 136, 121); colors[23] = srgb_to_linear_vec4(243, 239, 125); colors[24] = srgb_to_linear_vec4(190, 18, 80); colors[25] = srgb_to_linear_vec4(255, 108, 36); colors[26] = srgb_to_linear_vec4(168, 231, 46); colors[27] = srgb_to_linear_vec4(0, 181, 67); colors[28] = srgb_to_linear_vec4(6, 90, 181); colors[29] = srgb_to_linear_vec4(117, 70, 101); colors[30] = srgb_to_linear_vec4(255, 110, 89); colors[31] = srgb_to_linear_vec4(255, 157, 129);
colors[32] = srgb_to_linear_vec4(34, 32, 52); colors[33] = srgb_to_linear_vec4(69, 40, 60); colors[34] = srgb_to_linear_vec4(102, 57, 49); colors[35] = srgb_to_linear_vec4(143, 86, 59); colors[36] = srgb_to_linear_vec4(223, 113, 38); colors[37] = srgb_to_linear_vec4(217, 160, 102); colors[38] = srgb_to_linear_vec4(238, 195, 154); colors[39] = srgb_to_linear_vec4(251, 242, 54); colors[40] = srgb_to_linear_vec4(153, 229, 80); colors[41] = srgb_to_linear_vec4(106, 190, 48); colors[42] = srgb_to_linear_vec4(55, 148, 110); colors[43] = srgb_to_linear_vec4(75, 105, 47); colors[44] = srgb_to_linear_vec4(82, 75, 36); colors[45] = srgb_to_linear_vec4(50, 60, 57); colors[46] = srgb_to_linear_vec4(63, 63, 116); colors[47] = srgb_to_linear_vec4(48, 96, 130); colors[48] = srgb_to_linear_vec4(91, 110, 225); colors[49] = srgb_to_linear_vec4(99, 155, 255); colors[50] = srgb_to_linear_vec4(95, 205, 228); colors[51] = srgb_to_linear_vec4(203, 219, 252); colors[52] = srgb_to_linear_vec4(155, 173, 183); colors[53] = srgb_to_linear_vec4(132, 126, 135); colors[54] = srgb_to_linear_vec4(105, 106, 106); colors[55] = srgb_to_linear_vec4(89, 86, 82); colors[56] = srgb_to_linear_vec4(118, 66, 138); colors[57] = srgb_to_linear_vec4(172, 50, 50); colors[58] = srgb_to_linear_vec4(217, 87, 99); colors[59] = srgb_to_linear_vec4(215, 123, 186); colors[60] = srgb_to_linear_vec4(143, 151, 74); colors[61] = srgb_to_linear_vec4(138, 111, 48); colors[62] = srgb_to_linear_vec4(75, 47, 55); colors[63] = srgb_to_linear_vec4(45, 45, 45);
(colors, 64)
}