Extra2D/src/renderer/shader.cpp

149 lines
4.2 KiB
C++
Raw Normal View History

#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