put global light into storage buffer

This commit is contained in:
2024-06-11 02:52:44 -04:00
parent 149c5a2659
commit b4adc07c96
8 changed files with 85 additions and 15 deletions

View File

@@ -41,7 +41,7 @@ pub fn init_world(world: &mut World) {
orientation: Rotation3::identity(),
grid: VoxelGrid::new(Array3::from_shape_fn(dim, |(x, y, z)| {
if y == 0 {
rand::random()
VoxelColor::random()
} else if (y == dim.1 - 1) && (x == 0 || x == dim.0 - 1 || z == 0 || z == dim.2 - 1) {
VoxelColor {
r: 255,

View File

@@ -44,7 +44,6 @@ impl Client {
init_world(&mut world);
let state = ClientState::new();
// render_channel.send(RenderMessage::ViewUpdate(state.camera)).expect("GRRRR");
Self {
window,
@@ -70,6 +69,8 @@ impl Client {
if self.exit {
self.renderer.send(RenderMessage::Exit).expect("AAAA");
// you know I'd like to do a timeout here...
// only because I have an NVIDIA GPU HELP
self.render_handle
.take()
.expect("uh oh")

View File

@@ -1,5 +1,5 @@
use std::marker::PhantomData;
use wgpu::{BufferAddress, BufferUsages};
use wgpu::{util::DeviceExt, BufferAddress, BufferUsages};
pub struct ArrBuf<T: bytemuck::Pod> {
len: usize,
@@ -74,6 +74,18 @@ impl<T: bytemuck::Pod> ArrBuf<T> {
}
}
pub fn init_with(device: &wgpu::Device, label: &str, usage: BufferUsages, data: &[T]) -> Self {
let label = &(label.to_owned() + " Buffer");
Self {
len: data.len(),
buffer: Self::init_buf_with(device, label, usage, data),
label: label.to_string(),
typ: PhantomData,
usage,
moves: Vec::new(),
}
}
fn init_buf(
device: &wgpu::Device,
label: &str,
@@ -91,6 +103,19 @@ impl<T: bytemuck::Pod> ArrBuf<T> {
})
}
fn init_buf_with(
device: &wgpu::Device,
label: &str,
usage: BufferUsages,
data: &[T],
) -> wgpu::Buffer {
device.create_buffer_init(&wgpu::util::BufferInitDescriptor {
label: Some(label),
usage: usage | BufferUsages::COPY_DST | BufferUsages::COPY_SRC,
contents: bytemuck::cast_slice(data),
})
}
pub fn buffer(&self) -> &wgpu::Buffer {
&self.buffer
}

View File

@@ -17,6 +17,17 @@ impl<T: PartialEq + bytemuck::Pod> Storage<T> {
binding,
}
}
pub fn init_with(device: &wgpu::Device, label: &str, binding: u32, data: &[T]) -> Self {
Self {
buf: ArrBuf::init_with(
device,
&(label.to_owned() + " Storage"),
BufferUsages::STORAGE,
data
),
binding,
}
}
}
impl<T: PartialEq + bytemuck::Pod> Storage<T> {

View File

@@ -1,7 +1,7 @@
use rand::distributions::{Distribution, Standard};
#[repr(C)]
#[derive(Debug, Clone, Copy, PartialEq, bytemuck::Zeroable, bytemuck::Pod)]
#[derive(Debug, Clone, Copy, PartialEq, bytemuck::Zeroable)]
pub struct VoxelColor {
pub r: u8,
pub g: u8,
@@ -9,6 +9,8 @@ pub struct VoxelColor {
pub a: u8,
}
unsafe impl bytemuck::Pod for VoxelColor {}
impl VoxelColor {
pub fn none() -> Self {
Self {
@@ -34,6 +36,9 @@ impl VoxelColor {
a: 255,
}
}
pub fn random() -> Self {
rand::random()
}
}
impl Distribution<VoxelColor> for Standard {

View File

@@ -0,0 +1,9 @@
use nalgebra::Vector3;
#[repr(C, align(16))]
#[derive(Clone, Copy, PartialEq, bytemuck::Zeroable)]
pub struct GlobalLight {
pub direction: Vector3<f32>,
}
unsafe impl bytemuck::Pod for GlobalLight {}

View File

@@ -1,13 +1,14 @@
mod grid;
mod view;
mod color;
mod grid;
mod group;
mod light;
mod view;
pub use color::*;
use nalgebra::{Projective3, Transform3, Translation3, Vector2};
use light::GlobalLight;
use nalgebra::{Projective3, Transform3, Translation3, Vector2, Vector3};
use {group::VoxelGroup, view::View};
use crate::client::{
camera::Camera,
render::{
@@ -15,6 +16,7 @@ use crate::client::{
CreateVoxelGrid,
},
};
use {group::VoxelGroup, view::View};
pub struct VoxelPipeline {
pipeline: wgpu::RenderPipeline,
@@ -23,6 +25,7 @@ pub struct VoxelPipeline {
bind_group: wgpu::BindGroup,
voxel_groups: Storage<VoxelGroup>,
voxels: Storage<VoxelColor>,
global_lights: Storage<GlobalLight>,
}
impl VoxelPipeline {
@@ -33,9 +36,17 @@ impl VoxelPipeline {
source: wgpu::ShaderSource::Wgsl(include_str!("shader.wgsl").into()),
});
let view = Uniform::<View>::init(device, "view", 0);
let view = Uniform::init(device, "view", 0);
let voxels = Storage::init(device, "voxels", 1);
let voxel_groups = Storage::init(device, "voxel groups", 2);
let global_lights = Storage::init_with(
device,
"global lights",
3,
&[GlobalLight {
direction: Vector3::new(-0.5, -4.0, 2.0).normalize(),
}],
);
// bind groups
let bind_group_layout = device.create_bind_group_layout(&wgpu::BindGroupLayoutDescriptor {
@@ -43,6 +54,7 @@ impl VoxelPipeline {
view.bind_group_layout_entry(),
voxels.bind_group_layout_entry(),
voxel_groups.bind_group_layout_entry(),
global_lights.bind_group_layout_entry(),
],
label: Some("tile_bind_group_layout"),
});
@@ -53,6 +65,7 @@ impl VoxelPipeline {
view.bind_group_entry(),
voxels.bind_group_entry(),
voxel_groups.bind_group_entry(),
global_lights.bind_group_entry(),
],
label: Some("tile_bind_group"),
});
@@ -109,6 +122,7 @@ impl VoxelPipeline {
bind_group_layout,
voxels,
voxel_groups,
global_lights,
}
}
@@ -156,6 +170,7 @@ impl VoxelPipeline {
self.view.bind_group_entry(),
self.voxels.bind_group_entry(),
self.voxel_groups.bind_group_entry(),
self.global_lights.bind_group_entry(),
],
label: Some("tile_bind_group"),
});

View File

@@ -1,5 +1,9 @@
// Vertex shader
struct GlobalLight {
dir: vec3<f32>,
};
struct VertexOutput {
@builtin(position) clip_position: vec4<f32>,
@location(0) tex_coords: vec2<f32>,
@@ -26,6 +30,8 @@ var<uniform> view: View;
var<storage, read> voxels: array<u32>;
@group(0) @binding(2)
var<storage, read> voxel_groups: array<VoxelGroup>;
@group(0) @binding(3)
var<storage, read> global_lights: array<GlobalLight>;
@vertex
fn vs_main(
@@ -62,7 +68,7 @@ fn fs_main(
let dir = view.transform * vec4<f32>(normalize(pixel_pos), 0.0);
var color = trace_full(pos, dir);
let light_mult = clamp((-dot(dir.xyz, normalize(GLOBAL_LIGHT)) - 0.99) * 200.0, 0.0, 1.0);
let light_mult = clamp((-dot(dir.xyz, global_lights[0].dir) - 0.99) * 200.0, 0.0, 1.0);
let sky_color = light_mult * vec3<f32>(1.0, 1.0, 1.0);
color += vec4<f32>(sky_color * (1.0 - color.a), 1.0 - color.a);
color.a = 1.0;
@@ -73,7 +79,6 @@ const ZERO3F = vec3<f32>(0.0);
const ZERO2F = vec2<f32>(0.0);
const DEPTH = 16u;
const FULL_ALPHA = 0.9999;
const GLOBAL_LIGHT = vec3<f32>(-0.5, -4.0, 2.0);
fn trace_full(pos: vec4<f32>, dir: vec4<f32>) -> vec4<f32> {
// GPUs hate this
@@ -124,7 +129,6 @@ fn apply_group(
(group.transform * vec4<f32>(0.0, 0.0, dir_if.z, 0.0)).xyz,
);
var next_normal = vec3<f32>(0.0, 0.0, 0.0);
let norm_light = normalize(GLOBAL_LIGHT);
// find where ray intersects with group
let plane_point = (vec3<f32>(1.0) - dir_if) / 2.0 * dim_f;
@@ -204,10 +208,10 @@ fn apply_group(
// lighting
let light = trace_light(full_pos);
let diffuse = max(dot(norm_light, normal) * ((dot(dir_view.xyz, normal) + 1.0) / 2.0 * .7 + .3) * 1.3 + 0.1, 0.0);
let diffuse = max(dot(global_lights[0].dir, normal) * ((dot(dir_view.xyz, normal) + 1.0) / 2.0 * .7 + .3) * 1.3 + 0.1, 0.0);
let ambient = 0.2;
let specular = (exp(max(
-(dot(reflect(dir_view.xyz, normal), norm_light) + 0.90) * 4.0, 0.0
-(dot(reflect(dir_view.xyz, normal), global_lights[0].dir) + 0.90) * 4.0, 0.0
)) - 1.0) * light;
let lighting = max(diffuse * light.a, ambient);
let new_rgb = min(vcolor.xyz * lighting + specular.xyz + light.xyz * vcolor.xyz, vec3<f32>(1.0));
@@ -233,7 +237,7 @@ fn apply_group(
fn trace_light(
pos: vec4<f32>
) -> vec4<f32> {
let dir = vec4<f32>(-normalize(GLOBAL_LIGHT), 0.0);
let dir = vec4<f32>(-global_lights[0].dir, 0.0);
var mask = vec4<f32>(0.0);
let start = pos + dir * .001;
for (var gi: u32 = 0; gi < arrayLength(&voxel_groups); gi = gi + 1) {