mirror of
https://gitlab.com/veloren/veloren.git
synced 2024-08-30 18:12:32 +00:00
Merge branch 'imbris/srgb' into 'master'
Handle srgb values more accurately, Load shaders at runtime + hotloading Closes #79 See merge request veloren/veloren!412
This commit is contained in:
commit
f12821db35
@ -138,7 +138,6 @@ commit:linux-debug:
|
|||||||
- cp target/debug/veloren-server-cli commit-build
|
- cp target/debug/veloren-server-cli commit-build
|
||||||
- cp target/debug/veloren-voxygen commit-build
|
- cp target/debug/veloren-voxygen commit-build
|
||||||
- cp -r assets commit-build/
|
- cp -r assets commit-build/
|
||||||
- cp -r voxygen/shaders commit-build/
|
|
||||||
- tar -cvjSf bin/commit-linux-debug.tar.bz2 commit-build
|
- tar -cvjSf bin/commit-linux-debug.tar.bz2 commit-build
|
||||||
- cp bin/commit-linux-debug.tar.bz2 $CI_PROJECT_DIR
|
- cp bin/commit-linux-debug.tar.bz2 $CI_PROJECT_DIR
|
||||||
artifacts:
|
artifacts:
|
||||||
@ -156,7 +155,6 @@ commit:windows-debug:
|
|||||||
- cp target/x86_64-pc-windows-gnu/debug/veloren-server-cli.exe commit-build
|
- cp target/x86_64-pc-windows-gnu/debug/veloren-server-cli.exe commit-build
|
||||||
- cp target/x86_64-pc-windows-gnu/debug/veloren-voxygen.exe commit-build
|
- cp target/x86_64-pc-windows-gnu/debug/veloren-voxygen.exe commit-build
|
||||||
- cp -r assets commit-build/
|
- cp -r assets commit-build/
|
||||||
- cp -r voxygen/shaders commit-build/
|
|
||||||
- zip -r bin/commit-windows-debug.zip commit-build
|
- zip -r bin/commit-windows-debug.zip commit-build
|
||||||
- cp bin/commit-windows-debug.zip $CI_PROJECT_DIR
|
- cp bin/commit-windows-debug.zip $CI_PROJECT_DIR
|
||||||
artifacts:
|
artifacts:
|
||||||
@ -187,7 +185,6 @@ optional:linux-debug:
|
|||||||
- cp target/debug/veloren-server-cli optional-build
|
- cp target/debug/veloren-server-cli optional-build
|
||||||
- cp target/debug/veloren-voxygen optional-build
|
- cp target/debug/veloren-voxygen optional-build
|
||||||
- cp -r assets optional-build/
|
- cp -r assets optional-build/
|
||||||
- cp -r voxygen/shaders optional-build/
|
|
||||||
- tar -cvjSf bin/optional-linux-debug.tar.bz2 optional-build
|
- tar -cvjSf bin/optional-linux-debug.tar.bz2 optional-build
|
||||||
- cp bin/optional-linux-debug.tar.bz2 $CI_PROJECT_DIR
|
- cp bin/optional-linux-debug.tar.bz2 $CI_PROJECT_DIR
|
||||||
artifacts:
|
artifacts:
|
||||||
@ -205,7 +202,6 @@ optional:windows-debug:
|
|||||||
- cp target/x86_64-pc-windows-gnu/debug/veloren-server-cli.exe optional-build
|
- cp target/x86_64-pc-windows-gnu/debug/veloren-server-cli.exe optional-build
|
||||||
- cp target/x86_64-pc-windows-gnu/debug/veloren-voxygen.exe optional-build
|
- cp target/x86_64-pc-windows-gnu/debug/veloren-voxygen.exe optional-build
|
||||||
- cp -r assets optional-build/
|
- cp -r assets optional-build/
|
||||||
- cp -r voxygen/shaders optional-build/
|
|
||||||
- zip -r bin/optional-windows-debug.zip optional-build
|
- zip -r bin/optional-windows-debug.zip optional-build
|
||||||
- cp bin/optional-windows-debug.zip $CI_PROJECT_DIR
|
- cp bin/optional-windows-debug.zip $CI_PROJECT_DIR
|
||||||
artifacts:
|
artifacts:
|
||||||
@ -236,7 +232,6 @@ optional-release:linux-debug:
|
|||||||
- cp target/debug/veloren-server-cli optional-release-build
|
- cp target/debug/veloren-server-cli optional-release-build
|
||||||
- cp target/debug/veloren-voxygen optional-release-build
|
- cp target/debug/veloren-voxygen optional-release-build
|
||||||
- cp -r assets optional-release-build/
|
- cp -r assets optional-release-build/
|
||||||
- cp -r voxygen/shaders optional-release-build/
|
|
||||||
- tar -cvjSf bin/optional-release-linux-debug.tar.bz2 optional-release-build
|
- tar -cvjSf bin/optional-release-linux-debug.tar.bz2 optional-release-build
|
||||||
- cp bin/optional-release-linux-debug.tar.bz2 $CI_PROJECT_DIR
|
- cp bin/optional-release-linux-debug.tar.bz2 $CI_PROJECT_DIR
|
||||||
artifacts:
|
artifacts:
|
||||||
@ -254,7 +249,6 @@ optional-release:windows-debug:
|
|||||||
- cp target/x86_64-pc-windows-gnu/debug/veloren-server-cli.exe optional-release-build
|
- cp target/x86_64-pc-windows-gnu/debug/veloren-server-cli.exe optional-release-build
|
||||||
- cp target/x86_64-pc-windows-gnu/debug/veloren-voxygen.exe optional-release-build
|
- cp target/x86_64-pc-windows-gnu/debug/veloren-voxygen.exe optional-release-build
|
||||||
- cp -r assets optional-release-build/
|
- cp -r assets optional-release-build/
|
||||||
- cp -r voxygen/shaders optional-release-build/
|
|
||||||
- zip -r bin/optional-release-windows-debug.zip optional-release-build
|
- zip -r bin/optional-release-windows-debug.zip optional-release-build
|
||||||
- cp bin/optional-release-windows-debug.zip $CI_PROJECT_DIR
|
- cp bin/optional-release-windows-debug.zip $CI_PROJECT_DIR
|
||||||
artifacts:
|
artifacts:
|
||||||
@ -284,7 +278,6 @@ nightly:linux-optimized:
|
|||||||
- cp target/release/veloren-server-cli nightly-build
|
- cp target/release/veloren-server-cli nightly-build
|
||||||
- cp target/release/veloren-voxygen nightly-build
|
- cp target/release/veloren-voxygen nightly-build
|
||||||
- cp -r assets nightly-build/
|
- cp -r assets nightly-build/
|
||||||
- cp -r voxygen/shaders nightly-build/
|
|
||||||
- tar -cvjSf bin/nightly-linux-optimized.tar.bz2 nightly-build
|
- tar -cvjSf bin/nightly-linux-optimized.tar.bz2 nightly-build
|
||||||
- cp bin/nightly-linux-optimized.tar.bz2 $CI_PROJECT_DIR
|
- cp bin/nightly-linux-optimized.tar.bz2 $CI_PROJECT_DIR
|
||||||
artifacts:
|
artifacts:
|
||||||
@ -302,7 +295,6 @@ nightly:windows-optimized:
|
|||||||
- cp target/x86_64-pc-windows-gnu/release/veloren-server-cli.exe nightly-build
|
- cp target/x86_64-pc-windows-gnu/release/veloren-server-cli.exe nightly-build
|
||||||
- cp target/x86_64-pc-windows-gnu/release/veloren-voxygen.exe nightly-build
|
- cp target/x86_64-pc-windows-gnu/release/veloren-voxygen.exe nightly-build
|
||||||
- cp -r assets nightly-build/
|
- cp -r assets nightly-build/
|
||||||
- cp -r voxygen/shaders nightly-build/
|
|
||||||
- zip -r bin/nightly-windows-optimized.zip nightly-build
|
- zip -r bin/nightly-windows-optimized.zip nightly-build
|
||||||
- cp bin/nightly-windows-optimized.zip $CI_PROJECT_DIR
|
- cp bin/nightly-windows-optimized.zip $CI_PROJECT_DIR
|
||||||
artifacts:
|
artifacts:
|
||||||
|
444
Cargo.lock
generated
444
Cargo.lock
generated
File diff suppressed because it is too large
Load Diff
BIN
assets/voxygen/element/slider/indicator.png
(Stored with Git LFS)
BIN
assets/voxygen/element/slider/indicator.png
(Stored with Git LFS)
Binary file not shown.
BIN
assets/voxygen/element/slider/track.png
(Stored with Git LFS)
BIN
assets/voxygen/element/slider/track.png
(Stored with Git LFS)
Binary file not shown.
@ -23,12 +23,13 @@ uniform u_bones {
|
|||||||
|
|
||||||
#include <sky.glsl>
|
#include <sky.glsl>
|
||||||
#include <light.glsl>
|
#include <light.glsl>
|
||||||
|
#include <srgb.glsl>
|
||||||
|
|
||||||
out vec4 tgt_color;
|
out vec4 tgt_color;
|
||||||
|
|
||||||
void main() {
|
void main() {
|
||||||
vec3 light = get_sun_diffuse(f_norm, time_of_day.x) + light_at(f_pos, f_norm);
|
vec3 light = get_sun_diffuse(f_norm, time_of_day.x) + light_at(f_pos, f_norm);
|
||||||
vec3 surf_color = model_col.rgb * f_col * 2.0 * light;
|
vec3 surf_color = srgb_to_linear(model_col.rgb * f_col) * 4.0 * light;
|
||||||
|
|
||||||
float fog_level = fog(f_pos.xy, focus_pos.xy);
|
float fog_level = fog(f_pos.xy, focus_pos.xy);
|
||||||
vec3 fog_color = get_sky_color(normalize(f_pos - cam_pos.xyz), time_of_day.x);
|
vec3 fog_color = get_sky_color(normalize(f_pos - cam_pos.xyz), time_of_day.x);
|
@ -8,6 +8,8 @@ uniform u_lights {
|
|||||||
Light lights[32];
|
Light lights[32];
|
||||||
};
|
};
|
||||||
|
|
||||||
|
#include <srgb.glsl>
|
||||||
|
|
||||||
float attenuation_strength(vec3 rpos) {
|
float attenuation_strength(vec3 rpos) {
|
||||||
return 1.0 / (rpos.x * rpos.x + rpos.y * rpos.y + rpos.z * rpos.z);
|
return 1.0 / (rpos.x * rpos.x + rpos.y * rpos.y + rpos.z * rpos.z);
|
||||||
}
|
}
|
||||||
@ -30,7 +32,7 @@ vec3 light_at(vec3 wpos, vec3 wnorm) {
|
|||||||
float strength = attenuation_strength(difference);
|
float strength = attenuation_strength(difference);
|
||||||
|
|
||||||
// Multiply the vec3 only once
|
// Multiply the vec3 only once
|
||||||
vec3 color = L.light_col.rgb * (strength * L.light_col.a);
|
vec3 color = srgb_to_linear(L.light_col.rgb) * (strength * L.light_col.a);
|
||||||
|
|
||||||
// This is commented out to avoid conditional branching. See here: https://community.khronos.org/t/glsl-float-multiply-by-zero/104391
|
// This is commented out to avoid conditional branching. See here: https://community.khronos.org/t/glsl-float-multiply-by-zero/104391
|
||||||
// if (max(max(color.r, color.g), color.b) < 0.002) {
|
// if (max(max(color.r, color.g), color.b) < 0.002) {
|
@ -1,14 +1,14 @@
|
|||||||
const float PI = 3.141592;
|
const float PI = 3.141592;
|
||||||
|
|
||||||
const vec3 SKY_DAY_TOP = vec3(0.35, 0.45, 0.9);
|
const vec3 SKY_DAY_TOP = vec3(0.1, 0.2, 0.9);
|
||||||
const vec3 SKY_DAY_MID = vec3(0.25, 0.35, 0.8);
|
const vec3 SKY_DAY_MID = vec3(0.02, 0.08, 0.8);
|
||||||
const vec3 SKY_DAY_BOT = vec3(0.02, 0.1, 0.3);
|
const vec3 SKY_DAY_BOT = vec3(0.02, 0.01, 0.3);
|
||||||
const vec3 DAY_LIGHT = vec3(0.5, 0.5, 1.0);
|
const vec3 DAY_LIGHT = vec3(0.75, 0.75, 1.0);
|
||||||
|
|
||||||
const vec3 SKY_DUSK_TOP = vec3(0.1, 0.15, 0.3);
|
const vec3 SKY_DUSK_TOP = vec3(0.21, 0.28, 0.50);
|
||||||
const vec3 SKY_DUSK_MID = vec3(0.8, 0.25, 0.2);
|
const vec3 SKY_DUSK_MID = vec3(0.68, 0.03, 0.0);
|
||||||
const vec3 SKY_DUSK_BOT = vec3(0.01, 0.05, 0.15);
|
const vec3 SKY_DUSK_BOT = vec3(0.0, 0.0, 0.13);
|
||||||
const vec3 DUSK_LIGHT = vec3(0.9, 0.4, 0.3);
|
const vec3 DUSK_LIGHT = vec3(0.95, 0.6, 0.4);
|
||||||
|
|
||||||
const vec3 SKY_NIGHT_TOP = vec3(0.001, 0.001, 0.0025);
|
const vec3 SKY_NIGHT_TOP = vec3(0.001, 0.001, 0.0025);
|
||||||
const vec3 SKY_NIGHT_MID = vec3(0.001, 0.005, 0.02);
|
const vec3 SKY_NIGHT_MID = vec3(0.001, 0.005, 0.02);
|
8
assets/voxygen/shaders/include/srgb.glsl
Normal file
8
assets/voxygen/shaders/include/srgb.glsl
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
//https://gamedev.stackexchange.com/questions/92015/optimized-linear-to-srgb-glsl
|
||||||
|
vec3 srgb_to_linear(vec3 srgb) {
|
||||||
|
bvec3 cutoff = lessThan(srgb, vec3(0.04045));
|
||||||
|
vec3 higher = pow((srgb + vec3(0.055))/vec3(1.055), vec3(2.4));
|
||||||
|
vec3 lower = srgb/vec3(12.92);
|
||||||
|
|
||||||
|
return mix(higher, lower, cutoff);
|
||||||
|
}
|
@ -170,7 +170,8 @@ void main() {
|
|||||||
hsva_color.y *= 1.45;
|
hsva_color.y *= 1.45;
|
||||||
hsva_color.z *= 0.85;
|
hsva_color.z *= 0.85;
|
||||||
//hsva_color.z = 1.0 - 1.0 / (1.0 * hsva_color.z + 1.0);
|
//hsva_color.z = 1.0 - 1.0 / (1.0 * hsva_color.z + 1.0);
|
||||||
vec4 final_color = vec4(hsv2rgb(hsva_color.rgb), hsva_color.a);
|
vec4 final_color = fxaa_color;
|
||||||
|
//vec4 final_color = vec4(hsv2rgb(hsva_color.rgb), hsva_color.a);
|
||||||
|
|
||||||
tgt_color = vec4(final_color.rgb, 1);
|
tgt_color = vec4(final_color.rgb, 1);
|
||||||
}
|
}
|
@ -1,6 +1,7 @@
|
|||||||
#version 330 core
|
#version 330 core
|
||||||
|
|
||||||
#include <globals.glsl>
|
#include <globals.glsl>
|
||||||
|
#include <srgb.glsl>
|
||||||
|
|
||||||
in uint v_pos_norm;
|
in uint v_pos_norm;
|
||||||
in uint v_col_light;
|
in uint v_col_light;
|
||||||
@ -34,11 +35,11 @@ void main() {
|
|||||||
// Use an array to avoid conditional branching
|
// Use an array to avoid conditional branching
|
||||||
f_norm = normals[norm_axis + norm_dir];
|
f_norm = normals[norm_axis + norm_dir];
|
||||||
|
|
||||||
f_col = vec3(
|
f_col = srgb_to_linear(vec3(
|
||||||
float((v_col_light >> 8) & 0xFFu),
|
float((v_col_light >> 8) & 0xFFu),
|
||||||
float((v_col_light >> 16) & 0xFFu),
|
float((v_col_light >> 16) & 0xFFu),
|
||||||
float((v_col_light >> 24) & 0xFFu)
|
float((v_col_light >> 24) & 0xFFu)
|
||||||
) / 200.0;
|
) / 255.0);
|
||||||
|
|
||||||
f_light = float(v_col_light & 0xFFu) / 255.0;
|
f_light = float(v_col_light & 0xFFu) / 255.0;
|
||||||
|
|
@ -1,7 +1,7 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "veloren-common"
|
name = "veloren-common"
|
||||||
version = "0.3.0"
|
version = "0.3.0"
|
||||||
authors = ["Joshua Barretto <joshua.s.barretto@gmail.com>", "Maciej Ćwięka <mckol363@gmail.com>"]
|
authors = ["Joshua Barretto <joshua.s.barretto@gmail.com>", "Maciej Ćwięka <mckol363@gmail.com>", "Imbris <imbrisf@gmail.com>"]
|
||||||
edition = "2018"
|
edition = "2018"
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
@ -27,3 +27,4 @@ hashbrown = { version = "0.5.0", features = ["serde", "nightly"] }
|
|||||||
find_folder = "0.3.0"
|
find_folder = "0.3.0"
|
||||||
parking_lot = "0.9.0"
|
parking_lot = "0.9.0"
|
||||||
crossbeam = "0.7.2"
|
crossbeam = "0.7.2"
|
||||||
|
notify = "5.0.0-pre.1"
|
||||||
|
@ -1,9 +1,11 @@
|
|||||||
//! Load assets (images or voxel data) from files
|
//! Load assets (images or voxel data) from files
|
||||||
|
pub mod watch;
|
||||||
|
|
||||||
use dot_vox::DotVoxData;
|
use dot_vox::DotVoxData;
|
||||||
use hashbrown::HashMap;
|
use hashbrown::HashMap;
|
||||||
use image::DynamicImage;
|
use image::DynamicImage;
|
||||||
use lazy_static::lazy_static;
|
use lazy_static::lazy_static;
|
||||||
|
use log::error;
|
||||||
use serde_json::Value;
|
use serde_json::Value;
|
||||||
use std::{
|
use std::{
|
||||||
any::Any,
|
any::Any,
|
||||||
@ -60,7 +62,7 @@ pub fn load_map<A: Asset + 'static, F: FnOnce(A) -> A>(
|
|||||||
f: F,
|
f: F,
|
||||||
) -> Result<Arc<A>, Error> {
|
) -> Result<Arc<A>, Error> {
|
||||||
let mut assets_write = ASSETS.write().unwrap();
|
let mut assets_write = ASSETS.write().unwrap();
|
||||||
match assets_write.get(&(specifier.to_owned() + A::ENDINGS[0])) {
|
match assets_write.get(specifier) {
|
||||||
Some(asset) => Ok(Arc::clone(asset).downcast()?),
|
Some(asset) => Ok(Arc::clone(asset).downcast()?),
|
||||||
None => {
|
None => {
|
||||||
let asset = Arc::new(f(A::parse(load_file(specifier, A::ENDINGS)?)?));
|
let asset = Arc::new(f(A::parse(load_file(specifier, A::ENDINGS)?)?));
|
||||||
@ -95,8 +97,56 @@ pub fn load_expect<A: Asset + 'static>(specifier: &str) -> Arc<A> {
|
|||||||
load(specifier).unwrap_or_else(|_| panic!("Failed loading essential asset: {}", specifier))
|
load(specifier).unwrap_or_else(|_| panic!("Failed loading essential asset: {}", specifier))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Load an asset while registering it to be watched and reloaded when it changes
|
||||||
|
pub fn load_watched<A: Asset + 'static>(
|
||||||
|
specifier: &str,
|
||||||
|
indicator: &mut watch::ReloadIndicator,
|
||||||
|
) -> Result<Arc<A>, Error> {
|
||||||
|
let asset = load(specifier)?;
|
||||||
|
|
||||||
|
// Determine path to watch
|
||||||
|
let path = unpack_specifier(specifier);
|
||||||
|
let mut path_with_extension = None;
|
||||||
|
for ending in A::ENDINGS {
|
||||||
|
let mut path = path.clone();
|
||||||
|
path.set_extension(ending);
|
||||||
|
|
||||||
|
if path.exists() {
|
||||||
|
path_with_extension = Some(path);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let owned_specifier = specifier.to_string();
|
||||||
|
indicator.add(
|
||||||
|
path_with_extension.ok_or_else(|| Error::NotFound(path.to_string_lossy().into_owned()))?,
|
||||||
|
move || {
|
||||||
|
if let Err(err) = reload::<A>(&owned_specifier) {
|
||||||
|
error!("Error reloading {}: {:#?}", &owned_specifier, err);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
||||||
|
Ok(asset)
|
||||||
|
}
|
||||||
|
|
||||||
/// The Asset trait, which is implemented by all structures that have their data stored in the
|
/// The Asset trait, which is implemented by all structures that have their data stored in the
|
||||||
/// filesystem.
|
/// filesystem.
|
||||||
|
fn reload<A: Asset + 'static>(specifier: &str) -> Result<(), Error> {
|
||||||
|
let asset = Arc::new(A::parse(load_file(specifier, A::ENDINGS)?)?);
|
||||||
|
let clone = Arc::clone(&asset);
|
||||||
|
let mut assets_write = ASSETS.write().unwrap();
|
||||||
|
match assets_write.get_mut(specifier) {
|
||||||
|
Some(a) => *a = clone,
|
||||||
|
None => {
|
||||||
|
assets_write.insert(specifier.to_owned(), clone);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Asset Trait
|
||||||
pub trait Asset: Send + Sync + Sized {
|
pub trait Asset: Send + Sync + Sized {
|
||||||
const ENDINGS: &'static [&'static str];
|
const ENDINGS: &'static [&'static str];
|
||||||
/// Parse the input file and return the correct Asset.
|
/// Parse the input file and return the correct Asset.
|
||||||
@ -129,53 +179,64 @@ impl Asset for Value {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Function to find where the asset/ directory is.
|
impl Asset for String {
|
||||||
fn assets_dir() -> PathBuf {
|
const ENDINGS: &'static [&'static str] = &["glsl"];
|
||||||
let mut paths = Vec::new();
|
fn parse(mut buf_reader: BufReader<File>) -> Result<Self, Error> {
|
||||||
|
let mut string = String::new();
|
||||||
// VELOREN_ASSETS environment variable
|
buf_reader.read_to_string(&mut string)?;
|
||||||
if let Ok(var) = std::env::var("VELOREN_ASSETS") {
|
Ok(string)
|
||||||
paths.push(var.to_owned().into());
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Executable path
|
/// Lazy static to find and cache where the asset directory is.
|
||||||
if let Ok(mut path) = std::env::current_exe() {
|
lazy_static! {
|
||||||
path.pop();
|
static ref ASSETS_PATH: PathBuf = {
|
||||||
paths.push(path);
|
let mut paths = Vec::new();
|
||||||
}
|
|
||||||
|
|
||||||
// Working path
|
// VELOREN_ASSETS environment variable
|
||||||
if let Ok(path) = std::env::current_dir() {
|
if let Ok(var) = std::env::var("VELOREN_ASSETS") {
|
||||||
paths.push(path);
|
paths.push(var.to_owned().into());
|
||||||
}
|
|
||||||
|
|
||||||
// System paths
|
|
||||||
#[cfg(target_os = "linux")]
|
|
||||||
paths.push("/usr/share/veloren/assets".into());
|
|
||||||
|
|
||||||
for path in paths.clone() {
|
|
||||||
match find_folder::Search::ParentsThenKids(3, 1)
|
|
||||||
.of(path)
|
|
||||||
.for_folder("assets")
|
|
||||||
{
|
|
||||||
Ok(assets_path) => return assets_path,
|
|
||||||
Err(_) => continue,
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
panic!(
|
// Executable path
|
||||||
"Asset directory not found. In attempting to find it, we searched:\n{})",
|
if let Ok(mut path) = std::env::current_exe() {
|
||||||
paths.iter().fold(String::new(), |mut a, path| {
|
path.pop();
|
||||||
a += &path.to_string_lossy();
|
paths.push(path);
|
||||||
a += "\n";
|
}
|
||||||
a
|
|
||||||
}),
|
// Working path
|
||||||
);
|
if let Ok(path) = std::env::current_dir() {
|
||||||
|
paths.push(path);
|
||||||
|
}
|
||||||
|
|
||||||
|
// System paths
|
||||||
|
#[cfg(target_os = "linux")]
|
||||||
|
paths.push("/usr/share/veloren/assets".into());
|
||||||
|
|
||||||
|
for path in paths.clone() {
|
||||||
|
match find_folder::Search::ParentsThenKids(3, 1)
|
||||||
|
.of(path)
|
||||||
|
.for_folder("assets")
|
||||||
|
{
|
||||||
|
Ok(assets_path) => return assets_path,
|
||||||
|
Err(_) => continue,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
panic!(
|
||||||
|
"Asset directory not found. In attempting to find it, we searched:\n{})",
|
||||||
|
paths.iter().fold(String::new(), |mut a, path| {
|
||||||
|
a += &path.to_string_lossy();
|
||||||
|
a += "\n";
|
||||||
|
a
|
||||||
|
}),
|
||||||
|
);
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Converts a specifier like "core.backgrounds.city" to ".../veloren/assets/core/backgrounds/city".
|
/// Converts a specifier like "core.backgrounds.city" to ".../veloren/assets/core/backgrounds/city".
|
||||||
fn unpack_specifier(specifier: &str) -> PathBuf {
|
fn unpack_specifier(specifier: &str) -> PathBuf {
|
||||||
let mut path = assets_dir();
|
let mut path = ASSETS_PATH.clone();
|
||||||
path.push(specifier.replace(".", "/"));
|
path.push(specifier.replace(".", "/"));
|
||||||
path
|
path
|
||||||
}
|
}
|
||||||
|
165
common/src/assets/watch.rs
Normal file
165
common/src/assets/watch.rs
Normal file
@ -0,0 +1,165 @@
|
|||||||
|
use crossbeam::channel::{select, unbounded, Receiver, Sender};
|
||||||
|
use lazy_static::lazy_static;
|
||||||
|
use log::warn;
|
||||||
|
use notify::{event::Flag, Event, EventKind, RecommendedWatcher, RecursiveMode, Watcher as _};
|
||||||
|
use std::{
|
||||||
|
collections::HashMap,
|
||||||
|
path::PathBuf,
|
||||||
|
sync::{
|
||||||
|
atomic::{AtomicBool, Ordering},
|
||||||
|
Arc, Mutex, Weak,
|
||||||
|
},
|
||||||
|
thread,
|
||||||
|
time::Duration,
|
||||||
|
};
|
||||||
|
|
||||||
|
type Handler = Box<dyn Fn() + Send>;
|
||||||
|
|
||||||
|
lazy_static! {
|
||||||
|
static ref WATCHER_TX: Mutex<Sender<(PathBuf, Handler, Weak<AtomicBool>)>> =
|
||||||
|
Mutex::new(Watcher::new().run());
|
||||||
|
}
|
||||||
|
|
||||||
|
// This will need to be adjusted when specifier mapping to asset location becomes more dynamic
|
||||||
|
struct Watcher {
|
||||||
|
watching: HashMap<PathBuf, (Handler, Vec<Weak<AtomicBool>>)>,
|
||||||
|
watcher: RecommendedWatcher,
|
||||||
|
event_rx: Receiver<Result<Event, notify::Error>>,
|
||||||
|
}
|
||||||
|
impl Watcher {
|
||||||
|
fn new() -> Self {
|
||||||
|
let (event_tx, event_rx) = unbounded();
|
||||||
|
Watcher {
|
||||||
|
watching: HashMap::new(),
|
||||||
|
watcher: notify::Watcher::new(event_tx, Duration::from_secs(2))
|
||||||
|
.expect("Failed to create notify::Watcher"),
|
||||||
|
event_rx,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
fn watch(&mut self, path: PathBuf, handler: Handler, signal: Weak<AtomicBool>) {
|
||||||
|
match self.watching.get_mut(&path) {
|
||||||
|
Some((_, ref mut v)) => {
|
||||||
|
if !v.iter().any(|s| match (s.upgrade(), signal.upgrade()) {
|
||||||
|
(Some(arc1), Some(arc2)) => Arc::ptr_eq(&arc1, &arc2),
|
||||||
|
_ => false,
|
||||||
|
}) {
|
||||||
|
v.push(signal);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
None => {
|
||||||
|
if let Err(err) = self.watcher.watch(path.clone(), RecursiveMode::Recursive) {
|
||||||
|
warn!("Could not start watching {:#?} due to: {}", &path, err);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
self.watching.insert(path, (handler, vec![signal]));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
fn handle_event(&mut self, event: Event) {
|
||||||
|
// Skip notice events
|
||||||
|
if let Some(Flag::Notice) = event.flag() {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if let Event {
|
||||||
|
kind: EventKind::Modify(_),
|
||||||
|
paths,
|
||||||
|
..
|
||||||
|
} = event
|
||||||
|
{
|
||||||
|
for path in paths {
|
||||||
|
match self.watching.get_mut(&path) {
|
||||||
|
Some((reloader, ref mut signals)) => {
|
||||||
|
if !signals.is_empty() {
|
||||||
|
// Reload this file
|
||||||
|
reloader();
|
||||||
|
|
||||||
|
signals.retain(|signal| match signal.upgrade() {
|
||||||
|
Some(signal) => {
|
||||||
|
signal.store(true, Ordering::Release);
|
||||||
|
true
|
||||||
|
}
|
||||||
|
None => false,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
// If there is no one to signal stop watching this path
|
||||||
|
if signals.is_empty() {
|
||||||
|
if let Err(err) = self.watcher.unwatch(&path) {
|
||||||
|
warn!("Error unwatching: {}", err);
|
||||||
|
}
|
||||||
|
self.watching.remove(&path);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
None => {
|
||||||
|
warn!("Watching {:#?} but there are no signals for this path. The path will be unwatched.", path);
|
||||||
|
if let Err(err) = self.watcher.unwatch(&path) {
|
||||||
|
warn!("Error unwatching: {}", err);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
fn run(mut self) -> Sender<(PathBuf, Handler, Weak<AtomicBool>)> {
|
||||||
|
let (watch_tx, watch_rx) = unbounded();
|
||||||
|
|
||||||
|
thread::spawn(move || {
|
||||||
|
loop {
|
||||||
|
select! {
|
||||||
|
recv(watch_rx) -> res => match res {
|
||||||
|
Ok((path, handler, signal)) => self.watch(path, handler, signal),
|
||||||
|
// Disconnected
|
||||||
|
Err(_) => (),
|
||||||
|
},
|
||||||
|
recv(self.event_rx) -> res => match res {
|
||||||
|
Ok(Ok(event)) => self.handle_event(event),
|
||||||
|
// Notify Error
|
||||||
|
Ok(Err(err)) => error!("Notify error: {}", err),
|
||||||
|
// Disconnected
|
||||||
|
Err(_) => (),
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
watch_tx
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct ReloadIndicator {
|
||||||
|
reloaded: Arc<AtomicBool>,
|
||||||
|
// Paths that have already been added
|
||||||
|
paths: Vec<PathBuf>,
|
||||||
|
}
|
||||||
|
impl ReloadIndicator {
|
||||||
|
pub fn new() -> Self {
|
||||||
|
Self {
|
||||||
|
reloaded: Arc::new(AtomicBool::new(false)),
|
||||||
|
paths: Vec::new(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
pub fn add<F>(&mut self, path: PathBuf, reloader: F)
|
||||||
|
where
|
||||||
|
F: 'static + Fn() + Send,
|
||||||
|
{
|
||||||
|
// Check to see if this was already added
|
||||||
|
if self.paths.iter().any(|p| *p == path) {
|
||||||
|
// Nothing else needs to be done
|
||||||
|
return;
|
||||||
|
} else {
|
||||||
|
self.paths.push(path.clone());
|
||||||
|
};
|
||||||
|
|
||||||
|
if WATCHER_TX
|
||||||
|
.lock()
|
||||||
|
.unwrap()
|
||||||
|
.send((path, Box::new(reloader), Arc::downgrade(&self.reloaded)))
|
||||||
|
.is_err()
|
||||||
|
{
|
||||||
|
error!("Could not add. Asset watcher channel disconnected.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Returns true if the watched file was changed
|
||||||
|
pub fn reloaded(&self) -> bool {
|
||||||
|
self.reloaded.swap(false, Ordering::Acquire)
|
||||||
|
}
|
||||||
|
}
|
@ -1 +1,100 @@
|
|||||||
pub const GIT_HASH: &str = include_str!(concat!(env!("OUT_DIR"), "/githash"));
|
pub const GIT_HASH: &str = include_str!(concat!(env!("OUT_DIR"), "/githash"));
|
||||||
|
|
||||||
|
use vek::{Rgb, Rgba, Vec3};
|
||||||
|
|
||||||
|
#[inline(always)]
|
||||||
|
pub fn srgb_to_linear(col: Rgb<f32>) -> Rgb<f32> {
|
||||||
|
#[inline(always)]
|
||||||
|
fn to_linear(x: f32) -> f32 {
|
||||||
|
if x <= 0.04045 {
|
||||||
|
x / 12.92
|
||||||
|
} else {
|
||||||
|
((x + 0.055) / 1.055).powf(2.4)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
col.map(to_linear)
|
||||||
|
}
|
||||||
|
#[inline(always)]
|
||||||
|
pub fn linear_to_srgb(col: Rgb<f32>) -> Rgb<f32> {
|
||||||
|
#[inline(always)]
|
||||||
|
fn to_srgb(x: f32) -> f32 {
|
||||||
|
if x <= 0.0031308 {
|
||||||
|
x * 12.92
|
||||||
|
} else {
|
||||||
|
x.powf(1.0 / 2.4) * 1.055 - 0.055
|
||||||
|
}
|
||||||
|
}
|
||||||
|
col.map(to_srgb)
|
||||||
|
}
|
||||||
|
#[inline(always)]
|
||||||
|
pub fn srgba_to_linear(col: Rgba<f32>) -> Rgba<f32> {
|
||||||
|
Rgba::from_translucent(srgb_to_linear(Rgb::from(col)), col.a)
|
||||||
|
}
|
||||||
|
#[inline(always)]
|
||||||
|
pub fn linear_to_srgba(col: Rgba<f32>) -> Rgba<f32> {
|
||||||
|
Rgba::from_translucent(linear_to_srgb(Rgb::from(col)), col.a)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Convert rgb to hsv. Expects rgb to be [0, 1].
|
||||||
|
#[inline(always)]
|
||||||
|
pub fn rgb_to_hsv(rgb: Rgb<f32>) -> Vec3<f32> {
|
||||||
|
let (r, g, b) = rgb.into_tuple();
|
||||||
|
let (max, min, diff, add) = {
|
||||||
|
let (max, min, diff, add) = if r > g {
|
||||||
|
(r, g, g - b, 0.0)
|
||||||
|
} else {
|
||||||
|
(g, r, b - r, 2.0)
|
||||||
|
};
|
||||||
|
if b > max {
|
||||||
|
(b, min, r - g, 4.0)
|
||||||
|
} else {
|
||||||
|
(max, b.min(min), diff, add)
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
let v = max;
|
||||||
|
let h = if max == min {
|
||||||
|
0.0
|
||||||
|
} else {
|
||||||
|
let mut h = (60.0 * (add + diff / (max - min)));
|
||||||
|
if h < 0.0 {
|
||||||
|
h += 360.0;
|
||||||
|
}
|
||||||
|
h
|
||||||
|
};
|
||||||
|
let s = if max == 0.0 { 0.0 } else { (max - min) / max };
|
||||||
|
|
||||||
|
Vec3::new(h, s, v)
|
||||||
|
}
|
||||||
|
/// Convert hsv to rgb. Expects h [0, 360], s [0, 1], v [0, 1]
|
||||||
|
#[inline(always)]
|
||||||
|
pub fn hsv_to_rgb(hsv: Vec3<f32>) -> Rgb<f32> {
|
||||||
|
let (h, s, v) = hsv.into_tuple();
|
||||||
|
let c = s * v;
|
||||||
|
let h = h / 60.0;
|
||||||
|
let x = c * (1.0 - (h % 2.0 - 1.0).abs());
|
||||||
|
let m = v - c;
|
||||||
|
|
||||||
|
let (r, g, b) = if h >= 0.0 && h <= 1.0 {
|
||||||
|
(c, x, 0.0)
|
||||||
|
} else if h <= 2.0 {
|
||||||
|
(x, c, 0.0)
|
||||||
|
} else if h <= 3.0 {
|
||||||
|
(0.0, c, x)
|
||||||
|
} else if h <= 4.0 {
|
||||||
|
(0.0, x, c)
|
||||||
|
} else if h <= 5.0 {
|
||||||
|
(x, 0.0, c)
|
||||||
|
} else {
|
||||||
|
(c, 0.0, x)
|
||||||
|
};
|
||||||
|
|
||||||
|
Rgb::new(r + m, g + m, b + m)
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline(always)]
|
||||||
|
pub fn saturate_srgb(col: Rgb<f32>, value: f32) -> Rgb<f32> {
|
||||||
|
let mut hsv = rgb_to_hsv(srgb_to_linear(col));
|
||||||
|
hsv.y *= 1.0 + value;
|
||||||
|
linear_to_srgb(hsv_to_rgb(hsv).map(|e| e.min(1.0).max(0.0)))
|
||||||
|
}
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "veloren-voxygen"
|
name = "veloren-voxygen"
|
||||||
version = "0.3.0"
|
version = "0.3.0"
|
||||||
authors = ["Joshua Barretto <joshua.s.barretto@gmail.com>"]
|
authors = ["Joshua Barretto <joshua.s.barretto@gmail.com>", "Imbris <imbrisf@gmail.com>"]
|
||||||
edition = "2018"
|
edition = "2018"
|
||||||
default-run = "veloren-voxygen"
|
default-run = "veloren-voxygen"
|
||||||
|
|
||||||
|
@ -147,11 +147,11 @@ image_ids! {
|
|||||||
charlist_frame: "voxygen.element.frames.window_4",
|
charlist_frame: "voxygen.element.frames.window_4",
|
||||||
server_frame: "voxygen.element.frames.server_frame",
|
server_frame: "voxygen.element.frames.server_frame",
|
||||||
selection: "voxygen.element.frames.selection",
|
selection: "voxygen.element.frames.selection",
|
||||||
|
|
||||||
<ImageGraphic>
|
|
||||||
slider_range: "voxygen.element.slider.track",
|
slider_range: "voxygen.element.slider.track",
|
||||||
slider_indicator: "voxygen.element.slider.indicator",
|
slider_indicator: "voxygen.element.slider.indicator",
|
||||||
|
|
||||||
|
<ImageGraphic>
|
||||||
|
|
||||||
// Tool Icons
|
// Tool Icons
|
||||||
daggers: "voxygen.element.icons.daggers",
|
daggers: "voxygen.element.icons.daggers",
|
||||||
sword: "voxygen.element.icons.sword",
|
sword: "voxygen.element.icons.sword",
|
||||||
|
@ -4,6 +4,7 @@ use crate::{
|
|||||||
};
|
};
|
||||||
use common::{
|
use common::{
|
||||||
figure::Segment,
|
figure::Segment,
|
||||||
|
util::{linear_to_srgb, srgb_to_linear},
|
||||||
vol::{ReadVol, SizedVol},
|
vol::{ReadVol, SizedVol},
|
||||||
};
|
};
|
||||||
use vek::*;
|
use vek::*;
|
||||||
@ -28,7 +29,12 @@ impl Meshable for Segment {
|
|||||||
offs + pos.map(|e| e as f32),
|
offs + pos.map(|e| e as f32),
|
||||||
col,
|
col,
|
||||||
|origin, norm, col, ao, light| {
|
|origin, norm, col, ao, light| {
|
||||||
FigureVertex::new(origin, norm, col * ao * light, 0)
|
FigureVertex::new(
|
||||||
|
origin,
|
||||||
|
norm,
|
||||||
|
linear_to_srgb(srgb_to_linear(col) * ao * light),
|
||||||
|
0,
|
||||||
|
)
|
||||||
},
|
},
|
||||||
true,
|
true,
|
||||||
&[[[1.0; 3]; 3]; 3],
|
&[[[1.0; 3]; 3]; 3],
|
||||||
|
@ -54,9 +54,9 @@ impl Vertex {
|
|||||||
| ((pos.z.max(0.0).min((1 << 13) as f32) as u32) & 0x1FFF) << 16
|
| ((pos.z.max(0.0).min((1 << 13) as f32) as u32) & 0x1FFF) << 16
|
||||||
| ((norm_bits as u32) & 0x7) << 29,
|
| ((norm_bits as u32) & 0x7) << 29,
|
||||||
col_light: 0
|
col_light: 0
|
||||||
| ((col.r.mul(200.0) as u32) & 0xFF) << 8
|
| ((col.r.mul(255.0) as u32) & 0xFF) << 8
|
||||||
| ((col.g.mul(200.0) as u32) & 0xFF) << 16
|
| ((col.g.mul(255.0) as u32) & 0xFF) << 16
|
||||||
| ((col.b.mul(200.0) as u32) & 0xFF) << 24
|
| ((col.b.mul(255.0) as u32) & 0xFF) << 24
|
||||||
| ((light.mul(255.0) as u32) & 0xFF) << 0,
|
| ((light.mul(255.0) as u32) & 0xFF) << 0,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -7,21 +7,23 @@ use super::{
|
|||||||
texture::Texture,
|
texture::Texture,
|
||||||
Pipeline, RenderError,
|
Pipeline, RenderError,
|
||||||
};
|
};
|
||||||
|
use common::assets::{self, watch::ReloadIndicator};
|
||||||
use gfx::{
|
use gfx::{
|
||||||
self,
|
self,
|
||||||
handle::Sampler,
|
handle::Sampler,
|
||||||
traits::{Device, Factory, FactoryExt},
|
traits::{Device, Factory, FactoryExt},
|
||||||
};
|
};
|
||||||
use glsl_include::Context as IncludeContext;
|
use glsl_include::Context as IncludeContext;
|
||||||
|
use log::error;
|
||||||
use vek::*;
|
use vek::*;
|
||||||
|
|
||||||
/// Represents the format of the pre-processed color target.
|
/// Represents the format of the pre-processed color target.
|
||||||
pub type TgtColorFmt = gfx::format::Rgba16F;
|
pub type TgtColorFmt = gfx::format::Srgba8;
|
||||||
/// Represents the format of the pre-processed depth target.
|
/// Represents the format of the pre-processed depth target.
|
||||||
pub type TgtDepthFmt = gfx::format::Depth;
|
pub type TgtDepthFmt = gfx::format::Depth;
|
||||||
|
|
||||||
/// Represents the format of the window's color target.
|
/// Represents the format of the window's color target.
|
||||||
pub type WinColorFmt = gfx::format::Rgba8;
|
pub type WinColorFmt = gfx::format::Srgba8;
|
||||||
/// Represents the format of the window's depth target.
|
/// Represents the format of the window's depth target.
|
||||||
pub type WinDepthFmt = gfx::format::Depth;
|
pub type WinDepthFmt = gfx::format::Depth;
|
||||||
|
|
||||||
@ -64,6 +66,8 @@ pub struct Renderer {
|
|||||||
terrain_pipeline: GfxPipeline<terrain::pipe::Init<'static>>,
|
terrain_pipeline: GfxPipeline<terrain::pipe::Init<'static>>,
|
||||||
ui_pipeline: GfxPipeline<ui::pipe::Init<'static>>,
|
ui_pipeline: GfxPipeline<ui::pipe::Init<'static>>,
|
||||||
postprocess_pipeline: GfxPipeline<postprocess::pipe::Init<'static>>,
|
postprocess_pipeline: GfxPipeline<postprocess::pipe::Init<'static>>,
|
||||||
|
|
||||||
|
shader_reload_indicator: ReloadIndicator,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Renderer {
|
impl Renderer {
|
||||||
@ -74,74 +78,10 @@ impl Renderer {
|
|||||||
win_color_view: WinColorView,
|
win_color_view: WinColorView,
|
||||||
win_depth_view: WinDepthView,
|
win_depth_view: WinDepthView,
|
||||||
) -> Result<Self, RenderError> {
|
) -> Result<Self, RenderError> {
|
||||||
let globals = include_str!(concat!(
|
let mut shader_reload_indicator = ReloadIndicator::new();
|
||||||
env!("CARGO_MANIFEST_DIR"),
|
|
||||||
"/shaders/include/globals.glsl"
|
|
||||||
));
|
|
||||||
let sky = include_str!(concat!(
|
|
||||||
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();
|
let (skybox_pipeline, figure_pipeline, terrain_pipeline, ui_pipeline, postprocess_pipeline) =
|
||||||
include_ctx.include("globals.glsl", globals);
|
create_pipelines(&mut factory, &mut shader_reload_indicator)?;
|
||||||
include_ctx.include("sky.glsl", sky);
|
|
||||||
include_ctx.include("light.glsl", light);
|
|
||||||
|
|
||||||
// Construct a pipeline for rendering skyboxes
|
|
||||||
let skybox_pipeline = create_pipeline(
|
|
||||||
&mut factory,
|
|
||||||
skybox::pipe::new(),
|
|
||||||
include_str!(concat!(env!("CARGO_MANIFEST_DIR"), "/shaders/skybox.vert")),
|
|
||||||
include_str!(concat!(env!("CARGO_MANIFEST_DIR"), "/shaders/skybox.frag")),
|
|
||||||
&include_ctx,
|
|
||||||
)?;
|
|
||||||
|
|
||||||
// Construct a pipeline for rendering figures
|
|
||||||
let figure_pipeline = create_pipeline(
|
|
||||||
&mut factory,
|
|
||||||
figure::pipe::new(),
|
|
||||||
include_str!(concat!(env!("CARGO_MANIFEST_DIR"), "/shaders/figure.vert")),
|
|
||||||
include_str!(concat!(env!("CARGO_MANIFEST_DIR"), "/shaders/figure.frag")),
|
|
||||||
&include_ctx,
|
|
||||||
)?;
|
|
||||||
|
|
||||||
// Construct a pipeline for rendering terrain
|
|
||||||
let terrain_pipeline = create_pipeline(
|
|
||||||
&mut factory,
|
|
||||||
terrain::pipe::new(),
|
|
||||||
include_str!(concat!(env!("CARGO_MANIFEST_DIR"), "/shaders/terrain.vert")),
|
|
||||||
include_str!(concat!(env!("CARGO_MANIFEST_DIR"), "/shaders/terrain.frag")),
|
|
||||||
&include_ctx,
|
|
||||||
)?;
|
|
||||||
|
|
||||||
// Construct a pipeline for rendering UI elements
|
|
||||||
let ui_pipeline = create_pipeline(
|
|
||||||
&mut factory,
|
|
||||||
ui::pipe::new(),
|
|
||||||
include_str!(concat!(env!("CARGO_MANIFEST_DIR"), "/shaders/ui.vert")),
|
|
||||||
include_str!(concat!(env!("CARGO_MANIFEST_DIR"), "/shaders/ui.frag")),
|
|
||||||
&include_ctx,
|
|
||||||
)?;
|
|
||||||
|
|
||||||
// Construct a pipeline for rendering our post-processing
|
|
||||||
let postprocess_pipeline = create_pipeline(
|
|
||||||
&mut factory,
|
|
||||||
postprocess::pipe::new(),
|
|
||||||
include_str!(concat!(
|
|
||||||
env!("CARGO_MANIFEST_DIR"),
|
|
||||||
"/shaders/postprocess.vert"
|
|
||||||
)),
|
|
||||||
include_str!(concat!(
|
|
||||||
env!("CARGO_MANIFEST_DIR"),
|
|
||||||
"/shaders/postprocess.frag"
|
|
||||||
)),
|
|
||||||
&include_ctx,
|
|
||||||
)?;
|
|
||||||
|
|
||||||
let dims = win_color_view.get_dimensions();
|
let dims = win_color_view.get_dimensions();
|
||||||
let (tgt_color_view, tgt_depth_view, tgt_color_res) =
|
let (tgt_color_view, tgt_depth_view, tgt_color_res) =
|
||||||
@ -168,6 +108,8 @@ impl Renderer {
|
|||||||
terrain_pipeline,
|
terrain_pipeline,
|
||||||
ui_pipeline,
|
ui_pipeline,
|
||||||
postprocess_pipeline,
|
postprocess_pipeline,
|
||||||
|
|
||||||
|
shader_reload_indicator,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -242,6 +184,29 @@ impl Renderer {
|
|||||||
pub fn flush(&mut self) {
|
pub fn flush(&mut self) {
|
||||||
self.encoder.flush(&mut self.device);
|
self.encoder.flush(&mut self.device);
|
||||||
self.device.cleanup();
|
self.device.cleanup();
|
||||||
|
|
||||||
|
// If the shaders files were changed attempt to recreate the shaders
|
||||||
|
if self.shader_reload_indicator.reloaded() {
|
||||||
|
match create_pipelines(&mut self.factory, &mut self.shader_reload_indicator) {
|
||||||
|
Ok((
|
||||||
|
skybox_pipeline,
|
||||||
|
figure_pipeline,
|
||||||
|
terrain_pipline,
|
||||||
|
ui_pipeline,
|
||||||
|
postprocess_pipeline,
|
||||||
|
)) => {
|
||||||
|
self.skybox_pipeline = skybox_pipeline;
|
||||||
|
self.figure_pipeline = figure_pipeline;
|
||||||
|
self.terrain_pipeline = terrain_pipline;
|
||||||
|
self.ui_pipeline = ui_pipeline;
|
||||||
|
self.postprocess_pipeline = postprocess_pipeline;
|
||||||
|
}
|
||||||
|
Err(e) => error!(
|
||||||
|
"Could not recreate shaders from assets due to an error: {:#?}",
|
||||||
|
e
|
||||||
|
),
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Create a new set of constants with the provided values.
|
/// Create a new set of constants with the provided values.
|
||||||
@ -488,6 +453,109 @@ struct GfxPipeline<P: gfx::pso::PipelineInit> {
|
|||||||
pso: gfx::pso::PipelineState<gfx_backend::Resources, P::Meta>,
|
pso: gfx::pso::PipelineState<gfx_backend::Resources, P::Meta>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Creates all the pipelines used to render.
|
||||||
|
fn create_pipelines(
|
||||||
|
factory: &mut gfx_backend::Factory,
|
||||||
|
shader_reload_indicator: &mut ReloadIndicator,
|
||||||
|
) -> Result<
|
||||||
|
(
|
||||||
|
GfxPipeline<skybox::pipe::Init<'static>>,
|
||||||
|
GfxPipeline<figure::pipe::Init<'static>>,
|
||||||
|
GfxPipeline<terrain::pipe::Init<'static>>,
|
||||||
|
GfxPipeline<ui::pipe::Init<'static>>,
|
||||||
|
GfxPipeline<postprocess::pipe::Init<'static>>,
|
||||||
|
),
|
||||||
|
RenderError,
|
||||||
|
> {
|
||||||
|
let globals =
|
||||||
|
assets::load_watched::<String>("voxygen.shaders.include.globals", shader_reload_indicator)
|
||||||
|
.unwrap();
|
||||||
|
let sky =
|
||||||
|
assets::load_watched::<String>("voxygen.shaders.include.sky", shader_reload_indicator)
|
||||||
|
.unwrap();
|
||||||
|
let light =
|
||||||
|
assets::load_watched::<String>("voxygen.shaders.include.light", shader_reload_indicator)
|
||||||
|
.unwrap();
|
||||||
|
let srgb =
|
||||||
|
assets::load_watched::<String>("voxygen.shaders.include.srgb", shader_reload_indicator)
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
|
let mut include_ctx = IncludeContext::new();
|
||||||
|
include_ctx.include("globals.glsl", &globals);
|
||||||
|
include_ctx.include("sky.glsl", &sky);
|
||||||
|
include_ctx.include("light.glsl", &light);
|
||||||
|
include_ctx.include("srgb.glsl", &srgb);
|
||||||
|
|
||||||
|
// Construct a pipeline for rendering skyboxes
|
||||||
|
let skybox_pipeline = create_pipeline(
|
||||||
|
factory,
|
||||||
|
skybox::pipe::new(),
|
||||||
|
&assets::load_watched::<String>("voxygen.shaders.skybox-vert", shader_reload_indicator)
|
||||||
|
.unwrap(),
|
||||||
|
&assets::load_watched::<String>("voxygen.shaders.skybox-frag", shader_reload_indicator)
|
||||||
|
.unwrap(),
|
||||||
|
&include_ctx,
|
||||||
|
)?;
|
||||||
|
|
||||||
|
// Construct a pipeline for rendering figures
|
||||||
|
let figure_pipeline = create_pipeline(
|
||||||
|
factory,
|
||||||
|
figure::pipe::new(),
|
||||||
|
&assets::load_watched::<String>("voxygen.shaders.figure-vert", shader_reload_indicator)
|
||||||
|
.unwrap(),
|
||||||
|
&assets::load_watched::<String>("voxygen.shaders.figure-frag", shader_reload_indicator)
|
||||||
|
.unwrap(),
|
||||||
|
&include_ctx,
|
||||||
|
)?;
|
||||||
|
|
||||||
|
// Construct a pipeline for rendering terrain
|
||||||
|
let terrain_pipeline = create_pipeline(
|
||||||
|
factory,
|
||||||
|
terrain::pipe::new(),
|
||||||
|
&assets::load_watched::<String>("voxygen.shaders.terrain-vert", shader_reload_indicator)
|
||||||
|
.unwrap(),
|
||||||
|
&assets::load_watched::<String>("voxygen.shaders.terrain-frag", shader_reload_indicator)
|
||||||
|
.unwrap(),
|
||||||
|
&include_ctx,
|
||||||
|
)?;
|
||||||
|
|
||||||
|
// Construct a pipeline for rendering UI elements
|
||||||
|
let ui_pipeline = create_pipeline(
|
||||||
|
factory,
|
||||||
|
ui::pipe::new(),
|
||||||
|
&assets::load_watched::<String>("voxygen.shaders.ui-vert", shader_reload_indicator)
|
||||||
|
.unwrap(),
|
||||||
|
&assets::load_watched::<String>("voxygen.shaders.ui-frag", shader_reload_indicator)
|
||||||
|
.unwrap(),
|
||||||
|
&include_ctx,
|
||||||
|
)?;
|
||||||
|
|
||||||
|
// Construct a pipeline for rendering our post-processing
|
||||||
|
let postprocess_pipeline = create_pipeline(
|
||||||
|
factory,
|
||||||
|
postprocess::pipe::new(),
|
||||||
|
&assets::load_watched::<String>(
|
||||||
|
"voxygen.shaders.postprocess-vert",
|
||||||
|
shader_reload_indicator,
|
||||||
|
)
|
||||||
|
.unwrap(),
|
||||||
|
&assets::load_watched::<String>(
|
||||||
|
"voxygen.shaders.postprocess-frag",
|
||||||
|
shader_reload_indicator,
|
||||||
|
)
|
||||||
|
.unwrap(),
|
||||||
|
&include_ctx,
|
||||||
|
)?;
|
||||||
|
|
||||||
|
Ok((
|
||||||
|
skybox_pipeline,
|
||||||
|
figure_pipeline,
|
||||||
|
terrain_pipeline,
|
||||||
|
ui_pipeline,
|
||||||
|
postprocess_pipeline,
|
||||||
|
))
|
||||||
|
}
|
||||||
|
|
||||||
/// Create a new pipeline from the provided vertex shader and fragment shader.
|
/// Create a new pipeline from the provided vertex shader and fragment shader.
|
||||||
fn create_pipeline<'a, P: gfx::pso::PipelineInit>(
|
fn create_pipeline<'a, P: gfx::pso::PipelineInit>(
|
||||||
factory: &mut gfx_backend::Factory,
|
factory: &mut gfx_backend::Factory,
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
use super::super::{linear_to_srgb, srgb_to_linear};
|
|
||||||
use common::{
|
use common::{
|
||||||
figure::Segment,
|
figure::Segment,
|
||||||
|
util::{linear_to_srgba, srgba_to_linear},
|
||||||
vol::{ReadVol, SizedVol, Vox},
|
vol::{ReadVol, SizedVol, Vox},
|
||||||
};
|
};
|
||||||
use euc::{buffer::Buffer2d, rasterizer, Pipeline};
|
use euc::{buffer::Buffer2d, rasterizer, Pipeline};
|
||||||
@ -46,13 +46,13 @@ impl<'a> Pipeline for Voxel {
|
|||||||
}: &Self::Vertex,
|
}: &Self::Vertex,
|
||||||
) -> ([f32; 3], Self::VsOut) {
|
) -> ([f32; 3], Self::VsOut) {
|
||||||
let light = Rgba::from_opaque(Rgb::from(*ao_level as f32 / 4.0 + 0.25));
|
let light = Rgba::from_opaque(Rgb::from(*ao_level as f32 / 4.0 + 0.25));
|
||||||
let color = light * srgb_to_linear(Rgba::from_opaque(*col));
|
let color = light * srgba_to_linear(Rgba::from_opaque(*col));
|
||||||
let position = Vec3::from(self.mvp * Vec4::from_point(*pos)).into_array();
|
let position = Vec3::from(self.mvp * Vec4::from_point(*pos)).into_array();
|
||||||
(position, color)
|
(position, color)
|
||||||
}
|
}
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
fn frag(&self, color: &Self::VsOut) -> Self::Pixel {
|
fn frag(&self, color: &Self::VsOut) -> Self::Pixel {
|
||||||
linear_to_srgb(*color)
|
linear_to_srgba(*color)
|
||||||
.map(|e| (e * 255.0) as u8)
|
.map(|e| (e * 255.0) as u8)
|
||||||
.into_array()
|
.into_array()
|
||||||
}
|
}
|
||||||
|
@ -2,7 +2,6 @@ mod cache;
|
|||||||
mod event;
|
mod event;
|
||||||
mod graphic;
|
mod graphic;
|
||||||
mod scale;
|
mod scale;
|
||||||
mod util;
|
|
||||||
mod widgets;
|
mod widgets;
|
||||||
#[macro_use]
|
#[macro_use]
|
||||||
pub mod img_ids;
|
pub mod img_ids;
|
||||||
@ -28,7 +27,7 @@ use crate::{
|
|||||||
Error,
|
Error,
|
||||||
};
|
};
|
||||||
use cache::Cache;
|
use cache::Cache;
|
||||||
use common::assets;
|
use common::{assets, util::srgba_to_linear};
|
||||||
use conrod_core::{
|
use conrod_core::{
|
||||||
event::Input,
|
event::Input,
|
||||||
graph::Graph,
|
graph::Graph,
|
||||||
@ -48,7 +47,6 @@ use std::{
|
|||||||
sync::Arc,
|
sync::Arc,
|
||||||
time::Duration,
|
time::Duration,
|
||||||
};
|
};
|
||||||
use util::{linear_to_srgb, srgb_to_linear};
|
|
||||||
use vek::*;
|
use vek::*;
|
||||||
use widgets::tooltip::TooltipManager;
|
use widgets::tooltip::TooltipManager;
|
||||||
|
|
||||||
@ -406,7 +404,7 @@ impl Ui {
|
|||||||
}
|
}
|
||||||
|
|
||||||
let color =
|
let color =
|
||||||
srgb_to_linear(color.unwrap_or(conrod_core::color::WHITE).to_fsa().into());
|
srgba_to_linear(color.unwrap_or(conrod_core::color::WHITE).to_fsa().into());
|
||||||
|
|
||||||
let resolution = Vec2::new(
|
let resolution = Vec2::new(
|
||||||
(rect.w() * p_scale_factor).round() as u16,
|
(rect.w() * p_scale_factor).round() as u16,
|
||||||
@ -485,7 +483,7 @@ impl Ui {
|
|||||||
})
|
})
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
|
||||||
let color = srgb_to_linear(color.to_fsa().into());
|
let color = srgba_to_linear(color.to_fsa().into());
|
||||||
|
|
||||||
for g in positioned_glyphs {
|
for g in positioned_glyphs {
|
||||||
if let Ok(Some((uv_rect, screen_rect))) =
|
if let Ok(Some((uv_rect, screen_rect))) =
|
||||||
@ -514,7 +512,7 @@ impl Ui {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
PrimitiveKind::Rectangle { color } => {
|
PrimitiveKind::Rectangle { color } => {
|
||||||
let color = srgb_to_linear(color.to_fsa().into());
|
let color = srgba_to_linear(color.to_fsa().into());
|
||||||
// Don't draw a transparent rectangle.
|
// Don't draw a transparent rectangle.
|
||||||
if color[3] == 0.0 {
|
if color[3] == 0.0 {
|
||||||
continue;
|
continue;
|
||||||
@ -534,7 +532,7 @@ impl Ui {
|
|||||||
}
|
}
|
||||||
PrimitiveKind::TrianglesSingleColor { color, triangles } => {
|
PrimitiveKind::TrianglesSingleColor { color, triangles } => {
|
||||||
// Don't draw transparent triangle or switch state if there are actually no triangles.
|
// Don't draw transparent triangle or switch state if there are actually no triangles.
|
||||||
let color = srgb_to_linear(Rgba::from(Into::<[f32; 4]>::into(color)));
|
let color = srgba_to_linear(Rgba::from(Into::<[f32; 4]>::into(color)));
|
||||||
if triangles.is_empty() || color[3] == 0.0 {
|
if triangles.is_empty() || color[3] == 0.0 {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
@ -1,36 +0,0 @@
|
|||||||
use vek::*;
|
|
||||||
|
|
||||||
#[inline(always)]
|
|
||||||
pub fn srgb_to_linear(c: Rgba<f32>) -> Rgba<f32> {
|
|
||||||
#[inline(always)]
|
|
||||||
fn to_linear(x: f32) -> f32 {
|
|
||||||
if x <= 0.04045 {
|
|
||||||
x / 12.92
|
|
||||||
} else {
|
|
||||||
((x + 0.055) / 1.055).powf(2.4)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Rgba {
|
|
||||||
r: to_linear(c.r),
|
|
||||||
g: to_linear(c.g),
|
|
||||||
b: to_linear(c.b),
|
|
||||||
a: c.a,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#[inline(always)]
|
|
||||||
pub fn linear_to_srgb(c: Rgba<f32>) -> Rgba<f32> {
|
|
||||||
#[inline(always)]
|
|
||||||
fn to_srgb(x: f32) -> f32 {
|
|
||||||
if x <= 0.0031308 {
|
|
||||||
x * 12.92
|
|
||||||
} else {
|
|
||||||
x.powf(1.0 / 2.4) * 1.055 - 0.055
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Rgba {
|
|
||||||
r: to_srgb(c.r),
|
|
||||||
g: to_srgb(c.g),
|
|
||||||
b: to_srgb(c.b),
|
|
||||||
a: c.a,
|
|
||||||
}
|
|
||||||
}
|
|
@ -7,6 +7,7 @@ use crate::{
|
|||||||
};
|
};
|
||||||
use common::{
|
use common::{
|
||||||
terrain::{structure::StructureBlock, Block, Structure},
|
terrain::{structure::StructureBlock, Block, Structure},
|
||||||
|
util::saturate_srgb,
|
||||||
vol::{ReadVol, Vox},
|
vol::{ReadVol, Vox},
|
||||||
};
|
};
|
||||||
use noise::NoiseFn;
|
use noise::NoiseFn;
|
||||||
@ -208,7 +209,9 @@ impl<'a> BlockGen<'a> {
|
|||||||
|
|
||||||
// Sample blocks
|
// Sample blocks
|
||||||
|
|
||||||
let stone_col = Rgb::new(240, 230, 220);
|
// let stone_col = Rgb::new(240, 230, 220);
|
||||||
|
let stone_col = Rgb::new(195, 187, 201);
|
||||||
|
|
||||||
// let dirt_col = Rgb::new(79, 67, 60);
|
// let dirt_col = Rgb::new(79, 67, 60);
|
||||||
|
|
||||||
let air = Block::empty();
|
let air = Block::empty();
|
||||||
@ -217,12 +220,14 @@ impl<'a> BlockGen<'a> {
|
|||||||
// let dirt = Block::new(1, dirt_col);
|
// let dirt = Block::new(1, dirt_col);
|
||||||
// let sand = Block::new(1, Rgb::new(180, 150, 50));
|
// let sand = Block::new(1, Rgb::new(180, 150, 50));
|
||||||
// let warm_stone = Block::new(1, Rgb::new(165, 165, 130));
|
// let warm_stone = Block::new(1, Rgb::new(165, 165, 130));
|
||||||
let water = Block::new(1, Rgb::new(100, 150, 255));
|
|
||||||
|
//let water = Block::new(1, Rgb::new(100, 150, 255));
|
||||||
|
let water = Block::new(1, Rgb::new(0, 24, 255));
|
||||||
|
|
||||||
let grass_depth = 1.5 + 2.0 * chaos;
|
let grass_depth = 1.5 + 2.0 * chaos;
|
||||||
let block = if (wposf.z as f32) < height - grass_depth {
|
let block = if (wposf.z as f32) < height - grass_depth {
|
||||||
let col = Lerp::lerp(
|
let col = Lerp::lerp(
|
||||||
sub_surface_color.map(|e| (e * 255.0) as u8),
|
saturate_srgb(sub_surface_color, 0.45).map(|e| (e * 255.0) as u8),
|
||||||
stone_col,
|
stone_col,
|
||||||
(height - grass_depth - wposf.z as f32) * 0.15,
|
(height - grass_depth - wposf.z as f32) * 0.15,
|
||||||
);
|
);
|
||||||
@ -242,7 +247,10 @@ impl<'a> BlockGen<'a> {
|
|||||||
.powf(0.5),
|
.powf(0.5),
|
||||||
);
|
);
|
||||||
// Surface
|
// Surface
|
||||||
Some(Block::new(1, col.map(|e| (e * 255.0) as u8)))
|
Some(Block::new(
|
||||||
|
1,
|
||||||
|
saturate_srgb(col, 0.45).map(|e| (e * 255.0) as u8),
|
||||||
|
))
|
||||||
} else if (wposf.z as f32) < water_height {
|
} else if (wposf.z as f32) < water_height {
|
||||||
// Ocean
|
// Ocean
|
||||||
Some(water)
|
Some(water)
|
||||||
@ -279,9 +287,9 @@ impl<'a> BlockGen<'a> {
|
|||||||
1,
|
1,
|
||||||
stone_col
|
stone_col
|
||||||
- Rgb::new(
|
- Rgb::new(
|
||||||
field0.get(wpos) as u8 % 32,
|
field0.get(wpos) as u8 % 16,
|
||||||
field1.get(wpos) as u8 % 32,
|
field1.get(wpos) as u8 % 16,
|
||||||
field2.get(wpos) as u8 % 32,
|
field2.get(wpos) as u8 % 16,
|
||||||
),
|
),
|
||||||
))
|
))
|
||||||
} else {
|
} else {
|
||||||
@ -407,7 +415,7 @@ impl StructureInfo {
|
|||||||
.map(|e: i32| (e.abs() / 2) * 2)
|
.map(|e: i32| (e.abs() / 2) * 2)
|
||||||
.reduce_max()
|
.reduce_max()
|
||||||
{
|
{
|
||||||
Some(Block::new(2, Rgb::new(180, 140, 90)))
|
Some(Block::new(2, Rgb::new(203, 170, 146)))
|
||||||
} else {
|
} else {
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
@ -445,35 +453,39 @@ fn block_from_structure(
|
|||||||
match sblock {
|
match sblock {
|
||||||
StructureBlock::TemperateLeaves => Some(Block::new(
|
StructureBlock::TemperateLeaves => Some(Block::new(
|
||||||
1,
|
1,
|
||||||
Lerp::lerp(Rgb::new(0.0, 70.0, 35.0), Rgb::new(100.0, 140.0, 0.0), lerp)
|
Lerp::lerp(
|
||||||
.map(|e| e as u8),
|
Rgb::new(0.0, 132.0, 94.0),
|
||||||
|
Rgb::new(142.0, 181.0, 0.0),
|
||||||
|
lerp,
|
||||||
|
)
|
||||||
|
.map(|e| e as u8),
|
||||||
)),
|
)),
|
||||||
StructureBlock::PineLeaves => Some(Block::new(
|
StructureBlock::PineLeaves => Some(Block::new(
|
||||||
1,
|
1,
|
||||||
Lerp::lerp(Rgb::new(0.0, 60.0, 50.0), Rgb::new(30.0, 100.0, 10.0), lerp)
|
Lerp::lerp(
|
||||||
.map(|e| e as u8),
|
Rgb::new(0.0, 108.0, 113.0),
|
||||||
|
Rgb::new(30.0, 156.0, 10.0),
|
||||||
|
lerp,
|
||||||
|
)
|
||||||
|
.map(|e| e as u8),
|
||||||
)),
|
)),
|
||||||
StructureBlock::PalmLeaves => Some(Block::new(
|
StructureBlock::PalmLeaves => Some(Block::new(
|
||||||
1,
|
1,
|
||||||
Lerp::lerp(
|
Lerp::lerp(
|
||||||
Rgb::new(15.0, 100.0, 30.0),
|
Rgb::new(15.0, 156.0, 70.0),
|
||||||
Rgb::new(55.0, 220.0, 0.0),
|
Rgb::new(40.0, 222.0, 0.0),
|
||||||
lerp,
|
lerp,
|
||||||
)
|
)
|
||||||
.map(|e| e as u8),
|
.map(|e| e as u8),
|
||||||
)),
|
)),
|
||||||
StructureBlock::Acacia => Some(Block::new(
|
StructureBlock::Acacia => Some(Block::new(
|
||||||
1,
|
1,
|
||||||
Lerp::lerp(
|
Lerp::lerp(Rgb::new(35.0, 156.0, 0.0), Rgb::new(62.0, 208.0, 0.0), lerp)
|
||||||
Rgb::new(35.0, 100.0, 10.0),
|
.map(|e| e as u8),
|
||||||
Rgb::new(70.0, 190.0, 25.0),
|
|
||||||
lerp,
|
|
||||||
)
|
|
||||||
.map(|e| e as u8),
|
|
||||||
)),
|
)),
|
||||||
StructureBlock::Fruit => Some(Block::new(
|
StructureBlock::Fruit => Some(Block::new(
|
||||||
1,
|
1,
|
||||||
Lerp::lerp(Rgb::new(255.0, 0.0, 0.0), Rgb::new(200.0, 255.0, 6.0), lerp)
|
Lerp::lerp(Rgb::new(237.0, 0.0, 0.0), Rgb::new(200.0, 237.0, 0.0), lerp)
|
||||||
.map(|e| e as u8),
|
.map(|e| e as u8),
|
||||||
)),
|
)),
|
||||||
StructureBlock::Hollow => Some(Block::empty()),
|
StructureBlock::Hollow => Some(Block::empty()),
|
||||||
|
@ -188,24 +188,28 @@ impl<'a> Sampler for ColumnGen<'a> {
|
|||||||
.add(marble_small.sub(0.5).mul(0.25));
|
.add(marble_small.sub(0.5).mul(0.25));
|
||||||
|
|
||||||
// Colours
|
// Colours
|
||||||
let cold_grass = Rgb::new(0.0, 0.25, 0.13);
|
let cold_grass = Rgb::new(0.0, 0.49, 0.42);
|
||||||
let warm_grass = Rgb::new(0.18, 0.65, 0.0);
|
let warm_grass = Rgb::new(0.03, 0.8, 0.0);
|
||||||
let cold_stone = Rgb::new(0.55, 0.7, 0.75);
|
let cold_stone = Rgb::new(0.57, 0.67, 0.8);
|
||||||
let warm_stone = Rgb::new(0.65, 0.65, 0.35);
|
let warm_stone = Rgb::new(0.77, 0.77, 0.64);
|
||||||
let beach_sand = Rgb::new(0.9, 0.85, 0.3);
|
let beach_sand = Rgb::new(0.89, 0.87, 0.64);
|
||||||
let desert_sand = Rgb::new(1.0, 0.7, 0.15);
|
let desert_sand = Rgb::new(0.93, 0.80, 0.54);
|
||||||
let snow = Rgb::broadcast(1.0);
|
let snow = Rgb::broadcast(0.77);
|
||||||
|
|
||||||
let dirt = Lerp::lerp(Rgb::new(0.2, 0.1, 0.05), Rgb::new(0.4, 0.25, 0.0), marble);
|
let dirt = Lerp::lerp(
|
||||||
|
Rgb::new(0.078, 0.078, 0.20),
|
||||||
|
Rgb::new(0.61, 0.49, 0.0),
|
||||||
|
marble,
|
||||||
|
);
|
||||||
let cliff = Rgb::lerp(cold_stone, warm_stone, marble);
|
let cliff = Rgb::lerp(cold_stone, warm_stone, marble);
|
||||||
|
|
||||||
let grass = Rgb::lerp(cold_grass, warm_grass, marble);
|
let grass = Rgb::lerp(cold_grass, warm_grass, marble.powf(1.5));
|
||||||
let sand = Rgb::lerp(beach_sand, desert_sand, marble);
|
let sand = Rgb::lerp(beach_sand, desert_sand, marble);
|
||||||
|
|
||||||
let tropical = Rgb::lerp(
|
let tropical = Rgb::lerp(
|
||||||
grass,
|
grass,
|
||||||
Rgb::new(0.85, 0.4, 0.2),
|
Rgb::new(0.87, 0.62, 0.56),
|
||||||
marble_small.sub(0.5).mul(0.2).add(0.75),
|
marble_small.sub(0.5).mul(0.2).add(0.75).powf(0.667),
|
||||||
);
|
);
|
||||||
|
|
||||||
let ground = Rgb::lerp(
|
let ground = Rgb::lerp(
|
||||||
|
Loading…
Reference in New Issue
Block a user