first commit
This commit is contained in:
commit
caa0e43c9c
6 changed files with 420 additions and 0 deletions
3
.gitignore
vendored
Normal file
3
.gitignore
vendored
Normal file
|
|
@ -0,0 +1,3 @@
|
|||
/target
|
||||
/output
|
||||
kloofendal.hdr
|
||||
260
Cargo.lock
generated
Normal file
260
Cargo.lock
generated
Normal file
|
|
@ -0,0 +1,260 @@
|
|||
# This file is automatically @generated by Cargo.
|
||||
# It is not intended for manual editing.
|
||||
version = 3
|
||||
|
||||
[[package]]
|
||||
name = "anstream"
|
||||
version = "0.6.14"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "418c75fa768af9c03be99d17643f93f79bbba589895012a80e3452a19ddda15b"
|
||||
dependencies = [
|
||||
"anstyle",
|
||||
"anstyle-parse",
|
||||
"anstyle-query",
|
||||
"anstyle-wincon",
|
||||
"colorchoice",
|
||||
"is_terminal_polyfill",
|
||||
"utf8parse",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "anstyle"
|
||||
version = "1.0.7"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "038dfcf04a5feb68e9c60b21c9625a54c2c0616e79b72b0fd87075a056ae1d1b"
|
||||
|
||||
[[package]]
|
||||
name = "anstyle-parse"
|
||||
version = "0.2.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c03a11a9034d92058ceb6ee011ce58af4a9bf61491aa7e1e59ecd24bd40d22d4"
|
||||
dependencies = [
|
||||
"utf8parse",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "anstyle-query"
|
||||
version = "1.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ad186efb764318d35165f1758e7dcef3b10628e26d41a44bc5550652e6804391"
|
||||
dependencies = [
|
||||
"windows-sys",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "anstyle-wincon"
|
||||
version = "3.0.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "61a38449feb7068f52bb06c12759005cf459ee52bb4adc1d5a7c4322d716fb19"
|
||||
dependencies = [
|
||||
"anstyle",
|
||||
"windows-sys",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "clap"
|
||||
version = "4.5.7"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5db83dced34638ad474f39f250d7fea9598bdd239eaced1bdf45d597da0f433f"
|
||||
dependencies = [
|
||||
"clap_builder",
|
||||
"clap_derive",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "clap_builder"
|
||||
version = "4.5.7"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f7e204572485eb3fbf28f871612191521df159bc3e15a9f5064c66dba3a8c05f"
|
||||
dependencies = [
|
||||
"anstream",
|
||||
"anstyle",
|
||||
"clap_lex",
|
||||
"strsim",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "clap_derive"
|
||||
version = "4.5.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c780290ccf4fb26629baa7a1081e68ced113f1d3ec302fa5948f1c381ebf06c6"
|
||||
dependencies = [
|
||||
"heck",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "clap_lex"
|
||||
version = "0.7.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "4b82cf0babdbd58558212896d1a4272303a57bdb245c2bf1147185fb45640e70"
|
||||
|
||||
[[package]]
|
||||
name = "colorchoice"
|
||||
version = "1.0.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0b6a852b24ab71dffc585bcb46eaf7959d175cb865a7152e35b348d1b2960422"
|
||||
|
||||
[[package]]
|
||||
name = "glam"
|
||||
version = "0.28.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "779ae4bf7e8421cf91c0b3b64e7e8b40b862fba4d393f59150042de7c4965a94"
|
||||
|
||||
[[package]]
|
||||
name = "heck"
|
||||
version = "0.5.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea"
|
||||
|
||||
[[package]]
|
||||
name = "is_terminal_polyfill"
|
||||
version = "1.70.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f8478577c03552c21db0e2724ffb8986a5ce7af88107e6be5d2ee6e158c12800"
|
||||
|
||||
[[package]]
|
||||
name = "proc-macro2"
|
||||
version = "1.0.86"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5e719e8df665df0d1c8fbfd238015744736151d4445ec0836b8e628aae103b77"
|
||||
dependencies = [
|
||||
"unicode-ident",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "quote"
|
||||
version = "1.0.36"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0fa76aaf39101c457836aec0ce2316dbdc3ab723cdda1c6bd4e6ad4208acaca7"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "remap_hdri"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"clap",
|
||||
"glam",
|
||||
"zune-hdr",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "strsim"
|
||||
version = "0.11.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7da8b5736845d9f2fcb837ea5d9e2628564b3b043a70948a3f0b778838c5fb4f"
|
||||
|
||||
[[package]]
|
||||
name = "syn"
|
||||
version = "2.0.68"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "901fa70d88b9d6c98022e23b4136f9f3e54e4662c3bc1bd1d84a42a9a0f0c1e9"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"unicode-ident",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "unicode-ident"
|
||||
version = "1.0.12"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b"
|
||||
|
||||
[[package]]
|
||||
name = "utf8parse"
|
||||
version = "0.2.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "06abde3611657adf66d383f00b093d7faecc7fa57071cce2578660c9f1010821"
|
||||
|
||||
[[package]]
|
||||
name = "windows-sys"
|
||||
version = "0.52.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d"
|
||||
dependencies = [
|
||||
"windows-targets",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "windows-targets"
|
||||
version = "0.52.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "6f0713a46559409d202e70e28227288446bf7841d3211583a4b53e3f6d96e7eb"
|
||||
dependencies = [
|
||||
"windows_aarch64_gnullvm",
|
||||
"windows_aarch64_msvc",
|
||||
"windows_i686_gnu",
|
||||
"windows_i686_gnullvm",
|
||||
"windows_i686_msvc",
|
||||
"windows_x86_64_gnu",
|
||||
"windows_x86_64_gnullvm",
|
||||
"windows_x86_64_msvc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "windows_aarch64_gnullvm"
|
||||
version = "0.52.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7088eed71e8b8dda258ecc8bac5fb1153c5cffaf2578fc8ff5d61e23578d3263"
|
||||
|
||||
[[package]]
|
||||
name = "windows_aarch64_msvc"
|
||||
version = "0.52.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9985fd1504e250c615ca5f281c3f7a6da76213ebd5ccc9561496568a2752afb6"
|
||||
|
||||
[[package]]
|
||||
name = "windows_i686_gnu"
|
||||
version = "0.52.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "88ba073cf16d5372720ec942a8ccbf61626074c6d4dd2e745299726ce8b89670"
|
||||
|
||||
[[package]]
|
||||
name = "windows_i686_gnullvm"
|
||||
version = "0.52.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "87f4261229030a858f36b459e748ae97545d6f1ec60e5e0d6a3d32e0dc232ee9"
|
||||
|
||||
[[package]]
|
||||
name = "windows_i686_msvc"
|
||||
version = "0.52.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "db3c2bf3d13d5b658be73463284eaf12830ac9a26a90c717b7f771dfe97487bf"
|
||||
|
||||
[[package]]
|
||||
name = "windows_x86_64_gnu"
|
||||
version = "0.52.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "4e4246f76bdeff09eb48875a0fd3e2af6aada79d409d33011886d3e1581517d9"
|
||||
|
||||
[[package]]
|
||||
name = "windows_x86_64_gnullvm"
|
||||
version = "0.52.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "852298e482cd67c356ddd9570386e2862b5673c85bd5f88df9ab6802b334c596"
|
||||
|
||||
[[package]]
|
||||
name = "windows_x86_64_msvc"
|
||||
version = "0.52.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "bec47e5bfd1bff0eeaf6d8b485cc1074891a197ab4225d504cb7a1ab88b02bf0"
|
||||
|
||||
[[package]]
|
||||
name = "zune-core"
|
||||
version = "0.4.12"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3f423a2c17029964870cfaabb1f13dfab7d092a62a29a89264f4d36990ca414a"
|
||||
|
||||
[[package]]
|
||||
name = "zune-hdr"
|
||||
version = "0.4.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "51ff474631f80b14afc6dbc6bab78702ed2de7cd6af85f7a4ab21d3b08686426"
|
||||
dependencies = [
|
||||
"zune-core",
|
||||
]
|
||||
9
Cargo.toml
Normal file
9
Cargo.toml
Normal file
|
|
@ -0,0 +1,9 @@
|
|||
[package]
|
||||
name = "remap_hdri"
|
||||
version = "0.1.0"
|
||||
edition = "2021"
|
||||
|
||||
[dependencies]
|
||||
clap = { version = "4.5.7", features = ["derive"] }
|
||||
glam = "0.28.0"
|
||||
zune-hdr = "0.4"
|
||||
9
README.md
Normal file
9
README.md
Normal file
|
|
@ -0,0 +1,9 @@
|
|||
# Hacky HDRi Rotator Tool
|
||||
|
||||
To get textures to use in bevy:
|
||||
|
||||
```
|
||||
remap_hdri <> kloofendal.hdr -o output/kloofendal_rotated.hdr
|
||||
```
|
||||
|
||||
Example usage to get textures in bevy in `run.sh`
|
||||
17
run.sh
Executable file
17
run.sh
Executable file
|
|
@ -0,0 +1,17 @@
|
|||
#!/bin/bash
|
||||
|
||||
rm -r output
|
||||
|
||||
mkdir -p output
|
||||
|
||||
name=$( basename "$1" .hdr )
|
||||
|
||||
cargo run --release -- -i "$1" -o output/"$name"_rotated.hdr
|
||||
|
||||
cd output
|
||||
|
||||
magick "$name"_rotated.hdr debug.png
|
||||
|
||||
ibl-sampler-cli -inputPath "$name"_rotated.hdr -outCubeMap "$name"_specular.ktx2 -distribution GGX -cubeMapResolution 512
|
||||
ibl-sampler-cli -inputPath "$name"_rotated.hdr -outCubeMap "$name"_diffuse.ktx2 -distribution Lambertian -cubeMapResolution 32
|
||||
bevy_mod_environment_map_tools --inputs "$name"_diffuse.ktx2,"$name"_specular.ktx2 --outputs "$name"_diffuse_rgb9e5_zstd.ktx2,"$name"_specular_rgb9e5_zstd.ktx2
|
||||
122
src/main.rs
Normal file
122
src/main.rs
Normal file
|
|
@ -0,0 +1,122 @@
|
|||
use std::{f64::consts::TAU, path::PathBuf};
|
||||
|
||||
use clap::Parser;
|
||||
use glam::{DQuat, DVec3, IVec2, Vec3};
|
||||
use zune_hdr::{
|
||||
zune_core::{bit_depth::BitDepth, options::EncoderOptions},
|
||||
HdrDecoder, HdrEncoder,
|
||||
};
|
||||
|
||||
#[derive(Debug, Parser)]
|
||||
pub struct Args {
|
||||
#[arg(long, short)]
|
||||
input: PathBuf,
|
||||
#[arg(long, short)]
|
||||
output: PathBuf,
|
||||
}
|
||||
|
||||
fn main() -> Result<(), Box<dyn std::error::Error>> {
|
||||
let args = Args::parse();
|
||||
let contents = std::fs::read(args.input)?;
|
||||
let mut data = HdrDecoder::new(contents);
|
||||
let pix: Vec<f32> = data.decode()?;
|
||||
|
||||
let (in_w, in_h) = data.get_dimensions().unwrap();
|
||||
const OUTW: usize = 1024;
|
||||
const OUTH: usize = 512;
|
||||
|
||||
let mut out: Vec<f32> = vec![0.0; OUTW * OUTH * 3];
|
||||
// Mask telling us which pixels have been filled
|
||||
let mut mask: Vec<bool> = vec![false; OUTW * OUTH];
|
||||
|
||||
// The rotation to apply
|
||||
let rotation = DQuat::from_axis_angle(DVec3::X, -TAU / 4.0);
|
||||
|
||||
// Copy texels from the original texture into the new one
|
||||
for y in 0..in_h {
|
||||
for x in 0..in_w {
|
||||
for i in 0..3 {
|
||||
let p = pix[y * in_w * 3 + x * 3 + i];
|
||||
let lat = (y as f64 / in_h as f64 - 0.5) * (TAU / 2.0);
|
||||
let lon = (x as f64 / in_w as f64 - 0.5) * TAU;
|
||||
let point = DQuat::from_axis_angle(DVec3::Z, lon)
|
||||
* DQuat::from_axis_angle(DVec3::Y, -lat)
|
||||
* DVec3::X;
|
||||
|
||||
let point = rotation * point;
|
||||
|
||||
let new_lat = point.z.asin();
|
||||
let new_lon = point.truncate().normalize().to_angle();
|
||||
|
||||
let new_r = ((new_lat / (TAU / 2.0) + 0.5) * (OUTH as f64)).floor() as usize;
|
||||
let new_c = ((new_lon / TAU + 0.5) * (OUTW as f64)).floor() as usize;
|
||||
out[(new_r * OUTW * 3 + new_c * 3 + i).min(OUTW * OUTH * 3 - 1)] = p;
|
||||
mask[(new_r * OUTW + new_c).min(OUTW * OUTH - 1)] = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Some texels of the output texture were never written to
|
||||
// fill them in by using flood fill
|
||||
let mut complete = false;
|
||||
while !complete {
|
||||
// slow, but we don't care :D
|
||||
let mut staging_out: Vec<f32> = out.clone();
|
||||
let mut staging_mask: Vec<bool> = mask.clone();
|
||||
|
||||
complete = true;
|
||||
for y in 0..OUTH {
|
||||
for x in 0..OUTW {
|
||||
let coord = IVec2::new(x as i32, y as i32);
|
||||
if !mask[y * OUTW + x] {
|
||||
// average out neighboring colors
|
||||
let (sum_color, sum) = [
|
||||
IVec2::new(-1, 0),
|
||||
IVec2::new(1, 0),
|
||||
IVec2::new(0, -1),
|
||||
IVec2::new(0, 1),
|
||||
]
|
||||
.into_iter()
|
||||
.fold((Vec3::ZERO, 0.0), |acc, offset| {
|
||||
let c = coord + offset;
|
||||
if c.clamp(IVec2::ZERO, IVec2::new(OUTW as i32 - 1, OUTH as i32 - 1)) == c {
|
||||
let col = &out[(c.y * OUTW as i32 * 3 + c.x * 3) as usize..][..3];
|
||||
if mask[(c.y * OUTW as i32 + c.x) as usize] {
|
||||
return (acc.0 + Vec3::new(col[0], col[1], col[2]), acc.1 + 1.0);
|
||||
}
|
||||
}
|
||||
acc
|
||||
});
|
||||
if sum == 0.0 {
|
||||
// no neighboring colors are filled in, skip it
|
||||
complete = false;
|
||||
continue;
|
||||
} else {
|
||||
// set the average as color
|
||||
let color = sum_color / sum;
|
||||
staging_out[y * OUTW * 3 + x * 3 + 0] = color.x;
|
||||
staging_out[y * OUTW * 3 + x * 3 + 1] = color.y;
|
||||
staging_out[y * OUTW * 3 + x * 3 + 2] = color.z;
|
||||
staging_mask[y * OUTW + x] = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
out = staging_out;
|
||||
mask = staging_mask;
|
||||
}
|
||||
|
||||
let encoder = HdrEncoder::new(
|
||||
&out,
|
||||
EncoderOptions::new(
|
||||
OUTW,
|
||||
OUTH,
|
||||
data.get_colorspace().unwrap(),
|
||||
BitDepth::Float32,
|
||||
),
|
||||
);
|
||||
std::fs::write(args.output, encoder.encode().unwrap()).unwrap();
|
||||
|
||||
Ok(())
|
||||
}
|
||||
Loading…
Reference in a new issue