Initial rendering implementation

This commit is contained in:
Thinkofname 2016-03-19 17:34:12 +00:00
parent ad81ef8f17
commit 6bee18b68c
6 changed files with 161 additions and 14 deletions

View File

@ -35,9 +35,12 @@ impl ChunkBuilder {
}
}
pub fn tick(&mut self, world: &mut world::World) {
pub fn tick(&mut self, world: &mut world::World, renderer: &mut render::Renderer) {
while let Ok((id, val)) = self.built_recv.try_recv() {
world.reset_building_flag(val.position);
renderer.update_chunk_solid(val.position, &val.solid_buffer, val.solid_count);
self.free_builders.push(id);
}
if self.free_builders.is_empty() {
@ -67,17 +70,21 @@ struct BuildReq {
struct BuildReply {
position: (i32, i32, i32),
solid_buffer: Vec<u8>,
solid_count: usize,
}
fn build_func(id: usize, textures: Arc<RwLock<render::TextureManager>>, work_recv: mpsc::Receiver<BuildReq>, built_send: mpsc::Sender<(usize, BuildReply)>) {
use rand::{self, Rng};
loop {
let BuildReq {
snapshot,
position,
} = work_recv.recv().unwrap();
println!("Build request for {:?}", position);
let mut solid_buffer = vec![];
let mut solid_count = 0;
let mut rng = rand::thread_rng();
for y in 0 .. 16 {
for x in 0 .. 16 {
@ -88,9 +95,14 @@ fn build_func(id: usize, textures: Arc<RwLock<render::TextureManager>>, work_rec
}
for verts in &PRECOMPUTED_VERTS {
let stone = render::Renderer::get_texture(&textures, rng.choose(&[
"minecraft:blocks/lava_flow",
"minecraft:blocks/stone",
"minecraft:blocks/melon_side",
"minecraft:blocks/sand",
]).unwrap());
solid_count += 6;
for vert in verts {
let stone = render::Renderer::get_texture(&textures, "minecraft:blocks/stone");
let mut vert = vert.clone();
// TODO
vert.r = 255;
@ -101,6 +113,9 @@ fn build_func(id: usize, textures: Arc<RwLock<render::TextureManager>>, work_rec
vert.y += y as f32;
vert.z += z as f32;
vert.toffsetx *= stone.get_width() as i16 * 16;
vert.toffsety *= stone.get_height() as i16 * 16;
// TODO
vert.block_light = 15 * 4000;
vert.sky_light = 15 * 4000;
@ -119,10 +134,10 @@ fn build_func(id: usize, textures: Arc<RwLock<render::TextureManager>>, work_rec
}
}
println!("> Build request for {:?}", position);
built_send.send((id, BuildReply {
position: position,
solid_buffer: solid_buffer,
solid_count: solid_count,
})).unwrap();
}
}
@ -138,7 +153,7 @@ const PRECOMPUTED_VERTS: [[BlockVertex; 4]; 6] = [
BlockVertex::base(0.0, 0.0, 0.0, 0, 1),
BlockVertex::base(0.0, 0.0, 1.0, 0, 0),
BlockVertex::base(1.0, 0.0, 0.0, 1, 1),
BlockVertex::base(1.0, 0.0, 1.0, 1, 1),
BlockVertex::base(1.0, 0.0, 1.0, 1, 0),
],
[ // North
BlockVertex::base(0.0, 0.0, 0.0, 1, 1),

View File

@ -124,13 +124,13 @@ fn main() {
let textures = renderer.get_textures();
let mut game = Game {
server: server::Server::dummy_server(resource_manager.clone()),
renderer: renderer,
screen_sys: screen_sys,
resource_manager: resource_manager,
console: con,
should_close: false,
mouse_pos: (0, 0),
server: server::Server::dummy_server(),
chunk_builder: chunk_builder::ChunkBuilder::new(textures),
};
@ -145,7 +145,18 @@ fn main() {
let delta = (diff.num_nanoseconds().unwrap() as f64) / frame_time;
let (width, height) = window.get_inner_size_pixels().unwrap();
game.chunk_builder.tick(&mut game.server.world);
// TODO: TEMP
game.renderer.camera.pos.x = 0.5;
game.renderer.camera.pos.z = 0.5;
game.renderer.camera.pos.y = 15.0;
game.renderer.camera.yaw += 0.005 * delta;
if game.renderer.camera.yaw > ::std::f64::consts::PI * 2.0 {
game.renderer.camera.yaw = 0.0;
}
game.server.tick();
game.chunk_builder.tick(&mut game.server.world, &mut game.renderer);
game.screen_sys.tick(delta, &mut game.renderer, &mut ui_container);
game.console

View File

@ -20,6 +20,7 @@ pub mod ui;
use std::collections::HashMap;
use std::sync::{Arc, RwLock};
use std::io::Write;
use resources;
use gl;
use image;
@ -54,7 +55,12 @@ pub struct Renderer {
chunk_shader_alpha: ChunkShaderAlpha,
trans_shader: TransShader,
camera: Camera,
chunks: HashMap<(i32, i32, i32), ChunkBuffer>,
element_buffer: gl::Buffer,
element_buffer_size: usize,
element_buffer_type: gl::Type,
pub camera: Camera,
perspective_matrix: cgmath::Matrix4<f32>,
trans: Option<TransInfo>,
@ -63,6 +69,20 @@ pub struct Renderer {
last_height: u32,
}
struct ChunkBuffer {
position: (i32, i32, i32),
solid: Option<ChunkRenderInfo>,
trans: Option<ChunkRenderInfo>,
}
struct ChunkRenderInfo {
array: gl::VertexArray,
buffer: gl::Buffer,
buffer_size: usize,
count: usize,
}
init_shader! {
Program ChunkShader {
vert = "chunk_vertex",
@ -163,6 +183,11 @@ impl Renderer {
chunk_shader_alpha: chunk_shader_alpha,
trans_shader: trans_shader,
chunks: HashMap::new(),
element_buffer: gl::Buffer::new(),
element_buffer_size: 0,
element_buffer_type: gl::UNSIGNED_BYTE,
last_width: 0,
last_height: 0,
@ -242,6 +267,14 @@ impl Renderer {
self.chunk_shader.light_level.set_float(LIGHT_LEVEL);
self.chunk_shader.sky_offset.set_float(SKY_OFFSET);
for (pos, info) in &self.chunks {
if let Some(solid) = info.solid.as_ref() {
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);
}
}
// Line rendering
// Model rendering
// Cloud rendering
@ -284,6 +317,67 @@ impl Renderer {
self.ui.tick(width, height);
}
fn ensure_element_buffer(&mut self, size: usize) {
if self.element_buffer_size < size {
let (data, ty) = self::generate_element_buffer(size);
self.element_buffer_type = ty;
self.element_buffer.bind(gl::ELEMENT_ARRAY_BUFFER);
self.element_buffer.set_data(gl::ELEMENT_ARRAY_BUFFER, &data, gl::DYNAMIC_DRAW);
self.element_buffer_size = size;
}
}
pub fn update_chunk_solid(&mut self, pos: (i32, i32, i32), data: &[u8], count: usize) {
self.ensure_element_buffer(count);
let buffer = self.chunks.entry(pos).or_insert(ChunkBuffer {
position: pos,
solid: None,
trans: None,
});
if count == 0 {
if buffer.solid.is_some() {
buffer.solid = None;
}
return;
}
let new = buffer.solid.is_none();
if buffer.solid.is_none() {
buffer.solid = Some(ChunkRenderInfo {
array: gl::VertexArray::new(),
buffer: gl::Buffer::new(),
buffer_size: 0,
count: 0,
});
}
let info = buffer.solid.as_mut().unwrap();
info.array.bind();
self.chunk_shader.position.enable();
self.chunk_shader.texture_info.enable();
self.chunk_shader.texture_offset.enable();
self.chunk_shader.color.enable();
self.chunk_shader.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 {
let mut target = info.buffer.map(gl::ARRAY_BUFFER, gl::WRITE_ONLY, data.len());
target.write_all(data).unwrap();
}
self.chunk_shader.position.vertex_pointer(3, gl::FLOAT, false, 40, 0);
self.chunk_shader.texture_info.vertex_pointer(4, gl::UNSIGNED_SHORT, false, 40, 12);
self.chunk_shader.texture_offset.vertex_pointer(3, gl::SHORT, false, 40, 20);
self.chunk_shader.color.vertex_pointer(3, gl::UNSIGNED_BYTE, true, 40, 28);
self.chunk_shader.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();
@ -404,6 +498,7 @@ impl Renderer {
val
} else {
t.load_texture(name);
println!("{:?} {:?}", name, t.textures);
t.get_texture(name).unwrap()
}
}
@ -746,10 +841,8 @@ impl TextureManager {
let missing = self.get_texture("steven:missing_texture").unwrap();
let mut full_name = String::new();
if plugin != "minecraft" {
full_name.push_str(plugin);
full_name.push_str(":");
}
full_name.push_str(plugin);
full_name.push_str(":");
full_name.push_str(name);
let t = Texture {

View File

@ -164,6 +164,7 @@ impl UIState {
self.shader.screensize.set_float2(width as f32, height as f32);
self.buffer.bind(gl::ARRAY_BUFFER);
self.index_buffer.bind(gl::ELEMENT_ARRAY_BUFFER);
if self.data.len() > self.prev_size {
self.prev_size = self.data.len();
self.buffer.set_data(gl::ARRAY_BUFFER, &self.data, gl::STREAM_DRAW);

View File

@ -16,14 +16,19 @@ use protocol;
use world;
use world::block;
use rand::{self, Rng};
use std::sync::{Arc, RwLock};
use resources;
pub struct Server {
conn: Option<protocol::Conn>,
pub world: world::World,
resources: Arc<RwLock<resources::Manager>>,
version: usize,
}
impl Server {
pub fn dummy_server() -> Server {
pub fn dummy_server(resources: Arc<RwLock<resources::Manager>>) -> Server {
let mut world = world::World::new();
let mut rng = rand::thread_rng();
for x in -7*16 .. 7*16 {
@ -34,9 +39,21 @@ impl Server {
}
}
}
let version = resources.read().unwrap().version();
Server {
conn: None,
world: world,
version: version,
resources: resources,
}
}
pub fn tick(&mut self) {
let version = self.resources.read().unwrap().version();
if version != self.version {
self.version = version;
self.world.flag_dirty_all();
}
}
}

View File

@ -68,6 +68,16 @@ impl World {
}
}
pub fn flag_dirty_all(&mut self) {
for (_, chunk) in &mut self.chunks {
for sec in &mut chunk.sections {
if let Some(sec) = sec.as_mut() {
sec.dirty = true;
}
}
}
}
pub fn capture_snapshot(&self, x: i32, y: i32, z: i32, w: i32, h: i32, d: i32) -> Snapshot {
use std::cmp::{min, max};
let mut snapshot = Snapshot {