#include #include #include #include #include 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