Compare commits
3 Commits
1a928159e5
...
f7e0882597
Author | SHA1 | Date | |
---|---|---|---|
|
f7e0882597 | ||
|
4194764d7a | ||
|
375af6829c |
@ -99,6 +99,7 @@ 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)
|
||||
|
@ -6,6 +6,7 @@
|
||||
|
||||
#include "systems/MACROS.h"
|
||||
#include "systems/AssetManager.h"
|
||||
#include "systems/assets/Texture2D.h"
|
||||
|
||||
namespace OX
|
||||
{
|
||||
@ -32,9 +33,7 @@ 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);
|
||||
}
|
||||
@ -42,6 +41,7 @@ namespace OX
|
||||
|
||||
std::string fullTitle = layerTitle + " - " + m_name;
|
||||
window.SetWindowTitle(fullTitle);
|
||||
renderer.Init(800, 600);
|
||||
|
||||
Logger::LogOk("Core Initialization Complete.");
|
||||
|
||||
@ -49,7 +49,6 @@ namespace OX
|
||||
}
|
||||
|
||||
|
||||
|
||||
void Core::Run()
|
||||
{
|
||||
m_running = true;
|
||||
@ -80,6 +79,18 @@ 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);
|
||||
|
@ -1,9 +1,194 @@
|
||||
//
|
||||
// Created by spenc on 5/21/2025.
|
||||
//
|
||||
|
||||
// File: src/Renderer.cpp
|
||||
#include "Renderer.h"
|
||||
#include <glm/gtc/matrix_transform.hpp>
|
||||
#include <iostream>
|
||||
|
||||
namespace OX {
|
||||
namespace OX
|
||||
{
|
||||
// ——— Camera2D implementation (unchanged) ———
|
||||
Camera2D::Camera2D(float left, float right, float bottom, float top)
|
||||
: _left(left), _right(right), _bottom(bottom), _top(top)
|
||||
{
|
||||
Recalculate();
|
||||
}
|
||||
|
||||
} // 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
|
||||
|
@ -1,26 +1,74 @@
|
||||
//
|
||||
// Created by spenc on 5/21/2025.
|
||||
//
|
||||
// File: src/Renderer.h
|
||||
#pragma once
|
||||
|
||||
#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 {
|
||||
|
||||
class Renderer {
|
||||
public:
|
||||
Renderer() = default;
|
||||
~Renderer() = default;
|
||||
struct Sprite {
|
||||
GLuint textureID;
|
||||
glm::vec2 position;
|
||||
glm::vec2 size;
|
||||
};
|
||||
|
||||
[[nodiscard]] GLuint GetRenderTarget() const {return m_renderTarget; }
|
||||
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;
|
||||
|
||||
private:
|
||||
GLuint m_renderTarget;
|
||||
};
|
||||
private:
|
||||
void Recalculate();
|
||||
glm::vec2 _position{0.0f};
|
||||
float _zoom{1.0f};
|
||||
float _left, _right, _bottom, _top;
|
||||
glm::mat4 _viewProj{1.0f};
|
||||
};
|
||||
|
||||
} // OX
|
||||
class Renderer {
|
||||
public:
|
||||
Renderer() = default;
|
||||
~Renderer();
|
||||
|
||||
#endif //RENDERER_H
|
||||
/// 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 color‐attachment 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
|
||||
|
@ -18,6 +18,7 @@ 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>();
|
||||
|
||||
@ -96,7 +97,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});
|
||||
@ -138,7 +139,6 @@ namespace OX
|
||||
// Also map original file path to this ID
|
||||
auto meta = s_MetadataMap[pending.id];
|
||||
s_PathToID[meta.absolutePath] = pending.id;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@ -224,6 +224,7 @@ 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) {
|
||||
|
@ -37,6 +37,9 @@ 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;
|
||||
@ -69,6 +72,6 @@ namespace OX {
|
||||
|
||||
// texture upload queue
|
||||
static std::queue<PendingTexture> s_TextureQueue;
|
||||
static std::mutex s_QueueMutex;
|
||||
static std::mutex s_QueueMutex;
|
||||
};
|
||||
}
|
||||
|
180
src/core/systems/Shader.cpp
Normal file
180
src/core/systems/Shader.cpp
Normal file
@ -0,0 +1,180 @@
|
||||
#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);
|
||||
}
|
||||
}
|
61
src/core/systems/Shader.h
Normal file
61
src/core/systems/Shader.h
Normal file
@ -0,0 +1,61 @@
|
||||
#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);
|
||||
};
|
||||
}
|
@ -146,7 +146,7 @@ namespace OX
|
||||
|
||||
// --- Render ImGui onto FBO 0 ---
|
||||
{
|
||||
OX_PROFILE_LABEL("VSYNC Wait");
|
||||
|
||||
|
||||
ImGui::EndFrame();
|
||||
ImGui::Render();
|
||||
|
@ -1,6 +1,7 @@
|
||||
// File: src/FileBrowser.cpp
|
||||
#include "FileBrowser.h"
|
||||
#include <filesystem>
|
||||
#include "systems/Profiler.h"
|
||||
|
||||
namespace OX
|
||||
{
|
||||
@ -13,6 +14,7 @@ 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 ---
|
||||
@ -86,6 +88,7 @@ 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));
|
||||
@ -93,9 +96,15 @@ namespace OX
|
||||
ImGui::BeginChild("GridRegion", ImVec2(0, 0), false, ImGuiWindowFlags_AlwaysUseWindowPadding);
|
||||
ImGui::Columns(cols, nullptr, false);
|
||||
|
||||
for (auto &c: node->children) {
|
||||
if (!_filter.empty() && !PassesFilter(c->name)) continue;
|
||||
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;
|
||||
|
||||
if (!_filter.empty() && !PassesFilter(c->name)) continue;
|
||||
|
||||
ImGui::PushID(c->path.c_str());
|
||||
ImGui::BeginGroup();
|
||||
|
||||
|
@ -13,6 +13,8 @@ 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));
|
||||
@ -24,14 +26,17 @@ 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);
|
||||
|
||||
}
|
||||
};
|
||||
|
Loading…
Reference in New Issue
Block a user