MCPcopy Create free account
hub / github.com/Bloom-Engine/engine / register_texture_kind

Method register_texture_kind

native/shared/src/renderer/mod.rs:11595–11766  ·  view source on GitHub ↗

Register a texture with optional normal-map preprocessing. For normal maps (is_normal_map=true), mip chain is built with vector-space averaging instead of scalar RGB averaging, and per-mip variance (1 - |vector_avg|²) is baked into the alpha channel. The shader reads alpha as a Toksvig-style σ² addition that accumulates normal-direction disagreement across the footprint the sampler ends up integr

(
        &mut self,
        width: u32,
        height: u32,
        data: &[u8],
        is_normal_map: bool,
    )

Source from the content-addressed store, hash-verified

11593 /// scalar LEADR/LEAN filter. Alpha is unused by glTF normal maps
11594 /// (they carry (x,y,z) in RGB) so we can safely repurpose it.
11595 pub fn register_texture_kind(
11596 &mut self,
11597 width: u32,
11598 height: u32,
11599 data: &[u8],
11600 is_normal_map: bool,
11601 ) -> u32 {
11602 let max_dim = if width > height { width } else { height };
11603 // On Android/Vulkan, multi-level mipmap upload can fail silently.
11604 // Use single mip for 2D textures; only generate mipmaps on desktop.
11605 #[cfg(target_os = "android")]
11606 let mip_count = 1u32;
11607 #[cfg(not(target_os = "android"))]
11608 let mip_count = (max_dim as f32).log2().floor() as u32 + 1;
11609
11610 // Generate mip chain data
11611 let mut mip_data = Vec::with_capacity(data.len() * 2); // overallocate
11612 if is_normal_map {
11613 // Level 0: normalize input RGB and clear alpha to 0 (no
11614 // variance at the finest level — each texel is assumed unit).
11615 mip_data.reserve(data.len());
11616 for i in 0..(width as usize * height as usize) {
11617 let r = data[i * 4];
11618 let g = data[i * 4 + 1];
11619 let b = data[i * 4 + 2];
11620 mip_data.push(r);
11621 mip_data.push(g);
11622 mip_data.push(b);
11623 mip_data.push(0);
11624 }
11625 } else {
11626 mip_data.extend_from_slice(data);
11627 }
11628 let mut mip_offsets = vec![0usize]; // byte offset of each mip level
11629 let mut mw = width;
11630 let mut mh = height;
11631 for _ in 1..mip_count {
11632 let prev_offset = *mip_offsets.last().unwrap();
11633 let pw = mw as usize; // previous width
11634 let ph = mh as usize; // previous height
11635 mw = if mw > 1 { mw / 2 } else { 1 };
11636 mh = if mh > 1 { mh / 2 } else { 1 };
11637 mip_offsets.push(mip_data.len());
11638 for y in 0..mh as usize {
11639 for x in 0..mw as usize {
11640 let sx = x * 2;
11641 let sy = y * 2;
11642 let sx1 = (sx + 1).min(pw - 1);
11643 let sy1 = (sy + 1).min(ph - 1);
11644 if is_normal_map {
11645 // Decode 4 children to signed [-1, 1] vectors
11646 let dec = |r: u8, g: u8, b: u8| -> [f32; 3] {
11647 [
11648 r as f32 * (2.0 / 255.0) - 1.0,
11649 g as f32 * (2.0 / 255.0) - 1.0,
11650 b as f32 * (2.0 / 255.0) - 1.0,
11651 ]
11652 };

Callers 2

load_gltf_with_texturesFunction · 0.80
register_textureMethod · 0.80

Calls 1

pushMethod · 0.45

Tested by

no test coverage detected