Tidy up chunk rendering

This commit is contained in:
Thinkofname 2016-03-24 21:13:24 +00:00
parent c5af132a21
commit 70ccd5cd3d
5 changed files with 61 additions and 64 deletions

View File

@ -16,7 +16,7 @@ pub struct ChunkBuilder {
free_builders: Vec<(usize, Vec<u8>)>, free_builders: Vec<(usize, Vec<u8>)>,
built_recv: mpsc::Receiver<(usize, BuildReply)>, built_recv: mpsc::Receiver<(usize, BuildReply)>,
sections: Vec<(i32, i32, i32, Arc<world::SectionKey>)>, sections: Vec<(i32, i32, i32)>,
next_collection: f64, next_collection: f64,
models: Arc<RwLock<model::Factory>>, models: Arc<RwLock<model::Factory>>,
@ -65,7 +65,9 @@ impl ChunkBuilder {
while let Ok((id, mut val)) = self.built_recv.try_recv() { while let Ok((id, mut val)) = self.built_recv.try_recv() {
world.reset_building_flag(val.position); world.reset_building_flag(val.position);
renderer.update_chunk_solid(val.position, val.key, &val.solid_buffer, val.solid_count); if let Some(render_buffer) = world.get_section_buffer(val.position.0, val.position.1, val.position.2) {
renderer.update_chunk_solid(render_buffer, &val.solid_buffer, val.solid_count);
}
val.solid_buffer.clear(); val.solid_buffer.clear();
self.free_builders.push((id, val.solid_buffer)); self.free_builders.push((id, val.solid_buffer));
@ -96,7 +98,7 @@ impl ChunkBuilder {
self.sections = sections; self.sections = sections;
self.next_collection = 60.0; self.next_collection = 60.0;
} }
while let Some((x, y, z, key)) = self.sections.pop() { while let Some((x, y, z)) = self.sections.pop() {
let t_id = self.free_builders.pop().unwrap(); let t_id = self.free_builders.pop().unwrap();
world.set_building_flag((x, y, z)); world.set_building_flag((x, y, z));
let (cx, cy, cz) = (x << 4, y << 4, z << 4); let (cx, cy, cz) = (x << 4, y << 4, z << 4);
@ -105,7 +107,6 @@ impl ChunkBuilder {
self.threads[t_id.0].0.send(BuildReq { self.threads[t_id.0].0.send(BuildReq {
snapshot: snapshot, snapshot: snapshot,
position: (x, y, z), position: (x, y, z),
key: key,
buffer: t_id.1, buffer: t_id.1,
}).unwrap(); }).unwrap();
if self.free_builders.is_empty() { if self.free_builders.is_empty() {
@ -118,7 +119,6 @@ impl ChunkBuilder {
struct BuildReq { struct BuildReq {
snapshot: world::Snapshot, snapshot: world::Snapshot,
position: (i32, i32, i32), position: (i32, i32, i32),
key: Arc<world::SectionKey>,
buffer: Vec<u8>, buffer: Vec<u8>,
} }
@ -126,7 +126,6 @@ struct BuildReply {
position: (i32, i32, i32), position: (i32, i32, i32),
solid_buffer: Vec<u8>, solid_buffer: Vec<u8>,
solid_count: usize, solid_count: usize,
key: Arc<world::SectionKey>,
} }
fn build_func(id: usize, models: Arc<RwLock<model::Factory>>, work_recv: mpsc::Receiver<BuildReq>, built_send: mpsc::Sender<(usize, BuildReply)>) { fn build_func(id: usize, models: Arc<RwLock<model::Factory>>, work_recv: mpsc::Receiver<BuildReq>, built_send: mpsc::Sender<(usize, BuildReply)>) {
@ -135,7 +134,6 @@ fn build_func(id: usize, models: Arc<RwLock<model::Factory>>, work_recv: mpsc::R
let BuildReq { let BuildReq {
snapshot, snapshot,
position, position,
key,
buffer, buffer,
} = match work_recv.recv() { } = match work_recv.recv() {
Ok(val) => val, Ok(val) => val,
@ -179,7 +177,6 @@ fn build_func(id: usize, models: Arc<RwLock<model::Factory>>, work_recv: mpsc::R
position: position, position: position,
solid_buffer: solid_buffer, solid_buffer: solid_buffer,
solid_count: solid_count, solid_count: solid_count,
key: key,
})).unwrap(); })).unwrap();
} }
} }

View File

@ -14,7 +14,6 @@
#![recursion_limit="200"] #![recursion_limit="200"]
#![feature(const_fn)] #![feature(const_fn)]
#![feature(arc_counts)]
extern crate glutin; extern crate glutin;
extern crate image; extern crate image;
@ -222,7 +221,7 @@ fn main() {
.unwrap() .unwrap()
.tick(&mut ui_container, &mut game.renderer, delta, width as f64); .tick(&mut ui_container, &mut game.renderer, delta, width as f64);
ui_container.tick(&mut game.renderer, delta, width as f64, height as f64); ui_container.tick(&mut game.renderer, delta, width as f64, height as f64);
game.renderer.tick(delta, width, height); game.renderer.tick(&mut game.server.world, delta, width, height);
let _ = window.swap_buffers(); let _ = window.swap_buffers();

View File

@ -60,7 +60,6 @@ pub struct Renderer {
chunk_shader_alpha: ChunkShaderAlpha, chunk_shader_alpha: ChunkShaderAlpha,
trans_shader: TransShader, trans_shader: TransShader,
chunks: HashMap<(i32, i32, i32), ChunkBuffer, BuildHasherDefault<FNVHash>>,
element_buffer: gl::Buffer, element_buffer: gl::Buffer,
element_buffer_size: usize, element_buffer_size: usize,
element_buffer_type: gl::Type, element_buffer_type: gl::Type,
@ -72,18 +71,22 @@ pub struct Renderer {
last_width: u32, last_width: u32,
last_height: u32, last_height: u32,
chunk_gc_timer: f64,
} }
struct ChunkBuffer { pub struct ChunkBuffer {
key: Arc<world::SectionKey>,
position: (i32, i32, i32),
solid: Option<ChunkRenderInfo>, solid: Option<ChunkRenderInfo>,
trans: Option<ChunkRenderInfo>, trans: Option<ChunkRenderInfo>,
} }
impl ChunkBuffer {
pub fn new() -> ChunkBuffer {
ChunkBuffer {
solid: None,
trans: None,
}
}
}
struct ChunkRenderInfo { struct ChunkRenderInfo {
array: gl::VertexArray, array: gl::VertexArray,
buffer: gl::Buffer, buffer: gl::Buffer,
@ -191,7 +194,6 @@ impl Renderer {
chunk_shader_alpha: chunk_shader_alpha, chunk_shader_alpha: chunk_shader_alpha,
trans_shader: trans_shader, trans_shader: trans_shader,
chunks: HashMap::with_hasher(BuildHasherDefault::default()),
element_buffer: gl::Buffer::new(), element_buffer: gl::Buffer::new(),
element_buffer_size: 0, element_buffer_size: 0,
element_buffer_type: gl::UNSIGNED_BYTE, element_buffer_type: gl::UNSIGNED_BYTE,
@ -207,12 +209,10 @@ impl Renderer {
perspective_matrix: cgmath::Matrix4::zero(), perspective_matrix: cgmath::Matrix4::zero(),
trans: None, trans: None,
chunk_gc_timer: 120.0,
} }
} }
pub fn tick(&mut self, delta: f64, width: u32, height: u32) { pub fn tick(&mut self, world: &mut world::World, delta: f64, width: u32, height: u32) {
use std::f64::consts::PI as PI64; use std::f64::consts::PI as PI64;
{ {
let rm = self.resources.read().unwrap(); let rm = self.resources.read().unwrap();
@ -242,20 +242,6 @@ impl Renderer {
self.init_trans(width, height); self.init_trans(width, height);
} }
self.chunk_gc_timer -= delta;
if self.chunk_gc_timer <= 0.0 {
self.chunk_gc_timer = 120.0;
let mut unload_queue = vec![];
for (pos, info) in &self.chunks {
if Arc::strong_count(&info.key) == 1 {
unload_queue.push(*pos);
}
}
for unload in unload_queue {
self.chunks.remove(&unload);
}
}
let trans = self.trans.as_mut().unwrap(); let trans = self.trans.as_mut().unwrap();
trans.main.bind(); trans.main.bind();
@ -283,8 +269,6 @@ impl Renderer {
); );
let camera_matrix = camera_matrix * cgmath::Matrix4::from_nonuniform_scale(-1.0, 1.0, 1.0); let camera_matrix = camera_matrix * cgmath::Matrix4::from_nonuniform_scale(-1.0, 1.0, 1.0);
// TODO Frustum
self.chunk_shader.perspective_matrix.set_matrix4(&self.perspective_matrix); self.chunk_shader.perspective_matrix.set_matrix4(&self.perspective_matrix);
self.chunk_shader.camera_matrix.set_matrix4(&camera_matrix); self.chunk_shader.camera_matrix.set_matrix4(&camera_matrix);
self.chunk_shader.texture.set_int(0); self.chunk_shader.texture.set_int(0);
@ -293,15 +277,11 @@ impl Renderer {
let frustum = collision::Frustum::from_matrix4(self.perspective_matrix * camera_matrix).unwrap(); let frustum = collision::Frustum::from_matrix4(self.perspective_matrix * camera_matrix).unwrap();
for (pos, info) in &self.chunks { for (pos, info) in world.get_render_list(&frustum) {
if let Some(solid) = info.solid.as_ref() { if let Some(solid) = info.solid.as_ref() {
let min = cgmath::Point3::new(pos.0 as f32 * 16.0, -pos.1 as f32 * 16.0, pos.2 as f32 * 16.0); self.chunk_shader.offset.set_int3(pos.0, pos.1 * 4096, pos.2);
let bounds = collision::Aabb3::new(min, min + cgmath::Vector3::new(16.0, -16.0, 16.0)); solid.array.bind();
if frustum.contains(bounds) != collision::Relation::Out { gl::draw_elements(gl::TRIANGLES, solid.count, self.element_buffer_type, 0);
self.chunk_shader.offset.set_int3(pos.0, pos.1 * 4096, pos.2);
solid.array.bind();
gl::draw_elements(gl::TRIANGLES, solid.count, self.element_buffer_type, 0);
}
} }
} }
@ -310,8 +290,12 @@ impl Renderer {
// Cloud rendering // Cloud rendering
// Trans chunk rendering // Trans chunk rendering
self.chunk_shader_alpha.program.use_program();
// TODO: trans chunk shader stuff self.chunk_shader_alpha.perspective_matrix.set_matrix4(&self.perspective_matrix);
self.chunk_shader_alpha.camera_matrix.set_matrix4(&camera_matrix);
self.chunk_shader_alpha.texture.set_int(0);
self.chunk_shader_alpha.light_level.set_float(LIGHT_LEVEL);
self.chunk_shader_alpha.sky_offset.set_float(SKY_OFFSET);
// Copy the depth buffer // Copy the depth buffer
trans.main.bind_read(); trans.main.bind_read();
@ -357,15 +341,8 @@ impl Renderer {
} }
} }
pub fn update_chunk_solid(&mut self, pos: (i32, i32, i32), key: Arc<world::SectionKey>, data: &[u8], count: usize) { pub fn update_chunk_solid(&mut self, buffer: &mut ChunkBuffer, data: &[u8], count: usize) {
self.ensure_element_buffer(count); self.ensure_element_buffer(count);
let buffer = self.chunks.entry(pos).or_insert_with(||ChunkBuffer {
key: key.clone(),
position: pos,
solid: None,
trans: None,
});
buffer.key = key;
if count == 0 { if count == 0 {
if buffer.solid.is_some() { if buffer.solid.is_some() {
buffer.solid = None; buffer.solid = None;

View File

@ -12,8 +12,6 @@
// See the License for the specific language governing permissions and // See the License for the specific language governing permissions and
// limitations under the License. // limitations under the License.
use std::rc::Rc;
use ui; use ui;
use render; use render;
use format::{self, Component, TextComponent}; use format::{self, Component, TextComponent};

View File

@ -14,13 +14,15 @@
pub mod block; pub mod block;
use std::sync::Arc;
use std::collections::HashMap; use std::collections::HashMap;
use std::hash::BuildHasherDefault; use std::hash::BuildHasherDefault;
use types::bit; use types::bit;
use types::nibble; use types::nibble;
use types::hash::FNVHash; use types::hash::FNVHash;
use protocol; use protocol;
use render;
use collision;
use cgmath;
pub mod biome; pub mod biome;
@ -55,13 +57,39 @@ impl World {
} }
} }
pub fn get_dirty_chunk_sections(&mut self) -> Vec<(i32, i32, i32, Arc<SectionKey>)> { pub fn get_render_list(&self, frustum: &collision::Frustum<f32>) -> Vec<((i32, i32, i32), &render::ChunkBuffer)> {
let mut ret = vec![];
for (pos, chunk) in &self.chunks {
for (y, sec) in chunk.sections.iter().enumerate() {
if let Some(sec) = sec.as_ref() {
let pos = (pos.0, y as i32, pos.1);
let min = cgmath::Point3::new(pos.0 as f32 * 16.0, -pos.1 as f32 * 16.0, pos.2 as f32 * 16.0);
let bounds = collision::Aabb3::new(min, min + cgmath::Vector3::new(16.0, -16.0, 16.0));
if frustum.contains(bounds) != collision::Relation::Out {
ret.push((pos, &sec.render_buffer));
}
}
}
}
ret
}
pub fn get_section_buffer(&mut self, x: i32, y: i32, z: i32) -> Option<&mut render::ChunkBuffer> {
if let Some(chunk) = self.chunks.get_mut(&CPos(x, z)) {
if let Some(sec) = chunk.sections[y as usize].as_mut() {
return Some(&mut sec.render_buffer);
}
}
None
}
pub fn get_dirty_chunk_sections(&mut self) -> Vec<(i32, i32, i32)> {
let mut out = vec![]; let mut out = vec![];
for (_, chunk) in &mut self.chunks { for (_, chunk) in &mut self.chunks {
for sec in &mut chunk.sections { for sec in &mut chunk.sections {
if let Some(sec) = sec.as_mut() { if let Some(sec) = sec.as_mut() {
if !sec.building && sec.dirty { if !sec.building && sec.dirty {
out.push((chunk.position.0, sec.y as i32, chunk.position.1, sec.key.clone())); out.push((chunk.position.0, sec.y as i32, chunk.position.1));
} }
} }
} }
@ -391,7 +419,7 @@ pub struct SectionKey {
} }
struct Section { struct Section {
key: Arc<SectionKey>, pub render_buffer: render::ChunkBuffer,
y: u8, y: u8,
blocks: bit::Map, blocks: bit::Map,
@ -408,9 +436,7 @@ struct Section {
impl Section { impl Section {
fn new(x: i32, y: u8, z: i32) -> Section { fn new(x: i32, y: u8, z: i32) -> Section {
let mut section = Section { let mut section = Section {
key: Arc::new(SectionKey{ render_buffer: render::ChunkBuffer::new(),
pos: (x, y, z),
}),
y: y, y: y,
blocks: bit::Map::new(4096, 4), blocks: bit::Map::new(4096, 4),