put global light into storage buffer
This commit is contained in:
@@ -41,7 +41,7 @@ pub fn init_world(world: &mut World) {
|
|||||||
orientation: Rotation3::identity(),
|
orientation: Rotation3::identity(),
|
||||||
grid: VoxelGrid::new(Array3::from_shape_fn(dim, |(x, y, z)| {
|
grid: VoxelGrid::new(Array3::from_shape_fn(dim, |(x, y, z)| {
|
||||||
if y == 0 {
|
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) {
|
} else if (y == dim.1 - 1) && (x == 0 || x == dim.0 - 1 || z == 0 || z == dim.2 - 1) {
|
||||||
VoxelColor {
|
VoxelColor {
|
||||||
r: 255,
|
r: 255,
|
||||||
|
|||||||
@@ -44,7 +44,6 @@ impl Client {
|
|||||||
|
|
||||||
init_world(&mut world);
|
init_world(&mut world);
|
||||||
let state = ClientState::new();
|
let state = ClientState::new();
|
||||||
// render_channel.send(RenderMessage::ViewUpdate(state.camera)).expect("GRRRR");
|
|
||||||
|
|
||||||
Self {
|
Self {
|
||||||
window,
|
window,
|
||||||
@@ -70,6 +69,8 @@ impl Client {
|
|||||||
|
|
||||||
if self.exit {
|
if self.exit {
|
||||||
self.renderer.send(RenderMessage::Exit).expect("AAAA");
|
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
|
self.render_handle
|
||||||
.take()
|
.take()
|
||||||
.expect("uh oh")
|
.expect("uh oh")
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
use std::marker::PhantomData;
|
use std::marker::PhantomData;
|
||||||
use wgpu::{BufferAddress, BufferUsages};
|
use wgpu::{util::DeviceExt, BufferAddress, BufferUsages};
|
||||||
|
|
||||||
pub struct ArrBuf<T: bytemuck::Pod> {
|
pub struct ArrBuf<T: bytemuck::Pod> {
|
||||||
len: usize,
|
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(
|
fn init_buf(
|
||||||
device: &wgpu::Device,
|
device: &wgpu::Device,
|
||||||
label: &str,
|
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 {
|
pub fn buffer(&self) -> &wgpu::Buffer {
|
||||||
&self.buffer
|
&self.buffer
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -17,6 +17,17 @@ impl<T: PartialEq + bytemuck::Pod> Storage<T> {
|
|||||||
binding,
|
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> {
|
impl<T: PartialEq + bytemuck::Pod> Storage<T> {
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
use rand::distributions::{Distribution, Standard};
|
use rand::distributions::{Distribution, Standard};
|
||||||
|
|
||||||
#[repr(C)]
|
#[repr(C)]
|
||||||
#[derive(Debug, Clone, Copy, PartialEq, bytemuck::Zeroable, bytemuck::Pod)]
|
#[derive(Debug, Clone, Copy, PartialEq, bytemuck::Zeroable)]
|
||||||
pub struct VoxelColor {
|
pub struct VoxelColor {
|
||||||
pub r: u8,
|
pub r: u8,
|
||||||
pub g: u8,
|
pub g: u8,
|
||||||
@@ -9,6 +9,8 @@ pub struct VoxelColor {
|
|||||||
pub a: u8,
|
pub a: u8,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
unsafe impl bytemuck::Pod for VoxelColor {}
|
||||||
|
|
||||||
impl VoxelColor {
|
impl VoxelColor {
|
||||||
pub fn none() -> Self {
|
pub fn none() -> Self {
|
||||||
Self {
|
Self {
|
||||||
@@ -34,6 +36,9 @@ impl VoxelColor {
|
|||||||
a: 255,
|
a: 255,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
pub fn random() -> Self {
|
||||||
|
rand::random()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Distribution<VoxelColor> for Standard {
|
impl Distribution<VoxelColor> for Standard {
|
||||||
|
|||||||
9
src/client/render/voxel/light.rs
Normal file
9
src/client/render/voxel/light.rs
Normal 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 {}
|
||||||
@@ -1,13 +1,14 @@
|
|||||||
mod grid;
|
|
||||||
mod view;
|
|
||||||
mod color;
|
mod color;
|
||||||
|
mod grid;
|
||||||
mod group;
|
mod group;
|
||||||
|
mod light;
|
||||||
|
mod view;
|
||||||
|
|
||||||
pub use color::*;
|
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::{
|
use crate::client::{
|
||||||
camera::Camera,
|
camera::Camera,
|
||||||
render::{
|
render::{
|
||||||
@@ -15,6 +16,7 @@ use crate::client::{
|
|||||||
CreateVoxelGrid,
|
CreateVoxelGrid,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
use {group::VoxelGroup, view::View};
|
||||||
|
|
||||||
pub struct VoxelPipeline {
|
pub struct VoxelPipeline {
|
||||||
pipeline: wgpu::RenderPipeline,
|
pipeline: wgpu::RenderPipeline,
|
||||||
@@ -23,6 +25,7 @@ pub struct VoxelPipeline {
|
|||||||
bind_group: wgpu::BindGroup,
|
bind_group: wgpu::BindGroup,
|
||||||
voxel_groups: Storage<VoxelGroup>,
|
voxel_groups: Storage<VoxelGroup>,
|
||||||
voxels: Storage<VoxelColor>,
|
voxels: Storage<VoxelColor>,
|
||||||
|
global_lights: Storage<GlobalLight>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl VoxelPipeline {
|
impl VoxelPipeline {
|
||||||
@@ -33,9 +36,17 @@ impl VoxelPipeline {
|
|||||||
source: wgpu::ShaderSource::Wgsl(include_str!("shader.wgsl").into()),
|
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 voxels = Storage::init(device, "voxels", 1);
|
||||||
let voxel_groups = Storage::init(device, "voxel groups", 2);
|
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
|
// bind groups
|
||||||
let bind_group_layout = device.create_bind_group_layout(&wgpu::BindGroupLayoutDescriptor {
|
let bind_group_layout = device.create_bind_group_layout(&wgpu::BindGroupLayoutDescriptor {
|
||||||
@@ -43,6 +54,7 @@ impl VoxelPipeline {
|
|||||||
view.bind_group_layout_entry(),
|
view.bind_group_layout_entry(),
|
||||||
voxels.bind_group_layout_entry(),
|
voxels.bind_group_layout_entry(),
|
||||||
voxel_groups.bind_group_layout_entry(),
|
voxel_groups.bind_group_layout_entry(),
|
||||||
|
global_lights.bind_group_layout_entry(),
|
||||||
],
|
],
|
||||||
label: Some("tile_bind_group_layout"),
|
label: Some("tile_bind_group_layout"),
|
||||||
});
|
});
|
||||||
@@ -53,6 +65,7 @@ impl VoxelPipeline {
|
|||||||
view.bind_group_entry(),
|
view.bind_group_entry(),
|
||||||
voxels.bind_group_entry(),
|
voxels.bind_group_entry(),
|
||||||
voxel_groups.bind_group_entry(),
|
voxel_groups.bind_group_entry(),
|
||||||
|
global_lights.bind_group_entry(),
|
||||||
],
|
],
|
||||||
label: Some("tile_bind_group"),
|
label: Some("tile_bind_group"),
|
||||||
});
|
});
|
||||||
@@ -109,6 +122,7 @@ impl VoxelPipeline {
|
|||||||
bind_group_layout,
|
bind_group_layout,
|
||||||
voxels,
|
voxels,
|
||||||
voxel_groups,
|
voxel_groups,
|
||||||
|
global_lights,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -156,6 +170,7 @@ impl VoxelPipeline {
|
|||||||
self.view.bind_group_entry(),
|
self.view.bind_group_entry(),
|
||||||
self.voxels.bind_group_entry(),
|
self.voxels.bind_group_entry(),
|
||||||
self.voxel_groups.bind_group_entry(),
|
self.voxel_groups.bind_group_entry(),
|
||||||
|
self.global_lights.bind_group_entry(),
|
||||||
],
|
],
|
||||||
label: Some("tile_bind_group"),
|
label: Some("tile_bind_group"),
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -1,5 +1,9 @@
|
|||||||
// Vertex shader
|
// Vertex shader
|
||||||
|
|
||||||
|
struct GlobalLight {
|
||||||
|
dir: vec3<f32>,
|
||||||
|
};
|
||||||
|
|
||||||
struct VertexOutput {
|
struct VertexOutput {
|
||||||
@builtin(position) clip_position: vec4<f32>,
|
@builtin(position) clip_position: vec4<f32>,
|
||||||
@location(0) tex_coords: vec2<f32>,
|
@location(0) tex_coords: vec2<f32>,
|
||||||
@@ -26,6 +30,8 @@ var<uniform> view: View;
|
|||||||
var<storage, read> voxels: array<u32>;
|
var<storage, read> voxels: array<u32>;
|
||||||
@group(0) @binding(2)
|
@group(0) @binding(2)
|
||||||
var<storage, read> voxel_groups: array<VoxelGroup>;
|
var<storage, read> voxel_groups: array<VoxelGroup>;
|
||||||
|
@group(0) @binding(3)
|
||||||
|
var<storage, read> global_lights: array<GlobalLight>;
|
||||||
|
|
||||||
@vertex
|
@vertex
|
||||||
fn vs_main(
|
fn vs_main(
|
||||||
@@ -62,7 +68,7 @@ fn fs_main(
|
|||||||
let dir = view.transform * vec4<f32>(normalize(pixel_pos), 0.0);
|
let dir = view.transform * vec4<f32>(normalize(pixel_pos), 0.0);
|
||||||
|
|
||||||
var color = trace_full(pos, dir);
|
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);
|
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 += vec4<f32>(sky_color * (1.0 - color.a), 1.0 - color.a);
|
||||||
color.a = 1.0;
|
color.a = 1.0;
|
||||||
@@ -73,7 +79,6 @@ const ZERO3F = vec3<f32>(0.0);
|
|||||||
const ZERO2F = vec2<f32>(0.0);
|
const ZERO2F = vec2<f32>(0.0);
|
||||||
const DEPTH = 16u;
|
const DEPTH = 16u;
|
||||||
const FULL_ALPHA = 0.9999;
|
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> {
|
fn trace_full(pos: vec4<f32>, dir: vec4<f32>) -> vec4<f32> {
|
||||||
// GPUs hate this
|
// GPUs hate this
|
||||||
@@ -124,7 +129,6 @@ fn apply_group(
|
|||||||
(group.transform * vec4<f32>(0.0, 0.0, dir_if.z, 0.0)).xyz,
|
(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);
|
var next_normal = vec3<f32>(0.0, 0.0, 0.0);
|
||||||
let norm_light = normalize(GLOBAL_LIGHT);
|
|
||||||
|
|
||||||
// find where ray intersects with group
|
// find where ray intersects with group
|
||||||
let plane_point = (vec3<f32>(1.0) - dir_if) / 2.0 * dim_f;
|
let plane_point = (vec3<f32>(1.0) - dir_if) / 2.0 * dim_f;
|
||||||
@@ -204,10 +208,10 @@ fn apply_group(
|
|||||||
|
|
||||||
// lighting
|
// lighting
|
||||||
let light = trace_light(full_pos);
|
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 ambient = 0.2;
|
||||||
let specular = (exp(max(
|
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;
|
)) - 1.0) * light;
|
||||||
let lighting = max(diffuse * light.a, ambient);
|
let lighting = max(diffuse * light.a, ambient);
|
||||||
let new_rgb = min(vcolor.xyz * lighting + specular.xyz + light.xyz * vcolor.xyz, vec3<f32>(1.0));
|
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(
|
fn trace_light(
|
||||||
pos: vec4<f32>
|
pos: vec4<f32>
|
||||||
) -> 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);
|
var mask = vec4<f32>(0.0);
|
||||||
let start = pos + dir * .001;
|
let start = pos + dir * .001;
|
||||||
for (var gi: u32 = 0; gi < arrayLength(&voxel_groups); gi = gi + 1) {
|
for (var gi: u32 = 0; gi < arrayLength(&voxel_groups); gi = gi + 1) {
|
||||||
|
|||||||
Reference in New Issue
Block a user