diff --git a/direct/src/directtools/DirectManipulation.py b/direct/src/directtools/DirectManipulation.py index 0607e42bf4..631eb710cd 100644 --- a/direct/src/directtools/DirectManipulation.py +++ b/direct/src/directtools/DirectManipulation.py @@ -1068,7 +1068,7 @@ class ObjectHandles(NodePath, DirectObject): # Load up object handles model and assign it to self self.assign(base.loader.loadModel('models/misc/objectHandles')) self.setName(name) - self.scalingNode = self.getChild(0) + self.scalingNode = NodePath(self) self.scalingNode.setName('ohScalingNode') self.ohScalingFactor = 1.0 self.directScalingFactor = 1.0 diff --git a/panda/src/egldisplay/config_egldisplay.cxx b/panda/src/egldisplay/config_egldisplay.cxx index a72112c8c6..e80137290d 100644 --- a/panda/src/egldisplay/config_egldisplay.cxx +++ b/panda/src/egldisplay/config_egldisplay.cxx @@ -12,7 +12,9 @@ */ #include "config_egldisplay.h" +#include "eglGraphicsBuffer.h" #include "eglGraphicsPipe.h" +#include "eglGraphicsPixmap.h" #include "eglGraphicsWindow.h" #include "eglGraphicsStateGuardian.h" #include "graphicsPipeSelection.h" @@ -44,8 +46,10 @@ init_libegldisplay() { } initialized = true; + eglGraphicsBuffer::init_type(); eglGraphicsPipe::init_type(); #ifdef HAVE_X11 + eglGraphicsPixmap::init_type(); eglGraphicsWindow::init_type(); #endif eglGraphicsStateGuardian::init_type(); diff --git a/panda/src/gles2gsg/gles2gsg.h b/panda/src/gles2gsg/gles2gsg.h index 729ee6e589..c328c99ac4 100644 --- a/panda/src/gles2gsg/gles2gsg.h +++ b/panda/src/gles2gsg/gles2gsg.h @@ -156,6 +156,18 @@ typedef char GLchar; #define GL_TEXTURE_MAX_LEVEL 0x813D #define GL_NUM_EXTENSIONS 0x821D #define GL_RG_INTEGER 0x8228 +#define GL_R8I 0x8231 +#define GL_R8UI 0x8232 +#define GL_R16I 0x8233 +#define GL_R16UI 0x8234 +#define GL_R32I 0x8235 +#define GL_R32UI 0x8236 +#define GL_RG8I 0x8237 +#define GL_RG8UI 0x8238 +#define GL_RG16I 0x8239 +#define GL_RG16UI 0x823A +#define GL_RG32I 0x823B +#define GL_RG32UI 0x823C #define GL_PROGRAM_BINARY_RETRIEVABLE_HINT 0x8257 #define GL_PROGRAM_BINARY_LENGTH 0x8741 #define GL_NUM_PROGRAM_BINARY_FORMATS 0x87FE @@ -196,6 +208,18 @@ typedef char GLchar; #define GL_SRGB8 0x8C41 #define GL_SRGB8_ALPHA8 0x8C43 #define GL_PRIMITIVE_RESTART_FIXED_INDEX 0x8D69 +#define GL_RGBA32UI 0x8D70 +#define GL_RGB32UI 0x8D71 +#define GL_RGBA16UI 0x8D76 +#define GL_RGB16UI 0x8D77 +#define GL_RGBA8UI 0x8D7C +#define GL_RGB8UI 0x8D7D +#define GL_RGBA32I 0x8D82 +#define GL_RGB32I 0x8D83 +#define GL_RGBA16I 0x8D88 +#define GL_RGB16I 0x8D89 +#define GL_RGBA8I 0x8D8E +#define GL_RGB8I 0x8D8F #define GL_RED_INTEGER 0x8D94 #define GL_RGB_INTEGER 0x8D98 #define GL_RGBA_INTEGER 0x8D99 diff --git a/panda/src/glstuff/glGraphicsStateGuardian_src.cxx b/panda/src/glstuff/glGraphicsStateGuardian_src.cxx index 0cf751cbb3..d2c62a627d 100644 --- a/panda/src/glstuff/glGraphicsStateGuardian_src.cxx +++ b/panda/src/glstuff/glGraphicsStateGuardian_src.cxx @@ -9531,6 +9531,8 @@ get_external_image_format(Texture *tex) const { case Texture::F_rgba16: case Texture::F_rgba32: case Texture::F_rgba8i: + case Texture::F_rgba16i: + case Texture::F_rgba32i: case Texture::F_rgb10_a2: return GL_COMPRESSED_RGBA; @@ -9542,7 +9544,9 @@ get_external_image_format(Texture *tex) const { case Texture::F_rgb12: case Texture::F_rgb332: case Texture::F_rgb16: + case Texture::F_rgb16i: case Texture::F_rgb32: + case Texture::F_rgb32i: return GL_COMPRESSED_RGB; case Texture::F_alpha: @@ -9561,7 +9565,9 @@ get_external_image_format(Texture *tex) const { case Texture::F_rg: case Texture::F_rg8i: case Texture::F_rg16: + case Texture::F_rg16i: case Texture::F_rg32: + case Texture::F_rg32i: return GL_COMPRESSED_RG; case Texture::F_luminance: @@ -9816,10 +9822,16 @@ get_external_image_format(Texture *tex) const { case Texture::F_r32i: return GL_RED_INTEGER; case Texture::F_rg8i: + case Texture::F_rg16i: + case Texture::F_rg32i: return GL_RG_INTEGER; case Texture::F_rgb8i: + case Texture::F_rgb16i: + case Texture::F_rgb32i: return GL_RGB_INTEGER; case Texture::F_rgba8i: + case Texture::F_rgba16i: + case Texture::F_rgba32i: return GL_RGBA_INTEGER; #endif @@ -9847,8 +9859,10 @@ get_internal_image_format(Texture *tex, bool force_sized) const { // no compression for render targets compression = Texture::CM_off; } - bool is_3d = (tex->get_texture_type() == Texture::TT_3d_texture || - tex->get_texture_type() == Texture::TT_2d_texture_array); + Texture::ComponentType component_type = tex->get_component_type(); + Texture::TextureType texture_type = tex->get_texture_type(); + bool is_3d = (texture_type == Texture::TT_3d_texture || + texture_type == Texture::TT_2d_texture_array); if (get_supports_compressed_texture_format(compression)) { switch (compression) { @@ -9871,7 +9885,13 @@ get_internal_image_format(Texture *tex, bool force_sized) const { case Texture::F_rgb8i: case Texture::F_rgba8i: case Texture::F_r16i: + case Texture::F_rg16i: + case Texture::F_rgb16i: + case Texture::F_rgba16i: case Texture::F_r32i: + case Texture::F_rg32i: + case Texture::F_rgb32i: + case Texture::F_rgba32i: case Texture::F_r11_g11_b10: case Texture::F_rgb9_e5: // Unsupported; fall through to below. @@ -9982,7 +10002,7 @@ get_internal_image_format(Texture *tex, bool force_sized) const { } #endif if (get_supports_compressed_texture_format(Texture::CM_eac) && !is_3d) { - if (Texture::is_unsigned(tex->get_component_type())) { + if (Texture::is_unsigned(component_type)) { return GL_COMPRESSED_R11_EAC; } else { return GL_COMPRESSED_SIGNED_R11_EAC; @@ -10008,7 +10028,7 @@ get_internal_image_format(Texture *tex, bool force_sized) const { } #endif if (get_supports_compressed_texture_format(Texture::CM_eac) && !is_3d) { - if (Texture::is_unsigned(tex->get_component_type())) { + if (Texture::is_unsigned(component_type)) { return GL_COMPRESSED_RG11_EAC; } else { return GL_COMPRESSED_SIGNED_RG11_EAC; @@ -10186,7 +10206,7 @@ get_internal_image_format(Texture *tex, bool force_sized) const { break; case Texture::CM_eac: - if (Texture::is_unsigned(tex->get_component_type())) { + if (Texture::is_unsigned(component_type)) { if (tex->get_num_components() == 1) { return GL_COMPRESSED_R11_EAC; } else { @@ -10219,7 +10239,7 @@ get_internal_image_format(Texture *tex, bool force_sized) const { case Texture::F_depth_stencil: if (_supports_depth_stencil) { #ifndef OPENGLES - if (tex->get_component_type() == Texture::T_float) { + if (component_type == Texture::T_float) { return GL_DEPTH32F_STENCIL8; } else #endif @@ -10231,7 +10251,7 @@ get_internal_image_format(Texture *tex, bool force_sized) const { case Texture::F_depth_component: #ifndef OPENGLES - if (tex->get_component_type() == Texture::T_float) { + if (component_type == Texture::T_float) { return GL_DEPTH_COMPONENT32F; } else #endif @@ -10266,7 +10286,7 @@ get_internal_image_format(Texture *tex, bool force_sized) const { return GL_DEPTH_COMPONENT16_OES; } #else - if (tex->get_component_type() == Texture::T_float) { + if (component_type == Texture::T_float) { return GL_DEPTH_COMPONENT32F; } else { return GL_DEPTH_COMPONENT32; @@ -10276,7 +10296,7 @@ get_internal_image_format(Texture *tex, bool force_sized) const { case Texture::F_rgba: case Texture::F_rgbm: #ifndef OPENGLES_1 - if (tex->get_component_type() == Texture::T_float) { + if (component_type == Texture::T_float) { return GL_RGBA16F; } else #endif @@ -10286,11 +10306,11 @@ get_internal_image_format(Texture *tex, bool force_sized) const { return _supports_bgr ? GL_BGRA : GL_RGBA; } #else - if (tex->get_component_type() == Texture::T_unsigned_short) { + if (component_type == Texture::T_unsigned_short) { return GL_RGBA16; - } else if (tex->get_component_type() == Texture::T_short) { + } else if (component_type == Texture::T_short) { return GL_RGBA16_SNORM; - } else if (tex->get_component_type() == Texture::T_byte) { + } else if (component_type == Texture::T_byte) { return GL_RGBA8_SNORM; } else { return force_sized ? GL_RGBA8 : GL_RGBA; @@ -10307,32 +10327,32 @@ get_internal_image_format(Texture *tex, bool force_sized) const { return _supports_bgr ? GL_BGRA : (force_sized ? GL_RGBA8 : GL_RGBA); #else case Texture::F_rgba8: - if (Texture::is_unsigned(tex->get_component_type())) { + if (Texture::is_unsigned(component_type)) { return GL_RGBA8; } else { return GL_RGBA8_SNORM; } case Texture::F_r8i: - if (Texture::is_unsigned(tex->get_component_type())) { + if (Texture::is_unsigned(component_type)) { return GL_R8UI; } else { return GL_R8I; } case Texture::F_rg8i: - if (Texture::is_unsigned(tex->get_component_type())) { + if (Texture::is_unsigned(component_type)) { return GL_RG8UI; } else { return GL_RG8I; } case Texture::F_rgb8i: - if (Texture::is_unsigned(tex->get_component_type())) { + if (Texture::is_unsigned(component_type)) { return GL_RGB8UI; } else { return GL_RGB8I; } case Texture::F_rgba8i: - if (Texture::is_unsigned(tex->get_component_type())) { + if (Texture::is_unsigned(component_type)) { return GL_RGBA8UI; } else { return GL_RGBA8I; @@ -10342,9 +10362,9 @@ get_internal_image_format(Texture *tex, bool force_sized) const { #endif // OPENGLES #ifndef OPENGLES case Texture::F_rgba16: - if (tex->get_component_type() == Texture::T_float) { + if (component_type == Texture::T_float) { return GL_RGBA16F; - } else if (Texture::is_unsigned(tex->get_component_type())) { + } else if (Texture::is_unsigned(component_type)) { return GL_RGBA16; } else { return GL_RGBA16_SNORM; @@ -10354,7 +10374,7 @@ get_internal_image_format(Texture *tex, bool force_sized) const { #endif // OPENGLES case Texture::F_rgb: - switch (tex->get_component_type()) { + switch (component_type) { case Texture::T_float: return GL_RGB16F; #ifndef OPENGLES case Texture::T_unsigned_short: return GL_RGB16; @@ -10384,7 +10404,7 @@ get_internal_image_format(Texture *tex, bool force_sized) const { return GL_RGB16F; #else case Texture::F_rgb8: - if (Texture::is_unsigned(tex->get_component_type())) { + if (Texture::is_unsigned(component_type)) { return GL_RGB8; } else { return GL_RGB8_SNORM; @@ -10392,9 +10412,9 @@ get_internal_image_format(Texture *tex, bool force_sized) const { case Texture::F_rgb12: return GL_RGB12; case Texture::F_rgb16: - if (tex->get_component_type() == Texture::T_float) { + if (component_type == Texture::T_float) { return GL_RGB16F; - } else if (Texture::is_unsigned(tex->get_component_type())) { + } else if (Texture::is_unsigned(component_type)) { return GL_RGB16; } else { return GL_RGB16_SNORM; @@ -10415,26 +10435,44 @@ get_internal_image_format(Texture *tex, bool force_sized) const { return GL_RG16F_EXT; #elif !defined(OPENGLES_1) case Texture::F_r16: - if (tex->get_component_type() == Texture::T_float) { + if (component_type == Texture::T_float) { return GL_R16F; - } else if (Texture::is_unsigned(tex->get_component_type())) { + } else if (Texture::is_unsigned(component_type)) { return GL_R16; } else { return GL_R16_SNORM; } + case Texture::F_rg16: + if (component_type == Texture::T_float) { + return GL_RG16F; + } else if (Texture::is_unsigned(component_type)) { + return GL_RG16; + } else { + return GL_RG16_SNORM; + } case Texture::F_r16i: - if (Texture::is_unsigned(tex->get_component_type())) { + if (Texture::is_unsigned(component_type)) { return GL_R16UI; } else { return GL_R16I; } - case Texture::F_rg16: - if (tex->get_component_type() == Texture::T_float) { - return GL_RG16F; - } else if (Texture::is_unsigned(tex->get_component_type())) { - return GL_RG16; + case Texture::F_rg16i: + if (Texture::is_unsigned(component_type)) { + return GL_RG16UI; } else { - return GL_RG16_SNORM; + return GL_RG16I; + } + case Texture::F_rgb16i: + if (Texture::is_unsigned(component_type)) { + return GL_RGB16UI; + } else { + return GL_RGB16I; + } + case Texture::F_rgba16i: + if (Texture::is_unsigned(component_type)) { + return GL_RGBA16UI; + } else { + return GL_RGBA16I; } #endif @@ -10448,7 +10486,7 @@ get_internal_image_format(Texture *tex, bool force_sized) const { case Texture::F_green: case Texture::F_blue: #ifndef OPENGLES - if (!Texture::is_unsigned(tex->get_component_type())) { + if (!Texture::is_unsigned(component_type)) { return GL_R8_SNORM; } else #endif @@ -10473,7 +10511,7 @@ get_internal_image_format(Texture *tex, bool force_sized) const { return force_sized ? GL_LUMINANCE8 : GL_LUMINANCE; #else if (_supports_luminance_texture) { - switch (tex->get_component_type()) { + switch (component_type) { case Texture::T_float: case Texture::T_half_float: return GL_LUMINANCE16F_ARB; @@ -10485,7 +10523,7 @@ get_internal_image_format(Texture *tex, bool force_sized) const { return force_sized ? GL_LUMINANCE8 : GL_LUMINANCE; } } else { - switch (tex->get_component_type()) { + switch (component_type) { case Texture::T_float: case Texture::T_half_float: return GL_R16F; @@ -10504,7 +10542,7 @@ get_internal_image_format(Texture *tex, bool force_sized) const { return force_sized ? GL_LUMINANCE8_ALPHA8 : GL_LUMINANCE_ALPHA; #else if (_supports_luminance_texture) { - switch (tex->get_component_type()) { + switch (component_type) { case Texture::T_float: case Texture::T_half_float: return GL_LUMINANCE_ALPHA16F_ARB; @@ -10516,7 +10554,7 @@ get_internal_image_format(Texture *tex, bool force_sized) const { return force_sized ? GL_LUMINANCE8_ALPHA8 : GL_LUMINANCE_ALPHA; } } else { - switch (tex->get_component_type()) { + switch (component_type) { case Texture::T_float: case Texture::T_half_float: return GL_RG16F; @@ -10548,9 +10586,31 @@ get_internal_image_format(Texture *tex, bool force_sized) const { return _core_profile ? GL_SRGB8_ALPHA8 : GL_SLUMINANCE8_ALPHA8; #endif -#ifndef OPENGLES +#ifndef OPENGLES_1 case Texture::F_r32i: - return GL_R32I; + if (Texture::is_unsigned(component_type)) { + return GL_R32UI; + } else { + return GL_R32I; + } + case Texture::F_rg32i: + if (Texture::is_unsigned(component_type)) { + return GL_RG32UI; + } else { + return GL_RG32I; + } + case Texture::F_rgb32i: + if (Texture::is_unsigned(component_type)) { + return GL_RGB32UI; + } else { + return GL_RGB32I; + } + case Texture::F_rgba32i: + if (Texture::is_unsigned(component_type)) { + return GL_RGBA32UI; + } else { + return GL_RGBA32I; + } #endif #ifndef OPENGLES_1 @@ -12632,10 +12692,20 @@ specify_texture(CLP(TextureContext) *gtc, const SamplerState &sampler) { } } - glTexParameteri(target, GL_TEXTURE_MIN_FILTER, - get_texture_filter_type(minfilter, !uses_mipmaps)); - glTexParameteri(target, GL_TEXTURE_MAG_FILTER, - get_texture_filter_type(magfilter, true)); + if (Texture::is_integer(tex->get_format())) { + // Integer format textures can't have filtering enabled, and in fact, some + // drivers (looking at you, Intel) will always sample (0, 0, 0, 1) if we + // don't set this correctly! + glTexParameteri(target, GL_TEXTURE_MIN_FILTER, + uses_mipmaps ? GL_NEAREST_MIPMAP_NEAREST + : GL_NEAREST); + glTexParameteri(target, GL_TEXTURE_MAG_FILTER, GL_NEAREST); + } else { + glTexParameteri(target, GL_TEXTURE_MIN_FILTER, + get_texture_filter_type(minfilter, !uses_mipmaps)); + glTexParameteri(target, GL_TEXTURE_MAG_FILTER, + get_texture_filter_type(magfilter, true)); + } // Set anisotropic filtering. if (_supports_anisotropy) { @@ -14185,7 +14255,9 @@ do_extract_texture_data(CLP(TextureContext) *gtc) { case GL_R3_G3_B2: format = Texture::F_rgb332; break; +#endif +#ifndef OPENGLES_1 case GL_R8I: type = Texture::T_byte; format = Texture::F_r8i; @@ -14224,11 +14296,69 @@ do_extract_texture_data(CLP(TextureContext) *gtc) { type = Texture::T_short; format = Texture::F_r16i; break; + case GL_RG16I: + type = Texture::T_short; + format = Texture::F_rg16i; + break; + case GL_RGB16I: + type = Texture::T_short; + format = Texture::F_rgb16i; + break; + case GL_RGBA16I: + type = Texture::T_short; + format = Texture::F_rgba16i; + break; + case GL_R16UI: type = Texture::T_unsigned_short; format = Texture::F_r16i; break; + case GL_RG16UI: + type = Texture::T_unsigned_short; + format = Texture::F_rg16i; + break; + case GL_RGB16UI: + type = Texture::T_unsigned_short; + format = Texture::F_rgb16i; + break; + case GL_RGBA16UI: + type = Texture::T_unsigned_short; + format = Texture::F_rgba16i; + break; + case GL_R32I: + type = Texture::T_int; + format = Texture::F_r32i; + break; + case GL_RG32I: + type = Texture::T_int; + format = Texture::F_rg32i; + break; + case GL_RGB32I: + type = Texture::T_int; + format = Texture::F_rgb32i; + break; + case GL_RGBA32I: + type = Texture::T_int; + format = Texture::F_rgba32i; + break; + + case GL_R32UI: + type = Texture::T_unsigned_int; + format = Texture::F_r32i; + break; + case GL_RG32UI: + type = Texture::T_unsigned_int; + format = Texture::F_rg32i; + break; + case GL_RGB32UI: + type = Texture::T_unsigned_int; + format = Texture::F_rgb32i; + break; + case GL_RGBA32UI: + type = Texture::T_unsigned_int; + format = Texture::F_rgba32i; + break; #endif #ifndef OPENGLES_1 @@ -14317,12 +14447,6 @@ do_extract_texture_data(CLP(TextureContext) *gtc) { format = Texture::F_red; break; #endif -#ifndef OPENGLES - case GL_R32I: - type = Texture::T_int; - format = Texture::F_r32i; - break; -#endif #ifndef OPENGLES case GL_RED: diff --git a/panda/src/glstuff/glShaderContext_src.cxx b/panda/src/glstuff/glShaderContext_src.cxx index 4f827b43cf..dbba4c7bee 100644 --- a/panda/src/glstuff/glShaderContext_src.cxx +++ b/panda/src/glstuff/glShaderContext_src.cxx @@ -2808,6 +2808,11 @@ update_shader_texture_bindings(ShaderContext *prev) { } continue; } + else if (Texture::is_integer(tex->get_format())) { + // Required to satisfy Intel drivers, which will otherwise sample zero. + sampler.set_minfilter(sampler.uses_mipmaps() ? SamplerState::FT_nearest_mipmap_nearest : SamplerState::FT_nearest); + sampler.set_magfilter(SamplerState::FT_nearest); + } if (tex->get_texture_type() != spec._desired_type) { switch (spec._part) { diff --git a/panda/src/gobj/texture.cxx b/panda/src/gobj/texture.cxx index d1d76d471c..8d4756fee4 100644 --- a/panda/src/gobj/texture.cxx +++ b/panda/src/gobj/texture.cxx @@ -676,7 +676,7 @@ estimate_texture_memory() const { CDReader cdata(_cycler); size_t pixels = cdata->_x_size * cdata->_y_size * cdata->_z_size; - size_t bpp = 4; + size_t bpp = 0; switch (cdata->_format) { case Texture::F_rgb332: bpp = 1; @@ -739,10 +739,8 @@ estimate_texture_memory() const { bpp = 8; break; - case Texture::F_rgba16: - bpp = 8; - break; case Texture::F_rgba32: + case Texture::F_rgba32i: bpp = 16; break; @@ -752,9 +750,13 @@ estimate_texture_memory() const { bpp = 2; break; case Texture::F_rg16: + case Texture::F_rg16i: bpp = 4; break; case Texture::F_rgb16: + case Texture::F_rgb16i: + case Texture::F_rgba16: + case Texture::F_rgba16i: bpp = 8; break; @@ -764,10 +766,12 @@ estimate_texture_memory() const { break; case Texture::F_rg32: + case Texture::F_rg32i: bpp = 8; break; case Texture::F_rgb32: + case Texture::F_rgb32i: bpp = 16; break; @@ -776,11 +780,12 @@ estimate_texture_memory() const { case Texture::F_rgb10_a2: bpp = 4; break; + } - default: + if (bpp == 0) { + bpp = 4; gobj_cat.warning() << "Unhandled format in estimate_texture_memory(): " << cdata->_format << "\n"; - break; } size_t bytes = pixels * bpp; @@ -1789,10 +1794,6 @@ write(ostream &out, int indent_level) const { case F_r16: out << "r16"; break; - case F_r16i: - out << "r16i"; - break; - case F_rg16: out << "rg16"; break; @@ -1852,6 +1853,29 @@ write(ostream &out, int indent_level) const { case F_rg: out << "rg"; break; + + case F_r16i: + out << "r16i"; + break; + case F_rg16i: + out << "rg16i"; + break; + case F_rgb16i: + out << "rgb16i"; + break; + case F_rgba16i: + out << "rgba16i"; + break; + + case F_rg32i: + out << "rg32i"; + break; + case F_rgb32i: + out << "rgb32i"; + break; + case F_rgba32i: + out << "rgba32i"; + break; } if (cdata->_compression != CM_default) { @@ -2217,8 +2241,6 @@ format_format(Format format) { return "rgba32"; case F_r16: return "r16"; - case F_r16i: - return "r16i"; case F_rg16: return "rg16"; case F_rgb16: @@ -2255,6 +2277,20 @@ format_format(Format format) { return "rgb10_a2"; case F_rg: return "rg"; + case F_r16i: + return "r16i"; + case F_rg16i: + return "rg16i"; + case F_rgb16i: + return "rgb16i"; + case F_rgba16i: + return "rgba16i"; + case F_rg32i: + return "rg32i"; + case F_rgb32i: + return "rgb32i"; + case F_rgba32i: + return "rgba32i"; } return "**invalid**"; } @@ -2340,6 +2376,14 @@ string_format(const string &str) { return F_rg32; } else if (cmp_nocase(str, "rgb32") == 0 || cmp_nocase(str, "r32g32b32") == 0) { return F_rgb32; + } else if (cmp_nocase_uh(str, "r8i") == 0) { + return F_r8i; + } else if (cmp_nocase_uh(str, "rg8i") == 0 || cmp_nocase_uh(str, "r8g8i") == 0) { + return F_rg8i; + } else if (cmp_nocase_uh(str, "rgb8i") == 0 || cmp_nocase_uh(str, "r8g8b8i") == 0) { + return F_rgb8i; + } else if (cmp_nocase_uh(str, "rgba8i") == 0 || cmp_nocase_uh(str, "r8g8b8a8i") == 0) { + return F_rgba8i; } else if (cmp_nocase(str, "r11g11b10") == 0) { return F_r11_g11_b10; } else if (cmp_nocase(str, "rgb9_e5") == 0) { @@ -2348,6 +2392,20 @@ string_format(const string &str) { return F_rgb10_a2; } else if (cmp_nocase_uh(str, "rg") == 0) { return F_rg; + } else if (cmp_nocase_uh(str, "r16i") == 0) { + return F_r16i; + } else if (cmp_nocase_uh(str, "rg16i") == 0 || cmp_nocase_uh(str, "r16g16i") == 0) { + return F_rg16i; + } else if (cmp_nocase_uh(str, "rgb16i") == 0 || cmp_nocase_uh(str, "r16g16b16i") == 0) { + return F_rgb16i; + } else if (cmp_nocase_uh(str, "rgba16i") == 0 || cmp_nocase_uh(str, "r16g16b16a16i") == 0) { + return F_rgba16i; + } else if (cmp_nocase_uh(str, "rg32i") == 0 || cmp_nocase_uh(str, "r32g32i") == 0) { + return F_rg32i; + } else if (cmp_nocase_uh(str, "rgb32i") == 0 || cmp_nocase_uh(str, "r32g32b32i") == 0) { + return F_rgb32i; + } else if (cmp_nocase_uh(str, "rgba32i") == 0 || cmp_nocase_uh(str, "r32g32b32a32i") == 0) { + return F_rgba32i; } gobj_cat->error() @@ -2588,6 +2646,8 @@ has_alpha(Format format) { case F_sluminance_alpha: case F_rgba8i: case F_rgb10_a2: + case F_rgba16i: + case F_rgba32i: return true; default: @@ -2628,6 +2688,31 @@ is_srgb(Format format) { } } +/** + * Returns true if the indicated format is an integer format, false otherwise. + */ +bool Texture:: +is_integer(Format format) { + switch (format) { + case F_r32i: + case F_r8i: + case F_rg8i: + case F_rgb8i: + case F_rgba8i: + case F_r16i: + case F_rg16i: + case F_rgb16i: + case F_rgba16i: + case F_rg32i: + case F_rgb32i: + case F_rgba32i: + return true; + + default: + return false; + } +} + /** * Computes the proper size of the texture, based on the original size, the * filename, and the resizing whims of the config file. @@ -3674,11 +3759,31 @@ do_read_dds(CData *cdata, istream &in, const string &filename, bool header_only) component_type = T_unsigned_short; func = read_dds_level_abgr16; break; + case 12: // DXGI_FORMAT_R16G16B16A16_UINT + format = F_rgba16i; + component_type = T_unsigned_short; + func = read_dds_level_abgr16; + break; + case 14: // DXGI_FORMAT_R16G16B16A16_SINT + format = F_rgba16i; + component_type = T_short; + func = read_dds_level_abgr16; + break; case 16: // DXGI_FORMAT_R32G32_FLOAT format = F_rg32; component_type = T_float; func = read_dds_level_raw; break; + case 17: // DXGI_FORMAT_R32G32_UINT + format = F_rg32i; + component_type = T_unsigned_int; + func = read_dds_level_raw; + break; + case 18: // DXGI_FORMAT_R32G32_SINT + format = F_rg32i; + component_type = T_int; + func = read_dds_level_raw; + break; case 27: // DXGI_FORMAT_R8G8B8A8_TYPELESS case 28: // DXGI_FORMAT_R8G8B8A8_UNORM format = F_rgba8; @@ -3712,11 +3817,21 @@ do_read_dds(CData *cdata, istream &in, const string &filename, bool header_only) component_type = T_unsigned_short; func = read_dds_level_raw; break; + case 36: // DXGI_FORMAT_R16G16_UINT: + format = F_rg16i; + component_type = T_unsigned_short; + func = read_dds_level_raw; + break; case 37: // DXGI_FORMAT_R16G16_SNORM: format = F_rg16; component_type = T_short; func = read_dds_level_raw; break; + case 38: // DXGI_FORMAT_R16G16_SINT: + format = F_rg16i; + component_type = T_short; + func = read_dds_level_raw; + break; case 40: // DXGI_FORMAT_D32_FLOAT format = F_depth_component32; component_type = T_float; @@ -4611,8 +4726,12 @@ do_read_ktx(CData *cdata, istream &in, const string &filename, bool header_only) break; case KTX_RG16I: case KTX_RG16UI: + format = F_rg16i; + break; case KTX_RG32I: case KTX_RG32UI: + format = F_rg32i; + break; default: gobj_cat.error() << filename << " has unsupported RG integer format " << internal_format << "\n"; @@ -4676,8 +4795,12 @@ do_read_ktx(CData *cdata, istream &in, const string &filename, bool header_only) break; case KTX_RGB16I: case KTX_RGB16UI: + format = F_rgb16i; + break; case KTX_RGB32I: case KTX_RGB32UI: + format = F_rgb32i; + break; default: gobj_cat.error() << filename << " has unsupported RGB integer format " << internal_format << "\n"; @@ -4739,8 +4862,12 @@ do_read_ktx(CData *cdata, istream &in, const string &filename, bool header_only) break; case KTX_RGBA16I: case KTX_RGBA16UI: + format = F_rgba16i; + break; case KTX_RGBA32I: case KTX_RGBA32UI: + format = F_rgba32i; + break; default: gobj_cat.error() << filename << " has unsupported RGBA integer format " << internal_format << "\n"; @@ -6877,6 +7004,8 @@ do_set_format(CData *cdata, Texture::Format format) { case F_rg32: case F_rg8i: case F_rg: + case F_rg16i: + case F_rg32i: cdata->_num_components = 2; break; @@ -6891,6 +7020,8 @@ do_set_format(CData *cdata, Texture::Format format) { case F_rgb8i: case F_r11_g11_b10: case F_rgb9_e5: + case F_rgb16i: + case F_rgb32i: cdata->_num_components = 3; break; @@ -6905,6 +7036,8 @@ do_set_format(CData *cdata, Texture::Format format) { case F_srgb_alpha: case F_rgba8i: case F_rgb10_a2: + case F_rgba16i: + case F_rgba32i: cdata->_num_components = 4; break; } diff --git a/panda/src/gobj/texture.h b/panda/src/gobj/texture.h index 4bde90c973..7abdb17216 100644 --- a/panda/src/gobj/texture.h +++ b/panda/src/gobj/texture.h @@ -161,7 +161,15 @@ PUBLISHED: F_rgb10_a2, F_rg, - F_r16i + + F_r16i, + F_rg16i, + F_rgb16i, // not recommended + F_rgba16i, + + F_rg32i, + F_rgb32i, + F_rgba32i, }; // Deprecated. See SamplerState.FilterType. @@ -625,6 +633,7 @@ public: static bool has_alpha(Format format); static bool has_binary_alpha(Format format); static bool is_srgb(Format format); + static bool is_integer(Format format); static bool adjust_size(int &x_size, int &y_size, const std::string &name, bool for_padding, AutoTextureScale auto_texture_scale = ATS_unspecified); diff --git a/panda/src/gobj/texturePeeker.cxx b/panda/src/gobj/texturePeeker.cxx index ece87f36a5..ee82e4644b 100644 --- a/panda/src/gobj/texturePeeker.cxx +++ b/panda/src/gobj/texturePeeker.cxx @@ -14,6 +14,58 @@ #include "texturePeeker.h" +static double get_unsigned_byte_i(const unsigned char *&p) { + return *p++; +} + +static double get_signed_byte_i(const unsigned char *&p) { + return *(signed char *)p++; +} + +static double get_unsigned_short_i(const unsigned char *&p) { + union { + unsigned short us; + unsigned char uc[2]; + } v; + v.uc[0] = (*p++); + v.uc[1] = (*p++); + return (double)v.us; +} + +static double get_signed_short_i(const unsigned char *&p) { + union { + signed short ss; + unsigned char uc[2]; + } v; + v.uc[0] = (*p++); + v.uc[1] = (*p++); + return (double)v.ss; +} + +static double get_unsigned_int_i(const unsigned char *&p) { + union { + unsigned int ui; + unsigned char uc[4]; + } v; + v.uc[0] = (*p++); + v.uc[1] = (*p++); + v.uc[2] = (*p++); + v.uc[3] = (*p++); + return (double)v.ui; +} + +static double get_signed_int_i(const unsigned char *&p) { + union { + signed int si; + unsigned char uc[4]; + } v; + v.uc[0] = (*p++); + v.uc[1] = (*p++); + v.uc[2] = (*p++); + v.uc[3] = (*p++); + return (double)v.si; +} + /** * Use Texture::peek() to construct a TexturePeeker. * @@ -73,35 +125,69 @@ TexturePeeker(Texture *tex, Texture::CData *cdata) { } _pixel_width = _component_width * _num_components; - switch (_component_type) { - case Texture::T_unsigned_byte: - _get_component = Texture::get_unsigned_byte; - break; + if (Texture::is_integer(_format)) { + switch (_component_type) { + case Texture::T_unsigned_byte: + _get_component = get_unsigned_byte_i; + break; - case Texture::T_unsigned_short: - _get_component = Texture::get_unsigned_short; - break; + case Texture::T_unsigned_short: + _get_component = get_unsigned_short_i; + break; - case Texture::T_unsigned_int: - _get_component = Texture::get_unsigned_int; - break; + case Texture::T_unsigned_int: + _get_component = get_unsigned_int_i; + break; - case Texture::T_float: - _get_component = Texture::get_float; - break; + case Texture::T_byte: + _get_component = get_signed_byte_i; + break; - case Texture::T_half_float: - _get_component = Texture::get_half_float; - break; + case Texture::T_short: + _get_component = get_signed_short_i; + break; - case Texture::T_unsigned_int_24_8: - _get_component = Texture::get_unsigned_int_24; - break; + case Texture::T_int: + _get_component = get_signed_int_i; + break; - default: - // Not supported. - _image.clear(); - return; + default: + // Not supported. + _image.clear(); + return; + } + } + else { + switch (_component_type) { + case Texture::T_unsigned_byte: + _get_component = Texture::get_unsigned_byte; + break; + + case Texture::T_unsigned_short: + _get_component = Texture::get_unsigned_short; + break; + + case Texture::T_unsigned_int: + _get_component = Texture::get_unsigned_int; + break; + + case Texture::T_float: + _get_component = Texture::get_float; + break; + + case Texture::T_half_float: + _get_component = Texture::get_half_float; + break; + + case Texture::T_unsigned_int_24_8: + _get_component = Texture::get_unsigned_int_24; + break; + + default: + // Not supported. + _image.clear(); + return; + } } switch (_format) { @@ -114,6 +200,7 @@ TexturePeeker(Texture *tex, Texture::CData *cdata) { case Texture::F_r16: case Texture::F_r32: case Texture::F_r32i: + case Texture::F_r16i: _get_texel = get_texel_r; break; @@ -140,21 +227,27 @@ TexturePeeker(Texture *tex, Texture::CData *cdata) { _get_texel = get_texel_la; break; - case Texture::F_rg16: - case Texture::F_rg32: case Texture::F_rg: + case Texture::F_rg8i: + case Texture::F_rg16: + case Texture::F_rg16i: + case Texture::F_rg32: + case Texture::F_rg32i: _get_texel = get_texel_rg; break; case Texture::F_rgb: case Texture::F_rgb5: case Texture::F_rgb8: + case Texture::F_rgb8i: case Texture::F_rgb12: case Texture::F_rgb16: + case Texture::F_rgb16i: case Texture::F_rgb332: case Texture::F_r11_g11_b10: case Texture::F_rgb9_e5: case Texture::F_rgb32: + case Texture::F_rgb32i: _get_texel = get_texel_rgb; break; @@ -163,9 +256,12 @@ TexturePeeker(Texture *tex, Texture::CData *cdata) { case Texture::F_rgba4: case Texture::F_rgba5: case Texture::F_rgba8: + case Texture::F_rgba8i: case Texture::F_rgba12: case Texture::F_rgba16: + case Texture::F_rgba16i: case Texture::F_rgba32: + case Texture::F_rgba32i: case Texture::F_rgb10_a2: _get_texel = get_texel_rgba; break; diff --git a/panda/src/grutil/multitexReducer.cxx b/panda/src/grutil/multitexReducer.cxx index 2fff484de3..fd94e1d173 100644 --- a/panda/src/grutil/multitexReducer.cxx +++ b/panda/src/grutil/multitexReducer.cxx @@ -714,6 +714,7 @@ make_texture_layer(const NodePath &render, case TextureStage::M_height: case TextureStage::M_selector: case TextureStage::M_normal_gloss: + case TextureStage::M_emission: // Don't know what to do with these funny modes. We should probably raise // an exception or something. Fall through for now. diff --git a/panda/src/pgraph/shaderInput_ext.cxx b/panda/src/pgraph/shaderInput_ext.cxx index 31c1e749bd..d7496120b6 100644 --- a/panda/src/pgraph/shaderInput_ext.cxx +++ b/panda/src/pgraph/shaderInput_ext.cxx @@ -274,7 +274,7 @@ __init__(CPT_InternalName name, PyObject *value, int priority) { return; } - Py_ssize_t num_items = PySequence_Fast_GET_SIZE(value); + Py_ssize_t num_items = PySequence_Fast_GET_SIZE(fast); if (num_items <= 0) { // We can't determine the type of a list of size 0. _this->_type = ShaderInput::M_numeric; diff --git a/tests/display/test_glsl_shader.py b/tests/display/test_glsl_shader.py index 891410c3e7..097a679a82 100644 --- a/tests/display/test_glsl_shader.py +++ b/tests/display/test_glsl_shader.py @@ -141,15 +141,77 @@ def test_glsl_sampler(gsg): tex2.setup_2d_texture(1, 1, core.Texture.T_float, core.Texture.F_rgba32) tex2.set_clear_color((1.0, 2.0, -3.14, 0.0)) + tex3 = core.Texture("") + tex3.setup_3d_texture(1, 1, 1, core.Texture.T_float, core.Texture.F_r32) + tex3.set_clear_color((0.5, 0.0, 0.0, 1.0)) + preamble = """ uniform sampler1D tex1; uniform sampler2D tex2; + uniform sampler3D tex3; """ code = """ assert(texelFetch(tex1, 0, 0) == vec4(0, 2 / 255.0, 1, 1)); assert(texelFetch(tex2, ivec2(0, 0), 0) == vec4(1.0, 2.0, -3.14, 0.0)); + assert(texelFetch(tex3, ivec3(0, 0, 0), 0) == vec4(0.5, 0.0, 0.0, 1.0)); """ - run_glsl_test(gsg, code, preamble, {'tex1': tex1, 'tex2': tex2}) + run_glsl_test(gsg, code, preamble, {'tex1': tex1, 'tex2': tex2, 'tex3': tex3}) + + +def test_glsl_isampler(gsg): + from struct import pack + + tex1 = core.Texture("") + tex1.setup_1d_texture(1, core.Texture.T_byte, core.Texture.F_rgba8i) + tex1.set_ram_image(pack('bbbb', 0, 1, 2, 3)) + + tex2 = core.Texture("") + tex2.setup_2d_texture(1, 1, core.Texture.T_short, core.Texture.F_r16i) + tex2.set_ram_image(pack('h', 4)) + + tex3 = core.Texture("") + tex3.setup_3d_texture(1, 1, 1, core.Texture.T_int, core.Texture.F_r32i) + tex3.set_ram_image(pack('i', 5)) + + preamble = """ + uniform isampler1D tex1; + uniform isampler2D tex2; + uniform isampler3D tex3; + """ + code = """ + assert(texelFetch(tex1, 0, 0) == ivec4(0, 1, 2, 3)); + assert(texelFetch(tex2, ivec2(0, 0), 0) == ivec4(4, 0, 0, 1)); + assert(texelFetch(tex3, ivec3(0, 0, 0), 0) == ivec4(5, 0, 0, 1)); + """ + run_glsl_test(gsg, code, preamble, {'tex1': tex1, 'tex2': tex2, 'tex3': tex3}) + + +def test_glsl_usampler(gsg): + from struct import pack + + tex1 = core.Texture("") + tex1.setup_1d_texture(1, core.Texture.T_unsigned_byte, core.Texture.F_rgba8i) + tex1.set_ram_image(pack('BBBB', 0, 1, 2, 3)) + + tex2 = core.Texture("") + tex2.setup_2d_texture(1, 1, core.Texture.T_unsigned_short, core.Texture.F_r16i) + tex2.set_ram_image(pack('H', 4)) + + tex3 = core.Texture("") + tex3.setup_3d_texture(1, 1, 1, core.Texture.T_unsigned_int, core.Texture.F_r32i) + tex3.set_ram_image(pack('I', 5)) + + preamble = """ + uniform usampler1D tex1; + uniform usampler2D tex2; + uniform usampler3D tex3; + """ + code = """ + assert(texelFetch(tex1, 0, 0) == uvec4(0, 1, 2, 3)); + assert(texelFetch(tex2, ivec2(0, 0), 0) == uvec4(4, 0, 0, 1)); + assert(texelFetch(tex3, ivec3(0, 0, 0), 0) == uvec4(5, 0, 0, 1)); + """ + run_glsl_test(gsg, code, preamble, {'tex1': tex1, 'tex2': tex2, 'tex3': tex3}) def test_glsl_image(gsg): @@ -172,6 +234,62 @@ def test_glsl_image(gsg): run_glsl_test(gsg, code, preamble, {'tex1': tex1, 'tex2': tex2}) +def test_glsl_iimage(gsg): + from struct import pack + + tex1 = core.Texture("") + tex1.setup_1d_texture(1, core.Texture.T_byte, core.Texture.F_rgba8i) + tex1.set_ram_image(pack('bbbb', 0, 1, 2, 3)) + + tex2 = core.Texture("") + tex2.setup_2d_texture(1, 1, core.Texture.T_short, core.Texture.F_r16i) + tex2.set_ram_image(pack('h', 4)) + + tex3 = core.Texture("") + tex3.setup_3d_texture(1, 1, 1, core.Texture.T_int, core.Texture.F_r32i) + tex3.set_ram_image(pack('i', 5)) + + preamble = """ + layout(rgba8i) uniform iimage1D tex1; + layout(r16i) uniform iimage2D tex2; + layout(r32i) uniform iimage3D tex3; + """ + code = """ + assert(imageLoad(tex1, 0) == ivec4(0, 1, 2, 3)); + assert(imageLoad(tex2, ivec2(0, 0)) == ivec4(4, 0, 0, 1)); + assert(imageLoad(tex3, ivec3(0, 0, 0)) == ivec4(5, 0, 0, 1)); + """ + run_glsl_test(gsg, code, preamble, {'tex1': tex1, 'tex2': tex2, 'tex3': tex3}) + + +def test_glsl_uimage(gsg): + from struct import pack + + tex1 = core.Texture("") + tex1.setup_1d_texture(1, core.Texture.T_unsigned_byte, core.Texture.F_rgba8i) + tex1.set_ram_image(pack('BBBB', 0, 1, 2, 3)) + + tex2 = core.Texture("") + tex2.setup_2d_texture(1, 1, core.Texture.T_unsigned_short, core.Texture.F_r16i) + tex2.set_ram_image(pack('H', 4)) + + tex3 = core.Texture("") + tex3.setup_3d_texture(1, 1, 1, core.Texture.T_unsigned_int, core.Texture.F_r32i) + tex3.set_ram_image(pack('I', 5)) + + preamble = """ + layout(rgba8ui) uniform uimage1D tex1; + layout(r16ui) uniform uimage2D tex2; + layout(r32ui) uniform uimage3D tex3; + """ + code = """ + assert(imageLoad(tex1, 0) == uvec4(0, 1, 2, 3)); + assert(imageLoad(tex2, ivec2(0, 0)) == uvec4(4, 0, 0, 1)); + assert(imageLoad(tex3, ivec3(0, 0, 0)) == uvec4(5, 0, 0, 1)); + """ + run_glsl_test(gsg, code, preamble, {'tex1': tex1, 'tex2': tex2, 'tex3': tex3}) + + def test_glsl_ssbo(gsg): from struct import pack num1 = pack('