Compare commits

...

2 commits

6 changed files with 228 additions and 130 deletions

View file

@ -40,7 +40,7 @@ pub struct AppState {
clients: Vec<SimpleObject>,
}
const BLOCKS: i32 = 1;
const BLOCKS: i32 = 4;
impl AppState {
// We don't need this to be async right now,
@ -54,17 +54,24 @@ impl AppState {
.renderer
.as_mut()
.unwrap()
.load_from_gltf(include_bytes!("assets/cube.glb"));
.load_from_gltf(include_bytes!("assets/sphere.glb"));
let block = file.first_object().unwrap();
let skybox = world.renderer.as_mut().unwrap().load_texture_from_bytes(
include_bytes!("assets/skybox1.png"),
include_bytes!("assets/skybox2.png"),
Some(image::ImageFormat::Png),
);
world.renderer.as_mut().unwrap().set_skybox(skybox);
//let color = &renderer.load_texture_from_bytes(include_bytes!("assets/plank/color.png"));
//let normal = &renderer.load_texture_from_bytes(include_bytes!("assets/plank/normal.png"));
//let roughness = &renderer.load_texture_from_bytes(include_bytes!("assets/plank/roughness.png"));
//let mat = renderer.new_material(color,normal,roughness);
world.renderer().set_skybox(skybox);
let color = world
.renderer()
.load_texture_from_bytes(include_bytes!("assets/plank/color.png"), None);
let normal = world
.renderer()
.load_texture_from_bytes(include_bytes!("assets/plank/normal.png"), None);
let roughness = world
.renderer()
.load_texture_from_bytes(include_bytes!("assets/plank/roughness.png"), None);
let mat = world.renderer().new_material(&color, &normal, &roughness);
block.0.borrow_mut().model.as_mut().unwrap().material = mat;
for x in -BLOCKS..BLOCKS {
for y in -BLOCKS..BLOCKS {
let block = block.hard_clone();
@ -72,7 +79,7 @@ impl AppState {
{
let mut model = block.0.borrow_mut();
model.model.as_mut().unwrap().instance.transform = Mat4::from_translation(
Vec3::new(-x as f32 * 3.0, -8.0, -y as f32 * 3.0),
Vec3::new(-x as f32 * 3.0, -2.0, -y as f32 * 3.0),
)
* Mat4::from_rotation_z((x * y) as f32 / 1.23);
model.model.as_mut().unwrap().instance.color = Vec4::new(

View file

@ -88,9 +88,9 @@ var t_rough: texture_2d<f32>;
fn sky_aspect(look: vec3<f32>) -> vec4<f32> {
var pi = 3.14159;
let u_angle = atan2(look.x,look.z);
let u = (u_angle/pi) + 0.5; // from -pi/2 -> pi/2 into 0 -> 1
let u = (u_angle/pi) * 0.5 + 0.5; // from -pi/2 -> pi/2 into 0 -> 1
let v_angle = atan2(-look.y,sqrt(look.x * look.x + look.z * look.z));
let v = (v_angle/pi) + 0.5;//(v_angle/pi) + 0.5; // from -pi/2 -> pi/2 into 0 -> 1
let v = (v_angle/pi) - 0.5;//(v_angle/pi) + 0.5; // from -pi/2 -> pi/2 into 0 -> 1
let uv = vec2<f32>(u,v); // Get UV on skybox
return textureSample(sky_texture, sky_sampler, uv);
}
@ -112,7 +112,9 @@ fn translation(mat: mat4x4<f32>) -> vec4<f32> {
fn fs_main(in: VertexOutput) -> @location(0) vec4<f32> {
let object_color: vec4<f32> = textureSample(t_diffuse, s_diffuse, in.tex_coords);
let object_normal: vec4<f32> = textureSample(t_normal, s_diffuse, in.tex_coords);
let object_rough: vec4<f32> = textureSample(t_rough, s_diffuse, in.tex_coords);
let diffuse_result = object_color.xyz * environment.ambient.xyz;
let diffuse_color = object_color.xyz;
let specular_color = vec3<f32>(0.0,0.0,0.0);
let reflection = sky_aspect(reflect(normalize(in.world_position-translation(eye.frame).xyz),normalize(in.world_normal)));
@ -129,9 +131,15 @@ fn fs_main(in: VertexOutput) -> @location(0) vec4<f32> {
//let specular_strength = pow(max(dot(tangent_normal, half_dir), 0.0), 32.0);
//let specular_color = specular_strength * environment.light.xyz;
let result = (environment.ambient.xyz + diffuse_color.xyz + specular_color.xyz) * object_color.xyz;
let reflect_factor = max(object_rough.x * 0.5,object_rough.y);
return vec4<f32>(reflection.xyz,object_color.a);
let diffuse_brightness = length(diffuse_color);
let diffuse_effect = (diffuse_result * (1 - reflect_factor)) + reflection.xyz * reflect_factor * diffuse_brightness;
let result = (diffuse_effect.xyz + specular_color.xyz);
return vec4<f32>(result.xyz,object_color.a);
}
struct SkyOutput {

BIN
src/assets/skybox2.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 892 KiB

View file

@ -63,7 +63,7 @@ impl Eye {
let dir = Vec3::new(1.0, 0.5, 1.0).normalize();
let environment = Environment {
ambient: Vec4::new(0.15, 0.15, 0.15, 0.0),
ambient: Vec4::new(0.1, 0.1, 0.1, 0.0),
light: Vec4::new(1.0, 1.0, 1.0, 0.0),
dir: Vec4::new(dir.x, dir.y, dir.z, 0.0),
};

View file

@ -826,7 +826,6 @@ impl Renderer {
collider: SimpleColliderData {
transform: Mat4::default(),
shape: Shape::None,
radius: 0.0,
},
})));
if len == 1 {

View file

@ -1,8 +1,7 @@
use crate::render::{Renderer, SimpleLightData, SimpleModelData};
use glam::{DVec3, IVec3, Mat4, UVec3, Vec3, Vec4Swizzles};
use glam::{IVec3, Mat4, Vec3};
use std::cell::RefCell;
use std::hash::{BuildHasherDefault, Hash, Hasher};
use std::ops::{Div, Mul};
use std::rc::Rc;
use wgpu::naga::{FastHashMap, FastHashSet};
@ -17,7 +16,29 @@ pub enum Shape {
pub struct SimpleColliderData {
pub transform: Mat4,
pub shape: Shape,
pub radius: f32,
}
impl SimpleColliderData {
fn aabb(&self) -> Option<AABB> {
let (_scale, _rotation, translation) = self.transform.to_scale_rotation_translation();
match self.shape {
Shape::Block(size) => {
let radius_offset = Vec3::splat(size.length());
Some(AABB(
translation - radius_offset,
translation + radius_offset,
))
}
Shape::Sphere(radius) => {
let radius_offset = Vec3::splat(radius);
Some(AABB(
translation - radius_offset,
translation + radius_offset,
))
}
Shape::None => None,
}
}
}
#[derive(Clone)]
@ -72,157 +93,220 @@ impl Hash for SimpleObject {
}
#[derive(Eq, Hash, PartialEq, Clone)]
enum Interest {
pub enum Interest {
Light(SimpleLight),
Object(SimpleObject),
}
struct Block {
debug: Option<SimpleObject>,
impl Interest {
fn aabb(&self) -> Option<AABB> {
match self {
Interest::Light(light) => {
let data = light.0.borrow();
Some(AABB::new(
data.transform.to_scale_rotation_translation().2,
Vec3::splat(data.instance.color.length()),
))
}
Interest::Object(object) => object.0.borrow().collider.aabb(),
}
}
}
#[derive(Copy, Clone)]
struct Material {
volume: u8,
velocity: Vec3,
material: u8,
interests: FastHashSet<Interest>,
blocks: [Option<Box<Block>>; 64],
}
const TREE_ATTACK: usize = 4;
const TREE_FLOOR: usize = 4;
impl Block {
fn new() -> Block {
Block {
debug: None,
impl Material {
const fn new() -> Material {
Material {
volume: 0,
velocity: Vec3::ZERO,
material: 0,
interests: FastHashSet::with_hasher(BuildHasherDefault::default()),
blocks: [const { None }; const { TREE_ATTACK * TREE_ATTACK * TREE_ATTACK }],
}
}
fn place_pos(&mut self, interest: Interest, pos: Vec3, rad: f32, block_size: f32) {
let cs = block_size / const { TREE_ATTACK as f32 };
if rad < cs || block_size >= TREE_FLOOR as f32 {
let rel = ((pos + block_size / 2.0) / cs).round().as_uvec3();
let new_pos = pos - (rel.as_vec3() + cs / 2.0);
let index = (rel.x + rel.y * 4 + rel.z * 16) as usize;
match self.blocks[index] {
Some(ref mut block) => {
block.place_pos(interest, new_pos, rad, cs);
}
None => {
let mut block = Box::new(Block::new());
block.place_pos(interest, new_pos, rad, cs);
self.blocks[index] = Some(block);
}
}
} else {
self.interests.insert(interest);
}
}
fn debug_step(&mut self, value: bool) {
match self.debug {
Some(ref mut debug) => {
if value {
} else {
}
}
None => {
if value {
} else {
}
}
}
for maybe_block in self.blocks.iter_mut() {
if let Some(block) = maybe_block {
block.debug_step(value)
}
#[derive(Clone, Copy)]
struct AABB(Vec3, Vec3);
impl AABB {
fn new(translation: Vec3, size: Vec3) -> AABB {
AABB(translation - size, translation + size)
}
fn bounded_by(&self, aabb: AABB) -> AABB {
AABB(self.0.max(aabb.0), self.1.min(aabb.1))
}
fn offset(&self) -> Vec3 {
self.1 - self.0
}
}
pub struct World {
chunk_size: u32,
map: FastHashMap<IVec3, Block>,
map: HashedMap,
pub renderer: Option<Renderer>,
debug_world_map: bool,
debug_world_map_object: Option<SimpleObject>,
}
impl World {
pub fn new() -> World {
World {
chunk_size: 512,
map: FastHashMap::with_hasher(BuildHasherDefault::default()),
map: HashedMap::new(),
renderer: None,
debug_world_map: false,
debug_world_map_object: None,
}
}
pub fn renderer(&mut self) -> &mut Renderer {
self.renderer.as_mut().unwrap()
}
pub fn add_renderer(&mut self, renderer: Renderer) {
self.renderer = Some(renderer);
self.debug_world_map_object = self
.renderer
.as_mut()
.unwrap()
.load_from_gltf(include_bytes!("../assets/cube.glb"))
.first_object()
}
pub fn add_object(&mut self, object: SimpleObject) {
self.place(Interest::Object(object.clone()));
if let Some(ref mut renderer) = self.renderer {
renderer.instances.add_object(object)
if let Some(aabb) = object.0.borrow().collider.aabb() {
self.map
.place_with_aabb(Interest::Object(object.clone()), aabb);
}
if let Some(ref mut renderer) = self.renderer
&& object.0.borrow().model.is_some()
{
renderer.instances.add_object(object.clone())
}
}
pub fn set_debug(&mut self, value: bool) {
self.debug_world_map = value;
pub fn remove_object(&mut self, object: SimpleObject) {}
pub fn set_debug(&mut self, value: Option<SimpleObject>) {
for (index, item) in self.map.it.iter_mut() {}
}
pub fn light_step(&mut self) {}
pub fn object_step(&mut self) {}
pub fn debug_step(&mut self) {
self.light_step();
self.object_step();
for (index, item) in self.map.iter_mut() {
item.debug_step(self.debug_world_map);
fn step(&mut self) {}
fn sync(&mut self) {}
}
type VecMap<T> = FastHashMap<IVec3,T>;
struct Level<T,S> {
sub_level:
entries: T
}
struct MatterLevel<T> {
blocks: Option<VecMap<Material>>
}
struct InterestLevel<T> {
blocks: Option<VecMap<Interest>>
}
struct HashedMap {
matter:
}
impl HashedMap {
fn new() -> HashedMap {
HashedMap {
it: FastHashMap::default()
}
}
fn place_pos(&mut self, interest: Interest, pos: Vec3, rad: f32) {
let cs = self.chunk_size as f32;
let c_rad = ((cs / 2.0) * (cs / 2.0)) * 3.0;
for x in (pos.x - rad).div(cs) as i32..=(pos.x + rad).div(cs).ceil() as i32 {
for y in (pos.y - rad).div(cs) as i32..=(pos.y + rad).div(cs).ceil() as i32 {
for z in (pos.z - rad).div(cs) as i32..=(pos.z + rad).div(cs).ceil() as i32 {
let block_pos = IVec3::new(x, y, z);
let block_pos_f32 = block_pos.as_vec3();
if block_pos_f32.distance_squared(pos) < rad + c_rad {
self.map.entry(block_pos).or_insert_with(|| {
let mut block = Block::new();
block.place_pos(
interest.clone(),
pos - block_pos_f32,
rad,
self.chunk_size as f32,
);
block
});
}
}
}
}
}
fn place(&mut self, interest: Interest) {
let (pos, rad) = match &interest {
Interest::Light(light) => {
let light = light.0.borrow();
(light.instance.location.xyz(), light.instance.color.length())
}
Interest::Object(object) => {
let collider = &object.0.borrow().collider;
(
collider.transform.to_scale_rotation_translation().2,
collider.radius,
)
}
};
self.place_pos(interest, pos, rad);
}
}
/*impl Block {
const FLOOR: i32 = 4;
const CHUNK_SIZE: i32 = Block::FLOOR * 64;
const MAX_IDEAL_INTEREST: usize = 4;
fn new() -> Block {
Block {
debug: None,
material: Material::new(),
interests: FastHashSet::default(),
blocks: None,
}
}
}
type Blocks = Box<[Block; 8]>;
struct Block {
debug: Option<SimpleObject>,
interests: FastHashSet<Interest>,
material: Material,
blocks: Option<Blocks>,
}
impl Block {
pub fn set_debug(&mut self, value: Option<SimpleObject>, pos: Vec3, size: f32) {}
}
pub trait WorldMap {
fn new() -> Self;
fn place_with_aabb(&mut self, interest: Interest, aabb: AABB);
}
struct OctreeMap {
it: FastHashMap<IVec3, Block>,
}
impl OctreeMap {
fn place_with_index(&mut self, interest: Interest, mut index: IVec3) {
let chunk_index = (index + IVec3::splat(Block::CHUNK_SIZE / 2)) / Block::CHUNK_SIZE;
let mut block = self.it.entry(chunk_index).or_insert_with(|| Block::new());
let mut offset_size = Block::CHUNK_SIZE / 4;
index = index - chunk_index * Block::CHUNK_SIZE;
while index != IVec3::ZERO {
let blocks = if let Some(ref mut blocks) = block.blocks {
blocks
} else if block.interests.len() < Block::MAX_IDEAL_INTEREST {
block.interests.insert(interest.clone());
return;
} else {
block.blocks = Some(Box::new(core::array::from_fn(|_| Block::new())));
block.blocks.as_mut().unwrap()
};
let mut block_index = 0;
if index.x < 0 {
index.x += offset_size;
} else {
index.x -= offset_size;
block_index += 1;
}
if index.y < 0 {
index.y += offset_size;
} else {
index.y -= offset_size;
block_index += 2;
}
if index.z < 0 {
index.z += offset_size;
} else {
index.z -= offset_size;
block_index += 4;
}
block = &mut blocks[block_index];
offset_size /= 2;
}
block.interests.insert(interest.clone());
}
}
impl WorldMap for OctreeMap {
fn place_with_aabb(&mut self, interest: Interest, aabb: AABB) {
let mut d = 4;
let offset = aabb.1 - aabb.0;
while offset.element_sum() > (d * 2) as f32 {
d *= 2
}
let iaabb0 = (aabb.0 / d as f32).floor().as_ivec3();
let iaabb1 = (aabb.1 / d as f32).ceil().as_ivec3();
for x in iaabb0.x..iaabb1.x {
for y in iaabb0.y..iaabb1.y {
for z in iaabb0.z..iaabb1.z {
self.place_with_index(interest.clone(), IVec3::new(x, y, z) * d as i32);
}
}
}
}
fn new() -> OctreeMap {
OctreeMap {
it: FastHashMap::with_hasher(BuildHasherDefault::default()),
}
}
}*/