mirror of
https://gitlab.com/veloren/veloren.git
synced 2024-08-30 18:12:32 +00:00
Add resolution downscaling to QuadPng's color channel, and use half-resolution QuadPng ingame.
This commit is contained in:
parent
f81539cb00
commit
a220cc569e
@ -316,7 +316,6 @@ impl VoxelImageDecoding for MixedEncoding {
|
||||
indices[1]..indices[2],
|
||||
indices[2]..quad.len(),
|
||||
];
|
||||
tracing::info!("{:?} {:?}", ranges, indices);
|
||||
let a = image_from_bytes(PngDecoder::new(&quad[ranges[0].clone()]).ok()?)?;
|
||||
let b = image_from_bytes(PngDecoder::new(&quad[ranges[1].clone()]).ok()?)?;
|
||||
let c = image_from_bytes(PngDecoder::new(&quad[ranges[2].clone()]).ok()?)?;
|
||||
@ -350,9 +349,9 @@ impl VoxelImageDecoding for MixedEncoding {
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Copy, Serialize, Deserialize)]
|
||||
pub struct QuadPngEncoding;
|
||||
pub struct QuadPngEncoding<const RESOLUTION_DIVIDER: u32>();
|
||||
|
||||
impl VoxelImageEncoding for QuadPngEncoding {
|
||||
impl<const N: u32> VoxelImageEncoding for QuadPngEncoding<N> {
|
||||
type Output = CompressedData<(Vec<u8>, [usize; 3])>;
|
||||
#[allow(clippy::type_complexity)]
|
||||
type Workspace = (
|
||||
@ -367,7 +366,7 @@ impl VoxelImageEncoding for QuadPngEncoding {
|
||||
ImageBuffer::new(width, height),
|
||||
ImageBuffer::new(width, height),
|
||||
ImageBuffer::new(width, height),
|
||||
ImageBuffer::new(width, height),
|
||||
ImageBuffer::new(width / N, height / N),
|
||||
)
|
||||
}
|
||||
|
||||
@ -375,7 +374,7 @@ impl VoxelImageEncoding for QuadPngEncoding {
|
||||
ws.0.put_pixel(x, y, image::Luma([kind as u8]));
|
||||
ws.1.put_pixel(x, y, image::Luma([0]));
|
||||
ws.2.put_pixel(x, y, image::Luma([0]));
|
||||
ws.3.put_pixel(x, y, image::Rgb([rgb.r, rgb.g, rgb.b]));
|
||||
ws.3.put_pixel(x / N, y / N, image::Rgb([rgb.r, rgb.g, rgb.b]));
|
||||
}
|
||||
|
||||
fn put_sprite(
|
||||
@ -389,7 +388,6 @@ impl VoxelImageEncoding for QuadPngEncoding {
|
||||
ws.0.put_pixel(x, y, image::Luma([kind as u8]));
|
||||
ws.1.put_pixel(x, y, image::Luma([sprite as u8]));
|
||||
ws.2.put_pixel(x, y, image::Luma([ori.unwrap_or(0)]));
|
||||
ws.3.put_pixel(x, y, image::Rgb([0; 3]));
|
||||
}
|
||||
|
||||
fn finish(ws: &Self::Workspace) -> Option<Self::Output> {
|
||||
@ -430,6 +428,48 @@ impl VoxelImageEncoding for QuadPngEncoding {
|
||||
}
|
||||
}
|
||||
|
||||
impl<const N: u32> VoxelImageDecoding for QuadPngEncoding<N> {
|
||||
fn start(data: &Self::Output) -> Option<Self::Workspace> {
|
||||
use image::codecs::png::PngDecoder;
|
||||
let (quad, indices) = data.decompress()?;
|
||||
let ranges: [_; 4] = [
|
||||
0..indices[0],
|
||||
indices[0]..indices[1],
|
||||
indices[1]..indices[2],
|
||||
indices[2]..quad.len(),
|
||||
];
|
||||
let a = image_from_bytes(PngDecoder::new(&quad[ranges[0].clone()]).ok()?)?;
|
||||
let b = image_from_bytes(PngDecoder::new(&quad[ranges[1].clone()]).ok()?)?;
|
||||
let c = image_from_bytes(PngDecoder::new(&quad[ranges[2].clone()]).ok()?)?;
|
||||
let d = image_from_bytes(PngDecoder::new(&quad[ranges[3].clone()]).ok()?)?;
|
||||
Some((a, b, c, d))
|
||||
}
|
||||
|
||||
fn get_block(ws: &Self::Workspace, x: u32, y: u32) -> Block {
|
||||
if let Some(kind) = BlockKind::from_u8(ws.0.get_pixel(x, y).0[0]) {
|
||||
if kind.is_filled() {
|
||||
let rgb = ws.3.get_pixel(x / N, y / N);
|
||||
Block::new(kind, Rgb {
|
||||
r: rgb[0],
|
||||
g: rgb[1],
|
||||
b: rgb[2],
|
||||
})
|
||||
} else {
|
||||
let mut block = Block::new(kind, Rgb { r: 0, g: 0, b: 0 });
|
||||
if let Some(spritekind) = SpriteKind::from_u8(ws.1.get_pixel(x, y).0[0]) {
|
||||
block = block.with_sprite(spritekind);
|
||||
}
|
||||
if let Some(oriblock) = block.with_ori(ws.2.get_pixel(x, y).0[0]) {
|
||||
block = oriblock;
|
||||
}
|
||||
block
|
||||
}
|
||||
} else {
|
||||
Block::empty()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn image_terrain_chonk<S: RectVolSize, M: Clone, P: PackingFormula, VIE: VoxelImageEncoding>(
|
||||
vie: VIE,
|
||||
packing: P,
|
||||
@ -480,7 +520,6 @@ pub fn image_terrain<
|
||||
lo: Vec3<u32>,
|
||||
hi: Vec3<u32>,
|
||||
) -> Option<VIE::Output> {
|
||||
tracing::info!("image_terrain: {:?} {:?}", lo, hi);
|
||||
let dims = Vec3::new(
|
||||
hi.x.wrapping_sub(lo.x),
|
||||
hi.y.wrapping_sub(lo.y),
|
||||
|
@ -9,7 +9,7 @@ pub use self::{
|
||||
client::{ClientGeneral, ClientMsg, ClientRegister, ClientType},
|
||||
compression::{
|
||||
CompressedData, GridLtrPacking, JpegEncoding, MixedEncoding, PackingFormula, PngEncoding,
|
||||
TallPacking, VoxelImageEncoding, WireChonk,
|
||||
QuadPngEncoding, TallPacking, VoxelImageEncoding, WireChonk,
|
||||
},
|
||||
ecs_packet::EcsCompPacket,
|
||||
server::{
|
||||
|
@ -1,6 +1,6 @@
|
||||
use super::{
|
||||
world_msg::EconomyInfo, ClientType, CompressedData, EcsCompPacket, MixedEncoding, PingMsg,
|
||||
TallPacking, WireChonk,
|
||||
QuadPngEncoding, TallPacking, WireChonk,
|
||||
};
|
||||
use crate::sync;
|
||||
use common::{
|
||||
@ -70,6 +70,7 @@ pub type ServerRegisterAnswer = Result<(), RegisterError>;
|
||||
pub enum SerializedTerrainChunk {
|
||||
DeflatedChonk(CompressedData<TerrainChunk>),
|
||||
PngPngPngJpeg(WireChonk<MixedEncoding, TallPacking, TerrainChunkMeta, TerrainChunkSize>),
|
||||
QuadPng(WireChonk<QuadPngEncoding<2>, TallPacking, TerrainChunkMeta, TerrainChunkSize>),
|
||||
}
|
||||
|
||||
impl SerializedTerrainChunk {
|
||||
@ -77,7 +78,7 @@ impl SerializedTerrainChunk {
|
||||
Self::DeflatedChonk(CompressedData::compress(chunk, 5))
|
||||
}
|
||||
|
||||
pub fn image(chunk: &TerrainChunk) -> Self {
|
||||
pub fn jpeg(chunk: &TerrainChunk) -> Self {
|
||||
if let Some(wc) = WireChonk::from_chonk(MixedEncoding, TallPacking { flip_y: true }, chunk)
|
||||
{
|
||||
Self::PngPngPngJpeg(wc)
|
||||
@ -87,10 +88,22 @@ impl SerializedTerrainChunk {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn image(chunk: &TerrainChunk) -> Self {
|
||||
if let Some(wc) =
|
||||
WireChonk::from_chonk(QuadPngEncoding(), TallPacking { flip_y: true }, chunk)
|
||||
{
|
||||
Self::QuadPng(wc)
|
||||
} else {
|
||||
warn!("Image encoding failure occurred, falling back to deflate");
|
||||
Self::deflate(chunk)
|
||||
}
|
||||
}
|
||||
|
||||
pub fn to_chunk(&self) -> Option<TerrainChunk> {
|
||||
match self {
|
||||
Self::DeflatedChonk(chonk) => chonk.decompress(),
|
||||
Self::PngPngPngJpeg(wc) => wc.to_chonk(),
|
||||
Self::QuadPng(wc) => wc.to_chonk(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,16 +1,15 @@
|
||||
use common::{
|
||||
spiral::Spiral2d,
|
||||
terrain::{chonk::Chonk, Block, BlockKind, SpriteKind},
|
||||
vol::{BaseVol, IntoVolIterator, ReadVol, RectVolSize, SizedVol, WriteVol},
|
||||
vol::{IntoVolIterator, RectVolSize, SizedVol, WriteVol},
|
||||
volumes::{
|
||||
dyna::{Access, ColumnAccess, Dyna},
|
||||
vol_grid_2d::VolGrid2d,
|
||||
},
|
||||
};
|
||||
use common_net::msg::compression::{
|
||||
image_terrain, image_terrain_chonk, image_terrain_volgrid, CompressedData, GridLtrPacking,
|
||||
JpegEncoding, MixedEncoding, PackingFormula, PngEncoding, QuadPngEncoding, TallPacking,
|
||||
VoxelImageEncoding,
|
||||
image_terrain_chonk, image_terrain_volgrid, CompressedData, GridLtrPacking, JpegEncoding,
|
||||
MixedEncoding, PngEncoding, QuadPngEncoding, TallPacking, VoxelImageEncoding,
|
||||
};
|
||||
use hashbrown::HashMap;
|
||||
use image::ImageBuffer;
|
||||
@ -329,8 +328,8 @@ fn main() {
|
||||
));
|
||||
|
||||
for (sitename, sitepos) in sites.iter() {
|
||||
let mut totals = [0.0; 13];
|
||||
let mut total_timings = [0.0; 10];
|
||||
let mut totals = [0.0; 15];
|
||||
let mut total_timings = [0.0; 12];
|
||||
let mut count = 0;
|
||||
let mut volgrid = VolGrid2d::new().unwrap();
|
||||
for (i, spiralpos) in Spiral2d::new()
|
||||
@ -420,11 +419,32 @@ fn main() {
|
||||
.unwrap();
|
||||
let mixeddense_post = Instant::now();
|
||||
|
||||
let quadpng_pre = Instant::now();
|
||||
let quadpng =
|
||||
image_terrain_chonk(QuadPngEncoding, TallPacking { flip_y: true }, &chunk)
|
||||
.unwrap();
|
||||
let quadpng_post = Instant::now();
|
||||
let quadpngfull_pre = Instant::now();
|
||||
let quadpngfull = image_terrain_chonk(
|
||||
QuadPngEncoding::<1>(),
|
||||
TallPacking { flip_y: true },
|
||||
&chunk,
|
||||
)
|
||||
.unwrap();
|
||||
let quadpngfull_post = Instant::now();
|
||||
|
||||
let quadpnghalf_pre = Instant::now();
|
||||
let quadpnghalf = image_terrain_chonk(
|
||||
QuadPngEncoding::<2>(),
|
||||
TallPacking { flip_y: true },
|
||||
&chunk,
|
||||
)
|
||||
.unwrap();
|
||||
let quadpnghalf_post = Instant::now();
|
||||
|
||||
let quadpngquart_pre = Instant::now();
|
||||
let quadpngquart = image_terrain_chonk(
|
||||
QuadPngEncoding::<4>(),
|
||||
TallPacking { flip_y: true },
|
||||
&chunk,
|
||||
)
|
||||
.unwrap();
|
||||
let quadpngquart_post = Instant::now();
|
||||
|
||||
let pngchonk_pre = Instant::now();
|
||||
let pngchonk = image_terrain_chonk(PngEncoding, GridLtrPacking, &chunk).unwrap();
|
||||
@ -443,7 +463,9 @@ fn main() {
|
||||
mixedchonk.0.len() as f32 / n as f32,
|
||||
mixeddeflate.data.len() as f32 / n as f32,
|
||||
mixeddense.0.len() as f32 / n as f32,
|
||||
quadpng.data.len() as f32 / n as f32,
|
||||
quadpngfull.data.len() as f32 / n as f32,
|
||||
quadpnghalf.data.len() as f32 / n as f32,
|
||||
quadpngquart.data.len() as f32 / n as f32,
|
||||
pngchonk.len() as f32 / n as f32,
|
||||
];
|
||||
let best_idx = sizes
|
||||
@ -466,7 +488,9 @@ fn main() {
|
||||
(mixedchonk_post - mixedchonk_pre).subsec_nanos(),
|
||||
(mixeddeflate_post - mixedchonk_pre).subsec_nanos(),
|
||||
(mixeddense_post - mixeddense_pre).subsec_nanos(),
|
||||
(quadpng_post - quadpng_pre).subsec_nanos(),
|
||||
(quadpngfull_post - quadpngfull_pre).subsec_nanos(),
|
||||
(quadpnghalf_post - quadpnghalf_pre).subsec_nanos(),
|
||||
(quadpngquart_post - quadpngquart_pre).subsec_nanos(),
|
||||
(pngchonk_post - pngchonk_pre).subsec_nanos(),
|
||||
];
|
||||
trace!(
|
||||
@ -542,8 +566,10 @@ fn main() {
|
||||
println!("Average mixedchonk: {}", totals[8] / count as f32);
|
||||
println!("Average mixeddeflate: {}", totals[9] / count as f32);
|
||||
println!("Average mixeddense: {}", totals[10] / count as f32);
|
||||
println!("Average quadpng: {}", totals[11] / count as f32);
|
||||
println!("Average pngchonk: {}", totals[12] / count as f32);
|
||||
println!("Average quadpngfull: {}", totals[11] / count as f32);
|
||||
println!("Average quadpnghalf: {}", totals[12] / count as f32);
|
||||
println!("Average quadpngquart: {}", totals[13] / count as f32);
|
||||
println!("Average pngchonk: {}", totals[14] / count as f32);
|
||||
println!("");
|
||||
println!(
|
||||
"Average lz4_chonk nanos : {:02}",
|
||||
@ -578,13 +604,21 @@ fn main() {
|
||||
total_timings[7] / count as f32
|
||||
);
|
||||
println!(
|
||||
"Average quadpng nanos: {:02}",
|
||||
"Average quadpngfull nanos: {:02}",
|
||||
total_timings[8] / count as f32
|
||||
);
|
||||
println!(
|
||||
"Average pngchonk nanos: {:02}",
|
||||
"Average quadpnghalf nanos: {:02}",
|
||||
total_timings[9] / count as f32
|
||||
);
|
||||
println!(
|
||||
"Average quadpngquart nanos: {:02}",
|
||||
total_timings[10] / count as f32
|
||||
);
|
||||
println!(
|
||||
"Average pngchonk nanos: {:02}",
|
||||
total_timings[11] / count as f32
|
||||
);
|
||||
println!("-----");
|
||||
}
|
||||
if i % 256 == 0 {
|
||||
|
Loading…
Reference in New Issue
Block a user