Bilinear linear-space texture sample (no sRGB decode). Used for MR / normal / occlusion textures per glTF spec.
(&self, tex_idx: usize, uv: Vec2)
| 345 | /// Bilinear linear-space texture sample (no sRGB decode). Used |
| 346 | /// for MR / normal / occlusion textures per glTF spec. |
| 347 | fn sample_texture_linear(&self, tex_idx: usize, uv: Vec2) -> Option<(f32, f32, f32)> { |
| 348 | let tex = self.textures.get(tex_idx)?; |
| 349 | let (x0, y0, tx, ty) = tex_sample_coords(tex, uv); |
| 350 | let w = tex.width as i32; |
| 351 | let h = tex.height as i32; |
| 352 | let fetch = |x: i32, y: i32| -> (f32, f32, f32) { |
| 353 | let idx = ((y.rem_euclid(h) as usize) * tex.width as usize |
| 354 | + (x.rem_euclid(w) as usize)) |
| 355 | * 4; |
| 356 | let r = tex.pixels[idx] as f32 / 255.0; |
| 357 | let g = tex.pixels[idx + 1] as f32 / 255.0; |
| 358 | let b = tex.pixels[idx + 2] as f32 / 255.0; |
| 359 | (r, g, b) |
| 360 | }; |
| 361 | let c00 = fetch(x0, y0); |
| 362 | let c10 = fetch(x0 + 1, y0); |
| 363 | let c01 = fetch(x0, y0 + 1); |
| 364 | let c11 = fetch(x0 + 1, y0 + 1); |
| 365 | let r = lerp(lerp(c00.0, c10.0, tx), lerp(c01.0, c11.0, tx), ty); |
| 366 | let g = lerp(lerp(c00.1, c10.1, tx), lerp(c01.1, c11.1, tx), ty); |
| 367 | let b = lerp(lerp(c00.2, c10.2, tx), lerp(c01.2, c11.2, tx), ty); |
| 368 | Some((r, g, b)) |
| 369 | } |
| 370 | } |
| 371 | |
| 372 | fn lerp(a: f32, b: f32, t: f32) -> f32 { |
no test coverage detected