This commit is contained in:
Matthew Deville 2025-08-31 12:48:46 +02:00
parent b037f9150b
commit 965aa40858
2 changed files with 33 additions and 26 deletions

View file

@ -1,30 +1,18 @@
// Simple UV gradient shader (vertex + fragment)
#import bevy_sprite::mesh2d_vertex_output::VertexOutput
struct VertexInput {
@location(0) position: vec3<f32>,
@location(1) uv: vec2<f32>,
}
struct VertexOutput {
@builtin(position) clip_position: vec4<f32>,
@location(0) uv: vec2<f32>,
}
@vertex
fn vertex(in: VertexInput) -> VertexOutput {
var out: VertexOutput;
// assume incoming positions are in clip-space (vec3 with z, or model-transformed)
out.clip_position = vec4<f32>(in.position, 1.0);
out.uv = in.uv;
return out;
}
@group(2) @binding(0) var<uniform> u_time: f32;
@group(2) @binding(1) var<uniform> u_resolution: vec2<f32>;
@fragment
fn fragment(in: VertexOutput) -> @location(0) vec4<f32> {
fn fragment(mesh: VertexOutput) -> @location(0) vec4<f32> {
// very simple vertical gradient between two colors
let bottom = vec3<f32>(1.0, 0.8, 0.2); // warm
let top = vec3<f32>(0.2, 0.6, 1.0); // cool
let color = mix(bottom, top, in.uv.y);
// use time to subtly shift the gradient
let t = u_time;
let shift = 0.2 * sin(t);
let color = mix(bottom, top, mesh.uv.y + shift);
return vec4<f32>(color, 1.0);
}

View file

@ -21,6 +21,7 @@ fn main() {
.add_systems(
Update,
(
update_material_time,
resize_fullscreen_quad,
exit_app.run_if(input_just_pressed(KeyCode::Escape)),
toggle_fullscreen.run_if(input_just_pressed(KeyCode::F11)),
@ -31,24 +32,30 @@ fn main() {
/// set up a simple 2D-screen-like surface
fn setup(
mut commands: Commands,
mut meshes: ResMut<Assets<Mesh>>,
mut materials: ResMut<Assets<CustomMaterial>>,
mut primary_window: Single<&mut Window, With<PrimaryWindow>>,
mut commands: Commands,
) {
primary_window.decorations = false;
commands.spawn(Camera2d);
// quad that fills the whole window
let size = Vec2::new(
let screen_size = Vec2::new(
primary_window.resolution.width(),
primary_window.resolution.height(),
);
// create material with initial time = 0.0
let material_handle = materials.add(CustomMaterial {
time: 0.0,
resolution: screen_size,
});
commands.spawn((
Mesh2d(meshes.add(Rectangle::default())),
MeshMaterial2d(materials.add(CustomMaterial {})),
Transform::from_scale(Vec3::new(size.x, size.y, 1.0)),
MeshMaterial2d(material_handle),
Transform::from_scale(Vec3::new(screen_size.x, screen_size.y, 1.0)),
FullscreenQuad,
));
}
@ -83,7 +90,19 @@ fn toggle_fullscreen(mut primary_window: Single<&mut Window, With<PrimaryWindow>
// This is the struct that will be passed to your shader
#[derive(Asset, TypePath, AsBindGroup, Clone)]
struct CustomMaterial {}
struct CustomMaterial {
#[uniform(0)]
time: f32,
#[uniform(1)]
resolution: Vec2,
}
fn update_material_time(mut materials: ResMut<Assets<CustomMaterial>>, time: Res<Time>) {
let t = time.elapsed_secs();
for (_handle, material) in materials.iter_mut() {
material.time = t;
}
}
/// The Material2d trait is very configurable, but comes with sensible defaults for all methods.
/// You only need to implement functions for features that need non-default behavior. See the Material2d api docs for details!