From 9773fd79692b6733faf5ef9779ce8459af38c3da Mon Sep 17 00:00:00 2001 From: rdb Date: Tue, 11 Aug 2015 17:08:31 +0200 Subject: [PATCH] Support cube map arrays --- panda/src/display/graphicsStateGuardian.I | 10 ++++ panda/src/display/graphicsStateGuardian.cxx | 1 + panda/src/display/graphicsStateGuardian.h | 2 + .../glstuff/glGraphicsStateGuardian_src.cxx | 42 ++++++++++++--- panda/src/glstuff/glShaderContext_src.cxx | 24 +++++++++ panda/src/gobj/shader.cxx | 52 ++++++++++++++----- panda/src/gobj/shader.h | 6 ++- panda/src/gobj/texture.I | 32 ++++++++++++ panda/src/gobj/texture.cxx | 31 +++++++++-- panda/src/gobj/texture.h | 4 ++ 10 files changed, 179 insertions(+), 25 deletions(-) diff --git a/panda/src/display/graphicsStateGuardian.I b/panda/src/display/graphicsStateGuardian.I index 15b2b89b78..1646f4a741 100644 --- a/panda/src/display/graphicsStateGuardian.I +++ b/panda/src/display/graphicsStateGuardian.I @@ -495,6 +495,16 @@ get_supports_buffer_texture() const { return _supports_buffer_texture; } +//////////////////////////////////////////////////////////////////// +// Function: GraphicsStateGuardian::get_supports_cube_map_array +// Access: Published +// Description: Returns true if this GSG can render cube map arrays. +//////////////////////////////////////////////////////////////////// +INLINE bool GraphicsStateGuardian:: +get_supports_cube_map_array() const { + return _supports_cube_map_array; +} + //////////////////////////////////////////////////////////////////// // Function: GraphicsStateGuardian::get_supports_tex_non_pow2 // Access: Published diff --git a/panda/src/display/graphicsStateGuardian.cxx b/panda/src/display/graphicsStateGuardian.cxx index 02ee982feb..fa17aa31da 100644 --- a/panda/src/display/graphicsStateGuardian.cxx +++ b/panda/src/display/graphicsStateGuardian.cxx @@ -198,6 +198,7 @@ GraphicsStateGuardian(CoordinateSystem internal_coordinate_system, _supports_2d_texture_array = false; _supports_cube_map = false; _supports_buffer_texture = false; + _supports_cube_map_array = false; _supports_tex_non_pow2 = false; _supports_texture_srgb = false; _supports_compressed_texture = false; diff --git a/panda/src/display/graphicsStateGuardian.h b/panda/src/display/graphicsStateGuardian.h index cc3c78a1bc..b657d867e9 100644 --- a/panda/src/display/graphicsStateGuardian.h +++ b/panda/src/display/graphicsStateGuardian.h @@ -132,6 +132,7 @@ PUBLISHED: INLINE bool get_supports_2d_texture_array() const; INLINE bool get_supports_cube_map() const; INLINE bool get_supports_buffer_texture() const; + INLINE bool get_supports_cube_map_array() const; INLINE bool get_supports_tex_non_pow2() const; INLINE bool get_supports_texture_srgb() const; @@ -489,6 +490,7 @@ protected: bool _supports_2d_texture_array; bool _supports_cube_map; bool _supports_buffer_texture; + bool _supports_cube_map_array; bool _supports_tex_non_pow2; bool _supports_texture_srgb; diff --git a/panda/src/glstuff/glGraphicsStateGuardian_src.cxx b/panda/src/glstuff/glGraphicsStateGuardian_src.cxx index 1a2317760a..ee713fbce2 100644 --- a/panda/src/glstuff/glGraphicsStateGuardian_src.cxx +++ b/panda/src/glstuff/glGraphicsStateGuardian_src.cxx @@ -856,6 +856,11 @@ reset() { } #endif +#ifndef OPENGLES + _supports_cube_map_array = is_at_least_gl_version(4, 0) || + has_extension("GL_ARB_texture_cube_map_array"); +#endif + #ifndef OPENGLES if (is_at_least_gl_version(3, 0)) { _glTexBuffer = (PFNGLTEXBUFFERPROC)get_extension_func("glTexBuffer"); @@ -4541,6 +4546,14 @@ prepare_texture(Texture *tex, int view) { } break; + case Texture::TT_cube_map_array: + if (!_supports_cube_map_array) { + GLCAT.warning() + << "Cube map arrays are not supported by this OpenGL driver.\n"; + return NULL; + } + break; + default: break; } @@ -5747,7 +5760,7 @@ framebuffer_copy_to_ram(Texture *tex, int view, int z, Texture::TextureType texture_type; int z_size; - //TODO: should be extended to support 3D textures and 2D arrays. + //TODO: should be extended to support 3D textures, 2D arrays and cube map arrays. if (z >= 0) { texture_type = Texture::TT_cube_map; z_size = 6; @@ -7512,7 +7525,7 @@ get_texture_target(Texture::TextureType texture_type) const { case Texture::TT_2d_texture_array: #ifndef OPENGLES if (_supports_2d_texture_array) { - return GL_TEXTURE_2D_ARRAY_EXT; + return GL_TEXTURE_2D_ARRAY; } #endif return GL_NONE; @@ -7524,6 +7537,14 @@ get_texture_target(Texture::TextureType texture_type) const { return GL_NONE; } + case Texture::TT_cube_map_array: +#ifndef OPENGLES + if (_supports_cube_map_array) { + return GL_TEXTURE_CUBE_MAP_ARRAY; + } +#endif + return GL_NONE; + case Texture::TT_buffer_texture: #ifndef OPENGLES if (_supports_buffer_texture) { @@ -9695,7 +9716,7 @@ update_standard_texture_bindings() { continue; } #ifndef OPENGLES - if (target == GL_TEXTURE_2D_ARRAY_EXT) { + if (target == GL_TEXTURE_2D_ARRAY || target == GL_TEXTURE_CUBE_MAP_ARRAY) { // Cannot be applied via the FFP. continue; } @@ -10748,6 +10769,12 @@ upload_texture(CLP(TextureContext) *gtc, bool force, bool uses_mipmaps) { max_dimension_z = _max_2d_texture_array_layers; break; + case Texture::TT_cube_map_array: + max_dimension_x = _max_texture_dimension; + max_dimension_y = _max_texture_dimension; + max_dimension_z = int(_max_2d_texture_array_layers / 6) * 6; + break; + case Texture::TT_buffer_texture: max_dimension_x = _max_buffer_texture_size; max_dimension_y = 1; @@ -11009,6 +11036,7 @@ upload_texture(CLP(TextureContext) *gtc, bool force, bool uses_mipmaps) { break; case Texture::TT_3d_texture: case Texture::TT_2d_texture_array: + case Texture::TT_cube_map_array: _glTexStorage3D(target, num_levels, internal_format, width, height, depth); break; } @@ -11343,7 +11371,8 @@ upload_texture_image(CLP(TextureContext) *gtc, bool needs_reload, #endif // OPENGLES #ifndef OPENGLES - case GL_TEXTURE_2D_ARRAY_EXT: + case GL_TEXTURE_2D_ARRAY: + case GL_TEXTURE_CUBE_MAP_ARRAY: if (_supports_2d_texture_array) { if (image_compression == Texture::CM_off) { _glTexSubImage3D(page_target, n - mipmap_bias, 0, 0, 0, width, height, depth, @@ -11525,7 +11554,8 @@ upload_texture_image(CLP(TextureContext) *gtc, bool needs_reload, #endif #ifndef OPENGLES - case GL_TEXTURE_2D_ARRAY_EXT: + case GL_TEXTURE_2D_ARRAY: + case GL_TEXTURE_CUBE_MAP_ARRAY: if (_supports_2d_texture_array) { if (image_compression == Texture::CM_off) { _glTexImage3D(page_target, n - mipmap_bias, internal_format, @@ -11876,7 +11906,7 @@ do_extract_texture_data(CLP(TextureContext) *gtc) { glGetTexLevelParameteriv(page_target, 0, GL_TEXTURE_DEPTH, &depth); } #ifndef OPENGLES - else if (_supports_2d_texture_array && target == GL_TEXTURE_2D_ARRAY_EXT) { + else if (target == GL_TEXTURE_2D_ARRAY || target == GL_TEXTURE_CUBE_MAP_ARRAY) { glGetTexLevelParameteriv(page_target, 0, GL_TEXTURE_DEPTH, &depth); } #endif diff --git a/panda/src/glstuff/glShaderContext_src.cxx b/panda/src/glstuff/glShaderContext_src.cxx index 7a7e89de89..8cfd20119f 100644 --- a/panda/src/glstuff/glShaderContext_src.cxx +++ b/panda/src/glstuff/glShaderContext_src.cxx @@ -1096,18 +1096,22 @@ reflect_uniform(int i, char *name_buffer, GLsizei name_buflen) { case GL_INT_SAMPLER_2D_ARRAY: case GL_INT_SAMPLER_CUBE: case GL_INT_SAMPLER_BUFFER: + case GL_INT_SAMPLER_CUBE_MAP_ARRAY: case GL_UNSIGNED_INT_SAMPLER_1D: case GL_UNSIGNED_INT_SAMPLER_2D: case GL_UNSIGNED_INT_SAMPLER_3D: case GL_UNSIGNED_INT_SAMPLER_CUBE: case GL_UNSIGNED_INT_SAMPLER_2D_ARRAY: case GL_UNSIGNED_INT_SAMPLER_BUFFER: + case GL_UNSIGNED_INT_SAMPLER_CUBE_MAP_ARRAY: case GL_SAMPLER_1D_SHADOW: case GL_SAMPLER_1D: case GL_SAMPLER_CUBE_SHADOW: case GL_SAMPLER_2D_ARRAY: case GL_SAMPLER_2D_ARRAY_SHADOW: case GL_SAMPLER_BUFFER: + case GL_SAMPLER_CUBE_MAP_ARRAY: + case GL_SAMPLER_CUBE_MAP_ARRAY_SHADOW: #endif // !OPENGLES case GL_SAMPLER_2D: case GL_SAMPLER_2D_SHADOW: @@ -1460,6 +1464,26 @@ get_sampler_texture_type(int &out, GLenum param_type) { return false; } + case GL_SAMPLER_CUBE_MAP_ARRAY_SHADOW: + if (!_glgsg->_supports_shadow_filter) { + GLCAT.error() + << "GLSL shader uses shadow sampler, which is unsupported by the driver.\n"; + return false; + } + // Fall through + case GL_INT_SAMPLER_CUBE_MAP_ARRAY: + case GL_UNSIGNED_INT_SAMPLER_CUBE_MAP_ARRAY: + case GL_SAMPLER_CUBE_MAP_ARRAY: + out = Texture::TT_cube_map_array; + if (_glgsg->_supports_cube_map_array) { + return true; + } else { + GLCAT.error() + << "GLSL shader uses cube map array, which is unsupported by the driver.\n"; + return false; + + } + case GL_INT_SAMPLER_BUFFER: case GL_UNSIGNED_INT_SAMPLER_BUFFER: case GL_SAMPLER_BUFFER: diff --git a/panda/src/gobj/shader.cxx b/panda/src/gobj/shader.cxx index 57b5882ea7..7761312d2f 100644 --- a/panda/src/gobj/shader.cxx +++ b/panda/src/gobj/shader.cxx @@ -82,12 +82,14 @@ cp_report_error(ShaderArgInfo &p, const string &msg) { case SAT_mat4x2: tstr = "mat4x2 "; break; case SAT_mat4x3: tstr = "mat4x3 "; break; case SAT_mat4x4: tstr = "mat4x4 "; break; - case SAT_sampler1d: tstr = "sampler1d "; break; - case SAT_sampler2d: tstr = "sampler2d "; break; - case SAT_sampler3d: tstr = "sampler3d "; break; - case SAT_sampler2dArray: tstr = "sampler2dArray "; break; - case SAT_samplercube: tstr = "samplercube "; break; - default: tstr = "unknown "; break; + case SAT_sampler1d: tstr = "sampler1D "; break; + case SAT_sampler2d: tstr = "sampler2D "; break; + case SAT_sampler3d: tstr = "sampler3D "; break; + case SAT_sampler2d_array: tstr = "sampler2DArray "; break; + case SAT_sampler_cube: tstr = "samplerCUBE "; break; + case SAT_sampler_buffer: tstr = "samplerBUF "; break; + case SAT_sampler_cube_array:tstr = "samplerCUBEARRAY "; break; + default: tstr = "unknown "; break; } string cstr = "invalid"; @@ -244,8 +246,10 @@ cp_errchk_parameter_sampler(ShaderArgInfo &p) if ((p._type!=SAT_sampler1d)&& (p._type!=SAT_sampler2d)&& (p._type!=SAT_sampler3d)&& - (p._type!=SAT_sampler2dArray)&& - (p._type!=SAT_samplercube)) { + (p._type!=SAT_sampler2d_array)&& + (p._type!=SAT_sampler_cube)&& + (p._type!=SAT_sampler_buffer)&& + (p._type!=SAT_sampler_cube_array)) { cp_report_error(p, "parameter should have a 'sampler' type"); return false; } @@ -1215,8 +1219,10 @@ compile_parameter(ShaderArgInfo &p, int *arg_dim) { case SAT_sampler1d: bind._desired_type = Texture::TT_1d_texture; break; case SAT_sampler2d: bind._desired_type = Texture::TT_2d_texture; break; case SAT_sampler3d: bind._desired_type = Texture::TT_3d_texture; break; - case SAT_sampler2dArray: bind._desired_type = Texture::TT_2d_texture_array; break; - case SAT_samplercube: bind._desired_type = Texture::TT_cube_map; break; + case SAT_sampler2d_array:bind._desired_type = Texture::TT_2d_texture_array; break; + case SAT_sampler_cube: bind._desired_type = Texture::TT_cube_map; break; + case SAT_sampler_buffer: bind._desired_type = Texture::TT_buffer_texture; break; + case SAT_sampler_cube_array:bind._desired_type = Texture::TT_cube_map_array; break; default: cp_report_error(p, "Invalid type for a tex-parameter"); return false; @@ -1358,7 +1364,7 @@ compile_parameter(ShaderArgInfo &p, int *arg_dim) { _tex_spec.push_back(bind); return true; } - case SAT_sampler2dArray: { + case SAT_sampler2d_array: { ShaderTexSpec bind; bind._id = p._id; bind._name = kinputname; @@ -1366,7 +1372,7 @@ compile_parameter(ShaderArgInfo &p, int *arg_dim) { _tex_spec.push_back(bind); return true; } - case SAT_samplercube: { + case SAT_sampler_cube: { ShaderTexSpec bind; bind._id = p._id; bind._name = kinputname; @@ -1374,6 +1380,22 @@ compile_parameter(ShaderArgInfo &p, int *arg_dim) { _tex_spec.push_back(bind); return true; } + case SAT_sampler_buffer: { + ShaderTexSpec bind; + bind._id = p._id; + bind._name = kinputname; + bind._desired_type = Texture::TT_buffer_texture; + _tex_spec.push_back(bind); + return true; + } + case SAT_sampler_cube_array: { + ShaderTexSpec bind; + bind._id = p._id; + bind._name = kinputname; + bind._desired_type = Texture::TT_cube_map_array; + _tex_spec.push_back(bind); + return true; + } default: cp_report_error(p, "invalid type for non-prefix parameter"); return false; @@ -1460,8 +1482,10 @@ cg_parameter_type(CGparameter p) { case CG_SAMPLER1D: return Shader::SAT_sampler1d; case CG_SAMPLER2D: return Shader::SAT_sampler2d; case CG_SAMPLER3D: return Shader::SAT_sampler3d; - case CG_SAMPLER2DARRAY: return Shader::SAT_sampler2dArray; - case CG_SAMPLERCUBE: return Shader::SAT_samplercube; + case CG_SAMPLER2DARRAY: return Shader::SAT_sampler2d_array; + case CG_SAMPLERCUBE: return Shader::SAT_sampler_cube; + case CG_SAMPLERBUF: return Shader::SAT_sampler_buffer; + case CG_SAMPLERCUBEARRAY:return Shader::SAT_sampler_cube_array; // CG_SAMPLER1DSHADOW and CG_SAMPLER2DSHADOW case 1313: return Shader::SAT_sampler1d; case 1314: return Shader::SAT_sampler2d; diff --git a/panda/src/gobj/shader.h b/panda/src/gobj/shader.h index c0c31afaae..c5b8a3095b 100644 --- a/panda/src/gobj/shader.h +++ b/panda/src/gobj/shader.h @@ -230,8 +230,10 @@ public: SAT_sampler1d, SAT_sampler2d, SAT_sampler3d, - SAT_sampler2dArray, - SAT_samplercube, + SAT_sampler2d_array, + SAT_sampler_cube, + SAT_sampler_buffer, + SAT_sampler_cube_array, SAT_unknown }; diff --git a/panda/src/gobj/texture.I b/panda/src/gobj/texture.I index 6c6b945d2f..24a21e06b4 100644 --- a/panda/src/gobj/texture.I +++ b/panda/src/gobj/texture.I @@ -215,6 +215,38 @@ setup_cube_map(int size, ComponentType component_type, Format format) { setup_texture(TT_cube_map, size, size, 6, component_type, format); } +//////////////////////////////////////////////////////////////////// +// Function: Texture::setup_cube_map_array +// Access: Published +// Description: Sets the texture as cube map array with N cube maps. +// Note that this number is not the same as the z_size. +// Follow up with read() or load() to fill +// the texture properties and image data, or use +// set_clear_color to let the texture be cleared to a +// solid color. +//////////////////////////////////////////////////////////////////// +INLINE void Texture:: +setup_cube_map_array(int num_cube_maps) { + setup_cube_map_array(0, num_cube_maps, T_unsigned_byte, F_rgb); +} + +//////////////////////////////////////////////////////////////////// +// Function: Texture::setup_cube_map_array +// Access: Published +// Description: Sets the texture as cube map array with N cube maps +// with the specified dimensions and format. Follow up +// with set_ram_image() or modify_ram_image() to fill +// the image data, or use set_clear_color to let the +// texture be cleared to a solid color. +// +// The num_cube_maps given here is multiplied by six +// to become the z_size of the image. +//////////////////////////////////////////////////////////////////// +INLINE void Texture:: +setup_cube_map_array(int size, int num_cube_maps, ComponentType component_type, Format format) { + setup_texture(TT_cube_map_array, size, size, num_cube_maps * 6, component_type, format); +} + //////////////////////////////////////////////////////////////////// // Function: Texture::setup_buffer_texture // Access: Published diff --git a/panda/src/gobj/texture.cxx b/panda/src/gobj/texture.cxx index 66bbe6767e..0ee3a85847 100644 --- a/panda/src/gobj/texture.cxx +++ b/panda/src/gobj/texture.cxx @@ -1525,6 +1525,10 @@ write(ostream &out, int indent_level) const { out << "cube map, " << cdata->_x_size << " x " << cdata->_y_size; break; + case TT_cube_map_array: + out << "cube map array, " << cdata->_x_size << " x " << cdata->_y_size << " x " << cdata->_z_size; + break; + case TT_buffer_texture: out << "buffer, " << cdata->_x_size; break; @@ -1928,6 +1932,8 @@ format_texture_type(TextureType tt) { return "2d_texture_array"; case TT_cube_map: return "cube_map"; + case TT_cube_map_array: + return "cube_map_array"; case TT_buffer_texture: return "buffer_texture"; } @@ -1952,6 +1958,8 @@ string_texture_type(const string &str) { return TT_2d_texture_array; } else if (cmp_nocase(str, "cube_map") == 0) { return TT_cube_map; + } else if (cmp_nocase(str, "cube_map_array") == 0) { + return TT_cube_map_array; } else if (cmp_nocase(str, "buffer_texture") == 0) { return TT_buffer_texture; } @@ -4875,11 +4883,17 @@ do_reconsider_image_properties(CData *cdata, int x_size, int y_size, int num_com } #ifndef NDEBUG - if (cdata->_texture_type == TT_1d_texture || - cdata->_texture_type == TT_buffer_texture) { + switch (cdata->_texture_type) { + case TT_1d_texture: + case TT_buffer_texture: nassertr(y_size == 1, false); - } else if (cdata->_texture_type == TT_cube_map) { + break; + case TT_cube_map: + case TT_cube_map_array: nassertr(x_size == y_size, false); + break; + default: + break; } #endif if ((cdata->_x_size != x_size)||(cdata->_y_size != y_size)) { @@ -5074,6 +5088,15 @@ do_setup_texture(CData *cdata, Texture::TextureType texture_type, cdata->_default_sampler.set_wrap_w(SamplerState::WM_clamp); break; + case TT_cube_map_array: + // Cube maps array z_size needs to be a multiple of 6. + nassertv(x_size == y_size && z_size % 6 == 0); + + cdata->_default_sampler.set_wrap_u(SamplerState::WM_clamp); + cdata->_default_sampler.set_wrap_v(SamplerState::WM_clamp); + cdata->_default_sampler.set_wrap_w(SamplerState::WM_clamp); + break; + case TT_buffer_texture: nassertv(y_size == 1 && z_size == 1); break; @@ -5246,6 +5269,7 @@ do_set_z_size(CData *cdata, int z_size) { if (cdata->_z_size != z_size) { nassertv((cdata->_texture_type == Texture::TT_3d_texture) || (cdata->_texture_type == Texture::TT_cube_map && z_size == 6) || + (cdata->_texture_type == Texture::TT_cube_map_array && z_size % 6 == 0) || (cdata->_texture_type == Texture::TT_2d_texture_array) || (z_size == 1)); cdata->_z_size = z_size; cdata->inc_image_modified(); @@ -8113,6 +8137,7 @@ make_this_from_bam(const FactoryParams ¶ms) { break; case TT_2d_texture_array: + case TT_cube_map_array: me = TexturePool::load_2d_texture_array(filename, has_read_mipmaps, options); break; diff --git a/panda/src/gobj/texture.h b/panda/src/gobj/texture.h index d3fc0c4bb8..729f3671ec 100644 --- a/panda/src/gobj/texture.h +++ b/panda/src/gobj/texture.h @@ -84,6 +84,7 @@ PUBLISHED: TT_2d_texture_array, TT_cube_map, TT_buffer_texture, + TT_cube_map_array, }; enum ComponentType { @@ -242,6 +243,9 @@ PUBLISHED: INLINE void setup_2d_texture_array(int z_size = 1); INLINE void setup_2d_texture_array(int x_size, int y_size, int z_size, ComponentType component_type, Format format); + INLINE void setup_cube_map_array(int num_cube_maps); + INLINE void setup_cube_map_array(int size, int num_cube_maps, + ComponentType component_type, Format format); INLINE void setup_buffer_texture(int size, ComponentType component_type, Format format, GeomEnums::UsageHint usage); void generate_normalization_cube_map(int size);