nightshade-renderer 0.57.0

GPU-driven wgpu renderer with a built-in frame graph.
#define_import_path nightshade_renderer::material_sampling

const NO_LAYER: u32 = 0xFFFFFFFFu;

struct UvGrad {
    ddx: vec2<f32>,
    ddy: vec2<f32>,
}

fn apply_wrap_axis(value: f32, mode: u32) -> f32 {
    if mode == 0u {
        return fract(value);
    } else if mode == 1u {
        let cycle = value - 2.0 * floor(value * 0.5);
        return min(cycle, 2.0 - cycle);
    }
    return clamp(value, 0.0, 1.0);
}

fn apply_wrap(uv: vec2<f32>, packed: u32) -> vec2<f32> {
    let mode_u = (packed >> 16u) & 0x3u;
    let mode_v = (packed >> 18u) & 0x3u;
    return vec2<f32>(apply_wrap_axis(uv.x, mode_u), apply_wrap_axis(uv.y, mode_v));
}

#ifdef BINDLESS

@group(2) @binding(0)
var material_textures: binding_array<texture_2d<f32>>;

@group(2) @binding(1)
var material_sampler_repeat: sampler;

@group(2) @binding(2)
var material_sampler_mirror: sampler;

@group(2) @binding(3)
var material_sampler_clamp: sampler;

fn sample_srgb_layer(packed: u32, uv: vec2<f32>, grad: UvGrad) -> vec4<f32> {
    if packed == NO_LAYER {
        return vec4<f32>(0.0);
    }
    let index = packed & 0xFFFFu;
    let mode_u = (packed >> 16u) & 0x3u;
    let mode_v = (packed >> 18u) & 0x3u;
    if mode_u == mode_v {
        switch mode_u {
            case 0u: {
                return textureSampleGrad(material_textures[index], material_sampler_repeat, uv, grad.ddx, grad.ddy);
            }
            case 1u: {
                return textureSampleGrad(material_textures[index], material_sampler_mirror, uv, grad.ddx, grad.ddy);
            }
            default: {
                return textureSampleGrad(material_textures[index], material_sampler_clamp, uv, grad.ddx, grad.ddy);
            }
        }
    }
    let wrapped = apply_wrap(uv, packed);
    return textureSampleGrad(material_textures[index], material_sampler_clamp, wrapped, grad.ddx, grad.ddy);
}

fn sample_linear_layer(packed: u32, uv: vec2<f32>, grad: UvGrad) -> vec4<f32> {
    if packed == NO_LAYER {
        return vec4<f32>(0.0);
    }
    let index = packed & 0xFFFFu;
    let mode_u = (packed >> 16u) & 0x3u;
    let mode_v = (packed >> 18u) & 0x3u;
    if mode_u == mode_v {
        switch mode_u {
            case 0u: {
                return textureSampleGrad(material_textures[index], material_sampler_repeat, uv, grad.ddx, grad.ddy);
            }
            case 1u: {
                return textureSampleGrad(material_textures[index], material_sampler_mirror, uv, grad.ddx, grad.ddy);
            }
            default: {
                return textureSampleGrad(material_textures[index], material_sampler_clamp, uv, grad.ddx, grad.ddy);
            }
        }
    }
    let wrapped = apply_wrap(uv, packed);
    return textureSampleGrad(material_textures[index], material_sampler_clamp, wrapped, grad.ddx, grad.ddy);
}

fn sample_srgb_index(layer: u32, uv: vec2<f32>) -> vec4<f32> {
    return textureSampleLevel(material_textures[layer], material_sampler_clamp, uv, 0.0);
}

#else

@group(2) @binding(0)
var material_srgb_array: texture_2d_array<f32>;

@group(2) @binding(1)
var material_linear_array: texture_2d_array<f32>;

@group(2) @binding(2)
var material_sampler_repeat: sampler;

@group(2) @binding(3)
var material_sampler_mirror: sampler;

@group(2) @binding(4)
var material_sampler_clamp: sampler;

fn sample_srgb_layer(packed: u32, uv: vec2<f32>, grad: UvGrad) -> vec4<f32> {
    if packed == NO_LAYER {
        return vec4<f32>(0.0);
    }
    let layer = packed & 0xFFFFu;
    let mode_u = (packed >> 16u) & 0x3u;
    let mode_v = (packed >> 18u) & 0x3u;
    if mode_u == mode_v {
        switch mode_u {
            case 0u: {
                return textureSampleGrad(material_srgb_array, material_sampler_repeat, uv, layer, grad.ddx, grad.ddy);
            }
            case 1u: {
                return textureSampleGrad(material_srgb_array, material_sampler_mirror, uv, layer, grad.ddx, grad.ddy);
            }
            default: {
                return textureSampleGrad(material_srgb_array, material_sampler_clamp, uv, layer, grad.ddx, grad.ddy);
            }
        }
    }
    let wrapped = apply_wrap(uv, packed);
    return textureSampleGrad(material_srgb_array, material_sampler_clamp, wrapped, layer, grad.ddx, grad.ddy);
}

fn sample_linear_layer(packed: u32, uv: vec2<f32>, grad: UvGrad) -> vec4<f32> {
    if packed == NO_LAYER {
        return vec4<f32>(0.0);
    }
    let layer = packed & 0xFFFFu;
    let mode_u = (packed >> 16u) & 0x3u;
    let mode_v = (packed >> 18u) & 0x3u;
    if mode_u == mode_v {
        switch mode_u {
            case 0u: {
                return textureSampleGrad(material_linear_array, material_sampler_repeat, uv, layer, grad.ddx, grad.ddy);
            }
            case 1u: {
                return textureSampleGrad(material_linear_array, material_sampler_mirror, uv, layer, grad.ddx, grad.ddy);
            }
            default: {
                return textureSampleGrad(material_linear_array, material_sampler_clamp, uv, layer, grad.ddx, grad.ddy);
            }
        }
    }
    let wrapped = apply_wrap(uv, packed);
    return textureSampleGrad(material_linear_array, material_sampler_clamp, wrapped, layer, grad.ddx, grad.ddy);
}

fn sample_srgb_index(layer: u32, uv: vec2<f32>) -> vec4<f32> {
    return textureSampleLevel(material_srgb_array, material_sampler_clamp, uv, layer, 0.0);
}

#endif