[Feature] fix mipmap issues (#19519)

This commit is contained in:
coulsonwang 2019-04-02 10:20:30 +08:00 committed by minggo
parent bb60c173a1
commit 688592b175
8 changed files with 156 additions and 52 deletions

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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