Initial commit
This commit is contained in:
166
src/renderer.cpp
Normal file
166
src/renderer.cpp
Normal 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
|
||||
Reference in New Issue
Block a user