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:
Gray Olson 2020-11-24 02:28:58 -07:00 committed by GitHub
parent 62da29e3c2
commit 353fa96af6
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
10 changed files with 71 additions and 150 deletions

13
Cargo.lock generated
View File

@ -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]]

View File

@ -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"]

View File

@ -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) => {};

View File

@ -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) }
}
}

View File

@ -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"

View File

@ -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

View File

@ -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()
}

View File

@ -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);
}

View File

@ -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

View File

@ -1,6 +1,3 @@
#!/usr/bin/env bash
rustup toolchain install nightly-2020-11-15 --component rust-src rustc-dev llvm-tools-preview
git submodule init
git submodule update