Files

79 lines
3.0 KiB
Rust

//! Original GPU translation of the L1 opaque surface and fixed studio reference.
//! Appended to the existing viewport shader so camera/output conventions are shared.
pub const VERTEX_SIZE: usize = 48;
pub const SOURCE: &str = r#"
struct PbrOut {
@builtin(position) pos: vec4<f32>,
@location(0) n: vec3<f32>,
@location(1) base: vec3<f32>,
@location(2) wp: vec3<f32>,
@location(3) parameters: vec3<f32>,
};
fn pbr_unit(v: vec3<f32>) -> vec3<f32> {
let scale = max(max(abs(v.x), abs(v.y)), abs(v.z));
if (scale == 0.0) { return vec3<f32>(0.0, 0.0, 1.0); }
let s = v / scale;
return s / length(s);
}
fn pbr_encode(c: vec3<f32>) -> vec3<f32> {
return select(c * 12.92, 1.055 * pow(c, vec3<f32>(1.0 / 2.4)) - vec3<f32>(0.055), c > vec3<f32>(0.0031308));
}
@vertex
fn vs_pbr(@location(0) p: vec3<f32>, @location(1) n: vec3<f32>, @location(2) base: vec3<f32>, @location(3) parameters: vec3<f32>) -> PbrOut {
var o: PbrOut;
o.pos = u.vp * vec4<f32>(p, 1.0);
o.n = n;
o.base = base;
o.wp = p;
o.parameters = parameters;
return o;
}
fn pbr_fresnel(f0: vec3<f32>, cosine: f32) -> vec3<f32> {
let t = 1.0 - cosine;
return f0 + (vec3<f32>(1.0) - f0) * (t * t * t * t * t);
}
fn pbr_brdf(base: vec3<f32>, parameters: vec3<f32>, n: vec3<f32>, v: vec3<f32>, l: vec3<f32>) -> vec3<f32> {
let nv = clamp(dot(n, v), -1.0, 1.0);
let nl = clamp(dot(n, l), -1.0, 1.0);
if (nv <= 0.0 || nl <= 0.0) { return vec3<f32>(0.0); }
let h = pbr_unit(v + l);
let nh = clamp(dot(n, h), 0.0, 1.0);
let vh = clamp(dot(v, h), 0.0, 1.0);
let alpha = parameters.y * parameters.y;
let a2 = alpha * alpha;
let denominator = (1.0 - nh * nh) + nh * nh * a2;
let distribution = a2 / (3.141592653589793 * denominator * denominator);
let gv = 2.0 / (nv + sqrt(a2 + (1.0 - a2) * nv * nv));
let gl = 2.0 / (nl + sqrt(a2 + (1.0 - a2) * nl * nl));
let ratio = (parameters.z - 1.0) / (parameters.z + 1.0);
let f0 = mix(vec3<f32>(ratio * ratio), base, parameters.x);
let specular = pbr_fresnel(f0, vh) * (distribution * 0.25 * gv * gl);
let diffuse = base * ((1.0 - parameters.x) / 3.141592653589793);
return specular + (vec3<f32>(1.0) - pbr_fresnel(f0, nv)) * (vec3<f32>(1.0) - pbr_fresnel(f0, nl)) * diffuse;
}
@fragment
fn fs_pbr(i: PbrOut) -> @location(0) vec4<f32> {
let n = pbr_unit(i.n);
var view = u.back.xyz;
if (u.eye.w > 0.5) { view = u.eye.xyz - i.wp; }
let v = pbr_unit(view);
let lights = array<vec4<f32>, 3>(vec4<f32>(0.6, 0.0, 0.8, 3.0), vec4<f32>(-0.8, 0.0, 0.6, 1.0), vec4<f32>(0.0, -0.6, 0.8, 1.5));
var radiance = vec3<f32>(0.0);
for (var k = 0u; k < 3u; k += 1u) {
let light = lights[k];
radiance += pbr_brdf(i.base, i.parameters, n, v, light.xyz) * (light.w * max(dot(n, light.xyz), 0.0));
}
let mapped = radiance / (vec3<f32>(1.0) + radiance);
if (u.back.w > 0.5) { return vec4<f32>(mapped, 1.0); }
return vec4<f32>(pbr_encode(mapped), 1.0);
}
"#;