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);
}