From f18c8c3fe39e871dc7cffee691b32696437b0b97 Mon Sep 17 00:00:00 2001 From: Redacted Date: Fri, 31 Jan 2025 19:26:11 -0500 Subject: [PATCH] Use JGL for more efficient rendering. --- CMakeLists.txt | 29 +++++++++-- main.cpp | 127 +++++++++++++++++++++++-------------------------- test.cpp | 20 ++++---- 3 files changed, 93 insertions(+), 83 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index fa17b98..14ca67a 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -28,20 +28,39 @@ include(cmake/CPM.cmake) # You specify the release name to target against. See the link below for releases: # https://git.redacted.cc/Redacted/ReWindow/releases +CPMAddPackage( + NAME mcolor + URL https://git.redacted.cc/maxine/mcolor/archive/Prerelease-5.zip +) + CPMAddPackage( NAME ReWindow - URL URL https://git.redacted.cc/Redacted/ReWindow/archive/Prerelease-31.zip + URL https://git.redacted.cc/Redacted/ReWindow/archive/Prerelease-32.zip +) + +CPMAddPackage( + NAME JGL + URL https://git.redacted.cc/josh/JGL/archive/Prerelease-47.zip ) add_executable(ReWalkerApp main.cpp) -target_include_directories(ReWalkerApp PUBLIC ${ReWindow_SOURCE_DIR}/include ${J3ML_SOURCE_DIR}/include) +target_include_directories(ReWalkerApp PUBLIC + ${ReWindow_SOURCE_DIR}/include + ${J3ML_SOURCE_DIR}/include + ${mcolor_SOURCE_DIR}/include + ${JGL_SOURCE_DIR}/include +) -target_link_libraries(ReWalkerApp PUBLIC J3ML ReWindowLibrary) +target_link_libraries(ReWalkerApp PUBLIC J3ML ReWindow mcolor JGL) # simple window test add_executable(TestWindowApp test.cpp) -target_include_directories(TestWindowApp PUBLIC ${ReWindow_SOURCE_DIR}/include ${J3ML_SOURCE_DIR}/include) +target_include_directories(TestWindowApp PUBLIC + ${ReWindow_SOURCE_DIR}/include + ${J3ML_SOURCE_DIR}/include + ${mcolor_SOURCE_DIR}/include +) -target_link_libraries(TestWindowApp PUBLIC J3ML ReWindowLibrary) \ No newline at end of file +target_link_libraries(TestWindowApp PUBLIC J3ML ReWindow) \ No newline at end of file diff --git a/main.cpp b/main.cpp index 6ec6375..14fb293 100644 --- a/main.cpp +++ b/main.cpp @@ -5,9 +5,10 @@ // Written by Rich // With help from (and thanks to) from Maxine, Josh and Bill -#include -#include -#include +#include +#include +#include +#include #include // Define window size and dot size (dot size should be odd for symmetry) @@ -18,6 +19,8 @@ // Define fading speed (higher = faster fading, range: 0.001 - 0.2) #define FADE_SPEED 0.05f +constexpr unsigned int TRAIL_LENGTH = 20; + // Enable debug mode (set to 0 to disable debug output) #define DEBUG 0 @@ -25,28 +28,28 @@ * @brief Represents the walker that moves randomly on the screen. */ struct Walker { - float x, y; // Current position of the walker + Vector2 position{}; // Current position of the walker /** * @brief Constructor initializes the walker at the center of the screen. */ - Walker() : x(WIDTH / 2.0f), y(HEIGHT / 2.0f) {} + Walker() : position(WIDTH / 2.0f, HEIGHT / 2.0f) {} /** * @brief Moves the walker one step in a random direction. */ void step() { float angle = static_cast(rand()) / RAND_MAX * 360.0f; - angle = angle * M_PI / 180.0f; // Convert degrees to radians + angle = Math::Radians(angle); float dx = std::cos(angle); float dy = std::sin(angle); // Update position and clamp within screen boundaries - x = std::clamp(x + dx, 0.0f, static_cast(WIDTH - 1)); - y = std::clamp(y + dy, 0.0f, static_cast(HEIGHT - 1)); + position.x = std::clamp(position.x + dx, 0.0f, static_cast(WIDTH - 1)); + position.y = std::clamp(position.y + dy, 0.0f, static_cast(HEIGHT - 1)); #if DEBUG - std::cout << "Walker Position: (" << x << ", " << y << ")\n"; + std::cout << "Walker Position: (" << position.x << ", " << position.y << ")\n"; #endif } @@ -59,8 +62,8 @@ struct Walker { void pushAway(float mouseX, float mouseY, float force) { float adjustedMouseY = HEIGHT - mouseY; // Adjust for coordinate system - float deltaX = x - mouseX; - float deltaY = y - adjustedMouseY; + float deltaX = position.x - mouseX; + float deltaY = position.y - adjustedMouseY; float distance = std::sqrt(deltaX * deltaX + deltaY * deltaY); @@ -70,8 +73,8 @@ struct Walker { float unitY = deltaY / distance; // Apply dynamic push force - x = std::clamp(x + unitX * force, 0.0f, static_cast(WIDTH - 1)); - y = std::clamp(y + unitY * force, 0.0f, static_cast(HEIGHT - 1)); + position.x = std::clamp(position.x + unitX * force, 0.0f, static_cast(WIDTH - 1)); + position.y = std::clamp(position.y + unitY * force, 0.0f, static_cast(HEIGHT - 1)); } } @@ -79,15 +82,14 @@ struct Walker { * @brief Resets the walker to the center of the screen. */ void resetPosition() { - x = WIDTH / 2.0f; - y = HEIGHT / 2.0f; + position = Vector2(WIDTH / 2.0f, HEIGHT / 2.0f); } }; /** * @brief Custom ReWindow window class that manages the random walker simulation. */ -class RandomWalkerWindow : public ReWindow::RWindow { +class RandomWalkerWindow : public ReWindow::OpenGLWindow { public: /** * @brief Constructor initializes the window, walker, and trail buffer. @@ -96,53 +98,54 @@ public: * @param height Window height */ RandomWalkerWindow(const std::string& title, int width, int height) - : ReWindow::RWindow(title, width, height), + : ReWindow::OpenGLWindow(title, width, height, 2, 1), walker(std::make_unique()), - trailBuffer(WIDTH * HEIGHT, 1.0f), // Initialize trail buffer to white (1.0) + trailBuffer{}, // Initialize trail buffer to white (1.0) pushForce(3.0f) // Default push force + {} - /** - * @brief Called once when the window is opened. - * Configures OpenGL to use a 2D orthographic projection. - */ void OnOpen() override { - glMatrixMode(GL_PROJECTION); - glLoadIdentity(); - glOrtho(0, WIDTH, HEIGHT, 0, -1, 1); // Map OpenGL coordinates to screen pixels - glMatrixMode(GL_MODELVIEW); + if (!JGL::Init({WIDTH, HEIGHT}, 0, 0)) + exit(0); + + this->render_target = new RenderTarget({WIDTH, HEIGHT}, Colors::White); } /** * @brief Called every frame to update and render the walker with a fading trail. */ void OnRefresh(float elapsed) override { - // Clear the OpenGL buffer (not the trail buffer) - glClear(GL_COLOR_BUFFER_BIT); - // Handle user inputs handleMouseInput(); handleKeyboardInput(); - // Update trail (fade effect) - fadeTrail(); - // Move the walker walker->step(); - // Update the trail buffer with the walkers current position - plotWalker(); - - // Render the updated trail - drawTrail(); + JGL::Update({WIDTH, HEIGHT}); + J2D::Begin(render_target, true); + // Update trail (fade effect) + fadeTrail(); + // Render the updated trail + drawTrail(); + // Update the trail buffer with the walkers current position + plotWalker(); + J2D::End(); + J2D::Begin(nullptr, true); + J2D::DrawRenderTarget(render_target, {0, 0}); + J2D::DrawString(Colors::Black, "Framerate: " + std::to_string((int) (1.f / delta_time)), 0, 0, 1, 16); + J2D::End(); // Swap buffers to display the frame - GLSwapBuffers(); + SwapBuffers(); } private: std::unique_ptr walker; - std::vector trailBuffer; // Stores grayscale intensity of pixels (1.0 = white, 0.0 = black) + std::vector> trailBuffer{}; // Stores grayscale intensity of pixels (1.0 = white, 0.0 = black) + RenderTarget* render_target = nullptr; + float pushForce; // Variable push force that can be adjusted in real time /** @@ -180,44 +183,34 @@ private: * @brief Applies the fade effect to the trail buffer. */ void fadeTrail() { - for (auto& pixel : trailBuffer) { - pixel = std::min(pixel + FADE_SPEED, 1.0f); // Ensure value does not exceed 1.0 (white) - } - } + // Fade out existing trail points + for (auto& trailPoint : trailBuffer) + trailPoint.second = std::max(trailPoint.second - FADE_SPEED, 0.0f); - /** - * @brief Plots the walkers current position as a black dot in the trail buffer. - */ - void plotWalker() { - int centerX = static_cast(walker->x); - int centerY = static_cast(walker->y); - int halfSize = DOT_SIZE / 2; + trailBuffer.emplace_back(walker->position, 1.0f); - for (int dy = -halfSize; dy <= halfSize; ++dy) { - for (int dx = -halfSize; dx <= halfSize; ++dx) { - int px = centerX + dx; - int py = centerY + dy; - - if (px >= 0 && px < WIDTH && py >= 0 && py < HEIGHT) { - trailBuffer[py * WIDTH + px] = 0.0f; - } - } - } + // Limit trail length + if (trailBuffer.size() > TRAIL_LENGTH) + trailBuffer.erase(trailBuffer.begin()); } void drawTrail() { - std::vector grayscale(WIDTH * HEIGHT); - for (size_t i = 0; i < trailBuffer.size(); ++i) { - grayscale[i] = static_cast(trailBuffer[i] * 255.0f); - } - glDrawPixels(WIDTH, HEIGHT, GL_LUMINANCE, GL_UNSIGNED_BYTE, grayscale.data()); + for (const auto& trailPoint : trailBuffer) + J2D::DrawPoint({0, 0, 0, (uint8_t) (trailPoint.second * 255.0f)}, trailPoint.first, DOT_SIZE); + } + + void plotWalker() { + J2D::DrawPoint(Colors::Black, walker->position, DOT_SIZE); } }; int main() { auto window = std::make_unique("Random Walker with ReWindow", WIDTH, HEIGHT); - window->SetRenderer(RenderingAPI::OPENGL); - window->Open(); + if (!window->Open()) + return -1; + + // Uncomment this to make things go super fast. + //window->SetVsyncEnabled(false); while (!window->IsClosing()) { window->ManagedRefresh(); diff --git a/test.cpp b/test.cpp index 73f12a1..2362bb1 100644 --- a/test.cpp +++ b/test.cpp @@ -1,32 +1,30 @@ // simple test program to open a window with // a blue background. -#include -#include +#include +#include #include #define WIDTH 800 #define HEIGHT 600 -class RandomWalkerWindow : public ReWindow::RWindow { +class RandomWalkerWindow : public ReWindow::OpenGLWindow { public: RandomWalkerWindow(const std::string& title, int width, int height) - : ReWindow::RWindow(title, width, height) {} + : ReWindow::OpenGLWindow(title, width, height, 2, 1) {} void OnRefresh(float elapsed) override { - glClearColor(0.0f, 0.0f, 1.0f, 1.0f); // Clear with blue - glClear(GL_COLOR_BUFFER_BIT); - GLSwapBuffers(); + //glClearColor(0.0f, 0.0f, 1.0f, 1.0f); // Clear with blue + //glClear(GL_COLOR_BUFFER_BIT); + SwapBuffers(); } }; int main() { - std::unique_ptr window = - std::make_unique("Random Walker with ReWindow", WIDTH, HEIGHT); - - window->SetRenderer(RenderingAPI::OPENGL); + std::unique_ptr window = + std::make_unique("Random Walker with ReWindow", WIDTH, HEIGHT); window->Open(); while (!window->IsClosing()) {