Compare commits

..
Author SHA1 Message Date
SirKnightly a520e810f2 Automated build commit 2017-08-22 12:56:27 -04:00
384 changed files with 11456 additions and 37469 deletions

No files matched your search

+30
View File
@@ -1,3 +1,33 @@
*.o
*.a
.dirstamp
libtool
ltmain.sh
m4/libtool.m4
m4/ltoptions.m4
m4/ltsugar.m4
m4/ltversion.m4
m4/lt~obsolete.m4
compile
.deps/
code/.deps/
Makefile
Makefile.in
aclocal.m4
autom4te.cache/
config.*
code/fs2_open_*
code/wxFRED2_*
configure
depcomp
install-sh
missing
.svn
*.layout
projects/Xcode/Frameworks/
#========
#OS junk files
[Tt]humbs.db
*.DS_Store
+3
View File
@@ -1,3 +1,6 @@
[submodule "cmake/external/cotire"]
path = cmake/external/cotire
url = https://github.com/sakra/cotire.git
[submodule "cmake/external/rpavlik-cmake-modules"]
path = cmake/external/rpavlik-cmake-modules
url = https://github.com/asarium/cmake-modules.git
+1 -1
View File
@@ -53,7 +53,7 @@ endif()
LIST(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake")
LIST(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake/finder")
LIST(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake/external/rpavlik-cmake-modules")
LIST(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake/external/cotire")
LIST(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake/external/cotire/CMake")
IF(RESET_INSTALL_PREFIX)
IF(NOT $ENV{FS2PATH} STREQUAL "")
+14 -1
View File
@@ -2,7 +2,20 @@
if ([System.Convert]::ToBoolean($env:ReleaseBuild) -Or [System.Convert]::ToBoolean($env:NightlyBuild) -Or [System.Convert]::ToBoolean($env:TestBuild)) {
# Skip tests for deployment
exit 0
} else {
} else {
# Appveyor doesn't have OpenAL so copy our DLLs to the output FOLDER
$arch=""
if ($Env:CMAKE_GENERATOR -Match "Win64") {
$arch="win64"
} else {
$arch="win32"
}
$dllPath = "$Env:APPVEYOR_BUILD_FOLDER\lib\openal\libs\$arch\OpenAL32.dll"
$copyDestination = "$pwd\bin\$Env:CONFIGURATION\"
write "Copying OpenAL DLL..."
Copy-Item "$dllPath" "$copyDestination"
write "Running unit tests..."
# Run unit tests
&"$pwd\bin\$Env:CONFIGURATION\unittests.exe" --gtest_shuffle 2>&1
-5
View File
@@ -6,11 +6,6 @@ mkdir -p build
cd build
if [ "$TRAVIS_OS_NAME" = "linux" ]; then
if [ "$RELEASE_BUILD" = true ]; then
PARENT_DIR="$(basename $PWD)"
(cd .. && tar -czvf /tmp/builds/$PACKAGE_NAME-source-Unix.tar.gz --exclude-vcs "$PARENT_DIR")
fi
CXXFLAGS="-m64 -mtune=generic -mfpmath=sse -msse -msse2 -pipe -Wno-unknown-pragmas"
CFLAGS="-m64 -mtune=generic -mfpmath=sse -msse -msse2 -pipe -Wno-unknown-pragmas"
+1 -1
View File
@@ -26,8 +26,8 @@ if [[ ! "$(curl -V)" == *"sftp"* ]]; then
cd ..
dpkg -l | grep curl
ls -al
sudo dpkg -i libcurl3*.deb
sudo dpkg -i curl*.deb
sudo dpkg -i libcurl3*.deb
elif [ "$TRAVIS_OS_NAME" = "osx" ]; then
brew install curl --with-libssh2
export PATH="/usr/local/opt/curl/bin:$PATH"
+5
View File
@@ -4,6 +4,11 @@ set -ex
mkdir -p /tmp/builds
if [ "$TRAVIS_OS_NAME" = "linux" ]; then
if [ "$RELEASE_BUILD" = true ]; then
PARENT_DIR="$(basename $PWD)"
(cd .. && tar cvf /tmp/builds/$PACKAGE_NAME-source-Unix.tar.gz --exclude-vcs "$PARENT_DIR")
fi
cd build
for config in $BUILD_CONFIGS
do
+1 -1
View File
@@ -1,4 +1,4 @@
#!/bin/sh
HERE=$(dirname $(readlink -f "${0}"))
export LD_LIBRARY_PATH="${HERE}"/lib:"$LD_LIBRARY_PATH"
export LD_LIBRARY_PATH="${HERE}"/lib:$PATH
"${HERE}"/bin/$<TARGET_FILE_NAME:Freespace2> $@
-3
View File
@@ -1,9 +1,6 @@
include(WriteCompilerDetectionHeader)
set(CMAKE_CXX_STANDARD_REQUIRED 11)
set(CMAKE_CXX_STANDARD 11)
set(REQUIRED_CXX_FEATURES cxx_rvalue_references cxx_nullptr)
get_property(CMAKE_CXX_KNOWN_FEATURES GLOBAL PROPERTY CMAKE_CXX_KNOWN_FEATURES)
+1 -8
View File
@@ -27,7 +27,6 @@ int main( int argc, char* argv[] )
int SSE = false;
int SSE2 = false;
int AVX = false;
int AVX2 = false;
int info[4];
cpuid(info, 0);
@@ -41,14 +40,8 @@ int main( int argc, char* argv[] )
AVX = (info[2] & ((int)1 << 28)) != 0;
}
if (nIds >= 7){
cpuid(info,0x00000007);
AVX2 = (info[1] & ((int)1 << 5)) != 0;
}
if (AVX2)
std::cout << "AVX2";
else if(AVX)
if(AVX)
std::cout << "AVX";
else if(SSE2)
std::cout << "SSE2";
Vendored Submodule
+1
Submodule cmake/external/cotire added at 40a46bf2fb.
-4054
View File
File diff suppressed because it is too large. Load diff
-9
View File
@@ -1,9 +0,0 @@
#ifndef __FREDRC_H
#define __FREDRC_H
#define ABOUT_LINE_1 "FRED2_OPEN - FreeSpace Editor, Version @FSO_PRODUCT_VERSION_STRING@ OpenGL"
#define MAINFRAME_CONTENTS "FRED2_OPEN @FSO_PRODUCT_VERSION_STRING@ - FreeSpace2 Mission Editor\nUntitled\nFRED2\nFreeSpace2 Missions (*.fs2)\n.fs2\nFreeSpace2Mission\nFreeSpace2 Mission"
#endif // __FREDRC_H
+1 -3
View File
@@ -1,7 +1,5 @@
include(Cxx11)
include(platformChecks)
include(Cxx11)
CONFIGURE_FILE(${CMAKE_CURRENT_LIST_DIR}/project.h.in ${GENERATED_SOURCE_DIR}/project.h)
CONFIGURE_FILE(${CMAKE_CURRENT_LIST_DIR}/fred_rc.h.in ${GENERATED_SOURCE_DIR}/fred_rc.h)
+2 -5
View File
@@ -15,9 +15,9 @@ CHECK_INCLUDE_FILE_CXX("cxxabi.h" HAVE_CXXAPI_H)
CHECK_TYPE_SIZE("max_align_t" MAX_ALIGN_T)
if("${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU" OR "${CMAKE_CXX_COMPILER_ID}" MATCHES "Clang")
if("${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU")
set(CMAKE_REQUIRED_FLAGS "-std=c++11") # required for g++ <= 5
endif()
endif("${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU")
set(CMAKE_EXTRA_INCLUDE_FILES "cstddef")
CHECK_TYPE_SIZE("std::max_align_t" STD_MAX_ALIGN_T LANGUAGE CXX)
@@ -25,9 +25,6 @@ set(CMAKE_EXTRA_INCLUDE_FILES "type_traits")
CHECK_TYPE_SIZE("std::is_trivially_copyable<int>" STD_IS_TRIVIALLY_COPYABLE LANGUAGE CXX)
set(CMAKE_EXTRA_INCLUDE_FILES)
CHECK_TYPE_SIZE("char32_t" CHAR32_T LANGUAGE CXX)
CHECK_TYPE_SIZE("U'b'" UNICODE_CHAR_LITERAL LANGUAGE CXX)
set(CMAKE_REQUIRED_FLAGS)
-4
View File
@@ -9,7 +9,6 @@
#cmakedefine HAVE_STD_MAX_ALIGN_T
#cmakedefine HAVE_STD_IS_TRIVIALLY_COPYABLE
#cmakedefine HAVE_STD_IS_TRIVIALLY_COPYABLE_ARRAY
#cmakedefine01 IS_64BIT
@@ -22,7 +21,4 @@
#cmakedefine01 HAVE_STRINGS_H
#cmakedefine01 HAVE_CHAR32_T
#cmakedefine01 HAVE_UNICODE_CHAR_LITERAL
#endif // __PLATFORM_CHECKS_H__
+1 -3
View File
@@ -33,9 +33,7 @@ set(WARNING_FLAGS
/wd4311 # Disables warnings about casting pointer types to ints. The funny thing is these warnings can't be resolved, just disabled... - m!m
/wd4302 # Same as above - m!m
/wd4366 # The result of the unary '&' operator may be unaligned - m!m
/wd4592 # "symbol will be dynamically initialized" is being generated by a compiler bug, see https://stackoverflow.com/a/34027257 for an explanation - m!m
$<$<CONFIG:Release>:/wd4101> # In release mode there are unreferenced variables because debug needs them
/wd4995 # "'vsprintf': name was marked as #pragma deprecated" is being caused by our custom definition of vsprintf. I have no idea what causes this or how to fix it - m!m
)
target_compile_options(compiler INTERFACE ${WARNING_FLAGS})
@@ -90,7 +88,7 @@ ENDIF(MSVC_USE_RUNTIME_DLL)
INCLUDE(MSVCMultipleProcessCompile)
# Visual Studio supports compiling for multiple vector instruction sets
SET(POSSIBLE_INSTUCTION_SETS "" SSE SSE2 AVX AVX2)
SET(POSSIBLE_INSTUCTION_SETS "" SSE SSE2 AVX)
if (NOT DEFINED MSVC_SIMD_INSTRUCTIONS)
detect_simd_instructions(MSVC_DETECTED_SIMD_INSTRUCTIONS)
+2 -2
View File
@@ -7,8 +7,8 @@ if (EXISTS "${PROJECT_SOURCE_DIR}/version_override.cmake")
endif()
set_if_not_defined(FSO_VERSION_MAJOR 3)
set_if_not_defined(FSO_VERSION_MINOR 8)
set_if_not_defined(FSO_VERSION_BUILD 1)
set_if_not_defined(FSO_VERSION_MINOR 7)
set_if_not_defined(FSO_VERSION_BUILD 5)
# A numeric revision e.g. the CI build number
set_if_not_defined(FSO_VERSION_REVISION 0)
+3 -3
View File
@@ -21,7 +21,7 @@ TARGET_INCLUDE_DIRECTORIES(code PUBLIC ${GENERATED_SOURCE_DIR}/code)
target_link_libraries(code PUBLIC OpenGL)
TARGET_LINK_LIBRARIES(code PUBLIC openal)
TARGET_LINK_LIBRARIES(code PUBLIC ${OPENAL_LIBS})
TARGET_LINK_LIBRARIES(code PUBLIC ${LUA_LIBS})
TARGET_LINK_LIBRARIES(code PUBLIC ${PNG_LIBS})
TARGET_LINK_LIBRARIES(code PUBLIC ${JPEG_LIBS})
@@ -30,8 +30,6 @@ TARGET_LINK_LIBRARIES(code PUBLIC sdl2)
TARGET_LINK_LIBRARIES(code PUBLIC ffmpeg)
TARGET_LINK_LIBRARIES(code PUBLIC utfcpp)
TARGET_LINK_LIBRARIES(code PUBLIC platform)
TARGET_LINK_LIBRARIES(code PUBLIC compiler)
@@ -60,6 +58,8 @@ set_target_properties(code PROPERTIES COTIRE_CXX_PREFIX_HEADER_INIT "prefix_head
include(util)
configure_cotire(code)
include(../cmake/Cxx11.cmake)
# Ensure that Xcode generates debug symbols on macOS for Debug builds
set_target_properties(code PROPERTIES XCODE_ATTRIBUTE_GCC_GENERATE_DEBUGGING_SYMBOLS[variant=Debug] "YES")
set_target_properties(code PROPERTIES XCODE_ATTRIBUTE_COPY_PHASE_STRIP[variant=Debug] "NO")
+3 -11
View File
@@ -10395,7 +10395,6 @@ void ai_get_dock_goal_indexes(object *objp, ai_info *aip, ai_goal *aigp, object
case AIS_DOCK_2:
case AIS_DOCK_3:
Warning(LOCATION, "Normally dock indexes should be calculated for only AIS_DOCK_0 and AIS_UNDOCK_0. Trace out and debug.");
FALLTHROUGH;
case AIS_DOCK_0:
{
// get them from the active goal
@@ -10413,7 +10412,6 @@ void ai_get_dock_goal_indexes(object *objp, ai_info *aip, ai_goal *aigp, object
case AIS_UNDOCK_1:
case AIS_UNDOCK_2:
Warning(LOCATION, "Normally dock indexes should be calculated for only AIS_DOCK_0 and AIS_UNDOCK_0. Trace out and debug.");
FALLTHROUGH;
case AIS_UNDOCK_0:
{
// get them from the guy I'm docked to
@@ -10480,11 +10478,9 @@ void ai_cleanup_dock_mode_subjective(object *objp)
case AIS_UNDOCK_0:
model_anim_start_type(shipp, TRIGGER_TYPE_DOCKED, docker_index, -1);
model_anim_start_type(goal_shipp, TRIGGER_TYPE_DOCKED, dockee_index, -1);
FALLTHROUGH;
case AIS_UNDOCK_1:
model_anim_start_type(shipp, TRIGGER_TYPE_DOCKING_STAGE_3, docker_index, -1);
model_anim_start_type(goal_shipp, TRIGGER_TYPE_DOCKING_STAGE_3, dockee_index, -1);
FALLTHROUGH;
case AIS_UNDOCK_2:
model_anim_start_type(shipp, TRIGGER_TYPE_DOCKING_STAGE_2, docker_index, -1);
model_anim_start_type(goal_shipp, TRIGGER_TYPE_DOCKING_STAGE_2, dockee_index, -1);
@@ -10494,11 +10490,9 @@ void ai_cleanup_dock_mode_subjective(object *objp)
case AIS_DOCK_4A:
model_anim_start_type(shipp, TRIGGER_TYPE_DOCKED, docker_index, -1);
model_anim_start_type(goal_shipp, TRIGGER_TYPE_DOCKED, dockee_index, -1);
FALLTHROUGH;
case AIS_DOCK_3:
model_anim_start_type(shipp, TRIGGER_TYPE_DOCKING_STAGE_3, docker_index, -1);
model_anim_start_type(goal_shipp, TRIGGER_TYPE_DOCKING_STAGE_3, dockee_index, -1);
FALLTHROUGH;
case AIS_DOCK_2:
model_anim_start_type(shipp, TRIGGER_TYPE_DOCKING_STAGE_2, docker_index, -1);
model_anim_start_type(goal_shipp, TRIGGER_TYPE_DOCKING_STAGE_2, dockee_index, -1);
@@ -10839,7 +10833,7 @@ void ai_dock()
if (aip->submode == AIS_DOCK_3) {
// Play a ship docking attach sound
snd_play_3d( gamesnd_get_game_sound(SND_DOCK_ATTACH), &Pl_objp->pos, &View_position );
snd_play_3d( &Snds[SND_DOCK_ATTACH], &Pl_objp->pos, &View_position );
// start the dock animation
model_anim_start_type(shipp, TRIGGER_TYPE_DOCKED, docker_index, 1);
@@ -10966,7 +10960,7 @@ void ai_dock()
ai_find_path(Pl_objp, OBJ_INDEX(goal_objp), path_num, 0);
// Play a ship docking detach sound
snd_play_3d( gamesnd_get_game_sound(SND_DOCK_DETACH), &Pl_objp->pos, &View_position );
snd_play_3d( &Snds[SND_DOCK_DETACH], &Pl_objp->pos, &View_position );
aip->submode = AIS_UNDOCK_1;
aip->submode_start_time = Missiontime;
@@ -10986,7 +10980,7 @@ void ai_dock()
// play the depart sound, but only once, since this mode is called multiple times per frame
if ( !(aigp->flags[AI::Goal_Flags::Depart_sound_played]))
{
snd_play_3d( gamesnd_get_game_sound(SND_DOCK_DEPART), &Pl_objp->pos, &View_position );
snd_play_3d( &Snds[SND_DOCK_DEPART], &Pl_objp->pos, &View_position );
aigp->flags.set(AI::Goal_Flags::Depart_sound_played);
}
@@ -12382,7 +12376,6 @@ void ai_maybe_evade_locked_missile(object *objp, ai_info *aip)
case AIM_DOCK: // Ships in dock mode can evade iif they are not currently repairing or docked.
if (object_is_docked(objp) || (aip->ai_flags[AI::AI_Flags::Repairing, AI::AI_Flags::Being_repaired]))
break;
FALLTHROUGH;
case AIM_GUARD:
// If in guard mode and far away from guard object, don't pursue guy that hit me.
if ((aip->guard_objnum != -1) && (aip->guard_signature == Objects[aip->guard_objnum].signature)) {
@@ -12390,7 +12383,6 @@ void ai_maybe_evade_locked_missile(object *objp, ai_info *aip)
return;
}
}
FALLTHROUGH;
case AIM_EVADE:
case AIM_GET_BEHIND:
case AIM_STAY_NEAR:
+2 -2
View File
@@ -2051,7 +2051,7 @@ bool turret_fire_weapon(int weapon_num, ship_subsys *turret, int parent_objnum,
if ( wip->launch_snd != -1 ) {
// Don't play turret firing sound if turret sits on player ship... it gets annoying.
if ( parent_objnum != OBJ_INDEX(Player_obj) || (turret->flags[Ship::Subsystem_Flags::Play_sound_for_player]) ) {
snd_play_3d( gamesnd_get_game_sound(wip->launch_snd), turret_pos, &View_position );
snd_play_3d( &Snds[wip->launch_snd], turret_pos, &View_position );
}
}
}
@@ -2138,7 +2138,7 @@ void turret_swarm_fire_from_turret(turret_swarm_info *tsi)
if ( Weapon_info[tsi->weapon_class].launch_snd != -1 ) {
// Don't play turret firing sound if turret sits on player ship... it gets annoying.
if ( tsi->parent_objnum != OBJ_INDEX(Player_obj) ) {
snd_play_3d( gamesnd_get_game_sound(Weapon_info[tsi->weapon_class].launch_snd), &turret_pos, &View_position );
snd_play_3d( &Snds[Weapon_info[tsi->weapon_class].launch_snd], &turret_pos, &View_position );
}
}
+2 -16
View File
@@ -512,14 +512,7 @@ int unpack_pixel(anim_instance *ai, ubyte *data, ubyte pix, int aabitmap, int bp
bit_16 = (ushort)pix;
break;
case 8:
// 8 bit-per-pixel aa bitmaps are a bit special since they only use value in the range [0, 15] where 15 wraps
// around back to 0. Since the rest of the code expects the value to be in the range [0, 255] the pixel value
// needs to be adjusted here. By muliplying the value with 17 the original range [0, 15] is mapped to [0, 255]
if (pix >= 15) {
bit_8 = 0;
} else {
bit_8 = (ubyte)(pix * 17);
}
bit_8 = pix;
break;
default:
Int3();
@@ -603,14 +596,7 @@ int unpack_pixel_count(anim_instance *ai, ubyte *data, ubyte pix, int count = 0,
bit_16 = (ushort)pix;
break;
case 8 :
// 8 bit-per-pixel aa bitmaps are a bit special since they only use value in the range [0, 15] where 15 wraps
// around back to 0. Since the rest of the code expects the value to be in the range [0, 255] the pixel value
// needs to be adjusted here. By muliplying the value with 17 the original range [0, 15] is mapped to [0, 255]
if (pix >= 15) {
bit_8 = 0;
} else {
bit_8 = (ubyte)(pix * 17);
}
bit_8 = pix;
break;
default :
Int3();
+1 -1
View File
@@ -1312,7 +1312,7 @@ void asteriod_explode_sound(object *objp, int type, int play_loud)
range_factor = 1.0f;
}
snd_play_3d( gamesnd_get_game_sound(sound_index), &objp->pos, &Eye_position, objp->radius, NULL, 0, 1.0f, SND_PRIORITY_MUST_PLAY, NULL, range_factor );
snd_play_3d( &Snds[sound_index], &objp->pos, &Eye_position, objp->radius, NULL, 0, 1.0f, SND_PRIORITY_MUST_PLAY, NULL, range_factor );
}
/**
+1 -2
View File
@@ -31,7 +31,6 @@ union bm_extra_info {
int keyframe; //!< used for animations -- keyframe info
float total_time; //!< used for animations -- total animation time (not always derived from num_frames/fps)
ubyte fps; //!< used for animations -- frames per second
bool is_array; //!< Flag for if all frames of an animation have the same size which means that it can be put into a texture array
struct {
// stuff for static animations
@@ -90,7 +89,7 @@ struct bitmap_entry {
#endif
};
extern bitmap_entry* bm_bitmaps;
extern bitmap_entry bm_bitmaps[MAX_BITMAPS];
// image specific lock functions
void bm_lock_ani( int handle, int bitmapnum, bitmap_entry *be, bitmap *bmp, int bpp, ubyte flags );
+30 -123
View File
@@ -24,7 +24,6 @@
#include "debugconsole/console.h"
#include "globalincs/systemvars.h"
#include "graphics/2d.h"
#include "graphics/matrix.h"
#include "graphics/grinternal.h"
#include "io/key.h"
#include "io/timer.h"
@@ -84,19 +83,17 @@ const int BM_ANI_NUM_TYPES = sizeof(bm_ani_type_list) / sizeof(bm_ani_type_list[
void(*bm_set_components)(ubyte *pixel, ubyte *r, ubyte *g, ubyte *b, ubyte *a) = NULL;
void(*bm_set_components_32)(ubyte *pixel, ubyte *r, ubyte *g, ubyte *b, ubyte *a) = NULL;
int MAX_BITMAPS = DEFAULT_MAX_BITMAPS;
// --------------------------------------------------------------------------------------------------------------------
// Declaration of protected variables (defined in cmdline.cpp).
extern int Cmdline_cache_bitmaps;
// --------------------------------------------------------------------------------------------------------------------
// Definition of public variables (declared as extern in bm_internal.h).
bitmap_entry* bm_bitmaps = nullptr;
bitmap_entry bm_bitmaps[MAX_BITMAPS];
// --------------------------------------------------------------------------------------------------------------------
// Definition of private variables at file scope (static).
static bool bm_inited = false;
static int bm_inited = 0;
static uint Bm_next_signature = 0x1234;
static int bm_next_handle = 1;
static int Bm_low_mem = 0;
@@ -483,11 +480,7 @@ void bm_close() {
for (i = 0; i<MAX_BITMAPS; i++) {
bm_free_data(i); // clears flags, bbp, data, etc
}
if (bm_bitmaps != nullptr) {
delete[] bm_bitmaps;
bm_bitmaps = nullptr;
}
bm_inited = false;
bm_inited = 0;
}
}
@@ -498,7 +491,7 @@ int bm_create(int bpp, int w, int h, void *data, int flags) {
Assert((bpp == 16) || (bpp == 24) || (bpp == 32));
}
Assertion(bm_inited, "bmpman must be initialized before this function can be called!");
if (!bm_inited) bm_init();
int n = -1;
@@ -878,7 +871,7 @@ int bm_get_info(int handle, int *w, int * h, ubyte * flags, int *nframes, int *f
if (h) *h = bmp->h;
if (flags) *flags = bmp->flags;
if (bm_is_anim(bitmapnum)) {
if (bm_is_anim(bitmapnum) == true) {
if (nframes) {
*nframes = bm_bitmaps[bitmapnum].info.ani.num_frames;
}
@@ -949,7 +942,7 @@ void bm_get_palette(int handle, ubyte *pal, char *name) {
}
uint bm_get_signature(int handle) {
Assertion(bm_inited, "bmpman must be initialized before this function can be called!");
if (!bm_inited) bm_init();
int bitmapnum = handle % MAX_BITMAPS;
Assertion(bm_bitmaps[bitmapnum].handle == handle, "Invalid bitmap handle %d passed to bm_get_signature().\nThis might be due to an invalid animation somewhere else.\n", handle); // INVALID BITMAP HANDLE!
@@ -974,7 +967,7 @@ int bm_get_tcache_type(int num) {
}
BM_TYPE bm_get_type(int handle) {
Assertion(bm_inited, "bmpman must be initialized before this function can be called!");
if (!bm_inited) bm_init();
int bitmapnum = handle % MAX_BITMAPS;
Assertion(bm_bitmaps[bitmapnum].handle == handle, "Invalid bitmap handle %d passed to bm_get_type().\nThis might be due to an invalid animation somewhere else.\n", handle); // INVALID BITMAP HANDLE!
@@ -996,17 +989,16 @@ bool bm_has_alpha_channel(int handle) {
}
void bm_init() {
Assertion(!bm_inited, "bmpman cannot be initialized more than once!");
int i;
if (bm_bitmaps == nullptr) {
bm_bitmaps = new bitmap_entry[MAX_BITMAPS];
}
mprintf(("Size of bitmap info = " SIZE_T_ARG " KB\n", (sizeof(bm_bitmaps[0]) * MAX_BITMAPS) / 1024));
mprintf(("Size of bitmap info = " SIZE_T_ARG " KB\n", sizeof(bm_bitmaps) / 1024));
mprintf(("Size of bitmap extra info = " SIZE_T_ARG " bytes\n", sizeof(bm_extra_info)));
if (!bm_inited) {
bm_inited = 1;
atexit(bm_close);
}
for (i = 0; i<MAX_BITMAPS; i++) {
bm_bitmaps[i].filename[0] = '\0';
bm_bitmaps[i].type = BM_TYPE_NONE;
@@ -1030,8 +1022,6 @@ void bm_init() {
bm_free_data(i); // clears flags, bbp, data, etc
}
bm_inited = true;
}
int bm_is_compressed(int num) {
@@ -1213,7 +1203,8 @@ int bm_load(const char *real_filename) {
CFILE *img_cfp = NULL;
int handle = -1;
Assertion(bm_inited, "bmpman must be initialized before this function can be called!");
if (!bm_inited)
bm_init();
// if no file was passed then get out now
if ((real_filename == NULL) || (strlen(real_filename) <= 0))
@@ -1518,7 +1509,8 @@ int bm_load_animation(const char *real_filename, int *nframes, int *fps, int *ke
size_t img_size = 0;
char clean_name[MAX_FILENAME_LEN];
Assertion(bm_inited, "bmpman must be initialized before this function can be called!");
if (!bm_inited)
bm_init();
// set output param defaults before going any further
if (nframes != nullptr)
@@ -1709,8 +1701,6 @@ int bm_load_animation(const char *real_filename, int *nframes, int *fps, int *ke
}
int first_handle = bm_get_next_handle();
// if all images of the animation have the same size then we can use a texture array
bool is_array = true;
for (i = 0; i < anim_frames; i++) {
memset(&bm_bitmaps[n + i], 0, sizeof(bitmap_entry));
@@ -1797,39 +1787,8 @@ int bm_load_animation(const char *real_filename, int *nframes, int *fps, int *ke
bm_bitmaps[n + i].info.ani.apng.is_apng = false;
}
if (bm_bitmaps[n].bm.w != bm_bitmaps[n + i].bm.w || bm_bitmaps[n].bm.h != bm_bitmaps[n + i].bm.h) {
// We found a frame with a different size than the first frame -> this can't be used as a texture array
is_array = false;
Warning(LOCATION, "Animation '%s' has images that are of different sizes (currently at frame %d)."
"Performance could be improved by making all images the same size.", filename, i + 1);
}
if (bm_bitmaps[n].comp_type != bm_bitmaps[n + i].comp_type) {
// Different compression type
is_array = false;
Warning(LOCATION, "Animation '%s' has images that are of different compression formats (currently at frame %d)."
"Performance could be improved by making all images the same compression format.", filename, i + 1);
}
if (bm_bitmaps[n].bm.true_bpp != bm_bitmaps[n + i].bm.true_bpp) {
// We found a frame with an incompatible pixel format
is_array = false;
Warning(LOCATION, "Animation '%s' has images that are of different pixel formats (currently at frame %d)."
"Performance could be improved by making all images the same pixel format.", filename, i + 1);
}
if (bm_bitmaps[n].num_mipmaps != bm_bitmaps[n + i].num_mipmaps) {
// We found a frame with a different number of mipmaps
is_array = false;
Warning(LOCATION, "Animation '%s' has images that have a different number of mipmaps (currently at frame %d)."
"Performance could be improved by giving all frames the same number of mipmaps.", filename, i + 1);
}
}
// Set array flag of first frame
bm_bitmaps[n].info.ani.is_array = is_array;
if (nframes != nullptr)
*nframes = anim_frames;
@@ -1938,7 +1897,7 @@ bitmap * bm_lock(int handle, int bpp, ubyte flags, bool nodebug) {
bitmap *bmp;
bitmap_entry *be;
Assertion(bm_inited, "bmpman must be initialized before this function can be called!");
if (!bm_inited) bm_init();
int bitmapnum = handle % MAX_BITMAPS;
@@ -2280,9 +2239,6 @@ void bm_lock_jpg(int handle, int bitmapnum, bitmap_entry *be, bitmap *bmp, int b
// Unload any existing data
bm_free_data(bitmapnum);
// JPEG actually only support 24 bits per pixel so we enforce that here
bpp = 24;
d_size = (bpp >> 3);
// allocate bitmap data
@@ -2343,7 +2299,7 @@ void bm_lock_pcx(int handle, int bitmapnum, bitmap_entry *be, bitmap *bmp, int b
// this will populate filename[] whether it's EFF or not
EFF_FILENAME_CHECK;
pcx_error = pcx_read_bitmap(filename, data, NULL, (bpp >> 3), (flags & BMP_AABITMAP), (flags & BMP_MASK_BITMAP) != 0, be->dir_type);
pcx_error = pcx_read_bitmap(filename, data, NULL, (bpp >> 3), (flags & BMP_AABITMAP), 0, be->dir_type);
if (pcx_error != PCX_ERROR_NONE) {
mprintf(("Couldn't load PCX!!! (%s)\n", filename));
@@ -2422,7 +2378,7 @@ void bm_lock_tga(int handle, int bitmapnum, bitmap_entry *be, bitmap *bmp, int b
Assert(byte_size);
Assert(be->mem_taken > 0);
data = (ubyte*)bm_malloc(bitmapnum, static_cast<size_t>(bmp->w * bmp->h * byte_size));
data = (ubyte*)bm_malloc(bitmapnum, be->mem_taken);
if (data) {
memset(data, 0, be->mem_taken);
@@ -2507,7 +2463,8 @@ int bm_make_render_target(int width, int height, int flags) {
int bpp = 32;
int size = 0;
Assertion(bm_inited, "bmpman must be initialized before this function can be called!");
if (!bm_inited)
bm_init();
// Find an open slot (starting from the end)
for (n = -1, i = MAX_BITMAPS - 1; i >= 0; i--) {
@@ -2880,16 +2837,12 @@ int bm_release(int handle, int clear_render_targets) {
}
// be sure that all frames of an ani are unloaded - taylor
if (bm_is_anim(n)) {
if (bm_is_anim(n) == true) {
int i, first = be->info.ani.first_frame, total = bm_bitmaps[first].info.ani.num_frames;
// The graphics system requires that the bitmap information for the whole animation is still valid when the data
// is freed so we first free all the data and then clear the bitmaps data
for (i = 0; i < total; i++) {
bm_free_data(first + i, true); // clears flags, bbp, data, etc
}
for (i = 0; i < total; i++) {
memset(&bm_bitmaps[first + i], 0, sizeof(bitmap_entry));
bm_bitmaps[first + i].type = BM_TYPE_NONE;
@@ -2938,7 +2891,8 @@ int bm_release(int handle, int clear_render_targets) {
}
int bm_reload(int bitmap_handle, const char* filename) {
Assertion(bm_inited, "bmpman must be initialized before this function can be called!");
if (!bm_inited)
bm_init();
// if no file was passed then get out now
if ((filename == NULL) || (strlen(filename) <= 0))
@@ -3118,7 +3072,10 @@ bool bm_set_render_target(int handle, int face) {
gr_reset_clip();
gr_setup_viewport();
if (gr_screen.mode == GR_OPENGL) {
extern void opengl_setup_viewport();
opengl_setup_viewport();
}
return true;
}
@@ -3248,7 +3205,7 @@ int bm_unload_fast(int handle, int clear_render_targets) {
void bm_unlock(int handle) {
bitmap_entry *be;
Assertion(bm_inited, "bmpman must be initialized before this function can be called!");
if (!bm_inited) bm_init();
int bitmapnum = handle % MAX_BITMAPS;
@@ -3304,53 +3261,3 @@ int find_block_of(int n)
return -1;
}
bool bm_is_texture_array(const int handle) {
int bitmapnum = handle % MAX_BITMAPS;
if (!bm_is_anim(bitmapnum)) {
return true;
}
// This will return the index of the first animation frame
int n = bm_get_cache_slot(handle, 0);
bitmap_entry *be = &bm_bitmaps[n];
return be->info.ani.is_array;
}
int bm_get_base_frame(const int handle, int* num_frames) {
// If the bitmap is no animation then num_frames will still be at least 1
auto animation_begin = bm_get_info(handle, nullptr, nullptr, nullptr, num_frames);
if (animation_begin < 0) {
// Some kind of error
return -1;
}
if (!bm_is_texture_array(animation_begin)) {
// If this is not a texture array then we just treat it like a single frame animation
animation_begin = handle;
if (num_frames != nullptr) {
*num_frames = 1;
}
}
return animation_begin;
}
int bm_get_array_index(const int handle) {
return handle - bm_get_base_frame(handle, nullptr);
}
int bmpman_count_bitmaps() {
if (!bm_inited)
return -1;
int total_bitmaps = 0;
for (int i = 0; i < MAX_BITMAPS; i++) {
if (bm_bitmaps[i].type != BM_TYPE_NONE) {
total_bitmaps++;
}
}
return total_bitmaps;
}
+2 -45
View File
@@ -33,7 +33,7 @@
*/
/**
* @brief How many bitmaps the game can handle by default
* @brief How many bitmaps the game can handle
*
* @attention MAX_BITMAPS shouldn't need to be bumped again. With the fixed bm_release() and it's proper use even the
* largest missions should stay under this number. With the largest retail missions and wasteful content we should
@@ -45,9 +45,7 @@
* If anything we could/should reduce MAX_BITMAPS in the future. Where it's at now should accomidate even the
* largest mods. -- Taylor
*/
#define DEFAULT_MAX_BITMAPS 4750
extern int MAX_BITMAPS;
#define MAX_BITMAPS 4750
// Flag positions for bitmap.flags
// ***** NOTE: bitmap.flags is an 8-bit value, no more BMP_TEX_* flags can be added unless the type is changed!! ******
@@ -58,7 +56,6 @@ extern int MAX_BITMAPS;
#define BMP_TEX_DXT3 (1<<4) //!< dxt3 compressed 8r8g8b4a (32bit)
#define BMP_TEX_DXT5 (1<<5) //!< dxt5 compressed 8r8g8b8a (32bit)
#define BMP_TEX_CUBEMAP (1<<6) //!< a texture made for cubic environment map
#define BMP_MASK_BITMAP (1<<7) //!< a bitmap that will be used for masking mouse interaction. Typically not used in render operations
// Combined flags
#define BMP_TEX_COMP ( BMP_TEX_DXT1 | BMP_TEX_DXT3 | BMP_TEX_DXT5 ) //!< Compressed textures
@@ -701,44 +698,4 @@ bool bm_load_and_parse_eff(const char *filename, int dir_type, int *nframes, int
*/
int bm_get_anim_frame(const int frame1_handle, float elapsed_time, const float divisor = 0.0f, const bool loop = false);
/**
* @brief Determines if the given handle could be used in a texture array
*
* @param handle The handle to query the value for
* @return @c true if all frames have the same size, @c false otherwise. Always returns @c true for single images
*/
bool bm_is_texture_array(const int handle);
/**
* @brief Gets the base frame of the specified animation
*
* @details The base frame is the frame of the animation that should be used to determine if two animation frames can be
* used in the same draw call. Use this if you want to optimize your draw calls to make use of texture arrays.
*
* @param handle The handle of the animation to check. This may also be a single frame bitmap
* @param num_frames Optionally return the number of frames in the animation
* @return The bitmap handle of the base frame or -1 on error
*/
int bm_get_base_frame(const int handle, int* num_frames = nullptr);
/**
* @brief Get the array index of the specified bitmap
*
* This should be used when passing the array index to the GPU (e.g. when building uniform structs or streaming particle
* data)
*
* @param handle The handle of the bitmap
* @return The index into the array
*/
int bm_get_array_index(const int handle);
/**
* @brief Counts how many slots are used in bm_bitmaps
*
* This needs to iterate through all the slots in order to determine whether or not they're used, so shouldn't be used frivolously.
*
* @return The number of used slots
*/
int bmpman_count_bitmaps();
#endif
+1 -1
View File
@@ -2,7 +2,7 @@
#include "globalincs/alphacolors.h"
#include "globalincs/linklist.h"
#include "globalincs/systemvars.h" //VM_FREECAMERA etc
#include "graphics/matrix.h"
#include "graphics/font.h"
#include "hud/hud.h" //hud_get_draw
#include "math/vecmat.h"
#include "mod_table/mod_table.h"
-1
View File
@@ -88,7 +88,6 @@ cf_pathtype Pathtypes[CF_MAX_PATH_TYPES] = {
{ CF_TYPE_INTEL_ANIMS, "data" DIR_SEPARATOR_STR "intelanims", ".pcx .ani .eff .tga .jpg .png .dds", CF_TYPE_DATA },
{ CF_TYPE_SCRIPTS, "data" DIR_SEPARATOR_STR "scripts", ".lua .lc", CF_TYPE_DATA },
{ CF_TYPE_FICTION, "data" DIR_SEPARATOR_STR "fiction", ".txt", CF_TYPE_DATA },
{ CF_TYPE_FREDDOCS, "data" DIR_SEPARATOR_STR "freddocs", ".html", CF_TYPE_DATA },
};
+1 -2
View File
@@ -78,9 +78,8 @@ typedef struct {
#define CF_TYPE_INTEL_ANIMS 34
#define CF_TYPE_SCRIPTS 35
#define CF_TYPE_FICTION 36
#define CF_TYPE_FREDDOCS 37
#define CF_MAX_PATH_TYPES 38 // Can be as high as you'd like //DTP; yeah but beware alot of things uses CF_MAX_PATH_TYPES
#define CF_MAX_PATH_TYPES 37 // Can be as high as you'd like //DTP; yeah but beware alot of things uses CF_MAX_PATH_TYPES
// TRUE if type is specified and valid
+6 -12
View File
@@ -1567,10 +1567,8 @@ int cf_get_file_list( SCP_vector<SCP_string> &list, int pathtype, const char *fi
continue;
char fn[MAX_PATH];
if (snprintf(fn, MAX_PATH, "%s/%s", filespec, dir->d_name) >= MAX_PATH) {
// Make sure the string is null terminated
fn[MAX_PATH-1] = 0;
}
snprintf(fn, MAX_PATH-1, "%s/%s", filespec, dir->d_name);
fn[MAX_PATH-1] = 0;
struct stat buf;
if (stat(fn, &buf) == -1) {
@@ -1778,10 +1776,8 @@ int cf_get_file_list( int max, char **list, int pathtype, const char *filter, in
continue;
char fn[MAX_PATH];
if (snprintf(fn, MAX_PATH, "%s/%s", filespec, dir->d_name) >= MAX_PATH) {
// Make sure the string is null terminated
fn[MAX_PATH-1] = 0;
}
snprintf(fn, MAX_PATH-1, "%s/%s", filespec, dir->d_name);
fn[MAX_PATH-1] = 0;
struct stat buf;
if (stat(fn, &buf) == -1) {
@@ -1995,10 +1991,8 @@ int cf_get_file_list_preallocated( int max, char arr[][MAX_FILENAME_LEN], char *
continue;
char fn[MAX_PATH];
if (snprintf(fn, MAX_PATH, "%s/%s", filespec, dir->d_name) >= MAX_PATH) {
// Make sure the string is null terminated
fn[MAX_PATH-1] = 0;
}
snprintf(fn, MAX_PATH-1, "%s/%s", filespec, dir->d_name);
fn[MAX_PATH-1] = 0;
struct stat buf;
if (stat(fn, &buf) == -1) {
+50 -268
View File
@@ -23,9 +23,6 @@
#include "globalincs/pstypes.h"
#include "osapi/osapi.h"
#include "cfile/cfilesystem.h"
#include "sound/speech.h"
#include "sound/openal.h"
#include "io/joy.h"
#ifdef _WIN32
#include <io.h>
@@ -41,9 +38,6 @@
#include <string.h>
#include <stdlib.h>
#include <cstdio>
#include <jansson.h>
// Stupid windows workaround...
#ifdef MessageBox
@@ -66,11 +60,6 @@ const char *cmdline_arg_types[] =
"STRING",
};
enum class flag_output_type {
Binary,
Json_V1,
};
// variables
class cmdline_parm {
public:
@@ -89,7 +78,6 @@ public:
float get_float();
char *str();
bool check_if_args_is_valid();
bool has_param();
};
static cmdline_parm Parm_list(NULL, NULL, AT_NONE);
@@ -189,6 +177,7 @@ Flag exe_params[] =
{ "-no_ap_interrupt", "Disable interrupting autopilot", true, 0, EASY_DEFAULT, "Gameplay", "http://www.hard-light.net/wiki/index.php/Command-Line_Reference#-no_ap_interrupt", },
{ "-stretch_menu", "Stretch interface to fill screen", true, 0, EASY_DEFAULT, "Gameplay", "http://www.hard-light.net/wiki/index.php/Command-Line_Reference#-stretch_menu", },
{ "-snd_preload", "Preload mission game sounds", true, EASY_MEM_ALL_ON, EASY_DEFAULT_MEM, "Audio", "http://www.hard-light.net/wiki/index.php/Command-Line_Reference#-snd_preload", },
{ "-nosound", "Disable all sound", false, 0, EASY_DEFAULT, "Audio", "http://www.hard-light.net/wiki/index.php/Command-Line_Reference#-nosound", },
{ "-nomusic", "Disable music", false, 0, EASY_DEFAULT, "Audio", "http://www.hard-light.net/wiki/index.php/Command-Line_Reference#-nomusic", },
{ "-no_enhanced_sound", "Disable enhanced sound", false, 0, EASY_DEFAULT, "Audio", "http://www.hard-light.net/wiki/index.php/Command-Line_Reference#-no_enhanced_sound", },
@@ -229,7 +218,6 @@ Flag exe_params[] =
{ "-voicer", "Enable voice recognition", true, 0, EASY_DEFAULT, "Experimental", "http://www.hard-light.net/wiki/index.php/Command-Line_Reference#-voicer", },
{ "-fps", "Show frames per second on HUD", false, 0, EASY_DEFAULT, "Dev Tool", "http://www.hard-light.net/wiki/index.php/Command-Line_Reference#-fps", },
{ "-bmpmanusage", "Show how many BMPMAN slots are in use", false, 0, EASY_DEFAULT, "Dev Tool", "http://www.hard-light.net/wiki/index.php/Command-Line_Reference#-bmpmanusage", },
{ "-pos", "Show position of camera", false, 0, EASY_DEFAULT, "Dev Tool", "http://www.hard-light.net/wiki/index.php/Command-Line_Reference#-pos", },
{ "-window", "Run in window", true, 0, EASY_DEFAULT, "Dev Tool", "http://www.hard-light.net/wiki/index.php/Command-Line_Reference#-window", },
{ "-fullscreen_window", "Run in fullscreen window", false, 0, EASY_DEFAULT, "Dev Tool", "http://www.hard-light.net/wiki/index.php/Command-Line_Reference#-fullscreen_window", },
@@ -405,9 +393,11 @@ int Cmdline_stretch_menu = 0;
// Audio related
cmdline_parm query_speech_arg("-query_speech", NULL, AT_NONE); // Cmdline_query_speech
cmdline_parm snd_preload_arg("-snd_preload", NULL, AT_NONE); // Cmdline_snd_preload
cmdline_parm voice_recognition_arg("-voicer", NULL, AT_NONE); // Cmdline_voice_recognition
int Cmdline_query_speech = 0;
int Cmdline_snd_preload = 0; // preload game sounds during mission load
int Cmdline_voice_recognition = 0;
int Cmdline_no_enhanced_sound = 0;
@@ -482,7 +472,6 @@ cmdline_parm dis_weapons("-dis_weapons", NULL, AT_NONE); // Cmdline_dis_weapons
cmdline_parm noparseerrors_arg("-noparseerrors", NULL, AT_NONE); // Cmdline_noparseerrors -- turns off parsing errors -C
cmdline_parm extra_warn_arg("-extra_warn", "Enable 'extra' warnings", AT_NONE); // Cmdline_extra_warn
cmdline_parm fps_arg("-fps", NULL, AT_NONE); // Cmdline_show_fps
cmdline_parm bmpmanusage_arg("-bmpmanusage", NULL, AT_NONE); // Cmdline_bmpman_usage
cmdline_parm pos_arg("-pos", NULL, AT_NONE); // Cmdline_show_pos
cmdline_parm stats_arg("-stats", NULL, AT_NONE); // Cmdline_show_stats
cmdline_parm save_render_targets_arg("-save_render_target", NULL, AT_NONE); // Cmdline_save_render_targets
@@ -513,7 +502,6 @@ int Cmdline_noparseerrors = 0;
int Cmdline_nowarn = 0; // turn warnings off in FRED
#endif
int Cmdline_extra_warn = 0;
int Cmdline_bmpman_usage = 0;
int Cmdline_show_pos = 0;
int Cmdline_show_stats = 0;
int Cmdline_save_render_targets = 0;
@@ -534,7 +522,7 @@ bool Cmdline_show_video_info = false;
bool Cmdline_debug_window = false;
// Other
cmdline_parm get_flags_arg("-get_flags", "Output the launcher flags file", AT_STRING);
cmdline_parm get_flags_arg("-get_flags", "Output the launcher flags file", AT_NONE);
cmdline_parm output_sexp_arg("-output_sexps", NULL, AT_NONE); //WMC - outputs all SEXPs to sexps.html
cmdline_parm output_scripting_arg("-output_scripting", NULL, AT_NONE); //WMC
@@ -547,7 +535,6 @@ cmdline_parm deprecated_tbp_arg("-tbp", "Deprecated", AT_NONE);
cmdline_parm deprecated_jpgtga_arg("-jpgtga", "Deprecated", AT_NONE);
cmdline_parm deprecated_htl_arg("-nohtl", "Deprecated", AT_NONE);
cmdline_parm deprecated_brieflighting_arg("-brief_lighting", "Deprecated", AT_NONE);
cmdline_parm deprecated_sndpreload_arg("-snd_preload", "Deprecated", AT_NONE);
int Cmdline_deprecated_spec = 0;
int Cmdline_deprecated_glow = 0;
@@ -1156,9 +1143,6 @@ char *cmdline_parm::str()
return args;
}
bool cmdline_parm::has_param() {
return args != nullptr;
}
#ifdef SCP_UNIX
// Return a vector with all filesystem names of "parent/dir" relative to parent.
@@ -1257,248 +1241,6 @@ static void handle_unix_modlist(char **modlist, size_t *len)
// external entry point into this modules
static json_t* json_get_v1() {
auto root = json_object();
{
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();
json_array_append_new(caps_array, json_string("OpenAL"));
json_array_append_new(caps_array, json_string("No D3D"));
json_array_append_new(caps_array, json_string("New Sound"));
json_array_append_new(caps_array, json_string("SDL"));
json_object_set_new(root, "caps", caps_array);
}
{
auto voices_array = json_array();
auto voices = speech_enumerate_voices();
for (auto& voice : voices) {
json_array_append_new(voices_array, json_string(voice.c_str()));
}
json_object_set_new(root, "voices", voices_array);
}
{
auto resolution_array = json_array();
auto displays = gr_enumerate_displays();
for (auto& display : displays) {
auto display_obj = json_object();
json_object_set_new(display_obj, "index", json_integer(display.index));
json_object_set_new(display_obj, "name", json_string(display.name.c_str()));
json_object_set_new(display_obj, "x", json_integer(display.x));
json_object_set_new(display_obj, "y", json_integer(display.y));
json_object_set_new(display_obj, "width", json_integer(display.width));
json_object_set_new(display_obj, "height", json_integer(display.height));
auto modes_array = json_array();
for (auto& mode : display.video_modes) {
auto mode_obj = json_object();
json_object_set_new(mode_obj, "x", json_integer(mode.width));
json_object_set_new(mode_obj, "y", json_integer(mode.height));
json_object_set_new(mode_obj, "bits", json_integer(mode.bit_depth));
json_array_append_new(modes_array, mode_obj);
}
json_object_set_new(display_obj, "modes", modes_array);
json_array_append_new(resolution_array, display_obj);
}
json_object_set_new(root, "displays", resolution_array);
}
{
auto openal_obj = json_object();
auto openal_info = openal_get_platform_information();
json_object_set_new(openal_obj, "version_major", json_integer(openal_info.version_major));
json_object_set_new(openal_obj, "version_minor", json_integer(openal_info.version_minor));
json_object_set(openal_obj, "default_playback", json_string(openal_info.default_playback_device.c_str()));
json_object_set(openal_obj, "default_capture", json_string(openal_info.default_capture_device.c_str()));
{
auto playback_array = json_array();
for (auto& device : openal_info.playback_devices) {
json_array_append_new(playback_array, json_string(device.c_str()));
}
json_object_set_new(openal_obj, "playback_devices", playback_array);
}
{
auto capture_array = json_array();
for (auto& device : openal_info.capture_devices) {
json_array_append_new(capture_array, json_string(device.c_str()));
}
json_object_set_new(openal_obj, "capture_devices", capture_array);
}
json_object_set_new(root, "openal", openal_obj);
}
{
auto joystick_array = json_array();
auto joysticks = io::joystick::getJoystickInformations();
for (auto& info : joysticks) {
auto joystick_obj = json_object();
json_object_set_new(joystick_obj, "name", json_string(info.name.c_str()));
json_object_set_new(joystick_obj, "guid", json_string(info.guid.c_str()));
json_object_set_new(joystick_obj, "num_axes", json_integer(info.num_axes));
json_object_set_new(joystick_obj, "num_balls", json_integer(info.num_balls));
json_object_set_new(joystick_obj, "num_buttons", json_integer(info.num_buttons));
json_object_set_new(joystick_obj, "num_hats", json_integer(info.num_hats));
json_object_set_new(joystick_obj, "is_haptic", json_boolean(info.is_haptic));
json_array_append_new(joystick_array, joystick_obj);
}
json_object_set_new(root, "joysticks", joystick_array);
}
{
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");
if (fp == NULL) {
os::dialogs::Message(os::dialogs::MESSAGEBOX_ERROR, "Error creating flag list for launcher");
return;
}
int easy_flag_size = sizeof(EasyFlag);
int flag_size = sizeof(Flag);
int num_easy_flags = sizeof(easy_flags) / easy_flag_size;
int num_flags = sizeof(exe_params) / flag_size;
// Launcher will check its using structures of the same size
fwrite(&easy_flag_size, sizeof(int), 1, fp);
fwrite(&flag_size, sizeof(int), 1, fp);
fwrite(&num_easy_flags, sizeof(int), 1, fp);
fwrite(&easy_flags, sizeof(easy_flags), 1, fp);
fwrite(&num_flags, sizeof(int), 1, fp);
fwrite(&exe_params, sizeof(exe_params), 1, fp);
{
// cheap and bastardly cap check for builds
// (needs to be compatible with older Launchers, which means having
// this implies an OpenAL build for old Launchers)
ubyte build_caps = 0;
/* portej05 defined this always */
build_caps |= BUILD_CAPS_OPENAL;
build_caps |= BUILD_CAPS_NO_D3D;
build_caps |= BUILD_CAPS_NEW_SND;
build_caps |= BUILD_CAPS_SDL;
fwrite(&build_caps, 1, 1, fp);
}
fflush(fp);
fclose(fp);
}
static flag_output_type get_flags_output_type() {
Assertion(get_flags_arg.found(), "This function is only valid if -get_flags is present!");
if (!get_flags_arg.has_param()) {
// Default to binary mode
return flag_output_type::Binary;
}
SCP_string type(get_flags_arg.str());
if (type == "binary") {
return flag_output_type::Binary;
} else if (type == "json_v1") {
return flag_output_type::Json_V1;
} else {
// This is supposed to make it easy for the launcher to recognize an unsupported type
printf("OUTPUT TYPE NOT SUPPORTED!\n");
// Default to json in this case so that no flags.lch file is created
return flag_output_type::Json_V1;
}
}
static void write_flags() {
auto type = get_flags_output_type();
switch(type) {
case flag_output_type::Binary:
write_flags_file();
break;
case flag_output_type::Json_V1:
json_t* root = json_get_v1();
json_dumpf(root, stdout, JSON_INDENT(4));
json_decref(root);
break;
}
}
bool SetCmdlineParams()
// Sets externed variables used for communication cmdline information
{
@@ -1506,7 +1248,47 @@ bool SetCmdlineParams()
// DO THIS FIRST to avoid unrecognized flag warnings when just getting flag file
if ( get_flags_arg.found() ) {
write_flags();
FILE *fp = fopen("flags.lch","w");
if (fp == NULL) {
os::dialogs::Message(os::dialogs::MESSAGEBOX_ERROR, "Error creating flag list for launcher");
return false;
}
int easy_flag_size = sizeof(EasyFlag);
int flag_size = sizeof(Flag);
int num_easy_flags = sizeof(easy_flags) / easy_flag_size;
int num_flags = sizeof(exe_params) / flag_size;
// Launcher will check its using structures of the same size
fwrite(&easy_flag_size, sizeof(int), 1, fp);
fwrite(&flag_size, sizeof(int), 1, fp);
fwrite(&num_easy_flags, sizeof(int), 1, fp);
fwrite(&easy_flags, sizeof(easy_flags), 1, fp);
fwrite(&num_flags, sizeof(int), 1, fp);
fwrite(&exe_params, sizeof(exe_params), 1, fp);
{
// cheap and bastardly cap check for builds
// (needs to be compatible with older Launchers, which means having
// this implies an OpenAL build for old Launchers)
ubyte build_caps = 0;
/* portej05 defined this always */
build_caps |= BUILD_CAPS_OPENAL;
build_caps |= BUILD_CAPS_NO_D3D;
build_caps |= BUILD_CAPS_NEW_SND;
build_caps |= BUILD_CAPS_SDL;
fwrite(&build_caps, 1, 1, fp);
}
fflush(fp);
fclose(fp);
return false;
}
@@ -1759,11 +1541,6 @@ bool SetCmdlineParams()
Show_framerate = 1;
}
if (bmpmanusage_arg.found())
{
Cmdline_bmpman_usage = 1;
}
if(pos_arg.found())
{
Cmdline_show_pos = 1;
@@ -1944,6 +1721,11 @@ bool SetCmdlineParams()
}
#endif
if ( snd_preload_arg.found() )
{
Cmdline_snd_preload = 1;
}
if ( env.found() ) {
Cmdline_env = 0;
}
+1 -1
View File
@@ -104,6 +104,7 @@ extern int Cmdline_stretch_menu;
// Audio related
extern int Cmdline_query_speech;
extern int Cmdline_snd_preload;
extern int Cmdline_voice_recognition;
extern int Cmdline_no_enhanced_sound;
@@ -147,7 +148,6 @@ extern int Cmdline_dis_collisions;
extern int Cmdline_dis_weapons;
extern int Cmdline_noparseerrors;
extern int Cmdline_extra_warn;
extern int Cmdline_bmpman_usage;
extern int Cmdline_show_pos;
extern int Cmdline_show_stats;
extern int Cmdline_save_render_targets;
+1 -1
View File
@@ -92,7 +92,7 @@ void cmeasure_maybe_alert_success(object *objp)
if ( objp->parent == OBJ_INDEX(Player_obj) ) {
hud_start_text_flash(XSTR("Evaded", 1430), 800);
snd_play(gamesnd_get_game_sound(ship_get_sound(Player_obj, SND_MISSILE_EVADED_POPUP)));
snd_play(&Snds[ship_get_sound(Player_obj, SND_MISSILE_EVADED_POPUP)]);
} else if ( Objects[objp->parent].flags[Object::Object_Flags::Player_ship] ) {
send_countermeasure_success_packet( objp->parent );
}
-21
View File
@@ -14,11 +14,6 @@ bool Decoder::tryPopAudioData(AudioFramePtr& out) {
return res == queue_op_status::success;
}
bool Decoder::tryPopSubtitleData(SubtitleFramePtr& out) {
auto res = m_subtitleQueue->try_pull_front(out);
return res == queue_op_status::success;
}
bool Decoder::tryPopVideoFrame(VideoFramePtr& out) {
auto res = m_videoQueue->try_pull_front(out);
return res == queue_op_status::success;
@@ -29,7 +24,6 @@ void Decoder::initializeQueues(size_t queueSize) {
m_videoQueue.reset(new sync_bounded_queue<VideoFramePtr>(m_queueSize));
m_audioQueue.reset(new sync_bounded_queue<AudioFramePtr>(m_queueSize));
m_subtitleQueue.reset(new sync_bounded_queue<SubtitleFramePtr>(m_queueSize));
}
void Decoder::stopDecoder() {
@@ -37,7 +31,6 @@ void Decoder::stopDecoder() {
m_videoQueue->close();
m_audioQueue->close();
m_subtitleQueue->close();
}
bool Decoder::canPushAudioData() {
@@ -55,20 +48,6 @@ void Decoder::pushAudioData(AudioFramePtr&& data) {
}
}
bool Decoder::canPushSubtitleData() {
return !isSubtitleQueueFull();
}
void Decoder::pushSubtitleData(SubtitleFramePtr&& data) {
Assertion(data, "Invalid audio data passed!");
try {
m_subtitleQueue->push_back(std::move(data));
}
catch (sync_queue_is_closed&) {
// Ignore
}
}
bool Decoder::canPushVideoData() {
return !isVideoQueueFull();
}
-23
View File
@@ -58,14 +58,6 @@ struct AudioFrame {
};
typedef std::unique_ptr<AudioFrame> AudioFramePtr;
struct SubtitleFrame {
double displayStartTime = -1.0;
double displayEndTime = -1.0;
SCP_string text;
};
typedef std::unique_ptr<SubtitleFrame> SubtitleFramePtr;
/**
* @brief Abstract class for decoding a video or audio stream
*
@@ -76,7 +68,6 @@ class Decoder {
private:
std::unique_ptr<sync_bounded_queue<VideoFramePtr>> m_videoQueue;
std::unique_ptr<sync_bounded_queue<AudioFramePtr>> m_audioQueue;
std::unique_ptr<sync_bounded_queue<SubtitleFramePtr>> m_subtitleQueue;
bool m_decoding;
size_t m_queueSize = 0;
@@ -118,8 +109,6 @@ class Decoder {
*/
virtual bool hasAudio() = 0;
virtual bool hasSubtitles() = 0;
/**
* @brief Ends decoding of the video file
*/
@@ -133,14 +122,6 @@ class Decoder {
bool tryPopAudioData(AudioFramePtr&);
bool isSubtitleQueueFull() { return m_subtitleQueue->size() == m_queueSize; }
bool isSubtitleFrameAvailable() { return !m_subtitleQueue->empty(); }
size_t getSubtitleQueueSize() { return m_subtitleQueue->size(); }
bool tryPopSubtitleData(SubtitleFramePtr&);
bool isVideoQueueFull() { return m_videoQueue->size() == m_queueSize; }
bool isVideoFrameAvailable() { return !m_videoQueue->empty(); }
@@ -160,10 +141,6 @@ class Decoder {
void pushAudioData(AudioFramePtr&& data);
bool canPushSubtitleData();
void pushSubtitleData(SubtitleFramePtr&& data);
bool canPushVideoData();
void pushFrameData(VideoFramePtr&& frame);
-95
View File
@@ -1,95 +0,0 @@
#include "VideoPresenter.h"
#include "graphics/matrix.h"
using namespace cutscene;
using namespace cutscene::player;
namespace {
struct movie_vertex {
vec2d pos;
vec2d uv;
};
}
namespace cutscene {
namespace player {
VideoPresenter::VideoPresenter(const MovieProperties& props) {
GR_DEBUG_SCOPE("Init video");
auto w = static_cast<int>(props.size.width);
auto h = static_cast<int>(props.size.height);
// Create buffer textures
_yTexBuffer.reset(new uint8_t[w * h]);
_ytex = bm_create(8, w, h, _yTexBuffer.get(), BMP_AABITMAP);
_uTexBuffer.reset(new uint8_t[w / 2 * h / 2]);
_utex = bm_create(8, w / 2, h / 2, _uTexBuffer.get(), BMP_AABITMAP);
_vTexBuffer.reset(new uint8_t[w / 2 * h / 2]);
_vtex = bm_create(8, w / 2, h / 2, _vTexBuffer.get(), BMP_AABITMAP);
material_set_movie(&_render_material, _ytex, _utex, _vtex);
}
VideoPresenter::~VideoPresenter() {
GR_DEBUG_SCOPE("Deinit video");
bm_release(_ytex);
bm_release(_utex);
bm_release(_vtex);
_ytex = _utex = _vtex = -1;
}
void VideoPresenter::uploadVideoFrame(const VideoFramePtr& frame) {
GR_DEBUG_SCOPE("Update video frame");
auto ptrs = frame->getDataPointers();
memcpy(_yTexBuffer.get(), ptrs.y, frame->ySize.stride * frame->ySize.height);
memcpy(_uTexBuffer.get(), ptrs.u, frame->uvSize.stride * frame->uvSize.height);
memcpy(_vTexBuffer.get(), ptrs.v, frame->uvSize.stride * frame->uvSize.height);
gr_update_texture(_ytex, 8, _yTexBuffer.get(), (int) frame->ySize.width, (int) frame->ySize.height);
gr_update_texture(_utex, 8, _uTexBuffer.get(), (int) frame->uvSize.width, (int) frame->uvSize.height);
gr_update_texture(_vtex, 8, _vTexBuffer.get(), (int) frame->uvSize.width, (int) frame->uvSize.height);
}
void VideoPresenter::displayFrame(float x1, float y1, float x2, float y2) {
GR_DEBUG_SCOPE("Draw video frame");
movie_vertex vertex_data[4];
vertex_data[0].pos.x = x1;
vertex_data[0].pos.y = y1;
vertex_data[0].uv.x = 0.0f;
vertex_data[0].uv.y = 0.0f;
vertex_data[1].pos.x = x1;
vertex_data[1].pos.y = y2;
vertex_data[1].uv.x = 0.0f;
vertex_data[1].uv.y = 1.0f;
vertex_data[2].pos.x = x2;
vertex_data[2].pos.y = y1;
vertex_data[2].uv.x = 1.0f;
vertex_data[2].uv.y = 0.0f;
vertex_data[3].pos.x = x2;
vertex_data[3].pos.y = y2;
vertex_data[3].uv.x = 1.0f;
vertex_data[3].uv.y = 1.0f;
// Use the immediate buffer for storing our data since that is exactly what we need
auto offset = gr_add_to_immediate_buffer(sizeof(vertex_data), vertex_data);
vertex_layout layout;
layout.add_vertex_component(vertex_format_data::POSITION2, sizeof(vertex_data[0]), offset + offsetof(movie_vertex, pos));
layout.add_vertex_component(vertex_format_data::TEX_COORD2, sizeof(vertex_data[0]), offset + offsetof(movie_vertex, uv));
gr_render_movie(&_render_material, PRIM_TYPE_TRISTRIP, &layout, 4, gr_immediate_buffer_handle);
}
}
}
-42
View File
@@ -1,42 +0,0 @@
#ifndef FS2_OPEN_OPENGLVIDEOPRESENTER_H
#define FS2_OPEN_OPENGLVIDEOPRESENTER_H
#include "globalincs/pstypes.h"
#include "graphics/2d.h"
#include "graphics/material.h"
#include "cutscene/Decoder.h"
#include <memory>
namespace cutscene {
namespace player {
class VideoPresenter {
int _ytex = -1;
std::unique_ptr<uint8_t[]> _yTexBuffer;
int _utex = -1;
std::unique_ptr<uint8_t[]> _uTexBuffer;
int _vtex = -1;
std::unique_ptr<uint8_t[]> _vTexBuffer;
movie_material _render_material;
public:
explicit VideoPresenter(const MovieProperties& props);
// Disallow copying
VideoPresenter(const VideoPresenter&) = delete;
VideoPresenter& operator=(const VideoPresenter&) = delete;
virtual ~VideoPresenter();
void uploadVideoFrame(const VideoFramePtr& frame);
void displayFrame(float x1, float y1, float x2, float y2);
};
}
}
#endif //FS2_OPEN_OPENGLVIDEOPRESENTER_H
+2 -96
View File
@@ -9,9 +9,6 @@
#include "cutscene/ffmpeg/AudioDecoder.h"
#include "cutscene/ffmpeg/VideoDecoder.h"
#include "cutscene/ffmpeg/SubtitleDecoder.h"
#include "localization/localize.h"
using namespace libs::ffmpeg;
@@ -65,8 +62,6 @@ CodecContextParameters getCodecParameters(AVStream* stream) {
paras.channel_layout = stream->codecpar->channel_layout;
paras.sample_rate = stream->codecpar->sample_rate;
paras.audio_format = (AVSampleFormat)stream->codecpar->format;
paras.codec_id = stream->codecpar->codec_id;
#else
paras.width = stream->codec->width;
paras.height = stream->codec->height;
@@ -75,29 +70,9 @@ CodecContextParameters getCodecParameters(AVStream* stream) {
paras.channel_layout = stream->codec->channel_layout;
paras.sample_rate = stream->codec->sample_rate;
paras.audio_format = stream->codec->sample_fmt;
paras.codec_id = stream->codec->codec_id;
#endif
return paras;
}
SCP_string normalizeLanguage(const char* langauge_name) {
if (!stricmp(langauge_name, "eng")) {
return "English";
}
if (!stricmp(langauge_name, "ger")) {
return "German";
}
if (!stricmp(langauge_name, "spa")) {
return "Spanish";
}
// Print to log so that we can find the actual value more easily later
mprintf(("FFmpeg log: Found unknown language value '%s'!\n", langauge_name));
// Default to english for everything else
return "English";
}
}
namespace cutscene {
@@ -180,30 +155,7 @@ std::unique_ptr<DecoderStatus> initializeStatus(std::unique_ptr<InputStream>& st
status->audioStream = ctx->streams[audioStream];
}
auto& current_language = Lcl_languages[Lcl_current_lang];
for (uint32_t i = 0; i < ctx->nb_streams; ++i) {
auto test_stream = ctx->streams[i];
auto& pars = test_stream->codecpar;
if (!(pars->codec_type == AVMEDIA_TYPE_SUBTITLE)) {
continue;
}
AVDictionaryEntry* tag = nullptr;
if ((tag = av_dict_get(test_stream->metadata, "language", nullptr, 0)) == nullptr) {
continue;
}
auto normalized_language = normalizeLanguage(tag->value);
if (!stricmp(normalized_language.c_str(), current_language.lang_name)) {
status->subtitleStreamIndex = i;
status->subtitleStream = test_stream;
break;
}
}
status->videoCodecPars = getCodecParameters(status->videoStream);
status->videoCodecPars = getCodecParameters(status->videoStream);
int err;
#if LIBAVCODEC_VERSION_INT > AV_VERSION_INT(57, 24, 255)
@@ -261,37 +213,6 @@ std::unique_ptr<DecoderStatus> initializeStatus(std::unique_ptr<InputStream>& st
status->audioCodec->name ? status->audioCodec->name : "<Unknown>"));
}
if (status->subtitleStreamIndex >= 0) {
// Not really sure if this makes sense for subtitles but it shouldn't break anything...
status->subtitleCodecPars = getCodecParameters(status->subtitleStream);
status->subtitleCodec = avcodec_find_decoder(status->subtitleCodecPars.codec_id);
#if LIBAVCODEC_VERSION_INT > AV_VERSION_INT(57, 24, 255)
status->subtitleCodecCtx = avcodec_alloc_context3(status->subtitleCodec);
err = avcodec_parameters_to_context(status->subtitleCodecCtx, status->subtitleStream->codecpar);
if (err < 0) {
char errorStr[512];
av_strerror(err, errorStr, sizeof(errorStr));
mprintf(("FFMPEG: Failed to copy context parameters! Error: %s\n", errorStr));
return nullptr;
}
#else
status->subtitleCodecCtx = status->subtitleStream->codec;
#endif
err = avcodec_open2(status->subtitleCodecCtx, status->subtitleCodec, nullptr);
if (err < 0) {
char errorStr[512];
av_strerror(err, errorStr, sizeof(errorStr));
mprintf(("FFMPEG: Failed to open subtitle codec! Error: %s\n", errorStr));
}
mprintf(("FFmpeg: Using subtitle codec %s (%s).\n", status->subtitleCodec->long_name ? status->subtitleCodec->long_name : "<Unknown>",
status->subtitleCodec->name ? status->subtitleCodec->name : "<Unknown>"));
}
return status;
}
@@ -358,14 +279,10 @@ void FFMPEGDecoder::startDecoding() {
std::unique_ptr<VideoDecoder> videoDecoder(new VideoDecoder(m_status.get()));
std::unique_ptr<AudioDecoder> audioDecoder;
std::unique_ptr<SubtitleDecoder> subtitleDecoder;
if (hasAudio()) {
audioDecoder.reset(new AudioDecoder(m_status.get()));
}
if (hasSubtitles()) {
subtitleDecoder.reset(new SubtitleDecoder(m_status.get()));
}
auto ctx = m_input->m_ctx->ctx();
AVPacket packet;
@@ -405,14 +322,7 @@ void FFMPEGDecoder::startDecoding() {
while ((ptr = audioDecoder->getFrame()) != nullptr) {
pushAudioData(std::move(ptr));
}
} else if (subtitleDecoder && packet.stream_index == m_status->subtitleStreamIndex) {
subtitleDecoder->decodePacket(&packet);
SubtitleFramePtr ptr;
while((ptr = subtitleDecoder->getFrame()) != nullptr) {
pushSubtitleData(std::move(ptr));
}
}
}
}
if (isDecoding()) {
@@ -439,10 +349,6 @@ bool FFMPEGDecoder::hasAudio() {
return m_status->audioStreamIndex >= 0;
}
bool FFMPEGDecoder::hasSubtitles() {
return m_status->subtitleStreamIndex >= 0;
}
void FFMPEGDecoder::close() {
if (m_status) {
m_status = nullptr;
-2
View File
@@ -27,8 +27,6 @@ class FFMPEGDecoder: public Decoder {
bool hasAudio() SCP_OVERRIDE;
bool hasSubtitles() SCP_OVERRIDE;
void close() SCP_OVERRIDE;
};
}
-117
View File
@@ -1,117 +0,0 @@
//
//
#include "SubtitleDecoder.h"
namespace {
double getFrameTime(int64_t pts, AVRational time_base) {
return pts * av_q2d(time_base);
}
}
namespace cutscene {
namespace ffmpeg {
SubtitleDecoder::SubtitleDecoder(cutscene::ffmpeg::DecoderStatus* status) : FFMPEGStreamDecoder(status) {
}
SubtitleDecoder::~SubtitleDecoder() {
}
void SubtitleDecoder::decodePacket(AVPacket* packet) {
int finishedFrame = 0;
AVSubtitle subtitle;
auto result = avcodec_decode_subtitle2(m_status->subtitleCodecCtx, &subtitle, &finishedFrame, packet);
if (result >= 0 && finishedFrame) {
pushSubtitleFrame(packet, &subtitle);
avsubtitle_free(&subtitle);
}
}
void SubtitleDecoder::finishDecoding() {
}
void SubtitleDecoder::pushSubtitleFrame(AVPacket* packet, AVSubtitle* subtitle) {
if (subtitle->format != 1) {
// Non-text subtitles are not supported yet.
mprintf(("FFmpeg: Detected a non-text subtitle! This is not supported yet!\n"));
return;
}
if (subtitle->num_rects < 1) {
return;
}
int64_t pts = subtitle->pts;
if (pts == AV_NOPTS_VALUE) {
pts = packet->pts;
}
if (pts == AV_NOPTS_VALUE) {
// Still no valid timestamp...
return;
}
auto packet_time = getFrameTime(pts, m_status->subtitleStream->time_base);
auto start_time = packet_time + (subtitle->start_display_time / 1000.0);
auto end_time = packet_time + (subtitle->end_display_time / 1000.0);
if (subtitle->end_display_time == 0 && m_status->subtitleStream->time_base.num != 0) {
end_time = packet_time + getFrameTime(packet->duration, m_status->subtitleStream->time_base);
}
SCP_string processed_text;
// For now we only use the first subtitle rectangle
auto subtitle_rect = subtitle->rects[0];
if (subtitle_rect->type == SUBTITLE_BITMAP) {
// Same as above, non-text subtitles are not supported yet.
mprintf(("FFmpeg: Detected a non-text subtitle! This is not supported yet!\n"));
return;
} else if (subtitle_rect->type == SUBTITLE_TEXT) {
// Subtitle does not need to be processed any further
processed_text = subtitle_rect->text;
} else if (subtitle_rect->type == SUBTITLE_ASS) {
SCP_string ass_text = subtitle_rect->ass;
// We are not interested in any of the other information contained in the ASS line but we still need to figure
// out where our text starts
auto comma_pos = ass_text.find(',');
for (auto i = 0; i < 8 && comma_pos != SCP_string::npos; ++i) {
comma_pos = ass_text.find(',', comma_pos + 1);
}
Assertion(comma_pos != SCP_string::npos, "Received an ill-formed ASS line from FFmpeg! Text was '%s'.", subtitle_rect->ass);
// This + 1 is safe since comma_pos points to a valid character so the next character is at worst the end of the string
processed_text = ass_text.substr(comma_pos + 1);
// ASS has a special sequence for new lines that needs to be converted to an actual new line
auto newline_pos = processed_text.find("\\N");
while(newline_pos != SCP_string::npos) {
processed_text.replace(newline_pos, 2, "\n");
newline_pos = processed_text.find("\\N");
}
} else {
mprintf(("FFmpeg: Detected unknown subtitle name in movie!\n"));
return;
}
// Remove \r from string. Some subtitles use \r\n for line breaks and we only support \n
auto ret_pos = processed_text.find('\r');
while(ret_pos != SCP_string::npos) {
processed_text.erase(ret_pos, 1);
ret_pos = processed_text.find('\r');
}
SubtitleFramePtr frame(new SubtitleFrame());
frame->text = processed_text;
frame->displayStartTime = start_time;
frame->displayEndTime = end_time;
pushFrame(std::move(frame));
}
}
}
-24
View File
@@ -1,24 +0,0 @@
#pragma once
#include "cutscene/ffmpeg/internal.h"
#include "cutscene/ffmpeg/FFMPEGDecoder.h"
namespace cutscene {
namespace ffmpeg {
class SubtitleDecoder: public FFMPEGStreamDecoder<SubtitleFrame> {
public:
explicit SubtitleDecoder(DecoderStatus* status);
virtual ~SubtitleDecoder();
virtual void decodePacket(AVPacket* packet) SCP_OVERRIDE;
virtual void finishDecoding() SCP_OVERRIDE;
void pushSubtitleFrame(AVPacket* subtitle, AVSubtitle* pSubtitle);
};
}
}
-12
View File
@@ -30,18 +30,6 @@ DecoderStatus::~DecoderStatus() {
#endif
audioCodecCtx = nullptr;
}
subtitleStreamIndex = -1;
subtitleStream = nullptr;
subtitleCodec = nullptr;
if (subtitleCodecCtx != nullptr) {
avcodec_close(subtitleCodecCtx);
#if LIBAVCODEC_VERSION_INT > AV_VERSION_INT(57, 24, 255)
avcodec_free_context(&subtitleCodecCtx);
#endif
subtitleCodecCtx = nullptr;
}
}
} // namespace ffmpeg
-8
View File
@@ -16,8 +16,6 @@ struct CodecContextParameters {
uint64_t channel_layout = 0;
int sample_rate = -1;
AVSampleFormat audio_format = AV_SAMPLE_FMT_NONE;
AVCodecID codec_id = AV_CODEC_ID_NONE;
};
struct DecoderStatus {
@@ -33,12 +31,6 @@ struct DecoderStatus {
AVCodec* audioCodec = nullptr;
AVCodecContext* audioCodecCtx = nullptr;
int subtitleStreamIndex = -1;
AVStream* subtitleStream = nullptr;
CodecContextParameters subtitleCodecPars;
AVCodec* subtitleCodec = nullptr;
AVCodecContext* subtitleCodecCtx = nullptr;
DecoderStatus();
~DecoderStatus();
+1 -200
View File
@@ -14,7 +14,6 @@
#endif
#include "globalincs/pstypes.h"
#include "globalincs/alphacolors.h"
#include "globalincs/systemvars.h"
#include "io/cursor.h"
#include "graphics/2d.h"
@@ -22,203 +21,10 @@
#include "cmdline/cmdline.h"
#include "cutscene/cutscenes.h" // cutscene_mark_viewable()
#include "cutscene/player.h" // cutscene_mark_viewable()
#include "tracing/categories.h"
#include "tracing/tracing.h"
#include "io/timer.h"
#include "io/key.h"
#include "mod_table/mod_table.h"
extern int Game_mode;
extern int Is_standalone;
namespace {
using namespace cutscene;
struct PlaybackState {
bool playing = true;
vec2d posTopLeft;
vec2d posBottomRight;
int subtitle_font = -1;
};
void processEvents(PlaybackState* state) {
io::mouse::CursorManager::get()->showCursor(false);
os_poll();
int k = key_inkey();
switch (k) {
case KEY_ESC:
case KEY_ENTER:
case KEY_SPACEBAR:
state->playing = false;
break;
default:
break;
}
}
template<typename... Args>
float print_string(float x, float y, const char* fmt, Args... params) {
SCP_string text;
sprintf(text, fmt, params...);
gr_string(x, y, text.c_str(), GR_RESIZE_NONE);
return y + font::get_current_font()->getHeight();
}
void showVideoInfo(const PlayerState& state) {
gr_set_color_fast(&Color_white);
font::set_font(font::FONT1);
float y = 200.f;
float x = 100.f;
y = print_string(x, y, "Movie FPS: %f", state.props.fps);
y = print_string(x, y, "Size: %dx%d", state.props.size.width, state.props.size.height);
y = gr_screen.max_h - 200.f;
size_t audio_queue_size = state.decoder->getAudioQueueSize();
if (state.hasAudio) {
ALint queued;
OpenAL_ErrorPrint(alGetSourcei(state.audioSid, AL_BUFFERS_QUEUED, &queued));
audio_queue_size += queued;
}
y = print_string(x, y, "Audio Queue size: " SIZE_T_ARG, audio_queue_size);
y = print_string(x, y, "Video Queue size: " SIZE_T_ARG, state.decoder->getVideoQueueSize());
y += font::get_current_font()->getHeight();
// Estimate the size of the video buffer
// We use YUV420p frames so one pixel uses 1.5 bytes of storage
size_t single_frame_size = (size_t) (state.props.size.width * state.props.size.height * 1.5);
size_t total_size = single_frame_size * state.decoder->getVideoQueueSize();
print_string(x, y, "Video buffer size: " SIZE_T_ARG "B", total_size);
}
void displayVideo(Player* player, PlaybackState* state) {
TRACE_SCOPE(tracing::CutsceneDrawVideoFrame);
GR_DEBUG_SCOPE("Display Video");
gr_clear();
player->draw(state->posTopLeft.x, state->posTopLeft.y, state->posBottomRight.x, state->posBottomRight.y);
auto subtitle = player->getCurrentSubtitle();
if (!subtitle.empty() && state->subtitle_font >= 0) {
gr_set_color_fast(&Color_bright_white);
font::set_font(state->subtitle_font);
int width;
int height;
gr_get_string_size(&width, &height, subtitle.c_str());
// Offset the subtitle by 20% of the viewport size from the bottom
auto y_offset = static_cast<int>((state->posBottomRight.y - state->posTopLeft.y) * 0.1);
auto center_x = (state->posBottomRight.x - state->posTopLeft.x) / 2;
auto text_x = center_x - width / 2;
auto text_y = state->posBottomRight.y - y_offset - height;
gr_string(text_x, text_y, subtitle.c_str(), GR_RESIZE_NONE);
}
if (Cmdline_show_video_info) {
showVideoInfo(player->getInternalState());
}
gr_flip();
}
void determine_display_positions(Player* player, PlaybackState* state) {
auto& props = player->getMovieProperties();
float screen_ratio = (float) gr_screen.center_w / (float) gr_screen.center_h;
float movie_ratio = (float) props.size.width / (float) props.size.height;
float scale_by;
if (screen_ratio > movie_ratio) {
scale_by = (float) gr_screen.center_h / (float) props.size.height;
} else {
scale_by = (float) gr_screen.center_w / (float) props.size.width;
}
float screenX;
float screenY;
if (!Cmdline_noscalevid && (scale_by != 1.0f)) {
screenX = ((gr_screen.center_w / 2.0f + gr_screen.center_offset_x) / scale_by) - (static_cast<int>(props.size.width) / 2.0f) + 0.5f;
screenY = ((gr_screen.center_h / 2.0f + gr_screen.center_offset_y) / scale_by) - (static_cast<int>(props.size.height) / 2.0f) + 0.5f;
} else {
// centers on 1024x768, fills on 640x480
screenX = i2fl(((gr_screen.center_w - static_cast<int>(props.size.width)) / 2) + gr_screen.center_offset_x);
screenY = i2fl(((gr_screen.center_h - static_cast<int>(props.size.height)) / 2) + gr_screen.center_offset_y);
}
// set additional values for screen width/height and UV coords
float screenXW = screenX + static_cast<int>(props.size.width);
float screenYH = screenY + static_cast<int>(props.size.height);
if (!Cmdline_noscalevid && (scale_by != 1.0f)) {
// Apply scaling
screenX *= scale_by;
screenY *= scale_by;
screenXW *= scale_by;
screenYH *= scale_by;
}
state->posTopLeft.x = screenX;
state->posTopLeft.y = screenY;
state->posBottomRight.x = screenXW;
state->posBottomRight.y = screenYH;
}
void initialize_player_state(Player* player, PlaybackState* state) {
determine_display_positions(player, state);
state->subtitle_font = font::FontManager::getFontIndex(Movie_subtitle_font);
if (state->subtitle_font < 0) {
Warning(LOCATION, "Failed to load subtitle font '%s'! Subtitles will be disabled.", Movie_subtitle_font.c_str());
}
}
void movie_display_loop(Player* player, PlaybackState* state) {
// Compute the maximum time we will sleep to make sure we can still maintain the movie FPS
// and not waste too much CPU time
// We will sleep at most half the time a frame would be displayed
auto sleepTime = static_cast<std::uint64_t>((1. / (4. * player->getMovieProperties().fps)) * 1000.);
auto lastDisplayTimestamp = timer_get_microseconds();
while (state->playing) {
TRACE_SCOPE(tracing::CutsceneStep);
auto timestamp = timer_get_microseconds();
auto passed = timestamp - lastDisplayTimestamp;
lastDisplayTimestamp = timestamp;
// Play as long as the player reports that there is more to display
state->playing = player->update(passed);
displayVideo(player, state);
processEvents(state);
if (passed < sleepTime) {
auto sleep = sleepTime - passed;
os_sleep(static_cast<uint>(sleep));
}
}
}
}
namespace movie {
// Play one movie
bool play(const char* name) {
@@ -251,12 +57,7 @@ bool play(const char* name) {
auto player = cutscene::Player::newPlayer(name);
if (player) {
PlaybackState state;
initialize_player_state(player.get(), &state);
movie_display_loop(player.get(), &state);
player->stopPlayback();
player->startPlayback();
} else {
// uh-oh, movie is invalid... Abory, Retry, Fail?
mprintf(("MOVIE ERROR: Found invalid movie! (%s)\n", name));
+176 -96
View File
@@ -1,7 +1,7 @@
#include "cutscene/player.h"
#include "cutscene/Decoder.h"
#include "cutscene/VideoPresenter.h"
#include "cutscene/player/VideoPresenter.h"
#include "cutscene/ffmpeg/FFMPEGDecoder.h"
#include "graphics/2d.h"
@@ -19,19 +19,62 @@
#include "parse/parselo.h"
#include "cutscene/player/OpenGLVideoPresenter.h"
using namespace cutscene::player;
namespace cutscene {
struct PlayerState {
MovieProperties props;
Decoder* decoder = nullptr;
bool playing = true;
bool playbackHasBegun = false;
// Timing state
std::uint64_t playback_time = 0;
// Audio state
bool audioInited = false;
bool hasAudio = false;
ALuint audioSid = 0;
SCP_vector<ALuint> audioBuffers;
SCP_queue<ALuint> unqueuedAudioBuffers;
// Graphics state following
bool videoInited = false;
VideoFramePtr currentFrame;
VideoFramePtr nextFrame;
bool newFrameAdded = false;
std::unique_ptr<VideoPresenter> videoPresenter;
PlayerState() : decoder(nullptr), playing(true), playbackHasBegun(false),
playback_time(0),
audioInited(0), hasAudio(false), audioSid(0),
videoInited(false), newFrameAdded(false) {}
private:
PlayerState(const PlayerState&) SCP_DELETED_FUNCTION;
PlayerState& operator=(const PlayerState&) SCP_DELETED_FUNCTION;
};
}
namespace {
using namespace cutscene;
const int MAX_AUDIO_BUFFERS = 15;
std::unique_ptr<Decoder> findDecoder(const SCP_string& name) {
Decoder* findDecoder(const SCP_string& name) {
{
std::unique_ptr<Decoder> ffmpeg(new ffmpeg::FFMPEGDecoder());
auto ffmpeg = new ffmpeg::FFMPEGDecoder();
if (ffmpeg->initialize(name)) {
return ffmpeg;
}
delete ffmpeg;
}
return nullptr;
@@ -50,7 +93,7 @@ void videoPlaybackInit(PlayerState* state) {
Assert(state != NULL);
if (gr_screen.mode == GR_OPENGL) {
state->videoPresenter.reset(new VideoPresenter(state->props));
state->videoPresenter.reset(new OpenGLVideoPresenter(state->props));
}
state->videoInited = true;
@@ -120,7 +163,7 @@ void processVideoData(PlayerState* state) {
return;
}
while (currentTime >= state->nextFrame->frameTime) {
while(currentTime >= state->nextFrame->frameTime) {
// Move the next frame to the current frame slot
state->currentFrame = std::move(state->nextFrame);
@@ -141,34 +184,6 @@ void processVideoData(PlayerState* state) {
}
}
void processSubtitleData(PlayerState* state) {
SubtitleFramePtr ptr;
while (state->decoder->tryPopSubtitleData(ptr)) {
// Take all subtitle frames from our queue
state->queued_subtitles.push(std::move(ptr));
}
if (state->currentSubtitle && playbackGetTime(state) <= state->currentSubtitle->displayEndTime) {
// We currently have a frame and it it still being displayed so there is nothing for us to do here
return;
}
// Subtitle has expired so we don't need it anymore
state->currentSubtitle = nullptr;
while(!state->queued_subtitles.empty()) {
// Take a look at the first entry and check if it's time to display it yet
auto& nextSubtitle = state->queued_subtitles.front();
if (playbackGetTime(state) >= nextSubtitle->displayStartTime) {
state->currentSubtitle = std::move(nextSubtitle);
state->queued_subtitles.pop();
} else {
// The next subtitle should not be displayed yet so we are done here
break;
}
}
}
bool processAudioData(PlayerState* state) {
TRACE_SCOPE(tracing::CutsceneProcessAudioData);
@@ -176,7 +191,7 @@ bool processAudioData(PlayerState* state) {
if (state->decoder->hasAudio()) {
// Even if we don't play the sound we still need to remove it from the queue
AudioFramePtr audioData;
while (state->decoder->tryPopAudioData(audioData)) {
while(state->decoder->tryPopAudioData(audioData)) {
// Intentionally left empty
}
}
@@ -201,9 +216,7 @@ bool processAudioData(PlayerState* state) {
ALenum format = (audioData->channels == 2) ? AL_FORMAT_STEREO16 : AL_FORMAT_MONO16;
OpenAL_ErrorCheck(alBufferData(buffer,
format,
audioData->audioData.data(),
OpenAL_ErrorCheck(alBufferData(buffer, format, audioData->audioData.data(),
static_cast<ALsizei>(audioData->audioData.size() * sizeof(short)),
static_cast<ALsizei>(audioData->rate)), return false);
@@ -256,10 +269,82 @@ void videoPlaybackClose(PlayerState* state) {
state->videoInited = false;
}
template<typename... Args>
float print_string(float x, float y, const char* fmt, Args... params) {
SCP_string text;
sprintf(text, fmt, params...);
gr_string(x, y, text.c_str(), GR_RESIZE_NONE);
return y + font::get_current_font()->getHeight();
}
void showVideoInfo(PlayerState* state) {
gr_set_color_fast(&Color_white);
float y = 200.f;
float x = 100.f;
y = print_string(x, y, "Movie FPS: %f", state->props.fps);
y = print_string(x, y, "Size: %dx%d", state->props.size.width, state->props.size.height);
y = gr_screen.max_h - 200.f;
size_t audio_queue_size = state->decoder->getAudioQueueSize();
if (state->hasAudio) {
ALint queued;
OpenAL_ErrorPrint(alGetSourcei(state->audioSid, AL_BUFFERS_QUEUED, &queued));
audio_queue_size += queued;
}
y = print_string(x, y, "Audio Queue size: " SIZE_T_ARG, audio_queue_size);
y = print_string(x, y, "Video Queue size: " SIZE_T_ARG, state->decoder->getVideoQueueSize());
y += font::get_current_font()->getHeight();
// Estimate the size of the video buffer
// We use YUV420p frames so one pixel uses 1.5 bytes of storage
size_t single_frame_size = (size_t) (state->props.size.width * state->props.size.height * 1.5);
size_t total_size = single_frame_size * state->decoder->getVideoQueueSize();
print_string(x, y, "Video buffer size: " SIZE_T_ARG "B", total_size);
}
void displayVideo(PlayerState* state) {
if (!state->currentFrame) {
return;
}
TRACE_SCOPE(tracing::CutsceneDrawVideoFrame);
gr_clear();
if (state->videoPresenter) {
state->videoPresenter->displayFrame();
}
if (Cmdline_show_video_info) {
showVideoInfo(state);
}
gr_flip();
}
void processEvents(PlayerState* state) {
io::mouse::CursorManager::get()->showCursor(false);
os_poll();
int k = key_inkey();
switch (k) {
case KEY_ESC:
case KEY_ENTER:
case KEY_SPACEBAR:
state->playing = false;
break;
default:
break;
}
}
bool shouldBeginPlayback(Decoder* decoder) {
auto video = decoder->isVideoQueueFull();
auto audio = decoder->isAudioQueueFull();
auto subtitles = decoder->isSubtitleQueueFull();
// Wait until one of the queues is full, that should make sure
// that we have enough frames at the beginning of playback and that
@@ -267,79 +352,92 @@ bool shouldBeginPlayback(Decoder* decoder) {
// or video at the beginning
// Also only wait while the decoder is still working. Otherwise we will wait indefinitely if the video
// is very short.
return (audio || video || subtitles) || !decoder->isDecoding();
return (audio || video) || !decoder->isDecoding();
}
}
namespace cutscene {
Player::Player(std::unique_ptr<Decoder>&& decoder) : m_decoder(std::move(decoder)) {
initPlayback();
Player::Player() {
}
Player::~Player() {
// If video is initialized it means that stopPlayback has not been called yet
if (m_state.videoInited) {
stopPlayback();
}
if (m_decoder) {
m_decoder->close();
}
}
bool Player::processDecoderData() {
if (!m_state.playbackHasBegun) {
void Player::processDecoderData(PlayerState* state) {
if (!state->playbackHasBegun) {
// Wait until video and audio are available
// If we don't have audio, don't wait for it (obviously...)
if (!shouldBeginPlayback(m_state.decoder)) {
return true;
if (!shouldBeginPlayback(state->decoder)) {
return;
}
m_state.playbackHasBegun = true;
state->playbackHasBegun = true;
}
TRACE_SCOPE(tracing::CutsceneProcessDecoder);
processVideoData(&m_state);
processVideoData(state);
processSubtitleData(&m_state);
auto audioPlaying = processAudioData(&m_state);
auto audioPlaying = processAudioData(state);
// Set the playing flag if the decoder is still active or there is still data available
auto decoding = m_decoder->isDecoding();
// Audio is pending if there is data left in the queue or if OpenAL is still playing audio
// Audio is pending if there is data left in the queue or of OpenAL is still playing audio
auto pendingAudio = (m_decoder->isAudioFrameAvailable() && m_decoder->hasAudio()) || audioPlaying;
auto pendingVideo = m_decoder->isVideoFrameAvailable();
return decoding || pendingAudio || pendingVideo;
state->playing = decoding || pendingAudio || pendingVideo;
}
void Player::initPlayback() {
Assertion(!m_state.videoInited, "Internal State has been initialized before! Create a new player for replaying a movie.");
void Player::startPlayback() {
m_decoderThread.reset(new std::thread(std::bind(&Player::decoderThread, this)));
m_state.props = m_decoder->getProperties();
m_state.decoder = m_decoder.get();
PlayerState state;
state.props = m_decoder->getProperties();
state.decoder = m_decoder.get();
videoPlaybackInit(&m_state);
// Compute the maximum time we will sleep to make sure we can still maintain the movie FPS
// and not waste too much CPU time
// We will sleep at most half the time a frame would be displayed
auto sleepTime = static_cast<std::uint64_t>((1. / (4. * state.props.fps)) * 1000.);
audioPlaybackInit(&m_state);
}
bool Player::update(uint64_t diff_time_micro) {
if (m_state.playbackHasBegun) {
m_state.playback_time += diff_time_micro;
videoPlaybackInit(&state);
audioPlaybackInit(&state);
auto lastDisplayTimestamp = timer_get_microseconds();
while (state.playing) {
TRACE_SCOPE(tracing::CutsceneStep);
processDecoderData(&state);
displayVideo(&state);
processEvents(&state);
auto timestamp = timer_get_microseconds();
auto passed = timestamp - lastDisplayTimestamp;
lastDisplayTimestamp = timestamp;
if (state.playbackHasBegun) {
state.playback_time += passed;
}
if (passed < sleepTime) {
auto sleep = sleepTime - passed;
os_sleep(static_cast<uint>(sleep));
}
}
return processDecoderData();
}
void Player::stopPlayback() {
m_decoder->stopDecoder();
audioPlaybackClose(&m_state);
videoPlaybackClose(&m_state);
audioPlaybackClose(&state);
videoPlaybackClose(&state);
m_decoderThread->join();
}
@@ -362,28 +460,10 @@ std::unique_ptr<Player> Player::newPlayer(const SCP_string& name) {
if (decoder == nullptr) {
return nullptr;
}
return std::unique_ptr<Player>(new Player(std::move(decoder)));
}
const PlayerState& Player::getInternalState() const {
return m_state;
}
const MovieProperties& Player::getMovieProperties() const {
return m_state.props;
}
void Player::draw(float x1, float y1, float x2, float y2) {
if (!m_state.currentFrame) {
return;
}
if (m_state.videoPresenter) {
m_state.videoPresenter->displayFrame(x1, y1, x2, y2);
}
}
SCP_string Player::getCurrentSubtitle() {
if (!m_state.currentSubtitle) {
return "";
} else {
return m_state.currentSubtitle->text;
}
std::unique_ptr<Player> player(new Player());
player->m_decoder.reset(decoder);
return player;
}
}
+8 -89
View File
@@ -5,48 +5,11 @@
#include <thread>
#include "globalincs/pstypes.h"
#include "sound/openal.h"
#include "Decoder.h"
#include "VideoPresenter.h"
namespace cutscene {
class Decoder;
struct PlayerState {
MovieProperties props;
Decoder* decoder = nullptr;
bool playbackHasBegun = false;
// Timing state
std::uint64_t playback_time = 0;
// Audio state
bool audioInited = false;
bool hasAudio = false;
ALuint audioSid = 0;
SCP_vector<ALuint> audioBuffers;
SCP_queue<ALuint> unqueuedAudioBuffers;
// Graphics state following
bool videoInited = false;
VideoFramePtr currentFrame;
VideoFramePtr nextFrame;
bool newFrameAdded = false;
std::unique_ptr<player::VideoPresenter> videoPresenter;
SCP_queue<SubtitleFramePtr> queued_subtitles;
SubtitleFramePtr currentSubtitle;
PlayerState() {
}
PlayerState(const PlayerState&) = delete;
PlayerState& operator=(const PlayerState&) = delete;
};
struct PlayerState;
/**
* @brief A movie player
@@ -57,66 +20,22 @@ class Player {
std::unique_ptr<std::thread> m_decoderThread;
PlayerState m_state;
bool processDecoderData();
void processDecoderData(PlayerState* state);
private:
Player(const Player&) = delete;
void decoderThread();
void initPlayback();
public:
explicit Player(std::unique_ptr<Decoder>&& decoder);
Player();
~Player();
Player(const Player&) = delete;
Player& operator=(const Player&) = delete;
/**
* @brief Update the player and increase display timestamp by specified delta time
* @param diff_time_micro The time to increase the display timestamp in microseconds (not milliseconds!)
* @return @c true if there is more content to display. @c false if the player reached the end of the movie and has
* displayed the last frame.
*/
bool update(uint64_t diff_time_micro);
/**
* @brief Gives access to the internal state of the player
*
* @warning This should only be used for debugging purposed!
*
* @return A reference to the internal state
*/
const PlayerState& getInternalState() const;
/**
* @brief Gets the properties of the movie that this player is displaying
* @return A reference to the movie properties
*/
const MovieProperties& getMovieProperties() const;
/**
* @brief Draws the current movie frame at the specified coordinates.
*
* This may not draw anything if there is currently not a frame to display.
*
* @param x1 The X coordinate of the top left corner
* @param y1 The Y coordinate of the top left corner
* @param x2 The X coordinate of the bottom right corner
* @param y2 The Y coordinate of the bottom right corner
*/
void draw(float x1, float y1, float x2, float y2);
SCP_string getCurrentSubtitle();
/**
* @brief Stops playback
*
* This is also automatically called when this instance is destroyed.
*/
void stopPlayback();
* @brief Begin playing the previously selected movie
*/
void startPlayback();
/**
* @brief Creates a player
@@ -0,0 +1,223 @@
#include "OpenGLVideoPresenter.h"
#include "graphics/opengl/gropenglstate.h"
#include "graphics/opengl/gropengltnl.h"
#include "graphics/opengl/gropengldraw.h"
using namespace cutscene;
using namespace cutscene::player;
namespace cutscene {
namespace player {
OpenGLVideoPresenter::OpenGLVideoPresenter(const MovieProperties& props) : _scaleVideo(false),
_ytex(0), _utex(0), _vtex(0) {
GR_DEBUG_SCOPE("Init video");
opengl_set_texture_target(GL_TEXTURE_2D);
_vertexBuffer = gr_create_vertex_buffer(true);
auto w = static_cast<int>(props.size.width);
auto h = static_cast<int>(props.size.height);
_sdr_handle = gr_maybe_create_shader(SDR_TYPE_VIDEO_PROCESS, 0);
glGenTextures(1, &_ytex);
glGenTextures(1, &_utex);
glGenTextures(1, &_vtex);
if (_ytex + _utex + _vtex == 0) {
throw std::runtime_error("Can't create a GL texture");
}
opengl_shader_set_current(_sdr_handle);
gr_set_lighting(false, false);
GL_state.SetAlphaBlendMode(ALPHA_BLEND_NONE);
GL_state.SetZbufferType(ZBUFFER_TYPE_NONE);
GL_state.Texture.SetActiveUnit(0);
GL_state.Texture.SetTarget(GL_texture_target);
GL_state.Texture.Enable(_ytex);
glTexParameteri(GL_texture_target, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_texture_target, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_texture_target, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_texture_target, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
// NOTE: using NULL instead of pixelbuf crashes some drivers, but then so does pixelbuf
glTexImage2D(GL_state.Texture.GetTarget(), 0, GL_RED, w, h, 0, GL_RED,
GL_UNSIGNED_BYTE, NULL);
GL_state.Texture.SetActiveUnit(1);
GL_state.Texture.SetTarget(GL_texture_target);
GL_state.Texture.Enable(_utex);
glTexParameteri(GL_texture_target, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_texture_target, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_texture_target, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_texture_target, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
// NOTE: using NULL instead of pixelbuf crashes some drivers, but then so does pixelbuf
glTexImage2D(GL_state.Texture.GetTarget(), 0, GL_RED, w / 2, h / 2, 0, GL_RED,
GL_UNSIGNED_BYTE, NULL);
GL_state.Texture.SetActiveUnit(2);
GL_state.Texture.SetTarget(GL_texture_target);
GL_state.Texture.Enable(_vtex);
glTexParameteri(GL_texture_target, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_texture_target, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_texture_target, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_texture_target, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
// NOTE: using NULL instead of pixelbuf crashes some drivers, but then so does pixelbuf
glTexImage2D(GL_state.Texture.GetTarget(), 0, GL_RED, w / 2, h / 2, 0, GL_RED,
GL_UNSIGNED_BYTE, NULL);
float screen_ratio = (float) gr_screen.center_w / (float) gr_screen.center_h;
float movie_ratio = (float) props.size.width / (float) props.size.height;
float scale_by;
if (screen_ratio > movie_ratio) {
scale_by = (float) gr_screen.center_h / (float) props.size.height;
} else {
scale_by = (float) gr_screen.center_w / (float) props.size.width;
}
// don't bother setting anything if we aren't going to need it
if (!Cmdline_noscalevid && (scale_by != 1.0f)) {
vec3d scale;
scale.xyz.x = scale_by;
scale.xyz.y = scale_by;
scale.xyz.z = -1.0f;
gr_push_scale_matrix(&scale);
_scaleVideo = true;
}
int screenX;
int screenY;
if (_scaleVideo) {
screenX = fl2i(((gr_screen.center_w / 2.0f + gr_screen.center_offset_x) / scale_by) - (static_cast<int>(props.size.width) / 2.0f) + 0.5f);
screenY = fl2i(((gr_screen.center_h / 2.0f + gr_screen.center_offset_y) / scale_by) - (static_cast<int>(props.size.height) / 2.0f) + 0.5f);
} else {
// centers on 1024x768, fills on 640x480
screenX = ((gr_screen.center_w - static_cast<int>(props.size.width)) / 2) + gr_screen.center_offset_x;
screenY = ((gr_screen.center_h - static_cast<int>(props.size.height)) / 2) + gr_screen.center_offset_y;
}
// set additional values for screen width/height and UV coords
int screenXW = screenX + static_cast<int>(props.size.width);
int screenYH = screenY + static_cast<int>(props.size.height);
Current_shader->program->Uniforms.setUniformi("ytex", 0);
Current_shader->program->Uniforms.setUniformi("utex", 1);
Current_shader->program->Uniforms.setUniformi("vtex", 2);
Current_shader->program->Uniforms.setUniformMatrix4f("projMatrix", GL_projection_matrix);
Current_shader->program->Uniforms.setUniformMatrix4f("modelViewMatrix", GL_model_view_matrix);
GLfloat glVertices[4][4] = {{0}};
glVertices[0][0] = (GLfloat)screenX;
glVertices[0][1] = (GLfloat)screenY;
glVertices[0][2] = 0.0f;
glVertices[0][3] = 0.0f;
glVertices[1][0] = (GLfloat)screenX;
glVertices[1][1] = (GLfloat)screenYH;
glVertices[1][2] = 0.0f;
glVertices[1][3] = 1.0f;
glVertices[2][0] = (GLfloat)screenXW;
glVertices[2][1] = (GLfloat)screenY;
glVertices[2][2] = 1.0f;
glVertices[2][3] = 0.0f;
glVertices[3][0] = (GLfloat)screenXW;
glVertices[3][1] = (GLfloat)screenYH;
glVertices[3][2] = 1.0f;
glVertices[3][3] = 1.0f;
_vertexLayout.add_vertex_component(vertex_format_data::POSITION2, sizeof(glVertices[0]), 0);
_vertexLayout.add_vertex_component(vertex_format_data::TEX_COORD, sizeof(glVertices[0]), sizeof(GLfloat) * 2);
gr_update_buffer_data(_vertexBuffer, sizeof(glVertices[0]) * 4, glVertices);
}
OpenGLVideoPresenter::~OpenGLVideoPresenter() {
GR_DEBUG_SCOPE("Deinit video");
if (_scaleVideo) {
gr_pop_scale_matrix();
}
gr_delete_buffer(_vertexBuffer);
_vertexBuffer = -1;
GL_state.Texture.Delete(_ytex);
GL_state.Texture.Delete(_utex);
GL_state.Texture.Delete(_vtex);
glDeleteTextures(1, &_ytex);
glDeleteTextures(1, &_utex);
glDeleteTextures(1, &_vtex);
opengl_set_texture_target();
_ytex = _utex = _vtex = 0;
opengl_shader_set_current();
}
void OpenGLVideoPresenter::uploadVideoFrame(const VideoFramePtr& frame) {
GR_DEBUG_SCOPE("Update video frame");
auto ptrs = frame->getDataPointers();
auto stride = static_cast<GLint>(frame->ySize.stride);
auto width = static_cast<GLint>(frame->ySize.width);
auto height = static_cast<GLint>(frame->ySize.height);
GL_state.Texture.SetActiveUnit(0);
GL_state.Texture.Enable(_ytex);
glPixelStorei(GL_UNPACK_ROW_LENGTH, stride);
glTexSubImage2D(GL_state.Texture.GetTarget(), 0, 0, 0, width, height, GL_RED, GL_UNSIGNED_BYTE,
ptrs.y);
stride = static_cast<int>(frame->uvSize.stride);
width = static_cast<int>(frame->uvSize.width);
height = static_cast<int>(frame->uvSize.height);
GL_state.Texture.SetActiveUnit(1);
GL_state.Texture.Enable(_utex);
glPixelStorei(GL_UNPACK_ROW_LENGTH, stride);
glTexSubImage2D(GL_state.Texture.GetTarget(), 0, 0, 0, width, height, GL_RED, GL_UNSIGNED_BYTE,
ptrs.u);
GL_state.Texture.SetActiveUnit(2);
GL_state.Texture.Enable(_vtex);
glTexSubImage2D(GL_state.Texture.GetTarget(), 0, 0, 0, width, height, GL_RED, GL_UNSIGNED_BYTE,
ptrs.v);
// Reset this back to default
glPixelStorei(GL_UNPACK_ROW_LENGTH, 0);
}
void OpenGLVideoPresenter::displayFrame() {
opengl_shader_set_current(_sdr_handle);
opengl_bind_buffer_object(_vertexBuffer);
opengl_bind_vertex_layout(_vertexLayout);
// Bind textures
GL_state.Texture.SetActiveUnit(0);
GL_state.Texture.Enable(_ytex);
GL_state.Texture.SetActiveUnit(1);
GL_state.Texture.Enable(_utex);
GL_state.Texture.SetActiveUnit(2);
GL_state.Texture.Enable(_vtex);
GR_DEBUG_SCOPE("Draw video frame");
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
}
}
}
@@ -0,0 +1,38 @@
#ifndef FS2_OPEN_OPENGLVIDEOPRESENTER_H
#define FS2_OPEN_OPENGLVIDEOPRESENTER_H
#include "globalincs/pstypes.h"
#include "cutscene/player/VideoPresenter.h"
#include <glad/glad.h>
#include <memory>
#include <graphics/2d.h>
namespace cutscene {
namespace player {
class OpenGLVideoPresenter: public VideoPresenter {
int _vertexBuffer = -1;
vertex_layout _vertexLayout;
int _sdr_handle = -1;
bool _scaleVideo = false;
GLuint _ytex = 0;
GLuint _utex = 0;
GLuint _vtex = 0;
public:
OpenGLVideoPresenter(const MovieProperties& props);
virtual ~OpenGLVideoPresenter();
virtual void uploadVideoFrame(const VideoFramePtr& frame) SCP_OVERRIDE;
virtual void displayFrame() SCP_OVERRIDE;
};
}
}
#endif //FS2_OPEN_OPENGLVIDEOPRESENTER_H
+21
View File
@@ -0,0 +1,21 @@
#ifndef FS2_OPEN_VIDEOPRESENTER_H
#define FS2_OPEN_VIDEOPRESENTER_H
#include "globalincs/pstypes.h"
#include "cutscene/Decoder.h"
namespace cutscene {
namespace player {
class VideoPresenter {
public:
virtual ~VideoPresenter() {}
virtual void uploadVideoFrame(const VideoFramePtr& frame) = 0;
virtual void displayFrame() = 0;
};
}
}
#endif //FS2_OPEN_VIDEOPRESENTER_H
+6 -6
View File
@@ -74,7 +74,7 @@ static void debris_start_death_roll(object *debris_obj, debris *debris_p)
// only play debris destroy sound if hull piece and it has been around for at least 2 seconds
if ( Missiontime > debris_p->time_started + 2*F1_0 ) {
snd_play_3d( gamesnd_get_game_sound(SND_MISSILE_IMPACT1), &debris_obj->pos, &View_position, debris_obj->radius );
snd_play_3d( &Snds[SND_MISSILE_IMPACT1], &debris_obj->pos, &View_position, debris_obj->radius );
}
}
@@ -324,19 +324,19 @@ void debris_process_post(object * obj, float frame_time)
//Play a sound effect
if ( lifetime > 750 ) {
// 1.00 second effect
snd_play_3d( gamesnd_get_game_sound(SND_DEBRIS_ARC_05), &snd_pos, &View_position, obj->radius );
snd_play_3d( &Snds[SND_DEBRIS_ARC_05], &snd_pos, &View_position, obj->radius );
} else if ( lifetime > 500 ) {
// 0.75 second effect
snd_play_3d( gamesnd_get_game_sound(SND_DEBRIS_ARC_04), &snd_pos, &View_position, obj->radius );
snd_play_3d( &Snds[SND_DEBRIS_ARC_04], &snd_pos, &View_position, obj->radius );
} else if ( lifetime > 250 ) {
// 0.50 second effect
snd_play_3d( gamesnd_get_game_sound(SND_DEBRIS_ARC_03), &snd_pos, &View_position, obj->radius );
snd_play_3d( &Snds[SND_DEBRIS_ARC_03], &snd_pos, &View_position, obj->radius );
} else if ( lifetime > 100 ) {
// 0.25 second effect
snd_play_3d( gamesnd_get_game_sound(SND_DEBRIS_ARC_02), &snd_pos, &View_position, obj->radius );
snd_play_3d( &Snds[SND_DEBRIS_ARC_02], &snd_pos, &View_position, obj->radius );
} else {
// 0.10 second effect
snd_play_3d( gamesnd_get_game_sound(SND_DEBRIS_ARC_01), &snd_pos, &View_position, obj->radius );
snd_play_3d( &Snds[SND_DEBRIS_ARC_01], &snd_pos, &View_position, obj->radius );
}
}
}
-15
View File
@@ -1,15 +0,0 @@
in vec4 fragTexCoord;
in vec4 fragColor;
out vec4 fragOut0;
uniform sampler2DArray baseMap;
uniform float intensity;
#define SRGB_GAMMA 2.2
void main()
{
vec4 baseColor = texture(baseMap, fragTexCoord.xyz);
baseColor.rgb = pow(baseColor.rgb, vec3(SRGB_GAMMA));
vec4 blendColor = vec4(pow(fragColor.rgb, vec3(SRGB_GAMMA)), fragColor.a);
fragOut0 = baseColor * blendColor * intensity;
}
-14
View File
@@ -1,14 +0,0 @@
in vec4 vertPosition;
in vec4 vertTexCoord;
in vec4 vertColor;
out vec4 fragTexCoord;
out vec4 fragColor;
uniform mat4 modelViewMatrix;
uniform mat4 projMatrix;
uniform vec4 color;
void main()
{
fragTexCoord = vec4(vertTexCoord.xyz, 0.0);
fragColor = vertColor * color;
gl_Position = projMatrix * modelViewMatrix * vertPosition;
}
-19
View File
@@ -1,19 +0,0 @@
in vec4 fragTexCoord;
in vec4 fragColor;
out vec4 fragOut0;
uniform sampler2DArray baseMap;
uniform int baseMapIndex;
uniform int alphaTexture;
uniform int noTexturing;
uniform int srgb;
uniform float intensity;
uniform float alphaThreshold;
#define SRGB_GAMMA 2.2
void main()
{
vec4 baseColor = texture(baseMap, vec3(fragTexCoord.xy, float(baseMapIndex)));
if(alphaThreshold > baseColor.a) discard;
baseColor.rgb = (srgb == 1) ? pow(baseColor.rgb, vec3(SRGB_GAMMA)) : baseColor.rgb;
vec4 blendColor = (srgb == 1) ? vec4(pow(fragColor.rgb, vec3(SRGB_GAMMA)), fragColor.a) : fragColor;
fragOut0 = mix(mix(baseColor * blendColor, vec4(blendColor.rgb, baseColor.r * blendColor.a), float(alphaTexture)), blendColor, float(noTexturing)) * intensity;
}
+9 -19
View File
@@ -1,31 +1,21 @@
in vec3 beamVec;
in vec3 lightPosition;
out vec4 fragOut0;
uniform sampler2D ColorBuffer;
uniform sampler2D NormalBuffer;
uniform sampler2D PositionBuffer;
uniform sampler2D SpecBuffer;
uniform float specFactor;
uniform float invScreenWidth;
uniform float invScreenHeight;
layout (std140) uniform lightData {
vec3 diffuseLightColor;
float coneAngle;
vec3 specLightColor;
float coneInnerAngle;
vec3 coneDir;
bool dualCone;
vec3 scale;
float lightRadius;
int lightType;
};
uniform int lightType;
uniform float lightRadius;
uniform vec3 diffuseLightColor;
uniform vec3 specLightColor;
uniform float coneAngle;
uniform float coneInnerAngle;
uniform bool dualCone;
uniform vec3 coneDir;
#define SPEC_INTENSITY_POINT 5.3 // Point light
#define SPEC_INTENSITY_DIRECTIONAL 3.0 // Directional light
@@ -103,4 +93,4 @@ void main()
vec4 fragmentColor = vec4(color * (diffuseLightColor * NdotL * attenuation), 1.0);
fragmentColor.rgb += SpecularBlinnPhong(specColor.rgb, lightDir, normal.xyz, halfVec, exp2(10.0 * gloss + 1.0), fresnel, NdotL).rgb * specLightColor * attenuation;
fragOut0 = max(fragmentColor, vec4(0.0));
}
}
+3 -18
View File
@@ -1,23 +1,8 @@
in vec4 vertPosition;
uniform mat4 modelViewMatrix;
uniform mat4 projMatrix;
layout (std140) uniform lightData {
vec3 diffuseLightColor;
float coneAngle;
vec3 specLightColor;
float coneInnerAngle;
vec3 coneDir;
bool dualCone;
vec3 scale;
float lightRadius;
int lightType;
};
uniform vec3 scale;
uniform int lightType;
out vec3 lightPosition;
out vec3 beamVec;
void main()
@@ -26,4 +11,4 @@ void main()
lightPosition = modelViewMatrix[3].xyz;
if(lightType == 1)
beamVec = vec3(modelViewMatrix * vec4(0.0, 0.0, -scale.z, 0.0));
}
}
+3 -3
View File
@@ -2,7 +2,7 @@ in vec4 fragTexCoord;
in vec4 fragColor;
in float fragOffset;
out vec4 fragOut0;
uniform sampler2DArray baseMap;
uniform sampler2D baseMap;
uniform sampler2D depthMap;
uniform float window_width;
uniform float window_height;
@@ -11,10 +11,10 @@ uniform sampler2D frameBuffer;
void main()
{
vec2 depthCoord = vec2(gl_FragCoord.x / window_width, gl_FragCoord.y / window_height);
vec4 fragmentColor = texture(baseMap, fragTexCoord.xyz) * fragColor.a;
vec4 fragmentColor = texture(baseMap, fragTexCoord.xy) * fragColor.a;
vec2 distortion = texture(distMap, fragTexCoord.xy+vec2(0.0, fragOffset)).rg;
float alpha = clamp(dot(fragmentColor.rgb,vec3(0.3333))*10.0,0.0,1.0);
distortion = ((distortion - 0.5) * 0.01) * alpha;
fragOut0 = texture(frameBuffer,depthCoord+distortion);
fragOut0.a = alpha;
}
}
+2 -2
View File
@@ -12,6 +12,6 @@ void main()
{
gl_Position = projMatrix * modelViewMatrix * vertPosition;
fragOffset = vertRadius * use_offset;
fragTexCoord = vec4(vertTexCoord.xyz, 0.0);
fragTexCoord = vertTexCoord;
fragColor = vertColor;
}
}
+10
View File
@@ -0,0 +1,10 @@
in vec4 fragTexCoord;
in vec4 fragColor;
out vec4 fragOut0;
uniform sampler2D baseMap;
uniform int textured;
void main()
{
vec4 fragmentColor = mix(fragColor, texture(baseMap, fragTexCoord.xy)*fragColor.a, (float)textured);
fragOut0 = fragmentColor;
}
+3 -3
View File
@@ -1,4 +1,4 @@
uniform sampler2DArray baseMap;
uniform sampler2D baseMap;
uniform sampler2D depthMap;
uniform float window_width;
uniform float window_height;
@@ -15,7 +15,7 @@ out vec4 fragOut0;
#define SRGB_GAMMA 2.2
void main()
{
vec4 fragmentColor = texture(baseMap, fragTexCoord.xyz);
vec4 fragmentColor = texture(baseMap, fragTexCoord.xy);
fragmentColor.rgb = mix(fragmentColor.rgb, pow(fragmentColor.rgb, vec3(SRGB_GAMMA)), float(srgb));
fragmentColor *= mix(fragColor, vec4(pow(fragColor.rgb, vec3(SRGB_GAMMA)), fragColor.a), float(srgb));
vec2 offset = vec2(fragRadius * abs(0.5 - fragTexCoord.x) * 2.0, fragRadius * abs(0.5 - fragTexCoord.y) * 2.0);
@@ -43,4 +43,4 @@ void main()
fragmentColor.rgb *= (srgb == 1) ? 1.5 : 1.0;
fragmentColor = (blend_alpha == 1) ? vec4(fragmentColor.rgb, fragmentColor.a * intensity) : vec4(fragmentColor.rgb * intensity, fragmentColor.a);
fragOut0 = max(fragmentColor, vec4(0.0));
}
}
+5 -6
View File
@@ -3,7 +3,6 @@ layout (triangle_strip, max_vertices = 4) out;
in vec3 geoUvec[];
in float geoRadius[];
in vec4 geoColor[];
in float geoArrayIndex[];
out float fragRadius;
out vec4 fragPosition;
out vec4 fragTexCoord;
@@ -19,7 +18,7 @@ void main(void)
pos = (gl_in[0].gl_Position - vec4(geoRadius[0] * up_vec, 0.0) - vec4(geoRadius[0] * right_vec, 0.0));
gl_Position = projMatrix * pos;
fragPosition = pos;
fragTexCoord = vec4(0.0, 0.0, geoArrayIndex[0], 0.0);
fragTexCoord = vec4(0.0, 0.0, 0.0, 0.0);
fragRadius = geoRadius[0];
fragColor = geoColor[0];
EmitVertex();
@@ -27,7 +26,7 @@ void main(void)
pos = (gl_in[0].gl_Position - vec4(geoRadius[0] * up_vec, 0.0) + vec4(geoRadius[0] * right_vec, 0.0));
gl_Position = projMatrix * pos;
fragPosition = pos;
fragTexCoord = vec4(0.0, 1.0, geoArrayIndex[0], 0.0);
fragTexCoord = vec4(0.0, 1.0, 0.0, 0.0);
fragRadius = geoRadius[0];
fragColor = geoColor[0];
EmitVertex();
@@ -35,7 +34,7 @@ void main(void)
pos = (gl_in[0].gl_Position + vec4(geoRadius[0] * up_vec, 0.0) - vec4(geoRadius[0] * right_vec, 0.0));
gl_Position = projMatrix * pos;
fragPosition = pos;
fragTexCoord = vec4(1.0, 0.0, geoArrayIndex[0], 0.0);
fragTexCoord = vec4(1.0, 0.0, 0.0, 0.0);
fragRadius = geoRadius[0];
fragColor = geoColor[0];
EmitVertex();
@@ -43,9 +42,9 @@ void main(void)
pos = (gl_in[0].gl_Position + vec4(geoRadius[0] * up_vec, 0.0) + vec4(geoRadius[0] * right_vec, 0.0));
gl_Position = projMatrix * pos;
fragPosition = pos;
fragTexCoord = vec4(1.0, 1.0, geoArrayIndex[0], 0.0);
fragTexCoord = vec4(1.0, 1.0, 0.0, 0.0);
fragRadius = geoRadius[0];
fragColor = geoColor[0];
EmitVertex();
EndPrimitive();
}
}
+2 -4
View File
@@ -7,7 +7,6 @@ in float vertRadius;
out vec3 geoUvec;
out float geoRadius;
out vec4 geoColor;
out float geoArrayIndex;
#else
out float fragRadius;
out vec4 fragPosition;
@@ -27,15 +26,14 @@ void main()
geoUvec = vertUvec;
gl_Position = modelViewMatrix * vertPosition;
geoColor = vertColor;
geoArrayIndex = vertTexCoord.z;
#else
fragRadius = vertRadius;
gl_Position = projMatrix * modelViewMatrix * vertPosition;
fragPosition = modelViewMatrix * vertPosition;
fragTexCoord = vec4(vertTexCoord.xyz, 0.0);
fragTexCoord = vertTexCoord;
fragColor = vertColor;
#endif
#ifdef FLAG_EFFECT_DISTORTION
fragOffset = vertRadius * use_offset;
#endif
}
}
+77 -114
View File
@@ -2,131 +2,88 @@
#define LT_DIRECTIONAL 0
#define LT_POINT 1
#define LT_TUBE 2
struct model_light {
vec4 position;
vec3 diffuse_color;
int light_type;
vec3 spec_color;
float attenuation;
vec3 direction;
};
layout (std140) uniform modelData {
mat4 modelViewMatrix;
mat4 modelMatrix;
mat4 viewMatrix;
mat4 projMatrix;
mat4 textureMatrix;
mat4 shadow_mv_matrix;
mat4 shadow_proj_matrix[4];
mat4 envMatrix;
vec4 color;
model_light lights[MAX_LIGHTS];
float extrudeWidth;
float fogStart;
float fogScale;
int buffer_matrix_offset;
vec4 clip_equation;
float thruster_scale;
bool use_clip_plane;
int n_lights;
float defaultGloss;
vec3 ambientFactor;
int desaturate;
vec3 diffuseFactor;
int blend_alpha;
vec3 emissionFactor;
bool overrideDiffuse;
vec3 diffuseClr;
bool overrideGlow;
vec3 glowClr;
bool overrideSpec;
vec3 specClr;
bool alphaGloss;
bool gammaSpec;
bool envGloss;
bool alpha_spec;
int effect_num;
vec4 fogColor;
vec3 base_color;
float anim_timer;
vec3 stripe_color;
float vpwidth;
float vpheight;
bool team_glow_enabled;
float znear;
float zfar;
float veryneardist;
float neardist;
float middist;
float fardist;
vec2 normalAlphaMinMax;
int sBasemapIndex;
int sGlowmapIndex;
int sSpecmapIndex;
int sNormalmapIndex;
int sAmbientmapIndex;
int sMiscmapIndex;
};
uniform vec4 color;
#ifdef FLAG_LIGHT
uniform vec4 lightPosition[MAX_LIGHTS];
uniform vec3 lightDirection[MAX_LIGHTS];
uniform vec3 lightDiffuseColor[MAX_LIGHTS];
uniform vec3 lightSpecColor[MAX_LIGHTS];
uniform int lightType[MAX_LIGHTS];
uniform float lightAttenuation[MAX_LIGHTS];
uniform int n_lights;
uniform float defaultGloss;
uniform vec3 ambientFactor;
uniform vec3 diffuseFactor;
uniform vec3 emissionFactor;
#endif
#ifdef FLAG_DIFFUSE_MAP
uniform sampler2DArray sBasemap;
uniform sampler2D sBasemap;
uniform int desaturate;
uniform int blend_alpha;
uniform bool overrideDiffuse;
uniform vec3 diffuseClr;
#endif
#ifdef FLAG_GLOW_MAP
uniform sampler2DArray sGlowmap;
uniform sampler2D sGlowmap;
uniform bool overrideGlow;
uniform vec3 glowClr;
#endif
#ifdef FLAG_SPEC_MAP
uniform sampler2DArray sSpecmap;
uniform sampler2D sSpecmap;
uniform bool overrideSpec;
uniform vec3 specClr;
uniform bool alphaGloss;
uniform bool gammaSpec;
#endif
#ifdef FLAG_ENV_MAP
uniform samplerCube sEnvmap;
uniform bool envGloss;
uniform bool alpha_spec;
in vec3 fragEnvReflect;
#endif
#ifdef FLAG_NORMAL_MAP
uniform sampler2DArray sNormalmap;
uniform sampler2D sNormalmap;
in mat3 fragTangentMatrix;
#endif
#ifdef FLAG_AMBIENT_MAP
uniform sampler2DArray sAmbientmap;
uniform sampler2D sAmbientmap;
#endif
#ifdef FLAG_FOG
uniform vec4 fogColor;
in float fragFogDist;
#endif
#ifdef FLAG_ANIMATED
uniform sampler2D sFramebuffer;
uniform int effect_num;
uniform float anim_timer;
uniform float vpwidth;
uniform float vpheight;
#endif
#ifdef FLAG_TRANSFORM
in float fragNotVisible;
#endif
#ifdef FLAG_TEAMCOLOR
uniform vec3 base_color;
uniform vec3 stripe_color;
uniform bool team_glow_enabled;
vec2 teamMask = vec2(0.0, 0.0);
#endif
#ifdef FLAG_MISC_MAP
uniform sampler2DArray sMiscmap;
uniform sampler2D sMiscmap;
#endif
#ifdef FLAG_SHADOWS
in vec4 fragShadowUV[4];
in vec4 fragShadowPos;
uniform sampler2DArray shadow_map;
uniform float znear;
uniform float zfar;
uniform float veryneardist;
uniform float neardist;
uniform float middist;
uniform float fardist;
#endif
#ifdef FLAG_NORMAL_ALPHA
uniform vec2 normalAlphaMinMax;
#endif
#define SPEC_INTENSITY_POINT 5.3 // Point light
#define SPEC_INTENSITY_DIRECTIONAL 3.0 // Directional light
@@ -253,26 +210,26 @@ vec3 SpecularBlinnPhong(vec3 specColor, vec3 light, vec3 normal, vec3 halfVec, f
#ifdef FLAG_LIGHT
void GetLightInfo(int i, out vec3 lightDir, out float attenuation)
{
lightDir = normalize(lights[i].position.xyz);
lightDir = normalize(lightPosition[i].xyz);
attenuation = 1.0;
if (lights[i].light_type != LT_DIRECTIONAL) {
if (lightType[i] != LT_DIRECTIONAL) {
// Positional light source
float dist = distance(lights[i].position.xyz, fragPosition.xyz);
lightDir = (lights[i].position.xyz - fragPosition.xyz);
float dist = distance(lightPosition[i].xyz, fragPosition.xyz);
lightDir = (lightPosition[i].xyz - fragPosition.xyz);
if (lights[i].light_type == LT_TUBE) { // Tube light
float beamlength = length(lights[i].direction);
vec3 beamDir = normalize(lights[i].direction);
if (lightType[i] == LT_TUBE) { // Tube light
float beamlength = length(lightDirection[i]);
vec3 beamDir = normalize(lightDirection[i]);
// Get nearest point on line
float neardist = dot(fragPosition.xyz - lights[i].position.xyz, beamDir);
float neardist = dot(fragPosition.xyz - lightPosition[i].xyz, beamDir);
// Move back from the endpoint of the beam along the beam by the distance we calculated
vec3 nearest = lights[i].position.xyz - beamDir * abs(neardist);
vec3 nearest = lightPosition[i].xyz - beamDir * abs(neardist);
lightDir = nearest - fragPosition.xyz;
dist = length(lightDir);
}
lightDir = normalize(lightDir);
attenuation = 1.0 / (1.0 + lights[i].attenuation * dist);
attenuation = 1.0 / (1.0 + lightAttenuation[i] * dist);
}
}
vec3 CalculateLighting(vec3 normal, vec3 diffuseMaterial, vec3 specularMaterial, float gloss, float fresnel, float shadow, float aoFactor)
@@ -282,7 +239,10 @@ vec3 CalculateLighting(vec3 normal, vec3 diffuseMaterial, vec3 specularMaterial,
vec3 lightDiffuse = vec3(0.0, 0.0, 0.0);
vec3 lightSpecular = vec3(0.0, 0.0, 0.0);
#pragma optionNV unroll all
for (int i = 0; i < n_lights; ++i) {
for (int i = 0; i < MAX_LIGHTS; ++i) {
if (i > n_lights)
break;
if(i > 0) {
shadow = 1.0;
}
@@ -294,14 +254,17 @@ vec3 CalculateLighting(vec3 normal, vec3 diffuseMaterial, vec3 specularMaterial,
vec3 halfVec = normalize(lightDir + eyeDir);
float NdotL = max(dot(normal, lightDir), 0.0);
// Ambient, Diffuse, and Specular
lightDiffuse += (lights[i].diffuse_color.rgb * diffuseFactor * NdotL * attenuation) * shadow;
lightSpecular += lights[i].spec_color * SpecularBlinnPhong(specularMaterial, lightDir, normal, halfVec, exp2(10.0 * gloss + 1.0), fresnel, NdotL) * attenuation * shadow;
lightDiffuse += (lightDiffuseColor[i].rgb * diffuseFactor * NdotL * attenuation) * shadow;
lightSpecular += lightSpecColor[i] * SpecularBlinnPhong(specularMaterial, lightDir, normal, halfVec, exp2(10.0 * gloss + 1.0), fresnel, NdotL) * attenuation * shadow;
}
return diffuseMaterial * (lightAmbient + lightDiffuse) + lightSpecular;
}
#endif
void main()
{
#ifdef FLAG_TRANSFORM
if(fragNotVisible >= 0.9) { discard; }
#endif
#ifdef FLAG_SHADOW_MAP
// need depth and depth squared for variance shadow maps
fragOut0 = vec4(fragPosition.z, fragPosition.z * fragPosition.z * VARIANCE_SHADOW_SCALE_INV, 0.0, 1.0);
@@ -320,14 +283,14 @@ void main()
#ifdef FLAG_AMBIENT_MAP
// red channel is ambient occlusion factor which only affects ambient lighting.
// green is cavity occlusion factor which only affects diffuse and specular lighting.
aoFactors = texture(sAmbientmap, vec3(texCoord, float(sAmbientmapIndex))).xy;
aoFactors = texture(sAmbientmap, texCoord).xy;
#endif
vec3 unitNormal = normalize(fragNormal);
vec3 normal = unitNormal;
#ifdef FLAG_NORMAL_MAP
// Normal map - convert from DXT5nm
vec2 normalSample;
normal.rg = normalSample = (texture(sNormalmap, vec3(texCoord, float(sNormalmapIndex))).ag * 2.0) - 1.0;
normal.rg = normalSample = (texture(sNormalmap, texCoord).ag * 2.0) - 1.0;
normal.b = clamp(sqrt(1.0 - dot(normal.rg, normal.rg)), 0.0001, 1.0);
normal = fragTangentMatrix * normal;
float norm = length(normal);
@@ -349,7 +312,7 @@ void main()
diffuseTexCoord = texCoord + distort*(1.0-anim_timer);
}
#endif
baseColor = texture(sBasemap, vec3(diffuseTexCoord, float(sBasemapIndex)));
baseColor = texture(sBasemap, diffuseTexCoord);
if ( blend_alpha == 0 && baseColor.a < 0.95 ) discard; // if alpha blending is not on, discard transparent pixels
// premultiply alpha if blend_alpha is 1. assume that our blend function is srcColor + (1-Alpha)*destColor.
// if blend_alpha is 2, assume blend func is additive and don't modify color
@@ -361,7 +324,7 @@ void main()
baseColor.rgb = pow(baseColor.rgb, vec3(SRGB_GAMMA));
#endif
#ifdef FLAG_SPEC_MAP
specColor = texture(sSpecmap, vec3(texCoord, float(sSpecmapIndex)));
specColor = texture(sSpecmap, texCoord);
if(alphaGloss) glossData = specColor.a;
if(overrideSpec) {
specColor.rgb = specClr;
@@ -380,7 +343,7 @@ void main()
#ifdef FLAG_MISC_MAP
#ifdef FLAG_TEAMCOLOR
vec4 teamMask = vec4(0.0, 0.0, 0.0, 0.0);
teamMask = texture(sMiscmap, vec3(texCoord, float(sMiscmapIndex)));
teamMask = texture(sMiscmap, texCoord);
vec3 base = max(base_color - vec3(0.5), vec3(0.0));
vec3 stripe = max(stripe_color - vec3(0.5), vec3(0.0));
baseColor.rgb += (base * teamMask.x) + (stripe * teamMask.y);
@@ -413,7 +376,7 @@ void main()
baseColor.rgb += envColour.rgb * FresnelLazarovEnv(specColor.rgb, eyeDir, normal, glossData);
#endif
#ifdef FLAG_GLOW_MAP
vec3 glowColor = texture(sGlowmap, vec3(texCoord, float(sGlowmapIndex))).rgb;
vec3 glowColor = texture(sGlowmap, texCoord).rgb;
if(overrideGlow) glowColor = glowClr;
#ifdef FLAG_HDR
glowColor = pow(glowColor, vec3(SRGB_GAMMA)) * 3.0f;
+12 -107
View File
@@ -1,130 +1,35 @@
#extension GL_ARB_gpu_shader5: enable
layout (triangles) in;
layout (triangle_strip, max_vertices = 3) out;
#ifdef GL_ARB_gpu_shader5
layout(invocations = 4) in;
#endif
#define MAX_LIGHTS 8
struct model_light {
vec4 position;
vec3 diffuse_color;
int light_type;
vec3 spec_color;
float attenuation;
vec3 direction;
};
layout (std140) uniform modelData {
mat4 modelViewMatrix;
mat4 modelMatrix;
mat4 viewMatrix;
mat4 projMatrix;
mat4 textureMatrix;
mat4 shadow_mv_matrix;
mat4 shadow_proj_matrix[4];
mat4 envMatrix;
vec4 color;
model_light lights[MAX_LIGHTS];
float extrudeWidth;
float fogStart;
float fogScale;
int buffer_matrix_offset;
vec4 clip_equation;
float thruster_scale;
bool use_clip_plane;
int n_lights;
float defaultGloss;
vec3 ambientFactor;
int desaturate;
vec3 diffuseFactor;
int blend_alpha;
vec3 emissionFactor;
bool overrideDiffuse;
vec3 diffuseClr;
bool overrideGlow;
vec3 glowClr;
bool overrideSpec;
vec3 specClr;
bool alphaGloss;
bool gammaSpec;
bool envGloss;
bool alpha_spec;
int effect_num;
vec4 fogColor;
vec3 base_color;
float anim_timer;
vec3 stripe_color;
float vpwidth;
float vpheight;
bool team_glow_enabled;
float znear;
float zfar;
float veryneardist;
float neardist;
float middist;
float fardist;
vec2 normalAlphaMinMax;
int sBasemapIndex;
int sGlowmapIndex;
int sSpecmapIndex;
int sNormalmapIndex;
int sAmbientmapIndex;
int sMiscmapIndex;
};
#if !defined(GL_ARB_gpu_shader5)
uniform mat4 shadow_proj_matrix[4];
in float geoInstance[];
#endif
in vec3 geoNormal[];
in vec4 geoTexCoord[];
out vec4 fragPosition;
out vec3 fragNormal;
out vec4 fragTexCoord;
#ifdef FLAG_TRANSFORM
in float geoNotVisible[];
out float fragNotVisible;
#endif
void main(void)
{
#ifdef GL_ARB_gpu_shader5
int instanceID = gl_InvocationID;
#else
int instanceID = int(geoInstance[0]);
#endif
for(int vert = 0; vert < gl_in.length(); vert++)
for(int vert = 0; vert < gl_in.length(); vert++)
{
gl_Position = shadow_proj_matrix[instanceID] * gl_in[vert].gl_Position;
if(gl_Position.z < -1.0)
gl_Position.z = -1.0;
fragPosition = gl_in[vert].gl_Position;
fragPosition = gl_in[vert].gl_Position;
fragNormal = geoNormal[vert];
fragTexCoord = geoTexCoord[vert];
gl_Layer = instanceID;
#if defined(FLAG_CLIP) || defined(FLAG_TRANSFORM)
#ifdef FLAG_TRANSFORM
fragNotVisible = geoNotVisible[0];
#endif
#ifdef FLAG_CLIP
gl_ClipDistance[0] = gl_in[vert].gl_ClipDistance[0];
#endif
EmitVertex();
}
EndPrimitive();
}
}
+41 -113
View File
@@ -1,117 +1,41 @@
#extension GL_ARB_gpu_shader5: enable
#define MAX_LIGHTS 8
struct model_light {
vec4 position;
vec3 diffuse_color;
int light_type;
vec3 spec_color;
float attenuation;
vec3 direction;
};
layout (std140) uniform modelData {
mat4 modelViewMatrix;
mat4 modelMatrix;
mat4 viewMatrix;
mat4 projMatrix;
mat4 textureMatrix;
mat4 shadow_mv_matrix;
mat4 shadow_proj_matrix[4];
mat4 envMatrix;
vec4 color;
model_light lights[MAX_LIGHTS];
float extrudeWidth;
float fogStart;
float fogScale;
int buffer_matrix_offset;
vec4 clip_equation;
float thruster_scale;
bool use_clip_plane;
int n_lights;
float defaultGloss;
vec3 ambientFactor;
int desaturate;
vec3 diffuseFactor;
int blend_alpha;
vec3 emissionFactor;
bool overrideDiffuse;
vec3 diffuseClr;
bool overrideGlow;
vec3 glowClr;
bool overrideSpec;
vec3 specClr;
bool alphaGloss;
bool gammaSpec;
bool envGloss;
bool alpha_spec;
int effect_num;
vec4 fogColor;
vec3 base_color;
float anim_timer;
vec3 stripe_color;
float vpwidth;
float vpheight;
bool team_glow_enabled;
float znear;
float zfar;
float veryneardist;
float neardist;
float middist;
float fardist;
vec2 normalAlphaMinMax;
int sBasemapIndex;
int sGlowmapIndex;
int sSpecmapIndex;
int sNormalmapIndex;
int sAmbientmapIndex;
int sMiscmapIndex;
};
in vec4 vertPosition;
in vec4 vertTexCoord;
in vec3 vertNormal;
in vec4 vertTangent;
in float vertModelID;
uniform mat4 modelViewMatrix;
uniform mat4 modelMatrix;
uniform mat4 viewMatrix;
uniform mat4 projMatrix;
uniform mat4 textureMatrix;
uniform vec4 color;
#ifdef FLAG_NORMAL_EXTRUDE
uniform float extrudeWidth;
#endif
#ifdef FLAG_ENV_MAP
uniform mat4 envMatrix;
out vec3 fragEnvReflect;
#endif
#ifdef FLAG_NORMAL_MAP
out mat3 fragTangentMatrix;
#endif
#ifdef FLAG_FOG
uniform float fogStart;
uniform float fogScale;
out float fragFogDist;
#endif
#ifdef FLAG_TRANSFORM
uniform samplerBuffer transform_tex;
uniform int buffer_matrix_offset;
#ifdef FLAG_SHADOW_MAP
out float geoNotVisible;
#else
out float fragNotVisible;
#endif
#endif
#ifdef FLAG_SHADOW_MAP
#if !defined(GL_ARB_gpu_shader5)
out float geoInstance;
#endif
uniform mat4 shadow_proj_matrix[4];
out vec3 geoNormal;
out vec4 geoTexCoord;
#else
@@ -120,18 +44,27 @@ out vec3 fragNormal;
out vec4 fragTexCoord;
#endif
#ifdef FLAG_SHADOWS
uniform mat4 shadow_mv_matrix;
uniform mat4 shadow_proj_matrix[4];
out vec4 fragShadowUV[4];
out vec4 fragShadowPos;
#endif
#ifdef FLAG_THRUSTER
uniform float thruster_scale;
#endif
#ifdef FLAG_CLIP
uniform int use_clip_plane;
uniform vec4 clip_equation;
#endif
#ifdef FLAG_TRANSFORM
#define TEXELS_PER_MATRIX 4
void getModelTransform(inout mat4 transform, out bool invisible, int id, int matrix_offset)
void getModelTransform(inout mat4 transform, out float invisible, int id, int matrix_offset)
{
transform[0] = texelFetch(transform_tex, (matrix_offset + id) * TEXELS_PER_MATRIX);
transform[1] = texelFetch(transform_tex, (matrix_offset + id) * TEXELS_PER_MATRIX + 1);
transform[2] = texelFetch(transform_tex, (matrix_offset + id) * TEXELS_PER_MATRIX + 2);
transform[3] = texelFetch(transform_tex, (matrix_offset + id) * TEXELS_PER_MATRIX + 3);
invisible = transform[3].w >= 0.9;
invisible = transform[3].w;
transform[3].w = 1.0;
}
#endif
@@ -155,10 +88,13 @@ void main()
mat4 orient = mat4(1.0);
mat4 scale = mat4(1.0);
#ifdef FLAG_TRANSFORM
bool clipModel;
getModelTransform(orient, clipModel, int(vertModelID), buffer_matrix_offset);
#else
bool clipModel = false;
float invisible;
getModelTransform(orient, invisible, int(vertModelID), buffer_matrix_offset);
#ifdef FLAG_SHADOW_MAP
geoNotVisible = invisible;
#else
fragNotVisible = invisible;
#endif
#endif
texCoord = textureMatrix * vertTexCoord;
vec4 vertex = vertPosition;
@@ -172,15 +108,11 @@ void main()
position = modelViewMatrix * orient * vertex;
#ifdef FLAG_SHADOW_MAP
gl_Position = position;
#if !defined(GL_ARB_gpu_shader5)
#ifdef APPLE
geoInstance = float(gl_InstanceIDARB);
geoInstance = float(gl_InstanceIDARB);
#else
geoInstance = float(gl_InstanceID);
geoInstance = float(gl_InstanceID);
#endif
#endif
#else
gl_Position = projMatrix * position;
#endif
@@ -209,15 +141,11 @@ void main()
fragFogDist = clamp((gl_Position.z - fogStart) * 0.75 * fogScale, 0.0, 1.0);
#endif
#ifdef FLAG_CLIP
if (clipModel) {
gl_ClipDistance[0] = -1.0;
} else if(use_clip_plane) {
if(use_clip_plane == 1) {
gl_ClipDistance[0] = dot(clip_equation, modelMatrix * orient * vertex);
} else {
gl_ClipDistance[0] = 1.0;
gl_ClipDistance[0] = -1.0f;
}
#elif defined(FLAG_TRANSFORM)
gl_ClipDistance[0] = clipModel ? -1.0 : 1.0;
#endif
#ifndef FLAG_SHADOW_MAP
fragPosition = position;
-108
View File
@@ -1,108 +0,0 @@
// Enabled at all times but the define is kept here in case this should be configurable in the future
#define EDGE_AA
layout(std140) uniform NanoVGUniformData {
mat3 scissorMat;
mat3 paintMat;
vec4 innerCol;
vec4 outerCol;
vec2 scissorExt;
vec2 scissorScale;
vec2 extent;
float radius;
float feather;
float strokeMult;
float strokeThr;
int texType;
int type;
vec2 viewSize;
int texArrayIndex;
};
uniform sampler2DArray nvg_tex;
in vec2 ftcoord;
in vec2 fpos;
out vec4 outColor;
float sdroundrect(vec2 pt, vec2 ext, float rad) {
vec2 ext2 = ext - vec2(rad,rad);
vec2 d = abs(pt) - ext2;
return min(max(d.x,d.y),0.0) + length(max(d,0.0)) - rad;
}
// Scissoring
float scissorMask(vec2 p) {
vec2 sc = (abs((scissorMat * vec3(p,1.0)).xy) - scissorExt);
sc = vec2(0.5,0.5) - sc * scissorScale;
return clamp(sc.x,0.0,1.0) * clamp(sc.y,0.0,1.0);
}
#ifdef EDGE_AA
// Stroke - from [0..1] to clipped pyramid, where the slope is 1px.
float strokeMask() {
return min(1.0, (1.0-abs(ftcoord.x*2.0-1.0))*strokeMult) * min(1.0, ftcoord.y);
}
#endif
// The value the distance field has when the pixel is exactly on the edge. This needs to match the values in fontstash.h!
const float ON_EDGE_DISTANCE = 180.0 / 255.0;
void main(void) {
vec4 result;
float scissor = scissorMask(fpos);
#ifdef EDGE_AA
float strokeAlpha = strokeMask();
#else
float strokeAlpha = 1.0;
#endif
#ifdef EDGE_AA
if (strokeAlpha < strokeThr) {
discard;
}
#endif
if (type == 0) { // Gradient
// Calculate gradient color using box gradient
vec2 pt = (paintMat * vec3(fpos,1.0)).xy;
float d = clamp((sdroundrect(pt, extent, radius) + feather*0.5) / feather, 0.0, 1.0);
vec4 color = mix(innerCol,outerCol,d);
// Combine alpha
color *= strokeAlpha * scissor;
result = color;
} else if (type == 1) { // Image
// Calculate color fron texture
vec2 pt = (paintMat * vec3(fpos,1.0)).xy / extent;
vec4 color = texture(nvg_tex, vec3(pt, float(texArrayIndex)));
// Apply color tint and alpha.
if (texType == 1) color = vec4(color.xyz*color.w,color.w);
if (texType == 2) color = vec4(color.r);
color *= innerCol;
// Combine alpha
color *= strokeAlpha * scissor;
result = color;
} else if (type == 2) { // Stencil fill
result = vec4(1,1,1,1);
} else if (type == 3) { // Textured tris
vec4 color = texture(nvg_tex, vec3(ftcoord, float(texArrayIndex)));
if (texType == 1) color = vec4(color.xyz*color.w,color.w); if (texType == 2) color = vec4(color.x); color *= scissor;
result = color * innerCol;
} else if (type == 4) { // Distance vector text
vec4 color = texture(nvg_tex, vec3(ftcoord, float(texArrayIndex)));
float dist = color.r;
float width = fwidth(dist) / 2.0;
float alpha = smoothstep(ON_EDGE_DISTANCE - width, ON_EDGE_DISTANCE + width, dist);
color = innerCol * alpha;
result = color * scissor;
}
outColor = result;
}
-37
View File
@@ -1,37 +0,0 @@
layout(std140) uniform NanoVGUniformData {
mat3 scissorMat;
mat3 paintMat;
vec4 innerCol;
vec4 outerCol;
vec2 scissorExt;
vec2 scissorScale;
vec2 extent;
float radius;
float feather;
float strokeMult;
float strokeThr;
int texType;
int type;
vec2 viewSize;
int texArrayIndex;
};
in vec2 vertPosition;
in vec2 vertTexCoord;
out vec2 ftcoord;
out vec2 fpos;
void main(void) {
ftcoord = vertTexCoord;
fpos = vertPosition;
gl_Position = vec4(2.0*vertPosition.x/viewSize.x - 1.0, 1.0 - 2.0*vertPosition.y/viewSize.y, 0, 1);
}
+6 -3
View File
@@ -2,14 +2,17 @@ in vec4 fragTexCoord;
in vec4 fragColor;
out vec4 fragOut0;
uniform sampler2D baseMap;
uniform int alphaTexture;
uniform int noTexturing;
uniform int srgb;
uniform float intensity;
uniform float alphaThreshold;
#define SRGB_GAMMA 2.2
void main()
{
vec4 baseColor = texture(baseMap, fragTexCoord.xy);
if(alphaThreshold > baseColor.a) discard;
baseColor.rgb = (srgb == 1) ? pow(baseColor.rgb, vec3(SRGB_GAMMA)) : baseColor.rgb;
vec4 blendColor = (srgb == 1) ? vec4(pow(fragColor.rgb, vec3(SRGB_GAMMA)), fragColor.a) : fragColor;
fragOut0 = mix(baseColor * blendColor, blendColor, float(noTexturing));
}
fragOut0 = mix(mix(baseColor * blendColor, vec4(blendColor.rgb, baseColor.r * blendColor.a), float(alphaTexture)), blendColor, float(noTexturing)) * intensity;
}
+1 -7
View File
@@ -26,9 +26,6 @@ uniform float cutoff;
#ifdef FLAG_DITH
uniform float dither;
#endif
#ifdef FLAG_TINT
uniform vec3 tint;
#endif
uniform sampler2D blurred_tex;
uniform sampler2D depth_tex;
void main()
@@ -101,10 +98,7 @@ void main()
float downsampling_factor = 4;
float bias = 0.5;
color_out.rgb = floor(color_out.rgb * downsampling_factor + bias) / downsampling_factor;
#endif
#ifdef FLAG_TINT
color_out.rgb += tint;
#endif
color_out.a = 1.0;
fragOut0 = color_out;
}
}
+3 -4
View File
@@ -1,8 +1,7 @@
in vec4 fragImpactUV;
in float fragNormOffset;
uniform vec4 color;
uniform sampler2DArray shieldMap;
uniform int shieldMapIndex;
uniform sampler2D shieldMap;
uniform int srgb;
out vec4 fragOut0;
#define SRGB_GAMMA 2.2
@@ -11,9 +10,9 @@ void main()
{
if(fragNormOffset < 0.0) discard;
if(fragImpactUV.x < 0.0 || fragImpactUV.x > 1.0 || fragImpactUV.y < 0.0 || fragImpactUV.y > 1.0) discard;
vec4 shieldColor = texture(shieldMap, vec3(fragImpactUV.xy, float(shieldMapIndex)));
vec4 shieldColor = texture(shieldMap, fragImpactUV.xy);
shieldColor.rgb = (srgb == 1) ? pow(shieldColor.rgb, vec3(SRGB_GAMMA)) * EMISSIVE_GAIN : shieldColor.rgb;
vec4 blendColor = color;
blendColor.rgb = (srgb == 1) ? pow(blendColor.rgb, vec3(SRGB_GAMMA)) * EMISSIVE_GAIN : blendColor.rgb;
fragOut0 = shieldColor * blendColor;
}
}
+5 -8
View File
@@ -1,16 +1,13 @@
in vec4 fragTexCoord;
out vec4 fragOut0;
uniform sampler2DArray ytex;
uniform sampler2DArray utex;
uniform sampler2DArray vtex;
uniform sampler2D ytex;
uniform sampler2D utex;
uniform sampler2D vtex;
void main()
{
float y = texture(ytex, vec3(fragTexCoord.st, 0.0)).r;
float u = texture(utex, vec3(fragTexCoord.st, 0.0)).r;
float v = texture(vtex, vec3(fragTexCoord.st, 0.0)).r;
vec3 val = vec3(y - 0.0625, u - 0.5, v - 0.5);
vec3 val = vec3(texture(ytex, fragTexCoord.st).r - 0.0625, texture(utex, fragTexCoord.st).r - 0.5, texture(vtex, fragTexCoord.st).r - 0.5);
fragOut0.r = dot(val, vec3(1.1640625, 0.0, 1.59765625));
fragOut0.g = dot(val, vec3(1.1640625, -0.390625, -0.8125));
fragOut0.b = dot(val, vec3(1.1640625, 2.015625, 0.0));
fragOut0.a = 1.0;
}
}
+2 -2
View File
@@ -87,7 +87,7 @@ void fireball_play_warphole_open_sound(int ship_class, fireball *fb)
}
}
snd_play_3d(gamesnd_get_game_sound(sound_index), &fireball_objp->pos, &Eye_position, fireball_objp->radius, NULL, 0, 1.0f, SND_PRIORITY_DOUBLE_INSTANCE, NULL, range_multiplier); // play warp sound effect
snd_play_3d(&Snds[sound_index], &fireball_objp->pos, &Eye_position, fireball_objp->radius, NULL, 0, 1.0f, SND_PRIORITY_DOUBLE_INSTANCE, NULL, range_multiplier); // play warp sound effect
}
/**
@@ -111,7 +111,7 @@ void fireball_play_warphole_close_sound(fireball *fb)
return;
}
snd_play_3d(gamesnd_get_game_sound(sound_index), &fireball_objp->pos, &Eye_position, fireball_objp->radius); // play warp sound effect
snd_play_3d(&Snds[sound_index], &fireball_objp->pos, &Eye_position, fireball_objp->radius); // play warp sound effect
}
/**
+1 -87
View File
@@ -27,21 +27,12 @@
#include <unistd.h>
#include <cerrno>
#include <sys/ioctl.h>
#include <signal.h>
#ifdef SCP_SOLARIS
#include <sys/filio.h>
#endif
#include <ctype.h>
#define WSAGetLastError() (errno)
#define RESTART(syscall) \
({ \
__typeof__(syscall) _res; \
do \
_res = syscall; \
while (_res == -1 && errno == EINTR); \
_res; \
})
#else
#include <windows.h>
#include <process.h>
@@ -118,18 +109,6 @@ int FS2NetD_ConnectToServer(const char *host, const char *port)
ulong arg = 1;
ioctlsocket(mySocket, FIONBIO, &arg);
// Where SO_NOSIGPIPE is defined (currently OS X):
// prevent SIGPIPE, which is generated when sending after receiver disconnected
// on other *nix use MSG_NOSIGNAL flag when sending data, or, failing that, use signal masking
// see FS2NetD_SendData()
#if defined(SCP_UNIX) && defined(SO_NOSIGPIPE)
int nosigpipe = 1;
if (setsockopt(mySocket, SOL_SOCKET, SO_NOSIGPIPE, (void*)&nosigpipe, sizeof(nosigpipe)) == -1) {
my_error = errno;
ml_printf("FS2NetD ERROR: Couldn't set SO_NOSIGPIPE on socket (\"%s\")!", strerror(my_error));
}
#endif // SCP_UNIX && SO_NOSIGPIPE
// blasted MS, probably need to use getaddrinfo() here for Win32, but I
// want to keep this as clean and simple as possible and that means
// using an actual standard :)
@@ -258,74 +237,9 @@ int FS2NetD_SendData(char *buffer, int blen)
{
int flags = 0;
// on Unix with MSG_NOSIGNAL, prevent SIGPIPE, which is generated if receiver has disconnected
// the MSG_NOSIGNAL flag doesn't work on OS X or Solaris
// on OS X, use setsockopt() with SO_NOSIGPIPE instead, see above
#if defined(SCP_UNIX) && defined(MSG_NOSIGNAL)
flags |= MSG_NOSIGNAL;
#endif // SCP_UNIX && MSG_NOSIGNAL
socklen_t to_len = sizeof(sockaddr);
// Borrowed from Kroki:
// https://github.com/kroki/XProbes/blob/1447f3d93b6dbf273919af15e59f35cca58fcc23/src/libxprobes.c#L156
#if defined(SCP_UNIX) && !defined(MSG_NOSIGNAL) && !defined(SO_NOSIGPIPE)
/*
We want to ignore possible SIGPIPE that we can generate on write.
SIGPIPE is delivered *synchronously* and *only* to the thread
doing the write. So if it is reported as already pending (which
means the thread blocks it), then we do nothing: if we generate
SIGPIPE, it will be merged with the pending one (there's no
queuing), and that suits us well. If it is not pending, we block
it in this thread (and we avoid changing signal action, because it
is per-process).
*/
sigset_t pending;
sigset_t sigpipe_mask;
bool sigpipe_pending;
bool sigpipe_unblock;
sigemptyset(&pending);
sigpending(&pending);
sigpipe_pending = sigismember(&pending, SIGPIPE);
if (!sigpipe_pending) {
sigset_t blocked;
sigemptyset(&blocked);
pthread_sigmask(SIG_BLOCK, &sigpipe_mask, &blocked);
/* Maybe is was blocked already? */
sigpipe_unblock = ! sigismember(&blocked, SIGPIPE);
}
#endif /* defined(SCP_UNIX) && ! defined(MSG_NOSIGNAL) && ! defined(SO_NOSIGPIPE) */
auto sent_chars = sendto(mySocket, buffer, blen, flags, (sockaddr*)&FS2NetD_addr, to_len);
#if defined(SCP_UNIX) && !defined(MSG_NOSIGNAL) && !defined(SO_NOSIGPIPE)
/*
If SIGPIPE was pending already we do nothing. Otherwise, if it
become pending (i.e., we generated it), then we sigwait() it (thus
clearing pending status). Then we unblock SIGPIPE, but only if it
were us who blocked it.
*/
if (!sigpipe_pending) {
sigemptyset(&pending);
sigpending(&pending);
if (sigismember(&pending, SIGPIPE)) {
/*
Protect ourselves from a situation when SIGPIPE was sent
by the user to the whole process, and was delivered to
other thread before we had a chance to wait for it.
*/
static const struct timespec nowait = { 0, 0 };
RESTART(sigtimedwait(&sigpipe_mask, NULL, &nowait));
}
if (sigpipe_unblock) {
pthread_sigmask(SIG_UNBLOCK, &sigpipe_mask, NULL);
}
}
#endif /* defined(SCP_UNIX) && ! defined(MSG_NOSIGNAL) && ! defined(SO_NOSIGPIPE) */
return sent_chars;
return sendto(mySocket, buffer, blen, flags, (sockaddr*)&FS2NetD_addr, to_len);
}
bool FS2NetD_DataReady()
+4 -5
View File
@@ -1186,9 +1186,7 @@ void parse_soundtrack()
}
//Track doesn't exist and has nocreate, so don't create it
if ( !skip_to_start_of_string_either("#SoundTrack Start", "#Menu Music Start") && !skip_to_string("#SoundTrack End")) {
error_display(1, "Couldn't find #Soundtrack Start, #Menu Music Start or #Soundtrack End.");
}
Assertion(skip_to_start_of_string_either("#SoundTrack Start", "#Menu Music Start") || skip_to_string("#SoundTrack End"), "Couldn't find #Soundtrack Start, #Menu Music Start or #Soundtrack End. Music.tbl or -mus.tbm is invalid.\n");
return;
}
@@ -1283,7 +1281,7 @@ void parse_soundtrack()
}
//We're done here.
required_string("#SoundTrack End");
//required_string("#SoundTrack End");
// Goober5000 - set the valid flag according to whether we can load all our patterns
@@ -1372,11 +1370,12 @@ void event_music_parse_musictbl(const char *filename)
read_file_text(filename, CF_TYPE_TABLES);
reset_parse();
while ( check_for_string("#Soundtrack Start") || check_for_string("#Menu Music Start") )
while ( skip_to_start_of_string_either("#Soundtrack Start", "#Menu Music Start", NULL ) )
{
if ( optional_string("#Soundtrack Start") )
{
parse_soundtrack( );
required_string("#Soundtrack End");
}
if ( optional_string("#Menu Music Start") )
{
+34 -227
View File
@@ -263,7 +263,7 @@ void gamesnd_play_iface(int n)
if (Snds_iface_handle[n] >= 0)
snd_stop(Snds_iface_handle[n]);
Snds_iface_handle[n] = snd_play(gamesnd_get_interface_sound(n));
Snds_iface_handle[n] = snd_play(&Snds_iface[n]);
}
/**
@@ -310,22 +310,16 @@ int gamesnd_get_by_name(const char* name)
int i = 0;
for(SCP_vector<game_snd>::iterator snd = Snds.begin(); snd != Snds.end(); ++snd)
{
if (snd->sound_entries.size() != 1) {
// Ignore game sounds with more than one sound entry
continue;
}
auto& entry = snd->sound_entries.front();
char *p = strrchr( entry.filename, '.' );
char *p = strrchr( snd->filename, '.' );
if(p == NULL)
{
if(!stricmp(entry.filename, name))
if(!stricmp(snd->filename, name))
{
index = i;
break;
}
}
else if(!strnicmp(entry.filename, name, p - entry.filename))
else if(!strnicmp(snd->filename, name, p-snd->filename))
{
index = i;
break;
@@ -350,22 +344,16 @@ int gamesnd_get_by_iface_name(const char* name)
int i = 0;
for(SCP_vector<game_snd>::iterator snd = Snds_iface.begin(); snd != Snds_iface.end(); ++snd)
{
if (snd->sound_entries.size() != 1) {
// Ignore game sounds with more than one sound entry
continue;
}
auto& entry = snd->sound_entries.front();
char *p = strrchr( entry.filename, '.' );
char *p = strrchr( snd->filename, '.' );
if(p == NULL)
{
if(!stricmp(entry.filename, name))
if(!stricmp(snd->filename, name))
{
index = i;
break;
}
}
else if(!strnicmp(entry.filename, name, p - entry.filename))
else if(!strnicmp(snd->filename, name, p-snd->filename))
{
index = i;
break;
@@ -527,12 +515,10 @@ void gamesnd_preload_common_sounds()
Assert( Snds.size() <= INT_MAX );
for (SCP_vector<game_snd>::iterator gs = Snds.begin(); gs != Snds.end(); ++gs) {
if ( gs->preload ) {
for (auto& entry : gs->sound_entries) {
if ( entry.filename[0] != 0 && strnicmp(entry.filename, NOX("none.wav"), 4) ) {
game_busy( NOX("** preloading common game sounds **") ); // Animate loading cursor... does nothing if loading screen not active.
entry.id = snd_load(&entry, gs->flags);
}
if ( gs->filename[0] != 0 && strnicmp(gs->filename, NOX("none.wav"), 4) ) {
if ( gs->preload ) {
game_busy( NOX("** preloading common game sounds **") ); // Animate loading cursor... does nothing if loading screen not active.
gs->id = snd_load(&(*gs));
}
}
}
@@ -548,12 +534,10 @@ void gamesnd_load_gameplay_sounds()
Assert( Snds.size() <= INT_MAX );
for (SCP_vector<game_snd>::iterator gs = Snds.begin(); gs != Snds.end(); ++gs) {
if ( !gs->preload ) { // don't try to load anything that's already preloaded
for (auto& entry : gs->sound_entries) {
if (entry.filename[0] != 0 && strnicmp(entry.filename, NOX("none.wav"), 4)) {
game_busy(NOX("** preloading gameplay sounds **")); // Animate loading cursor... does nothing if loading screen not active.
entry.id = snd_load(&entry, gs->flags);
}
if ( gs->filename[0] != 0 && strnicmp(gs->filename, NOX("none.wav"), 4) ) {
if ( !gs->preload ) { // don't try to load anything that's already preloaded
game_busy( NOX("** preloading gameplay sounds **") ); // Animate loading cursor... does nothing if loading screen not active.
gs->id = snd_load(&(*gs));
}
}
}
@@ -566,11 +550,9 @@ void gamesnd_unload_gameplay_sounds()
{
Assert( Snds.size() <= INT_MAX );
for (SCP_vector<game_snd>::iterator gs = Snds.begin(); gs != Snds.end(); ++gs) {
for (auto& entry : gs->sound_entries) {
if (entry.id != -1) {
snd_unload(entry.id);
entry.id = -1;
}
if ( gs->id != -1 ) {
snd_unload( gs->id );
gs->id = -1;
}
}
}
@@ -585,10 +567,8 @@ void gamesnd_load_interface_sounds()
Assert( Snds_iface.size() < INT_MAX );
for (SCP_vector<game_snd>::iterator si = Snds_iface.begin(); si != Snds_iface.end(); ++si) {
for (auto& entry : si->sound_entries) {
if ( entry.filename[0] != 0 && strnicmp(entry.filename, NOX("none.wav"), 4) ) {
entry.id = snd_load(&entry, si->flags);
}
if ( si->filename[0] != 0 && strnicmp(si->filename, NOX("none.wav"), 4) ) {
si->id = snd_load(&(*si));
}
}
}
@@ -600,12 +580,10 @@ void gamesnd_unload_interface_sounds()
{
Assert( Snds_iface.size() < INT_MAX );
for (SCP_vector<game_snd>::iterator si = Snds_iface.begin(); si != Snds_iface.end(); ++si) {
for (auto& entry : si->sound_entries) {
if ( entry.id != -1 ) {
snd_unload( entry.id );
entry.id = -1;
entry.id_sig = -1;
}
if ( si->id != -1 ) {
snd_unload( si->id );
si->id = -1;
si->id_sig = -1;
}
}
}
@@ -615,15 +593,11 @@ void parse_gamesnd_old(game_snd* gs)
int is_3d;
int temp;
// An old sound is just a single entry sound set
gs->sound_entries.resize(1);
auto& entry = gs->sound_entries.back();
stuff_string(gs->filename, F_NAME, MAX_FILENAME_LEN, ",");
stuff_string(entry.filename, F_NAME, MAX_FILENAME_LEN, ",");
if (!stricmp(entry.filename, NOX("empty")))
if (!stricmp(gs->filename, NOX("empty")))
{
entry.filename[0] = 0;
gs->filename[0] = 0;
advance_to_eoln(NULL);
return;
}
@@ -636,9 +610,7 @@ void parse_gamesnd_old(game_snd* gs)
gs->preload = true;
}
float default_volume;
stuff_float(&default_volume);
gs->volume_range = util::UniformFloatRange(default_volume);
stuff_float(&gs->default_volume);
stuff_int(&is_3d);
@@ -654,7 +626,7 @@ void parse_gamesnd_old(game_snd* gs)
gs->max = 0;
// silly retail, not abiding by its own format...
if (!stricmp(entry.filename, "l_hit.wav") || !stricmp(entry.filename, "m_hit.wav"))
if (!stricmp(gs->filename, "l_hit.wav") || !stricmp(gs->filename, "m_hit.wav"))
{
int temp_min, temp_max;
@@ -664,7 +636,7 @@ void parse_gamesnd_old(game_snd* gs)
ignore_gray_space();
if (stuff_int_optional(&temp_max, true) == 2)
{
mprintf(("Dutifully converting retail sound %s, '%s' to a 3D sound...\n", gs->name.c_str(), entry.filename));
mprintf(("Dutifully converting retail sound %s, '%s' to a 3D sound...\n", gs->name.c_str(), gs->filename));
is_3d = 1;
gs->flags |= GAME_SND_USE_DS3D;
@@ -675,14 +647,11 @@ void parse_gamesnd_old(game_snd* gs)
}
}
// Default pitch is 1.0
gs->pitch_range = util::UniformFloatRange(1.0f);
// check for extra values per Mantis #2408
ignore_gray_space();
if (stuff_int_optional(&temp, true) == 2)
{
Warning(LOCATION, "Unexpected extra value %d found for sound '%s' (filename '%s')! Check the format of the sounds.tbl (or .tbm) entry.", temp, gs->name.c_str(), entry.filename);
Warning(LOCATION, "Unexpected extra value %d found for sound '%s' (filename '%s')! Check the format of the sounds.tbl (or .tbm) entry.", temp, gs->name.c_str(), gs->filename);
}
advance_to_eoln(NULL);
@@ -734,124 +703,22 @@ bool required_string_no_create(const char* token, bool no_create)
return true;
}
static GameSoundCycleType parse_cycle_type() {
if (optional_string("Sequential")) {
return GameSoundCycleType::Sequential;
} else if (optional_string("Random")) {
return GameSoundCycleType::Random;
} else {
error_display(0, "Failed to parse sound cycle type. Expected 'sequential' or 'random'. Got [%.32s]", next_tokens());
// Ignore everything until the end of the line. That should hopefully skip the bad token.
advance_to_eoln(nullptr);
return GameSoundCycleType::Sequential;
}
}
void parse_gamesnd_soundset(game_snd* gs, bool no_create) {
// If this gets called then we just saw "+Entry:" so we can begin processing the first entry immediately
do {
// For now there is no way to change an existing entry so ever +Entry statement creates a new sound entry
gs->sound_entries.resize(gs->sound_entries.size() + 1);
auto& entry = gs->sound_entries.back();
stuff_string(entry.filename, F_NAME, MAX_FILENAME_LEN);
} while (optional_string("+Entry:"));
if (required_string_no_create("+Cycle type:", no_create)) {
gs->cycle_type = parse_cycle_type();
}
if (required_string_no_create("+Preload:", no_create))
{
stuff_boolean(&gs->preload);
}
if (required_string_no_create("+Volume:", no_create))
{
gs->volume_range = util::parseUniformRange(0.0f, 1.0f);
}
if (optional_string("+3D Sound:"))
{
gs->flags |= GAME_SND_USE_DS3D;
required_string("+Attenuation start:");
stuff_int(&gs->min);
required_string("+Attenuation end:");
stuff_int(&gs->max);
}
else
{
gs->min = 0;
gs->max = 0;
}
// jg18 - enhanced sound parameters
if (optional_string("+Priority:"))
{
SCP_string priority_string;
stuff_string(priority_string, F_NAME);
EnhancedSoundPriority priority = convert_to_enhanced_priority(priority_string.c_str());
if (priority != SND_ENHANCED_PRIORITY_INVALID)
{
gs->enhanced_sound_data.priority= priority;
}
// else case not needed since conversion function displays message on error
}
if (optional_string("+Limit:"))
{
int temp_limit;
stuff_int(&temp_limit);
if ((temp_limit > 0) && (static_cast<uint>(temp_limit) <= SND_ENHANCED_MAX_LIMIT))
{
gs->enhanced_sound_data.limit = (unsigned int)temp_limit;
}
else
{
error_display(1, "Invalid enhanced sound limit: %d\n", temp_limit);
}
}
if (optional_string("+Pitch:")) {
gs->pitch_range = util::parseUniformRange(0.0001f);
} else if (!no_create) {
// Default pitch is 1.0
gs->pitch_range = util::UniformFloatRange(1.0f);
}
}
void parse_gamesnd_new(game_snd* gs, bool no_create)
{
game_snd_entry* entry = nullptr;
if (!no_create) {
gs->sound_entries.resize(1);
entry = &gs->sound_entries.back();
} else {
if (gs->sound_entries.size() != 1) {
error_display(1, "The SCP syntax cannot be used to modify an existing sound that has more than one entry! Use the soundset syntax for adding new entries.");
}
entry = &gs->sound_entries.back();
}
char name[MAX_FILENAME_LEN];
// New extended format found
stuff_string(name, F_NAME, MAX_FILENAME_LEN);
if (!stricmp(name, NOX("empty")))
{
entry->filename[0] = 0;
gs->filename[0] = 0;
return;
}
// If the name _doesn't_ match <same> put it into gs->filename;
if (stricmp(name, "<same>"))
{
strcpy_s(entry->filename, name);
strcpy_s(gs->filename, name);
}
else if (!no_create)
{
@@ -867,9 +734,7 @@ void parse_gamesnd_new(game_snd* gs, bool no_create)
if (required_string_no_create("+Volume:", no_create))
{
float default_volume;
stuff_float(&default_volume);
gs->volume_range = util::UniformFloatRange(default_volume);
stuff_float(&gs->default_volume);
}
if (optional_string("+3D Sound:"))
@@ -916,9 +781,6 @@ void parse_gamesnd_new(game_snd* gs, bool no_create)
error_display(1, "Invalid enhanced sound limit: %d\n", temp_limit);
}
}
// Default pitch is 1.0
gs->pitch_range = util::UniformFloatRange(1.0f);
}
void gamesnd_parse_entry(game_snd *gs, bool no_create, SCP_vector<game_snd> *lookupVector)
@@ -958,8 +820,6 @@ void gamesnd_parse_entry(game_snd *gs, bool no_create, SCP_vector<game_snd> *loo
if (optional_string("+Filename:"))
{
parse_gamesnd_new(gs, no_create);
} else if (optional_string("+Entry:")) {
parse_gamesnd_soundset(gs, no_create);
}
else
{
@@ -1301,56 +1161,3 @@ void gamesnd_play_error_beep()
{
gamesnd_play_iface(SND_GENERAL_FAIL);
}
game_snd* gamesnd_get_game_sound(int handle) {
Assertion(handle >= 0 && handle < (int) Snds.size(), "Invalid game sound handle %d detected!", handle);
return &Snds[handle];
}
game_snd* gamesnd_get_interface_sound(int handle) {
Assertion(handle >= 0 && handle < (int) Snds_iface.size(), "Invalid interface sound handle %d detected!", handle);
return &Snds_iface[handle];
}
bool gamesnd_game_sound_valid(int sound) {
return sound >= 0 && sound < (int) Snds.size();
}
bool gamesnd_interface_sound_valid(int sound) {
return sound >= 0 && sound < (int) Snds_iface.size();
}
float gamesnd_get_max_duration(game_snd* gs) {
int max_length = 0;
for (auto& entry : gs->sound_entries) {
Assertion(entry.id != -1, "Game sound must be loaded to determine maximum duration!");
max_length = std::max(max_length, snd_get_duration(entry.id));
}
return max_length / gs->pitch_range.max();
}
game_snd_entry* gamesnd_choose_entry(game_snd* gs) {
Assertion(!gs->sound_entries.empty(), "No sound entries found in game sound! This may not happen!");
size_t index = 0;
switch(gs->cycle_type) {
case GameSoundCycleType::Random:
if (gs->sound_entries.size() == 1) {
index = 0;
} else {
index = util::UniformRange<size_t>(0, gs->sound_entries.size() - 1).next();
}
break;
case GameSoundCycleType::Sequential:
if (gs->last_entry_index == std::numeric_limits<size_t>::max()) {
// If this is the first time we must return the first sound to keep everything consistent
index = 0;
} else {
index = (gs->last_entry_index + 1) % gs->sound_entries.size();
}
break;
}
gs->last_entry_index = index;
return &gs->sound_entries[index];
}
+3 -49
View File
@@ -49,6 +49,9 @@ void parse_sound_list(const char* tag, SCP_vector<int>& destination, const char*
// this is a callback, so it needs to be a real function
void common_play_highlight_sound();
extern SCP_vector<game_snd> Snds;
extern SCP_vector<game_snd> Snds_iface;
/**
* symbolic names for misc. game sounds.
*
@@ -353,53 +356,4 @@ enum InterfaceSoundsIndex {
MIN_INTERFACE_SOUNDS =70 //!< MIN_INTERFACE_SOUNDS
};
/**
* @brief Gets a pointer to the game sound with the specified handle
* @param handle The sound handle
* @return The game sound handle
*/
game_snd* gamesnd_get_game_sound(int handle);
/**
* @brief Gets a pointer to the interface sound with the specified handle
* @param handle The sound handle
* @return The interface sound handle
*/
game_snd* gamesnd_get_interface_sound(int handle);
/**
* @brief Checks if the given sound handle is a valid game sound handle
* @param sound The handle to check
* @return @c true if the handle is valid
*/
bool gamesnd_game_sound_valid(int sound);
/**
* @brief Checks if the given sound handle is a valid interface sound handle
* @param sound The handle to check
* @return @c true if the handle is valid
*/
bool gamesnd_interface_sound_valid(int sound);
/**
* @brief Determines the maximum time this game sound may take to be played.
*
* @details Use this instead of snd_get_duration since a game sound may have multiple sounds with different durations.
* This function also accounts for pitch changes which also changes the length of a sound.
*
* @param gs The game sound to check
* @return The length of the sound in milliseconds
*/
float gamesnd_get_max_duration(game_snd* gs);
/**
* @brief Chooses a sound entry for the specified game sound according to the rules specified by the game data
*
* @warning The returned pointer is temporary and may not be valid forever. Do no store this pointer anywhere!
*
* @param gs The game sound to choose the entry from
* @return The chosen entry
*/
game_snd_entry* gamesnd_choose_entry(game_snd* gs);
#endif
+11 -30
View File
@@ -75,22 +75,11 @@ typedef struct vec4 {
};
} vec4;
struct bvec4 {
bool x;
bool y;
bool z;
bool w;
};
// sometimes, you just need some integers
typedef struct ivec3 {
int x, y, z;
} ivec3;
struct ivec2 {
int x, y;
};
/** Represents a point in 3d space.
Note: this is a struct, not a class, so no member functions. */
@@ -437,8 +426,10 @@ public:
SCP_string dump_stacktrace();
// DEBUG compile time catch for dangerous uses of memset/memcpy/memmove
// would prefer std::is_trivially_copyable but it's not supported by gcc yet
// ref: http://gcc.gnu.org/onlinedocs/libstdc++/manual/status.html
#ifndef NDEBUG
#if SCP_COMPILER_CXX_AUTO_TYPE && SCP_COMPILER_CXX_STATIC_ASSERT && defined(HAVE_STD_IS_TRIVIALLY_COPYABLE)
#if SCP_COMPILER_CXX_STATIC_ASSERT && SCP_COMPILER_CXX_AUTO_TYPE
// feature support seems to be: gcc clang msvc
// auto 4.4 2.9 2010
// std::is_trivial 4.5 ? 2012 (2010 only duplicates std::is_pod)
@@ -453,20 +444,10 @@ SCP_string dump_stacktrace();
// Put into std to be compatible with code that uses std::mem*
namespace std
{
// This is a separate check which also checks if arrays are trivially copyable since Visual Studio 2013 thinks they are not
#if SCP_COMPILER_IS_MSVC && _MSC_VER <= 1800
template<typename T>
using trivial_check = std::is_trivial<T>;
#else
template<typename T>
using trivial_check = std::is_trivially_copyable<T>;
#endif
template<typename T>
void *memset_if_trivial_else_error(T *memset_data, int ch, size_t count)
{
static_assert(trivial_check<T>::value, "memset on non-trivial object");
static_assert(std::is_trivial<T>::value, "memset on non-trivial object");
return ptr_memset(memset_data, ch, count);
}
@@ -484,8 +465,8 @@ using trivial_check = std::is_trivially_copyable<T>;
template<typename T, typename U>
void *memcpy_if_trivial_else_error(T *memcpy_dest, U *src, size_t count)
{
static_assert(trivial_check<T>::value, "memcpy on non-trivial object T");
static_assert(trivial_check<U>::value, "memcpy on non-trivial object U");
static_assert(std::is_trivial<T>::value, "memcpy on non-trivial object T");
static_assert(std::is_trivial<U>::value, "memcpy on non-trivial object U");
return ptr_memcpy(memcpy_dest, src, count);
}
@@ -500,20 +481,20 @@ using trivial_check = std::is_trivially_copyable<T>;
template<typename U>
void *memcpy_if_trivial_else_error(void *memcpy_dest, U *memcpy_src, size_t count)
{
static_assert(trivial_check<U>::value, "memcpy on non-trivial object U");
static_assert(std::is_trivial<U>::value, "memcpy on non-trivial object U");
return ptr_memcpy(memcpy_dest, memcpy_src, count);
}
template<typename T>
void *memcpy_if_trivial_else_error(T *memcpy_dest, void *memcpy_src, size_t count)
{
static_assert(trivial_check<T>::value, "memcpy on non-trivial object T");
static_assert(std::is_trivial<T>::value, "memcpy on non-trivial object T");
return ptr_memcpy(memcpy_dest, memcpy_src, count);
}
template<typename T>
void *memcpy_if_trivial_else_error(T *memcpy_dest, const void *memcpy_src, size_t count)
{
static_assert(trivial_check<T>::value, "memcpy on non-trivial object T");
static_assert(std::is_trivial<T>::value, "memcpy on non-trivial object T");
return ptr_memcpy(memcpy_dest, memcpy_src, count);
}
@@ -529,8 +510,8 @@ using trivial_check = std::is_trivially_copyable<T>;
template<typename T, typename U>
void *memmove_if_trivial_else_error(T *memmove_dest, U *memmove_src, size_t count)
{
static_assert(trivial_check<T>::value, "memmove on non-trivial object T");
static_assert(trivial_check<U>::value, "memmove on non-trivial object U");
static_assert(std::is_trivial<T>::value, "memmove on non-trivial object T");
static_assert(std::is_trivial<U>::value, "memmove on non-trivial object U");
return ptr_memmove(memmove_dest, memmove_src, count);
}
}
-8
View File
@@ -67,11 +67,3 @@
#define unlikely(x) __builtin_expect((long) !!(x), 0L)
#define USED_VARIABLE __attribute__((used))
#if __has_cpp_attribute(fallthough)
#define FALLTHROUGH [[fallthrough]]
#elif __has_cpp_attribute(clang::fallthough)
#define FALLTHROUGH [[clang::fallthrough]]
#else
#define FALLTHROUGH
#endif
-7
View File
@@ -51,10 +51,3 @@
* This can be used to ensure that a static variable is present even if it isn't referenced in the translation unit
*/
#define USED_VARIABLE
/**
* @brief For use in a case statement which falls through
*
* Some compilers issue a warning if a fallthrough is detected. This define can be used to suppress that warning.
*/
#define FALLTHROUGH
+1 -7
View File
@@ -65,10 +65,4 @@
#define likely(x) __builtin_expect((long) !!(x), 1L)
#define unlikely(x) __builtin_expect((long) !!(x), 0L)
#define USED_VARIABLE __attribute__((used))
#if SCP_COMPILER_VERSION_MAJOR >= 7
#define FALLTHROUGH [[fallthrough]]
#else
#define FALLTHROUGH
#endif
#define USED_VARIABLE __attribute__((used))
+1 -7
View File
@@ -62,10 +62,4 @@
#define __STDC_FORMAT_MACROS 1
#define USED_VARIABLE __attribute__((used))
#if SCP_COMPILER_VERSION_MAJOR >= 7
#define FALLTHROUGH [[fallthough]]
#else
#define FALLTHROUGH
#endif
#define USED_VARIABLE __attribute__((used))
-2
View File
@@ -85,5 +85,3 @@
#define unlikely(x)
#define USED_VARIABLE
#define FALLTHROUGH
+73 -118
View File
@@ -5,130 +5,85 @@
* or otherwise commercially exploit the source or things you created based on the
* source.
*
*/
*/
#include "globalincs/pstypes.h"
#include "globalincs/version.h"
#include "parse/parselo.h"
namespace gameversion {
bool check_at_least(const version& v) {
return get_executable_version() >= v;
}
SCP_string format_version(const version& v) {
SCP_stringstream ss;
ss << v.major << "." << v.minor << "." << v.build;
if (v.revision != 0) {
ss << "." << v.revision;
}
return ss.str();
}
version parse_version() {
version v;
required_string("+Major:");
stuff_int(&v.major);
required_string("+Minor:");
stuff_int(&v.minor);
required_string("+Build:");
stuff_int(&v.build);
if (optional_string("+Revision:")) {
stuff_int(&v.revision);
}
return v;
}
version get_executable_version() {
version v;
v.major = FS_VERSION_MAJOR;
v.minor = FS_VERSION_MINOR;
v.build = FS_VERSION_BUILD;
v.revision = FS_VERSION_REVIS;
return v;
}
version::version(int major_in, int minor_in, int build_in, int revision_in) :
major(major_in), minor(minor_in), build(build_in), revision(revision_in) {
}
bool version::operator<(const version& v) const {
if (major < v.major) {
return true;
}
if (major > v.major) {
// Major is greater than the given version => the rest doesn't matter
return false;
}
// major is now equal to our major version
if (minor < v.minor) {
return true;
}
if (minor > v.minor) {
// Minor is greater than the given version => the rest doesn't matter
return false;
}
// minor is now equal to our minor version
if (build < v.build) {
return true;
}
if (build > v.build) {
// build is greater than the given version => the rest doesn't matter
return false;
}
// build is now equal to our build version
if (revision == 0 || v.revision == 0) {
// Special case, if there is no revision info, then the versions are equal which means they are not less than each other
return false;
}
if (revision < v.revision) {
return true;
}
if (revision > v.revision) {
// build is greater than the given version => the rest doesn't matter
return false;
}
// revision is now equal to our revision version
return false;
}
bool version::operator==(const version& other) const {
if (major == other.major && minor == other.minor && build == other.build) {
if (revision == 0 || other.revision == 0) {
// Zero revisions always means that these are equal
namespace gameversion
{
bool check_at_least(int major, int minor, int build, int revision)
{
if (FS_VERSION_MAJOR < major)
{
return false;
}
if (FS_VERSION_MAJOR > major)
{
// Major is greater than the given version => the rest doesn't matter
return true;
}
return revision == other.revision;
// major is now equal to our major version
if (FS_VERSION_MINOR < minor)
{
return false;
}
if (FS_VERSION_MINOR > minor)
{
// Minor is greater than the given version => the rest doesn't matter
return true;
}
// minor is now equal to our minor version
if (FS_VERSION_BUILD < build)
{
return false;
}
if (FS_VERSION_BUILD > build)
{
// build is greater than the given version => the rest doesn't matter
return true;
}
// build is now equal to our build version
if (revision == 0)
{
// Special case, if there is no revision info, skip it
return true;
}
if (FS_VERSION_REVIS == 0)
{
// Special case, when there is no revision ignore it
return true;
}
if (FS_VERSION_REVIS < revision)
{
return false;
}
if (FS_VERSION_REVIS > revision)
{
// build is greater than the given version => the rest doesn't matter
return true;
}
// revision is now equal to our revision version
return true;
}
SCP_string format_version(int major, int minor, int build, int revision)
{
SCP_stringstream ss;
ss << major << "." << minor << "." << build;
if (revision != 0)
{
ss << "." << revision;
}
return ss.str();
}
return false;
}
bool version::operator>(const version& other) const {
return other < *this;
}
bool version::operator<=(const version& other) const {
return !(other < *this);
}
bool version::operator>=(const version& other) const {
return !(*this < other);
}
bool version::operator!=(const version& other) const {
return !(*this == other);
}
}
+24 -50
View File
@@ -5,7 +5,7 @@
* or otherwise commercially exploit the source or things you created based on the
* source.
*
*/
*/
@@ -36,55 +36,29 @@
#include "project.h"
// The GCC POSIX headers seem to think defining a common word like "major" is a good idea...
// FYI, no it isn't.
#ifdef major
#undef major
#endif
#ifdef minor
#undef minor
#endif
namespace gameversion {
struct version {
int major = 0;
int minor = 0;
int build = 0;
int revision = 0;
version() {}
version(int major, int minor, int build, int revision);
bool operator<(const version& other) const;
bool operator==(const version& other) const;
bool operator!=(const version& other) const;
bool operator>(const version& rhs) const;
bool operator<=(const version& rhs) const;
bool operator>=(const version& rhs) const;
};
version parse_version();
version get_executable_version();
/**
* @brief Checks if the current version is at least the given version
*
* @param v The version to check
*
* @returns @c true when we are at least the given version, @c false otherwise
*/
bool check_at_least(const version& v);
/**
* @brief Returns the string representation of the passed version
* @param major The version to format
* @returns A string representation of the version number
*/
SCP_string format_version(const version& v);
namespace gameversion
{
/**
* @brief Checks if the current version is at least the given version
*
* @param major The major version to check
* @param minor The minor version to check
* @param build The build version to check
* @param revision The revision version to check
*
* @returns @c true when we are at least the given version, @c false otherwise
*/
bool check_at_least(int major, int minor, int build, int revision);
/**
* @brief Returns the string representation of the passed version
* @param major The major version to format
* @param minor The minor version to format
* @param build The build version to format
* @param revision The revision version to format
* @returns A string representation of the version number
*/
SCP_string format_version(int major, int minor, int build, int revision);
}
#endif
+34 -185
View File
@@ -22,8 +22,6 @@
#include "gamesequence/gamesequence.h" //WMC - for scripting hooks in gr_flip()
#include "globalincs/systemvars.h"
#include "graphics/2d.h"
#include "graphics/matrix.h"
#include "graphics/light.h"
#include "graphics/font.h"
#include "graphics/grbatch.h"
#include "graphics/grinternal.h"
@@ -31,8 +29,6 @@
#include "graphics/opengl/gropengldraw.h"
#include "graphics/grstub.h"
#include "graphics/paths/PathRenderer.h"
#include "graphics/util/UniformBuffer.h"
#include "graphics/util/UniformBufferManager.h"
#include "io/keycontrol.h" // m!m
#include "io/timer.h"
#include "osapi/osapi.h"
@@ -40,7 +36,6 @@
#include "parse/parselo.h"
#include "render/3d.h"
#include "tracing/tracing.h"
#include "utils/boost/hash_combine.h"
#if ( SDL_VERSION_ATLEAST(1, 2, 7) )
#include "SDL_cpuinfo.h"
@@ -101,11 +96,6 @@ float Gr_save_menu_zoomed_offset_X = 0.0f, Gr_save_menu_zoomed_offset_Y = 0.0f;
bool Save_custom_screen_size;
// Forward definitions
static void uniform_buffer_managers_init();
static void uniform_buffer_managers_deinit();
static void uniform_buffer_managers_retire_buffers();
void gr_set_screen_scale(int w, int h, int zoom_w, int zoom_h, int max_w, int max_h, int center_w, int center_h, bool force_stretch)
{
bool do_zoom = zoom_w > 0 && zoom_h > 0 && (zoom_w != w || zoom_h != h);
@@ -644,16 +634,9 @@ void gr_close()
if ( !Gr_inited ) {
return;
}
// Cleanup uniform buffer managers
uniform_buffer_managers_deinit();
font::close();
gr_light_shutdown();
graphics::paths::PathRenderer::shutdown();
switch (gr_screen.mode) {
case GR_OPENGL:
gr_opengl_cleanup(true);
@@ -666,8 +649,6 @@ void gr_close()
Int3(); // Invalid graphics mode
}
bm_close();
Gr_inited = 0;
}
@@ -761,7 +742,10 @@ void gr_screen_resize(int width, int height)
gr_screen.save_max_w_unscaled_zoomed = gr_screen.max_w_unscaled_zoomed;
gr_screen.save_max_h_unscaled_zoomed = gr_screen.max_h_unscaled_zoomed;
gr_setup_viewport();
if (gr_screen.mode == GR_OPENGL) {
extern void opengl_setup_viewport();
opengl_setup_viewport();
}
}
int gr_get_resolution_class(int width, int height)
@@ -844,7 +828,6 @@ static bool gr_init_sub(std::unique_ptr<os::GraphicsOperations>&& graphicsOps, i
gr_screen.bytes_per_pixel= depth / 8;
gr_screen.rendering_to_texture = -1;
gr_screen.envmap_render_target = -1;
gr_screen.line_width = 1.0f;
gr_screen.mode = mode;
gr_screen.res = res;
gr_screen.aspect = 1.0f; // Normal PC screen
@@ -1067,19 +1050,14 @@ bool gr_init(std::unique_ptr<os::GraphicsOperations>&& graphicsOps, int d_mode,
return false;
}
gr_light_init();
mprintf(("Initializing path renderer...\n"));
graphics::paths::PathRenderer::init();
gr_set_palette_internal(Gr_current_palette_name, NULL, 0);
bm_init();
io::mouse::CursorManager::init();
mprintf(("Initializing path renderer...\n"));
graphics::paths::PathRenderer::init();
// Initialize uniform buffer managers
uniform_buffer_managers_init();
bool missing_installation = false;
if (!running_unittests && Web_cursor == nullptr) {
if (Is_standalone) {
@@ -2096,6 +2074,34 @@ void gr_shield_icon(coord2d coords[6], int resize_mode)
g3_render_shield_icon(&gr_screen.current_color, coords, resize_mode);
}
void gr_rect(int x, int y, int w, int h, int resize_mode)
{
if (gr_screen.mode == GR_STUB) {
return;
}
g3_render_colored_rect(&gr_screen.current_color, x, y, w, h, resize_mode);
}
void gr_shade(int x, int y, int w, int h, int resize_mode)
{
int r, g, b, a;
if (gr_screen.mode == GR_STUB) {
return;
}
r = (int)gr_screen.current_shader.r;
g = (int)gr_screen.current_shader.g;
b = (int)gr_screen.current_shader.b;
a = (int)gr_screen.current_shader.c;
color clr;
gr_init_alphacolor(&clr, r, g, b, a);
g3_render_colored_rect(&clr, x, y, w, h, resize_mode);
}
void gr_set_bitmap(int bitmap_num, int alphablend_mode, int bitblt_mode, float alpha)
{
gr_screen.current_alpha = alpha;
@@ -2117,11 +2123,6 @@ void gr_flip(bool execute_scripting)
Script_system.EndFrame();
}
gr_reset_immediate_buffer();
// Use this opportunity for retiring the uniform buffers
uniform_buffer_managers_retire_buffers();
gr_screen.gf_flip();
}
@@ -2241,155 +2242,3 @@ void gr_print_timestamp(int x, int y, fix timestamp, int resize_mode)
gr_string(x, y, time, resize_mode);
}
static std::unique_ptr<graphics::util::UniformBufferManager>
uniform_buffer_managers[static_cast<size_t>(uniform_block_type::NUM_BLOCK_TYPES)];
static void uniform_buffer_managers_init() {
for (size_t i = 0; i < static_cast<size_t>(uniform_block_type::NUM_BLOCK_TYPES); ++i) {
auto enumVal = static_cast<uniform_block_type>(i);
uniform_buffer_managers[i].reset(new graphics::util::UniformBufferManager(enumVal));
}
}
static void uniform_buffer_managers_deinit() {
for (auto& manager: uniform_buffer_managers) {
manager.reset();
}
}
static void uniform_buffer_managers_retire_buffers() {
GR_DEBUG_SCOPE("Retiring unused uniform buffers");
for (auto& manager: uniform_buffer_managers) {
manager->retireBuffers();
}
}
graphics::util::UniformBuffer* gr_get_uniform_buffer(uniform_block_type type) {
return uniform_buffer_managers[static_cast<size_t>(type)]->getBuffer();
}
SCP_vector<DisplayData> gr_enumerate_displays()
{
// It seems that linux cannot handle having the video subsystem inited
// too late
if (SDL_InitSubSystem(SDL_INIT_VIDEO) < 0) {
return SCP_vector<DisplayData>();
}
SCP_vector<DisplayData> data;
auto num_displays = SDL_GetNumVideoDisplays();
for (auto i = 0; i < num_displays; ++i) {
DisplayData display;
display.index = i;
SDL_Rect bounds;
if (SDL_GetDisplayBounds(i, &bounds) == 0) {
display.x = bounds.x;
display.y = bounds.y;
display.width = bounds.w;
display.height = bounds.h;
}
auto name = SDL_GetDisplayName(i);
if (name != nullptr) {
display.name = name;
}
auto num_mods = SDL_GetNumDisplayModes(i);
for (auto j = 0; j < num_mods; ++j) {
SDL_DisplayMode mode;
if (SDL_GetDisplayMode(i, j, &mode) != 0) {
continue;
}
VideoModeData videoMode;
videoMode.width = mode.w;
videoMode.height = mode.h;
int sdlBits = SDL_BITSPERPIXEL(mode.format);
if (SDL_ISPIXELFORMAT_ALPHA(mode.format)) {
videoMode.bit_depth = sdlBits;
} else {
// Fix a few values
if (sdlBits == 24) {
videoMode.bit_depth = 32;
} else if (sdlBits == 15) {
videoMode.bit_depth = 16;
} else {
videoMode.bit_depth = sdlBits;
}
}
display.video_modes.push_back(videoMode);
}
data.push_back(display);
}
SDL_QuitSubSystem(SDL_INIT_VIDEO);
return data;
}
namespace std {
size_t hash<vertex_format_data>::operator()(const vertex_format_data& data) const {
size_t seed = 0;
boost::hash_combine(seed, (size_t)data.format_type);
boost::hash_combine(seed, data.offset);
boost::hash_combine(seed, data.stride);
return seed;
}
size_t hash<vertex_layout>::operator()(const vertex_layout& data) const {
return data.hash();
}
}
bool vertex_layout::resident_vertex_format(vertex_format_data::vertex_format format_type) const {
return ( Vertex_mask & vertex_format_data::mask(format_type) ) ? true : false;
}
void vertex_layout::add_vertex_component(vertex_format_data::vertex_format format_type, size_t stride, size_t offset) {
// A stride value of 0 is not handled consistently by the graphics API so we must enforce that that does not happen
Assertion(stride != 0, "The stride of a vertex component may not be zero!");
if ( resident_vertex_format(format_type) ) {
// we already have a vertex component of this format type
return;
}
if (Vertex_mask == 0) {
// This is the first element so we need to initialize the global stride here
Vertex_stride = stride;
}
Assertion(Vertex_stride == stride, "The strides of all elements must be the same in a vertex layout!");
Vertex_mask |= (1 << format_type);
Vertex_components.push_back(vertex_format_data(format_type, stride, offset));
}
bool vertex_layout::operator==(const vertex_layout& other) const {
if (Vertex_mask != other.Vertex_mask) {
return false;
}
if (Vertex_components.size() != other.Vertex_components.size()) {
return false;
}
return std::equal(Vertex_components.cbegin(),
Vertex_components.cend(),
other.Vertex_components.cbegin());
}
size_t vertex_layout::hash() const {
size_t seed = 0;
boost::hash_combine(seed, Vertex_mask);
for (auto& comp : Vertex_components) {
boost::hash_combine(seed, comp);
}
return seed;
}
+263 -207
View File
@@ -5,7 +5,7 @@
* or otherwise commercially exploit the source or things you created based on the
* source.
*
*/
*/
@@ -13,7 +13,7 @@
#define _GRAPHICS_H
#include "graphics/grinternal.h"
#include "osapi/osapi.h"
#include <osapi/osapi.h>
#include "bmpman/bmpman.h"
#include "cfile/cfile.h"
#include "globalincs/pstypes.h"
@@ -22,13 +22,6 @@
#include "math/vecmat.h"
#include "io/cursor.h"
// Forward definition
namespace graphics {
namespace util {
class UniformBuffer;
}
}
extern const float Default_min_draw_distance;
extern const float Default_max_draw_distance;
extern float Min_draw_distance;
@@ -44,12 +37,9 @@ class model_material;
class particle_material;
class distortion_material;
class shield_material;
class movie_material;
class batched_bitmap_material;
class nanovg_material;
class transform_stack {
matrix4 Current_transform;
SCP_vector<matrix4> Stack;
public:
@@ -110,7 +100,7 @@ public:
vm_matrix4_x_matrix4(&Current_transform, &current_transform_copy, &new_transform);
Stack.push_back(Current_transform);
}
void pop()
{
if ( Stack.size() > 1 ) {
@@ -119,10 +109,6 @@ public:
Current_transform = Stack.back();
}
size_t depth() {
return Stack.size();
}
};
enum primitive_type {
@@ -152,11 +138,8 @@ enum shader_type {
SDR_TYPE_DEFERRED_LIGHTING,
SDR_TYPE_DEFERRED_CLEAR,
SDR_TYPE_VIDEO_PROCESS,
SDR_TYPE_PASSTHROUGH_RENDER, //!< Shader for doing the old style fixed-function rendering. Only used internally, use SDR_TYPE_DEFAULT_MATERIAL.
SDR_TYPE_PASSTHROUGH_RENDER,
SDR_TYPE_SHIELD_DECAL,
SDR_TYPE_BATCHED_BITMAP,
SDR_TYPE_DEFAULT_MATERIAL,
SDR_TYPE_NANOVG,
NUM_SHADER_TYPES
};
@@ -189,16 +172,6 @@ enum shader_type {
#define SDR_FLAG_BLUR_HORIZONTAL (1<<0)
#define SDR_FLAG_BLUR_VERTICAL (1<<1)
#define SDR_FLAG_NANOVG_EDGE_AA (1<<0)
enum class uniform_block_type {
Lights = 0,
ModelData = 1,
NanoVGData = 2,
NUM_BLOCK_TYPES
};
struct vertex_format_data
{
enum vertex_format {
@@ -208,59 +181,74 @@ struct vertex_format_data
SCREEN_POS,
COLOR3,
COLOR4,
TEX_COORD2,
TEX_COORD3,
TEX_COORD,
NORMAL,
TANGENT,
MODEL_ID,
RADIUS,
UVEC,
UVEC
};
vertex_format format_type;
size_t stride;
size_t offset;
void *data_src;
int offset;
vertex_format_data(vertex_format i_format_type, size_t i_stride, size_t i_offset) :
format_type(i_format_type), stride(i_stride), offset(i_offset) {}
vertex_format_data(vertex_format i_format_type, size_t i_stride, void *i_data_src) :
format_type(i_format_type), stride(i_stride), data_src(i_data_src), offset(-1) {}
vertex_format_data(vertex_format i_format_type, size_t i_stride, int i_offset) :
format_type(i_format_type), stride(i_stride), data_src(NULL), offset(i_offset) {}
static inline uint mask(vertex_format v_format) { return 1 << v_format; }
bool operator==(const vertex_format_data& other) const {
return format_type == other.format_type && stride == other.stride && offset == other.offset;
}
};
class vertex_layout
{
SCP_vector<vertex_format_data> Vertex_components;
uint Vertex_mask = 0;
size_t Vertex_stride = 0;
uint Vertex_mask;
public:
vertex_layout() {}
vertex_layout(): Vertex_mask(0) {}
size_t get_num_vertex_components() const { return Vertex_components.size(); }
vertex_layout(void* init_ptr): Vertex_mask(0) {}
const vertex_format_data* get_vertex_component(size_t index) const { return &Vertex_components[index]; }
size_t get_num_vertex_components() { return Vertex_components.size(); }
vertex_format_data* get_vertex_component(size_t index) { return &Vertex_components[index]; }
bool resident_vertex_format(vertex_format_data::vertex_format format_type) const;
bool resident_vertex_format(vertex_format_data::vertex_format format_type)
{
return ( Vertex_mask & vertex_format_data::mask(format_type) ) ? true : false;
}
void add_vertex_component(vertex_format_data::vertex_format format_type, size_t stride, size_t offset);
void add_vertex_component(vertex_format_data::vertex_format format_type, void* src)
{
add_vertex_component(format_type, 0, src);
}
size_t get_vertex_stride() { return Vertex_stride; }
void add_vertex_component(vertex_format_data::vertex_format format_type, size_t stride, void* src)
{
if ( resident_vertex_format(format_type) ) {
// we already have a vertex component of this format type
return;
}
bool operator==(const vertex_layout& other) const;
Vertex_mask |= (1 << format_type);
Vertex_components.push_back(vertex_format_data(format_type, stride, src));
}
size_t hash() const;
void add_vertex_component(vertex_format_data::vertex_format format_type, size_t stride, int offset)
{
if ( resident_vertex_format(format_type) ) {
// we already have a vertex component of this format type
return;
}
Vertex_mask |= (1 << format_type);
Vertex_components.push_back(vertex_format_data(format_type, stride, offset));
}
};
namespace std {
template<> struct hash<vertex_format_data> {
size_t operator()(const vertex_format_data& data) const;
};
template<> struct hash<vertex_layout> {
size_t operator()(const vertex_layout& data) const;
};
}
typedef enum gr_capability {
CAPABILITY_ENVIRONMENT_MAP,
@@ -276,10 +264,6 @@ typedef enum gr_capability {
CAPABILITY_TIMESTAMP_QUERY,
} gr_capability;
enum class gr_property {
UNIFORM_BUFFER_OFFSET_ALIGNMENT
};
// stencil buffering stuff
extern int gr_stencil_mode;
@@ -388,7 +372,7 @@ public:
{
return index;
}
uint i_first, i_last;
void release()
@@ -428,7 +412,7 @@ public:
index = NULL;
}
}
// Copy-constructor
buffer_data(const buffer_data& other)
{
@@ -441,17 +425,17 @@ public:
} else {
index = NULL;
}
flags = other.flags;
texture = other.texture;
n_verts = other.n_verts;
i_first = other.i_first;
i_last = other.i_last;
index_offset = other.index_offset;
}
// Copy-assignment operator
buffer_data& operator=(const buffer_data& rhs)
{
@@ -468,19 +452,19 @@ public:
index[i] = rhs.index[i];
}
}
flags = rhs.flags;
texture = rhs.texture;
n_verts = rhs.n_verts;
i_first = rhs.i_first;
i_last = rhs.i_last;
index_offset = rhs.index_offset;
}
return *this;
}
// Destructor
~buffer_data()
{
@@ -536,8 +520,8 @@ public:
};
struct indexed_vertex_source {
void *Vertex_list;
void *Index_list;
float *Vertex_list; // interleaved array
ubyte *Index_list;
int Vbuffer_handle;
int Ibuffer_handle;
@@ -570,23 +554,6 @@ enum class QueryType {
Timestamp
};
enum class BufferType {
Vertex,
Index,
Uniform
};
enum class BufferUsageHint {
Static,
Dynamic,
Streaming
};
/**
* @brief Type of a graphics sync object
*/
typedef void* gr_sync;
typedef struct screen {
uint signature; // changes when mode or palette or width or height changes
int max_w, max_h; // Width and height
@@ -637,11 +604,13 @@ typedef struct screen {
int envmap_render_target;
float line_width;
//switch onscreen, offscreen
void (*gf_flip)();
// Flash the screen
void (*gf_flash)( int r, int g, int b );
void (*gf_flash_alpha)(int r, int g, int b, int a);
// sets the clipping region
void (*gf_set_clip)(int x, int y, int w, int h, int resize_mode);
@@ -651,9 +620,43 @@ typedef struct screen {
// clears entire clipping region to current color
void (*gf_clear)();
// void (*gf_bitmap)(int x, int y, int resize_mode);
void (*gf_bitmap_ex)(int x, int y, int w, int h, int sx, int sy, int resize_mode);
void (*gf_aabitmap)(int x, int y, int resize_mode, bool mirror);
void (*gf_aabitmap_ex)(int x, int y, int w, int h, int sx, int sy, int resize_mode, bool mirror);
void(*gf_string)(float x, float y, const char * text, int resize_mode, int length);
// Draw a gradient line... x1,y1 is bright, x2,y2 is transparent.
void (*gf_gradient)(int x1, int y1, int x2, int y2, int resize_mode);
void (*gf_circle)(int x, int y, int r, int resize_mode);
void (*gf_unfilled_circle)(int x, int y, int r, int resize_mode);
void (*gf_arc)(int x, int y, float r, float angle_start, float angle_end, bool fill, int resize_mode);
void (*gf_curve)(int x, int y, int r, int direction, int resize_mode);
// Integer line. Used to draw a fast but pixely line.
void (*gf_line)(int x1, int y1, int x2, int y2, int resize_mode);
// Draws an antialiased line is the current color is an
// alphacolor, otherwise just draws a fast line. This
// gets called internally by g3_draw_line. This assumes
// the vertex's are already clipped, so call g3_draw_line
// not this if you have two 3d points.
void (*gf_aaline)(vertex *v1, vertex *v2);
void (*gf_pixel)( int x, int y, int resize_mode );
// dumps the current screen to a file
void (*gf_print_screen)(const char * filename);
// Call once before rendering anything.
void (*gf_start_frame)();
// Call after rendering is over.
void (*gf_stop_frame)();
// Retrieves the zbuffer mode.
int (*gf_zbuffer_get)();
@@ -670,24 +673,24 @@ typedef struct screen {
void (*gf_stencil_clear)();
int (*gf_alpha_mask_set)(int mode, float alpha);
// Saves screen. Returns an id you pass to restore and free.
int (*gf_save_screen)();
// Resets clip region and copies entire saved screen to the screen.
void (*gf_restore_screen)(int id);
// Frees up a saved screen.
void (*gf_free_screen)(int id);
// Sets the gamma
void (*gf_set_gamma)(float gamma);
// grab a region of the screen. assumes data is large enough
void (*gf_get_region)(int front, int w, int h, ubyte *data);
// set fog attributes
void (*gf_fog_set)(int fog_mode, int r, int g, int b, float fog_near, float fog_far);
void (*gf_fog_set)(int fog_mode, int r, int g, int b, float fog_near, float fog_far);
// poly culling
int (*gf_set_cull)(int cull);
@@ -717,15 +720,36 @@ typedef struct screen {
void (*gf_set_texture_addressing)(int);
int (*gf_create_buffer)(BufferType type, BufferUsageHint usage);
int (*gf_create_vertex_buffer)(bool static_buffer);
int (*gf_create_index_buffer)(bool static_buffer);
void (*gf_delete_buffer)(int handle);
void (*gf_update_buffer_data)(int handle, size_t size, void* data);
void (*gf_update_buffer_data_offset)(int handle, size_t offset, size_t size, void* data);
void (*gf_update_transform_buffer)(void* data, size_t size);
void (*gf_set_transform_buffer_offset)(size_t offset);
void (*gf_render_stream_buffer)(int buffer_handle, size_t offset, size_t n_verts, int flags);
//the projection matrix; fov, aspect ratio, near, far
void (*gf_set_proj_matrix)(float, float, float, float);
void (*gf_end_proj_matrix)();
//the view matrix
void (*gf_set_view_matrix)(const vec3d*, const matrix*);
void (*gf_end_view_matrix)();
//object scaleing
void (*gf_push_scale_matrix)(const vec3d*);
void (*gf_pop_scale_matrix)();
//object position and orientation
void (*gf_start_instance_matrix)(const vec3d*, const matrix*);
void (*gf_start_angles_instance_matrix)(const vec3d*, const angles*);
void (*gf_end_instance_matrix)();
void (*gf_set_light)(light*);
void (*gf_reset_lighting)();
void (*gf_set_ambient_light)(int,int,int);
// postprocessing effects
void (*gf_post_process_set_effect)(const char*, int, const vec3d*);
void (*gf_post_process_set_effect)(const char*, int);
void (*gf_post_process_set_defaults)();
void (*gf_post_process_begin)();
@@ -741,18 +765,24 @@ typedef struct screen {
void (*gf_scene_texture_end)();
void (*gf_copy_effect_texture)();
void (*gf_lighting)(bool,bool);
void (*gf_start_clip_plane)();
void (*gf_end_clip_plane)();
void (*gf_zbias)(int zbias);
void (*gf_set_fill_mode)(int);
void (*gf_set_texture_panning)(float u, float v, bool enable);
void (*gf_set_line_width)(float width);
void (*gf_sphere)(material *material_def, float rad);
int (*gf_maybe_create_shader)(shader_type type, unsigned int flags);
void (*gf_clear_states)();
void (*gf_update_texture)(int bitmap_handle, int bpp, const ubyte* data, int width, int height);
void (*gf_get_bitmap_from_texture)(void* data_out, int bitmap_num);
@@ -762,15 +792,14 @@ typedef struct screen {
// new drawing functions
void (*gf_render_model)(model_material* material_info, indexed_vertex_source *vert_source, vertex_buffer* bufferp, size_t texi);
void (*gf_render_shield_impact)(shield_material *material_info, primitive_type prim_type, vertex_layout *layout, int buffer_handle, int n_verts);
void (*gf_render_primitives)(material* material_info, primitive_type prim_type, vertex_layout* layout, int offset, int n_verts, int buffer_handle, size_t buffer_offset);
void (*gf_render_primitives)(material* material_info, primitive_type prim_type, vertex_layout* layout, int offset, int n_verts, int buffer_handle);
void (*gf_render_primitives_immediate)(material* material_info, primitive_type prim_type, vertex_layout* layout, int n_verts, void* data, int size);
void (*gf_render_primitives_particle)(particle_material* material_info, primitive_type prim_type, vertex_layout* layout, int offset, int n_verts, int buffer_handle);
void (*gf_render_primitives_distortion)(distortion_material* material_info, primitive_type prim_type, vertex_layout* layout, int offset, int n_verts, int buffer_handle);
void (*gf_render_movie)(movie_material* material_info, primitive_type prim_type, vertex_layout* layout, int n_verts, int buffer);
void (*gf_render_primitives_batched)(batched_bitmap_material* material_info, primitive_type prim_type, vertex_layout* layout, int offset, int n_verts, int buffer_handle);
void (*gf_render_nanovg)(nanovg_material* material_info, primitive_type prim_type, vertex_layout* layout, int offset, int n_verts, int buffer_handle);
void (*gf_render_primitives_2d)(material* material_info, primitive_type prim_type, vertex_layout* layout, int offset, int n_verts, int buffer_handle);
void (*gf_render_primitives_2d_immediate)(material* material_info, primitive_type prim_type, vertex_layout* layout, int n_verts, void* data, int size);
bool (*gf_is_capable)(gr_capability capability);
bool (*gf_get_property)(gr_property property, void* destination);
void (*gf_push_debug_group)(const char* name);
void (*gf_pop_debug_group)();
@@ -783,14 +812,6 @@ typedef struct screen {
std::unique_ptr<os::Viewport> (*gf_create_viewport)(const os::ViewPortProperties& props);
void (*gf_use_viewport)(os::Viewport* view);
void (*gf_bind_uniform_buffer)(uniform_block_type bind_point, size_t offset, size_t size, int buffer);
gr_sync (*gf_sync_fence)();
bool (*gf_sync_wait)(gr_sync sync, uint64_t timeoutns);
void (*gf_sync_delete)(gr_sync sync);
void (*gf_set_viewport)(int x, int y, int width, int height);
} screen;
// handy macro
@@ -802,7 +823,7 @@ typedef struct screen {
// # Software Re-added by Kazan --- THIS HAS TO STAY -- It is used by standalone!
#define GR_DEFAULT (-1) // set to use default settings
#define GR_STUB (100)
#define GR_STUB (100)
#define GR_OPENGL (104) // Use OpenGl hardware renderer
// resolution constants - always keep resolutions in ascending order and starting from 0
@@ -896,8 +917,71 @@ __inline void gr_set_clip(int x, int y, int w, int h, int resize_mode=GR_RESIZE_
void gr_set_bitmap(int bitmap_num, int alphablend = GR_ALPHABLEND_NONE, int bitbltmode = GR_BITBLT_MODE_NORMAL, float alpha = 1.0f);
#define gr_clear GR_CALL(gr_screen.gf_clear)
__inline void gr_aabitmap(int x, int y, int resize_mode = GR_RESIZE_FULL, bool mirror = false)
{
(*gr_screen.gf_aabitmap)(x,y,resize_mode,mirror);
}
__inline void gr_aabitmap_ex(int x, int y, int w, int h, int sx, int sy, int resize_mode = GR_RESIZE_FULL, bool mirror = false)
{
(*gr_screen.gf_aabitmap_ex)(x,y,w,h,sx,sy,resize_mode,mirror);
}
__inline void gr_bitmap_ex(int x, int y, int w, int h, int sx, int sy, int resize_mode = GR_RESIZE_FULL)
{
(*gr_screen.gf_bitmap_ex)(x, y, w, h, sx, sy, resize_mode);
}
void gr_shield_icon(coord2d coords[6], const int resize_mode = GR_RESIZE_FULL);
void gr_rect(int x, int y, int w, int h, int resize_mode = GR_RESIZE_FULL);
void gr_shade(int x, int y, int w, int h, int resize_mode = GR_RESIZE_FULL);
__inline void gr_string(float x, float y, const char* string, int resize_mode = GR_RESIZE_FULL, int length = -1)
{
(*gr_screen.gf_string)(x, y, string, resize_mode, length);
}
__inline void gr_string(int x, int y, const char* string, int resize_mode = GR_RESIZE_FULL, int length = -1)
{
gr_string(i2fl(x), i2fl(y), string, resize_mode, length);
}
__inline void gr_circle(int xc, int yc, int d, int resize_mode = GR_RESIZE_FULL)
{
(*gr_screen.gf_circle)(xc,yc,d,resize_mode);
}
__inline void gr_unfilled_circle(int xc, int yc, int d, int resize_mode = GR_RESIZE_FULL)
{
(*gr_screen.gf_unfilled_circle)(xc,yc,d,resize_mode);
}
__inline void gr_arc(int xc, int yc, float r, float angle_start, float angle_end, bool fill, int resize_mode = GR_RESIZE_FULL)
{
(*gr_screen.gf_arc)(xc,yc,r,angle_start,angle_end,fill,resize_mode);
}
#define gr_curve GR_CALL(gr_screen.gf_curve)
__inline void gr_line(int x1, int y1, int x2, int y2, int resize_mode = GR_RESIZE_FULL)
{
(*gr_screen.gf_line)(x1, y1, x2, y2, resize_mode);
}
#define gr_aaline GR_CALL(gr_screen.gf_aaline)
__inline void gr_pixel(int x, int y, int resize_mode = GR_RESIZE_FULL)
{
(*gr_screen.gf_pixel)(x, y, resize_mode);
}
__inline void gr_gradient(int x1, int y1, int x2, int y2, int resize_mode = GR_RESIZE_FULL)
{
(*gr_screen.gf_gradient)(x1, y1, x2, y2, resize_mode);
}
#define gr_flash GR_CALL(gr_screen.gf_flash)
#define gr_flash_alpha GR_CALL(gr_screen.gf_flash_alpha)
#define gr_zbuffer_get GR_CALL(gr_screen.gf_zbuffer_get)
#define gr_zbuffer_set GR_CALL(gr_screen.gf_zbuffer_set)
@@ -941,24 +1025,43 @@ __inline void gr_fog_set(int fog_mode, int r, int g, int b, float fog_near = -1.
#define gr_bm_page_in_start GR_CALL(*gr_screen.gf_bm_page_in_start)
#define gr_bm_data GR_CALL(*gr_screen.gf_bm_data)
#define gr_bm_make_render_target GR_CALL(*gr_screen.gf_bm_make_render_target)
#define gr_bm_make_render_target GR_CALL(*gr_screen.gf_bm_make_render_target)
__inline int gr_bm_set_render_target(int n, int face = -1)
{
return (*gr_screen.gf_bm_set_render_target)(n, face);
}
#define gr_set_texture_addressing GR_CALL(*gr_screen.gf_set_texture_addressing)
#define gr_set_texture_addressing GR_CALL(*gr_screen.gf_set_texture_addressing)
inline int gr_create_buffer(BufferType type, BufferUsageHint usage)
__inline int gr_create_vertex_buffer(bool static_buffer = false)
{
return (*gr_screen.gf_create_buffer)(type, usage);
return (*gr_screen.gf_create_vertex_buffer)(static_buffer);
}
__inline int gr_create_index_buffer(bool static_buffer = false)
{
return (*gr_screen.gf_create_index_buffer)(static_buffer);
}
#define gr_delete_buffer GR_CALL(*gr_screen.gf_delete_buffer)
#define gr_update_buffer_data GR_CALL(*gr_screen.gf_update_buffer_data)
#define gr_update_buffer_data_offset GR_CALL(*gr_screen.gf_update_buffer_data_offset)
#define gr_update_transform_buffer GR_CALL(*gr_screen.gf_update_transform_buffer)
#define gr_set_transform_buffer_offset GR_CALL(*gr_screen.gf_set_transform_buffer_offset)
#define gr_set_proj_matrix GR_CALL(*gr_screen.gf_set_proj_matrix)
#define gr_end_proj_matrix GR_CALL(*gr_screen.gf_end_proj_matrix)
#define gr_set_view_matrix GR_CALL(*gr_screen.gf_set_view_matrix)
#define gr_end_view_matrix GR_CALL(*gr_screen.gf_end_view_matrix)
#define gr_push_scale_matrix GR_CALL(*gr_screen.gf_push_scale_matrix)
#define gr_pop_scale_matrix GR_CALL(*gr_screen.gf_pop_scale_matrix)
#define gr_start_instance_matrix GR_CALL(*gr_screen.gf_start_instance_matrix)
#define gr_start_angles_instance_matrix GR_CALL(*gr_screen.gf_start_angles_instance_matrix)
#define gr_end_instance_matrix GR_CALL(*gr_screen.gf_end_instance_matrix)
#define gr_set_light GR_CALL(*gr_screen.gf_set_light)
#define gr_reset_lighting GR_CALL(*gr_screen.gf_reset_lighting)
#define gr_set_ambient_light GR_CALL(*gr_screen.gf_set_ambient_light)
#define gr_scene_texture_begin GR_CALL(*gr_screen.gf_scene_texture_begin)
#define gr_scene_texture_end GR_CALL(*gr_screen.gf_scene_texture_end)
@@ -977,8 +1080,14 @@ inline void gr_post_process_restore_zbuffer() {
#define gr_deferred_lighting_end GR_CALL(*gr_screen.gf_deferred_lighting_end)
#define gr_deferred_lighting_finish GR_CALL(*gr_screen.gf_deferred_lighting_finish)
#define gr_set_lighting GR_CALL(*gr_screen.gf_lighting)
#define gr_start_clip GR_CALL(*gr_screen.gf_start_clip_plane)
#define gr_end_clip GR_CALL(*gr_screen.gf_end_clip_plane)
#define gr_zbias GR_CALL(*gr_screen.gf_zbias)
#define gr_set_fill_mode GR_CALL(*gr_screen.gf_set_fill_mode)
#define gr_set_texture_panning GR_CALL(*gr_screen.gf_set_texture_panning)
#define gr_set_line_width GR_CALL(*gr_screen.gf_set_line_width)
@@ -996,9 +1105,14 @@ inline void gr_post_process_restore_zbuffer() {
#define gr_shadow_map_end GR_CALL(*gr_screen.gf_shadow_map_end)
#define gr_render_shield_impact GR_CALL(*gr_screen.gf_render_shield_impact)
__inline void gr_render_primitives(material* material_info, primitive_type prim_type, vertex_layout* layout, int vert_offset, int n_verts, int buffer_handle = -1, size_t buffer_offset = 0)
__inline void gr_render_primitives(material* material_info, primitive_type prim_type, vertex_layout* layout, int offset, int n_verts, int buffer_handle = -1)
{
(*gr_screen.gf_render_primitives)(material_info, prim_type, layout, vert_offset, n_verts, buffer_handle, buffer_offset);
(*gr_screen.gf_render_primitives)(material_info, prim_type, layout, offset, n_verts, buffer_handle);
}
__inline void gr_render_primitives_immediate(material* material_info, primitive_type prim_type, vertex_layout* layout, int n_verts, void* data, int size)
{
(*gr_screen.gf_render_primitives_immediate)(material_info, prim_type, layout, n_verts, data, size);
}
__inline void gr_render_primitives_particle(particle_material* material_info, primitive_type prim_type, vertex_layout* layout, int offset, int n_verts, int buffer_handle = -1)
@@ -1006,24 +1120,19 @@ __inline void gr_render_primitives_particle(particle_material* material_info, pr
(*gr_screen.gf_render_primitives_particle)(material_info, prim_type, layout, offset, n_verts, buffer_handle);
}
__inline void gr_render_primitives_batched(batched_bitmap_material* material_info, primitive_type prim_type, vertex_layout* layout, int offset, int n_verts, int buffer_handle = -1)
{
(*gr_screen.gf_render_primitives_batched)(material_info, prim_type, layout, offset, n_verts, buffer_handle);
}
__inline void gr_render_nanovg(nanovg_material* material_info, primitive_type prim_type, vertex_layout* layout, int offset, int n_verts, int buffer_handle)
{
(*gr_screen.gf_render_nanovg)(material_info, prim_type, layout, offset, n_verts, buffer_handle);
}
__inline void gr_render_primitives_distortion(distortion_material* material_info, primitive_type prim_type, vertex_layout* layout, int offset, int n_verts, int buffer_handle = -1)
{
(*gr_screen.gf_render_primitives_distortion)(material_info, prim_type, layout, offset, n_verts, buffer_handle);
}
inline void gr_render_movie(movie_material* material_info, primitive_type prim_type, vertex_layout* layout, int n_verts, int buffer)
__inline void gr_render_primitives_2d(material* material_info, primitive_type prim_type, vertex_layout* layout, int offset, int n_verts, int buffer_handle = -1)
{
(*gr_screen.gf_render_movie)(material_info, prim_type, layout, n_verts, buffer);
(*gr_screen.gf_render_primitives_2d)(material_info, prim_type, layout, offset, n_verts, buffer_handle);
}
__inline void gr_render_primitives_2d_immediate(material* material_info, primitive_type prim_type, vertex_layout* layout, int n_verts, void* data, int size)
{
(*gr_screen.gf_render_primitives_2d_immediate)(material_info, prim_type, layout, n_verts, data, size);
}
__inline void gr_render_model(model_material* material_info, indexed_vertex_source *vert_source, vertex_buffer* bufferp, size_t texi)
@@ -1036,11 +1145,6 @@ __inline bool gr_is_capable(gr_capability capability)
return (*gr_screen.gf_is_capable)(capability);
}
inline bool gr_get_property(gr_property property, void* destination)
{
return (*gr_screen.gf_get_property)(property, destination);
}
inline void gr_push_debug_group(const char* name)
{
(*gr_screen.gf_push_debug_group)(name);
@@ -1082,23 +1186,6 @@ inline std::unique_ptr<os::Viewport> gr_create_viewport(const os::ViewPortProper
inline void gr_use_viewport(os::Viewport* view) {
(*gr_screen.gf_use_viewport)(view);
}
inline void gr_set_viewport(int x, int y, int width, int height) {
(*gr_screen.gf_set_viewport)(x, y, width, height);
}
inline void gr_bind_uniform_buffer(uniform_block_type bind_point, size_t offset, size_t size, int buffer) {
(*gr_screen.gf_bind_uniform_buffer)(bind_point, offset, size, buffer);
}
inline gr_sync gr_sync_fence() {
return (*gr_screen.gf_sync_fence)();
}
inline bool gr_sync_wait(gr_sync sync, uint64_t timeoutns) {
return (*gr_screen.gf_sync_wait)(sync, timeoutns);
}
inline void gr_sync_delete(gr_sync sync) {
(*gr_screen.gf_sync_delete)(sync);
}
// color functions
void gr_get_color( int *r, int *g, int b );
@@ -1112,17 +1199,17 @@ void gr_create_shader(shader *shade, ubyte r, ubyte g, ubyte b, ubyte c);
void gr_set_shader(shader *shade);
uint gr_determine_model_shader_flags(
bool lighting,
bool fog,
bool textured,
bool in_shadow_map,
bool thruster_scale,
bool lighting,
bool fog,
bool textured,
bool in_shadow_map,
bool thruster_scale,
bool transform,
bool team_color_set,
int tmap_flags,
int spec_map,
int glow_map,
int normal_map,
int tmap_flags,
int spec_map,
int glow_map,
int normal_map,
int height_map,
int ambient_map,
int env_map,
@@ -1144,14 +1231,14 @@ void gr_opengl_update_texture(int bitmap_handle, int bpp, const ubyte* data, int
// Moreover, it is _really_ intended for use with 45 degree angles.
void gr_pline_special(SCP_vector<vec3d> *pts, int thickness,int resize_mode=GR_RESIZE_FULL);
#define VB_FLAG_POSITION (1<<0)
#define VB_FLAG_POSITION (1<<0)
#define VB_FLAG_RHW (1<<1) //incompatable with the next normal
#define VB_FLAG_NORMAL (1<<2)
#define VB_FLAG_DIFUSE (1<<3)
#define VB_FLAG_SPECULAR (1<<4)
#define VB_FLAG_NORMAL (1<<2)
#define VB_FLAG_DIFUSE (1<<3)
#define VB_FLAG_SPECULAR (1<<4)
#define VB_FLAG_UV1 (1<<5) //how many UV coords, only use one of these
#define VB_FLAG_UV2 (1<<6)
#define VB_FLAG_UV3 (1<<7)
#define VB_FLAG_UV2 (1<<6)
#define VB_FLAG_UV3 (1<<7)
#define VB_FLAG_UV4 (1<<8)
#define VB_FLAG_TANGENT (1<<9)
#define VB_FLAG_LARGE_INDEX (1<<10)
@@ -1188,35 +1275,4 @@ class DebugScope {
#define GR_DEBUG_SCOPE(name) do {} while(0)
#endif
enum AnimatedShader {
ANIMATED_SHADER_LOADOUTSELECT_FS1= 0,
ANIMATED_SHADER_LOADOUTSELECT_FS2= 1,
ANIMATED_SHADER_CLOAK = 2,
};
graphics::util::UniformBuffer* gr_get_uniform_buffer(uniform_block_type type);
struct VideoModeData {
uint32_t width = 0;
uint32_t height = 0;
uint32_t bit_depth = 0;
};
struct DisplayData {
uint32_t index;
SCP_string name;
int32_t x = 0;
int32_t y = 0;
int32_t width = 0;
int32_t height = 0;
SCP_vector<VideoModeData> video_modes;
};
SCP_vector<DisplayData> gr_enumerate_displays();
// Include this last to make the 2D rendering function available everywhere
#include "graphics/render.h"
#endif
+4 -16
View File
@@ -251,19 +251,13 @@ int generic_anim_stream(generic_anim *ga, const bool cache)
if ( p )
*p = 0;
char frame_name[MAX_FILENAME_LEN];
if (snprintf(frame_name, MAX_FILENAME_LEN, "%s_0000", ga->filename) >= MAX_FILENAME_LEN) {
// Make sure the string is null terminated
frame_name[MAX_FILENAME_LEN - 1] = '\0';
}
snprintf(frame_name, MAX_FILENAME_LEN, "%s_0000", ga->filename);
ga->bitmap_id = bm_load(frame_name);
if(ga->bitmap_id < 0) {
mprintf(("Cannot find first frame for eff streaming. eff Filename: %s", ga->filename));
return -1;
}
if (snprintf(frame_name, MAX_FILENAME_LEN, "%s_0001", ga->filename) >= MAX_FILENAME_LEN) {
// Make sure the string is null terminated
frame_name[MAX_FILENAME_LEN - 1] = '\0';
}
snprintf(frame_name, MAX_FILENAME_LEN, "%s_0001", ga->filename);
ga->eff.next_frame = bm_load(frame_name);
bm_get_info(ga->bitmap_id, &ga->width, &ga->height);
ga->previous_frame = 0;
@@ -375,10 +369,7 @@ void generic_render_eff_stream(generic_anim *ga)
mprintf(("frame: %d\n", ga->current_frame));
#endif
char frame_name[MAX_FILENAME_LEN];
if (snprintf(frame_name, MAX_FILENAME_LEN, "%s_%.4d", ga->filename, ga->current_frame) >= MAX_FILENAME_LEN) {
// Make sure the string is null terminated
frame_name[MAX_FILENAME_LEN - 1] = '\0';
}
snprintf(frame_name, MAX_FILENAME_LEN, "%s_%.4d", ga->filename, ga->current_frame);
if(bm_reload(ga->eff.next_frame, frame_name) == ga->eff.next_frame)
{
bitmap* next_frame_bmp = bm_lock(ga->eff.next_frame, bpp, (bpp==8)?BMP_AABITMAP:BMP_TEX_NONCOMP, true);
@@ -388,10 +379,7 @@ void generic_render_eff_stream(generic_anim *ga)
bm_unload(ga->eff.next_frame, 0, true);
if (ga->current_frame == ga->num_frames-1)
{
if (snprintf(frame_name, MAX_FILENAME_LEN, "%s_0001", ga->filename) >= MAX_FILENAME_LEN) {
// Make sure the string is null terminated
frame_name[MAX_FILENAME_LEN - 1] = '\0';
}
snprintf(frame_name, MAX_FILENAME_LEN, "%s_0001", ga->filename);
bm_reload(ga->eff.next_frame, frame_name);
}
}
+2
View File
@@ -11,6 +11,8 @@
#include "globalincs/pstypes.h"
#include "graphics/2d.h"
#include "graphics/grbatch.h"
#include "graphics/opengl/gropengldraw.h"
#include "graphics/opengl/gropenglstate.h"
#include "render/3d.h"
geometry_batcher::~geometry_batcher()
+6
View File
@@ -69,4 +69,10 @@ typedef enum gr_zbuffer_type {
ZBUFFER_TYPE_DEFAULT
} gr_zbuffer_type;
typedef enum gr_stencil_type {
STENCIL_TYPE_NONE,
STENCIL_TYPE_READ,
STENCIL_TYPE_WRITE
} gr_stencil_type;
#endif
+200 -30
View File
@@ -23,7 +23,12 @@ uint gr_stub_lock()
return 1;
}
int gr_stub_create_buffer(BufferType, BufferUsageHint)
int gr_stub_create_vertex_buffer(bool static_buffer)
{
return -1;
}
int gr_stub_create_index_buffer(bool static_buffer)
{
return -1;
}
@@ -57,10 +62,37 @@ void gr_set_fill_mode_stub(int mode)
{
}
void gr_stub_aabitmap_ex(int x,int y,int w,int h,int sx,int sy,int resize_mode,bool mirror)
{
}
void gr_stub_aabitmap(int x, int y,int resize_mode, bool mirror)
{
}
void gr_stub_aaline(vertex *v1, vertex *v2)
{
}
void gr_stub_activate(int active)
{
}
void gr_stub_bitmap_ex(int x, int y, int w, int h, int sx, int sy, int resize_mode)
{
}
void gr_stub_bitmap(int x, int y)
{
}
void gr_stub_circle( int xc, int yc, int d, int resize_mode )
{
}
void gr_stub_unfilled_circle( int xc, int yc, int d, int resize_mode )
{
}
void gr_stub_cleanup(int minimize)
{
@@ -70,6 +102,34 @@ void gr_stub_clear()
{
}
void gr_stub_curve(int xc, int yc, int r, int direction, int resize_mode)
{
}
void gr_stub_end_clip_plane()
{
}
void gr_stub_end_instance_matrix()
{
}
void gr_stub_end_projection_matrix()
{
}
void gr_stub_end_view_matrix()
{
}
void gr_stub_flash_alpha(int r, int g, int b, int a)
{
}
void gr_stub_flash(int r, int g, int b)
{
}
void gr_stub_flip()
{
}
@@ -86,6 +146,22 @@ void gr_stub_get_region(int front, int w, int h, ubyte *data)
{
}
void gr_stub_gradient(int x1,int y1,int x2,int y2, int resize_mode)
{
}
void gr_stub_line(int x1,int y1,int x2,int y2, int resize_mode = GR_RESIZE_NONE)
{
}
void gr_stub_pixel(int x, int y, int resize_mode)
{
}
void gr_stub_pop_scale_matrix()
{
}
void gr_stub_pop_texture_matrix(int unit)
{
}
@@ -98,6 +174,10 @@ void gr_stub_print_screen(const char *filename)
{
}
void gr_stub_push_scale_matrix(const vec3d *scale_factor)
{
}
void gr_stub_push_texture_matrix(int unit)
{
}
@@ -110,6 +190,10 @@ void gr_stub_reset_clip()
{
}
void gr_stub_reset_lighting()
{
}
void gr_stub_restore_screen(int id)
{
}
@@ -120,10 +204,7 @@ void gr_stub_save_mouse_area(int x, int y, int w, int h)
void gr_stub_update_buffer_data(int handle, size_t size, void* data)
{
}
void gr_stub_update_buffer_data_offset(int handle, size_t offset, size_t size, void* data)
{
}
void gr_stub_update_transform_buffer(void* data, size_t size)
@@ -131,6 +212,15 @@ void gr_stub_update_transform_buffer(void* data, size_t size)
}
void gr_stub_set_transform_buffer_offset(size_t offset)
{
}
void gr_stub_render_stream_buffer(int buffer_handle, size_t offset, size_t n_verts, int flags)
{
}
void gr_stub_set_clear_color(int r, int g, int b)
{
}
@@ -153,6 +243,18 @@ void gr_stub_set_gamma(float gamma)
{
}
void gr_stub_set_lighting(bool set, bool state)
{
}
void gr_stub_set_light(light *light)
{
}
void gr_stub_set_projection_matrix(float fov, float aspect, float z_near, float z_far)
{
}
void gr_stub_set_tex_env_scale(float scale)
{
}
@@ -161,6 +263,26 @@ void gr_stub_set_texture_addressing(int mode)
{
}
void gr_stub_set_view_matrix(const vec3d *pos, const matrix* orient)
{
}
void gr_stub_start_clip_plane()
{
}
void gr_stub_start_instance_angles(const vec3d *pos, const angles *rotation)
{
}
void gr_stub_start_instance_matrix(const vec3d *offset, const matrix *rotation)
{
}
void gr_stub_string( float sx, float sy, const char *s, int resize_mode = GR_RESIZE_NONE, int length = -1)
{
}
void gr_stub_stuff_fog_coord(vertex *v)
{
}
@@ -199,7 +321,7 @@ int gr_stub_alpha_mask_set(int mode, float alpha)
{
}*/
void gr_stub_post_process_set_effect(const char *name, int x, const vec3d *rgb)
void gr_stub_post_process_set_effect(const char *name, int x)
{
}
@@ -247,6 +369,14 @@ void gr_stub_deferred_lighting_finish()
{
}
void gr_stub_set_ambient_light(int red, int green, int blue)
{
}
void gr_stub_set_texture_panning(float u, float v, bool enable)
{
}
void gr_stub_set_line_width(float width)
{
}
@@ -321,7 +451,22 @@ void gr_stub_render_model(model_material* material_info, indexed_vertex_source *
}
void gr_stub_render_primitives(material* material_info, primitive_type prim_type, vertex_layout* layout, int offset, int n_verts, int buffer_handle, size_t buffer_offset)
void gr_stub_render_primitives(material* material_info, primitive_type prim_type, vertex_layout* layout, int offset, int n_verts, int buffer_handle)
{
}
void gr_stub_render_primitives_immediate(material* material_info, primitive_type prim_type, vertex_layout* layout, int n_verts, void* data, int size)
{
}
void gr_stub_render_primitives_2d(material* material_info, primitive_type prim_type, vertex_layout* layout, int offset, int n_verts, int buffer_handle)
{
}
void gr_stub_render_primitives_2d_immediate(material* material_info, primitive_type prim_type, vertex_layout* layout, int n_verts, void* data, int size)
{
}
@@ -334,21 +479,6 @@ void gr_stub_render_primitives_particle(particle_material* material_info, primit
void gr_stub_render_primitives_distortion(distortion_material* material_info, primitive_type prim_type, vertex_layout* layout, int offset, int n_verts, int buffer_handle)
{
}
void gr_stub_render_movie(movie_material* material_info, primitive_type prim_type, vertex_layout* layout, int n_verts, int buffer)
{
}
void gr_stub_render_nanovg(nanovg_material* material_info,
primitive_type prim_type,
vertex_layout* layout,
int offset,
int n_verts,
int buffer_handle) {
}
void gr_stub_render_primitives_batched(batched_bitmap_material* material_info, primitive_type prim_type, vertex_layout* layout, int offset, int n_verts, int buffer_handle)
{
}
bool gr_stub_is_capable(gr_capability capability)
@@ -417,12 +547,29 @@ bool gr_stub_init()
gr_screen.gf_reset_clip = gr_stub_reset_clip;
gr_screen.gf_clear = gr_stub_clear;
// gr_screen.gf_bitmap = gr_stub_bitmap;
gr_screen.gf_bitmap_ex = gr_stub_bitmap_ex;
gr_screen.gf_aabitmap = gr_stub_aabitmap;
gr_screen.gf_aabitmap_ex = gr_stub_aabitmap_ex;
// gr_screen.gf_rect = gr_stub_rect;
// gr_screen.gf_shade = gr_stub_shade;
gr_screen.gf_string = gr_stub_string;
gr_screen.gf_circle = gr_stub_circle;
gr_screen.gf_unfilled_circle = gr_stub_unfilled_circle;
gr_screen.gf_curve = gr_stub_curve;
gr_screen.gf_line = gr_stub_line;
gr_screen.gf_aaline = gr_stub_aaline;
gr_screen.gf_pixel = gr_stub_pixel;
gr_screen.gf_gradient = gr_stub_gradient;
gr_screen.gf_print_screen = gr_stub_print_screen;
gr_screen.gf_flash = gr_stub_flash;
gr_screen.gf_flash_alpha = gr_stub_flash_alpha;
gr_screen.gf_zbuffer_get = gr_stub_zbuffer_get;
gr_screen.gf_zbuffer_set = gr_stub_zbuffer_set;
gr_screen.gf_zbuffer_clear = gr_stub_zbuffer_clear;
@@ -466,13 +613,25 @@ bool gr_stub_init()
gr_screen.gf_set_texture_addressing = gr_stub_set_texture_addressing;
gr_screen.gf_zbias = gr_stub_zbias_stub;
gr_screen.gf_set_fill_mode = gr_set_fill_mode_stub;
gr_screen.gf_set_texture_panning = gr_stub_set_texture_panning;
gr_screen.gf_create_buffer = gr_stub_create_buffer;
gr_screen.gf_create_vertex_buffer = gr_stub_create_vertex_buffer;
gr_screen.gf_create_index_buffer = gr_stub_create_index_buffer;
gr_screen.gf_delete_buffer = gr_stub_delete_buffer;
gr_screen.gf_update_transform_buffer = gr_stub_update_transform_buffer;
gr_screen.gf_update_buffer_data = gr_stub_update_buffer_data;
gr_screen.gf_update_buffer_data_offset = gr_stub_update_buffer_data_offset;
gr_screen.gf_set_transform_buffer_offset = gr_stub_set_transform_buffer_offset;
gr_screen.gf_render_stream_buffer = gr_stub_render_stream_buffer;
gr_screen.gf_start_instance_matrix = gr_stub_start_instance_matrix;
gr_screen.gf_end_instance_matrix = gr_stub_end_instance_matrix;
gr_screen.gf_start_angles_instance_matrix = gr_stub_start_instance_angles;
gr_screen.gf_set_light = gr_stub_set_light;
gr_screen.gf_reset_lighting = gr_stub_reset_lighting;
gr_screen.gf_set_ambient_light = gr_stub_set_ambient_light;
gr_screen.gf_post_process_set_effect = gr_stub_post_process_set_effect;
gr_screen.gf_post_process_set_defaults = gr_stub_post_process_set_defaults;
@@ -490,6 +649,20 @@ bool gr_stub_init()
gr_screen.gf_deferred_lighting_end = gr_stub_deferred_lighting_end;
gr_screen.gf_deferred_lighting_finish = gr_stub_deferred_lighting_finish;
gr_screen.gf_start_clip_plane = gr_stub_start_clip_plane;
gr_screen.gf_end_clip_plane = gr_stub_end_clip_plane;
gr_screen.gf_lighting = gr_stub_set_lighting;
gr_screen.gf_set_proj_matrix = gr_stub_set_projection_matrix;
gr_screen.gf_end_proj_matrix = gr_stub_end_projection_matrix;
gr_screen.gf_set_view_matrix = gr_stub_set_view_matrix;
gr_screen.gf_end_view_matrix = gr_stub_end_view_matrix;
gr_screen.gf_push_scale_matrix = gr_stub_push_scale_matrix;
gr_screen.gf_pop_scale_matrix = gr_stub_pop_scale_matrix;
gr_screen.gf_set_line_width = gr_stub_set_line_width;
gr_screen.gf_sphere = gr_stub_draw_sphere;
@@ -508,14 +681,13 @@ bool gr_stub_init()
gr_screen.gf_render_model = gr_stub_render_model;
gr_screen.gf_render_primitives = gr_stub_render_primitives;
gr_screen.gf_render_primitives_immediate = gr_stub_render_primitives_immediate;
gr_screen.gf_render_primitives_2d = gr_stub_render_primitives_2d;
gr_screen.gf_render_primitives_2d_immediate = gr_stub_render_primitives_2d_immediate;
gr_screen.gf_render_primitives_particle = gr_stub_render_primitives_particle;
gr_screen.gf_render_primitives_distortion = gr_stub_render_primitives_distortion;
gr_screen.gf_render_movie = gr_stub_render_movie;
gr_screen.gf_render_nanovg = gr_stub_render_nanovg;
gr_screen.gf_render_primitives_batched = gr_stub_render_primitives_batched;
gr_screen.gf_is_capable = gr_stub_is_capable;
gr_screen.gf_get_property = [](gr_property,void*) { return false; };
gr_screen.gf_push_debug_group = gr_stub_push_debug_group;
gr_screen.gf_pop_debug_group = gr_stub_pop_debug_group;
@@ -532,7 +704,5 @@ bool gr_stub_init()
gr_screen.gf_use_viewport = [](os::Viewport*) {
};
gr_screen.gf_bind_uniform_buffer = [](uniform_block_type, size_t, size_t, int) {};
return true;
}
-383
View File
@@ -1,383 +0,0 @@
/*
* Copyright (C) Volition, Inc. 1999. All rights reserved.
*
* All source code herein is the property of Volition, Inc. You may not sell
* or otherwise commercially exploit the source or things you created based on the
* source.
*
*/
#include <math/bitarray.h>
#include "cmdline/cmdline.h"
#include "globalincs/pstypes.h"
#include "graphics/2d.h"
#include "light.h"
#include "matrix.h"
#include "render/3d.h"
// Structures
struct gr_light
{
vec4 Ambient;
vec4 Diffuse;
vec4 Specular;
// light position
vec4 Position;
// spotlight direction (for tube lights)
vec3d SpotDir;
float SpotExp, SpotCutOff;
float ConstantAtten, LinearAtten, QuadraticAtten;
bool occupied;
int type;
};
// Variables
gr_light* gr_lights = NULL;
graphics::model_light gr_light_uniforms[graphics::MAX_UNIFORM_LIGHTS];
int Num_active_gr_lights = 0;
// OGL defaults
const float gr_light_color[4] = { 0.8f, 0.8f, 0.8f, 1.0f };
const float gr_light_zero[4] = { 0.0f, 0.0f, 0.0f, 1.0f };
const float gr_light_emission[4] = { 0.09f, 0.09f, 0.09f, 1.0f };
float gr_light_ambient[4] = { 0.47f, 0.47f, 0.47f, 1.0f };
void FSLight2GLLight(light* FSLight, gr_light* GLLight) {
GLLight->Ambient.xyzw.x = 0.0f;
GLLight->Ambient.xyzw.y = 0.0f;
GLLight->Ambient.xyzw.z = 0.0f;
GLLight->Ambient.xyzw.w = 1.0f;
GLLight->Diffuse.xyzw.x = FSLight->r * FSLight->intensity;
GLLight->Diffuse.xyzw.y = FSLight->g * FSLight->intensity;
GLLight->Diffuse.xyzw.z = FSLight->b * FSLight->intensity;
GLLight->Diffuse.xyzw.w = 1.0f;
GLLight->Specular.xyzw.x = FSLight->spec_r * FSLight->intensity;
GLLight->Specular.xyzw.y = FSLight->spec_g * FSLight->intensity;
GLLight->Specular.xyzw.z = FSLight->spec_b * FSLight->intensity;
GLLight->Specular.xyzw.w = 1.0f;
GLLight->type = FSLight->type;
// GL default values...
// spot direction
GLLight->SpotDir.xyz.x = 0.0f;
GLLight->SpotDir.xyz.y = 0.0f;
GLLight->SpotDir.xyz.z = -1.0f;
// spot exponent
GLLight->SpotExp = Cmdline_ogl_spec * 0.5f;
// spot cutoff
GLLight->SpotCutOff = 180.0f; // special value, light in all directions
// defaults to disable attenuation
GLLight->ConstantAtten = 1.0f;
GLLight->LinearAtten = 0.0f;
GLLight->QuadraticAtten = 0.0f;
// position
GLLight->Position.xyzw.x = FSLight->vec.xyz.x;
GLLight->Position.xyzw.y = FSLight->vec.xyz.y;
GLLight->Position.xyzw.z = FSLight->vec.xyz.z; // flipped axis for FS2
GLLight->Position.xyzw.w = 1.0f;
switch (FSLight->type) {
case LT_POINT: {
// this crap still needs work...
GLLight->ConstantAtten = 1.0f;
GLLight->LinearAtten = (1.0f / MAX(FSLight->rada, FSLight->radb)) * 1.25f;
GLLight->Specular.xyzw.x *= static_point_factor;
GLLight->Specular.xyzw.y *= static_point_factor;
GLLight->Specular.xyzw.z *= static_point_factor;
break;
}
case LT_TUBE: {
GLLight->ConstantAtten = 1.0f;
GLLight->LinearAtten = (1.0f / MAX(FSLight->rada, FSLight->radb)) * 1.25f;
GLLight->QuadraticAtten = (1.0f / MAX(FSLight->rada_squared, FSLight->radb_squared)) * 1.25f;
GLLight->Specular.xyzw.x *= static_tube_factor;
GLLight->Specular.xyzw.y *= static_tube_factor;
GLLight->Specular.xyzw.z *= static_tube_factor;
GLLight->Position.xyzw.x = FSLight->vec2.xyz.x; // Valathil: Use endpoint of tube as light position
GLLight->Position.xyzw.y = FSLight->vec2.xyz.y;
GLLight->Position.xyzw.z = FSLight->vec2.xyz.z;
GLLight->Position.xyzw.w = 1.0f;
// Valathil: When using shaders pass the beam direction (not normalized IMPORTANT for calculation of tube)
vec3d a;
vm_vec_sub(&a, &FSLight->vec2, &FSLight->vec);
GLLight->SpotDir.xyz.x = a.xyz.x;
GLLight->SpotDir.xyz.y = a.xyz.y;
GLLight->SpotDir.xyz.z = a.xyz.z;
GLLight->SpotCutOff = 90.0f; // Valathil: So shader dectects tube light
break;
}
case LT_DIRECTIONAL: {
GLLight->Position.xyzw.x = -FSLight->vec.xyz.x;
GLLight->Position.xyzw.y = -FSLight->vec.xyz.y;
GLLight->Position.xyzw.z = -FSLight->vec.xyz.z;
GLLight->Position.xyzw.w = 0.0f; // This is a direction so the w part must be 0
GLLight->Specular.xyzw.x *= static_light_factor;
GLLight->Specular.xyzw.y *= static_light_factor;
GLLight->Specular.xyzw.z *= static_light_factor;
break;
}
case LT_CONE:
break;
default:
Int3();
break;
}
}
static void set_light(int light_num, gr_light* ltp) {
Assert(light_num < (int)graphics::MAX_UNIFORM_LIGHTS);
vm_vec_transform(&gr_light_uniforms[light_num].position, &ltp->Position, &gr_view_matrix);
vm_vec_transform(&gr_light_uniforms[light_num].direction, &ltp->SpotDir, &gr_view_matrix, false);
gr_light_uniforms[light_num].diffuse_color = vm_vec4_to_vec3(ltp->Diffuse);
gr_light_uniforms[light_num].spec_color = vm_vec4_to_vec3(ltp->Specular);
gr_light_uniforms[light_num].light_type = ltp->type;
gr_light_uniforms[light_num].attenuation = ltp->LinearAtten;
}
static bool sort_active_lights(const gr_light& la, const gr_light& lb) {
// directional lights always go first
if ((la.type != LT_DIRECTIONAL) && (lb.type == LT_DIRECTIONAL)) {
return false;
} else if ((la.type == LT_DIRECTIONAL) && (lb.type != LT_DIRECTIONAL)) {
return true;
}
// tube lights go next, they are generally large and intense
if ((la.type != LT_TUBE) && (lb.type == LT_TUBE)) {
return false;
} else if ((la.type == LT_TUBE) && (lb.type != LT_TUBE)) {
return true;
}
// everything else is sorted by linear atten (light size)
// NOTE: smaller atten is larger light radius!
if (la.LinearAtten > lb.LinearAtten) {
return false;
} else if (la.LinearAtten < lb.LinearAtten) {
return true;
}
// as one extra check, if we're still here, go with overall brightness of light
float la_value = la.Diffuse.xyzw.x + la.Diffuse.xyzw.y + la.Diffuse.xyzw.z;
float lb_value = lb.Diffuse.xyzw.x + lb.Diffuse.xyzw.y + lb.Diffuse.xyzw.z;
if (la_value < lb_value) {
return false;
} else if (la_value > lb_value) {
return true;
}
// the two are equal
return false;
}
static void pre_render_init_lights() {
// sort the lights to try and get the most visible lights on the first pass
std::sort(gr_lights, gr_lights + Num_active_gr_lights, sort_active_lights);
}
void gr_set_light(light* fs_light) {
if (Num_active_gr_lights >= MAX_LIGHTS) {
return;
}
//if (fs_light->type == LT_POINT)
// return;
// init the light
FSLight2GLLight(fs_light, &gr_lights[Num_active_gr_lights]);
gr_lights[Num_active_gr_lights++].occupied = true;
}
void gr_set_center_alpha(int type) {
if (!type) {
return;
}
if (Num_active_gr_lights == MAX_LIGHTS) {
return;
}
gr_light glight;
vec3d dir;
vm_vec_sub(&dir, &Eye_position, &Object_position);
vm_vec_normalize(&dir);
if (type == 1) {
glight.Diffuse.xyzw.x = 0.0f;
glight.Diffuse.xyzw.y = 0.0f;
glight.Diffuse.xyzw.z = 0.0f;
glight.Ambient.xyzw.x = gr_screen.current_alpha;
glight.Ambient.xyzw.y = gr_screen.current_alpha;
glight.Ambient.xyzw.z = gr_screen.current_alpha;
} else {
glight.Diffuse.xyzw.x = gr_screen.current_alpha;
glight.Diffuse.xyzw.y = gr_screen.current_alpha;
glight.Diffuse.xyzw.z = gr_screen.current_alpha;
glight.Ambient.xyzw.x = 0.0f;
glight.Ambient.xyzw.y = 0.0f;
glight.Ambient.xyzw.z = 0.0f;
}
glight.type = type;
glight.Specular.xyzw.x = 0.0f;
glight.Specular.xyzw.y = 0.0f;
glight.Specular.xyzw.z = 0.0f;
glight.Specular.xyzw.w = 0.0f;
glight.Ambient.xyzw.w = 1.0f;
glight.Diffuse.xyzw.w = 1.0f;
glight.Position.xyzw.x = -dir.xyz.x;
glight.Position.xyzw.y = -dir.xyz.y;
glight.Position.xyzw.z = -dir.xyz.z;
glight.Position.xyzw.w = 0.0f;
// defaults
glight.SpotDir.xyz.x = 0.0f;
glight.SpotDir.xyz.y = 0.0f;
glight.SpotDir.xyz.z = -1.0f;
glight.SpotExp = Cmdline_ogl_spec * 0.5f;
glight.SpotCutOff = 180.0f;
glight.ConstantAtten = 1.0f;
glight.LinearAtten = 0.0f;
glight.QuadraticAtten = 0.0f;
glight.occupied = false;
// first light
memcpy(&gr_lights[Num_active_gr_lights], &glight, sizeof(gr_light));
gr_lights[Num_active_gr_lights++].occupied = true;
// second light
glight.Position.xyzw.x = dir.xyz.x;
glight.Position.xyzw.y = dir.xyz.y;
glight.Position.xyzw.z = dir.xyz.z;
memcpy(&gr_lights[Num_active_gr_lights], &glight, sizeof(gr_light));
gr_lights[Num_active_gr_lights++].occupied = true;
}
void gr_reset_lighting() {
int i;
for (i = 0; i < (int)graphics::MAX_UNIFORM_LIGHTS; i++) {
gr_lights[i].occupied = false;
}
Num_active_gr_lights = 0;
}
static void calculate_ambient_factor() {
float amb_user = 0.0f;
// assuming that the default is "128", just skip this if not a user setting
if (Cmdline_ambient_factor == 128) {
return;
}
amb_user = (float) ((Cmdline_ambient_factor * 2) - 255) / 255.0f;
// set the ambient light
gr_light_ambient[0] += amb_user;
gr_light_ambient[1] += amb_user;
gr_light_ambient[2] += amb_user;
CLAMP(gr_light_ambient[0], 0.02f, 1.0f);
CLAMP(gr_light_ambient[1], 0.02f, 1.0f);
CLAMP(gr_light_ambient[2], 0.02f, 1.0f);
gr_light_ambient[3] = 1.0f;
}
void gr_light_shutdown() {
if (gr_lights != NULL) {
vm_free(gr_lights);
gr_lights = NULL;
}
}
void gr_light_init() {
calculate_ambient_factor();
// allocate memory for enabled lights
if (gr_lights == NULL) {
gr_lights = (gr_light*) vm_malloc(MAX_LIGHTS * sizeof(gr_light), memory::quiet_alloc);
}
if (gr_lights == NULL) {
Error(LOCATION, "Unable to allocate memory for lights!\n");
}
memset(gr_lights, 0, MAX_LIGHTS * sizeof(gr_light));
}
void gr_set_lighting(bool set, bool state) {
if (!state) {
return;
}
//Valathil: Sort lights by priority
extern bool Deferred_lighting;
if (!Deferred_lighting) {
pre_render_init_lights();
}
int i = 0;
for (i = 0; i < (int)graphics::MAX_UNIFORM_LIGHTS; i++) {
if (i >= Num_active_gr_lights) {
break;
}
if (gr_lights[i].occupied) {
set_light(i, &gr_lights[i]);
}
}
gr_light zero;
memset(&zero, 0, sizeof(gr_light));
zero.Position.xyzw.x = 1.0f;
// make sure that we turn off any lights that we aren't using right now
for (; i < (int)graphics::MAX_UNIFORM_LIGHTS; i++) {
set_light(i, &zero);
}
}
void gr_set_ambient_light(int red, int green, int blue) {
gr_light_ambient[0] = i2fl(red) / 255.0f;
gr_light_ambient[1] = i2fl(green) / 255.0f;
gr_light_ambient[2] = i2fl(blue) / 255.0f;
gr_light_ambient[3] = 1.0f;
calculate_ambient_factor();
}
-27
View File
@@ -1,27 +0,0 @@
#pragma once
#include "globalincs/pstypes.h"
#include "lighting/lighting.h"
#include "graphics/util/uniform_structs.h"
//Variables
extern graphics::model_light gr_light_uniforms[graphics::MAX_UNIFORM_LIGHTS];
//Variables
extern int Num_active_gr_lights;
extern const float gr_light_color[4];
extern const float gr_light_zero[4];
extern const float gr_light_emission[4];
extern float gr_light_ambient[4];
//Functions
void gr_set_light(light *fs_light);
void gr_reset_lighting();
void gr_set_lighting(bool set, bool state);
void gr_set_center_alpha(int type);
void gr_set_ambient_light(int red, int green, int blue);
void gr_light_init();
void gr_light_shutdown();
+35 -151
View File
@@ -124,42 +124,8 @@ void material_set_distortion(distortion_material *mat_info, int texture, bool th
mat_info->set_color(1.0f, 1.0f, 1.0f, 1.0f);
}
void material_set_movie(movie_material* mat_info, int y_bm, int u_bm, int v_bm) {
mat_info->set_depth_mode(ZBUFFER_TYPE_NONE);
mat_info->set_blend_mode(ALPHA_BLEND_ALPHA_BLEND_ALPHA);
mat_info->set_cull_mode(false);
mat_info->set_color(1.0f, 1.0f, 1.0f, 1.0f);
mat_info->setYtex(y_bm);
mat_info->setUtex(u_bm);
mat_info->setVtex(v_bm);
mat_info->set_texture_type(material::TEX_TYPE_AABITMAP);
}
void material_set_batched_bitmap(batched_bitmap_material* mat_info, int base_tex, float alpha, float color_scale) {
material_set_unlit(mat_info, base_tex, alpha, true, true);
mat_info->set_color_scale(color_scale);
}
void material_set_nanovg(nanovg_material* mat_info, int base_tex) {
material_set_unlit(mat_info, base_tex, 1.0f, true, false);
mat_info->set_cull_mode(false);
mat_info->set_color_mask(true, true, true, true);
mat_info->set_blend_mode(ALPHA_BLEND_PREMULTIPLIED);
mat_info->set_stencil_mask(0xFFFFFFFF);
mat_info->set_stencil_func(ComparisionFunction::Always, 0, 0xFFFFFFFF);
mat_info->set_front_stencil_op(StencilOperation::Keep, StencilOperation::Keep, StencilOperation::Keep);
mat_info->set_back_stencil_op(StencilOperation::Keep, StencilOperation::Keep, StencilOperation::Keep);
}
material::material():
Sdr_type(SDR_TYPE_DEFAULT_MATERIAL),
Sdr_type(SDR_TYPE_PASSTHROUGH_RENDER),
Tex_type(TEX_TYPE_NORMAL),
Texture_addressing(TMAP_ADDRESS_WRAP),
Depth_mode(ZBUFFER_TYPE_NONE),
@@ -192,10 +158,7 @@ Depth_bias(0)
Clip_params.enabled = false;
Color_mask.x = true;
Color_mask.y = true;
Color_mask.z = true;
Color_mask.w = true;
};
void material::set_shader_type(shader_type init_sdr_type)
@@ -203,12 +166,12 @@ void material::set_shader_type(shader_type init_sdr_type)
Sdr_type = init_sdr_type;
}
uint material::get_shader_flags() const
uint material::get_shader_flags()
{
return 0;
}
int material::get_shader_handle() const
int material::get_shader_handle()
{
return gr_maybe_create_shader(Sdr_type, get_shader_flags());
}
@@ -220,14 +183,14 @@ void material::set_texture_map(int tex_type, int texture_num)
Texture_maps[tex_type] = texture_num;
}
int material::get_texture_map(int tex_type) const
int material::get_texture_map(int tex_type)
{
Assert(tex_type > -1 && tex_type < TM_NUM_TYPES);
return Texture_maps[tex_type];
}
bool material::is_textured() const
bool material::is_textured()
{
return
Texture_maps[TM_BASE_TYPE] > -1 ||
@@ -243,7 +206,7 @@ void material::set_texture_type(texture_type t_type)
Tex_type = t_type;
}
int material::get_texture_type() const
int material::get_texture_type()
{
switch ( Tex_type ) {
default:
@@ -258,7 +221,7 @@ int material::get_texture_type() const
}
}
bool material::is_clipped() const
bool material::is_clipped()
{
return Clip_params.enabled;
}
@@ -275,7 +238,7 @@ void material::set_clip_plane()
Clip_params.enabled = false;
}
const material::clip_plane& material::get_clip_plane() const
material::clip_plane& material::get_clip_plane()
{
return Clip_params;
}
@@ -285,7 +248,7 @@ void material::set_texture_addressing(int addressing)
Texture_addressing = addressing;
}
int material::get_texture_addressing() const
int material::get_texture_addressing()
{
return Texture_addressing;
}
@@ -305,12 +268,12 @@ void material::set_fog()
Fog_params.enabled = false;
}
bool material::is_fogged() const
bool material::is_fogged()
{
return Fog_params.enabled;
}
const material::fog& material::get_fog() const
material::fog& material::get_fog()
{
return Fog_params;
}
@@ -320,7 +283,7 @@ void material::set_depth_mode(gr_zbuffer_type mode)
Depth_mode = mode;
}
gr_zbuffer_type material::get_depth_mode() const
gr_zbuffer_type material::get_depth_mode()
{
return Depth_mode;
}
@@ -330,7 +293,7 @@ void material::set_cull_mode(bool mode)
Cull_mode = mode;
}
bool material::get_cull_mode() const
bool material::get_cull_mode()
{
return Cull_mode;
}
@@ -340,7 +303,7 @@ void material::set_fill_mode(int mode)
Fill_mode = mode;
}
int material::get_fill_mode() const
int material::get_fill_mode()
{
return Fill_mode;
}
@@ -350,7 +313,7 @@ void material::set_blend_mode(gr_alpha_blend mode)
Blend_mode = mode;
}
gr_alpha_blend material::get_blend_mode() const
gr_alpha_blend material::get_blend_mode()
{
return Blend_mode;
}
@@ -360,7 +323,7 @@ void material::set_depth_bias(int bias)
Depth_bias = bias;
}
int material::get_depth_bias() const
int material::get_depth_bias()
{
return Depth_bias;
}
@@ -401,7 +364,7 @@ void material::set_color(color &clr_in)
}
}
const vec4& material::get_color() const
const vec4& material::get_color()
{
return Clr;
}
@@ -411,59 +374,10 @@ void material::set_color_scale(float scale)
Clr_scale = scale;
}
float material::get_color_scale() const
float material::get_color_scale()
{
return Clr_scale;
}
void material::set_stencil_test(bool stencil) {
Stencil_test = stencil;
}
bool material::is_stencil_enabled() const {
return Stencil_test;
}
void material::set_stencil_mask(uint32_t mask) {
Stencil_mask = mask;
}
uint32_t material::get_stencil_mask() const {
return Stencil_mask;
}
void material::set_stencil_func(ComparisionFunction compare, int ref, uint32_t mask) {
Stencil_func.compare = compare;
Stencil_func.ref = ref;
Stencil_func.mask = mask;
}
const material::StencilFunc& material::get_stencil_func() const {
return Stencil_func;
}
void material::set_front_stencil_op(StencilOperation stencilFailOperation,
StencilOperation depthFailOperation,
StencilOperation successOperation) {
Front_stencil_op.stencilFailOperation = stencilFailOperation;
Front_stencil_op.depthFailOperation = depthFailOperation;
Front_stencil_op.successOperation = successOperation;
}
const material::StencilOp& material::get_front_stencil_op() const {
return Front_stencil_op;
}
void material::set_back_stencil_op(StencilOperation stencilFailOperation,
StencilOperation depthFailOperation,
StencilOperation successOperation) {
Back_stencil_op.stencilFailOperation = stencilFailOperation;
Back_stencil_op.depthFailOperation = depthFailOperation;
Back_stencil_op.successOperation = successOperation;
}
const material::StencilOp& material::get_back_stencil_op() const {
return Back_stencil_op;
}
void material::set_color_mask(bool red, bool green, bool blue, bool alpha) {
Color_mask.x = red;
Color_mask.y = green;
Color_mask.z = blue;
Color_mask.w = alpha;
}
const bvec4& material::get_color_mask() const {
return Color_mask;
}
model_material::model_material() : material() {
set_shader_type(SDR_TYPE_MODEL);
@@ -474,7 +388,7 @@ void model_material::set_desaturation(bool enabled)
Desaturate = enabled;
}
bool model_material::is_desaturated() const
bool model_material::is_desaturated()
{
return Desaturate;
}
@@ -489,7 +403,7 @@ void model_material::set_light_factor(float factor)
Light_factor = factor;
}
float model_material::get_light_factor() const
float model_material::get_light_factor()
{
return Light_factor;
}
@@ -499,7 +413,7 @@ void model_material::set_lighting(bool mode)
lighting = mode;
}
bool model_material::is_lit() const
bool model_material::is_lit()
{
return lighting;
}
@@ -519,7 +433,7 @@ void model_material::set_center_alpha(int c_alpha)
Center_alpha = c_alpha;
}
int model_material::get_center_alpha() const
int model_material::get_center_alpha()
{
return Center_alpha;
}
@@ -529,7 +443,7 @@ void model_material::set_thrust_scale(float scale)
Thrust_scale = scale;
}
float model_material::get_thrust_scale() const
float model_material::get_thrust_scale()
{
return Thrust_scale;
}
@@ -545,7 +459,7 @@ void model_material::set_team_color()
Team_color_set = false;
}
const team_color& model_material::get_team_color() const
team_color& model_material::get_team_color()
{
return Tm_color;
}
@@ -562,12 +476,12 @@ void model_material::set_animated_effect()
Animated_timer = 0.0f;
}
int model_material::get_animated_effect() const
int model_material::get_animated_effect()
{
return Animated_effect;
}
float model_material::get_animated_effect_time() const
float model_material::get_animated_effect_time()
{
return Animated_timer;
}
@@ -577,7 +491,7 @@ void model_material::set_batching(bool enabled)
Batched = enabled;
}
bool model_material::is_batched() const
bool model_material::is_batched()
{
return Batched;
}
@@ -594,17 +508,17 @@ void model_material::set_normal_alpha()
Normal_alpha = false;
}
bool model_material::is_normal_alpha_active() const
bool model_material::is_normal_alpha_active()
{
return Normal_alpha;
}
float model_material::get_normal_alpha_min() const
float model_material::get_normal_alpha_min()
{
return Normal_alpha_min;
}
float model_material::get_normal_alpha_max() const
float model_material::get_normal_alpha_max()
{
return Normal_alpha_max;
}
@@ -620,17 +534,17 @@ void model_material::set_normal_extrude()
Normal_extrude = false;
}
bool model_material::is_normal_extrude_active() const
bool model_material::is_normal_extrude_active()
{
return Normal_extrude;
}
float model_material::get_normal_extrude_width() const
float model_material::get_normal_extrude_width()
{
return Normal_extrude_width;
}
uint model_material::get_shader_flags() const
uint model_material::get_shader_flags()
{
uint Shader_flags = 0;
@@ -740,7 +654,7 @@ bool particle_material::get_point_sprite_mode()
return Point_sprite;
}
uint particle_material::get_shader_flags() const
uint particle_material::get_shader_flags()
{
uint flags = 0;
@@ -806,33 +720,3 @@ float shield_material::get_impact_radius()
{
return Impact_radius;
}
movie_material::movie_material() : material() {
set_shader_type(SDR_TYPE_VIDEO_PROCESS);
}
int movie_material::getYtex() const {
return Ytex;
}
int movie_material::getUtex() const {
return Utex;
}
int movie_material::getVtex() const {
return Vtex;
}
void movie_material::setYtex(int _Ytex) {
this->Ytex = _Ytex;
}
void movie_material::setUtex(int _Utex) {
this->Utex = _Utex;
}
void movie_material::setVtex(int _Vtex) {
movie_material::Vtex = _Vtex;
}
batched_bitmap_material::batched_bitmap_material() {
set_shader_type(SDR_TYPE_BATCHED_BITMAP);
}
nanovg_material::nanovg_material() {
set_shader_type(SDR_TYPE_NANOVG);
}
+34 -127
View File
@@ -4,29 +4,6 @@
#include "graphics/grinternal.h"
#include "model/model.h"
enum class ComparisionFunction
{
Never,
Always,
Less,
Greater,
Equal,
NotEqual,
LessOrEqual,
GreaterOrEqual
};
enum class StencilOperation {
Keep,
Zero,
Replace,
Increment,
IncrementWrap,
Decrement,
DecrementWrap,
Invert
};
class material
{
public:
@@ -54,18 +31,6 @@ public:
TEX_TYPE_INTERFACE
};
struct StencilFunc {
ComparisionFunction compare = ComparisionFunction::Always;
int ref = 1;
uint32_t mask = 0xFFFFFFFF;
};
struct StencilOp {
StencilOperation stencilFailOperation = StencilOperation::Keep;
StencilOperation depthFailOperation = StencilOperation::Keep;
StencilOperation successOperation = StencilOperation::Keep;
};
private:
shader_type Sdr_type;
@@ -82,85 +47,57 @@ private:
vec4 Clr;
float Clr_scale;
int Depth_bias;
bvec4 Color_mask;
bool Stencil_test = false;
uint32_t Stencil_mask = 0xFF;
StencilFunc Stencil_func;
StencilOp Front_stencil_op;
StencilOp Back_stencil_op;
protected:
void set_shader_type(shader_type init_sdr_type = SDR_TYPE_NONE);
public:
material();
int get_shader_handle() const;
virtual uint get_shader_flags() const;
int get_shader_handle();
virtual uint get_shader_flags();
void set_texture_map(int tex_type, int texture_num);
int get_texture_map(int tex_type) const;
bool is_textured() const;
int get_texture_map(int tex_type);
bool is_textured();
void set_texture_type(texture_type t_type);
int get_texture_type() const;
int get_texture_type();
bool is_clipped() const;
bool is_clipped();
void set_clip_plane(const vec3d &normal, const vec3d &position);
void set_clip_plane();
const clip_plane& get_clip_plane() const;
clip_plane& get_clip_plane();
void set_texture_addressing(int addressing);
int get_texture_addressing() const;
int get_texture_addressing();
void set_fog(int r, int g, int b, float near, float far);
void set_fog();
bool is_fogged() const;
const fog& get_fog() const;
bool is_fogged();
fog& get_fog();
void set_depth_mode(gr_zbuffer_type mode);
gr_zbuffer_type get_depth_mode() const;
gr_zbuffer_type get_depth_mode();
void set_cull_mode(bool mode);
bool get_cull_mode() const;
bool get_cull_mode();
void set_fill_mode(int mode);
int get_fill_mode() const;
void set_color_mask(bool red, bool green, bool blue, bool alpha);
const bvec4& get_color_mask() const;
int get_fill_mode();
void set_blend_mode(gr_alpha_blend mode);
gr_alpha_blend get_blend_mode() const;
gr_alpha_blend get_blend_mode();
void set_depth_bias(int bias);
int get_depth_bias() const;
int get_depth_bias();
void set_color(float red, float green, float blue, float alpha);
void set_color(int r, int g, int b, int a);
void set_color(color &clr_in);
const vec4& get_color() const;
const vec4& get_color();
void set_color_scale(float scale);
float get_color_scale() const;
void set_stencil_test(bool stencil);
bool is_stencil_enabled() const;
void set_stencil_mask(uint32_t mask);
uint32_t get_stencil_mask() const;
void set_stencil_func(ComparisionFunction compare, int ref, uint32_t mask);
const StencilFunc& get_stencil_func() const;
void set_front_stencil_op(StencilOperation stencilFailOperation,
StencilOperation depthFailOperation,
StencilOperation successOperation);
const StencilOp& get_front_stencil_op() const;
void set_back_stencil_op(StencilOperation stencilFailOperation,
StencilOperation depthFailOperation,
StencilOperation successOperation);
const StencilOp& get_back_stencil_op() const;
float get_color_scale();
};
class model_material : public material
@@ -196,50 +133,50 @@ public:
model_material();
void set_desaturation(bool enabled);
bool is_desaturated() const;
bool is_desaturated();
void set_shadow_casting(bool enabled);
bool is_shadow_casting() const;
bool is_shadow_casting();
void set_light_factor(float factor);
float get_light_factor() const;
float get_light_factor();
void set_lighting(bool mode);
bool is_lit() const;
bool is_lit();
void set_deferred_lighting(bool enabled);
void set_high_dynamic_range(bool enabled);
void set_center_alpha(int center_alpha);
int get_center_alpha() const;
int get_center_alpha();
void set_thrust_scale(float scale = -1.0f);
float get_thrust_scale() const;
float get_thrust_scale();
void set_team_color(const team_color &Team_clr);
void set_team_color();
const team_color& get_team_color() const;
team_color& get_team_color();
void set_animated_effect(int effect, float time);
void set_animated_effect();
int get_animated_effect() const;
float get_animated_effect_time() const;
int get_animated_effect();
float get_animated_effect_time();
void set_normal_alpha(float min, float max);
void set_normal_alpha();
bool is_normal_alpha_active() const;
float get_normal_alpha_min() const;
float get_normal_alpha_max() const;
bool is_normal_alpha_active();
float get_normal_alpha_min();
float get_normal_alpha_max();
void set_normal_extrude(float width);
void set_normal_extrude();
bool is_normal_extrude_active() const;
float get_normal_extrude_width() const;
bool is_normal_extrude_active();
float get_normal_extrude_width();
void set_batching(bool enabled);
bool is_batched() const;
bool is_batched();
virtual uint get_shader_flags() const override;
virtual uint get_shader_flags();
};
class particle_material : public material
@@ -251,7 +188,7 @@ public:
void set_point_sprite_mode(bool enabled);
bool get_point_sprite_mode();
uint get_shader_flags() const override;
virtual uint get_shader_flags();
};
class distortion_material: public material
@@ -280,33 +217,6 @@ public:
float get_impact_radius();
};
class movie_material : public material {
int Ytex = -1;
int Utex = -1;
int Vtex = -1;
public:
movie_material();
int getYtex() const;
int getUtex() const;
int getVtex() const;
void setYtex(int _Ytex);
void setUtex(int _Utex);
void setVtex(int _Vtex);
};
class batched_bitmap_material : public material
{
public:
batched_bitmap_material();
};
class nanovg_material : public material {
public:
nanovg_material();
};
gr_alpha_blend material_determine_blend_mode(int base_bitmap, bool is_transparent);
gr_zbuffer_type material_determine_depth_mode(bool depth_testing, bool is_transparent);
@@ -317,8 +227,5 @@ void material_set_unlit_color(material* mat_info, int texture, color *clr, bool
void material_set_unlit_color(material* mat_info, int texture, color *clr, float alpha, bool blending, bool depth_testing);
void material_set_unlit_volume(particle_material* mat_info, int texture, bool point_sprites);
void material_set_distortion(distortion_material *mat_info, int texture, bool thruster);
void material_set_movie(movie_material *mat_info, int y_bm, int u_bm, int v_bm);
void material_set_batched_bitmap(batched_bitmap_material* mat_info, int base_tex, float alpha, float color_scale);
void material_set_nanovg(nanovg_material* mat_info, int base_tex);
#endif
-323
View File
@@ -1,323 +0,0 @@
#include "matrix.h"
transform_stack gr_model_matrix_stack;
matrix4 gr_view_matrix;
matrix4 gr_model_view_matrix;
matrix4 gr_projection_matrix;
matrix4 gr_last_projection_matrix;
matrix4 gr_last_view_matrix;
matrix4 gr_texture_matrix;
matrix4 gr_env_texture_matrix;
static bool gr_env_texture_matrix_set = false;
bool gr_htl_projection_matrix_set = false;
static int modelview_matrix_depth = 1;
static bool htl_view_matrix_set = false;
static int htl_2d_matrix_depth = 0;
static bool htl_2d_matrix_set = false;
static matrix4 create_view_matrix(const vec3d *pos, const matrix *orient)
{
vec3d scaled_pos;
vec3d inv_pos;
matrix scaled_orient = *orient;
matrix inv_orient;
vm_vec_copy_scale(&scaled_pos, pos, -1.0f);
vm_vec_scale(&scaled_orient.vec.fvec, -1.0f);
vm_copy_transpose(&inv_orient, &scaled_orient);
vm_vec_rotate(&inv_pos, &scaled_pos, &scaled_orient);
matrix4 out;
vm_matrix4_set_transform(&out, &inv_orient, &inv_pos);
return out;
}
static void create_perspective_projection_matrix(matrix4 *out, float left, float right, float bottom, float top, float near_dist, float far_dist)
{
memset(out, 0, sizeof(matrix4));
out->a1d[0] = 2.0f * near_dist / (right - left);
out->a1d[5] = 2.0f * near_dist / (top - bottom);
out->a1d[8] = (right + left) / (right - left);
out->a1d[9] = (top + bottom) / (top - bottom);
out->a1d[10] = -(far_dist + near_dist) / (far_dist - near_dist);
out->a1d[11] = -1.0f;
out->a1d[14] = -2.0f * far_dist * near_dist / (far_dist - near_dist);
}
static void create_orthographic_projection_matrix(matrix4* out, float left, float right, float bottom, float top, float near_dist, float far_dist)
{
memset(out, 0, sizeof(matrix4));
out->a1d[0] = 2.0f / (right - left);
out->a1d[5] = 2.0f / (top - bottom);
out->a1d[10] = -2.0f / (far_dist - near_dist);
out->a1d[12] = -(right + left) / (right - left);
out->a1d[13] = -(top + bottom) / (top - bottom);
out->a1d[14] = -(far_dist + near_dist) / (far_dist - near_dist);
out->a1d[15] = 1.0f;
}
void gr_start_instance_matrix(const vec3d *offset, const matrix *rotation)
{
Assert( htl_view_matrix_set );
if (offset == NULL) {
offset = &vmd_zero_vector;
}
if (rotation == NULL) {
rotation = &vmd_identity_matrix;
}
gr_model_matrix_stack.push(offset, rotation);
auto model_matrix = gr_model_matrix_stack.get_transform();
vm_matrix4_x_matrix4(&gr_model_view_matrix, &gr_view_matrix, &model_matrix);
modelview_matrix_depth++;
}
void gr_start_angles_instance_matrix(const vec3d *pos, const angles *rotation)
{
Assert(htl_view_matrix_set);
matrix m;
vm_angles_2_matrix(&m, rotation);
gr_start_instance_matrix(pos, &m);
}
void gr_end_instance_matrix()
{
Assert(htl_view_matrix_set);
gr_model_matrix_stack.pop();
auto model_matrix = gr_model_matrix_stack.get_transform();
vm_matrix4_x_matrix4(&gr_model_view_matrix, &gr_view_matrix, &model_matrix);
modelview_matrix_depth--;
}
// the projection matrix; fov, aspect ratio, near, far
void gr_set_proj_matrix(float fov, float aspect, float z_near, float z_far) {
if (gr_screen.rendering_to_texture != -1) {
gr_set_viewport(gr_screen.offset_x, gr_screen.offset_y, gr_screen.clip_width, gr_screen.clip_height);
} else {
gr_set_viewport(gr_screen.offset_x, (gr_screen.max_h - gr_screen.offset_y - gr_screen.clip_height), gr_screen.clip_width, gr_screen.clip_height);
}
float clip_width, clip_height;
clip_height = tan( fov * 0.5f ) * z_near;
clip_width = clip_height * aspect;
gr_last_projection_matrix = gr_projection_matrix;
if (gr_screen.rendering_to_texture != -1) {
create_perspective_projection_matrix(&gr_projection_matrix, -clip_width, clip_width, clip_height, -clip_height, z_near, z_far);
} else {
create_perspective_projection_matrix(&gr_projection_matrix, -clip_width, clip_width, -clip_height, clip_height, z_near, z_far);
}
gr_htl_projection_matrix_set = true;
}
void gr_end_proj_matrix() {
gr_set_viewport(0, 0, gr_screen.max_w, gr_screen.max_h);
gr_last_projection_matrix = gr_projection_matrix;
// the top and bottom positions are reversed on purpose, but RTT needs them the other way
if (gr_screen.rendering_to_texture != -1) {
create_orthographic_projection_matrix(&gr_projection_matrix, 0.0f, i2fl(gr_screen.max_w), 0.0f, i2fl(gr_screen.max_h), -1.0f, 1.0f);
} else {
create_orthographic_projection_matrix(&gr_projection_matrix, 0.0f, i2fl(gr_screen.max_w), i2fl(gr_screen.max_h), 0.0f, -1.0f, 1.0f);
}
gr_htl_projection_matrix_set = false;
}
void gr_set_view_matrix(const vec3d *pos, const matrix *orient)
{
Assert(modelview_matrix_depth == 1);
gr_view_matrix = create_view_matrix(pos, orient);
gr_model_matrix_stack.clear();
gr_model_view_matrix = gr_view_matrix;
if (Cmdline_env) {
gr_env_texture_matrix_set = true;
// setup the texture matrix which will make the the envmap keep lined
// up properly with the environment
// r.xyz <-- r.x, u.x, f.x
gr_env_texture_matrix.a1d[0] = gr_model_view_matrix.a1d[0];
gr_env_texture_matrix.a1d[1] = gr_model_view_matrix.a1d[4];
gr_env_texture_matrix.a1d[2] = gr_model_view_matrix.a1d[8];
// u.xyz <-- r.y, u.y, f.y
gr_env_texture_matrix.a1d[4] = gr_model_view_matrix.a1d[1];
gr_env_texture_matrix.a1d[5] = gr_model_view_matrix.a1d[5];
gr_env_texture_matrix.a1d[6] = gr_model_view_matrix.a1d[9];
// f.xyz <-- r.z, u.z, f.z
gr_env_texture_matrix.a1d[8] = gr_model_view_matrix.a1d[2];
gr_env_texture_matrix.a1d[9] = gr_model_view_matrix.a1d[6];
gr_env_texture_matrix.a1d[10] = gr_model_view_matrix.a1d[10];
gr_env_texture_matrix.a1d[15] = 1.0f;
}
modelview_matrix_depth = 2;
htl_view_matrix_set = true;
}
void gr_end_view_matrix()
{
Assert(modelview_matrix_depth == 2);
gr_model_matrix_stack.clear();
vm_matrix4_set_identity(&gr_view_matrix);
vm_matrix4_set_identity(&gr_model_view_matrix);
modelview_matrix_depth = 1;
htl_view_matrix_set = false;
gr_env_texture_matrix_set = false;
}
// set a view and projection matrix for a 2D element
// TODO: this probably needs to accept values
void gr_set_2d_matrix(/*int x, int y, int w, int h*/)
{
// don't bother with this if we aren't even going to need it
if (!gr_htl_projection_matrix_set) {
return;
}
Assert( htl_2d_matrix_set == 0 );
Assert( htl_2d_matrix_depth == 0 );
// the viewport needs to be the full screen size since glOrtho() is relative to it
gr_set_viewport(0, 0, gr_screen.max_w, gr_screen.max_h);
gr_last_projection_matrix = gr_projection_matrix;
// the top and bottom positions are reversed on purpose, but RTT needs them the other way
if (gr_screen.rendering_to_texture != -1) {
create_orthographic_projection_matrix(&gr_projection_matrix, 0, i2fl(gr_screen.max_w), 0, i2fl(gr_screen.max_h), -1, 1);
} else {
create_orthographic_projection_matrix(&gr_projection_matrix, 0, i2fl(gr_screen.max_w), i2fl(gr_screen.max_h), 0, -1, 1);
}
matrix4 identity_mat;
vm_matrix4_set_identity(&identity_mat);
gr_model_matrix_stack.push_and_replace(identity_mat);
gr_last_view_matrix = gr_view_matrix;
gr_view_matrix = identity_mat;
vm_matrix4_x_matrix4(&gr_model_view_matrix, &gr_view_matrix, &identity_mat);
htl_2d_matrix_set = true;
htl_2d_matrix_depth++;
}
// ends a previously set 2d view and projection matrix
void gr_end_2d_matrix()
{
if (!htl_2d_matrix_set)
return;
Assert( htl_2d_matrix_depth == 1 );
// reset viewport to what it was originally set to by the proj matrix
gr_set_viewport(gr_screen.offset_x, (gr_screen.max_h - gr_screen.offset_y - gr_screen.clip_height), gr_screen.clip_width, gr_screen.clip_height);
gr_projection_matrix = gr_last_projection_matrix;
gr_model_matrix_stack.pop();
gr_view_matrix = gr_last_view_matrix;
auto model_matrix = gr_model_matrix_stack.get_transform();
vm_matrix4_x_matrix4(&gr_model_view_matrix, &gr_view_matrix, &model_matrix);
htl_2d_matrix_set = false;
htl_2d_matrix_depth = 0;
}
static bool scale_matrix_set = false;
void gr_push_scale_matrix(const vec3d *scale_factor)
{
if ( (scale_factor->xyz.x == 1) && (scale_factor->xyz.y == 1) && (scale_factor->xyz.z == 1) )
return;
scale_matrix_set = true;
modelview_matrix_depth++;
gr_model_matrix_stack.push(NULL, NULL, scale_factor);
auto model_matrix = gr_model_matrix_stack.get_transform();
vm_matrix4_x_matrix4(&gr_model_view_matrix, &gr_view_matrix, &model_matrix);
}
void gr_pop_scale_matrix()
{
if (!scale_matrix_set)
return;
gr_model_matrix_stack.pop();
auto model_matrix = gr_model_matrix_stack.get_transform();
vm_matrix4_x_matrix4(&gr_model_view_matrix, &gr_view_matrix, &model_matrix);
modelview_matrix_depth--;
scale_matrix_set = false;
}
void gr_setup_viewport() {
if (Gr_inited) {
// This may be called by FRED before the gr system is actually initialized so we need to make sure that
// this function call is actually valid at this point.
gr_set_viewport(0, 0, gr_screen.max_w, gr_screen.max_h);
}
gr_last_projection_matrix = gr_projection_matrix;
// the top and bottom positions are reversed on purpose, but RTT needs them the other way
if (gr_screen.rendering_to_texture != -1) {
create_orthographic_projection_matrix(&gr_projection_matrix, 0, i2fl(gr_screen.max_w), 0, i2fl(gr_screen.max_h), -1, 1);
} else {
create_orthographic_projection_matrix(&gr_projection_matrix, 0, i2fl(gr_screen.max_w), i2fl(gr_screen.max_h), 0, -1, 1);
}
}
void gr_reset_matrices() {
vm_matrix4_set_identity(&gr_projection_matrix);
vm_matrix4_set_identity(&gr_last_projection_matrix);
vm_matrix4_set_identity(&gr_view_matrix);
vm_matrix4_set_identity(&gr_last_view_matrix);
vm_matrix4_set_identity(&gr_model_view_matrix);
gr_model_matrix_stack.clear();
vm_matrix4_set_identity(&gr_texture_matrix);
}
void gr_set_texture_panning(float u, float v, bool enable) {
vm_matrix4_set_identity(&gr_texture_matrix);
if (enable) {
gr_texture_matrix.a2d[3][0] = u;
gr_texture_matrix.a2d[3][1] = v;
}
}
-34
View File
@@ -1,34 +0,0 @@
#pragma once
#include "graphics/2d.h"
extern transform_stack gr_model_matrix_stack;
extern matrix4 gr_view_matrix;
extern matrix4 gr_model_view_matrix;
extern matrix4 gr_projection_matrix;
extern matrix4 gr_last_projection_matrix;
extern matrix4 gr_env_texture_matrix;
void gr_start_instance_matrix(const vec3d *offset, const matrix *rotation);
void gr_start_angles_instance_matrix(const vec3d *pos, const angles *rotation);
void gr_end_instance_matrix();
void gr_set_proj_matrix(float fov, float aspect, float z_near, float z_far);
void gr_end_proj_matrix();
void gr_set_view_matrix(const vec3d *pos, const matrix *orient);
void gr_end_view_matrix();
void gr_set_2d_matrix(/*int x, int y, int w, int h*/);
void gr_end_2d_matrix();
void gr_push_scale_matrix(const vec3d *scale_factor);
void gr_pop_scale_matrix();
void gr_setup_viewport();
void gr_reset_matrices();
extern matrix4 gr_texture_matrix;
void gr_set_texture_panning(float u, float v, bool enable);
+19 -15
View File
@@ -193,7 +193,7 @@ void opengl::ShaderProgram::linkProgram() {
freeCompiledShaders();
}
void opengl::ShaderProgram::initAttribute(const SCP_string& name, opengl_vert_attrib::attrib_id attr_id, const vec4& default_value)
void opengl::ShaderProgram::initAttribute(const SCP_string& name, const vec4& default_value)
{
auto attrib_loc = glGetAttribLocation(_program_id, name.c_str());
@@ -203,7 +203,7 @@ void opengl::ShaderProgram::initAttribute(const SCP_string& name, opengl_vert_at
return;
}
_attribute_locations.insert(std::make_pair(attr_id, attrib_loc));
_attribute_locations.insert(std::make_pair(name, attrib_loc));
// The shader needs to be in use before glVertexAttrib can be used
use();
@@ -215,8 +215,8 @@ void opengl::ShaderProgram::initAttribute(const SCP_string& name, opengl_vert_at
default_value.xyzw.w
);
}
GLint opengl::ShaderProgram::getAttributeLocation(opengl_vert_attrib::attrib_id attribute) {
auto iter = _attribute_locations.find(attribute);
GLint opengl::ShaderProgram::getAttributeLocation(const SCP_string& name) {
auto iter = _attribute_locations.find(name);
if (iter == _attribute_locations.end()) {
return -1;
} else {
@@ -228,6 +228,20 @@ opengl::ShaderUniforms::ShaderUniforms(ShaderProgram* shaderProgram) : _program(
Assertion(shaderProgram != nullptr, "Shader program may not be null!");
}
void opengl::ShaderUniforms::initUniform(const SCP_string& name)
{
auto location = glGetUniformLocation(_program->getShaderHandle(), name.c_str());
if (location == -1)
{
// This can happen if the uniform has been optimized out by the driver
mprintf(("WARNING: Failed to find uniform '%s'.\n", name.c_str()));
return;
}
_uniform_locations.insert(std::make_pair(name, location));
}
size_t opengl::ShaderUniforms::findUniform(const SCP_string& name)
{
auto iter = _uniform_lookup.find(name);
@@ -800,17 +814,7 @@ GLint opengl::ShaderUniforms::findUniformLocation(const SCP_string& name) {
auto iter = _uniform_locations.find(name);
if (iter == _uniform_locations.end()) {
// Lazily initialize the uniform locations when required. This avoids keeping a list of all uniforms in the code
auto location = glGetUniformLocation(_program->getShaderHandle(), name.c_str());
if (location == -1)
{
// This can happen if the uniform has been optimized out by the driver
mprintf(("WARNING: Failed to find uniform '%s'.\n", name.c_str()));
}
_uniform_locations.insert(std::make_pair(name, location));
return location;
return -1;
}
else {
return iter->second;
+5 -4
View File
@@ -4,7 +4,6 @@
#pragma once
#include "globalincs/pstypes.h"
#include "gropenglshader.h"
#include <glad/glad.h>
@@ -52,6 +51,8 @@ class ShaderUniforms {
public:
explicit ShaderUniforms(ShaderProgram* shaderProgram);
void initUniform(const SCP_string& name);
void setUniformi(const SCP_string &name, const int value);
void setUniform1iv(const SCP_string &name, const int count, const int *val);
void setUniformf(const SCP_string &name, const float value);
@@ -79,7 +80,7 @@ class ShaderProgram {
SCP_vector<GLuint> _compiled_shaders;
SCP_unordered_map<opengl_vert_attrib::attrib_id, GLint> _attribute_locations;
SCP_unordered_map<SCP_string, GLint> _attribute_locations;
void freeCompiledShaders();
public:
@@ -100,9 +101,9 @@ class ShaderProgram {
void linkProgram();
void initAttribute(const SCP_string& name, opengl_vert_attrib::attrib_id attr_id, const vec4& default_value);
void initAttribute(const SCP_string& name, const vec4& default_value);
GLint getAttributeLocation(opengl_vert_attrib::attrib_id attribute);
GLint getAttributeLocation(const SCP_string& name);
GLuint getShaderHandle();
};
+139 -68
View File
@@ -10,19 +10,17 @@
#include "debugconsole/console.h"
#include "globalincs/systemvars.h"
#include "graphics/2d.h"
#include "graphics/matrix.h"
#include "graphics/paths/PathRenderer.h"
#include "gropengl.h"
#include "gropenglbmpman.h"
#include "gropengldraw.h"
#include "gropengllight.h"
#include "gropenglpostprocessing.h"
#include "gropenglquery.h"
#include "gropenglsync.h"
#include "gropenglshader.h"
#include "gropenglstate.h"
#include "gropengltexture.h"
#include "gropengltnl.h"
#include "gropengldeferred.h"
#include "graphics/line.h"
#include "io/mouse.h"
#include "io/timer.h"
@@ -34,7 +32,6 @@
#include "render/3d.h"
#include "popup/popup.h"
#include "tracing/tracing.h"
#include "pngutils/pngutils.h"
#if defined(_WIN32)
#include <windows.h>
@@ -65,6 +62,8 @@ static ushort *GL_original_gamma_ramp = NULL;
int Use_PBOs = 0;
float GL_line_width = 1.0f;
static ubyte *GL_saved_screen = NULL;
static int GL_saved_screen_id = -1;
static GLuint GL_screen_pbo = 0;
@@ -72,7 +71,6 @@ static GLuint GL_screen_pbo = 0;
float GL_alpha_threshold = 0.0f;
extern const char *Osreg_title;
extern SCP_string Window_title;
extern GLfloat GL_anisotropy;
@@ -151,9 +149,6 @@ void gr_opengl_clear()
blue = pow(blue, SRGB_GAMMA);
}
// Make sure that all channels are enabled before doing this.
GL_state.ColorMask(true, true, true, true);
glClearColor(red, green, blue, alpha);
glClear ( GL_COLOR_BUFFER_BIT );
@@ -176,6 +171,7 @@ void gr_opengl_flip()
current_viewport->swapBuffers();
opengl_tcache_frame();
opengl_reset_immediate_buffer();
#ifndef NDEBUG
int ic = opengl_check_for_errors();
@@ -300,14 +296,23 @@ void gr_opengl_reset_clip()
void gr_opengl_print_screen(const char *filename)
{
char tmp[MAX_PATH_LEN];
ubyte tga_hdr[18];
int i;
ushort width, height;
GLubyte *pixels = NULL;
GLuint pbo = 0;
// save to a "screenshots" directory and tack on the filename
snprintf(tmp, MAX_PATH_LEN-1, "screenshots/%s.png", filename);
snprintf(tmp, MAX_PATH_LEN-1, "screenshots/%s.tga", filename);
_mkdir(os_get_config_path("screenshots").c_str());
FILE *fout = fopen(os_get_config_path(tmp).c_str(), "wb");
if (fout == NULL) {
return;
}
// glReadBuffer(GL_FRONT);
// now for the data
@@ -316,6 +321,9 @@ void gr_opengl_print_screen(const char *filename)
glGenBuffers(1, &pbo);
if ( !pbo ) {
if (fout != NULL)
fclose(fout);
return;
}
@@ -323,7 +331,7 @@ void gr_opengl_print_screen(const char *filename)
glBufferData(GL_PIXEL_PACK_BUFFER, (gr_screen.max_w * gr_screen.max_h * 4), NULL, GL_STATIC_READ);
glReadBuffer(GL_FRONT);
glReadPixels(0, 0, gr_screen.max_w, gr_screen.max_h, GL_RGBA, GL_UNSIGNED_INT_8_8_8_8_REV, NULL);
glReadPixels(0, 0, gr_screen.max_w, gr_screen.max_h, GL_read_format, GL_UNSIGNED_INT_8_8_8_8_REV, NULL);
// map the image data so that we can save it to file
pixels = (GLubyte*) glMapBuffer(GL_PIXEL_PACK_BUFFER, GL_READ_ONLY);
@@ -331,17 +339,44 @@ void gr_opengl_print_screen(const char *filename)
pixels = (GLubyte*) vm_malloc(gr_screen.max_w * gr_screen.max_h * 4, memory::quiet_alloc);
if (pixels == NULL) {
if (fout != NULL) {
fclose(fout);
}
return;
}
glReadPixels(0, 0, gr_screen.max_w, gr_screen.max_h, GL_RGBA, GL_UNSIGNED_INT_8_8_8_8_REV, pixels);
glReadPixels(0, 0, gr_screen.max_w, gr_screen.max_h, GL_read_format, GL_UNSIGNED_INT_8_8_8_8_REV, pixels);
glFlush();
}
if (!png_write_bitmap(os_get_config_path(tmp).c_str(), gr_screen.max_w, gr_screen.max_h, true, pixels)) {
ReleaseWarning(LOCATION, "Failed to write screenshot to \"%s\".", os_get_config_path(tmp).c_str());
// Write the TGA header
width = INTEL_SHORT((ushort)gr_screen.max_w);
height = INTEL_SHORT((ushort)gr_screen.max_h);
memset( tga_hdr, 0, sizeof(tga_hdr) );
tga_hdr[2] = 2; // ImageType 2 = 24bpp, uncompressed
memcpy( tga_hdr + 12, &width, sizeof(ushort) ); // Width
memcpy( tga_hdr + 14, &height, sizeof(ushort) ); // Height
tga_hdr[16] = 24; // PixelDepth
fwrite( tga_hdr, sizeof(tga_hdr), 1, fout );
// now for the data, we convert it from 32-bit to 24-bit
for (i = 0; i < (gr_screen.max_w * gr_screen.max_h * 4); i += 4) {
#if BYTE_ORDER == BIG_ENDIAN
int pix, *pix_tmp;
pix_tmp = (int*)(pixels + i);
pix = INTEL_INT(*pix_tmp);
fwrite( &pix, 1, 3, fout );
#else
fwrite( pixels + i, 1, 3, fout );
#endif
}
if (pbo) {
glUnmapBuffer(GL_PIXEL_PACK_BUFFER);
pixels = NULL;
@@ -349,6 +384,9 @@ void gr_opengl_print_screen(const char *filename)
glDeleteBuffers(1, &pbo);
}
// done!
fclose(fout);
if (pixels != NULL) {
vm_free(pixels);
}
@@ -356,7 +394,10 @@ void gr_opengl_print_screen(const char *filename)
void gr_opengl_shutdown()
{
graphics::paths::PathRenderer::shutdown();
opengl_tcache_shutdown();
opengl_light_shutdown();
opengl_tnl_shutdown();
opengl_scene_texture_shutdown();
opengl_post_process_shutdown();
@@ -366,7 +407,7 @@ void gr_opengl_shutdown()
glDeleteVertexArrays(1, &GL_vao);
GL_vao = 0;
if (GL_original_gamma_ramp != NULL && os::getSDLMainWindow() != nullptr) {
SDL_SetWindowGammaRamp( os::getSDLMainWindow(), GL_original_gamma_ramp, (GL_original_gamma_ramp+256), (GL_original_gamma_ramp+512) );
}
@@ -444,18 +485,17 @@ void gr_opengl_set_clear_color(int r, int g, int b)
int gr_opengl_set_color_buffer(int mode)
{
bvec4 enabled;
GLboolean enabled = GL_FALSE;
if ( mode ) {
enabled = GL_state.ColorMask(true, true, true, true);
enabled = GL_state.ColorMask(GL_TRUE);
} else {
enabled = GL_state.ColorMask(false, false, false, false);
enabled = GL_state.ColorMask(GL_FALSE);
}
GL_state.SetAlphaBlendMode(ALPHA_BLEND_ALPHA_BLEND_ALPHA);
// Check if all channels are active
return enabled.x && enabled.y && enabled.z && enabled.w;
return (enabled) ? 1 : 0;
}
int gr_opengl_zbuffer_get()
@@ -515,16 +555,13 @@ int gr_opengl_stencil_set(int mode)
if ( mode == GR_STENCIL_READ ) {
GL_state.StencilTest(1);
GL_state.StencilFunc(GL_NEVER, 1, 0xFFFF);
GL_state.StencilOpSeparate(GL_FRONT_AND_BACK, GL_KEEP, GL_KEEP, GL_KEEP);
GL_state.SetStencilType(STENCIL_TYPE_READ);
} else if ( mode == GR_STENCIL_WRITE ) {
GL_state.StencilTest(1);
GL_state.StencilFunc(GL_NOTEQUAL, 1, 0XFFFF);
GL_state.StencilOpSeparate(GL_FRONT_AND_BACK, GL_KEEP, GL_KEEP, GL_KEEP);
GL_state.SetStencilType(STENCIL_TYPE_WRITE);
} else {
GL_state.StencilTest(0);
GL_state.StencilFunc(GL_ALWAYS, 1, 0xFFFF);
GL_state.StencilOpSeparate(GL_FRONT_AND_BACK, GL_KEEP, GL_KEEP, GL_REPLACE);
GL_state.SetStencilType(STENCIL_TYPE_NONE);
}
return tmp;
@@ -838,7 +875,7 @@ void gr_opengl_set_line_width(float width)
if (width <= 1.0f) {
GL_state.SetLineWidth(width);
}
gr_screen.line_width = width;
GL_line_width = width;
}
int opengl_check_for_errors(const char *err_at)
@@ -875,6 +912,20 @@ void opengl_set_vsync(int status)
GL_CHECK_FOR_ERRORS("end of set_vsync()");
}
void opengl_setup_viewport()
{
glViewport(0, 0, gr_screen.max_w, gr_screen.max_h);
GL_last_projection_matrix = GL_projection_matrix;
// the top and bottom positions are reversed on purpose, but RTT needs them the other way
if (GL_rendering_to_texture) {
opengl_create_orthographic_projection_matrix(&GL_projection_matrix, 0, i2fl(gr_screen.max_w), 0, i2fl(gr_screen.max_h), -1.0, 1.0);
} else {
opengl_create_orthographic_projection_matrix(&GL_projection_matrix, 0, i2fl(gr_screen.max_w), i2fl(gr_screen.max_h), 0, -1.0, 1.0);
}
}
std::unique_ptr<os::Viewport> gr_opengl_create_viewport(const os::ViewPortProperties& props) {
os::ViewPortProperties attrs = props;
attrs.pixel_format.red_size = Gr_red.bits;
@@ -1026,9 +1077,6 @@ int opengl_init_display_device()
attrs.height = (uint32_t) gr_screen.max_h;
attrs.title = Osreg_title;
if (!Window_title.empty()) {
attrs.title = Window_title;
}
if (!Cmdline_window && ! Cmdline_fullscreen_window) {
attrs.flags.set(os::ViewPortFlags::Fullscreen);
@@ -1041,7 +1089,7 @@ int opengl_init_display_device()
return 1;
}
const int gl_versions[] = { 45, 44, 43, 42, 41, 40, 33, 32 };
const int gl_versions[] = { 41, 40, 33, 32, 31, 30, 21, 20 };
// find the latest and greatest OpenGL context
for (auto ver : gl_versions)
@@ -1085,11 +1133,29 @@ void opengl_setup_function_pointers()
gr_screen.gf_clear = gr_opengl_clear;
// gr_screen.gf_bitmap = gr_opengl_bitmap;
gr_screen.gf_bitmap_ex = gr_opengl_bitmap_ex;
gr_screen.gf_aabitmap = gr_opengl_aabitmap;
gr_screen.gf_aabitmap_ex = gr_opengl_aabitmap_ex;
// gr_screen.gf_rect = gr_opengl_rect;
// gr_screen.gf_shade = gr_opengl_shade;
gr_screen.gf_string = gr_opengl_string;
gr_screen.gf_circle = gr_opengl_circle;
gr_screen.gf_unfilled_circle = gr_opengl_unfilled_circle;
gr_screen.gf_arc = gr_opengl_arc;
gr_screen.gf_curve = gr_opengl_curve;
gr_screen.gf_line = gr_opengl_line;
gr_screen.gf_aaline = gr_opengl_aaline;
gr_screen.gf_pixel = gr_opengl_pixel;
gr_screen.gf_gradient = gr_opengl_gradient;
gr_screen.gf_print_screen = gr_opengl_print_screen;
gr_screen.gf_flash = gr_opengl_flash;
gr_screen.gf_flash_alpha = gr_opengl_flash_alpha;
gr_screen.gf_zbuffer_get = gr_opengl_zbuffer_get;
gr_screen.gf_zbuffer_set = gr_opengl_zbuffer_set;
gr_screen.gf_zbuffer_clear = gr_opengl_zbuffer_clear;
@@ -1133,14 +1199,23 @@ void opengl_setup_function_pointers()
gr_screen.gf_set_texture_addressing = gr_opengl_set_texture_addressing;
gr_screen.gf_zbias = gr_opengl_zbias;
gr_screen.gf_set_fill_mode = gr_opengl_set_fill_mode;
gr_screen.gf_set_texture_panning = gr_opengl_set_texture_panning;
gr_screen.gf_create_buffer = gr_opengl_create_buffer;
gr_screen.gf_create_vertex_buffer = gr_opengl_create_vertex_buffer;
gr_screen.gf_create_index_buffer = gr_opengl_create_index_buffer;
gr_screen.gf_delete_buffer = gr_opengl_delete_buffer;
gr_screen.gf_update_buffer_data = gr_opengl_update_buffer_data;
gr_screen.gf_update_buffer_data_offset = gr_opengl_update_buffer_data_offset;
gr_screen.gf_bind_uniform_buffer = gr_opengl_bind_uniform_buffer;
gr_screen.gf_update_transform_buffer = gr_opengl_update_transform_buffer;
gr_screen.gf_set_transform_buffer_offset = gr_opengl_set_transform_buffer_offset;
gr_screen.gf_start_instance_matrix = gr_opengl_start_instance_matrix;
gr_screen.gf_end_instance_matrix = gr_opengl_end_instance_matrix;
gr_screen.gf_start_angles_instance_matrix = gr_opengl_start_instance_angles;
gr_screen.gf_set_light = gr_opengl_set_light;
gr_screen.gf_reset_lighting = gr_opengl_reset_lighting;
gr_screen.gf_set_ambient_light = gr_opengl_set_ambient_light;
gr_screen.gf_post_process_set_effect = gr_opengl_post_process_set_effect;
gr_screen.gf_post_process_set_defaults = gr_opengl_post_process_set_defaults;
@@ -1158,10 +1233,24 @@ void opengl_setup_function_pointers()
gr_screen.gf_deferred_lighting_end = gr_opengl_deferred_lighting_end;
gr_screen.gf_deferred_lighting_finish = gr_opengl_deferred_lighting_finish;
gr_screen.gf_start_clip_plane = gr_opengl_start_clip_plane;
gr_screen.gf_end_clip_plane = gr_opengl_end_clip_plane;
gr_screen.gf_lighting = gr_opengl_set_lighting;
gr_screen.gf_set_proj_matrix = gr_opengl_set_projection_matrix;
gr_screen.gf_end_proj_matrix = gr_opengl_end_projection_matrix;
gr_screen.gf_set_view_matrix = gr_opengl_set_view_matrix;
gr_screen.gf_end_view_matrix = gr_opengl_end_view_matrix;
gr_screen.gf_push_scale_matrix = gr_opengl_push_scale_matrix;
gr_screen.gf_pop_scale_matrix = gr_opengl_pop_scale_matrix;
gr_screen.gf_set_line_width = gr_opengl_set_line_width;
gr_screen.gf_sphere = gr_opengl_sphere;
gr_screen.gf_maybe_create_shader = gr_opengl_maybe_create_shader;
gr_screen.gf_shadow_map_start = gr_opengl_shadow_map_start;
gr_screen.gf_shadow_map_end = gr_opengl_shadow_map_end;
@@ -1175,14 +1264,13 @@ void opengl_setup_function_pointers()
gr_screen.gf_render_model = gr_opengl_render_model;
gr_screen.gf_render_primitives= gr_opengl_render_primitives;
gr_screen.gf_render_primitives_immediate = gr_opengl_render_primitives_immediate;
gr_screen.gf_render_primitives_2d = gr_opengl_render_primitives_2d;
gr_screen.gf_render_primitives_2d_immediate = gr_opengl_render_primitives_2d_immediate;
gr_screen.gf_render_primitives_particle = gr_opengl_render_primitives_particle;
gr_screen.gf_render_primitives_batched = gr_opengl_render_primitives_batched;
gr_screen.gf_render_primitives_distortion = gr_opengl_render_primitives_distortion;
gr_screen.gf_render_movie = gr_opengl_render_movie;
gr_screen.gf_render_nanovg = gr_opengl_render_nanovg;
gr_screen.gf_is_capable = gr_opengl_is_capable;
gr_screen.gf_get_property = gr_opengl_get_property;
gr_screen.gf_push_debug_group = gr_opengl_push_debug_group;
gr_screen.gf_pop_debug_group = gr_opengl_pop_debug_group;
@@ -1196,12 +1284,6 @@ void opengl_setup_function_pointers()
gr_screen.gf_create_viewport = gr_opengl_create_viewport;
gr_screen.gf_use_viewport = gr_opengl_use_viewport;
gr_screen.gf_sync_fence = gr_opengl_sync_fence;
gr_screen.gf_sync_wait = gr_opengl_sync_wait;
gr_screen.gf_sync_delete = gr_opengl_sync_delete;
gr_screen.gf_set_viewport = gr_opengl_set_viewport;
// NOTE: All function pointers here should have a Cmdline_nohtl check at the top
// if they shouldn't be run in non-HTL mode, Don't keep separate entries.
// *****************************************************************************
@@ -1339,11 +1421,11 @@ static void init_extensions() {
Texture_compression_available = true;
// Swifty put this in, but it's not doing anything. Once he uses it, he can uncomment it.
//int use_base_vertex = Is_Extension_Enabled(OGL_ARB_DRAW_ELEMENTS_BASE_VERTEX);
if ( !Cmdline_no_pbo ) {
Use_PBOs = 1;
}
int ver = 0, major = 0, minor = 0;
const char *glsl_ver = (const char*)glGetString(GL_SHADING_LANGUAGE_VERSION);
@@ -1450,6 +1532,9 @@ bool gr_opengl_init(std::unique_ptr<os::GraphicsOperations>&& graphicsOps)
init_extensions();
// setup the lighting stuff that will get used later
opengl_light_init();
// init state system (must come AFTER light is set up)
GL_state.init();
@@ -1461,11 +1546,10 @@ bool gr_opengl_init(std::unique_ptr<os::GraphicsOperations>&& graphicsOps)
// create vertex array object to make OpenGL Core happy
glGenVertexArrays(1, &GL_vao);
GL_state.BindVertexArray(GL_vao);
glBindVertexArray(GL_vao);
GL_state.Texture.init(max_texture_units);
GL_state.Array.init(max_texture_coords);
GL_state.Constants.init();
opengl_set_texture_target();
GL_state.Texture.SetActiveUnit(0);
@@ -1487,8 +1571,9 @@ bool gr_opengl_init(std::unique_ptr<os::GraphicsOperations>&& graphicsOps)
// must be called after extensions are setup
opengl_set_vsync( !Cmdline_no_vsync );
gr_reset_matrices();
gr_setup_viewport();
opengl_setup_viewport();
vm_matrix4_set_identity(&GL_view_matrix);
vm_matrix4_set_identity(&GL_model_view_matrix);
glClear(GL_DEPTH_BUFFER_BIT);
glClear(GL_STENCIL_BUFFER_BIT);
@@ -1533,11 +1618,7 @@ bool gr_opengl_init(std::unique_ptr<os::GraphicsOperations>&& graphicsOps)
mprintf(( " Using %s texture filter.\n", (GL_mipmap_filter) ? NOX("trilinear") : NOX("bilinear") ));
mprintf(( " OpenGL Shader Version: %s\n", glGetString(GL_SHADING_LANGUAGE_VERSION) ));
mprintf((" Max uniform block size: %d\n", GL_state.Constants.GetMaxUniformBlockSize()));
mprintf((" Max uniform buffer bindings: %d\n", GL_state.Constants.GetMaxUniformBlockBindings()));
mprintf((" Uniform buffer byte offset alignment: %d\n", GL_state.Constants.GetUniformBufferOffsetAlignment()));
// This stops fred crashing if no textures are set
gr_screen.current_bitmap = -1;
@@ -1572,22 +1653,12 @@ bool gr_opengl_is_capable(gr_capability capability)
case CAPABILITY_POINT_PARTICLES:
return !Cmdline_no_geo_sdr_effects;
case CAPABILITY_TIMESTAMP_QUERY:
return GLAD_GL_ARB_timer_query != 0; // Timestamp queries are available from 3.3 onwards
return GL_version >= 33; // Timestamp queries are available from 3.3 onwards
}
return false;
}
bool gr_opengl_get_property(gr_property prop, void* dest) {
switch(prop) {
case gr_property::UNIFORM_BUFFER_OFFSET_ALIGNMENT:
*((int*)dest) = GL_state.Constants.GetUniformBufferOffsetAlignment();
return true;
default:
return false;
}
}
void gr_opengl_push_debug_group(const char* name) {
if (GLAD_GL_KHR_debug) {
glPushDebugGroup(GL_DEBUG_SOURCE_APPLICATION_KHR, 0, -1, name);
+1 -1
View File
@@ -22,7 +22,6 @@ bool gr_opengl_init(std::unique_ptr<os::GraphicsOperations>&& graphicsOps);
void gr_opengl_cleanup(bool closing, int minimize=1);
int opengl_check_for_errors(const char *err_at = NULL);
bool gr_opengl_is_capable(gr_capability capability);
bool gr_opengl_get_property(gr_property prop, void* dest);
void gr_opengl_push_debug_group(const char* name);
void gr_opengl_pop_debug_group();
@@ -57,5 +56,6 @@ extern int Use_PBOs;
extern GLuint GL_vao;
extern float GL_alpha_threshold;
extern float GL_line_width;
#endif
+8 -3
View File
@@ -55,8 +55,11 @@ void gr_opengl_bm_free_data(int n, bool release)
{
Assert( (n >= 0) && (n < MAX_BITMAPS) );
if ( release )
opengl_free_texture_slot( n );
// might as well free up the on card texture data too in order to get rid
// of old interface stuff but don't free USER types, unless it's a total release,
// since we can reuse ANI slots for faster and less resource intensive rendering
if ( release || (bm_bitmaps[n].type != BM_TYPE_USER) )
opengl_free_texture_slot( n );
if ( (bm_bitmaps[n].type == BM_TYPE_RENDER_TARGET_STATIC) || (bm_bitmaps[n].type == BM_TYPE_RENDER_TARGET_DYNAMIC) )
opengl_kill_render_target( n );
@@ -109,7 +112,9 @@ void gr_opengl_bm_save_render_target(int n)
return;
}
dds_save_image(bmp->w, bmp->h, bmp->true_bpp, be->num_mipmaps, (ubyte*)bmp->data, (bmp->flags & BMP_FLAG_CUBEMAP));
if (Cmdline_save_render_targets) {
dds_save_image(bmp->w, bmp->h, bmp->true_bpp, be->num_mipmaps, (ubyte*)bmp->data, (bmp->flags & BMP_FLAG_CUBEMAP));
}
}
int gr_opengl_bm_make_render_target(int n, int *width, int *height, int *bpp, int *mm_lvl, int flags)
Loaded 100 of 384 files, more files were not shown because too many files have changed in this diff. Show more