diff --git a/CMakeLists.txt b/CMakeLists.txt index 6ead108..bc2ec3f 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -264,6 +264,8 @@ set(SOURCE_FILES ${FUNGT_BASE_DIR}/GUI/gui.cpp ${FUNGT_BASE_DIR}/GUI/particle_rtc_window.cpp ${FUNGT_BASE_DIR}/GUI/physics/simulation_controller_window.cpp + ${FUNGT_BASE_DIR}/GUI/demo_particles_window.cpp + ${FUNGT_BASE_DIR}/GUI/render_action_window.cpp ${FUNGT_BASE_DIR}/GUI/physics/debug_rigidbody_renderer.cpp ${FUNGT_BASE_DIR}/SimpleModel/simple_model.cpp ${FUNGT_BASE_DIR}/SimpleGeometry/simple_geometry.cpp @@ -271,8 +273,8 @@ set(SOURCE_FILES ${FUNGT_BASE_DIR}/Physics/Collisions/manifold_collision.cpp ${FUNGT_BASE_DIR}/Physics/CollisionManager/collision_manager.cpp ${FUNGT_BASE_DIR}/Physics/Collider/collider.cpp - ${FUNGT_BASE_DIR}/Physics/Clothing/clothing.cpp ${FUNGT_BASE_DIR}/Physics/AnimationCreator/key_frame_recorder.cpp + ${FUNGT_BASE_DIR}/Physics/AnimationCreator/animation_exporter.cpp ${FUNGT_BASE_DIR}/ViewPort/viewport.cpp ${FUNGT_BASE_DIR}/ViewPort/progressive_path_tracer_viewport.cpp ${FUNGT_BASE_DIR}/Renders/framebuffer.cpp @@ -494,9 +496,24 @@ elseif (UNIX) else() set(SYCL_TARGETS spir64) endif() - target_compile_options(FunGT PRIVATE -fsycl -fsycl-targets=${SYCL_TARGETS}) + set(SYCL_SOURCES + ${FUNGT_BASE_DIR}/InfoDevice/sycl_backend.cpp + ${FUNGT_BASE_DIR}/ParticleSimulation/particle_simulation.cpp + ${FUNGT_BASE_DIR}/ParticleSimulation/particle_simulation_rtc.cpp + ${FUNGT_BASE_DIR}/Physics/AnimationCreator/animation_exporter.cpp + ${FUNGT_BASE_DIR}/GUI/demo_particles_window.cpp + ${FUNGT_BASE_DIR}/GUI/particle_rtc_window.cpp + ${FUNGT_BASE_DIR}/GUI/demo_particles_window.cpp + ${FUNGT_BASE_DIR}/GUI/render_action_window.cpp + ${FUNGT_BASE_DIR}/PBR/Space/space.cpp + ${FUNGT_BASE_DIR}/PBR/TriangleExtractor/triangle_extractor.cpp + ${FUNGT_BASE_DIR}/ViewPort/progressive_path_tracer_viewport.cpp + ) + + set_source_files_properties(${SYCL_SOURCES} + PROPERTIES COMPILE_FLAGS "-fsycl -fsycl-targets=${SYCL_TARGETS}" + ) target_link_options(FunGT PRIVATE -fsycl -fsycl-targets=${SYCL_TARGETS}) - if(FUNGT_USE_SYCL) target_compile_definitions(FunGT PRIVATE FUNGT_USE_SYCL) endif() diff --git a/ComputationalGeom/aabb.hpp b/ComputationalGeom/aabb.hpp index 973d87a..fc7edb1 100644 --- a/ComputationalGeom/aabb.hpp +++ b/ComputationalGeom/aabb.hpp @@ -3,6 +3,7 @@ #include "Vector/vector3.hpp" #include "gpu/include/fgt_cpu_device.hpp" #include +#include class AABB { public: diff --git a/GUI/demo_particles_window.cpp b/GUI/demo_particles_window.cpp new file mode 100644 index 0000000..e374dcb --- /dev/null +++ b/GUI/demo_particles_window.cpp @@ -0,0 +1,79 @@ +#include "demo_particles_window.hpp" +#include "ParticleSimulation/particle_simulation.hpp" +#include "ParticleSimulation/particle_demos.hpp" + +void ParticleSimDemoWindow::onImGuiRender() { + m_frameCount++; + auto currentTime = std::chrono::high_resolution_clock::now(); + float elapsed = std::chrono::duration(currentTime - m_lastFPSTime).count(); + + if (elapsed >= 0.5f) { + m_measuredFPS = m_frameCount / elapsed; + m_frameCount = 0; + m_lastFPSTime = currentTime; + } + + ImGui::Begin("Particle Demos"); + + if (!m_sceneManager) { + ImGui::TextColored(ImVec4(0.7f, 0.7f, 0.7f, 1.0f), "No scene manager"); + ImGui::End(); + return; + } + + const auto& allObjects = m_sceneManager->getRenderable(); + std::shared_ptr particleSim = nullptr; + + for (auto& obj : allObjects) { + auto sim = std::dynamic_pointer_cast(obj); + if (sim) { + particleSim = sim; + break; + } + } + + if (!particleSim) { + ImGui::TextColored(ImVec4(0.7f, 0.7f, 0.7f, 1.0f), "No particle simulation"); + ImGui::End(); + return; + } + + ImGui::TextColored(ImVec4(0.4f, 0.7f, 1.0f, 1.0f), "Active:"); + ImGui::SameLine(); + ImGui::Text("%s", fgt::demoNames[particleSim->getCurrentDemo()].c_str()); + ImGui::Separator(); + + if (ImGui::BeginCombo("##Demo", fgt::demoNames[m_selectedDemoIndex].c_str())) { + for (size_t i = 0; i < fgt::demoNames.size(); i++) { + bool isSelected = (m_selectedDemoIndex == static_cast(i)); + if (ImGui::Selectable(fgt::demoNames[i].c_str(), isSelected)) { + m_selectedDemoIndex = static_cast(i); + if (m_autoApply) { + particleSim->loadDemo(m_selectedDemoIndex); + } + } + if (isSelected) { + ImGui::SetItemDefaultFocus(); + } + } + ImGui::EndCombo(); + } + + ImGui::TextWrapped("%s", m_descriptions[m_selectedDemoIndex].c_str()); + + if (ImGui::Button("Load Demo", ImVec2(-1, 0))) { + particleSim->loadDemo(m_selectedDemoIndex); + } + + ImGui::Checkbox("Auto-load", &m_autoApply); + + if (ImGui::CollapsingHeader("Info")) { + ImGui::Text("Particles: %zu", particleSim->getParticleCount()); + ImGui::Text("Measured FPS: %.1f", m_measuredFPS); + ImGui::Text("ImGui FPS: %.1f", ImGui::GetIO().Framerate); + ImGui::Text("Frame time: %.2f ms", 1000.0f / m_measuredFPS); + ImGui::Text("Recommended: %d", m_recommendedCounts[m_selectedDemoIndex]); + } + + ImGui::End(); +} \ No newline at end of file diff --git a/GUI/demo_particles_window.hpp b/GUI/demo_particles_window.hpp index a727c5a..341cd94 100644 --- a/GUI/demo_particles_window.hpp +++ b/GUI/demo_particles_window.hpp @@ -2,10 +2,12 @@ #define _PARTICLE_SIM_DEMO_WINDOW_H_ #include "imgui_window.hpp" #include "SceneManager/scene_manager.hpp" -#include "ParticleSimulation/particle_simulation.hpp" -#include "ParticleSimulation/particle_demos.hpp" #include #include +#include +#include + +class ParticleSimulation; class ParticleSimDemoWindow : public ImGuiWindow { private: @@ -13,7 +15,6 @@ class ParticleSimDemoWindow : public ImGuiWindow { int m_selectedDemoIndex; bool m_autoApply; - // FPS measurement std::chrono::high_resolution_clock::time_point m_lastFPSTime; int m_frameCount; float m_measuredFPS; @@ -42,87 +43,7 @@ class ParticleSimDemoWindow : public ImGuiWindow { { } - void onImGuiRender() override { - // Measure FPS - m_frameCount++; - auto currentTime = std::chrono::high_resolution_clock::now(); - float elapsed = std::chrono::duration(currentTime - m_lastFPSTime).count(); - - if (elapsed >= 0.5f) { // Update twice per second for smooth display - m_measuredFPS = m_frameCount / elapsed; - m_frameCount = 0; - m_lastFPSTime = currentTime; - } - - ImGui::Begin("Particle Demos"); - - if (!m_sceneManager) { - ImGui::TextColored(ImVec4(0.7f, 0.7f, 0.7f, 1.0f), "No scene manager"); - ImGui::End(); - return; - } - - const auto& allObjects = m_sceneManager->getRenderable(); - std::shared_ptr particleSim = nullptr; - - for (auto& obj : allObjects) { - auto sim = std::dynamic_pointer_cast(obj); - if (sim) { - particleSim = sim; - break; - } - } - - if (!particleSim) { - ImGui::TextColored(ImVec4(0.7f, 0.7f, 0.7f, 1.0f), "No particle simulation"); - ImGui::End(); - return; - } - - // Current demo indicator (compact) - ImGui::TextColored(ImVec4(0.4f, 0.7f, 1.0f, 1.0f), "Active:"); - ImGui::SameLine(); - ImGui::Text("%s", fgt::demoNames[particleSim->getCurrentDemo()].c_str()); - ImGui::Separator(); - - // Demo selection - if (ImGui::BeginCombo("##Demo", fgt::demoNames[m_selectedDemoIndex].c_str())) { - for (int i = 0; i < fgt::demoNames.size(); i++) { - bool isSelected = (m_selectedDemoIndex == i); - if (ImGui::Selectable(fgt::demoNames[i].c_str(), isSelected)) { - m_selectedDemoIndex = i; - if (m_autoApply) { - particleSim->loadDemo(m_selectedDemoIndex); - } - } - if (isSelected) { - ImGui::SetItemDefaultFocus(); - } - } - ImGui::EndCombo(); - } - - // Compact description - ImGui::TextWrapped("%s", m_descriptions[m_selectedDemoIndex].c_str()); - - // Load button - if (ImGui::Button("Load Demo", ImVec2(-1, 0))) { - particleSim->loadDemo(m_selectedDemoIndex); - } - - ImGui::Checkbox("Auto-load", &m_autoApply); - - // Collapsing info section - if (ImGui::CollapsingHeader("Info")) { - ImGui::Text("Particles: %zu", particleSim->getParticleCount()); - ImGui::Text("Measured FPS: %.1f", m_measuredFPS); - ImGui::Text("ImGui FPS: %.1f", ImGui::GetIO().Framerate); - ImGui::Text("Frame time: %.2f ms", 1000.0f / m_measuredFPS); - ImGui::Text("Recommended: %d", m_recommendedCounts[m_selectedDemoIndex]); - } - - ImGui::End(); - } + void onImGuiRender() override; }; #endif // _PARTICLE_SIM_DEMO_WINDOW_H_ \ No newline at end of file diff --git a/GUI/imgui_layer.hpp b/GUI/imgui_layer.hpp index 97c5c27..076cff2 100644 --- a/GUI/imgui_layer.hpp +++ b/GUI/imgui_layer.hpp @@ -3,6 +3,7 @@ #include "imgui_window.hpp" #include "Layer/layer.hpp" #include "InfoDevice/gpu_device_info.hpp" +#include "Path_Manager/path_manager.hpp" #include "render_settings_window.hpp" #include @@ -191,8 +192,10 @@ class ImGuiLayer : public Layer { io.Fonts->Clear(); // Load your font file (TTF) + // + std::string fontPath = getAssetPath("GUI/fonts/Nunito/static/Nunito-Regular.ttf"); ImFont* myFont = io.Fonts->AddFontFromFileTTF( - "/home/juanchuletas/Documents/Development/FunGT/GUI/fonts/Nunito/static/Nunito-Regular.ttf", 18.0f + fontPath.c_str(), 18.0f ); if (myFont == nullptr) @@ -358,4 +361,4 @@ class ImGuiLayer : public Layer { } }; -#endif // _IMGUI_LAYER_H_ \ No newline at end of file +#endif // _IMGUI_LAYER_H_ diff --git a/GUI/particle_rtc_window.cpp b/GUI/particle_rtc_window.cpp index 25a852f..10f31af 100644 --- a/GUI/particle_rtc_window.cpp +++ b/GUI/particle_rtc_window.cpp @@ -1,4 +1,5 @@ #include "particle_rtc_window.hpp" +#include "ParticleSimulation/particle_simulation_rtc.hpp" #include #include static size_t WriteCallback(void* contents, size_t size, size_t nmemb, void* userp) { diff --git a/GUI/particle_rtc_window.hpp b/GUI/particle_rtc_window.hpp index d927d4c..5ccd68d 100644 --- a/GUI/particle_rtc_window.hpp +++ b/GUI/particle_rtc_window.hpp @@ -2,13 +2,12 @@ #define PARTICLE_RTC_WINDOW_HPP #include "GUI/imgui_window.hpp" -#include "ParticleSimulation/particle_simulation_rtc.hpp" #include #include #include #include - +class ParticleRTC; diff --git a/GUI/render_action_window.cpp b/GUI/render_action_window.cpp new file mode 100644 index 0000000..e55c2c7 --- /dev/null +++ b/GUI/render_action_window.cpp @@ -0,0 +1,271 @@ +#include "render_action_window.hpp" +#include "PBR/Space/space.hpp" +#include "SimpleModel/simple_model.hpp" +#include "SimpleGeometry/simple_geometry.hpp" +#include "Vector/vector3.hpp" + +void RenderWindow::onImGuiRender() { + ImGui::SetNextWindowSize(ImVec2(350, 500), ImGuiCond_FirstUseEver); + ImGui::Begin("Render"); + + if (!m_sceneManager || !m_camera) { + ImGui::TextColored(ImVec4(0.7f, 0.7f, 0.7f, 1.0f), "Waiting for scene..."); + ImGui::End(); + return; + } + + // ACTIVE COMPUTE DEVICE + ImGui::SeparatorText("Compute Backend"); + + if (m_gpuManager) { + const auto& devices = m_gpuManager->getDevices(); + int activeIdx = m_gpuManager->getActiveDeviceIndex(); + if (activeIdx >= 0 && activeIdx < static_cast(devices.size())) { + const auto& dev = devices[activeIdx]; + ImGui::Text("Device: %s", dev.name.c_str()); + ImGui::Text("Backend: %s", dev.getBackendName().c_str()); + if (dev.memory_bytes > 0) + ImGui::TextDisabled("Memory: %s", dev.getMemoryString().c_str()); + else if (dev.compute_units > 0) + ImGui::TextDisabled("Compute Units: %d EUs", dev.compute_units); + } + else { + ImGui::TextColored(ImVec4(1.0f, 0.5f, 0.0f, 1.0f), "No device selected"); + } + ImGui::TextDisabled("Change device in Render Settings"); + } + + ImGui::Spacing(); + ImGui::Separator(); + + // VIEWPORT PREVIEW + ImGui::SeparatorText("Viewport Preview"); + + if (ImGui::Checkbox("Enable RaySpace Preview", &m_viewportPathTrace)) { + if (m_viewport) { + m_viewport->enablePathTracing(m_viewportPathTrace); + if (m_viewportPathTrace) { + m_viewport->resetAccumulation(); + } + } + } + + if (m_viewportPathTrace) { + ImGui::SliderInt("Preview Samples", &m_previewSamples, 1, 128); + if (m_viewport) { + m_viewport->setMaxPreviewSamples(m_previewSamples); + } + + ImGui::TextColored(ImVec4(0.7f, 0.7f, 0.7f, 1.0f), + "Progressive rendering in viewport"); + ImGui::TextColored(ImVec4(0.7f, 0.7f, 0.7f, 1.0f), + "(resets when camera moves)"); + } + + // RESOLUTION SETTINGS + ImGui::SeparatorText("Resolution"); + + if (ImGui::Combo("Preset", &m_selectedPreset, m_resolutionPresets, 5)) { + switch (m_selectedPreset) { + case 1: m_renderWidth = 1920; m_renderHeight = 1080; break; + case 2: m_renderWidth = 2560; m_renderHeight = 1440; break; + case 3: m_renderWidth = 3840; m_renderHeight = 2160; break; + case 4: + m_renderWidth = m_viewportWidth; + m_renderHeight = m_viewportHeight; + m_useViewportSize = true; + break; + default: break; + } + } + + ImGui::Spacing(); + + if (m_selectedPreset == 0 || m_selectedPreset == 4) { + ImGui::BeginDisabled(m_useViewportSize); + ImGui::InputInt("Width", &m_renderWidth); + ImGui::InputInt("Height", &m_renderHeight); + ImGui::EndDisabled(); + + if (m_useViewportSize) { + ImGui::TextColored(ImVec4(0.5f, 0.5f, 0.5f, 1.0f), + "Using viewport: %dx%d", m_viewportWidth, m_viewportHeight); + } + } + else { + ImGui::Text("Resolution: %dx%d", m_renderWidth, m_renderHeight); + } + + float aspect = (float)m_renderWidth / m_renderHeight; + ImGui::Text("Aspect Ratio: %.3f", aspect); + + ImGui::Spacing(); + ImGui::Separator(); + + // QUALITY SETTINGS + ImGui::SeparatorText("Quality"); + + ImGui::SliderInt("Samples", &m_samples, 1, 512); + ImGui::TextColored(ImVec4(0.5f, 0.5f, 0.5f, 1.0f), + "Higher = better quality, slower"); + + ImGui::Spacing(); + ImGui::Separator(); + + // SCENE INFO + ImGui::SeparatorText("Scene Info"); + + const auto& objects = m_sceneManager->getRenderable(); + ImGui::Text("Objects in scene: %zu", objects.size()); + + glm::vec3 camPos = m_camera->getPosition(); + ImGui::Text("Camera: (%.1f, %.1f, %.1f)", camPos.x, camPos.y, camPos.z); + + ImGui::Spacing(); + ImGui::Separator(); + ImGui::Spacing(); + + // RENDER BUTTON + ImGui::BeginDisabled(m_isRendering); + + if (ImGui::Button("Render Image", ImVec2(-1, 40))) { + triggerRender(); + } + + ImGui::EndDisabled(); + + if (m_isRendering) { + ImGui::TextColored(ImVec4(1.0f, 0.8f, 0.0f, 1.0f), "Rendering..."); + ImGui::TextWrapped("Check console for progress"); + } + + ImGui::Spacing(); + if (m_gpuManager) { + const auto& devices = m_gpuManager->getDevices(); + int activeIdx = m_gpuManager->getActiveDeviceIndex(); + if (activeIdx >= 0 && activeIdx < static_cast(devices.size())) { + ImGui::TextColored(ImVec4(0.5f, 0.5f, 0.5f, 1.0f), + "Output: %s_output.png", devices[activeIdx].getBackendName().c_str()); + } + } + + ImGui::End(); +} + +void RenderWindow::triggerRender() { + std::cout << "\n========== STARTING PBR RENDER ==========" << std::endl; + + m_isRendering = true; + + try { + // SET COMPUTE BACKEND FROM SELECTED DEVICE + { + const auto& devices = m_gpuManager->getDevices(); + int activeIdx = m_gpuManager->getActiveDeviceIndex(); + if (activeIdx >= 0 && activeIdx < static_cast(devices.size())) { + const auto& dev = devices[activeIdx]; + if (dev.backend == fungt::GPUBackend::CUDA) { + ComputeRender::SetBackend(Compute::Backend::CUDA); + } + else if (dev.backend == fungt::GPUBackend::SYCL) { + bool isNvidia = dev.vendor.find("NVIDIA") != std::string::npos || + dev.vendor.find("nvidia") != std::string::npos; + ComputeRender::SetBackend(isNvidia ? Compute::Backend::SYCL_CUDA + : Compute::Backend::SYCL); + } + else { + ComputeRender::SetBackend(Compute::Backend::CPU); + } + } + else { + ComputeRender::SetBackend(Compute::Backend::CUDA); + } + } + std::cout << "Backend: " << ComputeRender::GetBackendName() << std::endl; + + // SYNC CAMERA FROM VIEWPORT + glm::vec3 pos = m_camera->getPosition(); + glm::vec3 front = m_camera->getFront(); + glm::vec3 up = m_camera->getUp(); + float fov = m_camera->getFOV(); + + glm::vec3 lookAt = pos + front; + + fungt::Vec3 pbrPos(pos.x, pos.y, pos.z); + fungt::Vec3 pbrLookAt(lookAt.x, lookAt.y, lookAt.z); + fungt::Vec3 pbrUp(up.x, up.y, up.z); + + int width = m_useViewportSize ? m_viewportWidth : m_renderWidth; + int height = m_useViewportSize ? m_viewportHeight : m_renderHeight; + float aspect = (float)width / height; + + std::cout << "Resolution: " << width << "x" << height << std::endl; + std::cout << "Samples: " << m_samples << std::endl; + std::cout << "Camera Position: (" << pos.x << ", " << pos.y << ", " << pos.z << ")" << std::endl; + + PBRCamera pbrCam(pbrPos, pbrLookAt, pbrUp, fov, aspect); + + // SETUP SPACE + Space space(pbrCam); + space.InitComputeRenderBackend(); + space.loadLightsFromScene(m_sceneManager->getLights()); + + // LOAD ALL MODELS FROM SCENE + const auto& objects = m_sceneManager->getRenderable(); + + int modelCount = 0; + int geometryCount = 0; + for (auto& obj : objects) { + auto simpleModel = std::dynamic_pointer_cast(obj); + if (simpleModel) { + std::cout << "Loading model " << (modelCount + 1) << " to PBR scene..." << std::endl; + space.LoadModelToRender(*simpleModel); + modelCount++; + continue; + } + auto simpleGeometry = std::dynamic_pointer_cast(obj); + if (simpleGeometry) { + std::cout << "Loading geometry " << (geometryCount + 1) << " to PBR scene..." << std::endl; + space.LoadGeometryToRender(*simpleGeometry); + geometryCount++; + } + } + + if (modelCount == 0 && geometryCount == 0) { + std::cerr << "No models or geometries found in scene!" << std::endl; + m_isRendering = false; + return; + } + + std::cout << "Loaded " << modelCount << " models" << std::endl; + + // BUILD BVH + std::cout << "Building BVH..." << std::endl; + space.BuildBVH(); + + // RENDER + space.setSamples(m_samples); + + auto renderStart = std::chrono::high_resolution_clock::now(); + std::cout << "Rendering..." << std::endl; + + auto framebuffer = space.Render(width, height); + + auto renderEnd = std::chrono::high_resolution_clock::now(); + auto renderTime = std::chrono::duration_cast(renderEnd - renderStart).count(); + + // SAVE OUTPUT + Space::SaveFrameBufferAsPNG(framebuffer, width, height); + + std::cout << "\n========== RENDER COMPLETE ==========" << std::endl; + std::cout << "Time: " << renderTime << " seconds" << std::endl; + std::cout << "Output: " << ComputeRender::GetBackendName() << "_output.png" << std::endl; + std::cout << "====================================\n" << std::endl; + + } + catch (const std::exception& e) { + std::cerr << "Render failed: " << e.what() << std::endl; + } + + m_isRendering = false; +} \ No newline at end of file diff --git a/GUI/render_action_window.hpp b/GUI/render_action_window.hpp index 89845f1..74ae34a 100644 --- a/GUI/render_action_window.hpp +++ b/GUI/render_action_window.hpp @@ -4,7 +4,6 @@ #include "imgui_window.hpp" #include "Camera/camera.hpp" #include "SceneManager/scene_manager.hpp" -#include "PBR/Space/space.hpp" #include "PBR/PBRCamera/pbr_camera.hpp" #include "PBR/Render/include/compute_backends.hpp" #include "ViewPort/viewport.hpp" @@ -12,31 +11,21 @@ #include #include -/** - * Render Window - PBR Path Tracing Controls - * - * Provides UI for: - * - Compute backend selection (CUDA/CPU) - * - Resolution settings - * - Sample count - * - Render triggering - */ class RenderWindow : public ImGuiWindow { private: std::shared_ptr m_sceneManager; std::shared_ptr m_gpuManager; Camera* m_camera; - // Render settings int m_samples = 128; int m_renderWidth = 1920; int m_renderHeight = 1080; bool m_useViewportSize = false; bool m_isRendering = false; - bool m_viewportPathTrace = false; // Enable viewport preview? - int m_previewSamples = 32; // Samples for preview + bool m_viewportPathTrace = false; + int m_previewSamples = 32; ViewPort* m_viewport = nullptr; - // Resolution presets + const char* m_resolutionPresets[5] = { "Custom", "HD (1920x1080)", @@ -44,15 +33,16 @@ class RenderWindow : public ImGuiWindow { "4K (3840x2160)", "Viewport Size" }; - int m_selectedPreset = 1; // Default to HD + int m_selectedPreset = 1; - // Viewport dimensions (set externally) int m_viewportWidth = 1920; int m_viewportHeight = 1080; + void triggerRender(); + public: RenderWindow(std::shared_ptr sceneManager, Camera* camera, ViewPort* viewport, - std::shared_ptr gpuManager) + std::shared_ptr gpuManager) : m_sceneManager(sceneManager) , m_gpuManager(gpuManager) , m_camera(camera) @@ -60,308 +50,12 @@ class RenderWindow : public ImGuiWindow { { } - // Set viewport dimensions from outside void setViewportSize(int width, int height) { m_viewportWidth = width; m_viewportHeight = height; } - void onImGuiRender() override { - ImGui::SetNextWindowSize(ImVec2(350, 500), ImGuiCond_FirstUseEver); - ImGui::Begin("Render"); - - if (!m_sceneManager || !m_camera) { - ImGui::TextColored(ImVec4(0.7f, 0.7f, 0.7f, 1.0f), "Waiting for scene..."); - ImGui::End(); - return; - } - - // ==================================================================== - // ACTIVE COMPUTE DEVICE - // ==================================================================== - ImGui::SeparatorText("Compute Backend"); - - if (m_gpuManager) { - const auto& devices = m_gpuManager->getDevices(); - int activeIdx = m_gpuManager->getActiveDeviceIndex(); - if (activeIdx >= 0 && activeIdx < static_cast(devices.size())) { - const auto& dev = devices[activeIdx]; - ImGui::Text("Device: %s", dev.name.c_str()); - ImGui::Text("Backend: %s", dev.getBackendName().c_str()); - if (dev.memory_bytes > 0) - ImGui::TextDisabled("Memory: %s", dev.getMemoryString().c_str()); - else if (dev.compute_units > 0) - ImGui::TextDisabled("Compute Units: %d EUs", dev.compute_units); - } else { - ImGui::TextColored(ImVec4(1.0f, 0.5f, 0.0f, 1.0f), "No device selected"); - } - ImGui::TextDisabled("Change device in Render Settings"); - } - - ImGui::Spacing(); - ImGui::Separator(); - // ==================================================================== - // NEW SECTION - VIEWPORT PREVIEW - // ==================================================================== - ImGui::SeparatorText("Viewport Preview"); - - if (ImGui::Checkbox("Enable RaySpace Preview", &m_viewportPathTrace)) { - if (m_viewport) { - m_viewport->enablePathTracing(m_viewportPathTrace); - if (m_viewportPathTrace) { - m_viewport->resetAccumulation(); - } - } - } - - if (m_viewportPathTrace) { - ImGui::SliderInt("Preview Samples", &m_previewSamples, 1, 128); - if (m_viewport) { - m_viewport->setMaxPreviewSamples(m_previewSamples); - } - - ImGui::TextColored(ImVec4(0.7f, 0.7f, 0.7f, 1.0f), - "Progressive rendering in viewport"); - ImGui::TextColored(ImVec4(0.7f, 0.7f, 0.7f, 1.0f), - "(resets when camera moves)"); - } - // ==================================================================== - // RESOLUTION SETTINGS - // ==================================================================== - ImGui::SeparatorText("Resolution"); - - if (ImGui::Combo("Preset", &m_selectedPreset, m_resolutionPresets, 5)) { - // Apply preset - switch (m_selectedPreset) { - case 1: m_renderWidth = 1920; m_renderHeight = 1080; break; // HD - case 2: m_renderWidth = 2560; m_renderHeight = 1440; break; // 2K - case 3: m_renderWidth = 3840; m_renderHeight = 2160; break; // 4K - case 4: - m_renderWidth = m_viewportWidth; - m_renderHeight = m_viewportHeight; - m_useViewportSize = true; - break; - default: break; // Custom - } - } - - ImGui::Spacing(); - - // Manual resolution input - if (m_selectedPreset == 0 || m_selectedPreset == 4) { - ImGui::BeginDisabled(m_useViewportSize); - ImGui::InputInt("Width", &m_renderWidth); - ImGui::InputInt("Height", &m_renderHeight); - ImGui::EndDisabled(); - - if (m_useViewportSize) { - ImGui::TextColored(ImVec4(0.5f, 0.5f, 0.5f, 1.0f), - "Using viewport: %dx%d", m_viewportWidth, m_viewportHeight); - } - } - else { - ImGui::Text("Resolution: %dx%d", m_renderWidth, m_renderHeight); - } - - // Aspect ratio info - float aspect = (float)m_renderWidth / m_renderHeight; - ImGui::Text("Aspect Ratio: %.3f", aspect); - - ImGui::Spacing(); - ImGui::Separator(); - - // ==================================================================== - // QUALITY SETTINGS - // ==================================================================== - ImGui::SeparatorText("Quality"); - - ImGui::SliderInt("Samples", &m_samples, 1, 512); - ImGui::TextColored(ImVec4(0.5f, 0.5f, 0.5f, 1.0f), - "Higher = better quality, slower"); - - ImGui::Spacing(); - ImGui::Separator(); - - // ==================================================================== - // RENDER INFO - // ==================================================================== - ImGui::SeparatorText("Scene Info"); - - const auto& objects = m_sceneManager->getRenderable(); - ImGui::Text("Objects in scene: %zu", objects.size()); - - glm::vec3 camPos = m_camera->getPosition(); - ImGui::Text("Camera: (%.1f, %.1f, %.1f)", camPos.x, camPos.y, camPos.z); - - ImGui::Spacing(); - ImGui::Separator(); - ImGui::Spacing(); - - // ==================================================================== - // RENDER BUTTON - // ==================================================================== - ImGui::BeginDisabled(m_isRendering); - - if (ImGui::Button("Render Image", ImVec2(-1, 40))) { - triggerRender(); - } - - ImGui::EndDisabled(); - - if (m_isRendering) { - ImGui::TextColored(ImVec4(1.0f, 0.8f, 0.0f, 1.0f), "Rendering..."); - ImGui::TextWrapped("Check console for progress"); - } - - ImGui::Spacing(); - if (m_gpuManager) { - const auto& devices = m_gpuManager->getDevices(); - int activeIdx = m_gpuManager->getActiveDeviceIndex(); - if (activeIdx >= 0 && activeIdx < static_cast(devices.size())) { - ImGui::TextColored(ImVec4(0.5f, 0.5f, 0.5f, 1.0f), - "Output: %s_output.png", devices[activeIdx].getBackendName().c_str()); - } - } - - ImGui::End(); - } - -private: - void triggerRender() { - std::cout << "\n========== STARTING PBR RENDER ==========" << std::endl; - - m_isRendering = true; - - try { - // ================================================================ - // 1. SET COMPUTE BACKEND FROM SELECTED DEVICE - // ================================================================ - { - const auto& devices = m_gpuManager->getDevices(); - int activeIdx = m_gpuManager->getActiveDeviceIndex(); - if (activeIdx >= 0 && activeIdx < static_cast(devices.size())) { - const auto& dev = devices[activeIdx]; - if (dev.backend == fungt::GPUBackend::CUDA) { - ComputeRender::SetBackend(Compute::Backend::CUDA); - } else if (dev.backend == fungt::GPUBackend::SYCL) { - // SYCL on NVIDIA hardware uses the SYCL_CUDA backend - bool isNvidia = dev.vendor.find("NVIDIA") != std::string::npos || - dev.vendor.find("nvidia") != std::string::npos; - ComputeRender::SetBackend(isNvidia ? Compute::Backend::SYCL_CUDA - : Compute::Backend::SYCL); - } else { - ComputeRender::SetBackend(Compute::Backend::CPU); - } - } else { - ComputeRender::SetBackend(Compute::Backend::CUDA); // fallback - } - } - std::cout << "Backend: " << ComputeRender::GetBackendName() << std::endl; - - // ================================================================ - // 2. SYNC CAMERA FROM VIEWPORT - // ================================================================ - glm::vec3 pos = m_camera->getPosition(); - glm::vec3 front = m_camera->getFront(); - glm::vec3 up = m_camera->getUp(); - float fov = m_camera->getFOV(); - - // Calculate look-at point - glm::vec3 lookAt = pos + front; - - // Convert to PBR format - fungt::Vec3 pbrPos(pos.x, pos.y, pos.z); - fungt::Vec3 pbrLookAt(lookAt.x, lookAt.y, lookAt.z); - fungt::Vec3 pbrUp(up.x, up.y, up.z); - - // Get resolution (use viewport size if enabled) - int width = m_useViewportSize ? m_viewportWidth : m_renderWidth; - int height = m_useViewportSize ? m_viewportHeight : m_renderHeight; - float aspect = (float)width / height; - - std::cout << "Resolution: " << width << "x" << height << std::endl; - std::cout << "Samples: " << m_samples << std::endl; - std::cout << "Camera Position: (" << pos.x << ", " << pos.y << ", " << pos.z << ")" << std::endl; - - // Create PBR camera - PBRCamera pbrCam(pbrPos, pbrLookAt, pbrUp, fov, aspect); - - // ================================================================ - // 3. SETUP SPACE - // ================================================================ - Space space(pbrCam); - space.InitComputeRenderBackend(); - // ADD LIGHT FROM THE SceneManager config - space.loadLightsFromScene(m_sceneManager->getLights()); - // ================================================================ - // 4. LOAD ALL MODELS FROM SCENE - // ================================================================ - const auto& objects = m_sceneManager->getRenderable(); - - int modelCount = 0; - int geometryCount = 0; - for (auto& obj : objects) { - // Try to cast to SimpleModel - auto simpleModel = std::dynamic_pointer_cast(obj); - if (simpleModel) { - std::cout << "Loading model " << (modelCount + 1) << " to PBR scene..." << std::endl; - space.LoadModelToRender(*simpleModel); - modelCount++; - continue; - } - auto simpleGeometry = std::dynamic_pointer_cast(obj); - if (simpleGeometry) { - std::cout << "Loading geometry " << (geometryCount + 1) << " to PBR scene..." << std::endl; - space.LoadGeometryToRender(*simpleGeometry); - geometryCount++; - } - } - // Try to cast to SimpleGeometry - - if (modelCount == 0 && geometryCount == 0) { - std::cerr << "No models or geometries found in scene!" << std::endl; - m_isRendering = false; - return; - } - - std::cout << "Loaded " << modelCount << " models" << std::endl; - - // ================================================================ - // 5. BUILD BVH - // ================================================================ - std::cout << "Building BVH..." << std::endl; - space.BuildBVH(); - - // ================================================================ - // 6. RENDER - // ================================================================ - space.setSamples(m_samples); - - auto renderStart = std::chrono::high_resolution_clock::now(); - std::cout << "Rendering..." << std::endl; - - auto framebuffer = space.Render(width, height); - - auto renderEnd = std::chrono::high_resolution_clock::now(); - auto renderTime = std::chrono::duration_cast(renderEnd - renderStart).count(); - - // ================================================================ - // 7. SAVE OUTPUT - // ================================================================ - Space::SaveFrameBufferAsPNG(framebuffer, width, height); - - std::cout << "\n========== RENDER COMPLETE ==========" << std::endl; - std::cout << "Time: " << renderTime << " seconds" << std::endl; - std::cout << "Output: " << ComputeRender::GetBackendName() << "_output.png" << std::endl; - std::cout << "====================================\n" << std::endl; - - } - catch (const std::exception& e) { - std::cerr << "Render failed: " << e.what() << std::endl; - } - - m_isRendering = false; - } + void onImGuiRender() override; }; #endif // _RENDER_WINDOW_H_ \ No newline at end of file diff --git a/PBR/BVH/aabb.hpp b/PBR/BVH/aabb.hpp index 5807ed8..eeedb63 100644 --- a/PBR/BVH/aabb.hpp +++ b/PBR/BVH/aabb.hpp @@ -3,6 +3,7 @@ #include "Vector/vector3.hpp" #include "gpu/include/fgt_cpu_device.hpp" #include +#include class AABB { public: diff --git a/PBR/BVH/bvh_builder.hpp b/PBR/BVH/bvh_builder.hpp index 7833fc6..b15d937 100644 --- a/PBR/BVH/bvh_builder.hpp +++ b/PBR/BVH/bvh_builder.hpp @@ -6,6 +6,7 @@ #include "Triangle/triangle.hpp" #include "PBR/BVH/aabb.hpp" #include "PBR/BVH/bvh_node.hpp" +#include struct TriangleBounds { AABB bounds; fungt::Vec3 centroid; diff --git a/PBR/PBRCamera/pbr_camera.hpp b/PBR/PBRCamera/pbr_camera.hpp index 8513418..323842f 100644 --- a/PBR/PBRCamera/pbr_camera.hpp +++ b/PBR/PBRCamera/pbr_camera.hpp @@ -46,7 +46,7 @@ class PBRCamera { float focusDist = 1.0f // Focus distance ) { // Convert FOV to radians - float theta = vfov * M_PI / 180.0f; + float theta = vfov * FGT_PI / 180.0f; float h = tanf(theta / 2.0f); float viewportHeight = 2.0f * h * focusDist; float viewportWidth = aspectRatio * viewportHeight; @@ -104,13 +104,14 @@ class PBRCamera { } }; - -#endif // _PBR_CAMERA_H_ - -#if defined(FUNGT_USE_SYCL) && !defined(PBRCAMERA_SYCL_DEVICE_COPYABLE_DEFINED) -#define PBRCAMERA_SYCL_DEVICE_COPYABLE_DEFINED +#if defined(SYCL_LANGUAGE_VERSION) || defined(__SYCL_DEVICE_ONLY__) +#include namespace sycl { - template<> - struct is_device_copyable : std::true_type {}; + inline namespace _V1 { + template <> + struct is_device_copyable : std::true_type {}; + } } #endif + +#endif // _PBR_CAMERA_H_ \ No newline at end of file diff --git a/PBR/Render/brdf/cook_torrance.hpp b/PBR/Render/brdf/cook_torrance.hpp index f4e69aa..fe5eded 100644 --- a/PBR/Render/brdf/cook_torrance.hpp +++ b/PBR/Render/brdf/cook_torrance.hpp @@ -12,7 +12,7 @@ fgt_device_forceinline float D_GGX(float NoH, float roughness) { float NoH2 = NoH * NoH; float denom = NoH2 * (a2 - 1.0f) + 1.0f; denom = fmaxf(denom, 1e-6f); - return a2 / (M_PI * denom * denom + 1e-8f); + return a2 / (FGT_PI * denom * denom + 1e-8f); } fgt_device_forceinline float G_SchlickGGX(float NoV, float k) { return NoV / (NoV * (1.0f - k) + k + 1e-8f); @@ -80,7 +80,7 @@ fgt_device_forceinline fungt::Vec3 evaluateCookTorrance( // Diffuse (Lambert) scaled by (1 - F) and (1 - metallic) fungt::Vec3 kS = F; fungt::Vec3 kD = (fungt::Vec3(1.0f, 1.0f, 1.0f) - kS) * (1.0f - metallic); - fungt::Vec3 diffuse = (baseColor / M_PI); + fungt::Vec3 diffuse = (baseColor / FGT_PI); fungt::Vec3 Lo = (kD * diffuse + specular) * radiance * NoL; diff --git a/PBR/Render/shared/core_renderer.hpp b/PBR/Render/shared/core_renderer.hpp index e1ef645..7b66770 100644 --- a/PBR/Render/shared/core_renderer.hpp +++ b/PBR/Render/shared/core_renderer.hpp @@ -58,7 +58,7 @@ fgt_device_gpu inline fungt::Vec3 sampleHemisphere(const fungt::Vec3& normal, fu float v = fgtRNG.nextFloat(); float theta = acosf(sqrtf(1.0f - u)); - float phi = 2.0f * M_PI * v; + float phi = 2.0f * FGT_PI * v; float xs = sinf(theta) * cosf(phi); float ys = sinf(theta) * sinf(phi); diff --git a/PBR/Space/space.cpp b/PBR/Space/space.cpp index d9a3575..96499df 100644 --- a/PBR/Space/space.cpp +++ b/PBR/Space/space.cpp @@ -1,4 +1,5 @@ #include "space.hpp" +#include "Vector/vector3_glm.hpp" #define STB_IMAGE_WRITE_IMPLEMENTATION #include "../../vendor/stb_image/stb_image_write.h" Space::Space(){ diff --git a/PBR/main/CMakeLists.txt b/PBR/main/CMakeLists.txt index 05af3dc..516fc73 100644 --- a/PBR/main/CMakeLists.txt +++ b/PBR/main/CMakeLists.txt @@ -1,7 +1,7 @@ cmake_minimum_required(VERSION 3.15) project(pbr_render) -option(FUNGT_USE_CUDA "Enable CUDA backend" ON) +option(FUNGT_USE_CUDA "Enable CUDA backend" OFF) option(FUNGT_USE_SYCL "Enable SYCL backend" ON) # ──────────────────────────────────────────────────────── @@ -175,9 +175,6 @@ target_include_directories(pbr_core PUBLIC ${FUNLIB_DIR}/include ) -target_compile_options(pbr_core PRIVATE -fsycl) -target_link_options(pbr_core PRIVATE -fsycl) - message(STATUS "Core PBR library configured (compiler: Intel clang + -fsycl)") # ──────────────────────────────────────────────────────── @@ -407,4 +404,4 @@ else() endif() message(STATUS "Output directory: ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}") message(STATUS "══════════════════════════════════════") -message(STATUS "") \ No newline at end of file +message(STATUS "") diff --git a/Physics/AnimationCreator/animation_controller.hpp b/Physics/AnimationCreator/animation_controller.hpp index 3b94480..dd6dc9c 100644 --- a/Physics/AnimationCreator/animation_controller.hpp +++ b/Physics/AnimationCreator/animation_controller.hpp @@ -5,6 +5,7 @@ #include "SceneManager/scene_manager.hpp" #include "SimpleModel/simple_model.hpp" #include "SimpleGeometry/simple_geometry.hpp" +#include "Vector/vector3_glm.hpp" #include #include #include diff --git a/Physics/AnimationCreator/animation_exporter.cpp b/Physics/AnimationCreator/animation_exporter.cpp new file mode 100644 index 0000000..21da06e --- /dev/null +++ b/Physics/AnimationCreator/animation_exporter.cpp @@ -0,0 +1,68 @@ +#include "animation_exporter.hpp" +#include "PBR/Space/space.hpp" +#include "PBR/PBRCamera/pbr_camera.hpp" +#include "PBR/TriangleExtractor/triangle_extractor.hpp" +#include "Vector/vector3.hpp" + +namespace fungt { + + void AnimationExporter::exportAnimation(int startFrame, int endFrame, const std::string& outputDir) { + std::cout << "\n========================================" << std::endl; + std::cout << "ANIMATION EXPORT STARTED" << std::endl; + std::cout << "========================================" << std::endl; + std::cout << "Frames: " << startFrame << " - " << endFrame << std::endl; + std::cout << "Total: " << (endFrame - startFrame + 1) << " frames" << std::endl; + std::cout << "Resolution: " << m_width << "x" << m_height << std::endl; + std::cout << "Samples: " << m_samplesPerPixel << std::endl; + std::cout << "Output: " << outputDir << std::endl; + std::cout << "========================================\n" << std::endl; + + glm::vec3 pos = m_camera->getPosition(); + glm::vec3 front = m_camera->getFront(); + glm::vec3 up = m_camera->getUp(); + float fov = m_camera->getFOV(); + + glm::vec3 lookAt = pos + front; + + fungt::Vec3 pbrPos(pos.x, pos.y, pos.z); + fungt::Vec3 pbrLookAt(lookAt.x, lookAt.y, lookAt.z); + fungt::Vec3 pbrUp(up.x, up.y, up.z); + float aspect = (float)m_width / m_height; + + PBRCamera pbrCam(pbrPos, pbrLookAt, pbrUp, fov, aspect); + + ComputeRender::SetBackend(m_backend); + Space space(pbrCam); + space.setSamples(m_samplesPerPixel); + space.InitComputeRenderBackend(); + + for (int frame = startFrame; frame <= endFrame; frame++) { + std::cout << "[" << (frame - startFrame + 1) << "/" << (endFrame - startFrame + 1) + << "] Rendering frame " << frame << "..." << std::endl; + + m_animController->updateFrame(frame); + space.ClearGeometry(); + + extractTriangles(m_sceneManager.get(), space); + + space.BuildBVH(); + + std::vector framebuffer = space.Render(m_width, m_height); + + char filename[512]; + snprintf(filename, sizeof(filename), "%sframe_%04d.png", outputDir.c_str(), frame); + Space::SaveFrameBufferAsPNG(framebuffer, m_width, m_height, std::string(filename)); + m_progressCallback(frame - startFrame + 1, endFrame - startFrame + 1); + std::cout << " Saved: " << filename << std::endl; + } + + std::cout << "\n========================================" << std::endl; + std::cout << "EXPORT COMPLETE!" << std::endl; + std::cout << "Total frames rendered: " << (endFrame - startFrame + 1) << std::endl; + std::cout << "Location: " << outputDir << std::endl; + std::cout << "\nTo create video, run:" << std::endl; + std::cout << "ffmpeg -framerate 30 -i " << outputDir << "frame_%04d.png -c:v libx264 -pix_fmt yuv420p -crf 18 output.mp4" << std::endl; + std::cout << "========================================\n" << std::endl; + } + +} // namespace fungt \ No newline at end of file diff --git a/Physics/AnimationCreator/animation_exporter.hpp b/Physics/AnimationCreator/animation_exporter.hpp index d1de627..87c6eeb 100644 --- a/Physics/AnimationCreator/animation_exporter.hpp +++ b/Physics/AnimationCreator/animation_exporter.hpp @@ -3,18 +3,14 @@ #include "Physics/AnimationCreator/animation_controller.hpp" #include "SceneManager/scene_manager.hpp" -#include "PBR/Space/space.hpp" -#include "PBR/TriangleExtractor/triangle_extractor.hpp" +#include "PBR/Render/include/compute_backends.hpp" +#include "Camera/camera.hpp" #include #include #include + namespace fungt { - /** - * AnimationExporter - Renders animation frames using PBR path tracer - * - * Takes recorded keyframes and renders them frame-by-frame to PNG files - */ class AnimationExporter { private: std::shared_ptr m_animController; @@ -24,10 +20,11 @@ namespace fungt { int m_height; int m_samplesPerPixel; Compute::Backend m_backend; - Camera* m_camera; + Camera* m_camera; + public: AnimationExporter(std::shared_ptr animController, - std::shared_ptr sceneManager,Camera* camera) + std::shared_ptr sceneManager, Camera* camera) : m_animController(animController) , m_sceneManager(sceneManager) , m_width(1920) @@ -37,9 +34,11 @@ namespace fungt { , m_camera(camera) { } - void setBackend(Compute::Backend backend) { // ← ADD THIS! + + void setBackend(Compute::Backend backend) { m_backend = backend; } + void setResolution(int width, int height) { m_width = width; m_height = height; @@ -48,77 +47,12 @@ namespace fungt { void setSamples(int samples) { m_samplesPerPixel = samples; } + void setProgressCallback(std::function cb) { m_progressCallback = cb; } - void exportAnimation(int startFrame, int endFrame, const std::string& outputDir) { - std::cout << "\n========================================" << std::endl; - std::cout << "ANIMATION EXPORT STARTED" << std::endl; - std::cout << "========================================" << std::endl; - std::cout << "Frames: " << startFrame << " - " << endFrame << std::endl; - std::cout << "Total: " << (endFrame - startFrame + 1) << " frames" << std::endl; - std::cout << "Resolution: " << m_width << "x" << m_height << std::endl; - std::cout << "Samples: " << m_samplesPerPixel << std::endl; - std::cout << "Output: " << outputDir << std::endl; - std::cout << "========================================\n" << std::endl; - glm::vec3 pos = m_camera->getPosition(); - glm::vec3 front = m_camera->getFront(); - glm::vec3 up = m_camera->getUp(); - float fov = m_camera->getFOV(); - - // Calculate look-at point - glm::vec3 lookAt = pos + front; - - // Convert to PBR format - fungt::Vec3 pbrPos(pos.x, pos.y, pos.z); - fungt::Vec3 pbrLookAt(lookAt.x, lookAt.y, lookAt.z); - fungt::Vec3 pbrUp(up.x, up.y, up.z); - float aspect = (float)m_width / m_height; - - // Create PBR camera - PBRCamera pbrCam(pbrPos, pbrLookAt, pbrUp, fov, aspect); - // Create Space (path tracer) ONCE - ComputeRender::SetBackend(m_backend); // Fucking important to set backend before initializing Space! - Space space(pbrCam); - space.setSamples(m_samplesPerPixel); - space.InitComputeRenderBackend(); - - - - // Render each frame - for (int frame = startFrame; frame <= endFrame; frame++) { - std::cout << "[" << (frame - startFrame + 1) << "/" << (endFrame - startFrame + 1) - << "] Rendering frame " << frame << "..." << std::endl; - - // 1. Update scene to this frame using keyframes - m_animController->updateFrame(frame); - space.ClearGeometry(); // Clear previous frame's geometry and lights - // 2. Extract triangles from scene (with updated transforms) - extractTriangles(m_sceneManager.get(), space); - - // 4. Build BVH acceleration structure - space.BuildBVH(); - - // 5. Render with path tracer - std::vector framebuffer = space.Render(m_width, m_height); - - // 6. Save PNG with frame number - char filename[512]; - snprintf(filename, sizeof(filename), "%sframe_%04d.png", outputDir.c_str(), frame); - Space::SaveFrameBufferAsPNG(framebuffer, m_width, m_height, std::string(filename)); - m_progressCallback(frame - startFrame + 1, endFrame - startFrame + 1); // Update progress bar - std::cout << " Saved: " << filename << std::endl; - } - - std::cout << "\n========================================" << std::endl; - std::cout << "EXPORT COMPLETE!" << std::endl; - std::cout << "Total frames rendered: " << (endFrame - startFrame + 1) << std::endl; - std::cout << "Location: " << outputDir << std::endl; - std::cout << "\nTo create video, run:" << std::endl; - std::cout << "ffmpeg -framerate 30 -i " << outputDir << "frame_%04d.png -c:v libx264 -pix_fmt yuv420p -crf 18 output.mp4" << std::endl; - std::cout << "========================================\n" << std::endl; - } + void exportAnimation(int startFrame, int endFrame, const std::string& outputDir); }; } // namespace fungt diff --git a/Physics/AnimationCreator/key_frame_recorder.hpp b/Physics/AnimationCreator/key_frame_recorder.hpp index 2ab831a..6e6f23e 100644 --- a/Physics/AnimationCreator/key_frame_recorder.hpp +++ b/Physics/AnimationCreator/key_frame_recorder.hpp @@ -6,6 +6,7 @@ #include #include #include +#include #include "Vector/vector3.hpp" namespace fungt { diff --git a/Random/fgt_rng.hpp b/Random/fgt_rng.hpp index 3a4f9d0..8b60c65 100644 --- a/Random/fgt_rng.hpp +++ b/Random/fgt_rng.hpp @@ -1,6 +1,7 @@ #if !defined(_FGT_RNG_H_) #define _FGT_RNG_H_ #include "gpu/include/fgt_cpu_device.hpp" +#include namespace fungt{ class RNG{ diff --git a/Samples/iwocl/CMakeLists.txt b/Samples/iwocl/CMakeLists.txt index 6ead108..bc2ec3f 100644 --- a/Samples/iwocl/CMakeLists.txt +++ b/Samples/iwocl/CMakeLists.txt @@ -264,6 +264,8 @@ set(SOURCE_FILES ${FUNGT_BASE_DIR}/GUI/gui.cpp ${FUNGT_BASE_DIR}/GUI/particle_rtc_window.cpp ${FUNGT_BASE_DIR}/GUI/physics/simulation_controller_window.cpp + ${FUNGT_BASE_DIR}/GUI/demo_particles_window.cpp + ${FUNGT_BASE_DIR}/GUI/render_action_window.cpp ${FUNGT_BASE_DIR}/GUI/physics/debug_rigidbody_renderer.cpp ${FUNGT_BASE_DIR}/SimpleModel/simple_model.cpp ${FUNGT_BASE_DIR}/SimpleGeometry/simple_geometry.cpp @@ -271,8 +273,8 @@ set(SOURCE_FILES ${FUNGT_BASE_DIR}/Physics/Collisions/manifold_collision.cpp ${FUNGT_BASE_DIR}/Physics/CollisionManager/collision_manager.cpp ${FUNGT_BASE_DIR}/Physics/Collider/collider.cpp - ${FUNGT_BASE_DIR}/Physics/Clothing/clothing.cpp ${FUNGT_BASE_DIR}/Physics/AnimationCreator/key_frame_recorder.cpp + ${FUNGT_BASE_DIR}/Physics/AnimationCreator/animation_exporter.cpp ${FUNGT_BASE_DIR}/ViewPort/viewport.cpp ${FUNGT_BASE_DIR}/ViewPort/progressive_path_tracer_viewport.cpp ${FUNGT_BASE_DIR}/Renders/framebuffer.cpp @@ -494,9 +496,24 @@ elseif (UNIX) else() set(SYCL_TARGETS spir64) endif() - target_compile_options(FunGT PRIVATE -fsycl -fsycl-targets=${SYCL_TARGETS}) + set(SYCL_SOURCES + ${FUNGT_BASE_DIR}/InfoDevice/sycl_backend.cpp + ${FUNGT_BASE_DIR}/ParticleSimulation/particle_simulation.cpp + ${FUNGT_BASE_DIR}/ParticleSimulation/particle_simulation_rtc.cpp + ${FUNGT_BASE_DIR}/Physics/AnimationCreator/animation_exporter.cpp + ${FUNGT_BASE_DIR}/GUI/demo_particles_window.cpp + ${FUNGT_BASE_DIR}/GUI/particle_rtc_window.cpp + ${FUNGT_BASE_DIR}/GUI/demo_particles_window.cpp + ${FUNGT_BASE_DIR}/GUI/render_action_window.cpp + ${FUNGT_BASE_DIR}/PBR/Space/space.cpp + ${FUNGT_BASE_DIR}/PBR/TriangleExtractor/triangle_extractor.cpp + ${FUNGT_BASE_DIR}/ViewPort/progressive_path_tracer_viewport.cpp + ) + + set_source_files_properties(${SYCL_SOURCES} + PROPERTIES COMPILE_FLAGS "-fsycl -fsycl-targets=${SYCL_TARGETS}" + ) target_link_options(FunGT PRIVATE -fsycl -fsycl-targets=${SYCL_TARGETS}) - if(FUNGT_USE_SYCL) target_compile_definitions(FunGT PRIVATE FUNGT_USE_SYCL) endif() diff --git a/SimpleModel/simple_model.cpp b/SimpleModel/simple_model.cpp index 97cbe65..f931fe8 100644 --- a/SimpleModel/simple_model.cpp +++ b/SimpleModel/simple_model.cpp @@ -1,4 +1,5 @@ #include "simple_model.hpp" +#include "Vector/vector3_glm.hpp" SimpleModel::SimpleModel() { diff --git a/Vector/vector3.hpp b/Vector/vector3.hpp index 91a8d2d..008da75 100644 --- a/Vector/vector3.hpp +++ b/Vector/vector3.hpp @@ -1,7 +1,6 @@ #if !defined(_VECTOR3_HPP_) #define _VECTOR3_HPP_ #include -#include "../include/glmath.hpp" #include "../gpu/include/fgt_cpu_device.hpp" // DEBUG: Print what fgt_device expands to @@ -96,16 +95,6 @@ namespace fungt{ fgt_device inline fungt::Vec3 operator*(float scalar, const fungt::Vec3& v) { return fungt::Vec3(v.x * scalar, v.y * scalar, v.z * scalar); } - fgt_device inline Vec3 toFungtVec3(const glm::vec3& v) { - return Vec3(v.x, v.y, v.z); - } - fgt_device inline Vec3 toFungtVec3(float vec[3]) { - return Vec3(vec[0], vec[1], vec[2]); - } - fgt_device inline glm::vec3 toGlmVec3(const fungt::Vec3& vec) { - - return glm::vec3(vec.x, vec.y, vec.z); - } } diff --git a/Vector/vector3_glm.hpp b/Vector/vector3_glm.hpp new file mode 100644 index 0000000..c6dd61d --- /dev/null +++ b/Vector/vector3_glm.hpp @@ -0,0 +1,20 @@ +#if !defined(_VECTOR3_GLM_HPP_) +#define _VECTOR3_GLM_HPP_ +#include "vector3.hpp" +#include "../include/glmath.hpp" + +namespace fungt { + + inline Vec3 toFungtVec3(const glm::vec3& v) { + return Vec3(v.x, v.y, v.z); + } + inline Vec3 toFungtVec3(float vec[3]) { + return Vec3(vec[0], vec[1], vec[2]); + } + inline glm::vec3 toGlmVec3(const fungt::Vec3& vec) { + return glm::vec3(vec.x, vec.y, vec.z); + } + +} + +#endif \ No newline at end of file diff --git a/ViewPort/progressive_path_tracer_viewport.cpp b/ViewPort/progressive_path_tracer_viewport.cpp index ef850b1..8340859 100644 --- a/ViewPort/progressive_path_tracer_viewport.cpp +++ b/ViewPort/progressive_path_tracer_viewport.cpp @@ -1,5 +1,11 @@ #include "progressive_path_tracer_viewport.hpp" - +#include "PBR/Space/space.hpp" +ProgressivePathTracer::ProgressivePathTracer() +{ +} +ProgressivePathTracer::~ProgressivePathTracer() +{ +} void ProgressivePathTracer::initialize(Camera* viewportCam, std::shared_ptr sceneManager, int width, int height) diff --git a/ViewPort/progressive_path_tracer_viewport.hpp b/ViewPort/progressive_path_tracer_viewport.hpp index b9ffb6a..dc596ca 100644 --- a/ViewPort/progressive_path_tracer_viewport.hpp +++ b/ViewPort/progressive_path_tracer_viewport.hpp @@ -4,12 +4,11 @@ #include "include/prerequisites.hpp" #include "Camera/camera.hpp" #include "SceneManager/scene_manager.hpp" -#include "PBR/Space/space.hpp" #include "PBR/PBRCamera/pbr_camera.hpp" #include "PBR/Render/include/compute_backends.hpp" #include #include - +class Space; class ProgressivePathTracer { private: std::unique_ptr m_space; @@ -19,8 +18,8 @@ class ProgressivePathTracer { bool m_initialized = false; public: - ProgressivePathTracer() = default; - ~ProgressivePathTracer() = default; + ProgressivePathTracer(); + ~ProgressivePathTracer(); // Initialize with camera and scene void initialize(Camera* viewportCam, diff --git a/funGT/fungt.hpp b/funGT/fungt.hpp index 1b97a32..3cd6ff7 100644 --- a/funGT/fungt.hpp +++ b/funGT/fungt.hpp @@ -4,10 +4,7 @@ #include "SceneManager/scene_manager.hpp" #include "CubeMap/cube_map.hpp" #include "Geometries/inf_grid.hpp" -#include "ParticleSimulation/particle_simulation.hpp" #include "Path_Manager/path_manager.hpp" -#include "Physics/Clothing/clothing.hpp" -#include "Physics/Clothing/clothing.hpp" #include "ViewPort/viewport.hpp" #include "ViewPort/progressive_path_tracer_viewport.hpp" #include "Layer/layer_stack.hpp" diff --git a/gpu/include/fgt_cpu_device.hpp b/gpu/include/fgt_cpu_device.hpp index ae17439..e9f882a 100644 --- a/gpu/include/fgt_cpu_device.hpp +++ b/gpu/include/fgt_cpu_device.hpp @@ -40,4 +40,5 @@ #define fgt_device_forceinline inline #define fgt_global #define fgt_shared -#endif \ No newline at end of file +#endif +constexpr float FGT_PI = 3.14159265f; \ No newline at end of file