Compare commits

..
Author SHA1 Message Date
SirKnightly d344361087 Automated build commit 2026-09-24 10:06:12 +00:00
241 changed files with 2083 additions and 6194 deletions

No files matched your search

+5 -8
View File
@@ -102,7 +102,7 @@ jobs:
strategy:
matrix:
configuration: [FastDebug, Release]
os: [windows-2025, windows-11-arm]
os: [windows-2022, windows-11-arm]
arch: [Win32, x64, ARM64]
simd: [SSE2, ""]
exclude:
@@ -111,8 +111,8 @@ jobs:
- arch: x64
os: windows-11-arm
- arch: ARM64
os: windows-2025
- os: windows-2025
os: windows-2022
- os: windows-2022
simd: ""
- os: windows-11-arm
simd: SSE2
@@ -126,9 +126,6 @@ jobs:
- name: Set workspace as safe
# This appears to be broken in current actions, so do it manually
run: git config --global --add safe.directory "$GITHUB_WORKSPACE"
- name: Install v143 ATL/MFC
shell: pwsh
run: ci/windows/install_v143_atlmfc.ps1
# Tree A: static CRT (/MT) for FSO + FRED2 (no Qt dependency needed)
- name: Configure CMake (static CRT /MT - FSO + FRED2)
env:
@@ -142,7 +139,7 @@ jobs:
cmake -DCMAKE_INSTALL_PREFIX="$(pwd)/install" -DFSO_USE_SPEECH=ON \
-DFSO_USE_VOICEREC=ON -DFORCED_SIMD_INSTRUCTIONS="$SIMD" \
-DFSO_BUILD_TESTS=ON -DFSO_INSTALL_DEBUG_FILES=ON -A "$ARCHITECTURE" \
-DFSO_BUILD_QTFRED=OFF -G "Visual Studio 18 2026" -T "v143" \
-DFSO_BUILD_QTFRED=OFF -G "Visual Studio 17 2022" -T "v143" \
-DCMAKE_BUILD_TYPE=$CONFIGURATION ..
- name: Compile (static CRT)
working-directory: ./build-mt
@@ -171,7 +168,7 @@ jobs:
-DFSO_USE_VOICEREC=ON -DFORCED_SIMD_INSTRUCTIONS="$SIMD" \
-DFSO_BUILD_TESTS=OFF -DFSO_INSTALL_DEBUG_FILES=ON -A "$ARCHITECTURE" \
-DFSO_BUILD_QTFRED=ON -DFSO_BUILD_FRED2=OFF -DQT_USE_PRECOMPILED=ON \
-G "Visual Studio 18 2026" -T "v143" -DCMAKE_BUILD_TYPE=$CONFIGURATION ..
-G "Visual Studio 17 2022" -T "v143" -DCMAKE_BUILD_TYPE=$CONFIGURATION ..
- name: Compile (dynamic CRT)
if: matrix.arch != 'Win32'
working-directory: ./build-md
+5 -8
View File
@@ -152,7 +152,7 @@ jobs:
strategy:
matrix:
configuration: [FastDebug, Release]
os: [windows-2025, windows-11-arm]
os: [windows-2022, windows-11-arm]
arch: [Win32, x64, ARM64]
simd: [SSE2, AVX, ""]
exclude:
@@ -161,8 +161,8 @@ jobs:
- arch: x64
os: windows-11-arm
- arch: ARM64
os: windows-2025
- os: windows-2025
os: windows-2022
- os: windows-2022
simd: ""
- os: windows-11-arm
simd: SSE2
@@ -181,9 +181,6 @@ jobs:
- name: Set workspace as safe
# This appears to be broken in current actions, so do it manually
run: git config --global --add safe.directory "$GITHUB_WORKSPACE"
- name: Install v143 ATL/MFC
shell: pwsh
run: ci/windows/install_v143_atlmfc.ps1
# Tree A: static CRT (/MT) for FSO + FRED2 (no Qt dependency needed)
- name: Configure CMake (static CRT /MT - FSO + FRED2)
env:
@@ -197,7 +194,7 @@ jobs:
cmake -DCMAKE_INSTALL_PREFIX="$(pwd)/install" -DFSO_USE_SPEECH=ON \
-DFSO_USE_VOICEREC=ON -DFORCED_SIMD_INSTRUCTIONS="$SIMD" \
-DFSO_BUILD_TESTS=ON -DFSO_INSTALL_DEBUG_FILES=ON -A "$ARCHITECTURE" \
-DFSO_BUILD_QTFRED=OFF -G "Visual Studio 18 2026" -T "v143" \
-DFSO_BUILD_QTFRED=OFF -G "Visual Studio 17 2022" -T "v143" \
-DCMAKE_BUILD_TYPE=$CONFIGURATION ..
- name: Compile (static CRT)
working-directory: ./build-mt
@@ -226,7 +223,7 @@ jobs:
-DFSO_USE_VOICEREC=ON -DFORCED_SIMD_INSTRUCTIONS="$SIMD" \
-DFSO_BUILD_TESTS=OFF -DFSO_INSTALL_DEBUG_FILES=ON -A "$ARCHITECTURE" \
-DFSO_BUILD_QTFRED=ON -DFSO_BUILD_FRED2=OFF -DQT_USE_PRECOMPILED=ON \
-G "Visual Studio 18 2026" -T "v143" -DCMAKE_BUILD_TYPE=$CONFIGURATION ..
-G "Visual Studio 17 2022" -T "v143" -DCMAKE_BUILD_TYPE=$CONFIGURATION ..
- name: Compile (dynamic CRT)
if: matrix.arch != 'Win32'
working-directory: ./build-md
+4 -7
View File
@@ -109,7 +109,7 @@ jobs:
strategy:
matrix:
configuration: [FastDebug, Release]
os: [windows-2025, windows-11-arm]
os: [windows-2022, windows-11-arm]
arch: [Win32, x64, ARM64]
simd: [SSE2, ""]
exclude:
@@ -118,8 +118,8 @@ jobs:
- arch: x64
os: windows-11-arm
- arch: ARM64
os: windows-2025
- os: windows-2025
os: windows-2022
- os: windows-2022
simd: ""
- os: windows-11-arm
simd: SSE2
@@ -139,9 +139,6 @@ jobs:
[[ "${{ github.ref }}" =~ ^refs\/heads\/test\/(.*)$ ]]
# Override the revision string so that the builds are named correctly
echo "set(FSO_VERSION_REVISION_STR ${BASH_REMATCH[1]})" > "version_override.cmake"
- name: Install v143 ATL/MFC
shell: pwsh
run: ci/windows/install_v143_atlmfc.ps1
- name: Configure CMake
env:
CONFIGURATION: ${{ matrix.configuration }}
@@ -154,7 +151,7 @@ jobs:
cmake -DCMAKE_INSTALL_PREFIX="$(pwd)/install" -DFSO_USE_SPEECH=ON \
-DFSO_USE_VOICEREC=ON -DFORCED_SIMD_INSTRUCTIONS="$SIMD" \
-DFSO_BUILD_TESTS=ON -DFSO_INSTALL_DEBUG_FILES=ON -A "$ARCHITECTURE" \
-DQT_USE_PRECOMPILED=ON -G "Visual Studio 18 2026" -T "v143" \
-DQT_USE_PRECOMPILED=ON -G "Visual Studio 17 2022" -T "v143" \
-DCMAKE_BUILD_TYPE=$CONFIGURATION ..
- name: Compile
working-directory: ./build
+2 -6
View File
@@ -78,7 +78,7 @@ jobs:
compiler: [MSVC]
arch: [Win32, x64]
name: Windows
runs-on: windows-2025
runs-on: windows-2022
steps:
- name: Prepare Environment
run: choco install ninja
@@ -89,10 +89,6 @@ jobs:
- name: Set workspace as safe
# This appears to be broken in current actions, so do it manually
run: git config --global --add safe.directory "$GITHUB_WORKSPACE"
- name: Install v143 ATL/MFC
if: matrix.compiler == 'MSVC'
shell: pwsh
run: ci/windows/install_v143_atlmfc.ps1
- name: Configure CMake
env:
CONFIGURATION: ${{ matrix.configuration }}
@@ -108,7 +104,7 @@ jobs:
-DFSO_BUILD_FRED2=OFF -DQT_USE_PRECOMPILED=ON -DCMAKE_BUILD_TYPE=$CONFIGURATION -G "Ninja" ..
else
cmake -DFSO_USE_SPEECH=ON -DFSO_FATAL_WARNINGS=ON -DFSO_USE_VOICEREC=OFF -DFSO_BUILD_TESTS=ON \
-DFORCED_SIMD_INSTRUCTIONS=SSE2 -G "Visual Studio 18 2026" -T "v143" -A "$ARCHITECTURE" \
-DFORCED_SIMD_INSTRUCTIONS=SSE2 -G "Visual Studio 17 2022" -T "v143" -A "$ARCHITECTURE" \
-DQT_USE_PRECOMPILED=ON -DCMAKE_BUILD_TYPE=$CONFIGURATION ..
fi
- name: Compile
+15 -34
View File
@@ -29,43 +29,24 @@ ENDIF(NOT DEFINED CMAKE_INSTALL_PREFIX)
SET(TARGET_COPY_FILES "" CACHE INTERNAL "" FORCE)
SET(TARGET_COPY_DIRS "" CACHE INTERNAL "" FORCE)
get_property(is_multi_config GLOBAL PROPERTY GENERATOR_IS_MULTI_CONFIG)
# Override standard CMake configurations
set(FSO_BUILD_TYPES Debug Release FastDebug)
if(is_multi_config)
set(CMAKE_CONFIGURATION_TYPES "${FSO_BUILD_TYPES}" CACHE STRING "Configuration types" FORCE)
elseif(NOT CMAKE_BUILD_TYPE)
### Define options and editable variables in the section below:
# This is only needed for single configuration generators so don't annoy others
if(NOT CMAKE_BUILD_TYPE AND NOT DEFINED CMAKE_CONFIGURATION_TYPES)
set(CMAKE_BUILD_TYPE "Release" CACHE STRING "Default build configuration used." FORCE)
message(WARNING "CMAKE_BUILD_TYPE was not specified, defaulting to Release configuration.")
set_property(CACHE CMAKE_BUILD_TYPE PROPERTY STRINGS "${FSO_BUILD_TYPES}")
endif()
endif(NOT CMAKE_BUILD_TYPE AND NOT DEFINED CMAKE_CONFIGURATION_TYPES)
# Override standard CMake configurations
set(CMAKE_CONFIGURATION_TYPES Debug Release FastDebug CACHE STRING "Available configurations" FORCE)
set(FSO_LANGUAGES C CXX)
if(APPLE)
set(FSO_LANGUAGES ${FSO_LANGUAGES} OBJC OBJCXX)
# 10.15 for c++17 std::filesystem
# NOTE: this must be set *before* the project() call to work properly!!
set(CMAKE_OSX_DEPLOYMENT_TARGET "10.15" CACHE STRING "macOS deployment target")
# fix all targets in scheme (so it's not just qtfred)
set(CMAKE_XCODE_GENERATE_SCHEME TRUE)
endif()
PROJECT(FS2_Open LANGUAGES ${FSO_LANGUAGES})
if (ANDROID)
message(STATUS "Building for Android (NDK)")
set(FSO_BUILD_INCLUDED_LIBS ON CACHE BOOL "" FORCE)
set(USING_PREBUILT_LIBS ON CACHE BOOL "" FORCE)
set(SDL3_USE_PRECOMPILED ON CACHE BOOL "" FORCE)
set(OPENAL_USE_PRECOMPILED ON CACHE BOOL "" FORCE)
set(USING_PREBUILT_VULKAN ON CACHE BOOL "" FORCE)
endif()
# Check if the external modules exists
IF(NOT IS_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}/lib/libRocket/Build")
message(FATAL_ERROR "External submodules could not be found. Please make sure you have updated your submodules.")
@@ -118,8 +99,8 @@ OPTION(FSO_BUILD_TESTS "Build unit tests" OFF)
OPTION(FSO_DEVELOPMENT_MODE "Generate binaries in development mode, only use if you know what you're doing!" OFF)
IF(WIN32 OR APPLE OR ANDROID)
# On windows, mac and android the default should be to always build the included libraries
IF(WIN32 OR APPLE)
# On windows and mac the default should be to always build the included libraries
SET(FSO_BUILD_INCLUDED_LIBS_DEFAULT ON)
ELSE()
SET(FSO_BUILD_INCLUDED_LIBS_DEFAULT OFF)
@@ -147,13 +128,13 @@ OPTION(FSO_BUILD_WITH_DISCORD "Build with Discord support" ON)
OPTION(FSO_BUILD_WITH_OPENGL "Enable compilation of the OpenGL renderer" ON)
OPTION(FSO_BUILD_WITH_OPENGL_DEBUG "Enables debug option for OpenGL" OFF)
OPTION(FSO_BUILD_WITH_OPENGL_ES "When building OpenGL, use OpenGL ES compatibility layer" OFF)
OPTION(FSO_BUILD_WITH_OPENGL_ES "When building OpenGL, use OpenGL ES compatibility layer (External shaders only!)" OFF)
OPTION(FSO_BUILD_WITH_VULKAN "Enable compilation of the Vulkan renderer" ON)
if(NOT FSO_BUILD_WITH_OPENGL AND FSO_BUILD_WITH_OPENGL_ES)
# Disable GLES if not building with OpenGL
set(FSO_BUILD_WITH_OPENGL_ES OFF CACHE BOOL "" FORCE)
set(FSO_BUILD_WITH_OPENGL_ES OFF FORCE)
endif()
@@ -215,11 +196,11 @@ include(clang-tidy)
include(CheckIPOSupported)
check_ipo_supported(RESULT LTO_AVAILABLE)
if (FSO_USE_LTO AND LTO_AVAILABLE)
if (CMAKE_BUILD_TYPE STREQUAL "Release" AND FSO_USE_LTO AND LTO_AVAILABLE)
set(CMAKE_POLICY_DEFAULT_CMP0069 NEW)
message("Enabled LTO for Release builds")
set(CMAKE_INTERPROCEDURAL_OPTIMIZATION_RELEASE TRUE)
endif (FSO_USE_LTO AND LTO_AVAILABLE)
message("Enabled LTO")
set(CMAKE_INTERPROCEDURAL_OPTIMIZATION TRUE)
endif (CMAKE_BUILD_TYPE STREQUAL "Release" AND FSO_USE_LTO AND LTO_AVAILABLE)
# This includes source code for some tools, either used in the build or also for something else
ADD_SUBDIRECTORY(tools)
+1 -1
View File
@@ -1,3 +1,3 @@
Mako==1.4.2
Mako==1.3.12
requests==2.33.0
semantic-version==2.8.5
-34
View File
@@ -1,34 +0,0 @@
# Installs ATL and MFC for the v143 toolset, which the Visual Studio 2026 runner images
# only ship for the latest toolset. ATL is needed by SAPI speech (sphelper.h) and MFC by FRED2.
$ErrorActionPreference = 'Stop'
$msvcVersion = '14.44'
$component = 'Microsoft.VisualStudio.Component.VC.14.44.17.14'
$suffix = if ($env:RUNNER_ARCH -eq 'ARM64') { '.ARM64' } else { '' }
$installerDir = "${env:ProgramFiles(x86)}\Microsoft Visual Studio\Installer"
$installPath = & "$installerDir\vswhere.exe" -version '[18.0,19.0)' -latest -property installationPath
if (-not $installPath) {
Write-Error 'Visual Studio 2026 was not found'
}
$arguments = @(
'/c', 'vs_installer.exe', 'modify',
'--installPath', "`"$installPath`"",
'--add', "$component.ATL$suffix",
'--add', "$component.MFC$suffix",
'--quiet', '--norestart', '--nocache'
)
$process = Start-Process -FilePath cmd.exe -ArgumentList $arguments -WorkingDirectory $installerDir -Wait -PassThru -NoNewWindow
# 3010 = success, reboot required
if ($process.ExitCode -notin 0, 3010) {
Write-Error "vs_installer exited with code $($process.ExitCode)"
}
# fail here rather than with a confusing compile error if the components didn't install
foreach ($header in 'atlbase.h', 'afxwin.h') {
if (-not (Test-Path "$installPath\VC\Tools\MSVC\$msvcVersion.*\atlmfc\include\$header")) {
Write-Error "$header for MSVC $msvcVersion is missing after install"
}
}
+4
View File
@@ -11,6 +11,10 @@ endif()
target_link_libraries(platform INTERFACE ${COCOA_LIBRARY})
# To support C++17 we need to target at least 10.13. maybe 10.14 for some rare features
# bump to 10.15 for c++17 std::filesystem usage in qtFRED
SET(CMAKE_OSX_DEPLOYMENT_TARGET "10.15")
SET(CMAKE_SKIP_RPATH FALSE)
SET(CMAKE_BUILD_WITH_INSTALL_RPATH TRUE)
SET(CMAKE_INSTALL_RPATH @loader_path/../Frameworks/)
+4 -11
View File
@@ -13,13 +13,6 @@ option(MSVC_RELEASE_DEBUGGING "Set options that allow to debug release builds" O
MARK_AS_ADVANCED(FORCE MSVC_USE_RUNTIME_DLL)
MARK_AS_ADVANCED(FORCE MSVC_RELEASE_DEBUGGING)
# Qt is only available as DLL-runtime builds, so qtFRED forces the DLL runtime for the whole tree
if(MSVC_USE_RUNTIME_DLL OR FSO_BUILD_QTFRED)
set(FSO_MSVC_RUNTIME_DLL ON)
else()
set(FSO_MSVC_RUNTIME_DLL OFF)
endif()
# These are the warnings we disable
set(WARNING_FLAGS
/wd4100 # unreferenced formal parameters
@@ -78,12 +71,12 @@ if (MSVC_RELEASE_DEBUGGING)
endif()
endif()
# The debug runtime is not redistributable (statically linked or not), so only Debug may use it
IF(FSO_MSVC_RUNTIME_DLL)
set(CMAKE_MSVC_RUNTIME_LIBRARY "MultiThreaded$<$<CONFIG:Debug>:Debug>DLL")
# This should be kept in sync with the corresponding IF() in fred2/CMakeLists.txt
IF(MSVC_USE_RUNTIME_DLL OR FSO_BUILD_QTFRED)
set(CMAKE_MSVC_RUNTIME_LIBRARY "MultiThreaded$<$<NOT:$<CONFIG:Release>>:Debug>DLL")
add_compile_definitions(_AFXDLL)
ELSE()
set(CMAKE_MSVC_RUNTIME_LIBRARY "MultiThreaded$<$<CONFIG:Debug>:Debug>")
set(CMAKE_MSVC_RUNTIME_LIBRARY "MultiThreaded$<$<NOT:$<CONFIG:Release>>:Debug>")
ENDIF()
# Debug
+10 -7
View File
@@ -3,13 +3,7 @@
add_library(compiler INTERFACE)
set(FSO_CONFIG_DEFINITIONS "$<$<CONFIG:Release>:NDEBUG>" "$<$<CONFIG:Debug>:_DEBUG>")
if(NOT MSVC)
# On MSVC the debug runtime flags (/MTd, /MDd) define _DEBUG themselves, and a FastDebug
# build on the release runtime must not have it
list(APPEND FSO_CONFIG_DEFINITIONS "$<$<CONFIG:FastDebug>:_DEBUG>")
endif()
target_compile_definitions(compiler INTERFACE ${FSO_CONFIG_DEFINITIONS})
target_compile_definitions(compiler INTERFACE "$<$<CONFIG:Release>:NDEBUG>;$<$<CONFIG:Debug>:_DEBUG>;$<$<CONFIG:FastDebug>:_DEBUG>")
set(FORCED_NATIVE_SIMD_INSTRUCTIONS ON CACHE BOOL "Override instruction set detection and compile with the maximum possible instructions for the current system.")
IF(IS_X86)
@@ -80,3 +74,12 @@ set(CMAKE_C_FLAGS_FASTDEBUG "${CMAKE_C_FLAGS_RELEASE}")
set(CMAKE_CXX_FLAGS_FASTDEBUG "${CMAKE_CXX_FLAGS_RELEASE}")
set(CMAKE_EXE_LINKER_FLAGS_FASTDEBUG "${CMAKE_EXE_LINKER_FLAGS_RELEASE}")
set(CMAKE_STATIC_LINKER_FLAGS_FASTDEBUG "${CMAKE_STATIC_LINKER_FLAGS_RELEASE}")
if (MSVC)
# Adjust runtime library
string(REPLACE "/MD" "/MDd" CMAKE_C_FLAGS_FASTDEBUG "${CMAKE_C_FLAGS_FASTDEBUG}")
string(REPLACE "/MT" "/MTd" CMAKE_C_FLAGS_FASTDEBUG "${CMAKE_C_FLAGS_FASTDEBUG}")
string(REPLACE "/MD" "/MDd" CMAKE_CXX_FLAGS_FASTDEBUG "${CMAKE_CXX_FLAGS_FASTDEBUG}")
string(REPLACE "/MT" "/MTd" CMAKE_CXX_FLAGS_FASTDEBUG "${CMAKE_CXX_FLAGS_FASTDEBUG}")
endif()
-11
View File
@@ -241,17 +241,6 @@ function(suppress_file_warnings)
endif()
endfunction(suppress_file_warnings)
# Suppress no symbols warnings in static libraries (on Xcode)
function(suppress_no_symbol_warnings _target)
if(XCODE)
get_target_property(target_type ${_target} TYPE)
if(target_type STREQUAL "STATIC_LIBRARY")
set_property(TARGET ${_target} APPEND PROPERTY
STATIC_LIBRARY_OPTIONS "-no_warning_for_no_symbols"
)
endif()
endif()
endfunction(suppress_no_symbol_warnings)
function(list_target_dependencies _target _out_var)
set(out_list)
+1 -1
View File
@@ -7,7 +7,7 @@ if (EXISTS "${PROJECT_SOURCE_DIR}/version_override.cmake")
endif()
set_if_not_defined(FSO_VERSION_MAJOR 26)
set_if_not_defined(FSO_VERSION_MINOR 3)
set_if_not_defined(FSO_VERSION_MINOR 1)
set_if_not_defined(FSO_VERSION_BUILD 0)
# A numeric revision e.g. the CI build number
-3
View File
@@ -130,8 +130,5 @@ set_target_properties(code PROPERTIES XCODE_ATTRIBUTE_COPY_PHASE_STRIP[variant=D
set_target_properties(code PROPERTIES XCODE_ATTRIBUTE_STRIP_INSTALLED_PRODUCT[variant=Debug] "NO")
set_target_properties(code PROPERTIES XCODE_ATTRIBUTE_GCC_SYMBOLS_PRIVATE_EXTERN[variant=Debug] "NO")
# Prevent warnings on files with no symbols on Mac
suppress_no_symbol_warnings(code)
# Prevent GCC warnings in third-party BitOp... see GitHub #4366
suppress_file_warnings(scripting/lua/bitop/bit.c)
+2 -6
View File
@@ -295,7 +295,6 @@ typedef struct ai_info {
vec3d path_create_pos; // Object's position at time of global path creation.
matrix path_create_orient; // Object's orientation at time of global path creation.
int mp_index; // Model path index. Index in polymodel:model_paths
int mp_randomized_vert; // Vertex of the model path that was given a random offset, or -1
fix path_next_check_time; // Last time checked to see if would collide with model.
int path_goal_dist; // minimum distance to first path point to consider path reached
int path_subsystem_next_check; // timestamp to next check if subsystem is still visible
@@ -535,7 +534,6 @@ extern void ai_ignore_wing(object *ignorer, int wingnum);
extern void ai_dock_with_object(object *docker, int docker_index, object *dockee, int dockee_index, int dock_type);
extern void ai_stay_still(object *still_objp, vec3d *view_pos);
extern void ai_do_default_behavior(object *obj);
extern void ai_reset_order_state(ai_info *aip);
extern void ai_start_waypoints(object *objp, int wl_index, int wp_flags, int start_index, bool force = false);
extern void ai_ship_hit(object *objp_ship, object *hit_objp, const vec3d *hit_normal);
extern void ai_ship_destroy(int shipnum);
@@ -598,9 +596,7 @@ extern int ai_maybe_fire_afterburner(object *objp, ai_info *aip);
extern void set_predicted_enemy_pos(vec3d *predicted_enemy_pos, object *pobjp, vec3d *enemy_pos, vec3d *enemy_vel, ai_info *aip);
extern int is_instructor(object *objp);
extern int find_enemy(int objnum, float range, int max_attackers, bool for_pursuit, int ship_info_index = -1, int class_type = -1);
extern bool ai_targets_for_pursuit(const ai_info *aip);
extern bool ai_declines_pursuit(const object *attacker_objp, const object *target_objp);
extern int find_enemy(int objnum, float range, int max_attackers, int ship_info_index = -1, int class_type = -1);
float ai_get_weapon_speed(const ship_weapon *swp);
void set_predicted_enemy_pos_turret(vec3d *predicted_enemy_pos, const vec3d *gun_pos, const object *pobjp, const vec3d *enemy_pos, const vec3d *enemy_vel, float weapon_speed, float time_enemy_in_range);
@@ -621,7 +617,7 @@ extern float dock_orient_and_approach(object *docker_objp, int docker_index, obj
void ai_set_mode_warp_out(object *objp, ai_info *aip);
// prototyped by Goober5000
int get_nearest_objnum(int objnum, int enemy_team_mask, int enemy_wing, float range, int max_attackers, bool for_pursuit, int ship_info_index, int class_type = -1);
int get_nearest_objnum(int objnum, int enemy_team_mask, int enemy_wing, float range, int max_attackers, int ship_info_index, int class_type = -1);
// moved to header file by Goober5000
void ai_announce_ship_dying(object *dying_objp);
+2 -10
View File
@@ -178,10 +178,8 @@ namespace AI {
Fix_standard_strafe,
Fix_ai_target_recovery, // a) strafing ships that lose their target re-process their orders, like chasing ships already do
// b) ships parked in AIM_NONE while holding a standing chase order (attack-any etc.) re-process their orders;
// c) target selection for pursuit (chasing, guard reactions, retaliation) skips ships outside the attacker's
// actively-pursues list; targets held while not chasing are unaffected, and explicitly ordered targets are
// still assigned but not chased or strafed;
// d) enemy_wing is reset when a new order takes over (shared with Fix_stale_ai_order_state)
// c) target selection skips ships outside the attacker's actively-pursues list, and self-chosen targets
// outside that list are dropped rather than held forever
Standard_strafe_used_more,
Unify_usage_ai_shield_manage_delay,
Fix_AI_shield_management_bug,
@@ -202,12 +200,6 @@ namespace AI {
// b) completion no longer requires moving 0.1m in a single frame (framerate-dependent)
Fix_shockwave_expire_before_do_damage, // shockwaves whose lifetime is shorter than one frame apply their area damage at least once before expiring
Fix_small_ai_recover_after_engines_repaired, // ensure small ship AI can switch back to useful AI modes if engines get repaired
Fix_model_path_refresh_randomization, // a subsystem path keeps its randomized point when the path is refreshed because the target moved
Fix_bay_speed_ramp, // the fighterbay speed ramp covers only the bay path itself, not points that route a departing ship around the carrier, and never exceeds max speed
Fix_stale_ai_order_state, // a) enemy_wing, guard_*, previous_mode, resume_goal_time, and the targeted subsystem (with its path) are reset when a new order takes over (enemy_wing is also reset under Fix_ai_target_recovery);
// b) a dynamic chase saves previous_mode/previous_submode; it and strafe entry leave them alone during an ongoing dynamic goal (evading a weapon still overwrites them, which is harmless since the evade resume re-processes orders);
// c) resuming guard duty discards any subsystem target and path left over from the interruption;
// d) a ship ordered to guard itself, or to guard a wing it leads (including one that becomes leader mid-mission), treats that goal as unachievable instead of holding it forever
NUM_VALUES
};
+7 -16
View File
@@ -140,7 +140,7 @@ void parse_ai_profiles_tbl(const char *filename)
// don't create multiple profiles with the same name
if (previous_profile != NULL)
{
Warning(LOCATION, "An AI profile named '%s' already exists! The new one will not be created.\n", profile_name);
Warning(LOCATION, "An ai profile named '%s' already exists! The new one will not be created.\n", profile_name);
}
else
{
@@ -412,7 +412,7 @@ void parse_ai_profiles_tbl(const char *filename)
set_flag(profile, "$disable player secondary doublefire:", AI::Profile_Flags::Disable_player_secondary_doublefire);
set_flag(profile, "$disable AI secondary doublefire:", AI::Profile_Flags::Disable_ai_secondary_doublefire);
set_flag(profile, "$disable ai secondary doublefire:", AI::Profile_Flags::Disable_ai_secondary_doublefire);
set_flag(profile, "$disable weapon damage scaling:", AI::Profile_Flags::Disable_weapon_damage_scaling);
@@ -450,7 +450,7 @@ void parse_ai_profiles_tbl(const char *filename)
set_flag(profile, "$force beam turrets to use normal fov:", AI::Profile_Flags::Force_beam_turret_fov);
set_flag(profile, "$fix AI class bug:", AI::Profile_Flags::Fix_ai_class_bug);
set_flag(profile, "$fix ai class bug:", AI::Profile_Flags::Fix_ai_class_bug);
set_flag(profile, "$turrets ignore targets radius in range checks:", AI::Profile_Flags::Turrets_ignore_target_radius);
@@ -505,13 +505,13 @@ void parse_ai_profiles_tbl(const char *filename)
profile->ai_path_mode = j;
}
else {
Warning(LOCATION, "Invalid AI path mode '%s' specified", buf);
Warning(LOCATION, "Invalid ai path mode '%s' specified", buf);
}
}
set_flag(profile, "$no warp camera:", AI::Profile_Flags::No_warp_camera);
set_flag(profile, "$fix AI path order bug:", AI::Profile_Flags::Fix_ai_path_order_bug);
set_flag(profile, "$fix ai path order bug:", AI::Profile_Flags::Fix_ai_path_order_bug);
set_flag(profile, "$strict turret-tagged-only targeting:", AI::Profile_Flags::Strict_turret_tagged_only_targeting);
@@ -622,7 +622,7 @@ void parse_ai_profiles_tbl(const char *filename)
profile->ai_range_aware_secondary_select_mode = j;
}
else {
Warning(LOCATION, "Invalid AI secondary range awareness mode '%s' specified", buf);
Warning(LOCATION, "Invalid ai secondary range awareness mode '%s' specified", buf);
}
}
@@ -677,7 +677,7 @@ void parse_ai_profiles_tbl(const char *filename)
set_flag(profile, "$fix standard strafe:", AI::Profile_Flags::Fix_standard_strafe);
set_flag(profile, "$fix AI target recovery:", AI::Profile_Flags::Fix_ai_target_recovery);
set_flag(profile, "$fix ai target recovery:", AI::Profile_Flags::Fix_ai_target_recovery);
set_flag(profile, "$standard strafe used more:", AI::Profile_Flags::Standard_strafe_used_more);
@@ -767,12 +767,6 @@ void parse_ai_profiles_tbl(const char *filename)
set_flag(profile, "$fix fighter/bomber AI recovers after engines repaired:", AI::Profile_Flags::Fix_small_ai_recover_after_engines_repaired);
set_flag(profile, "$fix subsystem path randomization on refresh:", AI::Profile_Flags::Fix_model_path_refresh_randomization);
set_flag(profile, "$fix fighterbay speed ramp:", AI::Profile_Flags::Fix_bay_speed_ramp);
set_flag(profile, "$fix stale AI order state:", AI::Profile_Flags::Fix_stale_ai_order_state);
// end of options ----------------------------------------
// if we've been through once already and are at the same place, force a move
@@ -1007,8 +1001,5 @@ void ai_profile_t::reset()
flags.set(AI::Profile_Flags::Fix_small_ai_recover_after_engines_repaired);
flags.set(AI::Profile_Flags::Fix_standard_strafe);
flags.set(AI::Profile_Flags::Fix_ai_target_recovery);
flags.set(AI::Profile_Flags::Fix_model_path_refresh_randomization);
flags.set(AI::Profile_Flags::Fix_bay_speed_ramp);
flags.set(AI::Profile_Flags::Fix_stale_ai_order_state);
}
}
+12 -22
View File
@@ -66,16 +66,6 @@ static bool ai_big_strafe_maybe_retreat(const vec3d *target_pos);
extern void compute_desired_rvec(vec3d *rvec, const vec3d *goal_pos, const vec3d *cur_pos);
extern void big_ship_collide_recover_start(const object *objp, const object *big_objp, const vec3d *collision_normal);
// Record the mode being left as the one to return to, unless a dynamic goal is already in progress
// (in which case previous_mode still refers to the mode that goal interrupted).
static void ai_big_save_previous_mode(ai_info *aip)
{
if (The_mission.ai_profile->flags[AI::Profile_Flags::Fix_stale_ai_order_state] && aip->active_goal == AI_ACTIVE_GOAL_DYNAMIC)
return;
aip->previous_mode = aip->mode;
}
// Called by ai_big_pick_attack_point.
// Generates a random attack point.
@@ -509,7 +499,7 @@ bool ai_big_maybe_follow_subsys_path(bool do_dot_check)
// for now, only follow the path to the first point
if ( aip->path_cur < (aip->path_start+aip->path_length-1) ) {
if ( aip->goal_objnum != aip->target_objnum ) {
ai_big_save_previous_mode(aip);
aip->previous_mode = aip->mode;
aip->mode = AIM_NONE;
aip->submode = -1;
aip->submode_start_time = Missiontime;
@@ -716,8 +706,7 @@ void ai_big_chase_attack(ai_info *aip, ship_info *sip, vec3d *enemy_pos, float d
if (vm_vec_dot(&in_vec, &objp->orient.vec.fvec) > 0.0f) {
dist = vm_vec_normalize(&in_vec);
if ((dist < 200.0f) && (vm_vec_dot(&in_vec, &objp->orient.vec.fvec) > 0.95f)) {
if ((Objects[objp->parent].signature == objp->parent_sig) && (vm_vec_dist_quick(&objp->pos, &Objects[objp->parent].pos) < 300.0f)
&& !ai_declines_pursuit(Pl_objp, &Objects[objp->parent])) {
if ((Objects[objp->parent].signature == objp->parent_sig) && (vm_vec_dist_quick(&objp->pos, &Objects[objp->parent].pos) < 300.0f)) {
set_target_objnum(aip, objp->parent);
aip->submode = SM_ATTACK;
aip->submode_start_time = Missiontime;
@@ -738,7 +727,7 @@ void ai_big_chase_attack(ai_info *aip, ship_info *sip, vec3d *enemy_pos, float d
// including ai_profile flag and if enemy fighters are near
if (Pl_objp->phys_info.speed < The_mission.ai_profile->standard_strafe_when_below_speed &&
(The_mission.ai_profile->flags[AI::Profile_Flags::Standard_strafe_used_more] || ai_big_maybe_start_strafe(aip, sip))) {
ai_big_save_previous_mode(aip);
aip->previous_mode = aip->mode;
aip->mode = AIM_STRAFE;
aip->submode_parm0 = Missiontime; // use parm0 as time strafe mode entered (i.e. MODE start time)
ai_big_strafe_position();
@@ -747,7 +736,7 @@ void ai_big_chase_attack(ai_info *aip, ship_info *sip, vec3d *enemy_pos, float d
//Maybe enter glide strafe (check every 8 seconds, on a different schedule for each ship)
if ((sip->can_glide == true) && !(aip->ai_flags[AI::AI_Flags::Kamikaze]) && static_randf((Missiontime + static_rand(aip->shipnum)) >> 19) < aip->ai_glide_strafe_percent) {
ai_big_save_previous_mode(aip);
aip->previous_mode = aip->mode;
aip->mode = AIM_STRAFE;
aip->submode_parm0 = Missiontime; // use parm0 as time strafe mode entered (i.e. MODE start time)
aip->submode = AIS_STRAFE_GLIDE_ATTACK;
@@ -1019,7 +1008,7 @@ static void ai_big_maybe_fire_weapons(float dist_to_enemy, float dot_to_enemy)
// switch ai ship into chase mode
void ai_big_switch_to_chase_mode(ai_info *aip)
{
ai_big_save_previous_mode(aip);
aip->previous_mode = aip->mode;
aip->mode = AIM_CHASE;
aip->submode = SM_ATTACK;
aip->submode_start_time = Missiontime;
@@ -1119,7 +1108,7 @@ void ai_big_chase()
} else if (En_objp->flags[Object::Object_Flags::Protected]) { // If protected and we're not attacking a subsystem, stop attacking!
update_aspect_lock_information(aip, &vec_to_enemy, dist_to_enemy - En_objp->radius, En_objp->radius);
aip->target_objnum = -1;
if (find_enemy(OBJ_INDEX(Pl_objp), MAX_ENEMY_DISTANCE, The_mission.ai_profile->max_attackers[Game_skill_level], ai_targets_for_pursuit(aip)) == -1) {
if (find_enemy(OBJ_INDEX(Pl_objp), MAX_ENEMY_DISTANCE, The_mission.ai_profile->max_attackers[Game_skill_level]) == -1) {
ai_do_default_behavior(Pl_objp);
return;
}
@@ -1979,25 +1968,26 @@ int ai_big_maybe_enter_strafe_mode(const object *pl_objp, int weapon_objnum)
return 0;
}
if (ai_declines_pursuit(pl_objp, parent_objp)) {
return 0;
}
// Maybe the ship which fired the weapon isn't the current target
if ( OBJ_INDEX(parent_objp) != aip->target_objnum ) {
//JAS IMPOSSIBLE if (1) { // consider_target_only ) {
//JAS IMPOSSIBLE return 0;
//JAS IMPOSSIBLE } else {
// switch targets
sip = &Ship_info[Ships[parent_objp->instance].ship_info_index];
if ( !(sip->is_big_or_huge()) || (sip->flags[Ship::Info_Flags::Transport]) ) {
return 0;
}
set_target_objnum(aip, OBJ_INDEX(parent_objp));
//JAS IMPOSSIBLE }
}
ai_big_strafe_maybe_attack_turret(pl_objp, weapon_objp);
// if we've got this far, the weapon must have come from the player's target, and it is a
// big/capital ship... so enter strafe mode
ai_big_save_previous_mode(aip);
aip->previous_mode = aip->mode;
aip->mode = AIM_STRAFE;
aip->submode_parm0 = Missiontime; // use parm0 as time strafe mode entered (i.e. MODE start time)
aip->submode = AIS_STRAFE_AVOID;
+42 -136
View File
@@ -2215,35 +2215,16 @@ static bool ai_class_type_actively_pursues(int attacker_class_type, int target_c
return std::any_of(pursues.begin(), pursues.end(), [target_class_type](int pursued_type) { return pursued_type == target_class_type; });
}
// Returns true if a target this ship picks for itself will be used for pursuit, and therefore applicable to the "actively_pursues" check.
// In other modes a ship's target is held for its turrets, and is also read by other ships (guard reactions, attacker counts).
bool ai_targets_for_pursuit(const ai_info *aip)
{
return aip->mode == AIM_CHASE || aip->mode == AIM_STRAFE;
}
// Returns true if attacker_objp should not pick target_objp as a target to pursue.
bool ai_declines_pursuit(const object *attacker_objp, const object *target_objp)
{
Assertion(attacker_objp->type == OBJ_SHIP, "ai_declines_pursuit() was called with an attacker of object type %d; it must be a ship!", attacker_objp->type);
if (!The_mission.ai_profile->flags[AI::Profile_Flags::Fix_ai_target_recovery] || target_objp->type != OBJ_SHIP)
return false;
return !ai_class_type_actively_pursues(Ship_info[Ships[attacker_objp->instance].ship_info_index].class_type,
Ship_info[Ships[target_objp->instance].ship_info_index].class_type);
}
typedef struct eval_nearest_objnum {
int objnum;
object *trial_objp;
int enemy_team_mask;
int enemy_ship_info_index;
int enemy_class_type;
int attacker_class_type;
int enemy_wing;
float range;
int max_attackers;
bool for_pursuit;
int nearest_objnum;
float nearest_dist;
int check_danger_weapon_objnum;
@@ -2299,10 +2280,11 @@ void evaluate_object_as_nearest_objnum(eval_nearest_objnum *eno)
float dist;
int num_attacking;
// If pursuing, don't pick a target that this ship's type refuses to pursue, or it will park in AIM_NONE holding a target it never attacks.
// Don't pick a target that this ship's type refuses to chase, or it will park in AIM_NONE holding a target it never attacks.
// Only for unconstrained searches: an explicit chase-ship-class/type order should still produce a target even if ai_chase() doesn't chase it.
if (eno->for_pursuit && eno->enemy_ship_info_index < 0 && eno->enemy_class_type < 0
&& ai_declines_pursuit(&Objects[eno->objnum], eno->trial_objp))
if (The_mission.ai_profile->flags[AI::Profile_Flags::Fix_ai_target_recovery]
&& eno->enemy_ship_info_index < 0 && eno->enemy_class_type < 0
&& !ai_class_type_actively_pursues(eno->attacker_class_type, Ship_info[shipp->ship_info_index].class_type))
return;
// Allow targeting of stealth in nebula by his firing at me
@@ -2370,11 +2352,10 @@ void evaluate_object_as_nearest_objnum(eval_nearest_objnum *eno)
* @param enemy_wing Enemy wing chosen
* @param range Ship must be within range "range".
* @param max_attackers Don't attack a ship that already has at least max_attackers attacking it.
* @param for_pursuit True if the ship will chase the enemy found; false if the target is only held (e.g. for turrets)
* @param ship_info_index If >=0, the enemy object must be of the specified ship class
* @param class_type If >=0, the enemy object must be of the specified ship type
*/
int get_nearest_objnum(int objnum, int enemy_team_mask, int enemy_wing, float range, int max_attackers, bool for_pursuit, int ship_info_index, int class_type)
int get_nearest_objnum(int objnum, int enemy_team_mask, int enemy_wing, float range, int max_attackers, int ship_info_index, int class_type)
{
object *danger_weapon_objp;
ai_info *aip;
@@ -2385,9 +2366,9 @@ int get_nearest_objnum(int objnum, int enemy_team_mask, int enemy_wing, float ra
eno.enemy_team_mask = enemy_team_mask;
eno.enemy_ship_info_index = ship_info_index;
eno.enemy_class_type = class_type;
eno.attacker_class_type = Ship_info[Ships[Objects[objnum].instance].ship_info_index].class_type;
eno.enemy_wing = enemy_wing;
eno.max_attackers = max_attackers;
eno.for_pursuit = for_pursuit;
eno.objnum = objnum;
eno.range = range;
eno.nearest_dist = range;
@@ -2428,17 +2409,10 @@ int get_nearest_objnum(int objnum, int enemy_team_mask, int enemy_wing, float ra
}
}
// If no wing member can be pursued, hold one anyway rather than leave the wing, as an explicit order to attack an unpursued ship does
if ((eno.nearest_objnum == -1) && (enemy_wing != -1) && for_pursuit && The_mission.ai_profile->flags[AI::Profile_Flags::Fix_ai_target_recovery]) {
int held_objnum = get_nearest_objnum(objnum, enemy_team_mask, enemy_wing, range, max_attackers, false, ship_info_index, class_type);
if (held_objnum >= 0 && Objects[held_objnum].type == OBJ_SHIP && Ships[Objects[held_objnum].instance].wingnum == enemy_wing)
return held_objnum;
}
// If only looking for target in certain wing and couldn't find anything in
// that wing, look for any object.
if ((eno.nearest_objnum == -1) && (enemy_wing != -1)) {
return get_nearest_objnum(objnum, enemy_team_mask, -1, range, max_attackers, for_pursuit, ship_info_index, class_type);
return get_nearest_objnum(objnum, enemy_team_mask, -1, range, max_attackers, ship_info_index, class_type);
}
return eno.nearest_objnum;
@@ -2545,11 +2519,10 @@ int get_enemy_timestamp()
* @param objnum Object number
* @param range Range within which to look
* @param max_attackers Don't attack a ship that already has at least max_attackers attacking it.
* @param for_pursuit True if the ship will chase the enemy found; false if the target is only held (e.g. for turrets)
* @param ship_info_index If specified, restrict the search to enemies with this ship class
* @param class_type If specified, restrict the search to enemies with this ship type
*/
int find_enemy(int objnum, float range, int max_attackers, bool for_pursuit, int ship_info_index, int class_type)
int find_enemy(int objnum, float range, int max_attackers, int ship_info_index, int class_type)
{
int enemy_team_mask;
@@ -2579,7 +2552,10 @@ int find_enemy(int objnum, float range, int max_attackers, bool for_pursuit, int
if (class_type < 0 || class_type == Ship_info[target_shipp->ship_info_index].class_type) {
if (!(target_objp->flags[Object::Object_Flags::Protected])) {
// same as get_nearest_objnum: only skip an unpursued target for unconstrained searches
if (!for_pursuit || ship_info_index >= 0 || class_type >= 0 || !ai_declines_pursuit(objp, target_objp)) {
if (!The_mission.ai_profile->flags[AI::Profile_Flags::Fix_ai_target_recovery]
|| ship_info_index >= 0 || class_type >= 0
|| ai_class_type_actively_pursues(Ship_info[shipp->ship_info_index].class_type,
Ship_info[target_shipp->ship_info_index].class_type)) {
return target_objnum;
}
}
@@ -2592,7 +2568,7 @@ int find_enemy(int objnum, float range, int max_attackers, bool for_pursuit, int
}
}
return get_nearest_objnum(objnum, enemy_team_mask, aip->enemy_wing, range, max_attackers, for_pursuit, ship_info_index, class_type);
return get_nearest_objnum(objnum, enemy_team_mask, aip->enemy_wing, range, max_attackers, ship_info_index, class_type);
} else {
aip->target_objnum = -1;
aip->target_signature = -1;
@@ -2666,7 +2642,7 @@ void ai_attack_object(object* attacker, object* attacked, int ship_info_index, i
if (attacked == nullptr) {
aip->choose_enemy_timestamp = timestamp(0);
// nebula safe
set_target_objnum(aip, find_enemy(OBJ_INDEX(attacker), 99999.9f, 4, true, ship_info_index, class_type));
set_target_objnum(aip, find_enemy(OBJ_INDEX(attacker), 99999.9f, 4, ship_info_index, class_type));
} else {
// check if we can see attacked in nebula
if (aip->target_objnum != OBJ_INDEX(attacked)) {
@@ -2727,24 +2703,10 @@ void ai_attack_wing(object *attacker, int wingnum)
if (count > 0) {
int index;
// prefer wing members we will pursue; if there are none, hold any member, as an explicit order to attack an unpursued ship does
SCP_vector<int> pursued_indexes;
if (The_mission.ai_profile->flags[AI::Profile_Flags::Fix_ai_target_recovery]) {
for (int i = 0; i < count; i++) {
auto member_shipp = &Ships[Wings[wingnum].ship_index[i]];
if (!member_shipp->flags[Ship::Ship_Flags::Dying] && !ai_declines_pursuit(attacker, &Objects[member_shipp->objnum]))
pursued_indexes.push_back(i);
}
}
index = (int) (frand() * count);
if (!pursued_indexes.empty()) {
index = pursued_indexes[Random::next(sz2i(pursued_indexes.size()))];
} else {
index = (int) (frand() * count);
if (index >= count)
index = 0;
}
if (index >= count)
index = 0;
set_target_objnum(aip, Ships[Wings[wingnum].ship_index[index]].objnum);
@@ -3164,7 +3126,6 @@ void create_model_path(object *pl_objp, object *mobjp, int path_num, int subsys_
aip->path_dir = PD_FORWARD;
aip->path_objnum = OBJ_INDEX(mobjp);
aip->mp_index = path_num;
aip->mp_randomized_vert = subsys_path ? mp->nverts-2 : -1;
aip->path_length = (int)(Ppfp - ppfp_start);
aip->path_next_check_time = timestamp(1);
@@ -3224,7 +3185,6 @@ void create_model_exit_path(object *pl_objp, object *mobjp, int path_num, int co
aip->path_dir = PD_FORWARD;
aip->path_objnum = OBJ_INDEX(mobjp);
aip->mp_index = path_num;
aip->mp_randomized_vert = -1;
aip->path_length = (int)(Ppfp - ppfp_start);
aip->path_next_check_time = timestamp(1);
@@ -3920,14 +3880,14 @@ void ai_afterburn_hard(object* objp, ai_info* aip) {
accelerate_ship(aip, 1.0f);
};
// Given an ai_info struct, by reading global path information,
// extract model path information and return in pmp and pmpv.
// Given an ai_info struct, by reading current goal and path information,
// extract base path information and return in pmp and pmpv.
// Return true if found, else return false.
// false means the current point is not on the original path.
int get_base_path_info(int path_cur, int path_objnum, model_path **pmp, mp_vert **pmpv)
int get_base_path_info(int path_cur, int goal_objnum, model_path **pmp, mp_vert **pmpv)
{
pnode *pn = &Path_points[path_cur];
ship *shipp = &Ships[Objects[path_objnum].instance];
ship *shipp = &Ships[Objects[goal_objnum].instance];
polymodel *pm = model_get(Ship_info[shipp->ship_info_index].model_num);
*pmpv = NULL;
@@ -3972,14 +3932,7 @@ void modify_model_path_points(object *objp)
dir = -1;
}
// an exit path may have been created with fewer than nverts points, so don't write past its end
int count = aip->path_length - static_cast<int>(pnp - &Path_points[aip->path_start]);
int randomize_pnt = -1;
if (The_mission.ai_profile->flags[AI::Profile_Flags::Fix_model_path_refresh_randomization])
randomize_pnt = aip->mp_randomized_vert;
copy_xlate_model_path_points(mobjp, &pm->paths[path_num], dir, count, path_num, pnp, randomize_pnt);
copy_xlate_model_path_points(mobjp, &pm->paths[path_num], dir, pm->paths[path_num].nverts, path_num, pnp);
}
// Return an indication of the distance between two matrices.
@@ -4082,18 +4035,12 @@ void set_accel_for_docking(object *objp, ai_info *aip, float dot, float dot_to_n
ai_afterburn_hard(Pl_objp, aip);
} else {
float max_bay_speed = sip->max_speed;
bool fix_bay_speed_ramp = The_mission.ai_profile->flags[AI::Profile_Flags::Fix_bay_speed_ramp];
ship_info *gsip = &Ship_info[Ships[gobjp->instance].ship_info_index];
polymodel *pm = model_get(gsip->model_num);
// a departure path can begin with points that route the ship around the carrier, ahead of the bay path itself
int ramp_start = aip->path_start;
if (aip->mode == AIM_BAY_DEPART && fix_bay_speed_ramp)
ramp_start = MAX(aip->path_start, aip->path_start + aip->path_length - pm->paths[aip->mp_index].nverts);
// Maybe gradually ramp up/down the speed of a ship flying a fighterbay path
if (aip->mode == AIM_BAY_EMERGE || (aip->mode == AIM_BAY_DEPART && aip->path_cur > ramp_start)) {
SCP_string pathName(pm->paths[aip->mp_index].name);
if (aip->mode == AIM_BAY_EMERGE || (aip->mode == AIM_BAY_DEPART && aip->path_cur != aip->path_start)) {
ship_info *gsip = &Ship_info[Ships[gobjp->instance].ship_info_index];
polymodel *pm = model_get(gsip->model_num);
SCP_string pathName(pm->paths[Path_points[aip->path_start].path_num].name);
float speed_mult = FLT_MIN;
if (aip->mode == AIM_BAY_EMERGE) { // Arriving
@@ -4117,7 +4064,7 @@ void set_accel_for_docking(object *objp, ai_info *aip, float dot, float dot_to_n
if (speed_mult != FLT_MIN && speed_mult != 1.0f) {
// We use the distance between the first and last point on the path here; it's not accurate
// if the path is not straight, but should be good enough usually; can be changed if necessary.
float total_path_length = vm_vec_dist_quick(&Path_points[ramp_start].pos, &Path_points[aip->path_start + aip->path_length - 1].pos);
float total_path_length = vm_vec_dist_quick(&Path_points[aip->path_start].pos, &Path_points[aip->path_start + aip->path_length - 1].pos);
float dist_to_end;
if (aip->mode == AIM_BAY_EMERGE) { // Arriving
@@ -4126,12 +4073,8 @@ void set_accel_for_docking(object *objp, ai_info *aip, float dot, float dot_to_n
dist_to_end = vm_vec_dist_quick(&Pl_objp->pos, &Path_points[aip->path_start + aip->path_length - 1].pos);
}
float ramp_fraction = dist_to_end / total_path_length;
if (fix_bay_speed_ramp)
CLAMP(ramp_fraction, 0.0f, 1.0f);
// Calculate max speed, but respect the waypoint speed cap if it's lower
max_bay_speed = sip->max_speed * (speed_mult + (1.0f - speed_mult) * ramp_fraction);
max_bay_speed = sip->max_speed * (speed_mult + (1.0f - speed_mult) * (dist_to_end / total_path_length));
}
}
@@ -5223,8 +5166,6 @@ int maybe_resume_previous_mode(object *objp, ai_info *aip)
aip->submode = AIS_GUARD_PATROL;
aip->submode_start_time = Missiontime;
aip->active_goal = AI_ACTIVE_GOAL_NONE;
if (The_mission.ai_profile->flags[AI::Profile_Flags::Fix_stale_ai_order_state])
set_targeted_subsys(aip, nullptr, -1); // also discards any subsystem path from attacking a big ship
return 1;
}
}
@@ -8390,7 +8331,6 @@ void ai_set_guard_wing(object *objp, int wingnum)
// prevents a ship from trying to guard a non-existent wing.
if (Wings[wingnum].current_count < 1) {
aip->guard_objnum = -1;
aip->guard_signature = -1;
aip->guard_wingnum = -1;
aip->mode = AIM_NONE;
} else {
@@ -9089,6 +9029,15 @@ void ai_chase()
//WMC - Guess we do need this
if (!go_after_it) {
// If we picked this target ourselves -- through auto-attack, dynamic chase, or a standing chase order --
// drop it, so that the retargeting logic in ai_frame() can find something we are willing to chase.
if (The_mission.ai_profile->flags[AI::Profile_Flags::Fix_ai_target_recovery]) {
if (aip->active_goal < 0 || aip->active_goal == AI_ACTIVE_GOAL_DYNAMIC
|| (aip->active_goal < MAX_AI_GOALS && ai_goal_is_standing_chase(aip->goals[aip->active_goal].ai_mode))) {
aip->target_objnum = -1;
aip->target_signature = -1;
}
}
aip->mode = AIM_NONE;
return;
}
@@ -10487,10 +10436,6 @@ void guard_object_was_hit(object *guard_objp, object *hitter_objp)
if (Ships[guard_objp->instance].team == Ships[hitter_objp->instance].team)
return;
// Keep guarding rather than chase a ship we won't pursue
if (ai_declines_pursuit(guard_objp, hitter_objp))
return;
// limit the number of ships attacking hitter_objnum (for now, only if hitter_objnum is player)
if ( ai_maybe_limit_attackers(hitter_objnum) == 1 ) {
return;
@@ -15532,7 +15477,7 @@ void ai_frame(int objnum)
} else if (aip->resume_goal_time == -1) {
// AL 12-9-97: Don't allow cargo and navbuoys to set their aip->target_objnum
if ( Ship_info[shipp->ship_info_index].class_type > -1 && (Ship_types[Ship_info[shipp->ship_info_index].class_type].flags[Ship::Type_Info_Flags::AI_auto_attacks]) ) {
target_objnum = find_enemy(objnum, MAX_ENEMY_DISTANCE, The_mission.ai_profile->max_attackers[Game_skill_level], ai_targets_for_pursuit(aip)); // Attack up to 2.5K units away.
target_objnum = find_enemy(objnum, MAX_ENEMY_DISTANCE, The_mission.ai_profile->max_attackers[Game_skill_level]); // Attack up to 2.5K units away.
if (target_objnum != -1) {
if (aip->target_objnum != target_objnum)
aip->aspect_locked_time = 0.0f;
@@ -15616,7 +15561,7 @@ void ai_frame(int objnum)
if ((aip->resume_goal_time > 0) && (aip->resume_goal_time < Missiontime)) {
aip->active_goal = AI_ACTIVE_GOAL_NONE;
aip->resume_goal_time = -1;
target_objnum = find_enemy(objnum, 2000.0f, The_mission.ai_profile->max_attackers[Game_skill_level], ai_targets_for_pursuit(aip));
target_objnum = find_enemy(objnum, 2000.0f, The_mission.ai_profile->max_attackers[Game_skill_level]);
if (target_objnum != -1) {
if (aip->target_objnum != target_objnum) {
aip->aspect_locked_time = 0.0f;
@@ -15936,7 +15881,6 @@ void init_ai_object(int objnum)
aip->path_start = -1;
aip->path_goal_dist = -1;
aip->path_length = 0;
aip->mp_randomized_vert = -1;
aip->path_subsystem_next_check = 1;
aip->support_ship_objnum = -1;
@@ -16095,29 +16039,6 @@ void init_aip_from_class_and_profile(ai_info *aip, ai_class *aicp, ai_profile_t
aip->ai_profile_flags = profile->flags | (aicp->ai_profile_flags & aicp->ai_profile_flags_set);
}
// Clear the fields that remember which order set them up or which order a dynamic goal interrupted.
// Call when a new order takes over; the order's own setup repopulates whatever it needs.
void ai_reset_order_state(ai_info *aip)
{
if (The_mission.ai_profile->flags[AI::Profile_Flags::Fix_stale_ai_order_state]
|| The_mission.ai_profile->flags[AI::Profile_Flags::Fix_ai_target_recovery])
aip->enemy_wing = -1;
if (The_mission.ai_profile->flags[AI::Profile_Flags::Fix_stale_ai_order_state])
{
aip->guard_objnum = -1;
aip->guard_signature = -1;
aip->guard_wingnum = -1;
aip->previous_mode = AIM_NONE;
aip->previous_submode = 0;
aip->resume_goal_time = -1;
// the player's targeted subsystem is HUD state, not order state
if (aip != Player_ai || Player_use_ai)
set_targeted_subsys(aip, nullptr, -1); // also discards any subsystem path
}
}
void ai_do_default_behavior(object *obj)
{
Assertion(obj != nullptr, "Ai_do_default_behavior() was given a bad information. Specifically obj is a nullptr. This is a coder error, please report!");
@@ -16131,7 +16052,6 @@ void ai_do_default_behavior(object *obj)
aip->mode = AIM_NONE;
aip->submode_start_time = Missiontime;
aip->active_goal = AI_ACTIVE_GOAL_NONE;
ai_reset_order_state(aip);
// if we're not docked, we may modify the behavior a bit
if (!object_is_docked(obj))
@@ -16139,7 +16059,7 @@ void ai_do_default_behavior(object *obj)
// fighters automatically chase things
if (!is_instructor(obj) && (sip->is_fighter_bomber()))
{
int enemy_objnum = find_enemy(OBJ_INDEX(obj), 1000.0f, The_mission.ai_profile->max_attackers[Game_skill_level], true);
int enemy_objnum = find_enemy(OBJ_INDEX(obj), 1000.0f, The_mission.ai_profile->max_attackers[Game_skill_level]);
set_target_objnum(aip, enemy_objnum);
aip->mode = AIM_CHASE;
aip->submode = SM_ATTACK;
@@ -16361,29 +16281,15 @@ void maybe_set_dynamic_chase(ai_info *aip, int hitter_objnum)
return;
}
if (ai_declines_pursuit(&Objects[Ships[aip->shipnum].objnum], &Objects[hitter_objnum])) {
return;
}
if (aip->target_objnum != hitter_objnum)
aip->aspect_locked_time = 0.0f;
set_target_objnum(aip, hitter_objnum);
if (The_mission.ai_profile->flags[AI::Profile_Flags::Fix_stale_ai_order_state]) {
// don't bash the mode we're returning to if this is a dynamic goal interrupting another one
if (aip->active_goal != AI_ACTIVE_GOAL_DYNAMIC) {
aip->previous_mode = aip->mode;
aip->previous_submode = aip->submode;
}
} else {
aip->previous_submode = aip->mode; // retail typo, almost certainly meant to be previous_mode
}
aip->resume_goal_time = Missiontime + i2f(20); // Only chase up to 20 seconds.
aip->active_goal = AI_ACTIVE_GOAL_DYNAMIC;
set_targeted_subsys(aip, NULL, -1); // Say not attacking any particular subsystem.
aip->previous_submode = aip->mode;
aip->mode = AIM_CHASE;
aip->submode = SM_ATTACK;
aip->submode_start_time = Missiontime;
+1 -16
View File
@@ -1803,20 +1803,6 @@ ai_achievability ai_mission_goal_achievable( int objnum, ai_goal *aigp )
auto target_ship_entry = aigp->target_name == nullptr ? nullptr : ship_registry_get(aigp->target_name);
// a ship can't guard itself, and the leader of a wing is the ship the rest of the wing guards
if (The_mission.ai_profile->flags[AI::Profile_Flags::Fix_stale_ai_order_state])
{
if (aigp->ai_mode == AI_GOAL_GUARD && target_ship_entry && target_ship_entry->has_shipp() && target_ship_entry->shipp() == shipp)
return ai_achievability::NOT_ACHIEVABLE;
if (aigp->ai_mode == AI_GOAL_GUARD_WING)
{
int wingnum = wing_name_lookup(aigp->target_name);
if (wingnum >= 0 && Wings[wingnum].ship_index[0] == objp->instance)
return ai_achievability::NOT_ACHIEVABLE;
}
}
// warp (depart) only achievable if there's somewhere to depart to
if (aigp->ai_mode == AI_GOAL_WARP)
{
@@ -2549,9 +2535,8 @@ void ai_process_mission_orders( int objnum, ai_info *aip )
if ( !(Player_use_ai) && (objp->flags[Object::Object_Flags::Player_ship]) && (current_goal->ai_mode != AI_GOAL_FORM_ON_WING) )
{
return;
}
}
ai_reset_order_state(aip);
std::unique_ptr<ai_goal> current_goal_backup;
auto current_goal_target_ship = current_goal->target_name ? ship_registry_get(current_goal->target_name) : nullptr;
+1 -1
View File
@@ -1693,7 +1693,7 @@ static void asteroid_do_area_effect(object *asteroid_objp)
if ( weapon_area_calc_damage(ship_objp, &asteroid_objp->pos, asip->inner_rad, asip->outer_rad, asip->blast, asip->damage, &blast, &damage, asip->outer_rad) == -1 )
continue;
ship_apply_global_damage(ship_objp, asteroid_objp, &asteroid_objp->pos, damage, asip->damage_type_idx, DamageSource::Explosion);
ship_apply_global_damage(ship_objp, asteroid_objp, &asteroid_objp->pos, damage, asip->damage_type_idx);
weapon_area_apply_blast(nullptr, ship_objp, &asteroid_objp->pos, blast, false);
} // end for
}
-7
View File
@@ -1036,13 +1036,6 @@ void bm_init() {
bm_inited = true;
}
bool bm_is_cubemap(int handle)
{
const BM_TYPE type = bm_get_entry(handle)->comp_type;
return type == BM_TYPE_CUBEMAP_DDS || type == BM_TYPE_CUBEMAP_DXT1 || type == BM_TYPE_CUBEMAP_DXT3 ||
type == BM_TYPE_CUBEMAP_DXT5;
}
int bm_is_compressed(int num) {
auto entry = bm_get_entry(num);
BM_TYPE type = BM_TYPE_NONE;
-8
View File
@@ -594,14 +594,6 @@ void bm_get_components(ubyte *pixel, ubyte *r, ubyte *g, ubyte *b, ubyte *a);
*/
int bm_is_compressed(int handle);
/**
* @brief Returns true if the bitmap indexed by handle was loaded from a cubemap image file
*
* @note Render targets return false, even cubemap ones, and so do BC7 (DX10) DDS cubemaps, whose cube flag the DDS
* loader does not keep
*/
bool bm_is_cubemap(int handle);
/**
* @brief Gets the correct TCACHE_TYPE for compressed graphics (uncompressed are assumed TCACHE_TYPE_NORMAL)
*/
+15 -90
View File
@@ -33,7 +33,7 @@
#include "parse/encrypt.h"
#include "cfilesystem.h"
#include <algorithm>
#include <limits>
char Cfile_root_dir[CFILE_ROOT_DIRECTORY_LEN] = "";
@@ -185,12 +185,7 @@ int cfile_init(const char *exe_dir, const char *cdrom_dir)
char buf[CFILE_ROOT_DIRECTORY_LEN];
#ifndef __ANDROID__
strncpy(buf, exe_dir, CFILE_ROOT_DIRECTORY_LEN - 1);
#else
(void)exe_dir;
strncpy(buf, os_android_get_working_folder_path().c_str(), CFILE_ROOT_DIRECTORY_LEN - 1);
#endif
strncpy(buf, exe_dir, CFILE_ROOT_DIRECTORY_LEN - 1);
buf[CFILE_ROOT_DIRECTORY_LEN - 1] = '\0';
@@ -1110,98 +1105,28 @@ void cfread_string(char *buf, int n, CFILE *file)
} while (c != 0 );
}
namespace {
struct string_len_header {
int len = 0;
int stored = 0;
int start = 0;
bool length_cut = false;
};
// a past-the-end length is clamped like any cfread, but a negative one has nothing to clamp to, so inside a
// limited section it throws and the loader skips the rest of the section
string_len_header read_string_len_header(CFILE* file)
void cfread_string_len(char *buf, int buffer_size, CFILE *file)
{
string_len_header h;
if (!cf_is_valid(file)) {
return h;
int len;
len = cfread_int(file);
Assertion( (len <= buffer_size), "String cannot fit in buffer, len: %i, buffer: %i", len, buffer_size);
if (len) {
cfread(buf, len, 1, file);
Assertion(len != buffer_size || buf[len - 1] == 0, "Unterminated string does not fit in buffer");
}
int before = cftell(file);
h.length_cut = cfread(&h.len, sizeof(h.len), 1, file) != 1;
h.start = cftell(file);
if (h.length_cut) {
// a clean end of file reads as an empty string without a warning, as cfread_int does
h.length_cut = (h.start != before) || (cfeof(file) == 0);
return h;
}
h.len = INTEL_INT(h.len);
if ((h.len < 0) && (file->max_read_len != 0)) {
throw cfile::max_read_length("Attempted to read a string of negative length " + std::to_string(h.len));
}
h.stored = static_cast<int>(cf_check_read_size(file, static_cast<size_t>(std::max(h.len, 0))));
return h;
}
// reads count of the stored characters and leaves the file just past the whole string; false if the read failed
bool read_string_len_body(const string_len_header& h, char* dest, int count, CFILE* file)
{
bool ok = (count <= 0) || (cfread(dest, count, 1, file) == 1);
if (!ok || (h.stored > count)) {
cfseek(file, h.start + h.stored, CF_SEEK_SET);
}
return ok;
}
// warned last, so the file position is right even if a debug build stops here
void warn_string_len(const string_len_header& h, bool read_ok, bool cut, int buffer_size, CFILE* file)
{
if (h.length_cut) {
Warning(LOCATION, "cfread_string_len: cut-off string length field in %s", cf_get_filename(file));
} else if (!read_ok) {
Warning(LOCATION,
"cfread_string_len: could not read a string of %d characters in %s",
h.stored,
cf_get_filename(file));
} else if (h.len != h.stored) {
Warning(LOCATION, "cfread_string_len: corrupt string length %d in %s", h.len, cf_get_filename(file));
} else if (cut) {
Warning(LOCATION,
"cfread_string_len: a string of %d bytes was cut to fit a buffer of %d in %s",
h.len,
buffer_size,
cf_get_filename(file));
}
}
} // namespace
void cfread_string_len(char* buf, int buffer_size, CFILE* file)
{
Assertion(buffer_size > 0, "cfread_string_len needs room for at least the terminator, buffer: %i", buffer_size);
string_len_header h = read_string_len_header(file);
if (buffer_size <= 0) {
bool read_ok = read_string_len_body(h, buf, 0, file);
warn_string_len(h, read_ok, h.stored > 0, buffer_size, file);
return;
}
int count = std::min(h.stored, buffer_size);
bool read_ok = read_string_len_body(h, buf, count, file);
int kept = read_ok ? count : 0;
bool cut = (kept == buffer_size) && (memchr(buf, 0, buffer_size) == nullptr);
buf[std::min(kept, buffer_size - 1)] = 0;
warn_string_len(h, read_ok, cut, buffer_size, file);
buf[MIN(len, buffer_size - 1)] = 0;
}
SCP_string cfread_string_len(CFILE *file)
{
string_len_header h = read_string_len_header(file);
int len = cfread_int(file);
SCP_string str;
str.resize(h.stored);
bool read_ok = read_string_len_body(h, str.data(), h.stored, file);
if (!read_ok) {
str.clear();
}
warn_string_len(h, read_ok, false, 0, file);
str.resize(len);
if (len)
cfread(&str[0], len, 1, file);
return str;
}
+2 -8
View File
@@ -320,26 +320,20 @@ void cfread_string(char *buf,int n, CFILE *file);
/**
* @brief Read a fixed length string that is not null-terminated, with the length stored in file.
*
* Keeps at most buffer_size - 1 characters and leaves the file just past the whole string, unless it throws.
*
* If it is not null-terminated, the length of the string *must* be less than the size of the buffer (to make room for one)
*
* @param buf Pre-allocated array to store string
* @param buffer_size Size of pre-allocated array
* @param file File to read from
*
* @note Appends NULL character to string (buf)
* @note Bad data gets a warning; at a clean end of file, or with an invalid file, the string is empty and nothing is
* warned. Inside a limited section (cf_set_max_read_len), a negative length, or a read that still passes the limit
* once clamped to the end of the file, throws cfile::max_read_length.
*/
void cfread_string_len(char *buf,int buffer_size, CFILE *file);
/**
* @brief Read a string from the file where the length is stored in the file
*
* @param file The file to read the string from
* @return The string that was read
*
* @note Warns and throws like the char* overload, except that nothing is cut.
*/
SCP_string cfread_string_len(CFILE *file);
+14 -24
View File
@@ -193,8 +193,21 @@ int cfseek( CFILE *cfile, int offset, int where )
}
size_t cf_check_read_size(CFILE* cfile, size_t size)
// cfread() reads from a file
//
// returns: returns the number of full elements read
//
//
int cfread(void *buf, int elsize, int nelem, CFILE *cfile)
{
if(!cf_is_valid(cfile))
return 0;
size_t size = elsize*nelem;
if(buf == NULL || size <= 0)
return 0;
if ( (cfile->raw_position+size) > cfile->size ) {
Assertion(cfile->raw_position <= cfile->size, "Invalid raw_position value detected!");
size = cfile->size - cfile->raw_position;
@@ -213,29 +226,6 @@ size_t cf_check_read_size(CFILE* cfile, size_t size)
}
}
return size;
}
// cfread() reads from a file
//
// returns: returns the number of full elements read
//
//
int cfread(void *buf, int elsize, int nelem, CFILE *cfile)
{
if(!cf_is_valid(cfile))
return 0;
size_t size = elsize*nelem;
if(buf == nullptr || size <= 0)
return 0;
size = cf_check_read_size(cfile, size);
if (size < 1) {
return 0;
}
size_t bytes_read;
if (cfile->data != nullptr) {
// This is a file from memory
-5
View File
@@ -62,9 +62,4 @@ void cf_check_compression(CFILE* cfile);
// Used to clear compression info data and free dynamic memory used by compression
void cf_clear_compression_info(CFILE* cfile);
// Clamps a read of size bytes to the end of the file and returns the clamped size, or 0 at the end of the file
// without checking the limit; throws cfile::max_read_length if the clamped read would pass the file's read limit
// (cf_set_max_read_len).
size_t cf_check_read_size(CFILE* cfile, size_t size);
#endif
+50 -85
View File
@@ -75,7 +75,6 @@ const char *cmdline_arg_types[] =
enum class flag_output_type {
Binary,
Json_V1,
Json_V2,
};
// variables
@@ -556,12 +555,7 @@ int Cmdline_show_pos = 0;
int Cmdline_show_stats = 0;
int Cmdline_save_render_targets = 0;
bool Cmdline_window = false;
#ifdef __ANDROID__
// Default to borderless in the legacy window-mode path as well.
bool Cmdline_fullscreen_window = true;
#else
bool Cmdline_fullscreen_window = false;
#endif
std::optional<std::pair<uint16_t, uint16_t>>Cmdline_window_res = std::nullopt;
char *Cmdline_res = 0;
char *Cmdline_center_res = 0;
@@ -1364,58 +1358,51 @@ static void handle_unix_modlist(char **modlist, size_t *len)
// external entry point into this modules
static void json_add_version(json_t* root) {
auto version_obj = json_object();
json_object_set_new(version_obj, "full", json_string(FS_VERSION_FULL));
json_object_set_new(version_obj, "major", json_integer(FS_VERSION_MAJOR));
json_object_set_new(version_obj, "minor", json_integer(FS_VERSION_MINOR));
json_object_set_new(version_obj, "build", json_integer(FS_VERSION_BUILD));
json_object_set_new(version_obj, "has_revision", json_boolean(FS_VERSION_HAS_REVIS));
json_object_set_new(version_obj, "revision", json_integer(FS_VERSION_REVIS));
json_object_set_new(version_obj, "revision_str", json_string(FS_VERSION_REVIS_STR));
json_object_set_new(root, "version", version_obj);
}
static void json_add_easy_flags(json_t* root) {
auto easy_array = json_array();
for (auto& easy_flag : easy_flags) {
json_array_append_new(easy_array, json_string(easy_flag.name));
}
json_object_set_new(root, "easy_flags", easy_array);
}
static void json_add_flags(json_t* root) {
auto flags_array = json_array();
for (auto& flag : exe_params) {
auto flag_obj = json_object();
json_object_set_new(flag_obj, "name", json_string(flag.name));
json_object_set_new(flag_obj, "description", json_string(flag.desc));
json_object_set_new(flag_obj, "fso_only", json_boolean(flag.fso_only));
json_object_set_new(flag_obj, "on_flags", json_integer(flag.on_flags));
json_object_set_new(flag_obj, "off_flags", json_integer(flag.off_flags));
json_object_set_new(flag_obj, "type", json_string(flag.type));
json_object_set_new(flag_obj, "web_url", json_string(flag.web_url));
json_array_append_new(flags_array, flag_obj);
}
json_object_set_new(root, "flags", flags_array);
}
static json_t* json_get_v1() {
auto root = json_object();
json_add_version(root);
json_add_easy_flags(root);
json_add_flags(root);
{
auto version_obj = json_object();
json_object_set_new(version_obj, "full", json_string(FS_VERSION_FULL));
json_object_set_new(version_obj, "major", json_integer(FS_VERSION_MAJOR));
json_object_set_new(version_obj, "minor", json_integer(FS_VERSION_MINOR));
json_object_set_new(version_obj, "build", json_integer(FS_VERSION_BUILD));
json_object_set_new(version_obj, "has_revision", json_boolean(FS_VERSION_HAS_REVIS));
json_object_set_new(version_obj, "revision", json_integer(FS_VERSION_REVIS));
json_object_set_new(version_obj, "revision_str", json_string(FS_VERSION_REVIS_STR));
json_object_set_new(root, "version", version_obj);
}
{
auto easy_array = json_array();
for (auto& easy_flag : easy_flags) {
json_array_append_new(easy_array, json_string(easy_flag.name));
}
json_object_set_new(root, "easy_flags", easy_array);
}
{
auto flags_array = json_array();
for (auto& flag : exe_params) {
auto flag_obj = json_object();
json_object_set_new(flag_obj, "name", json_string(flag.name));
json_object_set_new(flag_obj, "description", json_string(flag.desc));
json_object_set_new(flag_obj, "fso_only", json_boolean(flag.fso_only));
json_object_set_new(flag_obj, "on_flags", json_integer(flag.on_flags));
json_object_set_new(flag_obj, "off_flags", json_integer(flag.off_flags));
json_object_set_new(flag_obj, "type", json_string(flag.type));
json_object_set_new(flag_obj, "web_url", json_string(flag.web_url));
json_array_append_new(flags_array, flag_obj);
}
json_object_set_new(root, "flags", flags_array);
}
{
auto caps_array = json_array();
@@ -1526,19 +1513,6 @@ static json_t* json_get_v1() {
return root;
}
// json_v2 reports version, supported flags, and the preferences path for launchers,
// without querying graphics, audio, or joystick devices.
static json_t* json_get_v2() {
auto root = json_object();
json_add_version(root);
json_add_easy_flags(root);
json_add_flags(root);
json_object_set_new(root, "pref_path", json_string(os_get_config_path().c_str()));
return root;
}
static void write_flags_file() {
FILE *fp = fopen("flags.lch","w");
@@ -1596,8 +1570,6 @@ static flag_output_type get_flags_output_type() {
return flag_output_type::Binary;
} else if (type == "json_v1") {
return flag_output_type::Json_V1;
} else if (type == "json_v2") {
return flag_output_type::Json_V2;
} else {
// This is supposed to make it easy for the launcher to recognize an unsupported type
printf("OUTPUT TYPE NOT SUPPORTED!\n");
@@ -1608,23 +1580,17 @@ static flag_output_type get_flags_output_type() {
static void write_flags() {
auto type = get_flags_output_type();
if (type == flag_output_type::Binary) {
switch(type) {
case flag_output_type::Binary:
write_flags_file();
return;
break;
case flag_output_type::Json_V1:
json_t* root = json_get_v1();
json_dumpf(root, stdout, JSON_INDENT(4));
json_decref(root);
break;
}
json_t* root = (type == flag_output_type::Json_V1) ? json_get_v1() : json_get_v2();
#ifdef __ANDROID__
char* dumped = json_dumps(root, JSON_INDENT(4));
os_android_set_flags_string(dumped ? dumped : "");
free(dumped);
#else
json_dumpf(root, stdout, JSON_INDENT(4));
#endif
json_decref(root);
}
bool SetCmdlineParams()
@@ -1821,7 +1787,6 @@ bool SetCmdlineParams()
options::OptionsManager::instance()->setOverride("Graphics.WindowMode",
std::unique_ptr<json_t>(json_integer(static_cast<int>(os::ViewportState::Windowed))), "-window");
Cmdline_window = true;
Cmdline_fullscreen_window = false;
}
if ( fullscreen_window_arg.found( ) )
+15 -11
View File
@@ -1322,7 +1322,7 @@ bool control_config_accept(bool API_Access)
// Check if a hardcoded preset with name already exists. If so, complain to user and force retry
auto it = std::find_if(Control_config_presets.begin(), Control_config_presets.end(), [str](CC_preset& p) {
return ((p.name == str) && ((p.get_type() == Preset_t::tbl) || (p.get_type() == Preset_t::hardcode)));
return ((p.name == str) && ((p.type == Preset_t::tbl) || (p.type == Preset_t::hardcode)));
});
if (it != Control_config_presets.end()) {
@@ -1353,14 +1353,15 @@ bool control_config_accept(bool API_Access)
}
// Pack the current bindings into a preset, then save the file
CC_preset preset(std::move(str), Preset_t::pst);
CC_preset preset;
preset.name = std::move(str);
std::copy(Control_config.begin(), Control_config.end(), std::back_inserter(preset.bindings));
Control_config_presets.push_back(preset);
save_preset_file(preset, true);
// Reload the presets from file. Do this instead of just pushing the preset to the vector direct to get
// consistant ordering
Control_config_presets.erase(Control_config_presets.begin() + 1, Control_config_presets.end());
Control_config_presets.resize(1);
load_preset_files();
// finally, save the new preset so that changes will get saved to this preset
@@ -1777,7 +1778,7 @@ bool control_config_create_new_preset(const SCP_string& newName, bool overwrite)
// Check if a hardcoded preset with name already exists. If so, complain to user and force retry
auto it = std::find_if(Control_config_presets.begin(), Control_config_presets.end(), [newName](CC_preset& p) {
return (p.name == newName) && ((p.get_type() == Preset_t::tbl) || (p.get_type() == Preset_t::hardcode));
return (p.name == newName) && ((p.type == Preset_t::tbl) || (p.type == Preset_t::hardcode));
});
if (it != Control_config_presets.end()) {
@@ -1790,7 +1791,9 @@ bool control_config_create_new_preset(const SCP_string& newName, bool overwrite)
}
// Pack the current bindings into a preset, then save the file
CC_preset preset(newName, Preset_t::pst);
CC_preset preset;
preset.name = newName;
preset.type = Preset_t::pst;
std::copy(Control_config.begin(), Control_config.end(), std::back_inserter(preset.bindings));
// Done with the file
@@ -1802,7 +1805,7 @@ bool control_config_create_new_preset(const SCP_string& newName, bool overwrite)
save_preset_file(preset, true);
// Reload the presets from file.
Control_config_presets.erase(Control_config_presets.begin() + 1, Control_config_presets.end());
Control_config_presets.resize(1);
load_preset_files(newName);
// use the newly created preset
@@ -1810,9 +1813,10 @@ bool control_config_create_new_preset(const SCP_string& newName, bool overwrite)
return true;
} else if ((clone->name != preset.name) || (clone->get_type() != Preset_t::pst)) {
} else if ((clone->name != preset.name) || (clone->type != Preset_t::pst)) {
// Complain and ignore if the preset names or the type differs
return false;
}
return false; //should be unreachable, but just in case
@@ -1822,7 +1826,7 @@ bool control_config_clone_preset(const CC_preset& preset, const SCP_string& newN
// Check if a hardcoded preset with name already exists. If so, complain to user and force retry
auto it = std::find_if(Control_config_presets.begin(), Control_config_presets.end(), [newName](CC_preset& p) {
return (p.name == newName) && ((p.get_type() == Preset_t::tbl) || (p.get_type() == Preset_t::hardcode));
return (p.name == newName) && ((p.type == Preset_t::tbl) || (p.type == Preset_t::hardcode));
});
if (it != Control_config_presets.end()) {
@@ -1834,13 +1838,13 @@ bool control_config_clone_preset(const CC_preset& preset, const SCP_string& newN
return false;
}
CC_preset newPreset(newName, Preset_t::pst);
newPreset.bindings = preset.bindings;
CC_preset newPreset = preset;
newPreset.name = newName;
bool success = save_preset_file(newPreset, false);
// Reload the presets from file.
Control_config_presets.erase(Control_config_presets.begin() + 1, Control_config_presets.end());
Control_config_presets.resize(1);
load_preset_files(newName);
// use the newly cloned preset
+10 -18
View File
@@ -572,28 +572,20 @@ public:
* A preset, a collection of bindings for use in Control_config with an associated name
*/
class CC_preset {
public:
public:
SCP_vector<CCB> bindings;
SCP_string name;
Preset_t type = Preset_t::hardcode;
private:
// No default value: the type is always set explicitly by the constructor
Preset_t type;
public:
CC_preset() = default;
CC_preset(const CC_preset& A) = default;
public:
// No default constructor: every preset must be created with an explicit type
CC_preset(SCP_string preset_name, Preset_t preset_type) : name(std::move(preset_name)), type(preset_type) {}
CC_preset(const CC_preset&) = default;
// Preserve target's preset type during copy assignment
CC_preset& operator=(const CC_preset& other);
Preset_t get_type() const
{
return type;
}
bool is_duplicate_of(const CC_preset& other) const;
CC_preset& operator=(const CC_preset&);
/*!
* Checks if the given preset is a duplicate of this one
*/
bool is_duplicate_of(CC_preset&);
};
/*!
+19 -15
View File
@@ -292,8 +292,10 @@ void control_config_common_init_bindings() {
// init default preset
Control_config_presets.clear();
CC_preset preset("default", Preset_t::hardcode);
CC_preset preset;
preset.bindings.reserve(Control_config.size());
preset.name = "default";
preset.type = Preset_t::hardcode;
for (auto &item : Control_config) {
preset.bindings.push_back(CCB(item));
@@ -1731,13 +1733,14 @@ size_t read_bind_1(CC_preset &preset) {
*/
void control_config_common_read_section(int s, bool first_override) {
Assertion((s == 0) || (s == 1), "Expected value of s to be either 0 or 1, found %i instead.", s);
CC_preset new_preset("", Preset_t::tbl);
CC_preset new_preset;
// Set references to the default preset and bindings
auto& default_preset = Control_config_presets[0];
auto& default_bindings = default_preset.bindings;
new_preset.bindings.clear();
new_preset.type = Preset_t::tbl;
if (s == 0) {
// #ControlConfigOverride
@@ -2999,22 +3002,23 @@ CCI_builder& CCI_builder::operator()(IoActionId action_id, short primary, short
return *this;
}
CC_preset& CC_preset::operator=(const CC_preset& other)
{
if (this != &other) {
bindings = other.bindings;
name = other.name;
// 'type' is intentionally preserved to maintain instance identity
}
return *this;
}
CC_preset& CC_preset::operator=(const CC_preset& A) {
name = A.name;
type = A.type;
bool CC_preset::is_duplicate_of(const CC_preset& other) const
{
for (size_t i = 0; i < other.bindings.size(); ++i) {
if (bindings[i] != other.bindings[i]) {
std::copy(A.bindings.begin(), A.bindings.end(), bindings.begin());
return *this;
};
bool CC_preset::is_duplicate_of(CC_preset& A) {
for (size_t i = 0; i < A.bindings.size(); ++i) {
if (bindings[i] != A.bindings[i]) {
// Found a binding that's different. Thus, this preset is not a duplicate
return false;
}
}
// Else, did not find any differences in the bindings. Thus, this preset is a duplicate
return true;
}
+5 -3
View File
@@ -74,7 +74,9 @@ void load_preset_files(SCP_string clone) {
// Start reading in data
CC_preset preset(file, Preset_t::pst);
CC_preset preset;
preset.name = file;
preset.type = Preset_t::pst;
preset.bindings.resize(Control_config.size());
size_t size;
@@ -132,7 +134,7 @@ void load_preset_files(SCP_string clone) {
if ((clone == preset.name) || (it == Control_config_presets.end())) {
Control_config_presets.push_back(preset);
} else if ((it->name != preset.name) || ((it->get_type() != Preset_t::pst))) {
} else if ((it->name != preset.name) || (it->type != Preset_t::pst)) {
if (gameseq_get_state() == GS_STATE_CONTROL_CONFIG) {
popup(PF_TITLE_WHITE | PF_USE_AFFIRMATIVE_ICON, 1, POPUP_OK, "Preset '%s' is a duplicate of an existing preset, ignoring", preset.name.c_str());
} else {
@@ -171,7 +173,7 @@ bool delete_preset_file(CC_preset preset) {
cf_delete(filename.c_str(), CF_TYPE_PLAYER_BINDS, CF_LOCATION_ROOT_USER | CF_LOCATION_ROOT_GAME | CF_LOCATION_TYPE_ROOT);
// Reload the presets from file.
Control_config_presets.erase(Control_config_presets.begin() + 1, Control_config_presets.end());
Control_config_presets.resize(1);
load_preset_files();
return true;
+4 -6
View File
@@ -1,16 +1,12 @@
#ifdef GL_ES
precision highp float;
precision highp sampler2DArray;
#endif
#include "gamma.sdr"
layout(location=0) out vec4 fragOut0;
#ifdef VULKAN
layout (location = 0) in vec4 fragTexCoord;
layout (location = 1) in vec4 fragColor;
layout (location = 0) out vec4 fragOut0;
layout (set = 1, binding = 1) uniform sampler2DArray baseMap;
layout (set = 2, binding = 0, std140) uniform genericData {
@@ -21,6 +17,8 @@ layout (set = 2, binding = 0, std140) uniform genericData {
in vec4 fragTexCoord;
in vec4 fragColor;
out vec4 fragOut0;
uniform sampler2DArray baseMap;
layout (std140) uniform genericData {
@@ -1,7 +1,3 @@
#ifdef GL_ES
precision highp float;
#endif
#ifdef VULKAN
layout (location = 0) in vec4 vertPosition;
layout (location = 1) in vec4 vertColor;
+2 -7
View File
@@ -1,16 +1,11 @@
#ifdef GL_ES
precision highp float;
precision highp sampler2D;
#endif
layout(location=0) out vec4 fragOut0;
#ifdef VULKAN
layout(location = 0) in vec2 fragTexCoord;
layout(location = 0) out vec4 fragOut0;
layout(set = 1, binding = 1) uniform sampler2D bloomed;
#else
in vec4 fragTexCoord;
out vec4 fragOut0;
uniform sampler2D bloomed;
#endif
+2 -8
View File
@@ -1,15 +1,9 @@
#ifdef GL_ES
precision highp float;
precision highp int;
precision highp sampler2D;
#endif
layout(location = 0) out vec4 fragOut0;
#ifdef VULKAN
layout(location = 0) in vec2 fragTexCoord;
layout(location = 0) out vec4 fragOut0;
layout(set = 1, binding = 1) uniform sampler2D tex;
#else
out vec4 fragOut0;
in vec4 fragTexCoord;
uniform sampler2D tex;
#endif
+2 -8
View File
@@ -1,18 +1,12 @@
#ifdef GL_ES
precision highp float;
precision highp sampler2D;
#endif
layout(location = 0) out vec4 fragOut0;
#ifdef VULKAN
layout(location = 0) in vec2 fragTexCoord;
layout(location = 0) out vec4 fragOut0;
layout(set = 1, binding = 1) uniform sampler2D tex;
#else
in vec4 fragTexCoord;
out vec4 fragOut0;
uniform sampler2D tex;
#endif
const float Luminance = 0.08;
const float fMiddleGray = 0.2;
const float fWhiteCutoff = 0.4;
+2 -8
View File
@@ -1,16 +1,10 @@
#ifdef GL_ES
precision highp float;
precision highp sampler2D;
precision highp sampler2DArray;
#endif
layout(location = 0) out vec4 fragOut0;
#ifdef VULKAN
layout(location = 0) in vec2 fragTexCoord;
layout(location = 0) out vec4 fragOut0;
layout(set = 1, binding = 1) uniform sampler2D tex;
#else
in vec4 fragTexCoord;
out vec4 fragOut0;
#ifdef COPY_ARRAY
uniform sampler2DArray tex;
#else
+4 -15
View File
@@ -1,9 +1,3 @@
#ifdef GL_ES
precision highp float;
precision highp int;
precision highp sampler2D;
precision highp sampler2DArray;
#endif
// NOTE: The technique and some of this code is based on this tutorial:
// http://martindevans.me/game-development/2015/02/27/Drawing-Stuff-On-Other-Stuff-With-Deferred-Screenspace-Decals/
@@ -35,14 +29,9 @@ layout (set = 1, binding = 1) uniform sampler2DArray decalTextures;
layout (set = 1, binding = 4) uniform sampler2D gDepthBuffer;
layout (set = 1, binding = 6) uniform sampler2D gNormalBuffer;
#else
layout (location=0) out vec4 fragOut0; // Diffuse buffer
#ifndef GL_ES
layout (location=1) out vec4 fragOut1; // Normal buffer
layout (location=2) out vec4 fragOut2; // Emissive buffer
#else
layout (location=2) out vec4 fragOut1; // Normal buffer -> COLOR_ATTACHMENT2
layout (location=4) out vec4 fragOut2; // Emissive buffer -> COLOR_ATTACHMENT4
#endif
out vec4 fragOut0; // Diffuse buffer
out vec4 fragOut1; // Normal buffer
out vec4 fragOut2; // Emissive buffer
flat in mat4 invModelMatrix;
flat in vec3 decalDirection;
@@ -135,7 +124,7 @@ vec3 getPixelNormal(vec3 frag_position, vec2 tex_coord, inout float alpha, out v
}
// Make a smooth alpha transition leading up to an edge
alpha = alpha * (1.0 - smoothstep(angle_fade_start, normal_angle_cutoff, angle));
alpha = alpha * (1 - smoothstep(angle_fade_start, normal_angle_cutoff, angle));
return normal;
}
-4
View File
@@ -1,7 +1,3 @@
#ifdef GL_ES
precision highp float;
precision highp int;
#endif
#ifdef VULKAN
// Binding 0: box vertex positions
@@ -1,10 +1,3 @@
#ifdef GL_ES
#extension GL_EXT_clip_cull_distance : enable
precision highp float;
precision highp int;
precision highp sampler2DArray;
#endif
#ifdef VULKAN
layout(set = 2, binding = 0, std140)
#else
@@ -27,28 +20,22 @@ uniform genericData {
uint clipEnabled;
};
layout(location = 0) out vec4 fragOut0;
#ifdef VULKAN
layout(set = 1, binding = 1) uniform sampler2DArray baseMap;
layout(location = 0) in vec4 fragTexCoord;
layout(location = 1) in vec4 fragColor;
#ifdef SDR_FLAG_SW_CLIP_FALLBACK
layout(location = 2) in float vClipDist;
#endif
layout(location = 0) out vec4 fragOut0;
#else
#ifdef SDR_FLAG_SW_CLIP_FALLBACK
in float vClipDist;
#endif
uniform sampler2DArray baseMap;
in vec4 fragTexCoord;
in vec4 fragColor;
out vec4 fragOut0;
#endif
@@ -56,11 +43,6 @@ in vec4 fragColor;
void main()
{
#ifdef SDR_FLAG_SW_CLIP_FALLBACK
if (clipEnabled != 0u && vClipDist < 0.0) {
discard;
}
#endif
vec4 baseColor = texture(baseMap, vec3(fragTexCoord.xy, float(baseMapIndex)));
if(alphaThreshold > baseColor.a) discard;
baseColor.rgb = (srgb == 1) ? srgb_to_linear(baseColor.rgb) : baseColor.rgb;
@@ -1,9 +1,3 @@
#ifdef GL_ES
#extension GL_EXT_clip_cull_distance : enable
precision highp float;
precision highp int;
#endif
#ifdef VULKAN
layout(set = 2, binding = 0, std140)
#else
@@ -44,15 +38,10 @@ layout(location = 2) in vec4 vertTexCoord;
layout(location = 0) out vec4 fragTexCoord;
layout(location = 1) out vec4 fragColor;
#ifdef SDR_FLAG_SW_CLIP_FALLBACK
layout(location = 2) out float vClipDist;
#endif
#else
#ifdef SDR_FLAG_SW_CLIP_FALLBACK
out float vClipDist;
#endif
out float gl_ClipDistance[1];
out vec4 fragTexCoord;
in vec4 vertTexCoord;
@@ -69,16 +58,13 @@ void main()
gl_Position = projMatrix * modelViewMatrix * vertPosition;
if (clipEnabled != 0u) {
#ifndef SDR_FLAG_SW_CLIP_FALLBACK
gl_ClipDistance[0] = dot(clipEquation, modelMatrix * vertPosition);
#else
vClipDist = dot(clipEquation, modelMatrix * vertPosition);
#endif
} else {
#ifndef SDR_FLAG_SW_CLIP_FALLBACK
#ifdef VULKAN
// Vulkan has no glEnable(GL_CLIP_DISTANCE0) equivalent — clip distances are
// always evaluated when declared in the shader. Must write a positive value
// when clipping is disabled to prevent undefined-value vertex culling.
gl_ClipDistance[0] = 1.0;
#else
vClipDist = 1.0;
#endif
#endif
}
}
@@ -1,14 +1,9 @@
#ifdef GL_ES
precision highp float;
#endif
layout (location=0) out vec4 fragOut0;
layout (location=1) out vec4 fragOut1;
layout (location=2) out vec4 fragOut2;
layout (location=3) out vec4 fragOut3;
layout (location=4) out vec4 fragOut4;
layout (location=5) out vec4 fragOut5;
out vec4 fragOut0;
out vec4 fragOut1;
out vec4 fragOut2;
out vec4 fragOut3;
out vec4 fragOut4;
out vec4 fragOut5;
void main()
{
fragOut0 = vec4(0.0, 0.0, 0.0, 1.0); // color
+9 -17
View File
@@ -1,21 +1,13 @@
//? #version 150
#ifdef GL_ES
precision highp float;
precision highp int;
precision highp sampler2D;
precision highp samplerCube;
precision highp sampler2DArrayShadow;
#endif
#include "lighting.sdr" //! #include "lighting.sdr"
#include "gamma.sdr" //! #include "gamma.sdr"
#include "shadows.sdr" //! #include "shadows.sdr"
#include "z-compress.sdr" //! #include "z-compress.sdr"
#ifndef GL_ES
#ifdef VULKAN
layout(location = 0) out vec4 fragOut0;
#else
layout(location = 5) out vec4 fragOut0; //COLOR_ATTACHMENTn is on location n in ES, here it uses COLOR_ATTACHMENT5
out vec4 fragOut0;
#endif
#ifdef VULKAN
@@ -153,7 +145,7 @@ void GetLightInfo(vec3 position, in float alpha, in vec3 reflectDir, out vec3 li
dist = length(lightDirOut);
lightDist = dist;
// Energy conservation term
float alpha_adjust = clamp(alpha + (sourceRadius/(2.0*dist)), 0.0, 1.0);
float alpha_adjust = clamp(alpha + (sourceRadius/(2*dist)), 0.0, 1.0);
area_normalisation = alpha/alpha_adjust;
area_normalisation *= area_normalisation;
//end chunk
@@ -196,7 +188,7 @@ void GetLightInfo(vec3 position, in float alpha, in vec3 reflectDir, out vec3 li
float dist = length(lightDirOut);
lightDist = dist;
// Energy conservation term
float alpha_adjust = min(alpha + (sourceRadius/(2.0*dist)), 1.0);
float alpha_adjust = min(alpha + (sourceRadius/(2*dist)), 1.0);
area_normalisation = alpha/alpha_adjust;
// don't need to square as it's a line rather than a sphere.
//end chunk
@@ -243,11 +235,11 @@ void ComputeEnvLight(float alpha, float ao, vec3 light_dir, vec3 eyeDir, vec3 no
// so let s = (2/alpha^2 - 2)
// 1/2 log(s + 1) = 1/2 log(2/alpha^2 -1)
const float ENV_REZ = 512.0; // Ideally this would be #define'd and shader recompiled with envmap rez changes
const float REZ_BIAS = log2(ENV_REZ * sqrt(3.0));
const float ENV_REZ = 512; // Ideally this would be #define'd and shader recompiled with envmap rez changes
const float REZ_BIAS = log2(ENV_REZ * sqrt(3));
float alphaSqr = alpha * alpha;
float rough_bias = 0.5 * log2(2.0/alphaSqr - 1.0);
float rough_bias = 0.5 * log2(2/alphaSqr - 1);
float mip_bias = REZ_BIAS - rough_bias;
// Sample light, using mip bias to blur it.
@@ -265,7 +257,7 @@ void ComputeEnvLight(float alpha, float ao, vec3 light_dir, vec3 eyeDir, vec3 no
// Pseudo-IBL, so use k_IBL
float k = alpha * alpha/ 2.0f;
float NdotL = max(dot(light_dir, normal),0.0);
float NdotL = max(dot(light_dir, normal),0);
float g1vNL = GeometrySchlickGGX(NdotL, k);
vec3 specEnvLighting = specEnvColour.rgb * fresnel * g1vNL;
@@ -346,6 +338,6 @@ void main()
float NdotL = clamp(dot(normal, lightDir), 0.0, 1.0);
fragmentColor.rgb = computeLighting(specColor.rgb, diffColor, lightDir, normal.xyz, halfVec, eyeDir, roughness, fresnel, NdotL).rgb * diffuseLightColor * attenuation * area_normalisation;
}
fragOut0 = max(fragmentColor, vec4(0.0));
}
@@ -1,7 +1,3 @@
#ifdef GL_ES
precision highp float;
precision highp int;
#endif
#include "lighting.sdr"
@@ -1,16 +1,10 @@
#ifdef GL_ES
precision highp float;
precision highp sampler2D;
precision highp sampler2DArray;
#endif
layout(location = 0) out vec4 fragOut0;
#ifdef VULKAN
layout(location = 0) in vec4 fragTexCoord;
layout(location = 1) in vec4 fragColor;
layout(location = 2) in float fragOffset;
layout(location = 0) out vec4 fragOut0;
layout(set = 1, binding = 1) uniform sampler2DArray baseMap;
layout(set = 1, binding = 4) uniform sampler2D depthMap;
layout(set = 1, binding = 5) uniform sampler2D frameBuffer;
@@ -20,6 +14,8 @@ in vec4 fragTexCoord;
in vec4 fragColor;
in float fragOffset;
out vec4 fragOut0;
uniform sampler2DArray baseMap;
uniform sampler2D depthMap;
uniform sampler2D distMap;
@@ -1,7 +1,3 @@
#ifdef GL_ES
precision highp float;
#endif
#ifdef VULKAN
layout(location = 0) in vec4 vertPosition;
layout(location = 1) in vec4 vertColor;
+4 -8
View File
@@ -1,21 +1,15 @@
#ifdef GL_ES
precision highp float;
precision highp int;
precision highp sampler2D;
precision highp sampler2DArray;
#endif
#include "gamma.sdr"
#include "z-compress.sdr"
layout(location = 0) out vec4 fragOut0;
#ifdef VULKAN
layout(location = 0) in vec4 fragTexCoord;
layout(location = 1) in vec4 fragColor;
layout(location = 2) in float fragRadius;
layout(location = 3) in vec4 fragPosition;
layout(location = 0) out vec4 fragOut0;
layout(set = 1, binding = 1) uniform sampler2DArray baseMap;
layout(set = 1, binding = 4) uniform sampler2D depthMap;
#else
@@ -24,6 +18,8 @@ in vec4 fragPosition;
in vec4 fragTexCoord;
in vec4 fragColor;
out vec4 fragOut0;
uniform sampler2DArray baseMap;
uniform sampler2D depthMap;
#endif
-4
View File
@@ -1,7 +1,3 @@
#ifdef GL_ES
precision highp float;
#endif
layout (points) in;
layout (triangle_strip, max_vertices = 4) out;
-3
View File
@@ -1,6 +1,3 @@
#ifdef GL_ES
precision highp float;
#endif
#ifdef VULKAN
layout(location = 0) in vec4 vertPosition;
@@ -1,14 +1,11 @@
#define M_PI 3.1415926535897932384626433832795
#ifdef GL_ES
precision highp float;
precision highp samplerCube;
#endif
uniform samplerCube envmap;
in vec4 fragTexCoord;
layout(location=0) out vec4 fragOut0;
out vec4 fragOut0;
layout (location = 0) out vec4 outColor;
void main() {
const float theta = -fragTexCoord.x * (2.0 * M_PI);
+5 -8
View File
@@ -1,20 +1,17 @@
#ifdef GL_ES
precision highp float;
precision highp sampler2D;
#endif
#include "gamma.sdr"
layout(location=0) out vec4 fragOut0;
#ifdef VULKAN
layout(location = 0) in vec2 fragTexCoord;
layout(location = 0) out vec4 fragOut0;
layout(set = 1, binding = 1) uniform sampler2D tex;
layout(set = 1, binding = 4) uniform sampler2D depth_tex;
#else
in vec4 fragTexCoord;
out vec4 fragOut0;
uniform sampler2D tex;
uniform sampler2D depth_tex;
#endif
@@ -43,7 +40,7 @@ void main()
// If the scene is in fog then we change the color we operate on based on the depth of the pixel
float depth_val = texture(depth_tex, fragTexCoord.xy).x;
// Transform depth value from [0, 1] to [-1, 1]
float depth_normalized = 2.0 * depth_val - 1.0;
float depth_normalized = 2 * depth_val - 1;
// Now we compute the depth value in projection space using the clipping plane information
float view_depth = 2.0 * zNear * zFar / (zFar + zNear - depth_normalized * (zFar - zNear));
@@ -53,7 +50,7 @@ void main()
if (isinf(view_depth)) {
fragOut0.rgb = color_in.rgb;
} else {
float fog_dist = clamp(1.0 - pow(fog_density, view_depth - fog_start) , 0.0, 1.0);
float fog_dist = clamp(1 - pow(fog_density, view_depth - fog_start) , 0.0, 1.0);
vec3 finalFogColor = srgb_to_linear(fog_color);
fragOut0.rgb = mix(color_in.rgb, finalFogColor, fog_dist);
+1 -14
View File
@@ -1,12 +1,3 @@
#ifdef GL_ES
#ifdef GL_EXT_gpu_shader5
#extension GL_EXT_gpu_shader5 : enable
#define FXAA_GATHER4_ALPHA 1
#endif
precision highp float;
precision highp sampler2D;
#endif
#define FXAA_EARLY_EXIT 1
#define FXAA_DISCARD 1
#define FXAA_FAST_PIXEL_OFFSET 1 // With OpenGL 3.2 we can always do this
@@ -509,12 +500,8 @@ layout(std140, set = 2, binding = 0) uniform genericData {
#else
uniform sampler2D tex0;
in vec2 v_rcpFrame;
#ifdef GL_ES
in vec2 v_pos;
#else
noperspective in vec2 v_pos;
#endif
layout(location=0)out vec4 fragOut0;
out vec4 fragOut0;
#endif
void main() {
-7
View File
@@ -1,6 +1,3 @@
#ifdef GL_ES
precision highp float;
#endif
#ifdef VULKAN
layout(location = 0) out vec2 fragTexCoord;
@@ -13,11 +10,7 @@ void main() {
in vec4 vertPosition;
out vec2 v_rcpFrame;
#ifdef GL_ES
out vec2 v_pos;
#else
noperspective out vec2 v_pos;
#endif
layout (std140) uniform genericData {
float rt_w;
+2 -8
View File
@@ -1,12 +1,6 @@
#ifdef GL_ES
precision highp float;
precision highp sampler2D;
#endif
layout(location=0) out vec4 fragOut0;
#ifdef VULKAN
layout(location = 0) in vec2 fragTexCoord;
layout(location = 0) out vec4 fragOut0;
// [0]=real color (passed through as-is), [1]=luma detection proxy (see
// getAADetectionView; may be the same view as [0] when not HDR)
layout(set = 1, binding = 1) uniform sampler2D fxaaTex[2];
@@ -14,9 +8,9 @@ layout(set = 1, binding = 1) uniform sampler2D fxaaTex[2];
#define lumaTex fxaaTex[1]
#else
in vec4 fragTexCoord;
out vec4 fragOut0;
uniform sampler2D tex;
#endif
void main() {
vec4 color = texture(tex, fragTexCoord.xy);
#ifdef VULKAN
@@ -1,17 +1,12 @@
#ifdef GL_ES
precision highp float;
precision highp sampler2D;
#endif
#include "gamma.sdr"
layout(location=0)out vec4 fragOut0;
#ifdef VULKAN
layout(location = 0) in vec2 fragTexCoord;
layout(location = 0) out vec4 fragOut0;
layout(set = 1, binding = 1) uniform sampler2D tex;
#else
in vec4 fragTexCoord;
out vec4 fragOut0;
uniform sampler2D tex;
#endif
-3
View File
@@ -1,6 +1,3 @@
#ifdef GL_ES
precision highp float;
#endif
const float SRGB_GAMMA = 2.2;
const float SRGB_GAMMA_INVERSE = 1.0 / SRGB_GAMMA;
+6 -12
View File
@@ -1,21 +1,15 @@
//!#version 150
#ifdef GL_ES
precision highp float;
precision highp int;
precision highp samplerCube;
#endif
#include "gamma.sdr"
#include "gamma.sdr" //! #include "gamma.sdr"
#define PI 3.1415926535897932384626433832795
layout(location = 0) out vec4 fragOut0;
#ifdef VULKAN
layout(location = 0) in vec2 fragTexCoord;
layout(location = 0) out vec4 fragOut0;
layout(set = 1, binding = 1) uniform samplerCube envmap;
#else
uniform samplerCube envmap;
in vec4 fragTexCoord;
out vec4 fragOut0;
#endif
#ifdef VULKAN
@@ -160,8 +154,8 @@ vec3( 0.7305, 0.6698, 0.1333)
);
void main() {
float xpos = 2.0 * gl_FragCoord.x/16.0 - 1.0; // remap to (-1, 1)
float ypos = 2.0 * gl_FragCoord.y/16.0 - 1.0;
float xpos = 2 * gl_FragCoord.x/16 - 1; // remap to (-1, 1)
float ypos = 2 * gl_FragCoord.y/16 - 1;
vec3 fragDir;
vec4 fragCol = vec4(0.0);
@@ -197,5 +191,5 @@ void main() {
vec3 sampDir = points[i] + (aPdotD - PdotD) * fragDir;
fragCol += aPdotD * vec4(srgb_to_linear(texture(envmap, sampDir)).rgb, 1.0);
}
fragOut0 = linear_to_srgb(PI * fragCol * (1.0/128.0));
fragOut0 = linear_to_srgb(PI * fragCol * (1.0/128));
}
+2 -2
View File
@@ -57,7 +57,7 @@ vec3 ComputeGGX(vec3 specColor, vec3 diffColor, vec3 light, vec3 normal, vec3 ha
vec3 specular = distribution * fresnel * geometry / (4.0*dotNV*dotNL + 0.0001);
vec3 specular = distribution * fresnel * geometry / (4*dotNV*dotNL + 0.0001);
// Diffuse term - Lambertian, kD represents energy lost to specular reflection.
vec3 kD = vec3(1.0)-fresnel;
@@ -70,7 +70,7 @@ vec3 ComputeGGX(vec3 specColor, vec3 diffColor, vec3 light, vec3 normal, vec3 ha
vec3 computeLighting(vec3 specColor, vec3 diffColor, vec3 light, vec3 normal, vec3 halfVec, vec3 view, float roughness, float fresnelFactor, float dotNL)
{
#ifdef FLAG_LIGHT_MODEL_BLINN_PHONG
return SpecularBlinnPhong(specColor, light, normal, halfVec, 32.0, fresnelFactor, dotNL);
return SpecularBlinnPhong(specColor, light, normal, halfVec, 32, fresnelFactor, dotNL);
#else
return ComputeGGX(specColor, diffColor, light, normal, halfVec, view, roughness, fresnelFactor, dotNL);
#endif
+3 -8
View File
@@ -1,14 +1,7 @@
#ifdef GL_ES
precision highp float;
precision highp int;
precision highp sampler2D;
#endif
layout(location = 0) out vec4 fragOut0;
#ifdef VULKAN
layout(location = 0) in vec2 fragTexCoord;
layout(location = 0) out vec4 fragOut0;
layout(set = 1, binding = 1) uniform sampler2D textures[16];
#define scene textures[0]
@@ -16,6 +9,8 @@ layout(set = 1, binding = 1) uniform sampler2D textures[16];
#else
in vec4 fragTexCoord;
out vec4 fragOut0;
uniform sampler2D scene;
uniform sampler2D cockpit;
#endif
+14 -31
View File
@@ -1,13 +1,4 @@
//? #version 150
#ifdef GL_ES
#extension GL_EXT_clip_cull_distance: enable
precision highp float;
precision highp int;
precision highp sampler2D;
precision highp sampler2DArray;
precision highp sampler2DArrayShadow;
#endif
#include "shadows.sdr" //! #include "shadows.sdr"
#include "lighting.sdr" //! #include "lighting.sdr"
#include "gamma.sdr" //! #include "gamma.sdr"
@@ -121,13 +112,6 @@ uniform shadowCascadeParams {
vec4 smoothness_factors[(NUM_SHADOW_CASCADES + 4 - 1) / 4];
};
layout(location = 0) out vec4 fragOut0;
layout(location = 1) out vec4 fragOut1;
layout(location = 2) out vec4 fragOut2;
layout(location = 3) out vec4 fragOut3;
layout(location = 4) out vec4 fragOut4;
#ifdef VULKAN
layout(set = 1, binding = 1) uniform sampler2DArray materialTextures[16];
#define sBasemap materialTextures[0]
@@ -155,12 +139,13 @@ layout(location = 0) in VertexOutput {
vec4 shadowUV[NUM_SHADOW_CASCADES];
vec4 shadowPos;
#prereplace ENDIF_FLAG_COMPILED MODEL_SDR_FLAG_SHADOWS
#ifdef SDR_FLAG_SW_CLIP_FALLBACK
float vClipDist;
#endif
} vertIn;
layout(location = 0) out vec4 fragOut0;
layout(location = 1) out vec4 fragOut1;
layout(location = 2) out vec4 fragOut2;
layout(location = 3) out vec4 fragOut3;
layout(location = 4) out vec4 fragOut4;
#else
#prereplace IF_FLAG_COMPILED MODEL_SDR_FLAG_DIFFUSE
uniform sampler2DArray sBasemap;
@@ -200,10 +185,13 @@ in VertexOutput {
vec4 shadowUV[NUM_SHADOW_CASCADES];
vec4 shadowPos;
#prereplace ENDIF_FLAG_COMPILED MODEL_SDR_FLAG_SHADOWS
#ifdef SDR_FLAG_SW_CLIP_FALLBACK
float vClipDist;
#endif
} vertIn;
out vec4 fragOut0;
out vec4 fragOut1;
out vec4 fragOut2;
out vec4 fragOut3;
out vec4 fragOut4;
#endif
vec3 FresnelLazarovEnv(vec3 specColor, vec3 view, vec3 normal, float gloss)
@@ -295,10 +283,6 @@ vec3 CalculateLighting(vec3 normal, vec3 diffuseMaterial, vec3 specularMaterial,
void main()
{
#ifdef SDR_FLAG_SW_CLIP_FALLBACK
if (vertIn.vClipDist < 0.0) discard;
#endif
vec3 eyeDir = vec3(normalize(-vertIn.position).xyz);
vec2 texCoord = vertIn.texCoord.xy;
@@ -480,7 +464,7 @@ void main()
#prereplace ENDIF_FLAG //MODEL_SDR_FLAG_DIFFUSE
// This code will only be used by the forward renderer so we apply the fog effect to both the emissive and the base
// color.
float fogDensityFinal = clamp(1.0 - pow(fogDensity, vertIn.fogDist) , 0.0, 1.0);
float fogDensityFinal = clamp(1 - pow(fogDensity, vertIn.fogDist) , 0.0, 1.0);
baseColor.rgb = mix(emissiveColor.rgb + baseColor.rgb, finalFogColor, fogDensityFinal);
emissiveColor.rgb = vec3(0.0); // Zero the emissive color since it has already been added by the previous line
specColor.rgb *= fogDensityFinal;
@@ -525,12 +509,11 @@ void main()
#prereplace IF_NOT_FLAG MODEL_SDR_FLAG_LIGHT
#prereplace IF_FLAG MODEL_SDR_FLAG_SPEC
baseColor.rgb += pow(1.0 - clamp(dot(eyeDir, normal), 0.0, 1.0), 5.0 * clamp(glossData, 0.01, 1.0)) * specColor.rgb;
glossData = 0.0f;
glossData = 0;
#prereplace ENDIF_FLAG //MODEL_SDR_FLAG_SPEC
// If there is no lighting then we copy the color data so far into the emissive.
emissiveColor.rgb += baseColor.rgb;
aoFactors.x = 0.0f;
aoFactors.x = 0;
// and leave nothing for the light pass to add on top of it
baseColor.rgb = vec3(0.0);
specColor = vec4(0.0);
+1 -26
View File
@@ -1,11 +1,4 @@
#ifdef GL_ES
#extension GL_EXT_gpu_shader5: enable
#extension GL_EXT_clip_cull_distance: enable
precision highp float;
precision highp int;
#else
#extension GL_ARB_gpu_shader5: enable
#endif
#conditional_include +"LARGE_SHADER" "main_large.sdr"
#conditional_include -"LARGE_SHADER" "main_small.sdr"
@@ -107,9 +100,6 @@ in VertexOutput {
vec4 shadowUV[NUM_SHADOW_CASCADES];
vec4 shadowPos;
#prereplace ENDIF_FLAG_COMPILED MODEL_SDR_FLAG_SHADOWS
#ifdef SDR_FLAG_SW_CLIP_FALLBACK
float vClipDist;
#endif
} vertIn[];
out VertexOutput {
@@ -127,10 +117,6 @@ out VertexOutput {
vec4 shadowUV[NUM_SHADOW_CASCADES];
vec4 shadowPos;
#prereplace ENDIF_FLAG_COMPILED MODEL_SDR_FLAG_SHADOWS
#ifdef SDR_FLAG_SW_CLIP_FALLBACK
float vClipDist;
#endif
} vertOut;
#ifdef MODEL_SDR_FLAG_THICK_OUTLINES
@@ -180,19 +166,8 @@ out VertexOutput {
#prereplace ENDIF_FLAG //MODEL_SDR_FLAG_SHADOWS
if (use_clip_plane != 0) {
#ifdef SDR_FLAG_SW_CLIP_FALLBACK
vertOut.vClipDist = vertIn[vert].vClipDist;
#else
gl_ClipDistance[0] = gl_in[vert].gl_ClipDistance[0];
#endif
} else {
#ifdef SDR_FLAG_SW_CLIP_FALLBACK
vertOut.vClipDist = 1.0;
#else
gl_ClipDistance[0] = 1.0;
#endif
gl_ClipDistance[0] = gl_in[vert].gl_ClipDistance[0];
}
EmitVertex();
}
+6 -32
View File
@@ -1,18 +1,8 @@
#ifndef VULKAN
//? #version 150
#ifdef GL_ES
#extension GL_EXT_gpu_shader5: enable
#extension GL_EXT_clip_cull_distance: enable
precision highp float;
precision highp int;
precision highp samplerBuffer;
precision highp sampler2DArrayShadow;
#else
#extension GL_ARB_gpu_shader5: enable
#endif
#endif
#include "shadows.sdr"
#conditional_include +"LARGE_SHADER" "main_large.sdr"
@@ -155,10 +145,6 @@ layout(location = 0) out VertexOutput {
vec4 shadowUV[NUM_SHADOW_CASCADES];
vec4 shadowPos;
#prereplace ENDIF_FLAG_COMPILED MODEL_SDR_FLAG_SHADOWS
#ifdef SDR_FLAG_SW_CLIP_FALLBACK
float vClipDist;
#endif
} vertOut;
#else
#prereplace IF_FLAG_COMPILED MODEL_SDR_FLAG_TRANSFORM
@@ -180,10 +166,6 @@ out VertexOutput {
vec4 shadowUV[NUM_SHADOW_CASCADES];
vec4 shadowPos;
#prereplace ENDIF_FLAG_COMPILED MODEL_SDR_FLAG_SHADOWS
#ifdef SDR_FLAG_SW_CLIP_FALLBACK
float vClipDist;
#endif
} vertOut;
#define TEXELS_PER_MATRIX 4
@@ -265,20 +247,12 @@ void main()
}
#prereplace ENDIF_FLAG //MODEL_SDR_FLAG_TRANSFORM
#ifndef SDR_FLAG_SW_CLIP_FALLBACK
if (use_clip_plane != 0) {
gl_ClipDistance[0] = dot(clip_equation, modelMatrix * orient * vertex);
} else {
gl_ClipDistance[0] = 1.0;
}
#else
if (use_clip_plane != 0) {
vertOut.vClipDist = dot(clip_equation, modelMatrix * orient * vertex);
} else {
vertOut.vClipDist = 1.0;
}
#endif
// Clip plane
if(use_clip_plane != 0) {
gl_ClipDistance[0] = dot(clip_equation, modelMatrix * orient * vertex);
} else {
gl_ClipDistance[0] = 1.0;
}
vertOut.position = position;
vertOut.normal = normal;
+12 -13
View File
@@ -1,20 +1,14 @@
#ifdef GL_ES
precision highp float;
precision highp int;
precision highp sampler2DMS;
#endif
#include "z-compress.sdr"
#ifdef VULKAN
layout(location = 0) in vec2 fragTexCoord;
layout(location = 0) out vec4 fragOut0;
layout(location = 1) out vec4 fragOut1;
layout(location = 2) out vec4 fragOut2;
layout(location = 3) out vec4 fragOut3;
layout(location = 4) out vec4 fragOut4;
#ifdef VULKAN
layout(location = 0) in vec2 fragTexCoord;
layout(set = 1, binding = 1) uniform sampler2DMS msaaTex[6];
#define texColor msaaTex[0]
#define texPos msaaTex[1]
@@ -29,7 +23,12 @@ layout(std140, set = 2, binding = 0) uniform genericData {
};
#else
in vec4 fragTexCoord;
layout(location=5)out vec4 fragOut5;
out vec4 fragOut0;
out vec4 fragOut1;
out vec4 fragOut2;
out vec4 fragOut3;
out vec4 fragOut4;
out vec4 fragOut5;
uniform sampler2DMS texColor;
uniform sampler2DMS texPos;
@@ -177,7 +176,7 @@ float getMedianDist(ivec2 texel) {
//Fallback, do front first
float getMedianDist(ivec2 texel) {
float minDist = -1000000.0;
float minDist = -1000000;
for(int i = 0; i < samples; i++) {
minDist = max(minDist, uncompress_depth_value(texelFetch(texPos, texel, i).z));
}
@@ -191,7 +190,7 @@ float getMedianDist(ivec2 texel) {
void main()
{
vec2 texSize = vec2(textureSize(texColor));
vec2 texSize = textureSize(texColor);
#ifdef VULKAN
ivec2 texel = ivec2(texSize * fragTexCoord);
#else
@@ -207,7 +206,7 @@ void main()
vec4 normal = vec4(0);
vec4 specular = vec4(0);
vec4 emissive = vec4(0);
float depth = 0.0;
float depth = 0;
for(int i = 0; i < SAMPLE_CNT; i++) {
vec4 localPos = texelFetch(texPos, texel, i);
-5
View File
@@ -1,8 +1,3 @@
#ifdef GL_ES
precision highp float;
precision highp int;
precision highp sampler2DArray;
#endif
#ifdef VULKAN
layout (location = 0) in vec2 ftcoord;
-4
View File
@@ -1,7 +1,3 @@
#ifdef GL_ES
precision highp float;
precision highp int;
#endif
#ifdef VULKAN
layout (location = 0) in vec4 vertPosition;
+1 -1
View File
@@ -7,6 +7,6 @@
vec3 unpackNormal(vec2 normal_sample) {
vec3 normal;
normal.xy = normal_sample * 2.0 - 1.0;
normal.z = sqrt(1.0 - normal_sample.x * normal_sample.x - normal_sample.y * normal_sample.y);
normal.z = sqrt(1 - normal_sample.x * normal_sample.x - normal_sample.y * normal_sample.y);
return normal;
}
@@ -1,14 +1,9 @@
#ifdef GL_ES
precision highp float;
precision highp int;
precision highp sampler2D;
#endif
#include "gamma.sdr"
in vec4 fragTexCoord;
in vec4 fragColor;
layout(location=0) out vec4 fragOut0;
out vec4 fragOut0;
uniform sampler2D baseMap;
+2 -7
View File
@@ -1,16 +1,11 @@
#ifdef GL_ES
precision highp float;
precision highp sampler2D;
#endif
layout(location = 0) out vec4 fragOut0;
#ifdef VULKAN
layout(location = 0) in vec2 fragTexCoord;
layout(location = 0) out vec4 fragOut0;
layout(set = 1, binding = 1) uniform sampler2D tex;
layout(set = 1, binding = 4) uniform sampler2D depth_tex;
#else
in vec4 fragTexCoord;
out vec4 fragOut0;
uniform sampler2D tex;
uniform sampler2D depth_tex;
#endif
+3 -8
View File
@@ -1,17 +1,10 @@
#ifdef GL_ES
precision highp float;
precision highp int;
precision highp sampler2DArray;
#endif
layout(location = 0) out vec4 fragOut0;
#ifdef VULKAN
layout(location = 0) in vec2 fragTexCoord;
layout(location = 1) in vec4 fragColor;
layout(location = 2) in vec2 fragScreenPosition;
layout(location = 0) out vec4 fragOut0;
layout(set = 1, binding = 1) uniform sampler2DArray baseMap;
#else
@@ -19,6 +12,8 @@ in vec2 fragTexCoord;
in vec4 fragColor;
in vec2 fragScreenPosition;
out vec4 fragOut0;
uniform sampler2DArray baseMap;
#endif
@@ -1,7 +1,3 @@
#ifdef GL_ES
precision highp float;
precision highp int;
#endif
#ifdef VULKAN
layout(location = 0) in vec2 vertPosition;
@@ -1,24 +1,5 @@
//? #version 150
#ifdef GL_ES
#extension GL_EXT_clip_cull_distance: enable
precision highp float;
#endif
#ifdef SDR_FLAG_SW_CLIP_FALLBACK
#ifdef VULKAN
layout(location = 0) in VertexOutput {
float vClipDist;
} vertIn;
#else
in VertexOutput {
float vClipDist;
} vertIn;
#endif
#endif
void main()
{
#ifdef SDR_FLAG_SW_CLIP_FALLBACK
if (vertIn.vClipDist < 0.0) discard;
#endif
}
+4 -25
View File
@@ -1,16 +1,9 @@
//? #version 150
#ifdef GL_ES
#extension GL_EXT_gpu_shader5: enable
#extension GL_EXT_clip_cull_distance: enable
precision highp float;
precision highp int;
#else
#extension GL_ARB_gpu_shader5: enable
#endif
layout (triangles) in;
layout (triangle_strip, max_vertices = 3) out;
#if defined(GL_ARB_gpu_shader5) || defined(GL_EXT_gpu_shader5)
#ifdef GL_ARB_gpu_shader5
layout(invocations = NUM_SHADOW_CASCADES) in;
#endif
@@ -31,25 +24,16 @@ layout (std140) uniform shadowCascadeParams {
};
in VertexOutput {
#if !defined(GL_ARB_gpu_shader5) && !defined(GL_EXT_gpu_shader5)
#if !defined(GL_ARB_gpu_shader5)
float instance;
#endif
float clipModel;
vec3 normal;
#ifdef SDR_FLAG_SW_CLIP_FALLBACK
float vClipDist;
#endif
} vertIn[];
#ifdef SDR_FLAG_SW_CLIP_FALLBACK
out VertexOutput {
float vClipDist;
} vertOut;
#endif
void main(void)
{
#if defined(GL_ARB_gpu_shader5) || defined(GL_EXT_gpu_shader5)
#ifdef GL_ARB_gpu_shader5
if (gl_InvocationID >= cascade_count) return;
int cascade_id = cascade_offset + gl_InvocationID;
#else
@@ -65,12 +49,7 @@ void main(void)
}
gl_Layer = cascade_id;
#ifdef SDR_FLAG_SW_CLIP_FALLBACK
vertOut.vClipDist = vertIn[vert].vClipDist;
#else
gl_ClipDistance[0] = gl_in[vert].gl_ClipDistance[0];
#endif
gl_ClipDistance[0] = gl_in[vert].gl_ClipDistance[0];
EmitVertex();
}
+3 -31
View File
@@ -1,16 +1,9 @@
//? #version 150
#ifdef GL_ES
#extension GL_EXT_gpu_shader5: enable
#extension GL_EXT_clip_cull_distance: enable
precision highp float;
precision highp int;
precision highp samplerBuffer;
#else
#extension GL_ARB_gpu_shader5: enable
#ifndef GEOMETRY_FALLBACK
#extension GL_ARB_shader_viewport_layer_array : enable
#endif
#endif
#ifdef VULKAN
layout(location = 0) in vec4 vertPosition;
@@ -73,25 +66,12 @@ uniform samplerBuffer transform_tex;
// supports writing gl_Layer from the vertex shader, see CAPABILITY_FAST_SHADOWS).
#ifdef GEOMETRY_FALLBACK
out VertexOutput {
#if !defined(GL_ARB_gpu_shader5) && !defined(GL_EXT_gpu_shader5)
#if !defined(GL_ARB_gpu_shader5)
float instance;
#endif
float clipModel;
vec3 normal;
#ifdef SDR_FLAG_SW_CLIP_FALLBACK
float vClipDist;
#endif
} vertOut;
#elif defined(SDR_FLAG_SW_CLIP_FALLBACK)
#ifdef VULKAN
layout(location = 0) out VertexOutput {
float vClipDist;
} vertOut;
#else
out VertexOutput {
float vClipDist;
} vertOut;
#endif
#endif
#define TEXELS_PER_MATRIX 4
@@ -132,7 +112,7 @@ void main()
#ifdef VULKAN
int instanceIndex = gl_InstanceIndex;
#else
#if !defined(GL_ARB_gpu_shader5) && !defined(GL_EXT_gpu_shader5)
#if !defined(GL_ARB_gpu_shader5)
#ifdef APPLE
vertOut.instance = float(gl_InstanceIDARB);
#else
@@ -153,19 +133,11 @@ void main()
gl_Position = position;
}
#ifndef SDR_FLAG_SW_CLIP_FALLBACK
if (use_clip_plane != 0) {
gl_ClipDistance[0] = dot(clip_equation, modelMatrix * orient * vertex);
} else {
gl_ClipDistance[0] = 1.0;
}
#else
if (use_clip_plane != 0) {
vertOut.vClipDist = dot(clip_equation, modelMatrix * orient * vertex);
} else {
vertOut.vClipDist = 1.0;
}
#endif
#ifdef GEOMETRY_FALLBACK
vertOut.normal = normal;
@@ -1,22 +1,21 @@
#ifdef GL_ES
precision highp float;
precision highp int;
precision highp sampler2DArray;
#endif
#include "gamma.sdr"
const float EMISSIVE_GAIN = 2.0;
layout(location = 0) out vec4 fragOut0;
#ifdef VULKAN
layout(location = 0) in vec4 fragImpactUV;
layout(location = 1) in float fragNormOffset;
layout(location = 0) out vec4 fragOut0;
layout(set = 1, binding = 1) uniform sampler2DArray shieldMap;
#else
in vec4 fragImpactUV;
in float fragNormOffset;
out vec4 fragOut0;
uniform sampler2DArray shieldMap;
#endif
@@ -1,7 +1,3 @@
#ifdef GL_ES
precision highp float;
precision highp int;
#endif
#ifdef VULKAN
layout(location = 0) in vec4 vertPosition;
+4 -6
View File
@@ -1,7 +1,3 @@
#ifdef GL_ES
precision highp float;
precision highp sampler2D;
#endif
#ifdef VULKAN
layout(std140, set = 2, binding = 0) uniform genericData {
@@ -20,13 +16,13 @@ layout (std140) uniform genericData {
#include "SMAA.sdr"
layout(location=0) out vec4 fragOut0;
#ifdef VULKAN
layout(location = 0) in vec2 fragTexCoord;
layout(location = 1) in vec2 fragPixcoord;
layout(location = 2) in vec4 fragOffset[3];
layout(location = 0) out vec4 fragOut0;
// [0]=edgesTex, [1]=areaTex, [2]=searchTex
layout(set = 1, binding = 1) uniform sampler2D smaaTex[3];
#define edgesTex smaaTex[0]
@@ -37,6 +33,8 @@ in vec2 fragTexCoord;
in vec2 fragPixcoord;
in vec4 fragOffset[3];
out vec4 fragOut0;
uniform sampler2D edgesTex;
uniform sampler2D areaTex;
uniform sampler2D searchTex;
+4 -6
View File
@@ -1,7 +1,3 @@
#ifdef GL_ES
precision highp float;
precision highp sampler2D;
#endif
#ifdef VULKAN
layout(std140, set = 2, binding = 0) uniform genericData {
@@ -20,17 +16,19 @@ layout (std140) uniform genericData {
#include "SMAA.sdr"
layout(location = 0) out vec4 fragOut0;
#ifdef VULKAN
layout(location = 0) in vec2 fragTexCoord;
layout(location = 1) in vec4 fragOffset[3];
layout(location = 0) out vec4 fragOut0;
layout(set = 1, binding = 1) uniform sampler2D colorTex;
#else
in vec2 fragTexCoord;
in vec4 fragOffset[3];
out vec4 fragOut0;
uniform sampler2D colorTex;
#endif
@@ -1,7 +1,3 @@
#ifdef GL_ES
precision highp float;
precision highp sampler2D;
#endif
#ifdef VULKAN
layout(std140, set = 2, binding = 0) uniform genericData {
@@ -20,12 +16,11 @@ layout (std140) uniform genericData {
#include "SMAA.sdr"
layout(location = 0) out vec4 fragOut0;
#ifdef VULKAN
layout(location = 0) in vec2 fragTexCoord;
layout(location = 1) in vec4 fragOffset;
layout(location = 0) out vec4 fragOut0;
// [0]=colorTex, [1]=blendTex
layout(set = 1, binding = 1) uniform sampler2D smaaTex[2];
@@ -35,6 +30,8 @@ layout(set = 1, binding = 1) uniform sampler2D smaaTex[2];
in vec2 fragTexCoord;
in vec4 fragOffset;
out vec4 fragOut0;
uniform sampler2D colorTex;
uniform sampler2D blendTex;
#endif
@@ -1,15 +1,10 @@
#ifdef GL_ES
precision highp float;
precision highp sampler2D;
#endif
layout(location = 0) out vec4 fragOut0;
#ifdef VULKAN
layout(location = 0) in vec2 fragTexCoord;
layout(location = 0) out vec4 fragOut0;
layout(set = 1, binding = 1) uniform sampler2D tex;
#else
in vec4 fragTexCoord;
out vec4 fragOut0;
uniform sampler2D tex;
#endif
@@ -1,18 +1,13 @@
#ifdef GL_ES
precision highp float;
precision highp int;
precision highp sampler2D;
#endif
#include "gamma.sdr"
layout(location=0) out vec4 fragOut0;
#ifdef VULKAN
layout(location = 0) in vec2 fragTexCoord;
layout(location = 0) out vec4 fragOut0;
layout(set = 1, binding = 1) uniform sampler2D tex;
#else
in vec4 fragTexCoord;
out vec4 fragOut0;
uniform sampler2D tex;
#endif
+2 -7
View File
@@ -1,12 +1,6 @@
#ifdef GL_ES
precision highp float;
precision highp sampler2DArray;
#endif
layout(location = 0) out vec4 fragOut0;
#ifdef VULKAN
layout(location = 0) in vec4 fragTexCoord;
layout(location = 0) out vec4 fragOut0;
layout(set = 1, binding = 1) uniform sampler2DArray textures[16];
#define ytex textures[0]
@@ -14,6 +8,7 @@ layout(set = 1, binding = 1) uniform sampler2DArray textures[16];
#define vtex textures[2]
#else
in vec4 fragTexCoord;
out vec4 fragOut0;
uniform sampler2DArray ytex;
uniform sampler2DArray utex;
uniform sampler2DArray vtex;
+13 -28
View File
@@ -1,14 +1,7 @@
#ifdef GL_ES
precision highp float;
precision highp int;
precision highp sampler2D;
precision highp sampler3D;
#endif
layout(location = 0) out vec4 fragOut0;
#ifdef VULKAN
layout(location = 0) in vec2 fragTexCoord;
layout(location = 0) out vec4 fragOut0;
layout(set = 1, binding = 1) uniform sampler2D tex2D[16];
#define composite tex2D[0]
#define emissive tex2D[1]
@@ -17,7 +10,7 @@ layout(set = 1, binding = 5) uniform sampler3D volume_tex;
layout(set = 1, binding = 6) uniform sampler3D noise_volume_tex;
#else
in vec4 fragTexCoord;
out vec4 fragOut0;
layout (binding = 0) uniform sampler2D composite;
layout (binding = 1) uniform sampler2D emissive;
layout (binding = 2) uniform sampler2D depth_tex;
@@ -84,7 +77,7 @@ void main()
#else
vec4 eyeDirection = p_inv * vec4(fragTexCoord.xy * 2.0 - 1.0, -1, 1);
#endif
eyeDirection.w = 0.0;
eyeDirection.w = 0;
vec3 rayDirection = normalize((v_inv * eyeDirection).xyz);
vec4 color_in = texture(composite, fragTexCoord.xy);
@@ -110,14 +103,14 @@ void main()
#endif
//The t at which the ray enters the nebula cube
float maxtMin = max(0.0, max(tMin.x, max(tMin.y, tMin.z)));
float maxtMin = max(0,max(tMin.x, max(tMin.y, tMin.z)));
//The t at which the ray leaves the nebula cube
float mintMax = min(fragDepth, min(tMax.x, min(tMax.y, tMax.z)));
//The cumulative one minus alpha value of the nebula. Corresponds to the multiplier of the current step when additively drawing to a fragment for which the steps closer to the camera are already drawn.
float cumOMAlpha = 1.0;
float cumOMAlpha = 1;
//The cumulative distance already travelled through the nebula.
float cumnebdist = 0.0;
float cumnebdist = 0;
//The color of the current fragment
vec3 cumcolor = vec3(0, 0, 0);
@@ -128,14 +121,6 @@ void main()
vec3 sidestep = 1.0 / vec3(textureSize(volume_tex, 0));
#ifdef GL_ES
// The emissive texture has a complete mip chain generated by the engine.
ivec2 emissiveSize = textureSize(emissive, 0);
float maxEmissiveLod = float(findMSB(max(emissiveSize.x, emissiveSize.y)));
#else
float maxEmissiveLod = float(textureQueryLevels(emissive) - 1);
#endif
for(float stept = maxtMin; stept < mintMax;) {
//Step setup
vec3 position = camera + rayDirection * stept - nebPos;
@@ -174,7 +159,7 @@ void main()
#ifdef NOISE
//Mix the actual nebula color with the noise color depending on the product of the noise channels multiplied with intensity, smooth-clamped from 0 to 1
vec3 stepcolor_neb = mix(nebulaColor, noiseColor,
smoothstep(0.0, 1.0, (textureGrad(noise_volume_tex, position / noiseColorScale1, gradX, gradY).r + textureGrad(noise_volume_tex, position / noiseColorScale2, gradX, gradY).g) / 2.0 * noiseIntensity));
smoothstep(0, 1, (textureGrad(noise_volume_tex, position / noiseColorScale1, gradX, gradY).r + textureGrad(noise_volume_tex, position / noiseColorScale2, gradX, gradY).g) / 2.0 * noiseIntensity));
#else
vec3 stepcolor_neb = nebulaColor;
#endif
@@ -184,19 +169,19 @@ void main()
//From the current position in the volumetric cloud, sample towards the sun to test whether or not the current part of the nebula is bright or not
for(int dlstep = 1; dlstep <= directionalLightSampleSteps; dlstep++){
//TODO Sample these in a cone towards the sun, not just a line. Also add the high-distance sample for concave nebulae
vec3 dlsteppos = (position - globalLightDirection * (float(dlstep) * directionalLightStepSize)) / nebSize + 0.5;
float dlstepalpha = textureGrad(volume_tex, dlsteppos, gradX, gradY).a * step(0.0, dlsteppos.x) * step(dlsteppos.x, 1.0) * step(0.0, dlsteppos.y) * step(dlsteppos.y, 1.0) * step(0.0, dlsteppos.z) * step(dlsteppos.z, 1.0);
vec3 dlsteppos = (position - globalLightDirection * (dlstep * directionalLightStepSize)) / nebSize + 0.5;
float dlstepalpha = textureGrad(volume_tex, dlsteppos, gradX, gradY).a * step(0, dlsteppos.x) * step(dlsteppos.x, 1) * step(0, dlsteppos.y) * step(dlsteppos.y, 1) * step(0, dlsteppos.z) * step(dlsteppos.z, 1);
directionalLightDepth += dlstepalpha * directionalLightStep;
}
stepcolor_diffuse *= beer_powder_norm * (1.0 - exp(-directionalLightDepth * 2.0)) * exp(-directionalLightDepth);
stepcolor_diffuse *= beer_powder_norm * (1 - exp(-directionalLightDepth * 2.0)) * exp(-directionalLightDepth);
//Emissive
cumnebdist += stepcolor_alpha * stepsize_current;
vec3 emissive_lod = textureLod(emissive, fragTexCoord.xy, clamp(cumnebdist * emissiveSpreadFactor, 0.0, maxEmissiveLod)).rgb;
vec3 stepcolor_emissive = clamp(emissive_lod.rgb * pow(alphalim, 1.0 / (opacitydistance / ((fragDepth - stept) * emissiveFalloff + 0.01))) * emissiveIntensity, 0.0, 1.0);
vec3 emissive_lod = textureLod(emissive, fragTexCoord.xy, clamp(cumnebdist * emissiveSpreadFactor, 0, float(textureQueryLevels(emissive) - 1))).rgb;
vec3 stepcolor_emissive = clamp(emissive_lod.rgb * pow(alphalim, 1.0 / (opacitydistance / ((fragDepth - stept) * emissiveFalloff + 0.01))) * emissiveIntensity, 0, 1);
//Step finish
vec3 stepcolor = clamp(stepcolor_diffuse + stepcolor_emissive, 0.0, 1.0);
vec3 stepcolor = clamp(stepcolor_diffuse + stepcolor_emissive, 0, 1);
cumcolor += stepalpha * cumOMAlpha * stepcolor;
}
+1 -1
View File
@@ -381,7 +381,7 @@ int __cdecl RecordExceptionInfo(PEXCEPTION_POINTERS data, const char *Message)
wsprintf(DebugMessage, "%s location %08x caused an access violation.\r\n", readwrite, Exception->ExceptionInformation[1]);
#ifndef NDEBUG
#ifdef _DEBUG
// The VisualC++ debugger doesn't actually tell you whether a read
// or a write caused the access violation, nor does it tell what
// address was being read or written. So I fixed that.
-17
View File
@@ -28,23 +28,6 @@ protected:
return FALSE;
m_library = SDL_LoadObject(externlib);
#ifdef __ANDROID__
if (m_library == NULL) {
auto android_path = SDL_GetAndroidInternalStoragePath();
if (android_path != nullptr) {
SCP_string android_full_path = android_path;
if (android_full_path.back() != DIR_SEPARATOR_CHAR) {
android_full_path += DIR_SEPARATOR_CHAR;
}
android_full_path += SCP_string("natives") + DIR_SEPARATOR_CHAR + externlib;
#ifndef NDEBUG
mprintf(("Calling SDL_LoadObject with the following path: '%s'\n", android_full_path.c_str()));
#endif
m_library = SDL_LoadObject(android_full_path.c_str());
}
}
#endif
// check full path as a fallback for our own libraries
// NOTE: basePath is assumed to have a trailing slash!
+2 -29
View File
@@ -289,11 +289,7 @@ GraphicsAPI gr_get_configured_render_api()
#endif
#ifndef __ANDROID__
os::ViewportState Gr_configured_window_state = os::ViewportState::Fullscreen;
#else
os::ViewportState Gr_configured_window_state = os::ViewportState::Borderless;
#endif
static bool mode_change_func(os::ViewportState state, bool initial)
{
@@ -2188,30 +2184,7 @@ bool gr_init(std::unique_ptr<os::GraphicsOperations>&& graphicsOps, GraphicsAPI
//
// As such, window_res is effectively no longer optional, part of the core render path and must always be enabled.
// The only reason it is not yet refactored into an always-on thing is due to issues with FRED integration.
int window_width = width;
int window_height = height;
// In exclusive fullscreen, the window must match the monitor. Using the render resolution instead would require a
// video mode switch to that resolution, which may not exist as a display mode (leaving the window at a different
// size than window_res) and is repeated on every alt-tab.
if (!gr_is_viewport_window()) {
if (SDL_InitSubSystem(SDL_INIT_VIDEO)) {
auto displayMode = SDL_GetDesktopDisplayMode(gr_get_preferred_display());
if (displayMode) {
window_width = displayMode->w;
window_height = displayMode->h;
} else {
mprintf(("Could not query desktop display mode for fullscreen window size: %s\n", SDL_GetError()));
}
SDL_QuitSubSystem(SDL_INIT_VIDEO);
} else {
mprintf(("Could not initialize SDL video for fullscreen window size: %s\n", SDL_GetError()));
}
}
mprintf(("Forcing window_res to %dx%d (render resolution %dx%d)\n", window_width, window_height, width, height));
Cmdline_window_res.emplace(static_cast<uint16_t>(window_width), static_cast<uint16_t>(window_height));
Cmdline_window_res.emplace(static_cast<uint16_t>(width), static_cast<uint16_t>(height));
}
if (d_mode == GraphicsAPI::Default) {
@@ -2282,7 +2255,7 @@ bool gr_init(std::unique_ptr<os::GraphicsOperations>&& graphicsOps, GraphicsAPI
// built in debug mode. This helps if you run with the debugger active as the
// game won't be switching from fullscreen to minimized every time you hit a breakpoint or
// warning message.
#ifndef NDEBUG
#ifdef _DEBUG
#ifdef _FORCE_DEBUG_WIDESCREEN
width = 1280;
height = 800;
+3 -4
View File
@@ -32,7 +32,6 @@
#define GL_CLAMP_VERTEX_COLOR 0x891A
#define GL_CLAMP_FRAGMENT_COLOR 0x891B
#define GL_FIXED_ONLY 0x891D
#define GLAD_GL_ARB_shader_viewport_layer_array 0 // Disabled, no gl_layer in vertex shader //0x8DAE
//Enums Redefinitions
#define GL_CLIP_DISTANCE0 GL_CLIP_DISTANCE0_EXT // GL_EXT_clip_cull_distance
@@ -49,7 +48,6 @@
#define GLAD_GL_ARB_texture_storage GL_TRUE // ES 3.2
#define GLAD_GL_ARB_draw_buffers_blend GL_TRUE // ES 3.2 (glBlendFunci and glBlendEquationi)
#define GLAD_GL_ARB_vertex_attrib_binding GL_TRUE // ES 3.1
#define GL_DEPTH_CLAMP GL_DEPTH_CLAMP_EXT
//Functions Redefinitions
#define glBlendFunciARB glBlendFunci // ES 3.2
@@ -236,7 +234,9 @@ inline void glDrawBuffer(GLenum buf)
}
}
// ES uses layout(location = ) directly on shader
// does not exist on ES, ES uses layout(location=) directly on shader
// Notes:
// -This function is not required to run.
#define glBindFragDataLocation(program, colorNumber, name) ((void)0)
// glPolygonMode() is not supported on ES, no wireframe, GL_FILL is default, GL_POINTS, and GL_LINES needs an alternative path
@@ -254,7 +254,6 @@ static inline void glQueryCounter(GLuint id, GLenum target)
#else
(void)id;
#endif
(void)target;
}
// glGetCompressedTexImage not present on GLES and no equivalent
+4 -6
View File
@@ -6,7 +6,7 @@
#include <direct.h>
#endif
#if !defined __APPLE_CC__ && !defined __ANDROID__ && defined SCP_UNIX
#if !defined __APPLE_CC__ && defined SCP_UNIX
#include<glad/glad_glx.h>
//Required because X defines none and always, which is used later
#undef None
@@ -956,7 +956,7 @@ void gr_opengl_use_viewport(os::Viewport* view) {
int opengl_init_display_device()
{
os::ViewPortProperties attrs = {};
os::ViewPortProperties attrs;
attrs.enable_opengl = true;
attrs.gl_attributes.major_version = MIN_REQUIRED_GL_VERSION / 10;
@@ -1394,7 +1394,7 @@ bool gr_opengl_init(std::unique_ptr<os::GraphicsOperations>&& graphicsOps)
Error(LOCATION, "Failed to load OpenGL!");
}
#if !defined __APPLE_CC__ && !defined __ANDROID__ && defined SCP_UNIX
#if !defined __APPLE_CC__ && defined SCP_UNIX
if (!gladLoadGLXLoader(GL_context->getLoaderFunction(), nullptr, 0)) {
Error(LOCATION, "Failed to load GLX!");
}
@@ -1453,9 +1453,7 @@ bool gr_opengl_init(std::unique_ptr<os::GraphicsOperations>&& graphicsOps)
"Deferred lightning is enabled in settings but the gpu does not support the minimum of 6 draw buffers. "
"This will result in rendering errors.");
}
mprintf((" Depth Clamp support : %s\n", GLAD_GL_EXT_depth_clamp ? NOX("YES") : NOX("NO")));
mprintf((" HW Cull distance support : %s\n", GLAD_GL_EXT_clip_cull_distance ? NOX("YES") : NOX("NO")));
mprintf((" Precompiled shaders support : %s\n", GLAD_GL_OES_get_program_binary ? NOX("YES") : NOX("NO")));
mprintf((" Immutable buffer storage support : %s\n", GLAD_GL_EXT_buffer_storage ? NOX("YES") : NOX("NO")));
mprintf((" BGRA8888 format support: %s\n", GLAD_GL_EXT_texture_format_BGRA8888 ? NOX("YES") : NOX("NO")));
+1 -1
View File
@@ -72,7 +72,7 @@ bool gr_opengl_openxr_test_capabilities() {
#ifdef WIN32
bool gr_opengl_openxr_create_session() {
auto hdc = static_cast<HDC>(SDL_GetPointerProperty(SDL_GetWindowProperties(os::getSDLMainWindow()),
SDL_PROP_WINDOW_WIN32_HDC_POINTER,
SDL_PROP_WINDOW_WIN32_HWND_POINTER,
nullptr));
XrGraphicsBindingOpenGLWin32KHR graphicsBinding{
-10
View File
@@ -178,20 +178,10 @@ static SCP_string opengl_shader_get_header(shader_type type_id, int flags, bool
#ifndef USE_OPENGL_ES
sflags << "#version " << GLSL_version << " core\n";
if (GLSL_version < 330) {
sflags << "#extension GL_ARB_explicit_attrib_location : enable\n";
}
#else
sflags << "#version " << GLSL_version << " es\n";
#endif
sflags << "#define OPENGL\n";
#ifdef USE_OPENGL_ES
if (!GLAD_GL_EXT_clip_cull_distance) {
sflags << "#define SDR_FLAG_SW_CLIP_FALLBACK\n";
}
#endif
sflags << shader_get_shadow_cascade_defines();
sflags << shader_get_rt_shadow_light_limit_define();
-7
View File
@@ -360,13 +360,6 @@ GLboolean opengl_state::ClipDistance(GLint num, bool state)
GLboolean save_state = clipdistance_Status[num];
#ifdef USE_OPENGL_ES
if (!GLAD_GL_EXT_clip_cull_distance) {
clipdistance_Status[num] = state;
return save_state;
}
#endif
if (state != clipdistance_Status[num]) {
if (state) {
glEnable(GL_CLIP_DISTANCE0+num);
-18
View File
@@ -732,13 +732,7 @@ void gr_opengl_shadow_map_start(matrix4 *shadow_view_matrix, const matrix *light
glClear(GL_DEPTH_BUFFER_BIT);
#ifdef USE_OPENGL_ES
if (GLAD_GL_EXT_depth_clamp) {
glEnable(GL_DEPTH_CLAMP);
}
#else
glEnable(GL_DEPTH_CLAMP);
#endif
Glowpoint_override_save = Glowpoint_override;
Glowpoint_override = true;
@@ -759,13 +753,7 @@ void gr_opengl_shadow_map_end()
{
gr_end_view_matrix();
#ifdef USE_OPENGL_ES
if (GLAD_GL_EXT_depth_clamp) {
glDisable(GL_DEPTH_CLAMP);
}
#else
glDisable(GL_DEPTH_CLAMP);
#endif
gr_zbuffer_set(ZBUFFER_TYPE_FULL);
GL_state.PopFramebufferState();
@@ -1148,12 +1136,6 @@ void opengl_tnl_set_material_nanovg(nanovg_material* material_info) {
void opengl_tnl_set_material_decal(decal_material* material_info) {
opengl_tnl_set_material(material_info, false);
#ifdef USE_OPENGL_ES
// ES decal outputs use G-buffer locations instead of packed draw-buffer indices.
GL_state.SetAlphaBlendModei(2, material_info->get_blend_mode(1));
GL_state.SetAlphaBlendModei(4, material_info->get_blend_mode(2));
#endif
float u_scale, v_scale;
uint32_t array_index;
-20
View File
@@ -75,27 +75,7 @@ void openxr_prepare(float hudscale) {
openxr_req = true;
}
static void openxr_check_api_layers() {
uint32_t layerCount = 0;
if (xrEnumerateApiLayerProperties(0, &layerCount, nullptr) != XR_SUCCESS || layerCount == 0)
return;
SCP_vector<XrApiLayerProperties> layers(layerCount, XrApiLayerProperties { XR_TYPE_API_LAYER_PROPERTIES, nullptr, "", 0, 0, "" });
if (xrEnumerateApiLayerProperties(layerCount, &layerCount, layers.data()) != XR_SUCCESS)
return;
for (const auto& layer : layers) {
mprintf(("OpenXR API layer: %s (version %u)\n", layer.layerName, layer.layerVersion));
if (!strcmp(layer.layerName, "XR_APILAYER_NOVENDOR_toolkit")) {
ReleaseWarning(LOCATION, "OpenXR Toolkit is installed and active. There are known compatibility issues with FSO that will likely crash the game.\nPlease disable or uninstall OpenXR Toolkit to use VR with FSO.");
}
}
}
static bool openxr_init_instance() {
openxr_check_api_layers();
auto extensions = gr_openxr_get_extensions();
const gameversion::version& fso_version = gameversion::get_executable_version();
-13
View File
@@ -162,19 +162,6 @@ static ShaderVariantInfo SHADER_VARIANTS[] = {
{SDR_TYPE_SHADOW_MAP_GEN, true, SDR_FLAG_SHADOW_FALLBACK, "GEOMETRY_FALLBACK", {}, "Use a geometry shader to select the cascade layer instead of writing gl_Layer from the vertex shader"}
};
static_assert(VATTRIB_MODEL_MATRIX + 4 <= 32, "vertex input mask is 32 bits wide");
uint32_t shader_vertex_input_mask(const ShaderTypeInfo& info)
{
uint32_t mask = 0;
for (auto attr : info.attributes) {
// The Vulkan pipeline drops every location the mask omits, so a mat4 needs all four of its bits.
const uint32_t locations = (attr == VATTRIB_MODEL_MATRIX) ? 4u : 1u;
mask |= ((1u << locations) - 1u) << attr;
}
return mask;
}
const ShaderTypeInfo* shader_get_type_info(shader_type type)
{
for (auto & i : SHADER_TYPES) {
-8
View File
@@ -55,14 +55,6 @@ const ShaderTypeInfo* shader_get_type_info(shader_type type);
// Lookup helper: find variant info by (type, flag). Returns nullptr if not found.
const ShaderVariantInfo* shader_get_variant_info(shader_type type, int flag);
/**
* @brief Bitmask of the vertex attribute locations a shader type reads.
*
* One bit per location; VATTRIB_MODEL_MATRIX contributes bits 8-11 because a
* mat4 input occupies four consecutive locations.
*/
uint32_t shader_vertex_input_mask(const ShaderTypeInfo& info);
// Iterate all variants matching type whose flag bit is set in flags.
void shader_for_each_active_variant(shader_type type, unsigned int flags, const std::function<void(const ShaderVariantInfo&)>& fn);
-4
View File
@@ -271,9 +271,6 @@ void vulkan_deferred_lighting_begin(bool clearNonColorBufs)
void vulkan_deferred_lighting_msaa()
{
if (!Deferred_lighting) {
return;
}
if (Cmdline_msaa_enabled <= 0) {
return;
}
@@ -959,7 +956,6 @@ void vulkan_render_decals(decal_material* material_info,
// Build pipeline config for decal rendering
PipelineConfig config;
config.shaderType = SDR_TYPE_DECAL;
config.shaderFlags = material_info->get_shader_flags();
config.primitiveType = prim_type;
config.depthMode = material_info->get_depth_mode();
config.depthWriteEnabled = false;
+5 -6
View File
@@ -748,7 +748,7 @@ void VulkanDrawManager::renderShadowDraw(gr_buffer_handle ubo_handle, size_t ubo
}
stateTracker->bindPipeline(pipeline, pipelineManager->getPipelineLayout());
stateTracker->setDepthBias(1024.0f, 1.0f); // GL shadow pass: gr_zbias(-1024) = polygon offset factor 1, units 1024
stateTracker->setDepthBias(-1024.0f, 0.0f);
// Bind descriptor sets: shadowMapData (per-draw) and shadowCascadeParams
// (bound separately, per-frame, via shadow_cascade_params_bind) both live in
@@ -1281,10 +1281,6 @@ bool VulkanDrawManager::applyMaterial(material* mat, primitive_type prim_type, v
m_frameStats.applyMaterialCalls++;
// Like opengl_tnl_set_material(), every material draw sets the texture addressing (e.g. MR_FORCE_CLAMP skyboxes)
setTextureAddressing(mat->get_texture_addressing());
vulkan_zbias(mat->get_depth_bias());
// Build pipeline configuration from material
PipelineConfig config = buildPipelineConfig(mat, prim_type);
@@ -1484,6 +1480,9 @@ bool VulkanDrawManager::applyMaterial(material* mat, primitive_type prim_type, v
stateTracker->setStencilMode(GR_STENCIL_NONE);
}
// Set depth bias if needed
stateTracker->setDepthBias(static_cast<float>(mat->get_depth_bias()), 0.0f);
return true;
}
@@ -1541,7 +1540,7 @@ void VulkanDrawManager::draw(primitive_type prim_type, int first_vertex, int ver
m_frameStats.totalVertices += vertex_count;
// Flush any dirty dynamic state (viewport, scissor, depth bias, stencil ref)
// before issuing the draw command. applyMaterial sets some of these AFTER bindPipeline,
// before issuing the draw command. applyMaterial sets these AFTER bindPipeline,
// so they may be dirty even when the pipeline didn't change.
stateTracker->applyDynamicState();
+6 -9
View File
@@ -98,7 +98,8 @@ void vulkan_set_default_material_uniforms(material* material_info)
(clip_plane.normal.xyz.y * clip_plane.position.xyz.y) +
(clip_plane.normal.xyz.z * clip_plane.position.xyz.z));
data->modelMatrix = gr_model_matrix_stack.get_transform();
// Model matrix (identity for now, material doesn't provide one)
vm_matrix4_set_identity(&data->modelMatrix);
} else {
data->clipEnabled = 0;
vm_matrix4_set_identity(&data->modelMatrix);
@@ -612,9 +613,6 @@ void vulkan_calculate_irrmap()
}
// Get envmap cubemap view
if (!texManager->ensureCubemapUploaded(ENVMAP)) {
return;
}
auto* envSlot = bm_get_slot(ENVMAP, true);
if (!envSlot || !envSlot->gr_info) {
return;
@@ -640,6 +638,9 @@ void vulkan_calculate_irrmap()
vk::CommandBuffer cmd = stateTracker->getCommandBuffer();
// End the current swap chain render pass
cmd.endRenderPass();
// Create pipeline for irradiance map generation
PipelineConfig config;
config.shaderType = SDR_TYPE_IRRADIANCE_MAP_GEN;
@@ -710,9 +711,6 @@ void vulkan_calculate_irrmap()
vk::Extent2D irrExtent(irrTs->width, irrTs->height);
// End the swap chain pass only after the early returns above, which never resume it
cmd.endRenderPass();
for (size_t face = 0; face < irrTs->cubeFaceFramebuffers.size(); face++) {
vk::Framebuffer fb = irrTs->cubeFaceFramebuffers[face];
if (!fb) {
@@ -763,8 +761,7 @@ void vulkan_calculate_irrmap()
writer.writeSet(materialSet, VulkanDescriptorManager::getSetTemplate(DescriptorSetIndex::Material));
{
std::array<vk::DescriptorImageInfo, VulkanDescriptorManager::MAX_TEXTURE_BINDINGS> texImages;
// irrmap-f.sdr declares this binding as samplerCube, so every element needs a cube view
texImages.fill(descManager->getFallbacks().textureCube);
texImages.fill(descManager->getFallbacks().texture2D);
texImages[0].imageView = envmapView;
writer.setImageArray(MaterialBinding::TextureArray, texImages);
}
-6
View File
@@ -121,12 +121,6 @@ public:
*/
vk::Pipeline getPipeline(const PipelineConfig& config, const vertex_layout& vertexLayout);
/**
* @brief Destroy all cached pipelines; later getPipeline calls build them again
* @note No submitted or recording command buffer may still use them
*/
void forgetAllPipelines() { m_pipelines.clear(); }
/**
* @brief Get the common pipeline layout
*
@@ -272,7 +272,8 @@ vk::DescriptorImageInfo VulkanDistortion::getTextureInfo() const
// Distortion_texture[!Distortion_switch] binding for thrusters).
// After update() toggles the switch, m_switch points to the old read
// source, which is the texture that was just written.
return {m_sampler, m_tex[m_switch].view, vk::ImageLayout::eShaderReadOnlyOptimal};
return {m_ctx->linearSampler, m_tex[m_switch].view,
vk::ImageLayout::eShaderReadOnlyOptimal};
}
} // namespace graphics::vulkan
@@ -531,9 +531,6 @@ void VulkanLDR::executeLightshafts(vk::CommandBuffer cmd)
if (dot > 0.7f) {
sun_x = asinf_safe(vm_vec_dot(&light_dir, &Eye_matrix.vec.rvec)) / PI * 1.5f + 0.5f;
sun_y = asinf_safe(vm_vec_dot(&light_dir, &Eye_matrix.vec.uvec)) / PI * 1.5f * gr_screen.clip_aspect + 0.5f;
// The formula above is OpenGL's, whose texture V grows upward. The Vulkan fullscreen triangle in
// post-v.sdr has V = 0 at the top of the screen, so flip to the space ls-f.sdr's fragTexCoord is in.
sun_y = 1.0f - sun_y;
found = true;
break;
}
Loaded 100 of 241 files, more files were not shown because too many files have changed in this diff. Show more