This commit is contained in:
lujun 2023-02-07 16:15:25 +08:00
parent 934207d732
commit 457937ac7f
18 changed files with 3277 additions and 1135 deletions

View File

@ -945,7 +945,7 @@
"__expectedType__": "cc.SpriteFrame"
}
],
"listItemMax": 2,
"listItemMax": 200,
"_id": "9fuu+PfOFHPqnvdYJwsexB"
},
{

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.4 KiB

After

Width:  |  Height:  |  Size: 4.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 395 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 392 KiB

View File

@ -43,12 +43,12 @@ if(NOT COCOS_X_PATH)
message(FATAL_ERROR "COCOS_X_PATH is not set!")
endif()
# lcc-ui-sorting-group native
include(${CMAKE_CURRENT_LIST_DIR}/../lcc-ui-sorting-group-native/CMakeLists.txt)
include(${COCOS_X_PATH}/CMakeLists.txt)
list(APPEND CC_COMMON_SOURCES
${CMAKE_CURRENT_LIST_DIR}/Classes/Game.h
${CMAKE_CURRENT_LIST_DIR}/Classes/Game.cpp
)
# lcc-ui-sorting-group native
include(${CMAKE_CURRENT_LIST_DIR}/../lcc-ui-sorting-group-native/CMakeLists.txt)

View File

@ -1,29 +1,48 @@
string(REPLACE "/" "\\" CMD_COCOS_X_PATH "${COCOS_X_PATH}")
string(REPLACE "/" "\\" CMD_CMAKE_CURRENT_LIST_DIR "${CMAKE_CURRENT_LIST_DIR}")
#string(REPLACE "/" "\\" CMD_COCOS_X_PATH "${COCOS_X_PATH}")
#string(REPLACE "/" "\\" CMD_CMAKE_CURRENT_LIST_DIR "${CMAKE_CURRENT_LIST_DIR}")
#
add_custom_command(
OUTPUT ${CMAKE_CURRENT_LIST_DIR}/ENGINE_REPLACE.txt
COMMAND copy /y "\"${CMD_CMAKE_CURRENT_LIST_DIR}\\replace\\Batcher2d.h\"" "\"${CMD_COCOS_X_PATH}\\cocos\\2d\\renderer\\Batcher2d.h\""
COMMAND copy /y "\"${CMD_CMAKE_CURRENT_LIST_DIR}\\replace\\Batcher2d.cpp\"" "\"${CMD_COCOS_X_PATH}\\cocos\\2d\\renderer\\Batcher2d.cpp\""
COMMAND copy /y "\"${CMD_CMAKE_CURRENT_LIST_DIR}\\replace\\RenderEntity.h\"" "\"${CMD_COCOS_X_PATH}\\cocos\\2d\\renderer\\RenderEntity.h\""
COMMAND copy /y "\"${CMD_CMAKE_CURRENT_LIST_DIR}\\replace\\RenderEntity.cpp\"" "\"${CMD_COCOS_X_PATH}\\cocos\\2d\\renderer\\RenderEntity.cpp\""
COMMAND echo "ENGINE_REPLACE" >> "${CMD_CMAKE_CURRENT_LIST_DIR}\\ENGINE_REPLACE.txt"
COMMAND echo "LCC_UI_SORTING_GROUP pre"
WORKING_DIRECTORY ${CMAKE_CURRENT_LIST_DIR}
)
add_custom_target(LCC_UI_SORTING_GROUP_ENGINE_REPLACE DEPENDS ${CMAKE_CURRENT_LIST_DIR}/ENGINE_REPLACE.txt)
add_dependencies(${ENGINE_NAME} LCC_UI_SORTING_GROUP_ENGINE_REPLACE)
#add_custom_command(
# OUTPUT ${CMAKE_CURRENT_LIST_DIR}/ENGINE_REPLACE.txt
# COMMAND copy /y "\"${CMD_CMAKE_CURRENT_LIST_DIR}\\replace\\Batcher2d.h\"" "\"${CMD_COCOS_X_PATH}\\cocos\\2d\\renderer\\Batcher2d.h\""
# COMMAND copy /y "\"${CMD_CMAKE_CURRENT_LIST_DIR}\\replace\\Batcher2d.cpp\"" "\"${CMD_COCOS_X_PATH}\\cocos\\2d\\renderer\\Batcher2d.cpp\""
# COMMAND copy /y "\"${CMD_CMAKE_CURRENT_LIST_DIR}\\replace\\RenderEntity.h\"" "\"${CMD_COCOS_X_PATH}\\cocos\\2d\\renderer\\RenderEntity.h\""
# COMMAND copy /y "\"${CMD_CMAKE_CURRENT_LIST_DIR}\\replace\\RenderEntity.cpp\"" "\"${CMD_COCOS_X_PATH}\\cocos\\2d\\renderer\\RenderEntity.cpp\""
# COMMAND echo "ENGINE_REPLACE" >> "${CMD_CMAKE_CURRENT_LIST_DIR}\\ENGINE_REPLACE.txt"
# COMMAND echo "LCC_UI_SORTING_GROUP pre"
# WORKING_DIRECTORY ${CMAKE_CURRENT_LIST_DIR}
#)
#add_custom_target(LCC_UI_SORTING_GROUP_ENGINE_REPLACE DEPENDS ${CMAKE_CURRENT_LIST_DIR}/ENGINE_REPLACE.txt)
#add_dependencies(${ENGINE_NAME} LCC_UI_SORTING_GROUP_ENGINE_REPLACE)
#
add_custom_command(TARGET ${ENGINE_NAME}
POST_BUILD
COMMAND copy /y "\"${CMD_CMAKE_CURRENT_LIST_DIR}\\backup\\Batcher2d.h\"" "\"${CMD_COCOS_X_PATH}\\cocos\\2d\\renderer\\Batcher2d.h\""
COMMAND copy /y "\"${CMD_CMAKE_CURRENT_LIST_DIR}\\backup\\Batcher2d.cpp\"" "\"${CMD_COCOS_X_PATH}\\cocos\\2d\\renderer\\Batcher2d.cpp\""
COMMAND copy /y "\"${CMD_CMAKE_CURRENT_LIST_DIR}\\backup\\RenderEntity.h\"" "\"${CMD_COCOS_X_PATH}\\cocos\\2d\\renderer\\RenderEntity.h\""
COMMAND copy /y "\"${CMD_CMAKE_CURRENT_LIST_DIR}\\backup\\RenderEntity.cpp\"" "\"${CMD_COCOS_X_PATH}\\cocos\\2d\\renderer\\RenderEntity.cpp\""
COMMAND del "${CMD_CMAKE_CURRENT_LIST_DIR}\\ENGINE_REPLACE.txt"
COMMAND echo "LCC_UI_SORTING_GROUP post"
WORKING_DIRECTORY ${CMAKE_CURRENT_LIST_DIR}
)
#add_custom_command(TARGET ${ENGINE_NAME}
# POST_BUILD
# COMMAND copy /y "\"${CMD_CMAKE_CURRENT_LIST_DIR}\\backup\\Batcher2d.h\"" "\"${CMD_COCOS_X_PATH}\\cocos\\2d\\renderer\\Batcher2d.h\""
# COMMAND copy /y "\"${CMD_CMAKE_CURRENT_LIST_DIR}\\backup\\Batcher2d.cpp\"" "\"${CMD_COCOS_X_PATH}\\cocos\\2d\\renderer\\Batcher2d.cpp\""
# COMMAND copy /y "\"${CMD_CMAKE_CURRENT_LIST_DIR}\\backup\\RenderEntity.h\"" "\"${CMD_COCOS_X_PATH}\\cocos\\2d\\renderer\\RenderEntity.h\""
# COMMAND copy /y "\"${CMD_CMAKE_CURRENT_LIST_DIR}\\backup\\RenderEntity.cpp\"" "\"${CMD_COCOS_X_PATH}\\cocos\\2d\\renderer\\RenderEntity.cpp\""
# COMMAND del "${CMD_CMAKE_CURRENT_LIST_DIR}\\ENGINE_REPLACE.txt"
# COMMAND echo "LCC_UI_SORTING_GROUP post"
# WORKING_DIRECTORY ${CMAKE_CURRENT_LIST_DIR}
#)
if(NOT DEFINED COCOS_SOURCE_PLUGIN_EXCULDE)
set(COCOS_SOURCE_PLUGIN_EXCULDE)
endif()
if(NOT DEFINED COCOS_SOURCE_PLUGIN_LIST)
set(COCOS_SOURCE_PLUGIN_LIST)
endif()
if(NOT DEFINED COCOS_SOURCE_PLUGIN_INCLUDES)
set(COCOS_SOURCE_PLUGIN_INCLUDES)
endif()
#
list(APPEND COCOS_SOURCE_PLUGIN_EXCULDE "${COCOS_X_PATH}/cocos/2d/renderer/Batcher2d.h" "${COCOS_X_PATH}/cocos/2d/renderer/Batcher2d.cpp" "${COCOS_X_PATH}/cocos/2d/renderer/RenderEntity.h" "${COCOS_X_PATH}/cocos/2d/renderer/RenderEntity.cpp")
#
list(APPEND COCOS_SOURCE_PLUGIN_LIST "${CMAKE_CURRENT_LIST_DIR}/native/cocos/2d/renderer/Batcher2d.h" "${CMAKE_CURRENT_LIST_DIR}/native/cocos/2d/renderer/Batcher2d.cpp" "${CMAKE_CURRENT_LIST_DIR}/native/cocos/2d/renderer/RenderEntity.h" "${CMAKE_CURRENT_LIST_DIR}/native/cocos/2d/renderer/RenderEntity.cpp")
#
list(APPEND COCOS_SOURCE_PLUGIN_INCLUDES "${CMAKE_CURRENT_LIST_DIR}/native" "${CMAKE_CURRENT_LIST_DIR}/native/cocos")

View File

@ -1,609 +0,0 @@
/****************************************************************************
Copyright (c) 2019-2021 Xiamen Yaji Software Co., Ltd.
http://www.cocos.com
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated engine source code (the "Software"), a limited,
worldwide, royalty-free, non-assignable, revocable and non-exclusive license
to use Cocos Creator solely to develop games on your target platforms. You shall
not use Cocos Creator software for developing other software or tools that's
used for developing games. You are not granted to publish, distribute,
sublicense, and/or sell copies of Cocos Creator.
The software or tools in this License Agreement are licensed, not sold.
Xiamen Yaji Software Co., Ltd. reserves all rights not expressly granted to you.
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.
****************************************************************************/
#include "2d/renderer/Batcher2d.h"
#include "application/ApplicationManager.h"
#include "base/TypeDef.h"
#include "core/Root.h"
#include "editor-support/MiddlewareManager.h"
#include "renderer/pipeline/Define.h"
#include "scene/Pass.h"
namespace cc {
Batcher2d::Batcher2d() : Batcher2d(nullptr) {
}
Batcher2d::Batcher2d(Root* root)
: _drawBatchPool([]() { return ccnew scene::DrawBatch2D(); }, [](auto* obj) { delete obj; }, 10U) {
if (root == nullptr) {
root = Root::getInstance();
}
_root = root;
_device = _root->getDevice();
_stencilManager = StencilManager::getInstance();
}
Batcher2d::~Batcher2d() { // NOLINT
_drawBatchPool.destroy();
for (auto iter : _descriptorSetCache) {
delete iter.second;
}
for (auto* drawBatch : _batches) {
delete drawBatch;
}
_attributes.clear();
if(_maskClearModel != nullptr) {
Root::getInstance()->destroyModel(_maskClearModel);
_maskClearModel = nullptr;
}
if (_maskModelMesh != nullptr) {
_maskModelMesh->destroy();
_maskModelMesh = nullptr;
}
_maskClearMtl = nullptr;
_maskAttributes.clear();
}
void Batcher2d::syncMeshBuffersToNative(uint16_t accId, ccstd::vector<UIMeshBuffer*>&& buffers) {
_meshBuffersMap[accId] = std::move(buffers);
}
UIMeshBuffer* Batcher2d::getMeshBuffer(uint16_t accId, uint16_t bufferId) { // NOLINT(bugprone-easily-swappable-parameters)
const auto& map = _meshBuffersMap[accId];
return map[bufferId];
}
gfx::Device* Batcher2d::getDevice() {
if (_device == nullptr) {
_device = Root::getInstance()->getDevice();
}
return _device;
}
void Batcher2d::updateDescriptorSet() {
}
void Batcher2d::syncRootNodesToNative(ccstd::vector<Node*>&& rootNodes) {
_rootNodeArr = std::move(rootNodes);
}
void Batcher2d::fillBuffersAndMergeBatches() {
for (auto* rootNode : _rootNodeArr) {
walk(rootNode, 1);
generateBatch(_currEntity, _currDrawInfo);
}
}
void Batcher2d::walk(Node* node, float parentOpacity) { // NOLINT(misc-no-recursion)
if (!node->isActiveInHierarchy()) {
return;
}
bool breakWalk = false;
auto* entity = static_cast<RenderEntity*>(node->getUserData());
if (entity) {
if (entity->getColorDirty()) {
float localOpacity = entity->getLocalOpacity();
float localColorAlpha = entity->getColorAlpha();
entity->setOpacity(parentOpacity * localOpacity * localColorAlpha);
entity->setColorDirty(false);
entity->setVBColorDirty(true);
}
if (entity->isEnabled()) {
uint32_t size = entity->getRenderDrawInfosSize();
for (uint32_t i = 0; i < size; i++) {
auto* drawInfo = entity->getRenderDrawInfoAt(i);
handleDrawInfo(entity, drawInfo, node);
}
entity->setVBColorDirty(false);
}
if (entity->getRenderEntityType() == RenderEntityType::CROSSED) {
breakWalk = true;
}
}
if (!breakWalk) {
const auto& children = node->getChildren();
float thisOpacity = entity ? entity->getOpacity() : parentOpacity;
for (const auto& child : children) {
// we should find parent opacity recursively upwards if it doesn't have an entity.
walk(child, thisOpacity);
}
}
// post assembler
if (_stencilManager->getMaskStackSize() > 0 && entity && entity->isEnabled()) {
handlePostRender(entity);
}
}
void Batcher2d::handlePostRender(RenderEntity* entity) {
bool isMask = entity->getIsMask();
if (isMask) {
generateBatch(_currEntity, _currDrawInfo);
resetRenderStates();
_stencilManager->exitMask();
}
}
CC_FORCE_INLINE void Batcher2d::handleComponentDraw(RenderEntity* entity, RenderDrawInfo* drawInfo, Node* node) {
ccstd::hash_t dataHash = drawInfo->getDataHash();
if (drawInfo->getIsMeshBuffer()) {
dataHash = 0;
}
// may slow
bool isMask = entity->getIsMask();
if (isMask) {
// Mask subComp
insertMaskBatch(entity);
} else {
entity->setEnumStencilStage(_stencilManager->getStencilStage());
}
auto tempStage = static_cast<StencilStage>(entity->getStencilStage());
if (_currHash != dataHash || dataHash == 0 || _currMaterial != drawInfo->getMaterial() || _currStencilStage != tempStage) {
// Generate a batch if not batching
generateBatch(_currEntity, _currDrawInfo);
if (!drawInfo->getIsMeshBuffer()) {
UIMeshBuffer* buffer = drawInfo->getMeshBuffer();
if (_currMeshBuffer != buffer) {
_currMeshBuffer = buffer;
_indexStart = _currMeshBuffer->getIndexOffset();
}
}
_currHash = dataHash;
_currMaterial = drawInfo->getMaterial();
_currStencilStage = tempStage;
_currLayer = entity->getNode()->getLayer();
_currEntity = entity;
_currDrawInfo = drawInfo;
_currTexture = drawInfo->getTexture();
_currSampler = drawInfo->getSampler();
if (_currSampler == nullptr) {
_currSamplerHash = 0;
} else {
_currSamplerHash = _currSampler->getHash();
}
}
if (!drawInfo->getIsMeshBuffer()) {
if (node->getChangedFlags() || drawInfo->getVertDirty()) {
fillVertexBuffers(entity, drawInfo);
drawInfo->setVertDirty(false);
}
if (entity->getVBColorDirty()) {
fillColors(entity, drawInfo);
}
fillIndexBuffers(drawInfo);
}
if (isMask) {
_stencilManager->enableMask();
}
}
CC_FORCE_INLINE void Batcher2d::handleModelDraw(RenderEntity* entity, RenderDrawInfo* drawInfo) {
generateBatch(_currEntity, _currDrawInfo);
resetRenderStates();
// stencil stage
gfx::DepthStencilState* depthStencil = nullptr;
ccstd::hash_t dssHash = 0;
Material* renderMat = drawInfo->getMaterial();
bool isMask = entity->getIsMask();
if (isMask) {
//Mask Comp
insertMaskBatch(entity);
} else {
entity->setEnumStencilStage(_stencilManager->getStencilStage());
}
StencilStage entityStage = entity->getEnumStencilStage();
depthStencil = _stencilManager->getDepthStencilState(entityStage, renderMat);
dssHash = _stencilManager->getStencilHash(entityStage);
// Model
auto* model = drawInfo->getModel();
if (model == nullptr) return;
auto stamp = CC_CURRENT_ENGINE()->getTotalFrames();
model->updateTransform(stamp);
model->updateUBOs(stamp);
const auto& subModelList = model->getSubModels();
for (const auto& submodel : subModelList) {
auto* curdrawBatch = _drawBatchPool.alloc();
curdrawBatch->setVisFlags(entity->getNode()->getLayer());
curdrawBatch->setModel(model);
curdrawBatch->setInputAssembler(submodel->getInputAssembler());
curdrawBatch->setDescriptorSet(submodel->getDescriptorSet());
curdrawBatch->fillPass(renderMat, depthStencil, dssHash, &(submodel->getPatches()));
_batches.push_back(curdrawBatch);
}
if(isMask) {
_stencilManager->enableMask();
}
}
CC_FORCE_INLINE void Batcher2d::handleMiddlewareDraw(RenderEntity* entity, RenderDrawInfo* drawInfo) {
auto layer = entity->getNode()->getLayer();
Material* material = drawInfo->getMaterial();
auto* texture = drawInfo->getTexture();
auto* sampler = drawInfo->getSampler();
auto* meshBuffer = drawInfo->getMeshBuffer();
// check for merge draw
auto enableBatch = !entity->getUseLocal();
if (enableBatch && _currTexture == texture && _currMeshBuffer == meshBuffer
&& !_currEntity->getUseLocal()
&& material->getHash() == _currMaterial->getHash()
&& drawInfo->getIndexOffset() == _currDrawInfo->getIndexOffset() + _currDrawInfo->getIbCount()
&& layer == _currLayer) {
auto ibCount = _currDrawInfo->getIbCount();
_currDrawInfo->setIbCount(ibCount + drawInfo->getIbCount());
} else {
generateBatch(_currEntity, _currDrawInfo);
_currLayer = layer;
_currMaterial = material;
_currTexture = texture;
_currMeshBuffer = meshBuffer;
_currEntity = entity;
_currDrawInfo = drawInfo;
_currHash = 0;
}
}
CC_FORCE_INLINE void Batcher2d::handleSubNode(RenderEntity* entity, RenderDrawInfo* drawInfo) { // NOLINT
if (drawInfo->getSubNode()) {
walk(drawInfo->getSubNode(), entity->getOpacity());
}
}
CC_FORCE_INLINE void Batcher2d::handleDrawInfo(RenderEntity* entity, RenderDrawInfo* drawInfo, Node* node) { //NOLINT(misc-no-recursion)
CC_ASSERT(entity);
CC_ASSERT(drawInfo);
RenderDrawInfoType drawInfoType = drawInfo->getEnumDrawInfoType();
switch (drawInfoType) {
case RenderDrawInfoType::COMP:
handleComponentDraw(entity, drawInfo, node);
break;
case RenderDrawInfoType::MODEL:
handleModelDraw(entity, drawInfo);
break;
case RenderDrawInfoType::MIDDLEWARE:
handleMiddlewareDraw(entity, drawInfo);
break;
case RenderDrawInfoType::SUB_NODE:
handleSubNode(entity, drawInfo);
break;
default:
break;
}
}
void Batcher2d::generateBatch(RenderEntity* entity, RenderDrawInfo* drawInfo) {
if (drawInfo == nullptr) {
return;
}
if (drawInfo->getEnumDrawInfoType() == RenderDrawInfoType::MIDDLEWARE) {
generateBatchForMiddleware(entity, drawInfo);
return;
}
if (_currMaterial == nullptr) {
return;
}
gfx::InputAssembler* ia = nullptr;
if (drawInfo->getIsMeshBuffer()) {
// Todo MeshBuffer RenderData
ia = drawInfo->requestIA(getDevice());
_meshRenderDrawInfo.emplace_back(drawInfo);
} else {
UIMeshBuffer* currMeshBuffer = drawInfo->getMeshBuffer();
currMeshBuffer->setDirty(true);
ia = currMeshBuffer->requireFreeIA(getDevice());
uint32_t indexCount = currMeshBuffer->getIndexOffset() - _indexStart;
if (ia == nullptr) {
return;
}
ia->setFirstIndex(_indexStart);
ia->setIndexCount(indexCount);
_indexStart = currMeshBuffer->getIndexOffset();
}
_currMeshBuffer = nullptr;
// stencilStage
gfx::DepthStencilState* depthStencil = nullptr;
ccstd::hash_t dssHash = 0;
StencilStage entityStage = entity->getEnumStencilStage();
depthStencil = _stencilManager->getDepthStencilState(entityStage, _currMaterial);
dssHash = _stencilManager->getStencilHash(entityStage);
auto* curdrawBatch = _drawBatchPool.alloc();
curdrawBatch->setVisFlags(_currLayer);
curdrawBatch->setInputAssembler(ia);
curdrawBatch->fillPass(_currMaterial, depthStencil, dssHash);
const auto& pass = curdrawBatch->getPasses().at(0);
if (entity->getUseLocal()) {
drawInfo->updateLocalDescriptorSet(entity->getRenderTransform(), pass->getLocalSetLayout());
curdrawBatch->setDescriptorSet(drawInfo->getLocalDes());
} else {
curdrawBatch->setDescriptorSet(getDescriptorSet(_currTexture, _currSampler, pass->getLocalSetLayout()));
}
_batches.push_back(curdrawBatch);
}
void Batcher2d::generateBatchForMiddleware(RenderEntity* entity, RenderDrawInfo* drawInfo) {
auto layer = entity->getNode()->getLayer();
auto* material = drawInfo->getMaterial();
auto* texture = drawInfo->getTexture();
auto* sampler = drawInfo->getSampler();
auto* meshBuffer = drawInfo->getMeshBuffer();
//set meshbuffer offset
auto indexOffset = drawInfo->getIndexOffset();
auto indexCount = drawInfo->getIbCount();
indexOffset += indexCount;
if (meshBuffer->getIndexOffset() < indexOffset) {
meshBuffer->setIndexOffset(indexOffset);
}
meshBuffer->setDirty(true);
gfx::InputAssembler* ia = meshBuffer->requireFreeIA(getDevice());
ia->setFirstIndex(drawInfo->getIndexOffset());
ia->setIndexCount(drawInfo->getIbCount());
// stencilstage
auto stencilStage = _stencilManager->getStencilStage();
gfx::DepthStencilState* depthStencil = _stencilManager->getDepthStencilState(stencilStage, material);
ccstd::hash_t dssHash = _stencilManager->getStencilHash(stencilStage);
auto* curdrawBatch = _drawBatchPool.alloc();
curdrawBatch->setVisFlags(_currLayer);
curdrawBatch->setInputAssembler(ia);
curdrawBatch->fillPass(material, depthStencil, dssHash);
const auto& pass = curdrawBatch->getPasses().at(0);
if (entity->getUseLocal()) {
drawInfo->updateLocalDescriptorSet(entity->getNode(), pass->getLocalSetLayout());
curdrawBatch->setDescriptorSet(drawInfo->getLocalDes());
} else {
curdrawBatch->setDescriptorSet(getDescriptorSet(texture, sampler, pass->getLocalSetLayout()));
}
_batches.push_back(curdrawBatch);
// make sure next generateBatch return.
resetRenderStates();
_currMeshBuffer = nullptr;
}
void Batcher2d::resetRenderStates() {
_currMaterial = nullptr;
_currTexture = nullptr;
_currSampler = nullptr;
_currSamplerHash = 0;
_currLayer = 0;
_currEntity = nullptr;
_currDrawInfo = nullptr;
}
gfx::DescriptorSet* Batcher2d::getDescriptorSet(gfx::Texture* texture, gfx::Sampler* sampler, gfx::DescriptorSetLayout* dsLayout) {
ccstd::hash_t hash = 2;
size_t textureHash;
if (texture != nullptr) {
textureHash = boost::hash_value(texture);
ccstd::hash_combine(hash, textureHash);
}
if (sampler != nullptr) {
ccstd::hash_combine(hash, sampler->getHash());
}
auto iter = _descriptorSetCache.find(hash);
if (iter != _descriptorSetCache.end()) {
if (texture != nullptr && sampler != nullptr) {
iter->second->bindTexture(static_cast<uint32_t>(pipeline::ModelLocalBindings::SAMPLER_SPRITE), texture);
iter->second->bindSampler(static_cast<uint32_t>(pipeline::ModelLocalBindings::SAMPLER_SPRITE), sampler);
}
iter->second->forceUpdate();
return iter->second;
}
_dsInfo.layout = dsLayout;
auto* ds = getDevice()->createDescriptorSet(_dsInfo);
if (texture != nullptr && sampler != nullptr) {
ds->bindTexture(static_cast<uint32_t>(pipeline::ModelLocalBindings::SAMPLER_SPRITE), texture);
ds->bindSampler(static_cast<uint32_t>(pipeline::ModelLocalBindings::SAMPLER_SPRITE), sampler);
}
ds->update();
_descriptorSetCache.emplace(hash, ds);
return ds;
}
void Batcher2d::releaseDescriptorSetCache(gfx::Texture* texture, gfx::Sampler* sampler) {
ccstd::hash_t hash = 2;
size_t textureHash;
if (texture != nullptr) {
textureHash = boost::hash_value(texture);
ccstd::hash_combine(hash, textureHash);
}
if (sampler != nullptr) {
ccstd::hash_combine(hash, sampler->getHash());
}
auto iter = _descriptorSetCache.find(hash);
if (iter != _descriptorSetCache.end()) {
delete iter->second;
_descriptorSetCache.erase(hash);
}
}
bool Batcher2d::initialize() {
_isInit = true;
return _isInit;
}
void Batcher2d::update() {
fillBuffersAndMergeBatches();
resetRenderStates();
for (const auto& scene : Root::getInstance()->getScenes()) {
for (auto* batch : _batches) {
scene->addBatch(batch);
}
}
}
void Batcher2d::uploadBuffers() {
if (_batches.empty()) {
return;
}
for (auto& meshRenderData : _meshRenderDrawInfo) {
meshRenderData->uploadBuffers();
}
for (auto& map : _meshBuffersMap) {
for (auto& buffer : map.second) {
buffer->uploadBuffers();
buffer->reset();
}
}
updateDescriptorSet();
}
void Batcher2d::reset() {
for (auto& batch : _batches) {
batch->clear();
_drawBatchPool.free(batch);
}
_batches.clear();
for (auto& meshRenderData : _meshRenderDrawInfo) {
meshRenderData->resetMeshIA();
}
_meshRenderDrawInfo.clear();
// meshDataArray
for (auto& map : _meshBuffersMap) {
for (auto& buffer : map.second) {
if (buffer) {
buffer->resetIA();
}
}
}
//meshBuffer cannot clear because it is not transported at every frame.
_currMeshBuffer = nullptr;
_indexStart = 0;
_currHash = 0;
_currLayer = 0;
_currMaterial = nullptr;
_currTexture = nullptr;
_currSampler = nullptr;
// stencilManager
}
void Batcher2d::insertMaskBatch(RenderEntity* entity){
generateBatch(_currEntity, _currDrawInfo);
resetRenderStates();
createClearModel();
_maskClearModel->setNode(entity->getNode());
_maskClearModel->setTransform(entity->getNode());
_stencilManager->pushMask();
auto stage = _stencilManager->clear(entity);
gfx::DepthStencilState* depthStencil = nullptr;
ccstd::hash_t dssHash = 0;
if(_maskClearMtl != nullptr){
depthStencil = _stencilManager->getDepthStencilState(stage, _maskClearMtl);
dssHash = _stencilManager->getStencilHash(stage);
}
// Model
if (_maskClearModel == nullptr) return;
auto stamp = CC_CURRENT_ENGINE()->getTotalFrames();
_maskClearModel->updateTransform(stamp);
_maskClearModel->updateUBOs(stamp);
const auto& subModelList = _maskClearModel->getSubModels();
for (const auto& submodel : subModelList) {
auto* curdrawBatch = _drawBatchPool.alloc();
curdrawBatch->setVisFlags(entity->getNode()->getLayer());
curdrawBatch->setModel(_maskClearModel);
curdrawBatch->setInputAssembler(submodel->getInputAssembler());
curdrawBatch->setDescriptorSet(submodel->getDescriptorSet());
curdrawBatch->fillPass(_maskClearMtl, depthStencil, dssHash, &(submodel->getPatches()));
_batches.push_back(curdrawBatch);
}
_stencilManager->enterLevel(entity);
}
void Batcher2d::createClearModel() {
if (_maskClearModel == nullptr) {
_maskClearMtl = BuiltinResMgr::getInstance()->get<Material>(ccstd::string("default-clear-stencil"));
_maskClearModel = Root::getInstance()->createModel<scene::Model>();
uint32_t stride = 12;// vfmt
auto* vertexBuffer = _device->createBuffer({
gfx::BufferUsageBit::VERTEX | gfx::BufferUsageBit::TRANSFER_DST,
gfx::MemoryUsageBit::DEVICE,
4 * stride,
stride,
});
const float vertices[] = {-1, -1, 0, 1, -1, 0, -1, 1, 0, 1, 1, 0};
vertexBuffer->update(vertices);
auto* indexBuffer = _device->createBuffer({
gfx::BufferUsageBit::INDEX | gfx::BufferUsageBit::TRANSFER_DST,
gfx::MemoryUsageBit::DEVICE,
6 * sizeof(uint16_t),
sizeof(uint16_t),
});
const uint16_t indices[] = {0, 2, 1, 2, 1, 3};
indexBuffer->update(indices);
gfx::BufferList vbReference;
vbReference.emplace_back(vertexBuffer);
_maskModelMesh = ccnew RenderingSubMesh(vbReference, _maskAttributes, _primitiveMode, indexBuffer);
_maskModelMesh->setSubMeshIdx(0);
_maskClearModel->initSubModel(0, _maskModelMesh, _maskClearMtl);
}
}
} // namespace cc

View File

@ -1,203 +0,0 @@
/****************************************************************************
Copyright (c) 2019-2021 Xiamen Yaji Software Co., Ltd.
http://www.cocos.com
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated engine source code (the "Software"), a limited,
worldwide, royalty-free, non-assignable, revocable and non-exclusive license
to use Cocos Creator solely to develop games on your target platforms. You shall
not use Cocos Creator software for developing other software or tools that's
used for developing games. You are not granted to publish, distribute,
sublicense, and/or sell copies of Cocos Creator.
The software or tools in this License Agreement are licensed, not sold.
Xiamen Yaji Software Co., Ltd. reserves all rights not expressly granted to you.
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.
****************************************************************************/
#pragma once
#include "2d/renderer/RenderDrawInfo.h"
#include "2d/renderer/RenderEntity.h"
#include "2d/renderer/UIMeshBuffer.h"
#include "base/Macros.h"
#include "base/Ptr.h"
#include "base/TypeDef.h"
#include "core/assets/Material.h"
#include "core/memop/Pool.h"
#include "renderer/gfx-base/GFXTexture.h"
#include "renderer/gfx-base/states/GFXSampler.h"
#include "scene/DrawBatch2D.h"
namespace cc {
class Root;
using UIMeshBufferArray = ccstd::vector<UIMeshBuffer*>;
using UIMeshBufferMap = ccstd::unordered_map<uint16_t, UIMeshBufferArray>;
class Batcher2d final {
public:
Batcher2d();
explicit Batcher2d(Root* root);
~Batcher2d();
void syncMeshBuffersToNative(uint16_t accId, ccstd::vector<UIMeshBuffer*>&& buffers);
bool initialize();
void update();
void uploadBuffers();
void reset();
void syncRootNodesToNative(ccstd::vector<Node*>&& rootNodes);
void releaseDescriptorSetCache(gfx::Texture* texture, gfx::Sampler* sampler);
UIMeshBuffer* getMeshBuffer(uint16_t accId, uint16_t bufferId);
gfx::Device* getDevice();
inline ccstd::vector<gfx::Attribute>* getDefaultAttribute() { return &_attributes; }
void updateDescriptorSet();
void fillBuffersAndMergeBatches();
void walk(Node* node, float parentOpacity);
void handlePostRender(RenderEntity* entity);
void handleDrawInfo(RenderEntity* entity, RenderDrawInfo* drawInfo, Node* node);
void handleComponentDraw(RenderEntity* entity, RenderDrawInfo* drawInfo, Node* node);
void handleModelDraw(RenderEntity* entity, RenderDrawInfo* drawInfo);
void handleMiddlewareDraw(RenderEntity* entity, RenderDrawInfo* drawInfo);
void handleSubNode(RenderEntity* entity, RenderDrawInfo* drawInfo);
void generateBatch(RenderEntity* entity, RenderDrawInfo* drawInfo);
void generateBatchForMiddleware(RenderEntity* entity, RenderDrawInfo* drawInfo);
void resetRenderStates();
private:
bool _isInit = false;
inline void fillIndexBuffers(RenderDrawInfo* drawInfo) { // NOLINT(readability-convert-member-functions-to-static)
uint16_t* ib = drawInfo->getIDataBuffer();
UIMeshBuffer* buffer = drawInfo->getMeshBuffer();
uint32_t indexOffset = buffer->getIndexOffset();
uint16_t* indexb = drawInfo->getIbBuffer();
uint32_t indexCount = drawInfo->getIbCount();
memcpy(&ib[indexOffset], indexb, indexCount * sizeof(uint16_t));
indexOffset += indexCount;
buffer->setIndexOffset(indexOffset);
}
inline void fillVertexBuffers(RenderEntity* entity, RenderDrawInfo* drawInfo) { // NOLINT(readability-convert-member-functions-to-static)
Node* node = entity->getNode();
const Mat4& matrix = node->getWorldMatrix();
uint8_t stride = drawInfo->getStride();
uint32_t size = drawInfo->getVbCount() * stride;
float* vbBuffer = drawInfo->getVbBuffer();
for (int i = 0; i < size; i += stride) {
Render2dLayout* curLayout = drawInfo->getRender2dLayout(i);
// make sure that the layout of Vec3 is three consecutive floats
static_assert(sizeof(Vec3) == 3 * sizeof(float));
// cast to reduce value copy instructions
reinterpret_cast<Vec3*>(vbBuffer + i)->transformMat4(curLayout->position, matrix);
}
}
inline void setIndexRange(RenderDrawInfo* drawInfo) { // NOLINT(readability-convert-member-functions-to-static)
UIMeshBuffer* buffer = drawInfo->getMeshBuffer();
uint32_t indexOffset = drawInfo->getIndexOffset();
uint32_t indexCount = drawInfo->getIbCount();
indexOffset += indexCount;
if (buffer->getIndexOffset() < indexOffset) {
buffer->setIndexOffset(indexOffset);
}
}
inline void fillColors(RenderEntity* entity, RenderDrawInfo* drawInfo) { // NOLINT(readability-convert-member-functions-to-static)
Color temp = entity->getColor();
uint8_t stride = drawInfo->getStride();
uint32_t size = drawInfo->getVbCount() * stride;
float* vbBuffer = drawInfo->getVbBuffer();
uint32_t offset = 0;
for (int i = 0; i < size; i += stride) {
offset = i + 5;
vbBuffer[offset++] = static_cast<float>(temp.r) / 255.0F;
vbBuffer[offset++] = static_cast<float>(temp.g) / 255.0F;
vbBuffer[offset++] = static_cast<float>(temp.b) / 255.0F;
vbBuffer[offset++] = entity->getOpacity();
}
}
void insertMaskBatch(RenderEntity* entity);
void createClearModel ();
gfx::DescriptorSet* getDescriptorSet(gfx::Texture* texture, gfx::Sampler* sampler, gfx::DescriptorSetLayout* dsLayout);
StencilManager* _stencilManager{nullptr};
// weak reference
Root* _root{nullptr};
// weak reference
ccstd::vector<Node*> _rootNodeArr;
// manage memory manually
ccstd::vector<scene::DrawBatch2D*> _batches;
memop::Pool<scene::DrawBatch2D> _drawBatchPool;
// weak reference
gfx::Device* _device{nullptr}; // use getDevice()
// weak reference
RenderEntity* _currEntity{nullptr};
// weak reference
RenderDrawInfo* _currDrawInfo{nullptr};
// weak reference
UIMeshBuffer* _currMeshBuffer{nullptr};
uint32_t _indexStart{0};
ccstd::hash_t _currHash{0};
uint32_t _currLayer{0};
StencilStage _currStencilStage{StencilStage::DISABLED};
// weak reference
Material* _currMaterial{nullptr};
// weak reference
gfx::Texture* _currTexture{nullptr};
// weak reference
gfx::Sampler* _currSampler{nullptr};
ccstd::hash_t _currSamplerHash{0};
// weak reference
ccstd::vector<RenderDrawInfo*> _meshRenderDrawInfo;
// manage memory manually
ccstd::unordered_map<ccstd::hash_t, gfx::DescriptorSet*> _descriptorSetCache;
gfx::DescriptorSetInfo _dsInfo;
UIMeshBufferMap _meshBuffersMap;
// DefaultAttribute
ccstd::vector<gfx::Attribute> _attributes{
gfx::Attribute{gfx::ATTR_NAME_POSITION, gfx::Format::RGB32F},
gfx::Attribute{gfx::ATTR_NAME_TEX_COORD, gfx::Format::RG32F},
gfx::Attribute{gfx::ATTR_NAME_COLOR, gfx::Format::RGBA32F},
};
// Mask use
IntrusivePtr<scene::Model> _maskClearModel;
IntrusivePtr<Material> _maskClearMtl;
IntrusivePtr<RenderingSubMesh> _maskModelMesh;
ccstd::vector<gfx::Attribute> _maskAttributes{
gfx::Attribute{gfx::ATTR_NAME_POSITION, gfx::Format::RGB32F},
};
gfx::PrimitiveMode _primitiveMode{gfx::PrimitiveMode::TRIANGLE_LIST};
CC_DISALLOW_COPY_MOVE_ASSIGN(Batcher2d);
};
} // namespace cc

File diff suppressed because it is too large Load Diff

View File

@ -1,159 +0,0 @@
/****************************************************************************
Copyright (c) 2019-2021 Xiamen Yaji Software Co., Ltd.
http://www.cocos.com
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated engine source code (the "Software"), a limited,
worldwide, royalty-free, non-assignable, revocable and non-exclusive license
to use Cocos Creator solely to develop games on your target platforms. You shall
not use Cocos Creator software for developing other software or tools that's
used for developing games. You are not granted to publish, distribute,
sublicense, and/or sell copies of Cocos Creator.
The software or tools in this License Agreement are licensed, not sold.
Xiamen Yaji Software Co., Ltd. reserves all rights not expressly granted to you.
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.
****************************************************************************/
#pragma once
#include <array>
#include "2d/renderer/RenderDrawInfo.h"
#include "2d/renderer/StencilManager.h"
#include "base/Macros.h"
#include "base/TypeDef.h"
#include "bindings/utils/BindingUtils.h"
#include "core/ArrayBuffer.h"
#include "core/scene-graph/Node.h"
namespace cc {
class Batcher2d;
enum class RenderEntityType : uint8_t {
STATIC,
DYNAMIC,
CROSSED,
};
enum class MaskMode : uint8_t {
NONE,
MASK,
MASK_INVERTED,
MASK_NODE,
MASK_NODE_INVERTED
};
struct EntityAttrLayout {
float localOpacity{1.0F};
uint8_t colorR{255};
uint8_t colorG{255};
uint8_t colorB{255};
uint8_t colorA{255};
uint8_t maskMode{0};
uint8_t colorDirtyBit{1};
uint8_t enabledIndex{0};
uint8_t useLocal{0};
};
class RenderEntity final : public Node::UserData {
public:
static constexpr uint32_t STATIC_DRAW_INFO_CAPACITY = 4;
explicit RenderEntity(RenderEntityType type);
~RenderEntity() override;
void addDynamicRenderDrawInfo(RenderDrawInfo* drawInfo);
void setDynamicRenderDrawInfo(RenderDrawInfo* drawInfo, uint32_t index);
void removeDynamicRenderDrawInfo();
void clearDynamicRenderDrawInfos();
void clearStaticRenderDrawInfos();
inline bool getIsMask() const {
return static_cast<MaskMode>(_entityAttrLayout.maskMode) == MaskMode::MASK || static_cast<MaskMode>(_entityAttrLayout.maskMode) == MaskMode::MASK_INVERTED;
}
inline bool getIsSubMask() const {
return static_cast<MaskMode>(_entityAttrLayout.maskMode) == MaskMode::MASK_NODE || static_cast<MaskMode>(_entityAttrLayout.maskMode) == MaskMode::MASK_NODE_INVERTED;
}
inline bool getIsMaskInverted() const {
return static_cast<MaskMode>(_entityAttrLayout.maskMode) == MaskMode::MASK_INVERTED || static_cast<MaskMode>(_entityAttrLayout.maskMode) == MaskMode::MASK_NODE_INVERTED;
}
inline bool getUseLocal() const { return _entityAttrLayout.useLocal; }
inline void setUseLocal(bool useLocal) {
_entityAttrLayout.useLocal = useLocal;
}
inline Node* getNode() const { return _node; }
void setNode(Node* node);
inline Node* getRenderTransform() const { return _renderTransform; }
void setRenderTransform(Node* renderTransform);
inline uint32_t getStencilStage() const { return static_cast<uint32_t>(_stencilStage); }
inline void setStencilStage(uint32_t stage) {
_stencilStage = static_cast<StencilStage>(stage);
}
inline StencilStage getEnumStencilStage() const { return _stencilStage; }
inline void setEnumStencilStage(StencilStage stage) {
_stencilStage = stage;
}
inline RenderEntityType getRenderEntityType() const { return _renderEntityType; };
inline uint32_t getStaticDrawInfoSize() const { return _staticDrawInfoSize; };
void setStaticDrawInfoSize(uint32_t size);
RenderDrawInfo* getStaticRenderDrawInfo(uint32_t index);
std::array<RenderDrawInfo, RenderEntity::STATIC_DRAW_INFO_CAPACITY>& getStaticRenderDrawInfos();
RenderDrawInfo* getDynamicRenderDrawInfo(uint32_t index);
ccstd::vector<RenderDrawInfo*>& getDynamicRenderDrawInfos();
inline se::Object* getEntitySharedBufferForJS() const { return _entitySharedBufferActor.getSharedArrayBufferObject(); }
inline bool getColorDirty() const { return _entityAttrLayout.colorDirtyBit != 0; }
inline void setColorDirty(bool dirty) { _entityAttrLayout.colorDirtyBit = dirty ? 1 : 0; }
inline bool getVBColorDirty() const { return _vbColorDirty; }
inline void setVBColorDirty(bool vbColorDirty) { _vbColorDirty = vbColorDirty; }
inline Color getColor() const { return Color(_entityAttrLayout.colorR, _entityAttrLayout.colorG, _entityAttrLayout.colorB, _entityAttrLayout.colorA); }
inline float getColorAlpha() const { return static_cast<float>(_entityAttrLayout.colorA) / 255.F; }
inline float getLocalOpacity() const { return _entityAttrLayout.localOpacity; }
inline float getOpacity() const { return _opacity; }
inline void setOpacity(float opacity) { _opacity = opacity; }
inline bool isEnabled() const { return _entityAttrLayout.enabledIndex != 0; }
inline uint32_t getRenderDrawInfosSize() const {
return _renderEntityType == RenderEntityType::STATIC ? _staticDrawInfoSize : static_cast<uint32_t>(_dynamicDrawInfos.size());
}
inline RenderDrawInfo* getRenderDrawInfoAt(uint32_t index) {
return _renderEntityType == RenderEntityType::STATIC ? &(_staticDrawInfos[index]) : _dynamicDrawInfos[index];
}
private:
CC_DISALLOW_COPY_MOVE_ASSIGN(RenderEntity);
// weak reference
Node* _node{nullptr};
// weak reference
Node* _renderTransform{nullptr};
EntityAttrLayout _entityAttrLayout;
float _opacity{1.0F};
bindings::NativeMemorySharedToScriptActor _entitySharedBufferActor;
union {
std::array<RenderDrawInfo, RenderEntity::STATIC_DRAW_INFO_CAPACITY> _staticDrawInfos;
ccstd::vector<RenderDrawInfo*> _dynamicDrawInfos;
};
StencilStage _stencilStage{StencilStage::DISABLED};
RenderEntityType _renderEntityType{RenderEntityType::STATIC};
uint8_t _staticDrawInfoSize{0};
bool _vbColorDirty{true};
};
} // namespace cc

View File

@ -635,7 +635,7 @@ void Batcher2d::createClearModel() {
void Batcher2d::flushRendererCache() {
if(rendererCache.size() > 0){
if(rendererOrder){
std::sort(rendererCache.begin(), rendererCache.end(), [](RenderEntity* a, RenderEntity* b) { return a->getSortingPriority() < b->getSortingPriority(); });
std::stable_sort(rendererCache.begin(), rendererCache.end(), [](RenderEntity* a, RenderEntity* b) { return a->getSortingPriority() < b->getSortingPriority(); });
}
// CC_LOG_INFO("flushRendererCache %d", rendererCache.size());
for(ccstd::vector<RenderEntity*>::iterator it = rendererCache.begin(); it != rendererCache.end(); it++)

View File

@ -1 +1,7 @@
cocos creator 3.6.3
当前版本: cocos creator 3.6.3
涉及源文件:
cocos/2d/renderer/Batcher2d.h
cocos/2d/renderer/Batcher2d.cpp
cocos/2d/renderer/RenderEntity.h
cocos/2d/renderer/RenderEntity.cpp

View File

@ -1,8 +0,0 @@
{
"files.associations": {
"array": "cpp",
"initializer_list": "cpp",
"xutility": "cpp",
"algorithm": "cpp"
}
}

View File

@ -1,116 +0,0 @@
/****************************************************************************
Copyright (c) 2019-2021 Xiamen Yaji Software Co., Ltd.
http://www.cocos.com
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated engine source code (the "Software"), a limited,
worldwide, royalty-free, non-assignable, revocable and non-exclusive license
to use Cocos Creator solely to develop games on your target platforms. You shall
not use Cocos Creator software for developing other software or tools that's
used for developing games. You are not granted to publish, distribute,
sublicense, and/or sell copies of Cocos Creator.
The software or tools in this License Agreement are licensed, not sold.
Xiamen Yaji Software Co., Ltd. reserves all rights not expressly granted to you.
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.
****************************************************************************/
#include "2d/renderer/RenderEntity.h"
#include "2d/renderer/Batcher2d.h"
#include "bindings/utils/BindingUtils.h"
namespace cc {
RenderEntity::RenderEntity(RenderEntityType type) : _renderEntityType(type) {
if (type == RenderEntityType::STATIC) {
ccnew_placement(&_staticDrawInfos) std::array<RenderDrawInfo, RenderEntity::STATIC_DRAW_INFO_CAPACITY>();
} else {
ccnew_placement(&_dynamicDrawInfos) ccstd::vector<RenderDrawInfo*>();
}
_entitySharedBufferActor.initialize(&_entityAttrLayout, sizeof(EntityAttrLayout));
}
RenderEntity::~RenderEntity() {
if (_renderEntityType == RenderEntityType::STATIC) {
_staticDrawInfos.~array();
} else {
_dynamicDrawInfos.~vector();
}
};
void RenderEntity::addDynamicRenderDrawInfo(RenderDrawInfo* drawInfo) {
CC_ASSERT(_renderEntityType != RenderEntityType::STATIC);
_dynamicDrawInfos.push_back(drawInfo);
}
void RenderEntity::setDynamicRenderDrawInfo(RenderDrawInfo* drawInfo, uint32_t index) {
CC_ASSERT(_renderEntityType != RenderEntityType::STATIC);
if (index < _dynamicDrawInfos.size()) {
_dynamicDrawInfos[index] = drawInfo;
}
}
void RenderEntity::removeDynamicRenderDrawInfo() {
CC_ASSERT(_renderEntityType != RenderEntityType::STATIC);
if (_dynamicDrawInfos.empty()) return;
_dynamicDrawInfos.pop_back(); // warning: memory leaking & crash
}
void RenderEntity::clearDynamicRenderDrawInfos() {
CC_ASSERT(_renderEntityType != RenderEntityType::STATIC);
_dynamicDrawInfos.clear();
}
void RenderEntity::clearStaticRenderDrawInfos() {
CC_ASSERT(_renderEntityType == RenderEntityType::STATIC);
for (uint32_t i = 0; i < _staticDrawInfoSize; i++) {
RenderDrawInfo& drawInfo = _staticDrawInfos[i];
drawInfo.resetDrawInfo();
}
_staticDrawInfoSize = 0;
}
void RenderEntity::setNode(Node* node) {
if (_node) {
_node->setUserData(nullptr);
}
_node = node;
if (_node) {
_node->setUserData(this);
}
}
void RenderEntity::setRenderTransform(Node* renderTransform) {
_renderTransform = renderTransform;
}
RenderDrawInfo* RenderEntity::getDynamicRenderDrawInfo(uint32_t index) {
CC_ASSERT(_renderEntityType != RenderEntityType::STATIC);
if (index >= _dynamicDrawInfos.size()) {
return nullptr;
}
return _dynamicDrawInfos[index];
}
ccstd::vector<RenderDrawInfo*>& RenderEntity::getDynamicRenderDrawInfos() {
CC_ASSERT(_renderEntityType != RenderEntityType::STATIC);
return _dynamicDrawInfos;
}
void RenderEntity::setStaticDrawInfoSize(uint32_t size) {
CC_ASSERT(_renderEntityType == RenderEntityType::STATIC && size <= RenderEntity::STATIC_DRAW_INFO_CAPACITY);
_staticDrawInfoSize = size;
}
RenderDrawInfo* RenderEntity::getStaticRenderDrawInfo(uint32_t index) {
CC_ASSERT(_renderEntityType == RenderEntityType::STATIC && index < _staticDrawInfoSize);
return &(_staticDrawInfos[index]);
}
std::array<RenderDrawInfo, RenderEntity::STATIC_DRAW_INFO_CAPACITY>& RenderEntity::getStaticRenderDrawInfos() {
CC_ASSERT(_renderEntityType == RenderEntityType::STATIC);
return _staticDrawInfos;
}
} // namespace cc

View File

@ -6,21 +6,44 @@
# 效果对比
在ScrollView下生成200个项目测试对比。
测试平台web-mobile
测试设备HUAWEI P30 Pro
项目预制体结构:![QQ截图20230205190757|225x258](./docs/images/QQ截图20230205190757.png)
* 未使用UI渲染优化![Screenshot_20230205_172414|230x500](./docs/images/Screenshot_20230205_172414.jpg)
* 使用UI渲染优化![Screenshot_20230205_172320|230x500](./docs/images/Screenshot_20230205_172320.jpg)
* ## 测试平台web-mobile
`未使用UI渲染优化`![Screenshot_20230205_172414|230x500](./docs/images/Screenshot_20230205_172414.jpg)
`使用UI渲染优化`![Screenshot_20230205_172320|230x500](./docs/images/Screenshot_20230205_172320.jpg)
* ## 测试平台android
`未使用UI渲染优化`![Screenshot_20230205_172414|230x500](./docs/images/Screenshot_20230207_103552.jpg)
`使用UI渲染优化`![Screenshot_20230205_172320|230x500](./docs/images/Screenshot_20230207_103431.jpg)
项目越多,差距越明显。
# 使用方式 (当前不支持原生平台)
看到标题的时候相信使用过Unity的同学就差不多知道使用方式了。API设计其实就是照搬的Unity的SortingGroup。使用步骤如下
1. 导入扩展包到项目assets目录内扩展包其实就是包含了几个ts文件的文件夹(下面会上传示例工程,直接可以在工程里面获得)
2. 定义排序层枚举,扩展包目录如下 ![QQ截图20230205173234|277x153](./docs/images/QQ截图20230205173234.png) 打开sorting-define.ts文件添加或修改SortingLayer枚举
# 使用方式
看到标题的时候相信使用过Unity的同学就差不多知道使用方式了。API设计其实就是照搬的Unity的SortingGroup。使用步骤如下 (下面用到的扩展包,可以在后面的示例工程中获得)
1. 导入扩展包`lcc-ui-sorting-group`到项目assets目录内
2. 如果是原生项目,需要进行以下步骤;
* 构建原生项目,在根目录生成`native`目录
* 导入Native扩展包`lcc-ui-sorting-group-native`到`native/engine`目录下
* 检查Native扩展包的`readme.txt`文件以确保匹配creator版本
* 复制`lcc-ui-sorting-group-native/backup/CMakeLists.txt`文件到引擎Native目录替换。主要是引擎的`CMakeLists.txt`文件没有提供自定义接口。扩展包的`CMakeLists.txt`只是添加了部分自定义接口,在删除此插件的时候可以选择保留,不会有其他影响。
* 修改`native/engine/common/CMakeLists.txt`文件,在代码`include(${COCOS_X_PATH}/CMakeLists.txt)`上面添加插件配置,具体如下;
```
...
# 插件配置 引入lcc-ui-sorting-group native部分
include(${CMAKE_CURRENT_LIST_DIR}/../lcc-ui-sorting-group-native/CMakeLists.txt)
include(${COCOS_X_PATH}/CMakeLists.txt) #在这一行上面插入插件配置
...
```
3. 定义排序层枚举,扩展包目录如下 ![QQ截图20230205173234|277x153](./docs/images/QQ截图20230205173234.png) 打开sorting-define.ts文件添加或修改SortingLayer枚举
```
/**
* 排序层级
@ -45,10 +68,10 @@ export enum SortingLayer {
*/
export const ORDER_IN_LAYER_MAX = 100000;
```
3. 在需要排序的UI渲染器上(Sprite或者Label等)添加SortingGroup组件并设置排序层和排序值 ![QQ截图20230205173334|524x176](./docs/images/QQ截图20230205173334.png)
4. 在需要排序的UI渲染器上(Sprite或者Label等)添加SortingGroup组件并设置排序层和排序值 ![QQ截图20230205173334|524x176](./docs/images/QQ截图20230205173334.png)
和Unity不同的是`Order In Layer`不必是整数,这里可以使用小数。
不同`Sorting Layer`的情况下,`Sorting Layer`枚举越小越先渲染;相同`Sorting Layer`的情况下,`Order In Layer`的值越小越先渲染。
# 注意
1. 该扩展包对引擎进行过小改,如果想移除这个功能,在删除扩展包目录后需要重启编辑器。
2. 该扩展包应该很长一段时间不会支持原生平台。 看源码的时候感觉3.6的UI渲染系统是临时的可能官方什么时候是要重构而且原生平台修改麻烦。
2. 由于没有MacOS设备Native扩展CMakeLists.txt目前只支持Windows平台