mirror of
https://github.com/godotengine/godot.git
synced 2025-10-19 07:53:26 +00:00
Merge pull request #106200 from BlueCube3310/image-16-u16
Image: Implement 16-bit unorm and uint formats
This commit is contained in:
commit
cd3a6c88fd
13 changed files with 914 additions and 63 deletions
|
@ -78,6 +78,14 @@ const char *Image::format_names[Image::FORMAT_MAX] = {
|
|||
"ASTC_4x4_HDR",
|
||||
"ASTC_8x8",
|
||||
"ASTC_8x8_HDR",
|
||||
"R16",
|
||||
"RG16",
|
||||
"RGB16",
|
||||
"RGBA16",
|
||||
"R16Int",
|
||||
"RG16Int",
|
||||
"RGB16Int",
|
||||
"RGBA16Int",
|
||||
};
|
||||
|
||||
// External VRAM compression function pointers.
|
||||
|
@ -201,6 +209,22 @@ int Image::get_format_pixel_size(Format p_format) {
|
|||
return 1;
|
||||
case FORMAT_ASTC_8x8_HDR:
|
||||
return 1;
|
||||
case FORMAT_R16:
|
||||
return 2;
|
||||
case FORMAT_RG16:
|
||||
return 4;
|
||||
case FORMAT_RGB16:
|
||||
return 6;
|
||||
case FORMAT_RGBA16:
|
||||
return 8;
|
||||
case FORMAT_R16I:
|
||||
return 2;
|
||||
case FORMAT_RG16I:
|
||||
return 4;
|
||||
case FORMAT_RGB16I:
|
||||
return 6;
|
||||
case FORMAT_RGBA16I:
|
||||
return 8;
|
||||
case FORMAT_MAX: {
|
||||
}
|
||||
}
|
||||
|
@ -759,6 +783,78 @@ void Image::convert(Format p_new_format) {
|
|||
case FORMAT_RGBAF | (FORMAT_RGBF << 8):
|
||||
_convert_fast<uint32_t, 4, 3, 0x00000000, 0x3F800000>(mip_width, mip_height, (const uint32_t *)rptr, (uint32_t *)wptr);
|
||||
break;
|
||||
case FORMAT_R16 | (FORMAT_RG16 << 8):
|
||||
_convert_fast<uint16_t, 1, 2, 0x0000, 0xFFFF>(mip_width, mip_height, (const uint16_t *)rptr, (uint16_t *)wptr);
|
||||
break;
|
||||
case FORMAT_R16 | (FORMAT_RGB16 << 8):
|
||||
_convert_fast<uint16_t, 1, 3, 0x0000, 0xFFFF>(mip_width, mip_height, (const uint16_t *)rptr, (uint16_t *)wptr);
|
||||
break;
|
||||
case FORMAT_R16 | (FORMAT_RGBA16 << 8):
|
||||
_convert_fast<uint16_t, 1, 4, 0x0000, 0xFFFF>(mip_width, mip_height, (const uint16_t *)rptr, (uint16_t *)wptr);
|
||||
break;
|
||||
case FORMAT_RG16 | (FORMAT_R16 << 8):
|
||||
_convert_fast<uint16_t, 2, 1, 0x0000, 0xFFFF>(mip_width, mip_height, (const uint16_t *)rptr, (uint16_t *)wptr);
|
||||
break;
|
||||
case FORMAT_RG16 | (FORMAT_RGB16 << 8):
|
||||
_convert_fast<uint16_t, 2, 3, 0x0000, 0xFFFF>(mip_width, mip_height, (const uint16_t *)rptr, (uint16_t *)wptr);
|
||||
break;
|
||||
case FORMAT_RG16 | (FORMAT_RGBA16 << 8):
|
||||
_convert_fast<uint16_t, 2, 4, 0x0000, 0xFFFF>(mip_width, mip_height, (const uint16_t *)rptr, (uint16_t *)wptr);
|
||||
break;
|
||||
case FORMAT_RGB16 | (FORMAT_R16 << 8):
|
||||
_convert_fast<uint16_t, 3, 1, 0x0000, 0xFFFF>(mip_width, mip_height, (const uint16_t *)rptr, (uint16_t *)wptr);
|
||||
break;
|
||||
case FORMAT_RGB16 | (FORMAT_RG16 << 8):
|
||||
_convert_fast<uint16_t, 3, 2, 0x0000, 0xFFFF>(mip_width, mip_height, (const uint16_t *)rptr, (uint16_t *)wptr);
|
||||
break;
|
||||
case FORMAT_RGB16 | (FORMAT_RGBA16 << 8):
|
||||
_convert_fast<uint16_t, 3, 4, 0x0000, 0xFFFF>(mip_width, mip_height, (const uint16_t *)rptr, (uint16_t *)wptr);
|
||||
break;
|
||||
case FORMAT_RGBA16 | (FORMAT_R16 << 8):
|
||||
_convert_fast<uint16_t, 4, 1, 0x0000, 0xFFFF>(mip_width, mip_height, (const uint16_t *)rptr, (uint16_t *)wptr);
|
||||
break;
|
||||
case FORMAT_RGBA16 | (FORMAT_RG16 << 8):
|
||||
_convert_fast<uint16_t, 4, 2, 0x0000, 0xFFFF>(mip_width, mip_height, (const uint16_t *)rptr, (uint16_t *)wptr);
|
||||
break;
|
||||
case FORMAT_RGBA16 | (FORMAT_RGB16 << 8):
|
||||
_convert_fast<uint16_t, 4, 3, 0x0000, 0xFFFF>(mip_width, mip_height, (const uint16_t *)rptr, (uint16_t *)wptr);
|
||||
break;
|
||||
case FORMAT_R16I | (FORMAT_RG16I << 8):
|
||||
_convert_fast<uint16_t, 1, 2, 0x0000, 0x0001>(mip_width, mip_height, (const uint16_t *)rptr, (uint16_t *)wptr);
|
||||
break;
|
||||
case FORMAT_R16I | (FORMAT_RGB16I << 8):
|
||||
_convert_fast<uint16_t, 1, 3, 0x0000, 0x0001>(mip_width, mip_height, (const uint16_t *)rptr, (uint16_t *)wptr);
|
||||
break;
|
||||
case FORMAT_R16I | (FORMAT_RGBA16I << 8):
|
||||
_convert_fast<uint16_t, 1, 4, 0x0000, 0x0001>(mip_width, mip_height, (const uint16_t *)rptr, (uint16_t *)wptr);
|
||||
break;
|
||||
case FORMAT_RG16I | (FORMAT_R16I << 8):
|
||||
_convert_fast<uint16_t, 2, 1, 0x0000, 0x0001>(mip_width, mip_height, (const uint16_t *)rptr, (uint16_t *)wptr);
|
||||
break;
|
||||
case FORMAT_RG16I | (FORMAT_RGB16I << 8):
|
||||
_convert_fast<uint16_t, 2, 3, 0x0000, 0x0001>(mip_width, mip_height, (const uint16_t *)rptr, (uint16_t *)wptr);
|
||||
break;
|
||||
case FORMAT_RG16I | (FORMAT_RGBA16I << 8):
|
||||
_convert_fast<uint16_t, 2, 4, 0x0000, 0x0001>(mip_width, mip_height, (const uint16_t *)rptr, (uint16_t *)wptr);
|
||||
break;
|
||||
case FORMAT_RGB16I | (FORMAT_R16I << 8):
|
||||
_convert_fast<uint16_t, 3, 1, 0x0000, 0x0001>(mip_width, mip_height, (const uint16_t *)rptr, (uint16_t *)wptr);
|
||||
break;
|
||||
case FORMAT_RGB16I | (FORMAT_RG16I << 8):
|
||||
_convert_fast<uint16_t, 3, 2, 0x0000, 0x0001>(mip_width, mip_height, (const uint16_t *)rptr, (uint16_t *)wptr);
|
||||
break;
|
||||
case FORMAT_RGB16I | (FORMAT_RGBA16I << 8):
|
||||
_convert_fast<uint16_t, 3, 4, 0x0000, 0x0001>(mip_width, mip_height, (const uint16_t *)rptr, (uint16_t *)wptr);
|
||||
break;
|
||||
case FORMAT_RGBA16I | (FORMAT_R16I << 8):
|
||||
_convert_fast<uint16_t, 4, 1, 0x0000, 0x0001>(mip_width, mip_height, (const uint16_t *)rptr, (uint16_t *)wptr);
|
||||
break;
|
||||
case FORMAT_RGBA16I | (FORMAT_RG16I << 8):
|
||||
_convert_fast<uint16_t, 4, 2, 0x0000, 0x0001>(mip_width, mip_height, (const uint16_t *)rptr, (uint16_t *)wptr);
|
||||
break;
|
||||
case FORMAT_RGBA16I | (FORMAT_RGB16I << 8):
|
||||
_convert_fast<uint16_t, 4, 3, 0x0000, 0x0001>(mip_width, mip_height, (const uint16_t *)rptr, (uint16_t *)wptr);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -769,6 +865,11 @@ Image::Format Image::get_format() const {
|
|||
return format;
|
||||
}
|
||||
|
||||
enum ImageScaleType {
|
||||
IMAGE_SCALING_INT,
|
||||
IMAGE_SCALING_FLOAT,
|
||||
};
|
||||
|
||||
static double _bicubic_interp_kernel(double x) {
|
||||
x = Math::abs(x);
|
||||
|
||||
|
@ -783,7 +884,7 @@ static double _bicubic_interp_kernel(double x) {
|
|||
return bc;
|
||||
}
|
||||
|
||||
template <int CC, typename T>
|
||||
template <int CC, typename T, ImageScaleType TYPE>
|
||||
static void _scale_cubic(const uint8_t *__restrict p_src, uint8_t *__restrict p_dst, uint32_t p_src_width, uint32_t p_src_height, uint32_t p_dst_width, uint32_t p_dst_height) {
|
||||
// get source image size
|
||||
int width = p_src_width;
|
||||
|
@ -845,7 +946,7 @@ static void _scale_cubic(const uint8_t *__restrict p_src, uint8_t *__restrict p_
|
|||
const T *__restrict p = ((T *)p_src) + (oy2 * p_src_width + ox2) * CC;
|
||||
|
||||
for (int i = 0; i < CC; i++) {
|
||||
if constexpr (sizeof(T) == 2) { //half float
|
||||
if constexpr (sizeof(T) == 2 && TYPE == IMAGE_SCALING_FLOAT) { //half float
|
||||
color[i] = Math::half_to_float(p[i]);
|
||||
} else {
|
||||
color[i] += p[i] * k2;
|
||||
|
@ -857,8 +958,12 @@ static void _scale_cubic(const uint8_t *__restrict p_src, uint8_t *__restrict p_
|
|||
for (int i = 0; i < CC; i++) {
|
||||
if constexpr (sizeof(T) == 1) { //byte
|
||||
dst[i] = CLAMP(Math::fast_ftoi(color[i]), 0, 255);
|
||||
} else if constexpr (sizeof(T) == 2) { //half float
|
||||
dst[i] = Math::make_half_float(color[i]);
|
||||
} else if constexpr (sizeof(T) == 2) {
|
||||
if constexpr (TYPE == IMAGE_SCALING_FLOAT) {
|
||||
dst[i] = Math::make_half_float(color[i]); //half float
|
||||
} else {
|
||||
dst[i] = CLAMP(Math::fast_ftoi(color[i]), 0, 65535); // uint16
|
||||
}
|
||||
} else {
|
||||
dst[i] = color[i];
|
||||
}
|
||||
|
@ -867,7 +972,7 @@ static void _scale_cubic(const uint8_t *__restrict p_src, uint8_t *__restrict p_
|
|||
}
|
||||
}
|
||||
|
||||
template <int CC, typename T>
|
||||
template <int CC, typename T, ImageScaleType TYPE>
|
||||
static void _scale_bilinear(const uint8_t *__restrict p_src, uint8_t *__restrict p_dst, uint32_t p_src_width, uint32_t p_src_height, uint32_t p_dst_width, uint32_t p_dst_height) {
|
||||
constexpr uint32_t FRAC_BITS = 8;
|
||||
constexpr uint32_t FRAC_LEN = (1 << FRAC_BITS);
|
||||
|
@ -915,23 +1020,40 @@ static void _scale_bilinear(const uint8_t *__restrict p_src, uint8_t *__restrict
|
|||
uint32_t interp = interp_up + (((interp_down - interp_up) * src_yofs_frac) >> FRAC_BITS);
|
||||
interp >>= FRAC_BITS;
|
||||
p_dst[i * p_dst_width * CC + j * CC + l] = uint8_t(interp);
|
||||
} else if constexpr (sizeof(T) == 2) { //half float
|
||||
} else if constexpr (sizeof(T) == 2) {
|
||||
if constexpr (TYPE == IMAGE_SCALING_FLOAT) { //half float
|
||||
float xofs_frac = float(src_xofs_frac) / (1 << FRAC_BITS);
|
||||
float yofs_frac = float(src_yofs_frac) / (1 << FRAC_BITS);
|
||||
const T *src = ((const T *)p_src);
|
||||
T *dst = ((T *)p_dst);
|
||||
|
||||
float xofs_frac = float(src_xofs_frac) / (1 << FRAC_BITS);
|
||||
float yofs_frac = float(src_yofs_frac) / (1 << FRAC_BITS);
|
||||
const T *src = ((const T *)p_src);
|
||||
T *dst = ((T *)p_dst);
|
||||
float p00 = Math::half_to_float(src[y_ofs_up + src_xofs_left + l]);
|
||||
float p10 = Math::half_to_float(src[y_ofs_up + src_xofs_right + l]);
|
||||
float p01 = Math::half_to_float(src[y_ofs_down + src_xofs_left + l]);
|
||||
float p11 = Math::half_to_float(src[y_ofs_down + src_xofs_right + l]);
|
||||
|
||||
float p00 = Math::half_to_float(src[y_ofs_up + src_xofs_left + l]);
|
||||
float p10 = Math::half_to_float(src[y_ofs_up + src_xofs_right + l]);
|
||||
float p01 = Math::half_to_float(src[y_ofs_down + src_xofs_left + l]);
|
||||
float p11 = Math::half_to_float(src[y_ofs_down + src_xofs_right + l]);
|
||||
float interp_up = p00 + (p10 - p00) * xofs_frac;
|
||||
float interp_down = p01 + (p11 - p01) * xofs_frac;
|
||||
float interp = interp_up + ((interp_down - interp_up) * yofs_frac);
|
||||
|
||||
float interp_up = p00 + (p10 - p00) * xofs_frac;
|
||||
float interp_down = p01 + (p11 - p01) * xofs_frac;
|
||||
float interp = interp_up + ((interp_down - interp_up) * yofs_frac);
|
||||
dst[i * p_dst_width * CC + j * CC + l] = Math::make_half_float(interp);
|
||||
} else { //uint16
|
||||
float xofs_frac = float(src_xofs_frac) / (1 << FRAC_BITS);
|
||||
float yofs_frac = float(src_yofs_frac) / (1 << FRAC_BITS);
|
||||
const T *src = ((const T *)p_src);
|
||||
T *dst = ((T *)p_dst);
|
||||
|
||||
dst[i * p_dst_width * CC + j * CC + l] = Math::make_half_float(interp);
|
||||
float p00 = src[y_ofs_up + src_xofs_left + l];
|
||||
float p10 = src[y_ofs_up + src_xofs_right + l];
|
||||
float p01 = src[y_ofs_down + src_xofs_left + l];
|
||||
float p11 = src[y_ofs_down + src_xofs_right + l];
|
||||
|
||||
float interp_up = p00 + (p10 - p00) * xofs_frac;
|
||||
float interp_down = p01 + (p11 - p01) * xofs_frac;
|
||||
float interp = interp_up + ((interp_down - interp_up) * yofs_frac);
|
||||
|
||||
dst[i * p_dst_width * CC + j * CC + l] = uint16_t(interp);
|
||||
}
|
||||
} else if constexpr (sizeof(T) == 4) { //float
|
||||
|
||||
float xofs_frac = float(src_xofs_frac) / (1 << FRAC_BITS);
|
||||
|
@ -982,7 +1104,7 @@ static float _lanczos(float p_x) {
|
|||
return Math::abs(p_x) >= LANCZOS_TYPE ? 0 : Math::sincn(p_x) * Math::sincn(p_x / LANCZOS_TYPE);
|
||||
}
|
||||
|
||||
template <int CC, typename T>
|
||||
template <int CC, typename T, ImageScaleType TYPE>
|
||||
static void _scale_lanczos(const uint8_t *__restrict p_src, uint8_t *__restrict p_dst, uint32_t p_src_width, uint32_t p_src_height, uint32_t p_dst_width, uint32_t p_dst_height) {
|
||||
int32_t src_width = p_src_width;
|
||||
int32_t src_height = p_src_height;
|
||||
|
@ -1023,7 +1145,7 @@ static void _scale_lanczos(const uint8_t *__restrict p_src, uint8_t *__restrict
|
|||
const T *__restrict src_data = ((const T *)p_src) + (buffer_y * src_width + target_x) * CC;
|
||||
|
||||
for (uint32_t i = 0; i < CC; i++) {
|
||||
if constexpr (sizeof(T) == 2) { //half float
|
||||
if constexpr (sizeof(T) == 2 && TYPE == IMAGE_SCALING_FLOAT) { //half float
|
||||
pixel[i] += Math::half_to_float(src_data[i]) * lanczos_val;
|
||||
} else {
|
||||
pixel[i] += src_data[i] * lanczos_val;
|
||||
|
@ -1082,8 +1204,13 @@ static void _scale_lanczos(const uint8_t *__restrict p_src, uint8_t *__restrict
|
|||
|
||||
if constexpr (sizeof(T) == 1) { //byte
|
||||
dst_data[i] = CLAMP(Math::fast_ftoi(pixel[i]), 0, 255);
|
||||
} else if constexpr (sizeof(T) == 2) { //half float
|
||||
dst_data[i] = Math::make_half_float(pixel[i]);
|
||||
} else if constexpr (sizeof(T) == 2) {
|
||||
if constexpr (TYPE == IMAGE_SCALING_FLOAT) { //half float
|
||||
dst_data[i] = Math::make_half_float(pixel[i]);
|
||||
} else { //uint16
|
||||
dst_data[i] = CLAMP(Math::fast_ftoi(pixel[i]), 0, 65535);
|
||||
}
|
||||
|
||||
} else { // float
|
||||
dst_data[i] = pixel[i];
|
||||
}
|
||||
|
@ -1226,6 +1353,21 @@ void Image::resize(int p_width, int p_height, Interpolation p_interpolation) {
|
|||
_scale_nearest<4, uint16_t>(r_ptr, w_ptr, width, height, p_width, p_height);
|
||||
break;
|
||||
}
|
||||
} else if (format >= FORMAT_R16 && format <= FORMAT_RGBA16I) {
|
||||
switch (get_format_pixel_size(format)) {
|
||||
case 2:
|
||||
_scale_nearest<1, uint16_t>(r_ptr, w_ptr, width, height, p_width, p_height);
|
||||
break;
|
||||
case 4:
|
||||
_scale_nearest<2, uint16_t>(r_ptr, w_ptr, width, height, p_width, p_height);
|
||||
break;
|
||||
case 6:
|
||||
_scale_nearest<3, uint16_t>(r_ptr, w_ptr, width, height, p_width, p_height);
|
||||
break;
|
||||
case 8:
|
||||
_scale_nearest<4, uint16_t>(r_ptr, w_ptr, width, height, p_width, p_height);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
} break;
|
||||
|
@ -1270,46 +1412,61 @@ void Image::resize(int p_width, int p_height, Interpolation p_interpolation) {
|
|||
if (format >= FORMAT_L8 && format <= FORMAT_RGBA8) {
|
||||
switch (get_format_pixel_size(format)) {
|
||||
case 1:
|
||||
_scale_bilinear<1, uint8_t>(src_ptr, w_ptr, src_width, src_height, p_width, p_height);
|
||||
_scale_bilinear<1, uint8_t, IMAGE_SCALING_INT>(src_ptr, w_ptr, src_width, src_height, p_width, p_height);
|
||||
break;
|
||||
case 2:
|
||||
_scale_bilinear<2, uint8_t>(src_ptr, w_ptr, src_width, src_height, p_width, p_height);
|
||||
_scale_bilinear<2, uint8_t, IMAGE_SCALING_INT>(src_ptr, w_ptr, src_width, src_height, p_width, p_height);
|
||||
break;
|
||||
case 3:
|
||||
_scale_bilinear<3, uint8_t>(src_ptr, w_ptr, src_width, src_height, p_width, p_height);
|
||||
_scale_bilinear<3, uint8_t, IMAGE_SCALING_INT>(src_ptr, w_ptr, src_width, src_height, p_width, p_height);
|
||||
break;
|
||||
case 4:
|
||||
_scale_bilinear<4, uint8_t>(src_ptr, w_ptr, src_width, src_height, p_width, p_height);
|
||||
_scale_bilinear<4, uint8_t, IMAGE_SCALING_INT>(src_ptr, w_ptr, src_width, src_height, p_width, p_height);
|
||||
break;
|
||||
}
|
||||
} else if (format >= FORMAT_RF && format <= FORMAT_RGBAF) {
|
||||
switch (get_format_pixel_size(format)) {
|
||||
case 4:
|
||||
_scale_bilinear<1, float>(src_ptr, w_ptr, src_width, src_height, p_width, p_height);
|
||||
_scale_bilinear<1, float, IMAGE_SCALING_FLOAT>(src_ptr, w_ptr, src_width, src_height, p_width, p_height);
|
||||
break;
|
||||
case 8:
|
||||
_scale_bilinear<2, float>(src_ptr, w_ptr, src_width, src_height, p_width, p_height);
|
||||
_scale_bilinear<2, float, IMAGE_SCALING_FLOAT>(src_ptr, w_ptr, src_width, src_height, p_width, p_height);
|
||||
break;
|
||||
case 12:
|
||||
_scale_bilinear<3, float>(src_ptr, w_ptr, src_width, src_height, p_width, p_height);
|
||||
_scale_bilinear<3, float, IMAGE_SCALING_FLOAT>(src_ptr, w_ptr, src_width, src_height, p_width, p_height);
|
||||
break;
|
||||
case 16:
|
||||
_scale_bilinear<4, float>(src_ptr, w_ptr, src_width, src_height, p_width, p_height);
|
||||
_scale_bilinear<4, float, IMAGE_SCALING_FLOAT>(src_ptr, w_ptr, src_width, src_height, p_width, p_height);
|
||||
break;
|
||||
}
|
||||
} else if (format >= FORMAT_RH && format <= FORMAT_RGBAH) {
|
||||
switch (get_format_pixel_size(format)) {
|
||||
case 2:
|
||||
_scale_bilinear<1, uint16_t>(src_ptr, w_ptr, src_width, src_height, p_width, p_height);
|
||||
_scale_bilinear<1, uint16_t, IMAGE_SCALING_FLOAT>(src_ptr, w_ptr, src_width, src_height, p_width, p_height);
|
||||
break;
|
||||
case 4:
|
||||
_scale_bilinear<2, uint16_t>(src_ptr, w_ptr, src_width, src_height, p_width, p_height);
|
||||
_scale_bilinear<2, uint16_t, IMAGE_SCALING_FLOAT>(src_ptr, w_ptr, src_width, src_height, p_width, p_height);
|
||||
break;
|
||||
case 6:
|
||||
_scale_bilinear<3, uint16_t>(src_ptr, w_ptr, src_width, src_height, p_width, p_height);
|
||||
_scale_bilinear<3, uint16_t, IMAGE_SCALING_FLOAT>(src_ptr, w_ptr, src_width, src_height, p_width, p_height);
|
||||
break;
|
||||
case 8:
|
||||
_scale_bilinear<4, uint16_t>(src_ptr, w_ptr, src_width, src_height, p_width, p_height);
|
||||
_scale_bilinear<4, uint16_t, IMAGE_SCALING_FLOAT>(src_ptr, w_ptr, src_width, src_height, p_width, p_height);
|
||||
break;
|
||||
}
|
||||
} else if (format >= FORMAT_R16 && format <= FORMAT_RGBA16I) {
|
||||
switch (get_format_pixel_size(format)) {
|
||||
case 2:
|
||||
_scale_bilinear<1, uint16_t, IMAGE_SCALING_INT>(src_ptr, w_ptr, src_width, src_height, p_width, p_height);
|
||||
break;
|
||||
case 4:
|
||||
_scale_bilinear<2, uint16_t, IMAGE_SCALING_INT>(src_ptr, w_ptr, src_width, src_height, p_width, p_height);
|
||||
break;
|
||||
case 6:
|
||||
_scale_bilinear<3, uint16_t, IMAGE_SCALING_INT>(src_ptr, w_ptr, src_width, src_height, p_width, p_height);
|
||||
break;
|
||||
case 8:
|
||||
_scale_bilinear<4, uint16_t, IMAGE_SCALING_INT>(src_ptr, w_ptr, src_width, src_height, p_width, p_height);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -1326,46 +1483,61 @@ void Image::resize(int p_width, int p_height, Interpolation p_interpolation) {
|
|||
if (format >= FORMAT_L8 && format <= FORMAT_RGBA8) {
|
||||
switch (get_format_pixel_size(format)) {
|
||||
case 1:
|
||||
_scale_cubic<1, uint8_t>(r_ptr, w_ptr, width, height, p_width, p_height);
|
||||
_scale_cubic<1, uint8_t, IMAGE_SCALING_INT>(r_ptr, w_ptr, width, height, p_width, p_height);
|
||||
break;
|
||||
case 2:
|
||||
_scale_cubic<2, uint8_t>(r_ptr, w_ptr, width, height, p_width, p_height);
|
||||
_scale_cubic<2, uint8_t, IMAGE_SCALING_INT>(r_ptr, w_ptr, width, height, p_width, p_height);
|
||||
break;
|
||||
case 3:
|
||||
_scale_cubic<3, uint8_t>(r_ptr, w_ptr, width, height, p_width, p_height);
|
||||
_scale_cubic<3, uint8_t, IMAGE_SCALING_INT>(r_ptr, w_ptr, width, height, p_width, p_height);
|
||||
break;
|
||||
case 4:
|
||||
_scale_cubic<4, uint8_t>(r_ptr, w_ptr, width, height, p_width, p_height);
|
||||
_scale_cubic<4, uint8_t, IMAGE_SCALING_INT>(r_ptr, w_ptr, width, height, p_width, p_height);
|
||||
break;
|
||||
}
|
||||
} else if (format >= FORMAT_RF && format <= FORMAT_RGBAF) {
|
||||
switch (get_format_pixel_size(format)) {
|
||||
case 4:
|
||||
_scale_cubic<1, float>(r_ptr, w_ptr, width, height, p_width, p_height);
|
||||
_scale_cubic<1, float, IMAGE_SCALING_FLOAT>(r_ptr, w_ptr, width, height, p_width, p_height);
|
||||
break;
|
||||
case 8:
|
||||
_scale_cubic<2, float>(r_ptr, w_ptr, width, height, p_width, p_height);
|
||||
_scale_cubic<2, float, IMAGE_SCALING_FLOAT>(r_ptr, w_ptr, width, height, p_width, p_height);
|
||||
break;
|
||||
case 12:
|
||||
_scale_cubic<3, float>(r_ptr, w_ptr, width, height, p_width, p_height);
|
||||
_scale_cubic<3, float, IMAGE_SCALING_FLOAT>(r_ptr, w_ptr, width, height, p_width, p_height);
|
||||
break;
|
||||
case 16:
|
||||
_scale_cubic<4, float>(r_ptr, w_ptr, width, height, p_width, p_height);
|
||||
_scale_cubic<4, float, IMAGE_SCALING_FLOAT>(r_ptr, w_ptr, width, height, p_width, p_height);
|
||||
break;
|
||||
}
|
||||
} else if (format >= FORMAT_RH && format <= FORMAT_RGBAH) {
|
||||
switch (get_format_pixel_size(format)) {
|
||||
case 2:
|
||||
_scale_cubic<1, uint16_t>(r_ptr, w_ptr, width, height, p_width, p_height);
|
||||
_scale_cubic<1, uint16_t, IMAGE_SCALING_FLOAT>(r_ptr, w_ptr, width, height, p_width, p_height);
|
||||
break;
|
||||
case 4:
|
||||
_scale_cubic<2, uint16_t>(r_ptr, w_ptr, width, height, p_width, p_height);
|
||||
_scale_cubic<2, uint16_t, IMAGE_SCALING_FLOAT>(r_ptr, w_ptr, width, height, p_width, p_height);
|
||||
break;
|
||||
case 6:
|
||||
_scale_cubic<3, uint16_t>(r_ptr, w_ptr, width, height, p_width, p_height);
|
||||
_scale_cubic<3, uint16_t, IMAGE_SCALING_FLOAT>(r_ptr, w_ptr, width, height, p_width, p_height);
|
||||
break;
|
||||
case 8:
|
||||
_scale_cubic<4, uint16_t>(r_ptr, w_ptr, width, height, p_width, p_height);
|
||||
_scale_cubic<4, uint16_t, IMAGE_SCALING_FLOAT>(r_ptr, w_ptr, width, height, p_width, p_height);
|
||||
break;
|
||||
}
|
||||
} else if (format >= FORMAT_R16 && format <= FORMAT_RGBA16I) {
|
||||
switch (get_format_pixel_size(format)) {
|
||||
case 2:
|
||||
_scale_cubic<1, uint16_t, IMAGE_SCALING_INT>(r_ptr, w_ptr, width, height, p_width, p_height);
|
||||
break;
|
||||
case 4:
|
||||
_scale_cubic<2, uint16_t, IMAGE_SCALING_INT>(r_ptr, w_ptr, width, height, p_width, p_height);
|
||||
break;
|
||||
case 6:
|
||||
_scale_cubic<3, uint16_t, IMAGE_SCALING_INT>(r_ptr, w_ptr, width, height, p_width, p_height);
|
||||
break;
|
||||
case 8:
|
||||
_scale_cubic<4, uint16_t, IMAGE_SCALING_INT>(r_ptr, w_ptr, width, height, p_width, p_height);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -1374,46 +1546,61 @@ void Image::resize(int p_width, int p_height, Interpolation p_interpolation) {
|
|||
if (format >= FORMAT_L8 && format <= FORMAT_RGBA8) {
|
||||
switch (get_format_pixel_size(format)) {
|
||||
case 1:
|
||||
_scale_lanczos<1, uint8_t>(r_ptr, w_ptr, width, height, p_width, p_height);
|
||||
_scale_lanczos<1, uint8_t, IMAGE_SCALING_INT>(r_ptr, w_ptr, width, height, p_width, p_height);
|
||||
break;
|
||||
case 2:
|
||||
_scale_lanczos<2, uint8_t>(r_ptr, w_ptr, width, height, p_width, p_height);
|
||||
_scale_lanczos<2, uint8_t, IMAGE_SCALING_INT>(r_ptr, w_ptr, width, height, p_width, p_height);
|
||||
break;
|
||||
case 3:
|
||||
_scale_lanczos<3, uint8_t>(r_ptr, w_ptr, width, height, p_width, p_height);
|
||||
_scale_lanczos<3, uint8_t, IMAGE_SCALING_INT>(r_ptr, w_ptr, width, height, p_width, p_height);
|
||||
break;
|
||||
case 4:
|
||||
_scale_lanczos<4, uint8_t>(r_ptr, w_ptr, width, height, p_width, p_height);
|
||||
_scale_lanczos<4, uint8_t, IMAGE_SCALING_INT>(r_ptr, w_ptr, width, height, p_width, p_height);
|
||||
break;
|
||||
}
|
||||
} else if (format >= FORMAT_RF && format <= FORMAT_RGBAF) {
|
||||
switch (get_format_pixel_size(format)) {
|
||||
case 4:
|
||||
_scale_lanczos<1, float>(r_ptr, w_ptr, width, height, p_width, p_height);
|
||||
_scale_lanczos<1, float, IMAGE_SCALING_FLOAT>(r_ptr, w_ptr, width, height, p_width, p_height);
|
||||
break;
|
||||
case 8:
|
||||
_scale_lanczos<2, float>(r_ptr, w_ptr, width, height, p_width, p_height);
|
||||
_scale_lanczos<2, float, IMAGE_SCALING_FLOAT>(r_ptr, w_ptr, width, height, p_width, p_height);
|
||||
break;
|
||||
case 12:
|
||||
_scale_lanczos<3, float>(r_ptr, w_ptr, width, height, p_width, p_height);
|
||||
_scale_lanczos<3, float, IMAGE_SCALING_FLOAT>(r_ptr, w_ptr, width, height, p_width, p_height);
|
||||
break;
|
||||
case 16:
|
||||
_scale_lanczos<4, float>(r_ptr, w_ptr, width, height, p_width, p_height);
|
||||
_scale_lanczos<4, float, IMAGE_SCALING_FLOAT>(r_ptr, w_ptr, width, height, p_width, p_height);
|
||||
break;
|
||||
}
|
||||
} else if (format >= FORMAT_RH && format <= FORMAT_RGBAH) {
|
||||
switch (get_format_pixel_size(format)) {
|
||||
case 2:
|
||||
_scale_lanczos<1, uint16_t>(r_ptr, w_ptr, width, height, p_width, p_height);
|
||||
_scale_lanczos<1, uint16_t, IMAGE_SCALING_FLOAT>(r_ptr, w_ptr, width, height, p_width, p_height);
|
||||
break;
|
||||
case 4:
|
||||
_scale_lanczos<2, uint16_t>(r_ptr, w_ptr, width, height, p_width, p_height);
|
||||
_scale_lanczos<2, uint16_t, IMAGE_SCALING_FLOAT>(r_ptr, w_ptr, width, height, p_width, p_height);
|
||||
break;
|
||||
case 6:
|
||||
_scale_lanczos<3, uint16_t>(r_ptr, w_ptr, width, height, p_width, p_height);
|
||||
_scale_lanczos<3, uint16_t, IMAGE_SCALING_FLOAT>(r_ptr, w_ptr, width, height, p_width, p_height);
|
||||
break;
|
||||
case 8:
|
||||
_scale_lanczos<4, uint16_t>(r_ptr, w_ptr, width, height, p_width, p_height);
|
||||
_scale_lanczos<4, uint16_t, IMAGE_SCALING_FLOAT>(r_ptr, w_ptr, width, height, p_width, p_height);
|
||||
break;
|
||||
}
|
||||
} else if (format >= FORMAT_R16 && format <= FORMAT_RGBA16I) {
|
||||
switch (get_format_pixel_size(format)) {
|
||||
case 2:
|
||||
_scale_lanczos<1, uint16_t, IMAGE_SCALING_INT>(r_ptr, w_ptr, width, height, p_width, p_height);
|
||||
break;
|
||||
case 4:
|
||||
_scale_lanczos<2, uint16_t, IMAGE_SCALING_INT>(r_ptr, w_ptr, width, height, p_width, p_height);
|
||||
break;
|
||||
case 6:
|
||||
_scale_lanczos<3, uint16_t, IMAGE_SCALING_INT>(r_ptr, w_ptr, width, height, p_width, p_height);
|
||||
break;
|
||||
case 8:
|
||||
_scale_lanczos<4, uint16_t, IMAGE_SCALING_INT>(r_ptr, w_ptr, width, height, p_width, p_height);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -1871,6 +2058,30 @@ void Image::_generate_mipmap_from_format(Image::Format p_format, const uint8_t *
|
|||
case Image::FORMAT_RGBE9995:
|
||||
_generate_po2_mipmap<uint32_t, 1, false, Image::average_4_rgbe9995, Image::renormalize_rgbe9995>(src_u32, dst_u32, p_width, p_height);
|
||||
break;
|
||||
case Image::FORMAT_R16:
|
||||
case Image::FORMAT_R16I:
|
||||
_generate_po2_mipmap<uint16_t, 1, false, Image::average_4_uint16, Image::renormalize_uint16>(src_u16, dst_u16, p_width, p_height);
|
||||
break;
|
||||
case Image::FORMAT_RG16:
|
||||
case Image::FORMAT_RG16I:
|
||||
_generate_po2_mipmap<uint16_t, 2, false, Image::average_4_uint16, Image::renormalize_uint16>(src_u16, dst_u16, p_width, p_height);
|
||||
break;
|
||||
case Image::FORMAT_RGB16:
|
||||
case Image::FORMAT_RGB16I: {
|
||||
if (p_renormalize) {
|
||||
_generate_po2_mipmap<uint16_t, 3, true, Image::average_4_uint16, Image::renormalize_uint16>(src_u16, dst_u16, p_width, p_height);
|
||||
} else {
|
||||
_generate_po2_mipmap<uint16_t, 3, false, Image::average_4_uint16, Image::renormalize_uint16>(src_u16, dst_u16, p_width, p_height);
|
||||
}
|
||||
} break;
|
||||
case Image::FORMAT_RGBA16:
|
||||
case Image::FORMAT_RGBA16I: {
|
||||
if (p_renormalize) {
|
||||
_generate_po2_mipmap<uint16_t, 4, true, Image::average_4_uint16, Image::renormalize_uint16>(src_u16, dst_u16, p_width, p_height);
|
||||
} else {
|
||||
_generate_po2_mipmap<uint16_t, 4, false, Image::average_4_uint16, Image::renormalize_uint16>(src_u16, dst_u16, p_width, p_height);
|
||||
}
|
||||
} break;
|
||||
|
||||
default:
|
||||
return;
|
||||
|
@ -2468,6 +2679,17 @@ bool Image::is_invisible() const {
|
|||
}
|
||||
}
|
||||
} break;
|
||||
case FORMAT_RGBA16:
|
||||
case FORMAT_RGBA16I: {
|
||||
const int pixel_count = len / 8;
|
||||
const uint16_t *pixeldata = reinterpret_cast<const uint16_t *>(data.ptr());
|
||||
|
||||
for (int i = 0; i < pixel_count; i++) {
|
||||
if (pixeldata[i * 4 + 3] != 0) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
} break;
|
||||
default: {
|
||||
// Formats that are compressed or don't support alpha channels are presumed to be visible.
|
||||
return false;
|
||||
|
@ -2671,7 +2893,7 @@ bool Image::is_compressed() const {
|
|||
}
|
||||
|
||||
bool Image::is_format_compressed(Format p_format) {
|
||||
return p_format > FORMAT_RGBE9995;
|
||||
return p_format > FORMAT_RGBE9995 && p_format < FORMAT_R16;
|
||||
}
|
||||
|
||||
Error Image::decompress() {
|
||||
|
@ -3252,6 +3474,50 @@ Color Image::_get_color_at_ofs(const uint8_t *ptr, uint32_t ofs) const {
|
|||
case FORMAT_RGBE9995: {
|
||||
return Color::from_rgbe9995(((uint32_t *)ptr)[ofs]);
|
||||
}
|
||||
case FORMAT_R16: {
|
||||
float r = ((uint16_t *)ptr)[ofs] / 65535.0f;
|
||||
return Color(r, 0, 0, 1);
|
||||
}
|
||||
case FORMAT_RG16: {
|
||||
float r = ((uint16_t *)ptr)[ofs * 2 + 0] / 65535.0f;
|
||||
float g = ((uint16_t *)ptr)[ofs * 2 + 1] / 65535.0f;
|
||||
return Color(r, g, 0, 1);
|
||||
}
|
||||
case FORMAT_RGB16: {
|
||||
float r = ((uint16_t *)ptr)[ofs * 3 + 0] / 65535.0f;
|
||||
float g = ((uint16_t *)ptr)[ofs * 3 + 1] / 65535.0f;
|
||||
float b = ((uint16_t *)ptr)[ofs * 3 + 2] / 65535.0f;
|
||||
return Color(r, g, b, 1);
|
||||
}
|
||||
case FORMAT_RGBA16: {
|
||||
float r = ((uint16_t *)ptr)[ofs * 4 + 0] / 65535.0f;
|
||||
float g = ((uint16_t *)ptr)[ofs * 4 + 1] / 65535.0f;
|
||||
float b = ((uint16_t *)ptr)[ofs * 4 + 2] / 65535.0f;
|
||||
float a = ((uint16_t *)ptr)[ofs * 4 + 3] / 65535.0f;
|
||||
return Color(r, g, b, a);
|
||||
}
|
||||
case FORMAT_R16I: {
|
||||
uint16_t r = ((uint16_t *)ptr)[ofs];
|
||||
return Color(r, 0, 0, 1);
|
||||
}
|
||||
case FORMAT_RG16I: {
|
||||
uint16_t r = ((uint16_t *)ptr)[ofs * 2 + 0];
|
||||
uint16_t g = ((uint16_t *)ptr)[ofs * 2 + 1];
|
||||
return Color(r, g, 0, 1);
|
||||
}
|
||||
case FORMAT_RGB16I: {
|
||||
uint16_t r = ((uint16_t *)ptr)[ofs * 3 + 0];
|
||||
uint16_t g = ((uint16_t *)ptr)[ofs * 3 + 1];
|
||||
uint16_t b = ((uint16_t *)ptr)[ofs * 3 + 2];
|
||||
return Color(r, g, b, 1);
|
||||
}
|
||||
case FORMAT_RGBA16I: {
|
||||
uint16_t r = ((uint16_t *)ptr)[ofs * 4 + 0];
|
||||
uint16_t g = ((uint16_t *)ptr)[ofs * 4 + 1];
|
||||
uint16_t b = ((uint16_t *)ptr)[ofs * 4 + 2];
|
||||
uint16_t a = ((uint16_t *)ptr)[ofs * 4 + 3];
|
||||
return Color(r, g, b, a);
|
||||
}
|
||||
|
||||
default: {
|
||||
ERR_FAIL_V_MSG(Color(), "Can't get_pixel() on compressed image, sorry.");
|
||||
|
@ -3344,6 +3610,42 @@ void Image::_set_color_at_ofs(uint8_t *ptr, uint32_t ofs, const Color &p_color)
|
|||
case FORMAT_RGBE9995: {
|
||||
((uint32_t *)ptr)[ofs] = p_color.to_rgbe9995();
|
||||
} break;
|
||||
case FORMAT_R16: {
|
||||
((uint16_t *)ptr)[ofs] = uint16_t(CLAMP(p_color.r * 65535.0, 0, 65535));
|
||||
} break;
|
||||
case FORMAT_RG16: {
|
||||
((uint16_t *)ptr)[ofs * 2 + 0] = uint16_t(CLAMP(p_color.r * 65535.0, 0, 65535));
|
||||
((uint16_t *)ptr)[ofs * 2 + 1] = uint16_t(CLAMP(p_color.g * 65535.0, 0, 65535));
|
||||
} break;
|
||||
case FORMAT_RGB16: {
|
||||
((uint16_t *)ptr)[ofs * 3 + 0] = uint16_t(CLAMP(p_color.r * 65535.0, 0, 65535));
|
||||
((uint16_t *)ptr)[ofs * 3 + 1] = uint16_t(CLAMP(p_color.g * 65535.0, 0, 65535));
|
||||
((uint16_t *)ptr)[ofs * 3 + 2] = uint16_t(CLAMP(p_color.b * 65535.0, 0, 65535));
|
||||
} break;
|
||||
case FORMAT_RGBA16: {
|
||||
((uint16_t *)ptr)[ofs * 4 + 0] = uint16_t(CLAMP(p_color.r * 65535.0, 0, 65535));
|
||||
((uint16_t *)ptr)[ofs * 4 + 1] = uint16_t(CLAMP(p_color.g * 65535.0, 0, 65535));
|
||||
((uint16_t *)ptr)[ofs * 4 + 2] = uint16_t(CLAMP(p_color.b * 65535.0, 0, 65535));
|
||||
((uint16_t *)ptr)[ofs * 4 + 3] = uint16_t(CLAMP(p_color.a * 65535.0, 0, 65535));
|
||||
} break;
|
||||
case FORMAT_R16I: {
|
||||
((uint16_t *)ptr)[ofs] = uint16_t(CLAMP(p_color.r, 0, 65535));
|
||||
} break;
|
||||
case FORMAT_RG16I: {
|
||||
((uint16_t *)ptr)[ofs * 2 + 0] = uint16_t(CLAMP(p_color.r, 0, 65535));
|
||||
((uint16_t *)ptr)[ofs * 2 + 1] = uint16_t(CLAMP(p_color.g, 0, 65535));
|
||||
} break;
|
||||
case FORMAT_RGB16I: {
|
||||
((uint16_t *)ptr)[ofs * 3 + 0] = uint16_t(CLAMP(p_color.r, 0, 65535));
|
||||
((uint16_t *)ptr)[ofs * 3 + 1] = uint16_t(CLAMP(p_color.g, 0, 65535));
|
||||
((uint16_t *)ptr)[ofs * 3 + 2] = uint16_t(CLAMP(p_color.b, 0, 65535));
|
||||
} break;
|
||||
case FORMAT_RGBA16I: {
|
||||
((uint16_t *)ptr)[ofs * 4 + 0] = uint16_t(CLAMP(p_color.r, 0, 65535));
|
||||
((uint16_t *)ptr)[ofs * 4 + 1] = uint16_t(CLAMP(p_color.g, 0, 65535));
|
||||
((uint16_t *)ptr)[ofs * 4 + 2] = uint16_t(CLAMP(p_color.b, 0, 65535));
|
||||
((uint16_t *)ptr)[ofs * 4 + 3] = uint16_t(CLAMP(p_color.a, 0, 65535));
|
||||
} break;
|
||||
|
||||
default: {
|
||||
ERR_FAIL_MSG("Can't set_pixel() on compressed image, sorry.");
|
||||
|
@ -3419,11 +3721,11 @@ Image::UsedChannels Image::detect_used_channels(CompressSource p_source) const {
|
|||
|
||||
if (format == FORMAT_L8) {
|
||||
return USED_CHANNELS_L; // Grayscale only cannot have any channel less.
|
||||
} else if (format == FORMAT_R8 || format == FORMAT_RH || format == FORMAT_RF) {
|
||||
} else if (format == FORMAT_R8 || format == FORMAT_RH || format == FORMAT_RF || format == FORMAT_R16 || format == FORMAT_R16I) {
|
||||
return USED_CHANNELS_R; // Red only cannot have any channel less.
|
||||
}
|
||||
|
||||
const bool supports_alpha = format == FORMAT_RGBA8 || format == FORMAT_RGBA4444 || format == FORMAT_RGBAH || format == FORMAT_RGBAF;
|
||||
const bool supports_alpha = format == FORMAT_RGBA8 || format == FORMAT_RGBA4444 || format == FORMAT_RGBAH || format == FORMAT_RGBAF || format == FORMAT_RGBA16 || format == FORMAT_RGBA16I;
|
||||
bool r = false, g = false, b = false, a = false, c = false;
|
||||
|
||||
const uint8_t *data_ptr = data.ptr();
|
||||
|
@ -3657,6 +3959,14 @@ void Image::_bind_methods() {
|
|||
BIND_ENUM_CONSTANT(FORMAT_ASTC_4x4_HDR);
|
||||
BIND_ENUM_CONSTANT(FORMAT_ASTC_8x8);
|
||||
BIND_ENUM_CONSTANT(FORMAT_ASTC_8x8_HDR);
|
||||
BIND_ENUM_CONSTANT(FORMAT_R16);
|
||||
BIND_ENUM_CONSTANT(FORMAT_RG16);
|
||||
BIND_ENUM_CONSTANT(FORMAT_RGB16);
|
||||
BIND_ENUM_CONSTANT(FORMAT_RGBA16);
|
||||
BIND_ENUM_CONSTANT(FORMAT_R16I);
|
||||
BIND_ENUM_CONSTANT(FORMAT_RG16I);
|
||||
BIND_ENUM_CONSTANT(FORMAT_RGB16I);
|
||||
BIND_ENUM_CONSTANT(FORMAT_RGBA16I);
|
||||
BIND_ENUM_CONSTANT(FORMAT_MAX);
|
||||
|
||||
BIND_ENUM_CONSTANT(INTERPOLATE_NEAREST);
|
||||
|
@ -4070,6 +4380,22 @@ uint32_t Image::get_format_component_mask(Format p_format) {
|
|||
return rgba;
|
||||
case FORMAT_ASTC_8x8_HDR:
|
||||
return rgba;
|
||||
case FORMAT_R16:
|
||||
return r;
|
||||
case FORMAT_RG16:
|
||||
return rg;
|
||||
case FORMAT_RGB16:
|
||||
return rgb;
|
||||
case FORMAT_RGBA16:
|
||||
return rgba;
|
||||
case FORMAT_R16I:
|
||||
return r;
|
||||
case FORMAT_RG16I:
|
||||
return rg;
|
||||
case FORMAT_RGB16I:
|
||||
return rgb;
|
||||
case FORMAT_RGBA16I:
|
||||
return rgba;
|
||||
default:
|
||||
ERR_PRINT("Unhandled format.");
|
||||
return rgba;
|
||||
|
@ -4213,6 +4539,10 @@ void Image::average_4_rgbe9995(uint32_t &p_out, const uint32_t &p_a, const uint3
|
|||
p_out = ((Color::from_rgbe9995(p_a) + Color::from_rgbe9995(p_b) + Color::from_rgbe9995(p_c) + Color::from_rgbe9995(p_d)) * 0.25f).to_rgbe9995();
|
||||
}
|
||||
|
||||
void Image::average_4_uint16(uint16_t &p_out, const uint16_t &p_a, const uint16_t &p_b, const uint16_t &p_c, const uint16_t &p_d) {
|
||||
p_out = static_cast<uint16_t>((p_a + p_b + p_c + p_d + 2) >> 2);
|
||||
}
|
||||
|
||||
void Image::renormalize_uint8(uint8_t *p_rgb) {
|
||||
Vector3 n(p_rgb[0] / 255.0, p_rgb[1] / 255.0, p_rgb[2] / 255.0);
|
||||
n *= 2.0;
|
||||
|
@ -4246,6 +4576,19 @@ void Image::renormalize_rgbe9995(uint32_t *p_rgb) {
|
|||
// Never used.
|
||||
}
|
||||
|
||||
void Image::renormalize_uint16(uint16_t *p_rgb) {
|
||||
Vector3 n(p_rgb[0] / 65535.0, p_rgb[1] / 65535.0, p_rgb[2] / 65535.0);
|
||||
n *= 2.0;
|
||||
n -= Vector3(1, 1, 1);
|
||||
n.normalize();
|
||||
n += Vector3(1, 1, 1);
|
||||
n *= 0.5;
|
||||
n *= 65535;
|
||||
p_rgb[0] = CLAMP(int(n.x), 0, 65535);
|
||||
p_rgb[1] = CLAMP(int(n.y), 0, 65535);
|
||||
p_rgb[2] = CLAMP(int(n.z), 0, 65535);
|
||||
}
|
||||
|
||||
Image::Image(const uint8_t *p_mem_png_jpg, int p_len) {
|
||||
width = 0;
|
||||
height = 0;
|
||||
|
|
|
@ -111,6 +111,14 @@ public:
|
|||
FORMAT_ASTC_4x4_HDR,
|
||||
FORMAT_ASTC_8x8,
|
||||
FORMAT_ASTC_8x8_HDR,
|
||||
FORMAT_R16,
|
||||
FORMAT_RG16,
|
||||
FORMAT_RGB16,
|
||||
FORMAT_RGBA16,
|
||||
FORMAT_R16I,
|
||||
FORMAT_RG16I,
|
||||
FORMAT_RGB16I,
|
||||
FORMAT_RGBA16I,
|
||||
FORMAT_MAX
|
||||
};
|
||||
|
||||
|
@ -282,10 +290,12 @@ private:
|
|||
static void average_4_float(float &p_out, const float &p_a, const float &p_b, const float &p_c, const float &p_d);
|
||||
static void average_4_half(uint16_t &p_out, const uint16_t &p_a, const uint16_t &p_b, const uint16_t &p_c, const uint16_t &p_d);
|
||||
static void average_4_rgbe9995(uint32_t &p_out, const uint32_t &p_a, const uint32_t &p_b, const uint32_t &p_c, const uint32_t &p_d);
|
||||
static void average_4_uint16(uint16_t &p_out, const uint16_t &p_a, const uint16_t &p_b, const uint16_t &p_c, const uint16_t &p_d);
|
||||
static void renormalize_uint8(uint8_t *p_rgb);
|
||||
static void renormalize_float(float *p_rgb);
|
||||
static void renormalize_half(uint16_t *p_rgb);
|
||||
static void renormalize_rgbe9995(uint32_t *p_rgb);
|
||||
static void renormalize_uint16(uint16_t *p_rgb);
|
||||
|
||||
public:
|
||||
int get_width() const;
|
||||
|
|
|
@ -761,7 +761,43 @@
|
|||
<constant name="FORMAT_ASTC_8x8_HDR" value="38" enum="Format">
|
||||
Same format as [constant FORMAT_ASTC_8x8], but with the hint to let the GPU know it is used for HDR.
|
||||
</constant>
|
||||
<constant name="FORMAT_MAX" value="39" enum="Format">
|
||||
<constant name="FORMAT_R16" value="39" enum="Format">
|
||||
OpenGL texture format [code]GL_R16[/code] where there's one component, a 16-bit unsigned normalized integer value. Since the value is normalized, each component is clamped between [code]0.0[/code] and [code]1.0[/code] (inclusive).
|
||||
[b]Note:[/b] Due to limited hardware support, it is mainly recommended to be used on desktop or console devices. It may be unsupported on mobile or web, and will consequently be converted to [constant FORMAT_RF].
|
||||
</constant>
|
||||
<constant name="FORMAT_RG16" value="40" enum="Format">
|
||||
OpenGL texture format [code]GL_RG16[/code] where there are two components, each a 16-bit unsigned normalized integer value. Since the value is normalized, each component is clamped between [code]0.0[/code] and [code]1.0[/code] (inclusive).
|
||||
[b]Note:[/b] Due to limited hardware support, it is mainly recommended to be used on desktop or console devices. It may be unsupported on mobile or web, and will consequently be converted to [constant FORMAT_RGF].
|
||||
</constant>
|
||||
<constant name="FORMAT_RGB16" value="41" enum="Format">
|
||||
OpenGL texture format [code]GL_RGB16[/code] where there are three components, each a 16-bit unsigned normalized integer value. Since the value is normalized, each component is clamped between [code]0.0[/code] and [code]1.0[/code] (inclusive).
|
||||
[b]Note:[/b] Due to limited hardware support, it is mainly recommended to be used on desktop or console devices. It may be unsupported on mobile or web, and will consequently be converted to [constant FORMAT_RGBF].
|
||||
</constant>
|
||||
<constant name="FORMAT_RGBA16" value="42" enum="Format">
|
||||
OpenGL texture format [code]GL_RGBA16[/code] where there are four components, each a 16-bit unsigned normalized integer value. Since the value is normalized, each component is clamped between [code]0.0[/code] and [code]1.0[/code] (inclusive).
|
||||
[b]Note:[/b] Due to limited hardware support, it is mainly recommended to be used on desktop or console devices. It may be unsupported on mobile or web, and will consequently be converted to [constant FORMAT_RGBAF].
|
||||
</constant>
|
||||
<constant name="FORMAT_R16I" value="43" enum="Format">
|
||||
OpenGL texture format [code]GL_R16UI[/code] where there's one component, a 16-bit unsigned integer value. Each component is clamped between [code]0[/code] and [code]65535[/code] (inclusive).
|
||||
[b]Note:[/b] When used in a shader, the texture requires usage of [code]usampler[/code] samplers. Additionally, it only supports nearest-neighbor filtering under the Compatibility renderer.
|
||||
[b]Note:[/b] When sampling using [method Image.get_pixel], returned [Color]s have to be divided by [code]65535[/code] to get the correct color value.
|
||||
</constant>
|
||||
<constant name="FORMAT_RG16I" value="44" enum="Format">
|
||||
OpenGL texture format [code]GL_RG16UI[/code] where there are two components, each a 16-bit unsigned integer value. Each component is clamped between [code]0[/code] and [code]65535[/code] (inclusive).
|
||||
[b]Note:[/b] When used in a shader, the texture requires usage of [code]usampler[/code] samplers. Additionally, it only supports nearest-neighbor filtering under the Compatibility renderer.
|
||||
[b]Note:[/b] When sampling using [method Image.get_pixel], returned [Color]s have to be divided by [code]65535[/code] to get the correct color value.
|
||||
</constant>
|
||||
<constant name="FORMAT_RGB16I" value="45" enum="Format">
|
||||
OpenGL texture format [code]GL_RGB16UI[/code] where there are three components, each a 16-bit unsigned integer value. Each component is clamped between [code]0[/code] and [code]65535[/code] (inclusive).
|
||||
[b]Note:[/b] When used in a shader, the texture requires usage of [code]usampler[/code] samplers. Additionally, it only supports nearest-neighbor filtering under the Compatibility renderer.
|
||||
[b]Note:[/b] When sampling using [method Image.get_pixel], returned [Color]s have to be divided by [code]65535[/code] to get the correct color value.
|
||||
</constant>
|
||||
<constant name="FORMAT_RGBA16I" value="46" enum="Format">
|
||||
OpenGL texture format [code]GL_RGBA16UI[/code] where there are four components, each a 16-bit unsigned integer value. Each component is clamped between [code]0[/code] and [code]65535[/code] (inclusive).
|
||||
[b]Note:[/b] When used in a shader, the texture requires usage of [code]usampler[/code] samplers. Additionally, it only supports nearest-neighbor filtering under the Compatibility renderer.
|
||||
[b]Note:[/b] When sampling using [method Image.get_pixel], returned [Color]s have to be divided by [code]65535[/code] to get the correct color value.
|
||||
</constant>
|
||||
<constant name="FORMAT_MAX" value="47" enum="Format">
|
||||
Represents the size of the [enum Format] enum.
|
||||
</constant>
|
||||
<constant name="INTERPOLATE_NEAREST" value="0" enum="Interpolation">
|
||||
|
|
|
@ -90,6 +90,7 @@ Config::Config() {
|
|||
s3tc_supported = true;
|
||||
rgtc_supported = true; //RGTC - core since OpenGL version 3.0
|
||||
srgb_framebuffer_supported = true;
|
||||
unorm16_texture_supported = true;
|
||||
} else {
|
||||
float_texture_supported = extensions.has("GL_EXT_color_buffer_float");
|
||||
float_texture_linear_supported = extensions.has("GL_OES_texture_float_linear");
|
||||
|
@ -104,6 +105,7 @@ Config::Config() {
|
|||
#endif
|
||||
rgtc_supported = extensions.has("GL_EXT_texture_compression_rgtc") || extensions.has("GL_ARB_texture_compression_rgtc");
|
||||
srgb_framebuffer_supported = extensions.has("GL_EXT_sRGB_write_control");
|
||||
unorm16_texture_supported = extensions.has("GL_EXT_texture_norm16");
|
||||
}
|
||||
|
||||
glGetIntegerv(GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS, &max_vertex_texture_image_units);
|
||||
|
|
|
@ -82,6 +82,7 @@ public:
|
|||
bool astc_layered_supported = false;
|
||||
bool astc_3d_supported = false;
|
||||
bool srgb_framebuffer_supported = false;
|
||||
bool unorm16_texture_supported = false;
|
||||
|
||||
bool force_vertex_shading = false;
|
||||
bool specular_occlusion = false;
|
||||
|
|
|
@ -505,6 +505,126 @@ static inline Error _get_gl_uncompressed_format(const Ref<Image> &p_image, Image
|
|||
r_gl_format = GL_RGB;
|
||||
r_gl_type = GL_UNSIGNED_INT_5_9_9_9_REV;
|
||||
} break;
|
||||
case Image::FORMAT_R16: {
|
||||
if (config->unorm16_texture_supported) {
|
||||
r_gl_internal_format = _EXT_R16;
|
||||
r_gl_format = GL_RED;
|
||||
r_gl_type = GL_UNSIGNED_SHORT;
|
||||
} else {
|
||||
if (config->float_texture_linear_supported) {
|
||||
if (p_image.is_valid()) {
|
||||
p_image->convert(Image::FORMAT_RF);
|
||||
}
|
||||
r_real_format = Image::FORMAT_RF;
|
||||
r_gl_internal_format = GL_R32F;
|
||||
r_gl_format = GL_RED;
|
||||
r_gl_type = GL_FLOAT;
|
||||
} else {
|
||||
if (p_image.is_valid()) {
|
||||
p_image->convert(Image::FORMAT_RH);
|
||||
}
|
||||
r_real_format = Image::FORMAT_RH;
|
||||
r_gl_internal_format = GL_R16F;
|
||||
r_gl_format = GL_RED;
|
||||
r_gl_type = GL_HALF_FLOAT;
|
||||
}
|
||||
}
|
||||
} break;
|
||||
case Image::FORMAT_RG16: {
|
||||
if (config->unorm16_texture_supported) {
|
||||
r_gl_internal_format = _EXT_RG16;
|
||||
r_gl_format = GL_RG;
|
||||
r_gl_type = GL_UNSIGNED_SHORT;
|
||||
} else {
|
||||
if (config->float_texture_linear_supported) {
|
||||
if (p_image.is_valid()) {
|
||||
p_image->convert(Image::FORMAT_RGF);
|
||||
}
|
||||
r_real_format = Image::FORMAT_RGF;
|
||||
r_gl_internal_format = GL_RG32F;
|
||||
r_gl_format = GL_RG;
|
||||
r_gl_type = GL_FLOAT;
|
||||
} else {
|
||||
if (p_image.is_valid()) {
|
||||
p_image->convert(Image::FORMAT_RGH);
|
||||
}
|
||||
r_real_format = Image::FORMAT_RGH;
|
||||
r_gl_internal_format = GL_RG16F;
|
||||
r_gl_format = GL_RG;
|
||||
r_gl_type = GL_HALF_FLOAT;
|
||||
}
|
||||
}
|
||||
} break;
|
||||
case Image::FORMAT_RGB16: {
|
||||
if (config->unorm16_texture_supported) {
|
||||
r_gl_internal_format = _EXT_RGB16;
|
||||
r_gl_format = GL_RGB;
|
||||
r_gl_type = GL_UNSIGNED_SHORT;
|
||||
} else {
|
||||
if (config->float_texture_linear_supported) {
|
||||
if (p_image.is_valid()) {
|
||||
p_image->convert(Image::FORMAT_RGBF);
|
||||
}
|
||||
r_real_format = Image::FORMAT_RGBF;
|
||||
r_gl_internal_format = GL_RGB32F;
|
||||
r_gl_format = GL_RGB;
|
||||
r_gl_type = GL_FLOAT;
|
||||
} else {
|
||||
if (p_image.is_valid()) {
|
||||
p_image->convert(Image::FORMAT_RGBH);
|
||||
}
|
||||
r_real_format = Image::FORMAT_RGBH;
|
||||
r_gl_internal_format = GL_RGB16F;
|
||||
r_gl_format = GL_RGB;
|
||||
r_gl_type = GL_HALF_FLOAT;
|
||||
}
|
||||
}
|
||||
} break;
|
||||
case Image::FORMAT_RGBA16: {
|
||||
if (config->unorm16_texture_supported) {
|
||||
r_gl_internal_format = _EXT_RGBA16;
|
||||
r_gl_format = GL_RGBA;
|
||||
r_gl_type = GL_UNSIGNED_SHORT;
|
||||
} else {
|
||||
if (config->float_texture_linear_supported) {
|
||||
if (p_image.is_valid()) {
|
||||
p_image->convert(Image::FORMAT_RGBAF);
|
||||
}
|
||||
r_real_format = Image::FORMAT_RGBAF;
|
||||
r_gl_internal_format = GL_RGBA32F;
|
||||
r_gl_format = GL_RGBA;
|
||||
r_gl_type = GL_FLOAT;
|
||||
} else {
|
||||
if (p_image.is_valid()) {
|
||||
p_image->convert(Image::FORMAT_RGH);
|
||||
}
|
||||
r_real_format = Image::FORMAT_RGH;
|
||||
r_gl_internal_format = GL_RGBA16F;
|
||||
r_gl_format = GL_RGBA;
|
||||
r_gl_type = GL_HALF_FLOAT;
|
||||
}
|
||||
}
|
||||
} break;
|
||||
case Image::FORMAT_R16I: {
|
||||
r_gl_internal_format = GL_R16UI;
|
||||
r_gl_format = GL_RED_INTEGER;
|
||||
r_gl_type = GL_UNSIGNED_SHORT;
|
||||
} break;
|
||||
case Image::FORMAT_RG16I: {
|
||||
r_gl_internal_format = GL_RG16UI;
|
||||
r_gl_format = GL_RG_INTEGER;
|
||||
r_gl_type = GL_UNSIGNED_SHORT;
|
||||
} break;
|
||||
case Image::FORMAT_RGB16I: {
|
||||
r_gl_internal_format = GL_RGB16UI;
|
||||
r_gl_format = GL_RGB_INTEGER;
|
||||
r_gl_type = GL_UNSIGNED_SHORT;
|
||||
} break;
|
||||
case Image::FORMAT_RGBA16I: {
|
||||
r_gl_internal_format = GL_RGBA16UI;
|
||||
r_gl_format = GL_RGBA_INTEGER;
|
||||
r_gl_type = GL_UNSIGNED_SHORT;
|
||||
} break;
|
||||
default: {
|
||||
return ERR_UNAVAILABLE;
|
||||
}
|
||||
|
|
|
@ -112,6 +112,11 @@ namespace GLES3 {
|
|||
|
||||
#define _EXT_TEXTURE_CUBE_MAP_SEAMLESS 0x884F
|
||||
|
||||
#define _EXT_R16 0x822A
|
||||
#define _EXT_RG16 0x822C
|
||||
#define _EXT_RGB16 0x8054
|
||||
#define _EXT_RGBA16 0x805B
|
||||
|
||||
enum DefaultGLTexture {
|
||||
DEFAULT_GL_TEXTURE_WHITE,
|
||||
DEFAULT_GL_TEXTURE_BLACK,
|
||||
|
|
|
@ -351,6 +351,40 @@ static Error get_src_texture_format(Image *r_img, RD::DataFormat &r_format) {
|
|||
r_format = RD::DATA_FORMAT_E5B9G9R9_UFLOAT_PACK32;
|
||||
break;
|
||||
|
||||
case Image::FORMAT_R16:
|
||||
r_format = RD::DATA_FORMAT_R16_UNORM;
|
||||
break;
|
||||
|
||||
case Image::FORMAT_RG16:
|
||||
r_format = RD::DATA_FORMAT_R16G16_UNORM;
|
||||
break;
|
||||
|
||||
case Image::FORMAT_RGB16:
|
||||
r_img->convert(Image::FORMAT_RGBA16);
|
||||
r_format = RD::DATA_FORMAT_R16G16B16A16_UNORM;
|
||||
break;
|
||||
|
||||
case Image::FORMAT_RGBA16:
|
||||
r_format = RD::DATA_FORMAT_R16G16B16A16_UNORM;
|
||||
break;
|
||||
|
||||
case Image::FORMAT_R16I:
|
||||
r_format = RD::DATA_FORMAT_R16_UINT;
|
||||
break;
|
||||
|
||||
case Image::FORMAT_RG16I:
|
||||
r_format = RD::DATA_FORMAT_R16G16_UINT;
|
||||
break;
|
||||
|
||||
case Image::FORMAT_RGB16I:
|
||||
r_img->convert(Image::FORMAT_RGBA16I);
|
||||
r_format = RD::DATA_FORMAT_R16G16B16A16_UINT;
|
||||
break;
|
||||
|
||||
case Image::FORMAT_RGBA16I:
|
||||
r_format = RD::DATA_FORMAT_R16G16B16A16_UINT;
|
||||
break;
|
||||
|
||||
default: {
|
||||
return ERR_UNAVAILABLE;
|
||||
}
|
||||
|
|
|
@ -74,6 +74,7 @@ enum DDSFourCC {
|
|||
DDFCC_BC5U = PF_FOURCC("BC5U"),
|
||||
DDFCC_A2XY = PF_FOURCC("A2XY"),
|
||||
DDFCC_DX10 = PF_FOURCC("DX10"),
|
||||
DDFCC_RGBA16 = 36,
|
||||
DDFCC_R16F = 111,
|
||||
DDFCC_RG16F = 112,
|
||||
DDFCC_RGBA16F = 113,
|
||||
|
@ -87,14 +88,20 @@ enum DXGIFormat {
|
|||
DXGI_R32G32B32A32_FLOAT = 2,
|
||||
DXGI_R32G32B32_FLOAT = 6,
|
||||
DXGI_R16G16B16A16_FLOAT = 10,
|
||||
DXGI_R16G16B16A16_UNORM = 11,
|
||||
DXGI_R16G16B16A16_UINT = 12,
|
||||
DXGI_R32G32_FLOAT = 16,
|
||||
DXGI_R10G10B10A2_UNORM = 24,
|
||||
DXGI_R8G8B8A8_UNORM = 28,
|
||||
DXGI_R8G8B8A8_UNORM_SRGB = 29,
|
||||
DXGI_R16G16_FLOAT = 34,
|
||||
DXGI_R16G16_UNORM = 35,
|
||||
DXGI_R16G16_UINT = 36,
|
||||
DXGI_R32_FLOAT = 41,
|
||||
DXGI_R8G8_UNORM = 49,
|
||||
DXGI_R16_FLOAT = 54,
|
||||
DXGI_R16_UNORM = 56,
|
||||
DXGI_R16_UINT = 57,
|
||||
DXGI_R8_UNORM = 61,
|
||||
DXGI_A8_UNORM = 65,
|
||||
DXGI_R9G9B9E5 = 67,
|
||||
|
@ -127,6 +134,12 @@ enum DDSFormat {
|
|||
DDS_BC6U,
|
||||
DDS_BC6S,
|
||||
DDS_BC7,
|
||||
DDS_R16,
|
||||
DDS_RG16,
|
||||
DDS_RGBA16,
|
||||
DDS_R16I,
|
||||
DDS_RG16I,
|
||||
DDS_RGBA16I,
|
||||
DDS_R16F,
|
||||
DDS_RG16F,
|
||||
DDS_RGBA16F,
|
||||
|
@ -180,6 +193,12 @@ static const DDSFormatInfo dds_format_info[DDS_MAX] = {
|
|||
{ "BC6UF", true, 4, 16, Image::FORMAT_BPTC_RGBFU },
|
||||
{ "BC6SF", true, 4, 16, Image::FORMAT_BPTC_RGBF },
|
||||
{ "BC7", true, 4, 16, Image::FORMAT_BPTC_RGBA },
|
||||
{ "R16", false, 1, 2, Image::FORMAT_R16 },
|
||||
{ "RG16", false, 1, 4, Image::FORMAT_RG16 },
|
||||
{ "RGBA16", false, 1, 8, Image::FORMAT_RGBA16 },
|
||||
{ "R16I", false, 1, 2, Image::FORMAT_R16I },
|
||||
{ "RG16I", false, 1, 4, Image::FORMAT_RG16I },
|
||||
{ "RGBA16I", false, 1, 8, Image::FORMAT_RGBA16I },
|
||||
{ "R16F", false, 1, 2, Image::FORMAT_RH },
|
||||
{ "RG16F", false, 1, 4, Image::FORMAT_RGH },
|
||||
{ "RGBA16F", false, 1, 8, Image::FORMAT_RGBAH },
|
||||
|
|
|
@ -67,6 +67,7 @@ DDSFormatType _dds_format_get_type(DDSFormat p_format) {
|
|||
case DDS_R32F:
|
||||
case DDS_RG32F:
|
||||
case DDS_RGBA32F:
|
||||
case DDS_RGBA16:
|
||||
return DDFT_FOURCC;
|
||||
|
||||
case DDS_BC6S:
|
||||
|
@ -74,6 +75,9 @@ DDSFormatType _dds_format_get_type(DDSFormat p_format) {
|
|||
case DDS_BC7:
|
||||
case DDS_RGB9E5:
|
||||
case DDS_RGB32F:
|
||||
case DDS_R16I:
|
||||
case DDS_RG16I:
|
||||
case DDS_RGBA16I:
|
||||
return DDFT_DXGI;
|
||||
|
||||
default:
|
||||
|
@ -151,6 +155,24 @@ DDSFormat _image_format_to_dds_format(Image::Format p_image_format) {
|
|||
case Image::FORMAT_BPTC_RGBA: {
|
||||
return DDS_BC7;
|
||||
}
|
||||
case Image::FORMAT_R16: {
|
||||
return DDS_R16;
|
||||
}
|
||||
case Image::FORMAT_RG16: {
|
||||
return DDS_RG16;
|
||||
}
|
||||
case Image::FORMAT_RGBA16: {
|
||||
return DDS_RGBA16;
|
||||
}
|
||||
case Image::FORMAT_R16I: {
|
||||
return DDS_R16I;
|
||||
}
|
||||
case Image::FORMAT_RG16I: {
|
||||
return DDS_RG16I;
|
||||
}
|
||||
case Image::FORMAT_RGBA16I: {
|
||||
return DDS_RGBA16I;
|
||||
}
|
||||
default: {
|
||||
return DDS_MAX;
|
||||
}
|
||||
|
@ -181,6 +203,8 @@ uint32_t _image_format_to_fourcc_format(Image::Format p_format) {
|
|||
return DDFCC_RG16F;
|
||||
case Image::FORMAT_RGBAH:
|
||||
return DDFCC_RGBA16F;
|
||||
case Image::FORMAT_RGBA16:
|
||||
return DDFCC_RGBA16;
|
||||
|
||||
default:
|
||||
return 0;
|
||||
|
@ -221,6 +245,18 @@ uint32_t _image_format_to_dxgi_format(Image::Format p_format) {
|
|||
return DXGI_R16G16B16A16_FLOAT;
|
||||
case Image::FORMAT_RGBE9995:
|
||||
return DXGI_R9G9B9E5;
|
||||
case Image::FORMAT_R16:
|
||||
return DXGI_R16_UNORM;
|
||||
case Image::FORMAT_RG16:
|
||||
return DXGI_R16G16_UNORM;
|
||||
case Image::FORMAT_RGBA16:
|
||||
return DXGI_R16G16B16A16_UNORM;
|
||||
case Image::FORMAT_R16I:
|
||||
return DXGI_R16_UINT;
|
||||
case Image::FORMAT_RG16I:
|
||||
return DXGI_R16G16_UINT;
|
||||
case Image::FORMAT_RGBA16I:
|
||||
return DXGI_R16G16B16A16_UINT;
|
||||
|
||||
default:
|
||||
return 0;
|
||||
|
@ -276,6 +312,20 @@ void _get_dds_pixel_bitmask(Image::Format p_format, uint32_t &r_bit_count, uint3
|
|||
r_blue_mask = 0x1f;
|
||||
r_alpha_mask = 0;
|
||||
} break;
|
||||
case Image::FORMAT_R16: {
|
||||
r_bit_count = 16;
|
||||
r_red_mask = 0xffff;
|
||||
r_green_mask = 0;
|
||||
r_blue_mask = 0;
|
||||
r_alpha_mask = 0;
|
||||
} break;
|
||||
case Image::FORMAT_RG16: {
|
||||
r_bit_count = 32;
|
||||
r_red_mask = 0xffff;
|
||||
r_green_mask = 0xffff0000;
|
||||
r_blue_mask = 0;
|
||||
r_alpha_mask = 0;
|
||||
} break;
|
||||
|
||||
default: {
|
||||
r_bit_count = 0;
|
||||
|
|
|
@ -47,6 +47,12 @@ DDSFormat _dxgi_to_dds_format(uint32_t p_dxgi_format) {
|
|||
case DXGI_R16G16B16A16_FLOAT: {
|
||||
return DDS_RGBA16F;
|
||||
}
|
||||
case DXGI_R16G16B16A16_UNORM: {
|
||||
return DDS_RGBA16;
|
||||
}
|
||||
case DXGI_R16G16B16A16_UINT: {
|
||||
return DDS_RGBA16I;
|
||||
}
|
||||
case DXGI_R32G32_FLOAT: {
|
||||
return DDS_RG32F;
|
||||
}
|
||||
|
@ -60,6 +66,12 @@ DDSFormat _dxgi_to_dds_format(uint32_t p_dxgi_format) {
|
|||
case DXGI_R16G16_FLOAT: {
|
||||
return DDS_RG16F;
|
||||
}
|
||||
case DXGI_R16G16_UNORM: {
|
||||
return DDS_RG16;
|
||||
}
|
||||
case DXGI_R16G16_UINT: {
|
||||
return DDS_RG16I;
|
||||
}
|
||||
case DXGI_R32_FLOAT: {
|
||||
return DDS_R32F;
|
||||
}
|
||||
|
@ -70,6 +82,12 @@ DDSFormat _dxgi_to_dds_format(uint32_t p_dxgi_format) {
|
|||
case DXGI_R16_FLOAT: {
|
||||
return DDS_R16F;
|
||||
}
|
||||
case DXGI_R16_UNORM: {
|
||||
return DDS_R16;
|
||||
}
|
||||
case DXGI_R16_UINT: {
|
||||
return DDS_R16I;
|
||||
}
|
||||
case DXGI_R8G8_UNORM: {
|
||||
return DDS_LUMINANCE_ALPHA;
|
||||
}
|
||||
|
@ -550,6 +568,9 @@ static Vector<Ref<Image>> _dds_load_images_from_buffer(Ref<FileAccess> p_f, DDSF
|
|||
case DDFCC_A2XY: {
|
||||
r_dds_format = DDS_ATI2;
|
||||
} break;
|
||||
case DDFCC_RGBA16: {
|
||||
r_dds_format = DDS_RGBA16;
|
||||
} break;
|
||||
case DDFCC_R16F: {
|
||||
r_dds_format = DDS_R16F;
|
||||
} break;
|
||||
|
@ -630,6 +651,10 @@ static Vector<Ref<Image>> _dds_load_images_from_buffer(Ref<FileAccess> p_f, DDSF
|
|||
}
|
||||
}
|
||||
|
||||
if (format_rgb_bits == 32 && format_red_mask == 0xffff && format_green_mask == 0xffff0000) {
|
||||
r_dds_format = DDS_RG16;
|
||||
}
|
||||
|
||||
} else {
|
||||
// Other formats.
|
||||
if (format_flags & DDPF_ALPHAONLY && format_rgb_bits == 8 && format_alpha_mask == 0xff) {
|
||||
|
@ -653,6 +678,8 @@ static Vector<Ref<Image>> _dds_load_images_from_buffer(Ref<FileAccess> p_f, DDSF
|
|||
// Without alpha.
|
||||
if (format_rgb_bits == 8 && format_red_mask == 0xff) {
|
||||
r_dds_format = DDS_LUMINANCE;
|
||||
} else if (format_rgb_bits == 16 && format_red_mask == 0xffff) {
|
||||
r_dds_format = DDS_R16;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -186,6 +186,30 @@ static Ref<Image> load_from_file_access(Ref<FileAccess> f, Error *r_error) {
|
|||
case GL_RGB9_E5:
|
||||
format = Image::FORMAT_RGBE9995;
|
||||
break;
|
||||
case GL_R16:
|
||||
format = Image::FORMAT_R16;
|
||||
break;
|
||||
case GL_RG16:
|
||||
format = Image::FORMAT_RG16;
|
||||
break;
|
||||
case GL_RGB16:
|
||||
format = Image::FORMAT_RGB16;
|
||||
break;
|
||||
case GL_RGBA16:
|
||||
format = Image::FORMAT_RGBA16;
|
||||
break;
|
||||
case GL_R16UI:
|
||||
format = Image::FORMAT_R16I;
|
||||
break;
|
||||
case GL_RG16UI:
|
||||
format = Image::FORMAT_RG16I;
|
||||
break;
|
||||
case GL_RGB16UI:
|
||||
format = Image::FORMAT_RGB16I;
|
||||
break;
|
||||
case GL_RGBA16UI:
|
||||
format = Image::FORMAT_RGBA16I;
|
||||
break;
|
||||
case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
|
||||
case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
|
||||
format = Image::FORMAT_DXT1;
|
||||
|
@ -382,6 +406,30 @@ static Ref<Image> load_from_file_access(Ref<FileAccess> f, Error *r_error) {
|
|||
case VK_FORMAT_E5B9G9R9_UFLOAT_PACK32:
|
||||
format = Image::FORMAT_RGBE9995;
|
||||
break;
|
||||
case VK_FORMAT_R16_UNORM:
|
||||
format = Image::FORMAT_R16;
|
||||
break;
|
||||
case VK_FORMAT_R16G16_UNORM:
|
||||
format = Image::FORMAT_RG16;
|
||||
break;
|
||||
case VK_FORMAT_R16G16B16_UNORM:
|
||||
format = Image::FORMAT_RGB16;
|
||||
break;
|
||||
case VK_FORMAT_R16G16B16A16_UNORM:
|
||||
format = Image::FORMAT_RGBA16;
|
||||
break;
|
||||
case VK_FORMAT_R16_UINT:
|
||||
format = Image::FORMAT_R16I;
|
||||
break;
|
||||
case VK_FORMAT_R16G16_UINT:
|
||||
format = Image::FORMAT_RG16I;
|
||||
break;
|
||||
case VK_FORMAT_R16G16B16_UINT:
|
||||
format = Image::FORMAT_RGB16I;
|
||||
break;
|
||||
case VK_FORMAT_R16G16B16A16_UINT:
|
||||
format = Image::FORMAT_RGBA16I;
|
||||
break;
|
||||
case VK_FORMAT_BC1_RGB_UNORM_BLOCK:
|
||||
case VK_FORMAT_BC1_RGBA_UNORM_BLOCK:
|
||||
format = Image::FORMAT_DXT1;
|
||||
|
|
|
@ -2324,6 +2324,98 @@ Ref<Image> TextureStorage::_validate_texture_format(const Ref<Image> &p_image, T
|
|||
r_format.swizzle_a = RD::TEXTURE_SWIZZLE_A;
|
||||
|
||||
} break; // astc 8x8 HDR
|
||||
case Image::FORMAT_R16: {
|
||||
if (RD::get_singleton()->texture_is_format_supported_for_usage(RD::DATA_FORMAT_R16_UNORM, RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_CAN_UPDATE_BIT)) {
|
||||
r_format.format = RD::DATA_FORMAT_R16_UNORM;
|
||||
} else {
|
||||
// Not supported, reconvert.
|
||||
r_format.format = RD::DATA_FORMAT_R32_SFLOAT;
|
||||
image->convert(Image::FORMAT_RF);
|
||||
}
|
||||
r_format.swizzle_r = RD::TEXTURE_SWIZZLE_R;
|
||||
r_format.swizzle_g = RD::TEXTURE_SWIZZLE_ZERO;
|
||||
r_format.swizzle_b = RD::TEXTURE_SWIZZLE_ZERO;
|
||||
r_format.swizzle_a = RD::TEXTURE_SWIZZLE_ONE;
|
||||
} break; // unorm16
|
||||
case Image::FORMAT_RG16: {
|
||||
if (RD::get_singleton()->texture_is_format_supported_for_usage(RD::DATA_FORMAT_R16G16_UNORM, RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_CAN_UPDATE_BIT)) {
|
||||
r_format.format = RD::DATA_FORMAT_R16G16_UNORM;
|
||||
} else {
|
||||
// Not supported, reconvert.
|
||||
r_format.format = RD::DATA_FORMAT_R32G32_SFLOAT;
|
||||
image->convert(Image::FORMAT_RGF);
|
||||
}
|
||||
r_format.swizzle_r = RD::TEXTURE_SWIZZLE_R;
|
||||
r_format.swizzle_g = RD::TEXTURE_SWIZZLE_G;
|
||||
r_format.swizzle_b = RD::TEXTURE_SWIZZLE_ZERO;
|
||||
r_format.swizzle_a = RD::TEXTURE_SWIZZLE_ONE;
|
||||
} break;
|
||||
case Image::FORMAT_RGB16: {
|
||||
if (RD::get_singleton()->texture_is_format_supported_for_usage(RD::DATA_FORMAT_R16G16B16_UNORM, RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_CAN_UPDATE_BIT)) {
|
||||
r_format.format = RD::DATA_FORMAT_R16G16B16_UNORM;
|
||||
} else {
|
||||
// Not supported, reconvert.
|
||||
if (RD::get_singleton()->texture_is_format_supported_for_usage(RD::DATA_FORMAT_R16G16B16A16_UNORM, RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_CAN_UPDATE_BIT)) {
|
||||
r_format.format = RD::DATA_FORMAT_R16G16B16A16_UNORM;
|
||||
image->convert(Image::FORMAT_RGBA16);
|
||||
} else {
|
||||
r_format.format = RD::DATA_FORMAT_R32G32B32A32_SFLOAT;
|
||||
image->convert(Image::FORMAT_RGBAF);
|
||||
}
|
||||
}
|
||||
r_format.swizzle_r = RD::TEXTURE_SWIZZLE_R;
|
||||
r_format.swizzle_g = RD::TEXTURE_SWIZZLE_G;
|
||||
r_format.swizzle_b = RD::TEXTURE_SWIZZLE_B;
|
||||
r_format.swizzle_a = RD::TEXTURE_SWIZZLE_ONE;
|
||||
} break;
|
||||
case Image::FORMAT_RGBA16: {
|
||||
if (RD::get_singleton()->texture_is_format_supported_for_usage(RD::DATA_FORMAT_R16G16B16A16_UNORM, RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_CAN_UPDATE_BIT)) {
|
||||
r_format.format = RD::DATA_FORMAT_R16G16B16A16_UNORM;
|
||||
} else {
|
||||
// Not supported, reconvert.
|
||||
r_format.format = RD::DATA_FORMAT_R32G32B32A32_SFLOAT;
|
||||
image->convert(Image::FORMAT_RGBAF);
|
||||
}
|
||||
r_format.swizzle_r = RD::TEXTURE_SWIZZLE_R;
|
||||
r_format.swizzle_g = RD::TEXTURE_SWIZZLE_G;
|
||||
r_format.swizzle_b = RD::TEXTURE_SWIZZLE_B;
|
||||
r_format.swizzle_a = RD::TEXTURE_SWIZZLE_A;
|
||||
} break;
|
||||
case Image::FORMAT_R16I: {
|
||||
r_format.format = RD::DATA_FORMAT_R16_UINT;
|
||||
r_format.swizzle_r = RD::TEXTURE_SWIZZLE_R;
|
||||
r_format.swizzle_g = RD::TEXTURE_SWIZZLE_ZERO;
|
||||
r_format.swizzle_b = RD::TEXTURE_SWIZZLE_ZERO;
|
||||
r_format.swizzle_a = RD::TEXTURE_SWIZZLE_ONE;
|
||||
} break; // uint16
|
||||
case Image::FORMAT_RG16I: {
|
||||
r_format.format = RD::DATA_FORMAT_R16G16_UINT;
|
||||
r_format.swizzle_r = RD::TEXTURE_SWIZZLE_R;
|
||||
r_format.swizzle_g = RD::TEXTURE_SWIZZLE_G;
|
||||
r_format.swizzle_b = RD::TEXTURE_SWIZZLE_ZERO;
|
||||
r_format.swizzle_a = RD::TEXTURE_SWIZZLE_ONE;
|
||||
} break;
|
||||
case Image::FORMAT_RGB16I: {
|
||||
//this format is not mandatory for specification, check if supported first
|
||||
if (RD::get_singleton()->texture_is_format_supported_for_usage(RD::DATA_FORMAT_R16G16B16_UINT, RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_CAN_UPDATE_BIT)) {
|
||||
r_format.format = RD::DATA_FORMAT_R16G16B16_UINT;
|
||||
} else {
|
||||
//not supported, reconvert
|
||||
r_format.format = RD::DATA_FORMAT_R16G16B16A16_UINT;
|
||||
image->convert(Image::FORMAT_RGBA16I);
|
||||
}
|
||||
r_format.swizzle_r = RD::TEXTURE_SWIZZLE_R;
|
||||
r_format.swizzle_g = RD::TEXTURE_SWIZZLE_G;
|
||||
r_format.swizzle_b = RD::TEXTURE_SWIZZLE_B;
|
||||
r_format.swizzle_a = RD::TEXTURE_SWIZZLE_ONE;
|
||||
} break;
|
||||
case Image::FORMAT_RGBA16I: {
|
||||
r_format.format = RD::DATA_FORMAT_R16G16B16A16_UINT;
|
||||
r_format.swizzle_r = RD::TEXTURE_SWIZZLE_R;
|
||||
r_format.swizzle_g = RD::TEXTURE_SWIZZLE_G;
|
||||
r_format.swizzle_b = RD::TEXTURE_SWIZZLE_B;
|
||||
r_format.swizzle_a = RD::TEXTURE_SWIZZLE_A;
|
||||
} break;
|
||||
|
||||
default: {
|
||||
}
|
||||
|
@ -2716,7 +2808,7 @@ void TextureStorage::_texture_format_from_rd(RD::DataFormat p_rd_format, Texture
|
|||
r_format.swizzle_a = RD::TEXTURE_SWIZZLE_A;
|
||||
} break; // astc 8x8
|
||||
case RD::DATA_FORMAT_D16_UNORM: {
|
||||
r_format.image_format = Image::FORMAT_RH;
|
||||
r_format.image_format = Image::FORMAT_R16;
|
||||
r_format.rd_format = RD::DATA_FORMAT_D16_UNORM;
|
||||
r_format.swizzle_r = RD::TEXTURE_SWIZZLE_R;
|
||||
r_format.swizzle_g = RD::TEXTURE_SWIZZLE_ZERO;
|
||||
|
@ -2731,6 +2823,70 @@ void TextureStorage::_texture_format_from_rd(RD::DataFormat p_rd_format, Texture
|
|||
r_format.swizzle_b = RD::TEXTURE_SWIZZLE_ZERO;
|
||||
r_format.swizzle_a = RD::TEXTURE_SWIZZLE_ONE;
|
||||
} break;
|
||||
case RD::DATA_FORMAT_R16_UNORM: {
|
||||
r_format.image_format = Image::FORMAT_R16;
|
||||
r_format.rd_format = RD::DATA_FORMAT_R16_UNORM;
|
||||
r_format.swizzle_r = RD::TEXTURE_SWIZZLE_R;
|
||||
r_format.swizzle_g = RD::TEXTURE_SWIZZLE_ZERO;
|
||||
r_format.swizzle_b = RD::TEXTURE_SWIZZLE_ZERO;
|
||||
r_format.swizzle_a = RD::TEXTURE_SWIZZLE_ONE;
|
||||
} break; // unorm16
|
||||
case RD::DATA_FORMAT_R16G16_UNORM: {
|
||||
r_format.image_format = Image::FORMAT_RG16;
|
||||
r_format.rd_format = RD::DATA_FORMAT_R16G16_UNORM;
|
||||
r_format.swizzle_r = RD::TEXTURE_SWIZZLE_R;
|
||||
r_format.swizzle_g = RD::TEXTURE_SWIZZLE_G;
|
||||
r_format.swizzle_b = RD::TEXTURE_SWIZZLE_ZERO;
|
||||
r_format.swizzle_a = RD::TEXTURE_SWIZZLE_ONE;
|
||||
} break;
|
||||
case RD::DATA_FORMAT_R16G16B16_UNORM: {
|
||||
r_format.image_format = Image::FORMAT_RGB16;
|
||||
r_format.rd_format = RD::DATA_FORMAT_R16G16B16_UNORM;
|
||||
r_format.swizzle_r = RD::TEXTURE_SWIZZLE_R;
|
||||
r_format.swizzle_g = RD::TEXTURE_SWIZZLE_G;
|
||||
r_format.swizzle_b = RD::TEXTURE_SWIZZLE_B;
|
||||
r_format.swizzle_a = RD::TEXTURE_SWIZZLE_ONE;
|
||||
} break;
|
||||
case RD::DATA_FORMAT_R16G16B16A16_UNORM: {
|
||||
r_format.image_format = Image::FORMAT_RGBA16;
|
||||
r_format.rd_format = RD::DATA_FORMAT_R16G16B16A16_UNORM;
|
||||
r_format.swizzle_r = RD::TEXTURE_SWIZZLE_R;
|
||||
r_format.swizzle_g = RD::TEXTURE_SWIZZLE_G;
|
||||
r_format.swizzle_b = RD::TEXTURE_SWIZZLE_B;
|
||||
r_format.swizzle_a = RD::TEXTURE_SWIZZLE_A;
|
||||
} break;
|
||||
case RD::DATA_FORMAT_R16_UINT: {
|
||||
r_format.image_format = Image::FORMAT_R16I;
|
||||
r_format.rd_format = RD::DATA_FORMAT_R16_UINT;
|
||||
r_format.swizzle_r = RD::TEXTURE_SWIZZLE_R;
|
||||
r_format.swizzle_g = RD::TEXTURE_SWIZZLE_ZERO;
|
||||
r_format.swizzle_b = RD::TEXTURE_SWIZZLE_ZERO;
|
||||
r_format.swizzle_a = RD::TEXTURE_SWIZZLE_ONE;
|
||||
} break; // uint16
|
||||
case RD::DATA_FORMAT_R16G16_UINT: {
|
||||
r_format.image_format = Image::FORMAT_RG16I;
|
||||
r_format.rd_format = RD::DATA_FORMAT_R16G16_UINT;
|
||||
r_format.swizzle_r = RD::TEXTURE_SWIZZLE_R;
|
||||
r_format.swizzle_g = RD::TEXTURE_SWIZZLE_G;
|
||||
r_format.swizzle_b = RD::TEXTURE_SWIZZLE_ZERO;
|
||||
r_format.swizzle_a = RD::TEXTURE_SWIZZLE_ONE;
|
||||
} break;
|
||||
case RD::DATA_FORMAT_R16G16B16_UINT: {
|
||||
r_format.image_format = Image::FORMAT_RGB16I;
|
||||
r_format.rd_format = RD::DATA_FORMAT_R16G16B16_UINT;
|
||||
r_format.swizzle_r = RD::TEXTURE_SWIZZLE_R;
|
||||
r_format.swizzle_g = RD::TEXTURE_SWIZZLE_G;
|
||||
r_format.swizzle_b = RD::TEXTURE_SWIZZLE_B;
|
||||
r_format.swizzle_a = RD::TEXTURE_SWIZZLE_ONE;
|
||||
} break;
|
||||
case RD::DATA_FORMAT_R16G16B16A16_UINT: {
|
||||
r_format.image_format = Image::FORMAT_RGBA16I;
|
||||
r_format.rd_format = RD::DATA_FORMAT_R16G16B16A16_UINT;
|
||||
r_format.swizzle_r = RD::TEXTURE_SWIZZLE_R;
|
||||
r_format.swizzle_g = RD::TEXTURE_SWIZZLE_G;
|
||||
r_format.swizzle_b = RD::TEXTURE_SWIZZLE_B;
|
||||
r_format.swizzle_a = RD::TEXTURE_SWIZZLE_A;
|
||||
} break;
|
||||
|
||||
default: {
|
||||
ERR_FAIL_MSG("Unsupported image format");
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue