mirror of https://github.com/axmolengine/axmol.git
[Feature] fix mipmap issues (#19519)
This commit is contained in:
parent
bb60c173a1
commit
688592b175
|
@ -271,8 +271,7 @@ bool Material::parseSampler(backend::ProgramState* programState, Properties* sam
|
|||
bool usemipmap = false;
|
||||
const char* mipmap = getOptionalString(samplerProperties, "mipmap", "false");
|
||||
if (mipmap && strcasecmp(mipmap, "true")==0) {
|
||||
// TODO coulsonwang
|
||||
// texture->generateMipmap();
|
||||
texture->generateMipmap();
|
||||
usemipmap = true;
|
||||
}
|
||||
|
||||
|
|
|
@ -913,18 +913,15 @@ void Texture2D::setTexParameters(const Texture2D::TexParams &desc)
|
|||
_texture->updateSamplerDescriptor(desc);
|
||||
}
|
||||
|
||||
// TODO coulsonwang
|
||||
//// implementation Texture2D (GLFilter)
|
||||
void Texture2D::generateMipmap()
|
||||
{
|
||||
// CCASSERT(_pixelsWide == ccNextPOT(_pixelsWide) && _pixelsHigh == ccNextPOT(_pixelsHigh), "Mipmap texture only works in POT textures");
|
||||
// glActiveTexture(GL_TEXTURE0);
|
||||
// glBindTexture(GL_TEXTURE_2D, _name);
|
||||
// glGenerateMipmap(GL_TEXTURE_2D);
|
||||
// _hasMipmaps = true;
|
||||
//#if CC_ENABLE_CACHE_TEXTURE_DATA
|
||||
// VolatileTextureMgr::setHasMipmaps(this, _hasMipmaps);
|
||||
//#endif
|
||||
CCASSERT(_pixelsWide == ccNextPOT(_pixelsWide) && _pixelsHigh == ccNextPOT(_pixelsHigh), "Mipmap texture only works in POT textures");
|
||||
|
||||
_texture->generateMipmaps();
|
||||
_hasMipmaps = true;
|
||||
#if CC_ENABLE_CACHE_TEXTURE_DATA
|
||||
VolatileTextureMgr::setHasMipmaps(this, _hasMipmaps);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -25,6 +25,7 @@ class Texture : public Ref
|
|||
public:
|
||||
virtual void updateSamplerDescriptor(const SamplerDescriptor &sampler) = 0;
|
||||
virtual void getBytes(int x, int y, int width, int height, bool flipImage, std::function<void(const unsigned char*, int, int)> callback) = 0;
|
||||
virtual void generateMipmaps() = 0;
|
||||
|
||||
inline TextureFormat getTextureFormat() const { return _textureFormat; }
|
||||
inline TextureUsage getTextureUsage() const { return _textureUsage; }
|
||||
|
@ -38,6 +39,7 @@ protected:
|
|||
uint8_t _bitsPerElement = 0;
|
||||
bool _isMipmapEnabled = false;
|
||||
bool _isCompressed = false;
|
||||
bool _isMipmapGenerated = false;
|
||||
|
||||
TextureType _textureType = TextureType::TEXTURE_2D;
|
||||
TextureFormat _textureFormat = TextureFormat::R8G8B8;
|
||||
|
|
|
@ -154,6 +154,34 @@ namespace
|
|||
|
||||
return mtlDescritpor;
|
||||
}
|
||||
|
||||
id<MTLTexture> getMTLTexture(Texture* texture)
|
||||
{
|
||||
switch (texture->getTextureType())
|
||||
{
|
||||
case TextureType::TEXTURE_2D:
|
||||
return static_cast<TextureMTL*>(texture)->getMTLTexture();
|
||||
case TextureType::TEXTURE_CUBE:
|
||||
return static_cast<TextureCubeMTL*>(texture)->getMTLTexture();
|
||||
default:
|
||||
assert(false);
|
||||
return nil;
|
||||
}
|
||||
}
|
||||
|
||||
id<MTLSamplerState> getMTLSamplerState(Texture* texture)
|
||||
{
|
||||
switch (texture->getTextureType())
|
||||
{
|
||||
case TextureType::TEXTURE_2D:
|
||||
return static_cast<TextureMTL*>(texture)->getMTLSamplerState();
|
||||
case TextureType::TEXTURE_CUBE:
|
||||
return static_cast<TextureCubeMTL*>(texture)->getMTLSamplerState();
|
||||
default:
|
||||
assert(false);
|
||||
return nil;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
CommandBufferMTL::CommandBufferMTL(DeviceMTL* deviceMTL)
|
||||
|
@ -363,30 +391,29 @@ void CommandBufferMTL::doSetTextures(bool isVertex) const
|
|||
const auto& bindTextureInfos = (isVertex) ? _programState->getVertexTextureInfos() : _programState->getFragmentTextureInfos();
|
||||
|
||||
for(const auto& iter : bindTextureInfos)
|
||||
{
|
||||
//FIXME: should support texture array.
|
||||
{
|
||||
//FIXME: should support texture array.
|
||||
int i = 0;
|
||||
auto location = iter.first;
|
||||
const auto& textures = iter.second.textures;
|
||||
const auto& mtlTexture = static_cast<TextureMTL*>(textures[i]);
|
||||
|
||||
if (isVertex)
|
||||
{
|
||||
[_mtlRenderEncoder setVertexTexture:mtlTexture->getMTLTexture()
|
||||
atIndex:location];
|
||||
[_mtlRenderEncoder setVertexSamplerState:mtlTexture->getMTLSamplerState()
|
||||
atIndex:location];
|
||||
}
|
||||
else
|
||||
{
|
||||
[_mtlRenderEncoder setFragmentTexture:mtlTexture->getMTLTexture()
|
||||
atIndex:location];
|
||||
[_mtlRenderEncoder setFragmentSamplerState:mtlTexture->getMTLSamplerState()
|
||||
atIndex:location];
|
||||
}
|
||||
|
||||
++i;
|
||||
|
||||
if (isVertex)
|
||||
{
|
||||
[_mtlRenderEncoder setVertexTexture:getMTLTexture(textures[i])
|
||||
atIndex:location];
|
||||
[_mtlRenderEncoder setVertexSamplerState:getMTLSamplerState(textures[i])
|
||||
atIndex:location];
|
||||
}
|
||||
else
|
||||
{
|
||||
[_mtlRenderEncoder setFragmentTexture:getMTLTexture(textures[i])
|
||||
atIndex:location];
|
||||
[_mtlRenderEncoder setFragmentSamplerState:getMTLSamplerState(textures[i])
|
||||
atIndex:location];
|
||||
}
|
||||
|
||||
++i;
|
||||
}
|
||||
}
|
||||
|
||||
void CommandBufferMTL::setUniformBuffer() const
|
||||
|
|
|
@ -17,6 +17,7 @@ public:
|
|||
|
||||
virtual void updateSamplerDescriptor(const SamplerDescriptor &sampler) override;
|
||||
virtual void getBytes(int x, int y, int width, int height, bool flipImage, std::function<void(const unsigned char*, int, int)> callback) override;
|
||||
virtual void generateMipmaps() override;
|
||||
|
||||
inline id<MTLTexture> getMTLTexture() const { return _mtlTexture; }
|
||||
inline id<MTLSamplerState> getMTLSamplerState() const { return _mtlSamplerState; }
|
||||
|
@ -46,6 +47,10 @@ public:
|
|||
virtual void updateSamplerDescriptor(const SamplerDescriptor &sampler) override;
|
||||
virtual void updateFaceData(TextureCubeFace side, void *data) override;
|
||||
virtual void getBytes(int x, int y, int width, int height, bool flipImage, std::function<void(const unsigned char*, int, int)> callback) override;
|
||||
virtual void generateMipmaps() override;
|
||||
|
||||
inline id<MTLTexture> getMTLTexture() const { return _mtlTexture; }
|
||||
inline id<MTLSamplerState> getMTLSamplerState() const { return _mtlSamplerState; }
|
||||
|
||||
private:
|
||||
void createTexture(id<MTLDevice> mtlDevice, const TextureDescriptor& descriptor);
|
||||
|
|
|
@ -78,6 +78,24 @@ namespace
|
|||
}
|
||||
return converted;
|
||||
}
|
||||
|
||||
bool isColorRenderable(TextureFormat textureFormat)
|
||||
{
|
||||
switch (textureFormat)
|
||||
{
|
||||
case TextureFormat::R8G8B8A8:
|
||||
case TextureFormat::R8G8B8:
|
||||
case TextureFormat::RGBA4444:
|
||||
case TextureFormat::RGB565:
|
||||
case TextureFormat::RGB5A1:
|
||||
case TextureFormat::MTL_BGR5A1:
|
||||
case TextureFormat::MTL_B5G6R5:
|
||||
case TextureFormat::MTL_ABGR4:
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
TextureMTL::TextureMTL(id<MTLDevice> mtlDevice, const TextureDescriptor& descriptor)
|
||||
|
@ -107,7 +125,6 @@ void TextureMTL::updateSamplerDescriptor(const SamplerDescriptor &sampler)
|
|||
createSampler(_mtlDevice, sampler);
|
||||
}
|
||||
|
||||
|
||||
void TextureMTL::updateData(uint8_t* data)
|
||||
{
|
||||
updateSubData(0, 0, (unsigned int)_mtlTexture.width, (unsigned int)_mtlTexture.height, data);
|
||||
|
@ -139,7 +156,10 @@ void TextureMTL::updateSubData(unsigned int xoffset, unsigned int yoffset, unsig
|
|||
|
||||
// metal doesn't generate mipmaps automatically, so should generate it manually.
|
||||
if (_isMipmapEnabled)
|
||||
Utils::generateMipmaps(_mtlTexture);
|
||||
{
|
||||
_isMipmapGenerated = false;
|
||||
generateMipmaps();
|
||||
}
|
||||
}
|
||||
|
||||
void TextureMTL::createTexture(id<MTLDevice> mtlDevice, const TextureDescriptor& descriptor)
|
||||
|
@ -148,7 +168,7 @@ void TextureMTL::createTexture(id<MTLDevice> mtlDevice, const TextureDescriptor&
|
|||
[MTLTextureDescriptor texture2DDescriptorWithPixelFormat:Utils::toMTLPixelFormat(descriptor.textureFormat)
|
||||
width:descriptor.width
|
||||
height:descriptor.height
|
||||
mipmapped:TRUE];
|
||||
mipmapped:YES];
|
||||
|
||||
if (TextureUsage::RENDER_TARGET == descriptor.textureUsage)
|
||||
{
|
||||
|
@ -217,6 +237,19 @@ void TextureMTL::getBytes(int x, int y, int width, int height, bool flipImage, s
|
|||
Utils::getTextureBytes(x, y, width, height, _mtlTexture, flipImageCallback);
|
||||
}
|
||||
|
||||
void TextureMTL::generateMipmaps()
|
||||
{
|
||||
if (TextureUsage::RENDER_TARGET == _textureUsage || isColorRenderable(_textureFormat) == false)
|
||||
return;
|
||||
|
||||
if(!_isMipmapGenerated)
|
||||
{
|
||||
_isMipmapGenerated = true;
|
||||
Utils::generateMipmaps(_mtlTexture);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
TextureCubeMTL::TextureCubeMTL(id<MTLDevice> mtlDevice, const TextureDescriptor& descriptor)
|
||||
: backend::TextureCubemap(descriptor)
|
||||
{
|
||||
|
@ -245,7 +278,7 @@ TextureCubeMTL::~TextureCubeMTL()
|
|||
void TextureCubeMTL::createTexture(id<MTLDevice> mtlDevice, const TextureDescriptor& descriptor)
|
||||
{
|
||||
MTLTextureDescriptor* textureDescriptor =
|
||||
[MTLTextureDescriptor textureCubeDescriptorWithPixelFormat:Utils::toMTLPixelFormat(descriptor.textureFormat) size:descriptor.width mipmapped:NO];
|
||||
[MTLTextureDescriptor textureCubeDescriptorWithPixelFormat:Utils::toMTLPixelFormat(descriptor.textureFormat) size:descriptor.width mipmapped:YES];
|
||||
|
||||
if (TextureUsage::RENDER_TARGET == descriptor.textureUsage)
|
||||
{
|
||||
|
@ -297,6 +330,11 @@ void TextureCubeMTL::updateFaceData(TextureCubeFace side, void *data)
|
|||
withBytes:data
|
||||
bytesPerRow:_bytesPerRow
|
||||
bytesPerImage:_bytesPerImage];
|
||||
if(_isMipmapEnabled)
|
||||
{
|
||||
_isMipmapGenerated = true;
|
||||
generateMipmaps();
|
||||
}
|
||||
}
|
||||
|
||||
void TextureCubeMTL::getBytes(int x, int y, int width, int height, bool flipImage, std::function<void(const unsigned char*, int, int)> callback)
|
||||
|
@ -328,5 +366,16 @@ void TextureCubeMTL::getBytes(int x, int y, int width, int height, bool flipImag
|
|||
Utils::getTextureBytes(x, y, width, height, _mtlTexture, flipImageCallback);
|
||||
}
|
||||
|
||||
void TextureCubeMTL::generateMipmaps()
|
||||
{
|
||||
if (TextureUsage::RENDER_TARGET == _textureUsage || isColorRenderable(_textureFormat) == false)
|
||||
return;
|
||||
|
||||
if(!_isMipmapGenerated)
|
||||
{
|
||||
_isMipmapGenerated = true;
|
||||
Utils::generateMipmaps(_mtlTexture);
|
||||
}
|
||||
}
|
||||
|
||||
CC_BACKEND_END
|
||||
|
|
|
@ -57,9 +57,6 @@ Texture2DGL::~Texture2DGL()
|
|||
|
||||
void Texture2DGL::updateSamplerDescriptor(const SamplerDescriptor &sampler) {
|
||||
bool isPow2 = ISPOW2(_width) && ISPOW2(_height);
|
||||
bool needGenerateMipmap = !_isMipmapEnabled && sampler.mipmapEnabled;
|
||||
_isMipmapEnabled = sampler.mipmapEnabled;
|
||||
|
||||
_textureInfo.applySamplerDescriptor(sampler, isPow2);
|
||||
|
||||
glActiveTexture(GL_TEXTURE0);
|
||||
|
@ -84,8 +81,6 @@ void Texture2DGL::updateSamplerDescriptor(const SamplerDescriptor &sampler) {
|
|||
{
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, _textureInfo.tAddressModeGL);
|
||||
}
|
||||
|
||||
if (needGenerateMipmap) generateMipmpas();
|
||||
}
|
||||
|
||||
void Texture2DGL::updateData(uint8_t* data)
|
||||
|
@ -145,8 +140,12 @@ void Texture2DGL::updateData(uint8_t* data)
|
|||
data);
|
||||
}
|
||||
CHECK_GL_ERROR_DEBUG();
|
||||
|
||||
generateMipmpas();
|
||||
|
||||
if(_isMipmapEnabled)
|
||||
{
|
||||
_isMipmapGenerated = false;
|
||||
generateMipmaps();
|
||||
}
|
||||
CHECK_GL_ERROR_DEBUG();
|
||||
}
|
||||
|
||||
|
@ -164,8 +163,12 @@ void Texture2DGL::updateSubData(unsigned int xoffset, unsigned int yoffset, unsi
|
|||
_textureInfo.type,
|
||||
data);
|
||||
CHECK_GL_ERROR_DEBUG();
|
||||
|
||||
generateMipmpas();
|
||||
|
||||
if(_isMipmapEnabled)
|
||||
{
|
||||
_isMipmapGenerated = false;
|
||||
generateMipmaps();
|
||||
}
|
||||
CHECK_GL_ERROR_DEBUG();
|
||||
}
|
||||
|
||||
|
@ -175,11 +178,16 @@ void Texture2DGL::apply(int index) const
|
|||
glBindTexture(GL_TEXTURE_2D, _textureInfo.texture);
|
||||
}
|
||||
|
||||
void Texture2DGL::generateMipmpas() const
|
||||
void Texture2DGL::generateMipmaps()
|
||||
{
|
||||
if (Texture2D::_isMipmapEnabled &&
|
||||
TextureUsage::RENDER_TARGET != Texture2D:: _textureUsage)
|
||||
if (TextureUsage::RENDER_TARGET == _textureUsage)
|
||||
return;
|
||||
|
||||
if(!_isMipmapGenerated)
|
||||
{
|
||||
_isMipmapGenerated = true;
|
||||
glGenerateMipmap(GL_TEXTURE_2D);
|
||||
}
|
||||
}
|
||||
|
||||
void Texture2DGL::getBytes(int x, int y, int width, int height, bool flipImage, std::function<void(const unsigned char*, int, int)> callback)
|
||||
|
@ -247,7 +255,7 @@ void TextureCubeGL::updateSamplerDescriptor(const SamplerDescriptor &sampler)
|
|||
glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAG_FILTER, _textureInfo.magFilterGL);
|
||||
glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_S, _textureInfo.sAddressModeGL);
|
||||
glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_T, _textureInfo.tAddressModeGL);
|
||||
|
||||
|
||||
glBindTexture(GL_TEXTURE_CUBE_MAP, 0);
|
||||
}
|
||||
|
||||
|
@ -273,6 +281,11 @@ void TextureCubeGL::updateFaceData(TextureCubeFace side, void *data)
|
|||
_textureInfo.internalFormat, // format
|
||||
_textureInfo.type, // type
|
||||
data); // pixel data
|
||||
if(_isMipmapEnabled)
|
||||
{
|
||||
_isMipmapGenerated = false;
|
||||
generateMipmaps();
|
||||
}
|
||||
CHECK_GL_ERROR_DEBUG();
|
||||
glBindTexture(GL_TEXTURE_CUBE_MAP, 0);
|
||||
}
|
||||
|
@ -312,4 +325,16 @@ void TextureCubeGL::getBytes(int x, int y, int width, int height, bool flipImage
|
|||
glDeleteFramebuffers(1, &frameBuffer);
|
||||
}
|
||||
|
||||
void TextureCubeGL::generateMipmaps()
|
||||
{
|
||||
if (TextureUsage::RENDER_TARGET == _textureUsage)
|
||||
return;
|
||||
|
||||
if(!_isMipmapGenerated)
|
||||
{
|
||||
_isMipmapGenerated = true;
|
||||
glGenerateMipmap(GL_TEXTURE_CUBE_MAP);
|
||||
}
|
||||
}
|
||||
|
||||
CC_BACKEND_END
|
||||
|
|
|
@ -32,13 +32,12 @@ public:
|
|||
virtual void updateSubData(unsigned int xoffset, unsigned int yoffset, unsigned int width, unsigned int height, uint8_t* data) override;
|
||||
virtual void updateSamplerDescriptor(const SamplerDescriptor &sampler) override;
|
||||
virtual void getBytes(int x, int y, int width, int height, bool flipImage, std::function<void(const unsigned char*, int, int)> callback) override;
|
||||
virtual void generateMipmaps() override;
|
||||
|
||||
void apply(int index) const;
|
||||
inline GLuint getHandler() const { return _textureInfo.texture; }
|
||||
|
||||
private:
|
||||
void generateMipmpas() const;
|
||||
|
||||
SamplerDescriptor _samplerDescriptor;
|
||||
bool _isCompressed = false;
|
||||
TextureInfoGL _textureInfo;
|
||||
|
@ -53,7 +52,8 @@ public:
|
|||
virtual void updateSamplerDescriptor(const SamplerDescriptor &sampler) override;
|
||||
virtual void updateFaceData(TextureCubeFace side, void *data) override;
|
||||
virtual void getBytes(int x, int y, int width, int height, bool flipImage, std::function<void(const unsigned char*, int, int)> callback) override;
|
||||
|
||||
virtual void generateMipmaps() override;
|
||||
|
||||
void apply(int index) const;
|
||||
inline GLuint getHandler() const { return _textureInfo.texture; }
|
||||
|
||||
|
|
Loading…
Reference in New Issue