Files
MapLibreParticleLab/include/mln/shaders/webgpu/background.hpp
Bart Louwers 2a8ebc4906 core: rename mbgl directories to mln (#4511)
Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
2026-08-22 20:50:14 +02:00

231 lines
6.1 KiB
C++

#pragma once
#include <mln/shaders/shader_source.hpp>
#include <mln/shaders/webgpu/shader_program.hpp>
#include <mln/shaders/background_layer_ubo.hpp>
namespace mln {
namespace shaders {
template <>
struct ShaderSource<BuiltIn::BackgroundShader, gfx::Backend::Type::WebGPU> {
static constexpr const char* name = "BackgroundShader";
static const std::array<AttributeInfo, 1> attributes;
static constexpr std::array<AttributeInfo, 0> instanceAttributes{};
static const std::array<TextureInfo, 0> textures;
static constexpr auto vertex = R"(
struct VertexInput {
@location(3) position: vec2<i32>,
};
struct VertexOutput {
@builtin(position) position: vec4<f32>,
};
struct BackgroundDrawableUBO {
matrix: mat4x4<f32>,
};
struct BackgroundDrawableUnionUBO {
matrix_col0: vec4<f32>,
matrix_col1: vec4<f32>,
matrix_col2: vec4<f32>,
matrix_col3: vec4<f32>,
extra0: vec4<f32>,
extra1: vec4<f32>,
};
struct BackgroundPropsUBO {
color: vec4<f32>,
opacity: f32,
pad1: f32,
pad2: f32,
pad3: f32,
};
struct GlobalIndexUBO {
value: u32,
pad0: vec3<u32>,
};
@group(0) @binding(1) var<uniform> globalIndex: GlobalIndexUBO;
@group(0) @binding(2) var<storage, read> drawableVector: array<BackgroundDrawableUnionUBO>;
@group(0) @binding(4) var<uniform> props: BackgroundPropsUBO;
@vertex
fn main(in: VertexInput) -> VertexOutput {
var out: VertexOutput;
let drawable = drawableVector[globalIndex.value];
let matrix = mat4x4<f32>(drawable.matrix_col0,
drawable.matrix_col1,
drawable.matrix_col2,
drawable.matrix_col3);
let clip = matrix * vec4<f32>(f32(in.position.x), f32(in.position.y), 0.0, 1.0);
out.position = clip;
return out;
}
)";
static constexpr auto fragment = R"(
struct BackgroundPropsUBO {
color: vec4<f32>,
opacity: f32,
pad1: f32,
pad2: f32,
pad3: f32,
};
@group(0) @binding(4) var<uniform> props: BackgroundPropsUBO;
@fragment
fn main() -> @location(0) vec4<f32> {
return props.color * props.opacity;
}
)";
};
template <>
struct ShaderSource<BuiltIn::BackgroundPatternShader, gfx::Backend::Type::WebGPU> {
static constexpr const char* name = "BackgroundPatternShader";
static const std::array<AttributeInfo, 1> attributes;
static constexpr std::array<AttributeInfo, 0> instanceAttributes{};
static const std::array<TextureInfo, 1> textures;
static constexpr auto vertex = R"(
struct VertexInput {
@location(3) position: vec2<i32>,
};
struct VertexOutput {
@builtin(position) position: vec4<f32>,
@location(0) pos_a: vec2<f32>,
@location(1) pos_b: vec2<f32>,
};
struct BackgroundPatternDrawableUnionUBO {
matrix_col0: vec4<f32>,
matrix_col1: vec4<f32>,
matrix_col2: vec4<f32>,
matrix_col3: vec4<f32>,
pixel_coord_upper: vec2<f32>,
pixel_coord_lower: vec2<f32>,
tile_units_to_pixels: f32,
pad1: f32,
pad2: f32,
pad3: f32,
};
struct BackgroundPatternPropsUBO {
pattern_tl_a: vec2<f32>,
pattern_br_a: vec2<f32>,
pattern_tl_b: vec2<f32>,
pattern_br_b: vec2<f32>,
pattern_size_a: vec2<f32>,
pattern_size_b: vec2<f32>,
scale_a: f32,
scale_b: f32,
mix: f32,
opacity: f32,
pad1: f32,
pad2: f32,
};
struct GlobalIndexUBO {
value: u32,
pad0: vec3<u32>,
};
@group(0) @binding(1) var<uniform> globalIndex: GlobalIndexUBO;
@group(0) @binding(2) var<storage, read> drawableVector: array<BackgroundPatternDrawableUnionUBO>;
@group(0) @binding(4) var<uniform> props: BackgroundPatternPropsUBO;
@vertex
fn main(in: VertexInput) -> VertexOutput {
var out: VertexOutput;
let drawable = drawableVector[globalIndex.value];
let matrix = mat4x4<f32>(drawable.matrix_col0,
drawable.matrix_col1,
drawable.matrix_col2,
drawable.matrix_col3);
let pos = vec2<f32>(f32(in.position.x), f32(in.position.y));
// Use get_pattern_pos helper function for pattern positioning
out.pos_a = get_pattern_pos(
drawable.pixel_coord_upper,
drawable.pixel_coord_lower,
props.scale_a * props.pattern_size_a,
drawable.tile_units_to_pixels,
pos
);
out.pos_b = get_pattern_pos(
drawable.pixel_coord_upper,
drawable.pixel_coord_lower,
props.scale_b * props.pattern_size_b,
drawable.tile_units_to_pixels,
pos
);
let clip = matrix * vec4<f32>(pos, 0.0, 1.0);
out.position = clip;
return out;
}
)";
static constexpr auto fragment = R"(
struct FragmentInput {
@location(0) pos_a: vec2<f32>,
@location(1) pos_b: vec2<f32>,
};
struct BackgroundPatternPropsUBO {
pattern_tl_a: vec2<f32>,
pattern_br_a: vec2<f32>,
pattern_tl_b: vec2<f32>,
pattern_br_b: vec2<f32>,
pattern_size_a: vec2<f32>,
pattern_size_b: vec2<f32>,
scale_a: f32,
scale_b: f32,
mix: f32,
opacity: f32,
pad1: f32,
pad2: f32,
};
struct GlobalPaintParamsUBO {
pattern_atlas_texsize: vec2<f32>,
// other fields...
};
@group(0) @binding(0) var<uniform> paintParams: GlobalPaintParamsUBO;
@group(0) @binding(4) var<uniform> props: BackgroundPatternPropsUBO;
@group(1) @binding(0) var texture_sampler: sampler;
@group(1) @binding(1) var pattern_texture: texture_2d<f32>;
@fragment
fn main(in: FragmentInput) -> @location(0) vec4<f32> {
let texsize = paintParams.pattern_atlas_texsize;
// Sample pattern A
let imagecoord_a = gl_mod(in.pos_a, vec2<f32>(1.0));
let pos_a = mix(props.pattern_tl_a / texsize, props.pattern_br_a / texsize, imagecoord_a);
let color_a = textureSample(pattern_texture, texture_sampler, pos_a);
// Sample pattern B
let imagecoord_b = gl_mod(in.pos_b, vec2<f32>(1.0));
let pos_b = mix(props.pattern_tl_b / texsize, props.pattern_br_b / texsize, imagecoord_b);
let color_b = textureSample(pattern_texture, texture_sampler, pos_b);
// Mix patterns and apply opacity
return mix(color_a, color_b, props.mix) * props.opacity;
}
)";
};
} // namespace shaders
} // namespace mln