Support cube map arrays

This commit is contained in:
rdb 2015-08-11 17:08:31 +02:00
parent a24531ff7b
commit 9773fd7969
10 changed files with 179 additions and 25 deletions

View File

@ -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

View File

@ -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;

View File

@ -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;

View File

@ -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

View File

@ -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:

View File

@ -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;

View File

@ -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
};

View File

@ -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

View File

@ -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;

View File

@ -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);