2019-11-23 20:27:39 +08:00
|
|
|
/****************************************************************************
|
|
|
|
Copyright (c) 2009 Jason Booth
|
|
|
|
Copyright (c) 2010-2012 cocos2d-x.org
|
|
|
|
Copyright (c) 2013-2016 Chukong Technologies Inc.
|
|
|
|
Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd.
|
2023-12-08 00:13:39 +08:00
|
|
|
Copyright (c) 2019-present Axmol Engine contributors (see AUTHORS.md).
|
2019-11-23 20:27:39 +08:00
|
|
|
|
2024-06-10 02:25:43 +08:00
|
|
|
https://axmol.dev/
|
2019-11-23 20:27:39 +08:00
|
|
|
|
|
|
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
|
|
of this software and associated documentation files (the "Software"), to deal
|
|
|
|
in the Software without restriction, including without limitation the rights
|
|
|
|
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
|
|
copies of the Software, and to permit persons to whom the Software is
|
|
|
|
furnished to do so, subject to the following conditions:
|
|
|
|
|
|
|
|
The above copyright notice and this permission notice shall be included in
|
|
|
|
all copies or substantial portions of the Software.
|
|
|
|
|
|
|
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
|
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
|
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
|
|
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
|
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
|
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
|
|
|
THE SOFTWARE.
|
|
|
|
****************************************************************************/
|
2023-06-11 13:08:08 +08:00
|
|
|
#include "2d/RenderTexture.h"
|
2019-11-23 20:27:39 +08:00
|
|
|
|
2023-06-11 13:08:08 +08:00
|
|
|
#include "base/Utils.h"
|
|
|
|
#include "platform/FileUtils.h"
|
|
|
|
#include "base/EventType.h"
|
|
|
|
#include "base/Configuration.h"
|
|
|
|
#include "base/Director.h"
|
|
|
|
#include "base/EventListenerCustom.h"
|
|
|
|
#include "base/EventDispatcher.h"
|
|
|
|
#include "renderer/Renderer.h"
|
|
|
|
#include "2d/Camera.h"
|
|
|
|
#include "renderer/TextureCache.h"
|
2023-12-11 21:59:25 +08:00
|
|
|
#include "renderer/backend/DriverBase.h"
|
2019-11-23 20:27:39 +08:00
|
|
|
#include "renderer/backend/Texture.h"
|
2020-09-21 22:10:50 +08:00
|
|
|
#include "renderer/backend/RenderTarget.h"
|
2024-09-20 07:30:12 +08:00
|
|
|
#if defined(AX_USE_GL)
|
|
|
|
# include "renderer/backend/opengl/CommandBufferGL.h"
|
|
|
|
#endif
|
2019-11-23 20:27:39 +08:00
|
|
|
|
2024-08-26 00:25:33 +08:00
|
|
|
namespace ax
|
|
|
|
{
|
2019-11-23 20:27:39 +08:00
|
|
|
|
|
|
|
// implementation RenderTexture
|
|
|
|
RenderTexture::RenderTexture()
|
|
|
|
{
|
2022-07-16 10:43:05 +08:00
|
|
|
#if AX_ENABLE_CACHE_TEXTURE_DATA
|
2019-11-23 20:27:39 +08:00
|
|
|
// Listen this event to save render texture before come to background.
|
|
|
|
// Then it can be restored after coming to foreground on Android.
|
2021-12-25 10:04:45 +08:00
|
|
|
auto toBackgroundListener =
|
2022-07-16 10:43:05 +08:00
|
|
|
EventListenerCustom::create(EVENT_COME_TO_BACKGROUND, AX_CALLBACK_1(RenderTexture::listenToBackground, this));
|
2019-11-23 20:27:39 +08:00
|
|
|
_eventDispatcher->addEventListenerWithSceneGraphPriority(toBackgroundListener, this);
|
|
|
|
|
2021-12-25 10:04:45 +08:00
|
|
|
auto toForegroundListener =
|
2022-07-16 10:43:05 +08:00
|
|
|
EventListenerCustom::create(EVENT_COME_TO_FOREGROUND, AX_CALLBACK_1(RenderTexture::listenToForeground, this));
|
2019-11-23 20:27:39 +08:00
|
|
|
_eventDispatcher->addEventListenerWithSceneGraphPriority(toForegroundListener, this);
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
|
|
|
RenderTexture::~RenderTexture()
|
|
|
|
{
|
2022-07-16 10:43:05 +08:00
|
|
|
AX_SAFE_RELEASE(_renderTarget);
|
|
|
|
AX_SAFE_RELEASE(_sprite);
|
|
|
|
AX_SAFE_RELEASE(_depthStencilTexture);
|
2019-11-23 20:27:39 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
void RenderTexture::listenToBackground(EventCustom* /*event*/)
|
|
|
|
{
|
|
|
|
// We have not found a way to dispatch the enter background message before the texture data are destroyed.
|
|
|
|
// So we disable this pair of message handler at present.
|
2022-07-16 10:43:05 +08:00
|
|
|
#if AX_ENABLE_CACHE_TEXTURE_DATA
|
2024-09-20 07:30:12 +08:00
|
|
|
if (!_cachedTextureDirty)
|
|
|
|
return;
|
2024-09-27 21:40:24 +08:00
|
|
|
_cachedTextureDirty = false;
|
2019-11-23 20:27:39 +08:00
|
|
|
// to get the rendered texture data
|
2024-05-31 13:01:42 +08:00
|
|
|
auto func = [&](RefPtr<Image> uiTextureImage) {
|
2019-11-23 20:27:39 +08:00
|
|
|
if (uiTextureImage)
|
|
|
|
{
|
|
|
|
_UITextureImage = uiTextureImage;
|
2024-09-20 07:30:12 +08:00
|
|
|
const Vec2& s = _texture2D->getContentSizeInPixels();
|
2021-12-25 10:04:45 +08:00
|
|
|
VolatileTextureMgr::addDataTexture(_texture2D, uiTextureImage->getData(), s.width * s.height * 4,
|
|
|
|
backend::PixelFormat::RGBA8, s);
|
2019-11-23 20:27:39 +08:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2024-07-05 07:51:36 +08:00
|
|
|
AXLOGW("Cache rendertexture failed!");
|
2019-11-23 20:27:39 +08:00
|
|
|
}
|
|
|
|
};
|
|
|
|
auto callback = std::bind(func, std::placeholders::_1);
|
2024-09-20 07:30:12 +08:00
|
|
|
newImage(callback, true);
|
2019-11-23 20:27:39 +08:00
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
|
|
|
void RenderTexture::listenToForeground(EventCustom* /*event*/)
|
|
|
|
{
|
2022-07-16 10:43:05 +08:00
|
|
|
#if AX_ENABLE_CACHE_TEXTURE_DATA
|
2019-11-23 20:27:39 +08:00
|
|
|
_texture2D->setAntiAliasTexParameters();
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
2022-06-28 17:33:00 +08:00
|
|
|
RenderTexture* RenderTexture::create(int w, int h, backend::PixelFormat eFormat, bool sharedRenderTarget)
|
2019-11-23 20:27:39 +08:00
|
|
|
{
|
2021-12-25 10:04:45 +08:00
|
|
|
RenderTexture* ret = new RenderTexture();
|
2019-11-23 20:27:39 +08:00
|
|
|
|
2022-06-28 17:33:00 +08:00
|
|
|
if (ret->initWithWidthAndHeight(w, h, eFormat, sharedRenderTarget))
|
2019-11-23 20:27:39 +08:00
|
|
|
{
|
|
|
|
ret->autorelease();
|
|
|
|
return ret;
|
|
|
|
}
|
2022-07-16 10:43:05 +08:00
|
|
|
AX_SAFE_DELETE(ret);
|
2019-11-23 20:27:39 +08:00
|
|
|
return nullptr;
|
|
|
|
}
|
|
|
|
|
2024-09-20 07:30:12 +08:00
|
|
|
RenderTexture* RenderTexture::create(int w,
|
|
|
|
int h,
|
|
|
|
backend::PixelFormat eFormat,
|
|
|
|
PixelFormat uDepthStencilFormat,
|
|
|
|
bool sharedRenderTarget)
|
2019-11-23 20:27:39 +08:00
|
|
|
{
|
2021-12-25 10:04:45 +08:00
|
|
|
RenderTexture* ret = new RenderTexture();
|
2019-11-23 20:27:39 +08:00
|
|
|
|
2022-06-28 17:33:00 +08:00
|
|
|
if (ret->initWithWidthAndHeight(w, h, eFormat, uDepthStencilFormat, sharedRenderTarget))
|
2019-11-23 20:27:39 +08:00
|
|
|
{
|
|
|
|
ret->autorelease();
|
|
|
|
return ret;
|
|
|
|
}
|
2022-07-16 10:43:05 +08:00
|
|
|
AX_SAFE_DELETE(ret);
|
2019-11-23 20:27:39 +08:00
|
|
|
return nullptr;
|
|
|
|
}
|
|
|
|
|
2022-06-28 17:33:00 +08:00
|
|
|
RenderTexture* RenderTexture::create(int w, int h, bool sharedRenderTarget)
|
2019-11-23 20:27:39 +08:00
|
|
|
{
|
2021-12-25 10:04:45 +08:00
|
|
|
RenderTexture* ret = new RenderTexture();
|
2019-11-23 20:27:39 +08:00
|
|
|
|
2022-06-28 17:33:00 +08:00
|
|
|
if (ret->initWithWidthAndHeight(w, h, backend::PixelFormat::RGBA8, PixelFormat::NONE, sharedRenderTarget))
|
2019-11-23 20:27:39 +08:00
|
|
|
{
|
|
|
|
ret->autorelease();
|
|
|
|
return ret;
|
|
|
|
}
|
2022-07-16 10:43:05 +08:00
|
|
|
AX_SAFE_DELETE(ret);
|
2019-11-23 20:27:39 +08:00
|
|
|
return nullptr;
|
|
|
|
}
|
|
|
|
|
2022-06-28 17:33:00 +08:00
|
|
|
bool RenderTexture::initWithWidthAndHeight(int w, int h, backend::PixelFormat eFormat, bool sharedRenderTarget)
|
2019-11-23 20:27:39 +08:00
|
|
|
{
|
2022-06-28 17:33:00 +08:00
|
|
|
return initWithWidthAndHeight(w, h, eFormat, PixelFormat::NONE, sharedRenderTarget);
|
2019-11-23 20:27:39 +08:00
|
|
|
}
|
|
|
|
|
2022-06-28 17:33:00 +08:00
|
|
|
bool RenderTexture::initWithWidthAndHeight(int w,
|
|
|
|
int h,
|
|
|
|
backend::PixelFormat format,
|
|
|
|
PixelFormat depthStencilFormat,
|
|
|
|
bool sharedRenderTarget)
|
2019-11-23 20:27:39 +08:00
|
|
|
{
|
2024-09-20 07:30:12 +08:00
|
|
|
AXASSERT(format == backend::PixelFormat::RGBA8 || format == PixelFormat::RGB8 || format == PixelFormat::RGBA4,
|
|
|
|
"only RGB and RGBA formats are valid for a render texture");
|
2019-11-23 20:27:39 +08:00
|
|
|
|
|
|
|
bool ret = false;
|
|
|
|
do
|
|
|
|
{
|
2021-12-25 10:04:45 +08:00
|
|
|
_fullRect = _rtTextureRect = Rect(0, 0, w, h);
|
2022-07-16 10:43:05 +08:00
|
|
|
w = (int)(w * AX_CONTENT_SCALE_FACTOR());
|
|
|
|
h = (int)(h * AX_CONTENT_SCALE_FACTOR());
|
2021-12-25 10:04:45 +08:00
|
|
|
_fullviewPort = Rect(0, 0, w, h);
|
|
|
|
|
2024-08-30 22:46:40 +08:00
|
|
|
setContentSize(Vec2(static_cast<float>(w), static_cast<float>(h)));
|
2024-09-20 07:30:12 +08:00
|
|
|
|
2019-11-23 20:27:39 +08:00
|
|
|
// textures must be power of two squared
|
|
|
|
int powW = 0;
|
|
|
|
int powH = 0;
|
|
|
|
|
|
|
|
if (Configuration::getInstance()->supportsNPOT())
|
|
|
|
{
|
|
|
|
powW = w;
|
|
|
|
powH = h;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2024-04-25 00:51:00 +08:00
|
|
|
powW = utils::nextPOT(w);
|
|
|
|
powH = utils::nextPOT(h);
|
2019-11-23 20:27:39 +08:00
|
|
|
}
|
2021-12-25 10:04:45 +08:00
|
|
|
|
2019-11-23 20:27:39 +08:00
|
|
|
backend::TextureDescriptor descriptor;
|
2021-12-25 10:04:45 +08:00
|
|
|
descriptor.width = powW;
|
|
|
|
descriptor.height = powH;
|
|
|
|
descriptor.textureUsage = TextureUsage::RENDER_TARGET;
|
2020-09-25 11:07:56 +08:00
|
|
|
descriptor.textureFormat = PixelFormat::RGBA8;
|
2021-12-25 10:04:45 +08:00
|
|
|
_texture2D = new Texture2D();
|
2022-07-16 10:43:05 +08:00
|
|
|
_texture2D->updateTextureDescriptor(descriptor, !!AX_ENABLE_PREMULTIPLIED_ALPHA);
|
2019-11-23 20:27:39 +08:00
|
|
|
|
2022-12-12 19:41:07 +08:00
|
|
|
if (PixelFormat::D24S8 == depthStencilFormat || sharedRenderTarget)
|
2019-11-23 20:27:39 +08:00
|
|
|
{
|
2022-12-12 19:41:07 +08:00
|
|
|
descriptor.textureFormat = PixelFormat::D24S8;
|
2019-11-23 20:27:39 +08:00
|
|
|
|
2023-04-28 14:54:57 +08:00
|
|
|
AX_SAFE_RELEASE(_depthStencilTexture);
|
|
|
|
|
2021-12-08 00:11:53 +08:00
|
|
|
_depthStencilTexture = new Texture2D();
|
2020-09-25 15:04:55 +08:00
|
|
|
_depthStencilTexture->updateTextureDescriptor(descriptor);
|
2019-11-23 20:27:39 +08:00
|
|
|
}
|
|
|
|
|
2022-07-16 10:43:05 +08:00
|
|
|
AX_SAFE_RELEASE(_renderTarget);
|
2022-06-28 17:33:00 +08:00
|
|
|
|
|
|
|
if (sharedRenderTarget)
|
|
|
|
{
|
|
|
|
_renderTarget = _director->getRenderer()->getOffscreenRenderTarget();
|
|
|
|
_renderTarget->retain();
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2024-09-20 07:30:12 +08:00
|
|
|
_renderTarget = backend::DriverBase::getInstance()->newRenderTarget(
|
|
|
|
_texture2D ? _texture2D->getBackendTexture() : nullptr,
|
|
|
|
_depthStencilTexture ? _depthStencilTexture->getBackendTexture() : nullptr,
|
|
|
|
_depthStencilTexture ? _depthStencilTexture->getBackendTexture() : nullptr);
|
2022-06-28 17:33:00 +08:00
|
|
|
}
|
2022-06-24 14:18:48 +08:00
|
|
|
|
|
|
|
_renderTarget->setColorAttachment(_texture2D ? _texture2D->getBackendTexture() : nullptr);
|
|
|
|
|
|
|
|
auto depthStencilTexture = _depthStencilTexture ? _depthStencilTexture->getBackendTexture() : nullptr;
|
|
|
|
_renderTarget->setDepthAttachment(depthStencilTexture);
|
|
|
|
_renderTarget->setStencilAttachment(depthStencilTexture);
|
2020-09-21 22:10:50 +08:00
|
|
|
|
|
|
|
clearColorAttachment();
|
|
|
|
|
2019-11-23 20:27:39 +08:00
|
|
|
_texture2D->setAntiAliasTexParameters();
|
|
|
|
|
|
|
|
// retained
|
|
|
|
setSprite(Sprite::createWithTexture(_texture2D));
|
|
|
|
|
2022-11-10 21:22:55 +08:00
|
|
|
#if defined(AX_USE_GL)
|
2019-11-23 20:27:39 +08:00
|
|
|
_sprite->setFlippedY(true);
|
|
|
|
#endif
|
|
|
|
|
2021-12-25 10:04:45 +08:00
|
|
|
if (_texture2D->hasPremultipliedAlpha())
|
|
|
|
{
|
2020-11-16 12:21:27 +08:00
|
|
|
_sprite->setBlendFunc(BlendFunc::ALPHA_PREMULTIPLIED);
|
|
|
|
_sprite->setOpacityModifyRGB(true);
|
|
|
|
}
|
2021-12-25 10:04:45 +08:00
|
|
|
else
|
|
|
|
{
|
2020-11-16 12:21:27 +08:00
|
|
|
_sprite->setBlendFunc(BlendFunc::ALPHA_NON_PREMULTIPLIED);
|
|
|
|
_sprite->setOpacityModifyRGB(false);
|
|
|
|
}
|
|
|
|
|
|
|
|
_texture2D->release();
|
|
|
|
|
2019-11-23 20:27:39 +08:00
|
|
|
// Disabled by default.
|
|
|
|
_autoDraw = false;
|
2021-12-25 10:04:45 +08:00
|
|
|
|
2019-11-23 20:27:39 +08:00
|
|
|
ret = true;
|
|
|
|
} while (0);
|
2021-12-25 10:04:45 +08:00
|
|
|
|
2019-11-23 20:27:39 +08:00
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
void RenderTexture::setSprite(Sprite* sprite)
|
|
|
|
{
|
2022-07-16 10:43:05 +08:00
|
|
|
#if AX_ENABLE_GC_FOR_NATIVE_OBJECTS
|
2019-11-23 20:27:39 +08:00
|
|
|
auto sEngine = ScriptEngineManager::getInstance()->getScriptEngine();
|
|
|
|
if (sEngine)
|
|
|
|
{
|
|
|
|
if (sprite)
|
|
|
|
sEngine->retainScriptObject(this, sprite);
|
|
|
|
if (_sprite)
|
|
|
|
sEngine->releaseScriptObject(this, _sprite);
|
|
|
|
}
|
2022-07-16 10:43:05 +08:00
|
|
|
#endif // AX_ENABLE_GC_FOR_NATIVE_OBJECTS
|
2023-04-28 14:54:57 +08:00
|
|
|
if (_sprite)
|
|
|
|
{
|
|
|
|
_sprite->removeFromParent();
|
|
|
|
_sprite->release();
|
|
|
|
}
|
|
|
|
|
2022-07-16 10:43:05 +08:00
|
|
|
AX_SAFE_RETAIN(sprite);
|
2019-11-23 20:27:39 +08:00
|
|
|
_sprite = sprite;
|
|
|
|
}
|
|
|
|
|
|
|
|
void RenderTexture::setVirtualViewport(const Vec2& rtBegin, const Rect& fullRect, const Rect& fullViewport)
|
|
|
|
{
|
|
|
|
_rtTextureRect.origin.x = rtBegin.x;
|
|
|
|
_rtTextureRect.origin.y = rtBegin.y;
|
|
|
|
|
|
|
|
_fullRect = fullRect;
|
|
|
|
|
|
|
|
_fullviewPort = fullViewport;
|
|
|
|
}
|
|
|
|
|
2022-06-28 17:33:00 +08:00
|
|
|
bool RenderTexture::isSharedRenderTarget() const
|
|
|
|
{
|
|
|
|
return _renderTarget == _director->getRenderer()->getOffscreenRenderTarget();
|
|
|
|
}
|
|
|
|
|
2019-11-23 20:27:39 +08:00
|
|
|
void RenderTexture::beginWithClear(float r, float g, float b, float a)
|
|
|
|
{
|
|
|
|
beginWithClear(r, g, b, a, 0, 0, ClearFlag::COLOR);
|
|
|
|
}
|
|
|
|
|
|
|
|
void RenderTexture::beginWithClear(float r, float g, float b, float a, float depthValue)
|
|
|
|
{
|
|
|
|
beginWithClear(r, g, b, a, depthValue, 0, ClearFlag::COLOR | ClearFlag::DEPTH);
|
|
|
|
}
|
|
|
|
|
|
|
|
void RenderTexture::beginWithClear(float r, float g, float b, float a, float depthValue, int stencilValue)
|
|
|
|
{
|
|
|
|
beginWithClear(r, g, b, a, depthValue, stencilValue, ClearFlag::ALL);
|
|
|
|
}
|
|
|
|
|
2021-12-25 10:04:45 +08:00
|
|
|
void RenderTexture::beginWithClear(float r,
|
|
|
|
float g,
|
|
|
|
float b,
|
|
|
|
float a,
|
|
|
|
float depthValue,
|
|
|
|
int stencilValue,
|
|
|
|
ClearFlag flags)
|
2019-11-23 20:27:39 +08:00
|
|
|
{
|
|
|
|
setClearColor(Color4F(r, g, b, a));
|
|
|
|
setClearDepth(depthValue);
|
|
|
|
setClearStencil(stencilValue);
|
|
|
|
setClearFlags(flags);
|
|
|
|
begin();
|
2020-09-13 19:16:59 +08:00
|
|
|
_director->getRenderer()->clear(_clearFlags, _clearColor, _clearDepth, _clearStencil, _globalZOrder);
|
2019-11-23 20:27:39 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
void RenderTexture::clear(float r, float g, float b, float a)
|
|
|
|
{
|
|
|
|
this->beginWithClear(r, g, b, a);
|
|
|
|
this->end();
|
|
|
|
}
|
|
|
|
|
|
|
|
void RenderTexture::clearDepth(float depthValue)
|
|
|
|
{
|
|
|
|
setClearDepth(depthValue);
|
|
|
|
}
|
|
|
|
|
|
|
|
void RenderTexture::clearStencil(int stencilValue)
|
|
|
|
{
|
|
|
|
setClearStencil(stencilValue);
|
|
|
|
}
|
|
|
|
|
2021-12-25 10:04:45 +08:00
|
|
|
void RenderTexture::visit(Renderer* renderer, const Mat4& parentTransform, uint32_t parentFlags)
|
2019-11-23 20:27:39 +08:00
|
|
|
{
|
|
|
|
// override visit.
|
|
|
|
// Don't call visit on its children
|
|
|
|
if (!_visible)
|
|
|
|
{
|
|
|
|
return;
|
|
|
|
}
|
2021-12-25 10:04:45 +08:00
|
|
|
|
2019-11-23 20:27:39 +08:00
|
|
|
uint32_t flags = processParentFlags(parentTransform, parentFlags);
|
|
|
|
|
|
|
|
// IMPORTANT:
|
|
|
|
// To ease the migration to v3.0, we still support the Mat4 stack,
|
|
|
|
// but it is deprecated and your code should not rely on it
|
2020-09-13 19:16:59 +08:00
|
|
|
_director->pushMatrix(MATRIX_STACK_TYPE::MATRIX_STACK_MODELVIEW);
|
|
|
|
_director->loadMatrix(MATRIX_STACK_TYPE::MATRIX_STACK_MODELVIEW, _modelViewTransform);
|
2019-11-23 20:27:39 +08:00
|
|
|
|
|
|
|
_sprite->visit(renderer, _modelViewTransform, flags);
|
|
|
|
if (isVisitableByVisitingCamera())
|
|
|
|
{
|
|
|
|
draw(renderer, _modelViewTransform, flags);
|
|
|
|
}
|
2021-12-25 10:04:45 +08:00
|
|
|
|
2020-09-13 19:16:59 +08:00
|
|
|
_director->popMatrix(MATRIX_STACK_TYPE::MATRIX_STACK_MODELVIEW);
|
2019-11-23 20:27:39 +08:00
|
|
|
|
|
|
|
// FIX ME: Why need to set _orderOfArrival to 0??
|
|
|
|
// Please refer to https://github.com/cocos2d/cocos2d-x/pull/6920
|
|
|
|
// setOrderOfArrival(0);
|
|
|
|
}
|
|
|
|
|
2021-12-31 12:12:40 +08:00
|
|
|
bool RenderTexture::saveToFileAsNonPMA(std::string_view filename, bool isRGBA, SaveFileCallbackType callback)
|
2019-11-23 20:27:39 +08:00
|
|
|
{
|
|
|
|
std::string basename(filename);
|
|
|
|
std::transform(basename.begin(), basename.end(), basename.begin(), ::tolower);
|
|
|
|
|
|
|
|
if (basename.find(".png") != std::string::npos)
|
|
|
|
{
|
2024-05-26 09:26:06 +08:00
|
|
|
return saveToFileAsNonPMA(filename, Image::Format::PNG, isRGBA, std::move(callback));
|
2019-11-23 20:27:39 +08:00
|
|
|
}
|
|
|
|
else if (basename.find(".jpg") != std::string::npos)
|
|
|
|
{
|
2021-12-25 10:04:45 +08:00
|
|
|
if (isRGBA)
|
2024-07-05 07:51:36 +08:00
|
|
|
AXLOGD("RGBA is not supported for JPG format.");
|
2024-05-26 09:26:06 +08:00
|
|
|
return saveToFileAsNonPMA(filename, Image::Format::JPG, false, std::move(callback));
|
2019-11-23 20:27:39 +08:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2024-07-05 07:51:36 +08:00
|
|
|
AXLOGD("Only PNG and JPG format are supported now!");
|
2019-11-23 20:27:39 +08:00
|
|
|
}
|
|
|
|
|
2024-05-26 09:26:06 +08:00
|
|
|
return saveToFileAsNonPMA(filename, Image::Format::JPG, false, std::move(callback));
|
2021-12-25 10:04:45 +08:00
|
|
|
}
|
|
|
|
|
2021-12-31 12:12:40 +08:00
|
|
|
bool RenderTexture::saveToFile(std::string_view filename, bool isRGBA, SaveFileCallbackType callback)
|
2019-11-23 20:27:39 +08:00
|
|
|
{
|
|
|
|
std::string basename(filename);
|
|
|
|
std::transform(basename.begin(), basename.end(), basename.begin(), ::tolower);
|
2021-12-25 10:04:45 +08:00
|
|
|
|
2019-11-23 20:27:39 +08:00
|
|
|
if (basename.find(".png") != std::string::npos)
|
|
|
|
{
|
2024-05-26 09:26:06 +08:00
|
|
|
return saveToFile(filename, Image::Format::PNG, isRGBA, std::move(callback));
|
2019-11-23 20:27:39 +08:00
|
|
|
}
|
|
|
|
else if (basename.find(".jpg") != std::string::npos)
|
|
|
|
{
|
2021-12-25 10:04:45 +08:00
|
|
|
if (isRGBA)
|
2024-07-05 07:51:36 +08:00
|
|
|
AXLOGD("RGBA is not supported for JPG format.");
|
2024-05-26 09:26:06 +08:00
|
|
|
return saveToFile(filename, Image::Format::JPG, false, std::move(callback));
|
2019-11-23 20:27:39 +08:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2024-07-05 07:51:36 +08:00
|
|
|
AXLOGD("Only PNG and JPG format are supported now!");
|
2019-11-23 20:27:39 +08:00
|
|
|
}
|
2021-12-25 10:04:45 +08:00
|
|
|
|
2024-05-26 09:26:06 +08:00
|
|
|
return saveToFile(filename, Image::Format::JPG, false, std::move(callback));
|
2019-11-23 20:27:39 +08:00
|
|
|
}
|
|
|
|
|
2021-12-31 12:12:40 +08:00
|
|
|
bool RenderTexture::saveToFileAsNonPMA(std::string_view fileName,
|
2021-12-25 10:04:45 +08:00
|
|
|
Image::Format format,
|
|
|
|
bool isRGBA,
|
2021-12-31 12:12:40 +08:00
|
|
|
SaveFileCallbackType callback)
|
2019-11-23 20:27:39 +08:00
|
|
|
{
|
2022-07-16 10:43:05 +08:00
|
|
|
AXASSERT(format == Image::Format::JPG || format == Image::Format::PNG,
|
2021-12-25 10:04:45 +08:00
|
|
|
"the image can only be saved as JPG or PNG format");
|
|
|
|
if (isRGBA && format == Image::Format::JPG)
|
2024-07-05 07:51:36 +08:00
|
|
|
AXLOGD("RGBA is not supported for JPG format");
|
2019-11-23 20:27:39 +08:00
|
|
|
|
2024-05-26 09:26:06 +08:00
|
|
|
_saveFileCallback = std::move(callback);
|
2019-11-23 20:27:39 +08:00
|
|
|
|
2021-12-31 12:12:40 +08:00
|
|
|
std::string fullpath = FileUtils::getInstance()->getWritablePath().append(fileName);
|
2019-11-23 20:27:39 +08:00
|
|
|
|
2022-06-24 14:18:48 +08:00
|
|
|
auto renderer = _director->getRenderer();
|
|
|
|
auto saveToFileCommand = renderer->nextCallbackCommand();
|
|
|
|
saveToFileCommand->init(_globalZOrder);
|
2023-01-03 23:02:17 +08:00
|
|
|
saveToFileCommand->func = AX_CALLBACK_0(RenderTexture::onSaveToFile, this, std::move(fullpath), isRGBA, true);
|
2022-06-24 14:18:48 +08:00
|
|
|
|
|
|
|
renderer->addCommand(saveToFileCommand);
|
2019-11-23 20:27:39 +08:00
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2021-12-31 12:12:40 +08:00
|
|
|
bool RenderTexture::saveToFile(std::string_view fileName,
|
2021-12-25 10:04:45 +08:00
|
|
|
Image::Format format,
|
|
|
|
bool isRGBA,
|
2022-06-24 14:18:48 +08:00
|
|
|
SaveFileCallbackType callback)
|
2019-11-23 20:27:39 +08:00
|
|
|
{
|
2022-07-16 10:43:05 +08:00
|
|
|
AXASSERT(format == Image::Format::JPG || format == Image::Format::PNG,
|
2019-11-23 20:27:39 +08:00
|
|
|
"the image can only be saved as JPG or PNG format");
|
2021-12-25 10:04:45 +08:00
|
|
|
if (isRGBA && format == Image::Format::JPG)
|
2024-07-05 07:51:36 +08:00
|
|
|
AXLOGD("RGBA is not supported for JPG format");
|
2021-12-25 10:04:45 +08:00
|
|
|
|
2024-05-26 09:26:06 +08:00
|
|
|
_saveFileCallback = std::move(callback);
|
2021-12-25 10:04:45 +08:00
|
|
|
|
2021-12-31 12:12:40 +08:00
|
|
|
std::string fullpath = FileUtils::getInstance()->getWritablePath().append(fileName);
|
2021-12-25 10:04:45 +08:00
|
|
|
|
2022-06-24 14:18:48 +08:00
|
|
|
auto renderer = _director->getRenderer();
|
|
|
|
auto saveToFileCommand = renderer->nextCallbackCommand();
|
|
|
|
saveToFileCommand->init(_globalZOrder);
|
2023-01-03 23:02:17 +08:00
|
|
|
saveToFileCommand->func = AX_CALLBACK_0(RenderTexture::onSaveToFile, this, std::move(fullpath), isRGBA, false);
|
2022-06-24 14:18:48 +08:00
|
|
|
|
|
|
|
_director->getRenderer()->addCommand(saveToFileCommand);
|
2019-11-23 20:27:39 +08:00
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2023-01-03 23:02:17 +08:00
|
|
|
void RenderTexture::onSaveToFile(std::string filename, bool isRGBA, bool forceNonPMA)
|
2019-11-23 20:27:39 +08:00
|
|
|
{
|
2023-01-03 23:02:17 +08:00
|
|
|
auto callbackFunc = [this, _filename = std::move(filename), isRGBA, forceNonPMA](RefPtr<Image> image) {
|
2019-11-23 20:27:39 +08:00
|
|
|
if (image)
|
|
|
|
{
|
|
|
|
if (forceNonPMA && image->hasPremultipliedAlpha())
|
|
|
|
{
|
2024-07-11 09:07:53 +08:00
|
|
|
_director->getJobSystem()->enqueue([self = RefPtr(this), image, _filename, isRGBA, forceNonPMA]() {
|
2024-05-26 09:26:06 +08:00
|
|
|
image->reversePremultipliedAlpha();
|
|
|
|
|
2024-07-11 09:07:53 +08:00
|
|
|
Director::getInstance()->getScheduler()->runOnAxmolThread([self, image, _filename, isRGBA] {
|
2024-05-26 09:26:06 +08:00
|
|
|
image->saveToFile(_filename, !isRGBA);
|
2024-07-11 09:07:53 +08:00
|
|
|
if (self->_saveFileCallback)
|
2024-05-26 09:26:06 +08:00
|
|
|
{
|
2024-07-11 09:07:53 +08:00
|
|
|
self->_saveFileCallback(self, _filename);
|
2024-05-26 09:26:06 +08:00
|
|
|
}
|
|
|
|
});
|
2024-06-07 00:33:01 +08:00
|
|
|
});
|
2024-05-26 09:26:06 +08:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
image->saveToFile(_filename, !isRGBA);
|
|
|
|
if (_saveFileCallback)
|
|
|
|
{
|
|
|
|
_saveFileCallback(this, _filename);
|
|
|
|
}
|
2019-11-23 20:27:39 +08:00
|
|
|
}
|
|
|
|
}
|
2024-05-26 09:26:06 +08:00
|
|
|
else
|
2019-11-23 20:27:39 +08:00
|
|
|
{
|
2024-05-26 09:26:06 +08:00
|
|
|
if (_saveFileCallback)
|
|
|
|
{
|
|
|
|
_saveFileCallback(this, _filename);
|
2024-08-15 12:14:02 +08:00
|
|
|
}
|
2019-11-23 20:27:39 +08:00
|
|
|
}
|
|
|
|
};
|
|
|
|
newImage(callbackFunc);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* get buffer as Image */
|
2024-09-20 07:30:12 +08:00
|
|
|
void RenderTexture::newImage(std::function<void(RefPtr<Image>)> imageCallback, bool eglCacheHint)
|
2019-11-23 20:27:39 +08:00
|
|
|
{
|
2022-07-16 10:43:05 +08:00
|
|
|
AXASSERT(_pixelFormat == backend::PixelFormat::RGBA8, "only RGBA8888 can be saved as image");
|
2019-11-23 20:27:39 +08:00
|
|
|
|
|
|
|
if ((nullptr == _texture2D))
|
|
|
|
{
|
2021-12-25 10:04:45 +08:00
|
|
|
return;
|
2019-11-23 20:27:39 +08:00
|
|
|
}
|
|
|
|
|
2021-10-23 23:27:14 +08:00
|
|
|
const Vec2& s = _texture2D->getContentSizeInPixels();
|
2019-11-23 20:27:39 +08:00
|
|
|
|
|
|
|
// to get the image size to save
|
|
|
|
// if the saving image domain exceeds the buffer texture domain,
|
|
|
|
// it should be cut
|
2021-12-25 10:04:45 +08:00
|
|
|
int savedBufferWidth = (int)s.width;
|
|
|
|
int savedBufferHeight = (int)s.height;
|
2020-06-12 11:24:10 +08:00
|
|
|
bool hasPremultipliedAlpha = _texture2D->hasPremultipliedAlpha();
|
2021-12-25 10:04:45 +08:00
|
|
|
|
2024-09-20 07:30:12 +08:00
|
|
|
auto callback = [hasPremultipliedAlpha, imageCallback](const backend::PixelBufferDescriptor& pbd) {
|
2021-12-25 10:04:45 +08:00
|
|
|
if (pbd)
|
|
|
|
{
|
|
|
|
auto image = utils::makeInstance<Image>(&Image::initWithRawData, pbd._data.getBytes(), pbd._data.getSize(),
|
|
|
|
pbd._width, pbd._height, 8, hasPremultipliedAlpha);
|
2020-06-12 11:24:10 +08:00
|
|
|
imageCallback(image);
|
2020-09-10 21:14:28 +08:00
|
|
|
}
|
2021-12-25 10:04:45 +08:00
|
|
|
else
|
|
|
|
imageCallback(nullptr);
|
2024-09-20 07:30:12 +08:00
|
|
|
};
|
|
|
|
#if defined(AX_USE_GL)
|
|
|
|
if (eglCacheHint)
|
|
|
|
{
|
|
|
|
auto colorAttachment = _renderTarget->_color[0].texture;
|
|
|
|
if (colorAttachment)
|
|
|
|
{
|
|
|
|
backend::PixelBufferDescriptor pbd;
|
|
|
|
static_cast<backend::CommandBufferGL*>(_director->getRenderer()->getCommandBuffer())
|
|
|
|
->readPixels(_renderTarget, 0, 0, colorAttachment->getWidth(), colorAttachment->getHeight(),
|
|
|
|
colorAttachment->getWidth() * 4, true, pbd);
|
|
|
|
callback(pbd);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
_director->getRenderer()->readPixels(_renderTarget, callback);
|
|
|
|
#else
|
|
|
|
_director->getRenderer()->readPixels(_renderTarget, callback);
|
|
|
|
#endif
|
2019-11-23 20:27:39 +08:00
|
|
|
}
|
|
|
|
|
2021-12-25 10:04:45 +08:00
|
|
|
void RenderTexture::draw(Renderer* renderer, const Mat4& transform, uint32_t flags)
|
2019-11-23 20:27:39 +08:00
|
|
|
{
|
|
|
|
if (_autoDraw)
|
|
|
|
{
|
2021-12-25 10:04:45 +08:00
|
|
|
// Begin will create a render group using new render target
|
2019-11-23 20:27:39 +08:00
|
|
|
begin();
|
|
|
|
|
2021-12-25 10:04:45 +08:00
|
|
|
// clear screen
|
2021-04-22 22:01:47 +08:00
|
|
|
_director->getRenderer()->clear(_clearFlags, _clearColor, _clearDepth, _clearStencil, _globalZOrder);
|
2019-11-23 20:27:39 +08:00
|
|
|
|
|
|
|
//! make sure all children are drawn
|
|
|
|
sortAllChildren();
|
|
|
|
|
2021-12-25 10:04:45 +08:00
|
|
|
for (const auto& child : _children)
|
2019-11-23 20:27:39 +08:00
|
|
|
{
|
|
|
|
if (child != _sprite)
|
|
|
|
child->visit(renderer, transform, flags);
|
|
|
|
}
|
|
|
|
|
2021-12-25 10:04:45 +08:00
|
|
|
// End will pop the current render group
|
2019-11-23 20:27:39 +08:00
|
|
|
end();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void RenderTexture::onBegin()
|
|
|
|
{
|
2021-04-22 22:01:47 +08:00
|
|
|
_oldProjMatrix = _director->getMatrix(MATRIX_STACK_TYPE::MATRIX_STACK_PROJECTION);
|
|
|
|
_director->loadMatrix(MATRIX_STACK_TYPE::MATRIX_STACK_PROJECTION, _projectionMatrix);
|
2019-11-23 20:27:39 +08:00
|
|
|
|
2021-04-22 22:01:47 +08:00
|
|
|
_oldTransMatrix = _director->getMatrix(MATRIX_STACK_TYPE::MATRIX_STACK_MODELVIEW);
|
|
|
|
_director->loadMatrix(MATRIX_STACK_TYPE::MATRIX_STACK_MODELVIEW, _transformMatrix);
|
2019-11-23 20:27:39 +08:00
|
|
|
|
2021-12-25 10:04:45 +08:00
|
|
|
if (!_keepMatrix)
|
2019-11-23 20:27:39 +08:00
|
|
|
{
|
2021-04-22 22:01:47 +08:00
|
|
|
_director->setProjection(_director->getProjection());
|
2021-10-23 23:27:14 +08:00
|
|
|
const Vec2& texSize = _texture2D->getContentSizeInPixels();
|
2019-11-23 20:27:39 +08:00
|
|
|
|
|
|
|
// Calculate the adjustment ratios based on the old and new projections
|
2021-12-25 10:04:45 +08:00
|
|
|
Vec2 size = _director->getWinSizeInPixels();
|
|
|
|
float widthRatio = size.width / texSize.width;
|
2019-11-23 20:27:39 +08:00
|
|
|
float heightRatio = size.height / texSize.height;
|
|
|
|
|
|
|
|
Mat4 orthoMatrix;
|
2021-12-25 10:04:45 +08:00
|
|
|
Mat4::createOrthographicOffCenter((float)-1.0 / widthRatio, (float)1.0 / widthRatio, (float)-1.0 / heightRatio,
|
|
|
|
(float)1.0 / heightRatio, -1, 1, &orthoMatrix);
|
2021-04-22 22:01:47 +08:00
|
|
|
_director->multiplyMatrix(MATRIX_STACK_TYPE::MATRIX_STACK_PROJECTION, orthoMatrix);
|
2019-11-23 20:27:39 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
Rect viewport;
|
2021-12-25 10:04:45 +08:00
|
|
|
viewport.size.width = _fullviewPort.size.width;
|
|
|
|
viewport.size.height = _fullviewPort.size.height;
|
|
|
|
float viewPortRectWidthRatio = float(viewport.size.width) / _fullRect.size.width;
|
|
|
|
float viewPortRectHeightRatio = float(viewport.size.height) / _fullRect.size.height;
|
|
|
|
viewport.origin.x = (_fullRect.origin.x - _rtTextureRect.origin.x) * viewPortRectWidthRatio;
|
|
|
|
viewport.origin.y = (_fullRect.origin.y - _rtTextureRect.origin.y) * viewPortRectHeightRatio;
|
|
|
|
|
|
|
|
Renderer* renderer = _director->getRenderer();
|
|
|
|
|
2019-11-23 20:27:39 +08:00
|
|
|
_oldViewport = renderer->getViewport();
|
|
|
|
renderer->setViewPort(viewport.origin.x, viewport.origin.y, viewport.size.width, viewport.size.height);
|
|
|
|
|
2020-09-21 22:10:50 +08:00
|
|
|
_oldRenderTarget = renderer->getRenderTarget();
|
|
|
|
renderer->setRenderTarget(_renderTarget);
|
2019-11-23 20:27:39 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
void RenderTexture::onEnd()
|
|
|
|
{
|
2021-04-22 22:01:47 +08:00
|
|
|
_director->loadMatrix(MATRIX_STACK_TYPE::MATRIX_STACK_PROJECTION, _oldProjMatrix);
|
|
|
|
_director->loadMatrix(MATRIX_STACK_TYPE::MATRIX_STACK_MODELVIEW, _oldTransMatrix);
|
2021-12-25 10:04:45 +08:00
|
|
|
|
|
|
|
Renderer* renderer = _director->getRenderer();
|
2023-09-02 19:56:50 +08:00
|
|
|
renderer->setViewPort(_oldViewport.x, _oldViewport.y, _oldViewport.width, _oldViewport.height);
|
2020-09-21 22:10:50 +08:00
|
|
|
|
|
|
|
renderer->setRenderTarget(_oldRenderTarget);
|
2019-11-23 20:27:39 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
void RenderTexture::begin()
|
|
|
|
{
|
2020-09-13 19:16:59 +08:00
|
|
|
_director->pushMatrix(MATRIX_STACK_TYPE::MATRIX_STACK_PROJECTION);
|
|
|
|
_projectionMatrix = _director->getMatrix(MATRIX_STACK_TYPE::MATRIX_STACK_PROJECTION);
|
2021-12-25 10:04:45 +08:00
|
|
|
|
2020-09-13 19:16:59 +08:00
|
|
|
_director->pushMatrix(MATRIX_STACK_TYPE::MATRIX_STACK_MODELVIEW);
|
|
|
|
_transformMatrix = _director->getMatrix(MATRIX_STACK_TYPE::MATRIX_STACK_MODELVIEW);
|
2021-12-25 10:04:45 +08:00
|
|
|
|
|
|
|
if (!_keepMatrix)
|
2019-11-23 20:27:39 +08:00
|
|
|
{
|
2020-09-13 19:16:59 +08:00
|
|
|
_director->setProjection(_director->getProjection());
|
2021-12-25 10:04:45 +08:00
|
|
|
|
2021-10-23 23:27:14 +08:00
|
|
|
const Vec2& texSize = _texture2D->getContentSizeInPixels();
|
2021-12-25 10:04:45 +08:00
|
|
|
|
2019-11-23 20:27:39 +08:00
|
|
|
// Calculate the adjustment ratios based on the old and new projections
|
2021-10-23 23:27:14 +08:00
|
|
|
Vec2 size = _director->getWinSizeInPixels();
|
2021-12-25 10:04:45 +08:00
|
|
|
|
|
|
|
float widthRatio = size.width / texSize.width;
|
2019-11-23 20:27:39 +08:00
|
|
|
float heightRatio = size.height / texSize.height;
|
2021-12-25 10:04:45 +08:00
|
|
|
|
2019-11-23 20:27:39 +08:00
|
|
|
Mat4 orthoMatrix;
|
2021-12-25 10:04:45 +08:00
|
|
|
Mat4::createOrthographicOffCenter((float)-1.0 / widthRatio, (float)1.0 / widthRatio, (float)-1.0 / heightRatio,
|
|
|
|
(float)1.0 / heightRatio, -1, 1, &orthoMatrix);
|
2020-09-13 19:16:59 +08:00
|
|
|
_director->multiplyMatrix(MATRIX_STACK_TYPE::MATRIX_STACK_PROJECTION, orthoMatrix);
|
2019-11-23 20:27:39 +08:00
|
|
|
}
|
|
|
|
|
2021-12-25 10:04:45 +08:00
|
|
|
Renderer* renderer = _director->getRenderer();
|
2022-11-28 08:37:22 +08:00
|
|
|
auto* groupCommand = renderer->getNextGroupCommand();
|
|
|
|
groupCommand->init(_globalZOrder);
|
|
|
|
renderer->addCommand(groupCommand);
|
|
|
|
renderer->pushGroup(groupCommand->getRenderQueueID());
|
2019-11-23 20:27:39 +08:00
|
|
|
|
2022-06-24 14:18:48 +08:00
|
|
|
auto beginCommand = renderer->nextCallbackCommand();
|
|
|
|
beginCommand->init(_globalZOrder);
|
2022-07-16 10:43:05 +08:00
|
|
|
beginCommand->func = AX_CALLBACK_0(RenderTexture::onBegin, this);
|
2022-06-24 14:18:48 +08:00
|
|
|
renderer->addCommand(beginCommand);
|
2024-09-20 07:30:12 +08:00
|
|
|
#if AX_ENABLE_CACHE_TEXTURE_DATA
|
|
|
|
_cachedTextureDirty = true;
|
|
|
|
#endif
|
2019-11-23 20:27:39 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
void RenderTexture::end()
|
|
|
|
{
|
2021-12-25 10:04:45 +08:00
|
|
|
Renderer* renderer = _director->getRenderer();
|
2022-06-24 14:18:48 +08:00
|
|
|
|
|
|
|
auto endCommand = renderer->nextCallbackCommand();
|
|
|
|
endCommand->init(_globalZOrder);
|
2022-07-16 10:43:05 +08:00
|
|
|
endCommand->func = AX_CALLBACK_0(RenderTexture::onEnd, this);
|
2022-06-24 14:18:48 +08:00
|
|
|
|
|
|
|
renderer->addCommand(endCommand);
|
2019-11-23 20:27:39 +08:00
|
|
|
renderer->popGroup();
|
|
|
|
|
2020-09-13 19:16:59 +08:00
|
|
|
_director->popMatrix(MATRIX_STACK_TYPE::MATRIX_STACK_PROJECTION);
|
|
|
|
_director->popMatrix(MATRIX_STACK_TYPE::MATRIX_STACK_MODELVIEW);
|
2019-11-23 20:27:39 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
void RenderTexture::setClearFlags(ClearFlag clearFlags)
|
|
|
|
{
|
|
|
|
_clearFlags = clearFlags;
|
2021-12-25 10:04:45 +08:00
|
|
|
if (_clearFlags != ClearFlag::NONE && !_depthStencilTexture)
|
2019-11-23 20:27:39 +08:00
|
|
|
{
|
|
|
|
_clearFlags = ClearFlag::COLOR;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void RenderTexture::clearColorAttachment()
|
|
|
|
{
|
2022-06-24 14:18:48 +08:00
|
|
|
auto renderer = _director->getRenderer();
|
|
|
|
auto beforeClearAttachmentCommand = renderer->nextCallbackCommand();
|
|
|
|
beforeClearAttachmentCommand->init(0);
|
2023-03-08 08:34:17 +08:00
|
|
|
beforeClearAttachmentCommand->func = [this, renderer]() -> void {
|
2020-10-16 16:25:10 +08:00
|
|
|
_oldRenderTarget = renderer->getRenderTarget();
|
|
|
|
renderer->setRenderTarget(_renderTarget);
|
|
|
|
};
|
2022-06-24 14:18:48 +08:00
|
|
|
renderer->addCommand(beforeClearAttachmentCommand);
|
2020-10-16 16:25:10 +08:00
|
|
|
|
|
|
|
Color4F color(0.f, 0.f, 0.f, 0.f);
|
|
|
|
renderer->clear(ClearFlag::COLOR, color, 1, 0, _globalZOrder);
|
|
|
|
|
2022-06-24 14:18:48 +08:00
|
|
|
// auto renderer = _director->getRenderer();
|
|
|
|
auto afterClearAttachmentCommand = renderer->nextCallbackCommand();
|
|
|
|
afterClearAttachmentCommand->init(0);
|
2023-03-08 08:34:17 +08:00
|
|
|
afterClearAttachmentCommand->func = [this, renderer]() -> void { renderer->setRenderTarget(_oldRenderTarget); };
|
2022-06-24 14:18:48 +08:00
|
|
|
renderer->addCommand(afterClearAttachmentCommand);
|
2019-11-23 20:27:39 +08:00
|
|
|
}
|
|
|
|
|
2024-09-20 07:30:12 +08:00
|
|
|
} // namespace ax
|