// GLESRenderer.cpp #include "EngineFrame/Render/GLESRenderer.h" #include #include #include #include #include #include // 顶点着色器源码 const char *vertexShaderSource = R"( #version 300 es precision mediump float; layout(location = 0) in vec2 aPosition; layout(location = 1) in vec2 aTexCoord; out vec2 vTexCoord; uniform mat4 uProjection; uniform mat4 uModel; void main() { gl_Position = uProjection * uModel * vec4(aPosition, 0.0, 1.0); vTexCoord = aTexCoord; } )"; // 片段着色器源码 const char *fragmentShaderSource = R"( #version 300 es precision mediump float; in vec2 vTexCoord; out vec4 FragColor; uniform sampler2D uTexture; uniform vec4 uColor; void main() { FragColor = texture(uTexture, vTexCoord) * uColor; } )"; GLESRenderer::GLESRenderer(SDL_Window *window) : m_window(window), m_glContext(nullptr) { } GLESRenderer::~GLESRenderer() { if (m_glContext) { SDL_GL_DeleteContext(m_glContext); } glDeleteProgram(m_shaderProgram); glDeleteShader(m_vertexShader); glDeleteShader(m_fragmentShader); glDeleteBuffers(1, &m_vbo); glDeleteVertexArrays(1, &m_vao); } bool GLESRenderer::Initialize() { // 设置 OpenGL ES 属性 SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_ES); SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 3); SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 0); // 创建 OpenGL ES 上下文 m_glContext = SDL_GL_CreateContext(m_window); if (!m_glContext) { std::cerr << "Failed to create OpenGL ES context: " << SDL_GetError() << std::endl; return false; } // 初始化 GLEW (如果需要) 或者直接使用 OpenGL ES 函数 // 创建着色器程序 if (!CreateShaderProgram()) { std::cerr << "Failed to create shader program" << std::endl; return false; } // 设置视口 int w, h; SDL_GetWindowSize(m_window, &w, &h); glViewport(0, 0, w, h); // 设置正交投影 SetOrthographicProjection(w, h); // 启用混合 glEnable(GL_BLEND); glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); // 创建VAO和VBO glGenVertexArrays(1, &m_vao); glGenBuffers(1, &m_vbo); glBindVertexArray(m_vao); glBindBuffer(GL_ARRAY_BUFFER, m_vbo); // 设置顶点属性指针 glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 4 * sizeof(float), (void *)0); glEnableVertexAttribArray(0); glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 4 * sizeof(float), (void *)(2 * sizeof(float))); glEnableVertexAttribArray(1); glBindBuffer(GL_ARRAY_BUFFER, 0); glBindVertexArray(0); return true; } void GLESRenderer::Clear() { glClearColor(0.0f, 0.0f, 0.0f, 1.0f); glClear(GL_COLOR_BUFFER_BIT); // 清空批处理 m_renderBatch.clear(); } void GLESRenderer::Present() { // 按Z顺序排序 std::stable_sort(m_renderBatch.begin(), m_renderBatch.end(), [](const RenderCommand &a, const RenderCommand &b) { return a.z_order < b.z_order; }); // 使用着色器程序 glUseProgram(m_shaderProgram); // 设置投影矩阵 GLint projLoc = glGetUniformLocation(m_shaderProgram, "uProjection"); // 这里需要设置正交投影矩阵 // 渲染批处理中的所有命令 for (const auto &cmd : m_renderBatch) { // 绑定纹理 glActiveTexture(GL_TEXTURE0); glBindTexture(GL_TEXTURE_2D, cmd.texture); glUniform1i(glGetUniformLocation(m_shaderProgram, "uTexture"), 0); // 计算模型矩阵(位置、旋转、缩放) glm::mat4 model = glm::mat4(1.0f); model = glm::translate(model, glm::vec3(cmd.dstrect.x, cmd.dstrect.y, 0.0f)); if (cmd.angle != 0) { // 应用旋转 model = glm::translate(model, glm::vec3(cmd.center.x, cmd.center.y, 0.0f)); model = glm::rotate(model, glm::radians(static_cast(cmd.angle)), glm::vec3(0.0f, 0.0f, 1.0f)); model = glm::translate(model, glm::vec3(-cmd.center.x, -cmd.center.y, 0.0f)); } model = glm::scale(model, glm::vec3(cmd.dstrect.w, cmd.dstrect.h, 1.0f)); // 设置模型矩阵 GLint modelLoc = glGetUniformLocation(m_shaderProgram, "uModel"); glUniformMatrix4fv(modelLoc, 1, GL_FALSE, glm::value_ptr(model)); // 绘制矩形 glBindVertexArray(m_vao); glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); glBindVertexArray(0); } // 交换缓冲区 SDL_GL_SwapWindow(m_window); } void GLESRenderer::RenderCopy(GLuint texture, const SDL_Rect *srcrect, const SDL_Rect *dstrect) { RenderCommand cmd; cmd.texture = texture; if (dstrect) cmd.dstrect = *dstrect; cmd.angle = 0; cmd.flip = SDL_FLIP_NONE; cmd.z_order = 0; // 需要从Sprite获取Z顺序 m_renderBatch.push_back(cmd); } void GLESRenderer::RenderCopyEx(GLuint texture, const SDL_Rect *srcrect, const SDL_Rect *dstrect, double angle, const SDL_Point *center, SDL_RendererFlip flip) { RenderCommand cmd; cmd.texture = texture; if (dstrect) cmd.dstrect = *dstrect; cmd.angle = angle; if (center) cmd.center = *center; cmd.flip = flip; cmd.z_order = 0; // 需要从Sprite获取Z顺序 m_renderBatch.push_back(cmd); } bool GLESRenderer::CompileShader(const char *source, GLenum type, GLuint &shader) { shader = glCreateShader(type); glShaderSource(shader, 1, &source, NULL); glCompileShader(shader); GLint success; glGetShaderiv(shader, GL_COMPILE_STATUS, &success); if (!success) { GLchar infoLog[512]; glGetShaderInfoLog(shader, 512, NULL, infoLog); std::cerr << "Shader compilation failed: " << infoLog << std::endl; return false; } return true; } bool GLESRenderer::LinkProgram(GLuint program) { glLinkProgram(program); GLint success; glGetProgramiv(program, GL_LINK_STATUS, &success); if (!success) { GLchar infoLog[512]; glGetProgramInfoLog(program, 512, NULL, infoLog); std::cerr << "Program linking failed: " << infoLog << std::endl; return false; } return true; } bool GLESRenderer::CreateShaderProgram() { if (!CompileShader(vertexShaderSource, GL_VERTEX_SHADER, m_vertexShader)) { return false; } if (!CompileShader(fragmentShaderSource, GL_FRAGMENT_SHADER, m_fragmentShader)) { return false; } m_shaderProgram = glCreateProgram(); glAttachShader(m_shaderProgram, m_vertexShader); glAttachShader(m_shaderProgram, m_fragmentShader); if (!LinkProgram(m_shaderProgram)) { return false; } glDeleteShader(m_vertexShader); glDeleteShader(m_fragmentShader); return true; } void GLESRenderer::SetOrthographicProjection(int width, int height) { // 设置正交投影矩阵 glm::mat4 projection = glm::ortho(0.0f, static_cast(width), static_cast(height), 0.0f, -1.0f, 1.0f); glUseProgram(m_shaderProgram); GLint projLoc = glGetUniformLocation(m_shaderProgram, "uProjection"); glUniformMatrix4fv(projLoc, 1, GL_FALSE, glm::value_ptr(projection)); }