149 lines
4.2 KiB
C++
149 lines
4.2 KiB
C++
#include <fstream>
|
||
#include <renderer/rhi_module.h>
|
||
#include <renderer/shader.h>
|
||
#include <sstream>
|
||
#include <utils/logger.h>
|
||
|
||
namespace extra2d {
|
||
|
||
Shader::Shader() = default;
|
||
|
||
Shader::~Shader() {
|
||
// RHIHandle 是轻量级句柄,不需要显式释放
|
||
// 实际的资源由 RHI 设备管理
|
||
pipeline_ = PipelineHandle();
|
||
handle_ = ShaderHandle();
|
||
}
|
||
|
||
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);
|
||
}
|
||
|
||
bool Shader::loadFromSource(const std::string &vsSource,
|
||
const std::string &fsSource) {
|
||
// 释放旧资源
|
||
pipeline_ = PipelineHandle();
|
||
handle_ = ShaderHandle();
|
||
|
||
// 获取 RHI 设备
|
||
auto *rhiModule = RHIModule::get();
|
||
if (!rhiModule) {
|
||
E2D_LOG_ERROR("RHIModule not available");
|
||
return false;
|
||
}
|
||
|
||
auto *device = rhiModule->getDevice();
|
||
if (!device) {
|
||
E2D_LOG_ERROR("RHIDevice not available");
|
||
return false;
|
||
}
|
||
|
||
// 处理源码(添加版本声明)
|
||
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");
|
||
return false;
|
||
}
|
||
|
||
// 获取着色器句柄
|
||
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();
|
||
return false;
|
||
}
|
||
|
||
// 获取管线句柄
|
||
pipeline_ = PipelineHandle(pipeline.release());
|
||
|
||
E2D_LOG_INFO("Shader created successfully");
|
||
return true;
|
||
}
|
||
|
||
void Shader::setUniformBlock(const std::string &name, uint32_t binding) {
|
||
// 存储 uniform block 绑定信息
|
||
uniformBlockBindings_[name] = binding;
|
||
|
||
// 注意:实际的 uniform block 绑定需要在渲染时通过 RHI 命令列表设置
|
||
// 这里仅存储绑定信息,供后续渲染使用
|
||
// 例如:commandList->setUniformBlock(binding, buffer);
|
||
}
|
||
|
||
uint32_t Shader::getUniformBlockBinding(const std::string &name) const {
|
||
auto it = uniformBlockBindings_.find(name);
|
||
if (it != uniformBlockBindings_.end()) {
|
||
return it->second;
|
||
}
|
||
return UINT32_MAX; // 未找到
|
||
}
|
||
|
||
std::string Shader::addVersionIfNeeded(const std::string &source,
|
||
bool isVertex) {
|
||
// 如果已经包含版本声明,直接返回
|
||
if (source.find("#version") != std::string::npos) {
|
||
return source;
|
||
}
|
||
|
||
// 添加 OpenGL ES 3.2 版本声明
|
||
std::string result = "#version 320 es\n";
|
||
|
||
// 片段着色器需要添加精度声明
|
||
if (!isVertex) {
|
||
result += "precision mediump float;\n";
|
||
}
|
||
|
||
result += source;
|
||
return result;
|
||
}
|
||
|
||
} // namespace extra2d
|