Transparent renderering

This commit is contained in:
Thinkofname 2016-03-25 01:17:03 +00:00
parent 93abbcc7cb
commit d7bc0b2b0f
4 changed files with 112 additions and 20 deletions

View File

@ -14,7 +14,7 @@ const NUM_WORKERS: usize = 8;
pub struct ChunkBuilder {
threads: Vec<(mpsc::Sender<BuildReq>, thread::JoinHandle<()>)>,
free_builders: Vec<(usize, Vec<u8>)>,
free_builders: Vec<(usize, Vec<u8>, Vec<u8>)>,
built_recv: mpsc::Receiver<(usize, BuildReply)>,
models: Arc<RwLock<model::Factory>>,
@ -35,7 +35,7 @@ impl ChunkBuilder {
let models = models.clone();
let id = i;
threads.push((work_send, thread::spawn(move || build_func(id, models, work_recv, built_send))));
free.push((i, vec![]));
free.push((i, vec![], vec![]));
}
ChunkBuilder {
threads: threads,
@ -62,10 +62,12 @@ impl ChunkBuilder {
if let Some(sec) = world.get_section_mut(val.position.0, val.position.1, val.position.2) {
sec.cull_info = val.cull_info;
renderer.update_chunk_solid(&mut sec.render_buffer, &val.solid_buffer, val.solid_count);
renderer.update_chunk_trans(&mut sec.render_buffer, &val.trans_buffer, val.trans_count);
}
val.solid_buffer.clear();
self.free_builders.push((id, val.solid_buffer));
val.trans_buffer.clear();
self.free_builders.push((id, val.solid_buffer, val.trans_buffer));
}
if self.free_builders.is_empty() {
return;
@ -83,7 +85,8 @@ impl ChunkBuilder {
self.threads[t_id.0].0.send(BuildReq {
snapshot: snapshot,
position: (x, y, z),
buffer: t_id.1,
solid_buffer: t_id.1,
trans_buffer: t_id.2,
}).unwrap();
if self.free_builders.is_empty() {
return;
@ -95,13 +98,16 @@ impl ChunkBuilder {
struct BuildReq {
snapshot: world::Snapshot,
position: (i32, i32, i32),
buffer: Vec<u8>,
solid_buffer: Vec<u8>,
trans_buffer: Vec<u8>,
}
struct BuildReply {
position: (i32, i32, i32),
solid_buffer: Vec<u8>,
solid_count: usize,
trans_buffer: Vec<u8>,
trans_count: usize,
cull_info: CullInfo,
}
@ -111,7 +117,8 @@ fn build_func(id: usize, models: Arc<RwLock<model::Factory>>, work_recv: mpsc::R
let BuildReq {
snapshot,
position,
buffer,
mut solid_buffer,
mut trans_buffer,
} = match work_recv.recv() {
Ok(val) => val,
Err(_) => return,
@ -124,14 +131,15 @@ fn build_func(id: usize, models: Arc<RwLock<model::Factory>>, work_recv: mpsc::R
(position.0 as u32 ^ position.2 as u32) | 1,
]);
let mut solid_buffer = buffer;
let mut solid_count = 0;
let mut trans_count = 0;
for y in 0 .. 16 {
for x in 0 .. 16 {
for z in 0 .. 16 {
let block = snapshot.get_block(x, y, z);
if !block.get_material().renderable {
let mat = block.get_material();
if !mat.renderable {
// Use one step of the rng so that
// if a block is placed in an empty
// location is variant doesn't change
@ -142,10 +150,17 @@ fn build_func(id: usize, models: Arc<RwLock<model::Factory>>, work_recv: mpsc::R
// TODO Liquids need a special case
let model_name = block.get_model();
let variant = block.get_model_variant();
solid_count += model::Factory::get_state_model(
&models, &model_name.0, &model_name.1, &variant, &mut rng,
&snapshot, x, y, z, &mut solid_buffer
);
if !mat.transparent {
solid_count += model::Factory::get_state_model(
&models, &model_name.0, &model_name.1, &variant, &mut rng,
&snapshot, x, y, z, &mut solid_buffer
);
} else {
trans_count += model::Factory::get_state_model(
&models, &model_name.0, &model_name.1, &variant, &mut rng,
&snapshot, x, y, z, &mut trans_buffer
);
}
}
}
}
@ -156,6 +171,8 @@ fn build_func(id: usize, models: Arc<RwLock<model::Factory>>, work_recv: mpsc::R
position: position,
solid_buffer: solid_buffer,
solid_count: solid_count,
trans_buffer: trans_buffer,
trans_count: trans_count,
cull_info: cull_info,
})).unwrap();
}

View File

@ -320,16 +320,24 @@ impl Renderer {
gl::ClearFlags::Depth, gl::NEAREST
);
trans.trans.bind();
gl::enable(gl::BLEND);
gl::depth_mask(false);
trans.trans.bind();
gl::clear_color(0.0, 0.0, 0.0, 1.0);
gl::clear(gl::ClearFlags::Color);
gl::clear_buffer(gl::COLOR, 0, &[0.0, 0.0, 0.0, 1.0]);
gl::clear_buffer(gl::COLOR, 1, &[0.0, 0.0, 0.0, 0.0]);
gl::blend_func_separate(gl::ONE_FACTOR, gl::ONE_FACTOR, gl::ZERO_FACTOR, gl::ONE_MINUS_SRC_ALPHA);
// TODO: Draw chunks
for (pos, info) in world.get_render_list().into_iter().rev() {
if let Some(trans) = info.trans.as_ref() {
if trans.count > 0 {
self.chunk_shader_alpha.offset.set_int3(pos.0, pos.1 * 4096, pos.2);
trans.array.bind();
gl::draw_elements(gl::TRIANGLES, trans.count, self.element_buffer_type, 0);
}
}
}
gl::unbind_framebuffer();
gl::disable(gl::DEPTH_TEST);
@ -402,6 +410,51 @@ impl Renderer {
info.count = count;
}
pub fn update_chunk_trans(&mut self, buffer: &mut ChunkBuffer, data: &[u8], count: usize) {
self.ensure_element_buffer(count);
if count == 0 {
if buffer.trans.is_some() {
buffer.trans = None;
}
return;
}
let new = buffer.trans.is_none();
if buffer.trans.is_none() {
buffer.trans = Some(ChunkRenderInfo {
array: gl::VertexArray::new(),
buffer: gl::Buffer::new(),
buffer_size: 0,
count: 0,
});
}
let info = buffer.trans.as_mut().unwrap();
info.array.bind();
self.chunk_shader_alpha.position.enable();
self.chunk_shader_alpha.texture_info.enable();
self.chunk_shader_alpha.texture_offset.enable();
self.chunk_shader_alpha.color.enable();
self.chunk_shader_alpha.lighting.enable();
self.element_buffer.bind(gl::ELEMENT_ARRAY_BUFFER);
info.buffer.bind(gl::ARRAY_BUFFER);
if new || info.buffer_size < data.len() {
info.buffer_size = data.len();
info.buffer.set_data(gl::ARRAY_BUFFER, data, gl::DYNAMIC_DRAW);
} else {
info.buffer.re_set_data(gl::ARRAY_BUFFER, data);
}
self.chunk_shader_alpha.position.vertex_pointer(3, gl::FLOAT, false, 40, 0);
self.chunk_shader_alpha.texture_info.vertex_pointer(4, gl::UNSIGNED_SHORT, false, 40, 12);
self.chunk_shader_alpha.texture_offset.vertex_pointer(3, gl::SHORT, false, 40, 20);
self.chunk_shader_alpha.color.vertex_pointer(3, gl::UNSIGNED_BYTE, true, 40, 28);
self.chunk_shader_alpha.lighting.vertex_pointer(2, gl::UNSIGNED_SHORT, false, 40, 32);
info.count = count;
}
fn do_pending_textures(&mut self) {
let len = {
let tex = self.textures.read().unwrap();
@ -483,7 +536,7 @@ impl Renderer {
fn init_trans(&mut self, width: u32, height: u32) {
self.trans = None;
self.trans = Some(TransInfo::new(width, height, &self.trans_shader));
self.trans = Some(TransInfo::new(width, height, &self.chunk_shader_alpha, &self.trans_shader));
}
pub fn get_textures(&self) -> Arc<RwLock<TextureManager>> {
@ -559,7 +612,7 @@ init_shader! {
}
impl TransInfo {
pub fn new(width: u32, height: u32, shader: &TransShader) -> TransInfo {
pub fn new(width: u32, height: u32, chunk_shader: &ChunkShaderAlpha, shader: &TransShader) -> TransInfo {
let trans = gl::Framebuffer::new();
trans.bind();
@ -584,9 +637,9 @@ impl TransInfo {
trans_depth.set_parameter(gl::TEXTURE_2D, gl::TEXTURE_MAX_LEVEL, gl::LINEAR);
trans.texture_2d(gl::DEPTH_ATTACHMENT, gl::TEXTURE_2D, &trans_depth, 0);
shader.program.use_program();
gl::bind_frag_data_location(&shader.program, 0, "accum");
gl::bind_frag_data_location(&shader.program, 1, "revealage");
chunk_shader.program.use_program();
gl::bind_frag_data_location(&chunk_shader.program, 0, "accum");
gl::bind_frag_data_location(&chunk_shader.program, 1, "revealage");
gl::draw_buffers(&[gl::COLOR_ATTACHMENT_0, gl::COLOR_ATTACHMENT_1]);
@ -605,6 +658,7 @@ impl TransInfo {
gl::unbind_framebuffer();
shader.program.use_program();
let array = gl::VertexArray::new();
array.bind();
let buffer = gl::Buffer::new();

View File

@ -212,6 +212,7 @@ pub struct Material {
pub renderable: bool,
pub should_cull_against: bool,
pub force_shade: bool,
pub transparent: bool,
}
#[derive(Clone, Copy)]
@ -229,6 +230,7 @@ define_blocks! {
renderable: false,
should_cull_against: false,
force_shade: false,
transparent: false,
},
model { ("minecraft", "air" ) },
}
@ -246,6 +248,7 @@ define_blocks! {
renderable: true,
should_cull_against: true,
force_shade: false,
transparent: false,
},
model { ("minecraft", variant.as_string() ) },
}
@ -258,6 +261,7 @@ define_blocks! {
renderable: true,
should_cull_against: true,
force_shade: false,
transparent: false,
},
model { ("minecraft", "grass" ) },
variant format!("snowy={}", snowy),
@ -270,6 +274,7 @@ define_blocks! {
renderable: true,
should_cull_against: true,
force_shade: false,
transparent: false,
},
model { ("minecraft", "dirt" ) },
}
@ -280,6 +285,7 @@ define_blocks! {
renderable: true,
should_cull_against: true,
force_shade: false,
transparent: false,
},
model { ("minecraft", "cobblestone" ) },
}
@ -290,6 +296,7 @@ define_blocks! {
renderable: true,
should_cull_against: true,
force_shade: false,
transparent: false,
},
model { ("minecraft", "planks" ) },
}
@ -300,6 +307,7 @@ define_blocks! {
renderable: true,
should_cull_against: false,
force_shade: false,
transparent: false,
},
model { ("minecraft", "sapling" ) },
}
@ -310,6 +318,7 @@ define_blocks! {
renderable: true,
should_cull_against: true,
force_shade: false,
transparent: false,
},
model { ("minecraft", "bedrock" ) },
}
@ -320,6 +329,7 @@ define_blocks! {
renderable: true,
should_cull_against: true,
force_shade: false,
transparent: false,
},
model { ("minecraft", "water" ) },
}
@ -330,6 +340,7 @@ define_blocks! {
renderable: true,
should_cull_against: true,
force_shade: false,
transparent: false,
},
model { ("minecraft", "water" ) },
}
@ -340,6 +351,7 @@ define_blocks! {
renderable: true,
should_cull_against: true,
force_shade: false,
transparent: false,
},
model { ("minecraft", "lava" ) },
}
@ -350,6 +362,7 @@ define_blocks! {
renderable: true,
should_cull_against: true,
force_shade: false,
transparent: false,
},
model { ("minecraft", "lava" ) },
}
@ -360,6 +373,7 @@ define_blocks! {
renderable: true,
should_cull_against: true,
force_shade: false,
transparent: false,
},
model { ("minecraft", "sand" ) },
}
@ -370,6 +384,7 @@ define_blocks! {
renderable: true,
should_cull_against: true,
force_shade: false,
transparent: false,
},
model { ("minecraft", "gravel" ) },
}
@ -380,6 +395,7 @@ define_blocks! {
renderable: true,
should_cull_against: true,
force_shade: false,
transparent: false,
},
model { ("minecraft", "gold_ore" ) },
}
@ -390,6 +406,7 @@ define_blocks! {
renderable: true,
should_cull_against: true,
force_shade: false,
transparent: false,
},
model { ("minecraft", "iron_ore" ) },
}
@ -400,6 +417,7 @@ define_blocks! {
renderable: true,
should_cull_against: true,
force_shade: false,
transparent: false,
},
model { ("minecraft", "coal_ore" ) },
}
@ -416,6 +434,7 @@ define_blocks! {
renderable: true,
should_cull_against: true,
force_shade: false,
transparent: false,
},
model { ("minecraft", format!("{}_log", variant.as_string()) ) },
variant format!("axis={}", axis.as_string()),
@ -437,6 +456,7 @@ define_blocks! {
renderable: true,
should_cull_against: false,
force_shade: true,
transparent: false,
},
model { ("minecraft", format!("{}_leaves", variant.as_string()) ) },
tint TintType::Foliage,
@ -448,6 +468,7 @@ define_blocks! {
renderable: true,
should_cull_against: true,
force_shade: false,
transparent: false,
},
model { ("steven", "missing_block" ) },
}

View File

@ -514,7 +514,7 @@ pub struct 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 {
cull_info: chunk_builder::CullInfo::all_vis(),
render_buffer: render::ChunkBuffer::new(),