mirror of
https://github.com/EmbarkStudios/rust-gpu.git
synced 2024-11-21 22:34:34 +00:00
Rename pow to powf, remove saturate from MathExt, and update to latest glam (#248)
* remove saturate from spirv_std MathExt and rename pow to powf * update to latest glam * update glam again and add `std` feature to `spirv-std` to support cpu runner * re-remove spirv-tools-sys submodule * fixup! Merge branch 'main' into powf-saturate * Use libm instead of MathExt * Fix lint for unused import when compiling with std Co-authored-by: khyperia <github@khyperia.com>
This commit is contained in:
parent
62da29e3c2
commit
353fa96af6
13
Cargo.lock
generated
13
Cargo.lock
generated
@ -983,9 +983,10 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "glam"
|
||||
version = "0.10.0"
|
||||
source = "git+https://github.com/EmbarkStudios/glam-rs?rev=c9561e4dfd55fa5a9d6838cae3c9e90c8edafaf9#c9561e4dfd55fa5a9d6838cae3c9e90c8edafaf9"
|
||||
version = "0.10.2"
|
||||
source = "git+https://github.com/EmbarkStudios/glam-rs?rev=ea8fe2766ca27f481656d3507cc129537e262182#ea8fe2766ca27f481656d3507cc129537e262182"
|
||||
dependencies = [
|
||||
"num-traits",
|
||||
"version_check",
|
||||
]
|
||||
|
||||
@ -1124,6 +1125,12 @@ dependencies = [
|
||||
"winapi 0.3.9",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "libm"
|
||||
version = "0.2.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c7d73b3f436185384286bd8098d17ec07c9a7d2388a6599f824d8502b529702a"
|
||||
|
||||
[[package]]
|
||||
name = "lock_api"
|
||||
version = "0.4.2"
|
||||
@ -1424,6 +1431,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9a64b1ec5cda2586e284722486d802acf1f7dbdc623e2bfc57e65ca1cd099290"
|
||||
dependencies = [
|
||||
"autocfg 1.0.1",
|
||||
"libm",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@ -2182,6 +2190,7 @@ name = "spirv-std"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"glam",
|
||||
"num-traits",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -8,4 +8,9 @@ repository = "https://github.com/EmbarkStudios/rust-gpu"
|
||||
|
||||
[dependencies]
|
||||
# https://github.com/bitshifter/glam-rs/pull/85
|
||||
glam = { git = "https://github.com/EmbarkStudios/glam-rs", rev = "c9561e4dfd55fa5a9d6838cae3c9e90c8edafaf9" }
|
||||
glam = { git = "https://github.com/EmbarkStudios/glam-rs", rev = "ea8fe2766ca27f481656d3507cc129537e262182", default-features = false, features = ["libm"] }
|
||||
num-traits = { version = "0.2.14", default-features = false }
|
||||
|
||||
[features]
|
||||
default = []
|
||||
std = ["glam/std"]
|
||||
|
@ -37,10 +37,8 @@
|
||||
nonstandard_style
|
||||
)]
|
||||
|
||||
mod math_ext;
|
||||
pub use math_ext::MathExt;
|
||||
|
||||
pub use glam;
|
||||
pub use num_traits;
|
||||
|
||||
macro_rules! pointer_addrspace_write {
|
||||
(false) => {};
|
||||
|
@ -1,95 +0,0 @@
|
||||
pub trait MathExt {
|
||||
fn pow(self, factor: Self) -> Self;
|
||||
fn sqrt(self) -> Self;
|
||||
fn log2(self) -> Self;
|
||||
fn abs(self) -> Self;
|
||||
fn cos(self) -> Self;
|
||||
fn sin(self) -> Self;
|
||||
fn sin_cos(self) -> (f32, f32);
|
||||
fn round(self) -> Self;
|
||||
fn floor(self) -> Self;
|
||||
fn ceil(self) -> Self;
|
||||
fn exp(self) -> Self;
|
||||
fn saturate(self) -> Self;
|
||||
fn trunc(self) -> Self;
|
||||
fn fract(self) -> Self;
|
||||
|
||||
fn signum(self) -> Self;
|
||||
fn copysign(self, sign: Self) -> Self;
|
||||
|
||||
// TODO: implement but need new intrinsic in core?
|
||||
//fn tan(self) -> Self;
|
||||
}
|
||||
|
||||
impl MathExt for f32 {
|
||||
fn pow(self, factor: f32) -> f32 {
|
||||
unsafe { core::intrinsics::powf32(self, factor) }
|
||||
}
|
||||
|
||||
fn sqrt(self) -> f32 {
|
||||
unsafe { core::intrinsics::sqrtf32(self) }
|
||||
}
|
||||
|
||||
fn log2(self) -> f32 {
|
||||
unsafe { core::intrinsics::log2f32(self) }
|
||||
}
|
||||
|
||||
fn abs(self) -> f32 {
|
||||
unsafe { core::intrinsics::fabsf32(self) }
|
||||
}
|
||||
|
||||
fn cos(self) -> f32 {
|
||||
unsafe { core::intrinsics::cosf32(self) }
|
||||
}
|
||||
|
||||
fn sin(self) -> f32 {
|
||||
unsafe { core::intrinsics::sinf32(self) }
|
||||
}
|
||||
|
||||
// TODO: implement but need new intrinsic in core?
|
||||
//fn tan(self) -> f32 {
|
||||
|
||||
fn sin_cos(self) -> (f32, f32) {
|
||||
(self.sin(), self.cos())
|
||||
}
|
||||
|
||||
fn round(self) -> f32 {
|
||||
unsafe { core::intrinsics::roundf32(self) }
|
||||
}
|
||||
|
||||
fn floor(self) -> f32 {
|
||||
unsafe { core::intrinsics::floorf32(self) }
|
||||
}
|
||||
|
||||
fn ceil(self) -> f32 {
|
||||
unsafe { core::intrinsics::ceilf32(self) }
|
||||
}
|
||||
|
||||
fn exp(self) -> f32 {
|
||||
unsafe { core::intrinsics::expf32(self) }
|
||||
}
|
||||
|
||||
fn saturate(self) -> f32 {
|
||||
self.max(0.0).min(1.0)
|
||||
}
|
||||
|
||||
fn trunc(self) -> f32 {
|
||||
unsafe { core::intrinsics::truncf32(self) }
|
||||
}
|
||||
|
||||
fn fract(self) -> f32 {
|
||||
self - self.trunc()
|
||||
}
|
||||
|
||||
fn signum(self) -> f32 {
|
||||
if self.is_nan() {
|
||||
Self::NAN
|
||||
} else {
|
||||
1.0_f32.copysign(self)
|
||||
}
|
||||
}
|
||||
|
||||
fn copysign(self, sign: f32) -> f32 {
|
||||
unsafe { core::intrinsics::copysignf32(self, sign) }
|
||||
}
|
||||
}
|
@ -11,7 +11,7 @@ minifb = "0.19.1"
|
||||
# bring in the shader as natively compiled code
|
||||
shared = { path = "../../shaders/shared" }
|
||||
sky-shader = { path = "../../shaders/sky-shader" }
|
||||
spirv-std = { path = "../../../crates/spirv-std" }
|
||||
spirv-std = { path = "../../../crates/spirv-std", features = ["std"] }
|
||||
|
||||
# for parallelism, not really needed though
|
||||
rayon = "1.5"
|
||||
|
@ -18,10 +18,10 @@ fn srgb_oetf(x: f32) -> f32 {
|
||||
fn color_u32_from_vec4(v: Vec4) -> u32 {
|
||||
let convert = |f: f32| -> u32 { (f.min(1.0).max(0.0) * 255.0).round() as u32 };
|
||||
|
||||
convert(srgb_oetf(v.z()))
|
||||
| convert(srgb_oetf(v.y())) << 8
|
||||
| convert(srgb_oetf(v.x())) << 16
|
||||
| convert(v.w()) << 24
|
||||
convert(srgb_oetf(v.z))
|
||||
| convert(srgb_oetf(v.y)) << 8
|
||||
| convert(srgb_oetf(v.x)) << 16
|
||||
| convert(v.w) << 24
|
||||
}
|
||||
|
||||
fn main() {
|
||||
@ -55,8 +55,7 @@ fn main() {
|
||||
-((i / WIDTH) as f32 / HEIGHT as f32 * 2.0 - 1.0),
|
||||
);
|
||||
|
||||
let frag_coord = (vec2(screen_pos.x(), -screen_pos.y()) + Vec2::one())
|
||||
/ Vec2::splat(2.0)
|
||||
let frag_coord = (vec2(screen_pos.x, -screen_pos.y) + Vec2::one()) / Vec2::splat(2.0)
|
||||
* vec2(WIDTH as f32, HEIGHT as f32);
|
||||
|
||||
// evaluate the fragment shader for the specific pixel
|
||||
|
@ -6,8 +6,12 @@
|
||||
#![register_attr(spirv)]
|
||||
|
||||
use core::f32::consts::PI;
|
||||
use spirv_std::glam::{Vec2, Vec3};
|
||||
use spirv_std::MathExt;
|
||||
use spirv_std::glam::Vec3;
|
||||
|
||||
// Note: This cfg is incorrect on its surface, it really should be "are we compiling with std", but
|
||||
// we tie #[no_std] above to the same condition, so it's fine.
|
||||
#[cfg(target_arch = "spirv")]
|
||||
use spirv_std::num_traits::Float;
|
||||
|
||||
#[derive(Copy, Clone)]
|
||||
pub struct ShaderConstants {
|
||||
@ -16,14 +20,16 @@ pub struct ShaderConstants {
|
||||
pub time: f32,
|
||||
}
|
||||
|
||||
// TODO: add this to glam? Rust std has it on f32/f64
|
||||
pub fn pow(v: Vec3, power: f32) -> Vec3 {
|
||||
Vec3::new(v.x().pow(power), v.y().pow(power), v.z().pow(power))
|
||||
pub fn saturate(x: f32) -> f32 {
|
||||
x.max(0.0).min(1.0)
|
||||
}
|
||||
|
||||
pub fn pow(v: Vec3, power: f32) -> Vec3 {
|
||||
Vec3::new(v.x.powf(power), v.y.powf(power), v.z.powf(power))
|
||||
}
|
||||
|
||||
// TODO: add this to glam? Rust std has it on f32/f64
|
||||
pub fn exp(v: Vec3) -> Vec3 {
|
||||
Vec3::new(v.x().exp(), v.y().exp(), v.z().exp())
|
||||
Vec3::new(v.x.exp(), v.y.exp(), v.z.exp())
|
||||
}
|
||||
|
||||
/// Based on: https://seblagarde.wordpress.com/2014/12/01/inverse-trigonometric-functions-gpu-optimization-for-amd-gcn-architecture/
|
||||
@ -41,25 +47,7 @@ pub fn acos_approx(v: f32) -> f32 {
|
||||
|
||||
pub fn smoothstep(edge0: f32, edge1: f32, x: f32) -> f32 {
|
||||
// Scale, bias and saturate x to 0..1 range
|
||||
let x = ((x - edge0) / (edge1 - edge0)).saturate();
|
||||
let x = saturate((x - edge0) / (edge1 - edge0));
|
||||
// Evaluate polynomial
|
||||
x * x * (3.0 - 2.0 * x)
|
||||
}
|
||||
|
||||
pub fn tonemap(col: Vec3) -> Vec3 {
|
||||
// see https://www.desmos.com/calculator/0eo9pzo1at
|
||||
const A: f32 = 2.35;
|
||||
const B: f32 = 2.8826666;
|
||||
const C: f32 = 789.7459;
|
||||
const D: f32 = 0.935;
|
||||
|
||||
let z = pow(col, A);
|
||||
z / (pow(z, D) * B + Vec3::splat(C))
|
||||
}
|
||||
|
||||
pub fn get_ray_dir(uv: Vec2, pos: Vec3, look_at_pos: Vec3) -> Vec3 {
|
||||
let forward = (look_at_pos - pos).normalize();
|
||||
let right = Vec3::new(0.0, 1.0, 0.0).cross(forward).normalize();
|
||||
let up = forward.cross(right);
|
||||
(forward + uv.x() * right + uv.y() * up).normalize()
|
||||
}
|
||||
|
@ -8,7 +8,12 @@
|
||||
use core::f32::consts::PI;
|
||||
use shared::*;
|
||||
use spirv_std::glam::{const_vec3, Vec2, Vec3, Vec4};
|
||||
use spirv_std::{Input, MathExt, Output, PushConstant};
|
||||
use spirv_std::{Input, Output, PushConstant};
|
||||
|
||||
// Note: This cfg is incorrect on its surface, it really should be "are we compiling with std", but
|
||||
// we tie #[no_std] above to the same condition, so it's fine.
|
||||
#[cfg(target_arch = "spirv")]
|
||||
use spirv_std::num_traits::Float;
|
||||
|
||||
const DEPOLARIZATION_FACTOR: f32 = 0.035;
|
||||
const MIE_COEFFICIENT: f32 = 0.005;
|
||||
@ -26,9 +31,20 @@ const SUN_INTENSITY_FACTOR: f32 = 1000.0;
|
||||
const SUN_INTENSITY_FALLOFF_STEEPNESS: f32 = 1.5;
|
||||
const TURBIDITY: f32 = 2.0;
|
||||
|
||||
pub fn tonemap(col: Vec3) -> Vec3 {
|
||||
// see https://www.desmos.com/calculator/0eo9pzo1at
|
||||
const A: f32 = 2.35;
|
||||
const B: f32 = 2.8826666;
|
||||
const C: f32 = 789.7459;
|
||||
const D: f32 = 0.935;
|
||||
|
||||
let z = pow(col, A);
|
||||
z / (pow(z, D) * B + Vec3::splat(C))
|
||||
}
|
||||
|
||||
fn total_rayleigh(lambda: Vec3) -> Vec3 {
|
||||
(8.0 * PI.pow(3.0)
|
||||
* (REFRACTIVE_INDEX.pow(2.0) - 1.0).pow(2.0)
|
||||
(8.0 * PI.powf(3.0)
|
||||
* (REFRACTIVE_INDEX.powf(2.0) - 1.0).powf(2.0)
|
||||
* (6.0 + 3.0 * DEPOLARIZATION_FACTOR))
|
||||
/ (3.0 * NUM_MOLECULES * pow(lambda, 4.0) * (6.0 - 7.0 * DEPOLARIZATION_FACTOR))
|
||||
}
|
||||
@ -39,11 +55,11 @@ fn total_mie(lambda: Vec3, k: Vec3, t: f32) -> Vec3 {
|
||||
}
|
||||
|
||||
fn rayleigh_phase(cos_theta: f32) -> f32 {
|
||||
(3.0 / (16.0 * PI)) * (1.0 + cos_theta.pow(2.0))
|
||||
(3.0 / (16.0 * PI)) * (1.0 + cos_theta.powf(2.0))
|
||||
}
|
||||
|
||||
fn henyey_greenstein_phase(cos_theta: f32, g: f32) -> f32 {
|
||||
(1.0 / (4.0 * PI)) * ((1.0 - g.pow(2.0)) / (1.0 - 2.0 * g * cos_theta + g.pow(2.0)).pow(1.5))
|
||||
(1.0 / (4.0 * PI)) * ((1.0 - g.powf(2.0)) / (1.0 - 2.0 * g * cos_theta + g.powf(2.0)).powf(1.5))
|
||||
}
|
||||
|
||||
fn sun_intensity(zenith_angle_cos: f32) -> f32 {
|
||||
@ -58,7 +74,7 @@ fn sun_intensity(zenith_angle_cos: f32) -> f32 {
|
||||
|
||||
fn sky(dir: Vec3, sun_position: Vec3) -> Vec3 {
|
||||
let up = Vec3::new(0.0, 1.0, 0.0);
|
||||
let sunfade = 1.0 - (1.0 - (sun_position.y() / 450000.0).exp()).saturate();
|
||||
let sunfade = 1.0 - (1.0 - saturate(sun_position.y / 450000.0).exp());
|
||||
let rayleigh_coefficient = RAYLEIGH - (1.0 * (1.0 - sunfade));
|
||||
let beta_r = total_rayleigh(PRIMARIES) * rayleigh_coefficient;
|
||||
|
||||
@ -67,7 +83,7 @@ fn sky(dir: Vec3, sun_position: Vec3) -> Vec3 {
|
||||
|
||||
// Optical length, cutoff angle at 90 to avoid singularity
|
||||
let zenith_angle = acos_approx(up.dot(dir).max(0.0));
|
||||
let denom = (zenith_angle).cos() + 0.15 * (93.885 - ((zenith_angle * 180.0) / PI)).pow(-1.253);
|
||||
let denom = (zenith_angle).cos() + 0.15 * (93.885 - ((zenith_angle * 180.0) / PI)).powf(-1.253);
|
||||
|
||||
let s_r = RAYLEIGH_ZENITH_LENGTH / denom;
|
||||
let s_m = MIE_ZENITH_LENGTH / denom;
|
||||
@ -92,7 +108,7 @@ fn sky(dir: Vec3, sun_position: Vec3) -> Vec3 {
|
||||
sun_e * ((beta_r_theta + beta_m_theta) / (beta_r + beta_m)) * fex,
|
||||
0.5,
|
||||
),
|
||||
((1.0 - up.dot(sun_direction)).pow(5.0)).saturate(),
|
||||
saturate((1.0 - up.dot(sun_direction)).powf(5.0)),
|
||||
);
|
||||
|
||||
// Composition + solar disc
|
||||
@ -108,10 +124,17 @@ fn sky(dir: Vec3, sun_position: Vec3) -> Vec3 {
|
||||
lin + l0
|
||||
}
|
||||
|
||||
fn get_ray_dir(uv: Vec2, pos: Vec3, look_at_pos: Vec3) -> Vec3 {
|
||||
let forward = (look_at_pos - pos).normalize();
|
||||
let right = Vec3::new(0.0, 1.0, 0.0).cross(forward).normalize();
|
||||
let up = forward.cross(right);
|
||||
(forward + uv.x * right + uv.y * up).normalize()
|
||||
}
|
||||
|
||||
pub fn fs(constants: &ShaderConstants, frag_coord: Vec2) -> Vec4 {
|
||||
let mut uv = (frag_coord - 0.5 * Vec2::new(constants.width as f32, constants.height as f32))
|
||||
/ constants.height as f32;
|
||||
uv.set_y(-uv.y());
|
||||
uv.y = -uv.y;
|
||||
|
||||
// hard-code information because we can't bind buffers at the moment
|
||||
let eye_pos = Vec3::new(0.0, 0.0997, 0.2);
|
||||
@ -136,7 +159,7 @@ pub fn main_fs(
|
||||
) {
|
||||
let constants = constants.load();
|
||||
|
||||
let frag_coord = Vec2::new(in_frag_coord.load().x(), in_frag_coord.load().y());
|
||||
let frag_coord = Vec2::new(in_frag_coord.load().x, in_frag_coord.load().y);
|
||||
let color = fs(&constants, frag_coord);
|
||||
output.store(color);
|
||||
}
|
||||
|
@ -1,6 +1,3 @@
|
||||
setlocal
|
||||
|
||||
rustup toolchain install nightly-2020-11-15 --component rust-src rustc-dev llvm-tools-preview
|
||||
|
||||
git submodule init
|
||||
git submodule update
|
||||
|
Loading…
Reference in New Issue
Block a user