1. 完善了对于不同平台的shader文件的处理

2. 新增了对红米5Plus的支持
3. 将嵌入式Linux平台的PTT按钮重构成了动态位置大小变化
4. 新增了以Debug编译时显示实时FPS信息显示,在桌面平台表现正常,在嵌入式Linux还存在问题
This commit is contained in:
Misaki
2026-07-06 18:21:30 +08:00
parent c036b005f8
commit 6b8983bc6d
10 changed files with 268 additions and 33 deletions
+33 -4
View File
@@ -10,13 +10,17 @@ set(CMAKE_AUTOUIC ON)
if(DEFINED TARGET_ARCH AND TARGET_ARCH STREQUAL "arm64") if(DEFINED TARGET_ARCH AND TARGET_ARCH STREQUAL "arm64")
set(PLAT "linux_arm") set(PLAT "linux_arm")
set(ARCH "arm64") set(ARCH "arm64")
if(NOT DEFINED CMAKE_PREFIX_PATH) # 优先使用外部传入的变量值
set(CMAKE_PREFIX_PATH "/home/misaki/MisakiCodes/rk3566-sdk/3rd/Qt6.6.3") set(CMAKE_PREFIX_PATH "/home/misaki/MisakiCodes/rk3566-sdk/3rd/Qt6.6.3")
endif()
add_definitions(-DCSM_TARGET_HARMONYOS_ES3) # OpenGL ES 3.0 渲染宏 add_definitions(-DCSM_TARGET_HARMONYOS_ES3) # OpenGL ES 3.0 渲染宏
add_definitions(-DEMBEDDED_LINUX) # 嵌入式Linux专用宏 add_definitions(-DEMBEDDED_LINUX) # 嵌入式Linux专用宏
elseif(CMAKE_SYSTEM_PROCESSOR MATCHES "aarch64|arm64|ARM64") elseif(CMAKE_SYSTEM_PROCESSOR MATCHES "aarch64|arm64|ARM64")
set(PLAT "linux_arm") set(PLAT "linux_arm")
set(ARCH "arm64") set(ARCH "arm64")
if(NOT DEFINED CMAKE_PREFIX_PATH)
set(CMAKE_PREFIX_PATH "/home/misaki/MisakiCodes/rk3566-sdk/3rd/Qt6.6.3") set(CMAKE_PREFIX_PATH "/home/misaki/MisakiCodes/rk3566-sdk/3rd/Qt6.6.3")
endif()
add_definitions(-DCSM_TARGET_HARMONYOS_ES3) add_definitions(-DCSM_TARGET_HARMONYOS_ES3)
add_definitions(-DEMBEDDED_LINUX) add_definitions(-DEMBEDDED_LINUX)
elseif(WIN32) elseif(WIN32)
@@ -73,6 +77,8 @@ file(GLOB_RECURSE YosugaSrc
"src/DAO/Src/*.cpp" "src/DAO/Src/*.cpp"
"src/UI/Render/TextRender/Src/*.cpp" "src/UI/Render/TextRender/Src/*.cpp"
"src/UI/Render/TextRender/Inc/*.h" "src/UI/Render/TextRender/Inc/*.h"
"src/UI/Widgets/Src/*.cpp"
"src/UI/Widgets/Inc/*.hpp"
"src/Core/Src/*.cpp" "src/Core/Src/*.cpp"
"src/Core/Inc/*.h" "src/Core/Inc/*.h"
"src/Utils/Inc/*.hpp" "src/Utils/Inc/*.hpp"
@@ -92,6 +98,10 @@ if(NOT PLAT STREQUAL "linux_arm")
list(APPEND YosugaSrc ${DesktopUI_Src}) list(APPEND YosugaSrc ${DesktopUI_Src})
endif() endif()
message(STATUS ">>> CMAKE_PREFIX_PATH = ${CMAKE_PREFIX_PATH}")
message(STATUS ">>> CMAKE_FIND_ROOT_PATH = ${CMAKE_FIND_ROOT_PATH}")
message(STATUS ">>> Qt6_DIR = ${Qt6_DIR}")
# 查找Qt6模块以及其他必须模块 # 查找Qt6模块以及其他必须模块
find_package(Qt6 COMPONENTS find_package(Qt6 COMPONENTS
Core Core
@@ -111,7 +121,8 @@ if(NOT PLAT STREQUAL "linux_arm")
find_package(OpenGL REQUIRED) find_package(OpenGL REQUIRED)
else () else ()
# 若为arm平台,对于C++采用静态链接标准库,避免环境复杂出现问题 # 若为arm平台,对于C++采用静态链接标准库,避免环境复杂出现问题
set(CMAKE_EXE_LINKER_FLAGS "-static-libstdc++ -static-libgcc") # --allow-shlib-undefined: 允许共享库存在未定义符号,运行时由目标设备的 glibc 解析(这是为了放置你使用的交叉编译工具链对glibc版本要求严格)
set(CMAKE_EXE_LINKER_FLAGS "-static-libstdc++ -static-libgcc -Wl,--allow-shlib-undefined")
endif () endif ()
# 添加第三方子项目 # 添加第三方子项目
@@ -222,9 +233,9 @@ if(PLAT STREQUAL "linux_arm") ## 针对嵌入式Linux的配置,部分条
Framework Framework
Live2DCubismCore Live2DCubismCore
# Mali GPU 驱动完整链接(EGLFS 必需) # Mali GPU 驱动完整链接(EGLFS 必需)
-lmali-hook # 注意此处,你的soc不一定是该GPU,可能需要修改 # -lmali-hook # 注意此处,你的soc不一定是该GPU,可能需要修改
-Wl,--whole-archive -lmali-hook-injector -Wl,--no-whole-archive # -Wl,--whole-archive -lmali-hook-injector -Wl,--no-whole-archive
-lmali # -lmali
-ldrm -ldrm
-lEGL -lEGL
-lGLESv2 -lGLESv2
@@ -268,16 +279,34 @@ target_include_directories(${PROJECT_NAME} PRIVATE
src/UI/Menu/Inc src/UI/Menu/Inc
src/UI/Setting/Inc src/UI/Setting/Inc
src/UI/Render/TextRender/Inc src/UI/Render/TextRender/Inc
src/UI/Widgets/Inc
src/Core/Inc src/Core/Inc
src/DAO/Inc src/DAO/Inc
src/Utils/Inc src/Utils/Inc
) )
# Debug 编译时启用 FPS 显示等调试功能
if(CMAKE_BUILD_TYPE STREQUAL "Debug")
add_definitions(-DYOSUGA_DEBUG)
endif()
# 资源复制(所有平台) # 资源复制(所有平台)
file(COPY "${CMAKE_CURRENT_SOURCE_DIR}/other/Resources" file(COPY "${CMAKE_CURRENT_SOURCE_DIR}/other/Resources"
DESTINATION "${CMAKE_CURRENT_BINARY_DIR}") DESTINATION "${CMAKE_CURRENT_BINARY_DIR}")
# 根据平台选择不同的 Shader 目录,但目标目录名统一为 FrameworkShaders
if(PLAT STREQUAL "linux_arm")
# 先清理旧的
file(REMOVE_RECURSE "${CMAKE_CURRENT_BINARY_DIR}/FrameworkShaders")
# 复制到构建目录 会生成 FrameworkShadersES
file(COPY "${CMAKE_CURRENT_SOURCE_DIR}/other/FrameworkShadersES"
DESTINATION "${CMAKE_CURRENT_BINARY_DIR}")
# 重命名为 FrameworkShaders,最终路径 build/FrameworkShaders/
file(RENAME "${CMAKE_CURRENT_BINARY_DIR}/FrameworkShadersES"
"${CMAKE_CURRENT_BINARY_DIR}/FrameworkShaders")
else()
file(COPY "${CMAKE_CURRENT_SOURCE_DIR}/other/FrameworkShaders" file(COPY "${CMAKE_CURRENT_SOURCE_DIR}/other/FrameworkShaders"
DESTINATION "${CMAKE_CURRENT_BINARY_DIR}") DESTINATION "${CMAKE_CURRENT_BINARY_DIR}")
endif()
# Windows 特有的 DLL 复制 # Windows 特有的 DLL 复制
if(PLAT STREQUAL "windows") if(PLAT STREQUAL "windows")
+20 -1
View File
@@ -95,6 +95,23 @@
"EGL_INCLUDE_DIR": "/home/misaki/MisakiCodes/rk3566-sdk/host/aarch64-buildroot-linux-gnu/sysroot/usr/include", "EGL_INCLUDE_DIR": "/home/misaki/MisakiCodes/rk3566-sdk/host/aarch64-buildroot-linux-gnu/sysroot/usr/include",
"EGL_LIBRARY": "/home/misaki/MisakiCodes/rk3566-sdk/host/aarch64-buildroot-linux-gnu/sysroot/usr/lib/libEGL.so" "EGL_LIBRARY": "/home/misaki/MisakiCodes/rk3566-sdk/host/aarch64-buildroot-linux-gnu/sysroot/usr/lib/libEGL.so"
} }
},
{
"name": "vince-cross",
"inherits": "embedded-base",
"displayName": "Redmi 5 Plus (vince) Cross Compile",
"description": "红米5 Plus 嵌入式交叉编译 (ARM64 + Qt6.6.3 EGLFS/DRM)",
"binaryDir": "${sourceDir}/build_vince",
"generator": "Unix Makefiles",
"cacheVariables": {
"CMAKE_BUILD_TYPE": "Debug",
"CMAKE_TOOLCHAIN_FILE": "/home/misaki/MisakiCodes/Redmi5Plus-SDK/vince_toolchain.cmake",
"CMAKE_PREFIX_PATH": "/home/misaki/MisakiCodes/Redmi5Plus-SDK/qt6.6.3-vince",
"GLESv2_INCLUDE_DIR": "/home/misaki/MisakiCodes/Redmi5Plus-SDK/vince-rootfs/usr/include",
"GLESv2_LIBRARY": "/home/misaki/MisakiCodes/Redmi5Plus-SDK/vince-rootfs/usr/lib/libGLESv2.so",
"EGL_INCLUDE_DIR": "/home/misaki/MisakiCodes/Redmi5Plus-SDK/vince-rootfs/usr/include",
"EGL_LIBRARY": "/home/misaki/MisakiCodes/Redmi5Plus-SDK/vince-rootfs/usr/lib/libEGL.so"
}
} }
], ],
"buildPresets": [ "buildPresets": [
@@ -107,6 +124,8 @@
{ "name": "macos-debug", "configurePreset": "macos-native", "configuration": "Debug" }, { "name": "macos-debug", "configurePreset": "macos-native", "configuration": "Debug" },
{ "name": "macos-release", "configurePreset": "macos-native", "configuration": "Release" }, { "name": "macos-release", "configurePreset": "macos-native", "configuration": "Release" },
{ "name": "rk3566-debug", "configurePreset": "rk3566-cross", "configuration": "Debug" }, { "name": "rk3566-debug", "configurePreset": "rk3566-cross", "configuration": "Debug" },
{ "name": "rk3566-release", "configurePreset": "rk3566-cross", "configuration": "Release" } { "name": "rk3566-release", "configurePreset": "rk3566-cross", "configuration": "Release" },
{ "name": "vince-debug", "configurePreset": "vince-cross", "configuration": "Debug" },
{ "name": "vince-release", "configurePreset": "vince-cross", "configuration": "Release" }
] ]
} }
+2 -1
View File
@@ -52,8 +52,9 @@ cmake ..
make make
``` ```
注意:本项目只是Yosuga的客户端部分,完整的还包括服务端 注意:本项目只是Yosuga的客户端部分,完整的还包括服务端和嵌入式端
- 服务端项目地址见:https://github.com/Misakityan/Yosuga_server - 服务端项目地址见:https://github.com/Misakityan/Yosuga_server
- 嵌入式项目地址见:https://github.com/Misakityan/Yosuga_embedded
当前支持平台(已测试过的) 当前支持平台(已测试过的)
- Windows: Windows 10 - Windows: Windows 10
Binary file not shown.

After

Width:  |  Height:  |  Size: 24 KiB

+8 -2
View File
@@ -6,7 +6,10 @@
#include "menu.h" #include "menu.h"
#endif #endif
#ifdef EMBEDDED_LINUX #ifdef EMBEDDED_LINUX
#include <QPushButton> #include "PttButton.hpp"
#endif
#ifdef YOSUGA_DEBUG
#include "FpsOverlay.hpp"
#endif #endif
#ifdef Q_OS_WIN #ifdef Q_OS_WIN
@@ -89,7 +92,10 @@ private:
Menu *contextMenu; /// 使用 Menu 类 Menu *contextMenu; /// 使用 Menu 类
#endif #endif
#ifdef EMBEDDED_LINUX #ifdef EMBEDDED_LINUX
QPushButton *pttButton; /// 嵌入式平台PTT按钮 PttButton *pttButton; /// 嵌入式平台PTT按钮
#endif
#ifdef YOSUGA_DEBUG
FpsOverlay fpsOverlay; /// 调试用FPS显示
#endif #endif
bool isLeftPressed; /// 鼠标左键是否按下 bool isLeftPressed; /// 鼠标左键是否按下
+18 -20
View File
@@ -7,6 +7,7 @@
#include <QTimer> #include <QTimer>
#include <QMouseEvent> #include <QMouseEvent>
#include <QDebug> #include <QDebug>
#include <QPainter>
#include <QFont> #include <QFont>
#include <QApplication> #include <QApplication>
@@ -94,28 +95,13 @@ GLCore::GLCore(const int width, const int height, QWidget *parent)
#ifdef EMBEDDED_LINUX #ifdef EMBEDDED_LINUX
AppCore::getInstance(); AppCore::getInstance();
pttButton = new QPushButton(this); pttButton = new PttButton(this);
pttButton->setFixedSize(64, 64); pttButton->updateLayout(width, height);
pttButton->move(width - 80, height - 80);
pttButton->setIcon(QIcon("Resources/Pic/Others/voice.png"));
pttButton->setIconSize(QSize(56, 56));
pttButton->setStyleSheet(
"QPushButton {"
" background-color: rgba(255, 255, 255, 60);"
" border-radius: 32px;"
" border: none;"
"}"
"QPushButton:pressed {"
" background-color: rgba(250, 80, 80, 150);"
"}"
);
pttButton->raise();
pttButton->show();
connect(pttButton, &QPushButton::pressed, this, []() { connect(pttButton, &PttButton::pressedForPtt, this, []() {
AppCore::getInstance()->startPttRecording(); AppCore::getInstance()->startPttRecording();
}); });
connect(pttButton, &QPushButton::released, this, []() { connect(pttButton, &PttButton::releasedForPtt, this, []() {
AppCore::getInstance()->stopPttRecording(); AppCore::getInstance()->stopPttRecording();
}); });
#endif #endif
@@ -342,6 +328,8 @@ void GLCore::initializeGL()
if (!LAppDelegate::GetInstance()->GetRenderContext()) { if (!LAppDelegate::GetInstance()->GetRenderContext()) {
LAppDelegate::GetInstance()->SetRenderContext(new GLRenderContext()); LAppDelegate::GetInstance()->SetRenderContext(new GLRenderContext());
} }
#ifndef EMBEDDED_LINUX
// 初始化GLEW 必须在任何Live2D渲染操作之前调用 // 初始化GLEW 必须在任何Live2D渲染操作之前调用
// Live2D预编译的libFramework.a使用GLEW函数指针(如glGenFramebuffers等), // Live2D预编译的libFramework.a使用GLEW函数指针(如glGenFramebuffers等),
// 未调用glewInit()会导致空指针解引用SIGSEGV // 未调用glewInit()会导致空指针解引用SIGSEGV
@@ -350,6 +338,7 @@ void GLCore::initializeGL()
qFatal("Failed to initialize GLEW"); qFatal("Failed to initialize GLEW");
return; return;
} }
#endif
// 注册窗口大小变更回调 模型加载后通过此回调通知GLCore调整窗口 // 注册窗口大小变更回调 模型加载后通过此回调通知GLCore调整窗口
LAppDelegate::GetInstance()->SetWindowResizeCallback([this](int w, int h) { LAppDelegate::GetInstance()->SetWindowResizeCallback([this](int w, int h) {
@@ -361,10 +350,15 @@ void GLCore::initializeGL()
void GLCore::paintGL() void GLCore::paintGL()
{ {
LAppDelegate::GetInstance()->update(); // Live2D画面渲染 // Live2D Model画面渲染
LAppDelegate::GetInstance()->update();
// 渲染文本 // 渲染文本
TextRenderer::getInstance()->update(); TextRenderer::getInstance()->update();
TextRenderer::getInstance()->render(); TextRenderer::getInstance()->render();
#ifdef YOSUGA_DEBUG
fpsOverlay.tick();
fpsOverlay.draw(width(), height());
#endif
} }
void GLCore::resizeGL(const int w, const int h) void GLCore::resizeGL(const int w, const int h)
@@ -373,6 +367,10 @@ void GLCore::resizeGL(const int w, const int h)
TextRenderer::getInstance()->setWindowSize(w, h); TextRenderer::getInstance()->setWindowSize(w, h);
LAppDelegate::GetInstance()->resize(w, h); LAppDelegate::GetInstance()->resize(w, h);
#ifdef EMBEDDED_LINUX
pttButton->updateLayout(w, h);
#endif
} }
// 设置窗口大小,并触发 resizeGL 事件 // 设置窗口大小,并触发 resizeGL 事件
+33
View File
@@ -0,0 +1,33 @@
#pragma once
#ifdef YOSUGA_DEBUG
#include <QElapsedTimer>
#include <QString>
class QTimer;
class FpsOverlay
{
public:
FpsOverlay();
~FpsOverlay();
void tick();
void draw(int parentWidth, int parentHeight);
float rightMargin = 0.03f;
float topMargin = 0.03f;
int fontSize = 20;
private:
QElapsedTimer _elapsed;
QTimer* _timer = nullptr;
int _frameCount = 0;
int _displayedFps = 0;
QString _text = "FPS: --";
void recalcFps();
};
#endif
+29
View File
@@ -0,0 +1,29 @@
#pragma once
#ifdef EMBEDDED_LINUX
#include <QPushButton>
class PttButton : public QPushButton
{
Q_OBJECT
public:
explicit PttButton(QWidget* parent = nullptr);
void updateLayout(int parentWidth, int parentHeight);
float scale = 0.15f;
float rightMargin = 0.05f;
float bottomMargin = 0.05f;
int minSize = 48;
int maxSize = 128;
signals:
void pressedForPtt();
void releasedForPtt();
private:
void applyStyleSheet(int btnSize);
};
#endif
+71
View File
@@ -0,0 +1,71 @@
#ifdef YOSUGA_DEBUG
#include "FpsOverlay.hpp"
#include <QPainter>
#include <QOpenGLPaintDevice>
#include <QTimer>
#include <cstdio>
FpsOverlay::FpsOverlay()
{
_timer = new QTimer;
_timer->setTimerType(Qt::PreciseTimer);
QObject::connect(_timer, &QTimer::timeout, [this]() { recalcFps(); });
_timer->start(1000);
_elapsed.start();
}
FpsOverlay::~FpsOverlay()
{
delete _timer;
}
void FpsOverlay::tick()
{
++_frameCount;
}
void FpsOverlay::draw(int parentWidth, int parentHeight)
{
QOpenGLPaintDevice device(QSize(parentWidth, parentHeight));
QPainter painter(&device);
painter.setRenderHint(QPainter::Antialiasing);
QFont f;
f.setPixelSize(fontSize);
f.setBold(true);
f.setStyleHint(QFont::Monospace);
QFontMetrics fm(f);
const int pad = 8;
const int textW = fm.horizontalAdvance(_text) + pad * 2;
const int textH = fm.height() + pad;
const int x = parentWidth - textW - static_cast<int>(parentWidth * rightMargin);
const int y = static_cast<int>(parentHeight * topMargin);
painter.setBrush(QColor(0, 0, 0, 180));
painter.setPen(Qt::NoPen);
painter.drawRoundedRect(x, y, textW, textH, 4, 4);
painter.setFont(f);
const QColor fg = _displayedFps <= 0 ? QColor(170, 170, 170) :
_displayedFps <= 30 ? QColor(255, 68, 68) :
_displayedFps <= 45 ? QColor(255, 170, 0) :
QColor( 68, 255, 68);
painter.setPen(fg);
painter.drawText(QRect(x + pad, y, textW - pad * 2, textH),
Qt::AlignVCenter | Qt::AlignLeft, _text);
}
void FpsOverlay::recalcFps()
{
const qint64 ms = _elapsed.elapsed();
if (ms == 0) return;
_displayedFps = static_cast<int>(_frameCount * 1000.0 / ms);
_frameCount = 0;
_elapsed.restart();
_text = QString("FPS: %1").arg(_displayedFps);
fprintf(stderr, "[FPS] %s\n", _text.toUtf8().constData());
}
#endif
+49
View File
@@ -0,0 +1,49 @@
#ifdef EMBEDDED_LINUX
#include "PttButton.hpp"
#include <QIcon>
#include <algorithm>
PttButton::PttButton(QWidget* parent)
: QPushButton(parent)
{
setIcon(QIcon("Resources/Pic/Others/voice.png"));
setFlat(true);
raise();
show();
connect(this, &QPushButton::pressed, this, &PttButton::pressedForPtt);
connect(this, &QPushButton::released, this, &PttButton::releasedForPtt);
}
void PttButton::updateLayout(int parentWidth, int parentHeight)
{
if (parentWidth <= 0 || parentHeight <= 0) return;
const int minDim = std::min(parentWidth, parentHeight);
const int btnSize = std::clamp(static_cast<int>(minDim * scale), minSize, maxSize);
const int x = parentWidth - btnSize - static_cast<int>(parentWidth * rightMargin);
const int y = parentHeight - btnSize - static_cast<int>(parentHeight * bottomMargin);
const int iconPad = btnSize / 8;
setFixedSize(btnSize, btnSize);
move(x, y);
setIconSize(QSize(btnSize - iconPad * 2, btnSize - iconPad * 2));
applyStyleSheet(btnSize);
}
void PttButton::applyStyleSheet(int btnSize)
{
setStyleSheet(
QString(
"QPushButton {"
" background-color: rgba(255, 255, 255, 60);"
" border-radius: %1px;"
" border: none;"
"}"
"QPushButton:pressed {"
" background-color: rgba(250, 80, 80, 150);"
"}"
).arg(btnSize / 2)
);
}
#endif