Initial rendering implementation
This commit is contained in:
parent
ad81ef8f17
commit
6bee18b68c
|
@ -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),
|
||||
|
|
15
src/main.rs
15
src/main.rs
|
@ -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
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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 {
|
||||
|
|
Loading…
Reference in New Issue