struct QuadCorner {
@location(0) center_offset: vec4<f32>,
@location(1) tex_coords: vec2<f32>,
@location(2) color: vec4<f32>,
@location(3) env_indices: vec2<i32>,
};
struct GroupInfo {
offset: vec2<f32>,
parallax: vec2<f32>,
};
struct QuadFragment {
@builtin(position) clip_position: vec4<f32>,
@location(0) tex_coords: vec2<f32>,
@location(1) color: vec4<f32>,
};
struct Camera {
position: vec2<f32>,
base_dimensions: vec2<f32>, // In tiles
zoom: vec2<f32>,
_padding: vec2<f32>,
};
struct LayerInfo {
color: vec4<f32>,
color_env: i32,
_padding: vec3<f32>,
};
// The y-axis is inverted between the map and gpu coordinate systems. Also for the camera dimensions.
const CORRECTION = vec2<f32>(2., -2.);
@group(0)
@binding(0)
var<uniform> camera: Camera; // Vertex
@group(0)
@binding(1)
var envelope_values: texture_1d<f32>; // Vertex
@group(0)
@binding(2)
var<uniform> group: GroupInfo; // Vertex
@group(0)
@binding(3)
var tex: texture_2d<f32>; // Fragment
@group(0)
@binding(4)
var tex_sampler: sampler; // Fragment
@vertex
fn vs_main(corner: QuadCorner) -> QuadFragment {
var frag: QuadFragment;
let pos_env_value = textureLoad(envelope_values, corner.env_indices.y, 0);
let rotation_sin = vec2<f32>(-corner.center_offset.w, corner.center_offset.z) * vec2<f32>(sin(pos_env_value.z));
let rotation_cos = corner.center_offset.zw * vec2<f32>(cos(pos_env_value.z));
var position = corner.center_offset.xy
- camera.position * group.parallax // Parallaxed Camera Position
- group.offset // Group Offset
+ pos_env_value.xy
+ rotation_sin
+ rotation_cos;
let parallax_zoom = clamp(max(group.parallax.x, group.parallax.y), 0., 1.);
let parallax_zoom_factor = mix(vec2<f32>(1.), camera.zoom, vec2<f32>(parallax_zoom));
let zoom_factor = CORRECTION / camera.base_dimensions / parallax_zoom_factor;
frag.clip_position = vec4<f32>(position * zoom_factor, 0., 1.);
frag.tex_coords = corner.tex_coords;
frag.color = corner.color * textureLoad(envelope_values, corner.env_indices.x, 0);
return frag;
}
@fragment
fn fs_main(frag: QuadFragment) -> @location(0) vec4<f32> {
return textureSample(tex, tex_sampler, frag.tex_coords) * frag.color;
}