2026-03-02 00:25:14 +08:00
|
|
|
|
#include <fstream>
|
2026-03-03 02:16:29 +08:00
|
|
|
|
#include <renderer/rhi_module.h>
|
2026-03-02 04:57:44 +08:00
|
|
|
|
#include <renderer/shader.h>
|
2026-03-02 00:25:14 +08:00
|
|
|
|
#include <sstream>
|
2026-03-02 04:57:44 +08:00
|
|
|
|
#include <utils/logger.h>
|
2026-03-02 00:25:14 +08:00
|
|
|
|
|
|
|
|
|
|
namespace extra2d {
|
|
|
|
|
|
|
|
|
|
|
|
Shader::Shader() = default;
|
|
|
|
|
|
|
|
|
|
|
|
Shader::~Shader() {
|
2026-03-03 02:16:29 +08:00
|
|
|
|
// RHIHandle 是轻量级句柄,不需要显式释放
|
|
|
|
|
|
// 实际的资源由 RHI 设备管理
|
|
|
|
|
|
pipeline_ = PipelineHandle();
|
|
|
|
|
|
handle_ = ShaderHandle();
|
2026-03-02 00:25:14 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
2026-03-02 04:57:44 +08:00
|
|
|
|
bool Shader::loadFromFile(const std::string &vsPath,
|
|
|
|
|
|
const std::string &fsPath) {
|
|
|
|
|
|
// 读取顶点着色器
|
|
|
|
|
|
std::ifstream vsFile(vsPath);
|
|
|
|
|
|
if (!vsFile.is_open()) {
|
|
|
|
|
|
E2D_LOG_ERROR("Failed to open vertex shader: {}", vsPath);
|
|
|
|
|
|
return false;
|
|
|
|
|
|
}
|
|
|
|
|
|
std::stringstream vsStream;
|
|
|
|
|
|
vsStream << vsFile.rdbuf();
|
|
|
|
|
|
std::string vsSource = vsStream.str();
|
|
|
|
|
|
|
|
|
|
|
|
// 读取片段着色器
|
|
|
|
|
|
std::ifstream fsFile(fsPath);
|
|
|
|
|
|
if (!fsFile.is_open()) {
|
|
|
|
|
|
E2D_LOG_ERROR("Failed to open fragment shader: {}", fsPath);
|
|
|
|
|
|
return false;
|
|
|
|
|
|
}
|
|
|
|
|
|
std::stringstream fsStream;
|
|
|
|
|
|
fsStream << fsFile.rdbuf();
|
|
|
|
|
|
std::string fsSource = fsStream.str();
|
|
|
|
|
|
|
|
|
|
|
|
return loadFromSource(vsSource, fsSource);
|
2026-03-02 00:25:14 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
2026-03-02 04:57:44 +08:00
|
|
|
|
bool Shader::loadFromSource(const std::string &vsSource,
|
|
|
|
|
|
const std::string &fsSource) {
|
2026-03-03 02:16:29 +08:00
|
|
|
|
// 释放旧资源
|
|
|
|
|
|
pipeline_ = PipelineHandle();
|
|
|
|
|
|
handle_ = ShaderHandle();
|
|
|
|
|
|
|
|
|
|
|
|
// 获取 RHI 设备
|
|
|
|
|
|
auto *rhiModule = RHIModule::get();
|
|
|
|
|
|
if (!rhiModule) {
|
|
|
|
|
|
E2D_LOG_ERROR("RHIModule not available");
|
|
|
|
|
|
return false;
|
2026-03-02 04:57:44 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
2026-03-03 02:16:29 +08:00
|
|
|
|
auto *device = rhiModule->getDevice();
|
|
|
|
|
|
if (!device) {
|
|
|
|
|
|
E2D_LOG_ERROR("RHIDevice not available");
|
2026-03-02 04:57:44 +08:00
|
|
|
|
return false;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2026-03-03 02:16:29 +08:00
|
|
|
|
// 处理源码(添加版本声明)
|
|
|
|
|
|
std::string processedVS = addVersionIfNeeded(vsSource, true);
|
|
|
|
|
|
std::string processedFS = addVersionIfNeeded(fsSource, false);
|
|
|
|
|
|
|
|
|
|
|
|
// 创建着色器描述
|
|
|
|
|
|
ShaderDesc shaderDesc;
|
|
|
|
|
|
shaderDesc.vertexSource = processedVS;
|
|
|
|
|
|
shaderDesc.fragmentSource = processedFS;
|
|
|
|
|
|
|
|
|
|
|
|
// 创建着色器
|
|
|
|
|
|
auto shader = device->createShader(shaderDesc);
|
|
|
|
|
|
if (!shader) {
|
|
|
|
|
|
E2D_LOG_ERROR("Failed to create shader");
|
2026-03-02 04:57:44 +08:00
|
|
|
|
return false;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2026-03-03 02:16:29 +08:00
|
|
|
|
// 获取着色器句柄
|
|
|
|
|
|
handle_ = ShaderHandle(shader.release());
|
|
|
|
|
|
|
|
|
|
|
|
// 创建顶点布局(2D 标准布局:位置 + 纹理坐标 + 颜色)
|
|
|
|
|
|
VertexLayout vertexLayout;
|
|
|
|
|
|
vertexLayout.stride = sizeof(float) * 8; // 2 (pos) + 2 (uv) + 4 (color)
|
|
|
|
|
|
vertexLayout.addAttribute(0, VertexFormat::Float2, 0); // 位置
|
|
|
|
|
|
vertexLayout.addAttribute(1, VertexFormat::Float2, 8); // 纹理坐标
|
|
|
|
|
|
vertexLayout.addAttribute(2, VertexFormat::Float4, 16); // 颜色
|
|
|
|
|
|
|
|
|
|
|
|
// 创建管线描述
|
|
|
|
|
|
PipelineDesc pipelineDesc;
|
|
|
|
|
|
pipelineDesc.vertexShader = handle_;
|
|
|
|
|
|
pipelineDesc.fragmentShader = handle_;
|
|
|
|
|
|
pipelineDesc.vertexLayout = vertexLayout;
|
|
|
|
|
|
pipelineDesc.blendState = BlendState::alphaBlend();
|
|
|
|
|
|
pipelineDesc.depthStencilState = DepthStencilState::noDepthTest();
|
|
|
|
|
|
pipelineDesc.rasterizerState = RasterizerState::noCull();
|
|
|
|
|
|
|
|
|
|
|
|
// 创建管线
|
|
|
|
|
|
auto pipeline = device->createPipeline(pipelineDesc);
|
|
|
|
|
|
if (!pipeline) {
|
|
|
|
|
|
E2D_LOG_ERROR("Failed to create pipeline");
|
|
|
|
|
|
handle_ = ShaderHandle();
|
2026-03-02 04:57:44 +08:00
|
|
|
|
return false;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2026-03-03 02:16:29 +08:00
|
|
|
|
// 获取管线句柄
|
|
|
|
|
|
pipeline_ = PipelineHandle(pipeline.release());
|
2026-03-02 04:57:44 +08:00
|
|
|
|
|
2026-03-03 02:16:29 +08:00
|
|
|
|
E2D_LOG_INFO("Shader created successfully");
|
2026-03-02 04:57:44 +08:00
|
|
|
|
return true;
|
2026-03-02 00:25:14 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
2026-03-02 04:57:44 +08:00
|
|
|
|
void Shader::setUniformBlock(const std::string &name, uint32_t binding) {
|
2026-03-03 02:16:29 +08:00
|
|
|
|
// 存储 uniform block 绑定信息
|
|
|
|
|
|
uniformBlockBindings_[name] = binding;
|
2026-03-02 00:25:14 +08:00
|
|
|
|
|
2026-03-03 02:16:29 +08:00
|
|
|
|
// 注意:实际的 uniform block 绑定需要在渲染时通过 RHI 命令列表设置
|
|
|
|
|
|
// 这里仅存储绑定信息,供后续渲染使用
|
|
|
|
|
|
// 例如:commandList->setUniformBlock(binding, buffer);
|
2026-03-02 00:25:14 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
2026-03-03 02:16:29 +08:00
|
|
|
|
uint32_t Shader::getUniformBlockBinding(const std::string &name) const {
|
|
|
|
|
|
auto it = uniformBlockBindings_.find(name);
|
|
|
|
|
|
if (it != uniformBlockBindings_.end()) {
|
2026-03-02 04:57:44 +08:00
|
|
|
|
return it->second;
|
|
|
|
|
|
}
|
2026-03-03 02:16:29 +08:00
|
|
|
|
return UINT32_MAX; // 未找到
|
2026-03-02 00:25:14 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
2026-03-03 02:16:29 +08:00
|
|
|
|
std::string Shader::addVersionIfNeeded(const std::string &source,
|
|
|
|
|
|
bool isVertex) {
|
2026-03-02 04:57:44 +08:00
|
|
|
|
// 如果已经包含版本声明,直接返回
|
|
|
|
|
|
if (source.find("#version") != std::string::npos) {
|
|
|
|
|
|
return source;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 添加 OpenGL ES 3.2 版本声明
|
|
|
|
|
|
std::string result = "#version 320 es\n";
|
|
|
|
|
|
|
|
|
|
|
|
// 片段着色器需要添加精度声明
|
2026-03-03 02:16:29 +08:00
|
|
|
|
if (!isVertex) {
|
2026-03-02 04:57:44 +08:00
|
|
|
|
result += "precision mediump float;\n";
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
result += source;
|
|
|
|
|
|
return result;
|
2026-03-02 00:25:14 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
} // namespace extra2d
|