Hazel Game Engine Rendering System Overview

The engine's rendering system initializes through the Application class constructor chain, starting with platform-agnostic setup followed by API-specific configuration:

Renderer::Initialize();
// Implementation details
void Renderer::Initialize() {
    RenderCommand::Initialize();
    Renderer2D::Initialize();
}

API-specific rendering parameter are set during initialization:

void OpenGLRendererAPI::Initialize() {
    glEnable(GL_BLEND);
    glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
    glEnable(GL_DEPTH_TEST);
}

The 2D renderer prepares geometry buffers and default resources:

struct Renderer2DContext {
    Ref<VertexArray> QuadGeometry;
    Ref<Shader> BaseShader;
    Ref<Texture2D> DefaultWhiteTexture;
};

void Renderer2D::Initialize() {
    auto context = new Renderer2DContext();
    
    // Vertex array configuration
    context->QuadGeometry = VertexArray::Create();
    float vertexData[5 * 4] = {
        // Position      TexCoords
        -0.5f, -0.5f, 0.0f, 0.0f, 0.0f,
         0.5f, -0.5f, 0.0f, 1.0f, 0.0f,
         0.5f,  0.5f, 0.0f, 1.0f, 1.0f,
        -0.5f,  0.5f, 0.0f, 0.0f, 1.0f
    };
    
    auto vertexBuffer = VertexBuffer::Create(vertexData, sizeof(vertexData));
    vertexBuffer->SetLayout({
        { ShaderDataType::Float3, "a_Position" },
        { ShaderDataType::Float2, "a_TexCoord" }
    });
    
    context->QuadGeometry->AddVertexBuffer(vertexBuffer);
    
    // Index buffer configuration
    uint32_t indices[6] = { 0, 1, 2, 2, 3, 0 };
    auto indexBuffer = IndexBuffer::Create(indices, 6);
    context->QuadGeometry->SetIndexBuffer(indexBuffer);
    
    // Default texture creation
    context->DefaultWhiteTexture = Texture2D::Create(1, 1);
    uint32_t defaultData = 0xffffffff;
    context->DefaultWhiteTexture->SetData(&defaultData, sizeof(uint32_t));
    
    // Shader initialization
    context->BaseShader = Shader::Create("assets/shaders/Texture.glsl");
    context->BaseShader->Bind();
    context->BaseShader->SetInt("u_Texture", 0);
}

Texture loading and application follows a standardized workflow:

// Texture creation
m_Texture = Texture2D::Create("assets/textures/Example.png");

// Rendering call
Renderer2D::DrawQuad(position, scale, rotation, m_Texture, color);

OpenGL Texture Implementation

OpenGLTexture2D::OpenGLTexture2D(const std::string& path) {
    int width, height, channels;
    stbi_set_flip_vertically_on_load(1);
    stbi_uc* data = stbi_load(path.c_str(), &width, &height, &channels, 0);
    
    // Texture format configuration
    GLenum internalFormat = 0, dataFormat = 0;
    if (channels == 4) {
        internalFormat = GL_RGBA8;
        dataFormat = GL_RGBA;
    } else if (channels == 3) {
        internalFormat = GL_RGB8;
        dataFormat = GL_RGB;
    }
    
    // Texture creation and parameter setup
    glCreateTextures(GL_TEXTURE_2D, 1, &m_RendererID);
    glTextureStorage2D(m_RendererID, 1, internalFormat, width, height);
    
    glTextureParameteri(m_RendererID, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
    glTextureParameteri(m_RendererID, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
    glTextureParameteri(m_RendererID, GL_TEXTURE_WRAP_S, GL_REPEAT);
    glTextureParameteri(m_RendererID, GL_TEXTURE_WRAP_T, GL_REPEAT);
    
    glTextureSubImage2D(m_RendererID, 0, 0, 0, width, height, dataFormat, GL_UNSIGNED_BYTE, data);
    stbi_image_free(data);
}

Draw commands execute through a standardized sequence:

void Renderer2D::DrawQuad(const glm::vec3& position, const glm::vec2& size, float rotation, const Ref<Texture2D>& texture, const glm::vec4& color) {
    auto context = Renderer2D::GetContext();
    context->BaseShader->SetFloat4("u_Color", color);
    texture->Bind();
    
    // Transformation matrix construction
    glm::mat4 transform = 
        glm::translate(glm::mat4(1.0f), position) *
        glm::rotate(glm::mat4(1.0f), rotation, glm::vec3(0.0f, 0.0f, 1.0f)) *
        glm::scale(glm::mat4(1.0f), glm::vec3(size.x, size.y, 1.0f));
    
    context->BaseShader->SetMat4("u_Transform", transform);
    context->QuadGeometry->Bind();
    RenderCommand::DrawIndexed(context->QuadGeometry);
}

Tags: OpenGL Shader Programming 2D Rendering Texture Mapping Game Engine Architecture

Posted on Thu, 08 Oct 2026 16:59:18 +0000 by countdrac