Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion .cargo/example-config.toml
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ linker = "clang"
rustflags = [
"-Clink-arg=-fuse-ld=lld",
"-Zshare-generics=yes",
"-Clink-arg=--ld-path=/usr/local/bin/mold",
"-Clink-arg=--ld-path=/usr/local/bin/mold", # you need mold installed.
]

# NOTE: you must install [Mach-O LLD Port](https://lld.llvm.org/MachO/index.html) on mac. you can easily do this by installing llvm which includes lld with the "brew" package manager:
Expand All @@ -29,5 +29,7 @@ rustflags = ["-Zshare-generics=n"]
#[profile.dev]
#debug = 1
#

[build]
rustc-wrapper = "/home/jer/.cargo/bin/sccache"
rustflags = ["-Ctarget-cpu=native"]
28 changes: 9 additions & 19 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

5 changes: 2 additions & 3 deletions Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
[package]
name = "shadplay"
version = "0.0.3"
version = "0.0.4"
resolver = "2"
edition = "2021"
edition = "2024"
authors = ["jeremy webb <[email protected]>"]
license = "MIT"
description = """
Expand All @@ -23,7 +23,6 @@ ui = []
# Bump-a-lots
bevy = { version = "0.16.1", features = ["file_watcher", "jpeg"] }
bevy_egui = { version = "0.35.0" }
bevy_panorbit_camera = "0.27.0"

# usually not bumped with bevy versions
anyhow = "1.0.79"
Expand Down
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -145,7 +145,7 @@ See the [guide](./CONTRIBUTING.md)
- [Alain's blog](https://alain.xyz/blog)
- [GM Shaders](https://gmshaders.com/)
- [WGSL function reference](https://webgpufundamentals.org/webgpu/lessons/webgpu-wgsl-function-reference.html)
- [My blog, sometimes I write about shaders/gp-gpu programming](https://jeremyfwebb.ninja/blog)
- [My blog, sometimes I write about shaders/gp-gpu programming](https://jeremyfwebb.ninja)

---

Expand Down
71,289 changes: 38,078 additions & 33,211 deletions bevy-shader-book.md

Large diffs are not rendered by default.

9 changes: 7 additions & 2 deletions build.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,9 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
.expect("Failed to execute git clone command")
.success()
{
eprintln!("Failed to clone Bevy repository.\nShadplay makes a copy of the bevy codebase here to help generate documentation for you, if you don't want that modify _this_ file `./shadplay/build.rs`");
eprintln!(
"Failed to clone Bevy repository.\nShadplay makes a copy of the bevy codebase here to help generate documentation for you, if you don't want that modify _this_ file `./shadplay/build.rs`"
);

exit(1);
}
Expand Down Expand Up @@ -67,7 +69,10 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
// Check for knight.glb in assets/scenes
let knight_model_path = Path::new("../assets/scenes/knight.glb");
if !knight_model_path.exists() {
dbg!("knight.glb does not exist at {:?}.\nThere's a free non-rigged version available of it here: https://sketchfab.com/3d-models/elysia-knight-d099f11914f445afbe727fe5c3ddd39d or,\nYou can a rigged version purchase here: https://www.artstation.com/marketplace/p/RGmbB/medieval-armor-set-unreal-engine-rigged", knight_model_path);
dbg!(
"knight.glb does not exist at {:?}.\nThere's a free non-rigged version available of it here: https://sketchfab.com/3d-models/elysia-knight-d099f11914f445afbe727fe5c3ddd39d or,\nYou can a rigged version purchase here: https://www.artstation.com/marketplace/p/RGmbB/medieval-armor-set-unreal-engine-rigged",
knight_model_path
);
// Handle the absence of knight.glb as needed (e.g., download, notify, etc.)
} else {
dbg!("knight.glb already exists at {:?}", knight_model_path);
Expand Down
4 changes: 2 additions & 2 deletions examples/might/Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
[package]
name = "pally_aura"
version = "0.1.0"
edition = "2021"
edition = "2024"

[dependencies]
bevy = { version = "0.16.1", features = [
Expand All @@ -10,4 +10,4 @@ bevy = { version = "0.16.1", features = [
"dynamic_linking",
] }

bevy_panorbit_camera = "0.27.0"
shadplay = { path = "../../shadplay" }
17 changes: 7 additions & 10 deletions examples/might/src/main.rs
Original file line number Diff line number Diff line change
@@ -1,18 +1,12 @@
use bevy::{
gltf::Gltf,
log,
pbr::{
CascadeShadowConfigBuilder,
DirectionalLightShadowMap,
// At some stage in the future I'll want to use these!
// ExtendedMaterial, MaterialExtension,
// OpaqueRendererMethod,
},
pbr::{CascadeShadowConfigBuilder, DirectionalLightShadowMap},
prelude::*,
render::render_resource::{AsBindGroup, ShaderRef},
};

use bevy_panorbit_camera::PanOrbitCamera;
use shadplay::camera::{PanOrbitCamera, PanOrbitCameraPlugin};

use std::f32::consts::*;

Expand All @@ -31,12 +25,15 @@ fn main() {
// The environment maps used, are automatically downloadable so the shadplay/build.rs fetches them for you.
let knight_model_path = std::path::Path::new("../assets/scenes/knight.glb");
if !knight_model_path.exists() {
dbg!("knight.glb does not exist at {:?}.\nThere's a free non-rigged version available of it here: https://sketchfab.com/3d-models/elysia-knight-d099f11914f445afbe727fe5c3ddd39d or,\nYou can a rigged version purchase here: https://www.artstation.com/marketplace/p/RGmbB/medieval-armor-set-unreal-engine-rigged", knight_model_path);
dbg!(
"knight.glb does not exist at {:?}.\nThere's a free non-rigged version available of it here: https://sketchfab.com/3d-models/elysia-knight-d099f11914f445afbe727fe5c3ddd39d or,\nYou can a rigged version purchase here: https://www.artstation.com/marketplace/p/RGmbB/medieval-armor-set-unreal-engine-rigged",
knight_model_path
);
}

App::new()
.insert_resource(DirectionalLightShadowMap { size: 4096 })
.add_plugins((DefaultPlugins, bevy_panorbit_camera::PanOrbitCameraPlugin))
.add_plugins((DefaultPlugins, PanOrbitCameraPlugin))
.add_systems(Startup, setup)
.add_systems(Update, (animate_light_direction, quit_listener))
// Our Systems:
Expand Down
129 changes: 129 additions & 0 deletions src/camera.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,129 @@
//NOTE: This is based on the bevy camera tutorial && the panorbit_camera code,
// it's reimplemented here because I want fewer dependencies in the Shadplay project && the delays of waiting for
// plugins everytime bevy updates, (having to depend on transient branches etc while the community plugins catch up)
// is nolonger something I have the time to track.

use bevy::{
input::mouse::{MouseMotion, MouseWheel},
prelude::*,
};

pub struct PanOrbitCameraPlugin;

impl Plugin for PanOrbitCameraPlugin {
fn build(&self, app: &mut App) {
app.add_systems(Update, pan_orbit_camera);
}
}

#[derive(Component)]
pub struct PanOrbitCamera {
pub focus: Vec3,
pub radius: f32,
pub upside_down: bool,
}

impl Default for PanOrbitCamera {
fn default() -> Self {
PanOrbitCamera {
focus: Vec3::ZERO,
radius: 5.0,
upside_down: false,
}
}
}

fn pan_orbit_camera(
windows: Query<&Window>,
mut ev_motion: EventReader<MouseMotion>,
mut ev_scroll: EventReader<MouseWheel>,
input_mouse: Res<ButtonInput<MouseButton>>,
input_keyboard: Res<ButtonInput<KeyCode>>,
mut query: Query<(&mut PanOrbitCamera, &mut Transform)>,
) {
let window = windows.single();
let window = match window {
Ok(w) => w,
Err(_) => return,
};
let mut pan = Vec2::ZERO;
let mut rotation_move = Vec2::ZERO;
let mut scroll = 0.0;
let orbit_button_changed = false;

if input_mouse.pressed(MouseButton::Left) {
for ev in ev_motion.read() {
rotation_move += ev.delta;
}
}

if input_mouse.pressed(MouseButton::Right) {
for ev in ev_motion.read() {
pan += ev.delta;
}
}

for ev in ev_scroll.read() {
scroll += ev.y;
}

if input_keyboard.pressed(KeyCode::ArrowUp) {
pan.y -= 1.0;
}
if input_keyboard.pressed(KeyCode::ArrowDown) {
pan.y += 1.0;
}
if input_keyboard.pressed(KeyCode::ArrowLeft) {
pan.x -= 1.0;
}
if input_keyboard.pressed(KeyCode::ArrowRight) {
pan.x += 1.0;
}

for (mut pan_orbit, mut transform) in query.iter_mut() {
if orbit_button_changed {
// only check for upside down when orbiting started or ended
let up = transform.rotation * Vec3::Y;
pan_orbit.upside_down = up.y <= 0.0;
}

let mut any = false;
if rotation_move.length_squared() > 0.0 {
any = true;
let window_size = Vec2::new(window.width(), window.height());
let delta_x = {
let delta = rotation_move.x / window_size.x * std::f32::consts::PI * 2.0;
if pan_orbit.upside_down { -delta } else { delta }
};
let delta_y = rotation_move.y / window_size.y * std::f32::consts::PI;
let yaw = Quat::from_rotation_y(-delta_x);
let pitch = Quat::from_rotation_x(-delta_y);
transform.rotation = yaw * transform.rotation; // rotate around global y axis
transform.rotation *= pitch; // rotate around local x axis
} else if pan.length_squared() > 0.0 {
any = true;
// make panning distance independent of resolution and FOV,
let window_size = Vec2::new(window.width(), window.height());
let pan_x = pan.x / window_size.x * pan_orbit.radius;
let pan_y = pan.y / window_size.y * pan_orbit.radius;
let right = transform.rotation * Vec3::X * -pan_x;
let up = transform.rotation * Vec3::Y * pan_y;
let translation = right + up;
pan_orbit.focus += translation;
} else if scroll.abs() > 0.0 {
any = true;
pan_orbit.radius -= scroll * pan_orbit.radius * 0.2;
// dont allow zoom to be negative or zero
pan_orbit.radius = f32::max(pan_orbit.radius, 0.05);
}

if any {
// emulating parent/child to make the yaw/y-axis rotation behave like a turntable
// parent = focus, child = camera
// child is offset from parent by radius
let rot_matrix = Mat3::from_quat(transform.rotation);
transform.translation =
pan_orbit.focus + rot_matrix.mul_vec3(Vec3::new(0.0, 0.0, pan_orbit.radius));
}
}
}
17 changes: 9 additions & 8 deletions src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
#![allow(unused_imports, dead_code)]

pub mod camera;
pub mod plugin;
pub mod shader_utils;
pub mod system;
Expand All @@ -12,21 +13,21 @@ pub mod prelude {
pub use crate::utils::toggle_window_passthrough;
pub use crate::{
shader_utils::{
common::ShadplayShaderLibrary,
texture_tooling::{self, swap_2d_tex_from_idx, swap_3d_tex_from_idx, SetNewTexture},
DragNDropShader, MousePos, YourShader, YourShader2D,
common::ShadplayShaderLibrary,
texture_tooling::{self, SetNewTexture, swap_2d_tex_from_idx, swap_3d_tex_from_idx},
},
system::drag_n_drop::{
add_and_set_dropped_file, file_drag_and_drop_listener, override_current_shader,
TexHandleQueue, UserAddedTexture,
TexHandleQueue, UserAddedTexture, add_and_set_dropped_file,
file_drag_and_drop_listener, override_current_shader,
},
system::screenshot::screenshot_and_version_shader_on_spacebar,
ui::colour_picker_plugin::ColourPickerPlugin,
utils::{
self, cam_switch_system, cleanup_2d, cleanup_3d, init_shapes, quit, rotate, setup_2d,
setup_3d, size_quad, switch_level, switch_shape, toggle_rotate, toggle_transparency,
update_mouse_pos, AppState, MonitorsSpecs, Rotating, ShadplayWindowDims, ShapeOptions,
TransparencySet,
self, AppState, MonitorsSpecs, Rotating, ShadplayWindowDims, ShapeOptions,
TransparencySet, cam_switch_system, cleanup_2d, cleanup_3d, init_shapes, quit, rotate,
setup_2d, setup_3d, size_quad, switch_level, switch_shape, toggle_rotate,
toggle_transparency, update_mouse_pos,
},
};
}
2 changes: 0 additions & 2 deletions src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -28,8 +28,6 @@ fn main() {
UserSession::runtime_updater
.run_if(on_event::<WindowResized>)
.run_if(time_passed(1.0)), // Rate limit the speed at which we write to the config file...

//
),
);

Expand Down
2 changes: 1 addition & 1 deletion src/plugin.rs
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
use crate::camera::PanOrbitCameraPlugin;
use bevy::{
input::keyboard::KeyboardInput, log::tracing_subscriber::util::SubscriberInitExt, prelude::*,
sprite::Material2dPlugin, window::WindowResized,
};
use bevy_panorbit_camera::PanOrbitCameraPlugin;

use crate::prelude::*;

Expand Down
Loading