Compare commits

..

No commits in common. "f7e08825976c63af7437d135701fd5ae5cf7b143" and "1a928159e55a8a8f2b1135bfddb0d44040be8cc4" have entirely different histories.

11 changed files with 35 additions and 539 deletions

View File

@ -99,7 +99,6 @@ add_library(Core STATIC
src/core/systems/Asset.h
src/core/systems/assets/Texture2D.cpp
src/core/systems/assets/Texture2D.h
src/core/systems/Shader.cpp
)
target_include_directories(Core PUBLIC src/core)

View File

@ -6,7 +6,6 @@
#include "systems/MACROS.h"
#include "systems/AssetManager.h"
#include "systems/assets/Texture2D.h"
namespace OX
{
@ -33,7 +32,9 @@ namespace OX
}
for (const auto &layer: m_layers) {
for (const auto &layer : m_layers) {
Logger::LogDebug("Initializing Layer: '%s'", layer->GetName().c_str());
layer->Init(*this);
}
@ -41,7 +42,6 @@ namespace OX
std::string fullTitle = layerTitle + " - " + m_name;
window.SetWindowTitle(fullTitle);
renderer.Init(800, 600);
Logger::LogOk("Core Initialization Complete.");
@ -49,6 +49,7 @@ namespace OX
}
void Core::Run()
{
m_running = true;
@ -79,18 +80,6 @@ namespace OX
{
OX_PROFILE_FUNCTION();
Camera2D cam(0, 800, 0, 600);
renderer.BeginScene(cam);
if (auto asset = AssetManager::Get("res://Assets/tile_001.png"); asset && asset->GetTypeName() == "texture2D") {
const auto tex = std::static_pointer_cast<Texture2D>(asset);
renderer.DrawSprite({tex->GetID(), {100, 100}, {64, 64}});
}
renderer.EndScene();
for (auto &layer: m_layers) {
layer->Draw(*this);

View File

@ -1,194 +1,9 @@
// File: src/Renderer.cpp
//
// Created by spenc on 5/21/2025.
//
#include "Renderer.h"
#include <glm/gtc/matrix_transform.hpp>
#include <iostream>
namespace OX
{
// ——— Camera2D implementation (unchanged) ———
Camera2D::Camera2D(float left, float right, float bottom, float top)
: _left(left), _right(right), _bottom(bottom), _top(top)
{
Recalculate();
}
namespace OX {
void Camera2D::SetPosition(const glm::vec2 &pos)
{
_position = pos;
Recalculate();
}
void Camera2D::SetZoom(float z)
{
_zoom = z;
Recalculate();
}
void Camera2D::Recalculate()
{
float halfW = (_right - _left) * 0.5f / _zoom;
float halfH = (_top - _bottom) * 0.5f / _zoom;
glm::mat4 proj = glm::ortho(-halfW, halfW, -halfH, halfH, -1.0f, 1.0f);
glm::mat4 view = glm::translate(glm::mat4(1.0f), glm::vec3(-_position, 0.0f));
_viewProj = proj * view;
}
const glm::mat4 &Camera2D::GetViewProjection() const { return _viewProj; }
// ——— Renderer ———
Renderer::~Renderer()
{
if (m_quadVAO)
glDeleteVertexArrays(1, &m_quadVAO);
if (m_quadVBO)
glDeleteBuffers(1, &m_quadVBO);
if (m_fbo)
glDeleteFramebuffers(1, &m_fbo);
if (m_colorTex) glDeleteTextures(1, &m_colorTex);
if (m_depthRBO)
glDeleteRenderbuffers(1, &m_depthRBO);
}
void Renderer::Init(int targetWidth, int targetHeight)
{
// create offscreen FBO & attachments
CreateFramebuffer(targetWidth, targetHeight);
// compile our sprite shader
static const char *vs = R"GLSL(
#version 330 core
layout(location = 0) in vec2 aPos;
layout(location = 1) in vec2 aUV;
uniform mat4 u_ViewProj;
uniform vec2 u_Offset;
uniform vec2 u_Scale;
out vec2 vUV;
void main(){
vUV = aUV;
vec2 pos = aPos * u_Scale + u_Offset;
gl_Position = u_ViewProj * vec4(pos,0,1);
}
)GLSL";
static const char *fs = R"GLSL(
#version 330 core
in vec2 vUV;
out vec4 FragColor;
uniform sampler2D u_Texture;
void main(){
FragColor = texture(u_Texture, vUV);
}
)GLSL";
m_shader.LoadFromSource(vs, fs);
CreateQuad();
}
void Renderer::CreateFramebuffer(int width, int height)
{
size = {width, height};
// cleanup old
if (m_fbo)
glDeleteFramebuffers(1, &m_fbo);
if (m_colorTex) glDeleteTextures(1, &m_colorTex);
if (m_depthRBO)
glDeleteRenderbuffers(1, &m_depthRBO);
// color texture
glGenTextures(1, &m_colorTex);
glBindTexture(GL_TEXTURE_2D, m_colorTex);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, width, height,
0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
// depth renderbuffer
glGenRenderbuffers(1, &m_depthRBO);
glBindRenderbuffer(GL_RENDERBUFFER, m_depthRBO);
glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH24_STENCIL8, width, height);
// framebuffer
glGenFramebuffers(1, &m_fbo);
glBindFramebuffer(GL_FRAMEBUFFER, m_fbo);
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
GL_TEXTURE_2D, m_colorTex, 0);
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT,
GL_RENDERBUFFER, m_depthRBO);
if (glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE)
std::cerr << "[Renderer] Framebuffer not complete!\n";
// unbind
glBindFramebuffer(GL_FRAMEBUFFER, 0);
}
void Renderer::ResizeTarget(int width, int height)
{
OX_PROFILE_FUNCTION();
if (size == Vec2i{width, height}) {
return;
}
CreateFramebuffer(width, height);
}
void Renderer::BeginScene(const Camera2D &camera)
{
OX_PROFILE_FUNCTION();
// bind offscreen
glBindFramebuffer(GL_FRAMEBUFFER, m_fbo);
// clear
glViewport(0, 0, size.x, size.y);
glClearColor(0.1f, 0.1f, 0.1f, 1);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
// setup shader & camera
m_viewProj = camera.GetViewProjection();
m_shader.Use();
m_shader.SetMat4("u_ViewProj", m_viewProj);
m_shader.SetInt("u_Texture", 0);
}
void Renderer::DrawSprite(const Sprite &s)
{
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, s.textureID);
m_shader.SetVec2("u_Offset", s.position);
m_shader.SetVec2("u_Scale", s.size);
glBindVertexArray(m_quadVAO);
glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, nullptr);
}
void Renderer::EndScene()
{
// unbind FBO → subsequent draws go to default framebuffer
glBindFramebuffer(GL_FRAMEBUFFER, 0);
}
void Renderer::CreateQuad()
{
float verts[] = {
-0.5f, -0.5f, 0, 0,
0.5f, -0.5f, 1, 0,
0.5f, 0.5f, 1, 1,
-0.5f, 0.5f, 0, 1
};
unsigned int idx[] = {0, 1, 2, 2, 3, 0};
glGenVertexArrays(1, &m_quadVAO);
glGenBuffers(1, &m_quadVBO);
glBindVertexArray(m_quadVAO);
glBindBuffer(GL_ARRAY_BUFFER, m_quadVBO);
glBufferData(GL_ARRAY_BUFFER, sizeof(verts), verts, GL_STATIC_DRAW);
glEnableVertexAttribArray(0);
glVertexAttribPointer(0, 2,GL_FLOAT,GL_FALSE, 4 * sizeof(float), (void *) 0);
glEnableVertexAttribArray(1);
glVertexAttribPointer(1, 2,GL_FLOAT,GL_FALSE, 4 * sizeof(float), (void *) (2 * sizeof(float)));
glBindVertexArray(0);
}
} // namespace OX
} // OX

View File

@ -1,74 +1,26 @@
// File: src/Renderer.h
#pragma once
//
// Created by spenc on 5/21/2025.
//
#ifndef RENDERER_H
#define RENDERER_H
#include "glfw/glfw3.h"
#include "glm/glm.hpp"
#include "systems/Shader.h"
#include <gl/glew.h>
#include "types/vec2.h"
namespace OX {
struct Sprite {
GLuint textureID;
glm::vec2 position;
glm::vec2 size;
};
class Renderer {
public:
Renderer() = default;
~Renderer() = default;
class Camera2D {
public:
Camera2D(float left, float right, float bottom, float top);
void SetPosition(const glm::vec2& pos);
void SetZoom(float zoom);
const glm::mat4& GetViewProjection() const;
[[nodiscard]] GLuint GetRenderTarget() const {return m_renderTarget; }
private:
void Recalculate();
glm::vec2 _position{0.0f};
float _zoom{1.0f};
float _left, _right, _bottom, _top;
glm::mat4 _viewProj{1.0f};
};
private:
GLuint m_renderTarget;
};
class Renderer {
public:
Renderer() = default;
~Renderer();
} // OX
/// Must call once after OpenGL context + GLEW init.
/// Provide the desired offscreen target size here.
void Init(int targetWidth, int targetHeight);
/// Call at start of each scene (binds FBO and sets camera).
void BeginScene(const Camera2D& camera);
/// Draw one sprite into the current scene.
void DrawSprite(const Sprite& sprite);
/// Finish rendering, unbinds FBO.
void EndScene();
/// Access the colorattachment texture ID that holds the rendered scene.
GLuint GetRenderTexture() const { return m_colorTex; }
/// If window resized, call this to resize the offscreen target.
void ResizeTarget(int width, int height);
private:
// offscreen
Vec2i size;
GLuint m_fbo = 0;
GLuint m_colorTex = 0;
GLuint m_depthRBO = 0;
// quad geometry
GLuint m_quadVAO = 0, m_quadVBO = 0;
// shader
Shader m_shader;
glm::mat4 m_viewProj{1.0f};
// helpers
void CreateQuad();
void CreateFramebuffer(int width, int height);
};
} // namespace OX
#endif //RENDERER_H

View File

@ -18,7 +18,6 @@ namespace OX
// Map from actual file path to virtual ID
std::unordered_map<std::string, std::string> AssetManager::s_PathToID;
std::mutex AssetManager::s_AssetMutex;
std::mutex AssetManager::s_TreeMutex;
std::shared_ptr<ResourceTreeNode> AssetManager::s_FileTree = std::make_shared<ResourceTreeNode>();
@ -97,7 +96,7 @@ namespace OX
{
std::lock_guard<std::mutex> lock(s_AssetMutex);
// now fill in the real metadata
s_MetadataMap[resPath] = {type, path.string()};
s_MetadataMap[resPath] = { type, path.string() };
}
std::lock_guard<std::mutex> qlock(s_QueueMutex);
s_TextureQueue.push({resPath, w, h, ch, data});
@ -139,6 +138,7 @@ namespace OX
// Also map original file path to this ID
auto meta = s_MetadataMap[pending.id];
s_PathToID[meta.absolutePath] = pending.id;
}
}
@ -224,7 +224,6 @@ namespace OX
pos = next + 1;
}
if (pos < resPath.size()) parts.push_back(resPath.substr(pos));
std::lock_guard<std::mutex> lock(AssetManager::s_TreeMutex);
auto current = s_FileTree;
for (size_t i = 1; i < parts.size(); ++i) {

View File

@ -37,9 +37,6 @@ namespace OX {
static std::shared_ptr<ResourceTreeNode> GetFileTree();
static void SaveAssetPack(const std::string& outputPath);
static std::mutex s_TreeMutex;
private:
struct AssetMetadata {
std::string type;
@ -72,6 +69,6 @@ namespace OX {
// texture upload queue
static std::queue<PendingTexture> s_TextureQueue;
static std::mutex s_QueueMutex;
static std::mutex s_QueueMutex;
};
}

View File

@ -1,180 +0,0 @@
#include "Shader.h"
#include <fstream>
#include <sstream>
#include <iostream>
#include "systems/Logger.h"
namespace OX
{
Shader::Shader(const std::string &vertexPath, const std::string &fragmentPath)
{
LoadFromFiles(vertexPath, fragmentPath);
}
bool Shader::LoadFromFiles(const std::string &vertexPath, const std::string &fragmentPath)
{
m_vertexPath = vertexPath;
m_fragmentPath = fragmentPath;
std::string vertexSrc = ReadFile(vertexPath);
std::string fragmentSrc = ReadFile(fragmentPath);
try {
m_vertTimestamp = std::filesystem::last_write_time(vertexPath);
m_fragTimestamp = std::filesystem::last_write_time(fragmentPath);
} catch (...) {
std::cerr << "[Shader] Warning: Could not get file timestamps.\n";
}
return LoadFromSource(vertexSrc, fragmentSrc);
}
bool Shader::LoadFromSource(const std::string &vertexSrc, const std::string &fragmentSrc)
{
GLuint vertexShader = CompileShader(GL_VERTEX_SHADER, vertexSrc);
GLuint fragmentShader = CompileShader(GL_FRAGMENT_SHADER, fragmentSrc);
if (!vertexShader || !fragmentShader) return false;
GLuint program = glCreateProgram();
glAttachShader(program, vertexShader);
glAttachShader(program, fragmentShader);
glLinkProgram(program);
GLint success;
glGetProgramiv(program, GL_LINK_STATUS, &success);
if (!success) {
char info[512];
glGetProgramInfoLog(program, 512, nullptr, info);
std::cerr << "[Shader] Linking failed:\n" << info << '\n';
glDeleteProgram(program);
return false;
}
if (m_programID)
glDeleteProgram(m_programID);
m_programID = program;
m_uniformCache.clear();
glDeleteShader(vertexShader);
glDeleteShader(fragmentShader);
Logger::LogOk("Shader Loaded (%s,%s)", m_vertexPath.c_str(), m_fragmentPath.c_str());
return true;
}
void Shader::Reload()
{
OX_PROFILE_FUNCTION();
LoadFromFiles(m_vertexPath, m_fragmentPath);
}
void Shader::Use() const
{
glUseProgram(m_programID);
}
GLuint Shader::CompileShader(GLenum type, const std::string &source)
{
OX_PROFILE_FUNCTION();
GLuint shader = glCreateShader(type);
const char *src = source.c_str();
glShaderSource(shader, 1, &src, nullptr);
glCompileShader(shader);
GLint success;
glGetShaderiv(shader, GL_COMPILE_STATUS, &success);
if (!success) {
char info[512];
glGetShaderInfoLog(shader, 512, nullptr, info);
Logger::LogError("Failed to Compile Shader '%s', '%s'", m_fragmentPath.c_str(), info);
return 0;
}
return shader;
}
void Shader::CheckHotReload()
{
OX_PROFILE_FUNCTION();
if (m_vertexPath.empty() || m_fragmentPath.empty()) {
return;
}
try {
OX_PROFILE_LABEL("Get Write Time");
auto vertTime = std::filesystem::last_write_time(m_vertexPath);
auto fragTime = std::filesystem::last_write_time(m_fragmentPath);
if (vertTime != m_vertTimestamp || fragTime != m_fragTimestamp) {
std::cout << "[Shader] Reloading shader: " << m_vertexPath << " / " << m_fragmentPath << "\n";
Reload();
}
} catch (const std::exception &e) {
Logger::LogError("Failed to Reload Shader '%s', %s", m_vertexPath.c_str(), e.what());
}
}
std::string Shader::ReadFile(const std::string &path)
{
if (!std::filesystem::exists(path)) {
std::ofstream file(path, std::ios::app);
}
std::ifstream file(path);
std::stringstream ss;
ss << file.rdbuf();
return ss.str();
}
GLint Shader::GetUniformLocation(const std::string &name)
{
if (m_uniformCache.contains(name))
return m_uniformCache[name];
GLint location = glGetUniformLocation(m_programID, name.c_str());
m_uniformCache[name] = location;
return location;
}
void Shader::SetInt(const std::string &name, int value)
{
glUniform1i(GetUniformLocation(name), value);
}
void Shader::SetFloat(const std::string &name, float value)
{
glUniform1f(GetUniformLocation(name), value);
}
void Shader::SetVec2(const std::string &name, const glm::vec2 &value)
{
glUniform2fv(GetUniformLocation(name), 1, &value[0]);
}
void Shader::SetVec3(const std::string &name, const glm::vec3 &value)
{
glUniform3fv(GetUniformLocation(name), 1, &value[0]);
}
void Shader::SetVec4(const std::string &name, const glm::vec4 &value)
{
glUniform4fv(GetUniformLocation(name), 1, &value[0]);
}
void Shader::SetMat4(const std::string &name, const glm::mat4 &value)
{
glUniformMatrix4fv(GetUniformLocation(name), 1, GL_FALSE, &value[0][0]);
}
void Shader::SetBool(const std::string &name, bool value)
{
glUniform1i(GetUniformLocation(name), (int) value);
}
}

View File

@ -1,61 +0,0 @@
#pragma once
#include <string>
#include <unordered_map>
#include <glm/glm.hpp>
#include <GL/glew.h>
#include <filesystem>
#include "systems/Profiler.h"
namespace OX
{
class Shader
{
public:
Shader() = default;
Shader(const std::string &vertexPath, const std::string &fragmentPath);
bool LoadFromFiles(const std::string &vertexPath, const std::string &fragmentPath);
bool LoadFromSource(const std::string &vertexSrc, const std::string &fragmentSrc);
void Reload();
void Use() const;
void CheckHotReload();
GLuint GetID() const { return m_programID; }
void SetInt(const std::string &name, int value);
void SetFloat(const std::string &name, float value);
void SetVec2(const std::string &name, const glm::vec2 &value);
void SetVec3(const std::string &name, const glm::vec3 &value);
void SetVec4(const std::string &name, const glm::vec4 &value);
void SetMat4(const std::string &name, const glm::mat4 &value);
void SetBool(const std::string &name, const bool value);
private:
GLuint m_programID = 0;
std::string m_vertexPath;
std::string m_fragmentPath;
std::unordered_map<std::string, GLint> m_uniformCache;
std::filesystem::file_time_type m_vertTimestamp;
std::filesystem::file_time_type m_fragTimestamp;
GLuint CompileShader(GLenum type, const std::string &source);
std::string ReadFile(const std::string &path);
GLint GetUniformLocation(const std::string &name);
};
}

View File

@ -146,7 +146,7 @@ namespace OX
// --- Render ImGui onto FBO 0 ---
{
OX_PROFILE_LABEL("VSYNC Wait");
ImGui::EndFrame();
ImGui::Render();

View File

@ -1,7 +1,6 @@
// File: src/FileBrowser.cpp
#include "FileBrowser.h"
#include <filesystem>
#include "systems/Profiler.h"
namespace OX
{
@ -14,7 +13,6 @@ namespace OX
void FileBrowser::Draw(const char *title)
{
OX_PROFILE_FUNCTION();
ImGui::Begin(title);
// --- toolbar now contains back button, inline path, filter & view toggle all on one row ---
@ -88,7 +86,6 @@ namespace OX
// ——— Polished grid view ———
void FileBrowser::DrawGridView(const std::shared_ptr<ResourceTreeNode> &node)
{
OX_PROFILE_FUNCTION();
const float cellW = _cfg.thumbnailSize + _cfg.padding * 2;
ImVec2 avail = ImGui::GetContentRegionAvail();
int cols = std::max(1, int(avail.x / cellW));
@ -96,15 +93,9 @@ namespace OX
ImGui::BeginChild("GridRegion", ImVec2(0, 0), false, ImGuiWindowFlags_AlwaysUseWindowPadding);
ImGui::Columns(cols, nullptr, false);
std::vector<std::shared_ptr<ResourceTreeNode> > children; {
std::lock_guard<std::mutex> lock(AssetManager::s_TreeMutex); // assume you add this mutex
children = node->children;
}
for (auto &c: children) {
if (!c) return;
for (auto &c: node->children) {
if (!_filter.empty() && !PassesFilter(c->name)) continue;
if (!c) return;
ImGui::PushID(c->path.c_str());
ImGui::BeginGroup();

View File

@ -13,8 +13,6 @@ namespace OX
{
// Construct title
std::string title = m_name + " (" + std::to_string(m_id) + ")";
GLuint textureID = core.GetRenderer().GetRenderTexture(); // You must define this method
// Remove window padding
ImGui::PushStyleVar(ImGuiStyleVar_WindowPadding, ImVec2(0, 0));
@ -26,17 +24,14 @@ namespace OX
ImVec2 viewportSize = ImGui::GetContentRegionAvail();
// === Fullscreen image ===
GLuint textureID = core.GetRenderer().GetRenderTarget(); // You must define this method
if (textureID != 0) {
ImGui::Image(textureID, viewportSize, ImVec2(0, 1), ImVec2(1, 0));
} else {
ImGui::Text("No Render Target.");
}
ImGui::End();
ImGui::PopStyleVar(); // Restore padding
core.GetRenderer().ResizeTarget(viewportSize.x, viewportSize.y);
}
};