Last active
November 25, 2024 04:16
-
-
Save DGriffin91/c3591937b1364f8a2626ac98db8ae9c2 to your computer and use it in GitHub Desktop.
bs13_custom_material_example
This file contains 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
#include "mesh_type.hlsl" | |
#include "shader_util.hlsl" | |
#include "view_model_type.hlsl" | |
cbuffer ubo : register(b0, space1) | |
{ | |
ViewUniform view; | |
} | |
struct CustomMaterial | |
{ | |
float4 base_color; | |
uint spare1; | |
uint spare2; | |
uint spare3; | |
uint spare4; | |
}; | |
[[vk::binding(1, 0)]] | |
ByteAddressBuffer vertex_buffer : register(t0, space0); | |
[[vk::binding(2, 0)]] | |
StructuredBuffer<uint> index_buffer : register(t0, space0); | |
[[vk::binding(1, 1)]] | |
StructuredBuffer<DynInstanceData> object_instance : register(t0, space1); | |
[[vk::binding(2, 1)]] | |
ByteAddressBuffer materials : register(t0, space1); | |
REFLECT(CustomMaterial) | |
struct VertexOutput | |
{ | |
float4 position : SV_Position; | |
uint instance_index : INSTANCE_INDEX; | |
}; | |
VertexOutput vertex_main(uint vertex_id: SV_VertexID, uint instance_id: SV_InstanceID) | |
{ | |
DynInstanceData instance = object_instance[instance_id]; | |
VertexData vert = vertex_buffer.Load<VertexData>(instance.first_vertex_byte_offset + index_buffer[vertex_id] * sizeof(VertexData)); | |
VertexOutput output; | |
float3 world_position = instance.position_local_to_world(vert.position); | |
output.position = view.position_jittered_world_to_clip(world_position); | |
output.instance_index = instance_id; | |
return output; | |
} | |
float4 fragment_main(VertexOutput input) | |
: SV_TARGET | |
{ | |
uint instance_material_offset = object_instance[input.instance_index].material_index; | |
CustomMaterial material = materials.Load<CustomMaterial>(instance_material_offset * 4); | |
return material.base_color; | |
} |
This file contains 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 std::path::Path; | |
use bevy::{ | |
prelude::*, | |
render::{settings::WgpuSettings, RenderPlugin}, | |
}; | |
use bs13_render::{ | |
dyn_material::DynMaterialArchetypes, | |
dyn_material_pipeline::dyn_layout_from_frag, | |
dyn_material_type::{ | |
DynMaterial, DynMaterialArchetype, DynMaterialHandle, DynMaterialPipelineBitFlag, | |
DynMaterialPipelineKey, | |
}, | |
BS13PluginsSet, | |
}; | |
use bytemuck::{Pod, Zeroable}; | |
use dyn_pod_struct::DynLayout; | |
use glam::vec4; | |
fn main() { | |
App::new() | |
.add_plugins(( | |
DefaultPlugins.set(RenderPlugin { | |
// Disable bevy's default render backend | |
render_creation: WgpuSettings { | |
backends: None, | |
..default() | |
} | |
.into(), | |
..default() | |
}), | |
BS13PluginsSet, | |
)) | |
.add_systems(Startup, setup) | |
.run(); | |
} | |
fn setup( | |
mut commands: Commands, | |
archetypes: Res<DynMaterialArchetypes>, | |
mut meshes: ResMut<Assets<Mesh>>, | |
) { | |
let shader_path = Path::new("assets/shaders/custom_material.hlsl"); | |
// Generate shader material struct layout from shader code | |
let layout = dyn_layout_from_frag(shader_path, "fragment_main", "CustomMaterial"); | |
// Create material archetype asset | |
let archetype_id = archetypes.add(DynMaterialArchetype { | |
layout: layout.clone(), | |
shader: shader_path.to_path_buf(), | |
..default() | |
}); | |
// Create pipeline key from archetype and pipeline options (Things like alpha blend could be specified here) | |
let main_key = DynMaterialPipelineKey::new( | |
DynMaterialPipelineBitFlag::ALPHA_BLEND, | |
archetype_id, | |
archetypes.clone(), | |
); | |
// Create material data | |
let material_data = CustomMaterial { | |
base_color: vec4(1.0, 0.0, 1.0, 1.0), | |
..default() | |
}; | |
// Create material instance that includes this material data, key and layout. | |
// Layout is included here directly so the archetype asset doesn't need to be accessed to reflect the material data. | |
let dyn_material = DynMaterial::default_prepass(&material_data, main_key, layout); | |
// Get handle for material asset. Using an entity for the asset here because of performance issues with using | |
// the asset system directly with large quantities of materials. | |
let material_h = DynMaterialHandle(commands.spawn(dyn_material).id()); | |
// Spawn an entity with a Bevy mesh, SpatialBundle, and the DynMaterialHandle. | |
commands.spawn(( | |
meshes.add(Cuboid::new(1.0, 1.0, 1.0)), | |
SpatialBundle { | |
transform: Transform::from_xyz(0.0, 0.5, 0.0), | |
..default() | |
}, | |
material_h, | |
)); | |
// Spawn a camera | |
commands.spawn((Camera3dBundle { | |
transform: Transform::from_xyz(-2.5, 4.5, 9.0).looking_at(Vec3::ZERO, Vec3::Y), | |
..default() | |
},)); | |
} | |
// The DynLayout derive here will allow us to reflect the layout of the fields and generate a DynLayout. | |
// A DynLayout can also be generated by reflecting spirv shader code. | |
#[repr(C)] | |
#[derive(DynLayout, Copy, Clone, Default, Pod, Zeroable, Debug)] | |
pub struct CustomMaterial { | |
base_color: Vec4, | |
spare1: u32, | |
spare2: u32, | |
spare3: u32, | |
spare4: u32, | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment