diff --git a/.github/workflows/cmake-multi-platform.yml b/.github/workflows/cmake-multi-platform.yml index 6681f8cc..865e37d4 100644 --- a/.github/workflows/cmake-multi-platform.yml +++ b/.github/workflows/cmake-multi-platform.yml @@ -8,37 +8,121 @@ on: env: BUILD_TYPE: Release + ACTIONS_ALLOW_USE_UNSECURE_NODE_VERSION: "true" + ACTIONS_RUNNER_FORCE_NODE24: "true" + FORCE_JAVASCRIPT_ACTIONS_TO_NODE24: "true" 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' - run: sudo apt update && sudo apt install -y cmake g++ make xorg-dev libgl1-mesa-dev libxrandr-dev libxinerama-dev libxcursor-dev libxi-dev + 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 - run: cmake -B ${{github.workspace}}/build -DCMAKE_BUILD_TYPE=${{env.BUILD_TYPE}} + # ------------------------------------------------------------------------ + # Web / Emscripten Dependencies + # ------------------------------------------------------------------------ + - name: Setup Emscripten (Web) + if: matrix.target == 'web' + uses: mymindstorm/setup-emsdk@v14 + with: + version: latest + + # ------------------------------------------------------------------------ + # 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 - working-directory: ${{github.workspace}}/build - run: ctest -C ${{env.BUILD_TYPE}} + - name: Test (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 (Linux) + if: matrix.target == 'linux' && always() + uses: actions/upload-artifact@v4 + with: + 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 \ + -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 + if: matrix.target == 'web' + run: | + mkdir -p game_export + # 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 + 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 + + - 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/.github/workflows/deploy-itch.yml b/.github/workflows/deploy-itch.yml new file mode 100644 index 00000000..04e7d060 --- /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 diff --git a/.github/workflows/format.yml b/.github/workflows/format.yml new file mode 100644 index 00000000..afa5ddec --- /dev/null +++ b/.github/workflows/format.yml @@ -0,0 +1,22 @@ +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: Set up Python + uses: actions/setup-python@v5 + with: + python-version: '3.x' + + - 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 00000000..254c2d21 --- /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/CMakeLists.txt b/CMakeLists.txt index 9f2fac9c..fdd20ec3 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) @@ -60,6 +60,10 @@ target_include_directories(imgui ${IMGUI_DIR}/backends ${CMAKE_CURRENT_SOURCE_DIR}/third-party/SDL/include ) +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} @@ -78,37 +82,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 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\"" ) # 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) @@ -144,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() @@ -161,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 @@ -210,3 +223,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/3d-experiments/CMakeLists.txt b/examples/3d-experiments/CMakeLists.txt index bb0c8448..978b697c 100644 --- a/examples/3d-experiments/CMakeLists.txt +++ b/examples/3d-experiments/CMakeLists.txt @@ -1,36 +1,80 @@ 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) + +# 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) + 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. @@ -49,48 +93,79 @@ 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" SUFFIX ".html") +endif() + # 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/3d-experiments/include/Classic.h b/examples/3d-experiments/include/Classic.h index 3533f261..27eb98a0 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 e15d9924..064fde3b 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 9a43bc18..fbc7d880 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/index.html b/examples/3d-experiments/src/index.html new file mode 100644 index 00000000..99a4611e --- /dev/null +++ b/examples/3d-experiments/src/index.html @@ -0,0 +1,42 @@ + + + + + + Weird3D + + + + + + + + + diff --git a/examples/3d-experiments/src/main.cpp b/examples/3d-experiments/src/main.cpp index 07236aa8..8bc976e7 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/CMakeLists.txt b/examples/empty-project/CMakeLists.txt index 2f8b4197..a0239686 100644 --- a/examples/empty-project/CMakeLists.txt +++ b/examples/empty-project/CMakeLists.txt @@ -1,44 +1,90 @@ 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) +# 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) + 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. @@ -47,48 +93,79 @@ 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" SUFFIX ".html") +endif() + # 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/empty-project/src/index.html b/examples/empty-project/src/index.html new file mode 100644 index 00000000..a02843cd --- /dev/null +++ b/examples/empty-project/src/index.html @@ -0,0 +1,42 @@ + + + + + + WeirdGame + + + + + + + + + diff --git a/examples/empty-project/src/main.cpp b/examples/empty-project/src/main.cpp index 5b16b84f..e76cab1e 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/CMakeLists.txt b/examples/opengl-experiments/CMakeLists.txt index 606a485a..96079282 100644 --- a/examples/opengl-experiments/CMakeLists.txt +++ b/examples/opengl-experiments/CMakeLists.txt @@ -1,36 +1,80 @@ 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) + +# 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) + 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. @@ -49,48 +93,79 @@ 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" SUFFIX ".html") +endif() + # 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/opengl-experiments/assets/fire/shaders/fireParticles.vert b/examples/opengl-experiments/assets/fire/shaders/fireParticles.vert index dc2dd66e..c94201c8 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 7da2fa70..8931871d 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 296ada61..f94e1bfc 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 5da45fba..8861958b 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 9ed2410c..db420669 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 1fbd6aac..96dc2803 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 3cf82d7f..b4ce3e7c 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 f77de2e3..781cfddf 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 256abda1..d9577d32 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/index.html b/examples/opengl-experiments/src/index.html new file mode 100644 index 00000000..8d27b742 --- /dev/null +++ b/examples/opengl-experiments/src/index.html @@ -0,0 +1,42 @@ + + + + + + WeirdOpenGL + + + + + + + + + diff --git a/examples/opengl-experiments/src/main.cpp b/examples/opengl-experiments/src/main.cpp index 097d1588..2c90ee3c 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/CMakeLists.txt b/examples/sample-scenes/CMakeLists.txt index 49e2a253..f2503d4b 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,21 @@ 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) +# 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) message(STATUS ">> DEPLOY MODE: Assets will be copied to output. Paths set to relative.") # Force the engine to expect runtime assets @@ -32,7 +51,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 +59,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) @@ -72,14 +93,17 @@ 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" SUFFIX ".html") +endif() + # 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 +120,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 +168,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/examples/sample-scenes/assets/Organisms/man.weird b/examples/sample-scenes/assets/Organisms/man.weird new file mode 100644 index 00000000..e7c653b8 --- /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/AquariumScene.h b/examples/sample-scenes/include/AquariumScene.h index fb351791..aaf604ef 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 47998d9b..489949ee 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 @@ -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/DestroyScene.h b/examples/sample-scenes/include/DestroyScene.h index ee4bbe77..731b274a 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 ae8ec5d1..8fddbb95 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; @@ -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/LifeScene.h b/examples/sample-scenes/include/LifeScene.h index 693d513c..8f7c2b45 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 @@ -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; @@ -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 93fe7763..3d05d5f9 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(){}; + MouseCollisionScene() {}; private: + struct CollisionCounter + { + int count; + }; + Entity m_cursorShape; // Inherited via Scene @@ -22,7 +28,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); @@ -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 431ca49c..9247159e 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; @@ -116,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); @@ -161,13 +160,14 @@ 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); - 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); } @@ -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 34f07cdf..958aefe8 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; @@ -35,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) { @@ -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/TextScene.h b/examples/sample-scenes/include/TextScene.h new file mode 100644 index 00000000..7774a40e --- /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/include/WalkScene.h b/examples/sample-scenes/include/WalkScene.h index ffe0aa41..d0c76fa9 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); @@ -133,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 { @@ -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/examples/sample-scenes/src/index.html b/examples/sample-scenes/src/index.html new file mode 100644 index 00000000..0fd56092 --- /dev/null +++ b/examples/sample-scenes/src/index.html @@ -0,0 +1,42 @@ + + + + + + WeirdSamples + + + + + + + + + diff --git a/examples/sample-scenes/src/main.cpp b/examples/sample-scenes/src/main.cpp index 348e1bd4..19f07eb5 100644 --- a/examples/sample-scenes/src/main.cpp +++ b/examples/sample-scenes/src/main.cpp @@ -9,11 +9,10 @@ #include "MouseCollisionScene.h" #include "RopeScene.h" #include "ShapesCombinations.h" +#include "TextScene.h" #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); @@ -24,19 +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("scene-editor", ASSETS_PATH "example.weird"); - // sceneManager.registerScene("molecule-editor"); + 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; diff --git a/include/weird-engine.h b/include/weird-engine.h index bdbfbf42..0bcc52c6 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; } @@ -222,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) { @@ -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 ac976368..729d1e4b 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 59bf1c56..dd7763f0 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 e1a622b1..10bb8184 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 13819200..1a4384c7 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 ccf4dee2..e481f90b 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,10 +298,11 @@ 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; + statIndex = static_cast(i); + m_currentIndex = static_cast(i + 1); found = true; break; } @@ -266,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()); } } @@ -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 1af91802..4124109d 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 e55da956..49d28af7 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 5c043aec..15ee544d 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]]; } @@ -148,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/ecs/ECS.h b/include/weird-engine/ecs/ECS.h index 559918cd..72964bdd 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 12a197e3..e268cd50 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 269c7fab..e5499ac6 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 12baa9c0..eb7befb0 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 cb3364ed..126aaf71 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 b98e7d56..0812aab0 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 15c5beac..ec22053a 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 7f3c695b..a31adab0 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 f0776c23..c395a519 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 4c02fd34..67794177 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 = 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; + + 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 = static_cast(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 = static_cast(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; + } - vec2 alignmentOffset(horizontalOffset, verticalOffset); + 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; + } - 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++) + vec2 alignmentOffset(horizontalOffset, verticalOffset); + + 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 f5dc4efe..60c86a2b 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,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++) { @@ -75,7 +78,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 +104,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 +190,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 +223,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 b7400bed..22ba11cd 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 5df3dedf..b002b061 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 f4d49438..101bed0e 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 b10e23c9..7a7d352d 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 74f4d53a..7fdd86e3 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 a1697963..9a4cd828 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 80a36929..673c0b99 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 fd767380..ea60ffc0 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 39f64cd3..5e36b2c8 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 5701277d..fa78f09e 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 442a9b3b..e9c1b4a5 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 a684210f..2e596ce1 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 8da26776..430ee39f 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 8586427a..67faf095 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 87dcaad7..9c028345 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 fa51d7c8..0487f698 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 81208227..ff7de1bb 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 3c5aa1a4..30d24686 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 @@ -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/Mesh.h b/include/weird-renderer/resources/Mesh.h index b565cb5e..205f5240 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/include/weird-renderer/resources/Shader.h b/include/weird-renderer/resources/Shader.h index ae652dc7..a6f21f12 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/Logger.cpp b/src/weird-engine/Logger.cpp index 18279ff4..1c8dc41d 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 174ad9a4..0d183702 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 @@ -318,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]; @@ -385,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 a491f7cf..05331fe5 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); } @@ -168,7 +167,7 @@ namespace WeirdEngine { if (m_debugFly) { - PlayerMovementSystem::update(m_ecs, delta); + PlayerMovementSystem::update(m_ecs, static_cast(delta)); } CameraSystem::update(m_ecs); @@ -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,14 +239,14 @@ 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; } { 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) @@ -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); } @@ -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 @@ -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 b282aec6..c2773e3b 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 8777ba6b..52619a2f 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 @@ -431,7 +434,7 @@ namespace WeirdEngine // Check bool currentCollision = false; ShapeCollisionEvent collisionEvent; - collisionEvent.body = i; + collisionEvent.body = static_cast(i); // Static shapes int shapeIdx; @@ -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; @@ -565,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; @@ -634,7 +637,6 @@ namespace WeirdEngine groupState->minDistance = currentMinDistance; } - for (const auto& group : groups) { d = std::min(d, group.minDistance); @@ -643,14 +645,14 @@ 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()) { continue; } - obj.parameters[8] = m_simulationTime; + obj.parameters[8] = static_cast(m_simulationTime); obj.parameters[9] = p.x; obj.parameters[10] = p.y; @@ -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) @@ -953,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. @@ -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); @@ -1126,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) @@ -1175,17 +1175,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 +1237,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 +1258,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 +1275,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 +1297,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); @@ -1313,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; } @@ -1370,7 +1368,7 @@ namespace WeirdEngine if (distanceSquared < m_radious * m_radious) { - return i; + return static_cast(i); } } @@ -1419,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 d12e20ee..de7439c3 100644 --- a/src/weird-renderer/audio/AudioEngine.cpp +++ b/src/weird-renderer/audio/AudioEngine.cpp @@ -1,12 +1,15 @@ #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 +#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/MeshRenderPipeline.cpp b/src/weird-renderer/core/MeshRenderPipeline.cpp index a20de21f..7e934878 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 b0247aa8..4c65c85a 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 dbcd9f76..8481a3a1 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(); } @@ -343,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; @@ -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); @@ -428,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); @@ -487,8 +494,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 +527,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 +631,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 +673,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 +687,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 +711,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 +753,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 +801,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 +837,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 d6b7c07d..ea0eaa22 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; @@ -611,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 @@ -683,7 +687,6 @@ namespace WeirdEngine { PROFILE_SCOPE(m_config.isUI ? "upscaleDistance (UI)" : "upscaleDistance (World)"); - m_distanceUpscaler.bind(); m_distanceUpscalerShader.use(); @@ -704,7 +707,6 @@ namespace WeirdEngine { PROFILE_SCOPE(m_config.isUI ? "renderMaterialColors (UI)" : "renderMaterialColors (World)"); - m_colorRender.bind(); m_materialColorShader.use(); @@ -730,7 +732,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 +755,7 @@ namespace WeirdEngine horizontal = !horizontal; } - + Profiler::get().gpuSync(); } @@ -765,8 +767,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 +780,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 +806,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 +870,12 @@ namespace WeirdEngine } else { - if (m_backgroundDoubleBufferIdx == 0) { + if (m_backgroundDoubleBufferIdx == 0) + { m_backgroundTextureFront.bind(2); - } else { + } + else + { m_backgroundTextureBack.bind(2); } } @@ -889,48 +900,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 8e6f8bd9..779bf737 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 5a9ea2b7..1830d69f 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 b35c0684..49c34caf 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 7ddddb1d..d2723781 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() @@ -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 292e6295..3e2774bd 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,14 +428,15 @@ 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"; } logMsg += "Elapsed time:" + std::to_string(ms) + " ms \n\n"; - WeirdEngine::Logger::Log(logMsg); + WeirdEngine::Logger::log(logMsg); #endif m_uniformLocationCache.clear(); @@ -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 3b89f171..2a25bde1 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/resources/VAO.cpp b/src/weird-renderer/resources/VAO.cpp index 3f84c28a..e1b69aa1 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(); } diff --git a/src/weird-renderer/scene/Camera.cpp b/src/weird-renderer/scene/Camera.cpp index 773987cb..35ad74c6 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 4eb66c6c..7d044c64 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 5439cf79..85de3a0d 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 66db86c3..62456f2d 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 6c2fa006..95e7dee6 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 90951e72..83af6523 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 01a318d0..53e708c5 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 026b9884..2ff7271c 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 6e201db0..f8d5a0c6 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 87ace251..cd97aaf2 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 3269fae6..2f6c8861 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 a40d1119..7bf51bf5 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 89f16d79..f34d91eb 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 7a506b3f..b4b34d88 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/CMakeLists.txt b/tools/CMakeLists.txt new file mode 100644 index 00000000..91d1e4ec --- /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 00000000..1968fd84 --- /dev/null +++ b/tools/molecule-editor/CMakeLists.txt @@ -0,0 +1,171 @@ +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") +file(MAKE_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}/src") + +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) + +# 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) + +# 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) + 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 ${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/*.*" +) + +# 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}) + +if(BUILD_WEB) + set_target_properties(${PROJECT_NAME} PROPERTIES OUTPUT_NAME "index" SUFFIX ".html") +endif() + +# 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() + +# ------------------------------------------------------------------------- +# 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/examples/sample-scenes/include/MoleculeEditor.h b/tools/molecule-editor/include/MoleculeEditor.h similarity index 98% rename from examples/sample-scenes/include/MoleculeEditor.h rename to tools/molecule-editor/include/MoleculeEditor.h index 74aa64d4..c170cc9d 100644 --- a/examples/sample-scenes/include/MoleculeEditor.h +++ b/tools/molecule-editor/include/MoleculeEditor.h @@ -13,15 +13,20 @@ #include #include -#include "globals.h" +#include "weird-engine/math/Default2DSDFs.h" +#include "weird-physics/components/DistanceConstraint.h" +#include "weird-physics/components/GlobalPhysicsSettings.h" +#include "weird-physics/components/Spring.h" +#include + +extern WeirdEngine::vec3 g_cameraPositon; using namespace WeirdEngine; class MoleculeEditor : public Scene2D { public: - MoleculeEditor(){ - } + MoleculeEditor() {} ECSManager* m_tempEcs = nullptr; @@ -611,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); @@ -1150,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/index.html b/tools/molecule-editor/src/index.html new file mode 100644 index 00000000..6e417246 --- /dev/null +++ b/tools/molecule-editor/src/index.html @@ -0,0 +1,42 @@ + + + + + + MoleculeEditor + + + + + + + + + diff --git a/tools/molecule-editor/src/main.cpp b/tools/molecule-editor/src/main.cpp new file mode 100644 index 00000000..036c0684 --- /dev/null +++ b/tools/molecule-editor/src/main.cpp @@ -0,0 +1,25 @@ +#include "MoleculeEditor.h" +#include + +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 00000000..cd982974 --- /dev/null +++ b/tools/scene-editor/CMakeLists.txt @@ -0,0 +1,171 @@ +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") +file(MAKE_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}/src") + +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) + +# 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) + +# 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) + 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 ${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/*.*" +) + +# 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}) + +if(BUILD_WEB) + set_target_properties(${PROJECT_NAME} PROPERTIES OUTPUT_NAME "index" SUFFIX ".html") +endif() + +# 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() + +# ------------------------------------------------------------------------- +# 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/examples/sample-scenes/include/SceneLoadExample.h b/tools/scene-editor/include/SceneEditor.h similarity index 92% rename from examples/sample-scenes/include/SceneLoadExample.h rename to tools/scene-editor/include/SceneEditor.h index 8ebbcb9f..5bf99ace 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) { } @@ -150,8 +154,8 @@ class SceneLoadExample : 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++) { @@ -548,7 +552,9 @@ class SceneLoadExample : 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; @@ -662,29 +668,47 @@ class SceneLoadExample : 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; } @@ -699,15 +723,24 @@ class SceneLoadExample : 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/index.html b/tools/scene-editor/src/index.html new file mode 100644 index 00000000..ddb31b99 --- /dev/null +++ b/tools/scene-editor/src/index.html @@ -0,0 +1,42 @@ + + + + + + SceneEditor + + + + + + + + + diff --git a/tools/scene-editor/src/main.cpp b/tools/scene-editor/src/main.cpp new file mode 100644 index 00000000..052d1efb --- /dev/null +++ b/tools/scene-editor/src/main.cpp @@ -0,0 +1,25 @@ +#include "SceneEditor.h" +#include + +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; +}