Applied good ideas from experimental branch

This commit is contained in:
Joshua Barretto 2020-02-23 15:30:45 +00:00
parent 58587b6854
commit be775c9484
9 changed files with 112 additions and 68 deletions

View File

@ -38,14 +38,14 @@ vec3 lod_pos(vec2 v_pos) {
vec3 lod_norm(vec2 pos) {
float alt00 = alt_at(pos);
float alt10 = alt_at(pos + vec2(100, 0));
float alt01 = alt_at(pos + vec2(0, 100));
float alt10 = alt_at(pos + vec2(32, 0));
float alt01 = alt_at(pos + vec2(0, 32));
float slope = abs(alt00 - alt10) + abs(alt00 - alt01);
return normalize(vec3(
(alt00 - alt10) / 100,
(alt00 - alt01) / 100,
100 / (slope + 0.00001) // Avoid NaN
(alt00 - alt10) / 32,
(alt00 - alt01) / 32,
32 / (slope + 0.00001) // Avoid NaN
));
}

View File

@ -15,7 +15,7 @@ out vec3 f_pos;
out float f_light;
void main() {
f_pos = lod_pos(v_pos + vec2(0, -v_pos.x * 0.5));
f_pos = lod_pos(v_pos);
f_pos.z -= 1.0 / pow(distance(focus_pos.xy, f_pos.xy) / (view_distance.x * 0.95), 20.0);

View File

@ -24,6 +24,7 @@ pub mod npc;
pub mod path;
pub mod ray;
pub mod region;
pub mod spiral;
pub mod state;
pub mod sync;
pub mod sys;

35
common/src/spiral.rs Normal file
View File

@ -0,0 +1,35 @@
use vek::*;
#[derive(Clone)]
pub struct Spiral2d {
layer: i32,
i: i32,
}
impl Spiral2d {
pub fn new() -> Self { Self { layer: 0, i: 0 } }
}
impl Iterator for Spiral2d {
type Item = Vec2<i32>;
fn next(&mut self) -> Option<Self::Item> {
let layer_size = (self.layer * 8 + 4 * self.layer.min(1) - 4).max(1);
if self.i >= layer_size {
self.layer += 1;
self.i = 0;
}
let layer_size = (self.layer * 8 + 4 * self.layer.min(1) - 4).max(1);
let pos = Vec2::new(
-self.layer + (self.i - (layer_size / 4) * 0).max(0).min(self.layer * 2)
- (self.i - (layer_size / 4) * 2).max(0).min(self.layer * 2),
-self.layer + (self.i - (layer_size / 4) * 1).max(0).min(self.layer * 2)
- (self.i - (layer_size / 4) * 3).max(0).min(self.layer * 2),
);
self.i += 1;
Some(pos)
}
}

View File

@ -1,4 +1,5 @@
use super::Pipeline;
use std::iter::FromIterator;
/// A `Vec`-based mesh structure used to store mesh data on the CPU.
#[derive(Clone)]
@ -57,6 +58,24 @@ impl<P: Pipeline> Mesh<P> {
}
}
impl<P: Pipeline> FromIterator<Tri<P>> for Mesh<P> {
fn from_iter<I: IntoIterator<Item = Tri<P>>>(tris: I) -> Self {
tris.into_iter().fold(Self::new(), |mut this, tri| {
this.push_tri(tri);
this
})
}
}
impl<P: Pipeline> FromIterator<Quad<P>> for Mesh<P> {
fn from_iter<I: IntoIterator<Item = Quad<P>>>(quads: I) -> Self {
quads.into_iter().fold(Self::new(), |mut this, quad| {
this.push_quad(quad);
this
})
}
}
/// Represents a triangle stored on the CPU.
pub struct Tri<P: Pipeline> {
a: P::Vertex,
@ -80,4 +99,18 @@ impl<P: Pipeline> Quad<P> {
pub fn new(a: P::Vertex, b: P::Vertex, c: P::Vertex, d: P::Vertex) -> Self {
Self { a, b, c, d }
}
pub fn rotated_by(self, n: usize) -> Self
where
P::Vertex: Clone,
{
let verts = [self.a, self.b, self.c, self.d];
Self {
a: verts[(0 + n) % 4].clone(),
b: verts[(1 + n) % 4].clone(),
c: verts[(2 + n) % 4].clone(),
d: verts[(3 + n) % 4].clone(),
}
}
}

View File

@ -3,6 +3,7 @@ use crate::render::{
Consts, FilterMethod, Globals, LodTerrainPipeline, Mesh, Model, Quad, Renderer, Texture,
};
use client::Client;
use common::spiral::Spiral2d;
use vek::*;
pub struct Lod {
@ -30,22 +31,25 @@ impl Lod {
}
fn create_lod_terrain_mesh(detail: usize) -> Mesh<LodTerrainPipeline> {
let transform = |x| (2.0 * x as f32) / detail as f32 - 1.0;
Spiral2d::new()
.take(detail * detail)
.map(|pos| {
let x = pos.x + detail as i32 / 2;
let y = pos.y + detail as i32 / 2;
let mut mesh = Mesh::new();
let transform = |x| (2.0 * x as f32) / detail as f32 - 1.0;
for x in 0..detail {
for y in 0..detail {
if Vec2::new(x, y).map(transform).magnitude() <= 1.0 {
mesh.push_quad(Quad::new(
Vertex::new(Vec2::new(x + 0, y + 0).map(transform)),
Vertex::new(Vec2::new(x + 1, y + 0).map(transform)),
Vertex::new(Vec2::new(x + 1, y + 1).map(transform)),
Vertex::new(Vec2::new(x + 0, y + 1).map(transform)),
));
}
}
}
mesh
Quad::new(
Vertex::new(Vec2::new(x + 0, y + 0).map(transform)),
Vertex::new(Vec2::new(x + 1, y + 0).map(transform)),
Vertex::new(Vec2::new(x + 1, y + 1).map(transform)),
Vertex::new(Vec2::new(x + 0, y + 1).map(transform)),
)
.rotated_by(if (x > detail as i32 / 2) ^ (y > detail as i32 / 2) {
0
} else {
1
})
})
.collect()
}

View File

@ -329,6 +329,13 @@ impl Scene {
/// Render the scene using the provided `Renderer`.
pub fn render(&mut self, renderer: &mut Renderer, client: &mut Client) {
// Render terrain and figures.
self.terrain.render(
renderer,
&self.globals,
&self.lights,
&self.shadows,
self.camera.get_focus_pos(),
);
self.figure_mgr.render(
renderer,
client,
@ -337,13 +344,6 @@ impl Scene {
&self.shadows,
&self.camera,
);
self.terrain.render(
renderer,
&self.globals,
&self.lights,
&self.shadows,
self.camera.get_focus_pos(),
);
self.lod.render(renderer, &self.globals);
// Render the skybox.

View File

@ -10,6 +10,7 @@ use client::Client;
use common::{
assets,
figure::Segment,
spiral::Spiral2d,
terrain::{Block, BlockKind, TerrainChunk},
vol::{BaseVol, ReadVol, RectRasterableVol, SampleVol, Vox},
volumes::vol_grid_2d::{VolGrid2d, VolGrid2dError},
@ -1404,9 +1405,11 @@ impl<V: RectRasterableVol> Terrain<V> {
if *n >= chunks.len() {
None
} else {
*n += 1;
let pos = focus_chunk + rpos;
Some(chunks.get(&pos).map(|c| (pos, c)))
Some(chunks.get(&pos).map(|c| {
*n += 1;
(pos, c)
}))
}
})
.filter_map(|x| x);
@ -1443,9 +1446,11 @@ impl<V: RectRasterableVol> Terrain<V> {
if *n >= chunks.len() {
None
} else {
*n += 1;
let pos = focus_chunk + rpos;
Some(chunks.get(&pos).map(|c| (pos, c)))
Some(chunks.get(&pos).map(|c| {
*n += 1;
(pos, c)
}))
}
})
.filter_map(|x| x);
@ -1488,37 +1493,3 @@ impl<V: RectRasterableVol> Terrain<V> {
});
}
}
#[derive(Clone)]
struct Spiral2d {
layer: i32,
i: i32,
}
impl Spiral2d {
pub fn new() -> Self { Self { layer: 0, i: 0 } }
}
impl Iterator for Spiral2d {
type Item = Vec2<i32>;
fn next(&mut self) -> Option<Self::Item> {
let layer_size = (self.layer * 8 + 4 * self.layer.min(1) - 4).max(1);
if self.i >= layer_size {
self.layer += 1;
self.i = 0;
}
let layer_size = (self.layer * 8 + 4 * self.layer.min(1) - 4).max(1);
let pos = Vec2::new(
-self.layer + (self.i - (layer_size / 4) * 0).max(0).min(self.layer * 2)
- (self.i - (layer_size / 4) * 2).max(0).min(self.layer * 2),
-self.layer + (self.i - (layer_size / 4) * 1).max(0).min(self.layer * 2)
- (self.i - (layer_size / 4) * 3).max(0).min(self.layer * 2),
);
self.i += 1;
Some(pos)
}
}

View File

@ -291,7 +291,7 @@ impl MapConfig {
),
};
let rgba = (rgb.0, rgb.1, rgb.2, (255.0 * alt) as u8);
let rgba = (rgb.0, rgb.1, rgb.2, (255.0 * alt.max(water_alt)) as u8);
write_pixel(Vec2::new(i, j), rgba);
});