diff --git a/.all_files.md b/.all_files.md deleted file mode 100644 index 9121de8..0000000 --- a/.all_files.md +++ /dev/null @@ -1,2820 +0,0 @@ -### 文件:src/basic/math.cpp - -```cpp -#include "basic/math.h" - -namespace are { - -Mat4 MathUtils::perspective(float fov, float aspect, float near, float far) { - return glm::perspective(fov, aspect, near, far); -} - -Mat4 MathUtils::look_at(const Vec3& eye, const Vec3& center, const Vec3& up) { - return glm::lookAt(eye, center, up); -} - -Vec3 MathUtils::normalize(const Vec3& v) { - return glm::normalize(v); -} - -float MathUtils::dot(const Vec3& a, const Vec3& b) { - return glm::dot(a, b); -} - -Vec3 MathUtils::cross(const Vec3& a, const Vec3& b) { - return glm::cross(a, b); -} - -Vec3 MathUtils::reflect(const Vec3& incident, const Vec3& normal) { - return glm::reflect(incident, normal); -} - -const float* MathUtils::value_ptr(const Mat4& mat) { - return glm::value_ptr(mat); -} - -} // namespace are -``` - -### 文件:src/core/bvh.cpp - -```cpp -#include "core/bvh.h" -#include "utils/logger.h" -#include "basic/constants.h" -#include -#include - -namespace are { - -// AABB implementation -void AABB::expand(const Vec3& point) { - min_ = glm::min(min_, point); - max_ = glm::max(max_, point); -} - -void AABB::expand(const AABB& other) { - min_ = glm::min(min_, other.min_); - max_ = glm::max(max_, other.max_); -} - -float AABB::surface_area() const { - Vec3 extent = max_ - min_; - return 2.0f * (extent.x * extent.y + extent.y * extent.z + extent.z * extent.x); -} - -bool AABB::is_valid() const { - return min_.x <= max_.x && min_.y <= max_.y && min_.z <= max_.z; -} - -// Triangle implementation -AABB Triangle::get_bounds() const { - AABB bounds(v0_, v0_); - bounds.expand(v1_); - bounds.expand(v2_); - return bounds; -} - -Vec3 Triangle::get_centroid() const { - return (v0_ + v1_ + v2_) / 3.0f; -} - -// BVH implementation -BVH::BVH() { -} - -BVH::~BVH() { - clear(); -} - -bool BVH::build(const std::vector>& meshes) { - clear(); - - Logger::info("Building BVH..."); - - // Extract all triangles from meshes - for (const auto& mesh : meshes) { - const auto& vertices = mesh->get_vertices(); - const auto& indices = mesh->get_indices(); - uint material_id = mesh->get_material(); - Mat4 transform = mesh->get_transform(); - - for (size_t i = 0; i < indices.size(); i += 3) { - Triangle tri; - - // Transform vertices - Vec4 v0 = transform * Vec4(vertices[indices[i]].position_, 1.0f); - Vec4 v1 = transform * Vec4(vertices[indices[i + 1]].position_, 1.0f); - Vec4 v2 = transform * Vec4(vertices[indices[i + 2]].position_, 1.0f); - - tri.v0_ = Vec3(v0) / v0.w; - tri.v1_ = Vec3(v1) / v1.w; - tri.v2_ = Vec3(v2) / v2.w; - - // Transform normals - Mat3 normal_matrix = glm::transpose(glm::inverse(Mat3(transform))); - tri.n0_ = glm::normalize(normal_matrix * vertices[indices[i]].normal_); - tri.n1_ = glm::normalize(normal_matrix * vertices[indices[i + 1]].normal_); - tri.n2_ = glm::normalize(normal_matrix * vertices[indices[i + 2]].normal_); - - // Copy UVs - tri.uv0_ = vertices[indices[i]].texcoord_; - tri.uv1_ = vertices[indices[i + 1]].texcoord_; - tri.uv2_ = vertices[indices[i + 2]].texcoord_; - - tri.material_id_ = material_id; - - triangles_.push_back(tri); - } - } - - if (triangles_.empty()) { - Logger::warning("No triangles to build BVH"); - return false; - } - - // Initialize triangle indices - triangle_indices_.resize(triangles_.size()); - for (size_t i = 0; i < triangles_.size(); ++i) { - triangle_indices_[i] = static_cast(i); - } - - // Reserve space for nodes (estimate) - nodes_.reserve(triangles_.size() * 2); - - // Create root node - nodes_.emplace_back(); - - // Build BVH recursively - build_recursive_(0, 0, static_cast(triangles_.size())); - - Logger::info("BVH built: " + std::to_string(nodes_.size()) + " nodes, " + - std::to_string(triangles_.size()) + " triangles"); - - return true; -} - -void BVH::build_recursive_(uint node_idx, uint first_prim, uint prim_count) { - BVHNode& node = nodes_[node_idx]; - - // Calculate bounds - AABB bounds = calculate_bounds_(first_prim, prim_count); - node.aabb_min_ = bounds.min_; - node.aabb_max_ = bounds.max_; - - // Leaf node threshold - const uint LEAF_SIZE = 4; - - if (prim_count <= LEAF_SIZE) { - // Create leaf node - node.left_first_ = first_prim; - node.count_ = prim_count; - return; - } - - // Find best split - int axis; - float split_pos; - float split_cost = find_best_split_(first_prim, prim_count, axis, split_pos); - - // Check if split is beneficial - float no_split_cost = prim_count * bounds.surface_area(); - if (split_cost >= no_split_cost) { - // Create leaf node - node.left_first_ = first_prim; - node.count_ = prim_count; - return; - } - - // Partition primitives - uint mid = first_prim; - for (uint i = first_prim; i < first_prim + prim_count; ++i) { - Triangle& tri = triangles_[triangle_indices_[i]]; - float centroid = tri.get_centroid()[axis]; - - if (centroid < split_pos) { - std::swap(triangle_indices_[i], triangle_indices_[mid]); - mid++; - } - } - - // Ensure we have primitives on both sides - if (mid == first_prim || mid == first_prim + prim_count) { - mid = first_prim + prim_count / 2; - } - - // Create interior node - uint left_count = mid - first_prim; - uint right_count = prim_count - left_count; - - node.left_first_ = static_cast(nodes_.size()); - node.count_ = 0; - - // Create child nodes - nodes_.emplace_back(); - nodes_.emplace_back(); - - // Recursively build children - build_recursive_(node.left_first_, first_prim, left_count); - build_recursive_(node.left_first_ + 1, mid, right_count); -} - -float BVH::find_best_split_(uint first_prim, uint prim_count, int& axis, float& split_pos) { - float best_cost = std::numeric_limits::max(); - - AABB centroid_bounds = calculate_centroid_bounds_(first_prim, prim_count); - - // Try each axis - for (int a = 0; a < 3; ++a) { - float extent = centroid_bounds.max_[a] - centroid_bounds.min_[a]; - if (extent < EPSILON) continue; - - // Try multiple split positions - const int NUM_BINS = 16; - for (int i = 1; i < NUM_BINS; ++i) { - float t = static_cast(i) / NUM_BINS; - float pos = centroid_bounds.min_[a] + t * extent; - - // Count primitives and calculate bounds for each side - AABB left_bounds, right_bounds; - uint left_count = 0, right_count = 0; - - for (uint j = first_prim; j < first_prim + prim_count; ++j) { - Triangle& tri = triangles_[triangle_indices_[j]]; - float centroid = tri.get_centroid()[a]; - - if (centroid < pos) { - left_bounds.expand(tri.get_bounds()); - left_count++; - } else { - right_bounds.expand(tri.get_bounds()); - right_count++; - } - } - - // Calculate SAH cost - if (left_count == 0 || right_count == 0) continue; - - float cost = left_count * left_bounds.surface_area() + - right_count * right_bounds.surface_area(); - - if (cost < best_cost) { - best_cost = cost; - axis = a; - split_pos = pos; - } - } - } - - return best_cost; -} - -AABB BVH::calculate_bounds_(uint first_prim, uint prim_count) { - AABB bounds{Vec3(std::numeric_limits::max()), - Vec3(std::numeric_limits::lowest())}; - - for (uint i = first_prim; i < first_prim + prim_count; ++i) { - Triangle& tri = triangles_[triangle_indices_[i]]; - bounds.expand(tri.get_bounds()); - } - - return bounds; -} - -AABB BVH::calculate_centroid_bounds_(uint first_prim, uint prim_count) { - AABB bounds{Vec3(std::numeric_limits::max()), - Vec3(std::numeric_limits::lowest())}; - - for (uint i = first_prim; i < first_prim + prim_count; ++i) { - Triangle& tri = triangles_[triangle_indices_[i]]; - bounds.expand(tri.get_centroid()); - } - - return bounds; -} - -bool BVH::upload_to_gpu(Buffer& node_buffer, Buffer& triangle_buffer) { - if (nodes_.empty() || triangles_.empty()) { - Logger::error("Cannot upload empty BVH to GPU"); - return false; - } - - // Reorder triangles according to BVH layout - std::vector ordered_triangles; - ordered_triangles.reserve(triangles_.size()); - - for (uint idx : triangle_indices_) { - ordered_triangles.push_back(triangles_[idx]); - } - - // Upload nodes - if (!node_buffer.create(BufferType::SHADER_STORAGE_BUFFER, - nodes_.size() * sizeof(BVHNode), - nodes_.data(), - BufferUsage::STATIC_DRAW)) { - Logger::error("Failed to upload BVH nodes to GPU"); - return false; - } - - // Upload triangles - if (!triangle_buffer.create(BufferType::SHADER_STORAGE_BUFFER, - ordered_triangles.size() * sizeof(Triangle), - ordered_triangles.data(), - BufferUsage::STATIC_DRAW)) { - Logger::error("Failed to upload BVH triangles to GPU"); - return false; - } - - Logger::info("BVH uploaded to GPU successfully"); - return true; -} - -void BVH::clear() { - nodes_.clear(); - triangles_.clear(); - triangle_indices_.clear(); -} - -} // namespace are -``` - -### 文件:src/core/gbuffer.cpp - -```cpp -#include "core/gbuffer.h" -#include "utils/logger.h" -#include - -namespace are { - -GBuffer::GBuffer(uint width, uint height) - : width_(width) - , height_(height) - , fbo_(INVALID_HANDLE) - , depth_texture_(INVALID_HANDLE) - , initialized_(false) { - for (int i = 0; i < GBUFFER_COUNT; ++i) { - textures_[i] = INVALID_HANDLE; - } -} - -GBuffer::~GBuffer() { - release(); -} - -bool GBuffer::initialize() { - if (initialized_) { - Logger::warning("GBuffer already initialized"); - return true; - } - - // Create framebuffer - glGenFramebuffers(1, &fbo_); - glBindFramebuffer(GL_FRAMEBUFFER, fbo_); - - // Create G-Buffer textures - textures_[GBUFFER_POSITION] = create_texture_(GL_RGBA32F, GL_RGBA, GL_FLOAT); - textures_[GBUFFER_NORMAL] = create_texture_(GL_RGBA32F, GL_RGBA, GL_FLOAT); - textures_[GBUFFER_ALBEDO] = create_texture_(GL_RGBA8, GL_RGBA, GL_UNSIGNED_BYTE); - - // Attach textures to framebuffer - glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0 + GBUFFER_POSITION, - GL_TEXTURE_2D, textures_[GBUFFER_POSITION], 0); - glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0 + GBUFFER_NORMAL, - GL_TEXTURE_2D, textures_[GBUFFER_NORMAL], 0); - glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0 + GBUFFER_ALBEDO, - GL_TEXTURE_2D, textures_[GBUFFER_ALBEDO], 0); - - // Create depth texture - 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, - GL_TEXTURE_2D, depth_texture_, 0); - - // Set draw buffers - GLenum draw_buffers[GBUFFER_COUNT] = { - GL_COLOR_ATTACHMENT0 + GBUFFER_POSITION, - GL_COLOR_ATTACHMENT0 + GBUFFER_NORMAL, - GL_COLOR_ATTACHMENT0 + GBUFFER_ALBEDO - }; - glDrawBuffers(GBUFFER_COUNT, draw_buffers); - - // Check framebuffer completeness - if (glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE) { - Logger::error("GBuffer framebuffer is not complete"); - glBindFramebuffer(GL_FRAMEBUFFER, 0); - return false; - } - - glBindFramebuffer(GL_FRAMEBUFFER, 0); - - initialized_ = true; - Logger::info("GBuffer initialized successfully"); - return true; -} - -void GBuffer::release() { - if (!initialized_) return; - - if (fbo_ != INVALID_HANDLE) { - glDeleteFramebuffers(1, &fbo_); - fbo_ = INVALID_HANDLE; - } - - for (int i = 0; i < GBUFFER_COUNT; ++i) { - if (textures_[i] != INVALID_HANDLE) { - glDeleteTextures(1, &textures_[i]); - textures_[i] = INVALID_HANDLE; - } - } - - if (depth_texture_ != INVALID_HANDLE) { - glDeleteTextures(1, &depth_texture_); - depth_texture_ = INVALID_HANDLE; - } - - initialized_ = false; - Logger::info("GBuffer released"); -} - -void GBuffer::render(const Scene& scene, const Shader& shader) { - if (!initialized_) { - Logger::error("GBuffer not initialized"); - return; - } - - // Bind framebuffer - glBindFramebuffer(GL_FRAMEBUFFER, fbo_); - glViewport(0, 0, width_, height_); - - // Clear buffers - glClearColor(0.0f, 0.0f, 0.0f, 0.0f); - glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); - - // Enable depth test - glEnable(GL_DEPTH_TEST); - glDepthFunc(GL_LESS); - - // Use shader - shader.use(); - - // Set camera matrices - const Camera& camera = scene.get_camera(); - Mat4 view = camera.get_view_matrix(); - Mat4 projection = camera.get_projection_matrix(); - - shader.set_mat4("u_view", view); - shader.set_mat4("u_projection", projection); - - // Render all meshes - const auto& meshes = scene.get_meshes(); - const auto& materials = scene.get_materials(); - - for (const auto& mesh : meshes) { - if (!mesh->is_uploaded()) { - Logger::warning("Mesh not uploaded to GPU, skipping"); - continue; - } - - // Set model matrix - Mat4 model = mesh->get_transform(); - shader.set_mat4("u_model", model); - - // Set material properties - uint material_id = mesh->get_material(); - if (material_id < materials.size()) { - const auto& material = materials[material_id]; - - shader.set_vec3("u_albedo", material->get_albedo()); - shader.set_float("u_metallic", material->get_metallic()); - shader.set_float("u_roughness", material->get_roughness()); - shader.set_uint("u_material_id", material_id); - - // Bind textures - auto albedo_tex = material->get_albedo_texture(); - if (albedo_tex && albedo_tex->is_valid()) { - albedo_tex->bind(0); - shader.set_int("u_albedo_map", 0); - shader.set_int("u_has_albedo_map", 1); - } else { - shader.set_int("u_has_albedo_map", 0); - } - - auto normal_tex = material->get_normal_texture(); - if (normal_tex && normal_tex->is_valid()) { - normal_tex->bind(1); - shader.set_int("u_normal_map", 1); - shader.set_int("u_has_normal_map", 1); - } else { - shader.set_int("u_has_normal_map", 0); - } - } - - // Draw mesh - glBindVertexArray(mesh->get_vao()); - glDrawElements(GL_TRIANGLES, mesh->get_indices().size(), GL_UNSIGNED_INT, 0); - glBindVertexArray(0); - } - - // Unbind framebuffer - glBindFramebuffer(GL_FRAMEBUFFER, 0); -} - -void GBuffer::resize(uint width, uint height) { - if (width == width_ && height == height_) return; - - width_ = width; - height_ = height; - - if (initialized_) { - release(); - initialize(); - } -} - -TextureHandle GBuffer::get_texture(int index) const { - if (index < 0 || index >= GBUFFER_COUNT) { - Logger::error("Invalid G-Buffer texture index"); - return INVALID_HANDLE; - } - return textures_[index]; -} - -void GBuffer::get_dimensions(uint& width, uint& height) const { - width = width_; - height = height_; -} - -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; -} - -} // namespace are -``` - -### 文件:src/core/raytracer.cpp - -```cpp -#include "core/raytracer.h" -#include "utils/logger.h" -#include "basic/constants.h" -#include - -namespace are { - -RayTracer::RayTracer(uint width, uint height, const RayTracerConfig& config) - : width_(width) - , height_(height) - , config_(config) - , accumulation_texture_(INVALID_HANDLE) - , scene_buffer_(INVALID_HANDLE) - , material_buffer_(INVALID_HANDLE) - , light_buffer_(INVALID_HANDLE) - , bvh_(nullptr) - , bvh_built_(false) - , frame_count_(0) - , initialized_(false) { -} - -RayTracer::~RayTracer() { - release(); -} - -bool RayTracer::initialize() { - if (initialized_) { - Logger::warning("RayTracer already initialized"); - return true; - } - - // Create accumulation texture - glGenTextures(1, &accumulation_texture_); - 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 - glGenBuffers(1, &material_buffer_); - glGenBuffers(1, &light_buffer_); - - // Load compute shader - Logger::info("Loading ray tracing compute shader in RayTracer..."); - if (!compute_shader_.load_compute("shaders/raytracing.comp")) { - Logger::error("Failed to load ray tracing compute shader in RayTracer"); - return false; - } - Logger::info("Ray tracing compute shader loaded in RayTracer"); - - // Initialize BVH if enabled - if (config_.use_bvh_) { - bvh_ = std::make_unique(); - } - - initialized_ = true; - Logger::info("RayTracer initialized successfully"); - return true; -} - -void RayTracer::release() { - if (!initialized_) return; - - if (accumulation_texture_ != INVALID_HANDLE) { - glDeleteTextures(1, &accumulation_texture_); - accumulation_texture_ = INVALID_HANDLE; - } - - if (material_buffer_ != INVALID_HANDLE) { - glDeleteBuffers(1, &material_buffer_); - material_buffer_ = INVALID_HANDLE; - } - - if (light_buffer_ != INVALID_HANDLE) { - glDeleteBuffers(1, &light_buffer_); - light_buffer_ = INVALID_HANDLE; - } - - bvh_node_buffer_.release(); - bvh_triangle_buffer_.release(); - - compute_shader_.release(); - - bvh_.reset(); - bvh_built_ = false; - - initialized_ = false; - Logger::info("RayTracer released"); -} - -bool RayTracer::rebuild_bvh(const Scene& scene) { - if (!config_.use_bvh_) { - Logger::warning("BVH is disabled in configuration"); - return false; - } - - if (!bvh_) { - bvh_ = std::make_unique(); - } - - Logger::info("Building BVH for ray tracing..."); - - if (!bvh_->build(scene.get_meshes())) { - Logger::error("Failed to build BVH"); - return false; - } - - if (!bvh_->upload_to_gpu(bvh_node_buffer_, bvh_triangle_buffer_)) { - Logger::error("Failed to upload BVH to GPU"); - return false; - } - - bvh_built_ = true; - Logger::info("BVH built and uploaded successfully"); - return true; -} - -void RayTracer::trace(const Scene& scene, const GBuffer& gbuffer, TextureHandle output_texture) { - if (!initialized_) { - Logger::error("RayTracer not initialized"); - return; - } - - if (!compute_shader_.is_valid()) { - Logger::error("Ray tracing compute shader not loaded"); - return; - } - - // Build BVH if enabled and not built yet - if (config_.use_bvh_ && !bvh_built_) { - rebuild_bvh(scene); - } - - // Upload scene data - upload_scene_data_(scene); - - // Use compute shader - compute_shader_.use(); - - // Bind G-Buffer textures - bind_gbuffer_(gbuffer); - - // Bind output and accumulation textures - glBindImageTexture(3, output_texture, 0, GL_FALSE, 0, GL_WRITE_ONLY, GL_RGBA32F); - glBindImageTexture(4, accumulation_texture_, 0, GL_FALSE, 0, GL_READ_WRITE, GL_RGBA32F); - - // Bind BVH buffers if enabled - if (config_.use_bvh_ && bvh_built_) { - bvh_node_buffer_.bind_base(2); - bvh_triangle_buffer_.bind_base(3); - compute_shader_.set_bool("u_use_bvh", true); - compute_shader_.set_uint("u_bvh_node_count", bvh_->get_node_count()); - } else { - compute_shader_.set_bool("u_use_bvh", false); - } - - // Set uniforms - compute_shader_.set_uint("u_frame_count", frame_count_); - compute_shader_.set_uint("u_samples_per_pixel", config_.samples_per_pixel_); - compute_shader_.set_uint("u_max_depth", config_.max_depth_); - compute_shader_.set_uint("u_light_count", static_cast(scene.get_lights().size())); - compute_shader_.set_bool("u_enable_accumulation", config_.enable_accumulation_); - - // Set camera data - const Camera& camera = scene.get_camera(); - compute_shader_.set_vec3("u_camera_position", camera.get_position()); - - Mat4 inv_vp = glm::inverse(camera.get_view_projection_matrix()); - compute_shader_.set_mat4("u_inv_view_projection", inv_vp); - - // Dispatch compute shader - uint num_groups_x = (width_ + COMPUTE_GROUP_SIZE_X - 1) / COMPUTE_GROUP_SIZE_X; - uint num_groups_y = (height_ + COMPUTE_GROUP_SIZE_Y - 1) / COMPUTE_GROUP_SIZE_Y; - - glDispatchCompute(num_groups_x, num_groups_y, 1); - - // Memory barrier - glMemoryBarrier(GL_SHADER_IMAGE_ACCESS_BARRIER_BIT); - - // Increment frame count for accumulation - if (config_.enable_accumulation_) { - frame_count_++; - } -} - -void RayTracer::resize(uint width, uint height) { - if (width == width_ && height == height_) return; - - width_ = width; - height_ = height; - - if (initialized_) { - // Recreate accumulation texture - if (accumulation_texture_ != INVALID_HANDLE) { - glDeleteTextures(1, &accumulation_texture_); - } - - glGenTextures(1, &accumulation_texture_); - 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(); - } -} - -void RayTracer::reset_accumulation() { - frame_count_ = 0; -} - -void RayTracer::set_config(const RayTracerConfig& config) { - bool bvh_changed = (config.use_bvh_ != config_.use_bvh_); - - config_ = config; - reset_accumulation(); - - if (bvh_changed) { - if (config_.use_bvh_ && !bvh_) { - bvh_ = std::make_unique(); - bvh_built_ = false; - } else if (!config_.use_bvh_) { - bvh_.reset(); - bvh_built_ = false; - } - } -} - -void RayTracer::upload_scene_data_(const Scene& scene) { - // Upload materials - const auto& materials = scene.get_materials(); - if (!materials.empty()) { - struct MaterialData { - Vec3 albedo; - float metallic; - Vec3 emission; - float roughness; - int type; - float ior; - Vec2 padding; - }; - - std::vector material_data; - material_data.reserve(materials.size()); - - for (const auto& mat : materials) { - MaterialData data; - data.albedo = mat->get_albedo(); - data.metallic = mat->get_metallic(); - data.emission = mat->get_emission(); - data.roughness = mat->get_roughness(); - data.type = static_cast(mat->get_type()); - data.ior = mat->get_ior(); - material_data.push_back(data); - } - - glBindBuffer(GL_SHADER_STORAGE_BUFFER, material_buffer_); - glBufferData(GL_SHADER_STORAGE_BUFFER, - material_data.size() * sizeof(MaterialData), - material_data.data(), GL_DYNAMIC_DRAW); - glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, material_buffer_); - } - - // Upload lights - const auto& lights = scene.get_lights(); - if (!lights.empty()) { - struct LightData { - Vec3 position; - int type; - Vec3 direction; - float intensity; - Vec3 color; - float range; - Vec2 spot_angles; - Vec2 padding; - }; - - std::vector light_data; - light_data.reserve(lights.size()); - - for (const auto& light : lights) { - LightData data; - data.position = light->get_position(); - data.type = static_cast(light->get_type()); - data.direction = light->get_direction(); - data.intensity = light->get_intensity(); - data.color = light->get_color(); - data.range = light->get_range(); - data.spot_angles = Vec2(light->get_inner_angle(), light->get_outer_angle()); - light_data.push_back(data); - } - - glBindBuffer(GL_SHADER_STORAGE_BUFFER, light_buffer_); - glBufferData(GL_SHADER_STORAGE_BUFFER, - light_data.size() * sizeof(LightData), - light_data.data(), GL_DYNAMIC_DRAW); - glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 1, light_buffer_); - } -} - -void RayTracer::bind_gbuffer_(const GBuffer& gbuffer) { - glBindImageTexture(0, gbuffer.get_texture(GBUFFER_POSITION), 0, GL_FALSE, 0, GL_READ_ONLY, GL_RGBA32F); - glBindImageTexture(1, gbuffer.get_texture(GBUFFER_NORMAL), 0, GL_FALSE, 0, GL_READ_ONLY, GL_RGBA32F); - glBindImageTexture(2, gbuffer.get_texture(GBUFFER_ALBEDO), 0, GL_FALSE, 0, GL_READ_ONLY, GL_RGBA8); -} - -void RayTracer::set_compute_shader(const Shader& shader) { - compute_shader_ = shader; - Logger::info("Compute shader set for RayTracer"); -} - -} // namespace are -``` - -### 文件:src/core/renderer.cpp - -```cpp -#include "core/renderer.h" -#include "utils/logger.h" -#include -#include - -namespace are { - -Renderer::Renderer(const RendererConfig &config) - : config_(config) - , initialized_(false) - , frame_count_(0) { -} - -Renderer::~Renderer() { - shutdown(); -} - -bool Renderer::initialize() { - if (initialized_) { - Logger::warning("Renderer already initialized"); - return true; - } - - Logger::info("Initializing Aurora Rendering Engine..."); - - // Initialize shader manager - shader_manager_ = std::make_unique(); - if (!shader_manager_->initialize()) { - Logger::error("Failed to initialize shader manager"); - return false; - } - - // Initialize G-Buffer - gbuffer_ = std::make_unique(config_.width_, config_.height_); - if (!gbuffer_->initialize()) { - Logger::error("Failed to initialize G-Buffer"); - return false; - } - - // Initialize ray tracer - RayTracerConfig rt_config; - rt_config.samples_per_pixel_ = config_.samples_per_pixel_; - rt_config.max_depth_ = config_.max_ray_depth_; - rt_config.enable_shadows_ = true; - rt_config.enable_reflections_ = true; - rt_config.enable_accumulation_ = config_.enable_accumulation_; - rt_config.use_bvh_ = true; - - raytracer_ = std::make_unique(config_.width_, config_.height_, rt_config); - if (!raytracer_->initialize()) { - Logger::error("Failed to initialize ray tracer"); - return false; - } - - // Pass compute shader to ray tracer - const Shader& rt_shader = shader_manager_->get_raytracing_shader(); - if (!rt_shader.is_valid()) { - Logger::error("Ray tracing shader is invalid"); - return false; - } - raytracer_->set_compute_shader(rt_shader); - - // Initialize screen blit - screen_blit_ = std::make_unique(); - if (!screen_blit_->initialize()) { - Logger::error("Failed to initialize screen blit"); - return false; - } - - initialized_ = true; - Logger::info("Aurora Rendering Engine initialized successfully"); - return true; -} - -void Renderer::shutdown() { - if (!initialized_) - return; - - Logger::info("Shutting down Aurora Rendering Engine..."); - - if (screen_blit_) { - screen_blit_->release(); - screen_blit_.reset(); - } - - if (raytracer_) { - raytracer_->release(); - raytracer_.reset(); - } - - if (gbuffer_) { - gbuffer_->release(); - gbuffer_.reset(); - } - - if (shader_manager_) { - shader_manager_->release(); - shader_manager_.reset(); - } - - initialized_ = false; - Logger::info("Aurora Rendering Engine shut down"); -} - -RenderStats Renderer::render(const Scene& scene, TextureHandle output_texture) { - RenderStats stats = {}; - - if (!initialized_) { - Logger::error("Renderer not initialized"); - return stats; - } - - // Start timing - auto start_time = std::chrono::high_resolution_clock::now(); - - // Phase 1: G-Buffer pass - auto gbuffer_start = std::chrono::high_resolution_clock::now(); - - const Shader& gbuffer_shader = shader_manager_->get_gbuffer_shader(); - gbuffer_->render(scene, gbuffer_shader); - - auto gbuffer_end = std::chrono::high_resolution_clock::now(); - stats.gbuffer_time_ms_ = std::chrono::duration(gbuffer_end - gbuffer_start).count(); - - // Phase 2: Ray tracing pass - auto raytrace_start = std::chrono::high_resolution_clock::now(); - - // Create output texture if not provided - TextureHandle rt_output = 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); - - auto raytrace_end = std::chrono::high_resolution_clock::now(); - stats.raytrace_time_ms_ = std::chrono::duration(raytrace_end - raytrace_start).count(); - - // Phase 3: Blit to screen if output is default framebuffer - if (created_temp_texture && output_texture == 0) { - screen_blit_->blit_fullscreen(rt_output); - glDeleteTextures(1, &rt_output); - } - - // Calculate total frame time - auto end_time = std::chrono::high_resolution_clock::now(); - stats.frame_time_ms_ = std::chrono::duration(end_time - start_time).count(); - - // Count triangles - const auto& meshes = scene.get_meshes(); - for (const auto& mesh : meshes) { - stats.triangle_count_ += mesh->get_indices().size() / 3; - } - - // Estimate ray count (very rough) - stats.ray_count_ = config_.width_ * config_.height_ * config_.samples_per_pixel_ * config_.max_ray_depth_; - - frame_count_++; - - return stats; -} - -void Renderer::resize(uint width, uint height) { - if (width == config_.width_ && height == config_.height_) - return; - - config_.width_ = width; - config_.height_ = height; - - if (initialized_) { - gbuffer_->resize(width, height); - raytracer_->resize(width, height); - - Logger::info("Renderer resized to " + std::to_string(width) + "x" + std::to_string(height)); - } -} - -void Renderer::set_config(const RendererConfig &config) { - bool size_changed = (config.width_ != config_.width_ || config.height_ != config_.height_); - - config_ = config; - - if (initialized_) { - if (size_changed) { - resize(config_.width_, config_.height_); - } - - // Update ray tracer config - RayTracerConfig rt_config = raytracer_->get_config(); - rt_config.samples_per_pixel_ = config_.samples_per_pixel_; - rt_config.max_depth_ = config_.max_ray_depth_; - rt_config.enable_accumulation_ = config_.enable_accumulation_; - raytracer_->set_config(rt_config); - } -} - -} // namespace are -``` - -### 文件:src/core/screen_blit.cpp - -```cpp -#include "core/screen_blit.h" -#include "utils/logger.h" -#include - -namespace are { - -namespace { - const char* VERTEX_SHADER_SOURCE = R"( - #version 430 core - layout(location = 0) in vec2 a_position; - layout(location = 1) in vec2 a_texcoord; - - out vec2 v_texcoord; - - void main() { - v_texcoord = a_texcoord; - gl_Position = vec4(a_position, 0.0, 1.0); - } - )"; - - const char* FRAGMENT_SHADER_SOURCE = R"( - #version 430 core - in vec2 v_texcoord; - out vec4 frag_color; - - uniform sampler2D u_texture; - - void main() { - frag_color = texture(u_texture, v_texcoord); - } - )"; -} - -ScreenBlit::ScreenBlit() - : vao_(0) - , vbo_(0) - , initialized_(false) { -} - -ScreenBlit::~ScreenBlit() { - release(); -} - -bool ScreenBlit::initialize() { - if (initialized_) { - Logger::warning("ScreenBlit already initialized"); - return true; - } - - // Compile shader - if (!shader_.compile(VERTEX_SHADER_SOURCE, FRAGMENT_SHADER_SOURCE)) { - Logger::error("Failed to compile screen blit shader"); - return false; - } - - // Create fullscreen quad - create_quad_(); - - initialized_ = true; - Logger::info("ScreenBlit initialized successfully"); - return true; -} - -void ScreenBlit::release() { - if (!initialized_) return; - - shader_.release(); - - if (vao_ != 0) { - glDeleteVertexArrays(1, &vao_); - vao_ = 0; - } - - if (vbo_ != 0) { - glDeleteBuffers(1, &vbo_); - vbo_ = 0; - } - - initialized_ = false; -} - -void ScreenBlit::blit(TextureHandle texture, int x, int y, uint width, uint height) { - if (!initialized_) { - Logger::error("ScreenBlit not initialized"); - return; - } - - // Set viewport - glViewport(x, y, width, height); - - // Disable depth test - glDisable(GL_DEPTH_TEST); - - // Use shader - shader_.use(); - shader_.set_int("u_texture", 0); - - // Bind texture - glActiveTexture(GL_TEXTURE0); - glBindTexture(GL_TEXTURE_2D, texture); - - // Draw quad - glBindVertexArray(vao_); - glDrawArrays(GL_TRIANGLES, 0, 6); - glBindVertexArray(0); - - // Re-enable depth test - glEnable(GL_DEPTH_TEST); -} - -void ScreenBlit::blit_fullscreen(TextureHandle texture) { - GLint viewport[4]; - glGetIntegerv(GL_VIEWPORT, viewport); - blit(texture, viewport[0], viewport[1], viewport[2], viewport[3]); -} - -void ScreenBlit::create_quad_() { - // Fullscreen quad vertices (position + texcoord) - float vertices[] = { - // Position // TexCoord - -1.0f, -1.0f, 0.0f, 0.0f, - 1.0f, -1.0f, 1.0f, 0.0f, - 1.0f, 1.0f, 1.0f, 1.0f, - - -1.0f, -1.0f, 0.0f, 0.0f, - 1.0f, 1.0f, 1.0f, 1.0f, - -1.0f, 1.0f, 0.0f, 1.0f - }; - - glGenVertexArrays(1, &vao_); - glGenBuffers(1, &vbo_); - - glBindVertexArray(vao_); - glBindBuffer(GL_ARRAY_BUFFER, vbo_); - glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW); - - // Position attribute - glEnableVertexAttribArray(0); - glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 4 * sizeof(float), (void*)0); - - // TexCoord attribute - glEnableVertexAttribArray(1); - glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 4 * sizeof(float), (void*)(2 * sizeof(float))); - - glBindVertexArray(0); -} - -} // namespace are -``` - -### 文件:src/core/shader_manager.cpp - -```cpp -#include "core/shader_manager.h" -#include "utils/logger.h" - -namespace are { - -ShaderManager::ShaderManager() - : initialized_(false) { -} - -ShaderManager::~ShaderManager() { - release(); -} - -bool ShaderManager::initialize() { - if (initialized_) { - Logger::warning("ShaderManager already initialized"); - return true; - } - - Logger::info("Loading built-in shaders..."); - - if (!load_builtin_shaders_()) { - Logger::error("Failed to load built-in shaders"); - return false; - } - - initialized_ = true; - Logger::info("ShaderManager initialized successfully"); - return true; -} - -void ShaderManager::release() { - if (!initialized_) return; - - gbuffer_shader_.release(); - raytracing_shader_.release(); - - for (auto& pair : shader_cache_) { - pair.second.release(); - } - shader_cache_.clear(); - - initialized_ = false; - Logger::info("ShaderManager released"); -} - -Shader ShaderManager::load_shader(const std::string& name, - const std::string& vertex_path, - const std::string& fragment_path) { - // Check cache - auto it = shader_cache_.find(name); - if (it != shader_cache_.end()) { - Logger::info("Shader '" + name + "' loaded from cache"); - return it->second; - } - - // Load shader - Shader shader; - if (!shader.load(vertex_path, fragment_path)) { - Logger::error("Failed to load shader '" + name + "'"); - return Shader(); - } - - shader_cache_[name] = shader; - Logger::info("Shader '" + name + "' loaded successfully"); - return shader; -} - -Shader ShaderManager::load_compute_shader(const std::string& name, - const std::string& compute_path) { - // Check cache - auto it = shader_cache_.find(name); - if (it != shader_cache_.end()) { - Logger::info("Compute shader '" + name + "' loaded from cache"); - return it->second; - } - - // Load shader - Shader shader; - if (!shader.load_compute(compute_path)) { - Logger::error("Failed to load compute shader '" + name + "'"); - return Shader(); - } - - shader_cache_[name] = shader; - Logger::info("Compute shader '" + name + "' loaded successfully"); - return shader; -} - -Shader ShaderManager::get_shader(const std::string& name) const { - auto it = shader_cache_.find(name); - if (it != shader_cache_.end()) { - return it->second; - } - - Logger::warning("Shader '" + name + "' not found in cache"); - return Shader(); -} - -bool ShaderManager::load_builtin_shaders_() { - // Load G-Buffer shader - if (!gbuffer_shader_.load("shaders/gbuffer.vert", "shaders/gbuffer.frag")) { - Logger::error("Failed to load G-Buffer shader"); - return false; - } - shader_cache_["gbuffer"] = gbuffer_shader_; - - // Load ray tracing compute shader - if (!raytracing_shader_.load_compute("shaders/raytracing.comp")) { - Logger::error("Failed to load ray tracing shader"); - return false; - } - shader_cache_["raytracing"] = raytracing_shader_; - - // Load ray tracing compute shader - Logger::info("Loading ray tracing compute shader..."); - if (!raytracing_shader_.load_compute("shaders/raytracing.comp")) { - Logger::error("Failed to load ray tracing shader"); - return false; - } - shader_cache_["raytracing"] = raytracing_shader_; - Logger::info("Ray tracing shader loaded successfully"); - - return true; -} - -} // namespace are -``` - -### 文件:src/scene/camera.cpp - -```cpp -#include "scene/camera.h" -#include "basic/math.h" -#include - -namespace are { - -Camera::Camera() - : position_(0.0f, 0.0f, 5.0f) - , target_(0.0f, 0.0f, 0.0f) - , up_(0.0f, 1.0f, 0.0f) - , projection_type_(ProjectionType::PERSPECTIVE) - , fov_(glm::radians(45.0f)) - , aspect_(16.0f / 9.0f) - , left_(-1.0f) - , right_(1.0f) - , bottom_(-1.0f) - , top_(1.0f) - , near_(0.1f) - , far_(100.0f) - , view_dirty_(true) - , projection_dirty_(true) { -} - -Camera::~Camera() { -} - -void Camera::set_perspective(float fov, float aspect, float near, float far) { - projection_type_ = ProjectionType::PERSPECTIVE; - fov_ = glm::radians(fov); - aspect_ = aspect; - near_ = near; - far_ = far; - projection_dirty_ = true; -} - -void Camera::set_orthographic(float left, float right, float bottom, float top, float near, float far) { - projection_type_ = ProjectionType::ORTHOGRAPHIC; - left_ = left; - right_ = right; - bottom_ = bottom; - top_ = top; - near_ = near; - far_ = far; - projection_dirty_ = true; -} - -void Camera::set_position(const Vec3& position) { - position_ = position; - view_dirty_ = true; -} - -void Camera::set_target(const Vec3& target) { - target_ = target; - view_dirty_ = true; -} - -void Camera::set_up(const Vec3& up) { - up_ = up; - view_dirty_ = true; -} - -Mat4 Camera::get_view_matrix() const { - if (view_dirty_) { - view_matrix_ = MathUtils::look_at(position_, target_, up_); - view_dirty_ = false; - } - return view_matrix_; -} - -Mat4 Camera::get_projection_matrix() const { - if (projection_dirty_) { - if (projection_type_ == ProjectionType::PERSPECTIVE) { - projection_matrix_ = MathUtils::perspective(fov_, aspect_, near_, far_); - } else { - projection_matrix_ = glm::ortho(left_, right_, bottom_, top_, near_, far_); - } - projection_dirty_ = false; - } - return projection_matrix_; -} - -Mat4 Camera::get_view_projection_matrix() const { - return get_projection_matrix() * get_view_matrix(); -} - -Vec3 Camera::get_forward() const { - return MathUtils::normalize(target_ - position_); -} - -Vec3 Camera::get_right() const { - Vec3 forward = get_forward(); - return MathUtils::normalize(MathUtils::cross(forward, up_)); -} - -Vec3 Camera::get_up() const { - Vec3 forward = get_forward(); - Vec3 right = get_right(); - return MathUtils::cross(right, forward); -} - -} // namespace are -``` - -### 文件:src/scene/material.cpp - -```cpp -#include "scene/material.h" - -namespace are { - -Material::Material() - : albedo_(1.0f, 1.0f, 1.0f) - , emission_(0.0f, 0.0f, 0.0f) - , metallic_(0.0f) - , roughness_(0.5f) - , ior_(1.5f) - , type_(MaterialType::DIFFUSE) - , albedo_texture_(nullptr) - , normal_texture_(nullptr) { -} - -Material::~Material() { -} - -void Material::set_albedo(const Vec3& albedo) { - albedo_ = albedo; -} - -void Material::set_emission(const Vec3& emission) { - emission_ = emission; -} - -void Material::set_metallic(float metallic) { - metallic_ = glm::clamp(metallic, 0.0f, 1.0f); -} - -void Material::set_roughness(float roughness) { - roughness_ = glm::clamp(roughness, 0.0f, 1.0f); -} - -void Material::set_ior(float ior) { - ior_ = ior; -} - -void Material::set_type(MaterialType type) { - type_ = type; -} - -void Material::set_albedo_texture(std::shared_ptr texture) { - albedo_texture_ = texture; -} - -void Material::set_normal_texture(std::shared_ptr texture) { - normal_texture_ = texture; -} - -} // namespace are -``` - -### 文件:src/scene/light.cpp - -```cpp -#include "scene/light.h" -#include - -namespace are { - -Light::Light() - : type_(LightType::POINT) - , position_(0.0f, 5.0f, 0.0f) - , direction_(0.0f, -1.0f, 0.0f) - , color_(1.0f, 1.0f, 1.0f) - , intensity_(1.0f) - , range_(10.0f) - , inner_angle_(glm::radians(30.0f)) - , outer_angle_(glm::radians(45.0f)) { -} - -Light::~Light() { -} - -void Light::set_type(LightType type) { - type_ = type; -} - -void Light::set_position(const Vec3& position) { - position_ = position; -} - -void Light::set_direction(const Vec3& direction) { - direction_ = glm::normalize(direction); -} - -void Light::set_color(const Vec3& color) { - color_ = color; -} - -void Light::set_intensity(float intensity) { - intensity_ = intensity; -} - -void Light::set_range(float range) { - range_ = range; -} - -void Light::set_spot_angles(float inner_angle, float outer_angle) { - inner_angle_ = glm::radians(inner_angle); - outer_angle_ = glm::radians(outer_angle); -} - -} // namespace are -``` - -### 文件:src/scene/scene.cpp - -```cpp -#include "scene/scene.h" - -namespace are { - -Scene::Scene() { - // Create default camera - camera_ = std::make_shared(); -} - -Scene::~Scene() { - clear(); -} - -uint Scene::add_mesh(std::shared_ptr mesh) { - meshes_.push_back(mesh); - return static_cast(meshes_.size() - 1); -} - -uint Scene::add_material(std::shared_ptr material) { - materials_.push_back(material); - return static_cast(materials_.size() - 1); -} - -uint Scene::add_light(std::shared_ptr light) { - lights_.push_back(light); - return static_cast(lights_.size() - 1); -} - -void Scene::set_camera(std::shared_ptr camera) { - camera_ = camera; -} - -void Scene::clear() { - meshes_.clear(); - materials_.clear(); - lights_.clear(); -} - -void Scene::update(float delta_time) { - // Reserved for future animation/physics updates - (void)delta_time; // Suppress unused parameter warning -} - -} // namespace are -``` - -### 文件:src/scene/mesh.cpp - -```cpp -#include "scene/mesh.h" -#include "utils/logger.h" -#include - -namespace are { - -Mesh::Mesh() - : material_id_(0) - , transform_(1.0f) - , vao_(0) - , vbo_(0) - , ebo_(0) - , uploaded_(false) { -} - -Mesh::~Mesh() { - release_gpu_resources(); -} - -void Mesh::set_vertices(const std::vector& vertices) { - vertices_ = vertices; - uploaded_ = false; -} - -void Mesh::set_indices(const std::vector& indices) { - indices_ = indices; - uploaded_ = false; -} - -void Mesh::set_material(uint material_id) { - material_id_ = material_id; -} - -void Mesh::set_transform(const Mat4& transform) { - transform_ = transform; -} - -bool Mesh::upload_to_gpu() { - if (uploaded_) { - Logger::warning("Mesh already uploaded to GPU"); - return true; - } - - if (vertices_.empty()) { - Logger::error("Cannot upload mesh: no vertices"); - return false; - } - - if (indices_.empty()) { - Logger::error("Cannot upload mesh: no indices"); - return false; - } - - // Generate VAO - glGenVertexArrays(1, &vao_); - glBindVertexArray(vao_); - - // Generate and upload VBO - glGenBuffers(1, &vbo_); - glBindBuffer(GL_ARRAY_BUFFER, vbo_); - glBufferData(GL_ARRAY_BUFFER, vertices_.size() * sizeof(Vertex), - vertices_.data(), GL_STATIC_DRAW); - - // Generate and upload EBO - glGenBuffers(1, &ebo_); - glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ebo_); - glBufferData(GL_ELEMENT_ARRAY_BUFFER, indices_.size() * sizeof(uint), - indices_.data(), GL_STATIC_DRAW); - - // Set vertex attributes - // Location 0: Position - glEnableVertexAttribArray(0); - glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, sizeof(Vertex), - (void*)offsetof(Vertex, position_)); - - // Location 1: Normal - glEnableVertexAttribArray(1); - glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, sizeof(Vertex), - (void*)offsetof(Vertex, normal_)); - - // Location 2: TexCoord - glEnableVertexAttribArray(2); - glVertexAttribPointer(2, 2, GL_FLOAT, GL_FALSE, sizeof(Vertex), - (void*)offsetof(Vertex, texcoord_)); - - // Location 3: Tangent - glEnableVertexAttribArray(3); - glVertexAttribPointer(3, 3, GL_FLOAT, GL_FALSE, sizeof(Vertex), - (void*)offsetof(Vertex, tangent_)); - - glBindVertexArray(0); - - uploaded_ = true; - Logger::info("Mesh uploaded to GPU successfully"); - return true; -} - -void Mesh::release_gpu_resources() { - if (!uploaded_) return; - - if (vao_ != 0) { - glDeleteVertexArrays(1, &vao_); - vao_ = 0; - } - - if (vbo_ != 0) { - glDeleteBuffers(1, &vbo_); - vbo_ = 0; - } - - if (ebo_ != 0) { - glDeleteBuffers(1, &ebo_); - ebo_ = 0; - } - - uploaded_ = false; -} - -} // namespace are -``` - -### 文件:src/resource/buffer.cpp - -```cpp -#include "resource/buffer.h" -#include "utils/logger.h" -#include - -namespace are { - -namespace { - GLenum get_gl_buffer_type(BufferType type) { - switch (type) { - case BufferType::VERTEX_BUFFER: return GL_ARRAY_BUFFER; - case BufferType::INDEX_BUFFER: return GL_ELEMENT_ARRAY_BUFFER; - case BufferType::UNIFORM_BUFFER: return GL_UNIFORM_BUFFER; - case BufferType::SHADER_STORAGE_BUFFER: return GL_SHADER_STORAGE_BUFFER; - default: return GL_ARRAY_BUFFER; - } - } - - GLenum get_gl_usage(BufferUsage usage) { - switch (usage) { - case BufferUsage::STATIC_DRAW: return GL_STATIC_DRAW; - case BufferUsage::DYNAMIC_DRAW: return GL_DYNAMIC_DRAW; - case BufferUsage::STREAM_DRAW: return GL_STREAM_DRAW; - default: return GL_STATIC_DRAW; - } - } -} - -Buffer::Buffer() - : handle_(INVALID_HANDLE) - , type_(BufferType::VERTEX_BUFFER) - , size_(0) - , usage_(BufferUsage::STATIC_DRAW) { -} - -Buffer::~Buffer() { - // Don't auto-release, let user control lifetime -} - -bool Buffer::create(BufferType type, size_t size, const void* data, BufferUsage usage) { - if (handle_ != INVALID_HANDLE) { - Logger::warning("Buffer already created, releasing old buffer"); - release(); - } - - type_ = type; - size_ = size; - usage_ = usage; - - glGenBuffers(1, &handle_); - - GLenum gl_type = get_gl_buffer_type(type); - GLenum gl_usage = get_gl_usage(usage); - - glBindBuffer(gl_type, handle_); - glBufferData(gl_type, size, data, gl_usage); - glBindBuffer(gl_type, 0); - - Logger::info("Buffer created successfully"); - return true; -} - -void Buffer::update(size_t offset, size_t size, const void* data) { - if (handle_ == INVALID_HANDLE) { - Logger::error("Cannot update invalid buffer"); - return; - } - - if (offset + size > size_) { - Logger::error("Buffer update out of bounds"); - return; - } - - GLenum gl_type = get_gl_buffer_type(type_); - - glBindBuffer(gl_type, handle_); - glBufferSubData(gl_type, offset, size, data); - glBindBuffer(gl_type, 0); -} - -void Buffer::bind() const { - if (handle_ == INVALID_HANDLE) { - Logger::warning("Attempting to bind invalid buffer"); - return; - } - - GLenum gl_type = get_gl_buffer_type(type_); - glBindBuffer(gl_type, handle_); -} - -void Buffer::bind_base(uint binding_point) const { - if (handle_ == INVALID_HANDLE) { - Logger::warning("Attempting to bind invalid buffer"); - return; - } - - GLenum gl_type = get_gl_buffer_type(type_); - glBindBufferBase(gl_type, binding_point, handle_); -} - -void Buffer::unbind() const { - GLenum gl_type = get_gl_buffer_type(type_); - glBindBuffer(gl_type, 0); -} - -void Buffer::release() { - if (handle_ != INVALID_HANDLE) { - glDeleteBuffers(1, &handle_); - handle_ = INVALID_HANDLE; - } - - size_ = 0; -} - -} // namespace are -``` - -### 文件:src/resource/model_loader.cpp - -```cpp -#include "resource/model_loader.h" -#include "utils/logger.h" -#include "resource/texture.h" - -// Note: This is a simplified implementation without Assimp -// For full implementation, include Assimp and implement properly - -namespace are { - -bool ModelLoader::load(const std::string& path, - std::vector>& meshes, - std::vector>& materials, - bool flip_uvs) { - Logger::error("ModelLoader requires Assimp library (not implemented in this version)"); - Logger::info("To implement: include , , "); - - // Placeholder implementation - // TODO: Implement with Assimp - /* - Assimp::Importer importer; - const aiScene* scene = importer.ReadFile(path, - aiProcess_Triangulate | - aiProcess_GenNormals | - aiProcess_CalcTangentSpace | - (flip_uvs ? aiProcess_FlipUVs : 0)); - - if (!scene || scene->mFlags & AI_SCENE_FLAGS_INCOMPLETE || !scene->mRootNode) { - Logger::error("Failed to load model: " + std::string(importer.GetErrorString())); - return false; - } - - std::string directory = path.substr(0, path.find_last_of('/')); - process_node_(scene->mRootNode, scene, meshes, materials, directory); - - Logger::info("Model loaded: " + path); - return true; - */ - - return false; -} - -bool ModelLoader::load_and_upload(const std::string& path, - std::vector>& meshes, - std::vector>& materials, - bool flip_uvs) { - if (!load(path, meshes, materials, flip_uvs)) { - return false; - } - - // Upload all meshes to GPU - for (auto& mesh : meshes) { - if (!mesh->upload_to_gpu()) { - Logger::error("Failed to upload mesh to GPU"); - return false; - } - } - - return true; -} - -void ModelLoader::process_node_(void* node, void* scene, - std::vector>& meshes, - std::vector>& materials, - const std::string& directory) { - // TODO: Implement with Assimp - /* - aiNode* ai_node = static_cast(node); - const aiScene* ai_scene = static_cast(scene); - - // Process all meshes in this node - for (uint i = 0; i < ai_node->mNumMeshes; ++i) { - aiMesh* ai_mesh = ai_scene->mMeshes[ai_node->mMeshes[i]]; - meshes.push_back(process_mesh_(ai_mesh, ai_scene, materials, directory)); - } - - // Process children recursively - for (uint i = 0; i < ai_node->mNumChildren; ++i) { - process_node_(ai_node->mChildren[i], ai_scene, meshes, materials, directory); - } - */ -} - -std::shared_ptr ModelLoader::process_mesh_(void* mesh, void* scene, - std::vector>& materials, - const std::string& directory) { - // TODO: Implement with Assimp - /* - aiMesh* ai_mesh = static_cast(mesh); - const aiScene* ai_scene = static_cast(scene); - - std::vector vertices; - std::vector indices; - - // Process vertices - for (uint i = 0; i < ai_mesh->mNumVertices; ++i) { - Vertex vertex; - - vertex.position_ = Vec3(ai_mesh->mVertices[i].x, - ai_mesh->mVertices[i].y, - ai_mesh->mVertices[i].z); - - if (ai_mesh->HasNormals()) { - vertex.normal_ = Vec3(ai_mesh->mNormals[i].x, - ai_mesh->mNormals[i].y, - ai_mesh->mNormals[i].z); - } - - if (ai_mesh->mTextureCoords[0]) { - vertex.texcoord_ = Vec2(ai_mesh->mTextureCoords[0][i].x, - ai_mesh->mTextureCoords[0][i].y); - } - - if (ai_mesh->HasTangentsAndBitangents()) { - vertex.tangent_ = Vec3(ai_mesh->mTangents[i].x, - ai_mesh->mTangents[i].y, - ai_mesh->mTangents[i].z); - } - - vertices.push_back(vertex); - } - - // Process indices - for (uint i = 0; i < ai_mesh->mNumFaces; ++i) { - aiFace face = ai_mesh->mFaces[i]; - for (uint j = 0; j < face.mNumIndices; ++j) { - indices.push_back(face.mIndices[j]); - } - } - - // Process material - uint material_id = materials.size(); - if (ai_mesh->mMaterialIndex >= 0) { - aiMaterial* ai_material = ai_scene->mMaterials[ai_mesh->mMaterialIndex]; - - auto material = std::make_shared(); - - // Load diffuse color - aiColor3D color; - if (ai_material->Get(AI_MATKEY_COLOR_DIFFUSE, color) == AI_SUCCESS) { - material->set_albedo(Vec3(color.r, color.g, color.b)); - } - - // Load textures - load_material_textures_(ai_material, aiTextureType_DIFFUSE, material, directory); - load_material_textures_(ai_material, aiTextureType_NORMALS, material, directory); - - materials.push_back(material); - } - - auto mesh_obj = std::make_shared(); - mesh_obj->set_vertices(vertices); - mesh_obj->set_indices(indices); - mesh_obj->set_material(material_id); - - return mesh_obj; - */ - - return nullptr; -} - -void ModelLoader::load_material_textures_(void* material, int type, - std::shared_ptr& mat, - const std::string& directory) { - // TODO: Implement with Assimp - /* - aiMaterial* ai_material = static_cast(material); - aiTextureType ai_type = static_cast(type); - - for (uint i = 0; i < ai_material->GetTextureCount(ai_type); ++i) { - aiString str; - ai_material->GetTexture(ai_type, i, &str); - - std::string filename = directory + "/" + std::string(str.C_Str()); - - auto texture = std::make_shared(); - if (texture->load_from_file(filename)) { - if (ai_type == aiTextureType_DIFFUSE) { - mat->set_albedo_texture(texture); - } else if (ai_type == aiTextureType_NORMALS) { - mat->set_normal_texture(texture); - } - } - } - */ -} - -} // namespace are -``` - -### 文件:src/resource/shader.cpp - -```cpp -#include "resource/shader.h" -#include "utils/logger.h" -#include "basic/math.h" // 修改为math.h -#include -#include -#include - -namespace are { - -Shader::Shader() - : handle_(INVALID_HANDLE) { -} - -Shader::~Shader() { - // Don't auto-release, let user control lifetime -} - -bool Shader::load(const std::string& vertex_path, const std::string& fragment_path) { - std::string vertex_source = read_file_(vertex_path); - std::string fragment_source = read_file_(fragment_path); - - if (vertex_source.empty() || fragment_source.empty()) { - Logger::error("Failed to read shader files"); - return false; - } - - return compile(vertex_source, fragment_source); -} - -bool Shader::load_compute(const std::string& compute_path) { - std::string compute_source = read_file_(compute_path); - - if (compute_source.empty()) { - Logger::error("Failed to read compute shader file"); - return false; - } - - return compile_compute(compute_source); -} - -bool Shader::compile(const std::string& vertex_source, const std::string& fragment_source) { - uint vertex_shader = compile_shader_(vertex_source, GL_VERTEX_SHADER); - if (vertex_shader == 0) return false; - - uint fragment_shader = compile_shader_(fragment_source, GL_FRAGMENT_SHADER); - if (fragment_shader == 0) { - glDeleteShader(vertex_shader); - return false; - } - - uint shaders[] = { vertex_shader, fragment_shader }; - bool success = link_program_(shaders, 2); - - glDeleteShader(vertex_shader); - glDeleteShader(fragment_shader); - - return success; -} - -bool Shader::compile_compute(const std::string& compute_source) { - uint compute_shader = compile_shader_(compute_source, GL_COMPUTE_SHADER); - if (compute_shader == 0) return false; - - uint shaders[] = { compute_shader }; - bool success = link_program_(shaders, 1); - - glDeleteShader(compute_shader); - - return success; -} - -void Shader::use() const { // 改为const - if (handle_ != INVALID_HANDLE) { - glUseProgram(handle_); - } -} - -void Shader::release() { - if (handle_ != INVALID_HANDLE) { - glDeleteProgram(handle_); - handle_ = INVALID_HANDLE; - } - uniform_cache_.clear(); -} - -void Shader::set_bool(const std::string& name, bool value) const { // 新增 - glUniform1i(get_uniform_location_(name), static_cast(value)); -} - -void Shader::set_int(const std::string& name, int value) const { // 改为const - glUniform1i(get_uniform_location_(name), value); -} - -void Shader::set_uint(const std::string& name, uint value) const { // 改为const - glUniform1ui(get_uniform_location_(name), value); -} - -void Shader::set_float(const std::string& name, float value) const { // 改为const - glUniform1f(get_uniform_location_(name), value); -} - -void Shader::set_vec2(const std::string& name, const Vec2& value) const { // 改为const - glUniform2fv(get_uniform_location_(name), 1, &value[0]); -} - -void Shader::set_vec3(const std::string& name, const Vec3& value) const { // 改为const - glUniform3fv(get_uniform_location_(name), 1, &value[0]); -} - -void Shader::set_vec4(const std::string& name, const Vec4& value) const { // 改为const - glUniform4fv(get_uniform_location_(name), 1, &value[0]); -} - -void Shader::set_mat3(const std::string& name, const Mat3& value) const { // 改为const - glUniformMatrix3fv(get_uniform_location_(name), 1, GL_FALSE, &value[0][0]); -} - -void Shader::set_mat4(const std::string& name, const Mat4& value) const { // 改为const - glUniformMatrix4fv(get_uniform_location_(name), 1, GL_FALSE, MathUtils::value_ptr(value)); -} - -int Shader::get_uniform_location_(const std::string& name) const { // 改为const - auto it = uniform_cache_.find(name); - if (it != uniform_cache_.end()) { - return it->second; - } - - int location = glGetUniformLocation(handle_, name.c_str()); - uniform_cache_[name] = location; // mutable允许修改 - - if (location == -1) { - Logger::warning("Uniform '" + name + "' not found in shader"); - } - - return location; -} - -uint Shader::compile_shader_(const std::string& source, uint type) { - uint shader = glCreateShader(type); - const char* source_cstr = source.c_str(); - glShaderSource(shader, 1, &source_cstr, nullptr); - glCompileShader(shader); - - int success; - glGetShaderiv(shader, GL_COMPILE_STATUS, &success); - if (!success) { - char info_log[512]; - glGetShaderInfoLog(shader, 512, nullptr, info_log); - - std::string type_str = (type == GL_VERTEX_SHADER) ? "VERTEX" : - (type == GL_FRAGMENT_SHADER) ? "FRAGMENT" : "COMPUTE"; - Logger::error("Shader compilation failed (" + type_str + "): " + std::string(info_log)); - - glDeleteShader(shader); - return 0; - } - - return shader; -} - -bool Shader::link_program_(const uint* shaders, uint count) { - handle_ = glCreateProgram(); - - for (uint i = 0; i < count; ++i) { - glAttachShader(handle_, shaders[i]); - } - - glLinkProgram(handle_); - - int success; - glGetProgramiv(handle_, GL_LINK_STATUS, &success); - if (!success) { - char info_log[512]; - glGetProgramInfoLog(handle_, 512, nullptr, info_log); - Logger::error("Shader linking failed: " + std::string(info_log)); - - glDeleteProgram(handle_); - handle_ = INVALID_HANDLE; - return false; - } - - return true; -} - -std::string Shader::read_file_(const std::string& path) { - std::ifstream file(path); - if (!file.is_open()) { - Logger::error("Failed to open file: " + path); - return ""; - } - - std::stringstream buffer; - buffer << file.rdbuf(); - return buffer.str(); -} - -} // namespace are -``` - -### 文件:src/resource/texture.cpp - -```cpp -#include "resource/texture.h" -#include "utils/logger.h" -#include -#include - -namespace are { - -namespace { - GLenum get_gl_internal_format(TextureFormat format) { - switch (format) { - case TextureFormat::R8: return GL_R8; - case TextureFormat::RG8: return GL_RG8; - case TextureFormat::RGB8: return GL_RGB8; - case TextureFormat::RGBA8: return GL_RGBA8; - case TextureFormat::R16F: return GL_R16F; - case TextureFormat::RG16F: return GL_RG16F; - case TextureFormat::RGB16F: return GL_RGB16F; - case TextureFormat::RGBA16F: return GL_RGBA16F; - case TextureFormat::R32F: return GL_R32F; - case TextureFormat::RG32F: return GL_RG32F; - case TextureFormat::RGB32F: return GL_RGB32F; - case TextureFormat::RGBA32F: return GL_RGBA32F; - case TextureFormat::DEPTH24_STENCIL8: return GL_DEPTH24_STENCIL8; - default: return GL_RGBA8; - } - } - - GLenum get_gl_format(TextureFormat format) { - switch (format) { - case TextureFormat::R8: - case TextureFormat::R16F: - case TextureFormat::R32F: - return GL_RED; - case TextureFormat::RG8: - case TextureFormat::RG16F: - case TextureFormat::RG32F: - return GL_RG; - case TextureFormat::RGB8: - case TextureFormat::RGB16F: - case TextureFormat::RGB32F: - return GL_RGB; - case TextureFormat::RGBA8: - case TextureFormat::RGBA16F: - case TextureFormat::RGBA32F: - return GL_RGBA; - case TextureFormat::DEPTH24_STENCIL8: - return GL_DEPTH_STENCIL; - default: - return GL_RGBA; - } - } - - GLenum get_gl_type(TextureFormat format) { - switch (format) { - case TextureFormat::R8: - case TextureFormat::RG8: - case TextureFormat::RGB8: - case TextureFormat::RGBA8: - return GL_UNSIGNED_BYTE; - case TextureFormat::R16F: - case TextureFormat::RG16F: - case TextureFormat::RGB16F: - case TextureFormat::RGBA16F: - case TextureFormat::R32F: - case TextureFormat::RG32F: - case TextureFormat::RGB32F: - case TextureFormat::RGBA32F: - return GL_FLOAT; - case TextureFormat::DEPTH24_STENCIL8: - return GL_UNSIGNED_INT_24_8; - default: - return GL_UNSIGNED_BYTE; - } - } - - GLenum get_gl_filter(TextureFilter filter) { - switch (filter) { - case TextureFilter::NEAREST: return GL_NEAREST; - case TextureFilter::LINEAR: return GL_LINEAR; - case TextureFilter::NEAREST_MIPMAP_NEAREST: return GL_NEAREST_MIPMAP_NEAREST; - case TextureFilter::LINEAR_MIPMAP_NEAREST: return GL_LINEAR_MIPMAP_NEAREST; - case TextureFilter::NEAREST_MIPMAP_LINEAR: return GL_NEAREST_MIPMAP_LINEAR; - case TextureFilter::LINEAR_MIPMAP_LINEAR: return GL_LINEAR_MIPMAP_LINEAR; - default: return GL_LINEAR; - } - } - - GLenum get_gl_wrap(TextureWrap wrap) { - switch (wrap) { - case TextureWrap::REPEAT: return GL_REPEAT; - case TextureWrap::MIRRORED_REPEAT: return GL_MIRRORED_REPEAT; - case TextureWrap::CLAMP_TO_EDGE: return GL_CLAMP_TO_EDGE; - case TextureWrap::CLAMP_TO_BORDER: return GL_CLAMP_TO_BORDER; - default: return GL_REPEAT; - } - } -} - -Texture::Texture() - : handle_(INVALID_HANDLE) - , width_(0) - , height_(0) - , format_(TextureFormat::RGBA8) - , has_mipmaps_(false) { -} - -Texture::~Texture() { - // Don't auto-release, let user control lifetime -} - -bool Texture::load_from_file(const std::string& path, bool generate_mipmaps) { - // Load image using stb_image - int width, height, channels; - stbi_set_flip_vertically_on_load(true); - unsigned char* data = stbi_load(path.c_str(), &width, &height, &channels, 0); - - if (!data) { - Logger::error("Failed to load texture: " + path); - return false; - } - - // Determine format based on channels - TextureFormat format; - switch (channels) { - case 1: format = TextureFormat::R8; break; - case 2: format = TextureFormat::RG8; break; - case 3: format = TextureFormat::RGB8; break; - case 4: format = TextureFormat::RGBA8; break; - default: - Logger::error("Unsupported channel count: " + std::to_string(channels)); - stbi_image_free(data); - return false; - } - - // Create texture - bool success = create(width, height, format); - if (!success) { - stbi_image_free(data); - return false; - } - - // Upload data - success = upload(data, width, height, format); - stbi_image_free(data); - - if (!success) { - return false; - } - - // Generate mipmaps if requested - if (generate_mipmaps) { - this->generate_mipmaps(); - } - - Logger::info("Texture loaded successfully: " + path); - return true; -} - -bool Texture::create(uint width, uint height, TextureFormat format) { - if (handle_ != INVALID_HANDLE) { - Logger::warning("Texture already created, releasing old texture"); - release(); - } - - width_ = width; - height_ = height; - format_ = format; - - glGenTextures(1, &handle_); - glBindTexture(GL_TEXTURE_2D, handle_); - - GLenum internal_format = get_gl_internal_format(format); - GLenum gl_format = get_gl_format(format); - GLenum type = get_gl_type(format); - - glTexImage2D(GL_TEXTURE_2D, 0, internal_format, width, height, 0, gl_format, type, nullptr); - - // Set default parameters - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); - - glBindTexture(GL_TEXTURE_2D, 0); - - return true; -} - -bool Texture::upload(const void* data, uint width, uint height, TextureFormat format) { - if (handle_ == INVALID_HANDLE) { - Logger::error("Cannot upload to invalid texture"); - return false; - } - - if (width != width_ || height != height_ || format != format_) { - Logger::warning("Upload parameters differ from texture creation, recreating texture"); - create(width, height, format); - } - - glBindTexture(GL_TEXTURE_2D, handle_); - - GLenum gl_format = get_gl_format(format); - GLenum type = get_gl_type(format); - - glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, width, height, gl_format, type, data); - - glBindTexture(GL_TEXTURE_2D, 0); - - return true; -} - -void Texture::set_filter(TextureFilter min_filter, TextureFilter mag_filter) { - if (handle_ == INVALID_HANDLE) { - Logger::error("Cannot set filter on invalid texture"); - return; - } - - glBindTexture(GL_TEXTURE_2D, handle_); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, get_gl_filter(min_filter)); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, get_gl_filter(mag_filter)); - glBindTexture(GL_TEXTURE_2D, 0); -} - -void Texture::set_wrap(TextureWrap wrap_s, TextureWrap wrap_t) { - if (handle_ == INVALID_HANDLE) { - Logger::error("Cannot set wrap mode on invalid texture"); - return; - } - - glBindTexture(GL_TEXTURE_2D, handle_); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, get_gl_wrap(wrap_s)); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, get_gl_wrap(wrap_t)); - glBindTexture(GL_TEXTURE_2D, 0); -} - -void Texture::generate_mipmaps() { - if (handle_ == INVALID_HANDLE) { - Logger::error("Cannot generate mipmaps for invalid texture"); - return; - } - - glBindTexture(GL_TEXTURE_2D, handle_); - glGenerateMipmap(GL_TEXTURE_2D); - glBindTexture(GL_TEXTURE_2D, 0); - - has_mipmaps_ = true; -} - -void Texture::bind(uint unit) const { - if (handle_ == INVALID_HANDLE) { - Logger::warning("Attempting to bind invalid texture"); - return; - } - - glActiveTexture(GL_TEXTURE0 + unit); - glBindTexture(GL_TEXTURE_2D, handle_); -} - -void Texture::unbind() const { - glBindTexture(GL_TEXTURE_2D, 0); -} - -void Texture::release() { - if (handle_ != INVALID_HANDLE) { - glDeleteTextures(1, &handle_); - handle_ = INVALID_HANDLE; - } - - width_ = 0; - height_ = 0; - has_mipmaps_ = false; -} - -} // namespace are -``` - -### 文件:src/utils/config.cpp - -```cpp -#include "utils/config.h" -#include "utils/logger.h" -#include -#include -#include - -namespace are { - -// Static storage -static std::unordered_map g_config_map; - -// Helper function to trim whitespace -static std::string trim(const std::string& str) { - size_t first = str.find_first_not_of(" \t\r\n"); - if (first == std::string::npos) return ""; - size_t last = str.find_last_not_of(" \t\r\n"); - return str.substr(first, last - first + 1); -} - -bool Config::load(const std::string& path) { - std::ifstream file(path); - if (!file.is_open()) { - Logger::error("Failed to open config file: " + path); - return false; - } - - g_config_map.clear(); - - std::string line; - std::string current_section; - - while (std::getline(file, line)) { - line = trim(line); - - // Skip empty lines and comments - if (line.empty() || line[0] == '#' || line[0] == ';') { - continue; - } - - // Section header - if (line[0] == '[' && line.back() == ']') { - current_section = line.substr(1, line.length() - 2); - continue; - } - - // Key-value pair - size_t pos = line.find('='); - if (pos != std::string::npos) { - std::string key = trim(line.substr(0, pos)); - std::string value = trim(line.substr(pos + 1)); - - // Add section prefix if in a section - if (!current_section.empty()) { - key = current_section + "." + key; - } - - g_config_map[key] = value; - } - } - - Logger::info("Config loaded: " + path + " (" + std::to_string(g_config_map.size()) + " entries)"); - return true; -} - -bool Config::save(const std::string& path) { - std::ofstream file(path); - if (!file.is_open()) { - Logger::error("Failed to open config file for writing: " + path); - return false; - } - - for (const auto& pair : g_config_map) { - file << pair.first << "=" << pair.second << std::endl; - } - - Logger::info("Config saved: " + path); - return true; -} - -std::string Config::get_string(const std::string& key, const std::string& default_value) { - auto it = g_config_map.find(key); - if (it != g_config_map.end()) { - return it->second; - } - return default_value; -} - -int Config::get_int(const std::string& key, int default_value) { - auto it = g_config_map.find(key); - if (it != g_config_map.end()) { - try { - return std::stoi(it->second); - } catch (...) { - Logger::warning("Failed to parse int for key: " + key); - } - } - return default_value; -} - -float Config::get_float(const std::string& key, float default_value) { - auto it = g_config_map.find(key); - if (it != g_config_map.end()) { - try { - return std::stof(it->second); - } catch (...) { - Logger::warning("Failed to parse float for key: " + key); - } - } - return default_value; -} - -bool Config::get_bool(const std::string& key, bool default_value) { - auto it = g_config_map.find(key); - if (it != g_config_map.end()) { - std::string value = it->second; - std::transform(value.begin(), value.end(), value.begin(), ::tolower); - - if (value == "true" || value == "1" || value == "yes" || value == "on") { - return true; - } - if (value == "false" || value == "0" || value == "no" || value == "off") { - return false; - } - } - return default_value; -} - -void Config::set_string(const std::string& key, const std::string& value) { - g_config_map[key] = value; -} - -void Config::set_int(const std::string& key, int value) { - g_config_map[key] = std::to_string(value); -} - -void Config::set_float(const std::string& key, float value) { - g_config_map[key] = std::to_string(value); -} - -void Config::set_bool(const std::string& key, bool value) { - g_config_map[key] = value ? "true" : "false"; -} - -} // namespace are -``` - -### 文件:src/utils/logger.cpp - -```cpp -#include "utils/logger.h" -#include -#include -#include -#include -#include - -namespace are { - -// Static members -static LogLevel g_min_level = LogLevel::DEBUG; -static std::ofstream g_log_file; -static bool g_initialized = false; - -bool Logger::initialize(const std::string& log_file) { - if (g_initialized) { - return true; - } - - if (!log_file.empty()) { - g_log_file.open(log_file, std::ios::out | std::ios::app); - if (!g_log_file.is_open()) { - std::cerr << "Failed to open log file: " << log_file << std::endl; - return false; - } - } - - g_initialized = true; - return true; -} - -void Logger::shutdown() { - if (g_log_file.is_open()) { - g_log_file.close(); - } - g_initialized = false; -} - -static std::string get_current_time() { - auto now = std::time(nullptr); - auto tm = *std::localtime(&now); - std::ostringstream oss; - oss << std::put_time(&tm, "%H:%M:%S"); - return oss.str(); -} - -static std::string level_to_string(LogLevel level) { - switch (level) { - case LogLevel::DEBUG: return "DEBUG"; - case LogLevel::INFO: return "INFO"; - case LogLevel::WARNING: return "WARN"; - case LogLevel::ERROR: return "ERROR"; - case LogLevel::FATAL: return "FATAL"; - default: return "UNKNOWN"; - } -} - -void Logger::log(LogLevel level, const std::string& message) { - if (level < g_min_level) return; - - std::string time_str = get_current_time(); - std::string level_str = level_to_string(level); - std::string formatted = "[" + time_str + "] [" + level_str + "] " + message; - - // Console output - if (level >= LogLevel::ERROR) { - std::cerr << formatted << std::endl; - } else { - std::cout << formatted << std::endl; - } - - // File output - if (g_log_file.is_open()) { - g_log_file << formatted << std::endl; - g_log_file.flush(); - } -} - -void Logger::debug(const std::string& message) { - log(LogLevel::DEBUG, message); -} - -void Logger::info(const std::string& message) { - log(LogLevel::INFO, message); -} - -void Logger::warning(const std::string& message) { - log(LogLevel::WARNING, message); -} - -void Logger::error(const std::string& message) { - log(LogLevel::ERROR, message); -} - -void Logger::fatal(const std::string& message) { - log(LogLevel::FATAL, message); -} - -void Logger::set_level(LogLevel level) { - g_min_level = level; -} - -} // namespace are -``` - diff --git a/.all_headers.md b/.all_headers.md deleted file mode 100644 index fd42fdd..0000000 --- a/.all_headers.md +++ /dev/null @@ -1,1762 +0,0 @@ -### 文件:include/basic/types.h - -```cpp -#ifndef ARE_INCLUDE_BASIC_TYPES_H -#define ARE_INCLUDE_BASIC_TYPES_H - -#include -#include -#include -#include -#include - -namespace are { - -/// @brief Basic vector types using GLM -using Vec2 = glm::vec2; -using Vec3 = glm::vec3; -using Vec4 = glm::vec4; - -/// @brief Basic matrix types using GLM -using Mat3 = glm::mat3; -using Mat4 = glm::mat4; - -/// @brief Basic integer types -using uint = uint32_t; -using uchar = uint8_t; - -/// @brief Handle types for GPU resources -using TextureHandle = uint; -using BufferHandle = uint; -using ShaderHandle = uint; -using FramebufferHandle = uint; - -/// @brief Invalid handle constant -constexpr uint INVALID_HANDLE = 0; - -/// @brief Vertex structure for mesh data -struct Vertex { - Vec3 position_; - Vec3 normal_; - Vec2 texcoord_; - Vec3 tangent_; -}; - -/// @brief Ray structure for ray tracing -struct Ray { - Vec3 origin_; - Vec3 direction_; - float t_min_; - float t_max_; -}; - -/// @brief Hit information for ray-surface intersection -struct HitInfo { - bool hit_; - float t_; - Vec3 position_; - Vec3 normal_; - Vec2 texcoord_; - uint material_id_; -}; - -/// @brief Rendering statistics -struct RenderStats { - float frame_time_ms_; - uint triangle_count_; - uint ray_count_; - float gbuffer_time_ms_; - float raytrace_time_ms_; -}; - -} // namespace are - -#endif // ARE_INCLUDE_BASIC_TYPES_H -``` - -### 文件:include/basic/constants.h - -```cpp -#ifndef ARE_INCLUDE_BASIC_CONSTANTS_H -#define ARE_INCLUDE_BASIC_CONSTANTS_H - -namespace are { - -/// @brief Maximum number of lights in scene -constexpr int MAX_LIGHTS = 16; - -/// @brief Maximum ray tracing depth -constexpr int MAX_RAY_DEPTH = 8; - -/// @brief Default samples per pixel for ray tracing -constexpr int DEFAULT_SPP = 1; - -/// @brief G-Buffer attachment indices -constexpr int GBUFFER_POSITION = 0; -constexpr int GBUFFER_NORMAL = 1; -constexpr int GBUFFER_ALBEDO = 2; -constexpr int GBUFFER_COUNT = 3; - -/// @brief Compute shader work group size -constexpr int COMPUTE_GROUP_SIZE_X = 16; -constexpr int COMPUTE_GROUP_SIZE_Y = 16; - -/// @brief Mathematical constants -constexpr float PI = 3.14159265359f; -constexpr float INV_PI = 0.31830988618f; -constexpr float EPSILON = 1e-4f; - -} // namespace are - -#endif // ARE_INCLUDE_BASIC_CONSTANTS_H -``` - -### 文件:include/basic/math.h - -```cpp -#ifndef ARE_INCLUDE_BASIC_MATH_UTILS_H -#define ARE_INCLUDE_BASIC_MATH_UTILS_H - -#include "types.h" -#include -#include - -namespace are { - -/// @brief Math utility functions wrapping GLM -class MathUtils { -public: - /// @brief Create perspective projection matrix - /// @param fov Field of view in radians - /// @param aspect Aspect ratio - /// @param near Near plane distance - /// @param far Far plane distance - /// @return Projection matrix - static Mat4 perspective(float fov, float aspect, float near, float far); - - /// @brief Create look-at view matrix - /// @param eye Camera position - /// @param center Look-at target - /// @param up Up vector - /// @return View matrix - static Mat4 look_at(const Vec3& eye, const Vec3& center, const Vec3& up); - - /// @brief Normalize a vector - /// @param v Input vector - /// @return Normalized vector - static Vec3 normalize(const Vec3& v); - - /// @brief Calculate dot product - /// @param a First vector - /// @param b Second vector - /// @return Dot product - static float dot(const Vec3& a, const Vec3& b); - - /// @brief Calculate cross product - /// @param a First vector - /// @param b Second vector - /// @return Cross product - static Vec3 cross(const Vec3& a, const Vec3& b); - - /// @brief Reflect vector around normal - /// @param incident Incident vector - /// @param normal Surface normal - /// @return Reflected vector - static Vec3 reflect(const Vec3& incident, const Vec3& normal); - - /// @brief Get pointer to matrix data (for OpenGL) - /// @param mat Input matrix - /// @return Pointer to matrix data - static const float* value_ptr(const Mat4& mat); -}; - -} // namespace are - -#endif // ARE_INCLUDE_BASIC_MATH_UTILS_H -``` - -### 文件:include/core/bvh.h - -```cpp -#ifndef ARE_INCLUDE_CORE_BVH_H -#define ARE_INCLUDE_CORE_BVH_H - -#include "basic/types.h" -#include "scene/mesh.h" -#include "resource/buffer.h" -#include -#include - -namespace are { - -/// @brief Axis-aligned bounding box -struct AABB { - Vec3 min_; - Vec3 max_; - - /// @brief Construct AABB from min and max points - AABB(const Vec3& min = Vec3(0.0f), const Vec3& max = Vec3(0.0f)) - : min_(min), max_(max) {} - - /// @brief Expand AABB to include point - void expand(const Vec3& point); - - /// @brief Expand AABB to include another AABB - void expand(const AABB& other); - - /// @brief Get center of AABB - Vec3 center() const { return (min_ + max_) * 0.5f; } - - /// @brief Get surface area of AABB - float surface_area() const; - - /// @brief Check if AABB is valid - bool is_valid() const; -}; - -/// @brief Triangle primitive for BVH -struct Triangle { - Vec3 v0_, v1_, v2_; - Vec3 n0_, n1_, n2_; - Vec2 uv0_, uv1_, uv2_; - uint material_id_; - - /// @brief Get bounding box of triangle - AABB get_bounds() const; - - /// @brief Get centroid of triangle - Vec3 get_centroid() const; -}; - -/// @brief BVH node for GPU -struct BVHNode { - Vec3 aabb_min_; - uint left_first_; // Left child index or first primitive index - Vec3 aabb_max_; - uint count_; // 0 for interior node, >0 for leaf node -}; - -/// @brief Bounding Volume Hierarchy for ray tracing acceleration -class BVH { -public: - /// @brief Constructor - BVH(); - - /// @brief Destructor - ~BVH(); - - /// @brief Build BVH from meshes - /// @param meshes Mesh list - /// @return True if build succeeded - bool build(const std::vector>& meshes); - - /// @brief Upload BVH to GPU - /// @param node_buffer Buffer for BVH nodes - /// @param triangle_buffer Buffer for triangles - /// @return True if upload succeeded - bool upload_to_gpu(Buffer& node_buffer, Buffer& triangle_buffer); - - /// @brief Get total node count - /// @return Node count - uint get_node_count() const { return static_cast(nodes_.size()); } - - /// @brief Get total triangle count - /// @return Triangle count - uint get_triangle_count() const { return static_cast(triangles_.size()); } - - /// @brief Clear BVH data - void clear(); - -private: - std::vector nodes_; - std::vector triangles_; - std::vector triangle_indices_; - - /// @brief Recursively build BVH - /// @param node_idx Current node index - /// @param first_prim First primitive index - /// @param prim_count Primitive count - void build_recursive_(uint node_idx, uint first_prim, uint prim_count); - - /// @brief Find best split using SAH - /// @param first_prim First primitive index - /// @param prim_count Primitive count - /// @param axis Split axis (output) - /// @param split_pos Split position (output) - /// @return Split cost - float find_best_split_(uint first_prim, uint prim_count, int& axis, float& split_pos); - - /// @brief Calculate node bounds - /// @param first_prim First primitive index - /// @param prim_count Primitive count - /// @return Bounding box - AABB calculate_bounds_(uint first_prim, uint prim_count); - - /// @brief Calculate centroid bounds - /// @param first_prim First primitive index - /// @param prim_count Primitive count - /// @return Centroid bounding box - AABB calculate_centroid_bounds_(uint first_prim, uint prim_count); -}; - -} // namespace are - -#endif // ARE_INCLUDE_CORE_BVH_H -``` - -### 文件:include/core/gbuffer.h - -```cpp -#ifndef ARE_INCLUDE_CORE_GBUFFER_H -#define ARE_INCLUDE_CORE_GBUFFER_H - -#include "basic/types.h" -#include "basic/constants.h" -#include "scene/scene.h" -#include "resource/shader.h" - -namespace are { - -/// @brief G-Buffer manager for deferred rendering -class GBuffer { -public: - /// @brief Constructor - /// @param width Buffer width - /// @param height Buffer height - GBuffer(uint width, uint height); - - /// @brief Destructor - ~GBuffer(); - - /// @brief Initialize G-Buffer (create framebuffer and textures) - /// @return True if initialization succeeded - bool initialize(); - - /// @brief Release G-Buffer resources - void release(); - - /// @brief Render scene to G-Buffer - /// @param scene Scene to render - /// @param shader Shader program for G-Buffer pass - void render(const Scene& scene, const Shader& shader); - - /// @brief Resize G-Buffer - /// @param width New width - /// @param height New height - void resize(uint width, uint height); - - /// @brief Get texture handle for specific buffer - /// @param index Buffer index (GBUFFER_POSITION, GBUFFER_NORMAL, etc.) - /// @return Texture handle - TextureHandle get_texture(int index) const; - - /// @brief Get framebuffer handle - /// @return Framebuffer handle - FramebufferHandle get_framebuffer() const { return fbo_; } - - /// @brief Get buffer dimensions - /// @param width Output width - /// @param height Output height - void get_dimensions(uint& width, uint& height) const; - -private: - uint width_; - uint height_; - FramebufferHandle fbo_; - TextureHandle textures_[GBUFFER_COUNT]; - TextureHandle depth_texture_; - - 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 - -#endif // ARE_INCLUDE_CORE_GBUFFER_H -``` - -### 文件:include/core/raytracer.h - -```cpp -#ifndef ARE_INCLUDE_CORE_RAYTRACER_H -#define ARE_INCLUDE_CORE_RAYTRACER_H - -#include "basic/types.h" -#include "core/bvh.h" // 添加 -#include "core/gbuffer.h" -#include "resource/buffer.h" -#include "resource/shader.h" -#include "scene/scene.h" - -namespace are { - -/// @brief Ray tracing configuration -struct RayTracerConfig { - uint samples_per_pixel_; - uint max_depth_; - bool enable_shadows_; - bool enable_reflections_; - bool enable_accumulation_; - bool use_bvh_; // 添加BVH开关 -}; - -/// @brief Compute shader based ray tracer -class RayTracer { -public: - /// @brief Constructor - /// @param width Output width - /// @param height Output height - /// @param config Ray tracer configuration - RayTracer(uint width, uint height, const RayTracerConfig &config); - - /// @brief Destructor - ~RayTracer(); - - /// @brief Initialize ray tracer - /// @return True if initialization succeeded - bool initialize(); - - /// @brief Release resources - void release(); - - /// @brief Trace rays using G-Buffer as input - /// @param scene Scene data - /// @param gbuffer G-Buffer containing geometry information - /// @param output_texture Output texture for ray traced result - void trace(const Scene &scene, const GBuffer &gbuffer, TextureHandle output_texture); - - /// @brief Resize output - /// @param width New width - /// @param height New height - void resize(uint width, uint height); - - /// @brief Reset accumulation buffer - void reset_accumulation(); - - /// @brief Get current configuration - /// @return Current configuration - const RayTracerConfig &get_config() const { - return config_; - } - - /// @brief Update configuration - /// @param config New configuration - void set_config(const RayTracerConfig &config); - - /// @brief Rebuild BVH from scene - /// @param scene Scene to build BVH from - /// @return True if build succeeded - bool rebuild_bvh(const Scene &scene); - - /// @brief Set compute shader (called by renderer) - /// @param shader Compute shader - void set_compute_shader(const Shader &shader); - -private: - uint width_; - uint height_; - RayTracerConfig config_; - - Shader compute_shader_; - TextureHandle accumulation_texture_; - BufferHandle scene_buffer_; - BufferHandle material_buffer_; - BufferHandle light_buffer_; - - // BVH related - std::unique_ptr bvh_; // 添加 - Buffer bvh_node_buffer_; // 添加 - Buffer bvh_triangle_buffer_; // 添加 - bool bvh_built_; // 添加 - - uint frame_count_; - bool initialized_; - - /// @brief Upload scene data to GPU buffers - /// @param scene Scene to upload - void upload_scene_data_(const Scene &scene); - - /// @brief Bind G-Buffer textures to compute shader - /// @param gbuffer G-Buffer to bind - void bind_gbuffer_(const GBuffer &gbuffer); -}; - -} // namespace are - -#endif // ARE_INCLUDE_CORE_RAYTRACER_H -``` - -### 文件:include/core/renderer.h - -```cpp -#ifndef ARE_INCLUDE_CORE_RENDERER_H -#define ARE_INCLUDE_CORE_RENDERER_H - -#include "basic/types.h" -#include "scene/scene.h" -#include "core/gbuffer.h" -#include "core/raytracer.h" -#include "core/screen_blit.h" -#include "core/shader_manager.h" -#include - -namespace are { - -/// @brief Main renderer configuration -struct RendererConfig { - uint width_; - uint height_; - uint samples_per_pixel_; - uint max_ray_depth_; - bool enable_denoising_; - bool enable_accumulation_; -}; - -/// @brief Main rendering engine interface -class Renderer { -public: - /// @brief Constructor - /// @param config Renderer configuration - Renderer(const RendererConfig& config); - - /// @brief Destructor - ~Renderer(); - - /// @brief Initialize renderer (OpenGL context must be current) - /// @return True if initialization succeeded - bool initialize(); - - /// @brief Shutdown renderer and release resources - void shutdown(); - - /// @brief Render a frame - /// @param scene Scene to render - /// @param output_texture Output texture handle (0 for default framebuffer) - /// @return Rendering statistics - RenderStats render(const Scene& scene, TextureHandle output_texture = 0); - - /// @brief Resize render targets - /// @param width New width - /// @param height New height - void resize(uint width, uint height); - - /// @brief Get current configuration - /// @return Current configuration - const RendererConfig& get_config() const { return config_; } - - /// @brief Update configuration - /// @param config New configuration - void set_config(const RendererConfig& config); - -private: - RendererConfig config_; - std::unique_ptr gbuffer_; - std::unique_ptr raytracer_; - std::unique_ptr shader_manager_; - std::unique_ptr screen_blit_; - - bool initialized_; - uint frame_count_; -}; - -} // namespace are - -#endif // ARE_INCLUDE_CORE_RENDERER_H -``` - -### 文件:include/core/screen_blit.h - -```cpp -#ifndef ARE_INCLUDE_CORE_SCREEN_BLIT_H -#define ARE_INCLUDE_CORE_SCREEN_BLIT_H - -#include "basic/types.h" -#include "resource/shader.h" - -namespace are { - -/// @brief Screen blit utility for rendering texture to screen -class ScreenBlit { -public: - /// @brief Constructor - ScreenBlit(); - - /// @brief Destructor - ~ScreenBlit(); - - /// @brief Initialize screen blit - /// @return True if initialization succeeded - bool initialize(); - - /// @brief Release resources - void release(); - - /// @brief Blit texture to screen - /// @param texture Texture to blit - /// @param x Screen X position - /// @param y Screen Y position - /// @param width Blit width - /// @param height Blit height - void blit(TextureHandle texture, int x, int y, uint width, uint height); - - /// @brief Blit texture to full screen - /// @param texture Texture to blit - void blit_fullscreen(TextureHandle texture); - -private: - Shader shader_; - uint vao_; - uint vbo_; - bool initialized_; - - /// @brief Create fullscreen quad - void create_quad_(); -}; - -} // namespace are - -#endif // ARE_INCLUDE_CORE_SCREEN_BLIT_H -``` - -### 文件:include/core/shader_manager.h - -```cpp -#ifndef ARE_INCLUDE_CORE_SHADER_MANAGER_H -#define ARE_INCLUDE_CORE_SHADER_MANAGER_H - -#include "basic/types.h" -#include "resource/shader.h" -#include -#include - -namespace are { - -/// @brief Shader manager for loading and caching shaders -class ShaderManager { -public: - /// @brief Constructor - ShaderManager(); - - /// @brief Destructor - ~ShaderManager(); - - /// @brief Initialize shader manager and load built-in shaders - /// @return True if initialization succeeded - bool initialize(); - - /// @brief Release all shaders - void release(); - - /// @brief Load shader from files - /// @param name Shader name for caching - /// @param vertex_path Vertex shader file path - /// @param fragment_path Fragment shader file path - /// @return Shader object - Shader load_shader(const std::string& name, - const std::string& vertex_path, - const std::string& fragment_path); - - /// @brief Load compute shader from file - /// @param name Shader name for caching - /// @param compute_path Compute shader file path - /// @return Shader object - Shader load_compute_shader(const std::string& name, - const std::string& compute_path); - - /// @brief Get cached shader by name - /// @param name Shader name - /// @return Shader object (invalid if not found) - Shader get_shader(const std::string& name) const; - - /// @brief Get G-Buffer shader - /// @return G-Buffer shader - const Shader& get_gbuffer_shader() const { return gbuffer_shader_; } - - /// @brief Get ray tracing compute shader - /// @return Ray tracing shader - const Shader& get_raytracing_shader() const { return raytracing_shader_; } - -private: - std::unordered_map shader_cache_; - Shader gbuffer_shader_; - Shader raytracing_shader_; - - bool initialized_; - - /// @brief Load built-in shaders - /// @return True if loading succeeded - bool load_builtin_shaders_(); -}; - -} // namespace are - -#endif // ARE_INCLUDE_CORE_SHADER_MANAGER_H -``` - -### 文件:include/scene/camera.h - -```cpp -#ifndef ARE_INCLUDE_SCENE_CAMERA_H -#define ARE_INCLUDE_SCENE_CAMERA_H - -#include "basic/types.h" - -namespace are { - -/// @brief Camera projection type -enum class ProjectionType { - PERSPECTIVE, - ORTHOGRAPHIC -}; - -/// @brief Camera for rendering -class Camera { -public: - /// @brief Constructor - Camera(); - - /// @brief Destructor - ~Camera(); - - /// @brief Set perspective projection - /// @param fov Field of view in degrees - /// @param aspect Aspect ratio - /// @param near Near plane - /// @param far Far plane - void set_perspective(float fov, float aspect, float near, float far); - - /// @brief Set orthographic projection - /// @param left Left plane - /// @param right Right plane - /// @param bottom Bottom plane - /// @param top Top plane - /// @param near Near plane - /// @param far Far plane - void set_orthographic(float left, float right, float bottom, float top, float near, float far); - - /// @brief Set camera position - /// @param position Position - void set_position(const Vec3& position); - - /// @brief Set camera target - /// @param target Target position - void set_target(const Vec3& target); - - /// @brief Set camera up vector - /// @param up Up vector - void set_up(const Vec3& up); - - /// @brief Get view matrix - /// @return View matrix - Mat4 get_view_matrix() const; - - /// @brief Get projection matrix - /// @return Projection matrix - Mat4 get_projection_matrix() const; - - /// @brief Get view-projection matrix - /// @return View-projection matrix - Mat4 get_view_projection_matrix() const; - - /// @brief Get camera position - /// @return Position - const Vec3& get_position() const { return position_; } - - /// @brief Get camera forward direction - /// @return Forward direction - Vec3 get_forward() const; - - /// @brief Get camera right direction - /// @return Right direction - Vec3 get_right() const; - - /// @brief Get camera up direction - /// @return Up direction - Vec3 get_up() const; - -private: - Vec3 position_; - Vec3 target_; - Vec3 up_; - - ProjectionType projection_type_; - - // Perspective parameters - float fov_; - float aspect_; - - // Orthographic parameters - float left_, right_, bottom_, top_; - - // Common parameters - float near_; - float far_; - - mutable Mat4 view_matrix_; - mutable Mat4 projection_matrix_; - mutable bool view_dirty_; - mutable bool projection_dirty_; -}; - -} // namespace are - -#endif // ARE_INCLUDE_SCENE_CAMERA_H -``` - -### 文件:include/scene/material.h - -```cpp -#ifndef ARE_INCLUDE_SCENE_MATERIAL_H -#define ARE_INCLUDE_SCENE_MATERIAL_H - -#include "basic/types.h" -#include "resource/texture.h" -#include - -namespace are { - -/// @brief Material type enumeration -enum class MaterialType { - DIFFUSE = 0, - METAL = 1, - DIELECTRIC = 2, - EMISSIVE = 3 -}; - -/// @brief Material properties -class Material { -public: - /// @brief Constructor - Material(); - - /// @brief Destructor - ~Material(); - - /// @brief Set albedo color - /// @param albedo Albedo color - void set_albedo(const Vec3& albedo); - - /// @brief Set emission color - /// @param emission Emission color - void set_emission(const Vec3& emission); - - /// @brief Set metallic value - /// @param metallic Metallic (0-1) - void set_metallic(float metallic); - - /// @brief Set roughness value - /// @param roughness Roughness (0-1) - void set_roughness(float roughness); - - /// @brief Set index of refraction - /// @param ior Index of refraction - void set_ior(float ior); - - /// @brief Set material type - /// @param type Material type - void set_type(MaterialType type); - - /// @brief Set albedo texture - /// @param texture Albedo texture - void set_albedo_texture(std::shared_ptr texture); - - /// @brief Set normal map - /// @param texture Normal map texture - void set_normal_texture(std::shared_ptr texture); - - /// @brief Get albedo color - /// @return Albedo color - const Vec3& get_albedo() const { return albedo_; } - - /// @brief Get emission color - /// @return Emission color - const Vec3& get_emission() const { return emission_; } - - /// @brief Get metallic value - /// @return Metallic - float get_metallic() const { return metallic_; } - - /// @brief Get roughness value - /// @return Roughness - float get_roughness() const { return roughness_; } - - /// @brief Get index of refraction - /// @return IOR - float get_ior() const { return ior_; } - - /// @brief Get material type - /// @return Material type - MaterialType get_type() const { return type_; } - - /// @brief Get albedo texture - /// @return Albedo texture (nullptr if none) - std::shared_ptr get_albedo_texture() const { return albedo_texture_; } - - /// @brief Get normal texture - /// @return Normal texture (nullptr if none) - std::shared_ptr get_normal_texture() const { return normal_texture_; } - -private: - Vec3 albedo_; - Vec3 emission_; - float metallic_; - float roughness_; - float ior_; - MaterialType type_; - - std::shared_ptr albedo_texture_; - std::shared_ptr normal_texture_; -}; - -} // namespace are - -#endif // ARE_INCLUDE_SCENE_MATERIAL_H -``` - -### 文件:include/scene/light.h - -```cpp -#ifndef ARE_INCLUDE_SCENE_LIGHT_H -#define ARE_INCLUDE_SCENE_LIGHT_H - -#include "basic/types.h" - -namespace are { - -/// @brief Light type enumeration -enum class LightType { - DIRECTIONAL = 0, - POINT = 1, - SPOT = 2 -}; - -/// @brief Light source -class Light { -public: - /// @brief Constructor - Light(); - - /// @brief Destructor - ~Light(); - - /// @brief Set light type - /// @param type Light type - void set_type(LightType type); - - /// @brief Set light position (for point and spot lights) - /// @param position Light position - void set_position(const Vec3 &position); - - /// @brief Set light direction (for directional and spot lights) - /// @param direction Light direction - void set_direction(const Vec3 &direction); - - /// @brief Set light color - /// @param color Light color - void set_color(const Vec3 &color); - - /// @brief Set light intensity - /// @param intensity Light intensity - void set_intensity(float intensity); - - /// @brief Set light range (for point and spot lights) - /// @param range Light range - void set_range(float range); - - /// @brief Set spot light angles - /// @param inner_angle Inner cone angle in degrees - /// @param outer_angle Outer cone angle in degrees - void set_spot_angles(float inner_angle, float outer_angle); - - /// @brief Get light type - /// @return Light type - LightType get_type() const { - return type_; - } - - /// @brief Get light position - /// @return Light position - const Vec3 &get_position() const { - return position_; - } - - /// @brief Get light direction - /// @return Light direction - const Vec3 &get_direction() const { - return direction_; - } - - /// @brief Get light color - /// @return Light color - const Vec3 &get_color() const { - return color_; - } - - /// @brief Get light intensity - /// @return Light intensity - float get_intensity() const { - return intensity_; - } - - /// @brief Get light range - /// @return Light range - float get_range() const { - return range_; - } - - /// @brief Get spot light inner angle - /// @return Inner angle in radians - float get_inner_angle() const { - return inner_angle_; - } - - /// @brief Get spot light outer angle - /// @return Outer angle in radians - float get_outer_angle() const { - return outer_angle_; - } - -private: - LightType type_; - Vec3 position_; - Vec3 direction_; - Vec3 color_; - float intensity_; - float range_; - float inner_angle_; - float outer_angle_; -}; - -} // namespace are - -#endif // ARE_INCLUDE_SCENE_LIGHT_H -``` - -### 文件:include/scene/scene.h - -```cpp -#ifndef ARE_INCLUDE_SCENE_SCENE_H -#define ARE_INCLUDE_SCENE_SCENE_H - -#include "basic/types.h" -#include "scene/camera.h" -#include "scene/mesh.h" -#include "scene/material.h" -#include "scene/light.h" -#include -#include - -namespace are { - -/// @brief Scene container holding all scene objects -class Scene { -public: - /// @brief Constructor - Scene(); - - /// @brief Destructor - ~Scene(); - - /// @brief Add mesh to scene - /// @param mesh Mesh to add - /// @return Mesh index - uint add_mesh(std::shared_ptr mesh); - - /// @brief Add material to scene - /// @param material Material to add - /// @return Material index - uint add_material(std::shared_ptr material); - - /// @brief Add light to scene - /// @param light Light to add - /// @return Light index - uint add_light(std::shared_ptr light); - - /// @brief Set active camera - /// @param camera Camera to set - void set_camera(std::shared_ptr camera); - - /// @brief Get active camera - /// @return Active camera - const Camera& get_camera() const { return *camera_; } - - /// @brief Get all meshes - /// @return Mesh list - const std::vector>& get_meshes() const { return meshes_; } - - /// @brief Get all materials - /// @return Material list - const std::vector>& get_materials() const { return materials_; } - - /// @brief Get all lights - /// @return Light list - const std::vector>& get_lights() const { return lights_; } - - /// @brief Clear all scene objects - void clear(); - - /// @brief Update scene (animations, transforms, etc.) - /// @param delta_time Time since last update - void update(float delta_time); - -private: - std::shared_ptr camera_; - std::vector> meshes_; - std::vector> materials_; - std::vector> lights_; -}; - -} // namespace are - -#endif // ARE_INCLUDE_SCENE_SCENE_H -``` - -### 文件:include/scene/mesh.h - -```cpp -#ifndef ARE_INCLUDE_SCENE_MESH_H -#define ARE_INCLUDE_SCENE_MESH_H - -#include "basic/types.h" -#include - -namespace are { - -/// @brief Mesh data container -class Mesh { -public: - /// @brief Constructor - Mesh(); - - /// @brief Destructor - ~Mesh(); - - /// @brief Set vertex data - /// @param vertices Vertex array - void set_vertices(const std::vector& vertices); - - /// @brief Set index data - /// @param indices Index array - void set_indices(const std::vector& indices); - - /// @brief Set material index - /// @param material_id Material index - void set_material(uint material_id); - - /// @brief Set transform matrix - /// @param transform Transform matrix - void set_transform(const Mat4& transform); - - /// @brief Get vertices - /// @return Vertex array - const std::vector& get_vertices() const { return vertices_; } - - /// @brief Get indices - /// @return Index array - const std::vector& get_indices() const { return indices_; } - - /// @brief Get material index - /// @return Material index - uint get_material() const { return material_id_; } - - /// @brief Get transform matrix - /// @return Transform matrix - const Mat4& get_transform() const { return transform_; } - - /// @brief Upload mesh data to GPU - /// @return True if upload succeeded - bool upload_to_gpu(); - - /// @brief Release GPU resources - void release_gpu_resources(); - - /// @brief Get VAO handle - /// @return VAO handle - uint get_vao() const { return vao_; } - - /// @brief Check if mesh is uploaded to GPU - /// @return True if uploaded - bool is_uploaded() const { return uploaded_; } - -private: - std::vector vertices_; - std::vector indices_; - uint material_id_; - Mat4 transform_; - - uint vao_; - uint vbo_; - uint ebo_; - bool uploaded_; -}; - -} // namespace are - -#endif // ARE_INCLUDE_SCENE_MESH_H -``` - -### 文件:include/resource/buffer.h - -```cpp -#ifndef ARE_INCLUDE_RESOURCE_BUFFER_H -#define ARE_INCLUDE_RESOURCE_BUFFER_H - -#include "basic/types.h" - -namespace are { - -/// @brief Buffer usage hint -enum class BufferUsage { - STATIC_DRAW, - DYNAMIC_DRAW, - STREAM_DRAW -}; - -/// @brief Buffer type -enum class BufferType { - VERTEX_BUFFER, - INDEX_BUFFER, - UNIFORM_BUFFER, - SHADER_STORAGE_BUFFER -}; - -/// @brief GPU buffer resource -class Buffer { -public: - /// @brief Constructor - Buffer(); - - /// @brief Destructor - ~Buffer(); - - /// @brief Create buffer - /// @param type Buffer type - /// @param size Buffer size in bytes - /// @param data Initial data (nullptr for empty buffer) - /// @param usage Usage hint - /// @return True if creation succeeded - bool create(BufferType type, size_t size, const void* data, BufferUsage usage); - - /// @brief Update buffer data - /// @param offset Offset in bytes - /// @param size Size in bytes - /// @param data Data to upload - void update(size_t offset, size_t size, const void* data); - - /// @brief Bind buffer - void bind() const; - - /// @brief Bind buffer to binding point (for UBO/SSBO) - /// @param binding_point Binding point index - void bind_base(uint binding_point) const; - - /// @brief Unbind buffer - void unbind() const; - - /// @brief Release buffer resources - void release(); - - /// @brief Get buffer handle - /// @return Buffer handle - BufferHandle get_handle() const { return handle_; } - - /// @brief Get buffer size - /// @return Size in bytes - size_t get_size() const { return size_; } - - /// @brief Get buffer type - /// @return Buffer type - BufferType get_type() const { return type_; } - - /// @brief Check if buffer is valid - /// @return True if valid - bool is_valid() const { return handle_ != INVALID_HANDLE; } - -private: - BufferHandle handle_; - BufferType type_; - size_t size_; - BufferUsage usage_; -}; - -} // namespace are - -#endif // ARE_INCLUDE_RESOURCE_BUFFER_H -``` - -### 文件:include/resource/model_loader.h - -```cpp -#ifndef ARE_INCLUDE_RESOURCE_MODEL_LOADER_H -#define ARE_INCLUDE_RESOURCE_MODEL_LOADER_H - -#include "basic/types.h" -#include "scene/mesh.h" -#include "scene/material.h" -#include -#include -#include - -namespace are { - -/// @brief Model loader using Assimp -class ModelLoader { -public: - /// @brief Load model from file - /// @param path Model file path - /// @param meshes Output mesh list - /// @param materials Output material list - /// @param flip_uvs Flip UV coordinates vertically - /// @return True if loading succeeded - static bool load(const std::string& path, - std::vector>& meshes, - std::vector>& materials, - bool flip_uvs = true); - - /// @brief Load model and automatically upload to GPU - /// @param path Model file path - /// @param meshes Output mesh list - /// @param materials Output material list - /// @param flip_uvs Flip UV coordinates vertically - /// @return True if loading succeeded - static bool load_and_upload(const std::string& path, - std::vector>& meshes, - std::vector>& materials, - bool flip_uvs = true); - -private: - /// @brief Process Assimp node recursively - static void process_node_(void* node, void* scene, - std::vector>& meshes, - std::vector>& materials, - const std::string& directory); - - /// @brief Process Assimp mesh - static std::shared_ptr process_mesh_(void* mesh, void* scene, - std::vector>& materials, - const std::string& directory); - - /// @brief Load material textures - static void load_material_textures_(void* material, int type, - std::shared_ptr& mat, - const std::string& directory); -}; - -} // namespace are - -#endif // ARE_INCLUDE_RESOURCE_MODEL_LOADER_H -``` - -### 文件:include/resource/shader.h - -```cpp -#ifndef ARE_INCLUDE_RESOURCE_SHADER_H -#define ARE_INCLUDE_RESOURCE_SHADER_H - -#include "basic/types.h" -#include -#include - -namespace are { - -/// @brief Shader program resource -class Shader { -public: - /// @brief Constructor - Shader(); - - /// @brief Destructor - ~Shader(); - - /// @brief Load and compile shader from files - /// @param vertex_path Vertex shader path - /// @param fragment_path Fragment shader path - /// @return True if compilation succeeded - bool load(const std::string& vertex_path, const std::string& fragment_path); - - /// @brief Load and compile compute shader - /// @param compute_path Compute shader path - /// @return True if compilation succeeded - bool load_compute(const std::string& compute_path); - - /// @brief Compile shader from source strings - /// @param vertex_source Vertex shader source - /// @param fragment_source Fragment shader source - /// @return True if compilation succeeded - bool compile(const std::string& vertex_source, const std::string& fragment_source); - - /// @brief Compile compute shader from source - /// @param compute_source Compute shader source - /// @return True if compilation succeeded - bool compile_compute(const std::string& compute_source); - - /// @brief Use/activate shader program - void use() const; // 改为const - - /// @brief Release shader resources - void release(); - - /// @brief Set uniform boolean - /// @param name Uniform name - /// @param value Value - void set_bool(const std::string& name, bool value) const; // 新增,const - - /// @brief Set uniform integer - /// @param name Uniform name - /// @param value Value - void set_int(const std::string& name, int value) const; // 改为const - - /// @brief Set uniform unsigned integer - /// @param name Uniform name - /// @param value Value - void set_uint(const std::string& name, uint value) const; // 改为const - - /// @brief Set uniform float - /// @param name Uniform name - /// @param value Value - void set_float(const std::string& name, float value) const; // 改为const - - /// @brief Set uniform vec2 - /// @param name Uniform name - /// @param value Value - void set_vec2(const std::string& name, const Vec2& value) const; // 改为const - - /// @brief Set uniform vec3 - /// @param name Uniform name - /// @param value Value - void set_vec3(const std::string& name, const Vec3& value) const; // 改为const - - /// @brief Set uniform vec4 - /// @param name Uniform name - /// @param value Value - void set_vec4(const std::string& name, const Vec4& value) const; // 改为const - - /// @brief Set uniform mat3 - /// @param name Uniform name - /// @param value Value - void set_mat3(const std::string& name, const Mat3& value) const; // 改为const - - /// @brief Set uniform mat4 - /// @param name Uniform name - /// @param value Value - void set_mat4(const std::string& name, const Mat4& value) const; // 改为const - - /// @brief Get shader program handle - /// @return Shader handle - ShaderHandle get_handle() const { return handle_; } - - /// @brief Check if shader is valid - /// @return True if valid - bool is_valid() const { return handle_ != INVALID_HANDLE; } - -private: - ShaderHandle handle_; - mutable std::unordered_map uniform_cache_; // 改为mutable - - /// @brief Get uniform location (with caching) - /// @param name Uniform name - /// @return Uniform location - int get_uniform_location_(const std::string& name) const; // 改为const - - /// @brief Compile shader stage - /// @param source Shader source code - /// @param type Shader type (GL_VERTEX_SHADER, etc.) - /// @return Shader object handle (0 on failure) - uint compile_shader_(const std::string& source, uint type); - - /// @brief Link shader program - /// @param shaders Array of shader object handles - /// @param count Number of shaders - /// @return True if linking succeeded - bool link_program_(const uint* shaders, uint count); - - /// @brief Read file content - /// @param path File path - /// @return File content - std::string read_file_(const std::string& path); -}; - -} // namespace are - -#endif // ARE_INCLUDE_RESOURCE_SHADER_H -``` - -### 文件:include/resource/texture.h - -```cpp -#ifndef ARE_INCLUDE_RESOURCE_TEXTURE_H -#define ARE_INCLUDE_RESOURCE_TEXTURE_H - -#include "basic/types.h" -#include - -namespace are { - -/// @brief Texture format enumeration -enum class TextureFormat { - R8, - RG8, - RGB8, - RGBA8, - R16F, - RG16F, - RGB16F, - RGBA16F, - R32F, - RG32F, - RGB32F, - RGBA32F, - DEPTH24_STENCIL8 -}; - -/// @brief Texture filter mode -enum class TextureFilter { - NEAREST, - LINEAR, - NEAREST_MIPMAP_NEAREST, - LINEAR_MIPMAP_NEAREST, - NEAREST_MIPMAP_LINEAR, - LINEAR_MIPMAP_LINEAR -}; - -/// @brief Texture wrap mode -enum class TextureWrap { - REPEAT, - MIRRORED_REPEAT, - CLAMP_TO_EDGE, - CLAMP_TO_BORDER -}; - -/// @brief Texture resource -class Texture { -public: - /// @brief Constructor - Texture(); - - /// @brief Destructor - ~Texture(); - - /// @brief Load texture from file - /// @param path File path - /// @param generate_mipmaps Generate mipmaps - /// @return True if loading succeeded - bool load_from_file(const std::string& path, bool generate_mipmaps = true); - - /// @brief Create empty texture - /// @param width Texture width - /// @param height Texture height - /// @param format Texture format - /// @return True if creation succeeded - bool create(uint width, uint height, TextureFormat format); - - /// @brief Upload data to texture - /// @param data Pixel data - /// @param width Data width - /// @param height Data height - /// @param format Data format - /// @return True if upload succeeded - bool upload(const void* data, uint width, uint height, TextureFormat format); - - /// @brief Set texture filter mode - /// @param min_filter Minification filter - /// @param mag_filter Magnification filter - void set_filter(TextureFilter min_filter, TextureFilter mag_filter); - - /// @brief Set texture wrap mode - /// @param wrap_s Wrap mode for S coordinate - /// @param wrap_t Wrap mode for T coordinate - void set_wrap(TextureWrap wrap_s, TextureWrap wrap_t); - - /// @brief Generate mipmaps - void generate_mipmaps(); - - /// @brief Bind texture to texture unit - /// @param unit Texture unit - void bind(uint unit) const; - - /// @brief Unbind texture - void unbind() const; - - /// @brief Release texture resources - void release(); - - /// @brief Get texture handle - /// @return Texture handle - TextureHandle get_handle() const { return handle_; } - - /// @brief Get texture width - /// @return Width - uint get_width() const { return width_; } - - /// @brief Get texture height - /// @return Height - uint get_height() const { return height_; } - - /// @brief Get texture format - /// @return Format - TextureFormat get_format() const { return format_; } - - /// @brief Check if texture is valid - /// @return True if valid - bool is_valid() const { return handle_ != INVALID_HANDLE; } - -private: - TextureHandle handle_; - uint width_; - uint height_; - TextureFormat format_; - bool has_mipmaps_; -}; - -} // namespace are - -#endif // ARE_INCLUDE_RESOURCE_TEXTURE_H -``` - -### 文件:include/utils/config.h - -```cpp -#ifndef ARE_INCLUDE_UTILS_CONFIG_H -#define ARE_INCLUDE_UTILS_CONFIG_H - -#include -#include - -namespace are { - -/// @brief Configuration manager for loading engine settings -/// @note This module should be implemented by the user -class Config { -public: - /// @brief Load configuration from file - /// @param path Configuration file path - /// @return True if loading succeeded - static bool load(const std::string& path); - - /// @brief Save configuration to file - /// @param path Configuration file path - /// @return True if saving succeeded - static bool save(const std::string& path); - - /// @brief Get string value - /// @param key Configuration key - /// @param default_value Default value if key not found - /// @return Configuration value - static std::string get_string(const std::string& key, const std::string& default_value = ""); - - /// @brief Get integer value - /// @param key Configuration key - /// @param default_value Default value if key not found - /// @return Configuration value - static int get_int(const std::string& key, int default_value = 0); - - /// @brief Get float value - /// @param key Configuration key - /// @param default_value Default value if key not found - /// @return Configuration value - static float get_float(const std::string& key, float default_value = 0.0f); - - /// @brief Get boolean value - /// @param key Configuration key - /// @param default_value Default value if key not found - /// @return Configuration value - static bool get_bool(const std::string& key, bool default_value = false); - - /// @brief Set string value - /// @param key Configuration key - /// @param value Configuration value - static void set_string(const std::string& key, const std::string& value); - - /// @brief Set integer value - /// @param key Configuration key - /// @param value Configuration value - static void set_int(const std::string& key, int value); - - /// @brief Set float value - /// @param key Configuration key - /// @param value Configuration value - static void set_float(const std::string& key, float value); - - /// @brief Set boolean value - /// @param key Configuration key - /// @param value Configuration value - static void set_bool(const std::string& key, bool value); -}; - -} // namespace are - -#endif // ARE_INCLUDE_UTILS_CONFIG_H -``` - -### 文件:include/utils/logger.h - -```cpp -#ifndef ARE_INCLUDE_UTILS_LOGGER_H -#define ARE_INCLUDE_UTILS_LOGGER_H - -#include - -namespace are { - -/// @brief Log level enumeration -enum class LogLevel { - DEBUG, - INFO, - WARNING, - ERROR, - FATAL -}; - -/// @brief Logger interface for engine logging -/// @note This module should be implemented by the user -class Logger { -public: - /// @brief Initialize logger - /// @param log_file Log file path (empty for console only) - /// @return True if initialization succeeded - static bool initialize(const std::string& log_file = ""); - - /// @brief Shutdown logger - static void shutdown(); - - /// @brief Log message - /// @param level Log level - /// @param message Message content - static void log(LogLevel level, const std::string& message); - - /// @brief Log debug message - /// @param message Message content - static void debug(const std::string& message); - - /// @brief Log info message - /// @param message Message content - static void info(const std::string& message); - - /// @brief Log warning message - /// @param message Message content - static void warning(const std::string& message); - - /// @brief Log error message - /// @param message Message content - static void error(const std::string& message); - - /// @brief Log fatal message - /// @param message Message content - static void fatal(const std::string& message); - - /// @brief Set minimum log level - /// @param level Minimum level to log - static void set_level(LogLevel level); -}; - -} // namespace are - -#endif // ARE_INCLUDE_UTILS_LOGGER_H -``` - diff --git a/.write.sh b/.write.sh deleted file mode 100644 index 8d08aa4..0000000 --- a/.write.sh +++ /dev/null @@ -1,54 +0,0 @@ -#!/bin/bash - -# query.sh - 遍历指定文件夹中的 .h 文件并生成 all_headers.md - -# 检查是否提供了目录参数 -if [ $# -ne 1 ]; then - echo "用法: $0 <目标文件夹路径>" - exit 1 -fi - -TARGET_DIR="$1" - -# 检查提供的路径是否为一个存在的目录 -if [ ! -d "$TARGET_DIR" ]; then - echo "错误: 目录 '$TARGET_DIR' 不存在。" - exit 1 -fi - -# 输出文件 -OUTPUT_FILE="all_files.md" - -# 清空或创建输出文件 -> "$OUTPUT_FILE" - -echo "正在扫描目录: $TARGET_DIR" -# 使用 find 命令查找所有 .h 文件 -H_FILES=$(find "$TARGET_DIR" -type f -name "*.cpp") - -# 检查是否找到了 .h 文件 -if [ -z "$H_FILES" ]; then - echo "在目录 '$TARGET_DIR' 及其子目录中未找到任何 .h 文件。" - exit 0 -fi - -# 遍历找到的每个 .h 文件 -for header_file in $H_FILES; do - # 获取相对于脚本执行位置的相对路径 - RELATIVE_PATH=$(realpath --relative-to=. "$header_file") - - # 写入分隔符和文件名 - { - echo "### 文件:$RELATIVE_PATH" - echo "" - echo '```cpp' - cat "$header_file" - echo '```' - echo "" # 添加一个空行,使文件之间有分隔 - } >> "$OUTPUT_FILE" - - echo "已处理: $RELATIVE_PATH" -done - -echo "" -echo "处理完成!所有头文件内容已合并到 $OUTPUT_FILE 中。"