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[1]..indices[2],
|
||||||
indices[2]..quad.len(),
|
indices[2]..quad.len(),
|
||||||
];
|
];
|
||||||
tracing::info!("{:?} {:?}", ranges, indices);
|
|
||||||
let a = image_from_bytes(PngDecoder::new(&quad[ranges[0].clone()]).ok()?)?;
|
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 b = image_from_bytes(PngDecoder::new(&quad[ranges[1].clone()]).ok()?)?;
|
||||||
let c = image_from_bytes(PngDecoder::new(&quad[ranges[2].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)]
|
#[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])>;
|
type Output = CompressedData<(Vec<u8>, [usize; 3])>;
|
||||||
#[allow(clippy::type_complexity)]
|
#[allow(clippy::type_complexity)]
|
||||||
type Workspace = (
|
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, 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.0.put_pixel(x, y, image::Luma([kind as u8]));
|
||||||
ws.1.put_pixel(x, y, image::Luma([0]));
|
ws.1.put_pixel(x, y, image::Luma([0]));
|
||||||
ws.2.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(
|
fn put_sprite(
|
||||||
@ -389,7 +388,6 @@ impl VoxelImageEncoding for QuadPngEncoding {
|
|||||||
ws.0.put_pixel(x, y, image::Luma([kind as u8]));
|
ws.0.put_pixel(x, y, image::Luma([kind as u8]));
|
||||||
ws.1.put_pixel(x, y, image::Luma([sprite 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.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> {
|
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>(
|
pub fn image_terrain_chonk<S: RectVolSize, M: Clone, P: PackingFormula, VIE: VoxelImageEncoding>(
|
||||||
vie: VIE,
|
vie: VIE,
|
||||||
packing: P,
|
packing: P,
|
||||||
@ -480,7 +520,6 @@ pub fn image_terrain<
|
|||||||
lo: Vec3<u32>,
|
lo: Vec3<u32>,
|
||||||
hi: Vec3<u32>,
|
hi: Vec3<u32>,
|
||||||
) -> Option<VIE::Output> {
|
) -> Option<VIE::Output> {
|
||||||
tracing::info!("image_terrain: {:?} {:?}", lo, hi);
|
|
||||||
let dims = Vec3::new(
|
let dims = Vec3::new(
|
||||||
hi.x.wrapping_sub(lo.x),
|
hi.x.wrapping_sub(lo.x),
|
||||||
hi.y.wrapping_sub(lo.y),
|
hi.y.wrapping_sub(lo.y),
|
||||||
|
@ -9,7 +9,7 @@ pub use self::{
|
|||||||
client::{ClientGeneral, ClientMsg, ClientRegister, ClientType},
|
client::{ClientGeneral, ClientMsg, ClientRegister, ClientType},
|
||||||
compression::{
|
compression::{
|
||||||
CompressedData, GridLtrPacking, JpegEncoding, MixedEncoding, PackingFormula, PngEncoding,
|
CompressedData, GridLtrPacking, JpegEncoding, MixedEncoding, PackingFormula, PngEncoding,
|
||||||
TallPacking, VoxelImageEncoding, WireChonk,
|
QuadPngEncoding, TallPacking, VoxelImageEncoding, WireChonk,
|
||||||
},
|
},
|
||||||
ecs_packet::EcsCompPacket,
|
ecs_packet::EcsCompPacket,
|
||||||
server::{
|
server::{
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
use super::{
|
use super::{
|
||||||
world_msg::EconomyInfo, ClientType, CompressedData, EcsCompPacket, MixedEncoding, PingMsg,
|
world_msg::EconomyInfo, ClientType, CompressedData, EcsCompPacket, MixedEncoding, PingMsg,
|
||||||
TallPacking, WireChonk,
|
QuadPngEncoding, TallPacking, WireChonk,
|
||||||
};
|
};
|
||||||
use crate::sync;
|
use crate::sync;
|
||||||
use common::{
|
use common::{
|
||||||
@ -70,6 +70,7 @@ pub type ServerRegisterAnswer = Result<(), RegisterError>;
|
|||||||
pub enum SerializedTerrainChunk {
|
pub enum SerializedTerrainChunk {
|
||||||
DeflatedChonk(CompressedData<TerrainChunk>),
|
DeflatedChonk(CompressedData<TerrainChunk>),
|
||||||
PngPngPngJpeg(WireChonk<MixedEncoding, TallPacking, TerrainChunkMeta, TerrainChunkSize>),
|
PngPngPngJpeg(WireChonk<MixedEncoding, TallPacking, TerrainChunkMeta, TerrainChunkSize>),
|
||||||
|
QuadPng(WireChonk<QuadPngEncoding<2>, TallPacking, TerrainChunkMeta, TerrainChunkSize>),
|
||||||
}
|
}
|
||||||
|
|
||||||
impl SerializedTerrainChunk {
|
impl SerializedTerrainChunk {
|
||||||
@ -77,7 +78,7 @@ impl SerializedTerrainChunk {
|
|||||||
Self::DeflatedChonk(CompressedData::compress(chunk, 5))
|
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)
|
if let Some(wc) = WireChonk::from_chonk(MixedEncoding, TallPacking { flip_y: true }, chunk)
|
||||||
{
|
{
|
||||||
Self::PngPngPngJpeg(wc)
|
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> {
|
pub fn to_chunk(&self) -> Option<TerrainChunk> {
|
||||||
match self {
|
match self {
|
||||||
Self::DeflatedChonk(chonk) => chonk.decompress(),
|
Self::DeflatedChonk(chonk) => chonk.decompress(),
|
||||||
Self::PngPngPngJpeg(wc) => wc.to_chonk(),
|
Self::PngPngPngJpeg(wc) => wc.to_chonk(),
|
||||||
|
Self::QuadPng(wc) => wc.to_chonk(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,16 +1,15 @@
|
|||||||
use common::{
|
use common::{
|
||||||
spiral::Spiral2d,
|
spiral::Spiral2d,
|
||||||
terrain::{chonk::Chonk, Block, BlockKind, SpriteKind},
|
terrain::{chonk::Chonk, Block, BlockKind, SpriteKind},
|
||||||
vol::{BaseVol, IntoVolIterator, ReadVol, RectVolSize, SizedVol, WriteVol},
|
vol::{IntoVolIterator, RectVolSize, SizedVol, WriteVol},
|
||||||
volumes::{
|
volumes::{
|
||||||
dyna::{Access, ColumnAccess, Dyna},
|
dyna::{Access, ColumnAccess, Dyna},
|
||||||
vol_grid_2d::VolGrid2d,
|
vol_grid_2d::VolGrid2d,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
use common_net::msg::compression::{
|
use common_net::msg::compression::{
|
||||||
image_terrain, image_terrain_chonk, image_terrain_volgrid, CompressedData, GridLtrPacking,
|
image_terrain_chonk, image_terrain_volgrid, CompressedData, GridLtrPacking, JpegEncoding,
|
||||||
JpegEncoding, MixedEncoding, PackingFormula, PngEncoding, QuadPngEncoding, TallPacking,
|
MixedEncoding, PngEncoding, QuadPngEncoding, TallPacking, VoxelImageEncoding,
|
||||||
VoxelImageEncoding,
|
|
||||||
};
|
};
|
||||||
use hashbrown::HashMap;
|
use hashbrown::HashMap;
|
||||||
use image::ImageBuffer;
|
use image::ImageBuffer;
|
||||||
@ -329,8 +328,8 @@ fn main() {
|
|||||||
));
|
));
|
||||||
|
|
||||||
for (sitename, sitepos) in sites.iter() {
|
for (sitename, sitepos) in sites.iter() {
|
||||||
let mut totals = [0.0; 13];
|
let mut totals = [0.0; 15];
|
||||||
let mut total_timings = [0.0; 10];
|
let mut total_timings = [0.0; 12];
|
||||||
let mut count = 0;
|
let mut count = 0;
|
||||||
let mut volgrid = VolGrid2d::new().unwrap();
|
let mut volgrid = VolGrid2d::new().unwrap();
|
||||||
for (i, spiralpos) in Spiral2d::new()
|
for (i, spiralpos) in Spiral2d::new()
|
||||||
@ -420,11 +419,32 @@ fn main() {
|
|||||||
.unwrap();
|
.unwrap();
|
||||||
let mixeddense_post = Instant::now();
|
let mixeddense_post = Instant::now();
|
||||||
|
|
||||||
let quadpng_pre = Instant::now();
|
let quadpngfull_pre = Instant::now();
|
||||||
let quadpng =
|
let quadpngfull = image_terrain_chonk(
|
||||||
image_terrain_chonk(QuadPngEncoding, TallPacking { flip_y: true }, &chunk)
|
QuadPngEncoding::<1>(),
|
||||||
.unwrap();
|
TallPacking { flip_y: true },
|
||||||
let quadpng_post = Instant::now();
|
&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_pre = Instant::now();
|
||||||
let pngchonk = image_terrain_chonk(PngEncoding, GridLtrPacking, &chunk).unwrap();
|
let pngchonk = image_terrain_chonk(PngEncoding, GridLtrPacking, &chunk).unwrap();
|
||||||
@ -443,7 +463,9 @@ fn main() {
|
|||||||
mixedchonk.0.len() as f32 / n as f32,
|
mixedchonk.0.len() as f32 / n as f32,
|
||||||
mixeddeflate.data.len() as f32 / n as f32,
|
mixeddeflate.data.len() as f32 / n as f32,
|
||||||
mixeddense.0.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,
|
pngchonk.len() as f32 / n as f32,
|
||||||
];
|
];
|
||||||
let best_idx = sizes
|
let best_idx = sizes
|
||||||
@ -466,7 +488,9 @@ fn main() {
|
|||||||
(mixedchonk_post - mixedchonk_pre).subsec_nanos(),
|
(mixedchonk_post - mixedchonk_pre).subsec_nanos(),
|
||||||
(mixeddeflate_post - mixedchonk_pre).subsec_nanos(),
|
(mixeddeflate_post - mixedchonk_pre).subsec_nanos(),
|
||||||
(mixeddense_post - mixeddense_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(),
|
(pngchonk_post - pngchonk_pre).subsec_nanos(),
|
||||||
];
|
];
|
||||||
trace!(
|
trace!(
|
||||||
@ -542,8 +566,10 @@ fn main() {
|
|||||||
println!("Average mixedchonk: {}", totals[8] / count as f32);
|
println!("Average mixedchonk: {}", totals[8] / count as f32);
|
||||||
println!("Average mixeddeflate: {}", totals[9] / count as f32);
|
println!("Average mixeddeflate: {}", totals[9] / count as f32);
|
||||||
println!("Average mixeddense: {}", totals[10] / count as f32);
|
println!("Average mixeddense: {}", totals[10] / count as f32);
|
||||||
println!("Average quadpng: {}", totals[11] / count as f32);
|
println!("Average quadpngfull: {}", totals[11] / count as f32);
|
||||||
println!("Average pngchonk: {}", totals[12] / 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!("");
|
||||||
println!(
|
println!(
|
||||||
"Average lz4_chonk nanos : {:02}",
|
"Average lz4_chonk nanos : {:02}",
|
||||||
@ -578,13 +604,21 @@ fn main() {
|
|||||||
total_timings[7] / count as f32
|
total_timings[7] / count as f32
|
||||||
);
|
);
|
||||||
println!(
|
println!(
|
||||||
"Average quadpng nanos: {:02}",
|
"Average quadpngfull nanos: {:02}",
|
||||||
total_timings[8] / count as f32
|
total_timings[8] / count as f32
|
||||||
);
|
);
|
||||||
println!(
|
println!(
|
||||||
"Average pngchonk nanos: {:02}",
|
"Average quadpnghalf nanos: {:02}",
|
||||||
total_timings[9] / count as f32
|
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!("-----");
|
println!("-----");
|
||||||
}
|
}
|
||||||
if i % 256 == 0 {
|
if i % 256 == 0 {
|
||||||
|
Loading…
Reference in New Issue
Block a user