Skip to content

Commit 16b9ee6

Browse files
committed
Image: Implement 16-bit unorm and uint formats
1 parent ebc36a7 commit 16b9ee6

File tree

13 files changed

+918
-67
lines changed

13 files changed

+918
-67
lines changed

core/io/image.cpp

Lines changed: 408 additions & 65 deletions
Large diffs are not rendered by default.

core/io/image.h

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -111,6 +111,14 @@ class Image : public Resource {
111111
FORMAT_ASTC_4x4_HDR,
112112
FORMAT_ASTC_8x8,
113113
FORMAT_ASTC_8x8_HDR,
114+
FORMAT_R16,
115+
FORMAT_RG16,
116+
FORMAT_RGB16,
117+
FORMAT_RGBA16,
118+
FORMAT_R16I,
119+
FORMAT_RG16I,
120+
FORMAT_RGB16I,
121+
FORMAT_RGBA16I,
114122
FORMAT_MAX
115123
};
116124

@@ -282,10 +290,12 @@ class Image : public Resource {
282290
static void average_4_float(float &p_out, const float &p_a, const float &p_b, const float &p_c, const float &p_d);
283291
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);
284292
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);
293+
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);
285294
static void renormalize_uint8(uint8_t *p_rgb);
286295
static void renormalize_float(float *p_rgb);
287296
static void renormalize_half(uint16_t *p_rgb);
288297
static void renormalize_rgbe9995(uint32_t *p_rgb);
298+
static void renormalize_uint16(uint16_t *p_rgb);
289299

290300
public:
291301
int get_width() const;

doc/classes/Image.xml

Lines changed: 37 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -760,7 +760,43 @@
760760
<constant name="FORMAT_ASTC_8x8_HDR" value="38" enum="Format">
761761
Same format as [constant FORMAT_ASTC_8x8], but with the hint to let the GPU know it is used for HDR.
762762
</constant>
763-
<constant name="FORMAT_MAX" value="39" enum="Format">
763+
<constant name="FORMAT_R16" value="39" enum="Format">
764+
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).
765+
[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].
766+
</constant>
767+
<constant name="FORMAT_RG16" value="40" enum="Format">
768+
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).
769+
[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].
770+
</constant>
771+
<constant name="FORMAT_RGB16" value="41" enum="Format">
772+
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).
773+
[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].
774+
</constant>
775+
<constant name="FORMAT_RGBA16" value="42" enum="Format">
776+
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).
777+
[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].
778+
</constant>
779+
<constant name="FORMAT_R16I" value="43" enum="Format">
780+
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).
781+
[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.
782+
[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.
783+
</constant>
784+
<constant name="FORMAT_RG16I" value="44" enum="Format">
785+
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).
786+
[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.
787+
[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.
788+
</constant>
789+
<constant name="FORMAT_RGB16I" value="45" enum="Format">
790+
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).
791+
[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.
792+
[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.
793+
</constant>
794+
<constant name="FORMAT_RGBA16I" value="46" enum="Format">
795+
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).
796+
[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.
797+
[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.
798+
</constant>
799+
<constant name="FORMAT_MAX" value="47" enum="Format">
764800
Represents the size of the [enum Format] enum.
765801
</constant>
766802
<constant name="INTERPOLATE_NEAREST" value="0" enum="Interpolation">

drivers/gles3/storage/config.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -89,6 +89,7 @@ Config::Config() {
8989
s3tc_supported = true;
9090
rgtc_supported = true; //RGTC - core since OpenGL version 3.0
9191
srgb_framebuffer_supported = true;
92+
unorm16_texture_supported = true;
9293
} else {
9394
float_texture_supported = extensions.has("GL_EXT_color_buffer_float");
9495
float_texture_linear_supported = extensions.has("GL_OES_texture_float_linear");
@@ -103,6 +104,7 @@ Config::Config() {
103104
#endif
104105
rgtc_supported = extensions.has("GL_EXT_texture_compression_rgtc") || extensions.has("GL_ARB_texture_compression_rgtc");
105106
srgb_framebuffer_supported = extensions.has("GL_EXT_sRGB_write_control");
107+
unorm16_texture_supported = extensions.has("GL_EXT_texture_norm16");
106108
}
107109

108110
glGetIntegerv(GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS, &max_vertex_texture_image_units);

drivers/gles3/storage/config.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -81,6 +81,7 @@ class Config {
8181
bool astc_hdr_supported = false;
8282
bool astc_layered_supported = false;
8383
bool srgb_framebuffer_supported = false;
84+
bool unorm16_texture_supported = false;
8485

8586
bool force_vertex_shading = false;
8687
bool specular_occlusion = false;

drivers/gles3/storage/texture_storage.cpp

Lines changed: 120 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -475,6 +475,126 @@ static inline Error _get_gl_uncompressed_format(const Ref<Image> &p_image, Image
475475
r_gl_format = GL_RGB;
476476
r_gl_type = GL_UNSIGNED_INT_5_9_9_9_REV;
477477
} break;
478+
case Image::FORMAT_R16: {
479+
if (config->unorm16_texture_supported) {
480+
r_gl_internal_format = _EXT_R16;
481+
r_gl_format = GL_RED;
482+
r_gl_type = GL_UNSIGNED_SHORT;
483+
} else {
484+
if (config->float_texture_linear_supported) {
485+
if (p_image.is_valid()) {
486+
p_image->convert(Image::FORMAT_RF);
487+
}
488+
r_real_format = Image::FORMAT_RF;
489+
r_gl_internal_format = GL_R32F;
490+
r_gl_format = GL_RED;
491+
r_gl_type = GL_FLOAT;
492+
} else {
493+
if (p_image.is_valid()) {
494+
p_image->convert(Image::FORMAT_RH);
495+
}
496+
r_real_format = Image::FORMAT_RH;
497+
r_gl_internal_format = GL_R16F;
498+
r_gl_format = GL_RED;
499+
r_gl_type = GL_HALF_FLOAT;
500+
}
501+
}
502+
} break;
503+
case Image::FORMAT_RG16: {
504+
if (config->unorm16_texture_supported) {
505+
r_gl_internal_format = _EXT_RG16;
506+
r_gl_format = GL_RG;
507+
r_gl_type = GL_UNSIGNED_SHORT;
508+
} else {
509+
if (config->float_texture_linear_supported) {
510+
if (p_image.is_valid()) {
511+
p_image->convert(Image::FORMAT_RGF);
512+
}
513+
r_real_format = Image::FORMAT_RGF;
514+
r_gl_internal_format = GL_RG32F;
515+
r_gl_format = GL_RG;
516+
r_gl_type = GL_FLOAT;
517+
} else {
518+
if (p_image.is_valid()) {
519+
p_image->convert(Image::FORMAT_RGH);
520+
}
521+
r_real_format = Image::FORMAT_RGH;
522+
r_gl_internal_format = GL_RG16F;
523+
r_gl_format = GL_RG;
524+
r_gl_type = GL_HALF_FLOAT;
525+
}
526+
}
527+
} break;
528+
case Image::FORMAT_RGB16: {
529+
if (config->unorm16_texture_supported) {
530+
r_gl_internal_format = _EXT_RGB16;
531+
r_gl_format = GL_RGB;
532+
r_gl_type = GL_UNSIGNED_SHORT;
533+
} else {
534+
if (config->float_texture_linear_supported) {
535+
if (p_image.is_valid()) {
536+
p_image->convert(Image::FORMAT_RGBF);
537+
}
538+
r_real_format = Image::FORMAT_RGBF;
539+
r_gl_internal_format = GL_RGB32F;
540+
r_gl_format = GL_RGB;
541+
r_gl_type = GL_FLOAT;
542+
} else {
543+
if (p_image.is_valid()) {
544+
p_image->convert(Image::FORMAT_RGBH);
545+
}
546+
r_real_format = Image::FORMAT_RGBH;
547+
r_gl_internal_format = GL_RGB16F;
548+
r_gl_format = GL_RGB;
549+
r_gl_type = GL_HALF_FLOAT;
550+
}
551+
}
552+
} break;
553+
case Image::FORMAT_RGBA16: {
554+
if (config->unorm16_texture_supported) {
555+
r_gl_internal_format = _EXT_RGBA16;
556+
r_gl_format = GL_RGBA;
557+
r_gl_type = GL_UNSIGNED_SHORT;
558+
} else {
559+
if (config->float_texture_linear_supported) {
560+
if (p_image.is_valid()) {
561+
p_image->convert(Image::FORMAT_RGBAF);
562+
}
563+
r_real_format = Image::FORMAT_RGBAF;
564+
r_gl_internal_format = GL_RGBA32F;
565+
r_gl_format = GL_RGBA;
566+
r_gl_type = GL_FLOAT;
567+
} else {
568+
if (p_image.is_valid()) {
569+
p_image->convert(Image::FORMAT_RGH);
570+
}
571+
r_real_format = Image::FORMAT_RGH;
572+
r_gl_internal_format = GL_RGBA16F;
573+
r_gl_format = GL_RGBA;
574+
r_gl_type = GL_HALF_FLOAT;
575+
}
576+
}
577+
} break;
578+
case Image::FORMAT_R16I: {
579+
r_gl_internal_format = GL_R16UI;
580+
r_gl_format = GL_RED_INTEGER;
581+
r_gl_type = GL_UNSIGNED_SHORT;
582+
} break;
583+
case Image::FORMAT_RG16I: {
584+
r_gl_internal_format = GL_RG16UI;
585+
r_gl_format = GL_RG_INTEGER;
586+
r_gl_type = GL_UNSIGNED_SHORT;
587+
} break;
588+
case Image::FORMAT_RGB16I: {
589+
r_gl_internal_format = GL_RGB16UI;
590+
r_gl_format = GL_RGB_INTEGER;
591+
r_gl_type = GL_UNSIGNED_SHORT;
592+
} break;
593+
case Image::FORMAT_RGBA16I: {
594+
r_gl_internal_format = GL_RGBA16UI;
595+
r_gl_format = GL_RGBA_INTEGER;
596+
r_gl_type = GL_UNSIGNED_SHORT;
597+
} break;
478598
default: {
479599
return ERR_UNAVAILABLE;
480600
}

drivers/gles3/storage/texture_storage.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -112,6 +112,11 @@ namespace GLES3 {
112112

113113
#define _EXT_TEXTURE_CUBE_MAP_SEAMLESS 0x884F
114114

115+
#define _EXT_R16 0x822A
116+
#define _EXT_RG16 0x822C
117+
#define _EXT_RGB16 0x8054
118+
#define _EXT_RGBA16 0x805B
119+
115120
enum DefaultGLTexture {
116121
DEFAULT_GL_TEXTURE_WHITE,
117122
DEFAULT_GL_TEXTURE_BLACK,

modules/betsy/image_compress_betsy.cpp

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -351,6 +351,40 @@ static Error get_src_texture_format(Image *r_img, RD::DataFormat &r_format) {
351351
r_format = RD::DATA_FORMAT_E5B9G9R9_UFLOAT_PACK32;
352352
break;
353353

354+
case Image::FORMAT_R16:
355+
r_format = RD::DATA_FORMAT_R16_UNORM;
356+
break;
357+
358+
case Image::FORMAT_RG16:
359+
r_format = RD::DATA_FORMAT_R16G16_UNORM;
360+
break;
361+
362+
case Image::FORMAT_RGB16:
363+
r_img->convert(Image::FORMAT_RGBA16);
364+
r_format = RD::DATA_FORMAT_R16G16B16A16_UNORM;
365+
break;
366+
367+
case Image::FORMAT_RGBA16:
368+
r_format = RD::DATA_FORMAT_R16G16B16A16_UNORM;
369+
break;
370+
371+
case Image::FORMAT_R16I:
372+
r_format = RD::DATA_FORMAT_R16_UINT;
373+
break;
374+
375+
case Image::FORMAT_RG16I:
376+
r_format = RD::DATA_FORMAT_R16G16_UINT;
377+
break;
378+
379+
case Image::FORMAT_RGB16I:
380+
r_img->convert(Image::FORMAT_RGBA16I);
381+
r_format = RD::DATA_FORMAT_R16G16B16A16_UINT;
382+
break;
383+
384+
case Image::FORMAT_RGBA16I:
385+
r_format = RD::DATA_FORMAT_R16G16B16A16_UINT;
386+
break;
387+
354388
default: {
355389
return ERR_UNAVAILABLE;
356390
}

modules/dds/dds_enums.h

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,7 @@ enum DDSFourCC {
7474
DDFCC_BC5U = PF_FOURCC("BC5U"),
7575
DDFCC_A2XY = PF_FOURCC("A2XY"),
7676
DDFCC_DX10 = PF_FOURCC("DX10"),
77+
DDFCC_RGBA16 = 36,
7778
DDFCC_R16F = 111,
7879
DDFCC_RG16F = 112,
7980
DDFCC_RGBA16F = 113,
@@ -87,14 +88,20 @@ enum DXGIFormat {
8788
DXGI_R32G32B32A32_FLOAT = 2,
8889
DXGI_R32G32B32_FLOAT = 6,
8990
DXGI_R16G16B16A16_FLOAT = 10,
91+
DXGI_R16G16B16A16_UNORM = 11,
92+
DXGI_R16G16B16A16_UINT = 12,
9093
DXGI_R32G32_FLOAT = 16,
9194
DXGI_R10G10B10A2_UNORM = 24,
9295
DXGI_R8G8B8A8_UNORM = 28,
9396
DXGI_R8G8B8A8_UNORM_SRGB = 29,
9497
DXGI_R16G16_FLOAT = 34,
98+
DXGI_R16G16_UNORM = 35,
99+
DXGI_R16G16_UINT = 36,
95100
DXGI_R32_FLOAT = 41,
96101
DXGI_R8G8_UNORM = 49,
97102
DXGI_R16_FLOAT = 54,
103+
DXGI_R16_UNORM = 56,
104+
DXGI_R16_UINT = 57,
98105
DXGI_R8_UNORM = 61,
99106
DXGI_A8_UNORM = 65,
100107
DXGI_R9G9B9E5 = 67,
@@ -127,6 +134,12 @@ enum DDSFormat {
127134
DDS_BC6U,
128135
DDS_BC6S,
129136
DDS_BC7,
137+
DDS_R16,
138+
DDS_RG16,
139+
DDS_RGBA16,
140+
DDS_R16I,
141+
DDS_RG16I,
142+
DDS_RGBA16I,
130143
DDS_R16F,
131144
DDS_RG16F,
132145
DDS_RGBA16F,
@@ -180,6 +193,12 @@ static const DDSFormatInfo dds_format_info[DDS_MAX] = {
180193
{ "BC6UF", true, 4, 16, Image::FORMAT_BPTC_RGBFU },
181194
{ "BC6SF", true, 4, 16, Image::FORMAT_BPTC_RGBF },
182195
{ "BC7", true, 4, 16, Image::FORMAT_BPTC_RGBA },
196+
{ "R16", false, 1, 2, Image::FORMAT_R16 },
197+
{ "RG16", false, 1, 4, Image::FORMAT_RG16 },
198+
{ "RGBA16", false, 1, 8, Image::FORMAT_RGBA16 },
199+
{ "R16I", false, 1, 2, Image::FORMAT_R16I },
200+
{ "RG16I", false, 1, 4, Image::FORMAT_RG16I },
201+
{ "RGBA16I", false, 1, 8, Image::FORMAT_RGBA16I },
183202
{ "R16F", false, 1, 2, Image::FORMAT_RH },
184203
{ "RG16F", false, 1, 4, Image::FORMAT_RGH },
185204
{ "RGBA16F", false, 1, 8, Image::FORMAT_RGBAH },

0 commit comments

Comments
 (0)