Files
zoom/src/Renderer.cpp

130 lines
3.8 KiB
C++

// src/Renderer.cpp
#include "Renderer.h"
#include <glad.h>
#include <iostream>
#include <chrono>
Renderer::Renderer() = default;
void Renderer::Initialize() {
// Nothing specific for now; ensure GLAD is loaded before this call
glEnable(GL_DEPTH_TEST);
glDepthFunc(GL_LESS);
glEnable(GL_CULL_FACE);
glCullFace(GL_BACK);
}
void Renderer::Shutdown() {
// Cleanup if needed
}
void Renderer::BeginFrame() {
stats_.draw_calls = 0;
stats_.vertices_rendered = 0;
stats_.triangles_rendered = 0;
frame_start_time_ = GetTime();
}
void Renderer::EndFrame() {
float frame_end = GetTime();
stats_.frame_time = frame_end - frame_start_time_;
}
void Renderer::Clear(const glm::vec4& color) {
glClearColor(color.r, color.g, color.b, color.a);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
}
void Renderer::SetViewport(int x, int y, int width, int height) {
viewport_size_ = { width, height };
glViewport(x, y, width, height);
}
void Renderer::SetCullFace(CullFace c) {
if (c == CullFace::None) glDisable(GL_CULL_FACE);
else {
glEnable(GL_CULL_FACE);
glCullFace(static_cast<GLenum>(c));
}
current_cull_face_ = c;
}
void Renderer::SetBlendMode(BlendMode mode) {
if (mode == BlendMode::None) {
glDisable(GL_BLEND);
} else {
glEnable(GL_BLEND);
switch (mode) {
case BlendMode::Alpha: glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); break;
case BlendMode::Additive: glBlendFunc(GL_SRC_ALPHA, GL_ONE); break;
case BlendMode::Multiply: glBlendFunc(GL_DST_COLOR, GL_ZERO); break;
default: break;
}
}
current_blend_mode_ = mode;
}
void Renderer::SetDepthTest(DepthTest dt) {
if (dt == DepthTest::None) glDisable(GL_DEPTH_TEST);
else {
glEnable(GL_DEPTH_TEST);
GLenum func = GL_LESS;
switch (dt) {
case DepthTest::Less: func = GL_LESS; break;
case DepthTest::LessEqual: func = GL_LEQUAL; break;
case DepthTest::Greater: func = GL_GREATER; break;
case DepthTest::GreaterEqual:func = GL_GEQUAL; break;
case DepthTest::Equal: func = GL_EQUAL; break;
case DepthTest::NotEqual: func = GL_NOTEQUAL; break;
case DepthTest::Always: func = GL_ALWAYS; break;
case DepthTest::Never: func = GL_NEVER; break;
default: break;
}
glDepthFunc(func);
}
current_depth_test_ = dt;
}
void Renderer::SetWireframe(bool enable) {
glPolygonMode(GL_FRONT_AND_BACK, enable ? GL_LINE : GL_FILL);
wireframe_enabled_ = enable;
}
void Renderer::PrintRenderInfo() const {
std::cout << "OpenGL Version: " << GetOpenGLVersion() << "\n";
std::cout << "Viewport: " << viewport_size_.x << "x" << viewport_size_.y << "\n";
std::cout << "Draw Calls: " << stats_.draw_calls << "\n";
std::cout << "Vertices: " << stats_.vertices_rendered << "\n";
std::cout << "Triangles: " << stats_.triangles_rendered << "\n";
}
void Renderer::ResetStats() {
stats_ = RenderStats{};
}
std::string Renderer::GetOpenGLVersion() {
return reinterpret_cast<const char*>(glGetString(GL_VERSION));
}
std::string Renderer::GetGPUInfo() {
return reinterpret_cast<const char*>(glGetString(GL_RENDERER));
}
bool Renderer::CheckOpenGLError(const std::string& op) {
GLenum err;
bool hasError = false;
while ((err = glGetError()) != GL_NO_ERROR) {
std::cerr << "OpenGL Error";
if (!op.empty()) std::cerr << " in " << op;
std::cerr << ": " << err << "\n";
hasError = true;
}
return !hasError;
}
float Renderer::GetTime() const {
using clock = std::chrono::high_resolution_clock;
return std::chrono::duration<float>(clock::now().time_since_epoch()).count();
}