76 lines
2.2 KiB
WebGPU Shading Language
76 lines
2.2 KiB
WebGPU Shading Language
struct VertexShaderInput {
|
|
// Per Vertex
|
|
@builtin(vertex_index) vertex_index: u32,
|
|
|
|
@location(0) pos: vec3<f32>,
|
|
@location(1) uv: vec2<f32>,
|
|
|
|
// Per Instance
|
|
@builtin(instance_index) instance_index: u32,
|
|
|
|
@location(2) tile: u32,
|
|
};
|
|
|
|
struct VertexShaderOutput {
|
|
@builtin(position) pos: vec4<f32>,
|
|
|
|
@location(0) uv: vec2<f32>,
|
|
@location(1) tile: u32,
|
|
};
|
|
|
|
struct FragmentShaderOutput {
|
|
@location(0) color: vec4<f32>,
|
|
};
|
|
|
|
struct Per_Frame_Data {
|
|
drag_start: vec2<i32>,
|
|
mouse: vec2<i32>,
|
|
grid_offset: vec2<f32>,
|
|
grid_width: u32,
|
|
map_width: u32,
|
|
};
|
|
|
|
@group(0) @binding(0) var<uniform> view_projection_matrix: mat4x4<f32>;
|
|
@group(0) @binding(1) var<uniform> per_frame: Per_Frame_Data;
|
|
|
|
@vertex fn main_vertex(input: VertexShaderInput) -> VertexShaderOutput {
|
|
var output: VertexShaderOutput;
|
|
|
|
let tile_pos = vec2<f32>(f32(input.instance_index % per_frame.map_width), f32(input.instance_index / per_frame.map_width)) - vec2<f32>(0.5, 0.5);
|
|
|
|
output.tile = input.tile;
|
|
output.pos = vec4<f32>(tile_pos + input.pos.xy, 0, 1) * view_projection_matrix;
|
|
output.uv = input.uv;
|
|
|
|
return output;
|
|
}
|
|
|
|
@group(1) @binding(0) var texture1: texture_2d<f32>;
|
|
@group(1) @binding(1) var sampler1: sampler;
|
|
|
|
@group(1) @binding(2) var<uniform> tint: vec3<f32>;
|
|
|
|
@group(1) @binding(3) var<storage> tile_uvs: array<vec4<f32>>;
|
|
|
|
@fragment fn main_fragment(input: VertexShaderOutput) -> FragmentShaderOutput {
|
|
var output: FragmentShaderOutput;
|
|
|
|
output.color = pixel_art_sample(texture1, sampler1, input.uv, input.tile);
|
|
output.color = vec4<f32>(output.color.rgb * tint.rgb, output.color.a);
|
|
|
|
return output;
|
|
}
|
|
|
|
fn pixel_art_sample(input_texture: texture_2d<f32>, input_sampler: sampler, input_uv: vec2<f32>, tile: u32) -> vec4<f32> {
|
|
let dimensions = vec2<f32>(textureDimensions(input_texture));
|
|
|
|
let tile_uv = tile_uvs[tile];
|
|
|
|
let texture_uv = mix(tile_uv.xy, tile_uv.zw, input_uv);
|
|
let sample_uv = (floor(texture_uv) + saturate(fract(texture_uv) / fwidth(texture_uv)) - 0.5) / dimensions;
|
|
|
|
let uv = clamp(sample_uv, (tile_uv.xy + 0.5) / dimensions, (tile_uv.zw - 0.5) / dimensions);
|
|
|
|
return textureSample(input_texture, input_sampler, uv);
|
|
}
|