Skip to content

Commit

Permalink
Yeet boilerplate
Browse files Browse the repository at this point in the history
  • Loading branch information
thedocruby committed Nov 2, 2023
1 parent d1e45cd commit 9c2bc09
Show file tree
Hide file tree
Showing 13 changed files with 91 additions and 153 deletions.
5 changes: 5 additions & 0 deletions Cargo.lock

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

2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ To learn more about the project, you can join the [**Discord**](https://discord.
- [x] Eliminate custom constants system; use `gravylib_helpers::Constants` instead
- [x] Implement `helpers` as a module expansion of `gravylib`
- [x] Use `lib.rs` as the common module instead of `common.rs`
- [ ] Use macros to reduce boilerplate
- [x] Use macros to reduce boilerplate
- [ ] Upgrade dependency versions (winit, wgpu)
- [ ] Implement hot reloading
- [ ] More examples from shadertoy
Expand Down
2 changes: 1 addition & 1 deletion examples/example.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ fn main() {
// TIP: Try changing the shader program below!
// Options: CIRCLE, RAINBOW, OCEAN

OCEAN
RAINBOW

);

Expand Down
3 changes: 2 additions & 1 deletion examples/shaders/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -12,5 +12,6 @@ crate-type = ["lib", "dylib"]

[dependencies]
spirv-std = { workspace = true }
# use `gravylib` instead when creating your own shader crate
# use `gravylib` instead of these when creating your own shader crate
gravylib_helpers = { path = "../../gravylib_helpers" }
gravylib_macros = { path = "../../gravylib_macros" }
3 changes: 0 additions & 3 deletions examples/shaders/src/circle.rs
Original file line number Diff line number Diff line change
@@ -1,18 +1,15 @@
// Ported to Rust from <https://www.shadertoy.com/view/3ltSW2>

// ** Imports

use crate::*;
// use core::f32::consts::PI; (included in `lib.rs`, imported above)

// ** Helpers

fn circle_sdf(p: Vec2, r: f32) -> f32 {
p.length()-r
}

// ** "Entry point" (effectively)

pub fn circle( constants: &Constants, frag_coord: Vec2) -> Vec4 {
let p: Vec2 = (2.0 * frag_coord
- vec2(constants.width as f32,
Expand Down
152 changes: 22 additions & 130 deletions examples/shaders/src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,19 +1,3 @@
// ** BOILERPLATE **
// This chunk of code is almost entirely boilerplate,
// and will be abstracted in a later version.
// If you are looking for the shader module boilerplate, check further down.
#![cfg_attr(target_arch = "spirv", no_std)]
#![deny(warnings)]
#![allow(dead_code)]
use spirv_std::*;
use glam::*;
// use `gravylib::helpers::*` instead when creating your own shaders
use gravylib_helpers::*;
#[cfg(target_arch = "spirv")]
use spirv_std::num_traits::Float;
// ** BOILERPLATE **


// ** This is a shader crate
// It is a rust crate consisting of a single library,
// which contains a number of shader modules and/or library modules.
Expand All @@ -22,13 +6,31 @@
// All functions and constants defined/imported here
// will be available to every shader module in the crate.
// Below you can find some examples of useful functions and constants.
// To learn how to build your own shader modules,
// see `examples/shaders/src/my_shader.rs`.

// ** Header
#![deny(warnings)] #![no_std]
// Gravylib imports. In your own crate, import `gravylib::*` instead.
use gravylib_helpers::*; use gravylib_macros::*;

// ** Shaders
// Here we declare the shader modules that will be published.

shader!(rainbow);
shader!(circle);
shader!(ocean);
// shader!(my_shader);

// Imports
// ** Common
// Here we declare the common functions and constants
// NOTE: Any public functions/constants defined here can be used by a dependent crate.

// Imports - functions/constants from other crates
use core::f32::consts::PI;

// Constants

const BLOOM: bool = true;
const _BLOOM: bool = true;

// Helpers
pub fn saturate(x: f32) -> f32 {
Expand Down Expand Up @@ -100,114 +102,4 @@ pub fn to_linear(color: Vec4) -> Vec4 {
to_linear_f32(color.z),
color.w,
)
}


// ** WARNING: BOILERPLATE AHEAD
// The code below is almost entirely boilerplate,
// and will be abstracted in a later version.
// For now, if you are building your own shader crate with Gravy,
// it is recommended to copy and paste the generic code below.
// See `test.rs` for an example of how to build a compatible shader program.

/* ~~~~~ FORMAT ~~~~~ //
// Example boilerplate for the shader file `test.rs`:
// This is the shader module. It must be named the same as the shader file, in snake_case
mod test; // Replace "test" with the name of the shader file, in snake_case
// This is the entry point of the shader. It must be named the same as the shader file, in snake_case
#[spirv(fragment)]
pub fn test( // Replace "test" with the name of the shader file, in snake_case
#[spirv(frag_coord)] in_frag_coord: Vec4,
#[spirv(push_constant)] constants: &Constants,
output: &mut Vec4,
) {
let frag_coord = vec2(in_frag_coord.x, in_frag_coord.y);
// Call the shader function from the shader file.
// The name of the function must be the same as the shader file, in snake_case
// The shader function must take the constants and the frag_coord (a Vec2) as arguments, and return a Vec4 RGBA color
*output = test::test(constants, frag_coord); // Replace "test" with the name of the shader file, in snake_case **(both times)**
}
// This is the RawShader struct. It must be named the same as the shader file, in CONSTANT_CASE
#[cfg(not(target_arch = "spirv"))]
#[allow(dead_code)]
pub const TEST: &RawShader = &RawShader { // Replace "TEST" with the name of the shader file, in CONSTANT_CASE
shader_type: ShaderType::Pixel,
crate_name: env!("CARGO_CRATE_NAME"),
entry_point: "test", // Replace "test" with the name of the shader file, in snake_case
};
// Once you have copied and updated the code above,
// you can import your `&RawShader` into `example.rs` and test it out!
// ~~~~~ FORMAT ~~~~~ */

// ** RAINBOW
mod rainbow;

#[spirv(fragment)]
pub fn rainbow(
#[spirv(frag_coord)] in_frag_coord: Vec4,
#[spirv(push_constant)] constants: &Constants,
output: &mut Vec4,
) {
let frag_coord = vec2(in_frag_coord.x, in_frag_coord.y);
*output = rainbow::rainbow(constants, frag_coord);
}

#[cfg(not(target_arch = "spirv"))]
#[allow(dead_code)]
pub const RAINBOW: &RawShader = &RawShader {
shader_type: ShaderType::Pixel,
crate_name: env!("CARGO_CRATE_NAME"),
entry_point: "rainbow",
};
// ** RAINBOW

// ** CIRCLE
mod circle;

#[spirv(fragment)]
pub fn circle(
#[spirv(frag_coord)] in_frag_coord: Vec4,
#[spirv(push_constant)] constants: &Constants,
output: &mut Vec4,
) {
let frag_coord = vec2(in_frag_coord.x, in_frag_coord.y);
*output = circle::circle(constants, frag_coord);
}

#[cfg(not(target_arch = "spirv"))]
#[allow(dead_code)]
pub const CIRCLE: &RawShader = &RawShader {
shader_type: ShaderType::Pixel,
crate_name: env!("CARGO_CRATE_NAME"),
entry_point: "circle",
};
// ** CIRCLE

// ** OCEAN
mod ocean;

#[spirv(fragment)]
pub fn ocean(
#[spirv(frag_coord)] in_frag_coord: Vec4,
#[spirv(push_constant)] constants: &Constants,
output: &mut Vec4,
) {
let frag_coord = vec2(in_frag_coord.x, in_frag_coord.y);
*output = ocean::ocean(constants, frag_coord);
}

#[cfg(not(target_arch = "spirv"))]
#[allow(dead_code)]
pub const OCEAN: &RawShader = &RawShader {
shader_type: ShaderType::Pixel,
crate_name: env!("CARGO_CRATE_NAME"),
entry_point: "ocean",
};

// ** OCEAN
}
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,8 @@
// but some parts (like the entry point signature) are required.
// The boilerplate is moved to the bottom of `lib.rs` for readability;
// this is temporary, and will be abstracted in a later version.
// When you are ready to test your new shader, head over to `lib.rs`
// and copy/paste the boilerplate code according to the instructions there.
// When you are ready to test your new shader,
// head over to `lib.rs` and declare it at the top
// ** Imports
Expand All @@ -32,7 +32,7 @@ pub fn tonemap(col: Vec3) -> Vec3 {
// ** "Entry point" (effectively)
pub fn test(
pub fn my_shader(
constants: &Constants,
frag_coord: Vec2,
) -> Vec4 {
Expand Down
5 changes: 0 additions & 5 deletions examples/shaders/src/ocean.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,20 +2,17 @@
// NOTE: Mouse input has been removed from the original

// ** Imports

use crate::*;
// use core::f32::consts::TAU; (example)

// ** Constants

const DRAG_MULT: f32 = 0.28; // changes how much waves pull on the water
const WATER_DEPTH: f32 = 1.0; // how deep is the water
const CAMERA_HEIGHT: f32 = 1.5; // how high the camera should be
const ITERATIONS_RAYMARCH: u32 = 12; // waves iterations of raymarching
const ITERATIONS_NORMAL: u32 = 40; // waves iterations when calculating normals

// ** Helpers

// Calculates wave value and its derivative,
// for the wave direction, position in space, wave frequency and time
fn wavedx(position: Vec2, direction: Vec2, frequency: f32, timeshift: f32) -> Vec2 {
Expand Down Expand Up @@ -169,8 +166,6 @@ fn aces_tonemap(color: Vec3) -> Vec3 {
}

// ** "Entry point" (effectively)

// Main
pub fn ocean(constants: &Constants, frag_coord: Vec2) -> Vec4 {
// get the ray
let resf = vec2(constants.width as f32, constants.height as f32);
Expand Down
4 changes: 0 additions & 4 deletions examples/shaders/src/rainbow.rs
Original file line number Diff line number Diff line change
@@ -1,16 +1,13 @@
// Adapted from <https://www.shadertoy.com/view/mtyGWy>

// ** Imports

use crate::*;
use core::f32::consts::TAU;

// ** Constants

const ITERATIONS: u32 = 4;

// ** Helpers

pub fn palette(t: f32) -> Vec3 {
let a = vec3(0.5, 0.5, 0.5);
let b = vec3(0.5, 0.5, 0.5);
Expand All @@ -21,7 +18,6 @@ pub fn palette(t: f32) -> Vec3 {
}

// ** "Entry point" (effectively)

pub fn rainbow(
constants: &Constants,
frag_coord: Vec2,
Expand Down
6 changes: 4 additions & 2 deletions gravylib_helpers/src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
#![cfg_attr(target_arch = "spirv", no_std)]
#![deny(warnings)]
use spirv_std::*;
use glam::*;
pub use spirv_std::*;
pub use glam::*;
#[cfg(target_arch = "spirv")]
pub use spirv_std::num_traits::Float;

use bytemuck::{Pod, Zeroable};
#[derive(Copy, Clone, Pod, Zeroable)]
Expand Down
6 changes: 5 additions & 1 deletion gravylib_macros/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -8,4 +8,8 @@ license.workspace = true
repository.workspace = true

[lib]
crate-type = ["proc-macro"]
proc-macro = true

[dependencies]
quote = "1.0"
proc-macro2 = "1.0"
47 changes: 46 additions & 1 deletion gravylib_macros/src/lib.rs
Original file line number Diff line number Diff line change
@@ -1 +1,46 @@
use proc_macro;
use proc_macro::*;
use quote::quote;

#[proc_macro]
pub fn shader(name: TokenStream) -> TokenStream {
let const_case = name.to_string()
.replace([' ', '-'], "_")
.to_uppercase();
let snake_case = const_case.to_lowercase();
let _pascal_case = snake_case
.split('_')
.map(|s| {
let mut c = s.chars();
match c.next() {
None => String::new(),
Some(f) => f.to_uppercase().collect::<String>() + c.as_str(),
}
})
.collect::<String>();
let function = proc_macro2::Ident::new(&snake_case, proc_macro2::Span::call_site());
let module = proc_macro2::Ident::new(&snake_case, proc_macro2::Span::call_site());
let constant = proc_macro2::Ident::new(&const_case, proc_macro2::Span::call_site());
let code = quote! {
mod #module;

#[spirv(fragment)]
pub fn #function(
#[spirv(frag_coord)] in_frag_coord: Vec4,
#[spirv(push_constant)] constants: &Constants,
output: &mut Vec4,
) {
let frag_coord = vec2(in_frag_coord.x, in_frag_coord.y);
*output = #module::#function(constants, frag_coord);
}

#[cfg(not(target_arch = "spirv"))]
#[allow(dead_code)]
pub const #constant: &RawShader = &RawShader {
shader_type: ShaderType::Pixel,
crate_name: env!("CARGO_CRATE_NAME"),
entry_point: stringify!(#function),
};
};

code.into()
}
3 changes: 2 additions & 1 deletion src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,8 @@ mod graphics;
use graphics::run;
pub use gravylib_macros as macros;
pub use gravylib_helpers as helpers;
use helpers::{ ShaderType, RawShader };
pub use helpers::*;
pub use macros::*;

pub struct Shader {
#[allow(dead_code)]
Expand Down

0 comments on commit 9c2bc09

Please sign in to comment.