hiraku-engine 0.1.0

Hiraku visual-novel engine
#import bevy_pbr::forward_io::VertexOutput

struct CustomScreenEffectMaterial {
    progress: f32,
    duration: f32,
    time: f32,
    mode: f32,
    p0: vec4<f32>,
    p1: vec4<f32>,
    p2: vec4<f32>,
    p3: vec4<f32>,
};

@group(#{MATERIAL_BIND_GROUP}) @binding(0) var<uniform> material: CustomScreenEffectMaterial;
@group(#{MATERIAL_BIND_GROUP}) @binding(1) var source_texture: texture_2d<f32>;
@group(#{MATERIAL_BIND_GROUP}) @binding(2) var source_sampler: sampler;
@group(#{MATERIAL_BIND_GROUP}) @binding(3) var target_texture: texture_2d<f32>;
@group(#{MATERIAL_BIND_GROUP}) @binding(4) var target_sampler: sampler;
@group(#{MATERIAL_BIND_GROUP}) @binding(5) var rule_texture: texture_2d<f32>;
@group(#{MATERIAL_BIND_GROUP}) @binding(6) var rule_sampler: sampler;
@group(#{MATERIAL_BIND_GROUP}) @binding(7) var aux0_texture: texture_2d<f32>;
@group(#{MATERIAL_BIND_GROUP}) @binding(8) var aux0_sampler: sampler;
@group(#{MATERIAL_BIND_GROUP}) @binding(9) var aux1_texture: texture_2d<f32>;
@group(#{MATERIAL_BIND_GROUP}) @binding(10) var aux1_sampler: sampler;

fn mode_crossfade(uv: vec2<f32>) -> vec4<f32> {
    let source = textureSample(source_texture, source_sampler, uv);
    let target = textureSample(target_texture, target_sampler, uv);
    return mix(source, target, clamp(material.progress, 0.0, 1.0));
}

fn mode_rule(uv: vec2<f32>) -> vec4<f32> {
    let source = textureSample(source_texture, source_sampler, uv);
    let target = textureSample(target_texture, target_sampler, uv);
    let rule = textureSample(rule_texture, rule_sampler, uv).r;
    let vague = max(material.p0.x, 0.0001);
    let edge = clamp((material.progress - rule) / vague + 0.5, 0.0, 1.0);
    return mix(source, target, edge);
}

fn mode_wave(uv: vec2<f32>) -> vec4<f32> {
    let amplitude = material.p0.x;
    let frequency = max(material.p0.y, 0.0001);
    let speed = material.p0.z;
    let mix_target = clamp(material.p0.w, 0.0, 1.0);
    let wave = sin((uv.y + material.time * speed) * frequency) * amplitude;
    let warped_uv = vec2(uv.x + wave, uv.y);
    let source = textureSample(source_texture, source_sampler, warped_uv);
    let target = textureSample(target_texture, target_sampler, uv);
    return mix(source, target, mix_target * clamp(material.progress, 0.0, 1.0));
}

@fragment
fn fragment(mesh: VertexOutput) -> @location(0) vec4<f32> {
    let uv = mesh.uv;
    let mode = i32(material.mode + 0.5);

    if mode == 1 {
        return mode_rule(uv);
    }
    if mode == 2 {
        return mode_wave(uv);
    }

    return mode_crossfade(uv);
}