#import bevy_sprite::mesh2d_view_bindings
#import bevy_sprite::mesh2d_bindings mesh
#import bevy_sprite::mesh2d_view_bindings globals

#import bevy_sprite::mesh2d_functions mesh2d_position_local_to_world
#import bevy_sprite::mesh2d_functions mesh2d_position_world_to_clip
#import bevy_pbr::mesh_vertex_output MeshVertexOutput


struct PlasmaMaterial {
    center_color : vec4<f32>,
    alpha_scale : f32,
    jitter : f32,
    bloom_magnitude: f32,
    noise_level: f32
};


@group(1) @binding(0) 
var<uniform> material: PlasmaMaterial;


struct Vertex {
    @location(0) position: vec3<f32>,
    @location(2) uv: vec2<f32>,
    @location(4) color: vec4<f32>,
};

struct VertexOutput {
    @builtin(position) clip_position: vec4<f32>,
    @location(0) world_position: vec4<f32>,
    @location(1) uv: vec2<f32>,
    @location(2) color: vec4<f32>,
};

fn rand2(n: vec2<f32>) -> f32 {
  return fract(sin(dot(n, vec2<f32>(12.9898, 4.1414))) * 43758.5453);
}

fn noise2(n: vec2<f32>) -> f32 {
  let d = vec2<f32>(0., 1.);
  let b = floor(n);
  let f = smoothstep(vec2<f32>(0.), vec2<f32>(1.), fract(n));
  return mix(mix(rand2(b), rand2(b + d.yx), f.x), mix(rand2(b + d.xy), rand2(b + d.yy), f.x), f.y);
}

@vertex
fn vertex(vertex: Vertex) -> VertexOutput {
    var out: VertexOutput;

    var model = mesh.model;

    var offset = vec3(noise2(vertex.position.xy*globals.time), noise2(vertex.position.xy*globals.time * 3.0), 0.);
    out.world_position = mesh2d_position_local_to_world(mesh.model, vec4<f32>(vertex.position + offset * material.jitter, 1.0));
    out.clip_position = mesh2d_position_world_to_clip(out.world_position);

    out.uv = vertex.uv;
    out.color = vertex.color;

    return out;
}


@fragment
fn fragment(
   in: VertexOutput
) -> @location(0) vec4<f32> {

    var tex = abs(in.uv * 2.0 - vec2(1.0));
    var res = smoothstep(0.0, tex.y, 0.02) * material.center_color.rgb * material.bloom_magnitude;
    var noise = 1.0 - (noise2(in.uv * 100.0) * material.noise_level);

    return vec4<f32>(res * noise, material.alpha_scale * in.color.a);
}
