Created
June 13, 2022 15:35
-
-
Save IceSentry/8bcf3d47714327ddc9c7a51e2f5bc137 to your computer and use it in GitHub Desktop.
ShaderType wrapped f32
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
struct WrappedF32 { | |
[[size(16)]] | |
value: f32; | |
}; | |
struct CustomMaterial { | |
data: array<WrappedF32, 4>; | |
}; | |
[[group(1), binding(0)]] | |
var<uniform> material: CustomMaterial; | |
[[stage(fragment)]] | |
fn fragment() -> [[location(0)]] vec4<f32> { | |
return vec4<f32>( | |
material.data[0].value, | |
material.data[1].value, | |
material.data[2].value, | |
material.data[3].value | |
); | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
use bevy::{ | |
ecs::system::{lifetimeless::SRes, SystemParamItem}, | |
pbr::MaterialPipeline, | |
prelude::*, | |
reflect::TypeUuid, | |
render::{ | |
render_asset::{PrepareAssetError, RenderAsset}, | |
render_resource::{ | |
encase, BindGroup, BindGroupDescriptor, BindGroupEntry, BindGroupLayout, | |
BindGroupLayoutDescriptor, BindGroupLayoutEntry, BindingType, Buffer, | |
BufferBindingType, BufferInitDescriptor, BufferUsages, ShaderStages, ShaderType, | |
}, | |
renderer::RenderDevice, | |
}, | |
}; | |
fn main() { | |
App::new() | |
.add_plugins(DefaultPlugins) | |
.add_plugin(MaterialPlugin::<CustomMaterial>::default()) | |
.add_startup_system(setup) | |
.run(); | |
} | |
fn setup( | |
mut commands: Commands, | |
mut meshes: ResMut<Assets<Mesh>>, | |
mut materials: ResMut<Assets<CustomMaterial>>, | |
) { | |
commands.spawn().insert_bundle(MaterialMeshBundle { | |
mesh: meshes.add(Mesh::from(shape::Cube { size: 1.0 })), | |
transform: Transform::from_xyz(0.0, 0.5, 0.0), | |
material: materials.add(CustomMaterial { | |
data: [ | |
// RGBA color | |
// red works, green or blue gives a black color | |
WrappedF32 { value: 1.0 }, | |
WrappedF32 { value: 0.0 }, | |
WrappedF32 { value: 0.0 }, | |
WrappedF32 { value: 1.0 }, | |
], | |
}), | |
..default() | |
}); | |
commands.spawn_bundle(Camera3dBundle { | |
transform: Transform::from_xyz(-2.0, 2.5, 5.0).looking_at(Vec3::ZERO, Vec3::Y), | |
..default() | |
}); | |
} | |
#[derive(Debug, Clone, ShaderType)] | |
struct WrappedF32 { | |
#[size(16)] | |
value: f32, | |
} | |
#[derive(Debug, Clone, TypeUuid, ShaderType)] | |
#[uuid = "f690fdae-d598-45ab-8225-97e2a3f056e0"] | |
pub struct CustomMaterial { | |
data: [WrappedF32; 4], | |
} | |
#[derive(Clone)] | |
pub struct GpuCustomMaterial { | |
_buffer: Buffer, | |
bind_group: BindGroup, | |
} | |
impl RenderAsset for CustomMaterial { | |
type ExtractedAsset = CustomMaterial; | |
type PreparedAsset = GpuCustomMaterial; | |
type Param = (SRes<RenderDevice>, SRes<MaterialPipeline<Self>>); | |
fn extract_asset(&self) -> Self::ExtractedAsset { | |
self.clone() | |
} | |
fn prepare_asset( | |
extracted_asset: Self::ExtractedAsset, | |
(render_device, material_pipeline): &mut SystemParamItem<Self::Param>, | |
) -> Result<Self::PreparedAsset, PrepareAssetError<Self::ExtractedAsset>> { | |
let mut buffer = encase::UniformBuffer::new(Vec::new()); | |
buffer.write(&extracted_asset).unwrap(); | |
info!("{:?}", extracted_asset); | |
let buffer = render_device.create_buffer_with_data(&BufferInitDescriptor { | |
contents: buffer.as_ref(), | |
label: None, | |
usage: BufferUsages::UNIFORM | BufferUsages::COPY_DST, | |
}); | |
let bind_group = render_device.create_bind_group(&BindGroupDescriptor { | |
entries: &[BindGroupEntry { | |
binding: 0, | |
resource: buffer.as_entire_binding(), | |
}], | |
label: None, | |
layout: &material_pipeline.material_layout, | |
}); | |
Ok(GpuCustomMaterial { | |
_buffer: buffer, | |
bind_group, | |
}) | |
} | |
} | |
impl Material for CustomMaterial { | |
fn fragment_shader(asset_server: &AssetServer) -> Option<Handle<Shader>> { | |
Some(asset_server.load("custom_material.wgsl")) | |
} | |
fn bind_group(render_asset: &<Self as RenderAsset>::PreparedAsset) -> &BindGroup { | |
&render_asset.bind_group | |
} | |
fn bind_group_layout(render_device: &RenderDevice) -> BindGroupLayout { | |
render_device.create_bind_group_layout(&BindGroupLayoutDescriptor { | |
entries: &[BindGroupLayoutEntry { | |
binding: 0, | |
visibility: ShaderStages::FRAGMENT, | |
ty: BindingType::Buffer { | |
ty: BufferBindingType::Uniform, | |
has_dynamic_offset: false, | |
min_binding_size: None, | |
}, | |
count: None, | |
}], | |
label: None, | |
}) | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment