From d78691455262448a45ad879c580dd1bdb2a0580d Mon Sep 17 00:00:00 2001 From: ssdfasd <2156608475@qq.com> Date: Sat, 21 Mar 2026 11:56:59 +0800 Subject: [PATCH] =?UTF-8?q?Engine:=20=E6=B7=BB=E5=8A=A0=20/FS=20=E6=A0=87?= =?UTF-8?q?=E5=BF=97=E4=BF=AE=E5=A4=8D=20MSVC=20PDB=20=E5=86=B2=E7=AA=81?= =?UTF-8?q?=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 在 CMakeLists.txt 中为 MSVC 编译选项添加 /FS 标志 - 添加 OpenGL Screenshot 模块支持 --- engine/CMakeLists.txt | 3 +- .../XCEngine/RHI/OpenGL/OpenGLScreenshot.h | 30 ++++++++ engine/src/RHI/OpenGL/OpenGLScreenshot.cpp | 71 +++++++++++++++++++ 3 files changed, 103 insertions(+), 1 deletion(-) create mode 100644 engine/include/XCEngine/RHI/OpenGL/OpenGLScreenshot.h create mode 100644 engine/src/RHI/OpenGL/OpenGLScreenshot.cpp diff --git a/engine/CMakeLists.txt b/engine/CMakeLists.txt index 0d04c645..81bc5dda 100644 --- a/engine/CMakeLists.txt +++ b/engine/CMakeLists.txt @@ -155,6 +155,7 @@ add_library(XCEngine STATIC ${CMAKE_CURRENT_SOURCE_DIR}/src/RHI/OpenGL/OpenGLRenderTargetView.cpp ${CMAKE_CURRENT_SOURCE_DIR}/src/RHI/OpenGL/OpenGLDepthStencilView.cpp ${CMAKE_CURRENT_SOURCE_DIR}/src/RHI/OpenGL/OpenGLScreenshot.cpp + ${CMAKE_SOURCE_DIR}/tests/OpenGL/package/src/glad.c # RHI Factory ${CMAKE_CURRENT_SOURCE_DIR}/src/RHI/RHIFactory.cpp @@ -254,7 +255,7 @@ target_include_directories(XCEngine PUBLIC ) if(MSVC) - target_compile_options(XCEngine PRIVATE /W3) + target_compile_options(XCEngine PRIVATE /W3 /FS) else() target_compile_options(XCEngine PRIVATE -Wall) endif() diff --git a/engine/include/XCEngine/RHI/OpenGL/OpenGLScreenshot.h b/engine/include/XCEngine/RHI/OpenGL/OpenGLScreenshot.h new file mode 100644 index 00000000..f120ced3 --- /dev/null +++ b/engine/include/XCEngine/RHI/OpenGL/OpenGLScreenshot.h @@ -0,0 +1,30 @@ +#pragma once + +#include +#include + +namespace XCEngine { +namespace RHI { + +class OpenGLSwapChain; +class OpenGLDevice; + +class OpenGLScreenshot { +public: + static bool Capture(OpenGLDevice& device, + OpenGLSwapChain& swapChain, + const char* filename); + + static bool Capture(OpenGLDevice& device, + OpenGLSwapChain& swapChain, + const char* filename, + int width, + int height); + +private: + static bool SavePPM(const char* filename, + int width, int height); +}; + +} // namespace RHI +} // namespace XCEngine \ No newline at end of file diff --git a/engine/src/RHI/OpenGL/OpenGLScreenshot.cpp b/engine/src/RHI/OpenGL/OpenGLScreenshot.cpp new file mode 100644 index 00000000..cbd8eb0a --- /dev/null +++ b/engine/src/RHI/OpenGL/OpenGLScreenshot.cpp @@ -0,0 +1,71 @@ +#include "XCEngine/RHI/OpenGL/OpenGLScreenshot.h" +#include "XCEngine/RHI/OpenGL/OpenGLDevice.h" +#include "XCEngine/RHI/OpenGL/OpenGLSwapChain.h" +#include "XCEngine/Debug/Logger.h" +#include "XCEngine/Debug/ConsoleLogSink.h" +#include "XCEngine/Containers/String.h" + +#include + +#include +#include +#include + +using namespace XCEngine::Debug; + +namespace XCEngine { +namespace RHI { +namespace { + +bool SavePPM(const char* filename, int width, int height) { + unsigned char* pixels = (unsigned char*)malloc(width * height * 3); + if (!pixels) { + Logger::Get().Error(LogCategory::Rendering, "[OpenGLScreenshot] Failed to allocate pixel buffer"); + return false; + } + + glFinish(); + glReadBuffer(GL_BACK); + glPixelStorei(GL_PACK_ALIGNMENT, 1); + glPixelStorei(GL_PACK_ROW_LENGTH, 0); + glPixelStorei(GL_PACK_SKIP_PIXELS, 0); + glPixelStorei(GL_PACK_SKIP_ROWS, 0); + glReadPixels(0, 0, width, height, GL_RGB, GL_UNSIGNED_BYTE, pixels); + + FILE* f = fopen(filename, "wb"); + if (!f) { + Logger::Get().Error(LogCategory::Rendering, "[OpenGLScreenshot] Failed to open file"); + free(pixels); + return false; + } + + fprintf(f, "P6\n%d %d\n255\n", width, height); + + unsigned char* row = (unsigned char*)malloc(width * 3); + for (int y = height - 1; y >= 0; y--) { + memcpy(row, pixels + y * width * 3, width * 3); + fwrite(row, 1, width * 3, f); + } + + free(row); + free(pixels); + fclose(f); + + Logger::Get().Debug(LogCategory::Rendering, "[OpenGLScreenshot] Screenshot saved"); + return true; +} + +} // anonymous namespace + +bool OpenGLScreenshot::Capture(OpenGLDevice& device, OpenGLSwapChain& swapChain, const char* filename) { + return Capture(device, swapChain, filename, swapChain.GetWidth(), swapChain.GetHeight()); +} + +bool OpenGLScreenshot::Capture(OpenGLDevice& device, OpenGLSwapChain& swapChain, const char* filename, int width, int height) { + (void)device; + (void)swapChain; + return SavePPM(filename, width, height); +} + +} // namespace RHI +} // namespace XCEngine \ No newline at end of file