Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Merged by Bors] - Fix KTX2 R8_SRGB, R8_UNORM, R8G8_SRGB, R8G8_UNORM, R8G8B8_SRGB, R8G8B8_UNORM support #4594

Closed
wants to merge 5 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
12 changes: 12 additions & 0 deletions crates/bevy_render/src/color/colorspace.rs
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,18 @@ impl SrgbColorSpace for f32 {
}
}

impl SrgbColorSpace for u8 {
#[inline]
fn linear_to_nonlinear_srgb(self) -> Self {
((self as f32 / u8::MAX as f32).linear_to_nonlinear_srgb() * u8::MAX as f32) as u8
}

#[inline]
fn nonlinear_to_linear_srgb(self) -> Self {
((self as f32 / u8::MAX as f32).nonlinear_to_linear_srgb() * u8::MAX as f32) as u8
}
}

pub struct HslRepresentation;
impl HslRepresentation {
/// converts a color in HLS space to sRGB space
Expand Down
1 change: 0 additions & 1 deletion crates/bevy_render/src/color/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@ mod colorspace;

pub use colorspace::*;

use crate::color::{HslRepresentation, SrgbColorSpace};
use bevy_math::{Vec3, Vec4};
use bevy_reflect::{FromReflect, Reflect, ReflectDeserialize, ReflectSerialize};
use serde::{Deserialize, Serialize};
Expand Down
6 changes: 5 additions & 1 deletion crates/bevy_render/src/texture/image.rs
Original file line number Diff line number Diff line change
Expand Up @@ -406,9 +406,13 @@ pub enum DataFormat {
#[derive(Clone, Copy, Debug)]
pub enum TranscodeFormat {
Etc1s,
Uastc(DataFormat),
// Has to be transcoded to R8Unorm for use with `wgpu`
R8UnormSrgb,
// Has to be transcoded to R8G8Unorm for use with `wgpu`
Rg8UnormSrgb,
// Has to be transcoded to Rgba8 for use with `wgpu`
Rgb8,
Uastc(DataFormat),
}

/// An error that occurs when loading a texture
Expand Down
56 changes: 50 additions & 6 deletions crates/bevy_render/src/texture/ktx2.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
#[cfg(any(feature = "flate2", feature = "ruzstd"))]
use std::io::Read;

use crate::color::SrgbColorSpace;
#[cfg(feature = "basis-universal")]
use basis_universal::{
DecodeFlags, LowLevelUastcTranscoder, SliceParametersUastc, TranscoderBlockFormat,
Expand Down Expand Up @@ -86,6 +87,44 @@ pub fn ktx2_buffer_to_image(
TextureError::FormatRequiresTranscodingError(transcode_format) => {
let mut transcoded = vec![Vec::default(); levels.len()];
let texture_format = match transcode_format {
TranscodeFormat::R8UnormSrgb => {
let (mut original_width, mut original_height) = (width, height);

for level_data in &levels {
transcoded.push(
level_data
.iter()
.copied()
.map(|v| v.nonlinear_to_linear_srgb())
.collect::<Vec<u8>>(),
);

// Next mip dimensions are half the current, minimum 1x1
original_width = (original_width / 2).max(1);
original_height = (original_height / 2).max(1);
}

TextureFormat::R8Unorm
}
TranscodeFormat::Rg8UnormSrgb => {
let (mut original_width, mut original_height) = (width, height);

for level_data in &levels {
transcoded.push(
level_data
.iter()
.copied()
.map(|v| v.nonlinear_to_linear_srgb())
.collect::<Vec<u8>>(),
);

// Next mip dimensions are half the current, minimum 1x1
original_width = (original_width / 2).max(1);
original_height = (original_height / 2).max(1);
}

TextureFormat::Rg8Unorm
}
TranscodeFormat::Rgb8 => {
let mut rgba = vec![255u8; width as usize * height as usize * 4];
for (level, level_data) in levels.iter().enumerate() {
Expand Down Expand Up @@ -1163,9 +1202,9 @@ pub fn ktx2_format_to_texture_format(
Ok(match ktx2_format {
ktx2::Format::R8_UNORM | ktx2::Format::R8_SRGB => {
if is_srgb {
return Err(TextureError::UnsupportedTextureFormat(format!(
"{ktx2_format:?}"
)));
return Err(TextureError::FormatRequiresTranscodingError(
TranscodeFormat::R8UnormSrgb,
));
}
TextureFormat::R8Unorm
}
Expand All @@ -1174,15 +1213,20 @@ pub fn ktx2_format_to_texture_format(
ktx2::Format::R8_SINT => TextureFormat::R8Sint,
ktx2::Format::R8G8_UNORM | ktx2::Format::R8G8_SRGB => {
if is_srgb {
return Err(TextureError::UnsupportedTextureFormat(format!(
"{ktx2_format:?}"
)));
return Err(TextureError::FormatRequiresTranscodingError(
TranscodeFormat::Rg8UnormSrgb,
));
}
TextureFormat::Rg8Unorm
}
ktx2::Format::R8G8_SNORM => TextureFormat::Rg8Snorm,
ktx2::Format::R8G8_UINT => TextureFormat::Rg8Uint,
ktx2::Format::R8G8_SINT => TextureFormat::Rg8Sint,
ktx2::Format::R8G8B8_UNORM | ktx2::Format::R8G8B8_SRGB => {
return Err(TextureError::FormatRequiresTranscodingError(
TranscodeFormat::Rgb8,
));
}
ktx2::Format::R8G8B8A8_UNORM | ktx2::Format::R8G8B8A8_SRGB => {
if is_srgb {
TextureFormat::Rgba8UnormSrgb
Expand Down