feat: 添加ResourceManager统一管理资源
- 注释规范化 - 修复shader_cache_引用错误 - 简化shader_manager.cpp release函数 - 添加ResourceManager用于资源管理master
parent
917281d8f4
commit
687a79b526
|
|
@ -0,0 +1,10 @@
|
||||||
|
* 1. 修复全局光照导致的采样问题
|
||||||
|
* 2. 重构代码,统一化结构、加入ResourceManager
|
||||||
|
* 2.1. 优化cpu-gpu交互效率
|
||||||
|
2.2 修改shader文件结构
|
||||||
|
3. 支持更多材质及pbr参数
|
||||||
|
4. 添加HDRI支持
|
||||||
|
5. 支持glTF 2.0模型加载
|
||||||
|
6. 加入ReSITR优化收敛速度
|
||||||
|
7. 添加基于PBR及简单机器学习模型的超分辨率采样
|
||||||
|
8. 加入粒子系统
|
||||||
Binary file not shown.
Binary file not shown.
|
|
@ -27,6 +27,7 @@ using TextureHandle = uint;
|
||||||
using BufferHandle = uint;
|
using BufferHandle = uint;
|
||||||
using ShaderHandle = uint;
|
using ShaderHandle = uint;
|
||||||
using FramebufferHandle = uint;
|
using FramebufferHandle = uint;
|
||||||
|
using VertexArrayHandle = uint;
|
||||||
|
|
||||||
// Invalid handle constant
|
// Invalid handle constant
|
||||||
constexpr uint INVALID_HANDLE = 0;
|
constexpr uint INVALID_HANDLE = 0;
|
||||||
|
|
|
||||||
|
|
@ -74,15 +74,6 @@ private:
|
||||||
TextureHandle depth_texture_;
|
TextureHandle depth_texture_;
|
||||||
|
|
||||||
bool initialized_;
|
bool initialized_;
|
||||||
|
|
||||||
/*
|
|
||||||
* @brief Create texture for G-Buffer attachment
|
|
||||||
* @param internal_format OpenGL internal format
|
|
||||||
* @param format OpenGL format
|
|
||||||
* @param type OpenGL type
|
|
||||||
* @return Texture handle
|
|
||||||
*/
|
|
||||||
TextureHandle create_texture_(uint internal_format, uint format, uint type);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace are
|
} // namespace are
|
||||||
|
|
|
||||||
|
|
@ -95,7 +95,6 @@ private:
|
||||||
|
|
||||||
std::shared_ptr<Shader> compute_shader_;
|
std::shared_ptr<Shader> compute_shader_;
|
||||||
TextureHandle accumulation_texture_;
|
TextureHandle accumulation_texture_;
|
||||||
BufferHandle scene_buffer_;
|
|
||||||
BufferHandle material_buffer_;
|
BufferHandle material_buffer_;
|
||||||
BufferHandle light_buffer_;
|
BufferHandle light_buffer_;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -74,6 +74,8 @@ private:
|
||||||
std::unique_ptr<ScreenBlit> screen_blit_;
|
std::unique_ptr<ScreenBlit> screen_blit_;
|
||||||
std::unique_ptr<Denoiser> denoiser_;
|
std::unique_ptr<Denoiser> denoiser_;
|
||||||
|
|
||||||
|
TextureHandle rt_output_texture_;
|
||||||
|
|
||||||
bool initialized_;
|
bool initialized_;
|
||||||
uint frame_count_;
|
uint frame_count_;
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,128 @@
|
||||||
|
#ifndef ARE_INCLUDE_RESOURCE_RESOURCE_MANAGER_H
|
||||||
|
#define ARE_INCLUDE_RESOURCE_RESOURCE_MANAGER_H
|
||||||
|
|
||||||
|
#include "basic/types.h"
|
||||||
|
#include "resource/buffer.h"
|
||||||
|
#include "resource/texture.h"
|
||||||
|
#include <memory>
|
||||||
|
#include <unordered_map>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
namespace are {
|
||||||
|
|
||||||
|
// Texture creation parameters
|
||||||
|
struct TextureDescription {
|
||||||
|
uint width = 1;
|
||||||
|
uint height = 1;
|
||||||
|
TextureFormat format = TextureFormat::RGBA8;
|
||||||
|
TextureFilter filter = TextureFilter::LINEAR;
|
||||||
|
TextureWrap wrap = TextureWrap::CLAMP_TO_EDGE;
|
||||||
|
bool generate_mipmaps = false;
|
||||||
|
};
|
||||||
|
|
||||||
|
// Buffer creation parameters
|
||||||
|
struct BufferDescription {
|
||||||
|
BufferType type = BufferType::VERTEX_BUFFER;
|
||||||
|
BufferUsage usage = BufferUsage::STATIC_DRAW;
|
||||||
|
size_t size = 0;
|
||||||
|
const void *data = nullptr;
|
||||||
|
};
|
||||||
|
|
||||||
|
// Texture array creation parameters
|
||||||
|
struct TextureArrayDescription {
|
||||||
|
uint width = 1;
|
||||||
|
uint height = 1;
|
||||||
|
TextureFormat format = TextureFormat::RGBA8;
|
||||||
|
TextureFilter filter = TextureFilter::LINEAR;
|
||||||
|
TextureWrap wrap = TextureWrap::REPEAT;
|
||||||
|
std::vector<std::shared_ptr<Texture>> textures;
|
||||||
|
};
|
||||||
|
|
||||||
|
// Framebuffer creation parameters
|
||||||
|
struct FramebufferDescription {
|
||||||
|
uint width = 1;
|
||||||
|
uint height = 1;
|
||||||
|
bool create_depth = true;
|
||||||
|
uint color_attachment_count = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
// GPU resource manager - centralized resource creation and lifecycle
|
||||||
|
class ResourceManager {
|
||||||
|
public:
|
||||||
|
static ResourceManager &instance();
|
||||||
|
|
||||||
|
// Initialization and release
|
||||||
|
bool initialize();
|
||||||
|
void release();
|
||||||
|
|
||||||
|
// === Texture Management ===
|
||||||
|
TextureHandle create_texture(const TextureDescription &desc);
|
||||||
|
TextureHandle create_texture(uint width, uint height, TextureFormat format);
|
||||||
|
TextureHandle create_texture(const std::string &path);
|
||||||
|
void destroy_texture(TextureHandle handle);
|
||||||
|
|
||||||
|
// === Buffer Management ===
|
||||||
|
BufferHandle create_buffer(const BufferDescription &desc);
|
||||||
|
void update_buffer(BufferHandle handle, size_t offset, size_t size, const void *data);
|
||||||
|
void destroy_buffer(BufferHandle handle);
|
||||||
|
|
||||||
|
// === Framebuffer Management ===
|
||||||
|
FramebufferHandle create_framebuffer(const FramebufferDescription &desc);
|
||||||
|
TextureHandle get_framebuffer_color_attachment(FramebufferHandle fbo, uint index);
|
||||||
|
TextureHandle get_framebuffer_depth_attachment(FramebufferHandle fbo);
|
||||||
|
void destroy_framebuffer(FramebufferHandle fbo);
|
||||||
|
|
||||||
|
// === Texture Array Management ===
|
||||||
|
TextureHandle create_texture_array(const TextureArrayDescription &desc);
|
||||||
|
void destroy_texture_array(TextureHandle handle);
|
||||||
|
|
||||||
|
// === VAO Management ===
|
||||||
|
VertexArrayHandle create_vertex_array();
|
||||||
|
void destroy_vertex_array(VertexArrayHandle vao);
|
||||||
|
|
||||||
|
// === Binding Management ===
|
||||||
|
void bind_buffer(BufferHandle buffer, uint binding_point);
|
||||||
|
void bind_image_texture(TextureHandle texture, uint binding, bool read, bool write);
|
||||||
|
void bind_texture_to_unit(TextureHandle texture, uint unit);
|
||||||
|
|
||||||
|
// === Query ===
|
||||||
|
bool is_texture_valid(TextureHandle handle) const;
|
||||||
|
bool is_buffer_valid(BufferHandle handle) const;
|
||||||
|
bool is_framebuffer_valid(FramebufferHandle handle) const;
|
||||||
|
|
||||||
|
private:
|
||||||
|
ResourceManager();
|
||||||
|
~ResourceManager();
|
||||||
|
|
||||||
|
struct TextureResource {
|
||||||
|
TextureHandle gl_handle;
|
||||||
|
uint width;
|
||||||
|
uint height;
|
||||||
|
TextureFormat format;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct BufferResource {
|
||||||
|
BufferHandle gl_handle;
|
||||||
|
BufferType type;
|
||||||
|
BufferUsage usage;
|
||||||
|
size_t size;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct FramebufferResource {
|
||||||
|
FramebufferHandle gl_handle;
|
||||||
|
uint width;
|
||||||
|
uint height;
|
||||||
|
std::vector<TextureHandle> color_attachments;
|
||||||
|
TextureHandle depth_attachment;
|
||||||
|
};
|
||||||
|
|
||||||
|
std::unordered_map<TextureHandle, TextureResource> textures_;
|
||||||
|
std::unordered_map<BufferHandle, BufferResource> buffers_;
|
||||||
|
std::unordered_map<FramebufferHandle, FramebufferResource> framebuffers_;
|
||||||
|
|
||||||
|
bool initialized_;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace are
|
||||||
|
|
||||||
|
#endif // ARE_INCLUDE_RESOURCE_RESOURCE_MANAGER_H
|
||||||
|
|
@ -53,7 +53,7 @@ public:
|
||||||
bool compile_compute(const std::string &compute_source);
|
bool compile_compute(const std::string &compute_source);
|
||||||
|
|
||||||
// Use/activate shader program
|
// Use/activate shader program
|
||||||
void use() const; // 改为const
|
void use() const;
|
||||||
|
|
||||||
// Release shader resources
|
// Release shader resources
|
||||||
void release();
|
void release();
|
||||||
|
|
@ -63,63 +63,63 @@ public:
|
||||||
* @param name Uniform name
|
* @param name Uniform name
|
||||||
* @param value Value
|
* @param value Value
|
||||||
*/
|
*/
|
||||||
void set_bool(const std::string &name, bool value) const; // 新增,const
|
void set_bool(const std::string &name, bool value) const;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* @brief Set uniform integer
|
* @brief Set uniform integer
|
||||||
* @param name Uniform name
|
* @param name Uniform name
|
||||||
* @param value Value
|
* @param value Value
|
||||||
*/
|
*/
|
||||||
void set_int(const std::string &name, int value) const; // 改为const
|
void set_int(const std::string &name, int value) const;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* @brief Set uniform unsigned integer
|
* @brief Set uniform unsigned integer
|
||||||
* @param name Uniform name
|
* @param name Uniform name
|
||||||
* @param value Value
|
* @param value Value
|
||||||
*/
|
*/
|
||||||
void set_uint(const std::string &name, uint value) const; // 改为const
|
void set_uint(const std::string &name, uint value) const;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* @brief Set uniform float
|
* @brief Set uniform float
|
||||||
* @param name Uniform name
|
* @param name Uniform name
|
||||||
* @param value Value
|
* @param value Value
|
||||||
*/
|
*/
|
||||||
void set_float(const std::string &name, float value) const; // 改为const
|
void set_float(const std::string &name, float value) const;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* @brief Set uniform vec2
|
* @brief Set uniform vec2
|
||||||
* @param name Uniform name
|
* @param name Uniform name
|
||||||
* @param value Value
|
* @param value Value
|
||||||
*/
|
*/
|
||||||
void set_vec2(const std::string &name, const Vec2 &value) const; // 改为const
|
void set_vec2(const std::string &name, const Vec2 &value) const;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* @brief Set uniform vec3
|
* @brief Set uniform vec3
|
||||||
* @param name Uniform name
|
* @param name Uniform name
|
||||||
* @param value Value
|
* @param value Value
|
||||||
*/
|
*/
|
||||||
void set_vec3(const std::string &name, const Vec3 &value) const; // 改为const
|
void set_vec3(const std::string &name, const Vec3 &value) const;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* @brief Set uniform vec4
|
* @brief Set uniform vec4
|
||||||
* @param name Uniform name
|
* @param name Uniform name
|
||||||
* @param value Value
|
* @param value Value
|
||||||
*/
|
*/
|
||||||
void set_vec4(const std::string &name, const Vec4 &value) const; // 改为const
|
void set_vec4(const std::string &name, const Vec4 &value) const;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* @brief Set uniform mat3
|
* @brief Set uniform mat3
|
||||||
* @param name Uniform name
|
* @param name Uniform name
|
||||||
* @param value Value
|
* @param value Value
|
||||||
*/
|
*/
|
||||||
void set_mat3(const std::string &name, const Mat3 &value) const; // 改为const
|
void set_mat3(const std::string &name, const Mat3 &value) const;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* @brief Set uniform mat4
|
* @brief Set uniform mat4
|
||||||
* @param name Uniform name
|
* @param name Uniform name
|
||||||
* @param value Value
|
* @param value Value
|
||||||
*/
|
*/
|
||||||
void set_mat4(const std::string &name, const Mat4 &value) const; // 改为const
|
void set_mat4(const std::string &name, const Mat4 &value) const;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* @brief Get shader program handle
|
* @brief Get shader program handle
|
||||||
|
|
@ -139,14 +139,14 @@ public:
|
||||||
|
|
||||||
private:
|
private:
|
||||||
ShaderHandle handle_;
|
ShaderHandle handle_;
|
||||||
mutable std::unordered_map<std::string, int> uniform_cache_; // 改为mutable
|
mutable std::unordered_map<std::string, int> uniform_cache_;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* @brief Get uniform location (with caching)
|
* @brief Get uniform location (with caching)
|
||||||
* @param name Uniform name
|
* @param name Uniform name
|
||||||
* @return Uniform location
|
* @return Uniform location
|
||||||
*/
|
*/
|
||||||
int get_uniform_location_(const std::string &name) const; // 改为const
|
int get_uniform_location_(const std::string &name) const;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* @brief Compile shader stage
|
* @brief Compile shader stage
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
#ifndef ARE_INCLUDE_CORE_LOGGER_H
|
#ifndef ARE_INCLUDE_UTILS_LOGGER_H
|
||||||
#define ARE_INCLUDE_CORE_LOGGER_H
|
#define ARE_INCLUDE_UTILS_LOGGER_H
|
||||||
|
|
||||||
#include <memory>
|
#include <memory>
|
||||||
#include <string>
|
#include <string>
|
||||||
|
|
@ -19,18 +19,18 @@ enum class LogLevel {
|
||||||
// Thread-safe logging system
|
// Thread-safe logging system
|
||||||
class Logger {
|
class Logger {
|
||||||
public:
|
public:
|
||||||
/**
|
/*
|
||||||
* @brief Initialize the logging system
|
* @brief Initialize the logging system
|
||||||
* @param min_level Minimum log level to display
|
* @param min_level Minimum log level to display
|
||||||
*/
|
*/
|
||||||
static void init(LogLevel min_level = LogLevel::ARE_LOG_INFO);
|
static void init(LogLevel min_level = LogLevel::ARE_LOG_INFO);
|
||||||
|
|
||||||
/**
|
/*
|
||||||
* @brief Shutdown the logging system
|
* @brief Shutdown the logging system
|
||||||
*/
|
*/
|
||||||
static void shutdown();
|
static void shutdown();
|
||||||
|
|
||||||
/**
|
/*
|
||||||
* @brief Log a message with file/function/line information
|
* @brief Log a message with file/function/line information
|
||||||
* @param level Log severity level
|
* @param level Log severity level
|
||||||
* @param file Source file name
|
* @param file Source file name
|
||||||
|
|
@ -41,7 +41,7 @@ public:
|
||||||
static void log(LogLevel level, const char *file, const char *func,
|
static void log(LogLevel level, const char *file, const char *func,
|
||||||
int line, const std::string &message);
|
int line, const std::string &message);
|
||||||
|
|
||||||
/**
|
/*
|
||||||
* @brief Set minimum log level
|
* @brief Set minimum log level
|
||||||
* @param level Minimum log level to display
|
* @param level Minimum log level to display
|
||||||
*/
|
*/
|
||||||
|
|
@ -62,4 +62,4 @@ private:
|
||||||
#define ARE_LOG_ERROR(msg) are::Logger::log(are::LogLevel::ARE_LOG_ERROR, __FILE__, __func__, __LINE__, msg)
|
#define ARE_LOG_ERROR(msg) are::Logger::log(are::LogLevel::ARE_LOG_ERROR, __FILE__, __func__, __LINE__, msg)
|
||||||
#define ARE_LOG_CRITICAL(msg) are::Logger::log(are::LogLevel::ARE_LOG_CRITICAL, __FILE__, __func__, __LINE__, msg)
|
#define ARE_LOG_CRITICAL(msg) are::Logger::log(are::LogLevel::ARE_LOG_CRITICAL, __FILE__, __func__, __LINE__, msg)
|
||||||
|
|
||||||
#endif // ARE_INCLUDE_CORE_LOGGER_H
|
#endif // ARE_INCLUDE_UTILS_LOGGER_H
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,6 @@
|
||||||
#include "core/denoiser.h"
|
#include "core/denoiser.h"
|
||||||
#include "basic/constants.h"
|
#include "basic/constants.h"
|
||||||
|
#include "resource/resource_manager.h"
|
||||||
#include "utils/logger.h"
|
#include "utils/logger.h"
|
||||||
#include <glad/glad.h>
|
#include <glad/glad.h>
|
||||||
|
|
||||||
|
|
@ -38,7 +39,7 @@ void Denoiser::release() {
|
||||||
shader_.reset();
|
shader_.reset();
|
||||||
|
|
||||||
if (output_texture_ != INVALID_HANDLE) {
|
if (output_texture_ != INVALID_HANDLE) {
|
||||||
glDeleteTextures(1, &output_texture_);
|
ResourceManager::instance().destroy_texture(output_texture_);
|
||||||
output_texture_ = INVALID_HANDLE;
|
output_texture_ = INVALID_HANDLE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -53,7 +54,7 @@ void Denoiser::resize(uint width, uint height) {
|
||||||
if (!initialized_) return;
|
if (!initialized_) return;
|
||||||
|
|
||||||
if (output_texture_ != INVALID_HANDLE) {
|
if (output_texture_ != INVALID_HANDLE) {
|
||||||
glDeleteTextures(1, &output_texture_);
|
ResourceManager::instance().destroy_texture(output_texture_);
|
||||||
output_texture_ = INVALID_HANDLE;
|
output_texture_ = INVALID_HANDLE;
|
||||||
}
|
}
|
||||||
create_output_texture_();
|
create_output_texture_();
|
||||||
|
|
@ -81,13 +82,14 @@ TextureHandle Denoiser::denoise(TextureHandle input_texture, int radius) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void Denoiser::create_output_texture_() {
|
void Denoiser::create_output_texture_() {
|
||||||
glGenTextures(1, &output_texture_);
|
ResourceManager &rm = ResourceManager::instance();
|
||||||
glBindTexture(GL_TEXTURE_2D, output_texture_);
|
TextureDescription desc;
|
||||||
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA32F, width_, height_, 0, GL_RGBA, GL_FLOAT, nullptr);
|
desc.width = width_;
|
||||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
|
desc.height = height_;
|
||||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
|
desc.format = TextureFormat::RGBA32F;
|
||||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
|
desc.filter = TextureFilter::NEAREST;
|
||||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
|
desc.wrap = TextureWrap::CLAMP_TO_EDGE;
|
||||||
|
output_texture_ = rm.create_texture(desc);
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace are
|
} // namespace are
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,5 @@
|
||||||
#include "core/gbuffer.h"
|
#include "core/gbuffer.h"
|
||||||
|
#include "resource/resource_manager.h"
|
||||||
#include "utils/logger.h"
|
#include "utils/logger.h"
|
||||||
#include <glad/glad.h>
|
#include <glad/glad.h>
|
||||||
|
|
||||||
|
|
@ -25,49 +26,58 @@ bool GBuffer::initialize() {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ResourceManager &rm = ResourceManager::instance();
|
||||||
|
|
||||||
|
// Create framebuffer
|
||||||
glGenFramebuffers(1, &fbo_);
|
glGenFramebuffers(1, &fbo_);
|
||||||
glBindFramebuffer(GL_FRAMEBUFFER, fbo_);
|
glBindFramebuffer(GL_FRAMEBUFFER, fbo_);
|
||||||
|
|
||||||
textures_[GBUFFER_POSITION] = create_texture_(GL_RGBA32F, GL_RGBA, GL_FLOAT);
|
// Create color attachments using ResourceManager
|
||||||
textures_[GBUFFER_NORMAL] = create_texture_(GL_RGBA32F, GL_RGBA, GL_FLOAT);
|
TextureDescription tex_desc;
|
||||||
textures_[GBUFFER_ALBEDO] = create_texture_(GL_RGBA8, GL_RGBA, GL_UNSIGNED_BYTE);
|
tex_desc.width = width_;
|
||||||
|
tex_desc.height = height_;
|
||||||
|
tex_desc.filter = TextureFilter::NEAREST;
|
||||||
|
tex_desc.wrap = TextureWrap::CLAMP_TO_EDGE;
|
||||||
|
|
||||||
// New: material params (metallic, roughness, ior, type)
|
tex_desc.format = TextureFormat::RGBA32F;
|
||||||
textures_[GBUFFER_MATERIAL] = create_texture_(GL_RGBA32F, GL_RGBA, GL_FLOAT);
|
textures_[GBUFFER_POSITION] = rm.create_texture(tex_desc);
|
||||||
|
|
||||||
// New: material id (integer)
|
tex_desc.format = TextureFormat::RGBA32F;
|
||||||
textures_[GBUFFER_MATERIAL_ID] = create_texture_(GL_R32UI, GL_RED_INTEGER, GL_UNSIGNED_INT);
|
textures_[GBUFFER_NORMAL] = rm.create_texture(tex_desc);
|
||||||
|
|
||||||
// New: texcoord + tangent (xy = texcoord, zw = tangent)
|
tex_desc.format = TextureFormat::RGBA8;
|
||||||
textures_[GBUFFER_TEXCOORD] = create_texture_(GL_RGBA32F, GL_RGBA, GL_FLOAT);
|
textures_[GBUFFER_ALBEDO] = rm.create_texture(tex_desc);
|
||||||
|
|
||||||
// New: tangent (xyz = tangent, w = unused)
|
tex_desc.format = TextureFormat::RGBA32F;
|
||||||
textures_[GBUFFER_TANGENT] = create_texture_(GL_RGBA32F, GL_RGBA, GL_FLOAT);
|
textures_[GBUFFER_MATERIAL] = rm.create_texture(tex_desc);
|
||||||
|
|
||||||
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0 + GBUFFER_POSITION,
|
textures_[GBUFFER_MATERIAL_ID] = rm.create_texture(width_, height_, TextureFormat::R32F);
|
||||||
GL_TEXTURE_2D, textures_[GBUFFER_POSITION], 0);
|
|
||||||
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0 + GBUFFER_NORMAL,
|
tex_desc.format = TextureFormat::RGBA32F;
|
||||||
GL_TEXTURE_2D, textures_[GBUFFER_NORMAL], 0);
|
textures_[GBUFFER_TEXCOORD] = rm.create_texture(tex_desc);
|
||||||
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0 + GBUFFER_ALBEDO,
|
|
||||||
GL_TEXTURE_2D, textures_[GBUFFER_ALBEDO], 0);
|
tex_desc.format = TextureFormat::RGBA32F;
|
||||||
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0 + GBUFFER_MATERIAL,
|
textures_[GBUFFER_TANGENT] = rm.create_texture(tex_desc);
|
||||||
GL_TEXTURE_2D, textures_[GBUFFER_MATERIAL], 0);
|
|
||||||
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0 + GBUFFER_MATERIAL_ID,
|
// Attach color textures to framebuffer
|
||||||
GL_TEXTURE_2D, textures_[GBUFFER_MATERIAL_ID], 0);
|
for (int i = 0; i < GBUFFER_COUNT; ++i) {
|
||||||
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0 + GBUFFER_TEXCOORD,
|
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0 + i,
|
||||||
GL_TEXTURE_2D, textures_[GBUFFER_TEXCOORD], 0);
|
GL_TEXTURE_2D, textures_[i], 0);
|
||||||
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0 + GBUFFER_TANGENT,
|
}
|
||||||
GL_TEXTURE_2D, textures_[GBUFFER_TANGENT], 0);
|
|
||||||
|
// Create depth texture using ResourceManager
|
||||||
|
TextureDescription depth_desc;
|
||||||
|
depth_desc.width = width_;
|
||||||
|
depth_desc.height = height_;
|
||||||
|
depth_desc.format = TextureFormat::DEPTH24_STENCIL8;
|
||||||
|
depth_desc.filter = TextureFilter::NEAREST;
|
||||||
|
depth_desc.wrap = TextureWrap::CLAMP_TO_EDGE;
|
||||||
|
depth_texture_ = rm.create_texture(depth_desc);
|
||||||
|
|
||||||
glGenTextures(1, &depth_texture_);
|
|
||||||
glBindTexture(GL_TEXTURE_2D, depth_texture_);
|
|
||||||
glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH24_STENCIL8, width_, height_, 0,
|
|
||||||
GL_DEPTH_STENCIL, GL_UNSIGNED_INT_24_8, nullptr);
|
|
||||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
|
|
||||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
|
|
||||||
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT,
|
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT,
|
||||||
GL_TEXTURE_2D, depth_texture_, 0);
|
GL_TEXTURE_2D, depth_texture_, 0);
|
||||||
|
|
||||||
|
// Set draw buffers
|
||||||
GLenum draw_buffers[GBUFFER_COUNT] = {
|
GLenum draw_buffers[GBUFFER_COUNT] = {
|
||||||
GL_COLOR_ATTACHMENT0 + GBUFFER_POSITION,
|
GL_COLOR_ATTACHMENT0 + GBUFFER_POSITION,
|
||||||
GL_COLOR_ATTACHMENT0 + GBUFFER_NORMAL,
|
GL_COLOR_ATTACHMENT0 + GBUFFER_NORMAL,
|
||||||
|
|
@ -96,6 +106,8 @@ void GBuffer::release() {
|
||||||
if (!initialized_)
|
if (!initialized_)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
ResourceManager &rm = ResourceManager::instance();
|
||||||
|
|
||||||
if (fbo_ != INVALID_HANDLE) {
|
if (fbo_ != INVALID_HANDLE) {
|
||||||
glDeleteFramebuffers(1, &fbo_);
|
glDeleteFramebuffers(1, &fbo_);
|
||||||
fbo_ = INVALID_HANDLE;
|
fbo_ = INVALID_HANDLE;
|
||||||
|
|
@ -103,13 +115,13 @@ void GBuffer::release() {
|
||||||
|
|
||||||
for (int i = 0; i < GBUFFER_COUNT; ++i) {
|
for (int i = 0; i < GBUFFER_COUNT; ++i) {
|
||||||
if (textures_[i] != INVALID_HANDLE) {
|
if (textures_[i] != INVALID_HANDLE) {
|
||||||
glDeleteTextures(1, &textures_[i]);
|
rm.destroy_texture(textures_[i]);
|
||||||
textures_[i] = INVALID_HANDLE;
|
textures_[i] = INVALID_HANDLE;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (depth_texture_ != INVALID_HANDLE) {
|
if (depth_texture_ != INVALID_HANDLE) {
|
||||||
glDeleteTextures(1, &depth_texture_);
|
rm.destroy_texture(depth_texture_);
|
||||||
depth_texture_ = INVALID_HANDLE;
|
depth_texture_ = INVALID_HANDLE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -117,18 +129,6 @@ void GBuffer::release() {
|
||||||
ARE_LOG_INFO("GBuffer released");
|
ARE_LOG_INFO("GBuffer released");
|
||||||
}
|
}
|
||||||
|
|
||||||
TextureHandle GBuffer::create_texture_(uint internal_format, uint format, uint type) {
|
|
||||||
TextureHandle texture;
|
|
||||||
glGenTextures(1, &texture);
|
|
||||||
glBindTexture(GL_TEXTURE_2D, texture);
|
|
||||||
glTexImage2D(GL_TEXTURE_2D, 0, internal_format, width_, height_, 0, format, type, nullptr);
|
|
||||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
|
|
||||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
|
|
||||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
|
|
||||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
|
|
||||||
return texture;
|
|
||||||
}
|
|
||||||
|
|
||||||
void GBuffer::render(const Scene &scene, const Shader &shader) {
|
void GBuffer::render(const Scene &scene, const Shader &shader) {
|
||||||
if (!initialized_) {
|
if (!initialized_) {
|
||||||
ARE_LOG_ERROR("GBuffer not initialized");
|
ARE_LOG_ERROR("GBuffer not initialized");
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,6 @@
|
||||||
#include "core/raytracer.h"
|
#include "core/raytracer.h"
|
||||||
#include "basic/constants.h"
|
#include "basic/constants.h"
|
||||||
|
#include "resource/resource_manager.h"
|
||||||
#include "utils/logger.h"
|
#include "utils/logger.h"
|
||||||
#include <glad/glad.h>
|
#include <glad/glad.h>
|
||||||
|
|
||||||
|
|
@ -22,7 +23,6 @@ RayTracer::RayTracer(uint width, uint height, const RayTracerConfig &config)
|
||||||
, height_(height)
|
, height_(height)
|
||||||
, config_(config)
|
, config_(config)
|
||||||
, accumulation_texture_(INVALID_HANDLE)
|
, accumulation_texture_(INVALID_HANDLE)
|
||||||
, scene_buffer_(INVALID_HANDLE)
|
|
||||||
, material_buffer_(INVALID_HANDLE)
|
, material_buffer_(INVALID_HANDLE)
|
||||||
, light_buffer_(INVALID_HANDLE)
|
, light_buffer_(INVALID_HANDLE)
|
||||||
, bvh_(nullptr)
|
, bvh_(nullptr)
|
||||||
|
|
@ -43,33 +43,27 @@ bool RayTracer::initialize(const std::shared_ptr<Shader> &shader) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ResourceManager &rm = ResourceManager::instance();
|
||||||
|
|
||||||
compute_shader_ = shader;
|
compute_shader_ = shader;
|
||||||
|
|
||||||
// Create accumulation texture
|
// Create accumulation texture
|
||||||
glGenTextures(1, &accumulation_texture_);
|
accumulation_texture_ = rm.create_texture(width_, height_, TextureFormat::RGBA32F);
|
||||||
glBindTexture(GL_TEXTURE_2D, accumulation_texture_);
|
|
||||||
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA32F, width_, height_, 0, GL_RGBA, GL_FLOAT, nullptr);
|
|
||||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
|
|
||||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
|
|
||||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
|
|
||||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
|
|
||||||
|
|
||||||
// Create shader storage buffers
|
// Create shader storage buffers
|
||||||
glGenBuffers(1, &material_buffer_);
|
BufferDescription ssbo_desc;
|
||||||
glGenBuffers(1, &light_buffer_);
|
ssbo_desc.type = BufferType::SHADER_STORAGE_BUFFER;
|
||||||
|
ssbo_desc.usage = BufferUsage::DYNAMIC_DRAW;
|
||||||
|
ssbo_desc.size = 1;
|
||||||
|
ssbo_desc.data = nullptr;
|
||||||
|
material_buffer_ = rm.create_buffer(ssbo_desc);
|
||||||
|
light_buffer_ = rm.create_buffer(ssbo_desc);
|
||||||
|
|
||||||
// Initialize texture arrays (empty for now)
|
// Initialize texture arrays (empty for now)
|
||||||
for (int i = 0; i < 6; i++) {
|
for (int i = 0; i < 6; i++) {
|
||||||
texture_arrays_[i] = 0;
|
texture_arrays_[i] = 0;
|
||||||
texture_array_sizes_[i] = 0;
|
texture_array_sizes_[i] = 0;
|
||||||
glGenTextures(1, &texture_arrays_[i]);
|
|
||||||
glBindTexture(GL_TEXTURE_2D_ARRAY, texture_arrays_[i]);
|
|
||||||
glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
|
|
||||||
glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
|
||||||
glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_WRAP_S, GL_REPEAT);
|
|
||||||
glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_WRAP_T, GL_REPEAT);
|
|
||||||
}
|
}
|
||||||
glBindTexture(GL_TEXTURE_2D_ARRAY, 0);
|
|
||||||
|
|
||||||
// Initialize BVH if enabled
|
// Initialize BVH if enabled
|
||||||
if (config_.use_bvh_) {
|
if (config_.use_bvh_) {
|
||||||
|
|
@ -85,26 +79,28 @@ void RayTracer::release() {
|
||||||
if (!initialized_)
|
if (!initialized_)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
ResourceManager &rm = ResourceManager::instance();
|
||||||
|
|
||||||
if (accumulation_texture_ != INVALID_HANDLE) {
|
if (accumulation_texture_ != INVALID_HANDLE) {
|
||||||
glDeleteTextures(1, &accumulation_texture_);
|
rm.destroy_texture(accumulation_texture_);
|
||||||
accumulation_texture_ = INVALID_HANDLE;
|
accumulation_texture_ = INVALID_HANDLE;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Release texture arrays
|
// Release texture arrays
|
||||||
for (int i = 0; i < 6; i++) {
|
for (int i = 0; i < 6; i++) {
|
||||||
if (texture_arrays_[i] != 0) {
|
if (texture_arrays_[i] != 0) {
|
||||||
glDeleteTextures(1, &texture_arrays_[i]);
|
rm.destroy_texture_array(texture_arrays_[i]);
|
||||||
texture_arrays_[i] = 0;
|
texture_arrays_[i] = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (material_buffer_ != INVALID_HANDLE) {
|
if (material_buffer_ != INVALID_HANDLE) {
|
||||||
glDeleteBuffers(1, &material_buffer_);
|
rm.destroy_buffer(material_buffer_);
|
||||||
material_buffer_ = INVALID_HANDLE;
|
material_buffer_ = INVALID_HANDLE;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (light_buffer_ != INVALID_HANDLE) {
|
if (light_buffer_ != INVALID_HANDLE) {
|
||||||
glDeleteBuffers(1, &light_buffer_);
|
rm.destroy_buffer(light_buffer_);
|
||||||
light_buffer_ = INVALID_HANDLE;
|
light_buffer_ = INVALID_HANDLE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -254,18 +250,14 @@ void RayTracer::resize(uint width, uint height) {
|
||||||
height_ = height;
|
height_ = height;
|
||||||
|
|
||||||
if (initialized_) {
|
if (initialized_) {
|
||||||
|
ResourceManager &rm = ResourceManager::instance();
|
||||||
|
|
||||||
// Recreate accumulation texture
|
// Recreate accumulation texture
|
||||||
if (accumulation_texture_ != INVALID_HANDLE) {
|
if (accumulation_texture_ != INVALID_HANDLE) {
|
||||||
glDeleteTextures(1, &accumulation_texture_);
|
rm.destroy_texture(accumulation_texture_);
|
||||||
}
|
}
|
||||||
|
|
||||||
glGenTextures(1, &accumulation_texture_);
|
accumulation_texture_ = rm.create_texture(width_, height_, TextureFormat::RGBA32F);
|
||||||
glBindTexture(GL_TEXTURE_2D, accumulation_texture_);
|
|
||||||
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA32F, width_, height_, 0, GL_RGBA, GL_FLOAT, nullptr);
|
|
||||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
|
|
||||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
|
|
||||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
|
|
||||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
|
|
||||||
|
|
||||||
reset_accumulation();
|
reset_accumulation();
|
||||||
}
|
}
|
||||||
|
|
@ -439,8 +431,16 @@ void RayTracer::build_texture_arrays_(const Scene &scene) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ResourceManager &rm = ResourceManager::instance();
|
||||||
|
|
||||||
// Build arrays for each slot
|
// Build arrays for each slot
|
||||||
for (int slot = 0; slot < 6; slot++) {
|
for (int slot = 0; slot < 6; slot++) {
|
||||||
|
// Destroy previous texture array if exists
|
||||||
|
if (texture_arrays_[slot] != 0) {
|
||||||
|
rm.destroy_texture_array(texture_arrays_[slot]);
|
||||||
|
texture_arrays_[slot] = 0;
|
||||||
|
}
|
||||||
|
|
||||||
if (textures[slot].empty()) {
|
if (textures[slot].empty()) {
|
||||||
texture_array_sizes_[slot] = 0;
|
texture_array_sizes_[slot] = 0;
|
||||||
continue;
|
continue;
|
||||||
|
|
@ -448,89 +448,25 @@ void RayTracer::build_texture_arrays_(const Scene &scene) {
|
||||||
|
|
||||||
texture_array_sizes_[slot] = static_cast<uint>(textures[slot].size());
|
texture_array_sizes_[slot] = static_cast<uint>(textures[slot].size());
|
||||||
|
|
||||||
// Get dimensions from first texture (assume all same size)
|
// Create texture array using ResourceManager
|
||||||
int width = textures[slot][0]->get_width();
|
TextureArrayDescription desc;
|
||||||
int height = textures[slot][0]->get_height();
|
desc.textures = textures[slot];
|
||||||
|
desc.filter = TextureFilter::LINEAR;
|
||||||
|
desc.wrap = TextureWrap::REPEAT;
|
||||||
|
|
||||||
// Create texture array
|
texture_arrays_[slot] = rm.create_texture_array(desc);
|
||||||
glBindTexture(GL_TEXTURE_2D_ARRAY, texture_arrays_[slot]);
|
|
||||||
glTexImage3D(GL_TEXTURE_2D_ARRAY, 0, GL_RGBA8, width, height,
|
|
||||||
static_cast<int>(textures[slot].size()), 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
|
|
||||||
|
|
||||||
// Copy each texture to array layer and set indices on materials
|
// Set texture index on all materials using each texture
|
||||||
for (size_t i = 0; i < textures[slot].size(); i++) {
|
for (size_t i = 0; i < textures[slot].size(); i++) {
|
||||||
auto &tex = textures[slot][i];
|
|
||||||
GLuint tex_handle = tex->get_handle();
|
|
||||||
if (tex_handle != 0) {
|
|
||||||
// Get original texture format
|
|
||||||
TextureFormat orig_format = tex->get_format();
|
|
||||||
int orig_width = tex->get_width();
|
|
||||||
int orig_height = tex->get_height();
|
|
||||||
|
|
||||||
// Get the correct format for reading
|
|
||||||
GLenum orig_gl_format = GL_RGBA;
|
|
||||||
int channels = 4;
|
|
||||||
switch (orig_format) {
|
|
||||||
case TextureFormat::R8:
|
|
||||||
orig_gl_format = GL_RED;
|
|
||||||
channels = 1;
|
|
||||||
break;
|
|
||||||
case TextureFormat::RG8:
|
|
||||||
orig_gl_format = GL_RG;
|
|
||||||
channels = 2;
|
|
||||||
break;
|
|
||||||
case TextureFormat::RGB8:
|
|
||||||
orig_gl_format = GL_RGB;
|
|
||||||
channels = 3;
|
|
||||||
break;
|
|
||||||
case TextureFormat::RGBA8:
|
|
||||||
orig_gl_format = GL_RGBA;
|
|
||||||
channels = 4;
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
orig_gl_format = GL_RGBA;
|
|
||||||
channels = 4;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Read texture data with correct format
|
|
||||||
std::vector<uint8_t> orig_pixels(orig_width * orig_height * channels);
|
|
||||||
glBindTexture(GL_TEXTURE_2D, tex_handle);
|
|
||||||
glGetTexImage(GL_TEXTURE_2D, 0, orig_gl_format, GL_UNSIGNED_BYTE, orig_pixels.data());
|
|
||||||
glBindTexture(GL_TEXTURE_2D, 0);
|
|
||||||
|
|
||||||
// Convert to RGBA for texture array (always RGBA8)
|
|
||||||
std::vector<uint8_t> pixels(orig_width * orig_height * 4, 255);
|
|
||||||
for (int y = 0; y < orig_height; y++) {
|
|
||||||
for (int x = 0; x < orig_width; x++) {
|
|
||||||
int src_idx = (y * orig_width + x) * channels;
|
|
||||||
int dst_idx = (y * orig_width + x) * 4;
|
|
||||||
pixels[dst_idx + 0] = orig_pixels[src_idx + 0];
|
|
||||||
pixels[dst_idx + 1] = (channels >= 2) ? orig_pixels[src_idx + 1] : orig_pixels[src_idx + 0];
|
|
||||||
pixels[dst_idx + 2] = (channels >= 3) ? orig_pixels[src_idx + 2] : orig_pixels[src_idx + 0];
|
|
||||||
pixels[dst_idx + 3] = (channels >= 4) ? orig_pixels[src_idx + 3] : 255;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
glTexSubImage3D(GL_TEXTURE_2D_ARRAY, 0, 0, 0, static_cast<int>(i),
|
|
||||||
width, height, 1, GL_RGBA, GL_UNSIGNED_BYTE, pixels.data());
|
|
||||||
|
|
||||||
// Set texture index on all materials using this texture
|
|
||||||
// Index is i+1 because 0 means "no texture" in the shader
|
// Index is i+1 because 0 means "no texture" in the shader
|
||||||
uint32_t array_index = static_cast<uint32_t>(i) + 1;
|
uint32_t array_index = static_cast<uint32_t>(i) + 1;
|
||||||
for (const auto &mat : materials) {
|
for (const auto &mat : materials) {
|
||||||
if (mat->get_texture(static_cast<TextureSlot>(slot)).get() == tex.get()) {
|
if (mat->get_texture(static_cast<TextureSlot>(slot)).get() == textures[slot][i].get()) {
|
||||||
mat->set_texture_index(static_cast<TextureSlot>(slot), array_index);
|
mat->set_texture_index(static_cast<TextureSlot>(slot), array_index);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Generate mipmaps
|
|
||||||
glGenerateMipmap(GL_TEXTURE_2D_ARRAY);
|
|
||||||
}
|
|
||||||
|
|
||||||
glBindTexture(GL_TEXTURE_2D_ARRAY, 0);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace are
|
} // namespace are
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,5 @@
|
||||||
#include "core/renderer.h"
|
#include "core/renderer.h"
|
||||||
|
#include "resource/resource_manager.h"
|
||||||
#include "utils/logger.h"
|
#include "utils/logger.h"
|
||||||
#include <chrono>
|
#include <chrono>
|
||||||
#include <glad/glad.h>
|
#include <glad/glad.h>
|
||||||
|
|
@ -7,6 +8,7 @@ namespace are {
|
||||||
|
|
||||||
Renderer::Renderer(const RendererConfig &config)
|
Renderer::Renderer(const RendererConfig &config)
|
||||||
: config_(config)
|
: config_(config)
|
||||||
|
, rt_output_texture_(INVALID_HANDLE)
|
||||||
, initialized_(false)
|
, initialized_(false)
|
||||||
, frame_count_(0) {
|
, frame_count_(0) {
|
||||||
}
|
}
|
||||||
|
|
@ -69,6 +71,10 @@ bool Renderer::initialize() {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Create ray tracing output texture (reused every frame)
|
||||||
|
ResourceManager &rm = ResourceManager::instance();
|
||||||
|
rt_output_texture_ = rm.create_texture(config_.width_, config_.height_, TextureFormat::RGBA32F);
|
||||||
|
|
||||||
initialized_ = true;
|
initialized_ = true;
|
||||||
ARE_LOG_INFO("Aurora Rendering Engine initialized successfully");
|
ARE_LOG_INFO("Aurora Rendering Engine initialized successfully");
|
||||||
return true;
|
return true;
|
||||||
|
|
@ -80,30 +86,18 @@ void Renderer::shutdown() {
|
||||||
|
|
||||||
ARE_LOG_INFO("Shutting down Aurora Rendering Engine...");
|
ARE_LOG_INFO("Shutting down Aurora Rendering Engine...");
|
||||||
|
|
||||||
if (screen_blit_) {
|
ResourceManager &rm = ResourceManager::instance();
|
||||||
screen_blit_->release();
|
|
||||||
|
if (rt_output_texture_ != INVALID_HANDLE) {
|
||||||
|
rm.destroy_texture(rt_output_texture_);
|
||||||
|
rt_output_texture_ = INVALID_HANDLE;
|
||||||
|
}
|
||||||
|
|
||||||
screen_blit_.reset();
|
screen_blit_.reset();
|
||||||
}
|
|
||||||
|
|
||||||
if (raytracer_) {
|
|
||||||
raytracer_->release();
|
|
||||||
raytracer_.reset();
|
raytracer_.reset();
|
||||||
}
|
|
||||||
|
|
||||||
if (gbuffer_) {
|
|
||||||
gbuffer_->release();
|
|
||||||
gbuffer_.reset();
|
gbuffer_.reset();
|
||||||
}
|
|
||||||
|
|
||||||
if (shader_manager_) {
|
|
||||||
shader_manager_->release();
|
|
||||||
shader_manager_.reset();
|
shader_manager_.reset();
|
||||||
}
|
|
||||||
|
|
||||||
if (denoiser_) {
|
|
||||||
denoiser_->release();
|
|
||||||
denoiser_.reset();
|
denoiser_.reset();
|
||||||
}
|
|
||||||
|
|
||||||
initialized_ = false;
|
initialized_ = false;
|
||||||
ARE_LOG_INFO("Aurora Rendering Engine shut down");
|
ARE_LOG_INFO("Aurora Rendering Engine shut down");
|
||||||
|
|
@ -136,19 +130,8 @@ RenderStats Renderer::render(const Scene& scene, TextureHandle output_texture) {
|
||||||
// Phase 2: Ray tracing pass
|
// Phase 2: Ray tracing pass
|
||||||
auto raytrace_start = std::chrono::high_resolution_clock::now();
|
auto raytrace_start = std::chrono::high_resolution_clock::now();
|
||||||
|
|
||||||
// Create output texture if not provided
|
// Use output texture if provided, otherwise use internal texture
|
||||||
TextureHandle rt_output = output_texture;
|
TextureHandle rt_output = (output_texture != 0) ? output_texture : rt_output_texture_;
|
||||||
bool created_temp_texture = false;
|
|
||||||
|
|
||||||
if (rt_output == 0) {
|
|
||||||
glGenTextures(1, &rt_output);
|
|
||||||
glBindTexture(GL_TEXTURE_2D, rt_output);
|
|
||||||
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA32F, config_.width_, config_.height_,
|
|
||||||
0, GL_RGBA, GL_FLOAT, nullptr);
|
|
||||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
|
||||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
|
||||||
created_temp_texture = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
raytracer_->trace(scene, *gbuffer_, rt_output);
|
raytracer_->trace(scene, *gbuffer_, rt_output);
|
||||||
|
|
||||||
|
|
@ -163,9 +146,8 @@ RenderStats Renderer::render(const Scene& scene, TextureHandle output_texture) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Phase 4: Blit to screen if output is default framebuffer
|
// Phase 4: Blit to screen if output is default framebuffer
|
||||||
if (created_temp_texture && output_texture == 0) {
|
if (output_texture == 0) {
|
||||||
screen_blit_->blit_fullscreen(final_output);
|
screen_blit_->blit_fullscreen(final_output);
|
||||||
glDeleteTextures(1, &rt_output);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Calculate total frame time
|
// Calculate total frame time
|
||||||
|
|
@ -194,6 +176,14 @@ void Renderer::resize(uint width, uint height) {
|
||||||
config_.height_ = height;
|
config_.height_ = height;
|
||||||
|
|
||||||
if (initialized_) {
|
if (initialized_) {
|
||||||
|
ResourceManager &rm = ResourceManager::instance();
|
||||||
|
|
||||||
|
// Recreate ray tracing output texture
|
||||||
|
if (rt_output_texture_ != INVALID_HANDLE) {
|
||||||
|
rm.destroy_texture(rt_output_texture_);
|
||||||
|
}
|
||||||
|
rt_output_texture_ = rm.create_texture(width, height, TextureFormat::RGBA32F);
|
||||||
|
|
||||||
gbuffer_->resize(width, height);
|
gbuffer_->resize(width, height);
|
||||||
raytracer_->resize(width, height);
|
raytracer_->resize(width, height);
|
||||||
denoiser_->resize(width, height);
|
denoiser_->resize(width, height);
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,5 @@
|
||||||
#include "core/screen_blit.h"
|
#include "core/screen_blit.h"
|
||||||
|
#include "resource/resource_manager.h"
|
||||||
#include "utils/logger.h"
|
#include "utils/logger.h"
|
||||||
#include <glad/glad.h>
|
#include <glad/glad.h>
|
||||||
|
|
||||||
|
|
@ -35,13 +36,15 @@ void ScreenBlit::release() {
|
||||||
|
|
||||||
shader_.reset();
|
shader_.reset();
|
||||||
|
|
||||||
|
ResourceManager &rm = ResourceManager::instance();
|
||||||
|
|
||||||
if (vao_ != 0) {
|
if (vao_ != 0) {
|
||||||
glDeleteVertexArrays(1, &vao_);
|
rm.destroy_vertex_array(vao_);
|
||||||
vao_ = 0;
|
vao_ = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (vbo_ != 0) {
|
if (vbo_ != 0) {
|
||||||
glDeleteBuffers(1, &vbo_);
|
rm.destroy_buffer(vbo_);
|
||||||
vbo_ = 0;
|
vbo_ = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -96,12 +99,19 @@ void ScreenBlit::create_quad_() {
|
||||||
-1.0f, 1.0f, 0.0f, 1.0f
|
-1.0f, 1.0f, 0.0f, 1.0f
|
||||||
};
|
};
|
||||||
|
|
||||||
glGenVertexArrays(1, &vao_);
|
ResourceManager &rm = ResourceManager::instance();
|
||||||
glGenBuffers(1, &vbo_);
|
|
||||||
|
|
||||||
|
vao_ = rm.create_vertex_array();
|
||||||
glBindVertexArray(vao_);
|
glBindVertexArray(vao_);
|
||||||
|
|
||||||
|
BufferDescription vbo_desc;
|
||||||
|
vbo_desc.type = BufferType::VERTEX_BUFFER;
|
||||||
|
vbo_desc.usage = BufferUsage::STATIC_DRAW;
|
||||||
|
vbo_desc.size = sizeof(vertices);
|
||||||
|
vbo_desc.data = vertices;
|
||||||
|
vbo_ = rm.create_buffer(vbo_desc);
|
||||||
|
|
||||||
glBindBuffer(GL_ARRAY_BUFFER, vbo_);
|
glBindBuffer(GL_ARRAY_BUFFER, vbo_);
|
||||||
glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);
|
|
||||||
|
|
||||||
// Position attribute
|
// Position attribute
|
||||||
glEnableVertexAttribArray(0);
|
glEnableVertexAttribArray(0);
|
||||||
|
|
|
||||||
|
|
@ -32,9 +32,6 @@ bool ShaderManager::initialize() {
|
||||||
void ShaderManager::release() {
|
void ShaderManager::release() {
|
||||||
if (!initialized_) return;
|
if (!initialized_) return;
|
||||||
|
|
||||||
for (auto& pair : shader_cache_) {
|
|
||||||
if (pair.second) pair.second->release();
|
|
||||||
}
|
|
||||||
shader_cache_.clear();
|
shader_cache_.clear();
|
||||||
|
|
||||||
gbuffer_shader_.reset();
|
gbuffer_shader_.reset();
|
||||||
|
|
@ -110,7 +107,7 @@ bool ShaderManager::load_builtin_shaders_() {
|
||||||
ARE_LOG_ERROR("Failed to load screen blit shader");
|
ARE_LOG_ERROR("Failed to load screen blit shader");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
shader_cache_["screen_blit"] = denoise_shader_;
|
shader_cache_["screen_blit"] = screen_blit_shader_;
|
||||||
ARE_LOG_INFO("Screen blit shader loaded successfully");
|
ARE_LOG_INFO("Screen blit shader loaded successfully");
|
||||||
|
|
||||||
// Load ray tracing shader
|
// Load ray tracing shader
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,667 @@
|
||||||
|
#include "resource/resource_manager.h"
|
||||||
|
#include "utils/logger.h"
|
||||||
|
#include <glad/glad.h>
|
||||||
|
|
||||||
|
namespace are {
|
||||||
|
|
||||||
|
ResourceManager::ResourceManager()
|
||||||
|
: initialized_(false) {
|
||||||
|
}
|
||||||
|
|
||||||
|
ResourceManager::~ResourceManager() {
|
||||||
|
release();
|
||||||
|
}
|
||||||
|
|
||||||
|
ResourceManager &ResourceManager::instance() {
|
||||||
|
static ResourceManager manager;
|
||||||
|
return manager;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ResourceManager::initialize() {
|
||||||
|
if (initialized_) {
|
||||||
|
ARE_LOG_WARN("ResourceManager already initialized");
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
initialized_ = true;
|
||||||
|
ARE_LOG_INFO("ResourceManager initialized successfully");
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ResourceManager::release() {
|
||||||
|
if (!initialized_)
|
||||||
|
return;
|
||||||
|
|
||||||
|
ARE_LOG_INFO("Releasing ResourceManager resources...");
|
||||||
|
|
||||||
|
// Release all textures
|
||||||
|
for (auto &[handle, resource] : textures_) {
|
||||||
|
glDeleteTextures(1, &resource.gl_handle);
|
||||||
|
}
|
||||||
|
textures_.clear();
|
||||||
|
|
||||||
|
// Release all buffers
|
||||||
|
for (auto &[handle, resource] : buffers_) {
|
||||||
|
glDeleteBuffers(1, &resource.gl_handle);
|
||||||
|
}
|
||||||
|
buffers_.clear();
|
||||||
|
|
||||||
|
// Release all framebuffers and their attachments
|
||||||
|
for (auto &[handle, resource] : framebuffers_) {
|
||||||
|
// Attachments are owned by textures_ map, already deleted
|
||||||
|
glDeleteFramebuffers(1, &resource.gl_handle);
|
||||||
|
}
|
||||||
|
framebuffers_.clear();
|
||||||
|
|
||||||
|
initialized_ = false;
|
||||||
|
ARE_LOG_INFO("ResourceManager released");
|
||||||
|
}
|
||||||
|
|
||||||
|
// === Texture Management ===
|
||||||
|
|
||||||
|
TextureHandle ResourceManager::create_texture(const TextureDescription &desc) {
|
||||||
|
TextureHandle handle;
|
||||||
|
glGenTextures(1, &handle);
|
||||||
|
glBindTexture(GL_TEXTURE_2D, handle);
|
||||||
|
|
||||||
|
// Convert format to GL types
|
||||||
|
GLenum gl_internal_format = GL_RGBA8;
|
||||||
|
GLenum gl_format = GL_RGBA;
|
||||||
|
GLenum gl_type = GL_UNSIGNED_BYTE;
|
||||||
|
|
||||||
|
switch (desc.format) {
|
||||||
|
case TextureFormat::R8:
|
||||||
|
gl_internal_format = GL_R8;
|
||||||
|
gl_format = GL_RED;
|
||||||
|
gl_type = GL_UNSIGNED_BYTE;
|
||||||
|
break;
|
||||||
|
case TextureFormat::RG8:
|
||||||
|
gl_internal_format = GL_RG8;
|
||||||
|
gl_format = GL_RG;
|
||||||
|
gl_type = GL_UNSIGNED_BYTE;
|
||||||
|
break;
|
||||||
|
case TextureFormat::RGB8:
|
||||||
|
gl_internal_format = GL_RGB8;
|
||||||
|
gl_format = GL_RGB;
|
||||||
|
gl_type = GL_UNSIGNED_BYTE;
|
||||||
|
break;
|
||||||
|
case TextureFormat::RGBA8:
|
||||||
|
gl_internal_format = GL_RGBA8;
|
||||||
|
gl_format = GL_RGBA;
|
||||||
|
gl_type = GL_UNSIGNED_BYTE;
|
||||||
|
break;
|
||||||
|
case TextureFormat::RGBA32F:
|
||||||
|
gl_internal_format = GL_RGBA32F;
|
||||||
|
gl_format = GL_RGBA;
|
||||||
|
gl_type = GL_FLOAT;
|
||||||
|
break;
|
||||||
|
case TextureFormat::R32F:
|
||||||
|
gl_internal_format = GL_R32F;
|
||||||
|
gl_format = GL_RED;
|
||||||
|
gl_type = GL_FLOAT;
|
||||||
|
break;
|
||||||
|
case TextureFormat::RG32F:
|
||||||
|
gl_internal_format = GL_RG32F;
|
||||||
|
gl_format = GL_RG;
|
||||||
|
gl_type = GL_FLOAT;
|
||||||
|
break;
|
||||||
|
case TextureFormat::DEPTH24_STENCIL8:
|
||||||
|
gl_internal_format = GL_DEPTH24_STENCIL8;
|
||||||
|
gl_format = GL_DEPTH_STENCIL;
|
||||||
|
gl_type = GL_UNSIGNED_INT_24_8;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
gl_internal_format = GL_RGBA8;
|
||||||
|
gl_format = GL_RGBA;
|
||||||
|
gl_type = GL_UNSIGNED_BYTE;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
glTexImage2D(GL_TEXTURE_2D, 0, gl_internal_format, desc.width, desc.height,
|
||||||
|
0, gl_format, gl_type, nullptr);
|
||||||
|
|
||||||
|
// Set filter
|
||||||
|
GLenum gl_min_filter = GL_LINEAR;
|
||||||
|
GLenum gl_mag_filter = GL_LINEAR;
|
||||||
|
|
||||||
|
switch (desc.filter) {
|
||||||
|
case TextureFilter::NEAREST:
|
||||||
|
gl_min_filter = GL_NEAREST;
|
||||||
|
gl_mag_filter = GL_NEAREST;
|
||||||
|
break;
|
||||||
|
case TextureFilter::LINEAR:
|
||||||
|
gl_min_filter = GL_LINEAR;
|
||||||
|
gl_mag_filter = GL_LINEAR;
|
||||||
|
break;
|
||||||
|
case TextureFilter::NEAREST_MIPMAP_NEAREST:
|
||||||
|
gl_min_filter = GL_NEAREST_MIPMAP_NEAREST;
|
||||||
|
gl_mag_filter = GL_NEAREST;
|
||||||
|
break;
|
||||||
|
case TextureFilter::LINEAR_MIPMAP_NEAREST:
|
||||||
|
gl_min_filter = GL_LINEAR_MIPMAP_NEAREST;
|
||||||
|
gl_mag_filter = GL_LINEAR;
|
||||||
|
break;
|
||||||
|
case TextureFilter::NEAREST_MIPMAP_LINEAR:
|
||||||
|
gl_min_filter = GL_NEAREST_MIPMAP_LINEAR;
|
||||||
|
gl_mag_filter = GL_NEAREST;
|
||||||
|
break;
|
||||||
|
case TextureFilter::LINEAR_MIPMAP_LINEAR:
|
||||||
|
gl_min_filter = GL_LINEAR_MIPMAP_LINEAR;
|
||||||
|
gl_mag_filter = GL_LINEAR;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
gl_min_filter = GL_LINEAR;
|
||||||
|
gl_mag_filter = GL_LINEAR;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, gl_min_filter);
|
||||||
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, gl_mag_filter);
|
||||||
|
|
||||||
|
// Set wrap
|
||||||
|
GLenum gl_wrap = GL_REPEAT;
|
||||||
|
switch (desc.wrap) {
|
||||||
|
case TextureWrap::REPEAT:
|
||||||
|
gl_wrap = GL_REPEAT;
|
||||||
|
break;
|
||||||
|
case TextureWrap::MIRRORED_REPEAT:
|
||||||
|
gl_wrap = GL_MIRRORED_REPEAT;
|
||||||
|
break;
|
||||||
|
case TextureWrap::CLAMP_TO_EDGE:
|
||||||
|
gl_wrap = GL_CLAMP_TO_EDGE;
|
||||||
|
break;
|
||||||
|
case TextureWrap::CLAMP_TO_BORDER:
|
||||||
|
gl_wrap = GL_CLAMP_TO_BORDER;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
gl_wrap = GL_REPEAT;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, gl_wrap);
|
||||||
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, gl_wrap);
|
||||||
|
|
||||||
|
// Generate mipmaps if requested
|
||||||
|
if (desc.generate_mipmaps) {
|
||||||
|
glGenerateMipmap(GL_TEXTURE_2D);
|
||||||
|
}
|
||||||
|
|
||||||
|
glBindTexture(GL_TEXTURE_2D, 0);
|
||||||
|
|
||||||
|
TextureResource resource;
|
||||||
|
resource.gl_handle = handle;
|
||||||
|
resource.width = desc.width;
|
||||||
|
resource.height = desc.height;
|
||||||
|
resource.format = desc.format;
|
||||||
|
textures_[handle] = resource;
|
||||||
|
|
||||||
|
ARE_LOG_DEBUG("Texture created: " + std::to_string(handle));
|
||||||
|
return handle;
|
||||||
|
}
|
||||||
|
|
||||||
|
TextureHandle ResourceManager::create_texture(uint width, uint height, TextureFormat format) {
|
||||||
|
TextureDescription desc;
|
||||||
|
desc.width = width;
|
||||||
|
desc.height = height;
|
||||||
|
desc.format = format;
|
||||||
|
return create_texture(desc);
|
||||||
|
}
|
||||||
|
|
||||||
|
TextureHandle ResourceManager::create_texture(const std::string &path) {
|
||||||
|
// Use Texture class for file loading (stb_image)
|
||||||
|
auto tex = std::make_shared<Texture>();
|
||||||
|
if (!tex->load_from_file(path, true)) {
|
||||||
|
ARE_LOG_ERROR("Failed to load texture: " + path);
|
||||||
|
return INVALID_HANDLE;
|
||||||
|
}
|
||||||
|
|
||||||
|
TextureHandle handle = tex->get_handle();
|
||||||
|
|
||||||
|
// Register in manager (but don't own - Texture class manages lifetime)
|
||||||
|
TextureResource resource;
|
||||||
|
resource.gl_handle = handle;
|
||||||
|
resource.width = tex->get_width();
|
||||||
|
resource.height = tex->get_height();
|
||||||
|
resource.format = tex->get_format();
|
||||||
|
textures_[handle] = resource;
|
||||||
|
|
||||||
|
return handle;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ResourceManager::destroy_texture(TextureHandle handle) {
|
||||||
|
auto it = textures_.find(handle);
|
||||||
|
if (it == textures_.end()) {
|
||||||
|
ARE_LOG_WARN("Attempting to destroy unknown texture: " + std::to_string(handle));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
glDeleteTextures(1, &it->second.gl_handle);
|
||||||
|
textures_.erase(it);
|
||||||
|
ARE_LOG_DEBUG("Texture destroyed: " + std::to_string(handle));
|
||||||
|
}
|
||||||
|
|
||||||
|
// === Buffer Management ===
|
||||||
|
|
||||||
|
BufferHandle ResourceManager::create_buffer(const BufferDescription &desc) {
|
||||||
|
BufferHandle handle;
|
||||||
|
glGenBuffers(1, &handle);
|
||||||
|
|
||||||
|
GLenum gl_type = GL_ARRAY_BUFFER;
|
||||||
|
switch (desc.type) {
|
||||||
|
case BufferType::VERTEX_BUFFER:
|
||||||
|
gl_type = GL_ARRAY_BUFFER;
|
||||||
|
break;
|
||||||
|
case BufferType::INDEX_BUFFER:
|
||||||
|
gl_type = GL_ELEMENT_ARRAY_BUFFER;
|
||||||
|
break;
|
||||||
|
case BufferType::UNIFORM_BUFFER:
|
||||||
|
gl_type = GL_UNIFORM_BUFFER;
|
||||||
|
break;
|
||||||
|
case BufferType::SHADER_STORAGE_BUFFER:
|
||||||
|
gl_type = GL_SHADER_STORAGE_BUFFER;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
gl_type = GL_ARRAY_BUFFER;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
GLenum gl_usage = GL_STATIC_DRAW;
|
||||||
|
switch (desc.usage) {
|
||||||
|
case BufferUsage::STATIC_DRAW:
|
||||||
|
gl_usage = GL_STATIC_DRAW;
|
||||||
|
break;
|
||||||
|
case BufferUsage::DYNAMIC_DRAW:
|
||||||
|
gl_usage = GL_DYNAMIC_DRAW;
|
||||||
|
break;
|
||||||
|
case BufferUsage::STREAM_DRAW:
|
||||||
|
gl_usage = GL_STREAM_DRAW;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
gl_usage = GL_STATIC_DRAW;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
glBindBuffer(gl_type, handle);
|
||||||
|
glBufferData(gl_type, desc.size, desc.data, gl_usage);
|
||||||
|
glBindBuffer(gl_type, 0);
|
||||||
|
|
||||||
|
BufferResource resource;
|
||||||
|
resource.gl_handle = handle;
|
||||||
|
resource.type = desc.type;
|
||||||
|
resource.usage = desc.usage;
|
||||||
|
resource.size = desc.size;
|
||||||
|
buffers_[handle] = resource;
|
||||||
|
|
||||||
|
ARE_LOG_DEBUG("Buffer created: " + std::to_string(handle) + " size: " + std::to_string(desc.size));
|
||||||
|
return handle;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ResourceManager::update_buffer(BufferHandle handle, size_t offset, size_t size, const void *data) {
|
||||||
|
auto it = buffers_.find(handle);
|
||||||
|
if (it == buffers_.end()) {
|
||||||
|
ARE_LOG_ERROR("Attempting to update unknown buffer: " + std::to_string(handle));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
GLenum gl_type = GL_ARRAY_BUFFER;
|
||||||
|
switch (it->second.type) {
|
||||||
|
case BufferType::VERTEX_BUFFER:
|
||||||
|
gl_type = GL_ARRAY_BUFFER;
|
||||||
|
break;
|
||||||
|
case BufferType::INDEX_BUFFER:
|
||||||
|
gl_type = GL_ELEMENT_ARRAY_BUFFER;
|
||||||
|
break;
|
||||||
|
case BufferType::UNIFORM_BUFFER:
|
||||||
|
gl_type = GL_UNIFORM_BUFFER;
|
||||||
|
break;
|
||||||
|
case BufferType::SHADER_STORAGE_BUFFER:
|
||||||
|
gl_type = GL_SHADER_STORAGE_BUFFER;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
gl_type = GL_ARRAY_BUFFER;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
glBindBuffer(gl_type, handle);
|
||||||
|
glBufferSubData(gl_type, offset, size, data);
|
||||||
|
glBindBuffer(gl_type, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ResourceManager::destroy_buffer(BufferHandle handle) {
|
||||||
|
auto it = buffers_.find(handle);
|
||||||
|
if (it == buffers_.end()) {
|
||||||
|
ARE_LOG_WARN("Attempting to destroy unknown buffer: " + std::to_string(handle));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
glDeleteBuffers(1, &it->second.gl_handle);
|
||||||
|
buffers_.erase(it);
|
||||||
|
ARE_LOG_DEBUG("Buffer destroyed: " + std::to_string(handle));
|
||||||
|
}
|
||||||
|
|
||||||
|
// === Framebuffer Management ===
|
||||||
|
|
||||||
|
FramebufferHandle ResourceManager::create_framebuffer(const FramebufferDescription &desc) {
|
||||||
|
FramebufferHandle fbo;
|
||||||
|
glGenFramebuffers(1, &fbo);
|
||||||
|
glBindFramebuffer(GL_FRAMEBUFFER, fbo);
|
||||||
|
|
||||||
|
FramebufferResource resource;
|
||||||
|
resource.gl_handle = fbo;
|
||||||
|
resource.width = desc.width;
|
||||||
|
resource.height = desc.height;
|
||||||
|
|
||||||
|
// Create color attachments
|
||||||
|
for (uint i = 0; i < desc.color_attachment_count; ++i) {
|
||||||
|
TextureDescription tex_desc;
|
||||||
|
tex_desc.width = desc.width;
|
||||||
|
tex_desc.height = desc.height;
|
||||||
|
tex_desc.format = TextureFormat::RGBA32F;
|
||||||
|
tex_desc.filter = TextureFilter::NEAREST;
|
||||||
|
tex_desc.wrap = TextureWrap::CLAMP_TO_EDGE;
|
||||||
|
|
||||||
|
TextureHandle color_tex = create_texture(tex_desc);
|
||||||
|
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0 + i,
|
||||||
|
GL_TEXTURE_2D, color_tex, 0);
|
||||||
|
|
||||||
|
resource.color_attachments.push_back(color_tex);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create depth attachment if requested
|
||||||
|
if (desc.create_depth) {
|
||||||
|
TextureDescription depth_desc;
|
||||||
|
depth_desc.width = desc.width;
|
||||||
|
depth_desc.height = desc.height;
|
||||||
|
depth_desc.format = TextureFormat::DEPTH24_STENCIL8;
|
||||||
|
depth_desc.filter = TextureFilter::NEAREST;
|
||||||
|
depth_desc.wrap = TextureWrap::CLAMP_TO_EDGE;
|
||||||
|
|
||||||
|
TextureHandle depth_tex = create_texture(depth_desc);
|
||||||
|
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT,
|
||||||
|
GL_TEXTURE_2D, depth_tex, 0);
|
||||||
|
|
||||||
|
resource.depth_attachment = depth_tex;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set draw buffers if color attachments exist
|
||||||
|
if (desc.color_attachment_count > 0) {
|
||||||
|
std::vector<GLenum> draw_buffers(desc.color_attachment_count);
|
||||||
|
for (uint i = 0; i < desc.color_attachment_count; ++i) {
|
||||||
|
draw_buffers[i] = GL_COLOR_ATTACHMENT0 + i;
|
||||||
|
}
|
||||||
|
glDrawBuffers(desc.color_attachment_count, draw_buffers.data());
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check completeness
|
||||||
|
if (glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE) {
|
||||||
|
ARE_LOG_ERROR("Framebuffer is not complete!");
|
||||||
|
glBindFramebuffer(GL_FRAMEBUFFER, 0);
|
||||||
|
destroy_framebuffer(fbo);
|
||||||
|
return INVALID_HANDLE;
|
||||||
|
}
|
||||||
|
|
||||||
|
glBindFramebuffer(GL_FRAMEBUFFER, 0);
|
||||||
|
|
||||||
|
framebuffers_[fbo] = resource;
|
||||||
|
|
||||||
|
ARE_LOG_DEBUG("Framebuffer created: " + std::to_string(fbo));
|
||||||
|
return fbo;
|
||||||
|
}
|
||||||
|
|
||||||
|
TextureHandle ResourceManager::get_framebuffer_color_attachment(FramebufferHandle fbo, uint index) {
|
||||||
|
auto it = framebuffers_.find(fbo);
|
||||||
|
if (it == framebuffers_.end()) {
|
||||||
|
ARE_LOG_ERROR("Invalid framebuffer handle: " + std::to_string(fbo));
|
||||||
|
return INVALID_HANDLE;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (index >= it->second.color_attachments.size()) {
|
||||||
|
ARE_LOG_ERROR("Color attachment index out of range: " + std::to_string(index));
|
||||||
|
return INVALID_HANDLE;
|
||||||
|
}
|
||||||
|
|
||||||
|
return it->second.color_attachments[index];
|
||||||
|
}
|
||||||
|
|
||||||
|
TextureHandle ResourceManager::get_framebuffer_depth_attachment(FramebufferHandle fbo) {
|
||||||
|
auto it = framebuffers_.find(fbo);
|
||||||
|
if (it == framebuffers_.end()) {
|
||||||
|
ARE_LOG_ERROR("Invalid framebuffer handle: " + std::to_string(fbo));
|
||||||
|
return INVALID_HANDLE;
|
||||||
|
}
|
||||||
|
|
||||||
|
return it->second.depth_attachment;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ResourceManager::destroy_framebuffer(FramebufferHandle fbo) {
|
||||||
|
auto it = framebuffers_.find(fbo);
|
||||||
|
if (it == framebuffers_.end()) {
|
||||||
|
ARE_LOG_WARN("Attempting to destroy unknown framebuffer: " + std::to_string(fbo));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Destroy color attachments
|
||||||
|
for (auto &color_tex : it->second.color_attachments) {
|
||||||
|
destroy_texture(color_tex);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Destroy depth attachment
|
||||||
|
if (it->second.depth_attachment != INVALID_HANDLE) {
|
||||||
|
destroy_texture(it->second.depth_attachment);
|
||||||
|
}
|
||||||
|
|
||||||
|
glDeleteFramebuffers(1, &it->second.gl_handle);
|
||||||
|
framebuffers_.erase(it);
|
||||||
|
ARE_LOG_DEBUG("Framebuffer destroyed: " + std::to_string(fbo));
|
||||||
|
}
|
||||||
|
|
||||||
|
// === Texture Array Management ===
|
||||||
|
|
||||||
|
TextureHandle ResourceManager::create_texture_array(const TextureArrayDescription &desc) {
|
||||||
|
if (desc.textures.empty()) {
|
||||||
|
ARE_LOG_WARN("Creating empty texture array");
|
||||||
|
return INVALID_HANDLE;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get dimensions from first texture
|
||||||
|
int tex_width = desc.textures[0]->get_width();
|
||||||
|
int tex_height = desc.textures[0]->get_height();
|
||||||
|
|
||||||
|
// Create texture array
|
||||||
|
GLuint tex_array;
|
||||||
|
glGenTextures(1, &tex_array);
|
||||||
|
glBindTexture(GL_TEXTURE_2D_ARRAY, tex_array);
|
||||||
|
|
||||||
|
// Allocate storage
|
||||||
|
glTexImage3D(GL_TEXTURE_2D_ARRAY, 0, GL_RGBA8, tex_width, tex_height,
|
||||||
|
static_cast<int>(desc.textures.size()), 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
|
||||||
|
|
||||||
|
// Copy each texture to array layer
|
||||||
|
for (size_t i = 0; i < desc.textures.size(); ++i) {
|
||||||
|
auto &tex = desc.textures[i];
|
||||||
|
GLuint tex_handle = tex->get_handle();
|
||||||
|
|
||||||
|
if (tex_handle == 0)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
TextureFormat orig_format = tex->get_format();
|
||||||
|
int orig_width = tex->get_width();
|
||||||
|
int orig_height = tex->get_height();
|
||||||
|
|
||||||
|
// Get format for reading
|
||||||
|
GLenum orig_gl_format = GL_RGBA;
|
||||||
|
int channels = 4;
|
||||||
|
switch (orig_format) {
|
||||||
|
case TextureFormat::R8:
|
||||||
|
orig_gl_format = GL_RED;
|
||||||
|
channels = 1;
|
||||||
|
break;
|
||||||
|
case TextureFormat::RG8:
|
||||||
|
orig_gl_format = GL_RG;
|
||||||
|
channels = 2;
|
||||||
|
break;
|
||||||
|
case TextureFormat::RGB8:
|
||||||
|
orig_gl_format = GL_RGB;
|
||||||
|
channels = 3;
|
||||||
|
break;
|
||||||
|
case TextureFormat::RGBA8:
|
||||||
|
orig_gl_format = GL_RGBA;
|
||||||
|
channels = 4;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
orig_gl_format = GL_RGBA;
|
||||||
|
channels = 4;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Read texture data
|
||||||
|
std::vector<uint8_t> orig_pixels(orig_width * orig_height * channels);
|
||||||
|
glBindTexture(GL_TEXTURE_2D, tex_handle);
|
||||||
|
glGetTexImage(GL_TEXTURE_2D, 0, orig_gl_format, GL_UNSIGNED_BYTE, orig_pixels.data());
|
||||||
|
glBindTexture(GL_TEXTURE_2D, 0);
|
||||||
|
|
||||||
|
// Convert to RGBA
|
||||||
|
std::vector<uint8_t> pixels(orig_width * orig_height * 4, 255);
|
||||||
|
for (int y = 0; y < orig_height; ++y) {
|
||||||
|
for (int x = 0; x < orig_width; ++x) {
|
||||||
|
int src_idx = (y * orig_width + x) * channels;
|
||||||
|
int dst_idx = (y * orig_width + x) * 4;
|
||||||
|
pixels[dst_idx + 0] = orig_pixels[src_idx + 0];
|
||||||
|
pixels[dst_idx + 1] = (channels >= 2) ? orig_pixels[src_idx + 1] : orig_pixels[src_idx + 0];
|
||||||
|
pixels[dst_idx + 2] = (channels >= 3) ? orig_pixels[src_idx + 2] : orig_pixels[src_idx + 0];
|
||||||
|
pixels[dst_idx + 3] = (channels >= 4) ? orig_pixels[src_idx + 3] : 255;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Upload to array layer
|
||||||
|
glTexSubImage3D(GL_TEXTURE_2D_ARRAY, 0, 0, 0, static_cast<int>(i),
|
||||||
|
tex_width, tex_height, 1, GL_RGBA, GL_UNSIGNED_BYTE, pixels.data());
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set filter
|
||||||
|
GLenum gl_min_filter = GL_LINEAR;
|
||||||
|
GLenum gl_mag_filter = GL_LINEAR;
|
||||||
|
switch (desc.filter) {
|
||||||
|
case TextureFilter::NEAREST:
|
||||||
|
gl_min_filter = GL_NEAREST;
|
||||||
|
gl_mag_filter = GL_NEAREST;
|
||||||
|
break;
|
||||||
|
case TextureFilter::LINEAR:
|
||||||
|
gl_min_filter = GL_LINEAR;
|
||||||
|
gl_mag_filter = GL_LINEAR;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
gl_min_filter = GL_LINEAR;
|
||||||
|
gl_mag_filter = GL_LINEAR;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MIN_FILTER, gl_min_filter);
|
||||||
|
glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MAG_FILTER, gl_mag_filter);
|
||||||
|
|
||||||
|
// Set wrap
|
||||||
|
GLenum gl_wrap = GL_REPEAT;
|
||||||
|
switch (desc.wrap) {
|
||||||
|
case TextureWrap::REPEAT:
|
||||||
|
gl_wrap = GL_REPEAT;
|
||||||
|
break;
|
||||||
|
case TextureWrap::CLAMP_TO_EDGE:
|
||||||
|
gl_wrap = GL_CLAMP_TO_EDGE;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
gl_wrap = GL_REPEAT;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_WRAP_S, gl_wrap);
|
||||||
|
glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_WRAP_T, gl_wrap);
|
||||||
|
|
||||||
|
glGenerateMipmap(GL_TEXTURE_2D_ARRAY);
|
||||||
|
|
||||||
|
glBindTexture(GL_TEXTURE_2D_ARRAY, 0);
|
||||||
|
|
||||||
|
TextureResource resource;
|
||||||
|
resource.gl_handle = tex_array;
|
||||||
|
resource.width = tex_width;
|
||||||
|
resource.height = tex_height;
|
||||||
|
resource.format = TextureFormat::RGBA8;
|
||||||
|
textures_[tex_array] = resource;
|
||||||
|
|
||||||
|
ARE_LOG_DEBUG("Texture array created: " + std::to_string(tex_array) + " layers: " + std::to_string(desc.textures.size()));
|
||||||
|
return tex_array;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ResourceManager::destroy_texture_array(TextureHandle handle) {
|
||||||
|
destroy_texture(handle);
|
||||||
|
}
|
||||||
|
|
||||||
|
// === VAO Management ===
|
||||||
|
|
||||||
|
VertexArrayHandle ResourceManager::create_vertex_array() {
|
||||||
|
VertexArrayHandle vao;
|
||||||
|
glGenVertexArrays(1, &vao);
|
||||||
|
ARE_LOG_DEBUG("Vertex array created: " + std::to_string(vao));
|
||||||
|
return vao;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ResourceManager::destroy_vertex_array(VertexArrayHandle vao) {
|
||||||
|
glDeleteVertexArrays(1, &vao);
|
||||||
|
ARE_LOG_DEBUG("Vertex array destroyed: " + std::to_string(vao));
|
||||||
|
}
|
||||||
|
|
||||||
|
// === Binding Management ===
|
||||||
|
|
||||||
|
void ResourceManager::bind_buffer(BufferHandle buffer, uint binding_point) {
|
||||||
|
auto it = buffers_.find(buffer);
|
||||||
|
if (it == buffers_.end()) {
|
||||||
|
ARE_LOG_ERROR("Attempting to bind unknown buffer: " + std::to_string(buffer));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
GLenum gl_type = GL_ARRAY_BUFFER;
|
||||||
|
switch (it->second.type) {
|
||||||
|
case BufferType::UNIFORM_BUFFER:
|
||||||
|
gl_type = GL_UNIFORM_BUFFER;
|
||||||
|
break;
|
||||||
|
case BufferType::SHADER_STORAGE_BUFFER:
|
||||||
|
gl_type = GL_SHADER_STORAGE_BUFFER;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
ARE_LOG_ERROR("Buffer type not supported for bind_buffer");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
glBindBufferBase(gl_type, binding_point, buffer);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ResourceManager::bind_image_texture(TextureHandle texture, uint binding, bool read, bool write) {
|
||||||
|
GLenum access = GL_READ_ONLY;
|
||||||
|
if (read && write) {
|
||||||
|
access = GL_READ_WRITE;
|
||||||
|
} else if (write) {
|
||||||
|
access = GL_WRITE_ONLY;
|
||||||
|
}
|
||||||
|
|
||||||
|
glBindImageTexture(binding, texture, 0, GL_FALSE, 0, access, GL_RGBA32F);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ResourceManager::bind_texture_to_unit(TextureHandle texture, uint unit) {
|
||||||
|
glActiveTexture(GL_TEXTURE0 + unit);
|
||||||
|
glBindTexture(GL_TEXTURE_2D, texture);
|
||||||
|
}
|
||||||
|
|
||||||
|
// === Query ===
|
||||||
|
|
||||||
|
bool ResourceManager::is_texture_valid(TextureHandle handle) const {
|
||||||
|
return textures_.find(handle) != textures_.end();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ResourceManager::is_buffer_valid(BufferHandle handle) const {
|
||||||
|
return buffers_.find(handle) != buffers_.end();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ResourceManager::is_framebuffer_valid(FramebufferHandle handle) const {
|
||||||
|
return framebuffers_.find(handle) != framebuffers_.end();
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace are
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
#include "resource/shader.h"
|
#include "resource/shader.h"
|
||||||
#include "utils/logger.h"
|
#include "utils/logger.h"
|
||||||
#include "basic/math.h" // 修改为math.h
|
#include "basic/math.h"
|
||||||
#include <glad/glad.h>
|
#include <glad/glad.h>
|
||||||
#include <fstream>
|
#include <fstream>
|
||||||
#include <sstream>
|
#include <sstream>
|
||||||
|
|
@ -19,7 +19,7 @@ Shader::Shader(Shader&& other) noexcept
|
||||||
}
|
}
|
||||||
|
|
||||||
Shader::~Shader() {
|
Shader::~Shader() {
|
||||||
// Don't auto-release, let user control lifetime
|
release();
|
||||||
}
|
}
|
||||||
|
|
||||||
Shader& Shader::operator=(Shader&& other) noexcept {
|
Shader& Shader::operator=(Shader&& other) noexcept {
|
||||||
|
|
@ -88,7 +88,7 @@ bool Shader::compile_compute(const std::string& compute_source) {
|
||||||
return success;
|
return success;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Shader::use() const { // 改为const
|
void Shader::use() const {
|
||||||
if (handle_ != INVALID_HANDLE) {
|
if (handle_ != INVALID_HANDLE) {
|
||||||
glUseProgram(handle_);
|
glUseProgram(handle_);
|
||||||
}
|
}
|
||||||
|
|
@ -102,50 +102,50 @@ void Shader::release() {
|
||||||
uniform_cache_.clear();
|
uniform_cache_.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
void Shader::set_bool(const std::string& name, bool value) const { // 新增
|
void Shader::set_bool(const std::string& name, bool value) const {
|
||||||
glUniform1i(get_uniform_location_(name), static_cast<int>(value));
|
glUniform1i(get_uniform_location_(name), static_cast<int>(value));
|
||||||
}
|
}
|
||||||
|
|
||||||
void Shader::set_int(const std::string& name, int value) const { // 改为const
|
void Shader::set_int(const std::string& name, int value) const {
|
||||||
glUniform1i(get_uniform_location_(name), value);
|
glUniform1i(get_uniform_location_(name), value);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Shader::set_uint(const std::string& name, uint value) const { // 改为const
|
void Shader::set_uint(const std::string& name, uint value) const {
|
||||||
glUniform1ui(get_uniform_location_(name), value);
|
glUniform1ui(get_uniform_location_(name), value);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Shader::set_float(const std::string& name, float value) const { // 改为const
|
void Shader::set_float(const std::string& name, float value) const {
|
||||||
glUniform1f(get_uniform_location_(name), value);
|
glUniform1f(get_uniform_location_(name), value);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Shader::set_vec2(const std::string& name, const Vec2& value) const { // 改为const
|
void Shader::set_vec2(const std::string& name, const Vec2& value) const {
|
||||||
glUniform2fv(get_uniform_location_(name), 1, &value[0]);
|
glUniform2fv(get_uniform_location_(name), 1, &value[0]);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Shader::set_vec3(const std::string& name, const Vec3& value) const { // 改为const
|
void Shader::set_vec3(const std::string& name, const Vec3& value) const {
|
||||||
glUniform3fv(get_uniform_location_(name), 1, &value[0]);
|
glUniform3fv(get_uniform_location_(name), 1, &value[0]);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Shader::set_vec4(const std::string& name, const Vec4& value) const { // 改为const
|
void Shader::set_vec4(const std::string& name, const Vec4& value) const {
|
||||||
glUniform4fv(get_uniform_location_(name), 1, &value[0]);
|
glUniform4fv(get_uniform_location_(name), 1, &value[0]);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Shader::set_mat3(const std::string& name, const Mat3& value) const { // 改为const
|
void Shader::set_mat3(const std::string& name, const Mat3& value) const {
|
||||||
glUniformMatrix3fv(get_uniform_location_(name), 1, GL_FALSE, &value[0][0]);
|
glUniformMatrix3fv(get_uniform_location_(name), 1, GL_FALSE, &value[0][0]);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Shader::set_mat4(const std::string& name, const Mat4& value) const { // 改为const
|
void Shader::set_mat4(const std::string& name, const Mat4& value) const {
|
||||||
glUniformMatrix4fv(get_uniform_location_(name), 1, GL_FALSE, MathUtils::value_ptr(value));
|
glUniformMatrix4fv(get_uniform_location_(name), 1, GL_FALSE, MathUtils::value_ptr(value));
|
||||||
}
|
}
|
||||||
|
|
||||||
int Shader::get_uniform_location_(const std::string& name) const { // 改为const
|
int Shader::get_uniform_location_(const std::string& name) const {
|
||||||
auto it = uniform_cache_.find(name);
|
auto it = uniform_cache_.find(name);
|
||||||
if (it != uniform_cache_.end()) {
|
if (it != uniform_cache_.end()) {
|
||||||
return it->second;
|
return it->second;
|
||||||
}
|
}
|
||||||
|
|
||||||
int location = glGetUniformLocation(handle_, name.c_str());
|
int location = glGetUniformLocation(handle_, name.c_str());
|
||||||
uniform_cache_[name] = location; // mutable允许修改
|
uniform_cache_[name] = location;
|
||||||
|
|
||||||
if (location == -1) {
|
if (location == -1) {
|
||||||
ARE_LOG_WARN("Uniform '" + name + "' not found in shader");
|
ARE_LOG_WARN("Uniform '" + name + "' not found in shader");
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,5 @@
|
||||||
#include "scene/mesh.h"
|
#include "scene/mesh.h"
|
||||||
|
#include "resource/resource_manager.h"
|
||||||
#include "utils/logger.h"
|
#include "utils/logger.h"
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
#include <glad/glad.h>
|
#include <glad/glad.h>
|
||||||
|
|
@ -52,21 +53,29 @@ bool Mesh::upload_to_gpu() {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ResourceManager &rm = ResourceManager::instance();
|
||||||
|
|
||||||
// Generate VAO
|
// Generate VAO
|
||||||
glGenVertexArrays(1, &vao_);
|
vao_ = rm.create_vertex_array();
|
||||||
glBindVertexArray(vao_);
|
glBindVertexArray(vao_);
|
||||||
|
|
||||||
// Generate and upload VBO
|
// Generate and upload VBO
|
||||||
glGenBuffers(1, &vbo_);
|
BufferDescription vbo_desc;
|
||||||
|
vbo_desc.type = BufferType::VERTEX_BUFFER;
|
||||||
|
vbo_desc.usage = BufferUsage::STATIC_DRAW;
|
||||||
|
vbo_desc.size = vertices_.size() * sizeof(Vertex);
|
||||||
|
vbo_desc.data = vertices_.data();
|
||||||
|
vbo_ = rm.create_buffer(vbo_desc);
|
||||||
glBindBuffer(GL_ARRAY_BUFFER, vbo_);
|
glBindBuffer(GL_ARRAY_BUFFER, vbo_);
|
||||||
glBufferData(GL_ARRAY_BUFFER, vertices_.size() * sizeof(Vertex),
|
|
||||||
vertices_.data(), GL_STATIC_DRAW);
|
|
||||||
|
|
||||||
// Generate and upload EBO
|
// Generate and upload EBO
|
||||||
glGenBuffers(1, &ebo_);
|
BufferDescription ebo_desc;
|
||||||
|
ebo_desc.type = BufferType::INDEX_BUFFER;
|
||||||
|
ebo_desc.usage = BufferUsage::STATIC_DRAW;
|
||||||
|
ebo_desc.size = indices_.size() * sizeof(uint);
|
||||||
|
ebo_desc.data = indices_.data();
|
||||||
|
ebo_ = rm.create_buffer(ebo_desc);
|
||||||
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ebo_);
|
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ebo_);
|
||||||
glBufferData(GL_ELEMENT_ARRAY_BUFFER, indices_.size() * sizeof(uint),
|
|
||||||
indices_.data(), GL_STATIC_DRAW);
|
|
||||||
|
|
||||||
// Set vertex attributes
|
// Set vertex attributes
|
||||||
// Location 0: Position
|
// Location 0: Position
|
||||||
|
|
@ -100,18 +109,20 @@ void Mesh::release_gpu_resources() {
|
||||||
if (!uploaded_)
|
if (!uploaded_)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
ResourceManager &rm = ResourceManager::instance();
|
||||||
|
|
||||||
if (vao_ != 0) {
|
if (vao_ != 0) {
|
||||||
glDeleteVertexArrays(1, &vao_);
|
rm.destroy_vertex_array(vao_);
|
||||||
vao_ = 0;
|
vao_ = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (vbo_ != 0) {
|
if (vbo_ != 0) {
|
||||||
glDeleteBuffers(1, &vbo_);
|
rm.destroy_buffer(vbo_);
|
||||||
vbo_ = 0;
|
vbo_ = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ebo_ != 0) {
|
if (ebo_ != 0) {
|
||||||
glDeleteBuffers(1, &ebo_);
|
rm.destroy_buffer(ebo_);
|
||||||
ebo_ = 0;
|
ebo_ = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue