diff --git a/source/EngineFrame/Component/Canvas.cpp b/source/EngineFrame/Component/Canvas.cpp index b23494e..ee349cd 100644 --- a/source/EngineFrame/Component/Canvas.cpp +++ b/source/EngineFrame/Component/Canvas.cpp @@ -3,10 +3,11 @@ #include "EngineFrame/Render/RenderManager.h" Canvas::Canvas(VecSize size) { + m_size = size; + m_renderRect = {0, 0, size.width, size.height}; + m_rect = {0, 0, (float)size.width, (float)size.height}; m_texture = new Texture(); - m_texture->Init(size); - m_sprite = new Sprite(); - m_sprite->SetTexture(m_texture); + m_texture->Init(VecSize(Game::GetInstance().Screen_W, Game::GetInstance().Screen_H)); Actor::Init(); @@ -25,38 +26,90 @@ Canvas::Canvas(VecSize size) void Canvas::PreRender() { - if (m_dirty) - { - glBindFramebuffer(GL_FRAMEBUFFER, m_fbo); // 绑定FBO - // glViewport(0, 0, m_texture->getSize().width, m_texture->getSize().height); - glClearColor(0.0f, 0.0f, 0.0f, 0.0f); // 全透明黑色 - glClear(GL_COLOR_BUFFER_BIT); - Actor::PreRender(); - } - else - { - m_sprite->PreRender(); - } + m_rect.x = GetWorldPos().x; + m_rect.y = GetWorldPos().y; } void Canvas::Render() { + RenderManager *renderer = Game::GetInstance().GetRenderer(); + SDL_FPoint AnchorPos = {0, 0}; if (m_dirty) { - - Actor::Render(); + glBindFramebuffer(GL_FRAMEBUFFER, m_fbo); // 绑定FBO + glClearColor(0.0f, 0.0f, 0.0f, 0.0f); + glClear(GL_COLOR_BUFFER_BIT); + for (auto &info : m_drawQueue) + { + renderer->DrawTexture(m_imgMap[info.texture], nullptr, &info.rect, 0.f, &AnchorPos, SDL_FLIP_NONE); + } glBindFramebuffer(GL_FRAMEBUFFER, 0); // 解绑FBO - // glViewport(0, 0, Game::GetInstance().Screen_W, Game::GetInstance().Screen_H); m_dirty = false; } - RenderManager *renderer = Game::GetInstance().GetRenderer(); + renderer->SetCurrentShaderProgram("flip_y"); - m_sprite->Render(); + // 混合 + if (this->_BlendMode != NONE) + Blend(); + renderer->DrawTexture(m_texture, &m_renderRect, &m_rect, 0.f, &AnchorPos, SDL_FLIP_NONE); + // 还原混合 + if (this->_BlendMode != NONE) + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); renderer->SetCurrentShaderProgram("normal"); } -void Canvas::AddChild(RefPtr child) +void Canvas::DrawImg(std::string img, int index, Vec2 pos) { m_dirty = true; - Actor::AddChild(child); + ImgKey key = {img, index}; + DrawInfo info; + info.rect.x = pos.x; + info.rect.y = pos.y; + info.texture = key; + + if (m_imgMap.find(key) == m_imgMap.end()) + { + RefPtr tex = new Texture(); + tex->Init(img, index); + m_imgMap[key] = tex; + } + + info.rect.w = m_imgMap[key]->getSize().width; + info.rect.h = m_imgMap[key]->getSize().height; + + m_drawQueue.push_back(info); +} + +void Canvas::DrawImg(std::string img, int index, SDL_FRect rect) +{ + m_dirty = true; + ImgKey key = {img, index}; + DrawInfo info; + info.rect = rect; + info.texture = key; + + if (m_imgMap.find(key) == m_imgMap.end()) + { + RefPtr tex = new Texture(); + tex->Init(img, index); + m_imgMap[key] = tex; + } + + m_drawQueue.push_back(info); +} + +void Canvas::Clear() +{ + m_drawQueue.clear(); + m_dirty = true; +} + +void Canvas::Blend() +{ + switch (this->_BlendMode) + { + case LINEARDODGE: + glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE, GL_ZERO, GL_ONE); + break; + } } diff --git a/source/EngineFrame/Component/Canvas.h b/source/EngineFrame/Component/Canvas.h index bb4d49a..092c2d5 100644 --- a/source/EngineFrame/Component/Canvas.h +++ b/source/EngineFrame/Component/Canvas.h @@ -4,20 +4,51 @@ #include "EngineFrame/Component/Sprite.h" class Canvas : public Actor { + struct ImgKey + { + std::string img; + int index; + + bool operator<(const ImgKey &other) const + { + if (img != other.img) + { + return img < other.img; // 字符串按字典序比较 + } + return index < other.index; // 字符串相同则比较index + } + }; + struct DrawInfo + { + ImgKey texture; + SDL_FRect rect = {0, 0, 0, 0}; + }; + private: /**纹理 */ RefPtr m_texture = nullptr; - /**精灵 */ - RefPtr m_sprite = nullptr; + /**大小 */ + VecSize m_size; + /**渲染大小 */ + SDL_Rect m_renderRect; + SDL_FRect m_rect; /**脏标记 */ bool m_dirty = true; /**FBO */ GLuint m_fbo = 0; + /**绘制纹理集 */ + std::map> m_imgMap; + /**绘制队列 */ + std::vector m_drawQueue; public: Canvas(VecSize size); void PreRender() override; void Render() override; - void AddChild(RefPtr child) override; + void Blend(); + + void DrawImg(std::string img, int index, Vec2 pos); + void DrawImg(std::string img, int index, SDL_FRect rect); + void Clear(); };