mirror of
https://gitlab.com/veloren/veloren.git
synced 2024-08-30 18:12:32 +00:00
Linearize light colors on the CPU
This commit is contained in:
parent
546811b4a1
commit
46cf1f1914
@ -58,6 +58,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|||||||
- The ability limit for non-humanoids has been removed
|
- The ability limit for non-humanoids has been removed
|
||||||
- Improved running, wielding, and riding animations
|
- Improved running, wielding, and riding animations
|
||||||
- Fixed offset of items carried on backs when wearing cloaks and backpacks
|
- Fixed offset of items carried on backs when wearing cloaks and backpacks
|
||||||
|
- Linearize light colors on the CPU rather than in shaders on the GPU
|
||||||
|
|
||||||
### Removed
|
### Removed
|
||||||
- Medium and large potions from all loot tables
|
- Medium and large potions from all loot tables
|
||||||
|
@ -84,7 +84,7 @@ vec3 light_at(vec3 wpos, vec3 wnorm) {
|
|||||||
|
|
||||||
float strength = attenuation_strength(difference);
|
float strength = attenuation_strength(difference);
|
||||||
|
|
||||||
vec3 color = srgb_to_linear(L.light_col.rgb) * strength;
|
vec3 color = L.light_col.rgb * strength;
|
||||||
|
|
||||||
light += color * (max(0, max(dot(normalize(difference), wnorm), 0.15)) + LIGHT_AMBIANCE);
|
light += color * (max(0, max(dot(normalize(difference), wnorm), 0.15)) + LIGHT_AMBIANCE);
|
||||||
}
|
}
|
||||||
|
@ -33,7 +33,7 @@ void apply_point_glow_light(Light L, vec3 wpos, vec3 dir, float max_dist, inout
|
|||||||
strength *= clamp(cam_dist_2 / 9.0, 0.25, 1.0);
|
strength *= clamp(cam_dist_2 / 9.0, 0.25, 1.0);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
vec3 light_color = srgb_to_linear(L.light_col.rgb) * strength;
|
vec3 light_color = L.light_col.rgb * strength;
|
||||||
|
|
||||||
const float LIGHT_AMBIANCE = 0.025;
|
const float LIGHT_AMBIANCE = 0.025;
|
||||||
color += light_color
|
color += light_color
|
||||||
|
@ -1,13 +1,13 @@
|
|||||||
use criterion::{black_box, criterion_group, criterion_main, Criterion};
|
use criterion::{black_box, criterion_group, criterion_main, Criterion};
|
||||||
|
|
||||||
use vek::*;
|
use vek::*;
|
||||||
use veloren_common::util::{linear_to_srgb, srgb_to_linear};
|
use veloren_common::util::{linear_to_srgb, srgb_to_linear_fast};
|
||||||
|
|
||||||
fn criterion_benchmark(c: &mut Criterion) {
|
fn criterion_benchmark(c: &mut Criterion) {
|
||||||
let mut c = c.benchmark_group("color");
|
let mut c = c.benchmark_group("color");
|
||||||
c.bench_function("srgb to linear (0.5, 0.1, 0.5)", |b| {
|
c.bench_function("srgb to linear (0.5, 0.1, 0.5)", |b| {
|
||||||
b.iter(|| {
|
b.iter(|| {
|
||||||
black_box(srgb_to_linear(black_box(Rgb::new(0.5, 0.1, 0.5))));
|
black_box(srgb_to_linear_fast(black_box(Rgb::new(0.5, 0.1, 0.5))));
|
||||||
})
|
})
|
||||||
});
|
});
|
||||||
c.bench_function("linear to srgb (0.5, 0.1, 0.5)", |b| {
|
c.bench_function("linear to srgb (0.5, 0.1, 0.5)", |b| {
|
||||||
|
@ -1,8 +1,9 @@
|
|||||||
use vek::{Mat3, Rgb, Rgba, Vec3};
|
use vek::{Mat3, Rgb, Rgba, Vec3};
|
||||||
|
|
||||||
|
/// This function is optimized for speed over perfect accuracy
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
#[allow(clippy::excessive_precision)]
|
#[allow(clippy::excessive_precision)]
|
||||||
pub fn srgb_to_linear(col: Rgb<f32>) -> Rgb<f32> {
|
pub fn srgb_to_linear_fast(col: Rgb<f32>) -> Rgb<f32> {
|
||||||
col.map(|c| {
|
col.map(|c| {
|
||||||
if c <= 0.104 {
|
if c <= 0.104 {
|
||||||
c * 0.08677088
|
c * 0.08677088
|
||||||
@ -12,6 +13,19 @@ pub fn srgb_to_linear(col: Rgb<f32>) -> Rgb<f32> {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// directly converted from 'vec3 srgb_to_linear(vec3 srgb)' function in
|
||||||
|
/// 'srgb.glsl'
|
||||||
|
#[inline(always)]
|
||||||
|
pub fn srgb_to_linear(col: Rgb<f32>) -> Rgb<f32> {
|
||||||
|
col.map(|c| {
|
||||||
|
if c <= 0.04045 {
|
||||||
|
c / 12.92
|
||||||
|
} else {
|
||||||
|
f32::powf((c + 0.055) / 1.055, 2.4)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
#[allow(clippy::excessive_precision)]
|
#[allow(clippy::excessive_precision)]
|
||||||
pub fn linear_to_srgb(col: Rgb<f32>) -> Rgb<f32> {
|
pub fn linear_to_srgb(col: Rgb<f32>) -> Rgb<f32> {
|
||||||
@ -29,7 +43,7 @@ pub fn linear_to_srgb(col: Rgb<f32>) -> Rgb<f32> {
|
|||||||
|
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
pub fn srgba_to_linear(col: Rgba<f32>) -> Rgba<f32> {
|
pub fn srgba_to_linear(col: Rgba<f32>) -> Rgba<f32> {
|
||||||
Rgba::from_translucent(srgb_to_linear(Rgb::from(col)), col.a)
|
Rgba::from_translucent(srgb_to_linear_fast(Rgb::from(col)), col.a)
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
@ -133,7 +147,7 @@ pub fn xyy_to_rgb(xyy: Vec3<f32>) -> Rgb<f32> {
|
|||||||
// TO-DO: speed this up
|
// TO-DO: speed this up
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
pub fn saturate_srgb(col: Rgb<f32>, value: f32) -> Rgb<f32> {
|
pub fn saturate_srgb(col: Rgb<f32>, value: f32) -> Rgb<f32> {
|
||||||
let mut hsv = rgb_to_hsv(srgb_to_linear(col));
|
let mut hsv = rgb_to_hsv(srgb_to_linear_fast(col));
|
||||||
hsv.y *= 1.0 + value;
|
hsv.y *= 1.0 + value;
|
||||||
linear_to_srgb(hsv_to_rgb(hsv).map(|e| e.clamp(0.0, 1.0)))
|
linear_to_srgb(hsv_to_rgb(hsv).map(|e| e.clamp(0.0, 1.0)))
|
||||||
}
|
}
|
||||||
@ -142,8 +156,8 @@ pub fn saturate_srgb(col: Rgb<f32>, value: f32) -> Rgb<f32> {
|
|||||||
/// other
|
/// other
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
pub fn chromify_srgb(luma: Rgb<f32>, chroma: Rgb<f32>) -> Rgb<f32> {
|
pub fn chromify_srgb(luma: Rgb<f32>, chroma: Rgb<f32>) -> Rgb<f32> {
|
||||||
let l = rgb_to_xyy(srgb_to_linear(luma)).z;
|
let l = rgb_to_xyy(srgb_to_linear_fast(luma)).z;
|
||||||
let mut xyy = rgb_to_xyy(srgb_to_linear(chroma));
|
let mut xyy = rgb_to_xyy(srgb_to_linear_fast(chroma));
|
||||||
xyy.z = l;
|
xyy.z = l;
|
||||||
|
|
||||||
linear_to_srgb(xyy_to_rgb(xyy).map(|e| e.clamp(0.0, 1.0)))
|
linear_to_srgb(xyy_to_rgb(xyy).map(|e| e.clamp(0.0, 1.0)))
|
||||||
|
@ -19,7 +19,7 @@ pub mod ui;
|
|||||||
use super::{Consts, Renderer, Texture};
|
use super::{Consts, Renderer, Texture};
|
||||||
use crate::scene::camera::CameraMode;
|
use crate::scene::camera::CameraMode;
|
||||||
use bytemuck::{Pod, Zeroable};
|
use bytemuck::{Pod, Zeroable};
|
||||||
use common::terrain::BlockKind;
|
use common::{terrain::BlockKind, util::srgb_to_linear};
|
||||||
use std::marker::PhantomData;
|
use std::marker::PhantomData;
|
||||||
use vek::*;
|
use vek::*;
|
||||||
|
|
||||||
@ -246,9 +246,12 @@ impl Default for Globals {
|
|||||||
|
|
||||||
impl Light {
|
impl Light {
|
||||||
pub fn new(pos: Vec3<f32>, col: Rgb<f32>, strength: f32) -> Self {
|
pub fn new(pos: Vec3<f32>, col: Rgb<f32>, strength: f32) -> Self {
|
||||||
|
let linearized_col = srgb_to_linear(col);
|
||||||
|
|
||||||
Self {
|
Self {
|
||||||
pos: Vec4::from(pos).into_array(),
|
pos: Vec4::from(pos).into_array(),
|
||||||
col: (Rgba::new(col.r, col.g, col.b, 0.0) * strength).into_array(),
|
col: (Rgba::new(linearized_col.r, linearized_col.g, linearized_col.b, 0.0) * strength)
|
||||||
|
.into_array(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -92,12 +92,12 @@ pub fn load_mesh(mesh_name: &str, position: Vec3<f32>) -> BoneMeshes {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn recolor_grey(rgb: Rgb<u8>, color: Rgb<u8>) -> Rgb<u8> {
|
fn recolor_grey(rgb: Rgb<u8>, color: Rgb<u8>) -> Rgb<u8> {
|
||||||
use common::util::{linear_to_srgb, srgb_to_linear};
|
use common::util::{linear_to_srgb, srgb_to_linear_fast};
|
||||||
|
|
||||||
const BASE_GREY: f32 = 178.0;
|
const BASE_GREY: f32 = 178.0;
|
||||||
if rgb.r == rgb.g && rgb.g == rgb.b {
|
if rgb.r == rgb.g && rgb.g == rgb.b {
|
||||||
let c1 = srgb_to_linear(rgb.map(|e| e as f32 / BASE_GREY));
|
let c1 = srgb_to_linear_fast(rgb.map(|e| e as f32 / BASE_GREY));
|
||||||
let c2 = srgb_to_linear(color.map(|e| e as f32 / 255.0));
|
let c2 = srgb_to_linear_fast(color.map(|e| e as f32 / 255.0));
|
||||||
|
|
||||||
linear_to_srgb(c1 * c2).map(|e| (e.clamp(0.0, 1.0) * 255.0) as u8)
|
linear_to_srgb(c1 * c2).map(|e| (e.clamp(0.0, 1.0) * 255.0) as u8)
|
||||||
} else {
|
} else {
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
use common::{
|
use common::{
|
||||||
figure::Segment,
|
figure::Segment,
|
||||||
util::{linear_to_srgba, srgb_to_linear},
|
util::{linear_to_srgba, srgb_to_linear_fast},
|
||||||
vol::{FilledVox, IntoFullVolIterator, ReadVol, SizedVol},
|
vol::{FilledVox, IntoFullVolIterator, ReadVol, SizedVol},
|
||||||
};
|
};
|
||||||
use euc::{buffer::Buffer2d, rasterizer, Pipeline};
|
use euc::{buffer::Buffer2d, rasterizer, Pipeline};
|
||||||
@ -97,7 +97,7 @@ impl Pipeline for Voxel {
|
|||||||
let diffuse = norm.dot(-self.light_dir).max(0.0);
|
let diffuse = norm.dot(-self.light_dir).max(0.0);
|
||||||
let brightness = 2.5;
|
let brightness = 2.5;
|
||||||
let light = Rgb::from(*ao_level as f32 / 4.0) * (diffuse + ambiance) * brightness;
|
let light = Rgb::from(*ao_level as f32 / 4.0) * (diffuse + ambiance) * brightness;
|
||||||
let color = light * srgb_to_linear(*col);
|
let color = light * srgb_to_linear_fast(*col);
|
||||||
let position = (self.mvp * Vec4::from_point(*pos)).into_array();
|
let position = (self.mvp * Vec4::from_point(*pos)).into_array();
|
||||||
(position, VsOut(Rgba::from_opaque(color)))
|
(position, VsOut(Rgba::from_opaque(color)))
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user