From 28c63cf8eeefaed021e07233dd16331b851db2d9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Mart=C3=AD?= <49535803+damacaa@users.noreply.github.com> Date: Sun, 19 Jul 2026 18:15:48 +0200 Subject: [PATCH 01/25] Separate tools folder --- CMakeLists.txt | 6 ++ examples/sample-scenes/src/main.cpp | 4 -- tools/CMakeLists.txt | 5 ++ tools/molecule-editor/CMakeLists.txt | 68 +++++++++++++++++++ .../molecule-editor}/include/MoleculeEditor.h | 9 ++- tools/molecule-editor/src/main.cpp | 25 +++++++ tools/scene-editor/CMakeLists.txt | 68 +++++++++++++++++++ .../scene-editor/include/SceneEditor.h | 10 ++- tools/scene-editor/src/main.cpp | 25 +++++++ 9 files changed, 212 insertions(+), 8 deletions(-) create mode 100644 tools/CMakeLists.txt create mode 100644 tools/molecule-editor/CMakeLists.txt rename {examples/sample-scenes => tools/molecule-editor}/include/MoleculeEditor.h (99%) create mode 100644 tools/molecule-editor/src/main.cpp create mode 100644 tools/scene-editor/CMakeLists.txt rename examples/sample-scenes/include/SceneLoadExample.h => tools/scene-editor/include/SceneEditor.h (99%) create mode 100644 tools/scene-editor/src/main.cpp diff --git a/CMakeLists.txt b/CMakeLists.txt index 9f2fac9..34b8750 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -210,3 +210,9 @@ if(WEIRD_ENGINE_BUILD_EXAMPLES) add_subdirectory(examples/opengl-experiments) add_subdirectory(examples/sample-scenes) endif() + +# Tools +option(WEIRD_ENGINE_BUILD_TOOLS "Build tool projects" OFF) +if(WEIRD_ENGINE_BUILD_TOOLS) + add_subdirectory(tools) +endif() diff --git a/examples/sample-scenes/src/main.cpp b/examples/sample-scenes/src/main.cpp index 348e1bd..ab36865 100644 --- a/examples/sample-scenes/src/main.cpp +++ b/examples/sample-scenes/src/main.cpp @@ -12,8 +12,6 @@ #include "WalkScene.h" #include "globals.h" -#include "MoleculeEditor.h" -#include "SceneLoadExample.h" #include "weird-renderer/core/Display.h" WeirdEngine::vec3 g_cameraPositon = vec3(15.0f, 7.5f, 35.0f); @@ -28,8 +26,6 @@ int main(int argc, char* argv[]) // sceneManager.registerScene("image"); // sceneManager.registerScene("collision-handling"); // sceneManager.registerScene("destroy-test"); - // sceneManager.registerScene("scene-editor", ASSETS_PATH "example.weird"); - // sceneManager.registerScene("molecule-editor"); sceneManager.registerScene("life"); // sceneManager.registerScene("walk"); // sceneManager.registerScene("aquarium"); diff --git a/tools/CMakeLists.txt b/tools/CMakeLists.txt new file mode 100644 index 0000000..91d1e4e --- /dev/null +++ b/tools/CMakeLists.txt @@ -0,0 +1,5 @@ +cmake_minimum_required(VERSION 3.10) +project(WeirdEngineTools) + +add_subdirectory(molecule-editor) +add_subdirectory(scene-editor) diff --git a/tools/molecule-editor/CMakeLists.txt b/tools/molecule-editor/CMakeLists.txt new file mode 100644 index 0000000..132e9a7 --- /dev/null +++ b/tools/molecule-editor/CMakeLists.txt @@ -0,0 +1,68 @@ +cmake_minimum_required(VERSION 3.10) +project(MoleculeEditorTool) + +# Create folders if they don't exist +file(MAKE_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}/assets") +file(MAKE_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}/include") +file(MAKE_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}/src") + +set(CMAKE_CXX_STANDARD 20) +set(CMAKE_CXX_STANDARD_REQUIRED ON) +set(CMAKE_CXX_EXTENSIONS OFF) + +option(USE_LOCAL_WEIRD_ENGINE "Use local version of WeirdEngine" ON) +set(WEIRD_ENGINE_LOCAL_PATH "../../") +option(DEPLOY_STANDALONE "Configure paths and copy assets for a standalone distribution" OFF) + +if(DEPLOY_STANDALONE) + message(STATUS ">> DEPLOY MODE: Assets will be copied to output. Paths set to relative.") + set(WEIRD_ENGINE_USE_RUNTIME_ASSETS ON CACHE BOOL "" FORCE) +else() + message(STATUS ">> DEV MODE: Assets read directly from source folder.") +endif() + +if(NOT TARGET WeirdEngine) + if(USE_LOCAL_WEIRD_ENGINE) + add_subdirectory(${WEIRD_ENGINE_LOCAL_PATH} ${CMAKE_BINARY_DIR}/weird-engine) + get_filename_component(WEIRD_ENGINE_REAL_SOURCE "${WEIRD_ENGINE_LOCAL_PATH}" ABSOLUTE) + else() + include(FetchContent) + FetchContent_Declare( + WeirdEngine + GIT_REPOSITORY https://github.com/damacaa/weird-engine + GIT_TAG main + ) + FetchContent_MakeAvailable(WeirdEngine) + set(WEIRD_ENGINE_REAL_SOURCE "${weirdengine_SOURCE_DIR}") + endif() +else() + get_filename_component(WEIRD_ENGINE_REAL_SOURCE "${WEIRD_ENGINE_LOCAL_PATH}" ABSOLUTE) +endif() + +file(GLOB_RECURSE WEIRDGAME_SOURCES "${CMAKE_CURRENT_SOURCE_DIR}/src/*.cpp") +file(GLOB_RECURSE WEIRDGAME_HEADERS "${CMAKE_CURRENT_SOURCE_DIR}/include/*.h" "${CMAKE_CURRENT_SOURCE_DIR}/include/*.hpp") +file(GLOB_RECURSE WEIRDGAME_ASSETS "${CMAKE_CURRENT_SOURCE_DIR}/assets/*.*") + +set_source_files_properties(${WEIRDGAME_HEADERS} PROPERTIES HEADER_FILE_ONLY TRUE) +add_executable(${PROJECT_NAME} ${WEIRDGAME_SOURCES} ${WEIRDGAME_HEADERS} ${WEIRDGAME_ASSETS}) +target_include_directories(${PROJECT_NAME} PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/include) +target_link_libraries(${PROJECT_NAME} PRIVATE WeirdEngine) + +if(DEPLOY_STANDALONE) + set(ASSETS_PATH "./assets/") +else() + set(ASSETS_PATH "${CMAKE_CURRENT_SOURCE_DIR}/assets/") +endif() + +target_compile_definitions(${PROJECT_NAME} PUBLIC ASSETS_PATH="${ASSETS_PATH}") + +if (MINGW) + target_link_options(${PROJECT_NAME} PRIVATE -static -static-libgcc -static-libstdc++) +endif() + +add_custom_command(TARGET ${PROJECT_NAME} POST_BUILD + COMMAND ${CMAKE_COMMAND} -E copy_directory "${CMAKE_CURRENT_SOURCE_DIR}/assets" "$/assets" + COMMAND ${CMAKE_COMMAND} -E copy_directory "${WEIRD_ENGINE_REAL_SOURCE}/src/weird-renderer/fonts" "$/fonts" + COMMAND ${CMAKE_COMMAND} -E copy_directory "${WEIRD_ENGINE_REAL_SOURCE}/src/weird-renderer/shaders" "$/shaders" + COMMENT "Copying Assets, Fonts, and Shaders" +) diff --git a/examples/sample-scenes/include/MoleculeEditor.h b/tools/molecule-editor/include/MoleculeEditor.h similarity index 99% rename from examples/sample-scenes/include/MoleculeEditor.h rename to tools/molecule-editor/include/MoleculeEditor.h index 74aa64d..60531f5 100644 --- a/examples/sample-scenes/include/MoleculeEditor.h +++ b/tools/molecule-editor/include/MoleculeEditor.h @@ -13,7 +13,14 @@ #include #include -#include "globals.h" + +#include "weird-engine/math/Default2DSDFs.h" +#include "weird-physics/components/GlobalPhysicsSettings.h" +#include "weird-physics/components/DistanceConstraint.h" +#include "weird-physics/components/Spring.h" +#include + +extern WeirdEngine::vec3 g_cameraPositon; using namespace WeirdEngine; diff --git a/tools/molecule-editor/src/main.cpp b/tools/molecule-editor/src/main.cpp new file mode 100644 index 0000000..d744487 --- /dev/null +++ b/tools/molecule-editor/src/main.cpp @@ -0,0 +1,25 @@ +#include +#include "MoleculeEditor.h" + +using namespace WeirdEngine; + +WeirdEngine::vec3 g_cameraPositon = vec3(15.0f, 7.5f, 35.0f); + +int main(int argc, char* argv[]) +{ + SceneManager& sceneManager = SceneManager::getInstance(); + sceneManager.registerScene("molecule-editor"); + + DisplaySettings displaySettings{}; + displaySettings.width = 640; + displaySettings.height = 480; + displaySettings.fullscreen = false; + + PhysicsSettings physicsSettings{}; + + AudioSettings audioSettings{}; + audioSettings.mute = false; + + start(sceneManager, displaySettings, physicsSettings, audioSettings, argc, argv); + return 0; +} diff --git a/tools/scene-editor/CMakeLists.txt b/tools/scene-editor/CMakeLists.txt new file mode 100644 index 0000000..0dc70c6 --- /dev/null +++ b/tools/scene-editor/CMakeLists.txt @@ -0,0 +1,68 @@ +cmake_minimum_required(VERSION 3.10) +project(SceneEditorTool) + +# Create folders if they don't exist +file(MAKE_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}/assets") +file(MAKE_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}/include") +file(MAKE_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}/src") + +set(CMAKE_CXX_STANDARD 20) +set(CMAKE_CXX_STANDARD_REQUIRED ON) +set(CMAKE_CXX_EXTENSIONS OFF) + +option(USE_LOCAL_WEIRD_ENGINE "Use local version of WeirdEngine" ON) +set(WEIRD_ENGINE_LOCAL_PATH "../../") +option(DEPLOY_STANDALONE "Configure paths and copy assets for a standalone distribution" OFF) + +if(DEPLOY_STANDALONE) + message(STATUS ">> DEPLOY MODE: Assets will be copied to output. Paths set to relative.") + set(WEIRD_ENGINE_USE_RUNTIME_ASSETS ON CACHE BOOL "" FORCE) +else() + message(STATUS ">> DEV MODE: Assets read directly from source folder.") +endif() + +if(NOT TARGET WeirdEngine) + if(USE_LOCAL_WEIRD_ENGINE) + add_subdirectory(${WEIRD_ENGINE_LOCAL_PATH} ${CMAKE_BINARY_DIR}/weird-engine) + get_filename_component(WEIRD_ENGINE_REAL_SOURCE "${WEIRD_ENGINE_LOCAL_PATH}" ABSOLUTE) + else() + include(FetchContent) + FetchContent_Declare( + WeirdEngine + GIT_REPOSITORY https://github.com/damacaa/weird-engine + GIT_TAG main + ) + FetchContent_MakeAvailable(WeirdEngine) + set(WEIRD_ENGINE_REAL_SOURCE "${weirdengine_SOURCE_DIR}") + endif() +else() + get_filename_component(WEIRD_ENGINE_REAL_SOURCE "${WEIRD_ENGINE_LOCAL_PATH}" ABSOLUTE) +endif() + +file(GLOB_RECURSE WEIRDGAME_SOURCES "${CMAKE_CURRENT_SOURCE_DIR}/src/*.cpp") +file(GLOB_RECURSE WEIRDGAME_HEADERS "${CMAKE_CURRENT_SOURCE_DIR}/include/*.h" "${CMAKE_CURRENT_SOURCE_DIR}/include/*.hpp") +file(GLOB_RECURSE WEIRDGAME_ASSETS "${CMAKE_CURRENT_SOURCE_DIR}/assets/*.*") + +set_source_files_properties(${WEIRDGAME_HEADERS} PROPERTIES HEADER_FILE_ONLY TRUE) +add_executable(${PROJECT_NAME} ${WEIRDGAME_SOURCES} ${WEIRDGAME_HEADERS} ${WEIRDGAME_ASSETS}) +target_include_directories(${PROJECT_NAME} PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/include) +target_link_libraries(${PROJECT_NAME} PRIVATE WeirdEngine) + +if(DEPLOY_STANDALONE) + set(ASSETS_PATH "./assets/") +else() + set(ASSETS_PATH "${CMAKE_CURRENT_SOURCE_DIR}/assets/") +endif() + +target_compile_definitions(${PROJECT_NAME} PUBLIC ASSETS_PATH="${ASSETS_PATH}") + +if (MINGW) + target_link_options(${PROJECT_NAME} PRIVATE -static -static-libgcc -static-libstdc++) +endif() + +add_custom_command(TARGET ${PROJECT_NAME} POST_BUILD + COMMAND ${CMAKE_COMMAND} -E copy_directory "${CMAKE_CURRENT_SOURCE_DIR}/assets" "$/assets" + COMMAND ${CMAKE_COMMAND} -E copy_directory "${WEIRD_ENGINE_REAL_SOURCE}/src/weird-renderer/fonts" "$/fonts" + COMMAND ${CMAKE_COMMAND} -E copy_directory "${WEIRD_ENGINE_REAL_SOURCE}/src/weird-renderer/shaders" "$/shaders" + COMMENT "Copying Assets, Fonts, and Shaders" +) diff --git a/examples/sample-scenes/include/SceneLoadExample.h b/tools/scene-editor/include/SceneEditor.h similarity index 99% rename from examples/sample-scenes/include/SceneLoadExample.h rename to tools/scene-editor/include/SceneEditor.h index 8ebbcb9..7d45cda 100644 --- a/examples/sample-scenes/include/SceneLoadExample.h +++ b/tools/scene-editor/include/SceneEditor.h @@ -6,14 +6,18 @@ #include #include -#include "globals.h" + +#include "weird-engine/math/Default2DSDFs.h" +#include + +extern WeirdEngine::vec3 g_cameraPositon; using namespace WeirdEngine; -class SceneLoadExample : public Scene2D +class SceneEditor : public Scene2D { public: - SceneLoadExample() : m_rng(12345) + SceneEditor() : m_rng(12345) { } diff --git a/tools/scene-editor/src/main.cpp b/tools/scene-editor/src/main.cpp new file mode 100644 index 0000000..4ac3c71 --- /dev/null +++ b/tools/scene-editor/src/main.cpp @@ -0,0 +1,25 @@ +#include +#include "SceneEditor.h" + +using namespace WeirdEngine; + +WeirdEngine::vec3 g_cameraPositon = vec3(15.0f, 7.5f, 35.0f); + +int main(int argc, char* argv[]) +{ + SceneManager& sceneManager = SceneManager::getInstance(); + sceneManager.registerScene("scene-editor"); + + DisplaySettings displaySettings{}; + displaySettings.width = 640; + displaySettings.height = 480; + displaySettings.fullscreen = false; + + PhysicsSettings physicsSettings{}; + + AudioSettings audioSettings{}; + audioSettings.mute = false; + + start(sceneManager, displaySettings, physicsSettings, audioSettings, argc, argv); + return 0; +} From a39f82729ff8dcd6f08c0c60cbf032729e619d7a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Mart=C3=AD?= <49535803+damacaa@users.noreply.github.com> Date: Sun, 19 Jul 2026 19:42:09 +0200 Subject: [PATCH 02/25] Unified CMakeLists of all projects --- examples/3d-experiments/CMakeLists.txt | 114 ++++++++++++--- examples/empty-project/CMakeLists.txt | 154 +++++++++++++++------ examples/opengl-experiments/CMakeLists.txt | 114 ++++++++++++--- examples/sample-scenes/CMakeLists.txt | 87 +++++++----- tools/molecule-editor/CMakeLists.txt | 120 ++++++++++++++-- tools/scene-editor/CMakeLists.txt | 120 ++++++++++++++-- 6 files changed, 566 insertions(+), 143 deletions(-) diff --git a/examples/3d-experiments/CMakeLists.txt b/examples/3d-experiments/CMakeLists.txt index bb0c844..bc0ec4e 100644 --- a/examples/3d-experiments/CMakeLists.txt +++ b/examples/3d-experiments/CMakeLists.txt @@ -1,36 +1,77 @@ cmake_minimum_required(VERSION 3.10) + +# ============================================================================== +# 1. Project Configuration +# ============================================================================== project(Weird3D) +# Path to the WeirdEngine directory. Change this depending on where your project is located. +# Examples inside weird-engine use "../../" +# External projects usually use "../weird-engine/" or similar. +set(WEIRD_ENGINE_LOCAL_PATH "../../") +# ============================================================================== + # Create folders if they don't exist file(MAKE_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}/assets") file(MAKE_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}/include") file(MAKE_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}/src") -set(CMAKE_CXX_STANDARD 17) +set(CMAKE_CXX_STANDARD 20) set(CMAKE_CXX_STANDARD_REQUIRED ON) +set(CMAKE_CXX_EXTENSIONS OFF) # Ensure strictly standard C++ # Option to switch between local and online version of WeirdEngine option(USE_LOCAL_WEIRD_ENGINE "Use local version of WeirdEngine" ON) -# Set paths for the local WeirdEngine -set(WEIRD_ENGINE_LOCAL_PATH "../../") +# Option to build for web (Emscripten) +option(BUILD_WEB "Build for web using Emscripten" OFF) + +# Option to build for standalone deployment +option(DEPLOY_STANDALONE "Configure paths and copy assets for a standalone distribution" OFF) + +# Force DEPLOY_STANDALONE when building for web +if(BUILD_WEB) + set(DEPLOY_STANDALONE ON CACHE BOOL "" FORCE) +endif() + +if(DEPLOY_STANDALONE) + message(STATUS ">> DEPLOY MODE: Assets will be copied to output. Paths set to relative.") + # Force the engine to expect runtime assets + set(WEIRD_ENGINE_USE_RUNTIME_ASSETS ON CACHE BOOL "" FORCE) +else() + message(STATUS ">> DEV MODE: Assets read directly from source folder.") +endif() +# ------------------------------------------------------------------------- +# INCLUDE ENGINE & CAPTURE SOURCE PATH +# ------------------------------------------------------------------------- if(NOT TARGET WeirdEngine) if(USE_LOCAL_WEIRD_ENGINE) # Use the local version of WeirdEngine - message(STATUS "Using local version of WeirdEngine") + message(STATUS "Using local version of WeirdEngine at ${WEIRD_ENGINE_LOCAL_PATH}") add_subdirectory(${WEIRD_ENGINE_LOCAL_PATH} ${CMAKE_BINARY_DIR}/weird-engine) + + # Resolve the local path to an absolute path for copying files later + get_filename_component(WEIRD_ENGINE_REAL_SOURCE "${WEIRD_ENGINE_LOCAL_PATH}" ABSOLUTE) else() # Fetch WeirdEngine from GitHub message(STATUS "Using online version of WeirdEngine") + set(WEIRD_ENGINE_GIT_REF "main") + include(FetchContent) FetchContent_Declare( WeirdEngine GIT_REPOSITORY https://github.com/damacaa/weird-engine - GIT_TAG main + GIT_TAG ${WEIRD_ENGINE_GIT_REF} ) FetchContent_MakeAvailable(WeirdEngine) + + # FetchContent defines _SOURCE_DIR (usually lowercase) + set(WEIRD_ENGINE_REAL_SOURCE "${weirdengine_SOURCE_DIR}") endif() +else() + # WeirdEngine already defined (built from root); resolve its source path + get_filename_component(WEIRD_ENGINE_REAL_SOURCE "${WEIRD_ENGINE_LOCAL_PATH}" ABSOLUTE) endif() # Glob source files and header files from the proper directories. @@ -50,47 +91,74 @@ set_source_files_properties(${WEIRDGAME_HEADERS} PROPERTIES HEADER_FILE_ONLY TRU add_executable(${PROJECT_NAME} ${WEIRDGAME_SOURCES} ${WEIRDGAME_HEADERS} ${WEIRDGAME_ASSETS}) # Set include directories. -target_include_directories(${PROJECT_NAME} PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/include) -target_include_directories(${PROJECT_NAME} PRIVATE - ${CMAKE_BINARY_DIR}/weird-engine/include - ${CMAKE_BINARY_DIR}/weird-engine/third-party/include -) +target_include_directories(${PROJECT_NAME} PRIVATE "${CMAKE_CURRENT_SOURCE_DIR}/include") # Link to WeirdEngine. target_link_libraries(${PROJECT_NAME} PRIVATE WeirdEngine) # Set Asset Path Macro -# Define the assets path variable -set(ASSETS_PATH "${CMAKE_CURRENT_SOURCE_DIR}/assets/") -# set(ASSETS_PATH "./assets") # Set the asset path macro in release mode to a relative path that assumes the assets folder is in the same directory as the game executable +if(DEPLOY_STANDALONE) + set(ASSETS_PATH "./assets/") +else() + set(ASSETS_PATH "${CMAKE_CURRENT_SOURCE_DIR}/assets/") +endif() -# Print the assets path for debugging or confirmation message(STATUS "Assets path: ${ASSETS_PATH}") - -# Use the variable in target_compile_definitions target_compile_definitions(${PROJECT_NAME} PUBLIC ASSETS_PATH="${ASSETS_PATH}") if (MINGW) target_link_options(${PROJECT_NAME} PRIVATE -static -static-libgcc -static-libstdc++) endif() -# ---------------------------------------------------------- -# Helper function to assign source groups based on folder structure. +# ------------------------------------------------------------------------- +# POST BUILD COMMANDS (DLLs + Assets + Fonts + Shaders) +# ------------------------------------------------------------------------- +if(DEPLOY_STANDALONE) + add_custom_command(TARGET ${PROJECT_NAME} POST_BUILD + # 1. Copy Project ASSETS folder -> Build/assets + COMMAND ${CMAKE_COMMAND} -E copy_directory + "${CMAKE_CURRENT_SOURCE_DIR}/assets" + "$/assets" + + # 2. Copy WeirdEngine FONTS -> Build/fonts + COMMAND ${CMAKE_COMMAND} -E copy_directory + "${WEIRD_ENGINE_REAL_SOURCE}/src/weird-renderer/fonts" + "$/fonts" + + # 3. Copy WeirdEngine SHADERS -> Build/shaders + COMMAND ${CMAKE_COMMAND} -E copy_directory + "${WEIRD_ENGINE_REAL_SOURCE}/src/weird-renderer/shaders" + "$/shaders" + + COMMENT "Copying Game Assets, Engine Fonts, and Engine Shaders" + ) + + if(BUILD_WEB) + # For web builds, copy index.html if it exists + if(EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/src/index.html") + add_custom_command(TARGET ${PROJECT_NAME} POST_BUILD + COMMAND ${CMAKE_COMMAND} -E copy_if_different + "${CMAKE_CURRENT_SOURCE_DIR}/src/index.html" + "$/index.html" + COMMENT "Copying index.html for web build" + ) + endif() + endif() +endif() + +# ------------------------------------------------------------------------- +# SOURCE GROUPS +# ------------------------------------------------------------------------- function(assign_source_groups TARGET) foreach(source_file IN LISTS ARGN) - # Get the full path to the file's directory. get_filename_component(FILE_PATH "${source_file}" PATH) - # Compute the path relative to the project's root. file(RELATIVE_PATH REL_PATH "${CMAKE_CURRENT_SOURCE_DIR}" "${FILE_PATH}") - # Replace forward slashes with backslashes for Visual Studio filter naming. string(REPLACE "/" "\\" FILTER_PATH "${REL_PATH}") if(FILTER_PATH STREQUAL "") set(FILTER_PATH "Root") endif() - # Assign the file to the computed filter. source_group("${FILTER_PATH}" FILES "${source_file}") endforeach() endfunction() -# Assign source groups for all your files. assign_source_groups(${PROJECT_NAME} ${WEIRDGAME_SOURCES} ${WEIRDGAME_HEADERS} ${WEIRDGAME_ASSETS}) diff --git a/examples/empty-project/CMakeLists.txt b/examples/empty-project/CMakeLists.txt index 2f8b419..d74d007 100644 --- a/examples/empty-project/CMakeLists.txt +++ b/examples/empty-project/CMakeLists.txt @@ -1,44 +1,87 @@ cmake_minimum_required(VERSION 3.10) + +# ============================================================================== +# 1. Project Configuration +# ============================================================================== project(WeirdGame) +# Path to the WeirdEngine directory. Change this depending on where your project is located. +# Examples inside weird-engine use "../../" +# External projects usually use "../weird-engine/" or similar. +set(WEIRD_ENGINE_LOCAL_PATH "../../") +# ============================================================================== + # Create folders if they don't exist -file(MAKE_DIRECTORY "${CMAKE_SOURCE_DIR}/assets") -file(MAKE_DIRECTORY "${CMAKE_SOURCE_DIR}/include") -file(MAKE_DIRECTORY "${CMAKE_SOURCE_DIR}/src") +file(MAKE_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}/assets") +file(MAKE_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}/include") +file(MAKE_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}/src") -set(CMAKE_CXX_STANDARD 17) +set(CMAKE_CXX_STANDARD 20) set(CMAKE_CXX_STANDARD_REQUIRED ON) +set(CMAKE_CXX_EXTENSIONS OFF) # Ensure strictly standard C++ # Option to switch between local and online version of WeirdEngine option(USE_LOCAL_WEIRD_ENGINE "Use local version of WeirdEngine" ON) -# Set paths for the local WeirdEngine -set(WEIRD_ENGINE_LOCAL_PATH "../../") +# Option to build for web (Emscripten) +option(BUILD_WEB "Build for web using Emscripten" OFF) + +# Option to build for standalone deployment +option(DEPLOY_STANDALONE "Configure paths and copy assets for a standalone distribution" OFF) -if(USE_LOCAL_WEIRD_ENGINE) - # Use the local version of WeirdEngine - message(STATUS "Using local version of WeirdEngine") - add_subdirectory(${WEIRD_ENGINE_LOCAL_PATH} ${CMAKE_BINARY_DIR}/weird-engine) +# Force DEPLOY_STANDALONE when building for web +if(BUILD_WEB) + set(DEPLOY_STANDALONE ON CACHE BOOL "" FORCE) +endif() + +if(DEPLOY_STANDALONE) + message(STATUS ">> DEPLOY MODE: Assets will be copied to output. Paths set to relative.") + # Force the engine to expect runtime assets + set(WEIRD_ENGINE_USE_RUNTIME_ASSETS ON CACHE BOOL "" FORCE) else() - # Fetch WeirdEngine from GitHub - message(STATUS "Using online version of WeirdEngine") - include(FetchContent) - FetchContent_Declare( - WeirdEngine - GIT_REPOSITORY https://github.com/damacaa/weird-engine - GIT_TAG main - ) - FetchContent_MakeAvailable(WeirdEngine) + message(STATUS ">> DEV MODE: Assets read directly from source folder.") +endif() + +# ------------------------------------------------------------------------- +# INCLUDE ENGINE & CAPTURE SOURCE PATH +# ------------------------------------------------------------------------- +if(NOT TARGET WeirdEngine) + if(USE_LOCAL_WEIRD_ENGINE) + # Use the local version of WeirdEngine + message(STATUS "Using local version of WeirdEngine at ${WEIRD_ENGINE_LOCAL_PATH}") + add_subdirectory(${WEIRD_ENGINE_LOCAL_PATH} ${CMAKE_BINARY_DIR}/weird-engine) + + # Resolve the local path to an absolute path for copying files later + get_filename_component(WEIRD_ENGINE_REAL_SOURCE "${WEIRD_ENGINE_LOCAL_PATH}" ABSOLUTE) + else() + # Fetch WeirdEngine from GitHub + message(STATUS "Using online version of WeirdEngine") + set(WEIRD_ENGINE_GIT_REF "main") + + include(FetchContent) + FetchContent_Declare( + WeirdEngine + GIT_REPOSITORY https://github.com/damacaa/weird-engine + GIT_TAG ${WEIRD_ENGINE_GIT_REF} + ) + FetchContent_MakeAvailable(WeirdEngine) + + # FetchContent defines _SOURCE_DIR (usually lowercase) + set(WEIRD_ENGINE_REAL_SOURCE "${weirdengine_SOURCE_DIR}") + endif() +else() + # WeirdEngine already defined (built from root); resolve its source path + get_filename_component(WEIRD_ENGINE_REAL_SOURCE "${WEIRD_ENGINE_LOCAL_PATH}" ABSOLUTE) endif() # Glob source files and header files from the proper directories. -file(GLOB_RECURSE WEIRDGAME_SOURCES "${CMAKE_SOURCE_DIR}/src/*.cpp") +file(GLOB_RECURSE WEIRDGAME_SOURCES "${CMAKE_CURRENT_SOURCE_DIR}/src/*.cpp") file(GLOB_RECURSE WEIRDGAME_HEADERS - "${CMAKE_SOURCE_DIR}/include/*.h" - "${CMAKE_SOURCE_DIR}/include/*.hpp" + "${CMAKE_CURRENT_SOURCE_DIR}/include/*.h" + "${CMAKE_CURRENT_SOURCE_DIR}/include/*.hpp" ) file(GLOB_RECURSE WEIRDGAME_ASSETS - "${CMAKE_SOURCE_DIR}/assets/*.*" + "${CMAKE_CURRENT_SOURCE_DIR}/assets/*.*" ) # Mark headers as header-only so that Visual Studio treats them appropriately. @@ -48,47 +91,74 @@ set_source_files_properties(${WEIRDGAME_HEADERS} PROPERTIES HEADER_FILE_ONLY TRU add_executable(${PROJECT_NAME} ${WEIRDGAME_SOURCES} ${WEIRDGAME_HEADERS} ${WEIRDGAME_ASSETS}) # Set include directories. -target_include_directories(${PROJECT_NAME} PRIVATE ${CMAKE_SOURCE_DIR}/include) -target_include_directories(${PROJECT_NAME} PRIVATE - ${CMAKE_BINARY_DIR}/weird-engine/include - ${CMAKE_BINARY_DIR}/weird-engine/third-party/include -) +target_include_directories(${PROJECT_NAME} PRIVATE "${CMAKE_CURRENT_SOURCE_DIR}/include") # Link to WeirdEngine. target_link_libraries(${PROJECT_NAME} PRIVATE WeirdEngine) # Set Asset Path Macro -# Define the assets path variable -set(ASSETS_PATH "${CMAKE_CURRENT_SOURCE_DIR}/assets/") -# set(ASSETS_PATH "./assets") # Set the asset path macro in release mode to a relative path that assumes the assets folder is in the same directory as the game executable +if(DEPLOY_STANDALONE) + set(ASSETS_PATH "./assets/") +else() + set(ASSETS_PATH "${CMAKE_CURRENT_SOURCE_DIR}/assets/") +endif() -# Print the assets path for debugging or confirmation message(STATUS "Assets path: ${ASSETS_PATH}") - -# Use the variable in target_compile_definitions target_compile_definitions(${PROJECT_NAME} PUBLIC ASSETS_PATH="${ASSETS_PATH}") if (MINGW) target_link_options(${PROJECT_NAME} PRIVATE -static -static-libgcc -static-libstdc++) endif() -# ---------------------------------------------------------- -# Helper function to assign source groups based on folder structure. +# ------------------------------------------------------------------------- +# POST BUILD COMMANDS (DLLs + Assets + Fonts + Shaders) +# ------------------------------------------------------------------------- +if(DEPLOY_STANDALONE) + add_custom_command(TARGET ${PROJECT_NAME} POST_BUILD + # 1. Copy Project ASSETS folder -> Build/assets + COMMAND ${CMAKE_COMMAND} -E copy_directory + "${CMAKE_CURRENT_SOURCE_DIR}/assets" + "$/assets" + + # 2. Copy WeirdEngine FONTS -> Build/fonts + COMMAND ${CMAKE_COMMAND} -E copy_directory + "${WEIRD_ENGINE_REAL_SOURCE}/src/weird-renderer/fonts" + "$/fonts" + + # 3. Copy WeirdEngine SHADERS -> Build/shaders + COMMAND ${CMAKE_COMMAND} -E copy_directory + "${WEIRD_ENGINE_REAL_SOURCE}/src/weird-renderer/shaders" + "$/shaders" + + COMMENT "Copying Game Assets, Engine Fonts, and Engine Shaders" + ) + + if(BUILD_WEB) + # For web builds, copy index.html if it exists + if(EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/src/index.html") + add_custom_command(TARGET ${PROJECT_NAME} POST_BUILD + COMMAND ${CMAKE_COMMAND} -E copy_if_different + "${CMAKE_CURRENT_SOURCE_DIR}/src/index.html" + "$/index.html" + COMMENT "Copying index.html for web build" + ) + endif() + endif() +endif() + +# ------------------------------------------------------------------------- +# SOURCE GROUPS +# ------------------------------------------------------------------------- function(assign_source_groups TARGET) foreach(source_file IN LISTS ARGN) - # Get the full path to the file's directory. get_filename_component(FILE_PATH "${source_file}" PATH) - # Compute the path relative to the project's root. - file(RELATIVE_PATH REL_PATH "${CMAKE_SOURCE_DIR}" "${FILE_PATH}") - # Replace forward slashes with backslashes for Visual Studio filter naming. + file(RELATIVE_PATH REL_PATH "${CMAKE_CURRENT_SOURCE_DIR}" "${FILE_PATH}") string(REPLACE "/" "\\" FILTER_PATH "${REL_PATH}") if(FILTER_PATH STREQUAL "") set(FILTER_PATH "Root") endif() - # Assign the file to the computed filter. source_group("${FILTER_PATH}" FILES "${source_file}") endforeach() endfunction() -# Assign source groups for all your files. assign_source_groups(${PROJECT_NAME} ${WEIRDGAME_SOURCES} ${WEIRDGAME_HEADERS} ${WEIRDGAME_ASSETS}) diff --git a/examples/opengl-experiments/CMakeLists.txt b/examples/opengl-experiments/CMakeLists.txt index 606a485..113d28f 100644 --- a/examples/opengl-experiments/CMakeLists.txt +++ b/examples/opengl-experiments/CMakeLists.txt @@ -1,36 +1,77 @@ cmake_minimum_required(VERSION 3.10) + +# ============================================================================== +# 1. Project Configuration +# ============================================================================== project(OpenGLExperiments) +# Path to the WeirdEngine directory. Change this depending on where your project is located. +# Examples inside weird-engine use "../../" +# External projects usually use "../weird-engine/" or similar. +set(WEIRD_ENGINE_LOCAL_PATH "../../") +# ============================================================================== + # Create folders if they don't exist file(MAKE_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}/assets") file(MAKE_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}/include") file(MAKE_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}/src") -set(CMAKE_CXX_STANDARD 17) +set(CMAKE_CXX_STANDARD 20) set(CMAKE_CXX_STANDARD_REQUIRED ON) +set(CMAKE_CXX_EXTENSIONS OFF) # Ensure strictly standard C++ # Option to switch between local and online version of WeirdEngine option(USE_LOCAL_WEIRD_ENGINE "Use local version of WeirdEngine" ON) -# Set paths for the local WeirdEngine -set(WEIRD_ENGINE_LOCAL_PATH "../../") +# Option to build for web (Emscripten) +option(BUILD_WEB "Build for web using Emscripten" OFF) + +# Option to build for standalone deployment +option(DEPLOY_STANDALONE "Configure paths and copy assets for a standalone distribution" OFF) + +# Force DEPLOY_STANDALONE when building for web +if(BUILD_WEB) + set(DEPLOY_STANDALONE ON CACHE BOOL "" FORCE) +endif() + +if(DEPLOY_STANDALONE) + message(STATUS ">> DEPLOY MODE: Assets will be copied to output. Paths set to relative.") + # Force the engine to expect runtime assets + set(WEIRD_ENGINE_USE_RUNTIME_ASSETS ON CACHE BOOL "" FORCE) +else() + message(STATUS ">> DEV MODE: Assets read directly from source folder.") +endif() +# ------------------------------------------------------------------------- +# INCLUDE ENGINE & CAPTURE SOURCE PATH +# ------------------------------------------------------------------------- if(NOT TARGET WeirdEngine) if(USE_LOCAL_WEIRD_ENGINE) # Use the local version of WeirdEngine - message(STATUS "Using local version of WeirdEngine") + message(STATUS "Using local version of WeirdEngine at ${WEIRD_ENGINE_LOCAL_PATH}") add_subdirectory(${WEIRD_ENGINE_LOCAL_PATH} ${CMAKE_BINARY_DIR}/weird-engine) + + # Resolve the local path to an absolute path for copying files later + get_filename_component(WEIRD_ENGINE_REAL_SOURCE "${WEIRD_ENGINE_LOCAL_PATH}" ABSOLUTE) else() # Fetch WeirdEngine from GitHub message(STATUS "Using online version of WeirdEngine") + set(WEIRD_ENGINE_GIT_REF "main") + include(FetchContent) FetchContent_Declare( WeirdEngine GIT_REPOSITORY https://github.com/damacaa/weird-engine - GIT_TAG main + GIT_TAG ${WEIRD_ENGINE_GIT_REF} ) FetchContent_MakeAvailable(WeirdEngine) + + # FetchContent defines _SOURCE_DIR (usually lowercase) + set(WEIRD_ENGINE_REAL_SOURCE "${weirdengine_SOURCE_DIR}") endif() +else() + # WeirdEngine already defined (built from root); resolve its source path + get_filename_component(WEIRD_ENGINE_REAL_SOURCE "${WEIRD_ENGINE_LOCAL_PATH}" ABSOLUTE) endif() # Glob source files and header files from the proper directories. @@ -50,47 +91,74 @@ set_source_files_properties(${WEIRDGAME_HEADERS} PROPERTIES HEADER_FILE_ONLY TRU add_executable(${PROJECT_NAME} ${WEIRDGAME_SOURCES} ${WEIRDGAME_HEADERS} ${WEIRDGAME_ASSETS}) # Set include directories. -target_include_directories(${PROJECT_NAME} PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/include) -target_include_directories(${PROJECT_NAME} PRIVATE - ${CMAKE_BINARY_DIR}/weird-engine/include - ${CMAKE_BINARY_DIR}/weird-engine/third-party/include -) +target_include_directories(${PROJECT_NAME} PRIVATE "${CMAKE_CURRENT_SOURCE_DIR}/include") # Link to WeirdEngine. target_link_libraries(${PROJECT_NAME} PRIVATE WeirdEngine) # Set Asset Path Macro -# Define the assets path variable -set(ASSETS_PATH "${CMAKE_CURRENT_SOURCE_DIR}/assets/") -# set(ASSETS_PATH "./assets") # Set the asset path macro in release mode to a relative path that assumes the assets folder is in the same directory as the game executable +if(DEPLOY_STANDALONE) + set(ASSETS_PATH "./assets/") +else() + set(ASSETS_PATH "${CMAKE_CURRENT_SOURCE_DIR}/assets/") +endif() -# Print the assets path for debugging or confirmation message(STATUS "Assets path: ${ASSETS_PATH}") - -# Use the variable in target_compile_definitions target_compile_definitions(${PROJECT_NAME} PUBLIC ASSETS_PATH="${ASSETS_PATH}") if (MINGW) target_link_options(${PROJECT_NAME} PRIVATE -static -static-libgcc -static-libstdc++) endif() -# ---------------------------------------------------------- -# Helper function to assign source groups based on folder structure. +# ------------------------------------------------------------------------- +# POST BUILD COMMANDS (DLLs + Assets + Fonts + Shaders) +# ------------------------------------------------------------------------- +if(DEPLOY_STANDALONE) + add_custom_command(TARGET ${PROJECT_NAME} POST_BUILD + # 1. Copy Project ASSETS folder -> Build/assets + COMMAND ${CMAKE_COMMAND} -E copy_directory + "${CMAKE_CURRENT_SOURCE_DIR}/assets" + "$/assets" + + # 2. Copy WeirdEngine FONTS -> Build/fonts + COMMAND ${CMAKE_COMMAND} -E copy_directory + "${WEIRD_ENGINE_REAL_SOURCE}/src/weird-renderer/fonts" + "$/fonts" + + # 3. Copy WeirdEngine SHADERS -> Build/shaders + COMMAND ${CMAKE_COMMAND} -E copy_directory + "${WEIRD_ENGINE_REAL_SOURCE}/src/weird-renderer/shaders" + "$/shaders" + + COMMENT "Copying Game Assets, Engine Fonts, and Engine Shaders" + ) + + if(BUILD_WEB) + # For web builds, copy index.html if it exists + if(EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/src/index.html") + add_custom_command(TARGET ${PROJECT_NAME} POST_BUILD + COMMAND ${CMAKE_COMMAND} -E copy_if_different + "${CMAKE_CURRENT_SOURCE_DIR}/src/index.html" + "$/index.html" + COMMENT "Copying index.html for web build" + ) + endif() + endif() +endif() + +# ------------------------------------------------------------------------- +# SOURCE GROUPS +# ------------------------------------------------------------------------- function(assign_source_groups TARGET) foreach(source_file IN LISTS ARGN) - # Get the full path to the file's directory. get_filename_component(FILE_PATH "${source_file}" PATH) - # Compute the path relative to the project's root. file(RELATIVE_PATH REL_PATH "${CMAKE_CURRENT_SOURCE_DIR}" "${FILE_PATH}") - # Replace forward slashes with backslashes for Visual Studio filter naming. string(REPLACE "/" "\\" FILTER_PATH "${REL_PATH}") if(FILTER_PATH STREQUAL "") set(FILTER_PATH "Root") endif() - # Assign the file to the computed filter. source_group("${FILTER_PATH}" FILES "${source_file}") endforeach() endfunction() -# Assign source groups for all your files. assign_source_groups(${PROJECT_NAME} ${WEIRDGAME_SOURCES} ${WEIRDGAME_HEADERS} ${WEIRDGAME_ASSETS}) diff --git a/examples/sample-scenes/CMakeLists.txt b/examples/sample-scenes/CMakeLists.txt index 49e2a25..a52c76e 100644 --- a/examples/sample-scenes/CMakeLists.txt +++ b/examples/sample-scenes/CMakeLists.txt @@ -1,6 +1,16 @@ cmake_minimum_required(VERSION 3.10) + +# ============================================================================== +# 1. Project Configuration +# ============================================================================== project(WeirdSamples) +# Path to the WeirdEngine directory. Change this depending on where your project is located. +# Examples inside weird-engine use "../../" +# External projects usually use "../weird-engine/" or similar. +set(WEIRD_ENGINE_LOCAL_PATH "../../") +# ============================================================================== + # Create folders if they don't exist file(MAKE_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}/assets") file(MAKE_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}/include") @@ -12,12 +22,18 @@ set(CMAKE_CXX_EXTENSIONS OFF) # Ensure strictly standard C++ # Option to switch between local and online version of WeirdEngine option(USE_LOCAL_WEIRD_ENGINE "Use local version of WeirdEngine" ON) -# Set paths for the local WeirdEngine -set(WEIRD_ENGINE_LOCAL_PATH "../../") + +# Option to build for web (Emscripten) +option(BUILD_WEB "Build for web using Emscripten" OFF) # Option to build for standalone deployment option(DEPLOY_STANDALONE "Configure paths and copy assets for a standalone distribution" OFF) +# Force DEPLOY_STANDALONE when building for web +if(BUILD_WEB) + set(DEPLOY_STANDALONE ON CACHE BOOL "" FORCE) +endif() + if(DEPLOY_STANDALONE) message(STATUS ">> DEPLOY MODE: Assets will be copied to output. Paths set to relative.") # Force the engine to expect runtime assets @@ -32,7 +48,7 @@ endif() if(NOT TARGET WeirdEngine) if(USE_LOCAL_WEIRD_ENGINE) # Use the local version of WeirdEngine - message(STATUS "Using local version of WeirdEngine") + message(STATUS "Using local version of WeirdEngine at ${WEIRD_ENGINE_LOCAL_PATH}") add_subdirectory(${WEIRD_ENGINE_LOCAL_PATH} ${CMAKE_BINARY_DIR}/weird-engine) # Resolve the local path to an absolute path for copying files later @@ -40,11 +56,13 @@ if(NOT TARGET WeirdEngine) else() # Fetch WeirdEngine from GitHub message(STATUS "Using online version of WeirdEngine") + set(WEIRD_ENGINE_GIT_REF "main") + include(FetchContent) FetchContent_Declare( WeirdEngine GIT_REPOSITORY https://github.com/damacaa/weird-engine - GIT_TAG main + GIT_TAG ${WEIRD_ENGINE_GIT_REF} ) FetchContent_MakeAvailable(WeirdEngine) @@ -73,13 +91,12 @@ set_source_files_properties(${WEIRDGAME_HEADERS} PROPERTIES HEADER_FILE_ONLY TRU add_executable(${PROJECT_NAME} ${WEIRDGAME_SOURCES} ${WEIRDGAME_HEADERS} ${WEIRDGAME_ASSETS}) # Set include directories. -target_include_directories(${PROJECT_NAME} PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/include) +target_include_directories(${PROJECT_NAME} PRIVATE "${CMAKE_CURRENT_SOURCE_DIR}/include") # Link to WeirdEngine. target_link_libraries(${PROJECT_NAME} PRIVATE WeirdEngine) # Set Asset Path Macro - if(DEPLOY_STANDALONE) set(ASSETS_PATH "./assets/") else() @@ -96,30 +113,38 @@ endif() # ------------------------------------------------------------------------- # POST BUILD COMMANDS (DLLs + Assets + Fonts + Shaders) # ------------------------------------------------------------------------- -add_custom_command(TARGET ${PROJECT_NAME} POST_BUILD - # 1. Copy DLLs (SDL3) - # COMMAND ${CMAKE_COMMAND} -E copy_if_different - # $ - # $ - - # 2. Copy Project ASSETS folder -> Build/assets - COMMAND ${CMAKE_COMMAND} -E copy_directory - "${CMAKE_CURRENT_SOURCE_DIR}/assets" - "$/assets" - - # 3. Copy WeirdEngine FONTS -> Build/fonts - # We look into the captured WEIRD_ENGINE_REAL_SOURCE/src/weird-renderer/fonts - COMMAND ${CMAKE_COMMAND} -E copy_directory - "${WEIRD_ENGINE_REAL_SOURCE}/src/weird-renderer/fonts" - "$/fonts" - - # 4. Copy WeirdEngine SHADERS -> Build/shaders - COMMAND ${CMAKE_COMMAND} -E copy_directory - "${WEIRD_ENGINE_REAL_SOURCE}/src/weird-renderer/shaders" - "$/shaders" - - COMMENT "Copying Runtime DLLs, Game Assets, Engine Fonts, and Engine Shaders" -) +if(DEPLOY_STANDALONE) + add_custom_command(TARGET ${PROJECT_NAME} POST_BUILD + # 1. Copy Project ASSETS folder -> Build/assets + COMMAND ${CMAKE_COMMAND} -E copy_directory + "${CMAKE_CURRENT_SOURCE_DIR}/assets" + "$/assets" + + # 2. Copy WeirdEngine FONTS -> Build/fonts + COMMAND ${CMAKE_COMMAND} -E copy_directory + "${WEIRD_ENGINE_REAL_SOURCE}/src/weird-renderer/fonts" + "$/fonts" + + # 3. Copy WeirdEngine SHADERS -> Build/shaders + COMMAND ${CMAKE_COMMAND} -E copy_directory + "${WEIRD_ENGINE_REAL_SOURCE}/src/weird-renderer/shaders" + "$/shaders" + + COMMENT "Copying Game Assets, Engine Fonts, and Engine Shaders" + ) + + if(BUILD_WEB) + # For web builds, copy index.html if it exists + if(EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/src/index.html") + add_custom_command(TARGET ${PROJECT_NAME} POST_BUILD + COMMAND ${CMAKE_COMMAND} -E copy_if_different + "${CMAKE_CURRENT_SOURCE_DIR}/src/index.html" + "$/index.html" + COMMENT "Copying index.html for web build" + ) + endif() + endif() +endif() # ------------------------------------------------------------------------- # SOURCE GROUPS @@ -136,4 +161,4 @@ function(assign_source_groups TARGET) endforeach() endfunction() -assign_source_groups(${PROJECT_NAME} ${WEIRDGAME_SOURCES} ${WEIRDGAME_HEADERS} ${WEIRDGAME_ASSETS}) \ No newline at end of file +assign_source_groups(${PROJECT_NAME} ${WEIRDGAME_SOURCES} ${WEIRDGAME_HEADERS} ${WEIRDGAME_ASSETS}) diff --git a/tools/molecule-editor/CMakeLists.txt b/tools/molecule-editor/CMakeLists.txt index 132e9a7..0ab18e2 100644 --- a/tools/molecule-editor/CMakeLists.txt +++ b/tools/molecule-editor/CMakeLists.txt @@ -1,6 +1,16 @@ cmake_minimum_required(VERSION 3.10) + +# ============================================================================== +# 1. Project Configuration +# ============================================================================== project(MoleculeEditorTool) +# Path to the WeirdEngine directory. Change this depending on where your project is located. +# Examples inside weird-engine use "../../" +# External projects usually use "../weird-engine/" or similar. +set(WEIRD_ENGINE_LOCAL_PATH "../../") +# ============================================================================== + # Create folders if they don't exist file(MAKE_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}/assets") file(MAKE_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}/include") @@ -8,61 +18,147 @@ file(MAKE_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}/src") set(CMAKE_CXX_STANDARD 20) set(CMAKE_CXX_STANDARD_REQUIRED ON) -set(CMAKE_CXX_EXTENSIONS OFF) +set(CMAKE_CXX_EXTENSIONS OFF) # Ensure strictly standard C++ +# Option to switch between local and online version of WeirdEngine option(USE_LOCAL_WEIRD_ENGINE "Use local version of WeirdEngine" ON) -set(WEIRD_ENGINE_LOCAL_PATH "../../") + +# Option to build for web (Emscripten) +option(BUILD_WEB "Build for web using Emscripten" OFF) + +# Option to build for standalone deployment option(DEPLOY_STANDALONE "Configure paths and copy assets for a standalone distribution" OFF) +# Force DEPLOY_STANDALONE when building for web +if(BUILD_WEB) + set(DEPLOY_STANDALONE ON CACHE BOOL "" FORCE) +endif() + if(DEPLOY_STANDALONE) message(STATUS ">> DEPLOY MODE: Assets will be copied to output. Paths set to relative.") + # Force the engine to expect runtime assets set(WEIRD_ENGINE_USE_RUNTIME_ASSETS ON CACHE BOOL "" FORCE) else() message(STATUS ">> DEV MODE: Assets read directly from source folder.") endif() +# ------------------------------------------------------------------------- +# INCLUDE ENGINE & CAPTURE SOURCE PATH +# ------------------------------------------------------------------------- if(NOT TARGET WeirdEngine) if(USE_LOCAL_WEIRD_ENGINE) + # Use the local version of WeirdEngine + message(STATUS "Using local version of WeirdEngine at ${WEIRD_ENGINE_LOCAL_PATH}") add_subdirectory(${WEIRD_ENGINE_LOCAL_PATH} ${CMAKE_BINARY_DIR}/weird-engine) + + # Resolve the local path to an absolute path for copying files later get_filename_component(WEIRD_ENGINE_REAL_SOURCE "${WEIRD_ENGINE_LOCAL_PATH}" ABSOLUTE) else() + # Fetch WeirdEngine from GitHub + message(STATUS "Using online version of WeirdEngine") + set(WEIRD_ENGINE_GIT_REF "main") + include(FetchContent) FetchContent_Declare( WeirdEngine GIT_REPOSITORY https://github.com/damacaa/weird-engine - GIT_TAG main + GIT_TAG ${WEIRD_ENGINE_GIT_REF} ) FetchContent_MakeAvailable(WeirdEngine) + + # FetchContent defines _SOURCE_DIR (usually lowercase) set(WEIRD_ENGINE_REAL_SOURCE "${weirdengine_SOURCE_DIR}") endif() else() + # WeirdEngine already defined (built from root); resolve its source path get_filename_component(WEIRD_ENGINE_REAL_SOURCE "${WEIRD_ENGINE_LOCAL_PATH}" ABSOLUTE) endif() +# Glob source files and header files from the proper directories. file(GLOB_RECURSE WEIRDGAME_SOURCES "${CMAKE_CURRENT_SOURCE_DIR}/src/*.cpp") -file(GLOB_RECURSE WEIRDGAME_HEADERS "${CMAKE_CURRENT_SOURCE_DIR}/include/*.h" "${CMAKE_CURRENT_SOURCE_DIR}/include/*.hpp") -file(GLOB_RECURSE WEIRDGAME_ASSETS "${CMAKE_CURRENT_SOURCE_DIR}/assets/*.*") +file(GLOB_RECURSE WEIRDGAME_HEADERS + "${CMAKE_CURRENT_SOURCE_DIR}/include/*.h" + "${CMAKE_CURRENT_SOURCE_DIR}/include/*.hpp" +) +file(GLOB_RECURSE WEIRDGAME_ASSETS + "${CMAKE_CURRENT_SOURCE_DIR}/assets/*.*" +) +# Mark headers as header-only so that Visual Studio treats them appropriately. set_source_files_properties(${WEIRDGAME_HEADERS} PROPERTIES HEADER_FILE_ONLY TRUE) + +# Add executable including both sources and headers. add_executable(${PROJECT_NAME} ${WEIRDGAME_SOURCES} ${WEIRDGAME_HEADERS} ${WEIRDGAME_ASSETS}) -target_include_directories(${PROJECT_NAME} PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/include) + +# Set include directories. +target_include_directories(${PROJECT_NAME} PRIVATE "${CMAKE_CURRENT_SOURCE_DIR}/include") + +# Link to WeirdEngine. target_link_libraries(${PROJECT_NAME} PRIVATE WeirdEngine) +# Set Asset Path Macro if(DEPLOY_STANDALONE) set(ASSETS_PATH "./assets/") else() set(ASSETS_PATH "${CMAKE_CURRENT_SOURCE_DIR}/assets/") endif() +message(STATUS "Assets path: ${ASSETS_PATH}") target_compile_definitions(${PROJECT_NAME} PUBLIC ASSETS_PATH="${ASSETS_PATH}") if (MINGW) target_link_options(${PROJECT_NAME} PRIVATE -static -static-libgcc -static-libstdc++) endif() -add_custom_command(TARGET ${PROJECT_NAME} POST_BUILD - COMMAND ${CMAKE_COMMAND} -E copy_directory "${CMAKE_CURRENT_SOURCE_DIR}/assets" "$/assets" - COMMAND ${CMAKE_COMMAND} -E copy_directory "${WEIRD_ENGINE_REAL_SOURCE}/src/weird-renderer/fonts" "$/fonts" - COMMAND ${CMAKE_COMMAND} -E copy_directory "${WEIRD_ENGINE_REAL_SOURCE}/src/weird-renderer/shaders" "$/shaders" - COMMENT "Copying Assets, Fonts, and Shaders" -) +# ------------------------------------------------------------------------- +# POST BUILD COMMANDS (DLLs + Assets + Fonts + Shaders) +# ------------------------------------------------------------------------- +if(DEPLOY_STANDALONE) + add_custom_command(TARGET ${PROJECT_NAME} POST_BUILD + # 1. Copy Project ASSETS folder -> Build/assets + COMMAND ${CMAKE_COMMAND} -E copy_directory + "${CMAKE_CURRENT_SOURCE_DIR}/assets" + "$/assets" + + # 2. Copy WeirdEngine FONTS -> Build/fonts + COMMAND ${CMAKE_COMMAND} -E copy_directory + "${WEIRD_ENGINE_REAL_SOURCE}/src/weird-renderer/fonts" + "$/fonts" + + # 3. Copy WeirdEngine SHADERS -> Build/shaders + COMMAND ${CMAKE_COMMAND} -E copy_directory + "${WEIRD_ENGINE_REAL_SOURCE}/src/weird-renderer/shaders" + "$/shaders" + + COMMENT "Copying Game Assets, Engine Fonts, and Engine Shaders" + ) + + if(BUILD_WEB) + # For web builds, copy index.html if it exists + if(EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/src/index.html") + add_custom_command(TARGET ${PROJECT_NAME} POST_BUILD + COMMAND ${CMAKE_COMMAND} -E copy_if_different + "${CMAKE_CURRENT_SOURCE_DIR}/src/index.html" + "$/index.html" + COMMENT "Copying index.html for web build" + ) + endif() + endif() +endif() + +# ------------------------------------------------------------------------- +# SOURCE GROUPS +# ------------------------------------------------------------------------- +function(assign_source_groups TARGET) + foreach(source_file IN LISTS ARGN) + get_filename_component(FILE_PATH "${source_file}" PATH) + file(RELATIVE_PATH REL_PATH "${CMAKE_CURRENT_SOURCE_DIR}" "${FILE_PATH}") + string(REPLACE "/" "\\" FILTER_PATH "${REL_PATH}") + if(FILTER_PATH STREQUAL "") + set(FILTER_PATH "Root") + endif() + source_group("${FILTER_PATH}" FILES "${source_file}") + endforeach() +endfunction() + +assign_source_groups(${PROJECT_NAME} ${WEIRDGAME_SOURCES} ${WEIRDGAME_HEADERS} ${WEIRDGAME_ASSETS}) diff --git a/tools/scene-editor/CMakeLists.txt b/tools/scene-editor/CMakeLists.txt index 0dc70c6..263d3b9 100644 --- a/tools/scene-editor/CMakeLists.txt +++ b/tools/scene-editor/CMakeLists.txt @@ -1,6 +1,16 @@ cmake_minimum_required(VERSION 3.10) + +# ============================================================================== +# 1. Project Configuration +# ============================================================================== project(SceneEditorTool) +# Path to the WeirdEngine directory. Change this depending on where your project is located. +# Examples inside weird-engine use "../../" +# External projects usually use "../weird-engine/" or similar. +set(WEIRD_ENGINE_LOCAL_PATH "../../") +# ============================================================================== + # Create folders if they don't exist file(MAKE_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}/assets") file(MAKE_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}/include") @@ -8,61 +18,147 @@ file(MAKE_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}/src") set(CMAKE_CXX_STANDARD 20) set(CMAKE_CXX_STANDARD_REQUIRED ON) -set(CMAKE_CXX_EXTENSIONS OFF) +set(CMAKE_CXX_EXTENSIONS OFF) # Ensure strictly standard C++ +# Option to switch between local and online version of WeirdEngine option(USE_LOCAL_WEIRD_ENGINE "Use local version of WeirdEngine" ON) -set(WEIRD_ENGINE_LOCAL_PATH "../../") + +# Option to build for web (Emscripten) +option(BUILD_WEB "Build for web using Emscripten" OFF) + +# Option to build for standalone deployment option(DEPLOY_STANDALONE "Configure paths and copy assets for a standalone distribution" OFF) +# Force DEPLOY_STANDALONE when building for web +if(BUILD_WEB) + set(DEPLOY_STANDALONE ON CACHE BOOL "" FORCE) +endif() + if(DEPLOY_STANDALONE) message(STATUS ">> DEPLOY MODE: Assets will be copied to output. Paths set to relative.") + # Force the engine to expect runtime assets set(WEIRD_ENGINE_USE_RUNTIME_ASSETS ON CACHE BOOL "" FORCE) else() message(STATUS ">> DEV MODE: Assets read directly from source folder.") endif() +# ------------------------------------------------------------------------- +# INCLUDE ENGINE & CAPTURE SOURCE PATH +# ------------------------------------------------------------------------- if(NOT TARGET WeirdEngine) if(USE_LOCAL_WEIRD_ENGINE) + # Use the local version of WeirdEngine + message(STATUS "Using local version of WeirdEngine at ${WEIRD_ENGINE_LOCAL_PATH}") add_subdirectory(${WEIRD_ENGINE_LOCAL_PATH} ${CMAKE_BINARY_DIR}/weird-engine) + + # Resolve the local path to an absolute path for copying files later get_filename_component(WEIRD_ENGINE_REAL_SOURCE "${WEIRD_ENGINE_LOCAL_PATH}" ABSOLUTE) else() + # Fetch WeirdEngine from GitHub + message(STATUS "Using online version of WeirdEngine") + set(WEIRD_ENGINE_GIT_REF "main") + include(FetchContent) FetchContent_Declare( WeirdEngine GIT_REPOSITORY https://github.com/damacaa/weird-engine - GIT_TAG main + GIT_TAG ${WEIRD_ENGINE_GIT_REF} ) FetchContent_MakeAvailable(WeirdEngine) + + # FetchContent defines _SOURCE_DIR (usually lowercase) set(WEIRD_ENGINE_REAL_SOURCE "${weirdengine_SOURCE_DIR}") endif() else() + # WeirdEngine already defined (built from root); resolve its source path get_filename_component(WEIRD_ENGINE_REAL_SOURCE "${WEIRD_ENGINE_LOCAL_PATH}" ABSOLUTE) endif() +# Glob source files and header files from the proper directories. file(GLOB_RECURSE WEIRDGAME_SOURCES "${CMAKE_CURRENT_SOURCE_DIR}/src/*.cpp") -file(GLOB_RECURSE WEIRDGAME_HEADERS "${CMAKE_CURRENT_SOURCE_DIR}/include/*.h" "${CMAKE_CURRENT_SOURCE_DIR}/include/*.hpp") -file(GLOB_RECURSE WEIRDGAME_ASSETS "${CMAKE_CURRENT_SOURCE_DIR}/assets/*.*") +file(GLOB_RECURSE WEIRDGAME_HEADERS + "${CMAKE_CURRENT_SOURCE_DIR}/include/*.h" + "${CMAKE_CURRENT_SOURCE_DIR}/include/*.hpp" +) +file(GLOB_RECURSE WEIRDGAME_ASSETS + "${CMAKE_CURRENT_SOURCE_DIR}/assets/*.*" +) +# Mark headers as header-only so that Visual Studio treats them appropriately. set_source_files_properties(${WEIRDGAME_HEADERS} PROPERTIES HEADER_FILE_ONLY TRUE) + +# Add executable including both sources and headers. add_executable(${PROJECT_NAME} ${WEIRDGAME_SOURCES} ${WEIRDGAME_HEADERS} ${WEIRDGAME_ASSETS}) -target_include_directories(${PROJECT_NAME} PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/include) + +# Set include directories. +target_include_directories(${PROJECT_NAME} PRIVATE "${CMAKE_CURRENT_SOURCE_DIR}/include") + +# Link to WeirdEngine. target_link_libraries(${PROJECT_NAME} PRIVATE WeirdEngine) +# Set Asset Path Macro if(DEPLOY_STANDALONE) set(ASSETS_PATH "./assets/") else() set(ASSETS_PATH "${CMAKE_CURRENT_SOURCE_DIR}/assets/") endif() +message(STATUS "Assets path: ${ASSETS_PATH}") target_compile_definitions(${PROJECT_NAME} PUBLIC ASSETS_PATH="${ASSETS_PATH}") if (MINGW) target_link_options(${PROJECT_NAME} PRIVATE -static -static-libgcc -static-libstdc++) endif() -add_custom_command(TARGET ${PROJECT_NAME} POST_BUILD - COMMAND ${CMAKE_COMMAND} -E copy_directory "${CMAKE_CURRENT_SOURCE_DIR}/assets" "$/assets" - COMMAND ${CMAKE_COMMAND} -E copy_directory "${WEIRD_ENGINE_REAL_SOURCE}/src/weird-renderer/fonts" "$/fonts" - COMMAND ${CMAKE_COMMAND} -E copy_directory "${WEIRD_ENGINE_REAL_SOURCE}/src/weird-renderer/shaders" "$/shaders" - COMMENT "Copying Assets, Fonts, and Shaders" -) +# ------------------------------------------------------------------------- +# POST BUILD COMMANDS (DLLs + Assets + Fonts + Shaders) +# ------------------------------------------------------------------------- +if(DEPLOY_STANDALONE) + add_custom_command(TARGET ${PROJECT_NAME} POST_BUILD + # 1. Copy Project ASSETS folder -> Build/assets + COMMAND ${CMAKE_COMMAND} -E copy_directory + "${CMAKE_CURRENT_SOURCE_DIR}/assets" + "$/assets" + + # 2. Copy WeirdEngine FONTS -> Build/fonts + COMMAND ${CMAKE_COMMAND} -E copy_directory + "${WEIRD_ENGINE_REAL_SOURCE}/src/weird-renderer/fonts" + "$/fonts" + + # 3. Copy WeirdEngine SHADERS -> Build/shaders + COMMAND ${CMAKE_COMMAND} -E copy_directory + "${WEIRD_ENGINE_REAL_SOURCE}/src/weird-renderer/shaders" + "$/shaders" + + COMMENT "Copying Game Assets, Engine Fonts, and Engine Shaders" + ) + + if(BUILD_WEB) + # For web builds, copy index.html if it exists + if(EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/src/index.html") + add_custom_command(TARGET ${PROJECT_NAME} POST_BUILD + COMMAND ${CMAKE_COMMAND} -E copy_if_different + "${CMAKE_CURRENT_SOURCE_DIR}/src/index.html" + "$/index.html" + COMMENT "Copying index.html for web build" + ) + endif() + endif() +endif() + +# ------------------------------------------------------------------------- +# SOURCE GROUPS +# ------------------------------------------------------------------------- +function(assign_source_groups TARGET) + foreach(source_file IN LISTS ARGN) + get_filename_component(FILE_PATH "${source_file}" PATH) + file(RELATIVE_PATH REL_PATH "${CMAKE_CURRENT_SOURCE_DIR}" "${FILE_PATH}") + string(REPLACE "/" "\\" FILTER_PATH "${REL_PATH}") + if(FILTER_PATH STREQUAL "") + set(FILTER_PATH "Root") + endif() + source_group("${FILTER_PATH}" FILES "${source_file}") + endforeach() +endfunction() + +assign_source_groups(${PROJECT_NAME} ${WEIRDGAME_SOURCES} ${WEIRDGAME_HEADERS} ${WEIRDGAME_ASSETS}) From 0af4d272cc7665f70f8f1d650e27483fd341a718 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Mart=C3=AD?= <49535803+damacaa@users.noreply.github.com> Date: Sun, 19 Jul 2026 19:43:33 +0200 Subject: [PATCH 03/25] Added web builds and diagnostics test to validate builds --- .github/workflows/build-web.yml | 75 ++++++++++++++++++++++ .github/workflows/cmake-multi-platform.yml | 33 ++++++++-- 2 files changed, 103 insertions(+), 5 deletions(-) create mode 100644 .github/workflows/build-web.yml diff --git a/.github/workflows/build-web.yml b/.github/workflows/build-web.yml new file mode 100644 index 0000000..fe27f08 --- /dev/null +++ b/.github/workflows/build-web.yml @@ -0,0 +1,75 @@ +name: Build Web + +on: + push: + branches: [ "main" ] + pull_request: + branches: [ "main" ] + +permissions: + contents: read + +jobs: + build: + runs-on: ubuntu-22.04 + + steps: + - name: Checkout code + uses: actions/checkout@v4 + with: + submodules: recursive + fetch-depth: 0 + + - name: Ensure submodules are up-to-date + run: git submodule update --init --recursive + + - name: Install dependencies + run: > + sudo apt-get update && sudo apt-get install -y + cmake build-essential libgl-dev libegl-dev + libwayland-dev libxkbcommon-dev wayland-protocols + libasound2-dev libpulse-dev libpipewire-0.3-dev + libx11-dev libxext-dev libxcursor-dev libxi-dev + libxrandr-dev libxss-dev libxtst-dev + + - name: Setup Emscripten + uses: mymindstorm/setup-emsdk@v14 + with: + version: latest + actions-cache-folder: 'emsdk-cache' + + - name: Build WeirdSamples for Web + run: | + mkdir build && cd build + + # Using emcmake and emmake to compile for the web. + # We only build the WeirdSamples target to avoid overwriting issues. + emcmake cmake .. \ + -DCMAKE_BUILD_TYPE=Release \ + -DWEIRD_ENGINE_BUILD_EXAMPLES=ON \ + -DBUILD_WEB=ON \ + -DCMAKE_C_FLAGS="-pthread" \ + -DCMAKE_CXX_FLAGS="-pthread" \ + -DCMAKE_EXE_LINKER_FLAGS="-pthread -sPTHREAD_POOL_SIZE=4 -sINITIAL_MEMORY=33554432 -sMAX_WEBGL_VERSION=2 -sMIN_WEBGL_VERSION=2 -o index.html --preload-file ../examples/sample-scenes/assets@/assets --preload-file ../src/weird-renderer/fonts@/fonts --preload-file ../src/weird-renderer/shaders@/shaders" + + emmake make WeirdSamples + + - name: Prepare Artifact + run: | + mkdir -p game_export + + # Emscripten outputs multiple files based on flags: + # index.html, index.wasm, index.js, index.worker.js, and index.data + cp build/index.* game_export/ + cp build/examples/sample-scenes/WeirdSamples.* game_export/ || true + + # Assets were copied to the target directory by our CMake template + cp -r build/examples/sample-scenes/assets game_export/ || true + cp -r build/examples/sample-scenes/fonts game_export/ || true + cp -r build/examples/sample-scenes/shaders game_export/ || true + + - name: Upload Artifact + uses: actions/upload-artifact@v4 + with: + name: weird-engine-web-sample + path: game_export/ diff --git a/.github/workflows/cmake-multi-platform.yml b/.github/workflows/cmake-multi-platform.yml index 6681f8c..cc4c65a 100644 --- a/.github/workflows/cmake-multi-platform.yml +++ b/.github/workflows/cmake-multi-platform.yml @@ -31,14 +31,37 @@ jobs: - name: Install dependencies (Linux) if: runner.os == 'Linux' - run: sudo apt update && sudo apt install -y cmake g++ make xorg-dev libgl1-mesa-dev libxrandr-dev libxinerama-dev libxcursor-dev libxi-dev + run: sudo apt update && sudo apt install -y cmake g++ make xorg-dev libgl1-mesa-dev libxrandr-dev libxinerama-dev libxcursor-dev libxi-dev xvfb - name: Configure CMake - run: cmake -B ${{github.workspace}}/build -DCMAKE_BUILD_TYPE=${{env.BUILD_TYPE}} + run: cmake -B ${{github.workspace}}/build -DCMAKE_BUILD_TYPE=${{env.BUILD_TYPE}} -DWEIRD_ENGINE_BUILD_EXAMPLES=ON -DWEIRD_TEST_HOOKS=ON - name: Build run: cmake --build ${{github.workspace}}/build --config ${{env.BUILD_TYPE}} - - name: Test - working-directory: ${{github.workspace}}/build - run: ctest -C ${{env.BUILD_TYPE}} + - name: Test (Linux) + if: runner.os == 'Linux' + working-directory: ${{github.workspace}}/build/examples/sample-scenes + env: + WEIRD_AUTO_QUIT_SECONDS: 3 + WEIRD_SCREENSHOT_FRAME: 10 + run: xvfb-run -a ./WeirdSamples + + - name: Test (Windows) + if: runner.os == 'Windows' + working-directory: ${{github.workspace}}/build/examples/sample-scenes/Release + env: + WEIRD_AUTO_QUIT_SECONDS: 3 + WEIRD_SCREENSHOT_FRAME: 10 + run: ./WeirdSamples.exe + + - name: Upload Test Artifacts + if: always() + uses: actions/upload-artifact@v4 + with: + name: test-artifacts-${{ matrix.os }} + path: | + ${{github.workspace}}/build/examples/sample-scenes/log.txt + ${{github.workspace}}/build/examples/sample-scenes/screenshot_*.bmp + ${{github.workspace}}/build/examples/sample-scenes/Release/log.txt + ${{github.workspace}}/build/examples/sample-scenes/Release/screenshot_*.bmp From 7d80206ebcdebb6b7f17c84943e64fdc1c3d7fa5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Mart=C3=AD?= <49535803+damacaa@users.noreply.github.com> Date: Sun, 19 Jul 2026 20:15:57 +0200 Subject: [PATCH 04/25] Format, format script and format test --- .github/workflows/format.yml | 29 + examples/3d-experiments/include/Classic.h | 8 +- examples/3d-experiments/include/CornellBox.h | 2 +- .../3d-experiments/include/MaterialShowcase.h | 46 +- examples/3d-experiments/src/main.cpp | 4 +- examples/empty-project/src/main.cpp | 4 +- .../assets/fire/shaders/fireParticles.vert | 6 +- .../assets/fire/shaders/flame.frag | 6 +- .../assets/lines/combination.frag | 6 +- .../assets/water/shaders/water.frag | 110 +-- .../assets/water/shaders/water.vert | 98 +-- examples/opengl-experiments/include/Fire.h | 11 +- examples/opengl-experiments/include/Lines.h | 7 +- examples/opengl-experiments/include/Water.h | 56 +- .../opengl-experiments/include/WaterPlane.h | 84 ++- examples/opengl-experiments/src/main.cpp | 2 - .../sample-scenes/include/AquariumScene.h | 13 +- .../sample-scenes/include/CollisionHandling.h | 2 +- examples/sample-scenes/include/DestroyScene.h | 161 ++-- examples/sample-scenes/include/ImageScene.h | 2 +- examples/sample-scenes/include/LifeScene.h | 8 +- .../include/MouseCollisionScene.h | 2 +- examples/sample-scenes/include/RopeScene.h | 10 +- .../include/ShapesCombinations.h | 5 +- examples/sample-scenes/include/WalkScene.h | 15 +- include/weird-engine.h | 45 +- include/weird-engine/Background.h | 36 +- include/weird-engine/Input.h | 34 +- include/weird-engine/Logger.h | 50 +- include/weird-engine/Material3D.h | 2 +- include/weird-engine/Profiler.h | 105 ++- include/weird-engine/ResourceManager.h | 3 +- include/weird-engine/Scene.h | 60 +- include/weird-engine/ecs/ComponentArray.h | 3 +- include/weird-engine/ecs/ECS.h | 39 +- include/weird-engine/math/Default2DSDFs.h | 49 +- include/weird-engine/math/Default3DSDFs.h | 65 +- include/weird-engine/math/MathExpressions.h | 8 +- include/weird-engine/math/Primitives.h | 711 +++++++++--------- include/weird-engine/math/Primitives3D.h | 396 +++++----- include/weird-engine/math/ShapeMacro.h | 9 +- .../systems/PhysicsInteractionSystem.h | 64 +- .../systems/PlayerMovementSystem.h | 23 +- .../weird-engine/systems/SDFRenderSystem.h | 177 ++--- .../systems/SDFShaderGenerationSystem.h | 45 +- include/weird-physics/Simulation2D.h | 4 +- .../components/CustomShapeManager.h | 9 +- .../components/DistanceConstraint.h | 8 +- .../components/DistanceConstraintManager.h | 8 +- .../components/GlobalPhysicsSettings.h | 7 +- include/weird-physics/components/RigidBody.h | 5 +- include/weird-physics/components/Spring.h | 9 +- .../weird-physics/components/SpringManager.h | 10 +- include/weird-renderer/components/Button.h | 1 - .../weird-renderer/components/MeshRenderer.h | 3 +- .../weird-renderer/components/TextRenderer.h | 1 - include/weird-renderer/core/Display.h | 2 - include/weird-renderer/core/Renderer.h | 2 +- .../weird-renderer/core/SDF2DRenderPipeline.h | 28 +- .../weird-renderer/core/SDF3DRenderPipeline.h | 24 +- include/weird-renderer/core/WeirdFBDevEGL.h | 36 +- include/weird-renderer/resources/DataBuffer.h | 27 +- include/weird-renderer/resources/Font.h | 2 +- include/weird-renderer/resources/Mesh.h | 8 +- scripts/format.sh | 12 + src/weird-engine/Logger.cpp | 71 +- src/weird-engine/ResourceManager.cpp | 7 +- src/weird-engine/Scene.cpp | 53 +- src/weird-engine/SceneSerializer.cpp | 49 +- src/weird-physics/Simulation2D.cpp | 189 +++-- src/weird-renderer/audio/AudioEngine.cpp | 2 +- .../core/MeshRenderPipeline.cpp | 22 +- src/weird-renderer/core/RenderTarget.cpp | 2 +- src/weird-renderer/core/Renderer.cpp | 73 +- .../core/SDF2DRenderPipeline.cpp | 116 +-- .../core/SDF3DRenderPipeline.cpp | 43 +- src/weird-renderer/core/SDLInitializer.cpp | 14 +- src/weird-renderer/core/WeirdFBDevEGL.cpp | 477 +++++++----- src/weird-renderer/resources/Mesh.cpp | 2 +- src/weird-renderer/resources/Shader.cpp | 13 +- src/weird-renderer/resources/Texture.cpp | 45 +- src/weird-renderer/scene/Camera.cpp | 2 +- src/weird-renderer/shaders/2d/background.frag | 12 +- .../shaders/2d/jump_flood_step.frag | 4 +- src/weird-renderer/shaders/2d/lighting.frag | 28 +- .../shaders/2d/material_color.frag | 2 +- .../shaders/2d/sdf_distance.frag | 11 +- src/weird-renderer/shaders/3d/gbuffer.frag | 10 +- src/weird-renderer/shaders/3d/geometry.frag | 32 +- .../shaders/3d/sdf_raymarching.frag | 241 +++--- src/weird-renderer/shaders/common/shapes.glsl | 42 +- .../misc/background_spherical_grid.frag | 2 +- .../shaders/postprocess/blur.frag | 2 +- .../shaders/postprocess/linear_to_srgb.frag | 7 +- .../shaders/postprocess/screen_output.frag | 12 +- .../molecule-editor/include/MoleculeEditor.h | 10 +- tools/molecule-editor/src/main.cpp | 2 +- tools/scene-editor/include/SceneEditor.h | 93 ++- tools/scene-editor/src/main.cpp | 2 +- 99 files changed, 2443 insertions(+), 2076 deletions(-) create mode 100644 .github/workflows/format.yml create mode 100755 scripts/format.sh diff --git a/.github/workflows/format.yml b/.github/workflows/format.yml new file mode 100644 index 0000000..b23a90a --- /dev/null +++ b/.github/workflows/format.yml @@ -0,0 +1,29 @@ +name: Clang Format Check + +on: + push: + branches: [ "main" ] + pull_request: + branches: [ "main" ] + +jobs: + format-check: + runs-on: ubuntu-latest + + steps: + - uses: actions/checkout@v4 + + - name: Install clang-format + run: sudo apt-get update && sudo apt-get install -y clang-format + + - name: Run format script + run: | + chmod +x ./scripts/format.sh + ./scripts/format.sh + + - name: Check for formatting changes + run: | + if ! git diff --exit-code; then + echo "::error::Code formatting check failed. Please run ./scripts/format.sh locally and commit the changes." + exit 1 + fi diff --git a/examples/3d-experiments/include/Classic.h b/examples/3d-experiments/include/Classic.h index 3533f26..27eb98a 100644 --- a/examples/3d-experiments/include/Classic.h +++ b/examples/3d-experiments/include/Classic.h @@ -18,10 +18,10 @@ class ClassicScene : public Scene3D auto& redMat = createMaterial(); redMat.color = vec4(.8f, 0.2f, 0.2f, 1.0f); - + auto& orangeMat = createMaterial(); orangeMat.color = vec4(.95f, 0.4f, 0.1f, 1.0f); - + auto& floorMaterial = createMaterial(); floorMaterial.color = vec4(1.0f, 1.0f, 1.0f, 1.0f); floorMaterial.secondaryColor = vec4(0.4f, 0.4f, 0.6f, 1.0f); @@ -64,8 +64,8 @@ class ClassicScene : public Scene3D Entity start = addShape(DefaultShapes3D::PLANE, vars1, floorMaterial, CombinationType::Addition, false); } - getLigths().push_back( - Light{0, glm::vec3(0.0f, 3.0f, 0.0f), 0, glm::vec3(0.35f, 0.45f, 0.5f), glm::vec4(1.0f, 0.95f, 0.9f, 2.0f)}); + getLigths().push_back(Light{0, glm::vec3(0.0f, 3.0f, 0.0f), 0, glm::vec3(0.35f, 0.45f, 0.5f), + glm::vec4(1.0f, 0.95f, 0.9f, 2.0f)}); ecs.getComponent(m_mainCamera).position = vec3(0, 2, 10); } diff --git a/examples/3d-experiments/include/CornellBox.h b/examples/3d-experiments/include/CornellBox.h index e15d992..064fde3 100644 --- a/examples/3d-experiments/include/CornellBox.h +++ b/examples/3d-experiments/include/CornellBox.h @@ -11,7 +11,7 @@ using namespace WeirdEngine; class CornellBox : public Scene3D { public: - CornellBox(){}; + CornellBox() {}; private: // Inherited via Scene diff --git a/examples/3d-experiments/include/MaterialShowcase.h b/examples/3d-experiments/include/MaterialShowcase.h index 9a43bc1..fbc7d88 100644 --- a/examples/3d-experiments/include/MaterialShowcase.h +++ b/examples/3d-experiments/include/MaterialShowcase.h @@ -11,17 +11,14 @@ using namespace WeirdEngine; class MaterialShowcaseScene : public Scene3D { public: - MaterialShowcaseScene(){}; + MaterialShowcaseScene() {}; private: - // Inherited via Scene void onStart(ECSManager& ecs) override { m_debugFly = true; - - { Entity entity = ecs.createEntity(); Transform& t = ecs.addComponent(entity); @@ -35,20 +32,19 @@ class MaterialShowcaseScene : public Scene3D auto& sdf = ecs.addComponent(entity); sdf.materialId = mat.id; } - + std::vector randomMats; vec4 colors[] = { - vec4(.95f, 0.4f, 0.1f, 1.0f), // Orange - vec4(0.5f, 0.0f, 1.0f, 1.0f), // Purple - vec4(0.0f, .9f, .9f, 1.0f), // Cyan - vec4(0.5f, 1.0f, 0.5f, 1.0f), // Light Green - vec4(1.0f, 0.3f, .6f, 1.0f), // Magenta - vec4(1.0f, 0.5f, 0.5f, 1.0f), // Pink - vec4(0.5f, 0.5f, 1.0f, 1.0f), // Light Blue - vec4(0.4f, 0.25f, 0.1f, 1.0f) // Brown + vec4(.95f, 0.4f, 0.1f, 1.0f), // Orange + vec4(0.5f, 0.0f, 1.0f, 1.0f), // Purple + vec4(0.0f, .9f, .9f, 1.0f), // Cyan + vec4(0.5f, 1.0f, 0.5f, 1.0f), // Light Green + vec4(1.0f, 0.3f, .6f, 1.0f), // Magenta + vec4(1.0f, 0.5f, 0.5f, 1.0f), // Pink + vec4(0.5f, 0.5f, 1.0f, 1.0f), // Light Blue + vec4(0.4f, 0.25f, 0.1f, 1.0f) // Brown }; - { auto& mat = createMaterial(); mat.color = vec4(.95f, 0.4f, 0.1f, 1.0f); @@ -67,7 +63,7 @@ class MaterialShowcaseScene : public Scene3D mat.roughness = 0.99f; mat.pattern = MaterialPattern::Checkers; mat.secondaryColor = mat.color * 0.8f; - + randomMats.push_back(mat.id); } @@ -75,11 +71,11 @@ class MaterialShowcaseScene : public Scene3D auto& mat = createMaterial(); mat.color = vec4(1.0f, 0.3f, .6f, 1.0f); mat.secondaryColor = vec4(1.0f, 0.2f, 0.05f, 1.0f); - + mat.metallic = 0.5f; mat.roughness = 0.05f; mat.pattern = MaterialPattern::Waves; - + randomMats.push_back(mat.id); } @@ -90,7 +86,7 @@ class MaterialShowcaseScene : public Scene3D mat.roughness = 0.99f; mat.pattern = MaterialPattern::Checkers; mat.secondaryColor = mat.color * 0.8f; - + randomMats.push_back(mat.id); } @@ -102,7 +98,7 @@ class MaterialShowcaseScene : public Scene3D mat.roughness = 0.001f; mat.pattern = MaterialPattern::PerlinNoise; mat.patternScale = 5.0f; - + randomMats.push_back(mat.id); } @@ -111,13 +107,11 @@ class MaterialShowcaseScene : public Scene3D mat.color = vec4(0.85f, 0.7f, 0.1f, 0.5f); mat.metallic = 0.5f; mat.roughness = 0.0f; - + randomMats.push_back(mat.id); } - - - for (size_t i = 0; i < randomMats.size(); i++) + for (size_t i = 0; i < randomMats.size(); i++) { Entity entity = ecs.createEntity(); Transform& t = ecs.addComponent(entity); @@ -145,7 +139,7 @@ class MaterialShowcaseScene : public Scene3D mirrorMaterial.roughness = 0.0f; { - + std::shared_ptr box = std::make_shared(); auto boxId = registerSDF(box); @@ -161,8 +155,8 @@ class MaterialShowcaseScene : public Scene3D Entity start = addShape(boxId, vars1, mirrorMaterial, CombinationType::Addition, false); } - getLigths().push_back( - Light{0, glm::vec3(0.0f, 0.0f, 0.0f), 0, normalize(glm::vec3(0.0f, 0.4f, 1.0f)), glm::vec4(1.0f, 1.0f, 1.0f, 0.5f)}); + getLigths().push_back(Light{0, glm::vec3(0.0f, 0.0f, 0.0f), 0, normalize(glm::vec3(0.0f, 0.4f, 1.0f)), + glm::vec4(1.0f, 1.0f, 1.0f, 0.5f)}); // getLigths().push_back( // Light{1, glm::vec3(0.0f, 0.0f, 0.0f), 0, glm::vec3(0.35f, 0.45f, 0.5f), glm::vec4(0.0f, 1.0f, 0.0f, 1.0f)}); diff --git a/examples/3d-experiments/src/main.cpp b/examples/3d-experiments/src/main.cpp index 07236aa..8bc976e 100644 --- a/examples/3d-experiments/src/main.cpp +++ b/examples/3d-experiments/src/main.cpp @@ -4,8 +4,8 @@ #include #include "Classic.h" -#include "MaterialShowcase.h" #include "CornellBox.h" +#include "MaterialShowcase.h" int main(int argc, char* argv[]) { @@ -31,8 +31,6 @@ int main(int argc, char* argv[]) displaySettings.colorPalette[DisplaySettings::Orange].a = 1.0f; - - PhysicsSettings physicsSettings{}; AudioSettings audioSettings{}; diff --git a/examples/empty-project/src/main.cpp b/examples/empty-project/src/main.cpp index 5b16b84..e76cab1 100644 --- a/examples/empty-project/src/main.cpp +++ b/examples/empty-project/src/main.cpp @@ -13,9 +13,7 @@ class EmptyScene : public Scene2D } private: - void onStart() override - { - } + void onStart() override {} void onUpdate(float delta) override {} void onCreate() override {} diff --git a/examples/opengl-experiments/assets/fire/shaders/fireParticles.vert b/examples/opengl-experiments/assets/fire/shaders/fireParticles.vert index dc2dd66..c94201c 100644 --- a/examples/opengl-experiments/assets/fire/shaders/fireParticles.vert +++ b/examples/opengl-experiments/assets/fire/shaders/fireParticles.vert @@ -35,10 +35,10 @@ void main() float maxHeight = 1.5 + (fract(instanceId * 123.45678) - 0.5); // Constant + random offset float y = plateauFunction(2.0 * delta, maxHeight, 0.8); - float distanceToCenterXZ = 0.1 + (0.3 * smoothstep(0.0, 1.0, sqrt(1.5 * delta))); // TODO: find an alternative to sqrt + float distanceToCenterXZ = + 0.1 + (0.3 * smoothstep(0.0, 1.0, sqrt(1.5 * delta))); // TODO: find an alternative to sqrt - vec3 offset = - vec3(distanceToCenterXZ * sin(u_time + instanceId), y, distanceToCenterXZ * cos(u_time + instanceId)); + vec3 offset = vec3(distanceToCenterXZ * sin(u_time + instanceId), y, distanceToCenterXZ * cos(u_time + instanceId)); v_worldPos = vec3(u_model * vec4(2.0 * (1.0 - delta * delta) * in_position, 1.0)) + offset; v_normal = u_normalMatrix * in_normal; diff --git a/examples/opengl-experiments/assets/fire/shaders/flame.frag b/examples/opengl-experiments/assets/fire/shaders/flame.frag index 7da2fa7..8931871 100644 --- a/examples/opengl-experiments/assets/fire/shaders/flame.frag +++ b/examples/opengl-experiments/assets/fire/shaders/flame.frag @@ -17,9 +17,9 @@ uniform sampler2D t_flameShape; const int NUM_STOPS = 4; const vec3 colors[NUM_STOPS] = vec3[](vec3(0.1, 0.1, 0.1), // Grey - vec3(0.8, 0.3, 0.2), // Red - vec3(1.1, 0.7, 0.2), // Orange - vec3(1.2, 1.2, 1.2) // White + vec3(0.8, 0.3, 0.2), // Red + vec3(1.1, 0.7, 0.2), // Orange + vec3(1.2, 1.2, 1.2) // White ); const float stops[NUM_STOPS] = float[](0.0, 0.7, 0.9, 1.0); diff --git a/examples/opengl-experiments/assets/lines/combination.frag b/examples/opengl-experiments/assets/lines/combination.frag index 296ada6..f94e1bf 100644 --- a/examples/opengl-experiments/assets/lines/combination.frag +++ b/examples/opengl-experiments/assets/lines/combination.frag @@ -12,9 +12,9 @@ uniform sampler2D t_lines; const int NUM_STOPS = 4; const vec3 colors[NUM_STOPS] = vec3[](vec3(0.82, 0.74, 0.88), // Muted lavender - vec3(0.78, 0.94, 0.76), // Pale pistachio - vec3(0.98, 0.85, 0.72), // Dusty pastel orange - vec3(0.68, 0.96, 0.95) // Soft cyan mist + vec3(0.78, 0.94, 0.76), // Pale pistachio + vec3(0.98, 0.85, 0.72), // Dusty pastel orange + vec3(0.68, 0.96, 0.95) // Soft cyan mist ); const float stops[NUM_STOPS] = float[](0.0, 0.33, 0.66, 1.0); diff --git a/examples/opengl-experiments/assets/water/shaders/water.frag b/examples/opengl-experiments/assets/water/shaders/water.frag index 5da45fb..8861958 100644 --- a/examples/opengl-experiments/assets/water/shaders/water.frag +++ b/examples/opengl-experiments/assets/water/shaders/water.frag @@ -10,41 +10,40 @@ in vec3 v_normal; in vec3 v_color; in vec2 v_texCoord; -uniform vec3 u_camPos; +uniform vec3 u_camPos; uniform float u_time; // Screen-space scene snapshot (taken before this draw call) uniform sampler2D u_sceneColor; uniform sampler2D u_sceneDepth; -uniform vec2 u_screenSize; +uniform vec2 u_screenSize; // Light array – same layout as sdf_raymarching.frag struct Light { vec3 position; vec3 direction; - vec4 color; // .rgb = tint, .a = intensity - int type; // 0 = directional, 1 = point, 2 = spot/cone + vec4 color; // .rgb = tint, .a = intensity + int type; // 0 = directional, 1 = point, 2 = spot/cone }; #define MAX_LIGHTS 8 -uniform int u_numLights; +uniform int u_numLights; uniform Light u_lights[MAX_LIGHTS]; // Water material -const vec3 u_shallowColor = vec3(0.05, 0.35, 0.55); -const vec3 u_deepColor = vec3(0.01, 0.10, 0.25); -const float u_metallic = 0.02; // F0 for water (Fresnel base ~2%) -const float u_fresnelPower = 5.0; -const float u_specExponent = 512.0; -const float u_absorptionRate = 2.0; // light absorbed per world-unit of depth -const float u_foamBand = 0.25; // max foam band width (world units) +const vec3 u_shallowColor = vec3(0.05, 0.35, 0.55); +const vec3 u_deepColor = vec3(0.01, 0.10, 0.25); +const float u_metallic = 0.02; // F0 for water (Fresnel base ~2%) +const float u_fresnelPower = 5.0; +const float u_specExponent = 512.0; +const float u_absorptionRate = 2.0; // light absorbed per world-unit of depth +const float u_foamBand = 0.25; // max foam band width (world units) // ── Perlin noise ───────────────────────────────────────────────────────────── vec2 _hash22(vec2 p) { - p = vec2(dot(p, vec2(127.1, 311.7)), - dot(p, vec2(269.5, 183.3))); + p = vec2(dot(p, vec2(127.1, 311.7)), dot(p, vec2(269.5, 183.3))); return -1.0 + 2.0 * fract(sin(p) * 43758.5453123); } @@ -53,18 +52,23 @@ float _perlin(vec2 p) vec2 i = floor(p); vec2 f = fract(p); vec2 u = f * f * (3.0 - 2.0 * f); // Hermite smoothstep - return mix( - mix(dot(_hash22(i + vec2(0.0, 0.0)), f - vec2(0.0, 0.0)), - dot(_hash22(i + vec2(1.0, 0.0)), f - vec2(1.0, 0.0)), u.x), - mix(dot(_hash22(i + vec2(0.0, 1.0)), f - vec2(0.0, 1.0)), - dot(_hash22(i + vec2(1.0, 1.0)), f - vec2(1.0, 1.0)), u.x), u.y); + return mix(mix(dot(_hash22(i + vec2(0.0, 0.0)), f - vec2(0.0, 0.0)), + dot(_hash22(i + vec2(1.0, 0.0)), f - vec2(1.0, 0.0)), u.x), + mix(dot(_hash22(i + vec2(0.0, 1.0)), f - vec2(0.0, 1.0)), + dot(_hash22(i + vec2(1.0, 1.0)), f - vec2(1.0, 1.0)), u.x), + u.y); } // Fractal Brownian Motion – returns [0, 1] float fbm(vec2 p) { float v = 0.0, a = 0.5, s = 1.0; - for (int i = 0; i < 4; i++) { v += a * _perlin(p * s); s *= 2.1; a *= 0.5; } + for (int i = 0; i < 4; i++) + { + v += a * _perlin(p * s); + s *= 2.1; + a *= 0.5; + } return v * 0.5 + 0.5; } @@ -84,10 +88,10 @@ float linearizeDepth(float d) vec3 getSkyColor(vec3 dir) { - float t = max(dir.y, 0.0); - vec3 zenithColor = vec3(0.05, 0.25, 0.7); - vec3 horizonColor = vec3(0.5, 0.6, 0.7); - vec3 groundColor = vec3(0.1, 0.1, 0.12); + float t = max(dir.y, 0.0); + vec3 zenithColor = vec3(0.05, 0.25, 0.7); + vec3 horizonColor = vec3(0.5, 0.6, 0.7); + vec3 groundColor = vec3(0.1, 0.1, 0.12); vec3 sky = mix(horizonColor, zenithColor, pow(t, 0.4)); if (dir.y < 0.0) @@ -99,7 +103,7 @@ vec3 getSkyColor(vec3 dir) { float sun = max(dot(dir, normalize(u_lights[i].direction)), 0.0); sky += vec3(1.0, 0.85, 0.6) * pow(sun, 4000.0) * 2.0; - sky += vec3(1.0, 0.6, 0.2) * pow(sun, 200.0) * 0.4; + sky += vec3(1.0, 0.6, 0.2) * pow(sun, 200.0) * 0.4; sky *= u_lights[i].color.w > 0.0 ? 1.0 : 0.0; } } @@ -110,8 +114,8 @@ vec3 getSkyColor(vec3 dir) vec3 surfaceLighting(vec3 p, vec3 rd, vec3 albedo, vec3 N) { - vec3 V = -rd; - float f0 = u_metallic; + vec3 V = -rd; + float f0 = u_metallic; float fresnel = f0 + (1.0 - f0) * pow(clamp(1.0 - dot(V, N), 0.0, 1.0), u_fresnelPower); vec3 directLighting = vec3(0.0); @@ -119,7 +123,7 @@ vec3 surfaceLighting(vec3 p, vec3 rd, vec3 albedo, vec3 N) for (int i = 0; i < u_numLights; i++) { Light light = u_lights[i]; - vec3 L; + vec3 L; float attenuation = 1.0; if (light.type == 0) @@ -128,32 +132,31 @@ vec3 surfaceLighting(vec3 p, vec3 rd, vec3 albedo, vec3 N) } else if (light.type == 1) { - vec3 lv = light.position - p; + vec3 lv = light.position - p; float dist = length(lv); - L = normalize(lv); + L = normalize(lv); attenuation = 10.0 / (3.0 * dist * dist + 0.7 * dist + 1.0); } else { - vec3 lv = light.position - p; + vec3 lv = light.position - p; float dist = length(lv); - L = normalize(lv); + L = normalize(lv); attenuation = 10.0 / (3.0 * dist * dist + 0.7 * dist + 1.0); - attenuation *= smoothstep(0.80, 0.95, - dot(normalize(lv), normalize(light.direction))); + attenuation *= smoothstep(0.80, 0.95, dot(normalize(lv), normalize(light.direction))); } - vec3 diffuse = albedo * max(dot(N, L), 0.0) * (1.0 - fresnel); - vec3 H = normalize(L + V); - float specPow = pow(max(dot(N, H), 0.0), u_specExponent); - vec3 specular = vec3(5.0) * specPow * fresnel; + vec3 diffuse = albedo * max(dot(N, L), 0.0) * (1.0 - fresnel); + vec3 H = normalize(L + V); + float specPow = pow(max(dot(N, H), 0.0), u_specExponent); + vec3 specular = vec3(5.0) * specPow * fresnel; directLighting += (diffuse + specular) * attenuation * light.color.rgb * light.color.a; } - vec3 R = reflect(rd, N); + vec3 R = reflect(rd, N); vec3 reflectionColor = getSkyColor(R); - vec3 ambient = albedo * 0.1 + reflectionColor * fresnel; + vec3 ambient = albedo * 0.1 + reflectionColor * fresnel; return directLighting + ambient; } @@ -162,14 +165,14 @@ vec3 surfaceLighting(vec3 p, vec3 rd, vec3 albedo, vec3 N) void main() { - vec3 N = normalize(v_normal); - vec3 rd = normalize(v_worldPos - u_camPos); + vec3 N = normalize(v_normal); + vec3 rd = normalize(v_worldPos - u_camPos); vec2 screenUV = gl_FragCoord.xy / u_screenSize; // ── Sample scene depth and compute underwater depth ─────────────────────── - float rawDepth = texture(u_sceneDepth, screenUV).r; - bool hasGeom = rawDepth < 0.9999; // false = sky / far-plane background + float rawDepth = texture(u_sceneDepth, screenUV).r; + bool hasGeom = rawDepth < 0.9999; // false = sky / far-plane background // Linear depth avoids the banding caused by perspective non-linearity in // the depth buffer; the difference is the actual view-space distance @@ -188,7 +191,7 @@ void main() sceneColor = texture(u_sceneColor, refractUV).rgb; // Exponential light absorption: deeper objects are tinted toward deep water colour float absorption = exp(-underwaterDepth * u_absorptionRate); - sceneColor = mix(u_deepColor * 0.3, sceneColor, absorption); + sceneColor = mix(u_deepColor * 0.3, sceneColor, absorption); } else { @@ -196,18 +199,18 @@ void main() // so distant views through the water look naturally blue rather than showing // the opaque background colour baked into the scene snapshot. vec3 refractDir = refract(rd, N, 1.0 / 1.33); // water IOR ≈ 1.33 - sceneColor = getSkyColor(refractDir); + sceneColor = getSkyColor(refractDir); } // ── Water surface colour ───────────────────────────────────────────────── - float depthFactor = clamp(abs(v_worldPos.y) * 2.0, 0.0, 1.0); - vec3 waterAlbedo = mix(u_shallowColor, u_deepColor, depthFactor); - vec3 surfaceColor = surfaceLighting(v_worldPos, rd, waterAlbedo, N); + float depthFactor = clamp(abs(v_worldPos.y) * 2.0, 0.0, 1.0); + vec3 waterAlbedo = mix(u_shallowColor, u_deepColor, depthFactor); + vec3 surfaceColor = surfaceLighting(v_worldPos, rd, waterAlbedo, N); // Fresnel: grazing angles are near-fully reflective; normal incidence is mostly transparent - float f0 = u_metallic; + float f0 = u_metallic; float fresnel = f0 + (1.0 - f0) * pow(clamp(1.0 - dot(-rd, N), 0.0, 1.0), u_fresnelPower); - float alpha = mix(0.4, 1.0, fresnel); // [0.4 .. 1.0] + float alpha = mix(0.4, 1.0, fresnel); // [0.4 .. 1.0] // ── Composite: water surface over (absorbed) scene colour ──────────────── vec3 finalColor = mix(sceneColor, surfaceColor, alpha); @@ -221,13 +224,12 @@ void main() // float foam = 1.0 - smoothstep(0.0, bandMax, underwaterDepth); // foam *= smoothstep(-0.2, 0.04, underwaterDepth); // fade above surface - // vec3 foamColor = vec3(1.0); // finalColor = mix(finalColor, foamColor, foam); // } - //finalColor = vec3((sceneLinearZ) - 2.5); - // finalColor = vec3(underwaterDepth); + // finalColor = vec3((sceneLinearZ) - 2.5); + // finalColor = vec3(underwaterDepth); // Output fully opaque – compositing was done manually above FragColor = vec4(finalColor, 1.0); diff --git a/examples/opengl-experiments/assets/water/shaders/water.vert b/examples/opengl-experiments/assets/water/shaders/water.vert index 9ed2410..db42066 100644 --- a/examples/opengl-experiments/assets/water/shaders/water.vert +++ b/examples/opengl-experiments/assets/water/shaders/water.vert @@ -13,8 +13,8 @@ out vec3 v_color; out vec2 v_texCoord; // Uniforms -uniform mat4 u_model; -uniform mat4 u_camMatrix; +uniform mat4 u_model; +uniform mat4 u_camMatrix; uniform float u_time; // ── Gerstner wave ───────────────────────────────────────────────────────────── @@ -29,16 +29,16 @@ uniform float u_time; struct GerstnerOut { - vec3 displacement; // vertex offset (x, y, z) - vec3 dPos_dx; // ∂P/∂x – used to build the normal - vec3 dPos_dz; // ∂P/∂z + vec3 displacement; // vertex offset (x, y, z) + vec3 dPos_dx; // ∂P/∂x – used to build the normal + vec3 dPos_dz; // ∂P/∂z }; GerstnerOut gerstner(vec2 xz, vec2 dir, float wavelength, float amplitude, float steepness) { - float k = 6.28318 / wavelength; // wavenumber - float c = sqrt(9.81 / k); // deep-water phase speed - float f = k * dot(dir, xz) - c * u_time; + float k = 6.28318 / wavelength; // wavenumber + float c = sqrt(9.81 / k); // deep-water phase speed + float f = k * dot(dir, xz) - c * u_time; float sinF = sin(f); float cosF = cos(f); @@ -46,30 +46,23 @@ GerstnerOut gerstner(vec2 xz, vec2 dir, float wavelength, float amplitude, float float Q = steepness; GerstnerOut o; - o.displacement = vec3( - Q * amplitude * dir.x * cosF, - amplitude * sinF, - Q * amplitude * dir.y * cosF - ); + o.displacement = vec3(Q * amplitude * dir.x * cosF, amplitude * sinF, Q * amplitude * dir.y * cosF); // Partial derivatives of the displaced position (for normal computation) float WA = k * amplitude; - o.dPos_dx = vec3( - -Q * WA * dir.x * dir.x * sinF, - WA * dir.x * cosF, - -Q * WA * dir.x * dir.y * sinF - ); - o.dPos_dz = vec3( - -Q * WA * dir.x * dir.y * sinF, - WA * dir.y * cosF, - -Q * WA * dir.y * dir.y * sinF - ); + o.dPos_dx = vec3(-Q * WA * dir.x * dir.x * sinF, WA * dir.x * cosF, -Q * WA * dir.x * dir.y * sinF); + o.dPos_dz = vec3(-Q * WA * dir.x * dir.y * sinF, WA * dir.y * cosF, -Q * WA * dir.y * dir.y * sinF); return o; } // ── Rotate a 2-D point ──────────────────────────────────────────────────────── -vec2 rot2(vec2 p, float a) { float c = cos(a); float s = sin(a); return vec2(c*p.x - s*p.y, s*p.x + c*p.y); } +vec2 rot2(vec2 p, float a) +{ + float c = cos(a); + float s = sin(a); + return vec2(c * p.x - s * p.y, s * p.x + c * p.y); +} void main() { @@ -79,55 +72,66 @@ void main() // Use six sinusoids whose spatial periods have no common rational factor. // Frequencies chosen as prime-like irrational multiples so the warp pattern // never tiles at any human-visible scale. - float t = u_time; + float t = u_time; vec2 warp = vec2( - sin(xz.x * 0.1731 + xz.y * 0.0893 + t * 0.071) * 1.6 - + cos(xz.x * 0.2473 - xz.y * 0.1337 + t * 0.043) * 0.9, - cos(xz.x * 0.0971 + xz.y * 0.2011 + t * 0.059) * 1.4 - + sin(xz.x * 0.1619 - xz.y * 0.3001 + t * 0.037) * 0.7 - ); + sin(xz.x * 0.1731 + xz.y * 0.0893 + t * 0.071) * 1.6 + cos(xz.x * 0.2473 - xz.y * 0.1337 + t * 0.043) * 0.9, + cos(xz.x * 0.0971 + xz.y * 0.2011 + t * 0.059) * 1.4 + sin(xz.x * 0.1619 - xz.y * 0.3001 + t * 0.037) * 0.7); vec2 xzW = xz + warp; // ── Wave cascade A – primary swell direction ────────────────────────────── - vec3 totalDisp = vec3(0.0); + vec3 totalDisp = vec3(0.0); vec3 total_dpdx = vec3(1.0, 0.0, 0.0); vec3 total_dpdz = vec3(0.0, 0.0, 1.0); - GerstnerOut g0 = gerstner(xzW, normalize(vec2( 1.0, 0.4)), 8.09, 0.110, 0.55); - totalDisp += g0.displacement; total_dpdx += g0.dPos_dx; total_dpdz += g0.dPos_dz; + GerstnerOut g0 = gerstner(xzW, normalize(vec2(1.0, 0.4)), 8.09, 0.110, 0.55); + totalDisp += g0.displacement; + total_dpdx += g0.dPos_dx; + total_dpdz += g0.dPos_dz; - GerstnerOut g1 = gerstner(xzW, normalize(vec2(-0.5, 1.0)), 5.00, 0.075, 0.45); - totalDisp += g1.displacement; total_dpdx += g1.dPos_dx; total_dpdz += g1.dPos_dz; + GerstnerOut g1 = gerstner(xzW, normalize(vec2(-0.5, 1.0)), 5.00, 0.075, 0.45); + totalDisp += g1.displacement; + total_dpdx += g1.dPos_dx; + total_dpdz += g1.dPos_dz; - GerstnerOut g2 = gerstner(xzW, normalize(vec2( 0.4, -1.0)), 3.09, 0.040, 0.30); - totalDisp += g2.displacement; total_dpdx += g2.dPos_dx; total_dpdz += g2.dPos_dz; + GerstnerOut g2 = gerstner(xzW, normalize(vec2(0.4, -1.0)), 3.09, 0.040, 0.30); + totalDisp += g2.displacement; + total_dpdx += g2.dPos_dx; + total_dpdz += g2.dPos_dz; // ── Wave cascade B – evaluated in a rotated frame ───────────────────────── // Rotation by sqrt(2) radians ≈ 81.03° – irrational, so cascade B can never // constructively align with cascade A at any finite scale. vec2 xzR = rot2(xzW, 1.41421356); - GerstnerOut g3 = gerstner(xzR, normalize(vec2( 1.0, 0.3)), 4.72, 0.055, 0.40); - totalDisp += g3.displacement; total_dpdx += g3.dPos_dx; total_dpdz += g3.dPos_dz; + GerstnerOut g3 = gerstner(xzR, normalize(vec2(1.0, 0.3)), 4.72, 0.055, 0.40); + totalDisp += g3.displacement; + total_dpdx += g3.dPos_dx; + total_dpdz += g3.dPos_dz; - GerstnerOut g4 = gerstner(xzR, normalize(vec2(-0.7, 1.0)), 2.62, 0.030, 0.28); - totalDisp += g4.displacement; total_dpdx += g4.dPos_dx; total_dpdz += g4.dPos_dz; + GerstnerOut g4 = gerstner(xzR, normalize(vec2(-0.7, 1.0)), 2.62, 0.030, 0.28); + totalDisp += g4.displacement; + total_dpdx += g4.dPos_dx; + total_dpdz += g4.dPos_dz; xzR = rot2(xzW, 2.123457); - GerstnerOut g5 = gerstner(xzR, normalize(vec2( 0.9, -0.6)), 1.62, 0.015, 0.18); - totalDisp += g5.displacement; total_dpdx += g5.dPos_dx; total_dpdz += g5.dPos_dz; + GerstnerOut g5 = gerstner(xzR, normalize(vec2(0.9, -0.6)), 1.62, 0.015, 0.18); + totalDisp += g5.displacement; + total_dpdx += g5.dPos_dx; + total_dpdz += g5.dPos_dz; - GerstnerOut g6 = gerstner(xzR, normalize(vec2(-1.0, -0.3)), 1.00, 0.008, 0.12); - totalDisp += g6.displacement; total_dpdx += g6.dPos_dx; total_dpdz += g6.dPos_dz; + GerstnerOut g6 = gerstner(xzR, normalize(vec2(-1.0, -0.3)), 1.00, 0.008, 0.12); + totalDisp += g6.displacement; + total_dpdx += g6.dPos_dx; + total_dpdz += g6.dPos_dz; vec3 pos = in_position + totalDisp; vec3 waveNormal = normalize(cross(total_dpdz, total_dpdx)); v_worldPos = vec3(u_model * vec4(pos, 1.0)); - v_normal = waveNormal; - v_color = in_color; + v_normal = waveNormal; + v_color = in_color; v_texCoord = in_texCoord; gl_Position = u_camMatrix * vec4(v_worldPos, 1.0); diff --git a/examples/opengl-experiments/include/Fire.h b/examples/opengl-experiments/include/Fire.h index 1fbd6aa..96dc280 100644 --- a/examples/opengl-experiments/include/Fire.h +++ b/examples/opengl-experiments/include/Fire.h @@ -6,7 +6,7 @@ using namespace WeirdEngine; class FireScene : public Scene3D { public: - FireScene(){}; + FireScene() {}; private: Shader m_flameShader; @@ -58,12 +58,9 @@ class FireScene : public Scene3D m_heatDistortionShader = Shader(SHADERS_PATH "3d/geometry.vert", ASSETS_PATH "fire/shaders/heatDistortion.frag"); + getLigths().push_back(Light{0, glm::vec3(0.0f), 0, glm::vec3(0.0f), glm::vec4(0.0f)}); getLigths().push_back( - Light{0, glm::vec3(0.0f), 0, glm::vec3(0.0f), glm::vec4(0.0f)} - ); - getLigths().push_back( - Light{1, glm::vec3(0.0f, 1.0f, 0.0f), 0, glm::vec3(0.0f), glm::vec4(1.0f, 0.95f, 0.9f, 2.0f)} - ); + Light{1, glm::vec3(0.0f, 1.0f, 0.0f), 0, glm::vec3(0.0f), glm::vec4(1.0f, 0.95f, 0.9f, 2.0f)}); // Load meshes // Quad geom @@ -309,7 +306,7 @@ class FireScene : public Scene3D m_renderPlane.draw(m_backgroundShader); -glEnable(GL_DEPTH_TEST); + glEnable(GL_DEPTH_TEST); glDepthMask(GL_TRUE); // Render stuff diff --git a/examples/opengl-experiments/include/Lines.h b/examples/opengl-experiments/include/Lines.h index 3cf82d7..b4ce3e7 100644 --- a/examples/opengl-experiments/include/Lines.h +++ b/examples/opengl-experiments/include/Lines.h @@ -8,7 +8,7 @@ using namespace WeirdEngine; class LinesScene : public Scene3D { public: - LinesScene(){}; + LinesScene() {}; private: uint16_t m_whiteMatId; @@ -26,7 +26,7 @@ class LinesScene : public Scene3D void onCreate() override { - + { auto& whiteMat = createMaterial(); m_whiteMatId = whiteMat.id; @@ -47,8 +47,7 @@ class LinesScene : public Scene3D m_lineTexture = new Texture(Display::rWidth, Display::rHeight, Texture::TextureType::Data); m_lineRender->bindColorTextureToFrameBuffer(*m_lineTexture); - m_combinationShader = - new Shader(SHADERS_PATH "common/screen_plane.vert", ASSETS_PATH "lines/combination.frag"); + m_combinationShader = new Shader(SHADERS_PATH "common/screen_plane.vert", ASSETS_PATH "lines/combination.frag"); } // Inherited via Scene diff --git a/examples/opengl-experiments/include/Water.h b/examples/opengl-experiments/include/Water.h index f77de2e..781cfdd 100644 --- a/examples/opengl-experiments/include/Water.h +++ b/examples/opengl-experiments/include/Water.h @@ -1,14 +1,14 @@ #pragma once -#include #include "WaterPlane.h" +#include using namespace WeirdEngine; class WaterScene : public Scene3D { public: - WaterScene(){}; + WaterScene() {}; private: Shader m_waterShader; @@ -18,10 +18,10 @@ class WaterScene : public Scene3D // Scene snapshot – taken each frame before the water draw to avoid // reading from and writing to the same framebuffer attachment. RenderTarget m_snapshotRender; - Texture m_snapshotColor; - Texture m_snapshotDepth; - int m_snapshotW = 0; - int m_snapshotH = 0; + Texture m_snapshotColor; + Texture m_snapshotDepth; + int m_snapshotW = 0; + int m_snapshotH = 0; WaterPlane m_waterPlane; @@ -33,8 +33,8 @@ class WaterScene : public Scene3D m_snapshotColor.dispose(); m_snapshotDepth.dispose(); } - m_snapshotColor = Texture(w, h, Texture::TextureType::Data); - m_snapshotDepth = Texture(w, h, Texture::TextureType::Depth); + m_snapshotColor = Texture(w, h, Texture::TextureType::Data); + m_snapshotDepth = Texture(w, h, Texture::TextureType::Depth); m_snapshotRender = RenderTarget(false); m_snapshotRender.bindColorTextureToFrameBuffer(m_snapshotColor); m_snapshotRender.bindDepthTextureToFrameBuffer(m_snapshotDepth); @@ -42,14 +42,12 @@ class WaterScene : public Scene3D m_snapshotH = h; } - // ------------------------------------------------------------------------- void onCreate() override { - m_waterShader = Shader(ASSETS_PATH "water/shaders/water.vert", - ASSETS_PATH "water/shaders/water.frag"); + m_waterShader = Shader(ASSETS_PATH "water/shaders/water.vert", ASSETS_PATH "water/shaders/water.frag"); getLigths().push_back(Light{0, glm::vec3(0.0f, 0.0f, 0.0f), 0, normalize(glm::vec3(0.0f, 0.4f, 1.0f)), glm::vec4(1.0f, 1.0f, 1.0f, 0.5f)}); @@ -102,7 +100,7 @@ class WaterScene : public Scene3D MeshRenderer& mr = ecs.addComponent(entity); auto id = m_resourceManager.getMeshId(ASSETS_PATH "monkey/demo.gltf", entity, true); mr.mesh = id; - + ecs.addComponent(entity); } @@ -120,31 +118,28 @@ class WaterScene : public Scene3D m_time += delta; - const auto& floatables = ecs.getComponentArray(); - for(int i = 0; i < floatables->getSize(); i++) + for (int i = 0; i < floatables->getSize(); i++) { auto& floatable = floatables->getDataAtIdx(i); // Keep the dot riding the water surface Transform& transform = ecs.getComponent(floatables->getEntityAtIdx(i)); - glm::vec2 flatPos = { transform.position.x, transform.position.z }; + glm::vec2 flatPos = {transform.position.x, transform.position.z}; float centerHeight = m_waterPlane.waterHeightAt(flatPos, m_time); transform.position.y = centerHeight; // Derive surface normal via central finite difference, then drift along it const float fdStep = 0.05f; float heightPlusX = m_waterPlane.waterHeightAt(flatPos + glm::vec2(fdStep, 0.0f), m_time); - float heightPlusZ = m_waterPlane.waterHeightAt(flatPos + glm::vec2(0.0f, fdStep), m_time); + float heightPlusZ = m_waterPlane.waterHeightAt(flatPos + glm::vec2(0.0f, fdStep), m_time); - glm::vec3 surfaceNormal = glm::normalize(glm::vec3(heightPlusX - centerHeight, fdStep, heightPlusZ - centerHeight)); + glm::vec3 surfaceNormal = + glm::normalize(glm::vec3(heightPlusX - centerHeight, fdStep, heightPlusZ - centerHeight)); transform.position.x += surfaceNormal.x * delta * floatable.buoyancy; transform.position.z += surfaceNormal.z * delta * floatable.buoyancy; } - - - } void onRender(WeirdRenderer::RenderTarget& renderTarget) override @@ -154,7 +149,6 @@ class WaterScene : public Scene3D auto& lights = getLigths(); - // ── Snapshot the current scene colour + depth ──────────────────────── // We need to read from these textures while drawing the water plane, // so we must copy them to separate textures first to avoid a feedback loop. @@ -180,28 +174,28 @@ class WaterScene : public Scene3D glDisable(GL_BLEND); m_waterShader.use(); - m_waterShader.setUniform("u_time", time); - m_waterShader.setUniform("u_camPos", sceneCamera.position); + m_waterShader.setUniform("u_time", time); + m_waterShader.setUniform("u_camPos", sceneCamera.position); m_waterShader.setUniform("u_camMatrix", sceneCamera.cameraMatrix); - m_waterShader.setUniform("u_near", sceneCamera.nearPlane); - m_waterShader.setUniform("u_far", sceneCamera.farPlane); + m_waterShader.setUniform("u_near", sceneCamera.nearPlane); + m_waterShader.setUniform("u_far", sceneCamera.farPlane); // Scene snapshot textures for underwater effects - m_waterShader.setUniform("u_sceneColor", 0); + m_waterShader.setUniform("u_sceneColor", 0); m_snapshotColor.bind(0); - m_waterShader.setUniform("u_sceneDepth", 1); + m_waterShader.setUniform("u_sceneDepth", 1); m_snapshotDepth.bind(1); - m_waterShader.setUniform("u_screenSize", glm::vec2((float)w, (float)h)); + m_waterShader.setUniform("u_screenSize", glm::vec2((float)w, (float)h)); int numLights = (std::min)((int)lights.size(), 8); m_waterShader.setUniform("u_numLights", numLights); for (int i = 0; i < numLights; i++) { std::string prefix = "u_lights[" + std::to_string(i) + "]."; - m_waterShader.setUniform(prefix + "position", lights[i].position); + m_waterShader.setUniform(prefix + "position", lights[i].position); m_waterShader.setUniform(prefix + "direction", lights[i].rotation); - m_waterShader.setUniform(prefix + "color", lights[i].color); - m_waterShader.setUniform(prefix + "type", (int)lights[i].type); + m_waterShader.setUniform(prefix + "color", lights[i].color); + m_waterShader.setUniform(prefix + "type", (int)lights[i].type); } glm::mat4 waterModel = glm::mat4(1.0f); diff --git a/examples/opengl-experiments/include/WaterPlane.h b/examples/opengl-experiments/include/WaterPlane.h index 256abda..d9577d3 100644 --- a/examples/opengl-experiments/include/WaterPlane.h +++ b/examples/opengl-experiments/include/WaterPlane.h @@ -1,8 +1,8 @@ #pragma once -#include #include #include +#include namespace WeirdEngine { @@ -17,9 +17,9 @@ namespace WeirdEngine void build() { - const int verts = GRID_SIZE + 1; - const float step = GRID_WORLD / static_cast(GRID_SIZE); - const float half = GRID_WORLD * 0.5f; + const int verts = GRID_SIZE + 1; + const float step = GRID_WORLD / static_cast(GRID_SIZE); + const float half = GRID_WORLD * 0.5f; std::vector vertices; vertices.reserve(static_cast(verts * verts)); @@ -30,10 +30,9 @@ namespace WeirdEngine { WaterVertex v{}; v.position = glm::vec3(x * step - half, 0.0f, z * step - half); - v.normal = glm::vec3(0.0f, 1.0f, 0.0f); - v.color = glm::vec3(1.0f); - v.texCoord = glm::vec2(static_cast(x) / GRID_SIZE, - static_cast(z) / GRID_SIZE); + v.normal = glm::vec3(0.0f, 1.0f, 0.0f); + v.color = glm::vec3(1.0f); + v.texCoord = glm::vec2(static_cast(x) / GRID_SIZE, static_cast(z) / GRID_SIZE); vertices.push_back(v); } } @@ -45,13 +44,17 @@ namespace WeirdEngine { for (int x = 0; x < GRID_SIZE; ++x) { - GLuint tl = static_cast( z * verts + x ); - GLuint tr = static_cast( z * verts + x + 1); - GLuint bl = static_cast((z + 1) * verts + x ); + GLuint tl = static_cast(z * verts + x); + GLuint tr = static_cast(z * verts + x + 1); + GLuint bl = static_cast((z + 1) * verts + x); GLuint br = static_cast((z + 1) * verts + x + 1); - indices.push_back(tl); indices.push_back(bl); indices.push_back(tr); - indices.push_back(tr); indices.push_back(bl); indices.push_back(br); + indices.push_back(tl); + indices.push_back(bl); + indices.push_back(tr); + indices.push_back(tr); + indices.push_back(bl); + indices.push_back(br); } } @@ -64,13 +67,11 @@ namespace WeirdEngine glBindVertexArray(m_waterVAO); glBindBuffer(GL_ARRAY_BUFFER, m_waterVBO); - glBufferData(GL_ARRAY_BUFFER, - static_cast(vertices.size() * sizeof(WaterVertex)), + glBufferData(GL_ARRAY_BUFFER, static_cast(vertices.size() * sizeof(WaterVertex)), vertices.data(), GL_STATIC_DRAW); glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, m_waterEBO); - glBufferData(GL_ELEMENT_ARRAY_BUFFER, - static_cast(indices.size() * sizeof(GLuint)), + glBufferData(GL_ELEMENT_ARRAY_BUFFER, static_cast(indices.size() * sizeof(GLuint)), indices.data(), GL_STATIC_DRAW); // layout(location = 0) in vec3 in_position @@ -98,9 +99,21 @@ namespace WeirdEngine void free() { - if (m_waterVAO) { glDeleteVertexArrays(1, &m_waterVAO); m_waterVAO = 0; } - if (m_waterVBO) { glDeleteBuffers(1, &m_waterVBO); m_waterVBO = 0; } - if (m_waterEBO) { glDeleteBuffers(1, &m_waterEBO); m_waterEBO = 0; } + if (m_waterVAO) + { + glDeleteVertexArrays(1, &m_waterVAO); + m_waterVAO = 0; + } + if (m_waterVBO) + { + glDeleteBuffers(1, &m_waterVBO); + m_waterVBO = 0; + } + if (m_waterEBO) + { + glDeleteBuffers(1, &m_waterEBO); + m_waterEBO = 0; + } } void draw(WeirdRenderer::Shader& shader, const glm::mat4& model) @@ -114,8 +127,7 @@ namespace WeirdEngine static glm::vec2 rot2(glm::vec2 p, float a) { - return { p.x * cosf(a) - p.y * sinf(a), - p.x * sinf(a) + p.y * cosf(a) }; + return {p.x * cosf(a) - p.y * sinf(a), p.x * sinf(a) + p.y * cosf(a)}; } static float gerstnerY(glm::vec2 xz, glm::vec2 dir, float wavelength, float amplitude, float t) @@ -128,25 +140,23 @@ namespace WeirdEngine float waterHeightAt(glm::vec2 xz, float t) const { // Domain warp (matches shader) - glm::vec2 warp = { - sinf(xz.x * 0.1731f + xz.y * 0.0893f + t * 0.071f) * 1.6f - + cosf(xz.x * 0.2473f - xz.y * 0.1337f + t * 0.043f) * 0.9f, - cosf(xz.x * 0.0971f + xz.y * 0.2011f + t * 0.059f) * 1.4f - + sinf(xz.x * 0.1619f - xz.y * 0.3001f + t * 0.037f) * 0.7f - }; + glm::vec2 warp = {sinf(xz.x * 0.1731f + xz.y * 0.0893f + t * 0.071f) * 1.6f + + cosf(xz.x * 0.2473f - xz.y * 0.1337f + t * 0.043f) * 0.9f, + cosf(xz.x * 0.0971f + xz.y * 0.2011f + t * 0.059f) * 1.4f + + sinf(xz.x * 0.1619f - xz.y * 0.3001f + t * 0.037f) * 0.7f}; glm::vec2 xzW = xz + warp; glm::vec2 xzR = rot2(xzW, 1.41421356f); float y = 0.0f; // Cascade A - y += gerstnerY(xzW, glm::normalize(glm::vec2( 1.0f, 0.4f)), 8.09f, 0.110f, t); - y += gerstnerY(xzW, glm::normalize(glm::vec2(-0.5f, 1.0f)), 5.00f, 0.075f, t); - y += gerstnerY(xzW, glm::normalize(glm::vec2( 0.4f, -1.0f)), 3.09f, 0.040f, t); + y += gerstnerY(xzW, glm::normalize(glm::vec2(1.0f, 0.4f)), 8.09f, 0.110f, t); + y += gerstnerY(xzW, glm::normalize(glm::vec2(-0.5f, 1.0f)), 5.00f, 0.075f, t); + y += gerstnerY(xzW, glm::normalize(glm::vec2(0.4f, -1.0f)), 3.09f, 0.040f, t); // Cascade B (rotated frame) - y += gerstnerY(xzR, glm::normalize(glm::vec2( 1.0f, 0.3f)), 4.72f, 0.055f, t); - y += gerstnerY(xzR, glm::normalize(glm::vec2(-0.7f, 1.0f)), 2.62f, 0.030f, t); - y += gerstnerY(xzR, glm::normalize(glm::vec2( 0.9f, -0.6f)), 1.62f, 0.015f, t); - y += gerstnerY(xzR, glm::normalize(glm::vec2(-1.0f, -0.3f)), 1.00f, 0.008f, t); + y += gerstnerY(xzR, glm::normalize(glm::vec2(1.0f, 0.3f)), 4.72f, 0.055f, t); + y += gerstnerY(xzR, glm::normalize(glm::vec2(-0.7f, 1.0f)), 2.62f, 0.030f, t); + y += gerstnerY(xzR, glm::normalize(glm::vec2(0.9f, -0.6f)), 1.62f, 0.015f, t); + y += gerstnerY(xzR, glm::normalize(glm::vec2(-1.0f, -0.3f)), 1.00f, 0.008f, t); return y; } @@ -164,7 +174,7 @@ namespace WeirdEngine GLuint m_waterEBO = 0; GLsizei m_waterIndexCount = 0; - static constexpr int GRID_SIZE = 512; + static constexpr int GRID_SIZE = 512; static constexpr float GRID_WORLD = 200.0f; }; -} +} // namespace WeirdEngine diff --git a/examples/opengl-experiments/src/main.cpp b/examples/opengl-experiments/src/main.cpp index 097d158..2c90ee3 100644 --- a/examples/opengl-experiments/src/main.cpp +++ b/examples/opengl-experiments/src/main.cpp @@ -31,8 +31,6 @@ int main(int argc, char* argv[]) displaySettings.colorPalette[DisplaySettings::Orange].a = 1.0f; - - PhysicsSettings physicsSettings{}; AudioSettings audioSettings{}; diff --git a/examples/sample-scenes/include/AquariumScene.h b/examples/sample-scenes/include/AquariumScene.h index fb35179..aaf604e 100644 --- a/examples/sample-scenes/include/AquariumScene.h +++ b/examples/sample-scenes/include/AquariumScene.h @@ -379,9 +379,8 @@ class AquariumScene : public Scene2D ecs.destroyEntity(foodEntity); Entity lastSeg = eel.segments.back(); - Entity prevSeg = eel.segments.size() > 1 - ? eel.segments[eel.segments.size() - 2] - : eel.segments[0]; + Entity prevSeg = + eel.segments.size() > 1 ? eel.segments[eel.segments.size() - 2] : eel.segments[0]; auto& lastT = transformArray->getDataFromEntity(lastSeg); auto& prevT = transformArray->getDataFromEntity(prevSeg); @@ -398,8 +397,8 @@ class AquariumScene : public Scene2D lastT.position.y + tailDir.y * eel.segmentSpacing, 0.0f); auto& nd = ecs.addComponent(newSeg); - nd.materialId = static_cast(eel.baseMaterial + - static_cast(eel.segments.size() % 4)); + nd.materialId = + static_cast(eel.baseMaterial + static_cast(eel.segments.size() % 4)); ecs.addComponent(newSeg); @@ -610,8 +609,8 @@ class AquariumScene : public Scene2D if (length(cohesion) > 0.001f) cohesion = normalize(cohesion) * fd.maxSpeed - fd.velocity; - boidsForce = separation * fd.separationWeight + alignment * fd.alignmentWeight + - cohesion * fd.cohesionWeight; + boidsForce = + separation * fd.separationWeight + alignment * fd.alignmentWeight + cohesion * fd.cohesionWeight; } if (seekingMate && closestMateDistSq > 0.000001f && closestMateDistSq < MATE_RADIUS * MATE_RADIUS) diff --git a/examples/sample-scenes/include/CollisionHandling.h b/examples/sample-scenes/include/CollisionHandling.h index 47998d9..f8c797e 100644 --- a/examples/sample-scenes/include/CollisionHandling.h +++ b/examples/sample-scenes/include/CollisionHandling.h @@ -8,7 +8,7 @@ using namespace WeirdEngine; class CollisionHandlingScene : public Scene2D { public: - CollisionHandlingScene(){}; + CollisionHandlingScene() {}; private: // Inherited via Scene diff --git a/examples/sample-scenes/include/DestroyScene.h b/examples/sample-scenes/include/DestroyScene.h index ee4bbe7..731b274 100644 --- a/examples/sample-scenes/include/DestroyScene.h +++ b/examples/sample-scenes/include/DestroyScene.h @@ -1,7 +1,7 @@ #pragma once -#include #include +#include #include "globals.h" #include "weird-physics/components/DistanceConstraint.h" @@ -52,101 +52,101 @@ class DestroyScene : public Scene2D switch (action) { - case 0: - { - if (m_testBalls.size() < 1000) + case 0: { - for (int j = 0; j < 10; ++j) + if (m_testBalls.size() < 1000) { - Entity e = ecs.createEntity(); - auto& t = ecs.addComponent(e); - t.position = vec3((std::rand() % 200) - 100.0f, (std::rand() % 100) - 50.0f, 0.0f); - ecs.setComponentDirty(t); - auto& ui = ecs.addComponent(e); - ui.materialId = 4 + (e % 12); - auto& rb = ecs.addComponent(e); - m_testBalls.push_back(e); + for (int j = 0; j < 10; ++j) + { + Entity e = ecs.createEntity(); + auto& t = ecs.addComponent(e); + t.position = vec3((std::rand() % 200) - 100.0f, (std::rand() % 100) - 50.0f, 0.0f); + ecs.setComponentDirty(t); + auto& ui = ecs.addComponent(e); + ui.materialId = 4 + (e % 12); + auto& rb = ecs.addComponent(e); + m_testBalls.push_back(e); + } } + break; } - break; - } - case 1: - { - if (m_testShapes.size() < 20) + case 1: { - float x = (std::rand() % 200) - 100.0f; - float y = (std::rand() % 100) - 50.0f; - float w = (float)(std::rand() % 4 + 1); - float h = (float)(std::rand() % 4 + 1); - float variables[8]{w, y, x, h, 0.0f, 0.0f, 0.0f, 0.0f}; - uint16_t material = std::rand() % 16; - Entity shape = addShape(DefaultShapes::BOX, variables, material, CombinationType::Addition); - m_testShapes.push_back(shape); + if (m_testShapes.size() < 20) + { + float x = (std::rand() % 200) - 100.0f; + float y = (std::rand() % 100) - 50.0f; + float w = (float)(std::rand() % 4 + 1); + float h = (float)(std::rand() % 4 + 1); + float variables[8]{w, y, x, h, 0.0f, 0.0f, 0.0f, 0.0f}; + uint16_t material = std::rand() % 16; + Entity shape = addShape(DefaultShapes::BOX, variables, material, CombinationType::Addition); + m_testShapes.push_back(shape); + } + break; } - break; - } - case 2: - { - if (m_testBalls.size() >= 2 && m_testConstraints.size() < 50) + case 2: { - int idx1 = std::rand() % m_testBalls.size(); - int idx2 = std::rand() % m_testBalls.size(); - if (idx1 != idx2) + if (m_testBalls.size() >= 2 && m_testConstraints.size() < 50) { - Entity constraintEnt = ecs.createEntity(); - if (std::rand() % 2 == 0) + int idx1 = std::rand() % m_testBalls.size(); + int idx2 = std::rand() % m_testBalls.size(); + if (idx1 != idx2) { - auto& constraint = ecs.addComponent(constraintEnt); - constraint.entityA = m_testBalls[idx1]; - constraint.entityB = m_testBalls[idx2]; - constraint.distance = 3.0f + (std::rand() % 5); + Entity constraintEnt = ecs.createEntity(); + if (std::rand() % 2 == 0) + { + auto& constraint = ecs.addComponent(constraintEnt); + constraint.entityA = m_testBalls[idx1]; + constraint.entityB = m_testBalls[idx2]; + constraint.distance = 3.0f + (std::rand() % 5); + } + else + { + auto& spring = ecs.addComponent(constraintEnt); + spring.entityA = m_testBalls[idx1]; + spring.entityB = m_testBalls[idx2]; + spring.restDistance = 3.0f + (std::rand() % 5); + spring.stiffness = 5.0f; + } + m_testConstraints.push_back(constraintEnt); } - else - { - auto& spring = ecs.addComponent(constraintEnt); - spring.entityA = m_testBalls[idx1]; - spring.entityB = m_testBalls[idx2]; - spring.restDistance = 3.0f + (std::rand() % 5); - spring.stiffness = 5.0f; - } - m_testConstraints.push_back(constraintEnt); } + break; } - break; - } - case 3: - { - if (!m_testShapes.empty()) + case 3: { - int idx = std::rand() % m_testShapes.size(); - ecs.destroyEntity(m_testShapes[idx]); - m_testShapes[idx] = m_testShapes.back(); - m_testShapes.pop_back(); + if (!m_testShapes.empty()) + { + int idx = std::rand() % m_testShapes.size(); + ecs.destroyEntity(m_testShapes[idx]); + m_testShapes[idx] = m_testShapes.back(); + m_testShapes.pop_back(); + } + break; } - break; - } - case 4: - { - if (!m_testBalls.empty()) + case 4: { - int idx = std::rand() % m_testBalls.size(); - ecs.destroyEntity(m_testBalls[idx]); - m_testBalls[idx] = m_testBalls.back(); - m_testBalls.pop_back(); + if (!m_testBalls.empty()) + { + int idx = std::rand() % m_testBalls.size(); + ecs.destroyEntity(m_testBalls[idx]); + m_testBalls[idx] = m_testBalls.back(); + m_testBalls.pop_back(); + } + break; } - break; - } - case 5: - { - if (!m_testConstraints.empty()) + case 5: { - int idx = std::rand() % m_testConstraints.size(); - ecs.destroyEntity(m_testConstraints[idx]); - m_testConstraints[idx] = m_testConstraints.back(); - m_testConstraints.pop_back(); + if (!m_testConstraints.empty()) + { + int idx = std::rand() % m_testConstraints.size(); + ecs.destroyEntity(m_testConstraints[idx]); + m_testConstraints[idx] = m_testConstraints.back(); + m_testConstraints.pop_back(); + } + break; } - break; - } } } } @@ -154,7 +154,8 @@ class DestroyScene : public Scene2D void onEntityCollision(ECSManager& ecs, WeirdEngine::EntityCollisionEvent& event) override { - if (std::rand() % 5 != 0) return; + if (std::rand() % 5 != 0) + return; Entity a = event.entityA; @@ -164,7 +165,7 @@ class DestroyScene : public Scene2D ecs.addComponent(a); ecs.getComponent(a).collisionCount++; } - + playSound({0.02f, 400.0f + (std::rand() % 200), false, vec3(0.0f), 1}); } diff --git a/examples/sample-scenes/include/ImageScene.h b/examples/sample-scenes/include/ImageScene.h index ae8ec5d..d1b59c0 100644 --- a/examples/sample-scenes/include/ImageScene.h +++ b/examples/sample-scenes/include/ImageScene.h @@ -10,7 +10,7 @@ using namespace WeirdEngine; class ImageScene : public Scene2D { public: - ImageScene(){}; + ImageScene() {}; private: std::string binaryString; diff --git a/examples/sample-scenes/include/LifeScene.h b/examples/sample-scenes/include/LifeScene.h index 693d513..e82ef9a 100644 --- a/examples/sample-scenes/include/LifeScene.h +++ b/examples/sample-scenes/include/LifeScene.h @@ -4,8 +4,8 @@ #include -#include #include "weird-physics/components/GlobalPhysicsSettings.h" +#include #include "globals.h" @@ -23,7 +23,7 @@ struct Head class LifeScene : public Scene2D { public: - LifeScene(){}; + LifeScene() {}; private: // Inherited via Scene @@ -86,8 +86,8 @@ class LifeScene : public Scene2D } } - ecs.getComponent(m_mainCamera).position = g_cameraPositon; - } + ecs.getComponent(m_mainCamera).position = g_cameraPositon; + } void onUpdate(float delta, ECSManager& ecs) override { diff --git a/examples/sample-scenes/include/MouseCollisionScene.h b/examples/sample-scenes/include/MouseCollisionScene.h index 93fe776..a21ce91 100644 --- a/examples/sample-scenes/include/MouseCollisionScene.h +++ b/examples/sample-scenes/include/MouseCollisionScene.h @@ -8,7 +8,7 @@ using namespace WeirdEngine; class MouseCollisionScene : public Scene2D { public: - MouseCollisionScene(){}; + MouseCollisionScene() {}; private: Entity m_cursorShape; diff --git a/examples/sample-scenes/include/RopeScene.h b/examples/sample-scenes/include/RopeScene.h index 431ca49..055a2da 100644 --- a/examples/sample-scenes/include/RopeScene.h +++ b/examples/sample-scenes/include/RopeScene.h @@ -10,8 +10,7 @@ using namespace WeirdEngine; class RopeScene : public Scene2D { public: - RopeScene(){ - } + RopeScene() {} private: Entity m_star = INVALID_ENTITY; @@ -161,9 +160,10 @@ class RopeScene : public Scene2D } // Animate custom shape over time - if(m_star != INVALID_ENTITY) + if (m_star != INVALID_ENTITY) { - // Instead of getSimulation().getSimulationTime(), we can just use getTime() if Scene provides it, or track delta. + // Instead of getSimulation().getSimulationTime(), we can just use getTime() if Scene provides it, or track + // delta. static float animTime = 0.0f; animTime += delta; auto& cs = ecs.getComponent(m_star); @@ -239,7 +239,7 @@ class RopeScene : public Scene2D [&](Entity e, RigidBody2D& rb, Transform& t) { vec2 force(0, -0.001f * (t.position.y * t.position.y)); - force.x += t.position.x < 0.0f ? - t.position.x : 0.0f; + force.x += t.position.x < 0.0f ? -t.position.x : 0.0f; force.x -= t.position.x > 30.0f ? t.position.x - 30.0f : 0.0f; force.x = 10.0f / delta * glm::clamp(force.x, -1.0f, 1.0f); diff --git a/examples/sample-scenes/include/ShapesCombinations.h b/examples/sample-scenes/include/ShapesCombinations.h index 34f07cd..f04a5a3 100644 --- a/examples/sample-scenes/include/ShapesCombinations.h +++ b/examples/sample-scenes/include/ShapesCombinations.h @@ -11,8 +11,7 @@ using namespace WeirdEngine; class ShapeCombinatiosScene : public Scene2D { public: - ShapeCombinatiosScene(){ - } + ShapeCombinatiosScene() {} private: Entity m_circle = INVALID_ENTITY; @@ -116,7 +115,7 @@ class ShapeCombinatiosScene : public Scene2D float halfHeight = Display::height / 2.0f; m_initialMousePositionInWorld = - ECS::Camera::screenPositionToWorldPosition2D(cameraTransform, vec2(halfWidth, halfHeight)); + ECS::Camera::screenPositionToWorldPosition2D(cameraTransform, vec2(halfWidth, halfHeight)); } if (Input::GetMouseButton(Input::RightClick)) diff --git a/examples/sample-scenes/include/WalkScene.h b/examples/sample-scenes/include/WalkScene.h index ffe0aa4..d485ed9 100644 --- a/examples/sample-scenes/include/WalkScene.h +++ b/examples/sample-scenes/include/WalkScene.h @@ -24,10 +24,9 @@ struct Foot class WalkScene : public Scene2D { public: - WalkScene(){}; + WalkScene() {}; private: - Entity m_head; // Inherited via Scene @@ -61,9 +60,9 @@ class WalkScene : public Scene2D m_head = tags["head"]; - float boundsVars2[8]{0.0f, -24.0f, 200.0f, 20.0f}; - Entity inside = addShape(DefaultShapes::BOX, boundsVars2, DisplaySettings::LightGreen, CombinationType::Addition); + Entity inside = + addShape(DefaultShapes::BOX, boundsVars2, DisplaySettings::LightGreen, CombinationType::Addition); ecs.getComponent(m_mainCamera).position = g_cameraPositon; @@ -97,9 +96,9 @@ class WalkScene : public Scene2D auto& foot = componentArray->getDataAtIdx(i); auto& rb = rigidBodies->getDataFromEntity(componentArray->getEntityAtIdx(i)); - if(i != m_currentFoot) + if (i != m_currentFoot) { - if(foot.onFloor) + if (foot.onFloor) { rb.isFixed = true; ecs.setComponentDirty(rb); @@ -152,7 +151,7 @@ class WalkScene : public Scene2D f = (foot.direction + vec2(0.0f, -10.0f * foot.t)) * foot.forceMagnitude * foot.t; } - if(m_feetTouching) + if (m_feetTouching) f.x = 0.0f; rb.pendingImpulseForce += f; @@ -164,7 +163,7 @@ class WalkScene : public Scene2D } } } - + m_feetTouching = false; } diff --git a/include/weird-engine.h b/include/weird-engine.h index bdbfbf4..6cb2249 100644 --- a/include/weird-engine.h +++ b/include/weird-engine.h @@ -15,8 +15,8 @@ #endif #include "weird-engine/Input.h" -#include "weird-engine/Profiler.h" #include "weird-engine/Logger.h" +#include "weird-engine/Profiler.h" #include "weird-engine/SceneManager.h" #include "weird-renderer/core/Renderer.h" #include "weird-renderer/core/SDLInitializer.h" @@ -40,7 +40,6 @@ extern "C" #define SHADERS_PATH #endif // !SHADERS_PATH - #include "weird-physics/PhysicsSettings.h" #include "weird-renderer/audio/AudioEngine.h" #include "weird-renderer/audio/AudioSettings.h" @@ -82,7 +81,8 @@ namespace WeirdEngine inline void runFrame(RuntimeContext& ctx) { // Measure time - ctx.time = static_cast(SDL_GetPerformanceCounter()) / static_cast(SDL_GetPerformanceFrequency()); + ctx.time = + static_cast(SDL_GetPerformanceCounter()) / static_cast(SDL_GetPerformanceFrequency()); ctx.delta = ctx.time - ctx.prevTime; ctx.timeDiff += ctx.delta; ctx.prevTime = ctx.time; @@ -111,8 +111,8 @@ namespace WeirdEngine ctx.totalFrames++; if (ctx.totalFrames % 120 == 0) { - std::cout << "[WeirdEngine] frame " << ctx.totalFrames - << " (t=" << (ctx.time - ctx.startTime) << "s)" << std::endl; + std::cout << "[WeirdEngine] frame " << ctx.totalFrames << " (t=" << (ctx.time - ctx.startTime) << "s)" + << std::endl; } if (ctx.autoQuitAt > 0.0 && ctx.time >= ctx.autoQuitAt) { @@ -139,14 +139,14 @@ namespace WeirdEngine Input::suppressKeyboardInput(); } #endif - + SDL_Event event; while (SDL_PollEvent(&event)) { #ifndef WEIRD_DISABLE_IMGUI ImGui_ImplSDL3_ProcessEvent(&event); #endif - + if (event.type == SDL_EVENT_QUIT) { ctx.quit = true; @@ -155,9 +155,10 @@ namespace WeirdEngine { int newWidth = event.window.data1; int newHeight = event.window.data2; - - WeirdEngine::Logger::log("Window resized to: " + std::to_string(newWidth) + "x" + std::to_string(newHeight)); - + + WeirdEngine::Logger::log("Window resized to: " + std::to_string(newWidth) + "x" + + std::to_string(newHeight)); + ctx.renderer.setWindowSize(newWidth, newHeight); newResolution = true; } @@ -259,16 +260,14 @@ namespace WeirdEngine if (arg == "--fullscreen" || arg == "-f") { displaySettings.fullscreen = true; - }else if ((arg == "--scene" || arg == "-s") && i + 1 < argc) + } + else if ((arg == "--scene" || arg == "-s") && i + 1 < argc) { startupScene = argv[++i]; // Get the next argument as the scene name WeirdEngine::Logger::log("Startup scene set to: " + startupScene); } } - - - sceneManager.setPhysicsSettings(physicsSettings); AudioEngine& audioEngine = AudioEngine::getInstance(); @@ -277,11 +276,12 @@ namespace WeirdEngine #ifdef __EMSCRIPTEN__ // In Emscripten, allocate all resources on the heap to prevent stack unwinding issues Detail::g_emscriptenEnv = new Detail::EmscriptenRuntimeEnvironment(); - + // Create SDLInitializer and Renderer on the heap try { - Detail::g_emscriptenEnv->sdlInitializer = new SDLInitializer(displaySettings, Detail::g_windowHandle, audioEngine); + Detail::g_emscriptenEnv->sdlInitializer = + new SDLInitializer(displaySettings, Detail::g_windowHandle, audioEngine); Detail::g_emscriptenEnv->renderer = new Renderer(displaySettings, Detail::g_windowHandle); } catch (...) @@ -311,12 +311,10 @@ namespace WeirdEngine } // Time - create RuntimeContext with references to heap-allocated objects - Detail::g_emscriptenEnv->runtimeContext = new Detail::RuntimeContext{ - sceneManager, - *Detail::g_emscriptenEnv->renderer, - audioEngine - }; - Detail::g_emscriptenEnv->runtimeContext->time = static_cast(SDL_GetPerformanceCounter()) / static_cast(SDL_GetPerformanceFrequency()); + Detail::g_emscriptenEnv->runtimeContext = + new Detail::RuntimeContext{sceneManager, *Detail::g_emscriptenEnv->renderer, audioEngine}; + Detail::g_emscriptenEnv->runtimeContext->time = + static_cast(SDL_GetPerformanceCounter()) / static_cast(SDL_GetPerformanceFrequency()); Detail::g_emscriptenEnv->runtimeContext->prevTime = Detail::g_emscriptenEnv->runtimeContext->time; #ifdef WEIRD_TEST_HOOKS Detail::g_emscriptenEnv->runtimeContext->startTime = Detail::g_emscriptenEnv->runtimeContext->time; @@ -339,7 +337,8 @@ namespace WeirdEngine // Time Detail::RuntimeContext runtimeContext{sceneManager, renderer, audioEngine}; - runtimeContext.time = static_cast(SDL_GetPerformanceCounter()) / static_cast(SDL_GetPerformanceFrequency()); + runtimeContext.time = + static_cast(SDL_GetPerformanceCounter()) / static_cast(SDL_GetPerformanceFrequency()); runtimeContext.prevTime = runtimeContext.time; #ifdef WEIRD_TEST_HOOKS runtimeContext.startTime = runtimeContext.time; diff --git a/include/weird-engine/Background.h b/include/weird-engine/Background.h index ac97636..729d1e4 100644 --- a/include/weird-engine/Background.h +++ b/include/weird-engine/Background.h @@ -5,22 +5,24 @@ namespace WeirdEngine { - enum class BackgroundType { - Solid, - Grid, - Sky, - Custom - }; + enum class BackgroundType + { + Solid, + Grid, + Sky, + Custom + }; - struct BackgroundParams { - BackgroundType type = BackgroundType::Grid; - - glm::vec4 primaryColor{0.7f, 0.7f, 0.71f, 1.0f}; - glm::vec4 secondaryColor{0.55f, 0.55f, 0.58f, 1.0f}; - float scale = 1.0f; - float intensity = 1.0f; - bool isDirty = true; + struct BackgroundParams + { + BackgroundType type = BackgroundType::Grid; - std::string customShaderCode = ""; - }; -} + glm::vec4 primaryColor{0.7f, 0.7f, 0.71f, 1.0f}; + glm::vec4 secondaryColor{0.55f, 0.55f, 0.58f, 1.0f}; + float scale = 1.0f; + float intensity = 1.0f; + bool isDirty = true; + + std::string customShaderCode = ""; + }; +} // namespace WeirdEngine diff --git a/include/weird-engine/Input.h b/include/weird-engine/Input.h index 59bf1c5..dd7763f 100644 --- a/include/weird-engine/Input.h +++ b/include/weird-engine/Input.h @@ -1,13 +1,13 @@ #pragma once +#include #include #include #include -#include -#include -#include "weird-renderer/core/Display.h" #include "weird-engine/Logger.h" +#include "weird-renderer/core/Display.h" +#include /// /// Stores the state of every key in the keyboard and mouse. @@ -66,7 +66,8 @@ namespace WeirdEngine delete[] m_gamepadAxisTable; for (auto pad : m_gamepads) { - if (pad) SDL_CloseGamepad(pad); + if (pad) + SDL_CloseGamepad(pad); } } @@ -273,11 +274,11 @@ namespace WeirdEngine auto& instance = getInstance(); for (int i = 0; i < 5; ++i) { - if (instance.m_mouseKeysTable[i] > NOT_PRESSED) // IS_PRESSED or FIRST_PRESSED - instance.m_mouseKeysTable[i] = RELEASED_THIS_FRAME; // fire key-up + if (instance.m_mouseKeysTable[i] > NOT_PRESSED) // IS_PRESSED or FIRST_PRESSED + instance.m_mouseKeysTable[i] = RELEASED_THIS_FRAME; // fire key-up else if (instance.m_mouseKeysTable[i] == RELEASED_THIS_FRAME) - instance.m_mouseKeysTable[i] = NOT_PRESSED; // clear existing key-up - // NOT_PRESSED stays NOT_PRESSED — no spurious key-ups + instance.m_mouseKeysTable[i] = NOT_PRESSED; // clear existing key-up + // NOT_PRESSED stays NOT_PRESSED — no spurious key-ups } } @@ -286,11 +287,11 @@ namespace WeirdEngine auto& instance = getInstance(); for (int i = 0; i < SDL_SCANCODE_COUNT; ++i) { - if (instance.m_keyTable[i] > NOT_PRESSED) // IS_PRESSED or FIRST_PRESSED - instance.m_keyTable[i] = RELEASED_THIS_FRAME; // fire key-up + if (instance.m_keyTable[i] > NOT_PRESSED) // IS_PRESSED or FIRST_PRESSED + instance.m_keyTable[i] = RELEASED_THIS_FRAME; // fire key-up else if (instance.m_keyTable[i] == RELEASED_THIS_FRAME) - instance.m_keyTable[i] = NOT_PRESSED; // clear existing key-up - // NOT_PRESSED stays NOT_PRESSED — no spurious key-ups + instance.m_keyTable[i] = NOT_PRESSED; // clear existing key-up + // NOT_PRESSED stays NOT_PRESSED — no spurious key-ups } } @@ -321,8 +322,8 @@ namespace WeirdEngine enum GamepadButton { South = SDL_GAMEPAD_BUTTON_SOUTH, // A - East = SDL_GAMEPAD_BUTTON_EAST, // B - West = SDL_GAMEPAD_BUTTON_WEST, // X + East = SDL_GAMEPAD_BUTTON_EAST, // B + West = SDL_GAMEPAD_BUTTON_WEST, // X North = SDL_GAMEPAD_BUTTON_NORTH, // Y Back = SDL_GAMEPAD_BUTTON_BACK, Guide = SDL_GAMEPAD_BUTTON_GUIDE, @@ -418,9 +419,8 @@ namespace WeirdEngine SDL_GUIDToString(SDL_GetGamepadGUIDForID(id), guid, sizeof(guid)); const char* mapping = SDL_GetGamepadMapping(pad); - Logger::log("Gamepad connected: " + std::string(name ? name : "Unknown") - + " [GUID: " + std::string(guid) + "]" - + " mapping: " + std::string(mapping ? mapping : "(none)")); + Logger::log("Gamepad connected: " + std::string(name ? name : "Unknown") + " [GUID: " + + std::string(guid) + "]" + " mapping: " + std::string(mapping ? mapping : "(none)")); } break; } diff --git a/include/weird-engine/Logger.h b/include/weird-engine/Logger.h index e1a622b..10bb818 100644 --- a/include/weird-engine/Logger.h +++ b/include/weird-engine/Logger.h @@ -1,36 +1,36 @@ #pragma once +#include #include #include -#include namespace WeirdEngine { - enum class LogLevel - { - Info, - Warning, - Error - }; + enum class LogLevel + { + Info, + Warning, + Error + }; - struct LogMessage - { - LogLevel level; - std::string message; - }; + struct LogMessage + { + LogLevel level; + std::string message; + }; - class Logger - { - public: - static void log(const std::string& message); - static void warning(const std::string& message); - static void error(const std::string& message); + class Logger + { + public: + static void log(const std::string& message); + static void warning(const std::string& message); + static void error(const std::string& message); - static bool s_enableConsoleOutput; - static void drawImGuiConsole(); + static bool s_enableConsoleOutput; + static void drawImGuiConsole(); - private: - static std::vector s_messages; - static std::mutex s_mutex; - }; -} + private: + static std::vector s_messages; + static std::mutex s_mutex; + }; +} // namespace WeirdEngine diff --git a/include/weird-engine/Material3D.h b/include/weird-engine/Material3D.h index 1381920..1a4384c 100644 --- a/include/weird-engine/Material3D.h +++ b/include/weird-engine/Material3D.h @@ -21,4 +21,4 @@ namespace WeirdEngine MaterialPattern pattern = MaterialPattern::None; float patternScale = 1.0f; }; -} +} // namespace WeirdEngine diff --git a/include/weird-engine/Profiler.h b/include/weird-engine/Profiler.h index ccf4dee..a64e5e1 100644 --- a/include/weird-engine/Profiler.h +++ b/include/weird-engine/Profiler.h @@ -1,13 +1,13 @@ #pragma once +#include "weird-engine/Logger.h" #include +#include +#include #include #include +#include #include #include -#include -#include -#include -#include "weird-engine/Logger.h" namespace WeirdEngine { @@ -56,13 +56,22 @@ namespace WeirdEngine m_pendingRealtimeEnable = false; } - bool isRealtime() const { return m_realtimeMode; } + bool isRealtime() const + { + return m_realtimeMode; + } - double getUnaccountedThreshold() const { return m_unaccountedThresholdPct; } - void setUnaccountedThreshold(double threshold) { m_unaccountedThresholdPct = threshold; } + double getUnaccountedThreshold() const + { + return m_unaccountedThresholdPct; + } + void setUnaccountedThreshold(double threshold) + { + m_unaccountedThresholdPct = threshold; + } - const std::vector& getLastFrameStats() const - { + const std::vector& getLastFrameStats() const + { if (m_paused && m_historyEnabled && !m_historyBuffer.empty()) { if (m_playbackIndex >= 0 && m_playbackIndex < m_historyBuffer.size()) @@ -70,7 +79,7 @@ namespace WeirdEngine return m_historyBuffer[m_playbackIndex]; } } - return m_lastFrameStats; + return m_lastFrameStats; } void setHistoryEnabled(bool enabled) @@ -85,16 +94,40 @@ namespace WeirdEngine } } } - bool isHistoryEnabled() const { return m_historyEnabled; } - int getHistoryCapturedCount() const { return (int)m_historyBuffer.size(); } - int getHistoryCapacity() const { return m_historyCapacity; } + bool isHistoryEnabled() const + { + return m_historyEnabled; + } + int getHistoryCapturedCount() const + { + return (int)m_historyBuffer.size(); + } + int getHistoryCapacity() const + { + return m_historyCapacity; + } - void pause() { m_pendingPause = true; } - void resume() { m_pendingResume = true; } - bool isPaused() const { return m_paused; } + void pause() + { + m_pendingPause = true; + } + void resume() + { + m_pendingResume = true; + } + bool isPaused() const + { + return m_paused; + } - int getPlaybackIndex() const { return m_playbackIndex; } - void setPlaybackIndex(int idx) { m_playbackIndex = idx; } + int getPlaybackIndex() const + { + return m_playbackIndex; + } + void setPlaybackIndex(int idx) + { + m_playbackIndex = idx; + } double getReportProgressSeconds() const { @@ -107,8 +140,14 @@ namespace WeirdEngine return 0.0; } - bool isReportFinished() const { return m_reportFinished; } - bool isRecordingReport() const { return m_recording && !m_realtimeMode; } + bool isReportFinished() const + { + return m_reportFinished; + } + bool isRecordingReport() const + { + return m_recording && !m_realtimeMode; + } std::string getReportString() const { @@ -116,7 +155,7 @@ namespace WeirdEngine ss << "Profiler Average Report\n"; ss << "=======================\n"; const auto& stats = getLastFrameStats(); - + double topMs = 0.0; for (const auto& s : stats) { @@ -126,15 +165,18 @@ namespace WeirdEngine break; } } - if (topMs <= 0.0) topMs = 1.0; + if (topMs <= 0.0) + topMs = 1.0; for (const auto& s : stats) { - if (s.count == 0 || s.depth == 0) continue; + if (s.count == 0 || s.depth == 0) + continue; double avgMs = s.totalTimeMs / s.count; float fraction = (float)(avgMs / topMs); fraction = std::min(1.0f, std::max(0.0f, fraction)); - for (int i = 1; i < s.depth; ++i) ss << " "; + for (int i = 1; i < s.depth; ++i) + ss << " "; ss << s.name << ": "; ss << std::fixed << std::setprecision(3) << avgMs << " ms ("; ss << std::fixed << std::setprecision(1) << (fraction * 100.0f) << "%)\n"; @@ -245,7 +287,8 @@ namespace WeirdEngine int parentIdx = m_stack.empty() ? -1 : m_stack.back().statIndex; int statIndex = -1; - if (m_currentIndex < m_stats.size() && m_stats[m_currentIndex].name == name && m_stats[m_currentIndex].parentIndex == parentIdx) + if (m_currentIndex < m_stats.size() && m_stats[m_currentIndex].name == name && + m_stats[m_currentIndex].parentIndex == parentIdx) { statIndex = m_currentIndex; m_currentIndex++; @@ -255,7 +298,8 @@ namespace WeirdEngine bool found = false; for (size_t i = 0; i < m_stats.size(); ++i) { - if (m_stats[i].name == name && m_stats[i].depth == m_currentDepth && m_stats[i].parentIndex == parentIdx) + if (m_stats[i].name == name && m_stats[i].depth == m_currentDepth && + m_stats[i].parentIndex == parentIdx) { statIndex = i; m_currentIndex = i + 1; @@ -300,7 +344,8 @@ namespace WeirdEngine } private: - void injectOthersRange(size_t start, size_t end, const std::vector& inStats, std::vector& outStats) + void injectOthersRange(size_t start, size_t end, const std::vector& inStats, + std::vector& outStats) { size_t i = start; while (i < end) @@ -324,7 +369,8 @@ namespace WeirdEngine injectOthersRange(i + 1, subEnd, inStats, outStats); double unaccountedMs = stat.totalTimeMs - childrenTotalMs; - double unaccountedPctOfScope = stat.totalTimeMs > 0.0 ? (unaccountedMs / stat.totalTimeMs) * 100.0 : 0.0; + double unaccountedPctOfScope = + stat.totalTimeMs > 0.0 ? (unaccountedMs / stat.totalTimeMs) * 100.0 : 0.0; if (unaccountedPctOfScope > m_unaccountedThresholdPct) { outStats.push_back({"Others", stat.depth + 1, unaccountedMs, stat.count, stat.parentIndex}); @@ -335,8 +381,6 @@ namespace WeirdEngine } } - - struct StackItem { int statIndex; @@ -379,6 +423,7 @@ namespace WeirdEngine if (m_active) Profiler::get().endScope(); } + private: bool m_active; }; diff --git a/include/weird-engine/ResourceManager.h b/include/weird-engine/ResourceManager.h index 1af9180..4124109 100644 --- a/include/weird-engine/ResourceManager.h +++ b/include/weird-engine/ResourceManager.h @@ -43,7 +43,8 @@ namespace WeirdEngine json m_json; // Loads a single mesh by its index, applying the given node world transform - void loadMesh(const char* file, unsigned int indMesh, std::vector& meshes, glm::mat4 transform = glm::mat4(1.0f)); + void loadMesh(const char* file, unsigned int indMesh, std::vector& meshes, + glm::mat4 transform = glm::mat4(1.0f)); // Traverses a node recursively, so it essentially traverses all connected nodes void traverseNode(const char* file, unsigned int nextNode, std::vector& meshes, diff --git a/include/weird-engine/Scene.h b/include/weird-engine/Scene.h index e55da95..49d28af 100644 --- a/include/weird-engine/Scene.h +++ b/include/weird-engine/Scene.h @@ -10,10 +10,10 @@ #include "weird-renderer/core/RenderTarget.h" #include "weird-renderer/resources/DrawCommand.h" +#include "weird-engine/Background.h" +#include "weird-engine/Material3D.h" #include "weird-physics/PhysicsSettings.h" #include "weird-physics/Simulation2D.h" -#include "weird-engine/Material3D.h" -#include "weird-engine/Background.h" #include #include @@ -68,15 +68,30 @@ namespace WeirdEngine WeirdRenderer::Camera& getCamera(); std::vector& getLigths(); - Simulation2D& getSimulation2D() { return m_simulation2D; } + Simulation2D& getSimulation2D() + { + return m_simulation2D; + } Material3D& createMaterial(); - Material3D& getMaterial(int index) { return m_materials[index]; } - const Material3D* getMaterials() const { return m_materials; } + Material3D& getMaterial(int index) + { + return m_materials[index]; + } + const Material3D* getMaterials() const + { + return m_materials; + } - BackgroundParams& getBackground() { return m_background; } - const BackgroundParams& getBackground() const { return m_background; } + BackgroundParams& getBackground() + { + return m_background; + } + const BackgroundParams& getBackground() const + { + return m_background; + } float getTime(); @@ -120,7 +135,8 @@ namespace WeirdEngine }; // Physics queries - RaymarchResult raymarch(glm::vec2 origin, glm::vec2 direction, float epsilon = 0.001f, float maxDistance = 150.0f); + RaymarchResult raymarch(glm::vec2 origin, glm::vec2 direction, float epsilon = 0.001f, + float maxDistance = 150.0f); void renderImGui(); void renderPhysicsStatsUI(); @@ -135,12 +151,12 @@ namespace WeirdEngine virtual void onUpdate(float delta, ECSManager& ecs) = 0; virtual void onRender(WeirdRenderer::RenderTarget& renderTarget) {}; virtual void onImGuiRender() {}; - + // Physics thread callbacks (No m_ecs access recommended!) virtual void onPhysicsStep(Simulation2D& simulation) {}; virtual void onCollision(Simulation2D& simulation, WeirdEngine::CollisionEvent& event) {}; virtual void onShapeCollision(Simulation2D& simulation, WeirdEngine::ShapeCollisionEvent& event) {}; - + // Main thread callbacks (m_ecs is safe to use here) // ARE YOU SURE??? virtual void onEntityCollision(ECSManager& ecs, WeirdEngine::EntityCollisionEvent& event) {}; virtual void onEntityShapeCollision(ECSManager& ecs, WeirdEngine::EntityShapeCollisionEvent& event) {}; @@ -154,7 +170,7 @@ namespace WeirdEngine Entity m_mainCamera; ResourceManager m_resourceManager; - + Material3D m_materials[16]; uint16_t m_materialCount = 0; @@ -169,7 +185,7 @@ namespace WeirdEngine { return addShape(shapeId, variables, material.id, combination, hasCollision, group); } - + Entity addUIShape(ShapeId shapeId, float* variables, uint16_t material, CombinationType combination = CombinationType::Addition, int group = 0); Entity addUIShape(ShapeId shapeId, float* variables, const Material3D& material, @@ -204,7 +220,8 @@ namespace WeirdEngine SDFRenderSystemContext m_3DWorldRenderContext; SDFRenderSystemContext m_UIRenderContext; // Resolve a physics SimulationID to the owning entity. - Entity getEntityForSimulationId(SimulationID simulationId, std::shared_ptr> rigidBodies); + Entity getEntityForSimulationId(SimulationID simulationId, + std::shared_ptr> rigidBodies); bool m_debugFly = false; bool m_debugInput = false; @@ -224,7 +241,7 @@ namespace WeirdEngine // Path to a .weird file to load when the scene starts (set via setSceneFilePath or registerScene) std::string m_sceneFilePath; - + BackgroundParams m_background; private: @@ -262,18 +279,27 @@ namespace WeirdEngine class Scene2D : public Scene { public: - Scene2D() { m_renderMode = RenderMode::RayMarching2D; } + Scene2D() + { + m_renderMode = RenderMode::RayMarching2D; + } }; class Scene3D : public Scene { public: - Scene3D() { m_renderMode = RenderMode::RayMarching3D; } + Scene3D() + { + m_renderMode = RenderMode::RayMarching3D; + } }; class SceneBoth : public Scene { public: - SceneBoth() { m_renderMode = RenderMode::RayMarchingBoth; } + SceneBoth() + { + m_renderMode = RenderMode::RayMarchingBoth; + } }; } // namespace WeirdEngine diff --git a/include/weird-engine/ecs/ComponentArray.h b/include/weird-engine/ecs/ComponentArray.h index 5c043ae..92d08c7 100644 --- a/include/weird-engine/ecs/ComponentArray.h +++ b/include/weird-engine/ecs/ComponentArray.h @@ -129,7 +129,8 @@ namespace WeirdEngine bool isEntityDirty(Entity entity) { - if (!hasData(entity)) return false; + if (!hasData(entity)) + return false; return dirtyFlags[entityToIndexMap[entity]]; } diff --git a/include/weird-engine/ecs/ECS.h b/include/weird-engine/ecs/ECS.h index 559918c..72964bd 100644 --- a/include/weird-engine/ecs/ECS.h +++ b/include/weird-engine/ecs/ECS.h @@ -8,15 +8,15 @@ #include #include #include +#include #include #include +#include #include #include -#include -#include #if defined(__GNUC__) || defined(__clang__) -#include #include +#include #endif namespace WeirdEngine @@ -128,8 +128,7 @@ namespace WeirdEngine // ===================================================================== // Primary form: lambda receives (Entity e, T&...) - template - void forEach(Func&& func) + template void forEach(Func&& func) { // Grab all the component arrays up front auto arrays = std::make_tuple(getComponentArray()...); @@ -140,8 +139,9 @@ namespace WeirdEngine size_t smallestIdx = 0; size_t idx = 0; ((void)(getComponentArray()->getSize() < smallestSize - ? (smallestSize = getComponentArray()->getSize(), smallestIdx = idx++, true) - : (idx++, false)), ...); + ? (smallestSize = getComponentArray()->getSize(), smallestIdx = idx++, true) + : (idx++, false)), + ...); // Dispatch to the driver that iterates the smallest array idx = 0; @@ -149,7 +149,6 @@ namespace WeirdEngine } private: - // Driver: called once per type in the pack. Only the one matching // smallestIdx actually runs the loop; the others return false. template @@ -177,7 +176,6 @@ namespace WeirdEngine } public: - template void registerComponent() { @@ -255,19 +253,24 @@ namespace WeirdEngine private: template void cacheComponentName(size_t id) { - if (m_componentNames.find(id) != m_componentNames.end()) return; + if (m_componentNames.find(id) != m_componentNames.end()) + return; const char* rawName = typeid(T).name(); std::string finalName; #if defined(__GNUC__) || defined(__clang__) int status = -4; char* demangled = abi::__cxa_demangle(rawName, nullptr, nullptr, &status); - if (status == 0 && demangled) { + if (status == 0 && demangled) + { finalName = demangled; std::free(demangled); - } else { + } + else + { finalName = rawName; - if (demangled) std::free(demangled); + if (demangled) + std::free(demangled); } #else finalName = rawName; @@ -275,12 +278,16 @@ namespace WeirdEngine // Strip namespaces (e.g. "WeirdEngine::Transform" -> "Transform") size_t colonPos = finalName.rfind("::"); - if (colonPos != std::string::npos) { + if (colonPos != std::string::npos) + { finalName = finalName.substr(colonPos + 2); - } else { + } + else + { // Strip "class " or "struct " prefixes if there was no namespace (mostly for MSVC) size_t spacePos = finalName.rfind(" "); - if (spacePos != std::string::npos) { + if (spacePos != std::string::npos) + { finalName = finalName.substr(spacePos + 1); } } diff --git a/include/weird-engine/math/Default2DSDFs.h b/include/weird-engine/math/Default2DSDFs.h index 12a197e..e268cd5 100644 --- a/include/weird-engine/math/Default2DSDFs.h +++ b/include/weird-engine/math/Default2DSDFs.h @@ -19,56 +19,49 @@ namespace WeirdEngine { namespace DefaultShapes { - inline auto var(uint8_t index) { return std::make_shared(index); } + inline auto var(uint8_t index) + { + return std::make_shared(index); + } inline const uint16_t CIRCLE = Scene::registerDefaultSDF(std::make_shared( - var(Primitives::Circle::POS_X), var(Primitives::Circle::POS_Y), var(Primitives::Circle::RADIUS) - )); + var(Primitives::Circle::POS_X), var(Primitives::Circle::POS_Y), var(Primitives::Circle::RADIUS))); inline const uint16_t CIRCLE_LINE = Scene::registerDefaultSDF(std::make_shared( - std::make_shared(var(Primitives::Circle::POS_X), var(Primitives::Circle::POS_Y), var(Primitives::Circle::RADIUS)), - var(Primitives::Circle::RADIUS + 1) - )); + std::make_shared(var(Primitives::Circle::POS_X), var(Primitives::Circle::POS_Y), + var(Primitives::Circle::RADIUS)), + var(Primitives::Circle::RADIUS + 1))); - inline const uint16_t BOX = Scene::registerDefaultSDF(std::make_shared( - var(Primitives::Box::POS_X), var(Primitives::Box::POS_Y), - var(Primitives::Box::SIZE_X), var(Primitives::Box::SIZE_Y) - )); + inline const uint16_t BOX = Scene::registerDefaultSDF( + std::make_shared(var(Primitives::Box::POS_X), var(Primitives::Box::POS_Y), + var(Primitives::Box::SIZE_X), var(Primitives::Box::SIZE_Y))); inline const uint16_t BOX_LINE = Scene::registerDefaultSDF(std::make_shared( std::make_shared(var(Primitives::Box::POS_X), var(Primitives::Box::POS_Y), var(Primitives::Box::SIZE_X), var(Primitives::Box::SIZE_Y)), - var(Primitives::Box::SIZE_Y + 1) - )); + var(Primitives::Box::SIZE_Y + 1))); inline const uint16_t TRIANGLE = Scene::registerDefaultSDF(std::make_shared( - var(Primitives::Triangle::POS_X), var(Primitives::Triangle::POS_Y), - var(Primitives::Triangle::SIZE_X), var(Primitives::Triangle::SIZE_Y), - var(Primitives::Triangle::ROTATION) - )); + var(Primitives::Triangle::POS_X), var(Primitives::Triangle::POS_Y), var(Primitives::Triangle::SIZE_X), + var(Primitives::Triangle::SIZE_Y), var(Primitives::Triangle::ROTATION))); inline const uint16_t TRIANGLE_LINE = Scene::registerDefaultSDF(std::make_shared( std::make_shared(var(Primitives::Triangle::POS_X), var(Primitives::Triangle::POS_Y), var(Primitives::Triangle::SIZE_X), var(Primitives::Triangle::SIZE_Y), var(Primitives::Triangle::ROTATION)), - var(Primitives::Triangle::ROTATION + 1) - )); + var(Primitives::Triangle::ROTATION + 1))); inline const uint16_t LINE = Scene::registerDefaultSDF(std::make_shared( - var(Primitives::Line::POS_A_X), var(Primitives::Line::POS_A_Y), - var(Primitives::Line::POS_B_X), var(Primitives::Line::POS_B_Y), - var(Primitives::Line::WIDTH) - )); + var(Primitives::Line::POS_A_X), var(Primitives::Line::POS_A_Y), var(Primitives::Line::POS_B_X), + var(Primitives::Line::POS_B_Y), var(Primitives::Line::WIDTH))); inline const uint16_t RAMP = Scene::registerDefaultSDF(std::make_shared( - var(Primitives::Ramp::POS_X), var(Primitives::Ramp::POS_Y), - var(Primitives::Ramp::WIDTH), var(Primitives::Ramp::HEIGHT), var(Primitives::Ramp::SKEW) - )); + var(Primitives::Ramp::POS_X), var(Primitives::Ramp::POS_Y), var(Primitives::Ramp::WIDTH), + var(Primitives::Ramp::HEIGHT), var(Primitives::Ramp::SKEW))); inline const uint16_t SINE = Scene::registerDefaultSDF(std::make_shared( - var(Primitives::SineWave::AMPLITUDE), var(Primitives::SineWave::PERIOD), - var(Primitives::SineWave::SPEED), var(Primitives::SineWave::OFFSET) - )); + var(Primitives::SineWave::AMPLITUDE), var(Primitives::SineWave::PERIOD), var(Primitives::SineWave::SPEED), + var(Primitives::SineWave::OFFSET))); inline const uint16_t STAR = Scene::registerDefaultSDF(getStarShape()); diff --git a/include/weird-engine/math/Default3DSDFs.h b/include/weird-engine/math/Default3DSDFs.h index 269c7fa..e5499ac 100644 --- a/include/weird-engine/math/Default3DSDFs.h +++ b/include/weird-engine/math/Default3DSDFs.h @@ -16,40 +16,37 @@ namespace WeirdEngine { - namespace DefaultShapes3D - { - inline auto var(uint8_t index) { return std::make_shared(index); } - - inline const uint16_t PLANE = Scene::registerDefaultSDF(std::make_shared( - var(Primitives3D::Plane::HEIGHT) - )); - - inline const uint16_t BOX = Scene::registerDefaultSDF(std::make_shared( - var(Primitives3D::Box::POS_X), var(Primitives3D::Box::POS_Y), var(Primitives3D::Box::POS_Z), - var(Primitives3D::Box::SIZE_X), var(Primitives3D::Box::SIZE_Y), var(Primitives3D::Box::SIZE_Z) - )); - - inline const uint16_t SPHERE = Scene::registerDefaultSDF(std::make_shared( - var(Primitives3D::Sphere::POS_X), var(Primitives3D::Sphere::POS_Y), var(Primitives3D::Sphere::POS_Z), - var(Primitives3D::Sphere::RADIUS) - )); - - inline const uint16_t CYLINDER = Scene::registerDefaultSDF(std::make_shared( - var(Primitives3D::Cylinder::POS_X), var(Primitives3D::Cylinder::POS_Y), var(Primitives3D::Cylinder::POS_Z), - var(Primitives3D::Cylinder::RADIUS), var(Primitives3D::Cylinder::HEIGHT) - )); - - inline const uint16_t TORUS = Scene::registerDefaultSDF(std::make_shared( - var(Primitives3D::Torus::POS_X), var(Primitives3D::Torus::POS_Y), var(Primitives3D::Torus::POS_Z), - var(Primitives3D::Torus::RADIUS_SMALL), var(Primitives3D::Torus::RADIUS_LARGE) - )); - - inline const uint16_t CAPSULE = Scene::registerDefaultSDF(std::make_shared( - var(Primitives3D::Capsule::POS_X), var(Primitives3D::Capsule::POS_Y), var(Primitives3D::Capsule::POS_Z), - var(Primitives3D::Capsule::RADIUS), var(Primitives3D::Capsule::HEIGHT) - )); - - } // namespace DefaultShapes3D + namespace DefaultShapes3D + { + inline auto var(uint8_t index) + { + return std::make_shared(index); + } + + inline const uint16_t PLANE = + Scene::registerDefaultSDF(std::make_shared(var(Primitives3D::Plane::HEIGHT))); + + inline const uint16_t BOX = Scene::registerDefaultSDF(std::make_shared( + var(Primitives3D::Box::POS_X), var(Primitives3D::Box::POS_Y), var(Primitives3D::Box::POS_Z), + var(Primitives3D::Box::SIZE_X), var(Primitives3D::Box::SIZE_Y), var(Primitives3D::Box::SIZE_Z))); + + inline const uint16_t SPHERE = Scene::registerDefaultSDF(std::make_shared( + var(Primitives3D::Sphere::POS_X), var(Primitives3D::Sphere::POS_Y), var(Primitives3D::Sphere::POS_Z), + var(Primitives3D::Sphere::RADIUS))); + + inline const uint16_t CYLINDER = Scene::registerDefaultSDF(std::make_shared( + var(Primitives3D::Cylinder::POS_X), var(Primitives3D::Cylinder::POS_Y), var(Primitives3D::Cylinder::POS_Z), + var(Primitives3D::Cylinder::RADIUS), var(Primitives3D::Cylinder::HEIGHT))); + + inline const uint16_t TORUS = Scene::registerDefaultSDF(std::make_shared( + var(Primitives3D::Torus::POS_X), var(Primitives3D::Torus::POS_Y), var(Primitives3D::Torus::POS_Z), + var(Primitives3D::Torus::RADIUS_SMALL), var(Primitives3D::Torus::RADIUS_LARGE))); + + inline const uint16_t CAPSULE = Scene::registerDefaultSDF(std::make_shared( + var(Primitives3D::Capsule::POS_X), var(Primitives3D::Capsule::POS_Y), var(Primitives3D::Capsule::POS_Z), + var(Primitives3D::Capsule::RADIUS), var(Primitives3D::Capsule::HEIGHT))); + + } // namespace DefaultShapes3D } // namespace WeirdEngine #endif // WEIRDSAMPLES_DEFAULT3DSDFS_H diff --git a/include/weird-engine/math/MathExpressions.h b/include/weird-engine/math/MathExpressions.h index 12baa9c..eb7befb 100644 --- a/include/weird-engine/math/MathExpressions.h +++ b/include/weird-engine/math/MathExpressions.h @@ -24,7 +24,6 @@ namespace WeirdEngine { private: std::ptrdiff_t m_offset; - public: explicit FloatVariable(std::ptrdiff_t offset) @@ -428,7 +427,6 @@ namespace WeirdEngine } }; - // Three float operation struct ThreeFloatOperation : IMathExpression { @@ -445,7 +443,8 @@ namespace WeirdEngine { } - ThreeFloatOperation(std::shared_ptr a, std::shared_ptr b, std::shared_ptr c) + ThreeFloatOperation(std::shared_ptr a, std::shared_ptr b, + std::shared_ptr c) : valueA(std::move(a)) , valueB(std::move(b)) , valueC(std::move(c)) @@ -459,7 +458,8 @@ namespace WeirdEngine { } - void setValues(std::shared_ptr a, std::shared_ptr b, std::shared_ptr c) + void setValues(std::shared_ptr a, std::shared_ptr b, + std::shared_ptr c) { valueA = (std::move(a)); valueB = (std::move(b)); diff --git a/include/weird-engine/math/Primitives.h b/include/weird-engine/math/Primitives.h index cb3364e..126aaf7 100644 --- a/include/weird-engine/math/Primitives.h +++ b/include/weird-engine/math/Primitives.h @@ -1,381 +1,382 @@ #pragma once #include +#include #include #include #include #include #include -#include -#include "weird-engine/vec.h" #include "CompiledMathExpressions.h" #include "MathExpressions.h" #include "StarShape.h" +#include "weird-engine/vec.h" namespace WeirdEngine::Primitives { - static constexpr uint8_t WORLD_X = 9; + static constexpr uint8_t WORLD_X = 9; static constexpr uint8_t WORLD_Y = 10; - struct Circle : IMathExpression + struct Circle : IMathExpression + { + protected: + std::shared_ptr m_px; + std::shared_ptr m_py; + std::shared_ptr m_r; + std::shared_ptr m_time; + std::shared_ptr m_worldX; + std::shared_ptr m_worldY; + + public: + static constexpr uint8_t POS_X = 0; + static constexpr uint8_t POS_Y = 1; + static constexpr uint8_t RADIUS = 2; + + // Common + static constexpr uint8_t TIME = 8; + static constexpr uint8_t WORLD_X = 9; + static constexpr uint8_t WORLD_Y = 10; + + Circle(std::shared_ptr px, std::shared_ptr py, + std::shared_ptr r) + : m_px(std::move(px)) + , m_py(std::move(py)) + , m_r(std::move(r)) + { + // Can I reuse these? + m_time = std::make_shared(TIME); + m_worldX = std::make_shared(WORLD_X); + m_worldY = std::make_shared(WORLD_Y); + } + + [[nodiscard]] + float getValue(const float* parameters) const override + { + vec2 p = vec2(m_worldX->getValue(parameters) - m_px->getValue(parameters), + m_worldY->getValue(parameters) - m_py->getValue(parameters)); + return length(p) - m_r->getValue(parameters); + } + + [[nodiscard]] + std::string print() const override { - protected: - std::shared_ptr m_px; - std::shared_ptr m_py; - std::shared_ptr m_r; - std::shared_ptr m_time; - std::shared_ptr m_worldX; - std::shared_ptr m_worldY; - - public: - static constexpr uint8_t POS_X = 0; - static constexpr uint8_t POS_Y = 1; - static constexpr uint8_t RADIUS = 2; - - // Common - static constexpr uint8_t TIME = 8; - static constexpr uint8_t WORLD_X = 9; - static constexpr uint8_t WORLD_Y = 10; - - Circle(std::shared_ptr px, std::shared_ptr py, - std::shared_ptr r) - : m_px(std::move(px)) - , m_py(std::move(py)) - , m_r(std::move(r)) - { - // Can I reuse these? - m_time = std::make_shared(TIME); - m_worldX = std::make_shared(WORLD_X); - m_worldY = std::make_shared(WORLD_Y); - } - - [[nodiscard]] - float getValue(const float* parameters) const override - { - vec2 p = vec2(m_worldX->getValue(parameters) - m_px->getValue(parameters), m_worldY->getValue(parameters) - m_py->getValue(parameters)); - return length(p) - m_r->getValue(parameters); - } - - [[nodiscard]] - std::string print() const override - { - return "(length(vec2(" + m_worldX->print() + " - " + m_px->print() + ", " + m_worldY->print() + " - " + - m_py->print() + ")) - " + m_r->print() + ")"; - } - }; - - struct Box : IMathExpression + return "(length(vec2(" + m_worldX->print() + " - " + m_px->print() + ", " + m_worldY->print() + " - " + + m_py->print() + ")) - " + m_r->print() + ")"; + } + }; + + struct Box : IMathExpression + { + protected: + std::shared_ptr m_px; + std::shared_ptr m_py; + std::shared_ptr m_w; + std::shared_ptr m_h; + std::shared_ptr m_worldX; + std::shared_ptr m_worldY; + + public: + static constexpr uint8_t POS_X = 0; + static constexpr uint8_t POS_Y = 1; + static constexpr uint8_t SIZE_X = 2; + static constexpr uint8_t SIZE_Y = 3; + + static constexpr uint8_t WORLD_X = 9; + static constexpr uint8_t WORLD_Y = 10; + + Box(std::shared_ptr px, std::shared_ptr py, + std::shared_ptr w, std::shared_ptr h) + : m_px(std::move(px)) + , m_py(std::move(py)) + , m_w(std::move(w)) + , m_h(std::move(h)) { - protected: - std::shared_ptr m_px; - std::shared_ptr m_py; - std::shared_ptr m_w; - std::shared_ptr m_h; - std::shared_ptr m_worldX; - std::shared_ptr m_worldY; - - public: - static constexpr uint8_t POS_X = 0; - static constexpr uint8_t POS_Y = 1; - static constexpr uint8_t SIZE_X = 2; - static constexpr uint8_t SIZE_Y = 3; - - static constexpr uint8_t WORLD_X = 9; - static constexpr uint8_t WORLD_Y = 10; - - Box(std::shared_ptr px, std::shared_ptr py, - std::shared_ptr w, std::shared_ptr h) - : m_px(std::move(px)) - , m_py(std::move(py)) - , m_w(std::move(w)) - , m_h(std::move(h)) - { - m_worldX = std::make_shared(WORLD_X); - m_worldY = std::make_shared(WORLD_Y); - } - - [[nodiscard]] - float getValue(const float* parameters) const override - { - vec2 p = vec2(m_worldX->getValue(parameters) - m_px->getValue(parameters), m_worldY->getValue(parameters) - m_py->getValue(parameters)); - vec2 b = vec2(m_w->getValue(parameters), m_h->getValue(parameters)); - vec2 d = abs(p) - b; - return length(max(d, vec2(0.0))) + std::min(std::max(d.x, d.y), 0.0f); - } - - [[nodiscard]] - std::string print() const override - { - return "sdBox(vec2(" + m_worldX->print() + " - " + m_px->print() + ", " + m_worldY->print() + " - " + - m_py->print() + "), vec2(" + m_w->print() + ", " + m_h->print() + "))"; - } - }; - - struct SineWave : IMathExpression + m_worldX = std::make_shared(WORLD_X); + m_worldY = std::make_shared(WORLD_Y); + } + + [[nodiscard]] + float getValue(const float* parameters) const override { - protected: - std::shared_ptr m_amplitude; - std::shared_ptr m_period; - std::shared_ptr m_speed; - std::shared_ptr m_offset; - std::shared_ptr m_time; - std::shared_ptr m_worldX; - std::shared_ptr m_worldY; - - public: - static constexpr uint8_t AMPLITUDE = 0; - static constexpr uint8_t PERIOD = 1; - static constexpr uint8_t SPEED = 2; - static constexpr uint8_t OFFSET = 3; - - static constexpr uint8_t TIME = 8; - static constexpr uint8_t WORLD_X = 9; - static constexpr uint8_t WORLD_Y = 10; - - SineWave(std::shared_ptr amplitude, std::shared_ptr period, + vec2 p = vec2(m_worldX->getValue(parameters) - m_px->getValue(parameters), + m_worldY->getValue(parameters) - m_py->getValue(parameters)); + vec2 b = vec2(m_w->getValue(parameters), m_h->getValue(parameters)); + vec2 d = abs(p) - b; + return length(max(d, vec2(0.0))) + std::min(std::max(d.x, d.y), 0.0f); + } + + [[nodiscard]] + std::string print() const override + { + return "sdBox(vec2(" + m_worldX->print() + " - " + m_px->print() + ", " + m_worldY->print() + " - " + + m_py->print() + "), vec2(" + m_w->print() + ", " + m_h->print() + "))"; + } + }; + + struct SineWave : IMathExpression + { + protected: + std::shared_ptr m_amplitude; + std::shared_ptr m_period; + std::shared_ptr m_speed; + std::shared_ptr m_offset; + std::shared_ptr m_time; + std::shared_ptr m_worldX; + std::shared_ptr m_worldY; + + public: + static constexpr uint8_t AMPLITUDE = 0; + static constexpr uint8_t PERIOD = 1; + static constexpr uint8_t SPEED = 2; + static constexpr uint8_t OFFSET = 3; + + static constexpr uint8_t TIME = 8; + static constexpr uint8_t WORLD_X = 9; + static constexpr uint8_t WORLD_Y = 10; + + SineWave(std::shared_ptr amplitude, std::shared_ptr period, std::shared_ptr speed, std::shared_ptr offset) - : m_amplitude(std::move(amplitude)) - , m_period(std::move(period)) - , m_speed(std::move(speed)) - , m_offset(std::move(offset)) - { - m_time = std::make_shared(TIME); - m_worldX = std::make_shared(WORLD_X); - m_worldY = std::make_shared(WORLD_Y); - } - - [[nodiscard]] - float getValue(const float* parameters) const override - { - return (m_worldY->getValue(parameters) - m_offset->getValue(parameters)) - - m_amplitude->getValue(parameters) * sinf(m_period->getValue(parameters) * m_worldX->getValue(parameters) + - m_speed->getValue(parameters) * m_time->getValue(parameters)); - } - - [[nodiscard]] - std::string print() const override - { - return "(" + m_worldY->print() + " - " + m_offset->print() + ") - " + m_amplitude->print() + - " * sin(" + m_period->print() + " * " + m_worldX->print() + " + " + m_speed->print() + " * " + - m_time->print() + ")"; - } - }; - - struct Ramp : IMathExpression + : m_amplitude(std::move(amplitude)) + , m_period(std::move(period)) + , m_speed(std::move(speed)) + , m_offset(std::move(offset)) + { + m_time = std::make_shared(TIME); + m_worldX = std::make_shared(WORLD_X); + m_worldY = std::make_shared(WORLD_Y); + } + + [[nodiscard]] + float getValue(const float* parameters) const override + { + return (m_worldY->getValue(parameters) - m_offset->getValue(parameters)) - + m_amplitude->getValue(parameters) * + sinf(m_period->getValue(parameters) * m_worldX->getValue(parameters) + + m_speed->getValue(parameters) * m_time->getValue(parameters)); + } + + [[nodiscard]] + std::string print() const override + { + return "(" + m_worldY->print() + " - " + m_offset->print() + ") - " + m_amplitude->print() + " * sin(" + + m_period->print() + " * " + m_worldX->print() + " + " + m_speed->print() + " * " + m_time->print() + + ")"; + } + }; + + struct Ramp : IMathExpression + { + protected: + std::shared_ptr m_px; + std::shared_ptr m_py; + std::shared_ptr m_w; + std::shared_ptr m_h; + std::shared_ptr m_skew; + std::shared_ptr m_worldX; + std::shared_ptr m_worldY; + + public: + static constexpr uint8_t POS_X = 0; + static constexpr uint8_t POS_Y = 1; + static constexpr uint8_t WIDTH = 2; + static constexpr uint8_t HEIGHT = 3; + static constexpr uint8_t SKEW = 4; + + static constexpr uint8_t WORLD_X = 9; + static constexpr uint8_t WORLD_Y = 10; + + Ramp(std::shared_ptr px, std::shared_ptr py, + std::shared_ptr width, std::shared_ptr height, + std::shared_ptr skew) + : m_px(std::move(px)) + , m_py(std::move(py)) + , m_w(std::move(width)) + , m_h(std::move(height)) + , m_skew(std::move(skew)) + { + m_worldX = std::make_shared(WORLD_X); + m_worldY = std::make_shared(WORLD_Y); + } + + [[nodiscard]] + float getValue(const float* parameters) const override { - protected: - std::shared_ptr m_px; - std::shared_ptr m_py; - std::shared_ptr m_w; - std::shared_ptr m_h; - std::shared_ptr m_skew; - std::shared_ptr m_worldX; - std::shared_ptr m_worldY; - - public: - static constexpr uint8_t POS_X = 0; - static constexpr uint8_t POS_Y = 1; - static constexpr uint8_t WIDTH = 2; - static constexpr uint8_t HEIGHT = 3; - static constexpr uint8_t SKEW = 4; - - static constexpr uint8_t WORLD_X = 9; - static constexpr uint8_t WORLD_Y = 10; - - Ramp(std::shared_ptr px, std::shared_ptr py, - std::shared_ptr width, std::shared_ptr height, - std::shared_ptr skew) - : m_px(std::move(px)) - , m_py(std::move(py)) - , m_w(std::move(width)) - , m_h(std::move(height)) - , m_skew(std::move(skew)) - { - m_worldX = std::make_shared(WORLD_X); - m_worldY = std::make_shared(WORLD_Y); - } - - [[nodiscard]] - float getValue(const float* parameters) const override - { - vec2 p = vec2(m_worldX->getValue(parameters) - m_px->getValue(parameters), m_worldY->getValue(parameters) - m_py->getValue(parameters)); - float wi = m_w->getValue(parameters); - float he = m_h->getValue(parameters); - float sk = m_skew->getValue(parameters); - - glm::vec2 e(wi, sk); - if (p.x < 0.0f) - p = -p; - glm::vec2 w = p - e; - w.y -= std::clamp(w.y, -he, he); - glm::vec2 d(glm::dot(w, w), -w.x); - float s = p.y * e.x - p.x * e.y; - if (s < 0.0f) - p = -p; - glm::vec2 v = p - glm::vec2(0.0f, he); - v -= e * std::clamp(glm::dot(v, e) / glm::dot(e, e), -1.0f, 1.0f); - d = glm::min(d, glm::vec2(glm::dot(v, v), wi * he - std::abs(s))); - return std::sqrt(d.x) * std::copysign(1.0f, -d.y); - } - - [[nodiscard]] - std::string print() const override - { - return "sdParallelogramVertical(vec2(" + m_worldX->print() + " - " + m_px->print() + ", " + - m_worldY->print() + " - " + m_py->print() + "), " + m_w->print() + ", " + m_h->print() + - ", " + m_skew->print() + ")"; - } - }; - - struct Triangle : IMathExpression + vec2 p = vec2(m_worldX->getValue(parameters) - m_px->getValue(parameters), + m_worldY->getValue(parameters) - m_py->getValue(parameters)); + float wi = m_w->getValue(parameters); + float he = m_h->getValue(parameters); + float sk = m_skew->getValue(parameters); + + glm::vec2 e(wi, sk); + if (p.x < 0.0f) + p = -p; + glm::vec2 w = p - e; + w.y -= std::clamp(w.y, -he, he); + glm::vec2 d(glm::dot(w, w), -w.x); + float s = p.y * e.x - p.x * e.y; + if (s < 0.0f) + p = -p; + glm::vec2 v = p - glm::vec2(0.0f, he); + v -= e * std::clamp(glm::dot(v, e) / glm::dot(e, e), -1.0f, 1.0f); + d = glm::min(d, glm::vec2(glm::dot(v, v), wi * he - std::abs(s))); + return std::sqrt(d.x) * std::copysign(1.0f, -d.y); + } + + [[nodiscard]] + std::string print() const override { - protected: - std::shared_ptr m_px; - std::shared_ptr m_py; - std::shared_ptr m_w; - std::shared_ptr m_h; - std::shared_ptr m_rotation; - std::shared_ptr m_worldX; - std::shared_ptr m_worldY; - - public: - static constexpr uint8_t POS_X = 0; - static constexpr uint8_t POS_Y = 1; - static constexpr uint8_t SIZE_X = 2; - static constexpr uint8_t SIZE_Y = 3; - static constexpr uint8_t ROTATION = 4; - - static constexpr uint8_t WORLD_X = 9; - static constexpr uint8_t WORLD_Y = 10; - - Triangle(std::shared_ptr px, std::shared_ptr py, + return "sdParallelogramVertical(vec2(" + m_worldX->print() + " - " + m_px->print() + ", " + + m_worldY->print() + " - " + m_py->print() + "), " + m_w->print() + ", " + m_h->print() + ", " + + m_skew->print() + ")"; + } + }; + + struct Triangle : IMathExpression + { + protected: + std::shared_ptr m_px; + std::shared_ptr m_py; + std::shared_ptr m_w; + std::shared_ptr m_h; + std::shared_ptr m_rotation; + std::shared_ptr m_worldX; + std::shared_ptr m_worldY; + + public: + static constexpr uint8_t POS_X = 0; + static constexpr uint8_t POS_Y = 1; + static constexpr uint8_t SIZE_X = 2; + static constexpr uint8_t SIZE_Y = 3; + static constexpr uint8_t ROTATION = 4; + + static constexpr uint8_t WORLD_X = 9; + static constexpr uint8_t WORLD_Y = 10; + + Triangle(std::shared_ptr px, std::shared_ptr py, std::shared_ptr w, std::shared_ptr h, std::shared_ptr rotation) - : m_px(std::move(px)) - , m_py(std::move(py)) - , m_w(std::move(w)) - , m_h(std::move(h)) - , m_rotation(std::move(rotation)) - { - m_worldX = std::make_shared(WORLD_X); - m_worldY = std::make_shared(WORLD_Y); - } - - static float cross(const vec2& a, const vec2& b) - { - return a.x * b.y - a.y * b.x; - } - - static float distanceToSegment(const vec2& p, const vec2& a, const vec2& b) - { - vec2 pa = p - a; - vec2 ba = b - a; - float h = glm::clamp(glm::dot(pa, ba) / glm::dot(ba, ba), 0.0f, 1.0f); - return length(pa - ba * h); - } - - static float signedDistanceToTriangle(const vec2& p, const vec2& a, const vec2& b, const vec2& c) - { - float d = std::min(std::min(distanceToSegment(p, a, b), distanceToSegment(p, b, c)), - distanceToSegment(p, c, a)); - - float c0 = cross(b - a, p - a); - float c1 = cross(c - b, p - b); - float c2 = cross(a - c, p - c); - - bool inside = (c0 >= 0.0f && c1 >= 0.0f && c2 >= 0.0f) || - (c0 <= 0.0f && c1 <= 0.0f && c2 <= 0.0f); - - return inside ? -d : d; - } - - [[nodiscard]] - float getValue(const float* parameters) const override - { - vec2 p = vec2(m_worldX->getValue(parameters) - m_px->getValue(parameters), m_worldY->getValue(parameters) - m_py->getValue(parameters)); - float angle = m_rotation->getValue(parameters); - float c = cosf(angle); - float s = sinf(angle); - - auto rotate = [&](const vec2& v) { - return vec2(c * v.x - s * v.y, s * v.x + c * v.y); - }; - - float halfWidth = m_w->getValue(parameters) * 0.5f; - float height = m_h->getValue(parameters); - - vec2 a = rotate(vec2(-halfWidth, -height / 3.0f)); - vec2 b = rotate(vec2(halfWidth, -height / 3.0f)); - vec2 c2 = rotate(vec2(0.0f, 2.0f * height / 3.0f)); - - return signedDistanceToTriangle(p, a, b, c2); - } - - [[nodiscard]] - std::string print() const override - { - return "sdTriangle(vec2(" + m_worldX->print() + " - " + m_px->print() + ", " + - m_worldY->print() + " - " + m_py->print() + "), " + m_w->print() + ", " + - m_h->print() + ", " + m_rotation->print() + ")"; - } - }; - - struct Line : IMathExpression + : m_px(std::move(px)) + , m_py(std::move(py)) + , m_w(std::move(w)) + , m_h(std::move(h)) + , m_rotation(std::move(rotation)) + { + m_worldX = std::make_shared(WORLD_X); + m_worldY = std::make_shared(WORLD_Y); + } + + static float cross(const vec2& a, const vec2& b) + { + return a.x * b.y - a.y * b.x; + } + + static float distanceToSegment(const vec2& p, const vec2& a, const vec2& b) + { + vec2 pa = p - a; + vec2 ba = b - a; + float h = glm::clamp(glm::dot(pa, ba) / glm::dot(ba, ba), 0.0f, 1.0f); + return length(pa - ba * h); + } + + static float signedDistanceToTriangle(const vec2& p, const vec2& a, const vec2& b, const vec2& c) + { + float d = + std::min(std::min(distanceToSegment(p, a, b), distanceToSegment(p, b, c)), distanceToSegment(p, c, a)); + + float c0 = cross(b - a, p - a); + float c1 = cross(c - b, p - b); + float c2 = cross(a - c, p - c); + + bool inside = (c0 >= 0.0f && c1 >= 0.0f && c2 >= 0.0f) || (c0 <= 0.0f && c1 <= 0.0f && c2 <= 0.0f); + + return inside ? -d : d; + } + + [[nodiscard]] + float getValue(const float* parameters) const override + { + vec2 p = vec2(m_worldX->getValue(parameters) - m_px->getValue(parameters), + m_worldY->getValue(parameters) - m_py->getValue(parameters)); + float angle = m_rotation->getValue(parameters); + float c = cosf(angle); + float s = sinf(angle); + + auto rotate = [&](const vec2& v) { return vec2(c * v.x - s * v.y, s * v.x + c * v.y); }; + + float halfWidth = m_w->getValue(parameters) * 0.5f; + float height = m_h->getValue(parameters); + + vec2 a = rotate(vec2(-halfWidth, -height / 3.0f)); + vec2 b = rotate(vec2(halfWidth, -height / 3.0f)); + vec2 c2 = rotate(vec2(0.0f, 2.0f * height / 3.0f)); + + return signedDistanceToTriangle(p, a, b, c2); + } + + [[nodiscard]] + std::string print() const override + { + return "sdTriangle(vec2(" + m_worldX->print() + " - " + m_px->print() + ", " + m_worldY->print() + " - " + + m_py->print() + "), " + m_w->print() + ", " + m_h->print() + ", " + m_rotation->print() + ")"; + } + }; + + struct Line : IMathExpression + { + protected: + std::shared_ptr m_ax; + std::shared_ptr m_ay; + std::shared_ptr m_bx; + std::shared_ptr m_by; + std::shared_ptr m_width; + std::shared_ptr m_worldX; + std::shared_ptr m_worldY; + + public: + static constexpr uint8_t POS_A_X = 0; + static constexpr uint8_t POS_A_Y = 1; + static constexpr uint8_t POS_B_X = 2; + static constexpr uint8_t POS_B_Y = 3; + static constexpr uint8_t WIDTH = 4; + + static constexpr uint8_t WORLD_X = 9; + static constexpr uint8_t WORLD_Y = 10; + + Line(std::shared_ptr ax, std::shared_ptr ay, + std::shared_ptr bx, std::shared_ptr by, + std::shared_ptr width) + : m_ax(std::move(ax)) + , m_ay(std::move(ay)) + , m_bx(std::move(bx)) + , m_by(std::move(by)) + , m_width(std::move(width)) + { + m_worldX = std::make_shared(WORLD_X); + m_worldY = std::make_shared(WORLD_Y); + } + + [[nodiscard]] + float getValue(const float* parameters) const override + { + vec2 p = vec2(m_worldX->getValue(parameters), m_worldY->getValue(parameters)); + + vec2 a = vec2(m_ax->getValue(parameters), m_ay->getValue(parameters)); + vec2 b = vec2(m_bx->getValue(parameters), m_by->getValue(parameters)); + + float width = m_width->getValue(parameters); + + vec2 pa = p - a, ba = b - a; + float h = glm::clamp(glm::dot(pa, ba) / glm::dot(ba, ba), 0.0f, 1.0f); + return length(pa - ba * h) - width; + } + + [[nodiscard]] + std::string print() const override { - protected: - std::shared_ptr m_ax; - std::shared_ptr m_ay; - std::shared_ptr m_bx; - std::shared_ptr m_by; - std::shared_ptr m_width; - std::shared_ptr m_worldX; - std::shared_ptr m_worldY; - - public: - static constexpr uint8_t POS_A_X = 0; - static constexpr uint8_t POS_A_Y = 1; - static constexpr uint8_t POS_B_X = 2; - static constexpr uint8_t POS_B_Y = 3; - static constexpr uint8_t WIDTH = 4; - - static constexpr uint8_t WORLD_X = 9; - static constexpr uint8_t WORLD_Y = 10; - - Line(std::shared_ptr ax, std::shared_ptr ay, - std::shared_ptr bx, std::shared_ptr by, - std::shared_ptr width) - : m_ax(std::move(ax)) - , m_ay(std::move(ay)) - , m_bx(std::move(bx)) - , m_by(std::move(by)) - , m_width(std::move(width)) - { - m_worldX = std::make_shared(WORLD_X); - m_worldY = std::make_shared(WORLD_Y); - } - - [[nodiscard]] - float getValue(const float* parameters) const override - { - vec2 p = vec2(m_worldX->getValue(parameters), m_worldY->getValue(parameters)); - - vec2 a = vec2(m_ax->getValue(parameters), m_ay->getValue(parameters)); - vec2 b = vec2(m_bx->getValue(parameters), m_by->getValue(parameters)); - - float width = m_width->getValue(parameters); - - vec2 pa = p - a, ba = b - a; - float h = glm::clamp(glm::dot(pa, ba) / glm::dot(ba, ba), 0.0f, 1.0f); - return length(pa - ba * h) - width; - } - - [[nodiscard]] - std::string print() const override - { - return "sdSegment(vec2(" + m_worldX->print() + ", " + m_worldY->print() + "), vec2(" + - m_ax->print() + ", " + m_ay->print() + "), vec2(" + m_bx->print() + ", " + m_by->print() + - ")) - " + m_width->print(); - } - }; -} // namespace WeirdEngine \ No newline at end of file + return "sdSegment(vec2(" + m_worldX->print() + ", " + m_worldY->print() + "), vec2(" + m_ax->print() + + ", " + m_ay->print() + "), vec2(" + m_bx->print() + ", " + m_by->print() + ")) - " + + m_width->print(); + } + }; +} // namespace WeirdEngine::Primitives \ No newline at end of file diff --git a/include/weird-engine/math/Primitives3D.h b/include/weird-engine/math/Primitives3D.h index b98e7d5..0812aab 100644 --- a/include/weird-engine/math/Primitives3D.h +++ b/include/weird-engine/math/Primitives3D.h @@ -12,173 +12,231 @@ namespace WeirdEngine::Primitives3D { - struct Plane : public WeirdEngine::IMathExpression - { - protected: - std::shared_ptr m_h; - - public: - static constexpr uint8_t HEIGHT = 0; - - Plane(std::shared_ptr h) : m_h(std::move(h)) {} - - float getValue(const float* parameters) const override { return 1000.0f; } - std::string print() const override { - return "fPlane(p, vec3(0.0, 1.0, 0.0), " + m_h->print() + ")\n"; - } - }; - - struct PerlinPlane : public WeirdEngine::IMathExpression - { - public: - PerlinPlane(float height) : m_height(height) {} - - float getValue(const float* parameters) const override { return 1000.0f; } - std::string print() const override { - return "fPlane(\n" - " p, vec3(0.0, 1.0, 0.0), 3.0 + (0.5 * perlin(1.2 * vec2(p.x, p.z))) + (3.0 * perlin(0.2 * vec2(p.x, p.z))))\n"; - } - private: - float m_height; - }; - - struct Box : public WeirdEngine::IMathExpression - { - protected: - std::shared_ptr m_px, m_py, m_pz; - std::shared_ptr m_sx, m_sy, m_sz; - - public: - static constexpr uint8_t POS_X = 0; - static constexpr uint8_t POS_Y = 1; - static constexpr uint8_t POS_Z = 2; - static constexpr uint8_t SIZE_X = 3; - static constexpr uint8_t SIZE_Y = 4; - static constexpr uint8_t SIZE_Z = 5; - - Box(std::shared_ptr px, std::shared_ptr py, std::shared_ptr pz, - std::shared_ptr sx, std::shared_ptr sy, std::shared_ptr sz) - : m_px(std::move(px)), m_py(std::move(py)), m_pz(std::move(pz)), - m_sx(std::move(sx)), m_sy(std::move(sy)), m_sz(std::move(sz)) - { - } - - Box() // Legacy constructor for existing code compatibility - { - } - - float getValue(const float* parameters) const override { return 1000.0f; } - std::string print() const override - { - if (m_px) - { - return "fBox(p - vec3(" + m_px->print() + ", " + m_py->print() + ", " + m_pz->print() + "), vec3(" + - m_sx->print() + ", " + m_sy->print() + ", " + m_sz->print() + "))"; - } - return "fBox(p - vec3(var0, var1, var2), vec3(var3, var4, var5))"; - } - }; - - struct Sphere : public WeirdEngine::IMathExpression - { - protected: - std::shared_ptr m_px, m_py, m_pz; - std::shared_ptr m_r; - - public: - static constexpr uint8_t POS_X = 0; - static constexpr uint8_t POS_Y = 1; - static constexpr uint8_t POS_Z = 2; - static constexpr uint8_t RADIUS = 3; - - Sphere(std::shared_ptr px, std::shared_ptr py, std::shared_ptr pz, - std::shared_ptr r) - : m_px(std::move(px)), m_py(std::move(py)), m_pz(std::move(pz)), m_r(std::move(r)) - { - } - - float getValue(const float* parameters) const override { return 1000.0f; } - std::string print() const override - { - return "fSphere(p - vec3(" + m_px->print() + ", " + m_py->print() + ", " + m_pz->print() + "), " + m_r->print() + ")"; - } - }; - - struct Cylinder : public WeirdEngine::IMathExpression - { - protected: - std::shared_ptr m_px, m_py, m_pz; - std::shared_ptr m_r, m_h; - - public: - static constexpr uint8_t POS_X = 0; - static constexpr uint8_t POS_Y = 1; - static constexpr uint8_t POS_Z = 2; - static constexpr uint8_t RADIUS = 3; - static constexpr uint8_t HEIGHT = 4; - - Cylinder(std::shared_ptr px, std::shared_ptr py, std::shared_ptr pz, - std::shared_ptr r, std::shared_ptr h) - : m_px(std::move(px)), m_py(std::move(py)), m_pz(std::move(pz)), m_r(std::move(r)), m_h(std::move(h)) - { - } - - float getValue(const float* parameters) const override { return 1000.0f; } - std::string print() const override - { - return "fCylinder(p - vec3(" + m_px->print() + ", " + m_py->print() + ", " + m_pz->print() + "), " + m_r->print() + ", " + m_h->print() + ")"; - } - }; - - struct Torus : public WeirdEngine::IMathExpression - { - protected: - std::shared_ptr m_px, m_py, m_pz; - std::shared_ptr m_r1, m_r2; - - public: - static constexpr uint8_t POS_X = 0; - static constexpr uint8_t POS_Y = 1; - static constexpr uint8_t POS_Z = 2; - static constexpr uint8_t RADIUS_SMALL = 3; - static constexpr uint8_t RADIUS_LARGE = 4; - - Torus(std::shared_ptr px, std::shared_ptr py, std::shared_ptr pz, - std::shared_ptr r1, std::shared_ptr r2) - : m_px(std::move(px)), m_py(std::move(py)), m_pz(std::move(pz)), m_r1(std::move(r1)), m_r2(std::move(r2)) - { - } - - float getValue(const float* parameters) const override { return 1000.0f; } - std::string print() const override - { - return "fTorus(p - vec3(" + m_px->print() + ", " + m_py->print() + ", " + m_pz->print() + "), " + m_r1->print() + ", " + m_r2->print() + ")"; - } - }; - - struct Capsule : public WeirdEngine::IMathExpression - { - protected: - std::shared_ptr m_px, m_py, m_pz; - std::shared_ptr m_r, m_h; - - public: - static constexpr uint8_t POS_X = 0; - static constexpr uint8_t POS_Y = 1; - static constexpr uint8_t POS_Z = 2; - static constexpr uint8_t RADIUS = 3; - static constexpr uint8_t HEIGHT = 4; - - Capsule(std::shared_ptr px, std::shared_ptr py, std::shared_ptr pz, - std::shared_ptr r, std::shared_ptr h) - : m_px(std::move(px)), m_py(std::move(py)), m_pz(std::move(pz)), m_r(std::move(r)), m_h(std::move(h)) - { - } - - float getValue(const float* parameters) const override { return 1000.0f; } - std::string print() const override - { - return "fCapsule(p - vec3(" + m_px->print() + ", " + m_py->print() + ", " + m_pz->print() + "), " + m_r->print() + ", " + m_h->print() + ")"; - } - }; + struct Plane : public WeirdEngine::IMathExpression + { + protected: + std::shared_ptr m_h; + + public: + static constexpr uint8_t HEIGHT = 0; + + Plane(std::shared_ptr h) + : m_h(std::move(h)) + { + } + + float getValue(const float* parameters) const override + { + return 1000.0f; + } + std::string print() const override + { + return "fPlane(p, vec3(0.0, 1.0, 0.0), " + m_h->print() + ")\n"; + } + }; + + struct PerlinPlane : public WeirdEngine::IMathExpression + { + public: + PerlinPlane(float height) + : m_height(height) + { + } + + float getValue(const float* parameters) const override + { + return 1000.0f; + } + std::string print() const override + { + return "fPlane(\n" + " p, vec3(0.0, 1.0, 0.0), 3.0 + (0.5 * perlin(1.2 * vec2(p.x, p.z))) + (3.0 * perlin(0.2 * " + "vec2(p.x, p.z))))\n"; + } + + private: + float m_height; + }; + + struct Box : public WeirdEngine::IMathExpression + { + protected: + std::shared_ptr m_px, m_py, m_pz; + std::shared_ptr m_sx, m_sy, m_sz; + + public: + static constexpr uint8_t POS_X = 0; + static constexpr uint8_t POS_Y = 1; + static constexpr uint8_t POS_Z = 2; + static constexpr uint8_t SIZE_X = 3; + static constexpr uint8_t SIZE_Y = 4; + static constexpr uint8_t SIZE_Z = 5; + + Box(std::shared_ptr px, std::shared_ptr py, + std::shared_ptr pz, std::shared_ptr sx, + std::shared_ptr sy, std::shared_ptr sz) + : m_px(std::move(px)) + , m_py(std::move(py)) + , m_pz(std::move(pz)) + , m_sx(std::move(sx)) + , m_sy(std::move(sy)) + , m_sz(std::move(sz)) + { + } + + Box() // Legacy constructor for existing code compatibility + { + } + + float getValue(const float* parameters) const override + { + return 1000.0f; + } + std::string print() const override + { + if (m_px) + { + return "fBox(p - vec3(" + m_px->print() + ", " + m_py->print() + ", " + m_pz->print() + "), vec3(" + + m_sx->print() + ", " + m_sy->print() + ", " + m_sz->print() + "))"; + } + return "fBox(p - vec3(var0, var1, var2), vec3(var3, var4, var5))"; + } + }; + + struct Sphere : public WeirdEngine::IMathExpression + { + protected: + std::shared_ptr m_px, m_py, m_pz; + std::shared_ptr m_r; + + public: + static constexpr uint8_t POS_X = 0; + static constexpr uint8_t POS_Y = 1; + static constexpr uint8_t POS_Z = 2; + static constexpr uint8_t RADIUS = 3; + + Sphere(std::shared_ptr px, std::shared_ptr py, + std::shared_ptr pz, std::shared_ptr r) + : m_px(std::move(px)) + , m_py(std::move(py)) + , m_pz(std::move(pz)) + , m_r(std::move(r)) + { + } + + float getValue(const float* parameters) const override + { + return 1000.0f; + } + std::string print() const override + { + return "fSphere(p - vec3(" + m_px->print() + ", " + m_py->print() + ", " + m_pz->print() + "), " + + m_r->print() + ")"; + } + }; + + struct Cylinder : public WeirdEngine::IMathExpression + { + protected: + std::shared_ptr m_px, m_py, m_pz; + std::shared_ptr m_r, m_h; + + public: + static constexpr uint8_t POS_X = 0; + static constexpr uint8_t POS_Y = 1; + static constexpr uint8_t POS_Z = 2; + static constexpr uint8_t RADIUS = 3; + static constexpr uint8_t HEIGHT = 4; + + Cylinder(std::shared_ptr px, std::shared_ptr py, + std::shared_ptr pz, std::shared_ptr r, + std::shared_ptr h) + : m_px(std::move(px)) + , m_py(std::move(py)) + , m_pz(std::move(pz)) + , m_r(std::move(r)) + , m_h(std::move(h)) + { + } + + float getValue(const float* parameters) const override + { + return 1000.0f; + } + std::string print() const override + { + return "fCylinder(p - vec3(" + m_px->print() + ", " + m_py->print() + ", " + m_pz->print() + "), " + + m_r->print() + ", " + m_h->print() + ")"; + } + }; + + struct Torus : public WeirdEngine::IMathExpression + { + protected: + std::shared_ptr m_px, m_py, m_pz; + std::shared_ptr m_r1, m_r2; + + public: + static constexpr uint8_t POS_X = 0; + static constexpr uint8_t POS_Y = 1; + static constexpr uint8_t POS_Z = 2; + static constexpr uint8_t RADIUS_SMALL = 3; + static constexpr uint8_t RADIUS_LARGE = 4; + + Torus(std::shared_ptr px, std::shared_ptr py, + std::shared_ptr pz, std::shared_ptr r1, + std::shared_ptr r2) + : m_px(std::move(px)) + , m_py(std::move(py)) + , m_pz(std::move(pz)) + , m_r1(std::move(r1)) + , m_r2(std::move(r2)) + { + } + + float getValue(const float* parameters) const override + { + return 1000.0f; + } + std::string print() const override + { + return "fTorus(p - vec3(" + m_px->print() + ", " + m_py->print() + ", " + m_pz->print() + "), " + + m_r1->print() + ", " + m_r2->print() + ")"; + } + }; + + struct Capsule : public WeirdEngine::IMathExpression + { + protected: + std::shared_ptr m_px, m_py, m_pz; + std::shared_ptr m_r, m_h; + + public: + static constexpr uint8_t POS_X = 0; + static constexpr uint8_t POS_Y = 1; + static constexpr uint8_t POS_Z = 2; + static constexpr uint8_t RADIUS = 3; + static constexpr uint8_t HEIGHT = 4; + + Capsule(std::shared_ptr px, std::shared_ptr py, + std::shared_ptr pz, std::shared_ptr r, + std::shared_ptr h) + : m_px(std::move(px)) + , m_py(std::move(py)) + , m_pz(std::move(pz)) + , m_r(std::move(r)) + , m_h(std::move(h)) + { + } + + float getValue(const float* parameters) const override + { + return 1000.0f; + } + std::string print() const override + { + return "fCapsule(p - vec3(" + m_px->print() + ", " + m_py->print() + ", " + m_pz->print() + "), " + + m_r->print() + ", " + m_h->print() + ")"; + } + }; } // namespace WeirdEngine::Primitives3D diff --git a/include/weird-engine/math/ShapeMacro.h b/include/weird-engine/math/ShapeMacro.h index 15c5bea..ec22053 100644 --- a/include/weird-engine/math/ShapeMacro.h +++ b/include/weird-engine/math/ShapeMacro.h @@ -1,20 +1,20 @@ #pragma once #include +#include #include #include #include #include #include -#include -#include "weird-engine/vec.h" #include "CompiledMathExpressions.h" #include "MathExpressions.h" +#include "weird-engine/vec.h" namespace WeirdEngine { - struct ShapeMacro : IMathExpression + struct ShapeMacro : IMathExpression { protected: static constexpr uint8_t VALUES_SIZE = 11; @@ -22,7 +22,6 @@ namespace WeirdEngine static constexpr uint8_t WORLD_X = 9; static constexpr uint8_t WORLD_Y = 10; - public: ShapeMacro() {} @@ -34,4 +33,4 @@ namespace WeirdEngine [[nodiscard]] std::string print() const override = 0; }; -} +} // namespace WeirdEngine diff --git a/include/weird-engine/systems/PhysicsInteractionSystem.h b/include/weird-engine/systems/PhysicsInteractionSystem.h index 7f3c695..a31adab 100644 --- a/include/weird-engine/systems/PhysicsInteractionSystem.h +++ b/include/weird-engine/systems/PhysicsInteractionSystem.h @@ -2,7 +2,6 @@ #include "weird-engine/ecs/ECS.h" #include "weird-engine/Input.h" - namespace WeirdEngine { using namespace ECS; @@ -38,22 +37,46 @@ namespace WeirdEngine inline bool getLeftClickDown() { - if (Input::GetMouseButtonDown(Input::LeftClick)) { m_usingController = false; return true; } - if (Input::GetGamepadButtonDown(Input::GamepadButton::RightShoulder)) { m_usingController = true; return true; } + if (Input::GetMouseButtonDown(Input::LeftClick)) + { + m_usingController = false; + return true; + } + if (Input::GetGamepadButtonDown(Input::GamepadButton::RightShoulder)) + { + m_usingController = true; + return true; + } return false; } inline bool getRightClickDown() { - if (Input::GetMouseButtonDown(Input::RightClick)) { m_usingController = false; return true; } - if (Input::GetGamepadButtonDown(Input::GamepadButton::LeftShoulder)) { m_usingController = true; return true; } + if (Input::GetMouseButtonDown(Input::RightClick)) + { + m_usingController = false; + return true; + } + if (Input::GetGamepadButtonDown(Input::GamepadButton::LeftShoulder)) + { + m_usingController = true; + return true; + } return false; } inline bool getRightClickUp() { - if (Input::GetMouseButtonUp(Input::RightClick)) { m_usingController = false; return true; } - if (Input::GetGamepadButtonUp(Input::GamepadButton::LeftShoulder)) { m_usingController = true; return true; } + if (Input::GetMouseButtonUp(Input::RightClick)) + { + m_usingController = false; + return true; + } + if (Input::GetGamepadButtonUp(Input::GamepadButton::LeftShoulder)) + { + m_usingController = true; + return true; + } return false; } @@ -96,10 +119,14 @@ namespace WeirdEngine dot.materialId = m_currentMaterial + 4; RigidBody2D& rb = ecs.addComponent(entity); - if (!m_usingController) { + if (!m_usingController) + { rb.pendingImpulseForce += 1000.0f * vec2(Input::GetMouseDeltaX(), -Input::GetMouseDeltaY()); - } else { - rb.pendingImpulseForce += 10.0f * vec2(Input::GetGamepadAxis(Input::GamepadAxis::RightX), -Input::GetGamepadAxis(Input::GamepadAxis::RightY)); + } + else + { + rb.pendingImpulseForce += 10.0f * vec2(Input::GetGamepadAxis(Input::GamepadAxis::RightX), + -Input::GetGamepadAxis(Input::GamepadAxis::RightY)); } m_firstIdInSpring = INVALID_ENTITY; @@ -222,7 +249,6 @@ namespace WeirdEngine { auto rbs = ecs.getComponentArray(); - float minD2 = 1.0f; vec2 mouseInWorld = getMousePositionInWorld(ecs); @@ -241,14 +267,12 @@ namespace WeirdEngine } } - - if(m_dragId != INVALID_ENTITY) + if (m_dragId != INVALID_ENTITY) { auto& rb = ecs.getComponent(m_dragId); rb.isFixed = true; rbs->setEntityDirty(m_dragId, true); } - } if (getRightClickUp()) @@ -257,10 +281,14 @@ namespace WeirdEngine { auto& rb = ecs.getComponent(m_dragId); rb.isFixed = false; - if (!m_usingController) { + if (!m_usingController) + { rb.pendingImpulseForce += 1000.0f * vec2(Input::GetMouseDeltaX(), -Input::GetMouseDeltaY()); - } else { - rb.pendingImpulseForce += 1000.0f * vec2(Input::GetGamepadAxis(Input::GamepadAxis::RightX), -Input::GetGamepadAxis(Input::GamepadAxis::RightY)); + } + else + { + rb.pendingImpulseForce += 1000.0f * vec2(Input::GetGamepadAxis(Input::GamepadAxis::RightX), + -Input::GetGamepadAxis(Input::GamepadAxis::RightY)); } ecs.getComponentArray()->setEntityDirty(m_dragId, true); @@ -338,7 +366,7 @@ namespace WeirdEngine // float maxDistance = (0.5f * dragDistance); constexpr float MAX_DISTANCE = 5.0f; - if(distance <= MAX_DISTANCE) + if (distance <= MAX_DISTANCE) { vec2 force = 1.0f * glm::clamp(MAX_DISTANCE - distance, 0.0f, 1.0f) * direction; diff --git a/include/weird-engine/systems/PlayerMovementSystem.h b/include/weird-engine/systems/PlayerMovementSystem.h index f0776c2..c395a51 100644 --- a/include/weird-engine/systems/PlayerMovementSystem.h +++ b/include/weird-engine/systems/PlayerMovementSystem.h @@ -74,8 +74,10 @@ namespace WeirdEngine // Handles key inputs float leftY = Input::GetGamepadAxis(Input::GamepadAxis::LeftY); float leftX = Input::GetGamepadAxis(Input::GamepadAxis::LeftX); - if (std::abs(leftY) < 0.1f) leftY = 0.0f; - if (std::abs(leftX) < 0.1f) leftX = 0.0f; + if (std::abs(leftY) < 0.1f) + leftY = 0.0f; + if (std::abs(leftX) < 0.1f) + leftX = 0.0f; if (!Input::GetKey(Input::LeftCtrl)) { @@ -134,10 +136,11 @@ namespace WeirdEngine float leftTrigger = Input::GetGamepadAxis(Input::GamepadAxis::LeftTrigger); float zoomInput = rightTrigger - leftTrigger; - + if (std::abs(zoomInput) > 0.1f) { - targetPosition += flyComponent.scrollSpeed * flyComponent.speed * zoomInput * 20.0f * safeDelta * t.rotation; + targetPosition += flyComponent.scrollSpeed * flyComponent.speed * zoomInput * 20.0f * + safeDelta * t.rotation; } if (targetPosition.z < 5.0f) @@ -184,8 +187,10 @@ namespace WeirdEngine // Handles key inputs float leftY = Input::GetGamepadAxis(Input::GamepadAxis::LeftY); float leftX = Input::GetGamepadAxis(Input::GamepadAxis::LeftX); - if (std::abs(leftY) < 0.1f) leftY = 0.0f; - if (std::abs(leftX) < 0.1f) leftX = 0.0f; + if (std::abs(leftY) < 0.1f) + leftY = 0.0f; + if (std::abs(leftX) < 0.1f) + leftX = 0.0f; if (Input::GetKey(Input::W) || leftY < -0.1f) { @@ -263,8 +268,10 @@ namespace WeirdEngine float rightX = Input::GetGamepadAxis(Input::GamepadAxis::RightX); float rightY = Input::GetGamepadAxis(Input::GamepadAxis::RightY); - if (std::abs(rightX) < 0.1f) rightX = 0.0f; - if (std::abs(rightY) < 0.1f) rightY = 0.0f; + if (std::abs(rightX) < 0.1f) + rightX = 0.0f; + if (std::abs(rightY) < 0.1f) + rightY = 0.0f; float rotX = 0.0f; float rotY = 0.0f; diff --git a/include/weird-engine/systems/SDFRenderSystem.h b/include/weird-engine/systems/SDFRenderSystem.h index 4c02fd3..eef2d74 100644 --- a/include/weird-engine/systems/SDFRenderSystem.h +++ b/include/weird-engine/systems/SDFRenderSystem.h @@ -18,7 +18,7 @@ namespace WeirdEngine SDFRenderSystemContext() : font(FONTS_PATH "small.bmp", 3, 4, 1, - "ABCDEFGHIJKLMNOPQRSTUVWXYZ[]{}abcdefghijklmnopqrstuvwxyz\\/<>1234567890!\" &_*()__-=_+?|.,:;") + "ABCDEFGHIJKLMNOPQRSTUVWXYZ[]{}abcdefghijklmnopqrstuvwxyz\\/<>1234567890!\" &_*()__-=_+?|.,:;") { } }; @@ -36,27 +36,29 @@ namespace WeirdEngine } uint32_t textDots = 0; - ecs.forEach([&](Entity entity, TextClass& text) { - if (ecs.isComponentDirty(text)) + ecs.forEach( + [&](Entity entity, TextClass& text) { - // Update dot count - text.bufferedDotCount = 0; - - for (const auto& c : text.text) + if (ecs.isComponentDirty(text)) { - text.bufferedDotCount += ctx.font.getCharData(c).dotCount; - } + // Update dot count + text.bufferedDotCount = 0; - int charCount = text.text.length(); - text.width = (charCount * ctx.font.getCharWidth() * 2 * ctx.dotRadious) + - ((charCount - 1) * ctx.charSpacing); - text.height = ctx.font.getCharHeight() * 2 * ctx.dotRadious; + for (const auto& c : text.text) + { + text.bufferedDotCount += ctx.font.getCharData(c).dotCount; + } - ecs.setComponentDirty(text, false); - } + int charCount = text.text.length(); + text.width = (charCount * ctx.font.getCharWidth() * 2 * ctx.dotRadious) + + ((charCount - 1) * ctx.charSpacing); + text.height = ctx.font.getCharHeight() * 2 * ctx.dotRadious; + + ecs.setComponentDirty(text, false); + } - textDots += text.bufferedDotCount; - }); + textDots += text.bufferedDotCount; + }); uint32_t dotCount = normalDots + textDots; @@ -87,87 +89,94 @@ namespace WeirdEngine // Process DotClass instances int dotIdx = 0; - ecs.forEach([&](Entity entity, DotClass& dotComp, Transform& t) { - data[dotIdx].x = t.position.x; - data[dotIdx].y = t.position.y; - data[dotIdx].z = t.position.z; - data[dotIdx].w = dotComp.materialId; - dotIdx++; - }); + ecs.forEach( + [&](Entity entity, DotClass& dotComp, Transform& t) + { + data[dotIdx].x = t.position.x; + data[dotIdx].y = t.position.y; + data[dotIdx].z = t.position.z; + data[dotIdx].w = dotComp.materialId; + dotIdx++; + }); float charWidth = ctx.font.getCharWidth() * 2 * ctx.dotRadious; // should be 40 // Text int dotIndex = 0; - ecs.forEach([&](Entity entity, TextClass& text, Transform& t) { - int charCount = text.text.length(); - - float horizontalOffset = 0.0f; - switch (text.horizontalAlignment) + ecs.forEach( + [&](Entity entity, TextClass& text, Transform& t) { - case TextRenderer::HorizontalAlignment::Left: - horizontalOffset = 0.0f; - break; - case TextRenderer::HorizontalAlignment::Center: - horizontalOffset = -text.width * 0.5f; - break; - case TextRenderer::HorizontalAlignment::Right: - horizontalOffset = -text.width; - break; - } + int charCount = text.text.length(); - float verticalOffset = 0.0f; - switch (text.verticalAlignment) - { - case TextRenderer::VerticalAlignment::Bottom: - verticalOffset = 0.0f; - break; - case TextRenderer::VerticalAlignment::Center: - verticalOffset = -text.height * 0.5f; - break; - case TextRenderer::VerticalAlignment::Top: - verticalOffset = -text.height; - break; - } + float horizontalOffset = 0.0f; + switch (text.horizontalAlignment) + { + case TextRenderer::HorizontalAlignment::Left: + horizontalOffset = 0.0f; + break; + case TextRenderer::HorizontalAlignment::Center: + horizontalOffset = -text.width * 0.5f; + break; + case TextRenderer::HorizontalAlignment::Right: + horizontalOffset = -text.width; + break; + } + + float verticalOffset = 0.0f; + switch (text.verticalAlignment) + { + case TextRenderer::VerticalAlignment::Bottom: + verticalOffset = 0.0f; + break; + case TextRenderer::VerticalAlignment::Center: + verticalOffset = -text.height * 0.5f; + break; + case TextRenderer::VerticalAlignment::Top: + verticalOffset = -text.height; + break; + } - vec2 alignmentOffset(horizontalOffset, verticalOffset); + vec2 alignmentOffset(horizontalOffset, verticalOffset); - for (size_t c = 0; c < charCount; c++) - { - auto charData = ctx.font.getCharData(text.text[c]); - for (size_t j = 0; j < charData.dotCount; j++) + for (size_t c = 0; c < charCount; c++) { - int idx = normalDots + dotIndex; - dotIndex++; - - vec2 charOffset = vec2(((charWidth + ctx.charSpacing) * c) + ctx.dotRadious, - ctx.dotRadious); // TODO: different lines - vec2 scaledDotPosition = 2 * ctx.dotRadious * charData.positions[j]; - vec2 position = (vec2)t.position + charOffset + scaledDotPosition + alignmentOffset; // + letter - data[idx].x = position.x; - data[idx].y = position.y; - data[idx].z = 1.0f; - data[idx].w = text.material; + auto charData = ctx.font.getCharData(text.text[c]); + for (size_t j = 0; j < charData.dotCount; j++) + { + int idx = normalDots + dotIndex; + dotIndex++; + + vec2 charOffset = vec2(((charWidth + ctx.charSpacing) * c) + ctx.dotRadious, + ctx.dotRadious); // TODO: different lines + vec2 scaledDotPosition = 2 * ctx.dotRadious * charData.positions[j]; + vec2 position = + (vec2)t.position + charOffset + scaledDotPosition + alignmentOffset; // + letter + data[idx].x = position.x; + data[idx].y = position.y; + data[idx].z = 1.0f; + data[idx].w = text.material; + } } - } - }); + }); // Process ShapeClass instances int shapeIdx = 0; - ecs.forEach([&](Entity entity, ShapeClass& shapeComp) { - // Assuming ShapeClass has m_parameters[0] through m_parameters[7] - // Make sure your ShapeClass provides these members. - data[dotCount + (2 * shapeIdx)].x = shapeComp.parameters[0]; - data[dotCount + (2 * shapeIdx)].y = shapeComp.parameters[1]; - data[dotCount + (2 * shapeIdx)].z = shapeComp.parameters[2]; - data[dotCount + (2 * shapeIdx)].w = shapeComp.parameters[3]; - - data[dotCount + (2 * shapeIdx) + 1].x = shapeComp.parameters[4]; - data[dotCount + (2 * shapeIdx) + 1].y = shapeComp.parameters[5]; - data[dotCount + (2 * shapeIdx) + 1].z = shapeComp.parameters[6]; - data[dotCount + (2 * shapeIdx) + 1].w = shapeComp.parameters[7]; - shapeIdx++; - }); + ecs.forEach( + [&](Entity entity, ShapeClass& shapeComp) + { + // Assuming ShapeClass has m_parameters[0] through m_parameters[7] + // Make sure your ShapeClass provides these members. + data[dotCount + (2 * shapeIdx)].x = shapeComp.parameters[0]; + data[dotCount + (2 * shapeIdx)].y = shapeComp.parameters[1]; + data[dotCount + (2 * shapeIdx)].z = shapeComp.parameters[2]; + data[dotCount + (2 * shapeIdx)].w = shapeComp.parameters[3]; + + data[dotCount + (2 * shapeIdx) + 1].x = shapeComp.parameters[4]; + data[dotCount + (2 * shapeIdx) + 1].y = shapeComp.parameters[5]; + data[dotCount + (2 * shapeIdx) + 1].z = shapeComp.parameters[6]; + data[dotCount + (2 * shapeIdx) + 1].w = shapeComp.parameters[7]; + shapeIdx++; + }); } } // namespace SDFRenderSystem diff --git a/include/weird-engine/systems/SDFShaderGenerationSystem.h b/include/weird-engine/systems/SDFShaderGenerationSystem.h index f5dc4ef..ee8bdef 100644 --- a/include/weird-engine/systems/SDFShaderGenerationSystem.h +++ b/include/weird-engine/systems/SDFShaderGenerationSystem.h @@ -1,4 +1,4 @@ - #pragma once +#pragma once #include "weird-engine/ecs/ECS.h" #include "weird-engine/Input.h" @@ -6,6 +6,7 @@ #include "weird-renderer/resources/Shader.h" #include +#include #include #include #include @@ -14,7 +15,6 @@ #include #include #include -#include namespace WeirdEngine::SDFShaderGenerationSystem { @@ -33,7 +33,8 @@ namespace WeirdEngine::SDFShaderGenerationSystem ctx.shapesNeedUpdate = false; - auto toGlslFloat = [](float value) { + auto toGlslFloat = [](float value) + { std::ostringstream ss; ss << std::fixed << std::setprecision(6) << value; return ss.str(); @@ -60,8 +61,9 @@ namespace WeirdEngine::SDFShaderGenerationSystem orderedIndices.push_back(i); } - std::stable_sort(orderedIndices.begin(), orderedIndices.end(), [&](size_t a, size_t b) - { return componentArray->getDataAtIdx(a).groupIdx < componentArray->getDataAtIdx(b).groupIdx; }); + std::stable_sort( + orderedIndices.begin(), orderedIndices.end(), [&](size_t a, size_t b) + { return componentArray->getDataAtIdx(a).groupIdx < componentArray->getDataAtIdx(b).groupIdx; }); for (size_t idx = 0; idx < componentArray->getSize() + 1; idx++) { @@ -75,7 +77,8 @@ namespace WeirdEngine::SDFShaderGenerationSystem { oss << "if(" << groupDistanceVariable << " <= max(minDist, 0.0)){ finalMaterialId = currentGroupColor;}\n"; - oss << "if(" << groupDistanceVariable << " <= minDist) { globalBlend = " << groupBlendVariable << "; }\n"; + oss << "if(" << groupDistanceVariable << " <= minDist) { globalBlend = " << groupBlendVariable + << "; }\n"; oss << "if(minDist > " << groupDistanceVariable << "){ minDist = " << groupDistanceVariable << ";}\n"; } @@ -100,24 +103,26 @@ namespace WeirdEngine::SDFShaderGenerationSystem oss << "vec4 parameters1 = texelFetch(t_shapeBuffer, ivec2((idx + 1) % 16384, (idx + 1) / 16384), 0);\n"; auto fragmentCode = sdfs[shape.distanceFieldId]->print(); - + // Replace integer literals with floats manually to avoid std::regex ABI issues std::string resultStr; resultStr.reserve(fragmentCode.size() * 2); - for (size_t k = 0; k < fragmentCode.size(); ) + for (size_t k = 0; k < fragmentCode.size();) { - bool isPrevValid = (k == 0) || ( !std::isalnum(fragmentCode[k-1]) && fragmentCode[k-1] != '_' && fragmentCode[k-1] != '.' ); - + bool isPrevValid = (k == 0) || (!std::isalnum(fragmentCode[k - 1]) && fragmentCode[k - 1] != '_' && + fragmentCode[k - 1] != '.'); + if (isPrevValid && std::isdigit(fragmentCode[k])) { size_t start = k; while (k < fragmentCode.size() && std::isdigit(fragmentCode[k])) k++; - - bool isNextValid = (k == fragmentCode.size()) || ( !std::isalnum(fragmentCode[k]) && fragmentCode[k] != '_' && fragmentCode[k] != '.' ); - + + bool isNextValid = (k == fragmentCode.size()) || (!std::isalnum(fragmentCode[k]) && + fragmentCode[k] != '_' && fragmentCode[k] != '.'); + resultStr.append(fragmentCode, start, k - start); - + if (isNextValid) resultStr.append(".0"); } @@ -184,8 +189,12 @@ namespace WeirdEngine::SDFShaderGenerationSystem oss << arrayPreamble; oss << "float dist = " << fragmentCode << ";\n"; - - // 3D shader uses this to apply dithering to the distance of shapes with transparent materials, this creates paterns where the shape is partially rendered, which creates the illusion of transparency without needing to sort objects or use alpha blending, which can be costly in raymarching shaders. The 2D shader ignores this step for now, but it could be used in the future if we decide to add transparency to 2D shapes as well. + + // 3D shader uses this to apply dithering to the distance of shapes with transparent materials, this creates + // paterns where the shape is partially rendered, which creates the illusion of transparency without needing + // to sort objects or use alpha blending, which can be costly in raymarching shaders. The 2D shader ignores + // this step for now, but it could be used in the future if we decide to add transparency to 2D shapes as + // well. oss << "dist = modifyDistanceBasedOnMaterial(dist, " << shape.material << ", idx);\n"; oss << "float currentMinDistance = " << (globalEffect ? "minDist" : groupDistanceVariable) << ";\n"; @@ -213,8 +222,8 @@ namespace WeirdEngine::SDFShaderGenerationSystem } case CombinationType::SmoothAddition: { - oss << "vec2 res = fOpUnionSoft_blend(currentMinDistance, dist, " - << toGlslFloat(shape.smoothFactor) << ");\n"; + oss << "vec2 res = fOpUnionSoft_blend(currentMinDistance, dist, " << toGlslFloat(shape.smoothFactor) + << ");\n"; oss << "if (res.y > 0.0) { currentBlend = max(currentBlend, res.y); }\n"; oss << "else if (dist < currentMinDistance) { currentBlend = 0.0; }\n"; oss << "currentMinDistance = res.x;\n"; diff --git a/include/weird-physics/Simulation2D.h b/include/weird-physics/Simulation2D.h index b7400be..22ba11c 100644 --- a/include/weird-physics/Simulation2D.h +++ b/include/weird-physics/Simulation2D.h @@ -134,7 +134,8 @@ namespace WeirdEngine bool isFixed(SimulationID id); // Performance Stats - struct PerformanceStats { + struct PerformanceStats + { double timePerStepMs = 0.0; double simulationRatio = 0.0; double broadPhaseMs = 0.0; @@ -172,7 +173,6 @@ namespace WeirdEngine SimulationID raycast(vec2 pos); float raymarch(vec2 pos, vec2 direction, const float FAR = 100.0f); float raymarch(vec2 pos, vec2 direction, const float FAR, int& closestShape); - void setGravity(float gravity) { diff --git a/include/weird-physics/components/CustomShapeManager.h b/include/weird-physics/components/CustomShapeManager.h index 5df3ded..b002b06 100644 --- a/include/weird-physics/components/CustomShapeManager.h +++ b/include/weird-physics/components/CustomShapeManager.h @@ -14,11 +14,13 @@ namespace WeirdEngine public: CustomShapeManager(Simulation2D& simulation, SDFRenderSystemContext& renderContext) - : m_simulation(&simulation), m_renderContext(&renderContext) + : m_simulation(&simulation) + , m_renderContext(&renderContext) { } - // Can't add the shape to the simulation here because the component data is not initialized yet, so we will add it in the next update of the PhysicsSystem2D + // Can't add the shape to the simulation here because the component data is not initialized yet, so we will add + // it in the next update of the PhysicsSystem2D void handleNewComponent(Entity entity, CustomShape& component) override { m_renderContext->shapesNeedUpdate = true; @@ -37,8 +39,7 @@ namespace WeirdEngine class CustomUIShapeManager : public ComponentManager { private: - SDFRenderSystemContext* m_renderContext; - + SDFRenderSystemContext* m_renderContext; public: CustomUIShapeManager(SDFRenderSystemContext& context) diff --git a/include/weird-physics/components/DistanceConstraint.h b/include/weird-physics/components/DistanceConstraint.h index f4d4943..101bed0 100644 --- a/include/weird-physics/components/DistanceConstraint.h +++ b/include/weird-physics/components/DistanceConstraint.h @@ -7,10 +7,12 @@ namespace WeirdEngine struct DistanceConstraint { DistanceConstraint() - : entityA(INVALID_ENTITY), entityB(INVALID_ENTITY), distance(1.0f) {}; - + : entityA(INVALID_ENTITY) + , entityB(INVALID_ENTITY) + , distance(1.0f) {}; + Entity entityA; Entity entityB; float distance; }; -} +} // namespace WeirdEngine diff --git a/include/weird-physics/components/DistanceConstraintManager.h b/include/weird-physics/components/DistanceConstraintManager.h index b10e23c..7a7d352 100644 --- a/include/weird-physics/components/DistanceConstraintManager.h +++ b/include/weird-physics/components/DistanceConstraintManager.h @@ -1,9 +1,9 @@ #pragma once #include "weird-engine/ecs/ComponentManager.h" -#include "weird-physics/Simulation2D.h" #include "weird-physics/components/DistanceConstraint.h" #include "weird-physics/components/RigidBody.h" +#include "weird-physics/Simulation2D.h" namespace WeirdEngine { @@ -24,9 +24,9 @@ namespace WeirdEngine { auto componentArray = std::static_pointer_cast>(m_componentArray); DistanceConstraint& removedConstraint = componentArray->getDataFromEntity(entity); - - if (m_ecs->hasComponent(removedConstraint.entityA) && - m_ecs->hasComponent(removedConstraint.entityB)) + + if (m_ecs->hasComponent(removedConstraint.entityA) && + m_ecs->hasComponent(removedConstraint.entityB)) { auto simIdA = m_ecs->getComponent(removedConstraint.entityA).simulationId; auto simIdB = m_ecs->getComponent(removedConstraint.entityB).simulationId; diff --git a/include/weird-physics/components/GlobalPhysicsSettings.h b/include/weird-physics/components/GlobalPhysicsSettings.h index 74f4d53..7fdd86e 100644 --- a/include/weird-physics/components/GlobalPhysicsSettings.h +++ b/include/weird-physics/components/GlobalPhysicsSettings.h @@ -7,9 +7,10 @@ namespace WeirdEngine struct GlobalPhysicsSettings { GlobalPhysicsSettings() - : gravity(0.0f), damping(0.05f) {}; - + : gravity(0.0f) + , damping(0.05f) {}; + float gravity; float damping; }; -} +} // namespace WeirdEngine diff --git a/include/weird-physics/components/RigidBody.h b/include/weird-physics/components/RigidBody.h index a169796..9a4cd82 100644 --- a/include/weird-physics/components/RigidBody.h +++ b/include/weird-physics/components/RigidBody.h @@ -13,7 +13,10 @@ namespace WeirdEngine struct RigidBody2D { RigidBody2D() - : simulationId(-1), velocity(0.0f, 0.0f), pendingImpulseForce(0.0f, 0.0f), isFixed(false) {}; + : simulationId(-1) + , velocity(0.0f, 0.0f) + , pendingImpulseForce(0.0f, 0.0f) + , isFixed(false) {}; unsigned int simulationId; glm::vec2 velocity; glm::vec2 pendingImpulseForce; diff --git a/include/weird-physics/components/Spring.h b/include/weird-physics/components/Spring.h index 80a3692..673c0b9 100644 --- a/include/weird-physics/components/Spring.h +++ b/include/weird-physics/components/Spring.h @@ -7,11 +7,14 @@ namespace WeirdEngine struct Spring { Spring() - : entityA(INVALID_ENTITY), entityB(INVALID_ENTITY), stiffness(1.0f), restDistance(1.0f) {}; - + : entityA(INVALID_ENTITY) + , entityB(INVALID_ENTITY) + , stiffness(1.0f) + , restDistance(1.0f) {}; + Entity entityA; Entity entityB; float stiffness; float restDistance; }; -} +} // namespace WeirdEngine diff --git a/include/weird-physics/components/SpringManager.h b/include/weird-physics/components/SpringManager.h index fd76738..ea60ffc 100644 --- a/include/weird-physics/components/SpringManager.h +++ b/include/weird-physics/components/SpringManager.h @@ -1,9 +1,9 @@ #pragma once #include "weird-engine/ecs/ComponentManager.h" -#include "weird-physics/Simulation2D.h" -#include "weird-physics/components/Spring.h" #include "weird-physics/components/RigidBody.h" +#include "weird-physics/components/Spring.h" +#include "weird-physics/Simulation2D.h" namespace WeirdEngine { @@ -24,9 +24,9 @@ namespace WeirdEngine { auto componentArray = std::static_pointer_cast>(m_componentArray); Spring& removedSpring = componentArray->getDataFromEntity(entity); - - if (m_ecs->hasComponent(removedSpring.entityA) && - m_ecs->hasComponent(removedSpring.entityB)) + + if (m_ecs->hasComponent(removedSpring.entityA) && + m_ecs->hasComponent(removedSpring.entityB)) { auto simIdA = m_ecs->getComponent(removedSpring.entityA).simulationId; auto simIdB = m_ecs->getComponent(removedSpring.entityB).simulationId; diff --git a/include/weird-renderer/components/Button.h b/include/weird-renderer/components/Button.h index 39f64cd..5e36b2c 100644 --- a/include/weird-renderer/components/Button.h +++ b/include/weird-renderer/components/Button.h @@ -1,6 +1,5 @@ #pragma once - #include namespace WeirdEngine diff --git a/include/weird-renderer/components/MeshRenderer.h b/include/weird-renderer/components/MeshRenderer.h index 5701277..fa78f09 100644 --- a/include/weird-renderer/components/MeshRenderer.h +++ b/include/weird-renderer/components/MeshRenderer.h @@ -18,6 +18,7 @@ namespace WeirdEngine : mesh(mesh) {}; MeshRenderer(MeshID mesh, int materialIndex) - : mesh(mesh), materialIndex(materialIndex) {}; + : mesh(mesh) + , materialIndex(materialIndex) {}; }; } // namespace WeirdEngine diff --git a/include/weird-renderer/components/TextRenderer.h b/include/weird-renderer/components/TextRenderer.h index 442a9b3..e9c1b4a 100644 --- a/include/weird-renderer/components/TextRenderer.h +++ b/include/weird-renderer/components/TextRenderer.h @@ -1,7 +1,6 @@ #pragma once #include - namespace WeirdEngine { struct TextRenderer diff --git a/include/weird-renderer/core/Display.h b/include/weird-renderer/core/Display.h index a684210..2e596ce 100644 --- a/include/weird-renderer/core/Display.h +++ b/include/weird-renderer/core/Display.h @@ -80,8 +80,6 @@ namespace WeirdEngine vec4(0.4f, 0.25f, 0.1f, 1.0f) // Brown }; - - std::string windowTitle = "Weird Engine"; }; } // namespace WeirdRenderer diff --git a/include/weird-renderer/core/Renderer.h b/include/weird-renderer/core/Renderer.h index 8da2677..430ee39 100644 --- a/include/weird-renderer/core/Renderer.h +++ b/include/weird-renderer/core/Renderer.h @@ -5,10 +5,10 @@ #include "weird-renderer/audio/AudioEngine.h" #include "weird-renderer/core/Display.h" +#include "weird-renderer/core/MeshRenderPipeline.h" #include "weird-renderer/core/RenderTarget.h" #include "weird-renderer/core/SDF2DRenderPipeline.h" #include "weird-renderer/core/SDF3DRenderPipeline.h" -#include "weird-renderer/core/MeshRenderPipeline.h" #include "weird-renderer/core/SDLInitializer.h" #include "weird-renderer/resources/DataBuffer.h" diff --git a/include/weird-renderer/core/SDF2DRenderPipeline.h b/include/weird-renderer/core/SDF2DRenderPipeline.h index 8586427..67faf09 100644 --- a/include/weird-renderer/core/SDF2DRenderPipeline.h +++ b/include/weird-renderer/core/SDF2DRenderPipeline.h @@ -1,5 +1,6 @@ #pragma once +#include "weird-engine/Background.h" #include "weird-engine/vec.h" #include "weird-renderer/core/RenderPlane.h" #include "weird-renderer/core/RenderTarget.h" @@ -7,7 +8,6 @@ #include "weird-renderer/resources/Shader.h" #include "weird-renderer/resources/Texture.h" #include "weird-renderer/scene/Camera.h" -#include "weird-engine/Background.h" #include namespace WeirdEngine @@ -119,12 +119,15 @@ namespace WeirdEngine DataBuffer m_gridIndicesBuffer; // Reusable scratch buffers for grid building — allocated once, reused every frame - struct ObjBounds { int minX, minY, maxX, maxY; }; - std::vector m_gridObjBounds; - std::vector m_gridCellCounts; - std::vector m_gridCellOffsets; - std::vector m_gridHeader; - std::vector m_gridIndices; + struct ObjBounds + { + int minX, minY, maxX, maxY; + }; + std::vector m_gridObjBounds; + std::vector m_gridCellCounts; + std::vector m_gridCellOffsets; + std::vector m_gridHeader; + std::vector m_gridIndices; glm::mat4 m_oldCameraMatrix; glm::mat4 @@ -134,10 +137,15 @@ namespace WeirdEngine bool horizontal = true; glm::vec3 cameraPositionChange = glm::vec3(0.0f); - struct GridInfo { float minX, minY, stepX, stepY; int gridCols, gridRows, indexTexWidth, indexTexHeight; }; + struct GridInfo + { + float minX, minY, stepX, stepY; + int gridCols, gridRows, indexTexWidth, indexTexHeight; + }; GridInfo buildAccelerationGrid(vec4* shapeData, uint32_t dataSize, uint32_t shapeCount, - const Camera& camera); void renderDistanceField(vec4* shapeData, uint32_t dataSize, uint32_t shapeCount, const Camera& camera, - double time, double delta); + const Camera& camera); + void renderDistanceField(vec4* shapeData, uint32_t dataSize, uint32_t shapeCount, const Camera& camera, + double time, double delta); void applyJumpFloodCorrection(double time); void upscaleDistance(); void renderMaterialColors(const Camera& camera, double time, double delta); diff --git a/include/weird-renderer/core/SDF3DRenderPipeline.h b/include/weird-renderer/core/SDF3DRenderPipeline.h index 87dcaad..9c02834 100644 --- a/include/weird-renderer/core/SDF3DRenderPipeline.h +++ b/include/weird-renderer/core/SDF3DRenderPipeline.h @@ -1,5 +1,6 @@ #pragma once +#include "weird-engine/Material3D.h" #include "weird-engine/vec.h" #include "weird-renderer/core/Display.h" #include "weird-renderer/core/RenderPlane.h" @@ -9,7 +10,6 @@ #include "weird-renderer/resources/Texture.h" #include "weird-renderer/scene/Camera.h" #include "weird-renderer/scene/Light.h" -#include "weird-engine/Material3D.h" #include namespace WeirdEngine @@ -41,19 +41,10 @@ namespace WeirdEngine // Renders the SDF 3D scene using ray marching with path-traced accumulation. // GBuffer textures come from MeshRenderPipeline and allow the shader to composite // mesh surfaces with SDF lighting (SDFs cast light on meshes; meshes don't affect SDFs). - void render( - vec4* shapeData, uint32_t dataSize, uint32_t shapeCount, - const std::vector& lights, - const Camera& camera, - double time, - Texture& gbufferAlbedo, - Texture& gbufferWorldPos, - Texture& gbufferNormal, - Texture& gbufferMaterial, - Texture& gbufferDepth, - Texture& gbufferBackDepth, - const Material3D* materials - ); + void render(vec4* shapeData, uint32_t dataSize, uint32_t shapeCount, const std::vector& lights, + const Camera& camera, double time, Texture& gbufferAlbedo, Texture& gbufferWorldPos, + Texture& gbufferNormal, Texture& gbufferMaterial, Texture& gbufferDepth, + Texture& gbufferBackDepth, const Material3D* materials); RenderTarget& getRenderTarget(); Texture& getOutputTexture(); @@ -62,7 +53,10 @@ namespace WeirdEngine void free(); void showDebugUI(); - Config& getConfig() { return m_config; } + Config& getConfig() + { + return m_config; + } private: Config m_config; diff --git a/include/weird-renderer/core/WeirdFBDevEGL.h b/include/weird-renderer/core/WeirdFBDevEGL.h index fa51d7c..0487f69 100644 --- a/include/weird-renderer/core/WeirdFBDevEGL.h +++ b/include/weird-renderer/core/WeirdFBDevEGL.h @@ -1,23 +1,25 @@ #pragma once -namespace WeirdEngine { -namespace WeirdRenderer { - // Returns true if the fbdev EGL backend initialized successfully and is - // the active video path. Always returns false when the engine is built - // without WEIRD_USE_FBDEV_EGL support. - bool IsFBDevEGLActive(); +namespace WeirdEngine +{ + namespace WeirdRenderer + { + // Returns true if the fbdev EGL backend initialized successfully and is + // the active video path. Always returns false when the engine is built + // without WEIRD_USE_FBDEV_EGL support. + bool IsFBDevEGLActive(); - // Initializes EGL directly against the framebuffer device (ARM libMali - // fbdev winsys). Fills width/height with the native display resolution. - bool InitFBDevEGL(int& width, int& height); + // Initializes EGL directly against the framebuffer device (ARM libMali + // fbdev winsys). Fills width/height with the native display resolution. + bool InitFBDevEGL(int& width, int& height); - void ShutdownFBDevEGL(); + void ShutdownFBDevEGL(); - // Presents the current frame. No-op if fbdev EGL is not active. - void SwapFBDevBuffers(); + // Presents the current frame. No-op if fbdev EGL is not active. + void SwapFBDevBuffers(); - // GL function loader suitable for glad (uses eglGetProcAddress with a - // dlopen fallback on libGLESv2). - void* GetEGLProcAddress(const char* name); -} -} + // GL function loader suitable for glad (uses eglGetProcAddress with a + // dlopen fallback on libGLESv2). + void* GetEGLProcAddress(const char* name); + } // namespace WeirdRenderer +} // namespace WeirdEngine diff --git a/include/weird-renderer/resources/DataBuffer.h b/include/weird-renderer/resources/DataBuffer.h index 8120822..ff7de1b 100644 --- a/include/weird-renderer/resources/DataBuffer.h +++ b/include/weird-renderer/resources/DataBuffer.h @@ -1,8 +1,8 @@ #pragma once #include #include -#include #include +#include namespace WeirdEngine { @@ -74,17 +74,17 @@ namespace WeirdEngine } GLint previousActiveTexture = 0; - GLint previousTextureBinding2D = 0; - glGetIntegerv(GL_ACTIVE_TEXTURE, &previousActiveTexture); - glGetIntegerv(GL_TEXTURE_BINDING_2D, &previousTextureBinding2D); - glBindTexture(GL_TEXTURE_2D, m_texture); - glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA32F, texW, texH, 0, GL_RGBA, GL_FLOAT, uploadPtr); - 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); - glBindTexture(GL_TEXTURE_2D, static_cast(previousTextureBinding2D)); - glActiveTexture(static_cast(previousActiveTexture)); + GLint previousTextureBinding2D = 0; + glGetIntegerv(GL_ACTIVE_TEXTURE, &previousActiveTexture); + glGetIntegerv(GL_TEXTURE_BINDING_2D, &previousTextureBinding2D); + glBindTexture(GL_TEXTURE_2D, m_texture); + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA32F, texW, texH, 0, GL_RGBA, GL_FLOAT, uploadPtr); + 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); + glBindTexture(GL_TEXTURE_2D, static_cast(previousTextureBinding2D)); + glActiveTexture(static_cast(previousActiveTexture)); } template void uploadData(const T* data, size_t count) const @@ -104,7 +104,8 @@ namespace WeirdEngine glGetIntegerv(GL_ACTIVE_TEXTURE, &previousActiveTexture); glGetIntegerv(GL_TEXTURE_BINDING_2D, &previousTextureBinding2D); glBindTexture(GL_TEXTURE_2D, m_texture); - glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA32F, static_cast(width), static_cast(height), 0, GL_RGBA, GL_FLOAT, data); + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA32F, static_cast(width), static_cast(height), 0, + GL_RGBA, GL_FLOAT, data); 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); diff --git a/include/weird-renderer/resources/Font.h b/include/weird-renderer/resources/Font.h index 3c5aa1a..ec9545e 100644 --- a/include/weird-renderer/resources/Font.h +++ b/include/weird-renderer/resources/Font.h @@ -1,8 +1,8 @@ #pragma once +#include "weird-engine/Logger.h" #include "weird-engine/vec.h" #include -#include "weird-engine/Logger.h" #include #include #include diff --git a/include/weird-renderer/resources/Mesh.h b/include/weird-renderer/resources/Mesh.h index b565cb5..205f524 100644 --- a/include/weird-renderer/resources/Mesh.h +++ b/include/weird-renderer/resources/Mesh.h @@ -43,11 +43,13 @@ namespace WeirdEngine ~Mesh(); // Draws the mesh - void draw(Shader& shader, const Camera& camera, glm::vec3 translation = glm::vec3(0), glm::vec3 rotation = glm::vec3(0), glm::vec3 scale = glm::vec3(1), int materialIndex = 0) const; + void draw(Shader& shader, const Camera& camera, glm::vec3 translation = glm::vec3(0), + glm::vec3 rotation = glm::vec3(0), glm::vec3 scale = glm::vec3(1), int materialIndex = 0) const; // Draws the mesh - void drawInstances(Shader& shader, const Camera& camera, unsigned int instances, glm::vec3 translation = glm::vec3(0), - glm::vec3 rotation = glm::vec3(0), glm::vec3 scale = glm::vec3(1), int materialIndex = 0) const; + void drawInstances(Shader& shader, const Camera& camera, unsigned int instances, + glm::vec3 translation = glm::vec3(0), glm::vec3 rotation = glm::vec3(0), + glm::vec3 scale = glm::vec3(1), int materialIndex = 0) const; void free(); diff --git a/scripts/format.sh b/scripts/format.sh new file mode 100755 index 0000000..bc717b4 --- /dev/null +++ b/scripts/format.sh @@ -0,0 +1,12 @@ +#!/usr/bin/env bash + +# Change to the project root directory +cd "$(dirname "$0")/.." || exit 1 + +echo "Formatting project files..." + +find . -type d \( -name "third-party" -o -name "build" -o -name "build-muos" -o -name "dist-muos" -o -name ".git" \) -prune -o \ + -type f \( -name "*.h" -o -name "*.cpp" -o -name "*.glsl" -o -name "*.frag" -o -name "*.vert" \) \ + -exec clang-format -i {} + + +echo "Formatting complete." diff --git a/src/weird-engine/Logger.cpp b/src/weird-engine/Logger.cpp index 18279ff..1c8dc41 100644 --- a/src/weird-engine/Logger.cpp +++ b/src/weird-engine/Logger.cpp @@ -6,36 +6,39 @@ namespace WeirdEngine { - std::vector Logger::s_messages; - std::mutex Logger::s_mutex; - bool Logger::s_enableConsoleOutput = true; + std::vector Logger::s_messages; + std::mutex Logger::s_mutex; + bool Logger::s_enableConsoleOutput = true; - void Logger::log(const std::string& message) - { - std::lock_guard lock(s_mutex); - s_messages.push_back({LogLevel::Info, message}); - if (s_messages.size() > 1000) s_messages.erase(s_messages.begin()); - if (s_enableConsoleOutput) - std::cout << "[INFO] " << message << std::endl; - } + void Logger::log(const std::string& message) + { + std::lock_guard lock(s_mutex); + s_messages.push_back({LogLevel::Info, message}); + if (s_messages.size() > 1000) + s_messages.erase(s_messages.begin()); + if (s_enableConsoleOutput) + std::cout << "[INFO] " << message << std::endl; + } - void Logger::warning(const std::string& message) - { - std::lock_guard lock(s_mutex); - s_messages.push_back({LogLevel::Warning, message}); - if (s_messages.size() > 1000) s_messages.erase(s_messages.begin()); - if (s_enableConsoleOutput) - std::cout << "[WARN] " << message << std::endl; - } + void Logger::warning(const std::string& message) + { + std::lock_guard lock(s_mutex); + s_messages.push_back({LogLevel::Warning, message}); + if (s_messages.size() > 1000) + s_messages.erase(s_messages.begin()); + if (s_enableConsoleOutput) + std::cout << "[WARN] " << message << std::endl; + } - void Logger::error(const std::string& message) - { - std::lock_guard lock(s_mutex); - s_messages.push_back({LogLevel::Error, message}); - if (s_messages.size() > 1000) s_messages.erase(s_messages.begin()); - if (s_enableConsoleOutput) - std::cerr << "[ERROR] " << message << std::endl; - } + void Logger::error(const std::string& message) + { + std::lock_guard lock(s_mutex); + s_messages.push_back({LogLevel::Error, message}); + if (s_messages.size() > 1000) + s_messages.erase(s_messages.begin()); + if (s_enableConsoleOutput) + std::cerr << "[ERROR] " << message << std::endl; + } void Logger::drawImGuiConsole() { @@ -49,9 +52,15 @@ namespace WeirdEngine ImVec4 color; switch (msg.level) { - case LogLevel::Info: color = ImVec4(1.0f, 1.0f, 1.0f, 1.0f); break; // White - case LogLevel::Warning: color = ImVec4(1.0f, 1.0f, 0.0f, 1.0f); break; // Yellow - case LogLevel::Error: color = ImVec4(1.0f, 0.4f, 0.4f, 1.0f); break; // Red + case LogLevel::Info: + color = ImVec4(1.0f, 1.0f, 1.0f, 1.0f); + break; // White + case LogLevel::Warning: + color = ImVec4(1.0f, 1.0f, 0.0f, 1.0f); + break; // Yellow + case LogLevel::Error: + color = ImVec4(1.0f, 0.4f, 0.4f, 1.0f); + break; // Red } ImGui::PushStyleColor(ImGuiCol_Text, color); ImGui::TextUnformatted(msg.message.c_str()); @@ -67,4 +76,4 @@ namespace WeirdEngine ImGui::EndChild(); #endif } -} +} // namespace WeirdEngine diff --git a/src/weird-engine/ResourceManager.cpp b/src/weird-engine/ResourceManager.cpp index 174ad9a..6362a7e 100644 --- a/src/weird-engine/ResourceManager.cpp +++ b/src/weird-engine/ResourceManager.cpp @@ -87,7 +87,8 @@ namespace WeirdEngine m_resourcesUsedByEntity.erase(entity); } - void ResourceManager::loadMesh(const char* file, unsigned int indMesh, std::vector& meshes, glm::mat4 transform) + void ResourceManager::loadMesh(const char* file, unsigned int indMesh, std::vector& meshes, + glm::mat4 transform) { // Get all accessor indices unsigned int posAccInd = m_json["meshes"][indMesh]["primitives"][0]["attributes"]["POSITION"]; @@ -113,12 +114,12 @@ namespace WeirdEngine for (auto& v : vertices) { v.position = glm::vec3(transform * glm::vec4(v.position, 1.0f)); - v.normal = glm::normalize(normalMatrix * v.normal); + v.normal = glm::normalize(normalMatrix * v.normal); } } std::vector indices = getIndices(m_json["accessors"][indAccInd]); - + std::vector textures = getTextures(file); // Combine the vertices, indices, and textures into a mesh diff --git a/src/weird-engine/Scene.cpp b/src/weird-engine/Scene.cpp index a491f7c..be6733a 100644 --- a/src/weird-engine/Scene.cpp +++ b/src/weird-engine/Scene.cpp @@ -10,12 +10,10 @@ #include "weird-engine/Profiler.h" #include "weird-engine/SceneSerializer.h" #include "weird-physics/components/CustomShapeManager.h" -#include "weird-physics/components/CustomShapeManager.h" #include "weird-physics/components/DistanceConstraintManager.h" #include "weird-physics/components/RigidBodyManager.h" #include "weird-physics/components/SpringManager.h" -#include "weird-engine/systems/SDFShaderGenerationSystem.h" #include "weird-engine/systems/ButtonSystem.h" #include "weird-engine/systems/CameraSystem.h" #include "weird-engine/systems/PhysicsInteractionSystem.h" @@ -23,7 +21,7 @@ #include "weird-engine/systems/PlayerMovementSystem.h" #include "weird-engine/systems/RenderSystem.h" #include "weird-engine/systems/SDFRenderSystem.h" -#include "weird-engine/systems/SDFRenderSystem.h" +#include "weird-engine/systems/SDFShaderGenerationSystem.h" namespace WeirdEngine { @@ -49,7 +47,6 @@ namespace WeirdEngine : m_simulation2D(MAX_ENTITIES, SceneManager::getInstance().getPhysicsSettings()) , m_runSimulationInThread(true) { - } Scene::~Scene() @@ -66,28 +63,30 @@ namespace WeirdEngine std::shared_ptr rbManager = std::make_shared(m_simulation2D); m_ecs.registerComponent(rbManager); - if(m_renderMode == RenderMode::RayMarching2D) + if (m_renderMode == RenderMode::RayMarching2D) { - std::shared_ptr shapeManager = std::make_shared(m_simulation2D, m_2DWorldRenderContext); + std::shared_ptr shapeManager = + std::make_shared(m_simulation2D, m_2DWorldRenderContext); m_ecs.registerComponent(shapeManager); } else { - std::shared_ptr shapeManager = std::make_shared(m_simulation2D, m_3DWorldRenderContext); + std::shared_ptr shapeManager = + std::make_shared(m_simulation2D, m_3DWorldRenderContext); m_ecs.registerComponent(shapeManager); } - std::shared_ptr distManager = std::make_shared(m_simulation2D, m_ecs); + std::shared_ptr distManager = + std::make_shared(m_simulation2D, m_ecs); m_ecs.registerComponent(distManager); std::shared_ptr springManager = std::make_shared(m_simulation2D, m_ecs); m_ecs.registerComponent(springManager); - std::shared_ptr uiShapeManager = std::make_shared(m_UIRenderContext); + std::shared_ptr uiShapeManager = + std::make_shared(m_UIRenderContext); m_ecs.registerComponent(uiShapeManager); - - // Shapes m_sdfs = Scene::getGlobalSDFs(); m_simulation2D.setSDFs(m_sdfs); @@ -108,7 +107,7 @@ namespace WeirdEngine // Initialize 2D world render context m_2DWorldRenderContext.dotRadious = 0.5f; m_2DWorldRenderContext.charSpacing = 1.0f; - + auto& defaultMaterial = createMaterial(); defaultMaterial.color = vec4(1.0f); defaultMaterial.metallic = 0.5f; @@ -151,7 +150,7 @@ namespace WeirdEngine default: break; } - + PhysicsSystem2D::update(m_ecs, m_simulation2D); } @@ -205,10 +204,11 @@ namespace WeirdEngine } auto rigidBodies = m_ecs.getComponentArray(); - + for (auto& ev : collisions) { - EntityCollisionEvent entityEvent{ev, getEntityForSimulationId(ev.bodyA, rigidBodies), getEntityForSimulationId(ev.bodyB, rigidBodies)}; + EntityCollisionEvent entityEvent{ev, getEntityForSimulationId(ev.bodyA, rigidBodies), + getEntityForSimulationId(ev.bodyB, rigidBodies)}; onEntityCollision(m_ecs, entityEvent); } @@ -239,7 +239,7 @@ namespace WeirdEngine playSound(WeirdRenderer::SimpleAudioRequest{volume, frequency, false, vec3(ev.position, 0.0f)}); } } - + m_frictionSoundLevelRead.store(m_frictionSoundLevel, std::memory_order_release); m_frictionSoundLevel = 0.0f; } @@ -272,7 +272,7 @@ namespace WeirdEngine { Scene* self = static_cast(userData); self->onCollision(self->m_simulation2D, event); - + std::lock_guard lock(self->m_collisionQueueMutex); self->m_queuedCollisions.push_back(event); } @@ -281,7 +281,7 @@ namespace WeirdEngine { Scene* self = static_cast(userData); self->onShapeCollision(self->m_simulation2D, event); - + { std::lock_guard lock(self->m_collisionQueueMutex); self->m_queuedShapeCollisions.push_back(event); @@ -355,7 +355,7 @@ namespace WeirdEngine void Scene::renderExtra(WeirdRenderer::RenderTarget& renderTarget) { - if(m_renderMode == RenderMode::RayMarching3D || m_renderMode == RenderMode::RayMarchingBoth) + if (m_renderMode == RenderMode::RayMarching3D || m_renderMode == RenderMode::RayMarchingBoth) { onRender(renderTarget); } @@ -441,7 +441,8 @@ namespace WeirdEngine return it->second; } - Entity Scene::getEntityForSimulationId(SimulationID simulationId, std::shared_ptr> rigidBodies) + Entity Scene::getEntityForSimulationId(SimulationID simulationId, + std::shared_ptr> rigidBodies) { if (simulationId >= static_cast(rigidBodies->getSize())) return INVALID_ENTITY; @@ -479,7 +480,7 @@ namespace WeirdEngine float time = getTime(); auto gridSnapshot = m_simulation2D.getSpatialGridSnapshot(); - if(epsilon <= 0.0f) + if (epsilon <= 0.0f) { epsilon = 0.001f; // Default epsilon } @@ -511,7 +512,7 @@ namespace WeirdEngine if (!shape.hasCollisions) continue; - + if (shape.distanceFieldId >= m_sdfs.size()) continue; @@ -694,13 +695,13 @@ namespace WeirdEngine } ImGui::SeparatorText("Background"); - const char* bgTypes[] = { "Solid", "Grid", "Sky", "Custom" }; + const char* bgTypes[] = {"Solid", "Grid", "Sky", "Custom"}; int bgTypeIdx = static_cast(m_background.type); if (ImGui::Combo("Type", &bgTypeIdx, bgTypes, 4)) { m_background.type = static_cast(bgTypeIdx); } - + if (m_background.type != BackgroundType::Custom) { ImGui::ColorEdit4("Primary Color", &m_background.primaryColor[0]); @@ -814,11 +815,11 @@ namespace WeirdEngine // Max materials reached, return the last one return m_materials[15]; } - + Material3D& mat = m_materials[m_materialCount]; mat.id = m_materialCount; m_materialCount++; - + return mat; } } // namespace WeirdEngine \ No newline at end of file diff --git a/src/weird-engine/SceneSerializer.cpp b/src/weird-engine/SceneSerializer.cpp index b282aec..c2773e3 100644 --- a/src/weird-engine/SceneSerializer.cpp +++ b/src/weird-engine/SceneSerializer.cpp @@ -1,13 +1,13 @@ #include "weird-engine/SceneSerializer.h" #include "weird-engine/Scene.h" +#include "weird-physics/components/DistanceConstraint.h" +#include "weird-physics/components/GlobalPhysicsSettings.h" +#include "weird-physics/components/Spring.h" #include #include #include #include -#include "weird-physics/components/DistanceConstraint.h" -#include "weird-physics/components/Spring.h" -#include "weird-physics/components/GlobalPhysicsSettings.h" namespace WeirdEngine { @@ -120,12 +120,10 @@ namespace WeirdEngine auto& rb = rigidBodyArray->getDataAtIdx(i); vec2 simPos = scene.m_simulation2D.getPosition(rb.simulationId); auto& ej = collectEntity(e); - ej["rigidBody2D"] = { - {"simulationId", rb.simulationId}, - {"physicsPosition", {simPos.x, simPos.y}}, - {"velocity", {rb.velocity.x, rb.velocity.y}}, - {"isFixed", rb.isFixed} - }; + ej["rigidBody2D"] = {{"simulationId", rb.simulationId}, + {"physicsPosition", {simPos.x, simPos.y}}, + {"velocity", {rb.velocity.x, rb.velocity.y}}, + {"isFixed", rb.isFixed}}; } // TextRenderer @@ -147,7 +145,8 @@ namespace WeirdEngine for (size_t i = 0; i < globalSettingsArray->getSize(); i++) { Entity e = globalSettingsArray->getEntityAtIdx(i); - if (isBlacklisted(e)) continue; + if (isBlacklisted(e)) + continue; auto& gs = globalSettingsArray->getDataAtIdx(i); auto& ej = collectEntity(e); ej["globalPhysicsSettings"] = {{"gravity", gs.gravity}, {"damping", gs.damping}}; @@ -194,9 +193,11 @@ namespace WeirdEngine for (size_t i = 0; i < distConstraintArray->getSize(); i++) { Entity e = distConstraintArray->getEntityAtIdx(i); - if (isBlacklisted(e)) continue; + if (isBlacklisted(e)) + continue; auto& dc = distConstraintArray->getDataAtIdx(i); - distanceConstraintsJson.push_back({{"entityA", dc.entityA}, {"entityB", dc.entityB}, {"distance", dc.distance}}); + distanceConstraintsJson.push_back( + {{"entityA", dc.entityA}, {"entityB", dc.entityB}, {"distance", dc.distance}}); } } @@ -207,9 +208,13 @@ namespace WeirdEngine for (size_t i = 0; i < springArray->getSize(); i++) { Entity e = springArray->getEntityAtIdx(i); - if (isBlacklisted(e)) continue; + if (isBlacklisted(e)) + continue; auto& sp = springArray->getDataAtIdx(i); - springsJson.push_back({{"entityA", sp.entityA}, {"entityB", sp.entityB}, {"distance", sp.restDistance}, {"k", sp.stiffness}}); + springsJson.push_back({{"entityA", sp.entityA}, + {"entityB", sp.entityB}, + {"distance", sp.restDistance}, + {"k", sp.stiffness}}); } } @@ -373,7 +378,8 @@ namespace WeirdEngine { rb.isFixed = rbj.value("isFixed", false); } - scene.m_ecs.getComponentArray()->setEntityDirty(entity, true); // Sync velocity and fixed state to simulation + scene.m_ecs.getComponentArray()->setEntityDirty( + entity, true); // Sync velocity and fixed state to simulation if (rbj.contains("physicsPosition")) { @@ -430,18 +436,23 @@ namespace WeirdEngine { Entity entityA = INVALID_ENTITY, entityB = INVALID_ENTITY; - if (dcj.contains("A")) { // Legacy format + if (dcj.contains("A")) + { // Legacy format int savedA = dcj.value("A", -1); int savedB = dcj.value("B", -1); - if (simIdMap.find(savedA) != simIdMap.end() && simIdMap.find(savedB) != simIdMap.end()) { + if (simIdMap.find(savedA) != simIdMap.end() && simIdMap.find(savedB) != simIdMap.end()) + { entityA = simIdToEntityMap[savedA]; entityB = simIdToEntityMap[savedB]; } } - else if (dcj.contains("entityA")) { // Modern format + else if (dcj.contains("entityA")) + { // Modern format Entity savedA = dcj.value("entityA", INVALID_ENTITY); Entity savedB = dcj.value("entityB", INVALID_ENTITY); - if (entityIdMap.find(savedA) != entityIdMap.end() && entityIdMap.find(savedB) != entityIdMap.end()) { + if (entityIdMap.find(savedA) != entityIdMap.end() && + entityIdMap.find(savedB) != entityIdMap.end()) + { entityA = entityIdMap[savedA]; entityB = entityIdMap[savedB]; } diff --git a/src/weird-physics/Simulation2D.cpp b/src/weird-physics/Simulation2D.cpp index 8777ba6..891e53e 100644 --- a/src/weird-physics/Simulation2D.cpp +++ b/src/weird-physics/Simulation2D.cpp @@ -120,8 +120,6 @@ namespace WeirdEngine process(); } - - void Simulation2D::process() { int steps = 0; @@ -142,54 +140,57 @@ namespace WeirdEngine { switch (cmd.type) { - case PhysicsCommandType::SetVelocity: - m_velocities[cmd.id] = cmd.vectorData; - break; - case PhysicsCommandType::SetPosition: - m_positions[cmd.id] = cmd.vectorData; - m_previousPositions[cmd.id] = cmd.vectorData; + case PhysicsCommandType::SetVelocity: + m_velocities[cmd.id] = cmd.vectorData; + break; + case PhysicsCommandType::SetPosition: + m_positions[cmd.id] = cmd.vectorData; + m_previousPositions[cmd.id] = cmd.vectorData; + { + std::lock_guard rLock(m_readMutex); + m_positionsRead[cmd.id] = cmd.vectorData; + } + break; + case PhysicsCommandType::SetMass: + m_mass[cmd.id] = cmd.floatData; + if (std::find(m_fixedObjects.begin(), m_fixedObjects.end(), cmd.id) == m_fixedObjects.end()) + { + m_invMass[cmd.id] = cmd.floatData > 0.0f ? 1.0f / cmd.floatData : 0.0f; + } + break; + case PhysicsCommandType::Fix: + if (std::find(m_fixedObjects.begin(), m_fixedObjects.end(), cmd.id) == m_fixedObjects.end()) + { + m_fixedObjects.emplace_back(cmd.id); + m_invMass[cmd.id] = 0.0f; + m_velocities[cmd.id] = vec2(0.0f); + m_forces[cmd.id] = vec2(0.0f); + } + break; + case PhysicsCommandType::UnFix: { - std::lock_guard rLock(m_readMutex); - m_positionsRead[cmd.id] = cmd.vectorData; - } - break; - case PhysicsCommandType::SetMass: - m_mass[cmd.id] = cmd.floatData; - if (std::find(m_fixedObjects.begin(), m_fixedObjects.end(), cmd.id) == m_fixedObjects.end()) { - m_invMass[cmd.id] = cmd.floatData > 0.0f ? 1.0f / cmd.floatData : 0.0f; + auto it = std::find(m_fixedObjects.begin(), m_fixedObjects.end(), cmd.id); + if (it != m_fixedObjects.end()) + { + m_fixedObjects.erase(it); + m_invMass[cmd.id] = m_mass[cmd.id] > 0.0f ? 1.0f / m_mass[cmd.id] : 0.0f; + } + break; } - break; - case PhysicsCommandType::Fix: - if (std::find(m_fixedObjects.begin(), m_fixedObjects.end(), cmd.id) == m_fixedObjects.end()) { - m_fixedObjects.emplace_back(cmd.id); - m_invMass[cmd.id] = 0.0f; - m_velocities[cmd.id] = vec2(0.0f); - m_forces[cmd.id] = vec2(0.0f); + case PhysicsCommandType::ActivatePending: + { + m_size = m_allocated; + break; } - break; - case PhysicsCommandType::UnFix: - { - auto it = std::find(m_fixedObjects.begin(), m_fixedObjects.end(), cmd.id); - if (it != m_fixedObjects.end()) { - m_fixedObjects.erase(it); - m_invMass[cmd.id] = m_mass[cmd.id] > 0.0f ? 1.0f / m_mass[cmd.id] : 0.0f; + case PhysicsCommandType::AddImpulse: + { + std::lock_guard lock(m_externalForcesMutex); + m_impulsesSinceLastUpdate = true; + m_impulses[cmd.id] += cmd.vectorData; + break; } - break; - } - case PhysicsCommandType::ActivatePending: - { - m_size = m_allocated; - break; - } - case PhysicsCommandType::AddImpulse: - { - std::lock_guard lock(m_externalForcesMutex); - m_impulsesSinceLastUpdate = true; - m_impulses[cmd.id] += cmd.vectorData; - break; - } - default: - break; + default: + break; } } @@ -219,7 +220,8 @@ namespace WeirdEngine auto timerForceStart = std::chrono::high_resolution_clock::now(); applyForces(); auto timerForceEnd = std::chrono::high_resolution_clock::now(); - double timerCollisionEvents = std::chrono::duration(timerForceEnd - timerForceStart).count(); + double timerCollisionEvents = + std::chrono::duration(timerForceEnd - timerForceStart).count(); auto timerIntStart = std::chrono::high_resolution_clock::now(); // 1. Predict where particles will go based on velocity and forces @@ -235,7 +237,8 @@ namespace WeirdEngine // 3. Derive the exact velocity based on how much the constraints moved the particles integrateVelocity((float)m_fixedDeltaTime); auto timerIntEnd = std::chrono::high_resolution_clock::now(); - double timerIntegration = std::chrono::duration(timerIntEnd - timerIntStart).count(); + double timerIntegration = + std::chrono::duration(timerIntEnd - timerIntStart).count(); { std::lock_guard lock(m_statsMutex); @@ -274,11 +277,12 @@ namespace WeirdEngine auto end = std::chrono::high_resolution_clock::now(); std::chrono::duration durationMs = end - start; - + { std::lock_guard lock(m_statsMutex); m_stats.timePerStepMs = durationMs.count(); - m_stats.simulationRatio = durationMs.count() > 0.0 ? (m_fixedDeltaTime * 1000.0) / durationMs.count() : 0.0; + m_stats.simulationRatio = + durationMs.count() > 0.0 ? (m_fixedDeltaTime * 1000.0) / durationMs.count() : 0.0; } } } @@ -359,15 +363,15 @@ namespace WeirdEngine // Update the spatial grid snapshot for read-only access (e.g. by raymarching in the main thread) { // TODO: [PERFORMANCE] Avoid heap allocation every physics step. - // Currently, we allocate a new std::shared_ptr and its internal std::vector buffers + // Currently, we allocate a new std::shared_ptr and its internal std::vector buffers // (head, next, positions) on the heap every single time this function runs. - // While std::shared_ptr safely manages the memory lifecycle for the main thread, + // While std::shared_ptr safely manages the memory lifecycle for the main thread, // this causes unnecessary memory fragmentation and malloc overhead. - // + // // PROPOSED SOLUTION: Implement an Object Pool (e.g. std::vector) - // with a custom std::shared_ptr deleter. Instead of allocating a new object here, - // pop an old one from the pool (which reuses the vector capacities). When the main - // thread's shared_ptr reference count drops to 0, the custom deleter should push + // with a custom std::shared_ptr deleter. Instead of allocating a new object here, + // pop an old one from the pool (which reuses the vector capacities). When the main + // thread's shared_ptr reference count drops to 0, the custom deleter should push // the object back into the pool instead of deleting it. auto snapshot = std::make_shared(); snapshot->head = m_head; @@ -411,7 +415,6 @@ namespace WeirdEngine { m_collisions.emplace_back(Collision(i, j, ij)); } - } j = m_next[j]; // Move to the next particle in the cell @@ -553,8 +556,8 @@ namespace WeirdEngine for (int i = 0; i < m_objects.size(); i++) { - DistanceFieldObject2D& obj = m_objects[i]; - if(obj.groupId == CustomShape::GLOBAL_GROUP) + DistanceFieldObject2D& obj = m_objects[i]; + if (obj.groupId == CustomShape::GLOBAL_GROUP) { globalShapes.push_back(i); continue; @@ -634,7 +637,6 @@ namespace WeirdEngine groupState->minDistance = currentMinDistance; } - for (const auto& group : groups) { d = std::min(d, group.minDistance); @@ -643,7 +645,7 @@ namespace WeirdEngine // Apply global shapes as well, but without grouping (they affect everything) for (int shapeIdx : globalShapes) { - DistanceFieldObject2D& obj = m_objects[shapeIdx]; + DistanceFieldObject2D& obj = m_objects[shapeIdx]; if (obj.distanceFieldId >= m_sdfs->size()) { @@ -709,7 +711,7 @@ namespace WeirdEngine // External forces { std::lock_guard lock(m_externalForcesMutex); - + for (size_t i = 0; i < m_size; i++) { m_forces[i] += m_continuousForcesRead[i]; @@ -744,7 +746,7 @@ namespace WeirdEngine float restitution = 0.5f; vec2 vRel = m_velocities[col.B] - m_velocities[col.A]; float velocityAlongNormal = glm::dot(normal, vRel); - + // Only apply impulse if objects are moving towards each other if (velocityAlongNormal < 0.0f) { @@ -770,8 +772,6 @@ namespace WeirdEngine CollisionEvent event{col.A, col.B}; m_collisionCallback(event, m_callbackUserData); } - - } // Shape collisions @@ -788,7 +788,7 @@ namespace WeirdEngine // Use the current velocity of the body for accurate response vec2 vel = m_velocities[collisionEvent.body]; - + float v_n = glm::dot(vel, collisionEvent.normal); vec2 vel_t = vel - (v_n * collisionEvent.normal); float speed_t = length(vel_t); @@ -798,27 +798,30 @@ namespace WeirdEngine { // Normal acceleration from the penalty method (calculated below: push * penetration^2) float normalAcceleration = m_push * collisionEvent.penetration * collisionEvent.penetration; - + // Coulomb friction (constant sliding resistance based on normal force) float coulombDrop = collisionEvent.friction * normalAcceleration * m_fixedDeltaTimeF; - + // Viscous friction (increases with speed to slow it down more when moving fast) float viscousDrop = collisionEvent.friction * speed_t * 10.0f * m_fixedDeltaTimeF; - + float totalDrop = coulombDrop + viscousDrop; - + // Clamp velocity drop so it never reverses the direction (fixes low-speed jitter) float drop = std::min(totalDrop, speed_t); - + m_velocities[collisionEvent.body] -= drop * (vel_t / speed_t); } // Absorption (Damping on the normal axis to prevent infinite bouncing) // Apply damping proportional to the normal velocity float dampingDrop = collisionEvent.absortion * v_n * m_fixedDeltaTimeF; - if (v_n > 0.0f) { + if (v_n > 0.0f) + { dampingDrop = std::min(dampingDrop, v_n); - } else { + } + else + { dampingDrop = std::max(dampingDrop, v_n); } m_velocities[collisionEvent.body] -= dampingDrop * collisionEvent.normal; @@ -893,7 +896,6 @@ namespace WeirdEngine // m_forces[constraint.A] += f * n; // m_forces[constraint.B] -= f * n; // } - } void Simulation2D::integratePredict(const float timeStep) @@ -1024,12 +1026,9 @@ namespace WeirdEngine // Remove constraints that affect deleted object auto RemoveByID = [toId](auto& container) { - container.erase(std::remove_if(container.begin(), container.end(), - [toId](const auto& constraint) - { - return constraint.A == toId || constraint.B == toId; - }), - container.end()); + container.erase(std::remove_if(container.begin(), container.end(), [toId](const auto& constraint) + { return constraint.A == toId || constraint.B == toId; }), + container.end()); }; RemoveByID(m_distanceConstraints); @@ -1175,17 +1174,16 @@ namespace WeirdEngine std::lock_guard lock(m_structuralMutex); size_t previousSize = m_distanceConstraints.size(); - m_distanceConstraints.erase( - std::remove_if(m_distanceConstraints.begin(), m_distanceConstraints.end(), - [a, b](const DistanceConstraint& constraint) - { - bool sameDirection = - (constraint.A == static_cast(a) && constraint.B == static_cast(b)); - bool reverseDirection = - (constraint.A == static_cast(b) && constraint.B == static_cast(a)); - return sameDirection || reverseDirection; - }), - m_distanceConstraints.end()); + m_distanceConstraints.erase(std::remove_if(m_distanceConstraints.begin(), m_distanceConstraints.end(), + [a, b](const DistanceConstraint& constraint) + { + bool sameDirection = (constraint.A == static_cast(a) && + constraint.B == static_cast(b)); + bool reverseDirection = (constraint.A == static_cast(b) && + constraint.B == static_cast(a)); + return sameDirection || reverseDirection; + }), + m_distanceConstraints.end()); return previousSize != m_distanceConstraints.size(); } @@ -1238,7 +1236,7 @@ namespace WeirdEngine { std::lock_guard lock(m_commandMutex); m_pendingCommands.push_back({PhysicsCommandType::SetPosition, id, pos}); - + std::lock_guard readLock(m_readMutex); m_positionsRead[id] = pos; } @@ -1259,7 +1257,7 @@ namespace WeirdEngine { std::lock_guard lock(m_commandMutex); m_pendingCommands.push_back({PhysicsCommandType::SetVelocity, id, vel}); - + std::lock_guard readLock(m_readMutex); m_velocitiesRead[id] = vel; } @@ -1276,7 +1274,7 @@ namespace WeirdEngine { PhysicsCommand cmd = {PhysicsCommandType::SetMass, id}; cmd.floatData = mass; - + if (std::this_thread::get_id() == m_physicsThreadId) { m_internalCommands.push_back(cmd); @@ -1298,8 +1296,7 @@ namespace WeirdEngine if (!shape.hasCollisions) return; - DistanceFieldObject2D sdf(owner, shape.distanceFieldId, shape.combination, shape.groupIdx, - shape.parameters); + DistanceFieldObject2D sdf(owner, shape.distanceFieldId, shape.combination, shape.groupIdx, shape.parameters); // Check if the key exists auto it = m_entityToObjectsIdx.find(owner); diff --git a/src/weird-renderer/audio/AudioEngine.cpp b/src/weird-renderer/audio/AudioEngine.cpp index d12e20e..3c0a5ed 100644 --- a/src/weird-renderer/audio/AudioEngine.cpp +++ b/src/weird-renderer/audio/AudioEngine.cpp @@ -1,9 +1,9 @@ #include "weird-renderer/audio/AudioEngine.h" +#include "weird-engine/Logger.h" #include #include #include #include -#include "weird-engine/Logger.h" #define MA_NO_DEVICE_IO #define MINIAUDIO_IMPLEMENTATION diff --git a/src/weird-renderer/core/MeshRenderPipeline.cpp b/src/weird-renderer/core/MeshRenderPipeline.cpp index a20de21..7e93487 100644 --- a/src/weird-renderer/core/MeshRenderPipeline.cpp +++ b/src/weird-renderer/core/MeshRenderPipeline.cpp @@ -37,7 +37,7 @@ namespace WeirdEngine return m_instancedGeometryShader; } -Texture& MeshRenderPipeline::getGBufferAlbedo() + Texture& MeshRenderPipeline::getGBufferAlbedo() { return m_gbufferAlbedo; } @@ -68,7 +68,7 @@ Texture& MeshRenderPipeline::getGBufferAlbedo() } void MeshRenderPipeline::render(Scene& scene, RenderTarget& outputTarget, const Camera& camera, - const std::vector& lights) + const std::vector& lights) { // Set GBuffer uniforms for both shaders m_gbufferShader.use(); @@ -79,7 +79,8 @@ Texture& MeshRenderPipeline::getGBufferAlbedo() // Bind GBuffer FBO and activate all 4 colour draw buffers m_gbufferRender.bind(); - const GLenum drawBuffers[4] = {GL_COLOR_ATTACHMENT0, GL_COLOR_ATTACHMENT1, GL_COLOR_ATTACHMENT2, GL_COLOR_ATTACHMENT3}; + const GLenum drawBuffers[4] = {GL_COLOR_ATTACHMENT0, GL_COLOR_ATTACHMENT1, GL_COLOR_ATTACHMENT2, + GL_COLOR_ATTACHMENT3}; glDrawBuffers(4, drawBuffers); glClearColor(0.0f, 0.0f, 0.0f, 0.0f); @@ -117,7 +118,8 @@ Texture& MeshRenderPipeline::getGBufferAlbedo() for (const auto& cmd : drawQueue) { - cmd.mesh->draw(m_gbufferShader, camera, cmd.translation, cmd.rotation, cmd.scale, cmd.materialIndex); + cmd.mesh->draw(m_gbufferShader, camera, cmd.translation, cmd.rotation, cmd.scale, + cmd.materialIndex); } glCullFace(GL_BACK); @@ -132,21 +134,21 @@ Texture& MeshRenderPipeline::getGBufferAlbedo() { free(); - m_gbufferAlbedo = Texture(newWidth, newHeight, Texture::TextureType::Data); + m_gbufferAlbedo = Texture(newWidth, newHeight, Texture::TextureType::Data); m_gbufferWorldPos = Texture(newWidth, newHeight, Texture::TextureType::LinearData); - m_gbufferNormal = Texture(newWidth, newHeight, Texture::TextureType::LinearData); + m_gbufferNormal = Texture(newWidth, newHeight, Texture::TextureType::LinearData); m_gbufferMaterial = Texture(newWidth, newHeight, Texture::TextureType::IntData); - m_depthTexture = Texture(newWidth, newHeight, Texture::TextureType::Depth); + m_depthTexture = Texture(newWidth, newHeight, Texture::TextureType::Depth); m_gbufferRender = RenderTarget(false); - m_gbufferRender.bindColorTextureToFrameBuffer(m_gbufferAlbedo, 0); + m_gbufferRender.bindColorTextureToFrameBuffer(m_gbufferAlbedo, 0); m_gbufferRender.bindColorTextureToFrameBuffer(m_gbufferWorldPos, 1); - m_gbufferRender.bindColorTextureToFrameBuffer(m_gbufferNormal, 2); + m_gbufferRender.bindColorTextureToFrameBuffer(m_gbufferNormal, 2); m_gbufferRender.bindColorTextureToFrameBuffer(m_gbufferMaterial, 3); m_gbufferRender.bindDepthTextureToFrameBuffer(m_depthTexture); m_backDepthTexture = Texture(newWidth, newHeight, Texture::TextureType::Depth); - m_backDepthRender = RenderTarget(false); + m_backDepthRender = RenderTarget(false); m_backDepthRender.bindDepthTextureToFrameBuffer(m_backDepthTexture); } diff --git a/src/weird-renderer/core/RenderTarget.cpp b/src/weird-renderer/core/RenderTarget.cpp index b0247aa..4c65c85 100644 --- a/src/weird-renderer/core/RenderTarget.cpp +++ b/src/weird-renderer/core/RenderTarget.cpp @@ -1,7 +1,7 @@ #include "weird-renderer/core/RenderTarget.h" -#include #include "weird-engine/Logger.h" +#include #include namespace WeirdEngine diff --git a/src/weird-renderer/core/Renderer.cpp b/src/weird-renderer/core/Renderer.cpp index dbcd9f7..6c0686e 100644 --- a/src/weird-renderer/core/Renderer.cpp +++ b/src/weird-renderer/core/Renderer.cpp @@ -1,8 +1,8 @@ #include "weird-renderer/core/Renderer.h" #include "weird-renderer/core/WeirdFBDevEGL.h" -#include #include +#include #include #include @@ -14,10 +14,10 @@ #include #include -#include "weird-engine/Profiler.h" #include "weird-engine/Logger.h" -#include "weird-renderer/core/MeshRenderPipeline.h" +#include "weird-engine/Profiler.h" #include "weird-renderer/audio/AudioEngine.h" +#include "weird-renderer/core/MeshRenderPipeline.h" #ifndef SHADERS_PATH #define SHADERS_PATH @@ -97,8 +97,7 @@ namespace WeirdEngine sdf3DConfig.renderHeight = m_renderHeight; sdf3DConfig.contrast = settings.raymarching3DContrast; sdf3DConfig.enablePathTracer = settings.enable3DPathTracer; - m_3DWorldPipeline = - new SDF3DRenderPipeline(sdf3DConfig, m_renderPlane); + m_3DWorldPipeline = new SDF3DRenderPipeline(sdf3DConfig, m_renderPlane); // Initialize mesh pipeline m_meshPipeline = new MeshRenderPipeline(); @@ -114,8 +113,8 @@ namespace WeirdEngine if (m_ditheringEnabled) m_outputShaderProgram.addDefine("DITHERING"); - m_surfaceBlurEnabled = settings.enableSurfaceBlur; - m_surfaceBlurRadius = std::max(1.0f, settings.surfaceBlurRadius); + m_surfaceBlurEnabled = settings.enableSurfaceBlur; + m_surfaceBlurRadius = std::max(1.0f, settings.surfaceBlurRadius); m_surfaceBlurSigmaColor = std::max(0.001f, settings.surfaceBlurSigmaColor); if (m_surfaceBlurEnabled) m_outputShaderProgram.addDefine("SURFACE_BLUR"); @@ -269,8 +268,10 @@ namespace WeirdEngine bool isMuted = AudioEngine::getInstance().isMuted(); if (ImGui::Checkbox("Mute Audio", &isMuted)) { - if (isMuted) AudioEngine::getInstance().mute(); - else AudioEngine::getInstance().unmute(); + if (isMuted) + AudioEngine::getInstance().mute(); + else + AudioEngine::getInstance().unmute(); } if (!m_lastScreenshotPath.empty()) @@ -320,7 +321,7 @@ namespace WeirdEngine { PROFILE_SCOPE("Synchronization"); - if (IsFBDevEGLActive()) + if (IsFBDevEGLActive()) { SwapFBDevBuffers(); } @@ -399,8 +400,8 @@ namespace WeirdEngine scene.getUIData(uiData, dataSize, shapeCount); double time = scene.getTime(); - auto& m_finalResultTexture = - m_uiPipeline->render(uiData, dataSize, shapeCount, m_uiCamera, time, delta, scene.getBackground(), &texture); + auto& m_finalResultTexture = m_uiPipeline->render(uiData, dataSize, shapeCount, m_uiCamera, time, delta, + scene.getBackground(), &texture); // TODO: abstract this glDisable(GL_DEPTH_TEST); @@ -487,8 +488,8 @@ namespace WeirdEngine char ftOverlay[32]; snprintf(ftOverlay, sizeof(ftOverlay), "%.2f ms", frameTimeMs); - ImGui::PlotLines("##ft", m_frametimeHistory, STATS_HISTORY_SIZE, m_historyOffset, - ftOverlay, 0.0f, 100.0f, ImVec2(ImGui::GetContentRegionAvail().x, 50)); + ImGui::PlotLines("##ft", m_frametimeHistory, STATS_HISTORY_SIZE, m_historyOffset, ftOverlay, 0.0f, 100.0f, + ImVec2(ImGui::GetContentRegionAvail().x, 50)); ImGui::Spacing(); @@ -520,11 +521,11 @@ namespace WeirdEngine topMs = 1.0; static const ImVec4 depthColors[] = { - {0.30f, 0.70f, 1.00f, 1.0f}, // depth 0 — blue - {0.35f, 0.90f, 0.50f, 1.0f}, // depth 1 — green - {1.00f, 0.70f, 0.25f, 1.0f}, // depth 2 — orange - {0.85f, 0.40f, 0.90f, 1.0f}, // depth 3 — purple - {0.85f, 0.35f, 0.35f, 1.0f}, // depth 4 — red + {0.30f, 0.70f, 1.00f, 1.0f}, // depth 0 — blue + {0.35f, 0.90f, 0.50f, 1.0f}, // depth 1 — green + {1.00f, 0.70f, 0.25f, 1.0f}, // depth 2 — orange + {0.85f, 0.40f, 0.90f, 1.0f}, // depth 3 — purple + {0.85f, 0.35f, 0.35f, 1.0f}, // depth 4 — red }; constexpr int MAX_DEPTH_COLORS = 5; const float NAME_COLUMN_W = 180.0f; @@ -624,7 +625,8 @@ namespace WeirdEngine if (w > 20.0f) { ImGui::PushClipRect(rectMin, rectMax, true); - drawList->AddText(ImVec2(rectMin.x + 2, rectMin.y + 1), IM_COL32(255, 255, 255, 255), stat.name); + drawList->AddText(ImVec2(rectMin.x + 2, rectMin.y + 1), IM_COL32(255, 255, 255, 255), + stat.name); ImGui::PopClipRect(); } @@ -665,7 +667,8 @@ namespace WeirdEngine if (historyEnabled) { ImGui::SameLine(); - ImGui::TextDisabled("(%d/%d frames captured)", profiler.getHistoryCapturedCount(), profiler.getHistoryCapacity()); + ImGui::TextDisabled("(%d/%d frames captured)", profiler.getHistoryCapturedCount(), + profiler.getHistoryCapacity()); } if (profiler.isPaused()) @@ -678,7 +681,8 @@ namespace WeirdEngine if (historyEnabled && profiler.getHistoryCapturedCount() > 0) { int maxIdx = profiler.getHistoryCapturedCount() - 1; - if (maxIdx < 0) maxIdx = 0; + if (maxIdx < 0) + maxIdx = 0; int pIndex = profiler.getPlaybackIndex(); if (ImGui::SliderInt("Scrub History", &pIndex, 0, maxIdx)) { @@ -701,7 +705,8 @@ namespace WeirdEngine } else if (profiler.isRecordingReport()) { - ImGui::TextColored(ImVec4(1.0f, 1.0f, 0.0f, 1.0f), "Recording average report... (%.1fs / 10.0s)", profiler.getReportProgressSeconds()); + ImGui::TextColored(ImVec4(1.0f, 1.0f, 0.0f, 1.0f), "Recording average report... (%.1fs / 10.0s)", + profiler.getReportProgressSeconds()); if (ImGui::Button("Cancel & Return to Realtime")) { profiler.enableRealtime(); @@ -742,7 +747,7 @@ namespace WeirdEngine // Get camera auto& sceneCamera = scene.getCamera(); - if(renderMode == Scene::RenderMode::RayMarchingBoth) + if (renderMode == Scene::RenderMode::RayMarchingBoth) { sceneCamera.fov = 90.0f; } @@ -790,16 +795,11 @@ namespace WeirdEngine static vec4* data3D = nullptr; scene.get3DShapesData(data3D, dataSize3D, shapeCount3D); - m_3DWorldPipeline->render( - data3D, dataSize3D, shapeCount3D, lights, sceneCamera, scene.getTime(), - m_meshPipeline->getGBufferAlbedo(), - m_meshPipeline->getGBufferWorldPos(), - m_meshPipeline->getGBufferNormal(), - m_meshPipeline->getGBufferMaterial(), - m_meshPipeline->getDepthTexture(), - m_meshPipeline->getBackDepthTexture(), - scene.getMaterials() - ); + m_3DWorldPipeline->render(data3D, dataSize3D, shapeCount3D, lights, sceneCamera, scene.getTime(), + m_meshPipeline->getGBufferAlbedo(), m_meshPipeline->getGBufferWorldPos(), + m_meshPipeline->getGBufferNormal(), m_meshPipeline->getGBufferMaterial(), + m_meshPipeline->getDepthTexture(), m_meshPipeline->getBackDepthTexture(), + scene.getMaterials()); glEnable(GL_CULL_FACE); glEnable(GL_DEPTH_TEST); @@ -831,8 +831,9 @@ namespace WeirdEngine scene.update2DWorldShader(m_worldPipeline->getDistanceShader()); scene.get2DShapesData(data, dataSize, shapeCount); - auto& texture = m_worldPipeline->render(data, dataSize, shapeCount, sceneCamera, scene.getTime(), delta, scene.getBackground(), - enable3D ? &m_3DWorldPipeline->getOutputTexture() : nullptr); + auto& texture = m_worldPipeline->render(data, dataSize, shapeCount, sceneCamera, scene.getTime(), delta, + scene.getBackground(), + enable3D ? &m_3DWorldPipeline->getOutputTexture() : nullptr); // In both pure 2D and RayMarchingBoth modes, the 2D pipeline's output is the final result. // When enable3D is true, the 3D texture was already passed as the background so it's baked in. return texture; diff --git a/src/weird-renderer/core/SDF2DRenderPipeline.cpp b/src/weird-renderer/core/SDF2DRenderPipeline.cpp index d6b7c07..263511c 100644 --- a/src/weird-renderer/core/SDF2DRenderPipeline.cpp +++ b/src/weird-renderer/core/SDF2DRenderPipeline.cpp @@ -6,8 +6,8 @@ #include #endif -#include "weird-engine/vec.h" #include "weird-engine/Profiler.h" +#include "weird-engine/vec.h" #include @@ -56,7 +56,7 @@ namespace WeirdEngine // Load shaders m_distanceShader = Shader(SHADERS_PATH "common/screen_plane.vert", SHADERS_PATH "2d/sdf_distance.frag"); - if(config.ballK > 0.0f) + if (config.ballK > 0.0f) m_distanceShader.addDefine("BLEND_SHAPES"); if (m_config.enableMotionBlur) @@ -179,7 +179,8 @@ namespace WeirdEngine m_postProcessDoubleBuffer[0] = &m_postProcessRenderFront; m_postProcessDoubleBuffer[1] = &m_postProcessRenderBack; - m_backgroundTextureFront = Texture(m_config.renderWidth, m_config.renderHeight, Texture::TextureType::Color); + m_backgroundTextureFront = + Texture(m_config.renderWidth, m_config.renderHeight, Texture::TextureType::Color); m_backgroundTextureBack = Texture(m_config.renderWidth, m_config.renderHeight, Texture::TextureType::Color); m_backgroundRenderFront = RenderTarget(false); m_backgroundRenderBack = RenderTarget(false); @@ -319,7 +320,8 @@ namespace WeirdEngine m_postProcessTextureBack = Texture(m_config.renderWidth, m_config.renderHeight, Texture::TextureType::Data); m_postProcessRenderBack.bindColorTextureToFrameBuffer(m_postProcessTextureBack); - m_backgroundTextureFront = Texture(m_config.renderWidth, m_config.renderHeight, Texture::TextureType::Color); + m_backgroundTextureFront = + Texture(m_config.renderWidth, m_config.renderHeight, Texture::TextureType::Color); m_backgroundTextureBack = Texture(m_config.renderWidth, m_config.renderHeight, Texture::TextureType::Color); m_backgroundRenderFront.bindColorTextureToFrameBuffer(m_backgroundTextureFront); m_backgroundRenderBack.bindColorTextureToFrameBuffer(m_backgroundTextureBack); @@ -344,7 +346,7 @@ namespace WeirdEngine upscaleDistance(); renderMaterialColors(camera, time, delta); blendMaterials(time); - if (!backgroundTexture) + if (!backgroundTexture) { renderBackground(camera, time, bgParams); } @@ -354,19 +356,20 @@ namespace WeirdEngine // Shift hue slightly (e.g. +15 degrees) to make shadows more interesting hsvAmbient.x += 15.0f; - if (hsvAmbient.x >= 360.0f) hsvAmbient.x -= 360.0f; + if (hsvAmbient.x >= 360.0f) + hsvAmbient.x -= 360.0f; // Increase saturation to get a pure, vibrant color tone hsvAmbient.y = std::min(hsvAmbient.y * 1.5f + 0.2f, 1.0f); hsvAmbient.z = 1.0f; glm::vec3 vibrantColor = glm::rgbColor(hsvAmbient); - - // Map the vibrant color to a valid transmittance range. - // We want the shadow to block at most ~25% of light (0.75 transmittance) + + // Map the vibrant color to a valid transmittance range. + // We want the shadow to block at most ~25% of light (0.75 transmittance) // to keep it from getting too dark, while fully letting the tinted color through. glm::vec3 shadowTransmittance = glm::mix(glm::vec3(0.75f), glm::vec3(1.0f), vibrantColor); - + m_config.shadowTint = shadowTransmittance; applyLighting(camera, time, backgroundTexture); @@ -562,7 +565,7 @@ namespace WeirdEngine m_oldCameraMatrix = camera.view; m_prevFrameCameraMatrix = camera.view; } - + m_distanceShader.setUniform("u_camMatrix", camera.view); m_distanceShader.setUniform("u_oldCamMatrix", m_oldCameraMatrix); m_oldCameraMatrix = camera.view; @@ -683,7 +686,6 @@ namespace WeirdEngine { PROFILE_SCOPE(m_config.isUI ? "upscaleDistance (UI)" : "upscaleDistance (World)"); - m_distanceUpscaler.bind(); m_distanceUpscalerShader.use(); @@ -704,7 +706,6 @@ namespace WeirdEngine { PROFILE_SCOPE(m_config.isUI ? "renderMaterialColors (UI)" : "renderMaterialColors (World)"); - m_colorRender.bind(); m_materialColorShader.use(); @@ -730,7 +731,7 @@ namespace WeirdEngine void SDF2DRenderPipeline::blendMaterials(double time) { PROFILE_SCOPE(m_config.isUI ? "blendMaterials (UI)" : "blendMaterials (World)"); - + m_materialBlendShader.use(); m_materialBlendShader.setUniform("t_colorTexture", 0); m_materialBlendShader.setUniform("u_time", time); @@ -753,7 +754,7 @@ namespace WeirdEngine horizontal = !horizontal; } - + Profiler::get().gpuSync(); } @@ -765,8 +766,9 @@ namespace WeirdEngine if (bgParams.isDirty) { std::string injectedCode = ""; - - switch (bgParams.type) { + + switch (bgParams.type) + { case BackgroundType::Solid: injectedCode = "vec3 getBackground(vec2 uv, vec2 worldPos) { return u_bgPrimaryColor.rgb; }"; break; @@ -777,21 +779,23 @@ namespace WeirdEngine " float threshold = 2.0 * freq * zoom / u_resolution.y;\n" " float gridLine = (fract(freq * worldPos.x) >= threshold && \n" " fract(freq * worldPos.y) >= threshold) ? 1.0 : 0.0;\n" - " return mix(u_bgPrimaryColor.rgb, u_bgSecondaryColor.rgb, 1.0 - gridLine) * u_bgIntensity;\n" + " return mix(u_bgPrimaryColor.rgb, u_bgSecondaryColor.rgb, 1.0 - gridLine) * " + "u_bgIntensity;\n" "}"; break; case BackgroundType::Sky: - injectedCode = "vec3 getBackground(vec2 uv, vec2 worldPos) {\n" - " float freq = 0.1 * u_bgScale;\n" - " float t = clamp((worldPos.y * freq + 1.0) * 0.5, 0.0, 1.0);\n" - " return mix(u_bgSecondaryColor.rgb, u_bgPrimaryColor.rgb, t) * u_bgIntensity;\n" - "}"; + injectedCode = + "vec3 getBackground(vec2 uv, vec2 worldPos) {\n" + " float freq = 0.1 * u_bgScale;\n" + " float t = clamp((worldPos.y * freq + 1.0) * 0.5, 0.0, 1.0);\n" + " return mix(u_bgSecondaryColor.rgb, u_bgPrimaryColor.rgb, t) * u_bgIntensity;\n" + "}"; break; case BackgroundType::Custom: injectedCode = bgParams.customShaderCode; break; } - + injectedCode = "#define HAS_CUSTOM_BACKGROUND\n" + injectedCode; m_defaultBackgroundShader.setFragmentIncludeCode(0, injectedCode); } @@ -801,16 +805,19 @@ namespace WeirdEngine m_defaultBackgroundShader.use(); m_defaultBackgroundShader.setUniform("t_prevBackground", 0); - if (m_backgroundDoubleBufferIdx == 0) { + if (m_backgroundDoubleBufferIdx == 0) + { m_backgroundTextureFront.bind(0); - } else { + } + else + { m_backgroundTextureBack.bind(0); } m_defaultBackgroundShader.setUniform("u_camMatrix", camera.view); m_defaultBackgroundShader.setUniform("u_time", time); m_defaultBackgroundShader.setUniform("u_resolution", glm::vec2(m_config.renderWidth, m_config.renderHeight)); - + // Background params m_defaultBackgroundShader.setUniform("u_bgPrimaryColor", bgParams.primaryColor); m_defaultBackgroundShader.setUniform("u_bgSecondaryColor", bgParams.secondaryColor); @@ -862,9 +869,12 @@ namespace WeirdEngine } else { - if (m_backgroundDoubleBufferIdx == 0) { + if (m_backgroundDoubleBufferIdx == 0) + { m_backgroundTextureFront.bind(2); - } else { + } + else + { m_backgroundTextureBack.bind(2); } } @@ -889,48 +899,64 @@ namespace WeirdEngine ImGui::SeparatorText("Shadows"); if (ImGui::Checkbox("Shadows", &m_config.enableShadows)) { - if (m_config.enableShadows) m_lightingShader.addDefine("SHADOWS_ENABLED"); - else m_lightingShader.removeDefine("SHADOWS_ENABLED"); + if (m_config.enableShadows) + m_lightingShader.addDefine("SHADOWS_ENABLED"); + else + m_lightingShader.removeDefine("SHADOWS_ENABLED"); } if (ImGui::Checkbox("Long Shadows", &m_config.enableLongShadows)) { - if (m_config.enableLongShadows) m_lightingShader.addDefine("LONG_SHADOWS"); - else m_lightingShader.removeDefine("LONG_SHADOWS"); + if (m_config.enableLongShadows) + m_lightingShader.addDefine("LONG_SHADOWS"); + else + m_lightingShader.removeDefine("LONG_SHADOWS"); } ImGui::SeparatorText("Rendering"); if (ImGui::Checkbox("Antialiasing", &m_config.enableAntialiasing)) { - if (m_config.enableAntialiasing) m_lightingShader.addDefine("ANTIALIASING"); - else m_lightingShader.removeDefine("ANTIALIASING"); + if (m_config.enableAntialiasing) + m_lightingShader.addDefine("ANTIALIASING"); + else + m_lightingShader.removeDefine("ANTIALIASING"); } if (ImGui::Checkbox("Motion Blur", &m_config.enableMotionBlur)) { - if (m_config.enableMotionBlur) m_distanceShader.addDefine("MOTION_BLUR"); - else m_distanceShader.removeDefine("MOTION_BLUR"); + if (m_config.enableMotionBlur) + m_distanceShader.addDefine("MOTION_BLUR"); + else + m_distanceShader.removeDefine("MOTION_BLUR"); } if (ImGui::Checkbox("Refraction", &m_config.enableRefraction)) { - if (m_config.enableRefraction) m_lightingShader.addDefine("REFRACTION"); - else m_lightingShader.removeDefine("REFRACTION"); + if (m_config.enableRefraction) + m_lightingShader.addDefine("REFRACTION"); + else + m_lightingShader.removeDefine("REFRACTION"); } ImGui::SeparatorText("Debug"); if (ImGui::Checkbox("Show Distance Field", &m_config.debugDistanceField)) { - if (m_config.debugDistanceField) m_lightingShader.addDefine("DEBUG_SHOW_DISTANCE"); - else m_lightingShader.removeDefine("DEBUG_SHOW_DISTANCE"); + if (m_config.debugDistanceField) + m_lightingShader.addDefine("DEBUG_SHOW_DISTANCE"); + else + m_lightingShader.removeDefine("DEBUG_SHOW_DISTANCE"); } if (ImGui::Checkbox("Show Material Colors", &m_config.debugMaterialColors)) { - if (m_config.debugMaterialColors) m_lightingShader.addDefine("DEBUG_SHOW_COLORS"); - else m_lightingShader.removeDefine("DEBUG_SHOW_COLORS"); + if (m_config.debugMaterialColors) + m_lightingShader.addDefine("DEBUG_SHOW_COLORS"); + else + m_lightingShader.removeDefine("DEBUG_SHOW_COLORS"); } if (ImGui::Checkbox("Show grid", &m_config.debugGrid)) { - if (m_config.debugGrid) m_distanceShader.addDefine("DEBUG_SHOW_GRID"); - else m_distanceShader.removeDefine("DEBUG_SHOW_GRID"); + if (m_config.debugGrid) + m_distanceShader.addDefine("DEBUG_SHOW_GRID"); + else + m_distanceShader.removeDefine("DEBUG_SHOW_GRID"); } ImGui::SeparatorText("Ambient Occlusion"); diff --git a/src/weird-renderer/core/SDF3DRenderPipeline.cpp b/src/weird-renderer/core/SDF3DRenderPipeline.cpp index 8e6f8bd..779bf73 100644 --- a/src/weird-renderer/core/SDF3DRenderPipeline.cpp +++ b/src/weird-renderer/core/SDF3DRenderPipeline.cpp @@ -25,7 +25,8 @@ namespace WeirdEngine , m_oldCameraMatrix(glm::mat4(0.0f)) { m_sdfShader = Shader(SHADERS_PATH "common/screen_plane.vert", SHADERS_PATH "3d/sdf_raymarching.frag"); - m_resolveShader = Shader(SHADERS_PATH "common/screen_plane.vert", SHADERS_PATH "postprocess/linear_to_srgb.frag"); + m_resolveShader = + Shader(SHADERS_PATH "common/screen_plane.vert", SHADERS_PATH "postprocess/linear_to_srgb.frag"); m_shapeDataBuffer = new DataBuffer(); resize(config.renderWidth, config.renderHeight); @@ -53,19 +54,11 @@ namespace WeirdEngine return m_sdfShader; } - void SDF3DRenderPipeline::render( - vec4* shapeData, uint32_t dataSize, uint32_t shapeCount, - const std::vector& lights, - const Camera& camera, - double time, - Texture& gbufferAlbedo, - Texture& gbufferWorldPos, - Texture& gbufferNormal, - Texture& gbufferMaterial, - Texture& gbufferDepth, - Texture& gbufferBackDepth, - const Material3D* materials - ) + void SDF3DRenderPipeline::render(vec4* shapeData, uint32_t dataSize, uint32_t shapeCount, + const std::vector& lights, const Camera& camera, double time, + Texture& gbufferAlbedo, Texture& gbufferWorldPos, Texture& gbufferNormal, + Texture& gbufferMaterial, Texture& gbufferDepth, Texture& gbufferBackDepth, + const Material3D* materials) { // Reset frame counter when path tracer is disabled (no accumulation) if (!m_config.enablePathTracer) @@ -132,11 +125,11 @@ namespace WeirdEngine m_shapeDataBuffer->bind(2); // GBuffer colour attachments - m_sdfShader.setUniform("t_gbufferAlbedo", 3); + m_sdfShader.setUniform("t_gbufferAlbedo", 3); gbufferAlbedo.bind(3); m_sdfShader.setUniform("t_gbufferWorldPos", 4); gbufferWorldPos.bind(4); - m_sdfShader.setUniform("t_gbufferNormal", 5); + m_sdfShader.setUniform("t_gbufferNormal", 5); gbufferNormal.bind(5); m_sdfShader.setUniform("t_gbufferMaterial", 6); gbufferMaterial.bind(6); @@ -154,7 +147,7 @@ namespace WeirdEngine // Resolve accumulation result to the main output target (applying gamma) m_outputRender.bind(); - + m_resolveShader.use(); m_resolveShader.setUniform("t_input", 0); m_accumTexture[m_accumIdx].bind(0); @@ -226,20 +219,22 @@ namespace WeirdEngine ImGui::PushID(label); if (ImGui::Checkbox("Enable Path Tracer", &m_config.enablePathTracer)) - { - WeirdEngine::Logger::log(std::string("Path tracer ") + (m_config.enablePathTracer ? "enabled" : "disabled")); + { + WeirdEngine::Logger::log(std::string("Path tracer ") + + (m_config.enablePathTracer ? "enabled" : "disabled")); - if(m_config.enablePathTracer) + if (m_config.enablePathTracer) m_sdfShader.addDefine("PATH_TRACING"); else m_sdfShader.removeDefine("PATH_TRACING"); } if (ImGui::Checkbox("Enable Anti-Aliasing", &m_config.enableAntialiasing)) - { - WeirdEngine::Logger::log(std::string("Anti-Aliasing ") + (m_config.enableAntialiasing ? "enabled" : "disabled")); + { + WeirdEngine::Logger::log(std::string("Anti-Aliasing ") + + (m_config.enableAntialiasing ? "enabled" : "disabled")); - if(m_config.enableAntialiasing) + if (m_config.enableAntialiasing) m_sdfShader.addDefine("ANTIALIASING"); else m_sdfShader.removeDefine("ANTIALIASING"); @@ -252,7 +247,7 @@ namespace WeirdEngine if (m_config.enablePathTracer) { - if(ImGui::SliderInt("Bounces", &m_config.rayBounces, 1, 10)) + if (ImGui::SliderInt("Bounces", &m_config.rayBounces, 1, 10)) m_frameCounter = 0; if (ImGui::SliderInt("Max Accumulation Frames", &m_config.maxAccumulationFrames, 10, 1000)) diff --git a/src/weird-renderer/core/SDLInitializer.cpp b/src/weird-renderer/core/SDLInitializer.cpp index 5a9ea2b..1830d69 100644 --- a/src/weird-renderer/core/SDLInitializer.cpp +++ b/src/weird-renderer/core/SDLInitializer.cpp @@ -7,8 +7,8 @@ #include #ifndef WEIRD_DISABLE_IMGUI #include -#include #include +#include #endif #include "weird-renderer/core/WeirdFBDevEGL.h" @@ -50,8 +50,8 @@ namespace WeirdEngine #endif if (!SDL_Init(SDL_INIT_VIDEO | SDL_INIT_AUDIO | SDL_INIT_GAMEPAD)) { - std::cout << "SDL_Init with audio failed: " << SDL_GetError() - << " - retrying without audio" << std::endl; + std::cout << "SDL_Init with audio failed: " << SDL_GetError() << " - retrying without audio" + << std::endl; if (!SDL_Init(SDL_INIT_VIDEO | SDL_INIT_GAMEPAD)) { std::string errorMsg = "SDL could not initialize! SDL_Error: "; @@ -147,8 +147,8 @@ namespace WeirdEngine } } - std::cout << "GL_SHADING_LANGUAGE_VERSION: " - << (const char*)glGetString(GL_SHADING_LANGUAGE_VERSION) << std::endl; + std::cout << "GL_SHADING_LANGUAGE_VERSION: " << (const char*)glGetString(GL_SHADING_LANGUAGE_VERSION) + << std::endl; #ifndef WEIRD_DISABLE_IMGUI IMGUI_CHECKVERSION(); @@ -194,8 +194,8 @@ namespace WeirdEngine if (!m_audioStream) { // Audio is not critical: log and keep running silent. - std::cerr << "Failed to open audio stream: " << SDL_GetError() - << " - continuing without audio" << std::endl; + std::cerr << "Failed to open audio stream: " << SDL_GetError() << " - continuing without audio" + << std::endl; } else { diff --git a/src/weird-renderer/core/WeirdFBDevEGL.cpp b/src/weird-renderer/core/WeirdFBDevEGL.cpp index b35c068..49c34ca 100644 --- a/src/weird-renderer/core/WeirdFBDevEGL.cpp +++ b/src/weird-renderer/core/WeirdFBDevEGL.cpp @@ -1,226 +1,287 @@ #include "weird-renderer/core/WeirdFBDevEGL.h" #ifdef WEIRD_USE_FBDEV_EGL -#include #include +#include #include #include #include #include #include -namespace WeirdEngine { -namespace WeirdRenderer { - -namespace { - // ARM libMali fbdev winsys expects a pointer to this struct as the - // EGLNativeWindowType. - struct fbdev_window { - unsigned short width; - unsigned short height; - }; - - EGLDisplay s_display = EGL_NO_DISPLAY; - EGLSurface s_surface = EGL_NO_SURFACE; - EGLContext s_context = EGL_NO_CONTEXT; - fbdev_window s_nativeWindow{0, 0}; - bool s_active = false; - - const char* eglErrorString(EGLint error) { - switch (error) { - case EGL_SUCCESS: return "EGL_SUCCESS"; - case EGL_NOT_INITIALIZED: return "EGL_NOT_INITIALIZED"; - case EGL_BAD_ACCESS: return "EGL_BAD_ACCESS"; - case EGL_BAD_ALLOC: return "EGL_BAD_ALLOC"; - case EGL_BAD_ATTRIBUTE: return "EGL_BAD_ATTRIBUTE"; - case EGL_BAD_CONTEXT: return "EGL_BAD_CONTEXT"; - case EGL_BAD_CONFIG: return "EGL_BAD_CONFIG"; - case EGL_BAD_CURRENT_SURFACE: return "EGL_BAD_CURRENT_SURFACE"; - case EGL_BAD_DISPLAY: return "EGL_BAD_DISPLAY"; - case EGL_BAD_SURFACE: return "EGL_BAD_SURFACE"; - case EGL_BAD_MATCH: return "EGL_BAD_MATCH"; - case EGL_BAD_PARAMETER: return "EGL_BAD_PARAMETER"; - case EGL_BAD_NATIVE_PIXMAP: return "EGL_BAD_NATIVE_PIXMAP"; - case EGL_BAD_NATIVE_WINDOW: return "EGL_BAD_NATIVE_WINDOW"; - case EGL_CONTEXT_LOST: return "EGL_CONTEXT_LOST"; - default: return "UNKNOWN"; - } - } - - void logEGLError(const char* where) { - EGLint error = eglGetError(); - if (error != EGL_SUCCESS) { - std::cerr << "[FBDevEGL] " << where << " failed: 0x" << std::hex << error << std::dec - << " (" << eglErrorString(error) << ")" << std::endl; - } - } -} // namespace - -bool IsFBDevEGLActive() { - return s_active; -} - -bool InitFBDevEGL(int& width, int& height) { - std::cout << "[FBDevEGL] Initializing framebuffer EGL backend..." << std::endl; - - int fbfd = open("/dev/fb0", O_RDWR); - if (fbfd < 0) { - std::cerr << "[FBDevEGL] Failed to open /dev/fb0 (errno=" << errno << ")" << std::endl; - return false; - } - - struct fb_var_screeninfo vinfo; - if (ioctl(fbfd, FBIOGET_VSCREENINFO, &vinfo)) { - std::cerr << "[FBDevEGL] Failed to get fb var screeninfo" << std::endl; - close(fbfd); - return false; - } - close(fbfd); - - width = vinfo.xres; - height = vinfo.yres; - std::cout << "[FBDevEGL] fb0: " << width << "x" << height - << " (virtual " << vinfo.xres_virtual << "x" << vinfo.yres_virtual - << ", " << vinfo.bits_per_pixel << " bpp)" << std::endl; - - // Log client extensions (EGL 1.5 only, harmless if it fails) - const char* clientExts = eglQueryString(EGL_NO_DISPLAY, EGL_EXTENSIONS); - std::cout << "[FBDevEGL] Client extensions: " << (clientExts ? clientExts : "") << std::endl; - - std::cout << "[FBDevEGL] eglGetDisplay..." << std::endl; - s_display = eglGetDisplay(EGL_DEFAULT_DISPLAY); - if (s_display == EGL_NO_DISPLAY) { - logEGLError("eglGetDisplay"); - return false; - } - - EGLint eglMajor = 0, eglMinor = 0; - if (!eglInitialize(s_display, &eglMajor, &eglMinor)) { - logEGLError("eglInitialize"); - s_display = EGL_NO_DISPLAY; - return false; - } - - std::cout << "[FBDevEGL] EGL " << eglMajor << "." << eglMinor << std::endl; - std::cout << "[FBDevEGL] Vendor: " << eglQueryString(s_display, EGL_VENDOR) << std::endl; - std::cout << "[FBDevEGL] Version: " << eglQueryString(s_display, EGL_VERSION) << std::endl; - std::cout << "[FBDevEGL] Client APIs: " << eglQueryString(s_display, EGL_CLIENT_APIS) << std::endl; - std::cout << "[FBDevEGL] Extensions: " << eglQueryString(s_display, EGL_EXTENSIONS) << std::endl; - - if (!eglBindAPI(EGL_OPENGL_ES_API)) { - logEGLError("eglBindAPI(EGL_OPENGL_ES_API)"); - return false; - } - - EGLint attribs[] = { - EGL_SURFACE_TYPE, EGL_WINDOW_BIT, - EGL_RENDERABLE_TYPE, EGL_OPENGL_ES3_BIT, - EGL_RED_SIZE, 8, - EGL_GREEN_SIZE, 8, - EGL_BLUE_SIZE, 8, - EGL_ALPHA_SIZE, 0, - EGL_NONE - }; - EGLConfig config = nullptr; - EGLint numConfigs = 0; - eglChooseConfig(s_display, attribs, &config, 1, &numConfigs); - if (numConfigs == 0 || !config) { - logEGLError("eglChooseConfig"); - std::cerr << "[FBDevEGL] No suitable EGL config found" << std::endl; - return false; - } - std::cout << "[FBDevEGL] Config chosen (" << numConfigs << " matched)" << std::endl; - - s_nativeWindow = fbdev_window{(unsigned short)width, (unsigned short)height}; - - std::cout << "[FBDevEGL] eglCreateWindowSurface (" << width << "x" << height << ")..." << std::endl; - s_surface = eglCreateWindowSurface(s_display, config, (EGLNativeWindowType)&s_nativeWindow, nullptr); - if (s_surface == EGL_NO_SURFACE) { - logEGLError("eglCreateWindowSurface"); - return false; - } - - EGLint ctxAttribs[] = {EGL_CONTEXT_CLIENT_VERSION, 3, EGL_NONE}; - std::cout << "[FBDevEGL] eglCreateContext (ES3)..." << std::endl; - s_context = eglCreateContext(s_display, config, EGL_NO_CONTEXT, ctxAttribs); - if (s_context == EGL_NO_CONTEXT) { - logEGLError("eglCreateContext"); - return false; - } - - if (!eglMakeCurrent(s_display, s_surface, s_surface, s_context)) { - logEGLError("eglMakeCurrent"); - return false; - } - - eglSwapInterval(s_display, 1); - logEGLError("eglSwapInterval"); // informational only - - s_active = true; - std::cout << "[FBDevEGL] Initialization successful!" << std::endl; - return true; -} - -void ShutdownFBDevEGL() { - if (s_display != EGL_NO_DISPLAY) { - eglMakeCurrent(s_display, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT); - if (s_context != EGL_NO_CONTEXT) { - eglDestroyContext(s_display, s_context); - s_context = EGL_NO_CONTEXT; - } - if (s_surface != EGL_NO_SURFACE) { - eglDestroySurface(s_display, s_surface); - s_surface = EGL_NO_SURFACE; - } - eglTerminate(s_display); - s_display = EGL_NO_DISPLAY; - } - s_active = false; -} - -void SwapFBDevBuffers() { - if (s_active) { - eglSwapBuffers(s_display, s_surface); - } -} - -void* GetEGLProcAddress(const char* name) { - void* p = (void*)eglGetProcAddress(name); - if (!p) { - static void* glesLib = nullptr; - static bool triedToLoad = false; - if (!triedToLoad) { - glesLib = dlopen("libGLESv2.so.2", RTLD_LAZY); - if (!glesLib) { - std::cout << "[FBDevEGL] dlopen libGLESv2.so.2 failed: " << dlerror() << std::endl; - glesLib = dlopen("libGLESv2.so", RTLD_LAZY); - if (!glesLib) { - std::cout << "[FBDevEGL] dlopen libGLESv2.so failed: " << dlerror() << std::endl; - } - } - triedToLoad = true; - } - if (glesLib) { - p = dlsym(glesLib, name); - } - } - return p; -} - -} // namespace WeirdRenderer +namespace WeirdEngine +{ + namespace WeirdRenderer + { + + namespace + { + // ARM libMali fbdev winsys expects a pointer to this struct as the + // EGLNativeWindowType. + struct fbdev_window + { + unsigned short width; + unsigned short height; + }; + + EGLDisplay s_display = EGL_NO_DISPLAY; + EGLSurface s_surface = EGL_NO_SURFACE; + EGLContext s_context = EGL_NO_CONTEXT; + fbdev_window s_nativeWindow{0, 0}; + bool s_active = false; + + const char* eglErrorString(EGLint error) + { + switch (error) + { + case EGL_SUCCESS: + return "EGL_SUCCESS"; + case EGL_NOT_INITIALIZED: + return "EGL_NOT_INITIALIZED"; + case EGL_BAD_ACCESS: + return "EGL_BAD_ACCESS"; + case EGL_BAD_ALLOC: + return "EGL_BAD_ALLOC"; + case EGL_BAD_ATTRIBUTE: + return "EGL_BAD_ATTRIBUTE"; + case EGL_BAD_CONTEXT: + return "EGL_BAD_CONTEXT"; + case EGL_BAD_CONFIG: + return "EGL_BAD_CONFIG"; + case EGL_BAD_CURRENT_SURFACE: + return "EGL_BAD_CURRENT_SURFACE"; + case EGL_BAD_DISPLAY: + return "EGL_BAD_DISPLAY"; + case EGL_BAD_SURFACE: + return "EGL_BAD_SURFACE"; + case EGL_BAD_MATCH: + return "EGL_BAD_MATCH"; + case EGL_BAD_PARAMETER: + return "EGL_BAD_PARAMETER"; + case EGL_BAD_NATIVE_PIXMAP: + return "EGL_BAD_NATIVE_PIXMAP"; + case EGL_BAD_NATIVE_WINDOW: + return "EGL_BAD_NATIVE_WINDOW"; + case EGL_CONTEXT_LOST: + return "EGL_CONTEXT_LOST"; + default: + return "UNKNOWN"; + } + } + + void logEGLError(const char* where) + { + EGLint error = eglGetError(); + if (error != EGL_SUCCESS) + { + std::cerr << "[FBDevEGL] " << where << " failed: 0x" << std::hex << error << std::dec << " (" + << eglErrorString(error) << ")" << std::endl; + } + } + } // namespace + + bool IsFBDevEGLActive() + { + return s_active; + } + + bool InitFBDevEGL(int& width, int& height) + { + std::cout << "[FBDevEGL] Initializing framebuffer EGL backend..." << std::endl; + + int fbfd = open("/dev/fb0", O_RDWR); + if (fbfd < 0) + { + std::cerr << "[FBDevEGL] Failed to open /dev/fb0 (errno=" << errno << ")" << std::endl; + return false; + } + + struct fb_var_screeninfo vinfo; + if (ioctl(fbfd, FBIOGET_VSCREENINFO, &vinfo)) + { + std::cerr << "[FBDevEGL] Failed to get fb var screeninfo" << std::endl; + close(fbfd); + return false; + } + close(fbfd); + + width = vinfo.xres; + height = vinfo.yres; + std::cout << "[FBDevEGL] fb0: " << width << "x" << height << " (virtual " << vinfo.xres_virtual << "x" + << vinfo.yres_virtual << ", " << vinfo.bits_per_pixel << " bpp)" << std::endl; + + // Log client extensions (EGL 1.5 only, harmless if it fails) + const char* clientExts = eglQueryString(EGL_NO_DISPLAY, EGL_EXTENSIONS); + std::cout << "[FBDevEGL] Client extensions: " << (clientExts ? clientExts : "") << std::endl; + + std::cout << "[FBDevEGL] eglGetDisplay..." << std::endl; + s_display = eglGetDisplay(EGL_DEFAULT_DISPLAY); + if (s_display == EGL_NO_DISPLAY) + { + logEGLError("eglGetDisplay"); + return false; + } + + EGLint eglMajor = 0, eglMinor = 0; + if (!eglInitialize(s_display, &eglMajor, &eglMinor)) + { + logEGLError("eglInitialize"); + s_display = EGL_NO_DISPLAY; + return false; + } + + std::cout << "[FBDevEGL] EGL " << eglMajor << "." << eglMinor << std::endl; + std::cout << "[FBDevEGL] Vendor: " << eglQueryString(s_display, EGL_VENDOR) << std::endl; + std::cout << "[FBDevEGL] Version: " << eglQueryString(s_display, EGL_VERSION) << std::endl; + std::cout << "[FBDevEGL] Client APIs: " << eglQueryString(s_display, EGL_CLIENT_APIS) << std::endl; + std::cout << "[FBDevEGL] Extensions: " << eglQueryString(s_display, EGL_EXTENSIONS) << std::endl; + + if (!eglBindAPI(EGL_OPENGL_ES_API)) + { + logEGLError("eglBindAPI(EGL_OPENGL_ES_API)"); + return false; + } + + EGLint attribs[] = {EGL_SURFACE_TYPE, + EGL_WINDOW_BIT, + EGL_RENDERABLE_TYPE, + EGL_OPENGL_ES3_BIT, + EGL_RED_SIZE, + 8, + EGL_GREEN_SIZE, + 8, + EGL_BLUE_SIZE, + 8, + EGL_ALPHA_SIZE, + 0, + EGL_NONE}; + EGLConfig config = nullptr; + EGLint numConfigs = 0; + eglChooseConfig(s_display, attribs, &config, 1, &numConfigs); + if (numConfigs == 0 || !config) + { + logEGLError("eglChooseConfig"); + std::cerr << "[FBDevEGL] No suitable EGL config found" << std::endl; + return false; + } + std::cout << "[FBDevEGL] Config chosen (" << numConfigs << " matched)" << std::endl; + + s_nativeWindow = fbdev_window{(unsigned short)width, (unsigned short)height}; + + std::cout << "[FBDevEGL] eglCreateWindowSurface (" << width << "x" << height << ")..." << std::endl; + s_surface = eglCreateWindowSurface(s_display, config, (EGLNativeWindowType)&s_nativeWindow, nullptr); + if (s_surface == EGL_NO_SURFACE) + { + logEGLError("eglCreateWindowSurface"); + return false; + } + + EGLint ctxAttribs[] = {EGL_CONTEXT_CLIENT_VERSION, 3, EGL_NONE}; + std::cout << "[FBDevEGL] eglCreateContext (ES3)..." << std::endl; + s_context = eglCreateContext(s_display, config, EGL_NO_CONTEXT, ctxAttribs); + if (s_context == EGL_NO_CONTEXT) + { + logEGLError("eglCreateContext"); + return false; + } + + if (!eglMakeCurrent(s_display, s_surface, s_surface, s_context)) + { + logEGLError("eglMakeCurrent"); + return false; + } + + eglSwapInterval(s_display, 1); + logEGLError("eglSwapInterval"); // informational only + + s_active = true; + std::cout << "[FBDevEGL] Initialization successful!" << std::endl; + return true; + } + + void ShutdownFBDevEGL() + { + if (s_display != EGL_NO_DISPLAY) + { + eglMakeCurrent(s_display, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT); + if (s_context != EGL_NO_CONTEXT) + { + eglDestroyContext(s_display, s_context); + s_context = EGL_NO_CONTEXT; + } + if (s_surface != EGL_NO_SURFACE) + { + eglDestroySurface(s_display, s_surface); + s_surface = EGL_NO_SURFACE; + } + eglTerminate(s_display); + s_display = EGL_NO_DISPLAY; + } + s_active = false; + } + + void SwapFBDevBuffers() + { + if (s_active) + { + eglSwapBuffers(s_display, s_surface); + } + } + + void* GetEGLProcAddress(const char* name) + { + void* p = (void*)eglGetProcAddress(name); + if (!p) + { + static void* glesLib = nullptr; + static bool triedToLoad = false; + if (!triedToLoad) + { + glesLib = dlopen("libGLESv2.so.2", RTLD_LAZY); + if (!glesLib) + { + std::cout << "[FBDevEGL] dlopen libGLESv2.so.2 failed: " << dlerror() << std::endl; + glesLib = dlopen("libGLESv2.so", RTLD_LAZY); + if (!glesLib) + { + std::cout << "[FBDevEGL] dlopen libGLESv2.so failed: " << dlerror() << std::endl; + } + } + triedToLoad = true; + } + if (glesLib) + { + p = dlsym(glesLib, name); + } + } + return p; + } + + } // namespace WeirdRenderer } // namespace WeirdEngine #else // !WEIRD_USE_FBDEV_EGL -namespace WeirdEngine { -namespace WeirdRenderer { +namespace WeirdEngine +{ + namespace WeirdRenderer + { -bool IsFBDevEGLActive() { return false; } -bool InitFBDevEGL(int&, int&) { return false; } -void ShutdownFBDevEGL() {} -void SwapFBDevBuffers() {} -void* GetEGLProcAddress(const char*) { return nullptr; } + bool IsFBDevEGLActive() + { + return false; + } + bool InitFBDevEGL(int&, int&) + { + return false; + } + void ShutdownFBDevEGL() {} + void SwapFBDevBuffers() {} + void* GetEGLProcAddress(const char*) + { + return nullptr; + } -} // namespace WeirdRenderer + } // namespace WeirdRenderer } // namespace WeirdEngine #endif diff --git a/src/weird-renderer/resources/Mesh.cpp b/src/weird-renderer/resources/Mesh.cpp index 7ddddb1..91b6fdd 100644 --- a/src/weird-renderer/resources/Mesh.cpp +++ b/src/weird-renderer/resources/Mesh.cpp @@ -93,7 +93,7 @@ namespace WeirdEngine // textures[i].bind(i); // textures[i].texUnit(shader, ("t_" + type + num).c_str(), unit); } - + glUniform1i(glGetUniformLocation(shader.ID, "u_materialIndex"), materialIndex); glUniform1i(glGetUniformLocation(shader.ID, "u_hasDiffuse"), textures.size() > 0 ? 1 : 0); diff --git a/src/weird-renderer/resources/Shader.cpp b/src/weird-renderer/resources/Shader.cpp index 292e629..6a2fd8f 100644 --- a/src/weird-renderer/resources/Shader.cpp +++ b/src/weird-renderer/resources/Shader.cpp @@ -1,9 +1,9 @@ #include "weird-renderer/resources/Shader.h" +#include "weird-engine/Logger.h" #include #include #include -#include "weird-engine/Logger.h" // #define LOG_SHADER_COMPILATION @@ -428,8 +428,9 @@ namespace WeirdEngine #if !defined(NDEBUG) && defined(LOG_SHADER_COMPILATION) auto endTime = std::chrono::high_resolution_clock::now(); auto ms = std::chrono::duration_cast(endTime - startTime).count(); - - std::string logMsg = std::string("Compiling program: \n V -> ") + m_vertexFile + "\n F -> " + m_fragmentFile + "\n"; + + std::string logMsg = + std::string("Compiling program: \n V -> ") + m_vertexFile + "\n F -> " + m_fragmentFile + "\n"; for (const auto& define : m_activeDefines) { logMsg += define + "\n"; @@ -453,7 +454,8 @@ namespace WeirdEngine glGetShaderiv(shader, GL_COMPILE_STATUS, &hasCompiled); if (hasCompiled == GL_FALSE) { - std::string logMsg = std::string("Compiling Shader Program:\n VS: ") + m_vertexFile + "\n FS: " + m_fragmentFile; + std::string logMsg = + std::string("Compiling Shader Program:\n VS: ") + m_vertexFile + "\n FS: " + m_fragmentFile; glGetShaderInfoLog(shader, 1024, NULL, infoLog); WeirdEngine::Logger::error(logMsg + "\nSHADER_COMPILATION_ERROR for:" + type + "\n" + infoLog); } @@ -463,7 +465,8 @@ namespace WeirdEngine glGetProgramiv(shader, GL_LINK_STATUS, &hasCompiled); if (hasCompiled == GL_FALSE) { - std::string logMsg = std::string("Compiling Shader Program:\n VS: ") + m_vertexFile + "\n FS: " + m_fragmentFile; + std::string logMsg = + std::string("Compiling Shader Program:\n VS: ") + m_vertexFile + "\n FS: " + m_fragmentFile; glGetProgramInfoLog(shader, 1024, NULL, infoLog); WeirdEngine::Logger::error(logMsg + "\nSHADER_LINKING_ERROR for:" + type + "\n" + infoLog); } diff --git a/src/weird-renderer/resources/Texture.cpp b/src/weird-renderer/resources/Texture.cpp index 3b89f17..2a25bde 100644 --- a/src/weird-renderer/resources/Texture.cpp +++ b/src/weird-renderer/resources/Texture.cpp @@ -84,7 +84,8 @@ namespace WeirdEngine if (data != nullptr) return data; - zeroDataU8.assign(static_cast(width) * static_cast(height) * static_cast(channels), 0u); + zeroDataU8.assign( + static_cast(width) * static_cast(height) * static_cast(channels), 0u); return zeroDataU8.data(); }; @@ -93,7 +94,8 @@ namespace WeirdEngine if (data != nullptr) return data; - zeroDataF32.assign(static_cast(width) * static_cast(height) * static_cast(channels), 0.0f); + zeroDataF32.assign( + static_cast(width) * static_cast(height) * static_cast(channels), 0.0f); return zeroDataF32.data(); }; @@ -116,7 +118,8 @@ namespace WeirdEngine // Handle color texture // Use sized internal format GL_RGB8; GL_RGB (unsized) is not guaranteed // to be color-renderable as a framebuffer attachment in GLES 3.0. - glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB8, width, height, 0, GL_RGB, GL_UNSIGNED_BYTE, getUploadDataU8(3)); + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB8, width, height, 0, GL_RGB, GL_UNSIGNED_BYTE, + getUploadDataU8(3)); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); @@ -132,7 +135,8 @@ namespace WeirdEngine // Handle color with alpha texture // Use sized internal format GL_RGBA8; GL_RGBA (unsized) is not guaranteed // to be color-renderable as a framebuffer attachment in GLES 3.0. - glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, getUploadDataU8(4)); + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, + getUploadDataU8(4)); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); @@ -146,7 +150,8 @@ namespace WeirdEngine case TextureType::SingleChannel: { - glTexImage2D(GL_TEXTURE_2D, 0, GL_R8, width, height, 0, GL_RED, GL_UNSIGNED_BYTE, getUploadDataU8(1)); + glTexImage2D(GL_TEXTURE_2D, 0, GL_R8, width, height, 0, GL_RED, GL_UNSIGNED_BYTE, + getUploadDataU8(1)); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); @@ -181,7 +186,8 @@ namespace WeirdEngine } case TextureType::Data: { - glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA16F, width, height, 0, GL_RGBA, GL_FLOAT, getUploadDataF32(4)); + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA16F, width, height, 0, GL_RGBA, GL_FLOAT, + getUploadDataF32(4)); 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); @@ -192,7 +198,8 @@ namespace WeirdEngine } case TextureType::LinearData: { - glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA16F, width, height, 0, GL_RGBA, GL_FLOAT, getUploadDataF32(4)); + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA16F, width, height, 0, GL_RGBA, GL_FLOAT, + getUploadDataF32(4)); 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_CLAMP_TO_EDGE); @@ -204,7 +211,8 @@ namespace WeirdEngine case TextureType::AccumulationData: { // Use 32-bit floats for accumulation to avoid precision stalling over thousands of frames - glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA32F, width, height, 0, GL_RGBA, GL_FLOAT, getUploadDataF32(4)); + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA32F, width, height, 0, GL_RGBA, GL_FLOAT, + getUploadDataF32(4)); 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_CLAMP_TO_EDGE); @@ -217,7 +225,8 @@ namespace WeirdEngine { // Use sized internal format GL_RGB8; GL_RGB (unsized) is not guaranteed // to be color-renderable as a framebuffer attachment in GLES 3.0. - glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB8, width, height, 0, GL_RGB, GL_UNSIGNED_BYTE, getUploadDataU8(3)); + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB8, width, height, 0, GL_RGB, GL_UNSIGNED_BYTE, + getUploadDataU8(3)); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); @@ -230,7 +239,8 @@ namespace WeirdEngine case TextureType::IntData: { std::vector zeroDataI32(width * height, 0); - glTexImage2D(GL_TEXTURE_2D, 0, GL_R32I, width, height, 0, GL_RED_INTEGER, GL_INT, zeroDataI32.data()); + glTexImage2D(GL_TEXTURE_2D, 0, GL_R32I, width, height, 0, GL_RED_INTEGER, GL_INT, + zeroDataI32.data()); 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); @@ -279,10 +289,11 @@ namespace WeirdEngine return; } - // In GLES, reading from floating-point or integer framebuffers using GL_UNSIGNED_BYTE + // In GLES, reading from floating-point or integer framebuffers using GL_UNSIGNED_BYTE // can fail with GL_INVALID_OPERATION. We must query the attachment component type. GLint attachmentType = 0; - glGetFramebufferAttachmentParameteriv(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_FRAMEBUFFER_ATTACHMENT_COMPONENT_TYPE, &attachmentType); + glGetFramebufferAttachmentParameteriv(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, + GL_FRAMEBUFFER_ATTACHMENT_COMPONENT_TYPE, &attachmentType); unsigned char* pixels_uchar = new unsigned char[width * height * 4]; @@ -304,7 +315,8 @@ namespace WeirdEngine for (int i = 0; i < width * height * 4; ++i) { - pixels_uchar[i] = static_cast(glm::clamp((float)pixels_i[i] / 255.0f, 0.0f, 1.0f) * 255.0f); + pixels_uchar[i] = + static_cast(glm::clamp((float)pixels_i[i] / 255.0f, 0.0f, 1.0f) * 255.0f); } delete[] pixels_i; } @@ -315,7 +327,8 @@ namespace WeirdEngine for (int i = 0; i < width * height * 4; ++i) { - pixels_uchar[i] = static_cast(glm::clamp((float)pixels_ui[i] / 255.0f, 0.0f, 1.0f) * 255.0f); + pixels_uchar[i] = + static_cast(glm::clamp((float)pixels_ui[i] / 255.0f, 0.0f, 1.0f) * 255.0f); } delete[] pixels_ui; } @@ -375,7 +388,7 @@ namespace WeirdEngine glGetTexImage(GL_TEXTURE_2D, 0, format, GL_FLOAT, pixels); unsigned char* pixels_uchar = new unsigned char[(size_t)width * height * 4]; - + for (int y = 0; y < height; y++) { size_t src_row_start = (size_t)format_channels * width * y; @@ -388,7 +401,7 @@ namespace WeirdEngine pixels_uchar[dest_idx] = static_cast(glm::clamp(pixels[src_idx], 0.0f, 1.0f) * 255.0f); - + if (format_channels >= 3) { pixels_uchar[dest_idx + 1] = diff --git a/src/weird-renderer/scene/Camera.cpp b/src/weird-renderer/scene/Camera.cpp index 773987c..35ad74c 100644 --- a/src/weird-renderer/scene/Camera.cpp +++ b/src/weird-renderer/scene/Camera.cpp @@ -7,7 +7,7 @@ namespace WeirdEngine namespace WeirdRenderer { Camera::Camera(glm::vec3 position) - : position(position) + : position(position) { } diff --git a/src/weird-renderer/shaders/2d/background.frag b/src/weird-renderer/shaders/2d/background.frag index 4eb66c6..7d044c6 100644 --- a/src/weird-renderer/shaders/2d/background.frag +++ b/src/weird-renderer/shaders/2d/background.frag @@ -30,7 +30,10 @@ uniform bool u_enableBlend; #include "background_injection" #ifndef HAS_CUSTOM_BACKGROUND -vec3 getBackground(vec2 uv, vec2 worldPos) { return u_bgPrimaryColor.rgb; } +vec3 getBackground(vec2 uv, vec2 worldPos) +{ + return u_bgPrimaryColor.rgb; +} #endif void main() @@ -43,12 +46,13 @@ void main() vec3 background = getBackground(uv, pos); - if (u_enableBlend) { + if (u_enableBlend) + { vec3 prevBackground = texture(t_prevBackground, v_texCoord).rgb; - + vec3 diff = background - prevBackground; vec3 blendStep = diff * 0.05; - + // Ensure we don't get stuck due to 8-bit color quantization blendStep += sign(diff) * (1.5 / 255.0); blendStep = clamp(blendStep, -abs(diff), abs(diff)); diff --git a/src/weird-renderer/shaders/2d/jump_flood_step.frag b/src/weird-renderer/shaders/2d/jump_flood_step.frag index 5439cf7..85de3a0 100644 --- a/src/weird-renderer/shaders/2d/jump_flood_step.frag +++ b/src/weird-renderer/shaders/2d/jump_flood_step.frag @@ -41,8 +41,8 @@ void main() float bestDist = data.z; // 8 directions - const vec2 OFFSETS[8] = - vec2[8](vec2(-1.0, 0.0), vec2(1.0, 0.0), vec2(0.0, -1.0), vec2(0.0, 1.0), vec2(-1.0, -1.0), vec2(-1.0, 1.0), vec2(1.0, -1.0), vec2(1.0, 1.0)); + const vec2 OFFSETS[8] = vec2[8](vec2(-1.0, 0.0), vec2(1.0, 0.0), vec2(0.0, -1.0), vec2(0.0, 1.0), vec2(-1.0, -1.0), + vec2(-1.0, 1.0), vec2(1.0, -1.0), vec2(1.0, 1.0)); // Check neighbors at jump distance for (int i = 0; i < 8; i++) diff --git a/src/weird-renderer/shaders/2d/lighting.frag b/src/weird-renderer/shaders/2d/lighting.frag index 66db86c..62456f2 100644 --- a/src/weird-renderer/shaders/2d/lighting.frag +++ b/src/weird-renderer/shaders/2d/lighting.frag @@ -45,8 +45,8 @@ uniform float u_ambienOcclusionStrength; uniform float u_overscan; uniform vec3 u_shadowTint; -// For cast shadows and ambient occlusion, we need a distance function that has been corrected to fix smooth union artifacts -// Real distance in screen UV space +// For cast shadows and ambient occlusion, we need a distance function that has been corrected to fix smooth union +// artifacts Real distance in screen UV space float mapOutside(vec2 p) { // Remap screen UV to overscan texture UV @@ -75,7 +75,8 @@ vec2 softShadow(vec2 ro, vec2 rd, float initialDistance, float far, float k) break; } - // Sample distance in screen UV space, which is the same space we're raymarching through, so no correction needed + // Sample distance in screen UV space, which is the same space we're raymarching through, so no correction + // needed float h = mapOutside(ro + rd * t); // Track where the shadow is strongest (closest approach to an occluder) @@ -131,9 +132,9 @@ float renderShadows(vec2 uv, vec2 rd) return shadowValue; } - // Ligthing inside shapes uses the original distance field, without correction (world coordinates) -// Only really used for normals, but it also gives a more consistent light falloff near edges that isn't affected by zoom level +// Only really used for normals, but it also gives a more consistent light falloff near edges that isn't affected by +// zoom level float mapInside(vec2 p) { return texture(t_distanceSampledTexture, p).x; @@ -158,11 +159,10 @@ float calculateLight(vec2 uv, vec2 rd, vec2 normal, float shadows, float innerDi // Apply border mask float lightOnBorderOnly = extraLight * borderMask; float light = 1.0 + lightOnBorderOnly; - + return clamp(light, 0.0, 10.0); } - void main() { vec2 screenUV = v_texCoord; @@ -209,8 +209,6 @@ void main() shapeFactor = 1.0; #endif - - // Point light // vec2 rd = normalize(vec2(1.0) - screenUV); @@ -230,7 +228,8 @@ void main() #else float shadows = 1.0; - float t = SHADOW_VALUE; // Force ambient occlusion to be fully applied when shadows are disabled, so we can still get darkening without directional light + float t = SHADOW_VALUE; // Force ambient occlusion to be fully applied when shadows are disabled, so we can still + // get darkening without directional light #endif @@ -282,7 +281,8 @@ void main() vec3 backgroundColor = (col0 + col1 + col2 + col3) * 0.25; - // Blend with the non-refraction-sampled background color based on shape factor to show refraction only inside shapes + // Blend with the non-refraction-sampled background color based on shape factor to show refraction only inside + // shapes backgroundColor = mix(texture(t_backgroundTexture, screenUV).rgb, backgroundColor, shapeFactor); #else @@ -298,13 +298,13 @@ void main() color = vec3(normal, 0.0); #endif - // Remap the shadow value (which normally goes from SHADOW_VALUE to 1.0) + // Remap the shadow value (which normally goes from SHADOW_VALUE to 1.0) // so we can apply the full shadow tint when fully shadowed. float litFactor = clamp((shadows - SHADOW_VALUE) / (1.0 - SHADOW_VALUE), 0.0, 1.0); - + // If AO pushes shadows below SHADOW_VALUE, we darken the ambient tint itself float ambientOcclusion = clamp(shadows / SHADOW_VALUE, 0.0, 1.0); - + vec3 shadowTransmittance = mix(u_shadowTint * ambientOcclusion, vec3(1.0), litFactor); vec3 shadedBackground = backgroundColor * shadowTransmittance; diff --git a/src/weird-renderer/shaders/2d/material_color.frag b/src/weird-renderer/shaders/2d/material_color.frag index 6c2fa00..95e7dee 100644 --- a/src/weird-renderer/shaders/2d/material_color.frag +++ b/src/weird-renderer/shaders/2d/material_color.frag @@ -71,7 +71,7 @@ void main() vec4 diff = clamp((c - currentColor), -1.0, 1.0); vec4 blendedColor = currentColor + (min(u_deltaTime * u_materialBlendSpeed, 1.0) * diff); - // Use the mask to force the centers of the dots to get the instantaneous color every frame, + // Use the mask to force the centers of the dots to get the instantaneous color every frame, // while still allowing temporal blending at the edges and outside. c = mix(blendedColor, c, clamp(mask, 0.0, 1.0)); diff --git a/src/weird-renderer/shaders/2d/sdf_distance.frag b/src/weird-renderer/shaders/2d/sdf_distance.frag index 90951e7..83af652 100644 --- a/src/weird-renderer/shaders/2d/sdf_distance.frag +++ b/src/weird-renderer/shaders/2d/sdf_distance.frag @@ -123,12 +123,12 @@ vec3 getDistanceMaterialMask(vec2 p, vec2 uv) int materialId = int(positionSizeMaterial.w); #ifdef UI_PIPELINE - float objectDist = shape_circle(p - positionSizeMaterial.xy, 5.0); + float objectDist = shape_circle(p - positionSizeMaterial.xy, 5.0); #else - float objectDist = shape_circle(p - positionSizeMaterial.xy); + float objectDist = shape_circle(p - positionSizeMaterial.xy); #endif - mask = max(mask, -objectDist * 4.0); + mask = max(mask, -objectDist * 4.0); #ifdef BLEND_SHAPES finalMaterialId = objectDist <= minColorDist ? materialId : finalMaterialId; @@ -284,9 +284,8 @@ void main() #ifdef DEBUG_SHOW_GRID vec2 localP = pos - u_gridBoundsMin; - bool inBounds = localP.x >= 0.0 && localP.y >= 0.0 && - localP.x < float(u_gridCols) * u_gridStep.x && - localP.y < float(u_gridRows) * u_gridStep.y; + bool inBounds = localP.x >= 0.0 && localP.y >= 0.0 && localP.x < float(u_gridCols) * u_gridStep.x && + localP.y < float(u_gridRows) * u_gridStep.y; if (inBounds) { vec2 fracLocal = mod(localP, u_gridStep); diff --git a/src/weird-renderer/shaders/3d/gbuffer.frag b/src/weird-renderer/shaders/3d/gbuffer.frag index 01a318d..53e708c 100644 --- a/src/weird-renderer/shaders/3d/gbuffer.frag +++ b/src/weird-renderer/shaders/3d/gbuffer.frag @@ -3,9 +3,9 @@ precision highp float; precision highp int; // GBuffer outputs -layout(location = 0) out vec4 out_albedo; // RGB = diffuse color, A = specular intensity -layout(location = 1) out vec4 out_worldPos; // RGB = world position, A = 1.0 (marks valid pixel) -layout(location = 2) out vec4 out_normal; // RGB = world normal (signed, not remapped), A = unused +layout(location = 0) out vec4 out_albedo; // RGB = diffuse color, A = specular intensity +layout(location = 1) out vec4 out_worldPos; // RGB = world position, A = 1.0 (marks valid pixel) +layout(location = 2) out vec4 out_normal; // RGB = world normal (signed, not remapped), A = unused layout(location = 3) out int out_material; // Inputs from vertex shader @@ -45,8 +45,8 @@ void main() albedo = vec3(1.0); // Override albedo to white for testing purposes - out_albedo = vec4(albedo, specVal); + out_albedo = vec4(albedo, specVal); out_worldPos = vec4(v_worldPos, 1.0); - out_normal = vec4(normalize(v_normal), 0.0); + out_normal = vec4(normalize(v_normal), 0.0); out_material = u_materialIndex; } diff --git a/src/weird-renderer/shaders/3d/geometry.frag b/src/weird-renderer/shaders/3d/geometry.frag index 026b988..2ff7271 100644 --- a/src/weird-renderer/shaders/3d/geometry.frag +++ b/src/weird-renderer/shaders/3d/geometry.frag @@ -97,42 +97,34 @@ float logisticDepth(float depth, float steepness, float offset) return 1.0 / (1.0 + exp(-steepness * (z - offset))); } -const int bayer4x4[16] = int[16]( - 0, 8, 2, 10, - 12, 4, 14, 6, - 3, 11, 1, 9, - 15, 7, 13, 5 -); - -float GetBayerThreshold(vec2 coord) +const int bayer4x4[16] = int[16](0, 8, 2, 10, 12, 4, 14, 6, 3, 11, 1, 9, 15, 7, 13, 5); + +float GetBayerThreshold(vec2 coord) { int x = int(coord.x) % 4; int y = int(coord.y) % 4; float bayerValue = float(bayer4x4[y * 4 + x]) + 0.5; - return bayerValue / 16.0; + return bayerValue / 16.0; } // Generates a consistent 2D offset based on an object ID to prevent Dither Correlation -vec2 HashID(float id) +vec2 HashID(float id) { - return vec2( - fract(sin(id * 12.9898) * 43758.5453) * 100.0, - fract(sin(id * 78.233) * 43758.5453) * 100.0 - ); + return vec2(fract(sin(id * 12.9898) * 43758.5453) * 100.0, fract(sin(id * 78.233) * 43758.5453) * 100.0); } void main() { float alpha = 1.0; - - if (alpha < 1.0) + + if (alpha < 1.0) { vec2 offset = HashID(float(2)); - + // Note: Change 1.0 to 2.0 or 4.0 here if you want chunkier retro dither pixels - float bayer = GetBayerThreshold((gl_FragCoord.xy + offset) / 1.0); - - if (alpha <= bayer) + float bayer = GetBayerThreshold((gl_FragCoord.xy + offset) / 1.0); + + if (alpha <= bayer) { discard; // Skip surface by pushing distance past the FAR plane } diff --git a/src/weird-renderer/shaders/3d/sdf_raymarching.frag b/src/weird-renderer/shaders/3d/sdf_raymarching.frag index 6e201db..f8d5a0c 100644 --- a/src/weird-renderer/shaders/3d/sdf_raymarching.frag +++ b/src/weird-renderer/shaders/3d/sdf_raymarching.frag @@ -60,14 +60,14 @@ layout(location = 0) out vec4 FragColor; in vec2 v_texCoord; uniform sampler2D t_previousColor; -uniform sampler2D t_depthTexture; // GBuffer depth (mesh geometry) +uniform sampler2D t_depthTexture; // GBuffer depth (mesh geometry) uniform highp sampler2D t_shapeBuffer; // Deferred GBuffer -uniform sampler2D t_gbufferAlbedo; // RGB = mesh diffuse, A = specular -uniform sampler2D t_gbufferWorldPos; // RGB = world-space position, A = 1 if valid -uniform sampler2D t_gbufferNormal; // RGB = world-space normal -uniform isampler2D t_gbufferMaterial; // R = material ID -uniform sampler2D t_gbufferBackDepth; // Back-face depth +uniform sampler2D t_gbufferAlbedo; // RGB = mesh diffuse, A = specular +uniform sampler2D t_gbufferWorldPos; // RGB = world-space position, A = 1 if valid +uniform sampler2D t_gbufferNormal; // RGB = world-space normal +uniform isampler2D t_gbufferMaterial; // R = material ID +uniform sampler2D t_gbufferBackDepth; // Back-face depth uniform int u_loadedObjects; uniform int u_customShapeCount; @@ -173,9 +173,7 @@ float perlin(vec2 p) // Hash 3D vec3 hash3D(vec3 p) { - p = vec3(dot(p, vec3(127.1, 311.7, 74.7)), - dot(p, vec3(269.5, 183.3, 246.1)), - dot(p, vec3(113.5, 271.9, 124.6))); + p = vec3(dot(p, vec3(127.1, 311.7, 74.7)), dot(p, vec3(269.5, 183.3, 246.1)), dot(p, vec3(113.5, 271.9, 124.6))); return normalize(fract(sin(p) * 43758.5453123) * 2.0 - 1.0); } @@ -265,25 +263,27 @@ float modifyDistanceBasedOnMaterial(float dist, int materialId, int objectId) // projects outside the screen or behind the camera. vec2 worldToGBufferUV(vec3 worldPos, out bool valid) { - vec4 clipPos = u_viewProjection * vec4(worldPos, 1.0); + vec4 clipPos = u_viewProjection * vec4(worldPos, 1.0); - // Behind the camera - if (clipPos.w <= 0.0) { - valid = false; - return vec2(0.0); - } + // Behind the camera + if (clipPos.w <= 0.0) + { + valid = false; + return vec2(0.0); + } - vec3 ndc = clipPos.xyz / clipPos.w; // [-1, 1] + vec3 ndc = clipPos.xyz / clipPos.w; // [-1, 1] - // Out-of-screen check with a small margin to avoid edge artifacts - const float MARGIN = 0.02; - if (abs(ndc.x) > 1.0 - MARGIN || abs(ndc.y) > 1.0 - MARGIN || ndc.z > 1.0 || ndc.z < -1.0) { - valid = false; - return vec2(0.0); - } + // Out-of-screen check with a small margin to avoid edge artifacts + const float MARGIN = 0.02; + if (abs(ndc.x) > 1.0 - MARGIN || abs(ndc.y) > 1.0 - MARGIN || ndc.z > 1.0 || ndc.z < -1.0) + { + valid = false; + return vec2(0.0); + } - valid = true; - return ndc.xy * 0.5 + 0.5; // [0, 1] UV + valid = true; + return ndc.xy * 0.5 + 0.5; // [0, 1] UV } // Forward declaration @@ -293,71 +293,71 @@ float linearizeGBufferDepth(float d); // Returns a large positive value if no mesh is visible at this projection. float meshSDF(vec3 p) { - bool valid; - vec2 uv = worldToGBufferUV(p, valid); - - if (!valid) - return u_far; // No mesh data here — don't occlude - - float frontDepthRaw = texture(t_depthTexture, uv).r; - if (frontDepthRaw > 1.0 - 0.0001) - return u_far; // Sky pixel — no mesh - - float backDepthRaw = texture(t_gbufferBackDepth, uv).r; - - float frontDepthLinear = linearizeGBufferDepth(frontDepthRaw); - float backDepthLinear = linearizeGBufferDepth(backDepthRaw); - - vec4 clipPos = u_viewProjection * vec4(p, 1.0); - float sampleDepthRaw = clipPos.z / clipPos.w * 0.5 + 0.5; - float sampleDepthLinear = linearizeGBufferDepth(sampleDepthRaw); - - // We are inside the mesh if our depth is between front and back faces - bool insideSlab = (sampleDepthLinear > frontDepthLinear) && (sampleDepthLinear < backDepthLinear); - - // Shrink the mesh slightly to prevent self-shadowing acne - const float SHADOW_BIAS = 0.05; - - if (insideSlab) - { - // Distance from sample to front face - vec3 meshWorldPos = texture(t_gbufferWorldPos, uv).rgb; - float distToFront = length(p - meshWorldPos); - - // Acne zone for front face - if (distToFront < SHADOW_BIAS) - { - return SHADOW_BIAS - distToFront; - } - - // Acne zone for back face (using Z depth difference as approximation) - float zDistToBack = backDepthLinear - sampleDepthLinear; - if (zDistToBack < SHADOW_BIAS) - { - return SHADOW_BIAS - zDistToBack; - } - - // Deep inside the mesh: return 0.0 to immediately register a hit! - // DO NOT return a negative value, otherwise the raymarcher will step backwards and rattle. - return 0.0; - } - else - { - if (sampleDepthLinear <= frontDepthLinear) - { - // In front of the mesh. Return Euclidean distance + bias so it overshoots - // slightly into the mesh, landing exactly at the 0.0 boundary. - vec3 meshWorldPos = texture(t_gbufferWorldPos, uv).rgb; - float distToFront = length(p - meshWorldPos); - return min(distToFront + SHADOW_BIAS, 2.0); - } - else - { - // Behind the back face. Return safe distance + bias. - float zDistToBack = sampleDepthLinear - backDepthLinear; - return min(zDistToBack * 0.5 + SHADOW_BIAS, 2.0); - } - } + bool valid; + vec2 uv = worldToGBufferUV(p, valid); + + if (!valid) + return u_far; // No mesh data here — don't occlude + + float frontDepthRaw = texture(t_depthTexture, uv).r; + if (frontDepthRaw > 1.0 - 0.0001) + return u_far; // Sky pixel — no mesh + + float backDepthRaw = texture(t_gbufferBackDepth, uv).r; + + float frontDepthLinear = linearizeGBufferDepth(frontDepthRaw); + float backDepthLinear = linearizeGBufferDepth(backDepthRaw); + + vec4 clipPos = u_viewProjection * vec4(p, 1.0); + float sampleDepthRaw = clipPos.z / clipPos.w * 0.5 + 0.5; + float sampleDepthLinear = linearizeGBufferDepth(sampleDepthRaw); + + // We are inside the mesh if our depth is between front and back faces + bool insideSlab = (sampleDepthLinear > frontDepthLinear) && (sampleDepthLinear < backDepthLinear); + + // Shrink the mesh slightly to prevent self-shadowing acne + const float SHADOW_BIAS = 0.05; + + if (insideSlab) + { + // Distance from sample to front face + vec3 meshWorldPos = texture(t_gbufferWorldPos, uv).rgb; + float distToFront = length(p - meshWorldPos); + + // Acne zone for front face + if (distToFront < SHADOW_BIAS) + { + return SHADOW_BIAS - distToFront; + } + + // Acne zone for back face (using Z depth difference as approximation) + float zDistToBack = backDepthLinear - sampleDepthLinear; + if (zDistToBack < SHADOW_BIAS) + { + return SHADOW_BIAS - zDistToBack; + } + + // Deep inside the mesh: return 0.0 to immediately register a hit! + // DO NOT return a negative value, otherwise the raymarcher will step backwards and rattle. + return 0.0; + } + else + { + if (sampleDepthLinear <= frontDepthLinear) + { + // In front of the mesh. Return Euclidean distance + bias so it overshoots + // slightly into the mesh, landing exactly at the 0.0 boundary. + vec3 meshWorldPos = texture(t_gbufferWorldPos, uv).rgb; + float distToFront = length(p - meshWorldPos); + return min(distToFront + SHADOW_BIAS, 2.0); + } + else + { + // Behind the back face. Return safe distance + bias. + float zDistToBack = sampleDepthLinear - backDepthLinear; + return min(zDistToBack * 0.5 + SHADOW_BIAS, 2.0); + } + } } vec3 sceneSdf(vec3 p) @@ -399,11 +399,14 @@ vec3 sceneSdf(vec3 p) objectDist = modifyDistanceBasedOnMaterial(objectDist, materialId, i); finalMaterialId = objectDist <= minDist ? materialId : finalMaterialId; - + vec2 res = fOpUnionSoft_blend(minDist, objectDist, DOT_BLEND_K); - if (res.y > 0.0) { + if (res.y > 0.0) + { globalBlend = max(globalBlend, res.y); - } else if (objectDist < minDist) { + } + else if (objectDist < minDist) + { globalBlend = 0.0; } minDist = res.x; @@ -412,9 +415,10 @@ vec3 sceneSdf(vec3 p) #ifdef MESH_SHADOW_SDF { float mDist = meshSDF(p); - if (mDist < minDist) { + if (mDist < minDist) + { minDist = mDist; - finalMaterialId = 15; // Use a designated "mesh shadow" material slot + finalMaterialId = 15; // Use a designated "mesh shadow" material slot } } #endif @@ -429,7 +433,7 @@ vec3 getMaterial(vec3 p, int id) int pattern = id < 16 ? u_materials[id].pattern : 0; float patternScale = id < 16 ? u_materials[id].patternScale : 1.0; - if(pattern > 0) + if (pattern > 0) { float patternShape = 0.0; vec3 sp = p * patternScale; @@ -438,22 +442,19 @@ vec3 getMaterial(vec3 p, int id) { patternShape = mod(floor(sp.x) + floor(sp.y) + floor(sp.z), 2.0); } - else if(pattern == 2) // Perlin Noise + else if (pattern == 2) // Perlin Noise { patternShape = perlin3D(sp.xyz * 10.0); } - else if(pattern == 3) // Waves + else if (pattern == 3) // Waves { - patternShape = (sin(10.0 * perlin3D(sp.xyz * 10.0)) + 1.0) * 0.5; + patternShape = (sin(10.0 * perlin3D(sp.xyz * 10.0)) + 1.0) * 0.5; patternShape = smoothstep(0.3, 0.7, patternShape); - } return mix(color, secondaryColor, patternShape); } - - return color; } @@ -625,14 +626,15 @@ vec3 pathTrace(vec3 p, vec3 rd, vec3 initialColor, int materialId, vec3 firstN, vec3 specMultiplier = vec3(5.0f); // =============================================================== - // Perform bounces - for (int bounce = 0; bounce <= u_rayBounces; bounce++) { float currentF0 = f0; - float currentRoughness = u_rayBounces == 1 ? max(roughness, 0.2) : min(roughness + (float(bounce) * 0.1 / float(u_rayBounces)), 1.0); // Add roughness with each bounce to prevent infinite mirror-like reflections + float currentRoughness = + u_rayBounces == 1 ? max(roughness, 0.2) + : min(roughness + (float(bounce) * 0.1 / float(u_rayBounces)), + 1.0); // Add roughness with each bounce to prevent infinite mirror-like reflections fresnelPower = mix(50.0, 1.0, currentF0); // On the first bounce use the injected normal (supports both SDF and mesh @@ -723,12 +725,12 @@ vec3 pathTrace(vec3 p, vec3 rd, vec3 initialColor, int materialId, vec3 firstN, // Add all direct light contributions for this bounce finalColor += throughput * directLighting; - if (bounce == u_rayBounces) + if (bounce == u_rayBounces) { // If this final hit is in a shadow, it will still evaluate to black. // Add a little bit of sky ambient so deep shadows always have some color. - if (bounce > 0) + if (bounce > 0) { finalColor += throughput * currentAlbedo * getSkyColor(N) * 0.15; } @@ -762,9 +764,9 @@ vec3 pathTrace(vec3 p, vec3 rd, vec3 initialColor, int materialId, vec3 firstN, { // Hit sky (ambient bounding) or ran out of steps grazing a surface // Path Tracing natively evaluates the bounceDir hemisphere into the procedural sky dome! - + // Keep sky at full brightness for reflections, but dim it for diffuse ambient lighting - float skyIntensity = isSpecular ? 1.0 : 0.5; + float skyIntensity = isSpecular ? 1.0 : 0.5; finalColor += throughput * getSkyColor(bounceDir) * skyIntensity; break; } @@ -886,8 +888,6 @@ vec3 standardLighting(vec3 p, vec3 rd, vec3 albedo, int materialId, vec3 N) return directLighting + ambient; } - - // Returns the linearised (eye-space) depth from a [0,1] depth-buffer value. float linearizeGBufferDepth(float d) { @@ -912,8 +912,8 @@ vec4 render(in vec2 uv) rd = (vec4(rd, 0) * u_camMatrix).xyz; #endif - float meshDepthSample = texture(t_depthTexture, v_texCoord).r; // [0,1], 1.0 = no mesh - float meshDepthLinear = linearizeGBufferDepth(meshDepthSample); // eye-space metres + float meshDepthSample = texture(t_depthTexture, v_texCoord).r; // [0,1], 1.0 = no mesh + float meshDepthLinear = linearizeGBufferDepth(meshDepthSample); // eye-space metres // Ray march SDF float object = rayMarch(ro, rd); @@ -932,7 +932,7 @@ vec4 render(in vec2 uv) float sdfDepthNDC = (z_n + 1.0) * 0.5; // Determine whether a valid mesh pixel is closer than the SDF hit - bool meshValid = (meshDepthSample < 1.0 - 0.0001); + bool meshValid = (meshDepthSample < 1.0 - 0.0001); bool meshInFront = meshValid && (meshDepthLinear < minDepth); // Output color @@ -959,10 +959,10 @@ vec4 render(in vec2 uv) vec2 gbufferUV = vec2(uv.x / _ar, uv.y) * 0.5 + 0.5; // --- Mesh surface is in front: apply SDF-aware deferred lighting --- - vec3 meshAlbedo = texture(t_gbufferAlbedo, gbufferUV).rgb; - vec3 meshWorldPos = texture(t_gbufferWorldPos, gbufferUV).rgb; + vec3 meshAlbedo = texture(t_gbufferAlbedo, gbufferUV).rgb; + vec3 meshWorldPos = texture(t_gbufferWorldPos, gbufferUV).rgb; // float meshSpecVal = texture(t_gbufferAlbedo, gbufferUV).a; - vec3 meshNormal = normalize(texture(t_gbufferNormal, gbufferUV).rgb); + vec3 meshNormal = normalize(texture(t_gbufferNormal, gbufferUV).rgb); int materialId = texture(t_gbufferMaterial, gbufferUV).r; meshAlbedo *= getMaterial(meshWorldPos, materialId); // Apply material palette color to mesh albedo @@ -972,7 +972,6 @@ vec4 render(in vec2 uv) #else col = standardLighting(meshWorldPos, rd, meshAlbedo, materialId, meshNormal); #endif - // Fog at mesh depth float fog = smoothstep(u_far * 0.0, u_far, meshDepthLinear); @@ -1062,7 +1061,7 @@ void main() { col *= 3.0 / maxComp; } - + // Apply contrast pivoting around mid-gray col = mix(vec3(0.5), col, u_contrast); // Clamp to ensure no weird artifacts from exceeding bounds @@ -1072,9 +1071,9 @@ void main() if (u_frameCounter > 0) { vec4 prevColor = texture(t_previousColor, screenUV); - - // Temporal Denoiser: Use an Exponential Moving Average (EMA) cap - // to prevent the weight from becoming too small, allowing the image to + + // Temporal Denoiser: Use an Exponential Moving Average (EMA) cap + // to prevent the weight from becoming too small, allowing the image to // continually refine and denoise even after many frames. float weight = max(1.0 / float(u_frameCounter + 1), 0.02); col = mix(prevColor.xyz, col, weight); diff --git a/src/weird-renderer/shaders/common/shapes.glsl b/src/weird-renderer/shaders/common/shapes.glsl index 87ace25..cd97aaf 100644 --- a/src/weird-renderer/shaders/common/shapes.glsl +++ b/src/weird-renderer/shaders/common/shapes.glsl @@ -68,8 +68,8 @@ float sdTriangle(in vec2 p, float w, float h, float angle) float cross0 = (b.x - a.x) * (q.y - a.y) - (b.y - a.y) * (q.x - a.x); float cross1 = (c2.x - b.x) * (q.y - b.y) - (c2.y - b.y) * (q.x - b.x); float cross2 = (a.x - c2.x) * (q.y - c2.y) - (a.y - c2.y) * (q.x - c2.x); - bool inside = (cross0 >= 0.0 && cross1 >= 0.0 && cross2 >= 0.0) || - (cross0 <= 0.0 && cross1 <= 0.0 && cross2 <= 0.0); + bool inside = + (cross0 >= 0.0 && cross1 >= 0.0 && cross2 >= 0.0) || (cross0 <= 0.0 && cross1 <= 0.0 && cross2 <= 0.0); return inside ? -d : d; } @@ -189,30 +189,26 @@ float dot2(vec3 v) return dot(v, v); } -float udTriangle( vec3 p, vec3 a, vec3 b, vec3 c ) +float udTriangle(vec3 p, vec3 a, vec3 b, vec3 c) { - vec3 ba = b - a; vec3 pa = p - a; - vec3 cb = c - b; vec3 pb = p - b; - vec3 ac = a - c; vec3 pc = p - c; - vec3 nor = cross( ba, ac ); + vec3 ba = b - a; + vec3 pa = p - a; + vec3 cb = c - b; + vec3 pb = p - b; + vec3 ac = a - c; + vec3 pc = p - c; + vec3 nor = cross(ba, ac); - return sqrt( - (sign(dot(cross(ba,nor),pa)) + - sign(dot(cross(cb,nor),pb)) + - sign(dot(cross(ac,nor),pc))<2.0) - ? - min( min( - dot2(ba*clamp(dot(ba,pa)/dot2(ba),0.0,1.0)-pa), - dot2(cb*clamp(dot(cb,pb)/dot2(cb),0.0,1.0)-pb) ), - dot2(ac*clamp(dot(ac,pc)/dot2(ac),0.0,1.0)-pc) ) - : - dot(nor,pa)*dot(nor,pa)/dot2(nor) ); + return sqrt((sign(dot(cross(ba, nor), pa)) + sign(dot(cross(cb, nor), pb)) + sign(dot(cross(ac, nor), pc)) < 2.0) + ? min(min(dot2(ba * clamp(dot(ba, pa) / dot2(ba), 0.0, 1.0) - pa), + dot2(cb * clamp(dot(cb, pb) / dot2(cb), 0.0, 1.0) - pb)), + dot2(ac * clamp(dot(ac, pc) / dot2(ac), 0.0, 1.0) - pc)) + : dot(nor, pa) * dot(nor, pa) / dot2(nor)); } - -float sdCapsule( vec3 p, vec3 a, vec3 b, float r ) +float sdCapsule(vec3 p, vec3 a, vec3 b, float r) { - vec3 pa = p - a, ba = b - a; - float h = clamp( dot(pa,ba)/dot(ba,ba), 0.0, 1.0 ); - return length( pa - ba*h ) - r; + vec3 pa = p - a, ba = b - a; + float h = clamp(dot(pa, ba) / dot(ba, ba), 0.0, 1.0); + return length(pa - ba * h) - r; } \ No newline at end of file diff --git a/src/weird-renderer/shaders/misc/background_spherical_grid.frag b/src/weird-renderer/shaders/misc/background_spherical_grid.frag index 3269fae..2f6c886 100644 --- a/src/weird-renderer/shaders/misc/background_spherical_grid.frag +++ b/src/weird-renderer/shaders/misc/background_spherical_grid.frag @@ -11,7 +11,7 @@ uniform mat4 u_camMatrix; uniform float u_fov; uniform vec2 u_resolution; -const float gridScale = 1.0; // Size of each grid cell in world units +const float gridScale = 1.0; // Size of each grid cell in world units const vec3 gridColor = vec3(1.0); // Color of the grid lines const vec3 backgroundColor = vec3(0.0); const float lineThickness = 0.2; // Thickness of the grid lines diff --git a/src/weird-renderer/shaders/postprocess/blur.frag b/src/weird-renderer/shaders/postprocess/blur.frag index a40d111..7bf51bf 100644 --- a/src/weird-renderer/shaders/postprocess/blur.frag +++ b/src/weird-renderer/shaders/postprocess/blur.frag @@ -15,7 +15,7 @@ const float u_weight[5] = float[5](0.227027, 0.1945946, 0.1216216, 0.054054, 0.0 // Taken form learnopengl.com and optimized it to reduce branching void main() { - vec2 tex_offset = 1.0 / vec2(textureSize(t_colorTexture, 0)); // gets size of single texel + vec2 tex_offset = 1.0 / vec2(textureSize(t_colorTexture, 0)); // gets size of single texel vec3 result = texture(t_colorTexture, v_texCoord).rgb * u_weight[0]; // current fragment's contribution for (int i = 1; i < 5; ++i) diff --git a/src/weird-renderer/shaders/postprocess/linear_to_srgb.frag b/src/weird-renderer/shaders/postprocess/linear_to_srgb.frag index 89f16d7..f34d91e 100644 --- a/src/weird-renderer/shaders/postprocess/linear_to_srgb.frag +++ b/src/weird-renderer/shaders/postprocess/linear_to_srgb.frag @@ -3,7 +3,8 @@ precision highp float; in vec2 v_texCoord; out vec4 FragColor; uniform sampler2D t_input; -void main() { - vec4 col = texture(t_input, v_texCoord); - FragColor = vec4(pow(col.rgb, vec3(0.4545)), col.a); +void main() +{ + vec4 col = texture(t_input, v_texCoord); + FragColor = vec4(pow(col.rgb, vec3(0.4545)), col.a); } \ No newline at end of file diff --git a/src/weird-renderer/shaders/postprocess/screen_output.frag b/src/weird-renderer/shaders/postprocess/screen_output.frag index 7a506b3..b4b34d8 100644 --- a/src/weird-renderer/shaders/postprocess/screen_output.frag +++ b/src/weird-renderer/shaders/postprocess/screen_output.frag @@ -34,7 +34,7 @@ vec3 surfaceBlur(sampler2D tex, vec2 uv, vec2 texelSize) vec3 result = vec3(0.0); float totalWeight = 0.0; - float sigmaSpace = max(u_surfaceBlurRadius * 0.5, 0.5); + float sigmaSpace = max(u_surfaceBlurRadius * 0.5, 0.5); float sigmaSpace2 = 2.0 * sigmaSpace * sigmaSpace; float sigmaColor2 = 2.0 * u_surfaceBlurSigmaColor * u_surfaceBlurSigmaColor; @@ -47,11 +47,11 @@ vec3 surfaceBlur(sampler2D tex, vec2 uv, vec2 texelSize) vec3 s = texture(tex, uv + offset).rgb; float spatialDist2 = float(x * x + y * y); - vec3 diff = s - center; - float colorDist2 = dot(diff, diff); + vec3 diff = s - center; + float colorDist2 = dot(diff, diff); float w = exp(-spatialDist2 / sigmaSpace2 - colorDist2 / sigmaColor2); - result += s * w; + result += s * w; totalWeight += w; } } @@ -77,7 +77,7 @@ void main() vec2 renderCoord = gl_FragCoord.xy * (u_renderResolution / u_resolution); int x = int(renderCoord.x); int y = int(renderCoord.y); - + // Boost saturation slightly before dithering to avoid "muddy" colors float luminance = dot(col, vec3(0.299, 0.587, 0.114)); col = mix(vec3(luminance), col, 1.5); @@ -85,7 +85,7 @@ void main() col += u_ditheringSpread * getBayer4(x, y); - vec3 levels = vec3(u_ditheringColorCount); + vec3 levels = vec3(u_ditheringColorCount); col = floor(col * levels + 0.5) / levels; diff --git a/tools/molecule-editor/include/MoleculeEditor.h b/tools/molecule-editor/include/MoleculeEditor.h index 60531f5..c170cc9 100644 --- a/tools/molecule-editor/include/MoleculeEditor.h +++ b/tools/molecule-editor/include/MoleculeEditor.h @@ -13,10 +13,9 @@ #include #include - #include "weird-engine/math/Default2DSDFs.h" -#include "weird-physics/components/GlobalPhysicsSettings.h" #include "weird-physics/components/DistanceConstraint.h" +#include "weird-physics/components/GlobalPhysicsSettings.h" #include "weird-physics/components/Spring.h" #include @@ -27,8 +26,7 @@ using namespace WeirdEngine; class MoleculeEditor : public Scene2D { public: - MoleculeEditor(){ - } + MoleculeEditor() {} ECSManager* m_tempEcs = nullptr; @@ -618,7 +616,7 @@ class MoleculeEditor : public Scene2D vec2 startPos = getMouseWorldPosition(); if (m_gridMode) startPos = snapToGrid(startPos, m_draggedBall); - + auto& t = m_tempEcs->getComponent(m_draggedBall); t.position = vec3(startPos.x, startPos.y, 0.0f); m_tempEcs->setComponentDirty(t); @@ -1157,7 +1155,7 @@ class MoleculeEditor : public Scene2D } std::string loadMsg = "[MoleculeEditor] Loaded " + std::to_string(simIdToEntity.size()) + " balls and " + - std::to_string(newSprings + newDists) + " links from " + path; + std::to_string(newSprings + newDists) + " links from " + path; WeirdEngine::Logger::log(loadMsg); } diff --git a/tools/molecule-editor/src/main.cpp b/tools/molecule-editor/src/main.cpp index d744487..036c068 100644 --- a/tools/molecule-editor/src/main.cpp +++ b/tools/molecule-editor/src/main.cpp @@ -1,5 +1,5 @@ -#include #include "MoleculeEditor.h" +#include using namespace WeirdEngine; diff --git a/tools/scene-editor/include/SceneEditor.h b/tools/scene-editor/include/SceneEditor.h index 7d45cda..5bf99ac 100644 --- a/tools/scene-editor/include/SceneEditor.h +++ b/tools/scene-editor/include/SceneEditor.h @@ -6,7 +6,6 @@ #include #include - #include "weird-engine/math/Default2DSDFs.h" #include @@ -17,7 +16,8 @@ using namespace WeirdEngine; class SceneEditor : public Scene2D { public: - SceneEditor() : m_rng(12345) + SceneEditor() + : m_rng(12345) { } @@ -154,8 +154,8 @@ class SceneEditor : public Scene2D // ===================================================================== void buildShapeButtons() { - const uint16_t types[] = {DefaultShapes::CIRCLE, DefaultShapes::BOX, DefaultShapes::TRIANGLE, DefaultShapes::LINE, DefaultShapes::RAMP, - DefaultShapes::STAR}; + const uint16_t types[] = {DefaultShapes::CIRCLE, DefaultShapes::BOX, DefaultShapes::TRIANGLE, + DefaultShapes::LINE, DefaultShapes::RAMP, DefaultShapes::STAR}; for (int i = 0; i < 6; i++) { @@ -552,7 +552,9 @@ class SceneEditor : public Scene2D if (idx >= pc) return; - std::string msg = "[" + std::string(shapeName(cs.distanceFieldId)) + "] " + std::string(paramName(cs.distanceFieldId, idx)) + " (now " + std::to_string(cs.parameters[idx]) + "): "; + std::string msg = "[" + std::string(shapeName(cs.distanceFieldId)) + "] " + + std::string(paramName(cs.distanceFieldId, idx)) + " (now " + + std::to_string(cs.parameters[idx]) + "): "; WeirdEngine::Logger::log(msg); float v; @@ -666,29 +668,47 @@ class SceneEditor : public Scene2D // ===================================================================== static const char* shapeName(uint16_t t) { - if (t == DefaultShapes::CIRCLE) return "Circle"; - if (t == DefaultShapes::BOX) return "Box"; - if (t == DefaultShapes::BOX_LINE) return "BoxLine"; - if (t == DefaultShapes::TRIANGLE) return "Triangle"; - if (t == DefaultShapes::TRIANGLE_LINE) return "TriangleLine"; - if (t == DefaultShapes::LINE) return "Line"; - if (t == DefaultShapes::RAMP) return "Ramp"; - if (t == DefaultShapes::SINE) return "Sine"; - if (t == DefaultShapes::STAR) return "Star"; + if (t == DefaultShapes::CIRCLE) + return "Circle"; + if (t == DefaultShapes::BOX) + return "Box"; + if (t == DefaultShapes::BOX_LINE) + return "BoxLine"; + if (t == DefaultShapes::TRIANGLE) + return "Triangle"; + if (t == DefaultShapes::TRIANGLE_LINE) + return "TriangleLine"; + if (t == DefaultShapes::LINE) + return "Line"; + if (t == DefaultShapes::RAMP) + return "Ramp"; + if (t == DefaultShapes::SINE) + return "Sine"; + if (t == DefaultShapes::STAR) + return "Star"; return "Shape"; } static int paramCount(uint16_t t) { - if (t == DefaultShapes::CIRCLE) return 3; - if (t == DefaultShapes::BOX) return 4; - if (t == DefaultShapes::BOX_LINE) return 5; - if (t == DefaultShapes::TRIANGLE) return 5; - if (t == DefaultShapes::TRIANGLE_LINE) return 6; - if (t == DefaultShapes::LINE) return 5; - if (t == DefaultShapes::RAMP) return 5; - if (t == DefaultShapes::SINE) return 4; - if (t == DefaultShapes::STAR) return 6; + if (t == DefaultShapes::CIRCLE) + return 3; + if (t == DefaultShapes::BOX) + return 4; + if (t == DefaultShapes::BOX_LINE) + return 5; + if (t == DefaultShapes::TRIANGLE) + return 5; + if (t == DefaultShapes::TRIANGLE_LINE) + return 6; + if (t == DefaultShapes::LINE) + return 5; + if (t == DefaultShapes::RAMP) + return 5; + if (t == DefaultShapes::SINE) + return 4; + if (t == DefaultShapes::STAR) + return 6; return 3; } @@ -703,15 +723,24 @@ class SceneEditor : public Scene2D static const char* R[] = {"posX", "posY", "w", "h", "skew"}; static const char* SI[] = {"amp", "per", "spd", "yOff"}; static const char* ST[] = {"posX", "posY", "rad", "disp", "pts", "spin"}; - if (t == DefaultShapes::CIRCLE) return C[i]; - if (t == DefaultShapes::BOX) return B[i]; - if (t == DefaultShapes::BOX_LINE) return BL[i]; - if (t == DefaultShapes::TRIANGLE) return T[i]; - if (t == DefaultShapes::TRIANGLE_LINE) return TL[i]; - if (t == DefaultShapes::LINE) return L[i]; - if (t == DefaultShapes::RAMP) return R[i]; - if (t == DefaultShapes::SINE) return SI[i]; - if (t == DefaultShapes::STAR) return ST[i]; + if (t == DefaultShapes::CIRCLE) + return C[i]; + if (t == DefaultShapes::BOX) + return B[i]; + if (t == DefaultShapes::BOX_LINE) + return BL[i]; + if (t == DefaultShapes::TRIANGLE) + return T[i]; + if (t == DefaultShapes::TRIANGLE_LINE) + return TL[i]; + if (t == DefaultShapes::LINE) + return L[i]; + if (t == DefaultShapes::RAMP) + return R[i]; + if (t == DefaultShapes::SINE) + return SI[i]; + if (t == DefaultShapes::STAR) + return ST[i]; return "?"; } diff --git a/tools/scene-editor/src/main.cpp b/tools/scene-editor/src/main.cpp index 4ac3c71..052d1ef 100644 --- a/tools/scene-editor/src/main.cpp +++ b/tools/scene-editor/src/main.cpp @@ -1,5 +1,5 @@ -#include #include "SceneEditor.h" +#include using namespace WeirdEngine; From de30163384394757314b5e260d6bc8be4609db0f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Mart=C3=AD?= <49535803+damacaa@users.noreply.github.com> Date: Sun, 19 Jul 2026 22:25:06 +0200 Subject: [PATCH 05/25] Trying pre-commit --- .github/workflows/format.yml | 19 ++++++------------- .pre-commit-config.yaml | 8 ++++++++ scripts/format.sh | 12 ------------ 3 files changed, 14 insertions(+), 25 deletions(-) create mode 100644 .pre-commit-config.yaml delete mode 100755 scripts/format.sh diff --git a/.github/workflows/format.yml b/.github/workflows/format.yml index b23a90a..afa5dde 100644 --- a/.github/workflows/format.yml +++ b/.github/workflows/format.yml @@ -12,18 +12,11 @@ jobs: steps: - uses: actions/checkout@v4 - - - name: Install clang-format - run: sudo apt-get update && sudo apt-get install -y clang-format - - name: Run format script - run: | - chmod +x ./scripts/format.sh - ./scripts/format.sh + - name: Set up Python + uses: actions/setup-python@v5 + with: + python-version: '3.x' - - name: Check for formatting changes - run: | - if ! git diff --exit-code; then - echo "::error::Code formatting check failed. Please run ./scripts/format.sh locally and commit the changes." - exit 1 - fi + - name: Run pre-commit + uses: pre-commit/action@v3.0.1 diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml new file mode 100644 index 0000000..254c2d2 --- /dev/null +++ b/.pre-commit-config.yaml @@ -0,0 +1,8 @@ +repos: + - repo: https://github.com/pre-commit/mirrors-clang-format + rev: v18.1.8 # Force this exact version for everyone + hooks: + - id: clang-format + # Removed types_or to ensure it catches custom shader extensions (.frag, .vert) + files: \.(h|cpp|glsl|frag|vert)$ + exclude: ^(third-party|build|build-muos|dist-muos|\.git)/ diff --git a/scripts/format.sh b/scripts/format.sh deleted file mode 100755 index bc717b4..0000000 --- a/scripts/format.sh +++ /dev/null @@ -1,12 +0,0 @@ -#!/usr/bin/env bash - -# Change to the project root directory -cd "$(dirname "$0")/.." || exit 1 - -echo "Formatting project files..." - -find . -type d \( -name "third-party" -o -name "build" -o -name "build-muos" -o -name "dist-muos" -o -name ".git" \) -prune -o \ - -type f \( -name "*.h" -o -name "*.cpp" -o -name "*.glsl" -o -name "*.frag" -o -name "*.vert" \) \ - -exec clang-format -i {} + - -echo "Formatting complete." From db90d61d8f43d3bdb77b901efa8b0f2df5f3b33a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Mart=C3=AD?= <49535803+damacaa@users.noreply.github.com> Date: Sun, 19 Jul 2026 22:28:17 +0200 Subject: [PATCH 06/25] Fix format --- include/weird-engine/systems/SDFShaderGenerationSystem.h | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/include/weird-engine/systems/SDFShaderGenerationSystem.h b/include/weird-engine/systems/SDFShaderGenerationSystem.h index ee8bdef..60c86a2 100644 --- a/include/weird-engine/systems/SDFShaderGenerationSystem.h +++ b/include/weird-engine/systems/SDFShaderGenerationSystem.h @@ -61,9 +61,10 @@ namespace WeirdEngine::SDFShaderGenerationSystem orderedIndices.push_back(i); } - std::stable_sort( - orderedIndices.begin(), orderedIndices.end(), [&](size_t a, size_t b) - { return componentArray->getDataAtIdx(a).groupIdx < componentArray->getDataAtIdx(b).groupIdx; }); + std::stable_sort(orderedIndices.begin(), orderedIndices.end(), + [&](size_t a, size_t b) { + return componentArray->getDataAtIdx(a).groupIdx < componentArray->getDataAtIdx(b).groupIdx; + }); for (size_t idx = 0; idx < componentArray->getSize() + 1; idx++) { From d22d7a6fd52dff8b2f02e350e5fbba93ff953f14 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Mart=C3=AD?= <49535803+damacaa@users.noreply.github.com> Date: Sun, 19 Jul 2026 22:45:59 +0200 Subject: [PATCH 07/25] Trying to fix builds. Use static SDL3 where possible always. --- CMakeLists.txt | 31 ++++++++++++++++++------------- 1 file changed, 18 insertions(+), 13 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 34b8750..0ff0b88 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -60,6 +60,7 @@ target_include_directories(imgui ${IMGUI_DIR}/backends ${CMAKE_CURRENT_SOURCE_DIR}/third-party/SDL/include ) +target_link_libraries(imgui PRIVATE glad GLESv2 EGL dl) endif() target_include_directories(${PROJECT_NAME} @@ -78,37 +79,41 @@ target_include_directories(glad # SDL3 setup # FORCE SDL3 to build as a STATIC library. -# This prevents the creation of libSDL3.so and embeds the code -# directly into your engine/game. -set(SDL_SHARED ON CACHE BOOL "Build SDL shared library" FORCE) -set(SDL_STATIC OFF CACHE BOOL "Build SDL static library" FORCE) -set(SDL_DEPS_SHARED ON CACHE BOOL "Load dependencies dynamically" FORCE) -set(SDL_KMSDRM_SHARED ON CACHE BOOL "Dynamically load KMS DRM support" FORCE) +set(SDL_SHARED OFF CACHE BOOL "Build SDL shared library" FORCE) +set(SDL_STATIC ON CACHE BOOL "Build SDL static library" FORCE) + +if(EMSCRIPTEN) + set(SDL_DEPS_SHARED OFF CACHE BOOL "Load dependencies dynamically" FORCE) + set(SDL_KMSDRM_SHARED OFF CACHE BOOL "Dynamically load KMS DRM support" FORCE) +else() + set(SDL_DEPS_SHARED ON CACHE BOOL "Load dependencies dynamically" FORCE) + set(SDL_KMSDRM_SHARED ON CACHE BOOL "Dynamically load KMS DRM support" FORCE) +endif() # Add dependencies add_subdirectory(${CMAKE_CURRENT_LIST_DIR}/third-party/SDL) # Force SDL3 to dynamically load KMSDRM libraries via dlopen instead of hard-linking. # This is necessary because cmake_dependent_option overrides our FORCE cache entries. -if(TARGET SDL3-shared) - target_compile_definitions(SDL3-shared PRIVATE +if(TARGET SDL3-static) + target_compile_definitions(SDL3-static PRIVATE "SDL_VIDEO_DRIVER_KMSDRM_DYNAMIC=\"libdrm.so.2\"" "SDL_VIDEO_DRIVER_KMSDRM_DYNAMIC_GBM=\"libgbm.so.1\"" ) # Keep the include directories for compilation but remove link dependencies - target_include_directories(SDL3-shared PRIVATE + target_include_directories(SDL3-static PRIVATE /usr/include/libdrm /usr/include ) # Remove the hard link dependencies that SDL added - get_target_property(_libs SDL3-shared LINK_LIBRARIES) + get_target_property(_libs SDL3-static LINK_LIBRARIES) if(_libs) list(FILTER _libs EXCLUDE REGEX "PC_LIBDRM|PC_GBM") - set_target_properties(SDL3-shared PROPERTIES LINK_LIBRARIES "${_libs}") + set_target_properties(SDL3-static PROPERTIES LINK_LIBRARIES "${_libs}") endif() - get_target_property(_iface_libs SDL3-shared INTERFACE_LINK_LIBRARIES) + get_target_property(_iface_libs SDL3-static INTERFACE_LINK_LIBRARIES) if(_iface_libs) list(FILTER _iface_libs EXCLUDE REGEX "PC_LIBDRM|PC_GBM") - set_target_properties(SDL3-shared PROPERTIES INTERFACE_LINK_LIBRARIES "${_iface_libs}") + set_target_properties(SDL3-static PROPERTIES INTERFACE_LINK_LIBRARIES "${_iface_libs}") endif() endif() # add_subdirectory(${CMAKE_CURRENT_LIST_DIR}/third-party/SDL_image) From fc477682edddee29c4bf87b8dc66779c4ff6c387 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Mart=C3=AD?= <49535803+damacaa@users.noreply.github.com> Date: Sun, 19 Jul 2026 22:54:11 +0200 Subject: [PATCH 08/25] Update CMakeLists.txt --- CMakeLists.txt | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 0ff0b88..6c4e5db 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -60,7 +60,10 @@ target_include_directories(imgui ${IMGUI_DIR}/backends ${CMAKE_CURRENT_SOURCE_DIR}/third-party/SDL/include ) -target_link_libraries(imgui PRIVATE glad GLESv2 EGL dl) +target_link_libraries(imgui PRIVATE glad) +if(UNIX AND NOT APPLE AND NOT EMSCRIPTEN) + target_link_libraries(imgui PRIVATE GLESv2 EGL dl) +endif() endif() target_include_directories(${PROJECT_NAME} @@ -94,7 +97,7 @@ add_subdirectory(${CMAKE_CURRENT_LIST_DIR}/third-party/SDL) # Force SDL3 to dynamically load KMSDRM libraries via dlopen instead of hard-linking. # This is necessary because cmake_dependent_option overrides our FORCE cache entries. -if(TARGET SDL3-static) +if(TARGET SDL3-static AND CMAKE_SYSTEM_NAME MATCHES "Linux") target_compile_definitions(SDL3-static PRIVATE "SDL_VIDEO_DRIVER_KMSDRM_DYNAMIC=\"libdrm.so.2\"" "SDL_VIDEO_DRIVER_KMSDRM_DYNAMIC_GBM=\"libgbm.so.1\"" @@ -149,11 +152,12 @@ target_include_directories(glad PUBLIC SDL3::SDL3 PRIVATE - GLESv2 - EGL - dl glad ) + if(UNIX AND NOT APPLE AND NOT EMSCRIPTEN) + target_link_libraries(${PROJECT_NAME} PRIVATE GLESv2 EGL dl) + endif() + if(NOT WEIRD_DISABLE_IMGUI) target_link_libraries(${PROJECT_NAME} PUBLIC imgui) else() From fcf535329d24cfb29b5b76c52c013d0601979bd6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Mart=C3=AD?= <49535803+damacaa@users.noreply.github.com> Date: Sun, 19 Jul 2026 23:03:00 +0200 Subject: [PATCH 09/25] Compilation error on windows --- examples/sample-scenes/include/LifeScene.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/sample-scenes/include/LifeScene.h b/examples/sample-scenes/include/LifeScene.h index e82ef9a..8f7c2b4 100644 --- a/examples/sample-scenes/include/LifeScene.h +++ b/examples/sample-scenes/include/LifeScene.h @@ -44,7 +44,7 @@ class LifeScene : public Scene2D for (const auto& entry : std::filesystem::directory_iterator(organismsDir)) { - Logger::log(entry.path()); + Logger::log(entry.path().string()); if (!entry.is_regular_file() || entry.path().extension() != ".weird") continue; From 85d4a0108b98113585fca7cd5e75583007ff5958 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Mart=C3=AD?= <49535803+damacaa@users.noreply.github.com> Date: Sun, 19 Jul 2026 23:08:31 +0200 Subject: [PATCH 10/25] Fixed stupid log stupid macros stupid conditional compilation --- examples/sample-scenes/include/WalkScene.h | 2 +- include/weird-engine.h | 2 +- src/weird-renderer/resources/Shader.cpp | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/examples/sample-scenes/include/WalkScene.h b/examples/sample-scenes/include/WalkScene.h index d485ed9..d0c76fa 100644 --- a/examples/sample-scenes/include/WalkScene.h +++ b/examples/sample-scenes/include/WalkScene.h @@ -132,7 +132,7 @@ class WalkScene : public Scene2D { foot.stepStarted = false; m_currentFoot = (m_currentFoot + 1) % componentArray->getSize(); - // WeirdEngine::Logger::Log("Switching foot: " + std::to_string(m_currentFoot)); + // WeirdEngine::Logger::log("Switching foot: " + std::to_string(m_currentFoot)); } else { diff --git a/include/weird-engine.h b/include/weird-engine.h index 6cb2249..0bcc52c 100644 --- a/include/weird-engine.h +++ b/include/weird-engine.h @@ -223,7 +223,7 @@ namespace WeirdEngine if (g_emscriptenEnv->runtimeContext->quit) { - WeirdEngine::Logger::Log("Quitting..."); + WeirdEngine::Logger::log("Quitting..."); // Clean up heap-allocated resources if (g_emscriptenEnv->runtimeContext != nullptr) { diff --git a/src/weird-renderer/resources/Shader.cpp b/src/weird-renderer/resources/Shader.cpp index 6a2fd8f..3e2774b 100644 --- a/src/weird-renderer/resources/Shader.cpp +++ b/src/weird-renderer/resources/Shader.cpp @@ -436,7 +436,7 @@ namespace WeirdEngine logMsg += define + "\n"; } logMsg += "Elapsed time:" + std::to_string(ms) + " ms \n\n"; - WeirdEngine::Logger::Log(logMsg); + WeirdEngine::Logger::log(logMsg); #endif m_uniformLocationCache.clear(); From 84475f6e0084ba1e60f65ad678670740fec45de7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Mart=C3=AD?= <49535803+damacaa@users.noreply.github.com> Date: Sun, 19 Jul 2026 23:22:47 +0200 Subject: [PATCH 11/25] Trying to make this worl --- .github/workflows/build-web.yml | 2 +- .github/workflows/cmake-multi-platform.yml | 8 +------- 2 files changed, 2 insertions(+), 8 deletions(-) diff --git a/.github/workflows/build-web.yml b/.github/workflows/build-web.yml index fe27f08..c93ac9a 100644 --- a/.github/workflows/build-web.yml +++ b/.github/workflows/build-web.yml @@ -50,7 +50,7 @@ jobs: -DBUILD_WEB=ON \ -DCMAKE_C_FLAGS="-pthread" \ -DCMAKE_CXX_FLAGS="-pthread" \ - -DCMAKE_EXE_LINKER_FLAGS="-pthread -sPTHREAD_POOL_SIZE=4 -sINITIAL_MEMORY=33554432 -sMAX_WEBGL_VERSION=2 -sMIN_WEBGL_VERSION=2 -o index.html --preload-file ../examples/sample-scenes/assets@/assets --preload-file ../src/weird-renderer/fonts@/fonts --preload-file ../src/weird-renderer/shaders@/shaders" + -DCMAKE_EXE_LINKER_FLAGS="-pthread -sPTHREAD_POOL_SIZE=4 -sINITIAL_MEMORY=33554432 -sMAX_WEBGL_VERSION=2 -sMIN_WEBGL_VERSION=2 -o index.html --preload-file \${GITHUB_WORKSPACE}/examples/sample-scenes/assets@/assets --preload-file \${GITHUB_WORKSPACE}/src/weird-renderer/fonts@/fonts --preload-file \${GITHUB_WORKSPACE}/src/weird-renderer/shaders@/shaders" emmake make WeirdSamples diff --git a/.github/workflows/cmake-multi-platform.yml b/.github/workflows/cmake-multi-platform.yml index cc4c65a..9c3073d 100644 --- a/.github/workflows/cmake-multi-platform.yml +++ b/.github/workflows/cmake-multi-platform.yml @@ -47,13 +47,7 @@ jobs: WEIRD_SCREENSHOT_FRAME: 10 run: xvfb-run -a ./WeirdSamples - - name: Test (Windows) - if: runner.os == 'Windows' - working-directory: ${{github.workspace}}/build/examples/sample-scenes/Release - env: - WEIRD_AUTO_QUIT_SECONDS: 3 - WEIRD_SCREENSHOT_FRAME: 10 - run: ./WeirdSamples.exe + - name: Upload Test Artifacts if: always() From 9de000e567ed9ab3003433e483cad6bb44e7976f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Mart=C3=AD?= <49535803+damacaa@users.noreply.github.com> Date: Sun, 19 Jul 2026 23:37:16 +0200 Subject: [PATCH 12/25] Update build-web.yml --- .github/workflows/build-web.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/build-web.yml b/.github/workflows/build-web.yml index c93ac9a..a5f27d3 100644 --- a/.github/workflows/build-web.yml +++ b/.github/workflows/build-web.yml @@ -50,7 +50,7 @@ jobs: -DBUILD_WEB=ON \ -DCMAKE_C_FLAGS="-pthread" \ -DCMAKE_CXX_FLAGS="-pthread" \ - -DCMAKE_EXE_LINKER_FLAGS="-pthread -sPTHREAD_POOL_SIZE=4 -sINITIAL_MEMORY=33554432 -sMAX_WEBGL_VERSION=2 -sMIN_WEBGL_VERSION=2 -o index.html --preload-file \${GITHUB_WORKSPACE}/examples/sample-scenes/assets@/assets --preload-file \${GITHUB_WORKSPACE}/src/weird-renderer/fonts@/fonts --preload-file \${GITHUB_WORKSPACE}/src/weird-renderer/shaders@/shaders" + -DCMAKE_EXE_LINKER_FLAGS="-pthread -sPTHREAD_POOL_SIZE=4 -sINITIAL_MEMORY=33554432 -sMAX_WEBGL_VERSION=2 -sMIN_WEBGL_VERSION=2 -o index.html --preload-file ${GITHUB_WORKSPACE}/examples/sample-scenes/assets@/assets --preload-file ${GITHUB_WORKSPACE}/src/weird-renderer/fonts@/fonts --preload-file ${GITHUB_WORKSPACE}/src/weird-renderer/shaders@/shaders" emmake make WeirdSamples From e38ff38836a1756bdec0f25369cc7fa42e30d33d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Mart=C3=AD?= <49535803+damacaa@users.noreply.github.com> Date: Sun, 19 Jul 2026 23:48:50 +0200 Subject: [PATCH 13/25] Update build-web.yml --- .github/workflows/build-web.yml | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/.github/workflows/build-web.yml b/.github/workflows/build-web.yml index a5f27d3..bc73452 100644 --- a/.github/workflows/build-web.yml +++ b/.github/workflows/build-web.yml @@ -58,15 +58,14 @@ jobs: run: | mkdir -p game_export - # Emscripten outputs multiple files based on flags: - # index.html, index.wasm, index.js, index.worker.js, and index.data - cp build/index.* game_export/ - cp build/examples/sample-scenes/WeirdSamples.* game_export/ || true + # Emscripten outputs multiple files named after the CMake target (WeirdSamples): + # WeirdSamples.html, WeirdSamples.wasm, WeirdSamples.js, WeirdSamples.worker.js, WeirdSamples.data + cp build/examples/sample-scenes/WeirdSamples.* game_export/ # Assets were copied to the target directory by our CMake template - cp -r build/examples/sample-scenes/assets game_export/ || true - cp -r build/examples/sample-scenes/fonts game_export/ || true - cp -r build/examples/sample-scenes/shaders game_export/ || true + cp -r build/examples/sample-scenes/assets game_export/ + cp -r build/examples/sample-scenes/fonts game_export/ + cp -r build/examples/sample-scenes/shaders game_export/ - name: Upload Artifact uses: actions/upload-artifact@v4 From 5e90ce8e65d80ce42ae3422e7f1e00bdf3e9d4e7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Mart=C3=AD?= <49535803+damacaa@users.noreply.github.com> Date: Mon, 20 Jul 2026 14:53:19 +0200 Subject: [PATCH 14/25] Web build should copy index.html now --- .github/workflows/build-web.yml | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/.github/workflows/build-web.yml b/.github/workflows/build-web.yml index bc73452..18dbc6e 100644 --- a/.github/workflows/build-web.yml +++ b/.github/workflows/build-web.yml @@ -58,9 +58,10 @@ jobs: run: | mkdir -p game_export - # Emscripten outputs multiple files named after the CMake target (WeirdSamples): - # WeirdSamples.html, WeirdSamples.wasm, WeirdSamples.js, WeirdSamples.worker.js, WeirdSamples.data - cp build/examples/sample-scenes/WeirdSamples.* game_export/ + # Emscripten outputs multiple files based on the -o index.html linker flag: + # index.html, index.wasm, index.js, index.worker.js, index.data + cp build/examples/sample-scenes/index.* game_export/ + cp build/examples/sample-scenes/WeirdSamples.* game_export/ 2>/dev/null || true # Assets were copied to the target directory by our CMake template cp -r build/examples/sample-scenes/assets game_export/ From 1d52f26905873fb8363936bd8f6a3a12c7f2519a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Mart=C3=AD?= <49535803+damacaa@users.noreply.github.com> Date: Mon, 20 Jul 2026 20:22:24 +0200 Subject: [PATCH 15/25] Update build-web.yml --- .github/workflows/build-web.yml | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/.github/workflows/build-web.yml b/.github/workflows/build-web.yml index 18dbc6e..93cb6ea 100644 --- a/.github/workflows/build-web.yml +++ b/.github/workflows/build-web.yml @@ -43,14 +43,14 @@ jobs: mkdir build && cd build # Using emcmake and emmake to compile for the web. - # We only build the WeirdSamples target to avoid overwriting issues. emcmake cmake .. \ -DCMAKE_BUILD_TYPE=Release \ -DWEIRD_ENGINE_BUILD_EXAMPLES=ON \ -DBUILD_WEB=ON \ -DCMAKE_C_FLAGS="-pthread" \ -DCMAKE_CXX_FLAGS="-pthread" \ - -DCMAKE_EXE_LINKER_FLAGS="-pthread -sPTHREAD_POOL_SIZE=4 -sINITIAL_MEMORY=33554432 -sMAX_WEBGL_VERSION=2 -sMIN_WEBGL_VERSION=2 -o index.html --preload-file ${GITHUB_WORKSPACE}/examples/sample-scenes/assets@/assets --preload-file ${GITHUB_WORKSPACE}/src/weird-renderer/fonts@/fonts --preload-file ${GITHUB_WORKSPACE}/src/weird-renderer/shaders@/shaders" + -DCMAKE_EXECUTABLE_SUFFIX=".html" \ + -DCMAKE_EXE_LINKER_FLAGS="-pthread -sPTHREAD_POOL_SIZE=4 -sINITIAL_MEMORY=33554432 -sMAX_WEBGL_VERSION=2 -sMIN_WEBGL_VERSION=2 --preload-file ${GITHUB_WORKSPACE}/examples/sample-scenes/assets@/assets --preload-file ${GITHUB_WORKSPACE}/src/weird-renderer/fonts@/fonts --preload-file ${GITHUB_WORKSPACE}/src/weird-renderer/shaders@/shaders" emmake make WeirdSamples @@ -58,10 +58,10 @@ jobs: run: | mkdir -p game_export - # Emscripten outputs multiple files based on the -o index.html linker flag: - # index.html, index.wasm, index.js, index.worker.js, index.data - cp build/examples/sample-scenes/index.* game_export/ - cp build/examples/sample-scenes/WeirdSamples.* game_export/ 2>/dev/null || true + # Emscripten outputs files named after the CMake target (WeirdSamples) since we used CMAKE_EXECUTABLE_SUFFIX: + # WeirdSamples.html, WeirdSamples.wasm, WeirdSamples.js, WeirdSamples.worker.js, WeirdSamples.data + cp build/examples/sample-scenes/WeirdSamples.* game_export/ + mv game_export/WeirdSamples.html game_export/index.html # Assets were copied to the target directory by our CMake template cp -r build/examples/sample-scenes/assets game_export/ From 0f685fbc24d23e1a858bf2a343b1c855516665c6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Mart=C3=AD?= <49535803+damacaa@users.noreply.github.com> Date: Mon, 20 Jul 2026 20:37:12 +0200 Subject: [PATCH 16/25] Update build-web.yml --- .github/workflows/build-web.yml | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/.github/workflows/build-web.yml b/.github/workflows/build-web.yml index 93cb6ea..b78fa63 100644 --- a/.github/workflows/build-web.yml +++ b/.github/workflows/build-web.yml @@ -50,7 +50,7 @@ jobs: -DCMAKE_C_FLAGS="-pthread" \ -DCMAKE_CXX_FLAGS="-pthread" \ -DCMAKE_EXECUTABLE_SUFFIX=".html" \ - -DCMAKE_EXE_LINKER_FLAGS="-pthread -sPTHREAD_POOL_SIZE=4 -sINITIAL_MEMORY=33554432 -sMAX_WEBGL_VERSION=2 -sMIN_WEBGL_VERSION=2 --preload-file ${GITHUB_WORKSPACE}/examples/sample-scenes/assets@/assets --preload-file ${GITHUB_WORKSPACE}/src/weird-renderer/fonts@/fonts --preload-file ${GITHUB_WORKSPACE}/src/weird-renderer/shaders@/shaders" + -DCMAKE_EXE_LINKER_FLAGS="-pthread -sPTHREAD_POOL_SIZE=4 -sINITIAL_MEMORY=33554432 -sMAX_WEBGL_VERSION=2 -sMIN_WEBGL_VERSION=2 -o index.html --preload-file ${GITHUB_WORKSPACE}/examples/sample-scenes/assets@/assets --preload-file ${GITHUB_WORKSPACE}/src/weird-renderer/fonts@/fonts --preload-file ${GITHUB_WORKSPACE}/src/weird-renderer/shaders@/shaders" emmake make WeirdSamples @@ -58,10 +58,8 @@ jobs: run: | mkdir -p game_export - # Emscripten outputs files named after the CMake target (WeirdSamples) since we used CMAKE_EXECUTABLE_SUFFIX: - # WeirdSamples.html, WeirdSamples.wasm, WeirdSamples.js, WeirdSamples.worker.js, WeirdSamples.data - cp build/examples/sample-scenes/WeirdSamples.* game_export/ - mv game_export/WeirdSamples.html game_export/index.html + # Emscripten outputs files named index.* since we pass -o index.html in CMAKE_EXE_LINKER_FLAGS + cp build/examples/sample-scenes/index.* game_export/ # Assets were copied to the target directory by our CMake template cp -r build/examples/sample-scenes/assets game_export/ From cf5c46ca6e294a6aa892423cf23b50e397b30a47 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Mart=C3=AD?= <49535803+damacaa@users.noreply.github.com> Date: Thu, 23 Jul 2026 17:00:18 +0200 Subject: [PATCH 17/25] Updated CMake files --- CMakeLists.txt | 6 +++++- examples/3d-experiments/CMakeLists.txt | 5 +++-- examples/empty-project/CMakeLists.txt | 5 +++-- examples/opengl-experiments/CMakeLists.txt | 5 +++-- examples/sample-scenes/CMakeLists.txt | 5 +++-- tools/molecule-editor/CMakeLists.txt | 5 +++-- tools/scene-editor/CMakeLists.txt | 5 +++-- 7 files changed, 23 insertions(+), 13 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 6c4e5db..fdd20ec 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -2,7 +2,7 @@ cmake_minimum_required(VERSION 3.10) project(WeirdEngine) -execute_process(COMMAND git submodule update --init --recursive) +execute_process(COMMAND git submodule update --init --recursive WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}) set(CMAKE_CXX_STANDARD 20) set(CMAKE_CXX_STANDARD_REQUIRED ON) @@ -170,6 +170,10 @@ endif() # Shaders +if(EMSCRIPTEN) + set(WEIRD_ENGINE_USE_RUNTIME_ASSETS ON CACHE BOOL "Load shaders/assets from runtime folder instead of source tree" FORCE) +endif() + option(WEIRD_ENGINE_USE_RUNTIME_ASSETS "Load shaders/assets from runtime folder instead of source tree" OFF diff --git a/examples/3d-experiments/CMakeLists.txt b/examples/3d-experiments/CMakeLists.txt index bc0ec4e..206bea6 100644 --- a/examples/3d-experiments/CMakeLists.txt +++ b/examples/3d-experiments/CMakeLists.txt @@ -29,8 +29,9 @@ option(BUILD_WEB "Build for web using Emscripten" OFF) # Option to build for standalone deployment option(DEPLOY_STANDALONE "Configure paths and copy assets for a standalone distribution" OFF) -# Force DEPLOY_STANDALONE when building for web -if(BUILD_WEB) +# Auto-detect Emscripten toolchain or explicit BUILD_WEB flag +if(EMSCRIPTEN OR BUILD_WEB) + set(BUILD_WEB ON CACHE BOOL "" FORCE) set(DEPLOY_STANDALONE ON CACHE BOOL "" FORCE) endif() diff --git a/examples/empty-project/CMakeLists.txt b/examples/empty-project/CMakeLists.txt index d74d007..4f268ca 100644 --- a/examples/empty-project/CMakeLists.txt +++ b/examples/empty-project/CMakeLists.txt @@ -29,8 +29,9 @@ option(BUILD_WEB "Build for web using Emscripten" OFF) # Option to build for standalone deployment option(DEPLOY_STANDALONE "Configure paths and copy assets for a standalone distribution" OFF) -# Force DEPLOY_STANDALONE when building for web -if(BUILD_WEB) +# Auto-detect Emscripten toolchain or explicit BUILD_WEB flag +if(EMSCRIPTEN OR BUILD_WEB) + set(BUILD_WEB ON CACHE BOOL "" FORCE) set(DEPLOY_STANDALONE ON CACHE BOOL "" FORCE) endif() diff --git a/examples/opengl-experiments/CMakeLists.txt b/examples/opengl-experiments/CMakeLists.txt index 113d28f..6f37b9a 100644 --- a/examples/opengl-experiments/CMakeLists.txt +++ b/examples/opengl-experiments/CMakeLists.txt @@ -29,8 +29,9 @@ option(BUILD_WEB "Build for web using Emscripten" OFF) # Option to build for standalone deployment option(DEPLOY_STANDALONE "Configure paths and copy assets for a standalone distribution" OFF) -# Force DEPLOY_STANDALONE when building for web -if(BUILD_WEB) +# Auto-detect Emscripten toolchain or explicit BUILD_WEB flag +if(EMSCRIPTEN OR BUILD_WEB) + set(BUILD_WEB ON CACHE BOOL "" FORCE) set(DEPLOY_STANDALONE ON CACHE BOOL "" FORCE) endif() diff --git a/examples/sample-scenes/CMakeLists.txt b/examples/sample-scenes/CMakeLists.txt index a52c76e..11603f7 100644 --- a/examples/sample-scenes/CMakeLists.txt +++ b/examples/sample-scenes/CMakeLists.txt @@ -29,8 +29,9 @@ option(BUILD_WEB "Build for web using Emscripten" OFF) # Option to build for standalone deployment option(DEPLOY_STANDALONE "Configure paths and copy assets for a standalone distribution" OFF) -# Force DEPLOY_STANDALONE when building for web -if(BUILD_WEB) +# Auto-detect Emscripten toolchain or explicit BUILD_WEB flag +if(EMSCRIPTEN OR BUILD_WEB) + set(BUILD_WEB ON CACHE BOOL "" FORCE) set(DEPLOY_STANDALONE ON CACHE BOOL "" FORCE) endif() diff --git a/tools/molecule-editor/CMakeLists.txt b/tools/molecule-editor/CMakeLists.txt index 0ab18e2..cd9842f 100644 --- a/tools/molecule-editor/CMakeLists.txt +++ b/tools/molecule-editor/CMakeLists.txt @@ -29,8 +29,9 @@ option(BUILD_WEB "Build for web using Emscripten" OFF) # Option to build for standalone deployment option(DEPLOY_STANDALONE "Configure paths and copy assets for a standalone distribution" OFF) -# Force DEPLOY_STANDALONE when building for web -if(BUILD_WEB) +# Auto-detect Emscripten toolchain or explicit BUILD_WEB flag +if(EMSCRIPTEN OR BUILD_WEB) + set(BUILD_WEB ON CACHE BOOL "" FORCE) set(DEPLOY_STANDALONE ON CACHE BOOL "" FORCE) endif() diff --git a/tools/scene-editor/CMakeLists.txt b/tools/scene-editor/CMakeLists.txt index 263d3b9..479eafc 100644 --- a/tools/scene-editor/CMakeLists.txt +++ b/tools/scene-editor/CMakeLists.txt @@ -29,8 +29,9 @@ option(BUILD_WEB "Build for web using Emscripten" OFF) # Option to build for standalone deployment option(DEPLOY_STANDALONE "Configure paths and copy assets for a standalone distribution" OFF) -# Force DEPLOY_STANDALONE when building for web -if(BUILD_WEB) +# Auto-detect Emscripten toolchain or explicit BUILD_WEB flag +if(EMSCRIPTEN OR BUILD_WEB) + set(BUILD_WEB ON CACHE BOOL "" FORCE) set(DEPLOY_STANDALONE ON CACHE BOOL "" FORCE) endif() From 39bc8a531e1a9e7ff1f04c65ec9d0194f51a4f3c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Mart=C3=AD?= <49535803+damacaa@users.noreply.github.com> Date: Thu, 23 Jul 2026 17:12:42 +0200 Subject: [PATCH 18/25] Combined build-web.yml into cmake-multi-platform.yml using a matrix strategy and updated CMake files to make sure web build generates an index.html --- .github/workflows/build-web.yml | 73 ---------------- .github/workflows/cmake-multi-platform.yml | 96 +++++++++++++++++----- examples/3d-experiments/CMakeLists.txt | 4 + examples/empty-project/CMakeLists.txt | 4 + examples/opengl-experiments/CMakeLists.txt | 4 + examples/sample-scenes/CMakeLists.txt | 4 + tools/molecule-editor/CMakeLists.txt | 4 + tools/scene-editor/CMakeLists.txt | 4 + 8 files changed, 101 insertions(+), 92 deletions(-) delete mode 100644 .github/workflows/build-web.yml diff --git a/.github/workflows/build-web.yml b/.github/workflows/build-web.yml deleted file mode 100644 index b78fa63..0000000 --- a/.github/workflows/build-web.yml +++ /dev/null @@ -1,73 +0,0 @@ -name: Build Web - -on: - push: - branches: [ "main" ] - pull_request: - branches: [ "main" ] - -permissions: - contents: read - -jobs: - build: - runs-on: ubuntu-22.04 - - steps: - - name: Checkout code - uses: actions/checkout@v4 - with: - submodules: recursive - fetch-depth: 0 - - - name: Ensure submodules are up-to-date - run: git submodule update --init --recursive - - - name: Install dependencies - run: > - sudo apt-get update && sudo apt-get install -y - cmake build-essential libgl-dev libegl-dev - libwayland-dev libxkbcommon-dev wayland-protocols - libasound2-dev libpulse-dev libpipewire-0.3-dev - libx11-dev libxext-dev libxcursor-dev libxi-dev - libxrandr-dev libxss-dev libxtst-dev - - - name: Setup Emscripten - uses: mymindstorm/setup-emsdk@v14 - with: - version: latest - actions-cache-folder: 'emsdk-cache' - - - name: Build WeirdSamples for Web - run: | - mkdir build && cd build - - # Using emcmake and emmake to compile for the web. - emcmake cmake .. \ - -DCMAKE_BUILD_TYPE=Release \ - -DWEIRD_ENGINE_BUILD_EXAMPLES=ON \ - -DBUILD_WEB=ON \ - -DCMAKE_C_FLAGS="-pthread" \ - -DCMAKE_CXX_FLAGS="-pthread" \ - -DCMAKE_EXECUTABLE_SUFFIX=".html" \ - -DCMAKE_EXE_LINKER_FLAGS="-pthread -sPTHREAD_POOL_SIZE=4 -sINITIAL_MEMORY=33554432 -sMAX_WEBGL_VERSION=2 -sMIN_WEBGL_VERSION=2 -o index.html --preload-file ${GITHUB_WORKSPACE}/examples/sample-scenes/assets@/assets --preload-file ${GITHUB_WORKSPACE}/src/weird-renderer/fonts@/fonts --preload-file ${GITHUB_WORKSPACE}/src/weird-renderer/shaders@/shaders" - - emmake make WeirdSamples - - - name: Prepare Artifact - run: | - mkdir -p game_export - - # Emscripten outputs files named index.* since we pass -o index.html in CMAKE_EXE_LINKER_FLAGS - cp build/examples/sample-scenes/index.* game_export/ - - # Assets were copied to the target directory by our CMake template - cp -r build/examples/sample-scenes/assets game_export/ - cp -r build/examples/sample-scenes/fonts game_export/ - cp -r build/examples/sample-scenes/shaders game_export/ - - - name: Upload Artifact - uses: actions/upload-artifact@v4 - with: - name: weird-engine-web-sample - path: game_export/ diff --git a/.github/workflows/cmake-multi-platform.yml b/.github/workflows/cmake-multi-platform.yml index 9c3073d..79aeca3 100644 --- a/.github/workflows/cmake-multi-platform.yml +++ b/.github/workflows/cmake-multi-platform.yml @@ -11,51 +11,109 @@ env: jobs: build: + runs-on: ${{ matrix.os }} strategy: + fail-fast: false matrix: - os: [windows-2025, ubuntu-latest] - - runs-on: ${{ matrix.os }} + include: + - name: Windows + os: windows-latest + target: windows + - name: Linux + os: ubuntu-latest + target: linux + - name: Web (WASM) + os: ubuntu-22.04 + target: web steps: - - uses: actions/checkout@v4 + - name: Checkout code + uses: actions/checkout@v4 with: submodules: recursive fetch-depth: 0 - - name: Ensure submodules are up-to-date - run: git submodule update --init --recursive - - - name: Check submodulesversions - run: git submodule status - + # ------------------------------------------------------------------------ + # Linux Dependencies + # ------------------------------------------------------------------------ - name: Install dependencies (Linux) - if: runner.os == 'Linux' + if: matrix.target == 'linux' run: sudo apt update && sudo apt install -y cmake g++ make xorg-dev libgl1-mesa-dev libxrandr-dev libxinerama-dev libxcursor-dev libxi-dev xvfb - - name: Configure CMake + # ------------------------------------------------------------------------ + # Web / Emscripten Dependencies + # ------------------------------------------------------------------------ + - name: Setup Emscripten (Web) + if: matrix.target == 'web' + uses: mymindstorm/setup-emsdk@v14 + with: + version: latest + actions-cache-folder: 'emsdk-cache' + + # ------------------------------------------------------------------------ + # Desktop Builds (Windows & Linux) + # ------------------------------------------------------------------------ + - name: Configure CMake (Desktop) + if: matrix.target != 'web' run: cmake -B ${{github.workspace}}/build -DCMAKE_BUILD_TYPE=${{env.BUILD_TYPE}} -DWEIRD_ENGINE_BUILD_EXAMPLES=ON -DWEIRD_TEST_HOOKS=ON - - name: Build + - name: Build (Desktop) + if: matrix.target != 'web' run: cmake --build ${{github.workspace}}/build --config ${{env.BUILD_TYPE}} - name: Test (Linux) - if: runner.os == 'Linux' + if: matrix.target == 'linux' working-directory: ${{github.workspace}}/build/examples/sample-scenes env: WEIRD_AUTO_QUIT_SECONDS: 3 WEIRD_SCREENSHOT_FRAME: 10 run: xvfb-run -a ./WeirdSamples - - - - name: Upload Test Artifacts - if: always() + - name: Upload Test Artifacts (Desktop) + if: matrix.target != 'web' && always() uses: actions/upload-artifact@v4 with: - name: test-artifacts-${{ matrix.os }} + name: test-artifacts-${{ matrix.target }} path: | ${{github.workspace}}/build/examples/sample-scenes/log.txt ${{github.workspace}}/build/examples/sample-scenes/screenshot_*.bmp ${{github.workspace}}/build/examples/sample-scenes/Release/log.txt ${{github.workspace}}/build/examples/sample-scenes/Release/screenshot_*.bmp + + # ------------------------------------------------------------------------ + # Web Build (Emscripten / WASM) + # ------------------------------------------------------------------------ + - name: Build WeirdSamples for Web + if: matrix.target == 'web' + run: | + mkdir build && cd build + emcmake cmake .. \ + -DCMAKE_BUILD_TYPE=Release \ + -DWEIRD_ENGINE_BUILD_EXAMPLES=ON \ + -DCMAKE_C_FLAGS="-pthread" \ + -DCMAKE_CXX_FLAGS="-pthread" \ + -DCMAKE_EXECUTABLE_SUFFIX=".html" \ + -DCMAKE_EXE_LINKER_FLAGS="-pthread -sPTHREAD_POOL_SIZE=4 -sINITIAL_MEMORY=33554432 -sMAX_WEBGL_VERSION=2 -sMIN_WEBGL_VERSION=2 --preload-file ${{github.workspace}}/examples/sample-scenes/assets@/assets --preload-file ${{github.workspace}}/src/weird-renderer/fonts@/fonts --preload-file ${{github.workspace}}/src/weird-renderer/shaders@/shaders" + emmake make WeirdSamples + + - name: Prepare Web Artifact + if: matrix.target == 'web' + run: | + mkdir -p game_export + # Copy generated index files or fallback to target name + if ls build/examples/sample-scenes/index.* 1> /dev/null 2>&1; then + cp build/examples/sample-scenes/index.* game_export/ + else + cp build/examples/sample-scenes/WeirdSamples.* game_export/ + cp game_export/WeirdSamples.html game_export/index.html + fi + cp -r build/examples/sample-scenes/assets game_export/ + cp -r build/examples/sample-scenes/fonts game_export/ + cp -r build/examples/sample-scenes/shaders game_export/ + + - name: Upload Web Artifact + if: matrix.target == 'web' + uses: actions/upload-artifact@v4 + with: + name: weird-engine-web-sample + path: game_export/ diff --git a/examples/3d-experiments/CMakeLists.txt b/examples/3d-experiments/CMakeLists.txt index 206bea6..1745b3a 100644 --- a/examples/3d-experiments/CMakeLists.txt +++ b/examples/3d-experiments/CMakeLists.txt @@ -91,6 +91,10 @@ set_source_files_properties(${WEIRDGAME_HEADERS} PROPERTIES HEADER_FILE_ONLY TRU # Add executable including both sources and headers. add_executable(${PROJECT_NAME} ${WEIRDGAME_SOURCES} ${WEIRDGAME_HEADERS} ${WEIRDGAME_ASSETS}) +if(BUILD_WEB) + set_target_properties(${PROJECT_NAME} PROPERTIES OUTPUT_NAME "index") +endif() + # Set include directories. target_include_directories(${PROJECT_NAME} PRIVATE "${CMAKE_CURRENT_SOURCE_DIR}/include") diff --git a/examples/empty-project/CMakeLists.txt b/examples/empty-project/CMakeLists.txt index 4f268ca..8aaf944 100644 --- a/examples/empty-project/CMakeLists.txt +++ b/examples/empty-project/CMakeLists.txt @@ -91,6 +91,10 @@ set_source_files_properties(${WEIRDGAME_HEADERS} PROPERTIES HEADER_FILE_ONLY TRU # Add executable including both sources and headers. add_executable(${PROJECT_NAME} ${WEIRDGAME_SOURCES} ${WEIRDGAME_HEADERS} ${WEIRDGAME_ASSETS}) +if(BUILD_WEB) + set_target_properties(${PROJECT_NAME} PROPERTIES OUTPUT_NAME "index") +endif() + # Set include directories. target_include_directories(${PROJECT_NAME} PRIVATE "${CMAKE_CURRENT_SOURCE_DIR}/include") diff --git a/examples/opengl-experiments/CMakeLists.txt b/examples/opengl-experiments/CMakeLists.txt index 6f37b9a..0998fd2 100644 --- a/examples/opengl-experiments/CMakeLists.txt +++ b/examples/opengl-experiments/CMakeLists.txt @@ -91,6 +91,10 @@ set_source_files_properties(${WEIRDGAME_HEADERS} PROPERTIES HEADER_FILE_ONLY TRU # Add executable including both sources and headers. add_executable(${PROJECT_NAME} ${WEIRDGAME_SOURCES} ${WEIRDGAME_HEADERS} ${WEIRDGAME_ASSETS}) +if(BUILD_WEB) + set_target_properties(${PROJECT_NAME} PROPERTIES OUTPUT_NAME "index") +endif() + # Set include directories. target_include_directories(${PROJECT_NAME} PRIVATE "${CMAKE_CURRENT_SOURCE_DIR}/include") diff --git a/examples/sample-scenes/CMakeLists.txt b/examples/sample-scenes/CMakeLists.txt index 11603f7..ad8f712 100644 --- a/examples/sample-scenes/CMakeLists.txt +++ b/examples/sample-scenes/CMakeLists.txt @@ -91,6 +91,10 @@ set_source_files_properties(${WEIRDGAME_HEADERS} PROPERTIES HEADER_FILE_ONLY TRU # Add executable including both sources and headers. add_executable(${PROJECT_NAME} ${WEIRDGAME_SOURCES} ${WEIRDGAME_HEADERS} ${WEIRDGAME_ASSETS}) +if(BUILD_WEB) + set_target_properties(${PROJECT_NAME} PROPERTIES OUTPUT_NAME "index") +endif() + # Set include directories. target_include_directories(${PROJECT_NAME} PRIVATE "${CMAKE_CURRENT_SOURCE_DIR}/include") diff --git a/tools/molecule-editor/CMakeLists.txt b/tools/molecule-editor/CMakeLists.txt index cd9842f..ed5e150 100644 --- a/tools/molecule-editor/CMakeLists.txt +++ b/tools/molecule-editor/CMakeLists.txt @@ -91,6 +91,10 @@ set_source_files_properties(${WEIRDGAME_HEADERS} PROPERTIES HEADER_FILE_ONLY TRU # Add executable including both sources and headers. add_executable(${PROJECT_NAME} ${WEIRDGAME_SOURCES} ${WEIRDGAME_HEADERS} ${WEIRDGAME_ASSETS}) +if(BUILD_WEB) + set_target_properties(${PROJECT_NAME} PROPERTIES OUTPUT_NAME "index") +endif() + # Set include directories. target_include_directories(${PROJECT_NAME} PRIVATE "${CMAKE_CURRENT_SOURCE_DIR}/include") diff --git a/tools/scene-editor/CMakeLists.txt b/tools/scene-editor/CMakeLists.txt index 479eafc..e708b3e 100644 --- a/tools/scene-editor/CMakeLists.txt +++ b/tools/scene-editor/CMakeLists.txt @@ -91,6 +91,10 @@ set_source_files_properties(${WEIRDGAME_HEADERS} PROPERTIES HEADER_FILE_ONLY TRU # Add executable including both sources and headers. add_executable(${PROJECT_NAME} ${WEIRDGAME_SOURCES} ${WEIRDGAME_HEADERS} ${WEIRDGAME_ASSETS}) +if(BUILD_WEB) + set_target_properties(${PROJECT_NAME} PROPERTIES OUTPUT_NAME "index") +endif() + # Set include directories. target_include_directories(${PROJECT_NAME} PRIVATE "${CMAKE_CURRENT_SOURCE_DIR}/include") From f403a8d391c52ac8e195665ca69a6126c9df66f3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Mart=C3=AD?= <49535803+damacaa@users.noreply.github.com> Date: Thu, 23 Jul 2026 17:45:22 +0200 Subject: [PATCH 19/25] ci: fix emsdk cache error, windows artifact step, and node warnings --- .github/workflows/cmake-multi-platform.yml | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/.github/workflows/cmake-multi-platform.yml b/.github/workflows/cmake-multi-platform.yml index 79aeca3..b27619b 100644 --- a/.github/workflows/cmake-multi-platform.yml +++ b/.github/workflows/cmake-multi-platform.yml @@ -8,6 +8,8 @@ on: env: BUILD_TYPE: Release + ACTIONS_ALLOW_USE_UNSECURE_NODE_VERSION: "true" + ACTIONS_RUNNER_FORCE_NODE24: "true" jobs: build: @@ -48,7 +50,6 @@ jobs: uses: mymindstorm/setup-emsdk@v14 with: version: latest - actions-cache-folder: 'emsdk-cache' # ------------------------------------------------------------------------ # Desktop Builds (Windows & Linux) @@ -69,8 +70,8 @@ jobs: WEIRD_SCREENSHOT_FRAME: 10 run: xvfb-run -a ./WeirdSamples - - name: Upload Test Artifacts (Desktop) - if: matrix.target != 'web' && always() + - name: Upload Test Artifacts (Linux) + if: matrix.target == 'linux' && always() uses: actions/upload-artifact@v4 with: name: test-artifacts-${{ matrix.target }} From 161acacc946106ea709bb024448cfeff79cf4423 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Mart=C3=AD?= <49535803+damacaa@users.noreply.github.com> Date: Thu, 23 Jul 2026 17:51:04 +0200 Subject: [PATCH 20/25] fix(web): ensure BUILD_WEB scope sets OUTPUT_NAME index and guarantee index.html in web artifact --- .github/workflows/cmake-multi-platform.yml | 23 +++++++++++++--------- examples/3d-experiments/CMakeLists.txt | 2 ++ examples/empty-project/CMakeLists.txt | 2 ++ examples/opengl-experiments/CMakeLists.txt | 2 ++ examples/sample-scenes/CMakeLists.txt | 2 ++ tools/molecule-editor/CMakeLists.txt | 2 ++ tools/scene-editor/CMakeLists.txt | 2 ++ 7 files changed, 26 insertions(+), 9 deletions(-) diff --git a/.github/workflows/cmake-multi-platform.yml b/.github/workflows/cmake-multi-platform.yml index b27619b..ed0fbd7 100644 --- a/.github/workflows/cmake-multi-platform.yml +++ b/.github/workflows/cmake-multi-platform.yml @@ -91,6 +91,7 @@ jobs: emcmake cmake .. \ -DCMAKE_BUILD_TYPE=Release \ -DWEIRD_ENGINE_BUILD_EXAMPLES=ON \ + -DBUILD_WEB=ON \ -DCMAKE_C_FLAGS="-pthread" \ -DCMAKE_CXX_FLAGS="-pthread" \ -DCMAKE_EXECUTABLE_SUFFIX=".html" \ @@ -101,16 +102,20 @@ jobs: if: matrix.target == 'web' run: | mkdir -p game_export - # Copy generated index files or fallback to target name - if ls build/examples/sample-scenes/index.* 1> /dev/null 2>&1; then - cp build/examples/sample-scenes/index.* game_export/ - else - cp build/examples/sample-scenes/WeirdSamples.* game_export/ - cp game_export/WeirdSamples.html game_export/index.html + # Copy generated outputs (index.* or WeirdSamples.*) + cp build/examples/sample-scenes/index.* game_export/ 2>/dev/null || true + cp build/examples/sample-scenes/WeirdSamples.* game_export/ 2>/dev/null || true + + # Guarantee index.html exists in game_export/ + if [ ! -f game_export/index.html ]; then + if [ -f game_export/WeirdSamples.html ]; then + cp game_export/WeirdSamples.html game_export/index.html + fi fi - cp -r build/examples/sample-scenes/assets game_export/ - cp -r build/examples/sample-scenes/fonts game_export/ - cp -r build/examples/sample-scenes/shaders game_export/ + + cp -r build/examples/sample-scenes/assets game_export/ 2>/dev/null || true + cp -r build/examples/sample-scenes/fonts game_export/ 2>/dev/null || true + cp -r build/examples/sample-scenes/shaders game_export/ 2>/dev/null || true - name: Upload Web Artifact if: matrix.target == 'web' diff --git a/examples/3d-experiments/CMakeLists.txt b/examples/3d-experiments/CMakeLists.txt index 1745b3a..5432943 100644 --- a/examples/3d-experiments/CMakeLists.txt +++ b/examples/3d-experiments/CMakeLists.txt @@ -32,7 +32,9 @@ option(DEPLOY_STANDALONE "Configure paths and copy assets for a standalone distr # Auto-detect Emscripten toolchain or explicit BUILD_WEB flag if(EMSCRIPTEN OR BUILD_WEB) set(BUILD_WEB ON CACHE BOOL "" FORCE) + set(BUILD_WEB ON) set(DEPLOY_STANDALONE ON CACHE BOOL "" FORCE) + set(DEPLOY_STANDALONE ON) endif() if(DEPLOY_STANDALONE) diff --git a/examples/empty-project/CMakeLists.txt b/examples/empty-project/CMakeLists.txt index 8aaf944..93bcbad 100644 --- a/examples/empty-project/CMakeLists.txt +++ b/examples/empty-project/CMakeLists.txt @@ -32,7 +32,9 @@ option(DEPLOY_STANDALONE "Configure paths and copy assets for a standalone distr # Auto-detect Emscripten toolchain or explicit BUILD_WEB flag if(EMSCRIPTEN OR BUILD_WEB) set(BUILD_WEB ON CACHE BOOL "" FORCE) + set(BUILD_WEB ON) set(DEPLOY_STANDALONE ON CACHE BOOL "" FORCE) + set(DEPLOY_STANDALONE ON) endif() if(DEPLOY_STANDALONE) diff --git a/examples/opengl-experiments/CMakeLists.txt b/examples/opengl-experiments/CMakeLists.txt index 0998fd2..a57a571 100644 --- a/examples/opengl-experiments/CMakeLists.txt +++ b/examples/opengl-experiments/CMakeLists.txt @@ -32,7 +32,9 @@ option(DEPLOY_STANDALONE "Configure paths and copy assets for a standalone distr # Auto-detect Emscripten toolchain or explicit BUILD_WEB flag if(EMSCRIPTEN OR BUILD_WEB) set(BUILD_WEB ON CACHE BOOL "" FORCE) + set(BUILD_WEB ON) set(DEPLOY_STANDALONE ON CACHE BOOL "" FORCE) + set(DEPLOY_STANDALONE ON) endif() if(DEPLOY_STANDALONE) diff --git a/examples/sample-scenes/CMakeLists.txt b/examples/sample-scenes/CMakeLists.txt index ad8f712..3035828 100644 --- a/examples/sample-scenes/CMakeLists.txt +++ b/examples/sample-scenes/CMakeLists.txt @@ -32,7 +32,9 @@ option(DEPLOY_STANDALONE "Configure paths and copy assets for a standalone distr # Auto-detect Emscripten toolchain or explicit BUILD_WEB flag if(EMSCRIPTEN OR BUILD_WEB) set(BUILD_WEB ON CACHE BOOL "" FORCE) + set(BUILD_WEB ON) set(DEPLOY_STANDALONE ON CACHE BOOL "" FORCE) + set(DEPLOY_STANDALONE ON) endif() if(DEPLOY_STANDALONE) diff --git a/tools/molecule-editor/CMakeLists.txt b/tools/molecule-editor/CMakeLists.txt index ed5e150..9c128fb 100644 --- a/tools/molecule-editor/CMakeLists.txt +++ b/tools/molecule-editor/CMakeLists.txt @@ -32,7 +32,9 @@ option(DEPLOY_STANDALONE "Configure paths and copy assets for a standalone distr # Auto-detect Emscripten toolchain or explicit BUILD_WEB flag if(EMSCRIPTEN OR BUILD_WEB) set(BUILD_WEB ON CACHE BOOL "" FORCE) + set(BUILD_WEB ON) set(DEPLOY_STANDALONE ON CACHE BOOL "" FORCE) + set(DEPLOY_STANDALONE ON) endif() if(DEPLOY_STANDALONE) diff --git a/tools/scene-editor/CMakeLists.txt b/tools/scene-editor/CMakeLists.txt index e708b3e..643441a 100644 --- a/tools/scene-editor/CMakeLists.txt +++ b/tools/scene-editor/CMakeLists.txt @@ -32,7 +32,9 @@ option(DEPLOY_STANDALONE "Configure paths and copy assets for a standalone distr # Auto-detect Emscripten toolchain or explicit BUILD_WEB flag if(EMSCRIPTEN OR BUILD_WEB) set(BUILD_WEB ON CACHE BOOL "" FORCE) + set(BUILD_WEB ON) set(DEPLOY_STANDALONE ON CACHE BOOL "" FORCE) + set(DEPLOY_STANDALONE ON) endif() if(DEPLOY_STANDALONE) From 25249dd0bf43703722540b3ce8f7397c13e6ae2a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Mart=C3=AD?= <49535803+damacaa@users.noreply.github.com> Date: Thu, 23 Jul 2026 18:23:07 +0200 Subject: [PATCH 21/25] fix(web): set target SUFFIX .html to force emcc to generate index.html and add index.html launcher fallback --- .github/workflows/cmake-multi-platform.yml | 3 +++ examples/3d-experiments/CMakeLists.txt | 2 +- examples/empty-project/CMakeLists.txt | 2 +- examples/opengl-experiments/CMakeLists.txt | 2 +- examples/sample-scenes/CMakeLists.txt | 2 +- tools/molecule-editor/CMakeLists.txt | 2 +- tools/scene-editor/CMakeLists.txt | 2 +- 7 files changed, 9 insertions(+), 6 deletions(-) diff --git a/.github/workflows/cmake-multi-platform.yml b/.github/workflows/cmake-multi-platform.yml index ed0fbd7..865e37d 100644 --- a/.github/workflows/cmake-multi-platform.yml +++ b/.github/workflows/cmake-multi-platform.yml @@ -10,6 +10,7 @@ env: BUILD_TYPE: Release ACTIONS_ALLOW_USE_UNSECURE_NODE_VERSION: "true" ACTIONS_RUNNER_FORCE_NODE24: "true" + FORCE_JAVASCRIPT_ACTIONS_TO_NODE24: "true" jobs: build: @@ -110,6 +111,8 @@ jobs: if [ ! -f game_export/index.html ]; then if [ -f game_export/WeirdSamples.html ]; then cp game_export/WeirdSamples.html game_export/index.html + elif [ -f game_export/index.js ]; then + echo 'WeirdEngine Web' > game_export/index.html fi fi diff --git a/examples/3d-experiments/CMakeLists.txt b/examples/3d-experiments/CMakeLists.txt index 5432943..978b697 100644 --- a/examples/3d-experiments/CMakeLists.txt +++ b/examples/3d-experiments/CMakeLists.txt @@ -94,7 +94,7 @@ set_source_files_properties(${WEIRDGAME_HEADERS} PROPERTIES HEADER_FILE_ONLY TRU add_executable(${PROJECT_NAME} ${WEIRDGAME_SOURCES} ${WEIRDGAME_HEADERS} ${WEIRDGAME_ASSETS}) if(BUILD_WEB) - set_target_properties(${PROJECT_NAME} PROPERTIES OUTPUT_NAME "index") + set_target_properties(${PROJECT_NAME} PROPERTIES OUTPUT_NAME "index" SUFFIX ".html") endif() # Set include directories. diff --git a/examples/empty-project/CMakeLists.txt b/examples/empty-project/CMakeLists.txt index 93bcbad..a023968 100644 --- a/examples/empty-project/CMakeLists.txt +++ b/examples/empty-project/CMakeLists.txt @@ -94,7 +94,7 @@ set_source_files_properties(${WEIRDGAME_HEADERS} PROPERTIES HEADER_FILE_ONLY TRU add_executable(${PROJECT_NAME} ${WEIRDGAME_SOURCES} ${WEIRDGAME_HEADERS} ${WEIRDGAME_ASSETS}) if(BUILD_WEB) - set_target_properties(${PROJECT_NAME} PROPERTIES OUTPUT_NAME "index") + set_target_properties(${PROJECT_NAME} PROPERTIES OUTPUT_NAME "index" SUFFIX ".html") endif() # Set include directories. diff --git a/examples/opengl-experiments/CMakeLists.txt b/examples/opengl-experiments/CMakeLists.txt index a57a571..9607928 100644 --- a/examples/opengl-experiments/CMakeLists.txt +++ b/examples/opengl-experiments/CMakeLists.txt @@ -94,7 +94,7 @@ set_source_files_properties(${WEIRDGAME_HEADERS} PROPERTIES HEADER_FILE_ONLY TRU add_executable(${PROJECT_NAME} ${WEIRDGAME_SOURCES} ${WEIRDGAME_HEADERS} ${WEIRDGAME_ASSETS}) if(BUILD_WEB) - set_target_properties(${PROJECT_NAME} PROPERTIES OUTPUT_NAME "index") + set_target_properties(${PROJECT_NAME} PROPERTIES OUTPUT_NAME "index" SUFFIX ".html") endif() # Set include directories. diff --git a/examples/sample-scenes/CMakeLists.txt b/examples/sample-scenes/CMakeLists.txt index 3035828..f2503d4 100644 --- a/examples/sample-scenes/CMakeLists.txt +++ b/examples/sample-scenes/CMakeLists.txt @@ -94,7 +94,7 @@ set_source_files_properties(${WEIRDGAME_HEADERS} PROPERTIES HEADER_FILE_ONLY TRU add_executable(${PROJECT_NAME} ${WEIRDGAME_SOURCES} ${WEIRDGAME_HEADERS} ${WEIRDGAME_ASSETS}) if(BUILD_WEB) - set_target_properties(${PROJECT_NAME} PROPERTIES OUTPUT_NAME "index") + set_target_properties(${PROJECT_NAME} PROPERTIES OUTPUT_NAME "index" SUFFIX ".html") endif() # Set include directories. diff --git a/tools/molecule-editor/CMakeLists.txt b/tools/molecule-editor/CMakeLists.txt index 9c128fb..1968fd8 100644 --- a/tools/molecule-editor/CMakeLists.txt +++ b/tools/molecule-editor/CMakeLists.txt @@ -94,7 +94,7 @@ set_source_files_properties(${WEIRDGAME_HEADERS} PROPERTIES HEADER_FILE_ONLY TRU add_executable(${PROJECT_NAME} ${WEIRDGAME_SOURCES} ${WEIRDGAME_HEADERS} ${WEIRDGAME_ASSETS}) if(BUILD_WEB) - set_target_properties(${PROJECT_NAME} PROPERTIES OUTPUT_NAME "index") + set_target_properties(${PROJECT_NAME} PROPERTIES OUTPUT_NAME "index" SUFFIX ".html") endif() # Set include directories. diff --git a/tools/scene-editor/CMakeLists.txt b/tools/scene-editor/CMakeLists.txt index 643441a..cd98297 100644 --- a/tools/scene-editor/CMakeLists.txt +++ b/tools/scene-editor/CMakeLists.txt @@ -94,7 +94,7 @@ set_source_files_properties(${WEIRDGAME_HEADERS} PROPERTIES HEADER_FILE_ONLY TRU add_executable(${PROJECT_NAME} ${WEIRDGAME_SOURCES} ${WEIRDGAME_HEADERS} ${WEIRDGAME_ASSETS}) if(BUILD_WEB) - set_target_properties(${PROJECT_NAME} PROPERTIES OUTPUT_NAME "index") + set_target_properties(${PROJECT_NAME} PROPERTIES OUTPUT_NAME "index" SUFFIX ".html") endif() # Set include directories. From 398c3e1183ee68c31631d26f781881e2bb8fb97a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Mart=C3=AD?= <49535803+damacaa@users.noreply.github.com> Date: Thu, 23 Jul 2026 18:26:35 +0200 Subject: [PATCH 22/25] feat(web): add customizable src/index.html templates for all examples and tools --- examples/3d-experiments/src/index.html | 42 ++++++++++++++++++++++ examples/empty-project/src/index.html | 42 ++++++++++++++++++++++ examples/opengl-experiments/src/index.html | 42 ++++++++++++++++++++++ examples/sample-scenes/src/index.html | 42 ++++++++++++++++++++++ tools/molecule-editor/src/index.html | 42 ++++++++++++++++++++++ tools/scene-editor/src/index.html | 42 ++++++++++++++++++++++ 6 files changed, 252 insertions(+) create mode 100644 examples/3d-experiments/src/index.html create mode 100644 examples/empty-project/src/index.html create mode 100644 examples/opengl-experiments/src/index.html create mode 100644 examples/sample-scenes/src/index.html create mode 100644 tools/molecule-editor/src/index.html create mode 100644 tools/scene-editor/src/index.html diff --git a/examples/3d-experiments/src/index.html b/examples/3d-experiments/src/index.html new file mode 100644 index 0000000..99a4611 --- /dev/null +++ b/examples/3d-experiments/src/index.html @@ -0,0 +1,42 @@ + + + + + + Weird3D + + + + + + + + + diff --git a/examples/empty-project/src/index.html b/examples/empty-project/src/index.html new file mode 100644 index 0000000..a02843c --- /dev/null +++ b/examples/empty-project/src/index.html @@ -0,0 +1,42 @@ + + + + + + WeirdGame + + + + + + + + + diff --git a/examples/opengl-experiments/src/index.html b/examples/opengl-experiments/src/index.html new file mode 100644 index 0000000..8d27b74 --- /dev/null +++ b/examples/opengl-experiments/src/index.html @@ -0,0 +1,42 @@ + + + + + + WeirdOpenGL + + + + + + + + + diff --git a/examples/sample-scenes/src/index.html b/examples/sample-scenes/src/index.html new file mode 100644 index 0000000..0fd5609 --- /dev/null +++ b/examples/sample-scenes/src/index.html @@ -0,0 +1,42 @@ + + + + + + WeirdSamples + + + + + + + + + diff --git a/tools/molecule-editor/src/index.html b/tools/molecule-editor/src/index.html new file mode 100644 index 0000000..6e41724 --- /dev/null +++ b/tools/molecule-editor/src/index.html @@ -0,0 +1,42 @@ + + + + + + MoleculeEditor + + + + + + + + + diff --git a/tools/scene-editor/src/index.html b/tools/scene-editor/src/index.html new file mode 100644 index 0000000..ddb31b9 --- /dev/null +++ b/tools/scene-editor/src/index.html @@ -0,0 +1,42 @@ + + + + + + SceneEditor + + + + + + + + + From 14c8cef40f2df31cff23dea2e10f625f1f31e72e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Mart=C3=AD?= <49535803+damacaa@users.noreply.github.com> Date: Fri, 24 Jul 2026 09:24:53 +0200 Subject: [PATCH 23/25] itch.io deploy action with Butler --- .github/workflows/deploy-itch.yml | 74 +++++++++++++++++++++++++++++++ 1 file changed, 74 insertions(+) create mode 100644 .github/workflows/deploy-itch.yml diff --git a/.github/workflows/deploy-itch.yml b/.github/workflows/deploy-itch.yml new file mode 100644 index 0000000..04e7d06 --- /dev/null +++ b/.github/workflows/deploy-itch.yml @@ -0,0 +1,74 @@ +name: Deploy to itch.io + +on: + # Run manually from the Actions tab + workflow_dispatch: + # Optionally also run when you push a version tag (e.g. v1.0) + # push: + # tags: + # - 'v*' + +env: + BUILD_TYPE: Release + +jobs: + build-and-deploy: + name: Build Web & Push to itch.io + runs-on: ubuntu-22.04 + + steps: + - name: Checkout code + uses: actions/checkout@v4 + with: + submodules: recursive + fetch-depth: 0 + + # ------------------------------------------------------------------------ + # Build the Web (Emscripten / WASM) version + # ------------------------------------------------------------------------ + - name: Setup Emscripten + uses: mymindstorm/setup-emsdk@v14 + with: + version: latest + + - name: Build WeirdSamples for Web + run: | + mkdir build && cd build + emcmake cmake .. \ + -DCMAKE_BUILD_TYPE=${{env.BUILD_TYPE}} \ + -DWEIRD_ENGINE_BUILD_EXAMPLES=ON \ + -DBUILD_WEB=ON \ + -DCMAKE_C_FLAGS="-pthread" \ + -DCMAKE_CXX_FLAGS="-pthread" \ + -DCMAKE_EXECUTABLE_SUFFIX=".html" \ + -DCMAKE_EXE_LINKER_FLAGS="-pthread -sPTHREAD_POOL_SIZE=4 -sINITIAL_MEMORY=33554432 -sMAX_WEBGL_VERSION=2 -sMIN_WEBGL_VERSION=2 --preload-file ${{github.workspace}}/examples/sample-scenes/assets@/assets --preload-file ${{github.workspace}}/src/weird-renderer/fonts@/fonts --preload-file ${{github.workspace}}/src/weird-renderer/shaders@/shaders" + emmake make WeirdSamples + + - name: Prepare Web Artifact + run: | + mkdir -p game_export + cp build/examples/sample-scenes/index.* game_export/ 2>/dev/null || true + cp build/examples/sample-scenes/WeirdSamples.* game_export/ 2>/dev/null || true + + if [ ! -f game_export/index.html ]; then + if [ -f game_export/WeirdSamples.html ]; then + cp game_export/WeirdSamples.html game_export/index.html + elif [ -f game_export/index.js ]; then + echo 'WeirdEngine Web' > game_export/index.html + fi + fi + + cp -r build/examples/sample-scenes/assets game_export/ 2>/dev/null || true + cp -r build/examples/sample-scenes/fonts game_export/ 2>/dev/null || true + cp -r build/examples/sample-scenes/shaders game_export/ 2>/dev/null || true + + # ------------------------------------------------------------------------ + # Publish to itch.io via Butler + # ------------------------------------------------------------------------ + - name: Setup Butler + uses: remarkablegames/setup-butler@v2 + + - name: Push to itch.io + env: + BUTLER_API_KEY: ${{ secrets.BUTLER_API_KEY }} + run: butler push ./game_export/ damaca/weird-engine:html \ No newline at end of file From ba8543845111db514b444667188ccccc82b67026 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Mart=C3=AD?= <49535803+damacaa@users.noreply.github.com> Date: Fri, 24 Jul 2026 09:25:35 +0200 Subject: [PATCH 24/25] Cleaned type warnings --- .../sample-scenes/include/CollisionHandling.h | 4 ++-- examples/sample-scenes/include/ImageScene.h | 6 ++--- .../include/MouseCollisionScene.h | 2 +- examples/sample-scenes/include/RopeScene.h | 2 +- .../include/ShapesCombinations.h | 4 ++-- include/weird-engine/Profiler.h | 8 +++---- include/weird-engine/ecs/ComponentArray.h | 2 +- .../weird-engine/systems/SDFRenderSystem.h | 6 ++--- include/weird-renderer/resources/Font.h | 22 +++++++++---------- include/weird-renderer/resources/Shader.h | 2 +- src/weird-engine/ResourceManager.cpp | 8 ++++--- src/weird-engine/Scene.cpp | 8 +++---- src/weird-physics/Simulation2D.cpp | 17 +++++++------- src/weird-renderer/audio/AudioEngine.cpp | 11 ++++++---- src/weird-renderer/core/Renderer.cpp | 12 +++++++--- .../core/SDF2DRenderPipeline.cpp | 5 +++-- src/weird-renderer/resources/Mesh.cpp | 4 ++-- src/weird-renderer/resources/VAO.cpp | 2 +- 18 files changed, 69 insertions(+), 56 deletions(-) diff --git a/examples/sample-scenes/include/CollisionHandling.h b/examples/sample-scenes/include/CollisionHandling.h index f8c797e..489949e 100644 --- a/examples/sample-scenes/include/CollisionHandling.h +++ b/examples/sample-scenes/include/CollisionHandling.h @@ -21,8 +21,8 @@ class CollisionHandlingScene : public Scene2D for (size_t i = 0; i < 10; i++) { - float y = 10 + i; - float x = 2 * i; + float y = 10.0f + static_cast(i); + float x = 2.0f * static_cast(i); int material = 4 + (i % 12); diff --git a/examples/sample-scenes/include/ImageScene.h b/examples/sample-scenes/include/ImageScene.h index d1b59c0..8fddbb9 100644 --- a/examples/sample-scenes/include/ImageScene.h +++ b/examples/sample-scenes/include/ImageScene.h @@ -48,7 +48,7 @@ class ImageScene : public Scene2D float y; int material = 0; - x = 15 + sin(i); + x = 15.0f + static_cast(sin(i)); y = 10 + (1.0f * i); std::string materialId; @@ -188,8 +188,8 @@ class ImageScene : public Scene2D Entity rbOwner = components->getEntityAtIdx(i); Transform& t = ecs.getComponent(rbOwner); - int x = floor(t.position.x); - int y = floor(30 - t.position.y); + int x = static_cast(floor(t.position.x)); + int y = static_cast(floor(30.0f - t.position.y)); vec2 uv = vec2(x, y) / 30.0f; diff --git a/examples/sample-scenes/include/MouseCollisionScene.h b/examples/sample-scenes/include/MouseCollisionScene.h index a21ce91..531bc9c 100644 --- a/examples/sample-scenes/include/MouseCollisionScene.h +++ b/examples/sample-scenes/include/MouseCollisionScene.h @@ -22,7 +22,7 @@ class MouseCollisionScene : public Scene2D for (size_t i = 0; i < 9900; i++) { - float y = (int)(i / 20); + float y = static_cast(i / 20); float x = 5 + (i % 20) + sin(y); int material = 4 + (i % 12); diff --git a/examples/sample-scenes/include/RopeScene.h b/examples/sample-scenes/include/RopeScene.h index 055a2da..048c2a1 100644 --- a/examples/sample-scenes/include/RopeScene.h +++ b/examples/sample-scenes/include/RopeScene.h @@ -167,7 +167,7 @@ class RopeScene : public Scene2D static float animTime = 0.0f; animTime += delta; auto& cs = ecs.getComponent(m_star); - cs.parameters[4] = static_cast(std::floor(animTime)) % 5 + 2; + cs.parameters[4] = static_cast((static_cast(std::floor(animTime)) % 5) + 2); cs.parameters[3] = std::sin(3.1416f * animTime); ecs.setComponentDirty(cs); } diff --git a/examples/sample-scenes/include/ShapesCombinations.h b/examples/sample-scenes/include/ShapesCombinations.h index f04a5a3..958aefe 100644 --- a/examples/sample-scenes/include/ShapesCombinations.h +++ b/examples/sample-scenes/include/ShapesCombinations.h @@ -34,11 +34,11 @@ class ShapeCombinatiosScene : public Scene2D std::random_device rd; std::mt19937 gen(rd()); float range = 20.0f; - std::uniform_real_distribution<> distrib(-range, range); + std::uniform_real_distribution distrib(-range, range); // Boxes { - std::uniform_real_distribution<> distribY(0, 5); + std::uniform_real_distribution distribY(0.0f, 5.0f); for (int i = 0; i < 0; ++i) { diff --git a/include/weird-engine/Profiler.h b/include/weird-engine/Profiler.h index a64e5e1..e481f90 100644 --- a/include/weird-engine/Profiler.h +++ b/include/weird-engine/Profiler.h @@ -301,8 +301,8 @@ namespace WeirdEngine if (m_stats[i].name == name && m_stats[i].depth == m_currentDepth && m_stats[i].parentIndex == parentIdx) { - statIndex = i; - m_currentIndex = i + 1; + statIndex = static_cast(i); + m_currentIndex = static_cast(i + 1); found = true; break; } @@ -310,8 +310,8 @@ namespace WeirdEngine if (!found) { m_stats.push_back({name, m_currentDepth, 0.0, 0, parentIdx}); - statIndex = m_stats.size() - 1; - m_currentIndex = m_stats.size(); + statIndex = static_cast(m_stats.size() - 1); + m_currentIndex = static_cast(m_stats.size()); } } diff --git a/include/weird-engine/ecs/ComponentArray.h b/include/weird-engine/ecs/ComponentArray.h index 92d08c7..15ee544 100644 --- a/include/weird-engine/ecs/ComponentArray.h +++ b/include/weird-engine/ecs/ComponentArray.h @@ -149,7 +149,7 @@ namespace WeirdEngine // Function to get the size of the array int getSize() const { - return size; + return static_cast(size); } private: diff --git a/include/weird-engine/systems/SDFRenderSystem.h b/include/weird-engine/systems/SDFRenderSystem.h index eef2d74..6779417 100644 --- a/include/weird-engine/systems/SDFRenderSystem.h +++ b/include/weird-engine/systems/SDFRenderSystem.h @@ -49,7 +49,7 @@ namespace WeirdEngine text.bufferedDotCount += ctx.font.getCharData(c).dotCount; } - int charCount = text.text.length(); + int charCount = static_cast(text.text.length()); text.width = (charCount * ctx.font.getCharWidth() * 2 * ctx.dotRadious) + ((charCount - 1) * ctx.charSpacing); text.height = ctx.font.getCharHeight() * 2 * ctx.dotRadious; @@ -95,7 +95,7 @@ namespace WeirdEngine data[dotIdx].x = t.position.x; data[dotIdx].y = t.position.y; data[dotIdx].z = t.position.z; - data[dotIdx].w = dotComp.materialId; + data[dotIdx].w = static_cast(dotComp.materialId); dotIdx++; }); @@ -106,7 +106,7 @@ namespace WeirdEngine ecs.forEach( [&](Entity entity, TextClass& text, Transform& t) { - int charCount = text.text.length(); + int charCount = static_cast(text.text.length()); float horizontalOffset = 0.0f; switch (text.horizontalAlignment) diff --git a/include/weird-renderer/resources/Font.h b/include/weird-renderer/resources/Font.h index ec9545e..30d2468 100644 --- a/include/weird-renderer/resources/Font.h +++ b/include/weird-renderer/resources/Font.h @@ -45,21 +45,21 @@ namespace WeirdEngine::WeirdRenderer int columns = width / charWidth; int rows = height / charHeight; - int charCount = charList.length(); + int charCount = static_cast(charList.length()); - for (size_t i = 0; i < charCount; i++) + for (size_t i = 0; i < static_cast(charCount); i++) { CharData charData; - int startX = charWidth * (i % columns); - int startY = (charHeight * (i / columns)); + int startX = charWidth * static_cast(i % columns); + int startY = (charHeight * static_cast(i / columns)); - for (size_t offsetX = 0; offsetX < charWidth; offsetX++) + for (size_t offsetX = 0; offsetX < static_cast(charWidth); offsetX++) { - for (size_t offsetY = 0; offsetY < charHeight; offsetY++) + for (size_t offsetY = 0; offsetY < static_cast(charHeight); offsetY++) { - int x = startX + offsetX; - int y = startY + offsetY; + int x = startX + static_cast(offsetX); + int y = startY + static_cast(offsetY); // Calculate the index of the pixel in the image data int index = (y * width + x) * channels; @@ -77,14 +77,14 @@ namespace WeirdEngine::WeirdRenderer if (r < 50) { - float localX = offsetX; - float localY = (charHeight * 0.5f) - offsetY; + float localX = static_cast(offsetX); + float localY = (charHeight * 0.5f) - static_cast(offsetY); charData.positions.emplace_back(localX, localY); } } } - charData.dotCount = charData.positions.size(); + charData.dotCount = static_cast(charData.positions.size()); m_charData[charList[i]] = charData; } diff --git a/include/weird-renderer/resources/Shader.h b/include/weird-renderer/resources/Shader.h index ae652dc..a6f21f1 100644 --- a/include/weird-renderer/resources/Shader.h +++ b/include/weird-renderer/resources/Shader.h @@ -46,7 +46,7 @@ namespace WeirdEngine void setUniform(const std::string& name, double value) const { - glUniform1f(getUniformLocation(name), value); + glUniform1f(getUniformLocation(name), static_cast(value)); } void setUniform(const std::string& name, int value) const diff --git a/src/weird-engine/ResourceManager.cpp b/src/weird-engine/ResourceManager.cpp index 6362a7e..0d18370 100644 --- a/src/weird-engine/ResourceManager.cpp +++ b/src/weird-engine/ResourceManager.cpp @@ -319,7 +319,7 @@ namespace WeirdEngine // Add it to mesh textures return m_textureMap[path]; } - catch (const std::exception& ex) + catch (const std::exception&) { // Couldn't load texture, using missing texture return m_textureMap[MISSING_TEXTURE]; @@ -386,12 +386,14 @@ namespace WeirdEngine if (texPath.find("baseColor") != std::string::npos || texPath.find("diffuse") != std::string::npos || texPath.find("albedo") != std::string::npos) { - textures.push_back(getTexture((fileDirectory + texPath).c_str(), DIFFUSE, textures.size())); + textures.push_back( + getTexture((fileDirectory + texPath).c_str(), DIFFUSE, static_cast(textures.size()))); } // Load defaultSpecular texture else if (texPath.find("roughness") != std::string::npos || texPath.find("specular") != std::string::npos) { - textures.push_back(getTexture((fileDirectory + texPath).c_str(), SPECULAR, textures.size())); + textures.push_back( + getTexture((fileDirectory + texPath).c_str(), SPECULAR, static_cast(textures.size()))); hasSpecular = true; } } diff --git a/src/weird-engine/Scene.cpp b/src/weird-engine/Scene.cpp index be6733a..05331fe 100644 --- a/src/weird-engine/Scene.cpp +++ b/src/weird-engine/Scene.cpp @@ -167,7 +167,7 @@ namespace WeirdEngine { if (m_debugFly) { - PlayerMovementSystem::update(m_ecs, delta); + PlayerMovementSystem::update(m_ecs, static_cast(delta)); } CameraSystem::update(m_ecs); @@ -246,7 +246,7 @@ namespace WeirdEngine { PROFILE_SCOPE("OnUpdate"); - onUpdate(delta, m_ecs); + onUpdate(static_cast(delta), m_ecs); } { @@ -259,7 +259,7 @@ namespace WeirdEngine float Scene::getTime() { - return m_simulation2D.getSimulationTime(); + return static_cast(m_simulation2D.getSimulationTime()); } void Scene::handlePhysicsStep(void* userData) @@ -368,7 +368,7 @@ namespace WeirdEngine m_sdfs.push_back(sdf); m_simulation2D.setSDFs(m_sdfs); - return m_sdfs.size() - 1; + return static_cast(m_sdfs.size() - 1); } // AUDIO diff --git a/src/weird-physics/Simulation2D.cpp b/src/weird-physics/Simulation2D.cpp index 891e53e..52619a2 100644 --- a/src/weird-physics/Simulation2D.cpp +++ b/src/weird-physics/Simulation2D.cpp @@ -434,7 +434,7 @@ namespace WeirdEngine // Check bool currentCollision = false; ShapeCollisionEvent collisionEvent; - collisionEvent.body = i; + collisionEvent.body = static_cast(i); // Static shapes int shapeIdx; @@ -568,7 +568,7 @@ namespace WeirdEngine continue; } - obj.parameters[8] = m_simulationTime; + obj.parameters[8] = static_cast(m_simulationTime); obj.parameters[9] = p.x; obj.parameters[10] = p.y; @@ -652,7 +652,7 @@ namespace WeirdEngine continue; } - obj.parameters[8] = m_simulationTime; + obj.parameters[8] = static_cast(m_simulationTime); obj.parameters[9] = p.x; obj.parameters[10] = p.y; @@ -955,7 +955,7 @@ namespace WeirdEngine { std::lock_guard lock(m_structuralMutex); - SimulationID id = m_allocated; + SimulationID id = static_cast(m_allocated); // Initialize particle with safe defaults so the physics // thread never processes stale/garbage data. @@ -1125,7 +1125,8 @@ namespace WeirdEngine std::lock_guard lock(m_structuralMutex); m_distanceConstraints.emplace_back( a, b, distance, - std::pow(stiffness, std::sqrt(m_relaxationSteps))); // Square to make stiffness more intuitive + static_cast( + std::pow(stiffness, std::sqrt(m_relaxationSteps)))); // Square to make stiffness more intuitive } void Simulation2D::addPositionConstraint(SimulationID a, SimulationID b, float distance) @@ -1310,7 +1311,7 @@ namespace WeirdEngine { // Key does not exist m_objects.push_back(sdf); - ShapeId id = m_objects.size() - 1; + ShapeId id = static_cast(m_objects.size() - 1); m_entityToObjectsIdx[owner] = id; shape.simulationId = id; } @@ -1367,7 +1368,7 @@ namespace WeirdEngine if (distanceSquared < m_radious * m_radious) { - return i; + return static_cast(i); } } @@ -1416,7 +1417,7 @@ namespace WeirdEngine } else { - int delay = std::ceil((m_fixedDeltaTime - m_simulationDelay) * 1000); // ms + int delay = static_cast(std::ceil((m_fixedDeltaTime - m_simulationDelay) * 1000)); // ms std::this_thread::sleep_for(std::chrono::milliseconds(delay)); } } diff --git a/src/weird-renderer/audio/AudioEngine.cpp b/src/weird-renderer/audio/AudioEngine.cpp index 3c0a5ed..de7439c 100644 --- a/src/weird-renderer/audio/AudioEngine.cpp +++ b/src/weird-renderer/audio/AudioEngine.cpp @@ -7,6 +7,9 @@ #define MA_NO_DEVICE_IO #define MINIAUDIO_IMPLEMENTATION +#ifdef APIENTRY +#undef APIENTRY +#endif #include #include "weird-engine/Input.h" @@ -125,7 +128,6 @@ namespace WeirdEngine // 2. Round to nearest integer (nearest semitone) int roundedNote = static_cast(std::round(continuousNote)); - // 3. Define a "Safe" Scale (C Major Pentatonic: C, D, E, G, A) // Notes relative to C: 0, 2, 4, 7, 9 // This removes notes that create high tension (like F and B) @@ -136,7 +138,7 @@ namespace WeirdEngine // If the current note isn't allowed, find the closest one that is. int closestNote = roundedNote; - int minDistance = 100; + float minDistance = 100.0f; // Search neighboring notes to find the closest allowed note for (int offset = -2; offset <= 2; ++offset) @@ -154,9 +156,10 @@ namespace WeirdEngine if (interval == allowed) { // If this allowed note is closer to original, pick it - if (std::abs(candidate - continuousNote) < minDistance) + float dist = std::abs(static_cast(candidate) - continuousNote); + if (dist < minDistance) { - minDistance = std::abs(candidate - continuousNote); + minDistance = dist; closestNote = candidate; } } diff --git a/src/weird-renderer/core/Renderer.cpp b/src/weird-renderer/core/Renderer.cpp index 6c0686e..8481a3a 100644 --- a/src/weird-renderer/core/Renderer.cpp +++ b/src/weird-renderer/core/Renderer.cpp @@ -344,8 +344,8 @@ namespace WeirdEngine { m_windowWidth = width; m_windowHeight = height; - m_renderWidth = width * m_renderScale; - m_renderHeight = height * m_renderScale; + m_renderWidth = static_cast(width * m_renderScale); + m_renderHeight = static_cast(height * m_renderScale); Display::width = m_windowWidth; Display::height = m_windowHeight; @@ -429,7 +429,13 @@ namespace WeirdEngine m_takeScreenshot = false; std::time_t t = std::time(nullptr); char timeBuf[32]; - std::strftime(timeBuf, sizeof(timeBuf), "%Y%m%d_%H%M%S", std::localtime(&t)); + struct tm tmBuf; +#if defined(_WIN32) + localtime_s(&tmBuf, &t); +#else + localtime_r(&t, &tmBuf); +#endif + std::strftime(timeBuf, sizeof(timeBuf), "%Y%m%d_%H%M%S", &tmBuf); std::string filename = std::string("screenshot_") + timeBuf + ".bmp"; m_outputResolutionRender.bind(); m_renderPlane.draw(m_outputShaderProgram); diff --git a/src/weird-renderer/core/SDF2DRenderPipeline.cpp b/src/weird-renderer/core/SDF2DRenderPipeline.cpp index 263511c..ea0eaa2 100644 --- a/src/weird-renderer/core/SDF2DRenderPipeline.cpp +++ b/src/weird-renderer/core/SDF2DRenderPipeline.cpp @@ -614,8 +614,9 @@ namespace WeirdEngine { PROFILE_SCOPE(m_config.isUI ? "applyJumpFloodCorrection (UI)" : "applyJumpFloodCorrection (World)"); - float maxDim = std::max(m_distanceSampleWidth, m_distanceSampleHeight); - uint16_t jumpFloodIterations = largestPowerOfTwoBelow(maxDim); + float maxDim = + std::max(static_cast(m_distanceSampleWidth), static_cast(m_distanceSampleHeight)); + uint16_t jumpFloodIterations = static_cast(largestPowerOfTwoBelow(static_cast(maxDim))); bool pingpong = true; // Initialize diff --git a/src/weird-renderer/resources/Mesh.cpp b/src/weird-renderer/resources/Mesh.cpp index 91b6fdd..d272378 100644 --- a/src/weird-renderer/resources/Mesh.cpp +++ b/src/weird-renderer/resources/Mesh.cpp @@ -44,7 +44,7 @@ namespace WeirdEngine UploadUniforms(shader, camera, translation, rotation, scale, materialIndex); // Draw the actual mesh - glDrawElements(GL_TRIANGLES, indices.size(), GL_UNSIGNED_INT, 0); + glDrawElements(GL_TRIANGLES, static_cast(indices.size()), GL_UNSIGNED_INT, 0); } void Mesh::drawInstances(Shader& shader, const Camera& camera, unsigned int instances, glm::vec3 translation, @@ -53,7 +53,7 @@ namespace WeirdEngine UploadUniforms(shader, camera, translation, rotation, scale, materialIndex); // Draw the actual mesh - glDrawElementsInstanced(GL_TRIANGLES, indices.size(), GL_UNSIGNED_INT, 0, instances); + glDrawElementsInstanced(GL_TRIANGLES, static_cast(indices.size()), GL_UNSIGNED_INT, 0, instances); } void Mesh::free() diff --git a/src/weird-renderer/resources/VAO.cpp b/src/weird-renderer/resources/VAO.cpp index 3f84c28..e1b69aa 100644 --- a/src/weird-renderer/resources/VAO.cpp +++ b/src/weird-renderer/resources/VAO.cpp @@ -15,7 +15,7 @@ namespace WeirdEngine void* offset) { VBO.bind(); - glVertexAttribPointer(layout, numComponents, type, GL_FALSE, stride, offset); + glVertexAttribPointer(layout, numComponents, type, GL_FALSE, static_cast(stride), offset); glEnableVertexAttribArray(layout); VBO.unbind(); } From 5af12bf920df0dbdc02795a262b3e088dc766b41 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Mart=C3=AD?= <49535803+damacaa@users.noreply.github.com> Date: Fri, 24 Jul 2026 16:08:22 +0200 Subject: [PATCH 25/25] Improved sample scenes --- .../sample-scenes/assets/Organisms/man.weird | 753 ++++++++++++++++++ .../include/MouseCollisionScene.h | 55 +- examples/sample-scenes/include/RopeScene.h | 2 +- examples/sample-scenes/include/TextScene.h | 168 ++++ examples/sample-scenes/src/main.cpp | 15 +- 5 files changed, 985 insertions(+), 8 deletions(-) create mode 100644 examples/sample-scenes/assets/Organisms/man.weird create mode 100644 examples/sample-scenes/include/TextScene.h diff --git a/examples/sample-scenes/assets/Organisms/man.weird b/examples/sample-scenes/assets/Organisms/man.weird new file mode 100644 index 0000000..e7c653b --- /dev/null +++ b/examples/sample-scenes/assets/Organisms/man.weird @@ -0,0 +1,753 @@ +{ + "camera": { + "position": [ + -3.5375001430511475, + 1.024999976158142, + 15.000022888183594 + ], + "rotation": [ + 0.0, + 0.0, + -1.0 + ], + "scale": [ + 1.0, + 1.0, + 1.0 + ] + }, + "entities": [ + { + "dot": { + "isStatic": false, + "materialId": 15 + }, + "id": 33, + "rigidBody2D": { + "physicsPosition": [ + 0.0, + 0.0 + ], + "simulationId": 0 + }, + "transform": { + "position": [ + 0.0, + 0.0, + 0.0 + ], + "rotation": [ + 0.0, + 0.0, + 0.0 + ], + "scale": [ + 1.0, + 1.0, + 1.0 + ] + } + }, + { + "dot": { + "isStatic": false, + "materialId": 15 + }, + "id": 34, + "rigidBody2D": { + "physicsPosition": [ + -1.0, + 0.0 + ], + "simulationId": 1 + }, + "transform": { + "position": [ + -1.0, + 0.0, + 0.0 + ], + "rotation": [ + 0.0, + 0.0, + 0.0 + ], + "scale": [ + 1.0, + 1.0, + 1.0 + ] + } + }, + { + "dot": { + "isStatic": false, + "materialId": 15 + }, + "id": 35, + "rigidBody2D": { + "physicsPosition": [ + -1.0, + -1.0 + ], + "simulationId": 2 + }, + "transform": { + "position": [ + -1.0, + -1.0, + 0.0 + ], + "rotation": [ + 0.0, + 0.0, + 0.0 + ], + "scale": [ + 1.0, + 1.0, + 1.0 + ] + } + }, + { + "dot": { + "isStatic": false, + "materialId": 15 + }, + "id": 36, + "rigidBody2D": { + "physicsPosition": [ + -1.0, + -2.0 + ], + "simulationId": 3 + }, + "transform": { + "position": [ + -1.0, + -2.0, + 0.0 + ], + "rotation": [ + 0.0, + 0.0, + 0.0 + ], + "scale": [ + 1.0, + 1.0, + 1.0 + ] + } + }, + { + "dot": { + "isStatic": false, + "materialId": 15 + }, + "id": 37, + "rigidBody2D": { + "physicsPosition": [ + 1.0, + 0.0 + ], + "simulationId": 4 + }, + "transform": { + "position": [ + 1.0, + 0.0, + 0.0 + ], + "rotation": [ + 0.0, + 0.0, + 0.0 + ], + "scale": [ + 1.0, + 1.0, + 1.0 + ] + } + }, + { + "dot": { + "isStatic": false, + "materialId": 15 + }, + "id": 38, + "rigidBody2D": { + "physicsPosition": [ + 1.0, + -1.0 + ], + "simulationId": 5 + }, + "transform": { + "position": [ + 1.0, + -1.0, + 0.0 + ], + "rotation": [ + 0.0, + 0.0, + 0.0 + ], + "scale": [ + 1.0, + 1.0, + 1.0 + ] + } + }, + { + "dot": { + "isStatic": false, + "materialId": 15 + }, + "id": 39, + "rigidBody2D": { + "physicsPosition": [ + 1.0, + -2.0 + ], + "simulationId": 6 + }, + "transform": { + "position": [ + 1.0, + -2.0, + 0.0 + ], + "rotation": [ + 0.0, + 0.0, + 0.0 + ], + "scale": [ + 1.0, + 1.0, + 1.0 + ] + } + }, + { + "dot": { + "isStatic": false, + "materialId": 11 + }, + "id": 40, + "rigidBody2D": { + "physicsPosition": [ + 0.0, + 2.0 + ], + "simulationId": 7 + }, + "transform": { + "position": [ + 0.0, + 2.0, + 0.0 + ], + "rotation": [ + 0.0, + 0.0, + 0.0 + ], + "scale": [ + 1.0, + 1.0, + 1.0 + ] + } + }, + { + "dot": { + "isStatic": false, + "materialId": 8 + }, + "id": 41, + "rigidBody2D": { + "physicsPosition": [ + -1.0, + 1.0 + ], + "simulationId": 8 + }, + "transform": { + "position": [ + -1.0, + 1.0, + 0.0 + ], + "rotation": [ + 0.0, + 0.0, + 0.0 + ], + "scale": [ + 1.0, + 1.0, + 1.0 + ] + } + }, + { + "dot": { + "isStatic": false, + "materialId": 8 + }, + "id": 42, + "rigidBody2D": { + "physicsPosition": [ + 1.0, + 1.0 + ], + "simulationId": 9 + }, + "transform": { + "position": [ + 1.0, + 1.0, + 0.0 + ], + "rotation": [ + 0.0, + 0.0, + 0.0 + ], + "scale": [ + 1.0, + 1.0, + 1.0 + ] + } + }, + { + "dot": { + "isStatic": false, + "materialId": 8 + }, + "id": 43, + "rigidBody2D": { + "physicsPosition": [ + 0.0, + 1.0 + ], + "simulationId": 10 + }, + "transform": { + "position": [ + 0.0, + 1.0, + 0.0 + ], + "rotation": [ + 0.0, + 0.0, + 0.0 + ], + "scale": [ + 1.0, + 1.0, + 1.0 + ] + } + }, + { + "dot": { + "isStatic": false, + "materialId": 8 + }, + "id": 44, + "rigidBody2D": { + "physicsPosition": [ + 2.0, + 1.0 + ], + "simulationId": 11 + }, + "transform": { + "position": [ + 2.0, + 1.0, + 0.0 + ], + "rotation": [ + 0.0, + 0.0, + 0.0 + ], + "scale": [ + 1.0, + 1.0, + 1.0 + ] + } + }, + { + "dot": { + "isStatic": false, + "materialId": 8 + }, + "id": 45, + "rigidBody2D": { + "physicsPosition": [ + 3.0, + 1.0 + ], + "simulationId": 12 + }, + "transform": { + "position": [ + 3.0, + 1.0, + 0.0 + ], + "rotation": [ + 0.0, + 0.0, + 0.0 + ], + "scale": [ + 1.0, + 1.0, + 1.0 + ] + } + }, + { + "dot": { + "isStatic": false, + "materialId": 11 + }, + "id": 46, + "rigidBody2D": { + "physicsPosition": [ + 4.0, + 1.0 + ], + "simulationId": 13 + }, + "transform": { + "position": [ + 4.0, + 1.0, + 0.0 + ], + "rotation": [ + 0.0, + 0.0, + 0.0 + ], + "scale": [ + 1.0, + 1.0, + 1.0 + ] + } + }, + { + "dot": { + "isStatic": false, + "materialId": 8 + }, + "id": 47, + "rigidBody2D": { + "physicsPosition": [ + -2.0, + 1.0 + ], + "simulationId": 14 + }, + "transform": { + "position": [ + -2.0, + 1.0, + 0.0 + ], + "rotation": [ + 0.0, + 0.0, + 0.0 + ], + "scale": [ + 1.0, + 1.0, + 1.0 + ] + } + }, + { + "dot": { + "isStatic": false, + "materialId": 8 + }, + "id": 48, + "rigidBody2D": { + "physicsPosition": [ + -3.0, + 1.0 + ], + "simulationId": 15 + }, + "transform": { + "position": [ + -3.0, + 1.0, + 0.0 + ], + "rotation": [ + 0.0, + 0.0, + 0.0 + ], + "scale": [ + 1.0, + 1.0, + 1.0 + ] + } + }, + { + "dot": { + "isStatic": false, + "materialId": 11 + }, + "id": 49, + "rigidBody2D": { + "physicsPosition": [ + -4.0, + 1.0 + ], + "simulationId": 16 + }, + "transform": { + "position": [ + -4.0, + 1.0, + 0.0 + ], + "rotation": [ + 0.0, + 0.0, + 0.0 + ], + "scale": [ + 1.0, + 1.0, + 1.0 + ] + } + } + ], + "physics": { + "distanceConstraints": [ + { + "A": 1, + "B": 0, + "distance": 1.0, + "k": 1.0 + }, + { + "A": 0, + "B": 4, + "distance": 1.0, + "k": 1.0 + }, + { + "A": 4, + "B": 9, + "distance": 1.0, + "k": 1.0 + }, + { + "A": 9, + "B": 10, + "distance": 1.0, + "k": 1.0 + }, + { + "A": 10, + "B": 7, + "distance": 1.0, + "k": 1.0 + }, + { + "A": 10, + "B": 8, + "distance": 1.0, + "k": 1.0 + }, + { + "A": 8, + "B": 1, + "distance": 1.0, + "k": 1.0 + }, + { + "A": 10, + "B": 0, + "distance": 1.0, + "k": 1.0 + }, + { + "A": 1, + "B": 10, + "distance": 1.4142135381698608, + "k": 1.0 + }, + { + "A": 8, + "B": 0, + "distance": 1.4142135381698608, + "k": 1.0 + }, + { + "A": 0, + "B": 9, + "distance": 1.4142135381698608, + "k": 1.0 + }, + { + "A": 10, + "B": 4, + "distance": 1.4142135381698608, + "k": 1.0 + }, + { + "A": 7, + "B": 8, + "distance": 1.4142135381698608, + "k": 1.0 + }, + { + "A": 7, + "B": 9, + "distance": 1.4142135381698608, + "k": 1.0 + }, + { + "A": 9, + "B": 11, + "distance": 1.0, + "k": 1.0 + }, + { + "A": 11, + "B": 12, + "distance": 1.0, + "k": 1.0 + }, + { + "A": 12, + "B": 13, + "distance": 1.0, + "k": 1.0 + }, + { + "A": 8, + "B": 14, + "distance": 1.0, + "k": 1.0 + }, + { + "A": 14, + "B": 15, + "distance": 1.0, + "k": 1.0 + }, + { + "A": 15, + "B": 16, + "distance": 1.0, + "k": 1.0 + }, + { + "A": 1, + "B": 2, + "distance": 1.0, + "k": 1.0 + }, + { + "A": 2, + "B": 3, + "distance": 1.0, + "k": 1.0 + }, + { + "A": 4, + "B": 5, + "distance": 1.0, + "k": 1.0 + }, + { + "A": 5, + "B": 6, + "distance": 1.0, + "k": 1.0 + }, + { + "A": 16, + "B": 7, + "distance": 4.123105525970459, + "k": 0.0024806864093989134 + }, + { + "A": 7, + "B": 13, + "distance": 4.123105525970459, + "k": 0.0024806864093989134 + }, + { + "A": 3, + "B": 14, + "distance": 3.1622776985168457, + "k": 0.0024806864093989134 + }, + { + "A": 3, + "B": 0, + "distance": 2.2360680103302, + "k": 0.0024806864093989134 + }, + { + "A": 0, + "B": 6, + "distance": 2.2360680103302, + "k": 0.0024806864093989134 + }, + { + "A": 6, + "B": 13, + "distance": 4.242640495300293, + "k": 0.0024806864093989134 + }, + { + "A": 6, + "B": 11, + "distance": 3.1622776985168457, + "k": 0.0024806864093989134 + }, + { + "A": 3, + "B": 16, + "distance": 4.242640495300293, + "k": 0.0024806864093989134 + } + ], + "fixedObjects": [], + "gravitationalConstraints": [] + }, + "tags": [ + { + "entityId": 40, + "name": "head" + } + ], + "version": 1 +} \ No newline at end of file diff --git a/examples/sample-scenes/include/MouseCollisionScene.h b/examples/sample-scenes/include/MouseCollisionScene.h index 531bc9c..3d05d5f 100644 --- a/examples/sample-scenes/include/MouseCollisionScene.h +++ b/examples/sample-scenes/include/MouseCollisionScene.h @@ -5,12 +5,18 @@ #include "globals.h" using namespace WeirdEngine; + class MouseCollisionScene : public Scene2D { public: MouseCollisionScene() {}; private: + struct CollisionCounter + { + int count; + }; + Entity m_cursorShape; // Inherited via Scene @@ -38,9 +44,10 @@ class MouseCollisionScene : public Scene2D } Dot& dot = ecs.addComponent(entity); - dot.materialId = material; + dot.materialId = 0; RigidBody2D& rb = ecs.addComponent(entity); + CollisionCounter& counter = ecs.addComponent(entity); } // Floor @@ -95,4 +102,50 @@ class MouseCollisionScene : public Scene2D ecs.setComponentDirty(cs); } } + + void onEntityCollision(ECSManager& ecs, WeirdEngine::EntityCollisionEvent& event) override + { + if (ecs.hasComponent(event.entityA)) + { + auto& counter = ecs.getComponent(event.entityA); + counter.count++; + + constexpr int COLLISIONS_PER_MATERIAL = 50; + if (counter.count <= 10 * COLLISIONS_PER_MATERIAL && counter.count % COLLISIONS_PER_MATERIAL == 0) + { + auto& dot = ecs.getComponent(event.entityA); + dot.materialId++; + + if (counter.count == 10 * COLLISIONS_PER_MATERIAL) + dot.materialId = 0; + } + } + + if (ecs.hasComponent(event.entityB)) + { + auto& counter = ecs.getComponent(event.entityB); + counter.count++; + + constexpr int COLLISIONS_PER_MATERIAL = 50; + if (counter.count <= 10 * COLLISIONS_PER_MATERIAL && counter.count % COLLISIONS_PER_MATERIAL == 0) + { + auto& dot = ecs.getComponent(event.entityB); + dot.materialId++; + + if (counter.count == 10 * COLLISIONS_PER_MATERIAL) + dot.materialId = 0; + } + } + } + + void onEntityShapeCollision(ECSManager& ecs, WeirdEngine::EntityShapeCollisionEvent& event) override + { + if (ecs.hasComponent(event.entity)) + { + auto& counter = ecs.getComponent(event.entity); + counter.count = 0; + auto& dot = ecs.getComponent(event.entity); + dot.materialId = 0; + } + } }; diff --git a/examples/sample-scenes/include/RopeScene.h b/examples/sample-scenes/include/RopeScene.h index 048c2a1..9247159 100644 --- a/examples/sample-scenes/include/RopeScene.h +++ b/examples/sample-scenes/include/RopeScene.h @@ -115,7 +115,7 @@ class RopeScene : public Scene2D addShape(DefaultShapes::SINE, vars0, 3); float vars1[8] = {25.0f, 10.0f, 5.0f, 0.5f, 13.0f, 5.0f}; // Custom shape - // m_star = addShape(DefaultShapes::STAR, vars1, 3); + m_star = addShape(DefaultShapes::STAR, vars1, 3); float vars3[8] = {15.0f, -98.0f, 15.0f, 100.0f}; addShape(DefaultShapes::BOX, vars3, 3, CombinationType::Addition); diff --git a/examples/sample-scenes/include/TextScene.h b/examples/sample-scenes/include/TextScene.h new file mode 100644 index 0000000..7774a40 --- /dev/null +++ b/examples/sample-scenes/include/TextScene.h @@ -0,0 +1,168 @@ +#pragma once + +#include + +#include "globals.h" +#include "weird-renderer/core/Display.h" + +using namespace WeirdEngine; + +class TextScene : public Scene2D +{ +public: + TextScene() {}; + +private: + Entity m_counterText = INVALID_ENTITY; + Entity m_centerText = INVALID_ENTITY; + Entity m_leftText = INVALID_ENTITY; + Entity m_rightText = INVALID_ENTITY; + Entity m_worldText = INVALID_ENTITY; + Entity m_worldMouseText = INVALID_ENTITY; + Entity m_nonResponsiveText = INVALID_ENTITY; + + int m_counter = 0; + int m_lastResolutionHash = 0; + + void onStart(ECSManager& ecs) override + { + m_debugInput = true; + m_debugFly = true; + + { + float vars[8] = {15.0f, -50.0f, 250.0f, 50.0f}; + addShape(DefaultShapes::BOX, vars, DisplaySettings::LightGray, CombinationType::SmoothAddition); + } + + ecs.getComponent(m_mainCamera).position = g_cameraPositon; + m_lastResolutionHash = Display::width + Display::height; + + { + m_worldText = ecs.createEntity(); + auto& t = ecs.addComponent(m_worldText); + t.position = vec3(15.0f, 12.0f, 0.0f); + + auto& text = ecs.addComponent(m_worldText); + text.text = "WORLD TEXT"; + text.material = DisplaySettings::Cyan; + text.horizontalAlignment = TextRenderer::HorizontalAlignment::Center; + text.verticalAlignment = TextRenderer::VerticalAlignment::Top; + } + + { + m_worldMouseText = ecs.createEntity(); + auto& t = ecs.addComponent(m_worldMouseText); + t.position = vec3(0.0f, 0.0f, 0.0f); + + auto& text = ecs.addComponent(m_worldMouseText); + text.text = "WORLD MOUSE"; + text.material = DisplaySettings::LightBlue; + text.horizontalAlignment = TextRenderer::HorizontalAlignment::Left; + text.verticalAlignment = TextRenderer::VerticalAlignment::Top; + } + + { + m_counterText = ecs.createEntity(); + auto& t = ecs.addComponent(m_counterText); + t.position = vec3(static_cast(Display::width) * 0.5f, 50.0f, 0.0f); + + auto& text = ecs.addComponent(m_counterText); + text.text = "0"; + text.material = DisplaySettings::LightGreen; + text.horizontalAlignment = TextRenderer::HorizontalAlignment::Left; + text.verticalAlignment = TextRenderer::VerticalAlignment::Bottom; + } + + { + m_centerText = ecs.createEntity(); + auto& t = ecs.addComponent(m_centerText); + t.position = vec3(static_cast(Display::width) * 0.5f, 20.0f, 0.0f); + + auto& text = ecs.addComponent(m_centerText); + text.text = "CENTERED"; + text.material = DisplaySettings::Yellow; + text.horizontalAlignment = TextRenderer::HorizontalAlignment::Center; + text.verticalAlignment = TextRenderer::VerticalAlignment::Bottom; + } + + { + m_leftText = ecs.createEntity(); + auto& t = ecs.addComponent(m_leftText); + t.position = vec3(10.0f, 20.0f, 0.0f); + + auto& text = ecs.addComponent(m_leftText); + text.text = "LEFT"; + text.material = DisplaySettings::Orange; + text.horizontalAlignment = TextRenderer::HorizontalAlignment::Left; + text.verticalAlignment = TextRenderer::VerticalAlignment::Bottom; + } + + { + m_rightText = ecs.createEntity(); + auto& t = ecs.addComponent(m_rightText); + t.position = vec3(static_cast(Display::width) - 10.0f, 20.0f, 0.0f); + + auto& text = ecs.addComponent(m_rightText); + text.text = "RIGHT"; + text.material = DisplaySettings::Magenta; + text.horizontalAlignment = TextRenderer::HorizontalAlignment::Right; + text.verticalAlignment = TextRenderer::VerticalAlignment::Bottom; + } + + { + m_nonResponsiveText = ecs.createEntity(); + auto& t = ecs.addComponent(m_nonResponsiveText); + t.position = + vec3(static_cast(Display::width) - 10.0f, static_cast(Display::height) - 10.0f, 0.0f); + + auto& text = ecs.addComponent(m_nonResponsiveText); + text.text = "STUCK"; + text.material = DisplaySettings::Red; + text.horizontalAlignment = TextRenderer::HorizontalAlignment::Right; + text.verticalAlignment = TextRenderer::VerticalAlignment::Top; + } + } + + void onUpdate(float delta, ECSManager& ecs) override + { + if (Input::GetKeyDown(Input::Q) || Input::GetGamepadButtonDown(Input::GamepadButton::North)) + { + setSceneComplete(); + } + + m_counter++; + { + auto& text = ecs.getComponent(m_counterText); + text.text = std::to_string(m_counter); + ecs.setComponentDirty(text); + + auto& t = ecs.getComponent(m_counterText); + t.position.x = Input::GetMouseX() + 20.0f; + t.position.y = Input::GetMouseY() + 10.0f; + } + + { + auto& cameraTransform = ecs.getComponent(m_mainCamera); + vec2 mouseScreen = vec2(Input::GetMouseX() + 20.0f, Input::GetMouseY() - 10.0f); + vec2 mouseWorld = ECS::Camera::screenPositionToWorldPosition2D(cameraTransform, mouseScreen); + + auto& t = ecs.getComponent(m_worldMouseText); + t.position.x = mouseWorld.x; + t.position.y = mouseWorld.y; + ecs.setComponentDirty(t); + } + + int hash = Display::width + Display::height; + if (hash != m_lastResolutionHash) + { + m_lastResolutionHash = hash; + + float halfW = static_cast(Display::width) * 0.5f; + + ecs.getComponent(m_counterText).position = vec3(halfW, 20.0f, 0.0f); + ecs.getComponent(m_centerText).position = vec3(halfW, 40.0f, 0.0f); + ecs.getComponent(m_rightText).position = + vec3(static_cast(Display::width) - 10.0f, 20.0f, 0.0f); + } + } +}; \ No newline at end of file diff --git a/examples/sample-scenes/src/main.cpp b/examples/sample-scenes/src/main.cpp index ab36865..19f07eb 100644 --- a/examples/sample-scenes/src/main.cpp +++ b/examples/sample-scenes/src/main.cpp @@ -9,6 +9,7 @@ #include "MouseCollisionScene.h" #include "RopeScene.h" #include "ShapesCombinations.h" +#include "TextScene.h" #include "WalkScene.h" #include "globals.h" @@ -22,17 +23,19 @@ int main(int argc, char* argv[]) sceneManager.registerScene("shapes"); sceneManager.registerScene("rope"); - // sceneManager.registerScene("cursor-collision"); - // sceneManager.registerScene("image"); - // sceneManager.registerScene("collision-handling"); - // sceneManager.registerScene("destroy-test"); + sceneManager.registerScene("text"); sceneManager.registerScene("life"); + sceneManager.registerScene("cursor-collision"); + sceneManager.registerScene("destroy-test"); + + // sceneManager.registerScene("collision-handling"); + // sceneManager.registerScene("image"); // sceneManager.registerScene("walk"); // sceneManager.registerScene("aquarium"); DisplaySettings displaySettings{}; - displaySettings.width = 640; - displaySettings.height = 480; + displaySettings.width = 800; + displaySettings.height = 800; displaySettings.fullscreen = false; displaySettings.colorPalette[DisplaySettings::Yellow].a = 0.25f; displaySettings.distanceSampleScale = 0.5f;