feat(渲染): 升级OpenGL版本至4.5并重构渲染模块
- 将OpenGL ES 3.0升级至OpenGL 4.5核心模式 - 重构RenderModule支持lambda配置和优先级设置 - 添加resetStats方法到RenderContext - 优化ShaderManager的shader路径处理 - 更新文本渲染示例使用新的API - 移除冗余注释并简化SDF字体着色器
This commit is contained in:
parent
f8c7298974
commit
d681f63905
|
|
@ -4,6 +4,7 @@
|
||||||
#include <extra2d/core/types.h>
|
#include <extra2d/core/types.h>
|
||||||
#include <extra2d/render/core/render_backend.h>
|
#include <extra2d/render/core/render_backend.h>
|
||||||
#include <extra2d/render/rhi/rhi_types.h>
|
#include <extra2d/render/rhi/rhi_types.h>
|
||||||
|
#include <functional>
|
||||||
|
|
||||||
namespace extra2d {
|
namespace extra2d {
|
||||||
|
|
||||||
|
|
@ -20,6 +21,7 @@ struct RenderModuleConfig {
|
||||||
bool enableDebug = false;
|
bool enableDebug = false;
|
||||||
float designWidth = 1280.0f;
|
float designWidth = 1280.0f;
|
||||||
float designHeight = 720.0f;
|
float designHeight = 720.0f;
|
||||||
|
int priority = 10;
|
||||||
|
|
||||||
RenderModuleConfig() = default;
|
RenderModuleConfig() = default;
|
||||||
|
|
||||||
|
|
@ -61,8 +63,14 @@ struct RenderModuleConfig {
|
||||||
*/
|
*/
|
||||||
class RenderModule : public Module {
|
class RenderModule : public Module {
|
||||||
public:
|
public:
|
||||||
|
/**
|
||||||
|
* @brief 构造函数(Lambda 配置)
|
||||||
|
* @param configFn 配置函数
|
||||||
|
*/
|
||||||
|
explicit RenderModule(std::function<void(RenderModuleConfig &)> configFn);
|
||||||
|
|
||||||
RenderModule();
|
RenderModule();
|
||||||
explicit RenderModule(const RenderModuleConfig& config);
|
explicit RenderModule(const RenderModuleConfig &config);
|
||||||
~RenderModule() override;
|
~RenderModule() override;
|
||||||
|
|
||||||
// ========================================================================
|
// ========================================================================
|
||||||
|
|
@ -87,18 +95,23 @@ public:
|
||||||
/**
|
/**
|
||||||
* @brief 获取模块名称
|
* @brief 获取模块名称
|
||||||
*/
|
*/
|
||||||
const char* name() const override { return "RenderModule"; }
|
const char *name() const override { return "RenderModule"; }
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief 获取模块优先级
|
* @brief 获取模块优先级
|
||||||
*/
|
*/
|
||||||
int priority() const override { return 10; }
|
int priority() const override { return config_.priority; }
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief 获取模块依赖
|
* @brief 获取模块依赖
|
||||||
*/
|
*/
|
||||||
std::vector<std::type_index> deps() const override;
|
std::vector<std::type_index> deps() const override;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief 禁用并行初始化(OpenGL 上下文需要在主线程)
|
||||||
|
*/
|
||||||
|
bool allowParallelInit() const override { return false; }
|
||||||
|
|
||||||
// ========================================================================
|
// ========================================================================
|
||||||
// 渲染器访问
|
// 渲染器访问
|
||||||
// ========================================================================
|
// ========================================================================
|
||||||
|
|
@ -106,7 +119,7 @@ public:
|
||||||
/**
|
/**
|
||||||
* @brief 获取渲染器
|
* @brief 获取渲染器
|
||||||
*/
|
*/
|
||||||
class Renderer* getRenderer() const { return renderer_.get(); }
|
class Renderer *getRenderer() const { return renderer_.get(); }
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief 获取渲染器(智能指针)
|
* @brief 获取渲染器(智能指针)
|
||||||
|
|
@ -120,12 +133,12 @@ public:
|
||||||
/**
|
/**
|
||||||
* @brief 获取配置
|
* @brief 获取配置
|
||||||
*/
|
*/
|
||||||
const RenderModuleConfig& getConfig() const { return config_; }
|
const RenderModuleConfig &getConfig() const { return config_; }
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief 设置配置
|
* @brief 设置配置
|
||||||
*/
|
*/
|
||||||
void setConfig(const RenderModuleConfig& config);
|
void setConfig(const RenderModuleConfig &config);
|
||||||
|
|
||||||
// ========================================================================
|
// ========================================================================
|
||||||
// 静态工厂
|
// 静态工厂
|
||||||
|
|
@ -134,7 +147,7 @@ public:
|
||||||
/**
|
/**
|
||||||
* @brief 创建渲染模块
|
* @brief 创建渲染模块
|
||||||
*/
|
*/
|
||||||
static Ptr<RenderModule> create(const RenderModuleConfig& config = {});
|
static Ptr<RenderModule> create(const RenderModuleConfig &config = {});
|
||||||
|
|
||||||
private:
|
private:
|
||||||
RenderModuleConfig config_;
|
RenderModuleConfig config_;
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,4 @@
|
||||||
#version 300 es
|
#version 450 core
|
||||||
precision highp float;
|
|
||||||
|
|
||||||
in vec2 v_texCoord;
|
in vec2 v_texCoord;
|
||||||
in vec4 v_color;
|
in vec4 v_color;
|
||||||
|
|
@ -13,26 +12,19 @@ uniform vec2 u_textureSize;
|
||||||
out vec4 fragColor;
|
out vec4 fragColor;
|
||||||
|
|
||||||
void main() {
|
void main() {
|
||||||
// 采样 SDF 纹理(SDF 值存储在 alpha 通道,范围 0-255 已映射到 0-1)
|
|
||||||
float sdfValue = texture(u_texture, v_texCoord).a;
|
float sdfValue = texture(u_texture, v_texCoord).a;
|
||||||
|
|
||||||
// 使用 fwidth 计算屏幕空间的变化率
|
|
||||||
float fw = fwidth(sdfValue);
|
float fw = fwidth(sdfValue);
|
||||||
|
|
||||||
// 平衡的抗锯齿:根据屏幕空间变化率调整平滑范围
|
|
||||||
// 在放大时更平滑,缩小时更锐利
|
|
||||||
float smoothRange = max(u_sdfSmoothness, fw * 0.5);
|
float smoothRange = max(u_sdfSmoothness, fw * 0.5);
|
||||||
|
|
||||||
// 使用 smoothstep 进行抗锯齿
|
|
||||||
float alpha = smoothstep(u_sdfThreshold - smoothRange,
|
float alpha = smoothstep(u_sdfThreshold - smoothRange,
|
||||||
u_sdfThreshold + smoothRange,
|
u_sdfThreshold + smoothRange,
|
||||||
sdfValue);
|
sdfValue);
|
||||||
|
|
||||||
// 应用颜色和透明度
|
|
||||||
fragColor = v_color;
|
fragColor = v_color;
|
||||||
fragColor.a *= alpha * u_opacity;
|
fragColor.a *= alpha * u_opacity;
|
||||||
|
|
||||||
// 丢弃完全透明的像素
|
|
||||||
if (fragColor.a < 0.001) {
|
if (fragColor.a < 0.001) {
|
||||||
discard;
|
discard;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,4 @@
|
||||||
#version 300 es
|
#version 450 core
|
||||||
precision highp float;
|
|
||||||
|
|
||||||
in vec4 v_color;
|
in vec4 v_color;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,4 @@
|
||||||
#version 300 es
|
#version 450 core
|
||||||
precision highp float;
|
|
||||||
|
|
||||||
layout(location = 0) in vec2 a_position;
|
layout(location = 0) in vec2 a_position;
|
||||||
layout(location = 1) in vec4 a_color;
|
layout(location = 1) in vec4 a_color;
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,4 @@
|
||||||
#version 300 es
|
#version 450 core
|
||||||
precision highp float;
|
|
||||||
|
|
||||||
in vec2 v_texCoord;
|
in vec2 v_texCoord;
|
||||||
in vec4 v_color;
|
in vec4 v_color;
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,4 @@
|
||||||
#version 300 es
|
#version 450 core
|
||||||
precision highp float;
|
|
||||||
|
|
||||||
layout(location = 0) in vec2 a_position;
|
layout(location = 0) in vec2 a_position;
|
||||||
layout(location = 1) in vec2 a_texCoord;
|
layout(location = 1) in vec2 a_texCoord;
|
||||||
|
|
|
||||||
|
|
@ -30,9 +30,9 @@ bool SDL2Window::create(const std::string &title, int width, int height,
|
||||||
flags |= SDL_WINDOW_FULLSCREEN_DESKTOP;
|
flags |= SDL_WINDOW_FULLSCREEN_DESKTOP;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 3);
|
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 4);
|
||||||
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 2);
|
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 5);
|
||||||
SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_ES);
|
SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_CORE);
|
||||||
|
|
||||||
SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1);
|
SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1);
|
||||||
SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE, 24);
|
SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE, 24);
|
||||||
|
|
@ -56,8 +56,8 @@ bool SDL2Window::create(const std::string &title, int width, int height,
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!gladLoadGLES2Loader((GLADloadproc)SDL_GL_GetProcAddress)) {
|
if (!gladLoadGLLoader((GLADloadproc)SDL_GL_GetProcAddress)) {
|
||||||
E2D_LOG_ERROR("初始化 GLAD GLES2 失败");
|
E2D_LOG_ERROR("初始化 GLAD 失败");
|
||||||
SDL_GL_DeleteContext(glContext_);
|
SDL_GL_DeleteContext(glContext_);
|
||||||
glContext_ = nullptr;
|
glContext_ = nullptr;
|
||||||
SDL_DestroyWindow(sdlWindow_);
|
SDL_DestroyWindow(sdlWindow_);
|
||||||
|
|
|
||||||
|
|
@ -282,4 +282,11 @@ void RenderContext::initDefaultState() {
|
||||||
scissorEnabled_ = false;
|
scissorEnabled_ = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void RenderContext::resetStats() {
|
||||||
|
stats_.reset();
|
||||||
|
if (device_) {
|
||||||
|
device_->resetStats();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace extra2d
|
} // namespace extra2d
|
||||||
|
|
|
||||||
|
|
@ -8,6 +8,13 @@
|
||||||
|
|
||||||
namespace extra2d {
|
namespace extra2d {
|
||||||
|
|
||||||
|
RenderModule::RenderModule(std::function<void(RenderModuleConfig&)> configFn)
|
||||||
|
: initialized_(false) {
|
||||||
|
if (configFn) {
|
||||||
|
configFn(config_);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
RenderModule::RenderModule() : initialized_(false) {}
|
RenderModule::RenderModule() : initialized_(false) {}
|
||||||
|
|
||||||
RenderModule::RenderModule(const RenderModuleConfig &config)
|
RenderModule::RenderModule(const RenderModuleConfig &config)
|
||||||
|
|
@ -24,7 +31,15 @@ bool RenderModule::init() {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
IWindow *window = nullptr;
|
auto *winModule = app_->get<WindowModule>();
|
||||||
|
if (!winModule) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
IWindow *window = winModule->win();
|
||||||
|
if (!window) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
renderer_ = Renderer::create();
|
renderer_ = Renderer::create();
|
||||||
|
|
||||||
|
|
@ -40,7 +55,10 @@ bool RenderModule::init() {
|
||||||
rendererConfig.viewportConfig =
|
rendererConfig.viewportConfig =
|
||||||
ViewportConfig(config_.designWidth, config_.designHeight);
|
ViewportConfig(config_.designWidth, config_.designHeight);
|
||||||
|
|
||||||
renderer_->setConfig(rendererConfig);
|
if (!renderer_->init(window, rendererConfig)) {
|
||||||
|
renderer_.reset();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
initialized_ = true;
|
initialized_ = true;
|
||||||
return true;
|
return true;
|
||||||
|
|
|
||||||
|
|
@ -3,6 +3,7 @@
|
||||||
#include <extra2d/platform/iwindow.h>
|
#include <extra2d/platform/iwindow.h>
|
||||||
#include <extra2d/render/core/backend_factory.h>
|
#include <extra2d/render/core/backend_factory.h>
|
||||||
#include <extra2d/render/core/render_backend.h>
|
#include <extra2d/render/core/render_backend.h>
|
||||||
|
#include <extra2d/resources/shader_manager.h>
|
||||||
#include <extra2d/scene/scene.h>
|
#include <extra2d/scene/scene.h>
|
||||||
|
|
||||||
namespace extra2d {
|
namespace extra2d {
|
||||||
|
|
@ -57,6 +58,13 @@ bool Renderer::init(IWindow *window, const RendererConfig &config) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
auto& shaderManager = ShaderManager::getInstance();
|
||||||
|
if (!shaderManager.isInitialized()) {
|
||||||
|
if (!shaderManager.init(context_->getDevice(), "shaders")) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (!createBatchers()) {
|
if (!createBatchers()) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -156,9 +156,8 @@ ResourceHandle<ShaderData> ShaderManager::loadFromMetadata(const std::string& js
|
||||||
metadata.name = name;
|
metadata.name = name;
|
||||||
metadataCache_[name] = metadata;
|
metadataCache_[name] = metadata;
|
||||||
|
|
||||||
fs::path jsonDir = fs::path(jsonPath).parent_path();
|
fs::path fullVertPath = fs::path(shaderDir_) / vertPath;
|
||||||
fs::path fullVertPath = jsonDir / vertPath;
|
fs::path fullFragPath = fs::path(shaderDir_) / fragPath;
|
||||||
fs::path fullFragPath = jsonDir / fragPath;
|
|
||||||
|
|
||||||
auto handle = loadFromFiles(name, fullVertPath.string(), fullFragPath.string());
|
auto handle = loadFromFiles(name, fullVertPath.string(), fullFragPath.string());
|
||||||
if (handle) {
|
if (handle) {
|
||||||
|
|
|
||||||
|
|
@ -2,8 +2,7 @@
|
||||||
* @file main.cpp
|
* @file main.cpp
|
||||||
* @brief Extra2D 文字渲染示例
|
* @brief Extra2D 文字渲染示例
|
||||||
*
|
*
|
||||||
* 演示如何使用 RenderBackend 抽象接口渲染文字
|
* 演示如何使用 RenderModule 渲染文字
|
||||||
* 此示例不依赖任何特定渲染后端(如 OpenGL)
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <extra2d/extra2d.h>
|
#include <extra2d/extra2d.h>
|
||||||
|
|
@ -14,99 +13,118 @@ using namespace extra2d;
|
||||||
class TextRenderingScene : public Scene {
|
class TextRenderingScene : public Scene {
|
||||||
public:
|
public:
|
||||||
void onEnter() override {
|
void onEnter() override {
|
||||||
// 加载字体
|
auto &fontManager = FontManager::getInstance();
|
||||||
// 注意:请确保有字体文件在 assets/fonts/ 目录下
|
auto *renderMod = Application::get().get<RenderModule>();
|
||||||
// 如果没有,可以使用系统字体路径
|
if (!renderMod) {
|
||||||
if (!renderer_) {
|
std::cerr << "RenderModule not available!" << std::endl;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto *renderer = renderMod->getRenderer();
|
||||||
|
if (!renderer) {
|
||||||
std::cerr << "Renderer not available!" << std::endl;
|
std::cerr << "Renderer not available!" << std::endl;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
auto *context = renderer->getContext();
|
||||||
font_ = renderer_->createFontAtlas("assets/fonts/fonts.ttf", 26, true);
|
if (!context) {
|
||||||
} catch (...) {
|
std::cerr << "RenderContext not available!" << std::endl;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!fontManager.isInitialized()) {
|
||||||
|
fontManager.init(context->getDevice());
|
||||||
|
}
|
||||||
|
|
||||||
|
fontHandle_ = fontManager.load("assets/fonts/fonts.ttf",
|
||||||
|
{.fontSize = 26, .useSDF = true});
|
||||||
|
if (fontHandle_) {
|
||||||
|
fontAtlas_ = fontManager.getAtlas(fontHandle_, 26);
|
||||||
|
if (fontAtlas_) {
|
||||||
|
std::cout << "Font loaded successfully!" << std::endl;
|
||||||
|
std::cout << " Font size: " << fontAtlas_->getFontSize() << std::endl;
|
||||||
|
std::cout << " Line height: " << fontAtlas_->getLineHeight()
|
||||||
|
<< std::endl;
|
||||||
|
std::cout << " Ascent: " << fontAtlas_->getAscent() << std::endl;
|
||||||
|
std::cout << " Descent: " << fontAtlas_->getDescent() << std::endl;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
std::cerr << "Failed to load font from assets/fonts/fonts.ttf"
|
std::cerr << "Failed to load font from assets/fonts/fonts.ttf"
|
||||||
<< std::endl;
|
<< std::endl;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (font_) {
|
|
||||||
std::cout << "Font loaded successfully!" << std::endl;
|
|
||||||
std::cout << " Font size: " << font_->getFontSize() << std::endl;
|
|
||||||
std::cout << " Line height: " << font_->getLineHeight() << std::endl;
|
|
||||||
std::cout << " Ascent: " << font_->getAscent() << std::endl;
|
|
||||||
std::cout << " Descent: " << font_->getDescent() << std::endl;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void onExit() override { font_.reset(); }
|
void onExit() override {
|
||||||
|
fontAtlas_.reset();
|
||||||
|
fontHandle_.reset();
|
||||||
|
}
|
||||||
|
|
||||||
void onRender(RenderBackend &renderer) override {
|
void onRender(RenderBackend &renderer) override {
|
||||||
Scene::onRender(renderer);
|
Scene::onRender(renderer);
|
||||||
|
|
||||||
if (!font_) {
|
if (!fontAtlas_) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
float y = 100.0f;
|
float y = 100.0f;
|
||||||
float x = 100.0f;
|
float x = 100.0f;
|
||||||
|
float fontSize = 26.0f;
|
||||||
|
|
||||||
renderText(renderer, "Extra2D Text Rendering Demo", x, y,
|
renderText(renderer, "Extra2D Text Rendering Demo", x, y, fontSize,
|
||||||
Color(1.0f, 0.8f, 0.2f, 1.0f));
|
Color(1.0f, 0.8f, 0.2f, 1.0f));
|
||||||
y += font_->getLineHeight() * 2;
|
y += fontAtlas_->getLineHeight() * 2;
|
||||||
|
|
||||||
// 渲染不同颜色的文字
|
renderText(renderer, "Red Text", x, y, fontSize,
|
||||||
renderText(renderer, "Red Text", x, y, Color(1.0f, 0.2f, 0.2f, 1.0f));
|
Color(1.0f, 0.2f, 0.2f, 1.0f));
|
||||||
y += font_->getLineHeight();
|
y += fontAtlas_->getLineHeight();
|
||||||
|
|
||||||
renderText(renderer, "Green Text", x, y, Color(0.2f, 1.0f, 0.2f, 1.0f));
|
renderText(renderer, "Green Text", x, y, fontSize,
|
||||||
y += font_->getLineHeight();
|
Color(0.2f, 1.0f, 0.2f, 1.0f));
|
||||||
|
y += fontAtlas_->getLineHeight();
|
||||||
|
|
||||||
renderText(renderer, "Blue Text", x, y, Color(0.2f, 0.2f, 1.0f, 1.0f));
|
renderText(renderer, "Blue Text", x, y, fontSize,
|
||||||
y += font_->getLineHeight() * 2;
|
Color(0.2f, 0.2f, 1.0f, 1.0f));
|
||||||
|
y += fontAtlas_->getLineHeight() * 2;
|
||||||
|
|
||||||
// 渲染多行文字
|
renderText(renderer, "This is a multi-line text example.", x, y, fontSize,
|
||||||
renderText(renderer, "This is a multi-line text example.", x, y,
|
|
||||||
Color(1.0f, 1.0f, 1.0f, 1.0f));
|
Color(1.0f, 1.0f, 1.0f, 1.0f));
|
||||||
y += font_->getLineHeight();
|
y += fontAtlas_->getLineHeight();
|
||||||
renderText(renderer, "You can render text with different colors", x, y,
|
renderText(renderer, "You can render text with different colors", x, y,
|
||||||
Color(0.8f, 0.8f, 0.8f, 1.0f));
|
fontSize, Color(0.8f, 0.8f, 0.8f, 1.0f));
|
||||||
y += font_->getLineHeight();
|
y += fontAtlas_->getLineHeight();
|
||||||
renderText(renderer, "and styles using FontAtlas.", x, y,
|
renderText(renderer, "and styles using FontAtlas.", x, y, fontSize,
|
||||||
Color(0.6f, 0.6f, 0.6f, 1.0f));
|
Color(0.6f, 0.6f, 0.6f, 1.0f));
|
||||||
y += font_->getLineHeight() * 2;
|
y += fontAtlas_->getLineHeight() * 2;
|
||||||
|
|
||||||
// 渲染半透明文字
|
renderText(renderer, "Semi-transparent text (50% opacity)", x, y, fontSize,
|
||||||
renderText(renderer, "Semi-transparent text (50% opacity)", x, y,
|
|
||||||
Color(1.0f, 1.0f, 1.0f, 0.5f));
|
Color(1.0f, 1.0f, 1.0f, 0.5f));
|
||||||
y += font_->getLineHeight() * 2;
|
y += fontAtlas_->getLineHeight() * 2;
|
||||||
|
|
||||||
// 渲染操作提示
|
renderText(renderer, "Press ESC to exit", x, y, fontSize,
|
||||||
renderText(renderer, "Press ESC to exit", x, y,
|
|
||||||
Color(0.5f, 0.5f, 0.5f, 1.0f));
|
Color(0.5f, 0.5f, 0.5f, 1.0f));
|
||||||
}
|
}
|
||||||
|
|
||||||
void setRenderer(RenderBackend *renderer) { renderer_ = renderer; }
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
/**
|
||||||
|
* @brief 渲染文本
|
||||||
|
*/
|
||||||
void renderText(RenderBackend &renderer, const std::string &text, float x,
|
void renderText(RenderBackend &renderer, const std::string &text, float x,
|
||||||
float y, const Color &color) {
|
float y, float fontSize, const Color &color) {
|
||||||
if (!font_) {
|
if (!fontAtlas_) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// 使用 RenderBackend 的 drawText 方法
|
renderer.drawText(text, Vec2(x, y), fontSize, color);
|
||||||
renderer.drawText(*font_, text, Vec2(x, y), color);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Ptr<FontAtlas> font_;
|
FontHandle fontHandle_;
|
||||||
RenderBackend *renderer_ = nullptr;
|
Ptr<FontAtlas> fontAtlas_;
|
||||||
};
|
};
|
||||||
|
|
||||||
int main(int argc, char *argv[]) {
|
int main(int argc, char *argv[]) {
|
||||||
|
|
||||||
Application &app = Application::get();
|
Application &app = Application::get();
|
||||||
|
|
||||||
// 注册模块
|
|
||||||
app.use<WindowModule>([](auto &cfg) {
|
app.use<WindowModule>([](auto &cfg) {
|
||||||
cfg.w = 1280;
|
cfg.w = 1280;
|
||||||
cfg.h = 720;
|
cfg.h = 720;
|
||||||
|
|
@ -115,7 +133,7 @@ int main(int argc, char *argv[]) {
|
||||||
cfg.backend = "sdl2";
|
cfg.backend = "sdl2";
|
||||||
});
|
});
|
||||||
|
|
||||||
app.use<RenderModule>([](auto &cfg) { cfg.priority = 10; });
|
app.use<RenderModule>([](auto &cfg) { cfg.api = rhi::GraphicsAPI::OpenGL; });
|
||||||
|
|
||||||
app.use<InputModule>([](auto &cfg) { cfg.priority = 20; });
|
app.use<InputModule>([](auto &cfg) { cfg.priority = 20; });
|
||||||
|
|
||||||
|
|
@ -129,7 +147,6 @@ int main(int argc, char *argv[]) {
|
||||||
E2D_LOG_INFO("Window :{} x {}", win->width(), win->height());
|
E2D_LOG_INFO("Window :{} x {}", win->width(), win->height());
|
||||||
}
|
}
|
||||||
|
|
||||||
// 设置事件监听
|
|
||||||
auto eventService = ServiceLocator::instance().getService<IEventService>();
|
auto eventService = ServiceLocator::instance().getService<IEventService>();
|
||||||
if (eventService) {
|
if (eventService) {
|
||||||
eventService->addListener(EventType::KeyPressed, [](Event &e) {
|
eventService->addListener(EventType::KeyPressed, [](Event &e) {
|
||||||
|
|
@ -141,12 +158,7 @@ int main(int argc, char *argv[]) {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
// 获取渲染器
|
|
||||||
RenderBackend *renderer = app.renderer();
|
|
||||||
|
|
||||||
// 创建并配置场景
|
|
||||||
auto scene = makeShared<TextRenderingScene>();
|
auto scene = makeShared<TextRenderingScene>();
|
||||||
scene->setRenderer(renderer);
|
|
||||||
scene->setBackgroundColor(Color(0.1f, 0.1f, 0.15f, 1.0f));
|
scene->setBackgroundColor(Color(0.1f, 0.1f, 0.15f, 1.0f));
|
||||||
|
|
||||||
if (win) {
|
if (win) {
|
||||||
|
|
@ -154,13 +166,12 @@ int main(int argc, char *argv[]) {
|
||||||
static_cast<float>(win->height()));
|
static_cast<float>(win->height()));
|
||||||
}
|
}
|
||||||
|
|
||||||
// 配置相机
|
|
||||||
auto cameraService = ServiceLocator::instance().getService<ICameraService>();
|
auto cameraService = ServiceLocator::instance().getService<ICameraService>();
|
||||||
if (cameraService && win) {
|
if (cameraService && win) {
|
||||||
cameraService->setViewportConfig([&](auto &cfg) {
|
cameraService->setViewportConfig([&](auto &cfg) {
|
||||||
cfg.logicWidth = static_cast<float>(win->width());
|
cfg.designWidth = static_cast<float>(win->width());
|
||||||
cfg.logicHeight = static_cast<float>(win->height());
|
cfg.designHeight = static_cast<float>(win->height());
|
||||||
cfg.mode = ViewportMode::AspectRatio;
|
cfg.scaleMode = ViewportScaleMode::Letterbox;
|
||||||
});
|
});
|
||||||
cameraService->updateViewport(win->width(), win->height());
|
cameraService->updateViewport(win->width(), win->height());
|
||||||
cameraService->applyViewportAdapter();
|
cameraService->applyViewportAdapter();
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue