Initial commit

This commit is contained in:
2026-09-27 01:33:35 +02:00
commit 3ac329a21b
1185 changed files with 543634 additions and 0 deletions

166
src/renderer.cpp Normal file
View File

@@ -0,0 +1,166 @@
#include <algorithm>
#include <string>
#include <glad/gl.h>
#include "renderer.hpp"
namespace Fan
{
void Renderer::init()
{
glEnable(GL_DEPTH_TEST);
glEnable(GL_CULL_FACE);
glCullFace(GL_BACK);
glFrontFace(GL_CCW);
}
void Renderer::set_viewport(int x, int y, int width, int height)
{
glViewport(x, y, width, height);
}
void Renderer::set_clear_color(const glm::vec4& color)
{
glClearColor(color.r, color.g, color.b, color.a);
}
void Renderer::set_wireframe(bool enabled)
{
glPolygonMode(GL_FRONT_AND_BACK, enabled ? GL_LINE : GL_FILL);
}
void Renderer::clear()
{
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
}
void Renderer::draw_scene(const Scene& scene, const Camera& camera,
int screen_width, int screen_height)
{
glm::mat4 view_projection = camera.get_view_projection_matrix(screen_width, screen_height);
GLuint last_shader_id = 0;
// TODO: Order entities by material to minimize uniform uploads
for (const Entity& entity : scene.get_entities()) {
if (!entity.mesh || !entity.material || !entity.material->shader) { continue; }
Rc<Shader> shader = entity.material->shader;
GLuint current_shader_id = shader->get_id();
// Only upload scene uniforms if the shader changed
if (current_shader_id != last_shader_id) {
shader->use();
// Upload camera uniforms
shader->set_mat4("u_view_projection", view_projection);
shader->set_vec3("u_view_pos", camera.position);
// Upload lighting uniforms
const LightEnvironment& env = scene.light_environment;
shader->set_vec3("u_directional_light.direction", env.directional_light.direction);
shader->set_vec3("u_directional_light.ambient", env.directional_light.ambient);
shader->set_vec3("u_directional_light.diffuse", env.directional_light.diffuse);
shader->set_vec3("u_directional_light.specular", env.directional_light.specular);
// Note: current limit is set to MAX_POINT_LIGHT_COUNT (8)
// TODO: Define this limits in a common header file
int point_count = std::min(static_cast<int>(env.point_lights.size()), 8);
shader->set_int("u_point_light_count", point_count);
for (int i = 0; i < point_count; ++i) {
std::string prefix = "u_point_lights[" + std::to_string(i) + "].";
shader->set_vec3(prefix + "position", env.point_lights[i].position);
shader->set_float(prefix + "constant", env.point_lights[i].constant);
shader->set_float(prefix + "linear", env.point_lights[i].linear);
shader->set_float(prefix + "quadratic", env.point_lights[i].quadratic);
shader->set_vec3(prefix + "ambient", env.point_lights[i].ambient);
shader->set_vec3(prefix + "diffuse", env.point_lights[i].diffuse);
shader->set_vec3(prefix + "specular", env.point_lights[i].specular);
}
// Note: current limit is set to MAX_SPOT_LIGHT_COUNT (8)
// TODO: Define this limits in a common header file
int spot_count = std::min(static_cast<int>(env.spot_lights.size()), 8);
shader->set_int("u_spot_light_count", spot_count);
for (int i = 0; i < spot_count; ++i) {
std::string prefix = "u_spot_lights[" + std::to_string(i) + "].";
shader->set_vec3(prefix + "position", env.spot_lights[i].position);
shader->set_vec3(prefix + "direction", env.spot_lights[i].direction);
shader->set_float(prefix + "cut_off", env.spot_lights[i].cut_off);
shader->set_float(prefix + "outer_cut_off", env.spot_lights[i].outer_cut_off);
shader->set_float(prefix + "constant", env.spot_lights[i].constant);
shader->set_float(prefix + "linear", env.spot_lights[i].linear);
shader->set_float(prefix + "quadratic", env.spot_lights[i].quadratic);
shader->set_vec3(prefix + "ambient", env.spot_lights[i].ambient);
shader->set_vec3(prefix + "diffuse", env.spot_lights[i].diffuse);
shader->set_vec3(prefix + "specular", env.spot_lights[i].specular);
}
last_shader_id = current_shader_id;
}
// Bind the specific textures and the shininess float
entity.material->bind();
// Upload the model matrix to transform the specific object
shader->set_mat4("u_model", entity.transform.get_model_matrix());
// Dispatch the draw call
entity.mesh->draw();
}
}
void Renderer::draw_debug_wireframes(const Scene& scene, const Camera& camera,
int screen_width, int screen_height,
const Rc<Shader>& debug_shader,
const Rc<Mesh>& default_mesh)
{
debug_shader->use();
debug_shader->set_mat4("u_view_projection", camera.get_view_projection_matrix(screen_width, screen_height));
// Force wireframe mode and disable depth testing so we can see through objects
set_wireframe(true);
glDisable(GL_DEPTH_TEST);
// Draw all standard entities (green)
debug_shader->set_vec3("u_color", glm::vec3(0.0f, 0.7f, 0.0f));
for (const Entity& entity : scene.get_entities()) {
// If an entity has no mesh, use the default debug mesh
auto mesh = entity.mesh ? entity.mesh : default_mesh;
debug_shader->set_mat4("u_model", entity.transform.get_model_matrix());
mesh->draw();
}
// Draw point lights (yellow)
debug_shader->set_vec3("u_color", glm::vec3(0.7f, 0.7f, 0.0f));
for (const PointLight& light : scene.light_environment.point_lights) {
glm::mat4 model = glm::translate(glm::mat4(1.0f), light.position);
model = glm::scale(model, glm::vec3(0.2f));
debug_shader->set_mat4("u_model", model);
default_mesh->draw();
}
// Draw spot lights (cyan)
debug_shader->set_vec3("u_color", glm::vec3(0.0f, 0.7f, 0.7f));
for (const SpotLight& light : scene.light_environment.spot_lights) {
glm::mat4 model = glm::translate(glm::mat4(1.0f), light.position);
model = glm::scale(model, glm::vec3(0.2f));
debug_shader->set_mat4("u_model", model);
default_mesh->draw();
}
// Restore state
glEnable(GL_DEPTH_TEST);
set_wireframe(false);
}
} // namespace Fan