This commit is contained in:
Vladislav Khorev 2026-07-14 20:14:30 +06:00
parent 34a55611d5
commit 804e34ce12
24 changed files with 335 additions and 7 deletions

View File

@ -126,6 +126,18 @@ $(pkg-config --cflags --libs vorbis vorbisfile ogg) \
-lopenal
```
Linux new:
sudo apt-get update
sudo apt-get install build-essential cmake pkg-config \
libsdl2-dev libsdl2-ttf-dev libsdl2-mixer-dev \
libgl1-mesa-dev libpng-dev libz-dev libzip-dev \
libboost-dev libeigen3-dev liblua5.4-dev
sudo apt-get install libglu1-mesa-dev
# Emscripten new
```

View File

@ -0,0 +1,28 @@
# cmake/FetchDependenciesLinux.cmake
set(THIRDPARTY_DIR "${CMAKE_CURRENT_LIST_DIR}/../thirdparty")
if(NOT EXISTS "${THIRDPARTY_DIR}")
file(MAKE_DIRECTORY "${THIRDPARTY_DIR}")
endif()
macro(check_and_download URL ARCHIVE_NAME EXTRACTED_DIR_NAME CHECK_FILE)
set(ARCHIVE_PATH "${THIRDPARTY_DIR}/${ARCHIVE_NAME}")
set(SRC_PATH "${THIRDPARTY_DIR}/${EXTRACTED_DIR_NAME}")
if(NOT EXISTS "${ARCHIVE_PATH}")
message(STATUS "Downloading ${ARCHIVE_NAME}...")
file(DOWNLOAD "${URL}" "${ARCHIVE_PATH}" SHOW_PROGRESS)
endif()
if(NOT EXISTS "${SRC_PATH}/${CHECK_FILE}")
message(STATUS "Extracting ${ARCHIVE_NAME}...")
execute_process(
COMMAND ${CMAKE_COMMAND} -E tar xvf "${ARCHIVE_PATH}"
WORKING_DIRECTORY "${THIRDPARTY_DIR}"
)
endif()
endmacro()
# 1) sol2 (header-only C++ bindings for Lua)
check_and_download("https://github.com/ThePhD/sol2/archive/refs/tags/v3.3.0.zip" "sol2-v3.3.0.zip" "sol2-3.3.0" "include/sol/sol.hpp")

222
proj-linux/CMakeLists.txt Normal file
View File

@ -0,0 +1,222 @@
cmake_minimum_required(VERSION 3.16)
project(witcher001 LANGUAGES C CXX)
set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
# ===========================================
# Поиск системных зависимостей Linux
# ===========================================
find_package(PkgConfig REQUIRED)
find_package(OpenGL REQUIRED)
find_package(ZLIB REQUIRED)
find_package(PNG REQUIRED)
find_package(Boost REQUIRED)
find_package(Freetype REQUIRED)
# Eigen3 ищется через свой конфиг, который ставится вместе с пакетом libeigen3-dev
find_package(Eigen3 REQUIRED NO_MODULE)
pkg_check_modules(SDL2 REQUIRED sdl2)
pkg_check_modules(SDL2_TTF REQUIRED SDL2_ttf)
pkg_check_modules(SDL2_MIXER REQUIRED SDL2_mixer)
pkg_check_modules(LIBZIP REQUIRED libzip)
# Имя пакета Lua может варьироваться (lua5.4, lua-5.4 или lua). Здесь указан дефолтный для Ubuntu
pkg_check_modules(LUA REQUIRED lua5.4)
include("${CMAKE_CURRENT_SOURCE_DIR}/../cmake/FetchDependenciesLinux.cmake")
# ===========================================
# sol2 (3.3.0) - header-only C++ bindings for Lua
# ===========================================
set(THIRDPARTY_DIR "${CMAKE_CURRENT_LIST_DIR}/../thirdparty")
set(SOL2_SRC_DIR "${THIRDPARTY_DIR}/sol2-3.3.0")
# Apply patch for Clang/Emscripten compatibility in optional<T&>::emplace().
# The sentinel file prevents re-applying on subsequent cmake runs.
set(_sol2_sentinel "${SOL2_SRC_DIR}/.patched")
if(NOT EXISTS "${_sol2_sentinel}")
find_package(Git QUIET)
if(GIT_FOUND)
execute_process(
COMMAND ${GIT_EXECUTABLE} apply --ignore-whitespace
"${CMAKE_CURRENT_LIST_DIR}/../cmake/patches/sol2-3.3.0-clang-optional.patch"
WORKING_DIRECTORY "${SOL2_SRC_DIR}"
RESULT_VARIABLE _sol2_patch_res
)
if(_sol2_patch_res EQUAL 0)
file(WRITE "${_sol2_sentinel}" "patched\n")
message(STATUS "Applied sol2 Clang optional patch")
else()
message(WARNING "sol2 patch failed (exit ${_sol2_patch_res}) — Clang/Emscripten builds may not compile")
endif()
else()
message(WARNING "Git not found — cannot apply sol2 patch automatically. "
"Apply cmake/patches/sol2-3.3.0-clang-optional.patch manually.")
endif()
endif()
# ===========================================
# Основной проект witcher001
# ===========================================
add_executable(witcher001
../src/main.cpp
../src/Game.cpp
../src/Game.h
../src/Character.cpp
../src/Character.h
../src/CharacterState.cpp
../src/CharacterState.h
../src/Environment.cpp
../src/Environment.h
../src/Localization.cpp
../src/Localization.h
../src/render/Renderer.cpp
../src/render/Renderer.h
../src/render/ShaderManager.cpp
../src/render/ShaderManager.h
../src/render/TextureManager.cpp
../src/render/TextureManager.h
../src/TextModel.cpp
../src/TextModel.h
../src/AudioPlayerAsync.cpp
../src/AudioPlayerAsync.h
../src/BoneAnimatedModelNew.cpp
../src/BoneAnimatedModelNew.h
../src/render/OpenGlExtensions.cpp
../src/render/OpenGlExtensions.h
../src/utils/Utils.cpp
../src/utils/Utils.h
../src/SparkEmitter.cpp
../src/SparkEmitter.h
../src/TeleportZone.h
../src/TeleportZone.cpp
../src/utils/TaskManager.cpp
../src/utils/TaskManager.h
../src/render/FrameBuffer.cpp
../src/render/FrameBuffer.h
../src/render/ShadowMap.cpp
../src/render/ShadowMap.h
../src/UiManager.cpp
../src/UiManager.h
../src/render/TextRenderer.h
../src/render/TextRenderer.cpp
../src/MenuManager.h
../src/MenuManager.cpp
../src/Location.h
../src/Location.cpp
../src/LocationState.h
../src/LocationState.cpp
../src/LocationEditor.h
../src/LocationEditor.cpp
../src/NpcCar.h
../src/NpcCar.cpp
../src/GameConstants.h
../src/GameConstants.cpp
../src/GameState.h
../src/GameState.cpp
../src/ScriptEngine.h
../src/ScriptEngine.cpp
../src/navigation/PathFinder.h
../src/navigation/PathFinder.cpp
../src/items/GameObjectLoader.h
../src/items/GameObjectLoader.cpp
../src/items/Item.h
../src/items/Item.cpp
../src/items/ItemRegistry.h
../src/items/ItemRegistry.cpp
../src/items/InteractiveObject.h
../src/items/InteractiveObject.cpp
../src/items/InteractiveObjectState.h
../src/dialogue/DialogueTypes.h
../src/dialogue/DialogueDatabase.h
../src/dialogue/DialogueDatabase.cpp
../src/dialogue/DialogueRuntime.h
../src/dialogue/DialogueRuntime.cpp
../src/dialogue/DialogueOverlay.h
../src/dialogue/DialogueOverlay.cpp
../src/dialogue/DialogueSystem.h
../src/dialogue/DialogueSystem.cpp
../src/dialogue/TranslationDatabase.h
../src/dialogue/TranslationDatabase.cpp
../src/quest/QuestTypes.h
../src/quest/QuestJournal.h
../src/quest/QuestJournal.cpp
../src/cutscene/CutsceneTypes.h
../src/cutscene/CutsceneDatabase.h
../src/cutscene/CutsceneDatabase.cpp
../src/cutscene/CutsceneRuntime.h
../src/cutscene/CutsceneRuntime.cpp
../src/cutscene/CutsceneOverlay.h
../src/cutscene/CutsceneOverlay.cpp
../src/render/UiQuad.h
)
# include-пути проекта
target_include_directories(witcher001 PRIVATE
"${CMAKE_CURRENT_SOURCE_DIR}/../src"
${SDL2_INCLUDE_DIRS}
${SDL2_TTF_INCLUDE_DIRS}
${SDL2_MIXER_INCLUDE_DIRS}
${LIBZIP_INCLUDE_DIRS}
${LUA_INCLUDE_DIRS}
${EIGEN3_INCLUDE_DIRS}
# sol2 - header-only, берем напрямую из thirdparty (если он там есть)
# или можно установить системный libsol-dev и убрать этот путь
"${CMAKE_CURRENT_SOURCE_DIR}/../thirdparty/sol2-3.3.0/include"
)
# Убираем WIN32_LEAN_AND_MEAN
target_compile_definitions(witcher001 PRIVATE
PNG_ENABLED
SDL_MAIN_HANDLED
)
# Линковка директорий для pkg-config (если пакеты не в /usr/lib)
target_link_directories(witcher001 PRIVATE
${SDL2_LIBRARY_DIRS}
${SDL2_TTF_LIBRARY_DIRS}
${SDL2_MIXER_LIBRARY_DIRS}
${LIBZIP_LIBRARY_DIRS}
${LUA_LIBRARY_DIRS}
)
# Линковка библиотек
target_link_libraries(witcher001 PRIVATE
OpenGL::GL
OpenGL::GLU
ZLIB::ZLIB
PNG::PNG
Boost::boost
Freetype::Freetype
${SDL2_LIBRARIES}
${SDL2_TTF_LIBRARIES}
${SDL2_MIXER_LIBRARIES}
${LIBZIP_LIBRARIES}
${LUA_LIBRARIES}
pthread
)
# ===========================================
# Копирование ресурсов после сборки
# ===========================================
set(RUNTIME_RESOURCE_DIRS
"resources"
"audio"
)
# В Linux (при использовании Make/Ninja) бинарник обычно создается в CMAKE_BINARY_DIR.
# Копируем ресурсы рядом с исполняемым файлом.
foreach(resdir IN LISTS RUNTIME_RESOURCE_DIRS)
add_custom_command(TARGET witcher001 POST_BUILD
COMMAND ${CMAKE_COMMAND} -E echo "Copying ${resdir} to binary dir..."
COMMAND ${CMAKE_COMMAND} -E copy_directory
"${CMAKE_SOURCE_DIR}/../${resdir}"
"${CMAKE_BINARY_DIR}/${resdir}"
)
endforeach()

View File

@ -1,3 +1,5 @@
#version 120
attribute vec3 vPosition;
attribute vec2 vTexCoord;
attribute vec3 vNormal;

View File

@ -1,3 +1,4 @@
#version 120
uniform sampler2D Texture;
uniform sampler2D uShadowMap;
uniform vec3 uLightDir;

View File

@ -1,3 +1,4 @@
#version 120
attribute vec3 vPosition;
attribute vec2 vTexCoord;
attribute vec3 vNormal;

View File

@ -1,3 +1,4 @@
#version 120
uniform sampler2D Texture;
uniform sampler2D uShadowMap;
uniform vec3 uLightDir;

View File

@ -1,3 +1,4 @@
#version 120
attribute vec3 vPosition;
attribute vec2 vTexCoord;
attribute vec4 aBoneIndices0;

View File

@ -1,3 +1,4 @@
#version 120
attribute vec3 vPosition;
attribute vec2 vTexCoord;
attribute vec3 vNormal;

View File

@ -1,3 +1,4 @@
#version 120
attribute vec3 vPosition;
attribute vec2 vTexCoord;
attribute vec3 vNormal;

View File

@ -1,3 +1,4 @@
#version 120
uniform sampler2D Texture;
uniform float uAlpha;
uniform int uPointLightCount;

View File

@ -1,3 +1,4 @@
#version 120
attribute vec3 vPosition;
attribute vec2 vTexCoord;
attribute vec3 vNormal;

View File

@ -1,3 +1,4 @@
#version 120
uniform sampler2D Texture;
uniform sampler2D uShadowMap;
uniform vec3 uLightDir;

View File

@ -1,3 +1,4 @@
#version 120
attribute vec3 vPosition;
attribute vec2 vTexCoord;
attribute vec3 vNormal;

View File

@ -1,3 +1,4 @@
#version 120
attribute vec3 vPosition;
attribute vec2 vTexCoord;
attribute vec3 vNormal;

View File

@ -1,3 +1,4 @@
#version 120
attribute vec3 vPosition;
attribute vec2 vTexCoord;
attribute vec3 vNormal;

View File

@ -12,6 +12,10 @@ namespace ZL
using std::min;
using std::max;
#endif
#ifdef __linux__
using std::min;
using std::max;
#endif
static std::unordered_map<std::string, BoneSystemNew> s_boneSystemCache;

View File

@ -28,7 +28,7 @@ SDL_Window* Environment::window = nullptr;
#ifdef EMSCRIPTEN
bool Environment::isFullscreen = false;
#else
bool Environment::isFullscreen = true;
bool Environment::isFullscreen = false;
#endif
bool Environment::isHighDPIEnabled = false;

View File

@ -15,6 +15,11 @@ namespace ZL {
using std::max;
#endif
#ifdef __linux__
using std::min;
using std::max;
#endif
constexpr float DEFAULT_ZOOM = 8.f;
class Environment {

View File

@ -94,11 +94,15 @@ namespace ZL
ZL::CheckGlError(__FILE__, __LINE__);
renderer.InitOpenGL();
#ifdef EMSCRIPTEN
#if defined(EMSCRIPTEN)
// These shaders and loading.png are preloaded separately (not from zip),
// so they are available immediately without waiting for resources.zip.
renderer.shaderManager.AddShaderFromFiles("defaultColor", "resources/shaders/defaultColor.vertex", "resources/shaders/defaultColor_web.fragment", "");
renderer.shaderManager.AddShaderFromFiles("default", "resources/shaders/default.vertex", "resources/shaders/default_web.fragment", "");
#elif defined(__linux__)
renderer.shaderManager.AddShaderFromFiles("defaultColor", "resources/shaders/defaultColor.vertex", "resources/shaders/defaultColor_desktop.fragment", CONST_ZIP_FILE);
renderer.shaderManager.AddShaderFromFiles("default", "resources/shaders/default.vertex", "resources/shaders/default_desktop.fragment", CONST_ZIP_FILE);
#else
renderer.shaderManager.AddShaderFromFiles("defaultColor", "resources/shaders/defaultColor.vertex", "resources/shaders/defaultColor_desktop.fragment", CONST_ZIP_FILE);
renderer.shaderManager.AddShaderFromFiles("default", "resources/shaders/default.vertex", "resources/shaders/default_desktop.fragment", CONST_ZIP_FILE);
@ -157,7 +161,7 @@ namespace ZL
});
loadSteps.push([this]() {
#ifdef EMSCRIPTEN
#if defined(EMSCRIPTEN)
renderer.shaderManager.AddShaderFromFiles("env_sky", "resources/shaders/env_sky.vertex", "resources/shaders/env_sky_web.fragment", CONST_ZIP_FILE);
renderer.shaderManager.AddShaderFromFiles("defaultAtmosphere", "resources/shaders/defaultAtmosphere.vertex", "resources/shaders/defaultAtmosphere_web.fragment", CONST_ZIP_FILE);
renderer.shaderManager.AddShaderFromFiles("planetBake", "resources/shaders/planet_bake.vertex", "resources/shaders/planet_bake_web.fragment", CONST_ZIP_FILE);
@ -182,7 +186,34 @@ namespace ZL
renderer.shaderManager.AddShaderFromFiles("night_fog_skinning", "resources/shaders/night_fog_skinning.vertex", "resources/shaders/night_fog_web.fragment", CONST_ZIP_FILE);
renderer.shaderManager.AddShaderFromFiles("night_fog_shadow", "resources/shaders/night_fog_shadow.vertex", "resources/shaders/night_fog_shadow_web.fragment", CONST_ZIP_FILE);
renderer.shaderManager.AddShaderFromFiles("night_fog_skinning_shadow", "resources/shaders/night_fog_skinning_shadow.vertex", "resources/shaders/night_fog_shadow_web.fragment", CONST_ZIP_FILE);
#else
#elif defined(__linux__)
renderer.shaderManager.AddShaderFromFiles("env_sky", "resources/shaders/env_sky.vertex", "resources/shaders/env_sky_desktop.fragment", CONST_ZIP_FILE);
renderer.shaderManager.AddShaderFromFiles("defaultAtmosphere", "resources/shaders/defaultAtmosphere.vertex", "resources/shaders/defaultAtmosphere_desktop.fragment", CONST_ZIP_FILE);
renderer.shaderManager.AddShaderFromFiles("planetBake", "resources/shaders/planet_bake.vertex", "resources/shaders/planet_bake_desktop.fragment", CONST_ZIP_FILE);
renderer.shaderManager.AddShaderFromFiles("planetStone", "resources/shaders/planet_stone.vertex", "resources/shaders/planet_stone_desktop.fragment", CONST_ZIP_FILE);
renderer.shaderManager.AddShaderFromFiles("planetLand", "resources/shaders/planet_land.vertex", "resources/shaders/planet_land_desktop.fragment", CONST_ZIP_FILE);
renderer.shaderManager.AddShaderFromFiles("spark", "resources/shaders/spark.vertex", "resources/shaders/spark_desktop.fragment", CONST_ZIP_FILE);
renderer.shaderManager.AddShaderFromFiles("skinning", "resources/shaders/skinning.vertex", "resources/shaders/default_desktop.fragment", CONST_ZIP_FILE);
renderer.shaderManager.AddShaderFromFiles("fog", "resources/shaders/fog.vertex", "resources/shaders/fog_desktop.fragment", CONST_ZIP_FILE);
renderer.shaderManager.AddShaderFromFiles("fog_skinning", "resources/shaders/fog_skinning.vertex", "resources/shaders/fog_desktop.fragment", CONST_ZIP_FILE);
renderer.shaderManager.AddShaderFromFiles("darklands_fog", "resources/shaders/darklands_fog.vertex", "resources/shaders/darklands_fog_desktop.fragment", CONST_ZIP_FILE);
renderer.shaderManager.AddShaderFromFiles("darklands_fog_skinning", "resources/shaders/darklands_fog_skinning.vertex", "resources/shaders/darklands_fog_desktop.fragment", CONST_ZIP_FILE);
renderer.shaderManager.AddShaderFromFiles("darklands_flash", "resources/shaders/default.vertex", "resources/shaders/darklands_flash_desktop.fragment", CONST_ZIP_FILE);
renderer.shaderManager.AddShaderFromFiles("cutsceneFade", "resources/shaders/default.vertex", "resources/shaders/cutscene_fade_desktop.fragment", CONST_ZIP_FILE);
renderer.shaderManager.AddShaderFromFiles("cutsceneBlack", "resources/shaders/default.vertex", "resources/shaders/cutscene_black_desktop.fragment", CONST_ZIP_FILE);
renderer.shaderManager.AddShaderFromFiles("shadow_depth", "resources/shaders/shadow_depth.vertex", "resources/shaders/shadow_depth_desktop.fragment", CONST_ZIP_FILE);
renderer.shaderManager.AddShaderFromFiles("shadow_depth_skinning", "resources/shaders/shadow_depth_skinning.vertex", "resources/shaders/shadow_depth_desktop.fragment", CONST_ZIP_FILE);
renderer.shaderManager.AddShaderFromFiles("default_shadow", "resources/shaders/default_shadow.vertex", "resources/shaders/default_shadow_desktop.fragment", CONST_ZIP_FILE);
renderer.shaderManager.AddShaderFromFiles("skinning_shadow", "resources/shaders/skinning_shadow.vertex", "resources/shaders/default_shadow_desktop.fragment", CONST_ZIP_FILE);
renderer.shaderManager.AddShaderFromFiles("fog_shadow", "resources/shaders/fog_shadow.vertex", "resources/shaders/fog_shadow_desktop.fragment", CONST_ZIP_FILE);
renderer.shaderManager.AddShaderFromFiles("fog_skinning_shadow", "resources/shaders/fog_skinning_shadow.vertex", "resources/shaders/fog_shadow_desktop.fragment", CONST_ZIP_FILE);
renderer.shaderManager.AddShaderFromFiles("night_fog", "resources/shaders/night_fog.vertex", "resources/shaders/night_fog_desktop.fragment", CONST_ZIP_FILE);
renderer.shaderManager.AddShaderFromFiles("night_fog_skinning", "resources/shaders/night_fog_skinning.vertex", "resources/shaders/night_fog_desktop.fragment", CONST_ZIP_FILE);
renderer.shaderManager.AddShaderFromFiles("night_fog_shadow", "resources/shaders/night_fog_shadow.vertex", "resources/shaders/night_fog_shadow_desktop.fragment", CONST_ZIP_FILE);
renderer.shaderManager.AddShaderFromFiles("night_fog_skinning_shadow", "resources/shaders/night_fog_skinning_shadow.vertex", "resources/shaders/night_fog_shadow_desktop.fragment", CONST_ZIP_FILE);
#else
renderer.shaderManager.AddShaderFromFiles("env_sky", "resources/shaders/env_sky.vertex", "resources/shaders/env_sky_desktop.fragment", CONST_ZIP_FILE);
renderer.shaderManager.AddShaderFromFiles("defaultAtmosphere", "resources/shaders/defaultAtmosphere.vertex", "resources/shaders/defaultAtmosphere_desktop.fragment", CONST_ZIP_FILE);
renderer.shaderManager.AddShaderFromFiles("planetBake", "resources/shaders/planet_bake.vertex", "resources/shaders/planet_bake_desktop.fragment", CONST_ZIP_FILE);

View File

@ -14,6 +14,10 @@ namespace ZL {
using std::min;
using std::max;
#endif
#ifdef __linux__
using std::min;
using std::max;
#endif
InteractiveObject InteractiveObject::createFromState(InteractiveObjectState st,
Renderer& renderer,

View File

@ -229,7 +229,7 @@ extern "C" int SDL_main(int argc, char* argv[]) {
#endif
#ifdef WIN32_LEAN_AND_MEAN
#if defined(WIN32) || defined(_WIN32) || defined(__WIN32__) || defined(__linux__)
int main(int argc, char *argv[]) {
try
@ -274,8 +274,10 @@ int main(int argc, char *argv[]) {
Uint32 windowFlags = SDL_WINDOW_OPENGL | SDL_WINDOW_SHOWN | SDL_WINDOW_ALLOW_HIGHDPI | SDL_WINDOW_RESIZABLE;
if (ZL::Environment::isFullscreen) {
windowFlags |= SDL_WINDOW_FULLSCREEN_DESKTOP;
// windowFlags |= SDL_WINDOW_FULLSCREEN_DESKTOP;
}
ZL::Environment::isFullscreen = false;
SDL_DisplayMode dm;
if (SDL_GetCurrentDisplayMode(0, &dm) == 0) {

View File

@ -173,6 +173,8 @@ namespace ZL {
"Fragment shader: %s", fragmentShaderFileName.c_str());
#endif
std::cout <<"Loading shader: " << shaderName << " " << vertexShaderFileName << " " << fragmentShaderFileName <<std::endl;
std::string vertexShader;
std::string fragmentShader;

View File

@ -11,6 +11,10 @@ namespace ZL
using std::min;
using std::max;
#endif
#ifdef __linux__
using std::min;
using std::max;
#endif
bool IsPowerOf2(size_t n) {
return n > 0 && (n & (n - 1)) == 0;
@ -533,7 +537,7 @@ namespace ZL
void TextureManager::UnloadByPrefix(const std::string& prefix)
{
for (auto& it = textureMap.begin(); it != textureMap.end(); ) {
for (auto it = textureMap.begin(); it != textureMap.end(); ) {
if (it->first.substr(0, prefix.size()) == prefix) {
std::cout << "Unloading texture with prefix: " << it->first << std::endl;
it = textureMap.erase(it);