use bevy::{
pbr::{MaterialPipeline, MaterialPipelineKey},
prelude::*,
reflect::TypePath,
render::{
mesh::{Indices, Mesh, MeshVertexBufferLayoutRef, PrimitiveTopology},
render_resource::{AsBindGroup, RenderPipelineDescriptor, ShaderDefVal, ShaderRef},
},
};
#[derive(Resource)]
pub struct AtmosphereSkyBoxMaterial(pub Handle<SkyBoxMaterial>);
pub const ATMOSPHERE_SKYBOX_SHADER_HANDLE: Handle<Shader> =
Handle::weak_from_u128(4511926918914205353);
#[derive(AsBindGroup, TypePath, Debug, Clone, Asset)]
#[bind_group_data(SkyBoxMaterialKey)]
pub struct SkyBoxMaterial {
#[texture(0, dimension = "cube")]
#[sampler(1)]
pub sky_texture: Handle<Image>,
#[cfg(feature = "dithering")]
pub dithering: bool,
}
#[derive(Copy, Clone, Hash, Eq, PartialEq)]
pub struct SkyBoxMaterialKey {
#[cfg(feature = "dithering")]
dithering: bool,
}
impl Material for SkyBoxMaterial {
fn fragment_shader() -> ShaderRef {
ATMOSPHERE_SKYBOX_SHADER_HANDLE.into()
}
fn specialize(
_pipeline: &MaterialPipeline<Self>,
descriptor: &mut RenderPipelineDescriptor,
_layout: &MeshVertexBufferLayoutRef,
key: MaterialPipelineKey<Self>,
) -> Result<(), bevy::render::render_resource::SpecializedMeshPipelineError> {
#[cfg(feature = "dithering")]
if key.bind_group_data.dithering {
if let Some(fragment) = &mut descriptor.fragment {
fragment
.shader_defs
.push(ShaderDefVal::Bool(String::from("DITHER"), true));
}
}
Ok(())
}
}
impl From<&SkyBoxMaterial> for SkyBoxMaterialKey {
fn from(material: &SkyBoxMaterial) -> SkyBoxMaterialKey {
SkyBoxMaterialKey {
#[cfg(feature = "dithering")]
dithering: material.dithering,
}
}
}
pub fn mesh(far: f32) -> Mesh {
let size = (far * f32::sqrt(0.5)) - 1.0;
let norm = f32::sqrt(1. / 3.); let (vertices, indices) = (
&[
([size, size, size], [norm, norm, norm]), ([-size, size, size], [-norm, norm, norm]), ([size, -size, size], [norm, -norm, norm]), ([size, size, -size], [norm, norm, -norm]), ([-size, -size, size], [-norm, -norm, norm]), ([size, -size, -size], [norm, -norm, -norm]), ([-size, size, -size], [-norm, norm, -norm]), ([-size, -size, -size], [-norm, -norm, -norm]), ],
&[
0, 5, 2, 5, 0, 3, 6, 4, 7, 4, 6, 1, 0, 6, 3, 6, 0, 1, 2, 7, 4, 7, 2, 5, 1, 2, 4, 2, 1, 0, 3, 7, 5, 7, 3, 6, ],
);
let positions: Vec<_> = vertices.iter().map(|(p, _)| *p).collect();
let normals: Vec<_> = vertices.iter().map(|(_, n)| *n).collect();
Mesh::new(PrimitiveTopology::TriangleList, Default::default())
.with_inserted_attribute(Mesh::ATTRIBUTE_POSITION, positions)
.with_inserted_attribute(Mesh::ATTRIBUTE_NORMAL, normals)
.with_inserted_indices(Indices::U16(indices.to_vec()))
}