Bug fixes: - Release static GL objects (UBOs, logo texture) before the context is destroyed via new Renderer::shutdown() - Fix max point/spot light warnings never firing - Show frame time in ms instead of seconds - Size the viewport framebuffer in physical pixels on HiDPI displays - Stop double-flipping OBJ UVs; add flip_uvs option to load_obj for models with a top-left UV origin (backpack) Build: - Track header dependencies (-MMD -MP) so header edits trigger rebuilds - Create build/ automatically Error handling: - Add gldebug module: KHR_debug output routed to the logger in debug builds, object labels, and error/status string helpers - Validate inputs and check GL errors when creating textures, meshes, framebuffers, uniform buffers and shaders; FrameBuffer::resize() and Renderer::init() now report failure Resources: - Add ResourceCache: shares textures and shaders by path and substitutes fallbacks (magenta checkerboard texture, unlit shader, cube mesh) for assets that fail to load; specular maps are optional - load_obj never fails, a broken model becomes a fallback cube - Renderer draws submeshes with broken materials using the fallback material instead of skipping them - Add Texture::create_from_pixels, Shader::create_from_source and Mesh::create_cube - Cache uniform locations in Shader, looked up with string_view so hits don't allocate; missing uniforms warn once Performance: - Add CpuTimer and GpuTimer (GL_TIME_ELAPSED, non-blocking readback) and a Performance section in the UI with averaged overlay numbers - Sample material textures once per fragment and apply material colors after accumulating lights - Pass camera position through CameraBlock instead of inverting the view matrix per fragment - Compute the normal matrix on the CPU instead of per vertex - Skip spot light work for fragments outside the outer cone
72 lines
1.9 KiB
C++
72 lines
1.9 KiB
C++
#ifndef FAN_MESH_HPP_
|
|
#define FAN_MESH_HPP_
|
|
|
|
#include <vector>
|
|
#include <glad/gl.h>
|
|
|
|
#include "vertex.hpp"
|
|
#include "material.hpp"
|
|
#include "utils.hpp"
|
|
|
|
namespace Fan
|
|
{
|
|
|
|
class Mesh
|
|
{
|
|
public:
|
|
// A range drawn with one material. Offset and count are in indices, or in
|
|
// vertices if the mesh has no index buffer
|
|
struct SubMesh
|
|
{
|
|
GLuint index_offset{};
|
|
GLuint index_count{};
|
|
Rc<Material> material{};
|
|
};
|
|
|
|
// Without indices the vertices are drawn in order. Without submeshes a single
|
|
// one with no material covers the whole mesh
|
|
static Rc<Mesh> create(const std::vector<Vertex>& vertices,
|
|
const std::vector<GLuint>& indices = {},
|
|
const std::vector<SubMesh>& submeshes = {});
|
|
// Unit cube centered at the origin, with normals and texture coordinates
|
|
static Rc<Mesh> create_cube();
|
|
Mesh(const std::vector<Vertex>& vertices,
|
|
const std::vector<GLuint>& indices,
|
|
const std::vector<SubMesh>& submeshes,
|
|
bool has_indices,
|
|
GLuint VBO, GLuint VAO, GLuint EBO)
|
|
: m_vertices(vertices)
|
|
, m_indices(indices)
|
|
, m_submeshes(submeshes)
|
|
, m_has_indices(has_indices)
|
|
, m_VBO(VBO)
|
|
, m_VAO(VAO)
|
|
, m_EBO(EBO) {}
|
|
|
|
~Mesh();
|
|
Mesh(const Mesh&) = delete;
|
|
Mesh& operator=(const Mesh&) = delete;
|
|
Mesh(Mesh&& other) noexcept;
|
|
Mesh& operator=(Mesh&& other) noexcept;
|
|
|
|
const std::vector<SubMesh>& get_submeshes() const;
|
|
|
|
// Geometry only: the caller binds the shader and material first
|
|
void draw() const;
|
|
void draw_submesh(GLuint index_offset, GLuint index_count) const;
|
|
|
|
private:
|
|
std::vector<Vertex> m_vertices{};
|
|
std::vector<GLuint> m_indices{};
|
|
std::vector<SubMesh> m_submeshes{};
|
|
bool m_has_indices{};
|
|
|
|
GLuint m_VBO{};
|
|
GLuint m_VAO{};
|
|
GLuint m_EBO{};
|
|
};
|
|
|
|
} // namespace Fan
|
|
|
|
#endif // FAN_MESH_HPP_
|