130 lines
3.8 KiB
C++
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();
|
|
}
|