mirror of
https://github.com/panda3d/panda3d.git
synced 2025-09-28 07:48:37 -04:00
gobj: Fix TexturePool sharing texture objects when loaded with different properties
Fixes #1047 Closes #1105 Co-authored-by: rdb <git@rdb.name>
This commit is contained in:
parent
3f3c65917b
commit
4fa90bd754
@ -96,6 +96,7 @@
|
||||
#include "uvScrollNode.h"
|
||||
#include "textureStagePool.h"
|
||||
#include "cmath.h"
|
||||
#include "loaderOptions.h"
|
||||
|
||||
#include <ctype.h>
|
||||
#include <algorithm>
|
||||
@ -879,6 +880,7 @@ load_texture(TextureDef &def, EggTexture *egg_tex) {
|
||||
// Check to see if we should reduce the number of channels in the texture.
|
||||
int wanted_channels = 0;
|
||||
bool wanted_alpha = false;
|
||||
|
||||
switch (egg_tex->get_format()) {
|
||||
case EggTexture::F_red:
|
||||
case EggTexture::F_green:
|
||||
@ -932,6 +934,7 @@ load_texture(TextureDef &def, EggTexture *egg_tex) {
|
||||
|
||||
// By convention, the egg loader will preload the simple texture images.
|
||||
LoaderOptions options;
|
||||
|
||||
if (egg_preload_simple_textures) {
|
||||
options.set_texture_flags(options.get_texture_flags() | LoaderOptions::TF_preload_simple);
|
||||
}
|
||||
@ -963,6 +966,15 @@ load_texture(TextureDef &def, EggTexture *egg_tex) {
|
||||
options.set_texture_flags(options.get_texture_flags() | LoaderOptions::TF_allow_compression);
|
||||
}
|
||||
|
||||
if (egg_force_srgb_textures) {
|
||||
options.set_texture_flags(options.get_texture_flags() | LoaderOptions::TF_force_srgb);
|
||||
}
|
||||
|
||||
//The following code sets up all the options for the textures
|
||||
//so that they can be differentiated later in texturePool
|
||||
SamplerState sampler;
|
||||
set_up_loader_options(egg_tex, options, sampler);
|
||||
|
||||
PT(Texture) tex;
|
||||
switch (egg_tex->get_texture_type()) {
|
||||
case EggTexture::TT_unspecified:
|
||||
@ -976,22 +988,26 @@ load_texture(TextureDef &def, EggTexture *egg_tex) {
|
||||
egg_tex->get_alpha_fullpath(),
|
||||
wanted_channels,
|
||||
egg_tex->get_alpha_file_channel(),
|
||||
egg_tex->get_read_mipmaps(), options);
|
||||
egg_tex->get_read_mipmaps(),
|
||||
options, sampler);
|
||||
} else {
|
||||
tex = TexturePool::load_texture(egg_tex->get_fullpath(),
|
||||
wanted_channels,
|
||||
egg_tex->get_read_mipmaps(), options);
|
||||
egg_tex->get_read_mipmaps(),
|
||||
options, sampler);
|
||||
}
|
||||
break;
|
||||
|
||||
case EggTexture::TT_3d_texture:
|
||||
tex = TexturePool::load_3d_texture(egg_tex->get_fullpath(),
|
||||
egg_tex->get_read_mipmaps(), options);
|
||||
egg_tex->get_read_mipmaps(),
|
||||
options, sampler);
|
||||
break;
|
||||
|
||||
case EggTexture::TT_cube_map:
|
||||
tex = TexturePool::load_cube_map(egg_tex->get_fullpath(),
|
||||
egg_tex->get_read_mipmaps(), options);
|
||||
egg_tex->get_read_mipmaps(),
|
||||
options, sampler);
|
||||
break;
|
||||
}
|
||||
|
||||
@ -1030,8 +1046,7 @@ load_texture(TextureDef &def, EggTexture *egg_tex) {
|
||||
egg_tex->set_anisotropic_degree(aux_egg_tex->get_anisotropic_degree());
|
||||
}
|
||||
}
|
||||
|
||||
apply_texture_attributes(tex, egg_tex);
|
||||
check_texture_attributes(tex, sampler, egg_tex);
|
||||
|
||||
// Make a texture stage for the texture.
|
||||
PT(TextureStage) stage = make_texture_stage(egg_tex);
|
||||
@ -1042,18 +1057,26 @@ load_texture(TextureDef &def, EggTexture *egg_tex) {
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
*
|
||||
* Populate the loader options for the incoming texture. These are applied to
|
||||
* the texture and also used to search for the texture. Textures are stored in
|
||||
* texturePool in _textures a map object
|
||||
*/
|
||||
void EggLoader::
|
||||
apply_texture_attributes(Texture *tex, const EggTexture *egg_tex) {
|
||||
if (egg_tex->get_compression_mode() != EggTexture::CM_default) {
|
||||
tex->set_compression(convert_compression_mode(egg_tex->get_compression_mode()));
|
||||
}
|
||||
|
||||
SamplerState sampler;
|
||||
set_up_loader_options(EggTexture *egg_tex, LoaderOptions &options, SamplerState &sampler) {
|
||||
//We store these options and Texture enums, so we need to convert them.
|
||||
options.set_texture_format(convert_format(egg_tex->get_format(), egg_tex->get_env_type()));
|
||||
options.set_texture_compression(convert_compression_mode(egg_tex->get_compression_mode()));
|
||||
options.set_texture_quality(convert_quality_level(egg_tex->get_quality_level()));
|
||||
set_up_sampler(sampler, egg_tex);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set up the sampler object that will be stored in the texture pool. Samplers
|
||||
* store the wrap mode, the min and mag filters, and anisotropic degree
|
||||
*/
|
||||
void EggLoader::
|
||||
set_up_sampler(SamplerState &sampler, const EggTexture *egg_tex) {
|
||||
EggTexture::WrapMode wrap_u = egg_tex->determine_wrap_u();
|
||||
EggTexture::WrapMode wrap_v = egg_tex->determine_wrap_v();
|
||||
EggTexture::WrapMode wrap_w = egg_tex->determine_wrap_w();
|
||||
@ -1185,12 +1208,109 @@ apply_texture_attributes(Texture *tex, const EggTexture *egg_tex) {
|
||||
if (egg_tex->has_lod_bias()) {
|
||||
sampler.set_lod_bias(egg_tex->get_lod_bias());
|
||||
}
|
||||
}
|
||||
|
||||
tex->set_default_sampler(sampler);
|
||||
/**
|
||||
* Now that the texture is fully loaded determine whether there are any
|
||||
* inconsistencies in the texture vs the attributes.
|
||||
*/
|
||||
void EggLoader::
|
||||
check_texture_attributes(Texture *tex, SamplerState sampler, const EggTexture *egg_tex) {
|
||||
switch (tex->get_num_components()) {
|
||||
case 1:
|
||||
switch (egg_tex->get_format()) {
|
||||
case EggTexture::F_unspecified:
|
||||
case EggTexture::F_red:
|
||||
case EggTexture::F_green:
|
||||
case EggTexture::F_blue:
|
||||
case EggTexture::F_alpha:
|
||||
case EggTexture::F_luminance:
|
||||
break;
|
||||
default:
|
||||
egg2pg_cat.warning()
|
||||
<< "Inappropriate format " << egg_tex->get_format()
|
||||
<< " for 1-component texture " << egg_tex->get_name() << "\n";
|
||||
}
|
||||
break;
|
||||
|
||||
case 2:
|
||||
switch (egg_tex->get_format()) {
|
||||
case EggTexture::F_unspecified:
|
||||
case EggTexture::F_luminance_alpha:
|
||||
case EggTexture::F_luminance_alphamask:
|
||||
break;
|
||||
default:
|
||||
egg2pg_cat.error()
|
||||
<< "Inappropriate format " << egg_tex->get_format()
|
||||
<< " for 2-component texture " << egg_tex->get_name() << "\n";
|
||||
}
|
||||
break;
|
||||
|
||||
case 3:
|
||||
// We'll quietly accept RGBA8 for a 3-component texture, since flt2egg
|
||||
// generates these for 3-component as well as for 4-component textures.
|
||||
switch (egg_tex->get_format()) {
|
||||
case EggTexture::F_unspecified:
|
||||
case EggTexture::F_rgb:
|
||||
case EggTexture::F_rgb8:
|
||||
case EggTexture::F_rgba8:
|
||||
case EggTexture::F_rgb5:
|
||||
case EggTexture::F_rgb332:
|
||||
case EggTexture::F_srgb:
|
||||
case EggTexture::F_srgb_alpha:
|
||||
break;
|
||||
case EggTexture::F_rgb12:
|
||||
if (!egg_force_srgb_textures && tex->get_component_width() < 2) {
|
||||
egg2pg_cat.error()
|
||||
<< "Inappropriate format " << egg_tex->get_format()
|
||||
<< " for 8-bit texture " << egg_tex->get_name() << "\n";
|
||||
}
|
||||
break;
|
||||
default:
|
||||
egg2pg_cat.error()
|
||||
<< "Inappropriate format " << egg_tex->get_format()
|
||||
<< " for 3-component texture " << egg_tex->get_name() << "\n";
|
||||
}
|
||||
break;
|
||||
|
||||
case 4:
|
||||
switch (egg_tex->get_format()) {
|
||||
case EggTexture::F_unspecified:
|
||||
case EggTexture::F_rgba:
|
||||
case EggTexture::F_rgbm:
|
||||
case EggTexture::F_rgba8:
|
||||
case EggTexture::F_rgba4:
|
||||
case EggTexture::F_rgba5:
|
||||
case EggTexture::F_srgb_alpha:
|
||||
break;
|
||||
case EggTexture::F_rgba12:
|
||||
if (!egg_force_srgb_textures || tex->get_component_width() < 2) {
|
||||
egg2pg_cat.warning()
|
||||
<< "Inappropriate format " << egg_tex->get_format()
|
||||
<< " for 8-bit texture " << egg_tex->get_name() << "\n";
|
||||
}
|
||||
break;
|
||||
default:
|
||||
egg2pg_cat.error()
|
||||
<< "Inappropriate format " << egg_tex->get_format()
|
||||
<< " for 4-component texture " << egg_tex->get_name() << "\n";
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the Texture::Format enum corresponding to the EggTexture::Format.
|
||||
* Returns 0 if the compression mode is unspecified.
|
||||
*/
|
||||
Texture::Format EggLoader::
|
||||
convert_format(EggTexture::Format format, EggTexture::EnvType env) {
|
||||
bool force_srgb = false;
|
||||
if (egg_force_srgb_textures) {
|
||||
switch (egg_tex->get_env_type()) {
|
||||
switch (env) {
|
||||
case EggTexture::ET_unspecified:
|
||||
case EggTexture::ET_modulate:
|
||||
case EggTexture::ET_decal:
|
||||
@ -1201,186 +1321,103 @@ apply_texture_attributes(Texture *tex, const EggTexture *egg_tex) {
|
||||
case EggTexture::ET_modulate_glow:
|
||||
case EggTexture::ET_modulate_gloss:
|
||||
force_srgb = true;
|
||||
if (egg2pg_cat.is_debug()) {
|
||||
egg2pg_cat.debug()
|
||||
<< "Enabling sRGB format on texture " << egg_tex->get_name() << "\n";
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (tex->get_num_components() == 1) {
|
||||
switch (egg_tex->get_format()) {
|
||||
case EggTexture::F_red:
|
||||
tex->set_format(Texture::F_red);
|
||||
break;
|
||||
case EggTexture::F_green:
|
||||
tex->set_format(Texture::F_green);
|
||||
break;
|
||||
case EggTexture::F_blue:
|
||||
tex->set_format(Texture::F_blue);
|
||||
break;
|
||||
case EggTexture::F_alpha:
|
||||
tex->set_format(Texture::F_alpha);
|
||||
break;
|
||||
case EggTexture::F_luminance:
|
||||
tex->set_format(force_srgb ? Texture::F_sluminance : Texture::F_luminance);
|
||||
break;
|
||||
switch (format) {
|
||||
case EggTexture::F_unspecified:
|
||||
// Gets handled in TexturePool
|
||||
return (Texture::Format)0;
|
||||
|
||||
default:
|
||||
egg2pg_cat.warning()
|
||||
<< "Ignoring inappropriate format " << egg_tex->get_format()
|
||||
<< " for 1-component texture " << egg_tex->get_name() << "\n";
|
||||
case EggTexture::F_red:
|
||||
return Texture::F_red;
|
||||
|
||||
case EggTexture::F_unspecified:
|
||||
if (force_srgb) {
|
||||
tex->set_format(Texture::F_sluminance);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case EggTexture::F_green:
|
||||
return Texture::F_green;
|
||||
|
||||
} else if (tex->get_num_components() == 2) {
|
||||
switch (egg_tex->get_format()) {
|
||||
case EggTexture::F_luminance_alpha:
|
||||
tex->set_format(force_srgb ? Texture::F_sluminance_alpha : Texture::F_luminance_alpha);
|
||||
break;
|
||||
case EggTexture::F_blue:
|
||||
return Texture::F_blue;
|
||||
|
||||
case EggTexture::F_luminance_alphamask:
|
||||
tex->set_format(force_srgb ? Texture::F_sluminance_alpha : Texture::F_luminance_alphamask);
|
||||
break;
|
||||
case EggTexture::F_alpha:
|
||||
return Texture::F_alpha;
|
||||
|
||||
default:
|
||||
egg2pg_cat.warning()
|
||||
<< "Ignoring inappropriate format " << egg_tex->get_format()
|
||||
<< " for 2-component texture " << egg_tex->get_name() << "\n";
|
||||
case EggTexture::F_luminance:
|
||||
return (force_srgb ? Texture::F_sluminance : Texture::F_luminance);
|
||||
|
||||
case EggTexture::F_unspecified:
|
||||
if (force_srgb) {
|
||||
tex->set_format(Texture::F_sluminance_alpha);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case EggTexture::F_rgba:
|
||||
return (force_srgb ? Texture::F_srgb_alpha : Texture::F_rgba);
|
||||
|
||||
} else if (tex->get_num_components() == 3) {
|
||||
switch (egg_tex->get_format()) {
|
||||
case EggTexture::F_rgb:
|
||||
tex->set_format(force_srgb ? Texture::F_srgb : Texture::F_rgb);
|
||||
break;
|
||||
case EggTexture::F_rgb12:
|
||||
if (force_srgb) {
|
||||
tex->set_format(Texture::F_srgb);
|
||||
} else if (tex->get_component_width() >= 2) {
|
||||
// Only do this if the component width supports it.
|
||||
tex->set_format(Texture::F_rgb12);
|
||||
} else {
|
||||
egg2pg_cat.warning()
|
||||
<< "Ignoring inappropriate format " << egg_tex->get_format()
|
||||
<< " for 8-bit texture " << egg_tex->get_name() << "\n";
|
||||
}
|
||||
break;
|
||||
case EggTexture::F_rgb8:
|
||||
case EggTexture::F_rgba8:
|
||||
// We'll quietly accept RGBA8 for a 3-component texture, since flt2egg
|
||||
// generates these for 3-component as well as for 4-component textures.
|
||||
tex->set_format(force_srgb ? Texture::F_srgb : Texture::F_rgb8);
|
||||
break;
|
||||
case EggTexture::F_rgb5:
|
||||
tex->set_format(force_srgb ? Texture::F_srgb : Texture::F_rgb5);
|
||||
break;
|
||||
case EggTexture::F_rgb332:
|
||||
tex->set_format(force_srgb ? Texture::F_srgb : Texture::F_rgb332);
|
||||
break;
|
||||
case EggTexture::F_srgb:
|
||||
case EggTexture::F_srgb_alpha:
|
||||
tex->set_format(Texture::F_srgb);
|
||||
break;
|
||||
case EggTexture::F_rgbm:
|
||||
return (force_srgb ? Texture::F_srgb_alpha : Texture::F_rgbm);
|
||||
|
||||
default:
|
||||
egg2pg_cat.warning()
|
||||
<< "Ignoring inappropriate format " << egg_tex->get_format()
|
||||
<< " for 3-component texture " << egg_tex->get_name() << "\n";
|
||||
case EggTexture::F_rgba12:
|
||||
return (force_srgb ? Texture::F_srgb_alpha : Texture::F_rgba12);
|
||||
|
||||
case EggTexture::F_unspecified:
|
||||
if (force_srgb) {
|
||||
tex->set_format(Texture::F_srgb);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case EggTexture::F_rgba8:
|
||||
return (force_srgb ? Texture::F_srgb_alpha : Texture::F_rgba8);
|
||||
|
||||
} else if (tex->get_num_components() == 4) {
|
||||
switch (egg_tex->get_format()) {
|
||||
case EggTexture::F_rgba:
|
||||
tex->set_format(force_srgb ? Texture::F_srgb_alpha : Texture::F_rgba);
|
||||
break;
|
||||
case EggTexture::F_rgbm:
|
||||
tex->set_format(force_srgb ? Texture::F_srgb_alpha : Texture::F_rgbm);
|
||||
break;
|
||||
case EggTexture::F_rgba12:
|
||||
if (force_srgb) {
|
||||
tex->set_format(Texture::F_srgb_alpha);
|
||||
} else if (tex->get_component_width() >= 2) {
|
||||
// Only do this if the component width supports it.
|
||||
tex->set_format(force_srgb ? Texture::F_srgb_alpha : Texture::F_rgba12);
|
||||
} else {
|
||||
egg2pg_cat.warning()
|
||||
<< "Ignoring inappropriate format " << egg_tex->get_format()
|
||||
<< " for 8-bit texture " << egg_tex->get_name() << "\n";
|
||||
}
|
||||
break;
|
||||
case EggTexture::F_rgba8:
|
||||
tex->set_format(force_srgb ? Texture::F_srgb_alpha : Texture::F_rgba8);
|
||||
break;
|
||||
case EggTexture::F_rgba4:
|
||||
tex->set_format(force_srgb ? Texture::F_srgb_alpha : Texture::F_rgba4);
|
||||
break;
|
||||
case EggTexture::F_rgba5:
|
||||
tex->set_format(force_srgb ? Texture::F_srgb_alpha : Texture::F_rgba5);
|
||||
break;
|
||||
case EggTexture::F_srgb_alpha:
|
||||
tex->set_format(Texture::F_srgb_alpha);
|
||||
break;
|
||||
case EggTexture::F_rgba4:
|
||||
return (force_srgb ? Texture::F_srgb_alpha : Texture::F_rgba4);
|
||||
|
||||
default:
|
||||
egg2pg_cat.warning()
|
||||
<< "Ignoring inappropriate format " << egg_tex->get_format()
|
||||
<< " for 4-component texture " << egg_tex->get_name() << "\n";
|
||||
case EggTexture::F_rgba5:
|
||||
return (force_srgb ? Texture::F_srgb : Texture::F_rgba5);
|
||||
|
||||
case EggTexture::F_unspecified:
|
||||
if (force_srgb) {
|
||||
tex->set_format(Texture::F_srgb_alpha);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case EggTexture::F_rgb:
|
||||
return (force_srgb ? Texture::F_srgb : Texture::F_rgb);
|
||||
|
||||
case EggTexture::F_rgb12:
|
||||
return (force_srgb ? Texture::F_srgb : Texture::F_rgb12);
|
||||
|
||||
case EggTexture::F_rgb8:
|
||||
return (force_srgb ? Texture::F_srgb : Texture::F_rgb8);
|
||||
|
||||
case EggTexture::F_rgb5:
|
||||
return (force_srgb ? Texture::F_srgb : Texture::F_rgb5);
|
||||
|
||||
case EggTexture::F_rgb332:
|
||||
return (force_srgb ? Texture::F_srgb : Texture::F_rgb332);
|
||||
|
||||
case EggTexture::F_luminance_alpha:
|
||||
return (force_srgb ? Texture::F_sluminance_alpha : Texture::F_luminance_alpha);
|
||||
|
||||
case EggTexture::F_luminance_alphamask:
|
||||
return (force_srgb ? Texture::F_sluminance_alpha : Texture::F_luminance_alphamask);
|
||||
|
||||
case EggTexture::F_srgb:
|
||||
return Texture::F_srgb;
|
||||
|
||||
case EggTexture::F_srgb_alpha:
|
||||
return Texture::F_srgb_alpha;
|
||||
}
|
||||
|
||||
if (force_srgb && tex->get_format() != Texture::F_alpha &&
|
||||
!Texture::is_srgb(tex->get_format())) {
|
||||
egg2pg_cat.warning()
|
||||
<< "Unable to enable sRGB format on texture " << egg_tex->get_name()
|
||||
<< " with specified format " << egg_tex->get_format() << "\n";
|
||||
}
|
||||
egg2pg_cat.warning()
|
||||
<< "Unexpected format scalar: " << (int)format << "\n";
|
||||
return (Texture::Format)0;
|
||||
}
|
||||
|
||||
switch (egg_tex->get_quality_level()) {
|
||||
/**
|
||||
* Returns the Texture::QualityLevel enum corresponding to the
|
||||
* EggTexture::QualityLevel. Returns QL_default if the quality level is
|
||||
* unspecified.
|
||||
*/
|
||||
Texture::QualityLevel EggLoader::
|
||||
convert_quality_level(EggTexture::QualityLevel quality) {
|
||||
switch (quality) {
|
||||
case EggTexture::QL_unspecified:
|
||||
case EggTexture::QL_default:
|
||||
tex->set_quality_level(Texture::QL_default);
|
||||
break;
|
||||
return Texture::QL_default;
|
||||
|
||||
case EggTexture::QL_fastest:
|
||||
tex->set_quality_level(Texture::QL_fastest);
|
||||
break;
|
||||
|
||||
case EggTexture::QL_normal:
|
||||
tex->set_quality_level(Texture::QL_normal);
|
||||
break;
|
||||
return Texture::QL_fastest;
|
||||
|
||||
case EggTexture::QL_best:
|
||||
tex->set_quality_level(Texture::QL_best);
|
||||
break;
|
||||
return Texture::QL_best;
|
||||
|
||||
case EggTexture::QL_normal:
|
||||
return Texture::QL_normal;
|
||||
}
|
||||
return Texture::QL_default;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -118,7 +118,11 @@ private:
|
||||
|
||||
void load_textures();
|
||||
bool load_texture(TextureDef &def, EggTexture *egg_tex);
|
||||
void apply_texture_attributes(Texture *tex, const EggTexture *egg_tex);
|
||||
void set_up_loader_options(EggTexture *egg_tex, LoaderOptions &options, SamplerState &sampler);
|
||||
void set_up_sampler(SamplerState &sampler, const EggTexture *egg_tex);
|
||||
void check_texture_attributes(Texture *tex, SamplerState sampler, const EggTexture *egg_tex);
|
||||
Texture::Format convert_format(EggTexture::Format format, EggTexture::EnvType env);
|
||||
Texture::QualityLevel convert_quality_level(EggTexture::QualityLevel mode);
|
||||
Texture::CompressionMode convert_compression_mode(EggTexture::CompressionMode compression_mode) const;
|
||||
SamplerState::WrapMode convert_wrap_mode(EggTexture::WrapMode wrap_mode) const;
|
||||
PT(TextureStage) make_texture_stage(const EggTexture *egg_tex);
|
||||
|
@ -20,9 +20,8 @@
|
||||
#include "luse.h"
|
||||
#include "memoryBase.h"
|
||||
#include "numeric_types.h"
|
||||
#include "bamReader.h"
|
||||
#include "config_gobj.h"
|
||||
|
||||
class BamReader;
|
||||
class FactoryParams;
|
||||
class GraphicsStateGuardianBase;
|
||||
class PreparedGraphicsObjects;
|
||||
|
@ -68,9 +68,9 @@ get_texture(const Filename &filename, const Filename &alpha_filename,
|
||||
*/
|
||||
INLINE Texture *TexturePool::
|
||||
load_texture(const Filename &filename, int primary_file_num_channels,
|
||||
bool read_mipmaps, const LoaderOptions &options) {
|
||||
bool read_mipmaps, const LoaderOptions &options, const SamplerState &sampler) {
|
||||
return get_global_ptr()->ns_load_texture(filename, primary_file_num_channels,
|
||||
read_mipmaps, options);
|
||||
read_mipmaps, options, sampler);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -86,11 +86,11 @@ load_texture(const Filename &filename, int primary_file_num_channels,
|
||||
INLINE Texture *TexturePool::
|
||||
load_texture(const Filename &filename, const Filename &alpha_filename,
|
||||
int primary_file_num_channels, int alpha_file_channel,
|
||||
bool read_mipmaps, const LoaderOptions &options) {
|
||||
bool read_mipmaps, const LoaderOptions &options, const SamplerState &sampler) {
|
||||
return get_global_ptr()->ns_load_texture(filename, alpha_filename,
|
||||
primary_file_num_channels,
|
||||
alpha_file_channel,
|
||||
read_mipmaps, options);
|
||||
read_mipmaps, options, sampler);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -105,9 +105,9 @@ load_texture(const Filename &filename, const Filename &alpha_filename,
|
||||
*/
|
||||
INLINE Texture *TexturePool::
|
||||
load_3d_texture(const Filename &filename_pattern, bool read_mipmaps,
|
||||
const LoaderOptions &options) {
|
||||
const LoaderOptions &options, const SamplerState &sampler) {
|
||||
return get_global_ptr()->ns_load_3d_texture(filename_pattern, read_mipmaps,
|
||||
options);
|
||||
options, sampler);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -122,9 +122,9 @@ load_3d_texture(const Filename &filename_pattern, bool read_mipmaps,
|
||||
*/
|
||||
INLINE Texture *TexturePool::
|
||||
load_2d_texture_array(const Filename &filename_pattern, bool read_mipmaps,
|
||||
const LoaderOptions &options) {
|
||||
const LoaderOptions &options, const SamplerState &sampler) {
|
||||
return get_global_ptr()->ns_load_2d_texture_array(filename_pattern, read_mipmaps,
|
||||
options);
|
||||
options, sampler);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -139,9 +139,9 @@ load_2d_texture_array(const Filename &filename_pattern, bool read_mipmaps,
|
||||
*/
|
||||
INLINE Texture *TexturePool::
|
||||
load_cube_map(const Filename &filename_pattern, bool read_mipmaps,
|
||||
const LoaderOptions &options) {
|
||||
const LoaderOptions &options, const SamplerState &sampler) {
|
||||
return get_global_ptr()->ns_load_cube_map(filename_pattern, read_mipmaps,
|
||||
options);
|
||||
options, sampler);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -333,11 +333,31 @@ unregister_filter(TexturePoolFilter *tex_filter) {
|
||||
return get_global_ptr()->ns_unregister_filter(tex_filter);
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
INLINE TexturePool::LookupKey::
|
||||
LookupKey(Texture::TextureType texture_type,
|
||||
int primary_file_num_channels, int alpha_file_channel,
|
||||
const LoaderOptions &options, const SamplerState &sampler) :
|
||||
_primary_file_num_channels(primary_file_num_channels),
|
||||
_alpha_file_channel(alpha_file_channel),
|
||||
_texture_type(texture_type),
|
||||
_texture_format((Texture::Format)options.get_texture_format()),
|
||||
_texture_compress((Texture::CompressionMode)options.get_texture_compression()),
|
||||
_texture_quality((Texture::QualityLevel)options.get_texture_quality()),
|
||||
_texture_sampler(sampler),
|
||||
_force_srgb(options.get_texture_flags() & LoaderOptions::TF_force_srgb) {
|
||||
}
|
||||
|
||||
/**
|
||||
* Defines relative ordering between LookupKey instances.
|
||||
*/
|
||||
INLINE bool TexturePool::LookupKey::
|
||||
operator < (const LookupKey &other) const {
|
||||
if (_texture_type != other._texture_type) {
|
||||
return _texture_type < other._texture_type;
|
||||
}
|
||||
if (_fullpath != other._fullpath) {
|
||||
return _fullpath < other._fullpath;
|
||||
}
|
||||
@ -350,5 +370,17 @@ operator < (const LookupKey &other) const {
|
||||
if (_alpha_file_channel != other._alpha_file_channel) {
|
||||
return _alpha_file_channel < other._alpha_file_channel;
|
||||
}
|
||||
return _texture_type < other._texture_type;
|
||||
if (_texture_format != other._texture_format) {
|
||||
return _texture_format < other._texture_format;
|
||||
}
|
||||
if (_texture_compress != other._texture_compress) {
|
||||
return _texture_compress < other._texture_compress;
|
||||
}
|
||||
if (_texture_quality != other._texture_quality) {
|
||||
return _texture_quality < other._texture_quality;
|
||||
}
|
||||
if (_texture_sampler != other._texture_sampler) {
|
||||
return _texture_sampler < other._texture_sampler;
|
||||
}
|
||||
return _force_srgb < other._force_srgb;
|
||||
}
|
||||
|
@ -334,9 +334,9 @@ ns_get_texture(const Filename &orig_filename,
|
||||
*/
|
||||
Texture *TexturePool::
|
||||
ns_load_texture(const Filename &orig_filename, int primary_file_num_channels,
|
||||
bool read_mipmaps, const LoaderOptions &options) {
|
||||
LookupKey key;
|
||||
key._primary_file_num_channels = primary_file_num_channels;
|
||||
bool read_mipmaps, const LoaderOptions &options, const SamplerState &sampler) {
|
||||
|
||||
LookupKey key(Texture::TT_2d_texture, primary_file_num_channels, 0, options, sampler);
|
||||
{
|
||||
MutexHolder holder(_lock);
|
||||
resolve_filename(key._fullpath, orig_filename, read_mipmaps, options);
|
||||
@ -484,7 +484,7 @@ ns_load_texture(const Filename &orig_filename, int primary_file_num_channels,
|
||||
if (use_filters) {
|
||||
tex = post_load(tex);
|
||||
}
|
||||
|
||||
apply_texture_attributes(tex, options, sampler);
|
||||
return tex;
|
||||
}
|
||||
|
||||
@ -496,15 +496,13 @@ ns_load_texture(const Filename &orig_filename,
|
||||
const Filename &orig_alpha_filename,
|
||||
int primary_file_num_channels,
|
||||
int alpha_file_channel,
|
||||
bool read_mipmaps, const LoaderOptions &options) {
|
||||
bool read_mipmaps, const LoaderOptions &options, const SamplerState &sampler) {
|
||||
if (!_fake_texture_image.empty()) {
|
||||
return ns_load_texture(_fake_texture_image, primary_file_num_channels,
|
||||
read_mipmaps, options);
|
||||
read_mipmaps, options, sampler);
|
||||
}
|
||||
|
||||
LookupKey key;
|
||||
key._primary_file_num_channels = primary_file_num_channels;
|
||||
key._alpha_file_channel = alpha_file_channel;
|
||||
LookupKey key(Texture::TT_2d_texture, primary_file_num_channels, alpha_file_channel, options, sampler);
|
||||
{
|
||||
MutexHolder holder(_lock);
|
||||
resolve_filename(key._fullpath, orig_filename, read_mipmaps, options);
|
||||
@ -619,7 +617,7 @@ ns_load_texture(const Filename &orig_filename,
|
||||
if (use_filters) {
|
||||
tex = post_load(tex);
|
||||
}
|
||||
|
||||
apply_texture_attributes(tex, options, sampler);
|
||||
return tex;
|
||||
}
|
||||
|
||||
@ -628,12 +626,11 @@ ns_load_texture(const Filename &orig_filename,
|
||||
*/
|
||||
Texture *TexturePool::
|
||||
ns_load_3d_texture(const Filename &filename_pattern,
|
||||
bool read_mipmaps, const LoaderOptions &options) {
|
||||
bool read_mipmaps, const LoaderOptions &options, const SamplerState &sampler) {
|
||||
Filename orig_filename(filename_pattern);
|
||||
orig_filename.set_pattern(true);
|
||||
|
||||
LookupKey key;
|
||||
key._texture_type = Texture::TT_3d_texture;
|
||||
LookupKey key(Texture::TT_3d_texture, 0, 0, options, sampler);
|
||||
{
|
||||
MutexHolder holder(_lock);
|
||||
resolve_filename(key._fullpath, orig_filename, read_mipmaps, options);
|
||||
@ -722,6 +719,7 @@ ns_load_3d_texture(const Filename &filename_pattern,
|
||||
}
|
||||
|
||||
nassertr(!tex->get_fullpath().empty(), tex);
|
||||
apply_texture_attributes(tex, options, sampler);
|
||||
return tex;
|
||||
}
|
||||
|
||||
@ -730,12 +728,11 @@ ns_load_3d_texture(const Filename &filename_pattern,
|
||||
*/
|
||||
Texture *TexturePool::
|
||||
ns_load_2d_texture_array(const Filename &filename_pattern,
|
||||
bool read_mipmaps, const LoaderOptions &options) {
|
||||
bool read_mipmaps, const LoaderOptions &options, const SamplerState &sampler) {
|
||||
Filename orig_filename(filename_pattern);
|
||||
orig_filename.set_pattern(true);
|
||||
|
||||
LookupKey key;
|
||||
key._texture_type = Texture::TT_2d_texture_array;
|
||||
LookupKey key(Texture::TT_2d_texture_array, 0, 0, options, sampler);
|
||||
{
|
||||
MutexHolder holder(_lock);
|
||||
resolve_filename(key._fullpath, orig_filename, read_mipmaps, options);
|
||||
@ -824,6 +821,7 @@ ns_load_2d_texture_array(const Filename &filename_pattern,
|
||||
}
|
||||
|
||||
nassertr(!tex->get_fullpath().empty(), tex);
|
||||
apply_texture_attributes(tex, options, sampler);
|
||||
return tex;
|
||||
}
|
||||
|
||||
@ -832,12 +830,11 @@ ns_load_2d_texture_array(const Filename &filename_pattern,
|
||||
*/
|
||||
Texture *TexturePool::
|
||||
ns_load_cube_map(const Filename &filename_pattern, bool read_mipmaps,
|
||||
const LoaderOptions &options) {
|
||||
const LoaderOptions &options, const SamplerState &sampler) {
|
||||
Filename orig_filename(filename_pattern);
|
||||
orig_filename.set_pattern(true);
|
||||
|
||||
LookupKey key;
|
||||
key._texture_type = Texture::TT_cube_map;
|
||||
LookupKey key(Texture::TT_cube_map, 0, 0, options, sampler);
|
||||
{
|
||||
MutexHolder holder(_lock);
|
||||
resolve_filename(key._fullpath, orig_filename, read_mipmaps, options);
|
||||
@ -926,6 +923,7 @@ ns_load_cube_map(const Filename &filename_pattern, bool read_mipmaps,
|
||||
}
|
||||
|
||||
nassertr(!tex->get_fullpath().empty(), tex);
|
||||
apply_texture_attributes(tex, options, sampler);
|
||||
return tex;
|
||||
}
|
||||
|
||||
@ -947,6 +945,49 @@ ns_get_normalization_cube_map(int size) {
|
||||
return _normalization_cube_map;
|
||||
}
|
||||
|
||||
/**
|
||||
* The texture is loaded, apply any atributes that were sent in with the texture through LoaderOptions
|
||||
* and Sampler State
|
||||
*/
|
||||
void TexturePool::
|
||||
apply_texture_attributes(Texture *tex, const LoaderOptions &options, const SamplerState &sampler) {
|
||||
int format = options.get_texture_format();
|
||||
if (format != 0) {
|
||||
tex->set_format((Texture::Format)format);
|
||||
}
|
||||
else if (options.get_texture_flags() & LoaderOptions::TF_force_srgb) {
|
||||
int num_components = tex->get_num_components();
|
||||
if (num_components == 1) {
|
||||
if (!Texture::has_alpha(tex->get_format())) {
|
||||
tex->set_format(Texture::F_sluminance);
|
||||
}
|
||||
}
|
||||
else if (num_components == 2 && Texture::has_alpha(tex->get_format())) {
|
||||
tex->set_format(Texture::F_sluminance_alpha);
|
||||
}
|
||||
else if (num_components == 3) {
|
||||
tex->set_format(Texture::F_srgb);
|
||||
}
|
||||
else if (num_components == 4) {
|
||||
tex->set_format(Texture::F_srgb_alpha);
|
||||
}
|
||||
else {
|
||||
gobj_cat.warning()
|
||||
<< "Unable to enable sRGB format on texture " << tex->get_name()
|
||||
<< " with specified format " << tex->get_format() << "\n";
|
||||
}
|
||||
}
|
||||
int compression = options.get_texture_compression();
|
||||
if (compression != 0) {
|
||||
tex->set_compression((Texture::CompressionMode)compression);
|
||||
}
|
||||
int quality = options.get_texture_quality();
|
||||
if (quality != 0) {
|
||||
tex->set_quality_level((Texture::QualityLevel)quality);
|
||||
}
|
||||
tex->set_default_sampler(sampler);
|
||||
}
|
||||
|
||||
/**
|
||||
* The nonstatic implementation of get_alpha_scale_map().
|
||||
*/
|
||||
|
@ -49,22 +49,27 @@ PUBLISHED:
|
||||
BLOCKING INLINE static Texture *load_texture(const Filename &filename,
|
||||
int primary_file_num_channels = 0,
|
||||
bool read_mipmaps = false,
|
||||
const LoaderOptions &options = LoaderOptions());
|
||||
const LoaderOptions &options = LoaderOptions(),
|
||||
const SamplerState &sampler = SamplerState());
|
||||
BLOCKING INLINE static Texture *load_texture(const Filename &filename,
|
||||
const Filename &alpha_filename,
|
||||
int primary_file_num_channels = 0,
|
||||
int alpha_file_channel = 0,
|
||||
bool read_mipmaps = false,
|
||||
const LoaderOptions &options = LoaderOptions());
|
||||
const LoaderOptions &options = LoaderOptions(),
|
||||
const SamplerState &sampler = SamplerState());
|
||||
BLOCKING INLINE static Texture *load_3d_texture(const Filename &filename_pattern,
|
||||
bool read_mipmaps = false,
|
||||
const LoaderOptions &options = LoaderOptions());
|
||||
const LoaderOptions &options = LoaderOptions(),
|
||||
const SamplerState &sampler = SamplerState());
|
||||
BLOCKING INLINE static Texture *load_2d_texture_array(const Filename &filename_pattern,
|
||||
bool read_mipmaps = false,
|
||||
const LoaderOptions &options = LoaderOptions());
|
||||
const LoaderOptions &options = LoaderOptions(),
|
||||
const SamplerState &sampler = SamplerState());
|
||||
BLOCKING INLINE static Texture *load_cube_map(const Filename &filename_pattern,
|
||||
bool read_mipmaps = false,
|
||||
const LoaderOptions &options = LoaderOptions());
|
||||
const LoaderOptions &options = LoaderOptions(),
|
||||
const SamplerState &sampler = SamplerState());
|
||||
|
||||
INLINE static Texture *get_normalization_cube_map(int size);
|
||||
INLINE static Texture *get_alpha_scale_map();
|
||||
@ -128,22 +133,31 @@ private:
|
||||
Texture *ns_load_texture(const Filename &orig_filename,
|
||||
int primary_file_num_channels,
|
||||
bool read_mipmaps,
|
||||
const LoaderOptions &options);
|
||||
const LoaderOptions &options,
|
||||
const SamplerState &sampler);
|
||||
Texture *ns_load_texture(const Filename &orig_filename,
|
||||
const Filename &orig_alpha_filename,
|
||||
int primary_file_num_channels,
|
||||
int alpha_file_channel,
|
||||
bool read_mipmaps,
|
||||
const LoaderOptions &options);
|
||||
const LoaderOptions &options,
|
||||
const SamplerState &sampler);
|
||||
Texture *ns_load_3d_texture(const Filename &filename_pattern,
|
||||
bool read_mipmaps,
|
||||
const LoaderOptions &options);
|
||||
const LoaderOptions &options,
|
||||
const SamplerState &sampler);
|
||||
Texture *ns_load_2d_texture_array(const Filename &filename_pattern,
|
||||
bool read_mipmaps,
|
||||
const LoaderOptions &options);
|
||||
const LoaderOptions &options,
|
||||
const SamplerState &sampler);
|
||||
Texture *ns_load_cube_map(const Filename &filename_pattern,
|
||||
bool read_mipmaps,
|
||||
const LoaderOptions &options);
|
||||
const LoaderOptions &options,
|
||||
const SamplerState &sampler);
|
||||
|
||||
void apply_texture_attributes(Texture *tex, const LoaderOptions &options,
|
||||
const SamplerState &sampler);
|
||||
|
||||
Texture *ns_get_normalization_cube_map(int size);
|
||||
Texture *ns_get_alpha_scale_map();
|
||||
|
||||
@ -187,14 +201,25 @@ private:
|
||||
Mutex _filter_lock;
|
||||
|
||||
struct LookupKey {
|
||||
LookupKey() = default;
|
||||
INLINE LookupKey(Texture::TextureType texture_type,
|
||||
int primary_file_num_channels, int alpha_file_channel,
|
||||
const LoaderOptions &options, const SamplerState &sampler);
|
||||
|
||||
Filename _fullpath;
|
||||
Filename _alpha_fullpath;
|
||||
int _primary_file_num_channels = 0;
|
||||
int _alpha_file_channel = 0;
|
||||
Texture::Format _texture_format = (Texture::Format)0;
|
||||
Texture::QualityLevel _texture_quality = Texture::QL_default;
|
||||
Texture::CompressionMode _texture_compress = Texture::CM_default;
|
||||
SamplerState _texture_sampler;
|
||||
Texture::TextureType _texture_type = Texture::TT_2d_texture;
|
||||
bool _force_srgb = false;
|
||||
|
||||
INLINE bool operator < (const LookupKey &other) const;
|
||||
};
|
||||
|
||||
typedef pmap<LookupKey, PT(Texture)> Textures;
|
||||
Textures _textures;
|
||||
typedef pmap<Filename, Filename> RelpathLookup;
|
||||
|
@ -18,6 +18,9 @@ constexpr LoaderOptions::
|
||||
LoaderOptions(int flags, int texture_flags) :
|
||||
_flags(flags),
|
||||
_texture_flags(texture_flags),
|
||||
_texture_format(0),
|
||||
_texture_compress(0),
|
||||
_texture_quality(0),
|
||||
_texture_num_views(0),
|
||||
_auto_texture_scale(ATS_unspecified)
|
||||
{
|
||||
@ -55,6 +58,55 @@ get_texture_flags() const {
|
||||
return _texture_flags;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the texture format
|
||||
*/
|
||||
|
||||
INLINE void LoaderOptions::
|
||||
set_texture_format(int format) {
|
||||
_texture_format = format;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the texture format
|
||||
*/
|
||||
INLINE int LoaderOptions::
|
||||
get_texture_format() const {
|
||||
return _texture_format;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the texture compression
|
||||
*/
|
||||
INLINE void LoaderOptions::
|
||||
set_texture_compression(int compress) {
|
||||
_texture_compress = compress;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the texture compression
|
||||
*/
|
||||
INLINE int LoaderOptions::
|
||||
get_texture_compression() const {
|
||||
return _texture_compress;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the texture quality
|
||||
*/
|
||||
INLINE void LoaderOptions::
|
||||
set_texture_quality(int quality) {
|
||||
_texture_quality = quality;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the texture quality
|
||||
*/
|
||||
INLINE int LoaderOptions::
|
||||
get_texture_quality() const {
|
||||
return _texture_quality;
|
||||
}
|
||||
|
||||
/**
|
||||
* Specifies the expected number of views to load for the texture. This is
|
||||
* ignored unless TF_multiview is included in texture_flags. This must be
|
||||
|
@ -24,6 +24,9 @@ LoaderOptions::
|
||||
LoaderOptions(int flags) :
|
||||
_flags(flags),
|
||||
_texture_flags(0),
|
||||
_texture_format(0),
|
||||
_texture_compress(0),
|
||||
_texture_quality(0),
|
||||
_texture_num_views(0),
|
||||
_auto_texture_scale(ATS_unspecified)
|
||||
{
|
||||
|
@ -47,6 +47,7 @@ PUBLISHED:
|
||||
TF_float = 0x0100, // Load as a floating-point (depth) texture
|
||||
TF_allow_compression = 0x0200, // Consider compressing RAM image
|
||||
TF_no_filters = 0x0400, // disallow using texture pool filters
|
||||
TF_force_srgb = 0x0800, // Force the texture to have an sRGB format
|
||||
};
|
||||
|
||||
explicit LoaderOptions(int flags = LF_search | LF_report_errors);
|
||||
@ -58,6 +59,13 @@ PUBLISHED:
|
||||
|
||||
INLINE void set_texture_flags(int flags);
|
||||
INLINE int get_texture_flags() const;
|
||||
INLINE void set_texture_format(int format);
|
||||
INLINE int get_texture_format() const;
|
||||
INLINE void set_texture_compression(int compress);
|
||||
INLINE int get_texture_compression() const;
|
||||
INLINE void set_texture_quality(int quality);
|
||||
INLINE int get_texture_quality() const;
|
||||
|
||||
INLINE void set_texture_num_views(int num_views);
|
||||
INLINE int get_texture_num_views() const;
|
||||
MAKE_PROPERTY(texture_flags, get_texture_flags, set_texture_flags);
|
||||
@ -78,6 +86,9 @@ private:
|
||||
const std::string &flag_name, int flag) const;
|
||||
int _flags;
|
||||
int _texture_flags;
|
||||
int _texture_format;
|
||||
int _texture_compress;
|
||||
int _texture_quality;
|
||||
int _texture_num_views;
|
||||
AutoTextureScale _auto_texture_scale;
|
||||
};
|
||||
|
Loading…
x
Reference in New Issue
Block a user