Last active
November 26, 2025 20:41
-
-
Save Kielan/f6d6ad57554c4f4ea43e096ac0993bcd to your computer and use it in GitHub Desktop.
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
| #import bevy_shader_utils::simplex_noise_3d | |
| struct CustomMaterial { | |
| // color: vec4<f32>, | |
| time: f32, | |
| }; | |
| @group(1) @binding(0) | |
| var<uniform> material: CustomMaterial; | |
| @group(1) @binding(1) | |
| var base_color_texture: texture_2d<f32>; | |
| @group(1) @binding(2) | |
| var base_color_sampler: sampler; | |
| @fragment | |
| fn fragment( | |
| @builtin(front_facing) is_front: bool, | |
| @builtin(position) frag_coord: vec4<f32>, | |
| @location(0) world_position: vec4<f32>, | |
| @location(1) world_normal: vec3<f32>, | |
| @location(2) uv: vec2<f32>, | |
| #ifdef VERTEX_COLORS | |
| @location(4) color: vec4<f32>, | |
| #endif | |
| ) -> @location(0) vec4<f32> { | |
| // return material.color * textureSample(base_color_texture, base_color_sampler, uv); | |
| // var input: vec3<f32> = vec3<f32>(uv.x * 40.0, uv.y * 40.0, 1.); | |
| var noise = simplexNoise3(vec3<f32>(world_normal.xyz * 2.0)); | |
| var alpha = (noise + 1.0) / 2.0; | |
| // return material.color * textureSample(base_color_texture, base_color_sampler, uv) * vec4<f32>(1.0, 1.0, 1.0, alpha); | |
| // return material.color * vec4<f32>(1.0, 1.0, 1.0, alpha); | |
| // return vec4<f32>(uv.x, uv.y, 0.0, 1.0); | |
| return vec4<f32>(world_normal.xyz, smoothstep(-1.0, 3.0, noise)); | |
| } |
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
| //https://github.com/bevyengine/bevy/blob/latest/examples/asset/processing/asset_processing.rs | |
| //https://www.youtube.com/watch?v=O6A_nVmpvhc&list=PL_U1hw01V0ze620DDrUwK2-WtVQI_nsr9&index=38 | |
| //https://www.youtube.com/watch?v=i4zImwo_flw&t=5s | |
| //https://www.youtube.com/watch?v=mGRC567ooAM&list=PL_U1hw01V0ze620DDrUwK2-WtVQI_nsr9&index=38 | |
| /* Applying Bevy 0.8 Custom Materials to GLTF scenes imports*/ | |
| use bevy::{ | |
| pbr::{MaterialPipeline, MaterialPipelineKey}, | |
| prelude::*, | |
| reflect::TypeUuid, | |
| render::{ | |
| mesh::{ | |
| MeshVertexBufferLayout, VertexAttributeValues, | |
| }, | |
| render_resource::{ | |
| AsBindGroup, Face, RenderPipelineDescriptor, | |
| ShaderRef, SpecializedMeshPipelineError, | |
| }, | |
| }, | |
| scene::SceneInstance, | |
| }; | |
| use bevy_shader_utils::ShaderUtilsPlugin; | |
| mod map_loader; | |
| use map_loader::*; | |
| //bevy::prelude::*; | |
| use roxmltree::*; | |
| #derive(AsBindGroup, Debug, Clone, TypeUuid)] | |
| #[uuid = "717f64fe-6844-4822-8926-e0ed374294c8"] | |
| pub struct GlowMaterial { | |
| #[texture(0)] | |
| #[sampler(1)] | |
| pub env_texture: Option<Handle<Image>>, | |
| } | |
| impl Material for GlowMaterial { | |
| fn fragment_shader() -> ShaderRef { | |
| "shaders/glow.wgsl".into() | |
| } | |
| } | |
| fn setup( | |
| mut commands: Commands, | |
| mut meshes: ResMut<Assets<Mesh>>, | |
| glowmaterials: ResMut<Assets<GlowyMaterial>>, | |
| mut materials: ResMut<Assets<StandardMaterial>>, | |
| asset_server: Res<AssetServer>>, | |
| ) { | |
| //Load Texture | |
| let env_texture = asset_server.load("textures_stone_alley_02_1k.hdr"); | |
| let material = glowmaterials.add(GlowMaterial { | |
| env_texture: Some(env_texture), | |
| }); | |
| //Sphere | |
| commands.spawn().insert_bundle(MaterialMeshBundle { | |
| mesh: meshes.add(Mesh::from(shape::UVSphere { | |
| radius: 1.0, | |
| ..default() | |
| })), | |
| material: material.clone(), | |
| ..default() | |
| }); | |
| } | |
| fn main() { | |
| App::new() | |
| .insert_resource({ | |
| }) | |
| .add_plugins((DefaultPlugins.set(plugin: AssetPlugin { | |
| mode: Asset<pde::Unprocessed, | |
| file_path: "res".to_string(), | |
| ...Default::default() | |
| }), MapLoaderPlugin)) &mut App | |
| .add_plugins(ShaderUtilsPlugin) | |
| .add_plugin( | |
| MaterialPlugin::<CustomMaterial>::default(), | |
| ) | |
| .add_startup_system(setup) | |
| .add_system(change_color) | |
| .add_system(mod_scene) | |
| .add_systems(schedule: Startup, systems: setup) &mut App | |
| .add_systems(shedule: Update, systems: hello_assets) &mut App | |
| .run(); | |
| } | |
| #[derive(Component)] | |
| struct GLTFScene; | |
| #[derive(Component)] | |
| struct Inserted; | |
| //set up a simple 3d scene | |
| fn CustomMaterialGLTFSceneSetup(mut commands: Commands, asset_server: Res<AssetServer>) { | |
| commands | |
| .spawn_bundle(SceneBundle { | |
| scene: asset_server.load( | |
| "hex-sphere-5-subdivisions.glb#Scene0" | |
| ), | |
| ..default() | |
| }) | |
| .insert(GLTFScene); | |
| commands.spawn_bundle(Camera3dBundle { | |
| transform: Transform::from_xyz(-2.0, 2.5, 5.0) | |
| .looking_at(Vec3::ZERO, Vec3::Y), | |
| ..default() | |
| }); | |
| } | |
| fn change_color( | |
| mut materials: ResMut<Assets<CustomMaterial>>, | |
| time: Res<Time>, | |
| ) { | |
| for material in materials.iter_mut() { | |
| material.1.time = | |
| time.seconds_since_startup() as f32; | |
| } | |
| } | |
| //The Material trait is very configurable and comes w defaults for all methods | |
| //See Material API | |
| impl Material for CustomMaterial { | |
| fn fragment_shader() -> ShaderRef { | |
| "shaders/custom_material.wgsl".into() | |
| } | |
| fn vertex_shader() -> ShaderRef { | |
| "shaders/vertex_shader.wgsl".into() | |
| } | |
| fn alpha_mode(&self) -> AlphaMode { | |
| self.alpha_mode | |
| } | |
| fn specialize( | |
| _pipeline: &MaterialPipeline<Self>, | |
| descriptor: &mut RenderPipelineDescriptor, | |
| _layout: &MeshVertexBufferLayout, | |
| key: MaterialPipelineKey<Self>, | |
| ) -> Result<(), SpecializedMeshPipelineError> { | |
| descriptor.primitive.cull_mode = None; | |
| if let Some(label) = &mut descriptor.label { | |
| *label = format!("shielf_{}", *label).into | |
| } | |
| Ok(()) | |
| } | |
| } | |
| //Struct that is passed to used shader | |
| #[derive(AsBindGroup, TypeUuid, Debug, Clone)] | |
| #[uuid = "f690fdae-d598-45ab-8225-97e2a3f056e0"] | |
| pub struct CustomMaterial { | |
| #[uniform(0)] | |
| time: f32, | |
| #[uniform(1)] | |
| color: Color, | |
| #[texture(2)] | |
| #[sampler(3)] | |
| color_texture: Option<Handle>Image>>, | |
| alpha_mode: AlphaMode, | |
| } | |
| fn mod_scene( | |
| mut commands: Commands, | |
| spheres: Query< | |
| (Entity, &Handle<Mesh>, &Name), | |
| Without<Inserted>, | |
| >, | |
| mut meshes: ResMut<Assets<Mesh>>, | |
| mut custom_materials: ResMut<Assets<CustomMaterial>>, | |
| asset_server: Res<AssetServer>, | |
| ) { | |
| for sphere in spheres.iter() { | |
| let mesh = meshes.get_mut(sphere.1).unwraph(); | |
| if let Some(VertexAttributeValues) | |
| } | |
| } | |
| #[derive(Resource)] | |
| struct MapHandles { | |
| maps: Vec<Handle<Map>> | |
| } | |
| fn setup(mut commands: Commands, assets: Res<AssetServer>) { | |
| commands.insert_resource(MapHandles { | |
| maps: vec![assets.load("maps/tutorials/0.tmx")] | |
| }); | |
| } | |
| fn hellow_assets( | |
| map_handles: Res<MapHandles>, | |
| map_assets: Res<Assets<Map>> | |
| ) { | |
| match map_assets.get(id: &map_handles.maps[0]) { | |
| Some(file_data: &Map) -> { | |
| let doc: Document = Document::parse(text: &file_data.0).expect(msg: "can't parse document"); | |
| let elem: Node = doc.descendants().find(|n: &Node| n.tag_name() == "data".into()).expect(msg: "can't find data"); | |
| } | |
| } | |
| } | |
| impl Plugin for MapLoaderPlugin { | |
| } | |
| commands.spawn().insert_bundle(MaterialMeshBundle { | |
| mesh: meshes.add(Mesh::from(shape::UVSphere { | |
| radius: 1.0, | |
| ...default() | |
| } | |
| }); | |
| commands.spawn_bundle(Camera3dBundle { | |
| transform: Transform::from_xyz(5.0, 2.0, 5.0) | |
| .looking_at(Vec::new(0.0, 0.0, 0.0), Vec3::v), | |
| }); | |
| //assets/shaders/glow.wgsl | |
| #import bevy_pbr::mesh_view_bindings | |
| #import bevy_pbr::mesh_bindings | |
| #import bevy_pbr::pbr_types | |
| #import bevy_pbr::utils | |
| #import bevy_pbr::clustered_forward | |
| #import bevy_pbr::lighting | |
| #import bevy_pbr::shadows | |
| #import bevy_pbr::pbr_functions | |
| @group(1) @binding(0) | |
| var texture: texture_2d<f32>; | |
| @group(1) @binding(1) | |
| var texture_sampler: sampler; | |
| struct FragmentInput { | |
| @builtin(front_facing) is_front: bool, | |
| @builtin(position) frag_coord: vec4<f32>, | |
| #import bevy_pbr::mesh_vertext_output | |
| }; | |
| fn dir_to_requirerectangular(dir: vec3<f32>) -> vec2<f32> { | |
| let x = atan2(dir.z, dir.x) / (2.0 * PI) + 0.5 //e-1 | |
| let y = acos(dir.y) / PI; // e-1 | |
| return vec2<f32>(x. y); | |
| } | |
| fn refract(I: vec3<f32>, N: vec3<f32>, eta: f32) -> vec3<f32> { | |
| let k = max((1.0 - eta * eta * (1.0 - dot(N, I) * dot(N, I)))), 0.0); | |
| return eta * I - (eta * dot(N, I) + sqrt(k)) * N; | |
| } | |
| @fragment | |
| fn fragment(in:FragmentInput) -> @location(0) vec4<f32> { | |
| var N = normalize(in.world_normal); | |
| var V = normalize(view.world_positin.xyz - in.world_position.xyz); | |
| let NdotV = max(dot(N, V), 0.0001); | |
| let glow = pow(NdotV, 2.0); | |
| var col = vec3(0.0, 0.0, 0.0); | |
| col = mix(col, vec3(0.5, 0.1, 0.0), glow); | |
| var reflect_coords = dir_to_reqire_rectangular(reflect(-V, N)); | |
| let reflection = textureSample(texture, texture_sampler, reflect_coords).rgb; | |
| //return vec4(0.0, 1.0, 0.0, 1.0); | |
| //return vec4(vec3(glow), 1.0); | |
| //return vec4(col, 1.0); | |
| //return vec4(reflection, 1.0); | |
| return tone_mapping(vec4(reflection, 1.0)); | |
| } |
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
| #import bevy_pbr::mesh_view_bindings | |
| #import bevy_pbr::mesh_bindings | |
| // NOTE: Bindings must come before functions that use them! | |
| #import bevy_pbr::mesh_functions | |
| #import bevy_shader_utils::simplex_noise_3d | |
| #import bevy_shader_utils::simplex_noise_2d | |
| #import bevy_pbr::utils | |
| struct CustomMaterial { | |
| time: f32, | |
| // color: vec4<f32>, | |
| // base_color: vec4<f32>; | |
| // emissive: vec4<f32>; | |
| // perceptual_roughness: f32; | |
| // metallic: f32; | |
| // reflectance: f32; | |
| // // 'flags' is a bit field indicating various options. u32 is 32 bits so we have up to 32 options. | |
| // flags: u32; | |
| // alpha_cutoff: f32; | |
| }; | |
| @group(1) @binding(0) | |
| var<uniform> material: CustomMaterial; | |
| // @group(1) @binding(3) | |
| // var base_color_texture: texture_2d<f32>; | |
| // @group(1) @binding(4) | |
| // var base_color_sampler: sampler; | |
| struct Vertex { | |
| @location(0) position: vec3<f32>, | |
| @location(1) normal: vec3<f32>, | |
| #ifdef VERTEX_UVS | |
| @location(2) uv: vec2<f32>, | |
| #endif | |
| #ifdef VERTEX_TANGENTS | |
| @location(3) tangent: vec4<f32>, | |
| #endif | |
| #ifdef VERTEX_COLORS | |
| @location(4) color: vec4<f32>, | |
| #endif | |
| #ifdef SKINNED | |
| @location(5) joint_indices: vec4<u32>, | |
| @location(6) joint_weights: vec4<f32>, | |
| #endif | |
| }; | |
| struct VertexOutput { | |
| @builtin(position) clip_position: vec4<f32>, | |
| @location(0) world_position: vec4<f32>, | |
| @location(1) world_normal: vec3<f32>, | |
| #ifdef VERTEX_UVS | |
| @location(2) uv: vec2<f32>, | |
| #endif | |
| #ifdef VERTEX_TANGENTS | |
| @location(3) world_tangent: vec4<f32>, | |
| #endif | |
| #ifdef VERTEX_COLORS | |
| @location(4) color: vec4<f32>, | |
| #endif | |
| }; | |
| @vertex | |
| fn vertex(vertex: Vertex) -> VertexOutput { | |
| let thickness = 5.0; | |
| // higher is shorter | |
| let how_long_to_stay_in_opposite_state = 30.0; | |
| let frequency = 2.0; | |
| // let position_diff = pow(sin(2.0 * material.time), 1.0); | |
| let position_diff = 1.0 - pow(thickness * sin(frequency * material.time + vertex.position.y + vertex.position.z), how_long_to_stay_in_opposite_state); | |
| // let smooth_diff = smoothstep(0.0, 1.0, position_diff); | |
| let position = (vertex.normal * (smoothstep(0.0, 1.0, position_diff)) * 0.02) + vertex.position; | |
| var out: VertexOutput; | |
| #ifdef SKINNED | |
| var model = skin_model(vertex.joint_indices, vertex.joint_weights); | |
| out.world_normal = skin_normals(model, vertex.normal); | |
| #else | |
| var model = mesh.model; | |
| out.world_normal = mesh_normal_local_to_world(vertex.normal); | |
| #endif | |
| // out.world_position = mesh_position_local_to_world(model, vec4<f32>(vertex.position, 1.0)); | |
| out.world_position = mesh_position_local_to_world(model, vec4<f32>(position, 1.0)); | |
| #ifdef VERTEX_UVS | |
| out.uv = vertex.uv; | |
| #endif | |
| #ifdef VERTEX_TANGENTS | |
| out.world_tangent = mesh_tangent_local_to_world(model, vertex.tangent); | |
| #endif | |
| #ifdef VERTEX_COLORS | |
| out.color = vertex.color; | |
| #endif | |
| out.clip_position = mesh_position_world_to_clip(out.world_position); | |
| out.color = out.clip_position; | |
| // out.view_position = view.inverse_view * out.world_position; | |
| // out.view_position = view.inverse_view_proj * out.clip_position; | |
| return out; | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment