feat(渲染): 添加SDF字体渲染支持
实现基于有符号距离场(SDF)的高质量字体渲染功能,包括: 1. 新增SDF专用着色器及配置文件 2. 扩展着色器管理器支持vec2/vec3类型uniform 3. 修改精灵批处理系统以支持自定义着色器 4. 更新渲染器实现SDF字体特殊处理逻辑 5. 替换示例中的字体资源为SDF字体
This commit is contained in:
parent
c32c2dd60d
commit
080fb56003
|
|
@ -134,6 +134,7 @@ private:
|
||||||
IWindow* window_;
|
IWindow* window_;
|
||||||
GLSpriteBatch spriteBatch_;
|
GLSpriteBatch spriteBatch_;
|
||||||
Ptr<IShader> shapeShader_;
|
Ptr<IShader> shapeShader_;
|
||||||
|
Ptr<IShader> sdfFontShader_; // SDF字体专用着色器
|
||||||
|
|
||||||
GLuint shapeVao_; // 形状 VAO(手动管理,用于顶点属性配置)
|
GLuint shapeVao_; // 形状 VAO(手动管理,用于顶点属性配置)
|
||||||
GLBuffer shapeBuffer_; // 形状 VBO(使用 GLBuffer 管理)
|
GLBuffer shapeBuffer_; // 形状 VBO(使用 GLBuffer 管理)
|
||||||
|
|
|
||||||
|
|
@ -4,6 +4,7 @@
|
||||||
#include <extra2d/graphics/backends/opengl/gl_texture.h>
|
#include <extra2d/graphics/backends/opengl/gl_texture.h>
|
||||||
#include <extra2d/graphics/batch/sprite_batch.h>
|
#include <extra2d/graphics/batch/sprite_batch.h>
|
||||||
#include <extra2d/graphics/shader/shader_interface.h>
|
#include <extra2d/graphics/shader/shader_interface.h>
|
||||||
|
#include <extra2d/graphics/shader/shader_manager.h>
|
||||||
|
|
||||||
#include <glad/glad.h>
|
#include <glad/glad.h>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
@ -27,6 +28,9 @@ public:
|
||||||
void begin(const glm::mat4 &viewProjection);
|
void begin(const glm::mat4 &viewProjection);
|
||||||
void end();
|
void end();
|
||||||
|
|
||||||
|
// 使用指定着色器开始批处理
|
||||||
|
void begin(const glm::mat4 &viewProjection, Ptr<IShader> shader);
|
||||||
|
|
||||||
// 绘制单个精灵
|
// 绘制单个精灵
|
||||||
void draw(const Texture &texture, const SpriteData &data);
|
void draw(const Texture &texture, const SpriteData &data);
|
||||||
|
|
||||||
|
|
@ -37,6 +41,16 @@ public:
|
||||||
// 获取绘制调用次数
|
// 获取绘制调用次数
|
||||||
uint32_t getDrawCallCount() const { return drawCallCount_; }
|
uint32_t getDrawCallCount() const { return drawCallCount_; }
|
||||||
|
|
||||||
|
// 设置自定义着色器(用于SDF字体等特殊渲染)
|
||||||
|
void setShader(Ptr<IShader> shader);
|
||||||
|
|
||||||
|
// 获取当前着色器
|
||||||
|
Ptr<IShader> getShader() const { return shader_; }
|
||||||
|
|
||||||
|
// 设置额外的uniform值(用于SDF字体等特殊渲染)
|
||||||
|
void setExtraUniforms(const UniformValueMap &uniforms) { extraUniforms_ = uniforms; }
|
||||||
|
void clearExtraUniforms() { extraUniforms_.clear(); }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
// OpenGL 对象
|
// OpenGL 对象
|
||||||
GLuint vao_;
|
GLuint vao_;
|
||||||
|
|
@ -60,6 +74,9 @@ private:
|
||||||
uint32_t drawCallCount_;
|
uint32_t drawCallCount_;
|
||||||
glm::mat4 viewProjection_;
|
glm::mat4 viewProjection_;
|
||||||
|
|
||||||
|
// 额外的uniform值(用于SDF字体等特殊渲染)
|
||||||
|
UniformValueMap extraUniforms_;
|
||||||
|
|
||||||
// 内部方法
|
// 内部方法
|
||||||
void flush();
|
void flush();
|
||||||
void submitBatch();
|
void submitBatch();
|
||||||
|
|
|
||||||
|
|
@ -27,6 +27,8 @@ struct ShaderUniformDef {
|
||||||
std::string type;
|
std::string type;
|
||||||
std::string description;
|
std::string description;
|
||||||
float defaultValue = 0.0f; // 默认值(用于float类型)
|
float defaultValue = 0.0f; // 默认值(用于float类型)
|
||||||
|
float defaultVec2[2] = {0, 0}; // 默认值(用于vec2类型)
|
||||||
|
float defaultVec3[3] = {0, 0, 0}; // 默认值(用于vec3类型)
|
||||||
float defaultVec4[4] = {0, 0, 0, 0}; // 默认值(用于vec4类型)
|
float defaultVec4[4] = {0, 0, 0, 0}; // 默认值(用于vec4类型)
|
||||||
float defaultMat4[16] = {
|
float defaultMat4[16] = {
|
||||||
1, 0, 0, 0, 0, 1, 0, 0,
|
1, 0, 0, 0, 0, 1, 0, 0,
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,39 @@
|
||||||
|
#version 300 es
|
||||||
|
precision highp float;
|
||||||
|
|
||||||
|
in vec2 v_texCoord;
|
||||||
|
in vec4 v_color;
|
||||||
|
|
||||||
|
uniform sampler2D u_texture;
|
||||||
|
uniform float u_opacity;
|
||||||
|
uniform float u_sdfThreshold;
|
||||||
|
uniform float u_sdfSmoothness;
|
||||||
|
uniform vec2 u_textureSize;
|
||||||
|
|
||||||
|
out vec4 fragColor;
|
||||||
|
|
||||||
|
void main() {
|
||||||
|
// 采样 SDF 纹理(SDF 值存储在 alpha 通道,范围 0-255 已映射到 0-1)
|
||||||
|
float sdfValue = texture(u_texture, v_texCoord).a;
|
||||||
|
|
||||||
|
// 使用 fwidth 计算屏幕空间的变化率
|
||||||
|
float fw = fwidth(sdfValue);
|
||||||
|
|
||||||
|
// 平衡的抗锯齿:根据屏幕空间变化率调整平滑范围
|
||||||
|
// 在放大时更平滑,缩小时更锐利
|
||||||
|
float smoothRange = max(u_sdfSmoothness, fw * 0.5);
|
||||||
|
|
||||||
|
// 使用 smoothstep 进行抗锯齿
|
||||||
|
float alpha = smoothstep(u_sdfThreshold - smoothRange,
|
||||||
|
u_sdfThreshold + smoothRange,
|
||||||
|
sdfValue);
|
||||||
|
|
||||||
|
// 应用颜色和透明度
|
||||||
|
fragColor = v_color;
|
||||||
|
fragColor.a *= alpha * u_opacity;
|
||||||
|
|
||||||
|
// 丢弃完全透明的像素
|
||||||
|
if (fragColor.a < 0.001) {
|
||||||
|
discard;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,60 @@
|
||||||
|
{
|
||||||
|
"name": "sdf_font",
|
||||||
|
"category": "builtin",
|
||||||
|
"version": "1.0",
|
||||||
|
"description": "SDF字体渲染Shader,支持高质量抗锯齿",
|
||||||
|
"uniforms": {
|
||||||
|
"u_viewProjection": {
|
||||||
|
"type": "mat4",
|
||||||
|
"default": [
|
||||||
|
1, 0, 0, 0,
|
||||||
|
0, 1, 0, 0,
|
||||||
|
0, 0, 1, 0,
|
||||||
|
0, 0, 0, 1
|
||||||
|
],
|
||||||
|
"description": "视图投影矩阵"
|
||||||
|
},
|
||||||
|
"u_model": {
|
||||||
|
"type": "mat4",
|
||||||
|
"default": [
|
||||||
|
1, 0, 0, 0,
|
||||||
|
0, 1, 0, 0,
|
||||||
|
0, 0, 1, 0,
|
||||||
|
0, 0, 0, 1
|
||||||
|
],
|
||||||
|
"description": "模型矩阵"
|
||||||
|
},
|
||||||
|
"u_opacity": {
|
||||||
|
"type": "float",
|
||||||
|
"default": 1.0,
|
||||||
|
"description": "透明度"
|
||||||
|
},
|
||||||
|
"u_sdfThreshold": {
|
||||||
|
"type": "float",
|
||||||
|
"default": 0.5,
|
||||||
|
"description": "SDF阈值,默认0.5,范围0-1。值越小字形越粗,越大越细"
|
||||||
|
},
|
||||||
|
"u_sdfSmoothness": {
|
||||||
|
"type": "float",
|
||||||
|
"default": 0.02,
|
||||||
|
"description": "SDF平滑度,控制抗锯齿范围,越小越锐利,默认0.02"
|
||||||
|
},
|
||||||
|
"u_textureSize": {
|
||||||
|
"type": "vec2",
|
||||||
|
"default": [512, 512],
|
||||||
|
"description": "SDF纹理尺寸,用于计算像素级平滑"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"samplers": {
|
||||||
|
"u_texture": {
|
||||||
|
"binding": 0,
|
||||||
|
"description": "SDF纹理采样器"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"backends": {
|
||||||
|
"opengl": {
|
||||||
|
"vertex": "backends/opengl/builtin/sprite.vert",
|
||||||
|
"fragment": "backends/opengl/builtin/sdf_font.frag"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -165,6 +165,7 @@ void GLFontAtlas::createAtlas() {
|
||||||
std::vector<uint8_t> emptyData(ATLAS_WIDTH * ATLAS_HEIGHT * channels, 0);
|
std::vector<uint8_t> emptyData(ATLAS_WIDTH * ATLAS_HEIGHT * channels, 0);
|
||||||
texture_ = std::make_unique<GLTexture>(ATLAS_WIDTH, ATLAS_HEIGHT,
|
texture_ = std::make_unique<GLTexture>(ATLAS_WIDTH, ATLAS_HEIGHT,
|
||||||
emptyData.data(), channels);
|
emptyData.data(), channels);
|
||||||
|
// 所有字体都使用线性过滤,SDF的抗锯齿由着色器处理
|
||||||
texture_->setFilter(true);
|
texture_->setFilter(true);
|
||||||
|
|
||||||
// 初始化矩形打包上下文 - 持久化以支持增量打包
|
// 初始化矩形打包上下文 - 持久化以支持增量打包
|
||||||
|
|
|
||||||
|
|
@ -654,6 +654,29 @@ void GLRenderer::drawText(const FontAtlas &font, const std::string &text,
|
||||||
float cursorY = y;
|
float cursorY = y;
|
||||||
float baselineY = cursorY + font.getAscent();
|
float baselineY = cursorY + font.getAscent();
|
||||||
|
|
||||||
|
// 检查是否为SDF字体
|
||||||
|
bool isSDF = font.isSDF();
|
||||||
|
|
||||||
|
// 如果是SDF字体,切换到SDF着色器
|
||||||
|
if (isSDF && sdfFontShader_) {
|
||||||
|
// 先提交当前普通批处理
|
||||||
|
if (autoBatchEnabled_ && !pendingSprites_.empty()) {
|
||||||
|
submitPendingSprites();
|
||||||
|
}
|
||||||
|
|
||||||
|
// 使用SDF着色器开始新的批处理
|
||||||
|
// 设置需要动态计算的uniform值
|
||||||
|
UniformValueMap sdfUniformValues;
|
||||||
|
sdfUniformValues["u_viewProjection"] = viewProjection_;
|
||||||
|
if (font.getTexture()) {
|
||||||
|
sdfUniformValues["u_textureSize"] = ShaderUniformValue(
|
||||||
|
glm::vec2(static_cast<float>(font.getTexture()->getWidth()),
|
||||||
|
static_cast<float>(font.getTexture()->getHeight())));
|
||||||
|
}
|
||||||
|
// 设置额外的uniform值,让submitBatch使用
|
||||||
|
spriteBatch_.setExtraUniforms(sdfUniformValues);
|
||||||
|
spriteBatch_.begin(viewProjection_, sdfFontShader_);
|
||||||
|
} else {
|
||||||
// 确保批处理已激活(自动批处理)
|
// 确保批处理已激活(自动批处理)
|
||||||
if (autoBatchEnabled_) {
|
if (autoBatchEnabled_) {
|
||||||
ensureBatchActive();
|
ensureBatchActive();
|
||||||
|
|
@ -667,6 +690,7 @@ void GLRenderer::drawText(const FontAtlas &font, const std::string &text,
|
||||||
if (autoBatchEnabled_) {
|
if (autoBatchEnabled_) {
|
||||||
currentBatchTexture_ = font.getTexture();
|
currentBatchTexture_ = font.getTexture();
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// 收集所有字符数据用于批处理
|
// 收集所有字符数据用于批处理
|
||||||
std::vector<SpriteData> sprites;
|
std::vector<SpriteData> sprites;
|
||||||
|
|
@ -677,7 +701,10 @@ void GLRenderer::drawText(const FontAtlas &font, const std::string &text,
|
||||||
if (codepoint == '\n') {
|
if (codepoint == '\n') {
|
||||||
// 换行时,将当前行添加到待处理列表
|
// 换行时,将当前行添加到待处理列表
|
||||||
if (!sprites.empty()) {
|
if (!sprites.empty()) {
|
||||||
if (autoBatchEnabled_) {
|
if (isSDF && sdfFontShader_) {
|
||||||
|
// SDF模式直接提交
|
||||||
|
spriteBatch_.drawBatch(*font.getTexture(), sprites);
|
||||||
|
} else if (autoBatchEnabled_) {
|
||||||
pendingSprites_.insert(pendingSprites_.end(), sprites.begin(),
|
pendingSprites_.insert(pendingSprites_.end(), sprites.begin(),
|
||||||
sprites.end());
|
sprites.end());
|
||||||
} else {
|
} else {
|
||||||
|
|
@ -724,7 +751,7 @@ void GLRenderer::drawText(const FontAtlas &font, const std::string &text,
|
||||||
sprites.push_back(data);
|
sprites.push_back(data);
|
||||||
|
|
||||||
// 自动批处理:如果缓冲区满,先提交当前批次
|
// 自动批处理:如果缓冲区满,先提交当前批次
|
||||||
if (autoBatchEnabled_ && sprites.size() >= MAX_BATCH_SPRITES) {
|
if (!isSDF && autoBatchEnabled_ && sprites.size() >= MAX_BATCH_SPRITES) {
|
||||||
pendingSprites_.insert(pendingSprites_.end(), sprites.begin(),
|
pendingSprites_.insert(pendingSprites_.end(), sprites.begin(),
|
||||||
sprites.end());
|
sprites.end());
|
||||||
sprites.clear();
|
sprites.clear();
|
||||||
|
|
@ -734,7 +761,10 @@ void GLRenderer::drawText(const FontAtlas &font, const std::string &text,
|
||||||
|
|
||||||
// 提交剩余的字符
|
// 提交剩余的字符
|
||||||
if (!sprites.empty()) {
|
if (!sprites.empty()) {
|
||||||
if (autoBatchEnabled_) {
|
if (isSDF && sdfFontShader_) {
|
||||||
|
// SDF模式直接提交
|
||||||
|
spriteBatch_.drawBatch(*font.getTexture(), sprites);
|
||||||
|
} else if (autoBatchEnabled_) {
|
||||||
pendingSprites_.insert(pendingSprites_.end(), sprites.begin(),
|
pendingSprites_.insert(pendingSprites_.end(), sprites.begin(),
|
||||||
sprites.end());
|
sprites.end());
|
||||||
} else {
|
} else {
|
||||||
|
|
@ -742,6 +772,18 @@ void GLRenderer::drawText(const FontAtlas &font, const std::string &text,
|
||||||
spriteBatch_.drawBatch(*font.getTexture(), sprites);
|
spriteBatch_.drawBatch(*font.getTexture(), sprites);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 如果是SDF字体,结束批处理并恢复普通着色器
|
||||||
|
if (isSDF && sdfFontShader_) {
|
||||||
|
spriteBatch_.end();
|
||||||
|
// 清除额外的uniform值
|
||||||
|
spriteBatch_.clearExtraUniforms();
|
||||||
|
// 恢复默认的sprite着色器
|
||||||
|
auto defaultShader = ShaderManager::getInstance().getBuiltin("sprite");
|
||||||
|
if (defaultShader) {
|
||||||
|
spriteBatch_.setShader(defaultShader);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -762,6 +804,14 @@ void GLRenderer::initShapeRendering() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 加载SDF字体着色器
|
||||||
|
sdfFontShader_ = ShaderManager::getInstance().getBuiltin("sdf_font");
|
||||||
|
if (!sdfFontShader_) {
|
||||||
|
E2D_LOG_WARN("获取SDF字体着色器失败,SDF字体将使用普通渲染");
|
||||||
|
} else {
|
||||||
|
E2D_LOG_INFO("SDF字体着色器加载成功");
|
||||||
|
}
|
||||||
|
|
||||||
// 初始化形状 GLBuffer(使用 Dynamic 使用模式,因为每帧都会更新)
|
// 初始化形状 GLBuffer(使用 Dynamic 使用模式,因为每帧都会更新)
|
||||||
BufferDesc shapeBufferDesc;
|
BufferDesc shapeBufferDesc;
|
||||||
shapeBufferDesc.type = BufferType::Vertex;
|
shapeBufferDesc.type = BufferType::Vertex;
|
||||||
|
|
@ -896,7 +946,8 @@ void GLRenderer::flushShapeBatch() {
|
||||||
|
|
||||||
// 使用ShaderManager自动应用uniform值(未提供的值使用JSON中的默认值)
|
// 使用ShaderManager自动应用uniform值(未提供的值使用JSON中的默认值)
|
||||||
// 使用着色器自己的名称(从JSON中解析的name字段)
|
// 使用着色器自己的名称(从JSON中解析的name字段)
|
||||||
ShaderManager::getInstance().applyUniforms(shapeShader_, shapeShader_->getName(), uniformValues);
|
ShaderManager::getInstance().applyUniforms(
|
||||||
|
shapeShader_, shapeShader_->getName(), uniformValues);
|
||||||
}
|
}
|
||||||
|
|
||||||
// 使用 GLBuffer::updateData() 更新缓冲区数据
|
// 使用 GLBuffer::updateData() 更新缓冲区数据
|
||||||
|
|
@ -932,7 +983,8 @@ void GLRenderer::flushLineBatch() {
|
||||||
|
|
||||||
// 使用ShaderManager自动应用uniform值(未提供的值使用JSON中的默认值)
|
// 使用ShaderManager自动应用uniform值(未提供的值使用JSON中的默认值)
|
||||||
// 使用着色器自己的名称(从JSON中解析的name字段)
|
// 使用着色器自己的名称(从JSON中解析的name字段)
|
||||||
ShaderManager::getInstance().applyUniforms(shapeShader_, shapeShader_->getName(), uniformValues);
|
ShaderManager::getInstance().applyUniforms(
|
||||||
|
shapeShader_, shapeShader_->getName(), uniformValues);
|
||||||
}
|
}
|
||||||
|
|
||||||
// 使用 GLBuffer::updateData() 更新缓冲区数据
|
// 使用 GLBuffer::updateData() 更新缓冲区数据
|
||||||
|
|
|
||||||
|
|
@ -93,6 +93,22 @@ void GLSpriteBatch::begin(const glm::mat4 &viewProjection) {
|
||||||
ebo_.bind();
|
ebo_.bind();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void GLSpriteBatch::begin(const glm::mat4 &viewProjection, Ptr<IShader> shader) {
|
||||||
|
// 设置自定义着色器
|
||||||
|
if (shader) {
|
||||||
|
shader_ = shader;
|
||||||
|
}
|
||||||
|
begin(viewProjection);
|
||||||
|
}
|
||||||
|
|
||||||
|
void GLSpriteBatch::setShader(Ptr<IShader> shader) {
|
||||||
|
// 如果当前有未提交的批次,先提交
|
||||||
|
if (batch_.getSpriteCount() > 0) {
|
||||||
|
flush();
|
||||||
|
}
|
||||||
|
shader_ = shader;
|
||||||
|
}
|
||||||
|
|
||||||
void GLSpriteBatch::end() {
|
void GLSpriteBatch::end() {
|
||||||
if (batch_.getSpriteCount() > 0) {
|
if (batch_.getSpriteCount() > 0) {
|
||||||
flush();
|
flush();
|
||||||
|
|
@ -166,6 +182,11 @@ void GLSpriteBatch::submitBatch() {
|
||||||
UniformValueMap uniformValues;
|
UniformValueMap uniformValues;
|
||||||
uniformValues["u_viewProjection"] = viewProjection_;
|
uniformValues["u_viewProjection"] = viewProjection_;
|
||||||
|
|
||||||
|
// 合并额外的uniform值(如SDF字体的u_textureSize)
|
||||||
|
for (const auto& [name, value] : extraUniforms_) {
|
||||||
|
uniformValues[name] = value;
|
||||||
|
}
|
||||||
|
|
||||||
// 使用ShaderManager自动应用uniform值(未提供的值使用JSON中的默认值)
|
// 使用ShaderManager自动应用uniform值(未提供的值使用JSON中的默认值)
|
||||||
// 使用着色器自己的名称(从JSON中解析的name字段)
|
// 使用着色器自己的名称(从JSON中解析的name字段)
|
||||||
ShaderManager::getInstance().applyUniforms(shader_, shader_->getName(),
|
ShaderManager::getInstance().applyUniforms(shader_, shader_->getName(),
|
||||||
|
|
|
||||||
|
|
@ -549,6 +549,16 @@ Ptr<IShader> ShaderManager::loadFromMetadata(const std::string &jsonPath,
|
||||||
def.defaultInt = value["default"].get<int>();
|
def.defaultInt = value["default"].get<int>();
|
||||||
} else if (def.type == "bool") {
|
} else if (def.type == "bool") {
|
||||||
def.defaultBool = value["default"].get<bool>();
|
def.defaultBool = value["default"].get<bool>();
|
||||||
|
} else if (def.type == "vec2" && value["default"].is_array()) {
|
||||||
|
auto arr = value["default"].get<std::vector<float>>();
|
||||||
|
for (size_t i = 0; i < arr.size() && i < 2; ++i) {
|
||||||
|
def.defaultVec2[i] = arr[i];
|
||||||
|
}
|
||||||
|
} else if (def.type == "vec3" && value["default"].is_array()) {
|
||||||
|
auto arr = value["default"].get<std::vector<float>>();
|
||||||
|
for (size_t i = 0; i < arr.size() && i < 3; ++i) {
|
||||||
|
def.defaultVec3[i] = arr[i];
|
||||||
|
}
|
||||||
} else if (def.type == "vec4" && value["default"].is_array()) {
|
} else if (def.type == "vec4" && value["default"].is_array()) {
|
||||||
auto arr = value["default"].get<std::vector<float>>();
|
auto arr = value["default"].get<std::vector<float>>();
|
||||||
for (size_t i = 0; i < arr.size() && i < 4; ++i) {
|
for (size_t i = 0; i < arr.size() && i < 4; ++i) {
|
||||||
|
|
@ -806,6 +816,12 @@ void ShaderManager::applyUniforms(Ptr<IShader> shader,
|
||||||
shader->setInt(name, def.defaultInt);
|
shader->setInt(name, def.defaultInt);
|
||||||
} else if (def.type == "bool") {
|
} else if (def.type == "bool") {
|
||||||
shader->setBool(name, def.defaultBool);
|
shader->setBool(name, def.defaultBool);
|
||||||
|
} else if (def.type == "vec2") {
|
||||||
|
shader->setVec2(name,
|
||||||
|
glm::vec2(def.defaultVec2[0], def.defaultVec2[1]));
|
||||||
|
} else if (def.type == "vec3") {
|
||||||
|
shader->setVec3(name, glm::vec3(def.defaultVec3[0], def.defaultVec3[1],
|
||||||
|
def.defaultVec3[2]));
|
||||||
} else if (def.type == "vec4") {
|
} else if (def.type == "vec4") {
|
||||||
shader->setVec4(name,
|
shader->setVec4(name,
|
||||||
glm::vec4(def.defaultVec4[0], def.defaultVec4[1],
|
glm::vec4(def.defaultVec4[0], def.defaultVec4[1],
|
||||||
|
|
|
||||||
Binary file not shown.
Binary file not shown.
|
|
@ -23,17 +23,10 @@ public:
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
font_ = renderer_->createFontAtlas("assets/fonts/arial.ttf", 24);
|
font_ = renderer_->createFontAtlas("assets/fonts/fonts.ttf", 26, true);
|
||||||
} catch (...) {
|
} catch (...) {
|
||||||
std::cerr << "Failed to load font from assets/fonts/arial.ttf"
|
std::cerr << "Failed to load font from assets/fonts/fonts.ttf"
|
||||||
<< std::endl;
|
<< std::endl;
|
||||||
// 尝试使用备用路径
|
|
||||||
try {
|
|
||||||
font_ = renderer_->createFontAtlas("C:/Windows/Fonts/arial.ttf", 24);
|
|
||||||
} catch (...) {
|
|
||||||
std::cerr << "Failed to load font from system path!" << std::endl;
|
|
||||||
font_ = nullptr;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (font_) {
|
if (font_) {
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue