2021-10-20 21:44:06 +00:00
|
|
|
/// Shader used for drawing all flavors of gradients.
|
|
|
|
|
2022-08-27 21:39:57 +00:00
|
|
|
struct wrapped_vecf32 {
|
|
|
|
elem: vec4<f32>,
|
|
|
|
_padding1: vec4<f32>,
|
|
|
|
_padding2: vec4<f32>,
|
|
|
|
_padding3: vec4<f32>
|
|
|
|
}
|
|
|
|
|
|
|
|
struct wrapped_f32 {
|
|
|
|
elem: f32,
|
|
|
|
_padding1: f32,
|
|
|
|
_padding2: f32,
|
|
|
|
_padding3: f32,
|
|
|
|
}
|
|
|
|
|
2021-10-20 21:44:06 +00:00
|
|
|
struct Gradient {
|
2022-08-27 21:39:57 +00:00
|
|
|
colors: array<wrapped_vecf32,16u>,
|
|
|
|
ratios: array<wrapped_f32,16u>,
|
2022-07-02 12:18:30 +00:00
|
|
|
gradient_type: i32,
|
|
|
|
num_colors: u32,
|
|
|
|
repeat_mode: i32,
|
|
|
|
interpolation: i32,
|
|
|
|
focal_point: f32,
|
2021-10-20 21:44:06 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
struct VertexOutput {
|
2022-07-02 12:18:30 +00:00
|
|
|
@builtin(position) position: vec4<f32>,
|
|
|
|
@location(0) uv: vec2<f32>,
|
2021-10-20 21:44:06 +00:00
|
|
|
};
|
|
|
|
|
2022-07-02 12:18:30 +00:00
|
|
|
@group(2) @binding(0) var<uniform> textureTransforms: TextureTransforms;
|
2022-08-27 21:39:57 +00:00
|
|
|
@group(2) @binding(1) var<uniform> gradient: Gradient;
|
2021-10-20 21:44:06 +00:00
|
|
|
|
2022-07-02 12:18:30 +00:00
|
|
|
@vertex
|
2021-10-26 04:36:19 +00:00
|
|
|
fn main_vertex(in: VertexInput) -> VertexOutput {
|
2022-07-02 12:18:30 +00:00
|
|
|
let matrix_ = textureTransforms.matrix_;
|
|
|
|
let uv = (mat3x3<f32>(matrix_[0].xyz, matrix_[1].xyz, matrix_[2].xyz) * vec3<f32>(in.position, 1.0)).xy;
|
2021-10-20 21:44:06 +00:00
|
|
|
let pos = globals.view_matrix * transforms.world_matrix * vec4<f32>(in.position.x, in.position.y, 0.0, 1.0);
|
|
|
|
return VertexOutput(pos, uv);
|
|
|
|
}
|
|
|
|
|
2022-07-02 12:18:30 +00:00
|
|
|
@fragment
|
|
|
|
fn main_fragment(in: VertexOutput) -> @location(0) vec4<f32> {
|
2021-10-20 21:44:06 +00:00
|
|
|
let last = gradient.num_colors - 1u;
|
|
|
|
|
|
|
|
// Calculate normalized `t` position in gradient, [0.0, 1.0] being the bounds of the ratios.
|
|
|
|
var t: f32;
|
|
|
|
switch( gradient.gradient_type ){
|
|
|
|
// Radial gradient
|
|
|
|
case 1: {
|
|
|
|
t = length(in.uv * 2.0 - 1.0);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Focal gradient
|
|
|
|
case 2: {
|
|
|
|
let uv = in.uv * 2.0 - 1.0;
|
|
|
|
var d: vec2<f32> = vec2<f32>(gradient.focal_point, 0.0) - uv;
|
|
|
|
let l = length(d);
|
|
|
|
d = d / l;
|
|
|
|
t = l / (sqrt(1.0 - gradient.focal_point * gradient.focal_point * d.y * d.y) + gradient.focal_point * d.x);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
2022-01-23 04:45:13 +00:00
|
|
|
// Linear gradient
|
2021-10-20 21:44:06 +00:00
|
|
|
default: {
|
2022-01-23 04:45:13 +00:00
|
|
|
t = in.uv.x;
|
2021-10-20 21:44:06 +00:00
|
|
|
break;
|
|
|
|
}
|
2022-01-23 04:45:13 +00:00
|
|
|
}
|
2021-10-20 21:44:06 +00:00
|
|
|
|
2022-01-23 04:45:13 +00:00
|
|
|
// Tweak out-of-bounds `t` based on the repeat mode.
|
|
|
|
switch( gradient.repeat_mode ){
|
2021-10-20 21:44:06 +00:00
|
|
|
// Repeat
|
|
|
|
case 1: {
|
|
|
|
t = fract(t);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Mirror
|
|
|
|
case 2: {
|
|
|
|
if( t < 0.0 )
|
|
|
|
{
|
|
|
|
t = -t;
|
|
|
|
}
|
|
|
|
if( (i32(t)&1) == 0 ) {
|
|
|
|
t = fract(t);
|
|
|
|
} else {
|
|
|
|
t = 1.0 - fract(t);
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
2022-01-23 04:45:13 +00:00
|
|
|
|
|
|
|
// Clamp
|
|
|
|
default: {
|
|
|
|
t = clamp(t, 0.0, 1.0);
|
|
|
|
break;
|
|
|
|
}
|
2021-10-20 21:44:06 +00:00
|
|
|
}
|
2022-08-27 21:39:57 +00:00
|
|
|
t = clamp(t, gradient.ratios[0].elem, gradient.ratios[last].elem);
|
2021-10-20 21:44:06 +00:00
|
|
|
|
|
|
|
// Find the two gradient colors bordering our position.
|
2021-10-26 04:36:19 +00:00
|
|
|
var j: u32;
|
2022-08-27 21:39:57 +00:00
|
|
|
for( j = 1u; t > gradient.ratios[j].elem; j = j + 1u) {
|
2021-10-20 21:44:06 +00:00
|
|
|
// Noop
|
|
|
|
}
|
2021-10-26 04:36:19 +00:00
|
|
|
let i = j - 1u;
|
2021-10-20 21:44:06 +00:00
|
|
|
|
|
|
|
// Lerp between the two colors.
|
2022-08-27 21:39:57 +00:00
|
|
|
let a = (t - gradient.ratios[i].elem) / (gradient.ratios[j].elem - gradient.ratios[i].elem);
|
|
|
|
var color: vec4<f32> = mix(gradient.colors[i].elem, gradient.colors[j].elem, a);
|
2021-10-20 21:44:06 +00:00
|
|
|
if( gradient.interpolation != 0 ) {
|
|
|
|
color = linear_to_srgb(color);
|
|
|
|
}
|
2022-04-13 05:28:02 +00:00
|
|
|
let out = color * transforms.mult_color + transforms.add_color;
|
2022-05-12 18:46:52 +00:00
|
|
|
let alpha = clamp(out.a, 0.0, 1.0);
|
|
|
|
return vec4<f32>(out.rgb * alpha, alpha);
|
2021-10-20 21:44:06 +00:00
|
|
|
}
|