Implement models and a sun/moon
This commit is contained in:
parent
93c58aad89
commit
2b26f841d0
|
@ -46,9 +46,15 @@ pub fn draw_arrays(ty: DrawType, offset: usize, count: usize) {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn draw_elements(ty: DrawType, count: usize, dty: Type, offset: usize) {
|
||||
pub fn draw_elements(ty: DrawType, count: i32, dty: Type, offset: usize) {
|
||||
unsafe {
|
||||
gl::DrawElements(ty, count as i32, dty, offset as *const gl::types::GLvoid);
|
||||
gl::DrawElements(ty, count, dty, offset as *const gl::types::GLvoid);
|
||||
}
|
||||
}
|
||||
|
||||
pub fn multi_draw_elements(ty: DrawType, count: &[i32], dty: Type, offsets: &[usize]) {
|
||||
unsafe {
|
||||
gl::MultiDrawElements(ty, count.as_ptr(), dty, offsets.as_ptr() as *const _, count.len() as i32);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -530,12 +536,25 @@ impl Uniform {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn set_float_mutli_raw(&self, data: *const f32, len: usize) {
|
||||
unsafe {
|
||||
gl::Uniform4fv(self.0, len as i32, data);
|
||||
}
|
||||
}
|
||||
|
||||
pub fn set_matrix4(&self, m: &::cgmath::Matrix4<f32>) {
|
||||
use cgmath::Matrix;
|
||||
unsafe {
|
||||
gl::UniformMatrix4fv(self.0, 1, false as u8, m.as_ptr());
|
||||
}
|
||||
}
|
||||
|
||||
pub fn set_matrix4_multi(&self, m: &[::cgmath::Matrix4<f32>]) {
|
||||
use cgmath::Matrix;
|
||||
unsafe {
|
||||
gl::UniformMatrix4fv(self.0, m.len() as i32, false as u8, m.as_ptr() as *const _); // TODO: Most likely isn't safe
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub struct Attribute(i32);
|
||||
|
|
|
@ -51,6 +51,7 @@ pub struct Renderer {
|
|||
pub resources: Arc<RwLock<resources::Manager>>,
|
||||
textures: Arc<RwLock<TextureManager>>,
|
||||
pub ui: ui::UIState,
|
||||
pub model: model::Manager,
|
||||
|
||||
gl_texture: gl::Texture,
|
||||
texture_layers: usize,
|
||||
|
@ -185,13 +186,13 @@ impl Renderer {
|
|||
|
||||
// UI
|
||||
// Line Drawer
|
||||
// Models
|
||||
// Clouds
|
||||
|
||||
gl::blend_func(gl::SRC_ALPHA, gl::ONE_MINUS_SRC_ALPHA);
|
||||
|
||||
Renderer {
|
||||
resource_version: version,
|
||||
model: model::Manager::new(&greg),
|
||||
textures: textures,
|
||||
ui: ui,
|
||||
resources: res,
|
||||
|
@ -237,6 +238,8 @@ impl Renderer {
|
|||
self.resource_version = rm.version();
|
||||
trace!("Updating textures to {}", self.resource_version);
|
||||
self.textures.write().unwrap().update_textures(self.resource_version);
|
||||
|
||||
self.model.rebuild_models(self.resource_version, &self.textures);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -306,13 +309,14 @@ impl Renderer {
|
|||
if solid.count > 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);
|
||||
gl::draw_elements(gl::TRIANGLES, solid.count as i32, self.element_buffer_type, 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Line rendering
|
||||
// Model rendering
|
||||
self.model.draw(&self.frustum, &self.perspective_matrix, &self.camera_matrix, self.light_level, self.sky_offset);
|
||||
// Cloud rendering
|
||||
|
||||
// Trans chunk rendering
|
||||
|
@ -346,7 +350,7 @@ impl Renderer {
|
|||
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::draw_elements(gl::TRIANGLES, trans.count as i32, self.element_buffer_type, 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,320 @@
|
|||
|
||||
use super::glsl;
|
||||
use super::shaders;
|
||||
use gl;
|
||||
use cgmath::{Point3, Matrix4, SquareMatrix};
|
||||
use collision::{self, Frustum, Sphere};
|
||||
use std::collections::HashMap;
|
||||
use std::hash::BuildHasherDefault;
|
||||
use std::sync::{Arc, RwLock};
|
||||
use types::hash::FNVHash;
|
||||
use byteorder::{WriteBytesExt, NativeEndian};
|
||||
|
||||
pub struct Manager {
|
||||
collections: Vec<Collection>,
|
||||
|
||||
index_buffer: gl::Buffer,
|
||||
index_type: gl::Type,
|
||||
max_index: usize,
|
||||
}
|
||||
|
||||
pub const DEFAULT: CollectionKey = CollectionKey(0);
|
||||
pub const SUN: CollectionKey = CollectionKey(1);
|
||||
|
||||
#[derive(Clone, Copy, PartialEq, Eq, Hash)]
|
||||
pub struct CollectionKey(usize);
|
||||
|
||||
#[derive(Clone, Copy, PartialEq, Eq, Hash)]
|
||||
pub struct ModelKey(CollectionKey, usize);
|
||||
|
||||
impl Manager {
|
||||
pub fn new(greg: &glsl::Registry) -> Manager {
|
||||
let mut m = Manager {
|
||||
collections: vec![],
|
||||
|
||||
index_buffer: gl::Buffer::new(),
|
||||
index_type: gl::UNSIGNED_SHORT,
|
||||
max_index: 0,
|
||||
};
|
||||
m.add_collection(
|
||||
&greg.get("model_vertex"),
|
||||
&greg.get("model_frag"),
|
||||
gl::SRC_ALPHA, gl::ONE_MINUS_SRC_ALPHA
|
||||
);
|
||||
m.add_collection(
|
||||
&greg.get("sun_vertex"),
|
||||
&greg.get("sun_frag"),
|
||||
gl::SRC_ALPHA, gl::ONE_FACTOR
|
||||
);
|
||||
m
|
||||
}
|
||||
|
||||
pub fn add_collection(&mut self, vert: &str, frag: &str, blend_s: gl::Factor, blend_d: gl::Factor) -> CollectionKey {
|
||||
let collection = Collection {
|
||||
shader: ModelShader::new_manual(vert, frag),
|
||||
models: HashMap::with_hasher(BuildHasherDefault::default()),
|
||||
blend_s: blend_s,
|
||||
blend_d: blend_d,
|
||||
next_id: 0,
|
||||
};
|
||||
self.collections.push(collection);
|
||||
CollectionKey(self.collections.len())
|
||||
}
|
||||
|
||||
pub fn get_model(&mut self, key: ModelKey) -> Option<&mut Model> {
|
||||
let collection = &mut self.collections[(key.0).0];
|
||||
collection.models.get_mut(&key)
|
||||
}
|
||||
|
||||
pub fn create_model(&mut self, ckey: CollectionKey, parts: Vec<Vec<Vertex>>) -> ModelKey {
|
||||
let array = gl::VertexArray::new();
|
||||
array.bind();
|
||||
self.index_buffer.bind(gl::ELEMENT_ARRAY_BUFFER);
|
||||
let buffer = gl::Buffer::new();
|
||||
buffer.bind(gl::ARRAY_BUFFER);
|
||||
|
||||
let mut model = {
|
||||
let collection = &mut self.collections[ckey.0];
|
||||
collection.shader.program.use_program();
|
||||
collection.shader.position.enable();
|
||||
collection.shader.texture_info.enable();
|
||||
collection.shader.texture_offset.enable();
|
||||
collection.shader.color.enable();
|
||||
collection.shader.id.enable();
|
||||
collection.shader.position.vertex_pointer(3, gl::FLOAT, false, 36, 0);
|
||||
collection.shader.texture_info.vertex_pointer(4, gl::UNSIGNED_SHORT, false, 36, 12);
|
||||
collection.shader.texture_offset.vertex_pointer_int(3, gl::SHORT, 36, 20);
|
||||
collection.shader.color.vertex_pointer(4, gl::UNSIGNED_BYTE, true, 36, 28);
|
||||
collection.shader.id.vertex_pointer_int(4, gl::UNSIGNED_BYTE, 36, 32);
|
||||
|
||||
let mut model = Model {
|
||||
// For culling only
|
||||
x: 0.0,
|
||||
y: 0.0,
|
||||
z: 0.0,
|
||||
radius: 0.0,
|
||||
// Per a part
|
||||
matrix: Vec::with_capacity(parts.len()),
|
||||
colors: Vec::with_capacity(parts.len()),
|
||||
block_light: 15.0,
|
||||
sky_light: 15.0,
|
||||
|
||||
array: array,
|
||||
buffer: buffer,
|
||||
buffer_size: 0,
|
||||
count: 0,
|
||||
|
||||
counts: Vec::with_capacity(parts.len()),
|
||||
offsets: Vec::with_capacity(parts.len()),
|
||||
|
||||
verts: vec![],
|
||||
};
|
||||
|
||||
for (i, part) in parts.into_iter().enumerate() {
|
||||
model.matrix.push(Matrix4::identity());
|
||||
model.colors.push([1.0, 1.0, 1.0, 1.0]);
|
||||
model.counts.push(((part.len() / 4) * 6) as i32);
|
||||
model.offsets.push((model.verts.len() / 4) * 6);
|
||||
for mut pp in part {
|
||||
pp.id = i as u8;
|
||||
model.verts.push(pp);
|
||||
}
|
||||
}
|
||||
model
|
||||
};
|
||||
|
||||
Self::rebuild_model(&mut model);
|
||||
if self.max_index < model.count {
|
||||
let (data, ty) = super::generate_element_buffer(model.count);
|
||||
self.index_buffer.bind(gl::ELEMENT_ARRAY_BUFFER);
|
||||
self.index_buffer.set_data(gl::ELEMENT_ARRAY_BUFFER, &data, gl::DYNAMIC_DRAW);
|
||||
self.max_index = model.count;
|
||||
self.index_type = ty;
|
||||
}
|
||||
|
||||
let collection = &mut self.collections[ckey.0];
|
||||
let key = ModelKey(ckey, collection.next_id);
|
||||
collection.next_id += 1;
|
||||
collection.models.insert(key, model);
|
||||
|
||||
key
|
||||
}
|
||||
|
||||
pub fn remove_model(&mut self, key: ModelKey) {
|
||||
let collection = &mut self.collections[(key.0).0];
|
||||
collection.models.remove(&key);
|
||||
}
|
||||
|
||||
fn rebuild_model(model: &mut Model) {
|
||||
model.array.bind();
|
||||
model.count = (model.verts.len() / 4) * 6;
|
||||
|
||||
let mut buffer = Vec::with_capacity(36 * model.verts.len());
|
||||
for vert in &model.verts {
|
||||
let _ = buffer.write_f32::<NativeEndian>(vert.x);
|
||||
let _ = buffer.write_f32::<NativeEndian>(vert.y);
|
||||
let _ = buffer.write_f32::<NativeEndian>(vert.z);
|
||||
let _ = buffer.write_u16::<NativeEndian>(vert.texture.get_x() as u16);
|
||||
let _ = buffer.write_u16::<NativeEndian>(vert.texture.get_y() as u16);
|
||||
let _ = buffer.write_u16::<NativeEndian>(vert.texture.get_width() as u16);
|
||||
let _ = buffer.write_u16::<NativeEndian>(vert.texture.get_height() as u16);
|
||||
let _ = buffer.write_i16::<NativeEndian>(((vert.texture.get_width() as f64) * 16.0 * vert.texture_x) as i16);
|
||||
let _ = buffer.write_i16::<NativeEndian>(((vert.texture.get_height() as f64) * 16.0 * vert.texture_y) as i16);
|
||||
let _ = buffer.write_i16::<NativeEndian>(vert.texture.atlas as i16);
|
||||
let _ = buffer.write_i16::<NativeEndian>(0);
|
||||
let _ = buffer.write_u8(vert.r);
|
||||
let _ = buffer.write_u8(vert.g);
|
||||
let _ = buffer.write_u8(vert.b);
|
||||
let _ = buffer.write_u8(vert.a);
|
||||
let _ = buffer.write_u8(vert.id);
|
||||
let _ = buffer.write_u8(0);
|
||||
let _ = buffer.write_u8(0);
|
||||
let _ = buffer.write_u8(0);
|
||||
}
|
||||
|
||||
model.buffer.bind(gl::ARRAY_BUFFER);
|
||||
if buffer.len() < model.buffer_size {
|
||||
model.buffer.re_set_data(gl::ARRAY_BUFFER, &buffer);
|
||||
} else {
|
||||
model.buffer.set_data(gl::ARRAY_BUFFER, &buffer, gl::DYNAMIC_DRAW);
|
||||
model.buffer_size = buffer.len();
|
||||
}
|
||||
}
|
||||
|
||||
pub fn rebuild_models(&mut self, version: usize, textures: &Arc<RwLock<super::TextureManager>>) {
|
||||
for collection in &mut self.collections {
|
||||
for (_, model) in &mut collection.models {
|
||||
for vert in &mut model.verts {
|
||||
vert.texture = if vert.texture.version == version {
|
||||
vert.texture.clone()
|
||||
} else {
|
||||
let mut new = super::Renderer::get_texture(&textures, &vert.texture.name);
|
||||
new.rel_x = vert.texture.rel_x;
|
||||
new.rel_y = vert.texture.rel_y;
|
||||
new.rel_width = vert.texture.rel_width;
|
||||
new.rel_height = vert.texture.rel_height;
|
||||
new.is_rel = vert.texture.is_rel;
|
||||
new
|
||||
};
|
||||
}
|
||||
Self::rebuild_model(model);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn draw(&mut self, frustum: &Frustum<f32>, perspective_matrix: &Matrix4<f32>, camera_matrix: &Matrix4<f32>, sky_offset: f32, light_level: f32) {
|
||||
let m = if self.index_type == gl::UNSIGNED_SHORT {
|
||||
2
|
||||
} else {
|
||||
4
|
||||
};
|
||||
|
||||
gl::enable(gl::BLEND);
|
||||
for collection in &self.collections {
|
||||
collection.shader.program.use_program();
|
||||
collection.shader.perspective_matrix.set_matrix4(perspective_matrix);
|
||||
collection.shader.camera_matrix.set_matrix4(camera_matrix);
|
||||
collection.shader.texture.set_int(0);
|
||||
collection.shader.sky_offset.set_float(sky_offset);
|
||||
collection.shader.light_level.set_float(light_level);
|
||||
gl::blend_func(collection.blend_s, collection.blend_d);
|
||||
|
||||
for (_, model) in &collection.models {
|
||||
if model.radius > 0.0 && frustum.contains(Sphere {
|
||||
center: Point3::new(model.x, -model.y, model.z),
|
||||
radius: model.radius
|
||||
}) == collision::Relation::Out {
|
||||
continue;
|
||||
}
|
||||
model.array.bind();
|
||||
collection.shader.lighting.set_float2(model.block_light, model.sky_light);
|
||||
if model.counts.len() > 1 {
|
||||
let mut offsets = model.offsets.clone();
|
||||
for offset in &mut offsets {
|
||||
*offset *= m;
|
||||
}
|
||||
collection.shader.model_matrix.set_matrix4_multi(&model.matrix);
|
||||
collection.shader.color_mul.set_float_mutli_raw(model.colors.as_ptr() as *const _, model.colors.len());
|
||||
gl::multi_draw_elements(gl::TRIANGLES, &model.counts, self.index_type, &offsets);
|
||||
} else {
|
||||
collection.shader.model_matrix.set_matrix4_multi(&model.matrix);
|
||||
collection.shader.color_mul.set_float_mutli_raw(model.colors.as_ptr() as *const _, model.colors.len());
|
||||
gl::draw_elements(gl::TRIANGLES, model.counts[0], self.index_type, model.offsets[0] * m);
|
||||
}
|
||||
}
|
||||
}
|
||||
gl::disable(gl::BLEND);
|
||||
}
|
||||
}
|
||||
|
||||
struct Collection {
|
||||
shader: ModelShader,
|
||||
|
||||
models: HashMap<ModelKey, Model, BuildHasherDefault<FNVHash>>,
|
||||
blend_s: gl::Factor,
|
||||
blend_d: gl::Factor,
|
||||
|
||||
next_id: usize,
|
||||
}
|
||||
|
||||
pub struct Model {
|
||||
// For culling only
|
||||
pub x: f32,
|
||||
pub y: f32,
|
||||
pub z: f32,
|
||||
pub radius: f32,
|
||||
// Per a part
|
||||
pub matrix: Vec<Matrix4<f32>>,
|
||||
pub colors: Vec<[f32; 4]>,
|
||||
pub block_light: f32,
|
||||
pub sky_light: f32,
|
||||
|
||||
array: gl::VertexArray,
|
||||
buffer: gl::Buffer,
|
||||
buffer_size: usize,
|
||||
count: usize,
|
||||
|
||||
counts: Vec<i32>,
|
||||
offsets: Vec<usize>,
|
||||
|
||||
pub verts: Vec<Vertex>,
|
||||
}
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct Vertex {
|
||||
pub x: f32,
|
||||
pub y: f32,
|
||||
pub z: f32,
|
||||
pub texture: super::Texture,
|
||||
pub texture_x: f64,
|
||||
pub texture_y: f64,
|
||||
pub r: u8,
|
||||
pub g: u8,
|
||||
pub b: u8,
|
||||
pub a: u8,
|
||||
pub id: u8,
|
||||
}
|
||||
|
||||
init_shader! {
|
||||
Program ModelShader {
|
||||
vert = "model_vertex",
|
||||
frag = "model_frag",
|
||||
attribute = {
|
||||
position => "aPosition",
|
||||
texture_info => "aTextureInfo",
|
||||
texture_offset => "aTextureOffset",
|
||||
color => "aColor",
|
||||
id => "id",
|
||||
},
|
||||
uniform = {
|
||||
perspective_matrix => "perspectiveMatrix",
|
||||
camera_matrix => "cameraMatrix",
|
||||
model_matrix => "modelMatrix[]",
|
||||
texture => "textures",
|
||||
light_level => "lightLevel",
|
||||
sky_offset => "skyOffset",
|
||||
lighting => "lighting",
|
||||
color_mul => "colorMul[]",
|
||||
},
|
||||
}
|
||||
}
|
|
@ -16,8 +16,7 @@ use render::glsl;
|
|||
use gl;
|
||||
|
||||
pub fn add_shaders(reg: &mut glsl::Registry) {
|
||||
reg.register("lookup_texture",
|
||||
include_str!("shaders/lookup_texture.glsl"));
|
||||
reg.register("lookup_texture", include_str!("shaders/lookup_texture.glsl"));
|
||||
reg.register("get_light", include_str!("shaders/get_light.glsl"));
|
||||
|
||||
reg.register("ui_vertex", include_str!("shaders/ui_vertex.glsl"));
|
||||
|
@ -28,6 +27,12 @@ pub fn add_shaders(reg: &mut glsl::Registry) {
|
|||
|
||||
reg.register("trans_vertex", include_str!("shaders/trans_vertex.glsl"));
|
||||
reg.register("trans_frag", include_str!("shaders/trans_frag.glsl"));
|
||||
|
||||
reg.register("model_vertex", include_str!("shaders/model_vertex.glsl"));
|
||||
reg.register("model_frag", include_str!("shaders/model_frag.glsl"));
|
||||
|
||||
reg.register("sun_vertex", include_str!("shaders/sun_vertex.glsl"));
|
||||
reg.register("sun_frag", include_str!("shaders/sun_frag.glsl"));
|
||||
}
|
||||
|
||||
macro_rules! get_shader {
|
||||
|
@ -69,9 +74,15 @@ macro_rules! init_shader {
|
|||
}
|
||||
|
||||
impl $name {
|
||||
#[allow(dead_code)]
|
||||
pub fn new(reg: &glsl::Registry) -> $name {
|
||||
let v = get_shader!(reg, $vert $(,stringify!($vdef))*);
|
||||
let f = get_shader!(reg, $frag $(,stringify!($fdef))*);
|
||||
$name::new_manual(&v, &f)
|
||||
}
|
||||
|
||||
#[allow(dead_code)]
|
||||
pub fn new_manual(v: &str, f: &str) -> $name {
|
||||
let shader = shaders::create_program(&v, &f);
|
||||
$name {
|
||||
$(
|
||||
|
|
|
@ -0,0 +1,21 @@
|
|||
uniform sampler2DArray textures;
|
||||
uniform vec4 colorMul[10];
|
||||
|
||||
in vec4 vColor;
|
||||
in vec4 vTextureInfo;
|
||||
in vec2 vTextureOffset;
|
||||
in float vAtlas;
|
||||
in vec3 vLighting;
|
||||
in float vID;
|
||||
|
||||
out vec4 fragColor;
|
||||
|
||||
#include lookup_texture
|
||||
|
||||
void main() {
|
||||
vec4 col = atlasTexture();
|
||||
if (col.a <= 0.05) discard;
|
||||
col *= vColor;
|
||||
col.rgb *= vLighting;
|
||||
fragColor = col * colorMul[int(vID)];
|
||||
}
|
|
@ -0,0 +1,34 @@
|
|||
in vec3 aPosition;
|
||||
in vec4 aTextureInfo;
|
||||
in ivec3 aTextureOffset;
|
||||
in vec4 aColor;
|
||||
in int id;
|
||||
|
||||
uniform mat4 perspectiveMatrix;
|
||||
uniform mat4 cameraMatrix;
|
||||
uniform mat4 modelMatrix[10];
|
||||
uniform float lightLevel;
|
||||
uniform float skyOffset;
|
||||
uniform vec2 lighting;
|
||||
|
||||
out vec4 vColor;
|
||||
out vec4 vTextureInfo;
|
||||
out vec2 vTextureOffset;
|
||||
out float vAtlas;
|
||||
out float vID;
|
||||
out vec3 vLighting;
|
||||
|
||||
#include get_light
|
||||
|
||||
void main() {
|
||||
vec3 pos = vec3(aPosition.x, -aPosition.y, aPosition.z);
|
||||
gl_Position = perspectiveMatrix * cameraMatrix * modelMatrix[id] * vec4(pos, 1.0);
|
||||
|
||||
vColor = aColor;
|
||||
vTextureInfo = aTextureInfo;
|
||||
vTextureOffset = aTextureOffset.xy / 16.0;
|
||||
vAtlas = aTextureOffset.z;
|
||||
vID = float(id);
|
||||
|
||||
vLighting = getLight(lighting);
|
||||
}
|
|
@ -0,0 +1,17 @@
|
|||
uniform sampler2DArray textures;
|
||||
uniform vec4 colorMul[10];
|
||||
|
||||
in vec4 vTextureInfo;
|
||||
in vec2 vTextureOffset;
|
||||
in float vAtlas;
|
||||
in float vID;
|
||||
|
||||
out vec4 fragColor;
|
||||
|
||||
#include lookup_texture
|
||||
|
||||
void main() {
|
||||
vec4 col = atlasTexture();
|
||||
if (col.a <= 0.05) discard;
|
||||
fragColor = col * colorMul[int(vID)];
|
||||
}
|
|
@ -0,0 +1,27 @@
|
|||
in vec3 aPosition;
|
||||
in vec4 aTextureInfo;
|
||||
in ivec3 aTextureOffset;
|
||||
in vec4 aColor;
|
||||
in int id;
|
||||
|
||||
uniform mat4 perspectiveMatrix;
|
||||
uniform mat4 cameraMatrix;
|
||||
uniform mat4 modelMatrix[10];
|
||||
uniform float lightLevel;
|
||||
uniform float skyOffset;
|
||||
uniform vec2 lighting;
|
||||
|
||||
out vec4 vTextureInfo;
|
||||
out vec2 vTextureOffset;
|
||||
out float vAtlas;
|
||||
out float vID;
|
||||
|
||||
void main() {
|
||||
vec3 pos = vec3(aPosition.x, -aPosition.y, aPosition.z);
|
||||
gl_Position = perspectiveMatrix * cameraMatrix * modelMatrix[id] * vec4(pos, 1.0);
|
||||
|
||||
vTextureInfo = aTextureInfo;
|
||||
vTextureOffset = aTextureOffset.xy / 16.0;
|
||||
vAtlas = aTextureOffset.z;
|
||||
vID = float(id);
|
||||
}
|
|
@ -170,7 +170,7 @@ impl UIState {
|
|||
} else {
|
||||
self.buffer.re_set_data(gl::ARRAY_BUFFER, &self.data);
|
||||
}
|
||||
gl::draw_elements(gl::TRIANGLES, self.count, self.index_type, 0);
|
||||
gl::draw_elements(gl::TRIANGLES, self.count as i32, self.index_type, 0);
|
||||
}
|
||||
|
||||
gl::disable(gl::BLEND);
|
||||
|
|
|
@ -34,6 +34,8 @@ use collision::Aabb;
|
|||
use sdl2::keyboard::Keycode;
|
||||
use types::Gamemode;
|
||||
|
||||
mod sun;
|
||||
|
||||
pub struct Server {
|
||||
conn: Option<protocol::Conn>,
|
||||
read_queue: Option<mpsc::Receiver<Result<packet::Packet, protocol::Error>>>,
|
||||
|
@ -64,6 +66,8 @@ pub struct Server {
|
|||
pressed_keys: HashMap<Keycode, bool, BuildHasherDefault<FNVHash>>,
|
||||
tick_timer: f64,
|
||||
entity_tick_timer: f64,
|
||||
|
||||
sun_model: Option<sun::SunModel>,
|
||||
}
|
||||
|
||||
macro_rules! handle_packet {
|
||||
|
@ -222,6 +226,7 @@ impl Server {
|
|||
|
||||
tick_timer: 0.0,
|
||||
entity_tick_timer: 0.0,
|
||||
sun_model: None,
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -235,6 +240,10 @@ impl Server {
|
|||
self.version = version;
|
||||
self.world.flag_dirty_all();
|
||||
}
|
||||
// TODO: Check if the world type actually needs a sun
|
||||
if self.sun_model.is_none() {
|
||||
self.sun_model = Some(sun::SunModel::new(renderer));
|
||||
}
|
||||
|
||||
self.entity_tick(renderer, delta);
|
||||
|
||||
|
@ -246,6 +255,10 @@ impl Server {
|
|||
|
||||
self.update_time(renderer, delta);
|
||||
|
||||
if let Some(sun_model) = self.sun_model.as_mut() {
|
||||
sun_model.tick(renderer, self.world_time, self.world_age);
|
||||
}
|
||||
|
||||
// Copy to camera
|
||||
if let Some(player) = self.player {
|
||||
let position = self.entities.get_component(player, self.position).unwrap();
|
||||
|
@ -295,6 +308,9 @@ impl Server {
|
|||
|
||||
pub fn remove(&mut self, renderer: &mut render::Renderer) {
|
||||
self.entities.remove_all_entities(&mut self.world, renderer);
|
||||
if let Some(mut sun_model) = self.sun_model.take() {
|
||||
sun_model.remove(renderer);
|
||||
}
|
||||
}
|
||||
|
||||
fn update_time(&mut self, renderer: &mut render::Renderer, delta: f64) {
|
|
@ -0,0 +1,96 @@
|
|||
|
||||
use render;
|
||||
use render::model;
|
||||
use cgmath::{Vector3, Matrix4, Decomposed, Rotation3, Rad, Angle, Quaternion};
|
||||
|
||||
pub struct SunModel {
|
||||
sun: model::ModelKey,
|
||||
moon: model::ModelKey,
|
||||
last_phase: i32,
|
||||
}
|
||||
|
||||
const SIZE: f32 = 50.0;
|
||||
|
||||
impl SunModel {
|
||||
|
||||
pub fn new(renderer: &mut render::Renderer) -> SunModel {
|
||||
SunModel {
|
||||
sun: SunModel::generate_sun(renderer),
|
||||
moon: SunModel::generate_moon(renderer, 0),
|
||||
last_phase: 0,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn tick(&mut self, renderer: &mut render::Renderer, world_time: f64, world_age: i64) {
|
||||
use std::f64::consts::PI;
|
||||
let phase = ((world_age / 24000) % 8) as i32;
|
||||
if phase != self.last_phase {
|
||||
renderer.model.remove_model(self.moon);
|
||||
self.moon = SunModel::generate_moon(renderer, phase);
|
||||
self.last_phase = phase;
|
||||
}
|
||||
|
||||
let time = world_time / 12000.0;
|
||||
let ox = (time * PI).cos() * 300.0;
|
||||
let oy = (time * PI).sin() * 300.0;
|
||||
|
||||
{
|
||||
let sun = renderer.model.get_model(self.sun).unwrap();
|
||||
sun.matrix[0] = Matrix4::from(Decomposed {
|
||||
scale: 1.0,
|
||||
rot: Quaternion::from_angle_z(Rad::new(-(time * PI) as f32)),
|
||||
disp: Vector3::new(
|
||||
(renderer.camera.pos.x + ox) as f32,
|
||||
-(renderer.camera.pos.y + oy) as f32,
|
||||
renderer.camera.pos.z as f32,
|
||||
),
|
||||
});
|
||||
}
|
||||
|
||||
{
|
||||
let moon = renderer.model.get_model(self.moon).unwrap();
|
||||
moon.matrix[0] = Matrix4::from(Decomposed {
|
||||
scale: 1.0,
|
||||
rot: Quaternion::from_angle_z(Rad::new((PI - (time * PI)) as f32)),
|
||||
disp: Vector3::new(
|
||||
(renderer.camera.pos.x - ox) as f32,
|
||||
-(renderer.camera.pos.y - oy) as f32,
|
||||
renderer.camera.pos.z as f32,
|
||||
),
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
pub fn remove(&mut self, renderer: &mut render::Renderer) {
|
||||
renderer.model.remove_model(self.sun);
|
||||
renderer.model.remove_model(self.moon);
|
||||
}
|
||||
|
||||
pub fn generate_sun(renderer: &mut render::Renderer) -> model::ModelKey {
|
||||
let tex = render::Renderer::get_texture(renderer.get_textures_ref(), "environment/sun");
|
||||
renderer.model.create_model(
|
||||
model::SUN,
|
||||
vec![vec![
|
||||
model::Vertex{x: 0.0, y: -SIZE, z: -SIZE, texture_x: 0.0, texture_y: 1.0, texture: tex.clone(), r: 255, g: 255, b: 255, a: 0, id: 0},
|
||||
model::Vertex{x: 0.0, y: SIZE, z: -SIZE, texture_x: 0.0, texture_y: 0.0, texture: tex.clone(), r: 255, g: 255, b: 255, a: 0, id: 0},
|
||||
model::Vertex{x: 0.0, y: -SIZE, z: SIZE, texture_x: 1.0, texture_y: 1.0, texture: tex.clone(), r: 255, g: 255, b: 255, a: 0, id: 0},
|
||||
model::Vertex{x: 0.0, y: SIZE, z: SIZE, texture_x: 1.0, texture_y: 0.0, texture: tex.clone(), r: 255, g: 255, b: 255, a: 0, id: 0}
|
||||
]]
|
||||
)
|
||||
}
|
||||
|
||||
pub fn generate_moon(renderer: &mut render::Renderer, phase: i32) -> model::ModelKey {
|
||||
let tex = render::Renderer::get_texture(renderer.get_textures_ref(), "environment/moon_phases");
|
||||
let mpx = (phase % 4) as f64 * (1.0 / 4.0);
|
||||
let mpy = (phase / 4) as f64 * (1.0 / 2.0);
|
||||
renderer.model.create_model(
|
||||
model::SUN,
|
||||
vec![vec![
|
||||
model::Vertex{x: 0.0, y: -SIZE, z: -SIZE, texture_x: mpx, texture_y: mpy + (1.0 / 2.0), texture: tex.clone(), r: 255, g: 255, b: 255, a: 0, id: 0},
|
||||
model::Vertex{x: 0.0, y: SIZE, z: -SIZE, texture_x: mpx, texture_y: mpy, texture: tex.clone(), r: 255, g: 255, b: 255, a: 0, id: 0},
|
||||
model::Vertex{x: 0.0, y: -SIZE, z: SIZE, texture_x: mpx + (1.0 / 4.0), texture_y: mpy + (1.0 / 2.0), texture: tex.clone(), r: 255, g: 255, b: 255, a: 0, id: 0},
|
||||
model::Vertex{x: 0.0, y: SIZE, z: SIZE, texture_x: mpx + (1.0 / 4.0), texture_y: mpy, texture: tex.clone(), r: 255, g: 255, b: 255, a: 0, id: 0}
|
||||
]]
|
||||
)
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue