mirror of
https://gitlab.com/veloren/veloren.git
synced 2024-08-30 18:12:32 +00:00
Added point lights
This commit is contained in:
parent
1dc654dde7
commit
b34d22565e
@ -1,7 +1,6 @@
|
||||
#version 330 core
|
||||
|
||||
#include <globals.glsl>
|
||||
#include <sky.glsl>
|
||||
|
||||
in vec3 f_pos;
|
||||
in vec3 f_norm;
|
||||
@ -23,6 +22,19 @@ uniform u_bones {
|
||||
BoneData bones[16];
|
||||
};
|
||||
|
||||
struct Light {
|
||||
vec4 light_pos;
|
||||
vec4 light_col;
|
||||
};
|
||||
|
||||
layout (std140)
|
||||
uniform u_lights {
|
||||
Light lights[32];
|
||||
};
|
||||
|
||||
#include <sky.glsl>
|
||||
#include <light.glsl>
|
||||
|
||||
out vec4 tgt_color;
|
||||
|
||||
void main() {
|
||||
@ -32,7 +44,7 @@ void main() {
|
||||
vec4(f_norm, 0.0)
|
||||
).xyz;
|
||||
|
||||
vec3 light = get_sun_diffuse(world_norm, time_of_day.x);
|
||||
vec3 light = get_sun_diffuse(world_norm, time_of_day.x) + light_at(f_pos, f_norm);
|
||||
vec3 surf_color = model_col.rgb * f_col * 2.0 * light;
|
||||
|
||||
float fog_level = fog(f_pos.xy, focus_pos.xy);
|
||||
|
@ -22,6 +22,16 @@ uniform u_bones {
|
||||
BoneData bones[16];
|
||||
};
|
||||
|
||||
struct Light {
|
||||
vec4 light_pos;
|
||||
vec4 light_col;
|
||||
};
|
||||
|
||||
layout (std140)
|
||||
uniform u_lights {
|
||||
Light lights[32];
|
||||
};
|
||||
|
||||
out vec3 f_pos;
|
||||
out vec3 f_norm;
|
||||
out vec3 f_col;
|
||||
|
@ -8,4 +8,5 @@ uniform u_globals {
|
||||
vec4 time_of_day;
|
||||
vec4 tick;
|
||||
vec4 screen_res;
|
||||
uvec4 light_count;
|
||||
};
|
||||
|
22
voxygen/shaders/include/light.glsl
Normal file
22
voxygen/shaders/include/light.glsl
Normal file
@ -0,0 +1,22 @@
|
||||
float attenuation_strength(vec3 rpos) {
|
||||
return 1.0 / (rpos.x * rpos.x + rpos.y * rpos.y + rpos.z * rpos.z);
|
||||
}
|
||||
|
||||
vec3 light_at(vec3 wpos, vec3 wnorm) {
|
||||
const float LIGHT_AMBIENCE = 0.1;
|
||||
|
||||
vec3 light = vec3(0);
|
||||
for (uint i = 0u; i < light_count.x; i ++) {
|
||||
vec3 light_pos = lights[i].light_pos.xyz;
|
||||
float strength = attenuation_strength(wpos - light_pos);
|
||||
|
||||
if (strength < 0.001) {
|
||||
continue;
|
||||
}
|
||||
|
||||
light += strength
|
||||
* lights[i].light_col.rgb
|
||||
* clamp(dot(normalize(light_pos - wpos), wnorm), LIGHT_AMBIENCE, 1.0);
|
||||
}
|
||||
return light;
|
||||
}
|
@ -1,7 +1,6 @@
|
||||
#version 330 core
|
||||
|
||||
#include <globals.glsl>
|
||||
#include <sky.glsl>
|
||||
|
||||
in vec3 f_pos;
|
||||
flat in uint f_pos_norm;
|
||||
@ -13,8 +12,21 @@ uniform u_locals {
|
||||
vec3 model_offs;
|
||||
};
|
||||
|
||||
struct Light {
|
||||
vec4 light_pos;
|
||||
vec4 light_col;
|
||||
};
|
||||
|
||||
layout (std140)
|
||||
uniform u_lights {
|
||||
Light lights[32];
|
||||
};
|
||||
|
||||
out vec4 tgt_color;
|
||||
|
||||
#include <sky.glsl>
|
||||
#include <light.glsl>
|
||||
|
||||
void main() {
|
||||
// Calculate normal from packed data
|
||||
vec3 f_norm;
|
||||
@ -28,7 +40,7 @@ void main() {
|
||||
f_norm = vec3(0.0, 0.0, 1.0) * norm_dir;
|
||||
}
|
||||
|
||||
vec3 light = get_sun_diffuse(f_norm, time_of_day.x) * f_light;
|
||||
vec3 light = get_sun_diffuse(f_norm, time_of_day.x) * f_light + light_at(f_pos, f_norm);
|
||||
vec3 surf_color = f_col * light;
|
||||
|
||||
float fog_level = fog(f_pos.xy, focus_pos.xy);
|
||||
|
@ -10,6 +10,16 @@ uniform u_locals {
|
||||
vec3 model_offs;
|
||||
};
|
||||
|
||||
struct Light {
|
||||
vec4 light_pos;
|
||||
vec4 light_col;
|
||||
};
|
||||
|
||||
layout (std140)
|
||||
uniform u_lights {
|
||||
Light lights[32];
|
||||
};
|
||||
|
||||
out vec3 f_pos;
|
||||
flat out uint f_pos_norm;
|
||||
out vec3 f_col;
|
||||
|
@ -5,7 +5,7 @@ use crate::{
|
||||
Animation, Skeleton, SkeletonAttr,
|
||||
},
|
||||
render::{
|
||||
create_pp_mesh, create_skybox_mesh, Consts, FigurePipeline, Globals, Model,
|
||||
create_pp_mesh, create_skybox_mesh, Consts, FigurePipeline, Globals, Light, Model,
|
||||
PostProcessLocals, PostProcessPipeline, Renderer, SkyboxLocals, SkyboxPipeline,
|
||||
},
|
||||
scene::{
|
||||
@ -33,6 +33,7 @@ struct PostProcess {
|
||||
|
||||
pub struct Scene {
|
||||
globals: Consts<Globals>,
|
||||
lights: Consts<Light>,
|
||||
camera: Camera,
|
||||
|
||||
skybox: Skybox,
|
||||
@ -50,6 +51,7 @@ impl Scene {
|
||||
|
||||
Self {
|
||||
globals: renderer.create_consts(&[Globals::default()]).unwrap(),
|
||||
lights: renderer.create_consts(&[Light::default(); 32]).unwrap(),
|
||||
camera: Camera::new(resolution.x / resolution.y),
|
||||
|
||||
skybox: Skybox {
|
||||
@ -99,6 +101,7 @@ impl Scene {
|
||||
55800.0,
|
||||
client.state().get_time(),
|
||||
renderer.get_resolution(),
|
||||
0,
|
||||
)],
|
||||
) {
|
||||
error!("Renderer failed to update: {:?}", err);
|
||||
@ -139,6 +142,7 @@ impl Scene {
|
||||
&self.globals,
|
||||
self.figure_state.locals(),
|
||||
self.figure_state.bone_consts(),
|
||||
&self.lights,
|
||||
);
|
||||
|
||||
renderer.render_figure(
|
||||
@ -146,6 +150,7 @@ impl Scene {
|
||||
&self.globals,
|
||||
self.backdrop_state.locals(),
|
||||
self.backdrop_state.bone_consts(),
|
||||
&self.lights,
|
||||
);
|
||||
|
||||
renderer.render_post_process(
|
||||
|
@ -22,7 +22,7 @@ pub use self::{
|
||||
create_quad as create_ui_quad, create_tri as create_ui_tri, Locals as UiLocals,
|
||||
Mode as UiMode, UiPipeline,
|
||||
},
|
||||
Globals,
|
||||
Globals, Light,
|
||||
},
|
||||
renderer::{Renderer, TgtColorFmt, TgtDepthFmt, WinColorFmt, WinDepthFmt},
|
||||
texture::Texture,
|
||||
|
@ -1,6 +1,6 @@
|
||||
use super::{
|
||||
super::{util::arr_to_mat, Pipeline, TgtColorFmt, TgtDepthFmt},
|
||||
Globals,
|
||||
Globals, Light,
|
||||
};
|
||||
use gfx::{
|
||||
self,
|
||||
@ -37,6 +37,7 @@ gfx_defines! {
|
||||
locals: gfx::ConstantBuffer<Locals> = "u_locals",
|
||||
globals: gfx::ConstantBuffer<Globals> = "u_globals",
|
||||
bones: gfx::ConstantBuffer<BoneData> = "u_bones",
|
||||
lights: gfx::ConstantBuffer<Light> = "u_lights",
|
||||
|
||||
tgt_color: gfx::RenderTarget<TgtColorFmt> = "tgt_color",
|
||||
tgt_depth: gfx::DepthTarget<TgtDepthFmt> = gfx::preset::depth::LESS_EQUAL_WRITE,
|
||||
|
@ -25,24 +25,16 @@ gfx_defines! {
|
||||
time_of_day: [f32; 4] = "time_of_day", // TODO: Make this f64.
|
||||
tick: [f32; 4] = "tick",
|
||||
screen_res: [f32; 4] = "screen_res",
|
||||
light_count: [u32; 4] = "light_count",
|
||||
}
|
||||
|
||||
constant Light {
|
||||
pos: [f32; 4] = "light_pos",
|
||||
col: [f32; 4] = "light_col",
|
||||
}
|
||||
}
|
||||
|
||||
impl Globals {
|
||||
/// Create global consts with default values.
|
||||
pub fn default() -> Self {
|
||||
Self {
|
||||
view_mat: arr_to_mat(Mat4::identity().into_col_array()),
|
||||
proj_mat: arr_to_mat(Mat4::identity().into_col_array()),
|
||||
cam_pos: [0.0; 4],
|
||||
focus_pos: [0.0; 4],
|
||||
view_distance: [0.0; 4],
|
||||
time_of_day: [0.0; 4],
|
||||
tick: [0.0; 4],
|
||||
screen_res: [800.0, 500.0, 0.0, 0.0],
|
||||
}
|
||||
}
|
||||
|
||||
/// Create global consts from the provided parameters.
|
||||
pub fn new(
|
||||
view_mat: Mat4<f32>,
|
||||
@ -53,6 +45,7 @@ impl Globals {
|
||||
time_of_day: f64,
|
||||
tick: f64,
|
||||
screen_res: Vec2<u16>,
|
||||
light_count: usize,
|
||||
) -> Self {
|
||||
Self {
|
||||
view_mat: arr_to_mat(view_mat.into_col_array()),
|
||||
@ -63,6 +56,38 @@ impl Globals {
|
||||
time_of_day: [time_of_day as f32; 4],
|
||||
tick: [tick as f32; 4],
|
||||
screen_res: Vec4::from(screen_res.map(|e| e as f32)).into_array(),
|
||||
light_count: [light_count as u32; 4],
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Default for Globals {
|
||||
fn default() -> Self {
|
||||
Self::new(
|
||||
Mat4::identity(),
|
||||
Mat4::identity(),
|
||||
Vec3::zero(),
|
||||
Vec3::zero(),
|
||||
0.0,
|
||||
0.0,
|
||||
0.0,
|
||||
Vec2::new(800, 500),
|
||||
0,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
impl Light {
|
||||
pub fn new(pos: Vec3<f32>, col: Rgb<f32>, strength: f32) -> Self {
|
||||
Self {
|
||||
pos: Vec4::from(pos).into_array(),
|
||||
col: Rgba::new(col.r, col.g, col.b, strength).into_array(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Default for Light {
|
||||
fn default() -> Self {
|
||||
Self::new(Vec3::zero(), Rgb::zero(), 0.0)
|
||||
}
|
||||
}
|
||||
|
@ -1,6 +1,6 @@
|
||||
use super::{
|
||||
super::{Pipeline, TgtColorFmt, TgtDepthFmt},
|
||||
Globals,
|
||||
Globals, Light,
|
||||
};
|
||||
use gfx::{
|
||||
self,
|
||||
@ -30,6 +30,7 @@ gfx_defines! {
|
||||
|
||||
locals: gfx::ConstantBuffer<Locals> = "u_locals",
|
||||
globals: gfx::ConstantBuffer<Globals> = "u_globals",
|
||||
lights: gfx::ConstantBuffer<Light> = "u_lights",
|
||||
|
||||
tgt_color: gfx::RenderTarget<TgtColorFmt> = "tgt_color",
|
||||
tgt_depth: gfx::DepthTarget<TgtDepthFmt> = gfx::preset::depth::LESS_EQUAL_WRITE,
|
||||
|
@ -3,7 +3,7 @@ use super::{
|
||||
gfx_backend,
|
||||
mesh::Mesh,
|
||||
model::{DynamicModel, Model},
|
||||
pipelines::{figure, postprocess, skybox, terrain, ui, Globals},
|
||||
pipelines::{figure, postprocess, skybox, terrain, ui, Globals, Light},
|
||||
texture::Texture,
|
||||
Pipeline, RenderError,
|
||||
};
|
||||
@ -82,10 +82,15 @@ impl Renderer {
|
||||
env!("CARGO_MANIFEST_DIR"),
|
||||
"/shaders/include/sky.glsl"
|
||||
));
|
||||
let light = include_str!(concat!(
|
||||
env!("CARGO_MANIFEST_DIR"),
|
||||
"/shaders/include/light.glsl"
|
||||
));
|
||||
|
||||
let mut include_ctx = IncludeContext::new();
|
||||
include_ctx.include("globals.glsl", globals);
|
||||
include_ctx.include("sky.glsl", sky);
|
||||
include_ctx.include("light.glsl", light);
|
||||
|
||||
// Construct a pipeline for rendering skyboxes
|
||||
let skybox_pipeline = create_pipeline(
|
||||
@ -389,6 +394,7 @@ impl Renderer {
|
||||
globals: &Consts<Globals>,
|
||||
locals: &Consts<figure::Locals>,
|
||||
bones: &Consts<figure::BoneData>,
|
||||
lights: &Consts<Light>,
|
||||
) {
|
||||
self.encoder.draw(
|
||||
&model.slice,
|
||||
@ -398,6 +404,7 @@ impl Renderer {
|
||||
locals: locals.buf.clone(),
|
||||
globals: globals.buf.clone(),
|
||||
bones: bones.buf.clone(),
|
||||
lights: lights.buf.clone(),
|
||||
tgt_color: self.tgt_color_view.clone(),
|
||||
tgt_depth: self.tgt_depth_view.clone(),
|
||||
},
|
||||
@ -410,6 +417,7 @@ impl Renderer {
|
||||
model: &Model<terrain::TerrainPipeline>,
|
||||
globals: &Consts<Globals>,
|
||||
locals: &Consts<terrain::Locals>,
|
||||
lights: &Consts<Light>,
|
||||
) {
|
||||
self.encoder.draw(
|
||||
&model.slice,
|
||||
@ -418,6 +426,7 @@ impl Renderer {
|
||||
vbuf: model.vbuf.clone(),
|
||||
locals: locals.buf.clone(),
|
||||
globals: globals.buf.clone(),
|
||||
lights: lights.buf.clone(),
|
||||
tgt_color: self.tgt_color_view.clone(),
|
||||
tgt_depth: self.tgt_depth_view.clone(),
|
||||
},
|
||||
|
@ -5,7 +5,7 @@ use crate::{
|
||||
},
|
||||
mesh::Meshable,
|
||||
render::{
|
||||
Consts, FigureBoneData, FigureLocals, FigurePipeline, Globals, Mesh, Model, Renderer,
|
||||
Consts, FigureBoneData, FigureLocals, FigurePipeline, Globals, Light, Mesh, Model, Renderer,
|
||||
},
|
||||
};
|
||||
use client::Client;
|
||||
@ -800,6 +800,7 @@ impl FigureMgr {
|
||||
renderer: &mut Renderer,
|
||||
client: &mut Client,
|
||||
globals: &Consts<Globals>,
|
||||
lights: &Consts<Light>,
|
||||
) {
|
||||
let tick = client.get_tick();
|
||||
let ecs = client.state().ecs();
|
||||
@ -855,7 +856,7 @@ impl FigureMgr {
|
||||
.get_or_create_model(renderer, *body, tick)
|
||||
.0;
|
||||
|
||||
renderer.render_figure(model, globals, locals, bone_consts);
|
||||
renderer.render_figure(model, globals, locals, bone_consts, lights);
|
||||
} else {
|
||||
warn!("Body has no saved figure");
|
||||
}
|
||||
|
@ -5,18 +5,21 @@ pub mod terrain;
|
||||
use self::{camera::Camera, figure::FigureMgr, terrain::Terrain};
|
||||
use crate::{
|
||||
render::{
|
||||
create_pp_mesh, create_skybox_mesh, Consts, Globals, Model, PostProcessLocals,
|
||||
create_pp_mesh, create_skybox_mesh, Consts, Globals, Light, Model, PostProcessLocals,
|
||||
PostProcessPipeline, Renderer, SkyboxLocals, SkyboxPipeline,
|
||||
},
|
||||
window::Event,
|
||||
};
|
||||
use client::Client;
|
||||
use common::comp;
|
||||
use specs::Join;
|
||||
use vek::*;
|
||||
|
||||
// TODO: Don't hard-code this.
|
||||
const CURSOR_PAN_SCALE: f32 = 0.005;
|
||||
|
||||
const LIGHT_DIST_RADIUS: f32 = 64.0; // The distance beyond which lights may not be visible
|
||||
|
||||
struct Skybox {
|
||||
model: Model<SkyboxPipeline>,
|
||||
locals: Consts<SkyboxLocals>,
|
||||
@ -29,6 +32,7 @@ struct PostProcess {
|
||||
|
||||
pub struct Scene {
|
||||
globals: Consts<Globals>,
|
||||
lights: Consts<Light>,
|
||||
camera: Camera,
|
||||
|
||||
skybox: Skybox,
|
||||
@ -46,6 +50,7 @@ impl Scene {
|
||||
|
||||
Self {
|
||||
globals: renderer.create_consts(&[Globals::default()]).unwrap(),
|
||||
lights: renderer.create_consts(&[Light::default(); 32]).unwrap(),
|
||||
camera: Camera::new(resolution.x / resolution.y),
|
||||
|
||||
skybox: Skybox {
|
||||
@ -128,9 +133,27 @@ impl Scene {
|
||||
let (view_mat, proj_mat, cam_pos) = self.camera.compute_dependents(client);
|
||||
|
||||
// Update chunk loaded distance smoothly for nice shader fog
|
||||
let loaded_distance = client.loaded_distance().unwrap_or(0) as f32 * 32.0;
|
||||
let loaded_distance = client.loaded_distance().unwrap_or(0) as f32 * 32.0; // TODO: No magic!
|
||||
self.loaded_distance = (0.98 * self.loaded_distance + 0.02 * loaded_distance).max(0.01);
|
||||
|
||||
// Update light constants
|
||||
let mut lights = (&client.state().ecs().read_storage::<comp::Pos>(),)
|
||||
.join()
|
||||
.filter(|(pos,)| {
|
||||
(pos.0.distance_squared(player_pos) as f32)
|
||||
< self.loaded_distance.powf(2.0) + LIGHT_DIST_RADIUS
|
||||
})
|
||||
.map(|(pos,)| pos.0)
|
||||
.map(|pos| Light::new(pos + Vec3::unit_z(), Rgb::broadcast(1.0), 100.0)) // TODO: Don't add 1 to z!
|
||||
.take(32)
|
||||
.collect::<Vec<_>>();
|
||||
lights.sort_by_key(|light| {
|
||||
Vec3::from(Vec4::from(light.pos)).distance_squared(player_pos) as i32
|
||||
});
|
||||
renderer
|
||||
.update_consts(&mut self.lights, &lights)
|
||||
.expect("Failed to update light constants");
|
||||
|
||||
// Update global constants.
|
||||
renderer
|
||||
.update_consts(
|
||||
@ -144,6 +167,7 @@ impl Scene {
|
||||
client.state().get_time_of_day(),
|
||||
client.state().get_time(),
|
||||
renderer.get_resolution(),
|
||||
lights.len(),
|
||||
)],
|
||||
)
|
||||
.expect("Failed to update global constants");
|
||||
@ -171,8 +195,9 @@ impl Scene {
|
||||
renderer.render_skybox(&self.skybox.model, &self.globals, &self.skybox.locals);
|
||||
|
||||
// Render terrain and figures.
|
||||
self.terrain.render(renderer, &self.globals);
|
||||
self.figure_mgr.render(renderer, client, &self.globals);
|
||||
self.terrain.render(renderer, &self.globals, &self.lights);
|
||||
self.figure_mgr
|
||||
.render(renderer, client, &self.globals, &self.lights);
|
||||
|
||||
renderer.render_post_process(
|
||||
&self.postprocess.model,
|
||||
|
@ -1,6 +1,6 @@
|
||||
use crate::{
|
||||
mesh::Meshable,
|
||||
render::{Consts, Globals, Mesh, Model, Renderer, TerrainLocals, TerrainPipeline},
|
||||
render::{Consts, Globals, Light, Mesh, Model, Renderer, TerrainLocals, TerrainPipeline},
|
||||
};
|
||||
use client::Client;
|
||||
use common::{
|
||||
@ -327,10 +327,15 @@ impl Terrain {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn render(&self, renderer: &mut Renderer, globals: &Consts<Globals>) {
|
||||
pub fn render(
|
||||
&self,
|
||||
renderer: &mut Renderer,
|
||||
globals: &Consts<Globals>,
|
||||
lights: &Consts<Light>,
|
||||
) {
|
||||
for (_pos, chunk) in &self.chunks {
|
||||
if chunk.visible {
|
||||
renderer.render_terrain_chunk(&chunk.model, globals, &chunk.locals);
|
||||
renderer.render_terrain_chunk(&chunk.model, globals, &chunk.locals, lights);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user