Procházet zdrojové kódy

Support cube map arrays

rdb před 10 roky
rodič
revize
9773fd7969

+ 10 - 0
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

+ 1 - 0
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;

+ 2 - 0
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;
 

+ 36 - 6
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

+ 24 - 0
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:

+ 38 - 14
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;

+ 4 - 2
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
 };
 

+ 32 - 0
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

+ 28 - 3
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 &params) {
         break;
 
       case TT_2d_texture_array:
+      case TT_cube_map_array:
         me = TexturePool::load_2d_texture_array(filename, has_read_mipmaps, options);
         break;
 

+ 4 - 0
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);