bevylder 0.1.0

Voxels brought to bevy
Documentation
#import bevy_pbr::mesh_view_bind_group
#import bevy_pbr::mesh_struct

[[group(1), binding(0)]]
var<uniform> mesh: Mesh;

struct Vertex {
    [[location(0)]] position: vec3<f32>;
    [[location(1)]] normal: vec3<f32>;
    [[location(2)]] uv: vec2<f32>;
};

struct VertexOutput {
    [[builtin(position)]] clip_position: vec4<f32>;
    [[location(0)]] vertex_position: vec3<f32>;
};

[[stage(vertex)]]
fn vertex(vertex: Vertex) -> VertexOutput {
    let world_position = mesh.model * vec4<f32>(vertex.position, 1.0);

    var out: VertexOutput;
    out.clip_position = view.view_proj * world_position;
    out.vertex_position = vertex.position;
    return out;
}

struct Voxel {
    data: array<u32, 4096>;
};

[[group(2), binding(0)]]
var<uniform> voxel: Voxel;

fn to_color(byte: u32) -> vec4<f32> {
    let a = (byte >> 24u) & 0xFFu;
    let r = (byte >> 16u) & 0xFFu;
    let g = (byte >> 8u) & 0xFFu;
    let b = byte & 0xFFu;

    return vec4<f32>(f32(r) / 255.0, f32(g) / 255.0, f32(b) / 255.0, f32(a) / 255.0);
}

fn get(vpos: vec3<i32>) -> vec4<f32> {
    let uvpos = vec3<u32>(vpos);
    let idx = uvpos.x + uvpos.z * 16u + uvpos.y * 256u;
    return to_color(voxel.data[idx]);
}

fn intersect_plane_t(p: vec3<f32>, dir: vec3<f32>, plane: vec3<f32>) -> f32 {
    // FIXME
    let eps = 0.0000001;
    let d = dot(plane, dir);
    if (abs(d) > eps) {
        let w = p - plane;
        let fac = -dot(plane, w) / d;
        return fac;
    }
    return 1000.0;
}

[[stage(fragment)]]
fn fragment(in: VertexOutput) -> [[location(0)]] vec4<f32> {
    let obj_space_camera_pos = (vec4<f32>(view.world_position, 1.0) * mesh.inverse_transpose_model).xyz;
    let view_dir = normalize(in.vertex_position - obj_space_camera_pos);
    var vpos = vec3<i32>((in.vertex_position + 0.5) * 15.9999);
    var color = get(vpos);

    if (color.a > 0.5) {
        return vec4<f32>(color.rgb, 0.0);
    }

    let vsign = sign(view_dir);
    let step = vec3<i32>(vsign);
    let t_delta = 1.0 / abs(view_dir);

    let sub_pos = 2.0 * ((in.vertex_position + 0.5) * 16.0 - vec3<f32>(vpos)) - 1.0;
    var t_max = 0.5 * vec3<f32>(
        intersect_plane_t(sub_pos, view_dir, vec3<f32>(vsign.x, 0.0, 0.0)),
        intersect_plane_t(sub_pos, view_dir, vec3<f32>(0.0, vsign.y, 0.0)),
        intersect_plane_t(sub_pos, view_dir, vec3<f32>(0.0, 0.0, vsign.z)),
    );

    loop {
        if (t_max.x < t_max.y) {
            if (t_max.x < t_max.z) {
                vpos.x = vpos.x + step.x;
                if (vpos.x < 0 || vpos.x >= 16) { return vec4<f32>(0.0, 0.0, 0.0, 0.0); }
                t_max.x = t_max.x + t_delta.x;
            } else {
                vpos.z = vpos.z + step.z;
                if (vpos.z < 0 || vpos.z >= 16) { return vec4<f32>(0.0, 0.0, 0.0, 0.0); }
                t_max.z = t_max.z + t_delta.z;
            }
        } else {
            if (t_max.y < t_max.z) {
                vpos.y = vpos.y + step.y;
                if (vpos.y < 0 || vpos.y >= 16) { return vec4<f32>(0.0, 0.0, 0.0, 0.0); }
                t_max.y = t_max.y + t_delta.y;
            } else {
                vpos.z = vpos.z + step.z;
                if (vpos.z < 0 || vpos.z >= 16) { return vec4<f32>(0.0, 0.0, 0.0, 0.0); }
                t_max.z = t_max.z + t_delta.z;
            }
        }
        color = get(vpos);

        if (color.a > 0.5) {
            return vec4<f32>(color.rgb, 0.0);
        }
    }
    return vec4<f32>(0.0, 0.0, 0.0, 0.0);
}