Compare commits

...
55 Commits
Author SHA1 Message Date
alufolie91 59a4627911 gl: use shaders for vhs effect
this is a fuckton faster lol
the old one did a gazillion draw calls now we do two, one for the fuzzy and the 2nd for the bars as both are handled within a single shader
thanks to RRs heat effect being super similar to the vhs bars lul
2026-11-12 21:02:07 +01:00
alufolie91 ecab383078 gl: use shaders for underwater / heatwave effect
basically ported over from RR
water was massively toned down and adjusted, it visually almost matches software at default res (note that the software effects are not properly scaled lol)
the heat effect is just the water effect adjusted to look like the fixed function version from before but slightly slower to accomidate the slower water effect here

this should speed things up a little since we now only need ONE draw call instead of 20 per effect
small note: this does not zoom into the image like the shaderless version, which was quite jarring tbh but there can be some very slight "stretch" marks at screen border, but theyre extremely unnoticable
2026-11-12 20:32:38 +01:00
alufolie91 ee4c060cc8 add rumble type for wallbonks
yoinked from blan
will also look into drift release rumble, but we have that per lua in sg anyways
2026-11-12 20:31:27 +01:00
alufolie91 ebd5b86e87 use screen_width/height for scr_resolution uniform
those are meant for this kinda crap
2026-11-12 19:39:50 +01:00
alufolie91 9321036049 further simplify downsample stuff
man idk why i even did the whole desktop res shit
somehow kept forgetting we should just check against the drawable/window size as it determines the main framebuffer size
so we just can use SDL_GetWindowSize and get rid of all the other crap
2026-11-11 12:26:53 +01:00
alufolie91 12f43ae504 move horizonline stuff back to plane preprocessor
well "back" we still had it there, but the subsector marking logic can just be there
was kinda too lazy before to do this lul
saves some time as we dont need to go thru all subsectors again at mapload, which there can be many of
2026-11-11 12:25:20 +01:00
alufolie91 cfc94c0f9e fix horizonlines on fofs in opengl
not super cool but seems to work just fine
the new subsector flag may even improve performance in some cases since the horizonspecial check seems to mess up the branch predictor often lol
2026-11-11 00:55:41 +01:00
alufolie91 3385df4c7e allow gl fbo to be enabled at all times
not just when downsampling
as this may improve performance in some cases
2026-11-10 17:48:30 +01:00
alufolie91 561f871e61 fix downsample state not refreshing in the right place
needs to be done before refreshing the surface, as OglSdlSurface needs to determine the state to toggle the fbo
2026-11-10 17:48:27 +01:00
alufolie91 bffafa0540 make screen fbo msaa compatible
quite a mess but "works"
the reason this didnt work before was
i mostly tried doing this per multisample textures which you cant really copy from
now we do it per color rbo which you also cant really copy from, but is the recommended way
so now each time we try to copy from the screen (screentextures, screenshots, etc.) we blit the msaa fbo into the normal fbo so we can copy from that
its probably a little slow, but cant really do much about it besides getting rid of screen textures and replacing them with more fbo logic.....
2026-11-10 17:27:11 +01:00
alufolie91 473619ab66 add I_CheckAboveDesktopRes
forgor i added this originally for the resolution list rework stuff so was missing here lul
2026-11-09 20:51:02 +01:00
alufolie91 d75638cbfc remove alpha to coverage (a2c) support
while this can look nice in some cases with msaa, it has the effect that everything transclucent is twice as translucent as it should be besides just being a kinda confusing option for almost everyone
so just delet it and simplify code
2026-11-09 20:26:50 +01:00
alufolie91 f09b591989 set screentexture filtermode to linear when downsampling
nearest-neighbour filtering is good from upscaling from a lower resolution, but will produce super ugly mixels and shimmering when downsampling from a higher resolution
2026-11-09 20:19:14 +01:00
alufolie91 79d75aa08d simplify gl "downsampling" stuff
still kinda meh but whatever, shit works
2026-11-09 20:19:08 +01:00
alufolie91 486560d79e fix typo
:blobcatpats:
2026-11-09 20:18:03 +01:00
alufolie91 953b0c8f94 opengl: make stencil attachment for fbo with EXT a requierement
while not compeletely needed, we use the stencil buffer for some stuff, so dont really feel like having to deal with potential issues here
besides, probably any gpu in almost the last 2 decades should support this and even gl3.0 anyways, so this is just bloat we do not need
2026-11-09 20:17:59 +01:00
alufolie91 5639e872f1 delet this
cant remember what this was used for lul
2026-11-09 20:17:51 +01:00
alufolie91 80da0fc538 fix G_GetDemoDate
forgor to change this back oopsie
2026-11-07 13:52:29 +01:00
alufolie91 014126b57d Merge branch 'origin/polyholes' into Saturn-Next 2026-11-06 17:21:19 +01:00
alufolie91 d7b150a04f (hopefully) make replay date stuff more thread safe
dont do locale stuff from thread, use localtime_r && localtime_r as localtime is not threadsafe either
G_GetDemoDate returns malloc´d buffer again, tho not strictly necessary
also, fix dates not always being initialized in all cases and type issue with G_GetCreationTime
2026-11-06 16:14:39 +01:00
alufolie91 5751f9b29b fix windoze compile
windoze does not have threads.h and thread_local is only a keyword per c23....
thanks michealslop....
2026-11-05 15:55:22 +01:00
alufolie91 1a29bd1e63 Merge branch 'Saturn-Next' into polyholes 2026-11-05 15:38:42 +01:00
alufolie91 e54b6a780d "fix" skywalls on hadal trench and candy lake
this whole sky handling is just incredibly stupid and wouldve been such an easy fix, but here we go
this is just more stupid hacks but i really dont feel bad here since the code already hacked around a bunch of shit
just hoping this wont cause any issues on some maps and needs testing
sigh
2026-11-05 15:38:11 +01:00
alufolie91 c1a0b97c54 add checks for missing bsp lumps
not sure why there werent any, the other map lumps have those, and a corrupted file may have those missing also which would just crash instead of telling you wtf is wrong
2026-11-05 15:38:07 +01:00
alufolie91 b8aaf63b20 use "rawlinedef" when checking for seg issues
smth smth byte order or whatever but is consistent with the rest of the code anyways
2026-11-05 15:38:04 +01:00
alufolie91 d43b60ad83 fix blendmodes and line translucency on polyobject sides in gl
this is also how vanilla kart handled this code eitherways
2026-11-05 15:38:00 +01:00
alufolie91 cb5d3ab4e1 add compile flag for building with thread sanitizer
indev noticed thats a thing that exists
wouldve been quite useful a bunch of times before lol
also some fixes for the other sanitizer flags
2026-11-04 01:42:11 +01:00
alufolie91 eba1cfb94d remove "flatcheck" from HWR_PrecacheLevelFlats
in practice this did nothing really
would be more useful for encore but that aint working for us so whatever
2026-11-04 01:38:30 +01:00
alufolie91 f5030e6a3c fix some holes and cracks in the gl renderer on some maps
hopefully...
this is adapted from the large refactor but that was slow as shit
needs testing to see if this messes with something
2026-11-04 00:27:22 +01:00
indev 3adcf608c3 (Hopefully) fix race condition in replay hut
It was probably caused by menupath being modified when replay load
thread is in the middle of checking it, now the check for "valid"
replay load thread is simpler. Also as comment says, there still are
few reported data races for replaynamesloaded but i THINK it should be
fine, since the only "data race" that could be harmful here is
replaynamesloaded switching from true to false, which would mean
demolist_all is suddenly invalidated, and that shouldn't be possible
because we only switch replaynamesloaded from true to false inside main
thread while also locking the "search mutex"
(this is so wordy lol)
2026-11-04 01:06:18 +03:00
indev 9682ab59c9 Make M_CheckParm thread-safe, it is called from different thread in http-mserv.c for example 2026-11-03 23:56:22 +03:00
alufolie91 51adf8869c HWR_PrecacheLevelTextures should also skip texture number 0
whoopsie
2026-11-02 14:58:55 +01:00
alufolie91 5183baed44 make HWR_ApplyDispoffset a little less ugly lol 2026-11-02 14:41:09 +01:00
alufolie91 e5c6cb635d make teleporter handling in P_ProcessLineSpecial a little less ugly lulul 2026-11-02 14:41:06 +01:00
alufolie91 1ba4fe99a7 fix fof noencore ceiling checks being flipped in opengl renderer
matches software now
even if most  custom maps were made with opengl in mind, stuff did not work anyways for years so this shouldnt hopefully cause any issues
2026-11-02 14:38:56 +01:00
alufolie91 c44d6f6aeb update HWR precache stuff
not much but matches stuff i did for blan
2026-11-02 14:32:12 +01:00
alufolie91 07427b391e dont run horizonline code on fofs in opengl
this currently does NOT work anyways and just wastes time for nothing on some maps
2026-11-02 00:15:38 +01:00
alufolie91 2210bd4e2d opengl: fix opaque fof planes checking the wrong sector for encore remap
it should check its own "master" sector for remap behavior NOT the sector it resides in
note: i did not change the ceiling/floor behavior here as i noticed there might be more issues than this with fofs
2026-10-31 12:51:01 +01:00
alufolie91 f4ac08d09f some smaller mobj related things
mostly cleanup and correctness fixes for phobos build
2026-10-31 12:50:18 +01:00
alufolie91 090580badf replace number with COM_SPLITSCREEN 2026-10-31 12:50:14 +01:00
SteelT 0eacda7494 discord.c: Fix joinSecret memory leak 2026-10-17 16:26:33 +02:00
alufolie91 14df9c01fa send over less mobj stuff in savegame on mobjscaled maps in some cases for phobos build
none of this ever accounted for mapobjectscale
sadly not vanilla compatible but oh well
from https://gitlab.com/kart-krew-dev/ring-racers/-/commit/c4cca8c8b703b4bb23e27be4c3bfd37b9d092215
2026-10-15 16:25:51 +02:00
alufolie91 a69fc07dcf fix smoldering smoke not accounting for mapobject scale (but vanilla compatible)
:chaosleep:
2026-10-15 16:17:33 +02:00
alufolie91 cea97226d5 fix driftdust and respawn lasers not accounting for mapobjectscale (but vanilla compatible)
super annoying, but at least it looks right like that
2026-10-15 14:52:49 +02:00
alufolie91 19a7a4c5c1 remove duped copyright 2026-10-15 10:15:51 +02:00
alufolie91 98d4ab3e9d do not attempt to netsync locally spawned mobjs
it is generally not really advised to locally load addons as a host as that might cause issues
2026-10-15 10:15:48 +02:00
alufolie91 1700db48b4 make player gravstretch and squish properly account for mapobjscale 2026-10-15 09:30:13 +02:00
alufolie91 ba3429f497 software: add helper for getting "wall lights"
slightly less ugly
2026-10-15 09:28:10 +02:00
Alug 3b98d6c44f addfilelocal/autoload: fix showing wrong error when file was not found
W_CheckFileContains returns -1 if file was not found which still triggered those conditions
so just handle if file was not found to skip doing other stuff in those cases
2026-10-14 13:56:31 +02:00
alufolie91 3183ec58ab simpler fix for localskin minimap angle display crash 2026-10-12 15:13:38 +02:00
alufolie91 46a72bda8e fix crash when applying localskin midgame 2026-10-08 09:24:30 +02:00
alufolie91 156400ffc2 fix arithmetic on NULL pointer when drawing 3d models
caused by localskin code.... sigh......
noticed this while messing with dynamic allocated (local)skins
2026-10-07 20:25:56 +02:00
alufolie91 116fbd93d0 cleanup squishdance stuff a bit
we dont need all those things saved per player really lol
2026-10-07 09:58:20 +02:00
alufolie91 30affaf451 cleanup saltyhop a little, move it to player struct 2026-10-07 09:58:20 +02:00
alufolie91 d66020e3a9 fix localskin menu not showing localskin 3d models
this should use the skins localnumber not the "actual" skinnumber
yeah localskin code still sucks....
fixes https://github.com/Indev450/SRB2Kart-Saturn/issues/230
2026-10-04 00:56:25 +02:00
45 changed files with 1811 additions and 918 deletions

No files matched your search

+2
View File
@@ -246,6 +246,8 @@ set(SRB2_CONFIG_ASAN OFF CACHE BOOL
"Compile with AddressSanitizer (libasan).")
set(SRB2_CONFIG_UBSAN OFF CACHE BOOL
"Compile with UndefinedBehaviorSanitizer (libubsan).")
set(SRB2_CONFIG_TSAN OFF CACHE BOOL
"Compile with ThreadSanitizer (libtsan).")
set(SRB2_CONFIG_MUMBLE ON CACHE BOOL
"Enable Mumble support")
+18 -5
View File
@@ -75,6 +75,7 @@
# PROFILEMODE=1 - Enable performance profiling (gprof).
# USEASAN=1 - Enable building with Address Sanitizer.
# USEUBSAN=1 - Enable building with Undefined Behavior Sanitizer.
# USETSAN=1 - Enable building with Thread Sanitizer.
# NOLIBBACKTRACE=1 - Disable using Libbacktrace for crashlog traces.
#
# General flags for building:
@@ -261,23 +262,35 @@ debug_opts=-D_DEBUG
else # build a normal optimized version
debug_opts=-DNDEBUG
opts+=-O3
ifndef NOLTO
# compile with LTO
opts+=-flto=auto
libs+=-flto=auto
endif
endif
ifdef USEASAN
# compile with asan
opts+=-O1 -fsanitize=address -fno-omit-frame-pointer -fno-common
libs+=-fsanitize=address
NOLTO=1
endif
ifdef USEUBSAN
# compile with ubsan
opts+=-O1 -fsanitize=undefined -fno-omit-frame-pointer
libs+=-fsanitize=undefined
NOLTO=1
endif
ifdef USETSAN
# compile with tsan
opts+=-O1 -fsanitize=thread -fno-omit-frame-pointer
libs+=-fsanitize=thread
NOLTO=1
endif
ifndef DEBUGMODE
ifndef NOLTO
# compile with LTO
opts+=-flto=auto
libs+=-flto=auto
endif
endif
ifdef USEJEMALLOC
+1
View File
@@ -1739,6 +1739,7 @@ static void CV_SetCVar(consvar_t *var, const char *value, boolean stealth)
// send the value of the variable
UINT8 buf[128];
UINT8 *p = buf;
if (!(server || (IsPlayerAdmin(consoleplayer))))
{
CONS_Alert(CONS_NOTICE, "Only the server or admin can change: %s %s\n", var->name, var->string);
+8 -2
View File
@@ -1149,13 +1149,19 @@ static void D_FindAddonsToAutoload(void)
// ok so theres still issues with players adding stuff to autoload by accident
// sometimes this stuff contains maps
// you can probably imagine how that goes in a netgame....
if (W_CheckAutoLoadContainsMap(wadsToAutoload))
int retmap = W_CheckAutoLoadContainsMap(wadsToAutoload);
if (retmap == -1)
{
CONS_Alert(CONS_WARNING, "Autoload: file %s was not found or not valid.\n", wadsToAutoload);
continue;
}
if (retmap > 0)
{
CONS_Alert(CONS_WARNING, "Autoload: file %s contains map data, this WILL cause crashes and desynchs! skipping...\n", wadsToAutoload);
continue;
}
if (!postload && W_CheckPostLoadList(wadsToAutoload))
if (!postload && W_CheckPostLoadList(wadsToAutoload) > 0)
{
CONS_Printf("Autoload: forcing postload for file %s\n", wadsToAutoload);
postload = true;
+2
View File
@@ -1043,6 +1043,8 @@ void D_RegisterClientCommands(void)
CV_RegisterVar(&cv_rumble[i]);
CV_RegisterVar(&cv_rumble_strength[i]);
CV_RegisterVar(&cv_rumble_wallbonk[i]);
CV_RegisterVar(&cv_rumble_spinout[i]);
CV_RegisterVar(&cv_rumble_sneakerboost[i]);
CV_RegisterVar(&cv_rumble_offroad[i]);
+12 -3
View File
@@ -361,11 +361,17 @@ typedef struct squishdance_s
{
tic_t countdown; // hold "custom 3" for 2 seconds to engange le dance
tic_t time;
fixed_t work;
fixed_t ang;
fixed_t bounce; // hehe squishy
} squishdance_t;
typedef struct salty_s
{
bool ready;
bool tapping;
fixed_t zoffset;
fixed_t momz;
bool jump;
} salty_t;
// ========================================================================
// PLAYER STRUCTURE
// ========================================================================
@@ -561,6 +567,9 @@ typedef struct player_s
fixed_t spinoutrot; // When a player spins out, this value increments modulus 360.
// saltyhop! hardcode edition
salty_t salty;
squishdance_t squishdance;
fixed_t fovadd; // adjust FOV for hw rendering
+8 -3
View File
@@ -119,20 +119,25 @@ target_compile_definitions(SRB2SDL2 PRIVATE
-DHAVE_THREADS
)
if(SRB2_CONFIG_LTO AND NOT SRB2_CONFIG_DEBUGMODE)
if(SRB2_CONFIG_LTO AND NOT SRB2_CONFIG_DEBUGMODE AND NOT SRB2_CONFIG_ASAN AND NOT SRB2_CONFIG_UBSAN AND NOT SRB2_CONFIG_TSAN)
set_property(TARGET SRB2SDL2 PROPERTY INTERPROCEDURAL_OPTIMIZATION TRUE)
endif()
if(SRB2_CONFIG_ASAN)
target_compile_options(SRB2SDL2 PRIVATE -fsanitize=address)
target_compile_options(SRB2SDL2 PRIVATE -O1 -fsanitize=address -fno-omit-frame-pointer -fno-common)
target_link_options(SRB2SDL2 PRIVATE -fsanitize=address)
endif()
if(SRB2_CONFIG_UBSAN)
target_compile_options(SRB2SDL2 PRIVATE -fsanitize=undefined)
target_compile_options(SRB2SDL2 PRIVATE -O1 -fsanitize=undefined -fno-omit-frame-pointer)
target_link_options(SRB2SDL2 PRIVATE -fsanitize=undefined)
endif()
if(SRB2_CONFIG_TSAN)
target_compile_options(SRB2SDL2 PRIVATE -O1 -fsanitize=thread -fno-omit-frame-pointer)
target_link_options(SRB2SDL2 PRIVATE -fsanitize=thread)
endif()
## strip debug symbols into separate file when using gcc
# if(CMAKE_COMPILER_IS_GNUCC)
# if(${CMAKE_BUILD_TYPE} MATCHES Debug)
+4 -1
View File
@@ -474,6 +474,7 @@ void DRPC_UpdatePresence(void)
char charname[11+SKINNAMESIZE+1];
boolean joinSecretSet = false;
char *clientJoinSecret = NULL;
DiscordRichPresence discordPresence;
memset(&discordPresence, 0, sizeof(discordPresence));
@@ -530,7 +531,8 @@ void DRPC_UpdatePresence(void)
// Grab the host's IP for joining.
if ((join = DRPC_GetServerIP()) != NULL)
{
discordPresence.joinSecret = DRPC_XORIPString(join);
clientJoinSecret = DRPC_XORIPString(join);
discordPresence.joinSecret = clientJoinSecret;
joinSecretSet = true;
}
}
@@ -712,6 +714,7 @@ void DRPC_UpdatePresence(void)
}
Discord_UpdatePresence(&discordPresence);
free(clientJoinSecret);
}
#endif // HAVE_DISCORDRPC
+27 -58
View File
@@ -63,7 +63,6 @@
// for replay dates
#include <time.h>
#include <locale.h>
// menu demo things
UINT32 demoDelayTime = 15*TICRATE;
@@ -2387,7 +2386,9 @@ void G_LoadDemoInfo(menudemo_t *pdemo)
#if defined (_WIN32)
// return the file creation time
// useful for demos that were renamed
static long G_GetCreationTime(char *filepath)
// windows only, as file creation times are
// very unreliable (or non existant depending on fs) on linux
static time_t G_GetCreationTime(char *filepath)
{
struct stat fileinfo;
@@ -2398,35 +2399,24 @@ static long G_GetCreationTime(char *filepath)
}
#endif
static char *G_GetDemoDate(menudemo_t *pdemo)
static char *G_GetDemoDate(menudemo_t *pdemo, const char *dateformat)
{
char *endPos = NULL;
static char datetime[11];
char *datetime;
time_t file_time = 0;
const char *format = NULL;
struct tm *tm_buf = NULL;
struct tm tm_buf;
CLEANUP(pfree) char *filename = NULL;
// get le filepath
filename = strdup(pdemo->filepath);
if (!filename)
{
#if defined (_WIN32)
// if we cant get a filename try just getting the file creation time
file_time = G_GetCreationTime(pdemo->filepath);
goto skipfilenametime;
#else
return NULL;
#endif
}
// get the actual filename Zzz...
nameonly(filename);
// the first 10 characters of a replay name usually is a unix timestamp
// not long enough to contain a valid timestamp
// the first 10 characters of a replay name is a unix timestamp
if (strlen(filename) < 10)
{
#if defined (_WIN32)
@@ -2458,67 +2448,49 @@ static char *G_GetDemoDate(menudemo_t *pdemo)
#endif
}
#if defined (_WIN32)
skipfilenametime:
#endif
// then throw it into localtime to get an actual human readable format lmao
tm_buf = localtime(&file_time);
// cant believe we ended up in 1970
if (tm_buf == NULL || tm_buf->tm_year <= 110)
#if defined(_WIN32)
skipfilenametime:
if ((localtime_s(&tm_buf, &file_time) != 0) ||
(tm_buf.tm_year <= 110)) // cant believe we ended up in 1970
{
#if defined (_WIN32)
// uh ohh, we got an invalid time
// try one more time getting the creation time
file_time = G_GetCreationTime(pdemo->filepath);
tm_buf = localtime(&file_time);
if (tm_buf == NULL || tm_buf->tm_year <= 110)
if ((localtime_s(&tm_buf, &file_time) != 0) ||
(tm_buf.tm_year <= 110))
return NULL;
goto gotcreationtime;
}
#else
if ((localtime_r(&file_time, &tm_buf) == NULL) ||
(tm_buf.tm_year <= 110)) // cant believe we ended up in 1970
return NULL;
#endif
}
#if defined (_WIN32)
gotcreationtime:
#endif
datetime = malloc(sizeof(pdemo->date)); // mallocma balls
// US ppl are special (:
if (cv_demodateformat.value == 2)
format = "%m.%d.%Y";
else if (cv_demodateformat.value == 1)
format = "%d.%m.%Y";
else
{
const char *locale = setlocale(LC_TIME, NULL);
// no mallocma balls... :c
if (!datetime)
return NULL;
if (locale == NULL)
format = "%d.%m.%Y"; // fallback to non US format
else if (strstr(locale, "en_US"))
format = "%m.%d.%Y";
else
format = "%d.%m.%Y";
}
if (strftime(datetime, sizeof(datetime), format, tm_buf) == 0)
if (strftime(datetime, sizeof(pdemo->date), dateformat, &tm_buf) == 0)
{
free(datetime);
return NULL;
}
return datetime;
}
void G_LoadDemoTitle(menudemo_t *pdemo)
void G_LoadDemoTitle(menudemo_t *pdemo, const char *dateformat)
{
UINT8 infobuffer[96], *info_p;
UINT16 pdemoversion;
char *demodate = NULL;
size_t count;
memset(pdemo->date, 0, sizeof(pdemo->date));
FILE *handle = fopen(pdemo->filepath, "rb");
if (!handle)
@@ -2546,8 +2518,6 @@ void G_LoadDemoTitle(menudemo_t *pdemo)
pdemoversion = READUINT16(info_p);
memset(pdemo->date, 0, sizeof(pdemo->date));
switch (pdemoversion)
{
case DEMOVERSION: // latest always supported
@@ -2555,13 +2525,12 @@ void G_LoadDemoTitle(menudemo_t *pdemo)
memcpy(pdemo->title, info_p, 64);
// demo date
demodate = G_GetDemoDate(pdemo);
char *demodate = G_GetDemoDate(pdemo, dateformat);
if (demodate)
{
strlcpy(pdemo->date, demodate, sizeof(pdemo->date));
free(demodate);
}
break;
#ifdef DEMO_COMPAT_100
case 0x0001:
+1 -1
View File
@@ -98,7 +98,7 @@ void G_SetDemoTime(UINT32 ptime, UINT32 plap);
UINT8 G_CmpDemoTime(char *oldname, char *newname);
void G_LoadDemoInfo(menudemo_t *pdemo);
void G_LoadDemoTitle(menudemo_t *pdemo); // For use in replay search feature
void G_LoadDemoTitle(menudemo_t *pdemo, const char *dateformat); // For use in replay search feature
void G_DeferedPlayDemo(const char *demo);
typedef enum
+39 -62
View File
@@ -17,14 +17,9 @@
#include "g_game.h"
#include "keys.h"
#include "hu_stuff.h" // need HUFONT start & end
#include "d_net.h"
#include "console.h"
#include "m_menu.h"
#include "i_system.h"
#include "i_video.h"
#include "r_draw.h"
#include "v_video.h"
#define MAXMOUSESENSITIVITY 100 // sensitivity steps
@@ -36,10 +31,11 @@ static CV_PossibleValue_t turnsmooth_cons_t[] = {{2, "Slow"}, {1, "Fast"}, {0, "
// mouse values are used once
consvar_t cv_mousexsens = {"mousexsens", "20", CV_SAVE, mousesens_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_mouseysens = {"mouseysens", "20", CV_SAVE, mousesens_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_controlperkey = {"controlperkey", "One", CV_SAVE, onecontrolperkey_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_turnsmooth[MAXSPLITSCREENPLAYERS] = {
{"turnsmoothing", "Slow", CV_SAVE, turnsmooth_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL},
{"turnsmoothing", "Slow", CV_SAVE, turnsmooth_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL},
{"turnsmoothing2", "Slow", CV_SAVE, turnsmooth_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL},
{"turnsmoothing3", "Slow", CV_SAVE, turnsmooth_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL},
{"turnsmoothing4", "Slow", CV_SAVE, turnsmooth_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL}
@@ -81,6 +77,7 @@ consvar_t cv_rumble_##type [MAXSPLITSCREENPLAYERS] = {\
{"rumble4_" #type, "On", CV_SAVE, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL}\
};
IMPL_RUMBLE_TYPE(wallbonk);
IMPL_RUMBLE_TYPE(spinout);
IMPL_RUMBLE_TYPE(sneakerboost);
IMPL_RUMBLE_TYPE(offroad);
@@ -89,7 +86,6 @@ IMPL_RUMBLE_TYPE(stairjank);
IMPL_RUMBLE_TYPE(brakedrift);
IMPL_RUMBLE_TYPE(driftcharge);
static CV_PossibleValue_t gamepadled_cons_t[] = {{0, "Off"}, {1, "Skincolor"}, {2, "Mobjcolor"}, {0, NULL}};
consvar_t cv_gamepadled[MAXSPLITSCREENPLAYERS] = {
{"gamepadled", "Skincolor", CV_SAVE|CV_CALL|CV_NOINIT, gamepadled_cons_t, led_off_handle, 0, NULL, NULL, 0, 0, NULL},
@@ -195,7 +191,6 @@ void G_MapEventsToControls(event_t *ev)
{
CONS_Debug(DBG_GAMELOGIC, "Bad downkey input %d\n",ev->data1);
}
#endif
break;
@@ -951,16 +946,15 @@ void G_SetPlayerGamepadIndicatorColor(INT32 playernum, UINT8 color)
I_Assert(playernum >= 0 && playernum < MAXSPLITSCREENPLAYERS);
if (cv_gamepadled[playernum].value == 0 || (window_notinfocus && cv_gamepadledifunfocused.value == 0)
|| color >= MAXTRANSLATIONS)
if (cv_gamepadled[playernum].value == 0 ||
(window_notinfocus && cv_gamepadledifunfocused.value == 0) ||
color >= MAXTRANSLATIONS)
{
return;
}
if (!I_GamepadHasLED(playernum))
{
return;
}
// so we can override this
skincolor = color ? color : G_GetSkinColorForGamepad(playernum);
@@ -990,29 +984,21 @@ void G_DeviceLEDTick(void)
UINT8 i, newcolor;
if (numcontrollers == 0)
{
return;
}
for (i = 0; i <= splitscreen; i++)
{
if (!cv_usejoystick[i].value || !cv_gamepadled[i].value)
{
continue;
}
// does not have a configurable led! :c
if (!I_GamepadHasLED(i))
{
continue;
}
newcolor = G_GetSkinColorForGamepad(i);
if (curcolor[i] == newcolor) // dont update if same colour
{
continue;
}
G_SetPlayerGamepadIndicatorColor(i, newcolor);
curcolor[i] = newcolor;
@@ -1046,9 +1032,7 @@ void G_PlayerDeviceRumble(INT32 playernum, UINT16 low_strength, UINT16 high_stre
I_Assert(playernum >= 0 && playernum < MAXSPLITSCREENPLAYERS);
if (cv_rumble[playernum].value == 0 || (window_notinfocus && cv_rumbleifunfocused.value == 0))
{
return;
}
// doesent need to be super precise
// but ensure this is within range (0-65535)
@@ -1077,46 +1061,34 @@ void G_DeviceRumbleTick(void)
UINT8 i;
if (dedicated || numcontrollers == 0 || gamestate != GS_LEVEL || demo.playback)
{
return;
}
for (i = 0; i <= splitscreen; i++)
{
if (!cv_usejoystick[i].value || !cv_rumble[i].value)
{
continue;
}
// does not support rumble! :c
if (!I_GamepadHasRumble(i))
{
continue;
}
if (camera[i].freecam)
{
continue;
}
// SDL rumble strength goes from a range or 0-65535 respectively
// the higher, the stronger it is
UINT16 low = 0, high = 0;
// for how long the action should rumble, in ms
UINT16 lenght = 57; // 57ms is a short pulse, matches super well with this updating once per tic
UINT16 length = 57; // 57ms is a short pulse, matches super well with this updating once per tic
const player_t *player = P_GetLocalPlayerForNum(i);
if (!player)
{
continue;
}
// allow lua to do some crap for spectators
if (player->spectator || !player->mo)
{
continue;
}
// reset the rumble if you exit or are ded lel
if (player->exiting ||
@@ -1127,21 +1099,28 @@ void G_DeviceRumbleTick(void)
continue;
}
if (cv_rumble_spinout[i].value
&& player->kartstuff[k_spinouttimer])
if (cv_rumble_wallbonk[i].value &&
(player->mo->eflags & MFE_JUSTBOUNCEDWALL))
{
high = RUMBLE_STRONG;
low = RUMBLE_MODERATE;
}
else if (cv_rumble_spinout[i].value &&
player->kartstuff[k_spinouttimer])
{
//low = high = FRACUNIT / 6;
low = high = FixedMul((RUMBLE_VERYSTRONG), (FixedDiv(player->kartstuff[k_spinouttimer], (3*TICRATE / 2)))); // try do some some kinda fadeout, 3*TICRATE / 2 is the "default" spinout time
// try do some some kinda fadeout, 3*TICRATE / 2 is the "default" spinout time
low = high = FixedMul(RUMBLE_VERYSTRONG, FixedDiv(player->kartstuff[k_spinouttimer], (3*TICRATE / 2)));
}
else if (cv_rumble_sneakerboost[i].value
&& (player->kartstuff[k_sneakertimer] > (sneakertime-(TICRATE/2))))
else if (cv_rumble_sneakerboost[i].value &&
(player->kartstuff[k_sneakertimer] > (sneakertime-(TICRATE/2))))
{
low = high = RUMBLE_STRONG;
}
else if (cv_rumble_offroad[i].value
&& (player->kartstuff[k_offroad])
&& (player->speed != 0)
&& P_IsObjectOnGround(player->mo))
else if (cv_rumble_offroad[i].value &&
(player->kartstuff[k_offroad]) &&
(player->speed != 0) &&
P_IsObjectOnGround(player->mo))
{
// weaken this depending on if you got hyu or invinc
if (player->kartstuff[k_hyudorotimer])
@@ -1157,50 +1136,48 @@ void G_DeviceRumbleTick(void)
low = high = RUMBLE_MODERATE;
}
}
else if (cv_rumble_bananadrag[i].value
&& (player->kartstuff[k_bananadrag] > TICRATE)
&& (player->speed != 0)
&& P_IsObjectOnGround(player->mo))
else if (cv_rumble_bananadrag[i].value &&
(player->kartstuff[k_bananadrag] > TICRATE) &&
(player->speed != 0) &&
P_IsObjectOnGround(player->mo))
{
if (leveltime & 1) // this is actually funny lel
high = RUMBLE_MODERATE;
}
else if (cv_rumble_stairjank[i].value
&& (player->stairjank > 8)
&& (player->speed != 0)
&& P_IsObjectOnGround(player->mo))
else if (cv_rumble_stairjank[i].value &&
(player->stairjank > 8) &&
(player->speed != 0) &&
P_IsObjectOnGround(player->mo))
{
low = high = RUMBLE_VERYWEAK;
}
if (cv_rumble_brakedrift[i].value
&& player->kartstuff[k_brakedrift])
if (cv_rumble_brakedrift[i].value &&
player->kartstuff[k_brakedrift])
{
high = CLAMP((high + RUMBLE_VERYWEAK), 0, UINT16_MAX);
}
// pulse when gettin new driftlevel
// let this come last
if (cv_rumble_driftcharge[i].value
&& player->kartstuff[k_driftcharge]
&& player->driftlevel)
if (cv_rumble_driftcharge[i].value &&
player->kartstuff[k_driftcharge] &&
player->driftlevel)
{
high = CLAMP((high + RUMBLE_VERYWEAK), 0, UINT16_MAX);
// make it rumble slightly longer the higher your driftlevel!
if (player->driftlevel == 2)
lenght = 114;
length = 114;
else if (player->driftlevel == 3)
lenght = 174;
length = 174;
}
// hack alert! i just dont want this thing constantly resetting the rumble lol
if (low == 0 && high == 0)
{
continue;
}
G_PlayerDeviceRumble(i, low, high, lenght);
G_PlayerDeviceRumble(i, low, high, length);
}
}
+2
View File
@@ -118,6 +118,8 @@ extern consvar_t cv_gamepadled[MAXSPLITSCREENPLAYERS];
extern consvar_t cv_rumble[MAXSPLITSCREENPLAYERS];
extern consvar_t cv_rumble_strength[MAXSPLITSCREENPLAYERS];
// rumble types
extern consvar_t cv_rumble_wallbonk[MAXSPLITSCREENPLAYERS];
extern consvar_t cv_rumble_spinout[MAXSPLITSCREENPLAYERS];
extern consvar_t cv_rumble_sneakerboost[MAXSPLITSCREENPLAYERS];
extern consvar_t cv_rumble_offroad[MAXSPLITSCREENPLAYERS];
+111 -30
View File
@@ -54,10 +54,6 @@ typedef struct {
// if no portals are found, the portal scanning phase can be skipped while rendering, saving a bit of time.
boolean gl_maphasportals = false;
// Determine on mapload if current map has any Horizonlines present
// avoids doing a bunch of work during rendering
boolean gl_maphashorizonlines = false;
// ==========================================================================
// FLOOR & CEILING CONVEX POLYS GENERATION
// ==========================================================================
@@ -96,7 +92,7 @@ static void HWR_FreePoly(poly_t *poly)
// divfrac = how far along partline vector is crossing pt
static boolean fracdivline(fdivline_t *partline, polyvertex_t *v1, polyvertex_t *v2)
{
double frac1, frac2;
double frac;
double num; // numerator
double den; // denominator
double v1x, v1y, v1dx, v1dy; // polygon side vector, v1->v2
@@ -122,24 +118,23 @@ static boolean fracdivline(fdivline_t *partline, polyvertex_t *v1, polyvertex_t
// first check the frac along the polygon segment,
// (do not accept hit with the extensions)
num = (v3x - v1x)*v3dy + (v1y - v3y)*v3dx;
frac1 = num / den;
frac = num / den;
// 0= cross at v1, 1.0= cross at v2
if (frac1 < 0.0 || frac1 > 1.0) // double
if (frac < 0.0 || frac > 1.0) // double
return false; // not within the polygon side
// now get the frac along the BSP line
// which is useful to determine what is left, what is right
num = (v3x - v1x)*v1dy + (v1y - v3y)*v1dx;
frac2 = num / den;
partline->divfrac = frac2; // how far along partline vector
partline->divfrac = num / den; // how far along partline vector
// [WDJ] find the interception point along the segment.
// It should be slightly more accurate because it is always closer to the
// crossing point than arbitrary positions on the partition line.
partline->divpt.x = v1x + v1dx*frac1;
partline->divpt.y = v1y + v1dy*frac1;
partline->divpt.x = v1x + v1dx*frac;
partline->divpt.y = v1y + v1dy*frac;
return true;
}
@@ -161,6 +156,71 @@ static boolean SameVertex(polyvertex_t *p1, polyvertex_t *p2)
return true;
}
// Adapted from function in prboom.
// Point is to rightside of divline when result > 0,
// but result is multiplied by length of divline.
// Returns near 0, when point is on, or nearly on, the divline.
static inline double point_rightside(fdivline_t *dl, polyvertex_t *v4)
{
// Cross product of dl and vector dl->(x,y) to v4,
// is > 0 when v4 is to right side of divline.
// Viewed along divline from vertex, looking towards positive dx,dy.
// If divline is rotated until dy>0 and dx = 0, then true when rotated
// vertex position is to the right of the divline (v4->x > dl->x).
return ((((double)(v4->x) - (double)(dl->x)) * (double)(dl->dy))
- (((double)(v4->y) - (double)(dl->y)) * (double)(dl->dx)));
}
// [WDJ] The front and back MUST match the BSP determination, else it will assign
// this poly to the wrong sector.
// May have 1 point on the line, and other points might be very close to the line.
// Can only trust a test of a point that is NOT on the line.
// Using a tstdist = 0.5f worked, but it might break on very small poly.
// Avactor.wad had polys with d = 9.09, 5552, 1.64, 1011, 14252, 0.0136, 0.00634, 14655, 3,
// -0.3044, 7, 1.53, etc..,
// and one poly with d = -0.023 with the rest of the points d > 0.
// One 14 point poly with divline len=8, had to test 9 points to find d = 36.
// Typical: divline len=70 d=6828, divline len=1.0 d=35, divline len=1.414 d=5.
// The result of point_rightside is proportional to the length of divline.
// The divline length can be from 1.414 to 14000.
static void UnsplitPoly(fdivline_t *dlnp, poly_t *poly,
poly_t **frontpoly, poly_t **backpoly)
{
int32_t i;
double d;
const double tstd = hypot((double)dlnp->dx, (double)dlnp->dy) / 2.0;
double sumd = 0; // accumulated left or rightness.
for (i = 0; i < poly->numpts; i++)
{
// Look for a point that is obviously to the left or right.
d = point_rightside(dlnp, &poly->pts[i]); // d > 0 is right
sumd += d;
if (d > tstd)
goto poly_rightside;
if (d < -tstd)
goto poly_leftside;
}
// Did not find an obvious left or right point, then
if (sumd < 0)
goto poly_leftside;
poly_rightside:
// poly is to rightside of divline.
*frontpoly = poly;
*backpoly = NULL;
return;
poly_leftside:
// poly is to leftside of divline.
*frontpoly = NULL;
*backpoly = poly;
return;
}
// split a _CONVEX_ polygon in two convex polygons
// outputs:
// frontpoly : polygon on right side of bsp line
@@ -263,10 +323,7 @@ static void SplitPoly (fdivline_t *dlnp, // splitting parametric line
// linedefs where each side point the same sector, that is:
// the deep water effect with the original Doom
//TODO: make sure front poly is to front of partition line?
*frontpoly = poly;
*backpoly = NULL;
UnsplitPoly(dlnp, poly, frontpoly, backpoly);
return;
}
@@ -274,16 +331,14 @@ static void SplitPoly (fdivline_t *dlnp, // splitting parametric line
if (pe < 0)
{
//I_Error("SplitPoly: only one point for split line (%d %d)", ps, pe);
*frontpoly = poly;
*backpoly = NULL;
UnsplitPoly(dlnp, poly, frontpoly, backpoly);
return;
}
if (pe <= ps)
{
//I_Error("SplitPoly: invalid splitting line (%d %d)", ps, pe);
*frontpoly = poly;
*backpoly = NULL;
UnsplitPoly(dlnp, poly, frontpoly, backpoly);
return;
}
@@ -346,7 +401,7 @@ static void SplitPoly (fdivline_t *dlnp, // splitting parametric line
}
// checks if any line is a portal or horizonline, for optimization
static inline void CheckForPortalsAndHorizonLines(boolean firstside, const line_t *line)
static inline void CheckForPortalsAndHorizonLines(boolean firstside, const line_t *line, subsector_t *sub)
{
// portal check
if (!gl_maphasportals && firstside && line->special == PORTALSPECIAL)
@@ -362,8 +417,8 @@ static inline void CheckForPortalsAndHorizonLines(boolean firstside, const line_
}
// horizonline check
if (!gl_maphashorizonlines && line->special == HORIZONSPECIAL)
gl_maphashorizonlines = true;
if (line->special == HORIZONSPECIAL)
sub->hashorizon = true;
}
// Use each seg of the poly as a partition line, keep only the
@@ -376,7 +431,7 @@ static inline void CheckForPortalsAndHorizonLines(boolean firstside, const line_
// segcount : number of seg in the array
// Return frontpoly, which may be new or ptr to poly.
// Called from: HWR_SubsecPoly
static poly_t *CutOutSubsecPoly(seg_t *lseg, INT32 segcount, poly_t *poly)
static poly_t *CutOutSubsecPoly(seg_t *lseg, INT32 segcount, poly_t *poly, subsector_t *sub)
{
INT32 i, j;
poly_t* frontpoly = poly; // default, return same poly
@@ -397,7 +452,7 @@ static poly_t *CutOutSubsecPoly(seg_t *lseg, INT32 segcount, poly_t *poly)
if (!line)
continue;
CheckForPortalsAndHorizonLines(lseg->side == 0, line);
CheckForPortalsAndHorizonLines(lseg->side == 0, line, sub);
if (line->sidenum[1] != NO_INDEX)
{
@@ -489,6 +544,23 @@ static poly_t *CutOutSubsecPoly(seg_t *lseg, INT32 segcount, poly_t *poly)
// need 2 points
if (pe >= 0)
{
// Cuts that miss the polygon.
if (ps_frac < 0.0 && cutseg.divfrac < 0.0)
continue;
if (ps_frac > 1.0 && cutseg.divfrac > 1.0)
continue;
#define FRAC_EP 0.01f
// Reject cuts that could make the polygon non-convex.
// Cannot make normal cut, ps_frac end is loose.
if ((ps_frac < (0.0 - FRAC_EP)) || (ps_frac > (1.0f + FRAC_EP)))
continue;
// Cannot make normal cut, cutseg.divfrac end is loose.
if ((cutseg.divfrac < (0.0 - FRAC_EP)) || (cutseg.divfrac > (1.0f + FRAC_EP)))
continue;
#undef FRAC_EP
// generate FRONT poly
frontpoly = HWR_AllocPoly(poly_num_pts);
@@ -543,7 +615,7 @@ static inline void HWR_SubsecPoly(INT32 ssindex, poly_t *poly)
if (poly)
{
poly = CutOutSubsecPoly(lseg, segcount, poly);
poly = CutOutSubsecPoly(lseg, segcount, poly, sub);
#ifdef DEBUG_HWBSP
totalsubsecpolys++;
#endif
@@ -672,7 +744,7 @@ static void WalkBSPNode(INT32 bspnum, poly_t *poly, UINT16 *leafnode, fixed_t *b
#endif
// Recursively divide front space.
if (LIKELY(frontpoly))
if (frontpoly)
{
WalkBSPNode(bsp->children[0], frontpoly, &bsp->children[0],bsp->bbox[0]);
@@ -680,7 +752,11 @@ static void WalkBSPNode(INT32 bspnum, poly_t *poly, UINT16 *leafnode, fixed_t *b
memcpy(bbox, bsp->bbox[0], 4*sizeof (fixed_t));
}
else
I_Error("WalkBSPNode: no front poly?");
{
// [WDJ] Having no front poly is as likely as no back poly, since
// logic in Split Poly was changed to check poly direction.
// I_Error("HWR_WalkBSPNode: no front poly, bspnum= %d\n", bspnum);
}
// Recursively divide back space.
if (backpoly)
@@ -795,7 +871,9 @@ static boolean PointInSeg(polyvertex_t *va, polyvertex_t *v1, polyvertex_t *v2)
#endif
}
#ifdef DEBUG_HWBSP
static INT32 numsplitpoly;
#endif
static void SearchSegInBSP(INT32 bspnum, polyvertex_t *p, poly_t *poly)
{
@@ -834,8 +912,9 @@ static void SearchSegInBSP(INT32 bspnum, polyvertex_t *p, poly_t *poly)
for (n = k+1; n < newpoly->numpts; n++)
newpoly->pts[n] = q->pts[n-1];
#ifdef DEBUG_HWBSP
numsplitpoly++;
#endif
extrasubsectors[bspnum].planepoly = newpoly;
HWR_FreePoly(q);
return;
@@ -881,7 +960,9 @@ static void SolveTProblem(void)
I_FinishUpdate(); // page flip or blit buffer
#endif
#ifdef DEBUG_HWBSP
numsplitpoly = 0;
#endif
for (ssnum = 0; ssnum < num_extra_subsector; ssnum++)
{
@@ -918,8 +999,8 @@ void HWR_CreatePlanePolygons(INT32 bspnum)
I_FinishUpdate(); // page flip or blit buffer
#endif
// reset the portal and horizonline flag
gl_maphasportals = gl_maphashorizonlines = false;
// reset the portal flag
gl_maphasportals = false;
// find min/max boundaries of map
#ifdef DEBUG_HWBSP
+19 -40
View File
@@ -614,24 +614,12 @@ void HWR_FreeMapTextures(void)
gl_numtextures = 0;
}
#define NAME flatcheck
#define KEY_TY UINT32
#define HASH_FN vt_hash_integer
#define CMPR_FN vt_cmpr_integer
#include "../verstable.h"
static void HWR_PrecacheLevelFlats(void)
{
// lookup for flats that may´ve been already loaded
flatcheck flatpresent;
size_t i;
#if 0
size_t j;
#endif
INT32 k;
// this kinda messes up encore remapping behavior at times
// so just disable it for now ig
// FIXME: this needs to account for FOFs to properly work
#ifdef GLENCORE
if (encoremap)
{
@@ -639,9 +627,6 @@ static void HWR_PrecacheLevelFlats(void)
}
#endif
flatcheck_init(&flatpresent);
flatcheck_reserve(&flatpresent, numlevelflats);
// special case for encore
#if 0
#ifdef GLENCORE
@@ -650,6 +635,7 @@ static void HWR_PrecacheLevelFlats(void)
// go through all sectors to determine if it should be remapped for encore
for (i = 0; i < numsectors; i++)
{
size_t j;
sector_t *sec = &sectors[i];
// gotta check sector floor and ceiling
@@ -692,11 +678,7 @@ static void HWR_PrecacheLevelFlats(void)
{
const levelflat_t *levelflat = &levelflats[i];
if (flatcheck_is_end(flatcheck_get(&flatpresent, levelflat->lumpnum)))
{
HWR_GetFlat(levelflat->lumpnum, false);
flatcheck_insert(&flatpresent, levelflat->lumpnum);
}
HWR_GetFlat(levelflat->lumpnum, false);
if (levelflat->speed) // is it an animated flat ?
{
@@ -704,17 +686,11 @@ static void HWR_PrecacheLevelFlats(void)
for (k = 0; k < levelflat->numpics; k++)
{
lumpnum_t lump = levelflat->baselumpnum + k;
if (flatcheck_is_end(flatcheck_get(&flatpresent, lump)))
{
HWR_GetFlat(lump, false);
flatcheck_insert(&flatpresent, lump);
}
HWR_GetFlat(lump, false);
}
}
}
}
flatcheck_cleanup(&flatpresent);
}
static void HWR_PrecacheLevelTextures(void)
@@ -738,7 +714,7 @@ static void HWR_PrecacheLevelTextures(void)
{
const line_t *line = &lines[i];
#ifdef GLENCORE
const int noencoremap = ((encoremap && (line->flags & ML_TFERLINE)) ? 2 : 1);
const boolean noencoremap = (encoremap && (line->flags & ML_TFERLINE));
#endif
// two sides
for (j = 0; j < 2; j++)
@@ -755,25 +731,27 @@ static void HWR_PrecacheLevelTextures(void)
{
const INT32 texnum = sidetex[f];
if (texnum < 0 || texnum >= (signed)gl_numtextures)
if (texnum <= 0 || (unsigned)texnum >= gl_numtextures)
continue;
if (texturepresent[texnum])
continue;
if (!(texturepresent[texnum] & 1))
{
texturepresent[texnum] |= 1;
HWR_GetTexture(texnum, false);
}
#ifdef GLENCORE
texturepresent[texnum] = 1|noencoremap;
#else
texturepresent[texnum] = 1;
#endif
HWR_GetTexture(texnum, false);
#ifdef GLENCORE
if (noencoremap & 2)
if (noencoremap
&& !(texturepresent[texnum] & 2))
{
texturepresent[texnum] |= 2;
HWR_GetTexture(texnum, true);
}
#endif
}
}
}
// check for animated textures
for (anim = anims; anim < lastanim; anim++)
{
if (!anim->istexture)
@@ -792,6 +770,7 @@ static void HWR_PrecacheLevelTextures(void)
{
HWR_GetTexture(animtexnum, false);
}
#ifdef GLENCORE
if (texpresent & 2)
{
@@ -913,7 +892,7 @@ GLMapTexture_t *HWR_GetTexture(INT32 tex, boolean noencore)
GLMapTexture_t *gltex;
GLMipmap_t *glMipmap;
if (tex < 0 || tex >= (signed)gl_numtextures)
if (tex < 0 || (unsigned)tex >= gl_numtextures)
{
#ifdef PARANOIA
I_Error("HWR_GetTexture: Invalid texture ID %d", tex);
+6
View File
@@ -196,6 +196,12 @@ enum
SHADER_PALETTE_POSTPROCESS,
SHADER_UI_COLORMAP_FADE,
SHADER_POSTPROCESS_WATER,
SHADER_POSTPROCESS_HEAT,
SHADER_VHS_FUZZ,
SHADER_VHS_BAR,
NUMSHADERTARGETS
};
+2 -1
View File
@@ -66,10 +66,11 @@ void GL_FlushScreenTextures(void);
void GL_DrawScreenTexture(int tex, FSurfaceInfo *surf, FBITFIELD polyflags);
void GL_DoScreenWipe(int wipeStart, int wipeEnd);
void GL_RenderVhsEffect(fixed_t upbary, fixed_t downbary, UINT8 updistort, UINT8 downdistort, UINT8 barsize);
void GL_RenderVhsEffect(fixed_t upbary, fixed_t downbary, UINT8 updistort, UINT8 downdistort, UINT8 barsize, boolean rewind);
void GL_DrawScreenFinalTexture(int tex, INT32 width, INT32 height);
void GL_PostImgRedraw(float points[SCREENVERTS][SCREENVERTS][2]);
void GL_DoPostProcessor(INT32 type);
boolean GL_InitShaders(void);
void GL_LoadShader(int slot, char *code, hwdshaderstage_t stage);
+406 -97
View File
@@ -16,6 +16,7 @@
#include <algorithm>
#include <vector>
#include "../d_main.h"
#include "../doomstat.h"
#include "../doomdef.h"
@@ -120,7 +121,7 @@ ps_metric_t ps_hw_batchdrawtime = {};
static void HWR_SplitWall(sector_t *sector, FOutVector *wallVerts, INT32 texnum, boolean noencore, FSurfaceInfo* Surf, INT32 cutflag, ffloor_t *pfloor, FBITFIELD polyflags);
static void HWR_RenderWall(FOutVector *wallVerts, FSurfaceInfo *pSurf, FBITFIELD blend, boolean fogwall, INT32 lightlevel, extracolormap_t *wallcolormap);
static void HWR_AddTransparentFloor(lumpnum_t lumpnum, extrasubsector_t *xsub, boolean isceiling, fixed_t fixedheight, INT32 lightlevel, INT32 alpha, sector_t *FOFSector, FBITFIELD blend, boolean fogplane, extracolormap_t *planecolormap);
static void HWR_AddTransparentFloor(lumpnum_t lumpnum, extrasubsector_t *xsub, boolean isceiling, fixed_t fixedheight, INT32 lightlevel, INT32 alpha, sector_t *FOFSector, FBITFIELD blend, boolean fogplane, extracolormap_t *planecolormap, subsector_t *subsector);
static void HWR_AddTransparentWall(FOutVector *wallVerts, FSurfaceInfo *pSurf, INT32 texnum, boolean noencore, FBITFIELD blend, boolean fogwall, INT32 lightlevel, extracolormap_t *wallcolormap);
static void HWR_AddTransparentPolyobjectFloor(lumpnum_t lumpnum, polyobj_t *polysector, boolean isceiling, fixed_t fixedheight, INT32 lightlevel, INT32 alpha, sector_t *FOFSector, FBITFIELD blend, extracolormap_t *planecolormap);
@@ -204,7 +205,8 @@ static CV_PossibleValue_t glpalettedepth_cons_t[] = {{16, "16 bits"}, {24, "24 b
consvar_t cv_glscreentextures = {"gr_screentextures", "All", CV_CALL|CV_SAVE, glscreentextures_cons_t, CV_screentextures_OnChange, 0, NULL, NULL, 0, 0, NULL};
#ifdef USE_FBO_OGL
consvar_t cv_glframebuffer = {"gr_framebuffer", "Off", CV_SAVE|CV_CALL|CV_NOINIT, CV_OnOff, CV_glframebuffer_OnChange, 0, NULL, NULL, 0, 0, NULL};
static CV_PossibleValue_t glframebuffer_cons_t[] = {{0, "Off"}, {1, "Downsample"}, {2, "Always"}, {0, NULL}};
consvar_t cv_glframebuffer = {"gr_framebuffer", "Off", CV_SAVE|CV_CALL, glframebuffer_cons_t, CV_glframebuffer_OnChange, 0, NULL, NULL, 0, 0, NULL};
#endif
consvar_t cv_glmdls = {"gr_mdls", "Off", CV_SAVE|CV_CALL, CV_OnOff, M_UpdateOGLMenu, 0, NULL, NULL, 0, 0, NULL};
@@ -255,6 +257,7 @@ static void CV_screentextures_OnChange(void)
#endif
intermissionbginit = false;
}
GL_SetSpecialState(HWD_SET_SCREEN_TEXTURES, cv_glscreentextures.value);
M_UpdateOGLMenu();
}
@@ -263,12 +266,11 @@ static void CV_screentextures_OnChange(void)
static void CV_glframebuffer_OnChange(void)
{
ONLY_IF_GL_LOADED
if ((cv_glframebuffer.value != 0 && cv_glscreentextures.value != 2)
|| (!supportFBO && cv_glframebuffer.value != 0)) // screen FBO needs screen textures
CV_SetValue(&cv_glframebuffer, 0);
I_DownSample();
RefreshOGLSDLSurface();
// screen FBO needs screen textures currently
if (cv_glframebuffer.value != 0 && ((cv_glscreentextures.value != 2) || !supportFBO))
CV_StealthSetValue(&cv_glframebuffer, 0); // dont recursively call this lul
if (loaded_config) // dont do this crap on startup, this is handled elsewhere
I_CheckDownSampleState(true);
M_UpdateOGLMenu();
intermissionbginit = false;
}
@@ -610,7 +612,7 @@ static void HWR_RenderPlane(subsector_t *subsector, extrasubsector_t *xsub, bool
fflatsize = 1024.0f;
flatflag = 1023;
break;
case 262144:// 512x512 lump
case 262144: // 512x512 lump
fflatsize = 512.0f;
flatflag = 511;
break;
@@ -721,7 +723,7 @@ static void HWR_RenderPlane(subsector_t *subsector, extrasubsector_t *xsub, bool
HWR_ProcessPolygon(&Surf, planeVerts, nrPlaneVerts, PolyFlags, shader, false);
if (gl_maphashorizonlines && subsector && cv_glhorizonlines.value)
if (subsector && subsector->hashorizon && cv_glhorizonlines.value)
{
// Horizon lines
FOutVector horizonpts[6];
@@ -742,7 +744,6 @@ static void HWR_RenderPlane(subsector_t *subsector, extrasubsector_t *xsub, bool
line_t* ld = line->linedef;
// this check sucks and is a hotspot lel
if (LIKELY(ld->special != HORIZONSPECIAL))
continue;
@@ -807,6 +808,268 @@ static void HWR_RenderPlane(subsector_t *subsector, extrasubsector_t *xsub, bool
#undef SETUP3DVERT
}
static void HWR_RenderFOFHorizonPlane(subsector_t *subsector, extrasubsector_t *xsub, boolean isceiling, fixed_t fixedheight, FBITFIELD PolyFlags, INT32 lightlevel, lumpnum_t lumpnum, sector_t *FOFsector, UINT8 alpha, extracolormap_t *planecolormap)
{
FSurfaceInfo Surf = {};
polyvertex_t *pv;
pslope_t *slope = NULL;
INT32 shader = SHADER_NONE;
size_t nrPlaneVerts;
INT32 i;
float height; // constant y for all points on the convex flat polygon
static float flatxref = 0.0f, flatyref = 0.0f;
static float fflatsize = 64.0f;
static INT32 flatflag = 63;
size_t len;
float tempxsow, tempytow;
float scrollx = 0.0f, scrolly = 0.0f;
float anglef = 0.0f, cosangf = 0.0f, sinangf = 0.0f;
angle_t angle = 0;
static FOutVector *planeVerts = NULL;
static UINT16 numAllocedPlaneVerts = 0;
poly_t *planepoly = xsub->planepoly;
if (!cv_glhorizonlines.value)
return;
if (!subsector || !subsector->hashorizon)
return;
// no convex poly were generated for this subsector
if (!planepoly)
return;
nrPlaneVerts = planepoly->numpts;
if (nrPlaneVerts < 3) // not even a triangle ?
return;
const sector_t *sec = FOFsector;
if (!(PolyFlags & PF_NoTexture))
{
HWR_GetFlat(lumpnum, R_NoEncore(FOFsector, !isceiling));
}
// Get the slope pointer to simplify future code
if (!isceiling && sec->f_slope)
slope = sec->f_slope;
else if (isceiling && sec->c_slope)
slope = sec->c_slope;
height = FixedToFloat(fixedheight);
// Allocate plane-vertex buffer if we need to
if (!planeVerts || nrPlaneVerts > numAllocedPlaneVerts)
{
numAllocedPlaneVerts = (UINT16)nrPlaneVerts;
Z_Free(planeVerts);
Z_Malloc(numAllocedPlaneVerts * sizeof (FOutVector), PU_LEVEL, &planeVerts);
}
len = W_LumpLength(lumpnum);
switch (len)
{
case 4194304: // 2048x2048 lump
fflatsize = 2048.0f;
flatflag = 2047;
break;
case 1048576: // 1024x1024 lump
fflatsize = 1024.0f;
flatflag = 1023;
break;
case 262144: // 512x512 lump
fflatsize = 512.0f;
flatflag = 511;
break;
case 65536: // 256x256 lump
fflatsize = 256.0f;
flatflag = 255;
break;
case 16384: // 128x128 lump
fflatsize = 128.0f;
flatflag = 127;
break;
case 1024: // 32x32 lump
fflatsize = 32.0f;
flatflag = 31;
break;
default: // 64x64 lump
fflatsize = 64.0f;
flatflag = 63;
break;
}
pv = planepoly->pts;
// reference point for flat texture coord for each vertex around the polygon
flatxref = static_cast<float>(static_cast<fixed_t>(pv->x) & (~flatflag)) / fflatsize;
flatyref = static_cast<float>(static_cast<fixed_t>(pv->y) & (~flatflag)) / fflatsize;
if (!isceiling) // it's a floor
{
scrollx = FixedToFloat(sec->floor_xoffs)/fflatsize;
scrolly = FixedToFloat(sec->floor_yoffs)/fflatsize;
angle = sec->floorpic_angle;
}
else // it's a ceiling
{
scrollx = FixedToFloat(sec->ceiling_xoffs)/fflatsize;
scrolly = FixedToFloat(sec->ceiling_yoffs)/fflatsize;
angle = sec->ceilingpic_angle;
}
if (angle) // Only needs to be done if there's an altered angle
{
// This needs to be done so that it scrolls in a different direction after rotation like software
tempxsow = flatxref;
tempytow = flatyref;
anglef = ANG2RAD(InvAngle(angle));
// This needs to be done so everything aligns after rotation
// It would be done so that rotation is done, THEN the translation, but I couldn't get it to rotate AND scroll like software does
cosangf = cosf(anglef);
sinangf = sinf(anglef);
flatxref = (tempxsow * cosangf) - (tempytow * sinangf);
flatyref = (tempxsow * sinangf) + (tempytow * cosangf);
}
#define SETUP3DVERT(vert, vx, vy) {\
/* Hurdler: add scrolling texture on floor/ceiling */\
vert->s = (float)(((vx) / fflatsize) - flatxref + scrollx);\
vert->t = (float)(flatyref - ((vy) / fflatsize) + scrolly);\
\
/* Need to rotate before translate */\
if (angle) /* Only needs to be done if there's an altered angle */\
{\
tempxsow = vert->s;\
tempytow = vert->t;\
vert->s = (tempxsow * cosangf) - (tempytow * sinangf);\
vert->t = (tempxsow * sinangf) + (tempytow * cosangf);\
}\
\
if (slope)\
{\
fixedheight = P_GetSlopeZAt(slope, FloatToFixed((vx)), FloatToFixed((vy)));\
height = FixedToFloat(fixedheight);\
}\
\
vert->x = (vx);\
vert->y = height;\
vert->z = (vy);\
\
}
HWR_Lighting(&Surf, lightlevel, planecolormap, false);
if (PolyFlags & (PF_Translucent|PF_Fog|PF_Additive|PF_Subtractive|PF_ReverseSubtract|PF_Multiplicative|PF_Environment))
{
Surf.PolyColor.s.alpha = (UINT8)alpha;
PolyFlags |= PF_Modulated;
}
else
PolyFlags |= PF_Masked|PF_Modulated;
if (HWR_UseShader())
{
if (PolyFlags & PF_Fog)
shader = SHADER_FOG;
else if (cv_ripplewater.value && (PolyFlags & PF_Ripple))
shader = SHADER_WATER;
else
shader = SHADER_FLOOR;
PolyFlags |= PF_ColorMapped;
}
// Horizon lines
FOutVector horizonpts[6];
float dist, vx, vy;
float x1, y1, xd, yd;
UINT8 numplanes, j;
vertex_t v; // For determining the closest distance from the line to the camera, to split render planes for minimum distortion;
static constexpr float renderdist = 27000.0f; // How far out to properly render the plane
static constexpr float farrenderdist = 32768.0f; // From here, raise plane to horizon level to fill in the line with some texture distortion
const seg_t *line = &segs[subsector->firstline];
for (i = 0; i < subsector->numlines; i++, line++)
{
if (line->polyseg)
continue;
line_t* ld = line->linedef;
if (LIKELY(ld->special != HORIZONSPECIAL))
continue;
if (R_PointOnSegSide(viewx, viewy, line) != 0)
continue;
P_ClosestPointOnLine(viewx, viewy, ld, &v);
dist = FixedToFloat(R_PointToDist(v.x, v.y));
x1 = (line->fv1.x);
y1 = (line->fv1.y);
xd = (line->fv2.x) - x1;
yd = (line->fv2.y) - y1;
// Based on the seg length and the distance from the line, split horizon into multiple poly sets to reduce distortion
dist = sqrtf((xd*xd) + (yd*yd)) / dist / 16.0f;
if (dist > 100.0f)
numplanes = 100;
else
numplanes = (UINT8)dist + 1;
for (j = 0; j < numplanes; j++)
{
// Left side
vx = x1 + xd * j / numplanes;
vy = y1 + yd * j / numplanes;
SETUP3DVERT((&horizonpts[1]), vx, vy);
dist = sqrtf(powf(vx - gl_viewx, 2) + powf(vy - gl_viewy, 2));
vx = (vx - gl_viewx) * renderdist / dist + gl_viewx;
vy = (vy - gl_viewy) * renderdist / dist + gl_viewy;
SETUP3DVERT((&horizonpts[0]), vx, vy);
// Right side
vx = x1 + xd * (j+1) / numplanes;
vy = y1 + yd * (j+1) / numplanes;
SETUP3DVERT((&horizonpts[2]), vx, vy);
dist = sqrtf(powf(vx - gl_viewx, 2) + powf(vy - gl_viewy, 2));
vx = (vx - gl_viewx) * renderdist / dist + gl_viewx;
vy = (vy - gl_viewy) * renderdist / dist + gl_viewy;
SETUP3DVERT((&horizonpts[3]), vx, vy);
// Horizon fills
vx = (horizonpts[0].x - gl_viewx) * farrenderdist / renderdist + gl_viewx;
vy = (horizonpts[0].z - gl_viewy) * farrenderdist / renderdist + gl_viewy;
SETUP3DVERT((&horizonpts[5]), vx, vy);
horizonpts[5].y = gl_viewz;
vx = (horizonpts[3].x - gl_viewx) * farrenderdist / renderdist + gl_viewx;
vy = (horizonpts[3].z - gl_viewy) * farrenderdist / renderdist + gl_viewy;
SETUP3DVERT((&horizonpts[4]), vx, vy);
horizonpts[4].y = gl_viewz;
// Draw
HWR_ProcessPolygon(&Surf, horizonpts, 6, PolyFlags, shader, true);
}
}
#undef SETUP3DVERT
}
#ifdef WALLSPLATS
static void HWR_DrawSegsSplats(FSurfaceInfo * pSurf)
{
@@ -1240,46 +1503,44 @@ static inline boolean HWR_BlendMidtextureSurface(FSurfaceInfo *pSurf)
pSurf->PolyColor.s.alpha = 0xFF;
if (LIKELY(!gl_curline->polyseg))
{
// check if linedef alpha is within range
const boolean linealpha = (gl_linedef->alpha >= 0 && gl_linedef->alpha < FRACUNIT);
// check if linedef alpha is within range
const boolean linealpha = (gl_linedef->alpha >= 0 && gl_linedef->alpha < FRACUNIT);
// set alpha for transparent walls
switch (gl_linedef->special)
{
// Translucent linedef types
case 102:
case 121 ... 125:
case 141 ... 145:
case 174:
case 175:
case 192:
case 195:
case 221:
case 253:
case 256:
if (gl_linedef->blendmode && linealpha)
// set alpha for transparent walls
switch (gl_linedef->special)
{
// Translucent linedef types
case 102:
case 121 ... 125:
case 141 ... 145:
case 174:
case 175:
case 192:
case 195:
case 221:
case 253:
case 256:
if (gl_linedef->blendmode && linealpha)
blendmode = HWR_SurfaceBlend(gl_linedef->blendmode, R_GetLinedefTransTable(gl_linedef->alpha), pSurf);
else
blendmode = PF_Translucent;
break;
default:
if (gl_linedef->blendmode)
{
if (linealpha)
blendmode = HWR_SurfaceBlend(gl_linedef->blendmode, R_GetLinedefTransTable(gl_linedef->alpha), pSurf);
else
blendmode = PF_Translucent;
break;
default:
if (gl_linedef->blendmode)
{
if (linealpha)
blendmode = HWR_SurfaceBlend(gl_linedef->blendmode, R_GetLinedefTransTable(gl_linedef->alpha), pSurf);
else
blendmode = HWR_GetBlendModeFlag(gl_linedef->blendmode);
}
else if (linealpha)
blendmode = HWR_TranstableToAlpha(R_GetLinedefTransTable(gl_linedef->alpha), pSurf);
else
blendmode = PF_Masked;
break;
}
blendmode = HWR_GetBlendModeFlag(gl_linedef->blendmode);
}
else if (linealpha)
blendmode = HWR_TranstableToAlpha(R_GetLinedefTransTable(gl_linedef->alpha), pSurf);
else
blendmode = PF_Masked;
break;
}
else if (gl_curline->polyseg->translucency > 0)
if (gl_curline->polyseg && gl_curline->polyseg->translucency > 0)
{
// Polyobject translucency is shared between all of its lines
if (gl_curline->polyseg->translucency >= NUMTRANSMAPS) // wall not drawn
@@ -1386,7 +1647,8 @@ void HWR_ProcessSeg(void) // Sort of like GLWall::Process in GZDoom
// two sided line
if (gl_backsector)
{
INT32 gl_toptexture = 0, gl_bottomtexture = 0;
const INT32 gl_toptexture = R_GetTextureNum(gl_sidedef->toptexture);
const INT32 gl_bottomtexture = R_GetTextureNum(gl_sidedef->bottomtexture);
fixed_t texturevpeg;
@@ -1397,7 +1659,7 @@ void HWR_ProcessSeg(void) // Sort of like GLWall::Process in GZDoom
if (!gl_curline->polyseg) // Don't do it for polyobjects
{
// Sky Ceilings
wallVerts[3].y = wallVerts[2].y = FLOATMAX;
wallVerts[2].y = wallVerts[3].y = FLOATMAX; // draw to top of map space
auto draw_sky_walls = []
(int vert1, int vert2, fixed_t world, fixed_t worldslope, auto& wwallVerts, auto& sSurf) FUNCINLINE
@@ -1407,6 +1669,9 @@ void HWR_ProcessSeg(void) // Sort of like GLWall::Process in GZDoom
HWR_DrawSkyWall(wwallVerts, &sSurf);
};
// worldtop = front ceiling
// worldhigh = back ceiling
if (gl_frontsector->ceilingpic == skyflatnum)
{
if (gl_backsector->ceilingpic == skyflatnum)
@@ -1425,6 +1690,17 @@ void HWR_ProcessSeg(void) // Sort of like GLWall::Process in GZDoom
worldtop = worldhigh;
worldtopslope = worldhighslope;
}
else if (!gl_toptexture &&
(worldhigh <= worldtop && worldhighslope <= worldtopslope) && // Assuming ESLOPE is always on with my changes
(worldhigh != worldtop || worldhighslope != worldtopslope))
{
// Only the frontsector is sky.
// If there's no upper texture, extend the sky wall
// down to the lower of the two ceilings.
fixed_t top = std::min(worldtop, worldhigh);
fixed_t topslope = std::min(worldtopslope, worldhighslope);
draw_sky_walls(0, 1, top, topslope, wallVerts, Surf);
}
else
{
// Only the frontsector is sky, just draw a skywall from the front ceiling
@@ -1437,8 +1713,11 @@ void HWR_ProcessSeg(void) // Sort of like GLWall::Process in GZDoom
draw_sky_walls(0, 1, worldtop, worldtopslope, wallVerts, Surf);
}
// worldbottom = front floor
// worldlow = back floor
// Sky Floors
wallVerts[0].y = wallVerts[1].y = FLOATMIN;
wallVerts[0].y = wallVerts[1].y = FLOATMIN; // draw to bottom of map space
if (gl_frontsector->floorpic == skyflatnum)
{
@@ -1450,7 +1729,7 @@ void HWR_ProcessSeg(void) // Sort of like GLWall::Process in GZDoom
if ((worldlow >= worldbottom && worldlowslope >= worldbottomslope)
&& (worldlow != worldbottom || worldlowslope != worldbottomslope)
// Removing the second line above will render more rarely visible skywalls. Example: Cave garden ceiling in Dark race
&& !(gl_sidedef->bottomtexture))
&& !(gl_bottomtexture))
{
draw_sky_walls(3, 2, worldlow, worldlowslope, wallVerts, Surf);
}
@@ -1461,15 +1740,25 @@ void HWR_ProcessSeg(void) // Sort of like GLWall::Process in GZDoom
draw_sky_walls(3, 2, worldbottom, worldbottomslope, wallVerts, Surf);
}
}
else if ((gl_backsector->floorpic == skyflatnum) && !(gl_sidedef->bottomtexture))
else if ((gl_backsector->floorpic == skyflatnum) && !(gl_bottomtexture))
{
// Only the backsector has sky, just draw a skywall from the back floor if there's no bottomtexture
draw_sky_walls(3, 2, worldlow, worldlowslope, wallVerts, Surf);
}
else if (gl_frontsector->ceilingpic == skyflatnum &&
gl_backsector->ceilingpic == skyflatnum &&
(worldlow >= worldbottom && worldlowslope >= worldbottomslope)
&& (worldlow != worldbottom || worldlowslope != worldbottomslope)
// Removing the second line above will render more rarely visible skywalls. Example: Cave garden ceiling in Dark race
&& !(gl_bottomtexture))
{
// Both ceilings are sky, but neither floor is sky.
// If there's a lower wall gap without a bottom texture,
// draw a skywall from the backsector's higher floor.
draw_sky_walls(3, 2, worldlow, worldlowslope, wallVerts, Surf);
}
}
gl_toptexture = R_GetTextureNum(gl_sidedef->toptexture);
// check TOP TEXTURE
if (gl_toptexture && (worldhighslope < worldtopslope || worldhigh < worldtop))
{
@@ -1533,8 +1822,6 @@ void HWR_ProcessSeg(void) // Sort of like GLWall::Process in GZDoom
HWR_ProjectWall(wallVerts, &Surf, PF_Masked, lightnum, colormap);
}
gl_bottomtexture = R_GetTextureNum(gl_sidedef->bottomtexture);
// check BOTTOM TEXTURE
if (gl_bottomtexture && (worldlowslope > worldbottomslope || worldlow > worldbottom))
{
@@ -2937,16 +3224,14 @@ static void HWR_Subsector(size_t num)
UINT8 alpha;
light = R_GetPlaneLight(gl_frontsector, centerHeight, underside);
alpha = HWR_FogBlockAlpha(*gl_frontsector->lightlist[light].lightlevel, rover->master->frontsector->extra_colormap);
HWR_AddTransparentFloor(0,
&extrasubsectors[num],
!bottom,
roverheight,
*gl_frontsector->lightlist[light].lightlevel,
alpha, rover->master->frontsector, PF_Fog|PF_NoTexture,
true, rover->master->frontsector->extra_colormap);
true, rover->master->frontsector->extra_colormap, sub);
}
else if ((rover->flags & FF_TRANSLUCENT && rover->alpha < 256) || rover->blend) // SoM: Flags are more efficient
{
@@ -2958,13 +3243,12 @@ static void HWR_Subsector(size_t num)
roverheight,
*gl_frontsector->lightlist[light].lightlevel,
CLAMP(rover->alpha, 0, 255), rover->master->frontsector, HWR_RippleBlend(gl_frontsector, rover, false) | (rover->blend ? HWR_GetBlendModeFlag(rover->blend) : static_cast<FBITFIELD>(PF_Translucent)),
false, gl_frontsector->lightlist[light].extra_colormap);
false, gl_frontsector->lightlist[light].extra_colormap, sub);
}
else
{
HWR_GetFlat(flatlump, R_NoEncore(gl_frontsector, !bottom));
HWR_GetFlat(flatlump, R_NoEncore(rover->master->frontsector, bottom));
light = R_GetPlaneLight(gl_frontsector, centerHeight, underside);
HWR_RenderPlane(sub, &extrasubsectors[num], !bottom, roverheight, HWR_RippleBlend(gl_frontsector, rover, false)|PF_Occlude, *gl_frontsector->lightlist[light].lightlevel, flatlump,
rover->master->frontsector, 255, gl_frontsector->lightlist[light].extra_colormap);
}
@@ -3460,8 +3744,12 @@ static inline void HWR_ApplyDispoffset(gl_vissprite_t *spr, FOutVector *wallVert
{
HWR_RotateSpritePolyToAim(spr, wallVerts, false, papersprite);
const float sprdist = sqrtf((spr->x1 - gl_viewx)*(spr->x1 - gl_viewx) + (spr->z1 - gl_viewy)*(spr->z1 - gl_viewy) + (spr->gzt - gl_viewz)*(spr->gzt - gl_viewz));
const float distfact = ((2.0f*spr->dispoffset) + 20.0f) / sprdist;
const float f_xdiff = (spr->x1 - gl_viewx);
const float f_ydiff = (spr->z1 - gl_viewy);
const float f_zdiff = (spr->gzt - gl_viewz);
const float sprdist = sqrtf((f_xdiff*f_xdiff) + (f_ydiff*f_ydiff) + (f_zdiff*f_zdiff));
const float distfact = ((2.0f * spr->dispoffset) + 20.0f) / sprdist;
for (size_t i = 0; i < 4; i++)
{
@@ -4164,7 +4452,7 @@ static void HWR_AddTransparentWall(FOutVector *wallVerts, FSurfaceInfo *pSurf, I
wallinfo->wallcolormap = wallcolormap;
}
static void HWR_AddTransparentFloor(lumpnum_t lumpnum, extrasubsector_t *xsub, boolean isceiling, fixed_t fixedheight, INT32 lightlevel, INT32 alpha, sector_t *FOFSector, FBITFIELD blend, boolean fogplane, extracolormap_t *planecolormap)
static void HWR_AddTransparentFloor(lumpnum_t lumpnum, extrasubsector_t *xsub, boolean isceiling, fixed_t fixedheight, INT32 lightlevel, INT32 alpha, sector_t *FOFSector, FBITFIELD blend, boolean fogplane, extracolormap_t *planecolormap, subsector_t *subsector)
{
planeinfo_t *planeinfo = static_cast<planeinfo_t*>(HWR_CreateDrawNode(DRAWNODE_PLANE));
@@ -4178,6 +4466,9 @@ static void HWR_AddTransparentFloor(lumpnum_t lumpnum, extrasubsector_t *xsub, b
planeinfo->blend = blend;
planeinfo->fogplane = fogplane;
planeinfo->planecolormap = planecolormap;
// horizonplanes need to be drawn BEFORE skywalls, so lets hope this works without too many issues....
HWR_RenderFOFHorizonPlane(subsector, planeinfo->xsub, planeinfo->isceiling, planeinfo->fixedheight, planeinfo->blend, planeinfo->lightlevel, planeinfo->lumpnum, planeinfo->FOFSector, (UINT8)planeinfo->alpha, planeinfo->planecolormap);
}
// Adding this for now until I can create extrasubsector info for polyobjects
@@ -4287,7 +4578,10 @@ static void HWR_RenderDrawNodes(void)
gl_frontsector = NULL;
if (!(plane->blend & PF_NoTexture))
HWR_GetFlat(plane->lumpnum, R_NoEncore(plane->FOFSector, plane->isceiling));
{
const boolean ceiling = plane->FOFSector ? !plane->isceiling : plane->isceiling; // match software!
HWR_GetFlat(plane->lumpnum, R_NoEncore(plane->FOFSector, ceiling));
}
HWR_RenderPlane(NULL, plane->xsub, plane->isceiling, plane->fixedheight, plane->blend, plane->lightlevel,
plane->lumpnum, plane->FOFSector, plane->alpha, plane->planecolormap);
@@ -5698,8 +5992,7 @@ void HWR_RenderPlayerView(void)
if (HWR_UseShader())
{
if (cv_ripplewater.value)
GL_SetShaderInfo(HWD_SHADERINFO_LEVELTIME, (INT32)leveltime); // The water surface shader needs the leveltime.
GL_SetShaderInfo(HWD_SHADERINFO_LEVELTIME, (INT32)leveltime); // The water surface shader needs the leveltime.
if (cv_glmdls.value)
{
@@ -5708,7 +6001,7 @@ void HWR_RenderPlayerView(void)
const angle_t light_angle = maplighting.angle - viewangle + ANGLE_90; // I fucking hate OGL's coordinate system
GL_SetShaderInfo(HWD_SHADERINFO_LIGHT_X, FINECOSINE(light_angle >> ANGLETOFINESHIFT));
GL_SetShaderInfo(HWD_SHADERINFO_LIGHT_Y, 0);
GL_SetShaderInfo(HWD_SHADERINFO_LIGHT_Z, -FINESINE(light_angle >> ANGLETOFINESHIFT));
GL_SetShaderInfo(HWD_SHADERINFO_LIGHT_Z, -FINESINE(light_angle >> ANGLETOFINESHIFT));
}
GL_SetShaderInfo(HWD_SHADERINFO_LIGHT_CONTRAST, maplighting.contrast);
@@ -5869,7 +6162,7 @@ void HWR_Startup(void)
HWR_TogglePaletteRendering();
if (msaa)
GL_SetSpecialState(HWD_SET_MSAA, a2c ? 2 : 1);
GL_SetSpecialState(HWD_SET_MSAA, 1);
HWR_RegisterCommands();
}
@@ -5957,7 +6250,7 @@ void HWR_Shutdown(void)
GL_FlushScreenTextures();
HWR_ClearAllTextures();
#ifdef USE_FBO_OGL
GL_Framebuffer_Disable();
GL_FBO_Disable();
#endif
}
@@ -6058,42 +6351,58 @@ static void HWR_DoPostProcessor(void)
GL_MakeScreenTexture(HWD_SCREENTEXTURE_GENERIC1);
// Drunken vision! WooOOooo~
// 10 by 10 grid. 2 coordinates (xy)
float v[SCREENVERTS][SCREENVERTS][2];
float disStart = (leveltime-1) + FixedToFloat(R_GetTimeFrac(RTF_LEVEL));
UINT8 x, y;
float WAVELENGTH;
float AMPLITUDE;
float FREQUENCY;
// Modifies the wave.
if (thiscam->postimg & POSTIMG_WATER)
// shader based, should be a bit faster!
if (HWR_UseShader())
{
WAVELENGTH = 5.0f;
AMPLITUDE = 40.0f;
FREQUENCY = 8.0f;
if (thiscam->postimg & POSTIMG_WATER)
{
GL_DoPostProcessor(POSTIMG_WATER);
}
else if (thiscam->postimg & POSTIMG_HEAT)
{
GL_DoPostProcessor(POSTIMG_HEAT);
}
}
else
{
WAVELENGTH = 10.0f;
AMPLITUDE = 60.0f;
FREQUENCY = 4.0f;
}
// 10 by 10 grid. 2 coordinates (xy)
float v[SCREENVERTS][SCREENVERTS][2];
float disStart = (leveltime-1) + FixedToFloat(R_GetTimeFrac(RTF_LEVEL));
//static constexpr float scale = ((float)SCREENVERTS - 1.0f) / 9.0f; // well this evals to just 1.0f and what is x / 1? kek
UINT8 x, y;
float WAVELENGTH;
float AMPLITUDE;
float FREQUENCY;
for (x = 0; x < SCREENVERTS; x++)
{
for (y = 0; y < SCREENVERTS; y++)
// Modifies the wave.
if (thiscam->postimg & POSTIMG_WATER)
{
// Change X position based on its Y position.
v[x][y][0] = x-4.5f + sinf(((disStart+(static_cast<float>(y) * WAVELENGTH)) / FREQUENCY)) / AMPLITUDE; // (x / scale)
v[x][y][1] = y-4.5f; // (y / scale)
WAVELENGTH = 5.0f;
AMPLITUDE = 40.0f;
FREQUENCY = 8.0f;
}
else
{
WAVELENGTH = 10.0f;
AMPLITUDE = 60.0f;
FREQUENCY = 4.0f;
}
}
GL_PostImgRedraw(v);
//static constexpr float scale = ((float)SCREENVERTS - 1.0f) / 9.0f; // well this evals to just 1.0f and what is x / 1? kek
for (x = 0; x < SCREENVERTS; x++)
{
for (y = 0; y < SCREENVERTS; y++)
{
// Change X position based on its Y position.
v[x][y][0] = x-4.5f + sinf(((disStart+(static_cast<float>(y) * WAVELENGTH)) / FREQUENCY)) / AMPLITUDE; // (x / scale)
v[x][y][1] = y-4.5f; // (y / scale)
}
}
GL_PostImgRedraw(v);
}
// Capture the screen again for screen waving on the intermission
if (gamestate != GS_INTERMISSION)
+2 -4
View File
@@ -43,7 +43,6 @@ void HWR_Startup(void);
void HWR_Shutdown(void);
extern unsigned msaa;
extern boolean a2c;
extern FTransform atransform;
extern float gl_viewsin, gl_viewcos;
@@ -146,9 +145,9 @@ FUNCINLINE static ATTRINLINE void HWR_DrawIntermissionBG(void)
GL_DrawScreenTexture(HWD_SCREENTEXTURE_GENERIC1, NULL, 0);
}
FUNCINLINE static ATTRINLINE void HWR_RenderVhsEffect(fixed_t upbary, fixed_t downbary, UINT8 updistort, UINT8 downdistort, UINT8 barsize)
FUNCINLINE static ATTRINLINE void HWR_RenderVhsEffect(fixed_t upbary, fixed_t downbary, UINT8 updistort, UINT8 downdistort, UINT8 barsize, boolean rewind)
{
GL_RenderVhsEffect(upbary, downbary, updistort, downdistort, barsize);
GL_RenderVhsEffect(upbary, downbary, updistort, downdistort, barsize, rewind);
}
FUNCINLINE static ATTRINLINE void HWR_MakeScreenTexture(void)
@@ -172,7 +171,6 @@ void HWR_ProcessSeg(void); // Sort of like GLWall::Process in GZDoom
// hw_bsp.c
void HWR_CreatePlanePolygons(INT32 bspnum);
extern boolean gl_maphasportals;
extern boolean gl_maphashorizonlines;
// Console variables
extern CV_PossibleValue_t glanisotropicmode_cons_t[];
+3 -3
View File
@@ -1146,8 +1146,8 @@ void HWR_DrawMD2(gl_vissprite_t *spr)
// Look at HWR_ProjectSprite for more
{
md2_t *md2s;
int skinnum;
md2_t *md2s = NULL;
int skinnum = 0;
patch_t *gpatch, *blendgpatch;
GLPatch_t *hwrPatch = NULL, *hwrBlendPatch = NULL;
INT32 durs = spr->mobj->state->tics;
@@ -1221,7 +1221,7 @@ void HWR_DrawMD2(gl_vissprite_t *spr)
skinnum = (skin_t *)spr->mobj->localskin - skins;
}
}
else
else if (spr->mobj->skin)
{
md2s = md2_playermodels;
skinnum = (skin_t *)spr->mobj->skin - skins;
+16
View File
@@ -53,6 +53,18 @@ static struct {
// UI colormap fade shader
{GLSL_DEFAULT_VERTEX_SHADER, GLSL_UI_COLORMAP_FADE_FRAGMENT_SHADER},
// water postprocess shader
{GLSL_DEFAULT_VERTEX_SHADER, GLSL_POSTPROCESS_FRAGMENT_WATER},
// heat postprocess shader
{GLSL_DEFAULT_VERTEX_SHADER, GLSL_POSTPROCESS_FRAGMENT_HEAT},
// vhs fuzz
{GLSL_DEFAULT_VERTEX_SHADER, GLSL_VHS_FUZZ_SHADER},
// vhs bars
{GLSL_DEFAULT_VERTEX_SHADER, GLSL_VHS_BAR_SHADER},
{NULL, NULL},
};
@@ -444,6 +456,10 @@ customshaderxlat_t shaderxlat[] =
{"Sky", SHADER_SKY},
{"PalettePostprocess", SHADER_PALETTE_POSTPROCESS},
{"UIColormapFade", SHADER_UI_COLORMAP_FADE},
{"PostProcessWater", SHADER_POSTPROCESS_WATER},
{"PostProcessHeat", SHADER_POSTPROCESS_HEAT},
{"VHSFuzz", SHADER_VHS_FUZZ},
{"VHSBar", SHADER_VHS_BAR},
{NULL, 0},
};
+119 -20
View File
@@ -193,26 +193,6 @@
"}\n" \
"#endif\0"
#define GLSL_SOFTWARE_FRAGMENT_SHADER_NOPAL \
"uniform sampler2D tex;\n" \
"uniform vec4 poly_color;\n" \
"uniform vec4 tint_color;\n" \
"uniform vec4 fade_color;\n" \
"uniform float lighting;\n" \
"uniform float fade_start;\n" \
"uniform float fade_end;\n" \
GLSL_DOOM_COLORMAP \
GLSL_DOOM_LIGHT_EQUATION \
"void main(void) {\n" \
"vec4 texel = texture2D(tex, gl_TexCoord[0].st);\n" \
"vec4 base_color = texel * poly_color;\n" \
"vec4 final_color = base_color;\n" \
GLSL_SOFTWARE_TINT_EQUATION \
GLSL_SOFTWARE_FADE_EQUATION \
"final_color.a = texel.a * poly_color.a;\n" \
"gl_FragColor = final_color;\n" \
"}\n" \
// hand tuned adjustments for light level calculation
#define GLSL_FLOOR_FUDGES \
"#define STARTMAP_FUDGE 1.06\n" \
@@ -357,6 +337,125 @@
"gl_FragColor = texture2D(lighttable_tex, lighttable_coord);\n" \
"}\0" \
// these are RRs postprocess shaders
// for water and heat
/*
#define GLSL_POSTPROCESS_FRAGMENT_WATER \
"uniform sampler2D tex;\n" \
"uniform float leveltime;\n" \
"void main(void) {\n" \
"vec2 uv = gl_TexCoord[0].st;\n" \
"float y = 1.0 - uv.y;\n" \
"uv.x += sin(leveltime * 2.0 + y * 20.0) * 0.01;\n" \
"uv = clamp(uv, vec2(0.0), vec2(0.9999));\n" \
"gl_FragColor = texture2D(tex, uv);\n" \
"}\0"
#define GLSL_POSTPROCESS_FRAGMENT_HEAT \
"uniform sampler2D tex;\n" \
"uniform float leveltime;\n" \
"void main(void) {\n" \
"vec2 uv = gl_TexCoord[0].st;\n" \
"float y = 1.0 - uv.y;\n" \
"float time = leveltime * 35.0;\n" \
"uv.x += max(sin((time / 35.0) * 1.2 - y * 5.0) - 0.995, 0.0);\n" \
"uv.x -= max(sin(((time + 24.0) / 35.0) * 0.2 - y * 1.5) - 0.990, 0.0);\n" \
"uv = clamp(uv, vec2(0.0), vec2(0.9999));\n" \
"gl_FragColor = texture2D(tex, uv);\n" \
"}\0"
*/
// for reference
// sin(leveltime * X + (y) + Y) * Z
// X = Speed, Y = Vertical phase, Z = Amplitude
// this matches software at 720p wonderfully
#define GLSL_POSTPROCESS_FRAGMENT_WATER \
"#version 120\n" \
"uniform sampler2D tex;\n" \
"uniform vec2 scr_resolution;\n" \
"uniform vec2 scr_tex_size;\n" \
"uniform float leveltime;\n" \
"void main(void) {\n" \
"vec2 uv = gl_TexCoord[0].st;\n" \
"vec2 maxuv = scr_resolution / scr_tex_size;\n" \
"float y = 1.0 - uv.y;\n" \
"uv.x += sin(leveltime * 3.0 + y * 15.0) * 0.0025;\n" \
"uv = clamp(uv, vec2(0.0), maxuv - vec2(0.0001));\n" \
"gl_FragColor = texture2D(tex, uv);\n" \
"}\0"
// like the fixed function version, this is just the water wave again
// a bit readjusted since the shader wave is more lean
// makes it less neausiating anyways :p
#define GLSL_POSTPROCESS_FRAGMENT_HEAT \
"#version 120\n" \
"uniform sampler2D tex;\n" \
"uniform vec2 scr_resolution;\n" \
"uniform vec2 scr_tex_size;\n" \
"uniform float leveltime;\n" \
"void main(void) {\n" \
"vec2 uv = gl_TexCoord[0].st;\n" \
"vec2 maxuv = scr_resolution / scr_tex_size;\n" \
"float y = 1.0 - uv.y;\n" \
"uv.x += sin(leveltime * 6.0 + y * 22.5) * 0.00125;\n" \
"uv = clamp(uv, vec2(0.0), maxuv - vec2(0.0001));\n" \
"gl_FragColor = texture2D(tex, uv);\n" \
"}\0"
// screen fuzzyness
// basically just what we did before as a shader lul
// thanks https://stackoverflow.com/a/4275343 for the pseudo random stuff for glsl
#define GLSL_VHS_FUZZ_SHADER \
"#version 120\n" \
"uniform sampler2D tex;\n" \
"uniform vec2 scr_resolution;\n" \
"uniform vec2 scr_tex_size;\n" \
"uniform float vhs_time;\n" \
"uniform float scr_dup;\n" \
"void main(void) {\n" \
"vec2 uv = gl_TexCoord[0].st;\n" \
"vec2 maxuv = scr_resolution / scr_tex_size;\n" \
"float y = 1.0 - uv.y;\n" \
"float ystep = (2.0 / scr_resolution.y) * scr_dup / 4.0;\n" \
"float rand = fract(sin((floor(y / ystep) + vhs_time) * 12.9898 + 78.233) * 43758.5453);\n" \
"uv.x += floor(rand * 128.0) / -22000.0;\n" \
"uv = clamp(uv, vec2(0.0), maxuv - vec2(0.0001));\n" \
"gl_FragColor = texture2D(tex, uv);\n" \
"}\0"
// repurposed the RR heat shader
// since it kinda matched the vhs bars lul
#define GLSL_VHS_BAR_SHADER \
"#version 120\n" \
"uniform sampler2D tex;\n" \
"uniform vec2 scr_resolution;\n" \
"uniform vec2 scr_tex_size;\n" \
"uniform float vhs_time;\n" \
"uniform float vhs_rewind;\n" \
"void main(void) {\n" \
"vec2 uv = gl_TexCoord[0].st;\n" \
"vec2 maxuv = scr_resolution / scr_tex_size;\n" \
"float y = 1.0 - uv.y;\n" \
"float downspd = (vhs_rewind > 0.5) ? 2.0 : 1.0;\n" \
"float downbar = max(sin(vhs_time * downspd - y * 5.0) - 0.95, 0.0);\n" \
"float upspd = (vhs_rewind > 0.5) ? 3.0 : 1.8;\n" \
"float upbar = max(sin((vhs_time * -1.0) * upspd - y * 5.0) - 0.95, 0.0);\n" \
"uv.x += (downbar) * 0.25;\n" \
"float updistort = (vhs_rewind > 0.5) ? 0.4125: 0.25;\n" \
"uv.x -= (upbar) * updistort;\n" \
"uv = clamp(uv, vec2(0.0), maxuv - vec2(0.0001));\n" \
"vec4 color = texture2D(tex, uv);\n" \
"float downcol = step(0.00001, downbar);\n" \
"float upcol = step(0.00001, upbar);\n" \
"color.rgb = mix(color.rgb, color.rgb * (190.0 / 255.0), downcol);\n" \
"color.rgb = mix(color.rgb, color.rgb * (190.0 / 255.0), upcol);\n" \
"color.a = mix(color.a, color.a * (250.0 / 255.0), downcol);\n" \
"color.a = mix(color.a, color.a * (250.0 / 255.0), upcol);\n" \
"gl_FragColor = color;\n" \
"}\0"
// ================
// Fallback shaders
// ================
+515 -169
View File
@@ -136,32 +136,61 @@ enum
{
FBO_NONE,
FBO_ARB,
FBO_EXT,
FBO_EXT_STENCIL // supports stencil attachment
FBO_EXT
};
typedef struct
{
GLuint fboobj; // actual Framebuffer Object
GLuint rboobj; // Renderbuffer Object
GLuint tex; // Framebuffer texture
GLuint fboobj; // normal single sample fbo
GLuint rboobj; // normal single sample rbo for depth and stencil stuff
GLuint tex; // fbo texture for color
GLuint msaa_fboobj; // msaa fbo
GLuint msaa_rboobj; // msaa rbo for color this time
GLuint msaa_depthrboobj; // msaa rbo for depth and stencil stuff
boolean init;
boolean msaa; // true if the msaa fbo is the render target ugh
boolean bound; // true if the fbo is currently bound as the framebuffer
} fboobj_t;
// this is a little messy but less messy than having two of those tbh
static fboobj_t framebufferobject = {};
int supportFBO = FBO_NONE;
// older gl versions might not have these, so prevent compile errors
// this should still give a simple depth only rbo
#ifndef GL_DEPTH_COMPONENT
#define GL_DEPTH_COMPONENT 0x1902
#endif
#ifndef GL_DEPTH_ATTACHMENT_EXT
#define GL_DEPTH_ATTACHMENT_EXT 0x8D00
#endif
#ifndef GL_DEPTH24_STENCIL8
GL_DEPTH24_STENCIL8 GL_DEPTH_COMPONENT_EXT
#define GL_DEPTH24_STENCIL8 0x88F0
#endif
#ifndef GL_DEPTH_STENCIL_ATTACHMENT
GL_DEPTH_STENCIL_ATTACHMENT GL_DEPTH_ATTACHMENT_EXT
#define GL_DEPTH_STENCIL_ATTACHMENT 0x821A
#endif
#ifndef GL_COLOR_ATTACHMENT0_EXT
#define GL_COLOR_ATTACHMENT0_EXT 0x8CE0
#endif
#ifndef GL_READ_FRAMEBUFFER_EXT
#define GL_READ_FRAMEBUFFER_EXT 0x8CA8
#endif
#ifndef GL_DRAW_FRAMEBUFFER_EXT
#define GL_DRAW_FRAMEBUFFER_EXT 0x8CA9
#endif
#ifndef GL_FRAMEBUFFER_EXT
#define GL_FRAMEBUFFER_EXT 0x8D40
#endif
#ifndef GL_RENDERBUFFER_EXT
#define GL_RENDERBUFFER_EXT 0x8D41
#endif
#ifndef GL_FRAMEBUFFER_COMPLETE_EXT
#define GL_FRAMEBUFFER_COMPLETE_EXT 0x8CD5
#endif
static void GL_Framebuffer_DeleteAttachments(void);
static void GL_FBO_DeleteAttachments(void);
static void GL_FBO_Resolve(GLbitfield mask);
#endif
// needed for glportals
@@ -479,6 +508,10 @@ typedef void (APIENTRY * PFNglRenderbufferStorage) (GLenum target, GLenum intern
static PFNglRenderbufferStorage pglRenderbufferStorage;
typedef void (APIENTRY * PFNglFramebufferRenderbuffer) (GLenum target, GLenum attachment, GLenum renderbuffertarget, GLenum renderbuffer);
static PFNglFramebufferRenderbuffer pglFramebufferRenderbuffer;
typedef void (APIENTRY * PFNglRenderbufferStorageMultisample) (GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height);
static PFNglRenderbufferStorageMultisample pglRenderbufferStorageMultisample;
typedef void (APIENTRY * PFNglBlitFramebuffer) (GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1, GLbitfield mask, GLenum filter);
static PFNglBlitFramebuffer pglBlitFramebuffer;
/* 2.1 extension functions for framebuffers and renderbuffers */
typedef void (APIENTRY * PFNglGenFramebuffersEXT) (GLsizei n, GLuint *ids);
@@ -728,6 +761,14 @@ typedef enum
gluniform_scr_resolution,
// postprocess stuff
gluniform_scr_dup,
gluniform_scr_tex_size,
// vhs
gluniform_vhs_rewind,
gluniform_vhs_time,
gluniform_max,
} gluniform_t;
@@ -760,6 +801,9 @@ static float shader_light_z = 0.0f;
static INT32 shader_light_contrast = 0;
static INT32 shader_light_backlight = 0;
static float shader_vhs_rewind = 1.0f;
static float shader_vhs_time = 0.0f;
// Lactozilla: Shader functions
static boolean GL_Shader_CompileProgram(gl_shader_t *shader, GLint i);
static void GL_Shader_SetUniforms(FSurfaceInfo *Surface, GLRGBAFloat *poly, GLRGBAFloat *tint, GLRGBAFloat *fade);
@@ -769,28 +813,22 @@ static GLRGBAFloat shader_defaultcolor = {1.0f, 1.0f, 1.0f, 1.0f};
#ifdef USE_FBO_OGL
static int GLFramebuffer_CheckExt(void)
{
// in opengl 3.0 and up fbos are standart and always supported
if (majorGL >= 3)
return FBO_ARB;
// gl versions from 2.1 may still support framebuffer objects
// maybe, just maybe, we support the standart extensions
// check for the standard arb extensions
// these should be there from version 3.0 onwards
if (GL_isExtAvailable("GL_ARB_framebuffer_no_attachments", gl_extensions) &&
GL_isExtAvailable("GL_ARB_framebuffer_object", gl_extensions) &&
GL_isExtAvailable("GL_ARB_framebuffer_sRGB", gl_extensions))
{
return FBO_ARB;
}
// nope, try the older 2.1 extensions
// gl versions from 2.1 and older may still support framebuffer objects
// depending on vendor and driver support
if (GL_isExtAvailable("GL_EXT_framebuffer_no_attachments", gl_extensions) &&
GL_isExtAvailable("GL_EXT_framebuffer_object", gl_extensions) &&
GL_isExtAvailable("GL_EXT_framebuffer_sRGB", gl_extensions))
GL_isExtAvailable("GL_EXT_framebuffer_sRGB", gl_extensions) &&
GL_isExtAvailable("GL_EXT_packed_depth_stencil", gl_extensions)) // we use the stencil buffer for stuff like portals, so its better to make stencil extension a requirement
{
// perhaps we may even support a stencil attachment
if (GL_isExtAvailable("GL_EXT_packed_depth_stencil", gl_extensions))
return FBO_EXT_STENCIL;
// no stencil support, sad
return FBO_EXT;
}
@@ -906,38 +944,69 @@ void SetupGLFunc4(void)
GetGLfunc(glRenderbufferStorage);
GetGLfunc(glFramebufferRenderbuffer);
// multisample support, this should be in core per gl 3.0 and newer
pglRenderbufferStorageMultisample = GetGLFunc("glRenderbufferStorageMultisample");
pglBlitFramebuffer = GetGLFunc("glBlitFramebuffer");
if (!pglRenderbufferStorageMultisample || !pglBlitFramebuffer)
{
pglRenderbufferStorageMultisample = NULL;
pglBlitFramebuffer = NULL;
GL_DBG_Printf("\nFBO: No multisample support\n");
}
GL_DBG_Printf("\nFBO: ARB extensions found\n");
}
else if (fbocheck == FBO_EXT || fbocheck == FBO_EXT_STENCIL) // uh oh only support for EXT prefix fbos...
else if (fbocheck == FBO_EXT) // uh oh only support old fbo extensions...
{
GetGLfunc(glGenFramebuffersEXT);
GetGLfunc(glBindFramebufferEXT);
GetGLfunc(glDeleteFramebuffersEXT);
GetGLfunc(glFramebufferTexture2DEXT);
GetGLfunc(glCheckFramebufferStatusEXT);
GetGLfunc(glGenRenderbuffersEXT);
GetGLfunc(glBindRenderbufferEXT);
GetGLfunc(glDeleteRenderbuffersEXT);
GetGLfunc(glRenderbufferStorageEXT);
GetGLfunc(glFramebufferRenderbufferEXT);
// remapping galore huehue
// do this so we dont have to dupe half our code
GetGLfunc(glGenFramebuffersEXT);
pglGenFramebuffers = pglGenFramebuffersEXT;
GetGLfunc(glBindFramebufferEXT);
pglBindFramebuffer = pglBindFramebufferEXT;
GetGLfunc(glDeleteFramebuffersEXT);
pglDeleteFramebuffers = pglDeleteFramebuffersEXT;
GetGLfunc(glFramebufferTexture2DEXT);
pglFramebufferTexture2D = pglFramebufferTexture2DEXT;
GetGLfunc(glCheckFramebufferStatusEXT);
pglCheckFramebufferStatus = pglCheckFramebufferStatusEXT;
GetGLfunc(glGenRenderbuffersEXT);
pglGenRenderbuffers = pglGenRenderbuffersEXT;
GetGLfunc(glBindRenderbufferEXT);
pglBindRenderbuffer = pglBindRenderbufferEXT;
GetGLfunc(glDeleteRenderbuffersEXT);
pglDeleteRenderbuffers = pglDeleteRenderbuffersEXT;
GetGLfunc(glRenderbufferStorageEXT);
pglRenderbufferStorage = pglRenderbufferStorageEXT;
GetGLfunc(glFramebufferRenderbufferEXT);
pglFramebufferRenderbuffer = pglFramebufferRenderbufferEXT;
if (fbocheck == FBO_EXT)
GL_DBG_Printf("\nFBO: EXT extensions found, no stencil\n");
else if (fbocheck == FBO_EXT_STENCIL)
GL_DBG_Printf("\nFBO: EXT extensions with packed depth-stencil\n");
// multisample support needs the EXT multisample and blit extensions
if (GL_isExtAvailable("GL_EXT_framebuffer_multisample", gl_extensions) &&
GL_isExtAvailable("GL_EXT_framebuffer_blit", gl_extensions))
{
pglRenderbufferStorageMultisample = GetGLFunc("glRenderbufferStorageMultisampleEXT");
pglBlitFramebuffer = GetGLFunc("glBlitFramebufferEXT");
}
if (!pglRenderbufferStorageMultisample || !pglBlitFramebuffer)
{
pglRenderbufferStorageMultisample = NULL;
pglBlitFramebuffer = NULL;
GL_DBG_Printf("\nFBO: No multisample support\n");
}
GL_DBG_Printf("\nFBO: EXT extensions with packed depth-stencil\n");
}
supportFBO = fbocheck;
@@ -1151,7 +1220,7 @@ void GL_SetModelView(GLint w, GLint h)
GL_FlushScreenTextures();
#ifdef USE_FBO_OGL
GL_Framebuffer_DeleteAttachments();
GL_FBO_DeleteAttachments();
#endif
}
@@ -1457,6 +1526,15 @@ void GL_ReadScreenTexture(int tex, UINT8 *restrict dest, INT32 scale)
const INT32 stride = (screen_width/scale)*3;
INT32 scanlines = screen_height;
GLubyte * restrict image;
#ifdef USE_FBO_OGL
const boolean msaa_fbo = (framebufferobject.bound && framebufferobject.msaa);
#endif
#ifdef USE_FBO_OGL
// cant read from the msaa fbo, so gotta blit it first into either the single sample fbo or the screen framebuffer....
if (msaa_fbo)
GL_FBO_Resolve(GL_COLOR_BUFFER_BIT);
#endif
// at the time this function is called, generic2 can be found drawn on the framebuffer
// if some other screen texture is needed, draw it to the framebuffer
@@ -1498,9 +1576,16 @@ void GL_ReadScreenTexture(int tex, UINT8 *restrict dest, INT32 scale)
memcpy(dest + i, image + i*scale, 3);
dest += stride;
}
// this probably could be done with fbos, might mess around with that some time :3
// ...yet still, restrict doesn't make the inner loop any faster
free(image - ((screen_height % scale) * screen_width*3));
#ifdef USE_FBO_OGL
// this´ll reenable the msaa fbo....
if (msaa_fbo)
GL_FBO_Enable();
#endif
}
// -----------------+
@@ -2254,7 +2339,14 @@ static void GL_Shader_SetUniforms(FSurfaceInfo *Surface, GLRGBAFloat *poly, GLRG
UNIFORM_1(shader->uniforms[gluniform_leveltime], shader_leveltime, pglUniform1f);
UNIFORM_2(shader->uniforms[gluniform_scr_resolution], (GLfloat)vid.width, (GLfloat)vid.height, pglUniform2f);
UNIFORM_2(shader->uniforms[gluniform_scr_resolution], (GLfloat)screen_width, (GLfloat)screen_height, pglUniform2f);
// udup is before highres scale adjustments
UNIFORM_1(shader->uniforms[gluniform_scr_dup], (GLfloat)vid.udup, pglUniform1f);
// grrrrr stupid 2.0 support.. used similar to yfix, xfix
UNIFORM_2(shader->uniforms[gluniform_scr_tex_size], (GLfloat)screen_texsizew, (GLfloat)screen_texsizeh, pglUniform2f);
UNIFORM_1(shader->uniforms[gluniform_vhs_rewind], shader_vhs_rewind, pglUniform1f);
UNIFORM_1(shader->uniforms[gluniform_vhs_time], shader_vhs_time, pglUniform1f);
#undef UNIFORM_1
#undef UNIFORM_2
@@ -2387,6 +2479,15 @@ static boolean GL_Shader_CompileProgram(gl_shader_t *shader, GLint i)
// misc.
shader->uniforms[gluniform_leveltime] = GETUNI("leveltime");
// postprocessor stuff (water/heat effect)
shader->uniforms[gluniform_scr_dup] = GETUNI("scr_dup");
shader->uniforms[gluniform_scr_tex_size] = GETUNI("scr_tex_size");
// vhs stuff
shader->uniforms[gluniform_vhs_rewind] = GETUNI("vhs_rewind");
shader->uniforms[gluniform_vhs_time] = GETUNI("vhs_time");
#undef GETUNI
// set permanent uniform values
@@ -2641,11 +2742,7 @@ void GL_SetSpecialState(hwdspecialstate_t IdState, INT32 Value)
case HWD_SET_MSAA:
if (Value)
{
pglEnable(GL_MULTISAMPLE);
if (Value == 2)
pglEnable(GL_SAMPLE_ALPHA_TO_COVERAGE);
}
break;
case HWD_SET_TEXTUREANISOTROPICMODE:
@@ -3246,9 +3343,9 @@ void GL_SetTransform(FTransform *stransform)
}
#ifdef USE_FBO_OGL
static void GL_Framebuffer_DeleteAttachments(void)
static void GL_FBO_DeleteAttachments(void)
{
if (supportFBO == FBO_NONE || !framebufferobject.init)
if (supportFBO == FBO_NONE)
return;
// Unbind the framebuffer
@@ -3261,14 +3358,45 @@ static void GL_Framebuffer_DeleteAttachments(void)
if (framebufferobject.rboobj)
pglDeleteRenderbuffers(1, &framebufferobject.rboobj);
if (framebufferobject.msaa_rboobj)
pglDeleteRenderbuffers(1, &framebufferobject.msaa_rboobj);
if (framebufferobject.msaa_depthrboobj)
pglDeleteRenderbuffers(1, &framebufferobject.msaa_depthrboobj);
framebufferobject.tex = 0;
framebufferobject.rboobj = 0;
framebufferobject.msaa_rboobj = 0;
framebufferobject.msaa_depthrboobj = 0;
framebufferobject.init = false;
framebufferobject.bound = false;
}
static void GL_Framebuffer_Generate(void)
// blit the msaa fbo into the normal single sample fbo
// so we can use it to copy from and stuff
static void GL_FBO_Resolve(GLbitfield mask)
{
if (supportFBO == FBO_NONE || framebufferobject.init || !UseScreenFBO())
if (supportFBO == FBO_NONE || !framebufferobject.init || !framebufferobject.msaa)
return;
if (!pglBlitFramebuffer)
return;
pglBindFramebuffer(GL_READ_FRAMEBUFFER_EXT, framebufferobject.msaa_fboobj);
pglBindFramebuffer(GL_DRAW_FRAMEBUFFER_EXT, framebufferobject.fboobj);
pglBlitFramebuffer(0, 0, screen_width, screen_height,
0, 0, screen_width, screen_height,
mask, GL_NEAREST);
pglBindFramebuffer(GL_FRAMEBUFFER_EXT, framebufferobject.fboobj);
}
static void GL_FBO_Generate(void)
{
GLint msaasamples;
if (supportFBO == FBO_NONE || framebufferobject.init)
return;
// Generate the framebuffer
@@ -3283,7 +3411,7 @@ static void GL_Framebuffer_Generate(void)
{
pglGenTextures(1, &framebufferobject.tex);
pglBindTexture(GL_TEXTURE_2D, framebufferobject.tex);
pglTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, screen_width, screen_height, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);
pglTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, screen_width, screen_height, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);
pglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
pglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
Clamp2D(GL_TEXTURE_WRAP_S);
@@ -3306,18 +3434,13 @@ static void GL_Framebuffer_Generate(void)
pglRenderbufferStorage(GL_RENDERBUFFER_EXT, GL_DEPTH24_STENCIL8, screen_width, screen_height);
pglFramebufferRenderbuffer(GL_FRAMEBUFFER_EXT, GL_DEPTH_STENCIL_ATTACHMENT, GL_RENDERBUFFER_EXT, framebufferobject.rboobj);
}
else if (supportFBO == FBO_EXT || supportFBO == FBO_EXT_STENCIL)
else if (supportFBO == FBO_EXT)
{
pglRenderbufferStorage(GL_RENDERBUFFER_EXT, (supportFBO == FBO_EXT_STENCIL) ? GL_DEPTH_STENCIL_EXT : GL_DEPTH_COMPONENT, screen_width, screen_height);
// attach a renderbuffer to depth attachment point
pglRenderbufferStorage(GL_RENDERBUFFER_EXT, GL_DEPTH_STENCIL_EXT, screen_width, screen_height);
// attach the renderbuffer to depth attachment point
pglFramebufferRenderbuffer(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, GL_RENDERBUFFER_EXT, framebufferobject.rboobj);
if (supportFBO == FBO_EXT_STENCIL)
{
// attach a renderbuffer to stencil attachment point
pglFramebufferRenderbuffer(GL_FRAMEBUFFER_EXT, GL_STENCIL_ATTACHMENT_EXT, GL_RENDERBUFFER_EXT, framebufferobject.rboobj);
}
// attach the renderbuffer to stencil attachment point
pglFramebufferRenderbuffer(GL_FRAMEBUFFER_EXT, GL_STENCIL_ATTACHMENT_EXT, GL_RENDERBUFFER_EXT, framebufferobject.rboobj);
}
// Clear the renderbuffer
@@ -3329,48 +3452,124 @@ static void GL_Framebuffer_Generate(void)
if (pglCheckFramebufferStatus(GL_FRAMEBUFFER_EXT) != GL_FRAMEBUFFER_COMPLETE_EXT)
{
//pglGetError(); TODO:implement this or smth
GL_MSG_Error("GL_Framebuffer_Generate: Failed to create Framebuffer Object");
GL_MSG_Error("GL_FBO_Generate: Failed to create Framebuffer Object");
// if this fails, dont retry it a gazillion times
// this wouldnt recover
// this probably wouldnt recover and we dont want any more black screens...
supportFBO = FBO_NONE;
pglBindFramebuffer(GL_FRAMEBUFFER_EXT, 0);
return;
}
// Try to set up a multisampled render target for MSAA
framebufferobject.msaa = false;
msaasamples = (GLint)msaa;
// maybe should just make more "supportFBO" cases or smth but :chaosleep:
if (msaasamples > 1 && pglRenderbufferStorageMultisample && pglBlitFramebuffer)
{
if (!framebufferobject.msaa_fboobj)
pglGenFramebuffers(1, &framebufferobject.msaa_fboobj);
pglBindFramebuffer(GL_FRAMEBUFFER_EXT, framebufferobject.msaa_fboobj);
// Generate the multisampled color renderbuffer
if (!framebufferobject.msaa_rboobj)
{
pglGenRenderbuffers(1, &framebufferobject.msaa_rboobj);
pglBindRenderbuffer(GL_RENDERBUFFER_EXT, framebufferobject.msaa_rboobj);
pglRenderbufferStorageMultisample(GL_RENDERBUFFER_EXT, msaasamples, GL_RGBA8, screen_width, screen_height);
pglFramebufferRenderbuffer(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_RENDERBUFFER_EXT, framebufferobject.msaa_rboobj);
}
// Generate the multisampled depth/stencil renderbuffer
if (!framebufferobject.msaa_depthrboobj)
{
pglGenRenderbuffers(1, &framebufferobject.msaa_depthrboobj);
pglBindRenderbuffer(GL_RENDERBUFFER_EXT, framebufferobject.msaa_depthrboobj);
if (supportFBO == FBO_ARB)
{
pglRenderbufferStorageMultisample(GL_RENDERBUFFER_EXT, msaasamples, GL_DEPTH24_STENCIL8, screen_width, screen_height);
pglFramebufferRenderbuffer(GL_FRAMEBUFFER_EXT, GL_DEPTH_STENCIL_ATTACHMENT, GL_RENDERBUFFER_EXT, framebufferobject.msaa_depthrboobj);
}
else if (supportFBO == FBO_EXT)
{
pglRenderbufferStorageMultisample(GL_RENDERBUFFER_EXT, msaasamples, GL_DEPTH_STENCIL_EXT, screen_width, screen_height);
// attach a renderbuffer to depth attachment point
pglFramebufferRenderbuffer(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, GL_RENDERBUFFER_EXT, framebufferobject.msaa_depthrboobj);
// attach a renderbuffer to stencil attachment point
pglFramebufferRenderbuffer(GL_FRAMEBUFFER_EXT, GL_STENCIL_ATTACHMENT_EXT, GL_RENDERBUFFER_EXT, framebufferobject.msaa_depthrboobj);
}
}
pglBindRenderbuffer(GL_RENDERBUFFER_EXT, 0);
if (pglCheckFramebufferStatus(GL_FRAMEBUFFER_EXT) == GL_FRAMEBUFFER_COMPLETE_EXT)
{
framebufferobject.msaa = true;
GL_ClearBuffer(true, true, true, NULL);
GL_DBG_Printf("\nGL_FBO_Generate: Multisampled framebuffer created with %d samples\n", msaasamples);
}
else
{
GL_MSG_Warning("GL_FBO_Generate: Failed to create multisampled Framebuffer Object, falling back to no MSAA");
if (framebufferobject.msaa_rboobj)
pglDeleteRenderbuffers(1, &framebufferobject.msaa_rboobj);
if (framebufferobject.msaa_depthrboobj)
pglDeleteRenderbuffers(1, &framebufferobject.msaa_depthrboobj);
framebufferobject.msaa_rboobj = 0;
framebufferobject.msaa_depthrboobj = 0;
}
}
// Unbind the framebuffer
pglBindFramebuffer(GL_FRAMEBUFFER_EXT, 0);
framebufferobject.init = true;
}
void GL_Framebuffer_Unbind(void)
void GL_FBO_BindMainFrameBuffer(void)
{
if (supportFBO == FBO_NONE || !framebufferobject.init)
if (supportFBO == FBO_NONE)
return;
pglBindFramebuffer(GL_FRAMEBUFFER_EXT, 0);
pglBindRenderbuffer(GL_RENDERBUFFER_EXT, 0);
framebufferobject.bound = false;
}
void GL_Framebuffer_Enable(void)
void GL_FBO_Enable(void)
{
if (supportFBO == FBO_NONE || !UseScreenFBO())
if (supportFBO == FBO_NONE)
return;
GL_Framebuffer_Generate();
GL_FBO_Generate();
// failed
if (supportFBO == FBO_NONE || !framebufferobject.init)
if (!framebufferobject.init)
return;
pglBindFramebuffer(GL_FRAMEBUFFER_EXT, framebufferobject.fboobj);
pglBindRenderbuffer(GL_RENDERBUFFER_EXT, framebufferobject.rboobj);
if (framebufferobject.msaa)
{
pglBindFramebuffer(GL_FRAMEBUFFER_EXT, framebufferobject.msaa_fboobj);
pglBindRenderbuffer(GL_RENDERBUFFER_EXT, framebufferobject.msaa_rboobj);
}
else
{
pglBindFramebuffer(GL_FRAMEBUFFER_EXT, framebufferobject.fboobj);
pglBindRenderbuffer(GL_RENDERBUFFER_EXT, framebufferobject.rboobj);
}
framebufferobject.bound = true;
}
void GL_Framebuffer_Disable(void)
void GL_FBO_Disable(void)
{
if (supportFBO == FBO_NONE || !framebufferobject.init)
if (supportFBO == FBO_NONE)
return;
pglBindFramebuffer(GL_FRAMEBUFFER_EXT, 0);
@@ -3381,7 +3580,14 @@ void GL_Framebuffer_Disable(void)
pglDeleteFramebuffers(1, &framebufferobject.fboobj);
framebufferobject.fboobj = 0;
GL_Framebuffer_DeleteAttachments();
if (framebufferobject.msaa_fboobj)
pglDeleteFramebuffers(1, &framebufferobject.msaa_fboobj);
framebufferobject.msaa_fboobj = 0;
GL_FBO_DeleteAttachments();
framebufferobject.msaa = false;
framebufferobject.bound = false;
}
#endif
@@ -3418,6 +3624,55 @@ INT32 GL_GetTextureUsed(void)
return res;
}
void GL_DoPostProcessor(INT32 type)
{
float fix[8];
float xfix, yfix;
if (gl_enable_screen_textures != 2)
return;
xfix = 1/((float)screen_texsizew/(float)screen_width);
yfix = 1/((float)screen_texsizeh/(float)screen_height);
fix[0] = fix[1] =
fix[2] = fix[7] = 0.0f;
fix[3] = fix[5] = yfix;
fix[4] = fix[6] = xfix;
// this shouldnt be necessary, since this comes after level draw
// but somehow it breaks without this??
pglMatrixMode(GL_PROJECTION);
pglPushMatrix();
pglLoadIdentity();
pglMatrixMode(GL_MODELVIEW);
pglPushMatrix();
pglLoadIdentity();
GL_SetBlend(PF_NoDepthTest);
pglActiveTexture(GL_TEXTURE0);
pglBindTexture(GL_TEXTURE_2D, screenTextures[HWD_SCREENTEXTURE_GENERIC1]);
tex_downloaded = screenTextures[HWD_SCREENTEXTURE_GENERIC1];
int shader = (type == POSTIMG_WATER) ? SHADER_POSTPROCESS_WATER : SHADER_POSTPROCESS_HEAT;
GL_SetShader(HWR_GetShaderFromTarget(shader));
GL_Shader_SetUniforms(NULL, NULL, NULL, NULL);
pglColor4ubv(white);
pglTexCoordPointer(2, GL_FLOAT, 0, fix);
pglVertexPointer(3, GL_FLOAT, 0, defaultscreenVerts);
pglDrawArrays(GL_TRIANGLE_FAN, 0, 4);
GL_UnSetShader();
pglMatrixMode(GL_PROJECTION);
pglPopMatrix();
pglMatrixMode(GL_MODELVIEW);
pglPopMatrix();
}
void GL_PostImgRedraw(float points[SCREENVERTS][SCREENVERTS][2])
{
INT32 x, y;
@@ -3537,7 +3792,6 @@ void GL_DrawScreenTexture(int tex, FSurfaceInfo *surf, FBITFIELD polyflags)
tex_downloaded = screenTextures[tex];
}
// Do screen fades!
void GL_DoScreenWipe(int wipeStart, int wipeEnd)
{
@@ -3612,130 +3866,204 @@ void GL_DoScreenWipe(int wipeStart, int wipeEnd)
tex_downloaded = screenTextures[wipeEnd];
}
void GL_RenderVhsEffect(fixed_t upbary, fixed_t downbary, UINT8 updistort, UINT8 downdistort, UINT8 barsize)
void GL_RenderVhsEffect(fixed_t upbary, fixed_t downbary, UINT8 updistort, UINT8 downdistort, UINT8 barsize, boolean rewind)
{
float xfix, yfix;
float fix[8];
float i;
if (gl_enable_screen_textures != 2)
return;
GLubyte color[4] = {255, 255, 255, 255};
float screenVerts[12] =
{
-1.0f, -1.0f, 1.0f,
-1.0f, 1.0f, 1.0f,
1.0f, 1.0f, 1.0f,
1.0f, -1.0f, 1.0f
};
const GLfloat scrwf = (float)screen_width;
const GLfloat scrwh = (float)screen_height;
const GLfloat scrhf = (float)screen_height;
xfix = 1/((float)screen_texsizew/scrwf);
yfix = 1/((float)screen_texsizeh/scrwh);
yfix = 1/((float)screen_texsizeh/scrhf);
GL_SetBlend(PF_Modulated|PF_Translucent|PF_NoDepthTest);
// Slight fuzziness
GL_MakeScreenTexture(HWD_SCREENTEXTURE_VHS);
pglBindTexture(GL_TEXTURE_2D, screenTextures[HWD_SCREENTEXTURE_VHS]);
uint32_t r = rand();
const float ystep = 2.f/scrwh * (float)vid.udup/4.f;
for (i = 0; i < 1; i += ystep)
// uses shaders to replicate the effect
// thanks RR for their heat effect being basically the vhs bars, made this lots easier lul
if (HWR_UseShader())
{
// avoid calling rand thousands of times
r ^= r >> 13;
r ^= r >> 11;
r ^= r << 21;
// leveltime pauses with the game so we need to keep our own ticker here
static tic_t lleveltime = 0;
if (renderisnewtic) lleveltime++;
shader_vhs_time = (((float)(lleveltime-1)) + FIXED_TO_FLOAT(R_GetTimeFrac(RTF_CAMERA))) / TICRATE; // RTF_CAMERA interpolates during pause gladly...
fix[2] = (float)(r & 127) / -22000.f * xfix;
fix[0] = fix[2];
fix[6] = fix[0] + xfix;
fix[4] = fix[2] + xfix;
fix[1] = fix[7] = i*yfix;
fix[3] = fix[5] = (i+0.015f)*yfix;
// easier to account for within the shader
shader_vhs_rewind = rewind ? 1.0f : 0.0f;
screenVerts[1] = screenVerts[10] = 2*i - 1.0f;
screenVerts[4] = screenVerts[7] = screenVerts[1] + 0.03f;
fix[0] = fix[1] =
fix[2] = fix[7] = 0.0f;
fix[3] = fix[5] = yfix;
fix[4] = fix[6] = xfix;
GL_SetBlend(PF_NoDepthTest);
// Slight fuzziness
GL_MakeScreenTexture(HWD_SCREENTEXTURE_VHS);
pglActiveTexture(GL_TEXTURE0);
pglBindTexture(GL_TEXTURE_2D, screenTextures[HWD_SCREENTEXTURE_VHS]);
tex_downloaded = screenTextures[HWD_SCREENTEXTURE_VHS];
GL_SetShader(HWR_GetShaderFromTarget(SHADER_VHS_FUZZ));
GL_Shader_SetUniforms(NULL, NULL, NULL, NULL);
pglColor4ubv(white);
pglEnableClientState(GL_TEXTURE_COORD_ARRAY);
pglTexCoordPointer(2, GL_FLOAT, 0, fix);
pglVertexPointer(3, GL_FLOAT, 0, defaultscreenVerts);
pglDrawArrays(GL_TRIANGLE_FAN, 0, 4);
GL_UnSetShader();
// Upward and Downward bars
// theyre combined since the original shader also did this
// also saves us another screen copy + draw anyways
GL_MakeScreenTexture(HWD_SCREENTEXTURE_VHS);
pglActiveTexture(GL_TEXTURE0);
pglBindTexture(GL_TEXTURE_2D, screenTextures[HWD_SCREENTEXTURE_VHS]);
tex_downloaded = screenTextures[HWD_SCREENTEXTURE_VHS];
GL_SetShader(HWR_GetShaderFromTarget(SHADER_VHS_BAR));
GL_Shader_SetUniforms(NULL, NULL, NULL, NULL);
pglColor4ubv(white);
pglEnableClientState(GL_TEXTURE_COORD_ARRAY);
pglTexCoordPointer(2, GL_FLOAT, 0, fix);
pglVertexPointer(3, GL_FLOAT, 0, defaultscreenVerts);
pglDrawArrays(GL_TRIANGLE_FAN, 0, 4);
GL_UnSetShader();
}
else // fallback fixed function version, this is quite slow
{
float i;
GLubyte color[4] = {255, 255, 255, 255};
float screenVerts[12] =
{
-1.0f, -1.0f, 1.0f,
-1.0f, 1.0f, 1.0f,
1.0f, 1.0f, 1.0f,
1.0f, -1.0f, 1.0f
};
xfix = 1/((float)screen_texsizew/scrwf);
yfix = 1/((float)screen_texsizeh/scrhf);
GL_SetBlend(PF_Modulated|PF_Translucent|PF_NoDepthTest);
// Slight fuzziness
GL_MakeScreenTexture(HWD_SCREENTEXTURE_VHS);
pglBindTexture(GL_TEXTURE_2D, screenTextures[HWD_SCREENTEXTURE_VHS]);
uint32_t r = rand();
const float ystep = 2.f/scrhf * (float)vid.udup/4.f;
for (i = 0; i < 1; i += ystep)
{
// avoid calling rand thousands of times
r ^= r >> 13;
r ^= r >> 11;
r ^= r << 21;
fix[2] = (float)(r & 127) / -22000.f * xfix;
fix[0] = fix[2];
fix[6] = fix[0] + xfix;
fix[4] = fix[2] + xfix;
fix[1] = fix[7] = i*yfix;
fix[3] = fix[5] = (i+0.015f)*yfix;
screenVerts[1] = screenVerts[10] = 2*i - 1.0f;
screenVerts[4] = screenVerts[7] = screenVerts[1] + 0.03f;
pglColor4ubv(color);
pglTexCoordPointer(2, GL_FLOAT, 0, fix);
pglVertexPointer(3, GL_FLOAT, 0, screenVerts);
pglDrawArrays(GL_TRIANGLE_FAN, 0, 4);
}
// Upward bar
GL_MakeScreenTexture(HWD_SCREENTEXTURE_VHS);
pglBindTexture(GL_TEXTURE_2D, screenTextures[HWD_SCREENTEXTURE_VHS]);
color[0] = color[1] = color[2] = 190;
color[3] = 250;
pglColor4ubv(color);
fix[0] = 0.0f;
fix[6] = xfix;
fix[2] = (float)updistort / scrwf * xfix;
fix[4] = fix[2] + fix[6];
screenVerts[1] = screenVerts[10] = 2.0f*upbary/scrhf - 1.0f;
screenVerts[4] = screenVerts[7] = screenVerts[1] + (float)barsize/scrhf;
fix[1] = fix[7] = (float)upbary/scrhf * yfix;
fix[3] = fix[5] = fix[1] + (float)barsize/2/scrhf * yfix;
pglTexCoordPointer(2, GL_FLOAT, 0, fix);
pglVertexPointer(3, GL_FLOAT, 0, screenVerts);
pglDrawArrays(GL_TRIANGLE_FAN, 0, 4);
fix[1] = fix[7] += (fix[3] - fix[7])*2;
screenVerts[1] = screenVerts[10] += (screenVerts[4] - screenVerts[1])*2;
pglTexCoordPointer(2, GL_FLOAT, 0, fix);
pglVertexPointer(3, GL_FLOAT, 0, screenVerts);
pglDrawArrays(GL_TRIANGLE_FAN, 0, 4);
// Downward bar
GL_MakeScreenTexture(HWD_SCREENTEXTURE_VHS);
pglBindTexture(GL_TEXTURE_2D, screenTextures[HWD_SCREENTEXTURE_VHS]);
fix[0] = 0.0f;
fix[6] = xfix;
fix[2] = (float)downdistort / scrwf * -xfix;
fix[4] = fix[2] + fix[6];
screenVerts[1] = screenVerts[10] = 2.0f*downbary/scrhf - 1.0f;
screenVerts[4] = screenVerts[7] = screenVerts[1] + (float)barsize/scrhf;
fix[1] = fix[7] = (float)downbary/scrhf * yfix;
fix[3] = fix[5] = fix[1] + (float)barsize/2/scrhf * yfix;
pglTexCoordPointer(2, GL_FLOAT, 0, fix);
pglVertexPointer(3, GL_FLOAT, 0, screenVerts);
pglDrawArrays(GL_TRIANGLE_FAN, 0, 4);
fix[1] = fix[7] += (fix[3] - fix[7])*2;
screenVerts[1] = screenVerts[10] += (screenVerts[4] - screenVerts[1])*2;
pglTexCoordPointer(2, GL_FLOAT, 0, fix);
pglVertexPointer(3, GL_FLOAT, 0, screenVerts);
pglDrawArrays(GL_TRIANGLE_FAN, 0, 4);
}
// Upward bar
GL_MakeScreenTexture(HWD_SCREENTEXTURE_VHS);
pglBindTexture(GL_TEXTURE_2D, screenTextures[HWD_SCREENTEXTURE_VHS]);
color[0] = color[1] = color[2] = 190;
color[3] = 250;
pglColor4ubv(color);
fix[0] = 0.0f;
fix[6] = xfix;
fix[2] = (float)updistort / scrwf * xfix;
fix[4] = fix[2] + fix[6];
screenVerts[1] = screenVerts[10] = 2.0f*upbary/scrwh - 1.0f;
screenVerts[4] = screenVerts[7] = screenVerts[1] + (float)barsize/scrwh;
fix[1] = fix[7] = (float)upbary/scrwh * yfix;
fix[3] = fix[5] = fix[1] + (float)barsize/2/scrwh * yfix;
pglTexCoordPointer(2, GL_FLOAT, 0, fix);
pglVertexPointer(3, GL_FLOAT, 0, screenVerts);
pglDrawArrays(GL_TRIANGLE_FAN, 0, 4);
fix[1] = fix[7] += (fix[3] - fix[7])*2;
screenVerts[1] = screenVerts[10] += (screenVerts[4] - screenVerts[1])*2;
pglTexCoordPointer(2, GL_FLOAT, 0, fix);
pglVertexPointer(3, GL_FLOAT, 0, screenVerts);
pglDrawArrays(GL_TRIANGLE_FAN, 0, 4);
// Downward bar
GL_MakeScreenTexture(HWD_SCREENTEXTURE_VHS);
pglBindTexture(GL_TEXTURE_2D, screenTextures[HWD_SCREENTEXTURE_VHS]);
fix[0] = 0.0f;
fix[6] = xfix;
fix[2] = (float)downdistort / scrwf * -xfix;
fix[4] = fix[2] + fix[6];
screenVerts[1] = screenVerts[10] = 2.0f*downbary/scrwh - 1.0f;
screenVerts[4] = screenVerts[7] = screenVerts[1] + (float)barsize/scrwh;
fix[1] = fix[7] = (float)downbary/scrwh * yfix;
fix[3] = fix[5] = fix[1] + (float)barsize/2/scrwh * yfix;
pglTexCoordPointer(2, GL_FLOAT, 0, fix);
pglVertexPointer(3, GL_FLOAT, 0, screenVerts);
pglDrawArrays(GL_TRIANGLE_FAN, 0, 4);
fix[1] = fix[7] += (fix[3] - fix[7])*2;
screenVerts[1] = screenVerts[10] += (screenVerts[4] - screenVerts[1])*2;
pglTexCoordPointer(2, GL_FLOAT, 0, fix);
pglVertexPointer(3, GL_FLOAT, 0, screenVerts);
pglDrawArrays(GL_TRIANGLE_FAN, 0, 4);
}
// Create a texture from the screen.
void GL_MakeScreenTexture(int tex)
{
boolean firstTime;
static GLint lastfiltermode[NUMSCREENTEXTURES] = {-1, -1, -1, -1, -1};
#ifdef USE_FBO_OGL
const boolean msaa_fbo = (framebufferobject.bound && framebufferobject.msaa);
#endif
if (!gl_enable_screen_textures)
return;
#ifdef USE_FBO_OGL
// cant read from the msaa fbo, so gotta blit it first into either the single sample fbo or the screen framebuffer....
if (msaa_fbo)
GL_FBO_Resolve(GL_COLOR_BUFFER_BIT);
#endif
firstTime = (screenTextures[tex] == 0);
// Create screen texture
@@ -3744,18 +4072,36 @@ void GL_MakeScreenTexture(int tex)
pglBindTexture(GL_TEXTURE_2D, screenTextures[tex]);
// if were downsampling, choose to do that with linear filter instead of nearest neighbor
// otherwise well get ugly mixels
GLint filtermode = I_IsDownsampling() ? GL_LINEAR : GL_NEAREST;
// avoid redundant calls to this, prob doesent really matter tbh
if (filtermode != lastfiltermode[tex] || firstTime)
{
pglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, filtermode);
pglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, filtermode);
lastfiltermode[tex] = filtermode;
}
if (firstTime)
{
pglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
pglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
Clamp2D(GL_TEXTURE_WRAP_S);
Clamp2D(GL_TEXTURE_WRAP_T);
pglCopyTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, 0, 0, screen_texsizew, screen_texsizeh, 0);
}
else
{
pglCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 0, 0, screen_texsizew, screen_texsizeh);
}
tex_downloaded = screenTextures[tex];
#ifdef USE_FBO_OGL
if (msaa_fbo)
GL_FBO_Enable();
#endif
}
void GL_DrawScreenFinalTexture(int tex, INT32 width, INT32 height)
+3 -3
View File
@@ -98,9 +98,9 @@ extern PFNglGetString pglGetString;
#endif
#ifdef USE_FBO_OGL
void GL_Framebuffer_Unbind(void);
void GL_Framebuffer_Enable(void);
void GL_Framebuffer_Disable(void);
void GL_FBO_BindMainFrameBuffer(void);
void GL_FBO_Enable(void);
void GL_FBO_Disable(void);
extern int supportFBO;
#endif
+2 -7
View File
@@ -118,19 +118,14 @@ void I_UpdateNoVsync(void);
*/
void I_ReadScreen(UINT8 * restrict scr, INT32 scale);
UINT32 I_GetRefreshRate(void);
boolean I_CheckNativeRes(void);
void I_SetBorderlessWindow(void);
#ifdef USE_FBO_OGL
void RefreshOGLSDLSurface(void);
void I_DownSample(void);
void I_CheckDownSampleState(boolean forcerefresh);
boolean I_IsDownsampling(void);
boolean UseScreenFBO(void);
extern boolean downsample;
#endif
// So we can call this from i_video event loop
+1 -3
View File
@@ -3829,10 +3829,8 @@ static void K_drawKartMinimap(void)
}
else
{
const INT32 skinnum = K_GetMobjLocalSkinNum(mobj->skin, mobj->localskin, mobj->skinlocal);
// special case if startcolor is not the default (160 / Green)
if (skinnum && skins[skinnum].starttranscolor != skins[0].starttranscolor)
if (K_GetMobjSkin(mobj)->starttranscolor != skins[0].starttranscolor)
{
colormap = R_GetTranslationColormap(TC_DEFAULT, mobj->color, GTC_CACHE);
}
+163 -100
View File
@@ -71,12 +71,11 @@ consvar_t cv_stairjank = {"stairjank", "Off", CV_SAVE|CV_CALL, CV_OnOff, PDistor
consvar_t cv_stairjanksfx = {"stairjanksfx", "Off", CV_SAVE, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL};
//hardcode saltyhop mhhm
static void saltyhop_onchange(void);
consvar_t cv_saltyhop = {"hardcodehop", "Off", CV_SAVE|CV_CALL|CV_NOINIT, CV_OnOff, saltyhop_onchange, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_saltyhop = {"hardcodehop", "Off", CV_SAVE, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_saltyhopsfx = {"hardcodehopsfx", "On", CV_SAVE, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_saltysquish = {"hardcodehopsquish", "On", CV_SAVE, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL};
static CV_PossibleValue_t saltyheight_t[] = {{FRACUNIT/4, "MIN"}, {2*FRACUNIT, "MAX"}, {0, NULL}};
consvar_t cv_saltyheight = {"hardcodehopheight", "1", CV_FLOAT|CV_SAVE|CV_CALL|CV_NOINIT, saltyheight_t, saltyhop_onchange, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_saltyheight = {"hardcodehopheight", "1", CV_FLOAT|CV_SAVE, saltyheight_t, NULL, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_saltyroll = {"hardcodehoproll", "Off", CV_SAVE, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_squishdance = {"squishdance", "On", CV_SAVE, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL};
@@ -84,23 +83,6 @@ consvar_t cv_squishdance = {"squishdance", "On", CV_SAVE, CV_OnOff, NULL, 0, NUL
static CV_PossibleValue_t squishdancespeed_cons_t[] = {{20, "MIN"}, {280, "MAX"}, {0, NULL}};
consvar_t cv_squishdancespeed = {"squishdance_speed", "140", CV_SAVE, squishdancespeed_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL};
static void saltyhop_onchange(void)
{
// reset everything when toggling saltyhop
if (gamestate != GS_LEVEL)
return;
for (INT32 i = 0; i < MAXPLAYERS; i++)
{
player_t *player = &players[i];
if (!player || P_MobjWasRemoved(player->mo))
continue;
memset(&player->mo->salty, 0, sizeof(player->mo->salty));
}
}
// SOME IMPORTANT VARIABLES DEFINED IN DOOMDEF.H:
// gamespeed is cc (0 for easy, 1 for normal, 2 for hard)
// franticitems is Frantic Mode items, bool
@@ -1827,25 +1809,56 @@ void K_RespawnChecker(player_t *player)
mobj_t *mo;
angle_t newangle;
fixed_t newx, newy, newz;
#ifdef PHOBOS_BUILD
const fixed_t fscale = player->mo->scale;
#else
static const fixed_t fscale = FRACUNIT; // does NOT use scale, since this effect doesn't scale properly
#endif
newangle = FixedAngle(((360/8)*i)*FRACUNIT);
newx = player->mo->x + P_ReturnThrustX(player->mo, newangle, 31<<FRACBITS); // does NOT use scale, since this effect doesn't scale properly
newy = player->mo->y + P_ReturnThrustY(player->mo, newangle, 31<<FRACBITS);
newx = player->mo->x + P_ReturnThrustX(player->mo, newangle, 31 * fscale);
newy = player->mo->y + P_ReturnThrustY(player->mo, newangle, 31 * fscale);
if (player->mo->eflags & MFE_VERTICALFLIP)
newz = player->mo->z + player->mo->height;
else
newz = player->mo->z;
mo = P_SpawnMobj(newx, newy, newz, MT_DEZLASER);
if (mo)
if (!P_MobjWasRemovedCompat(mo))
{
if (player->mo->eflags & MFE_VERTICALFLIP)
mo->eflags |= MFE_VERTICALFLIP;
P_SetTarget(&mo->target, player->mo);
mo->angle = newangle+ANGLE_90;
mo->momz = (8<<FRACBITS) * P_MobjFlip(player->mo);
P_SetScale(mo, (mo->destscale = FRACUNIT));
mo->momz = (8 * fscale) * P_MobjFlip(player->mo);
P_SetScale(mo, (mo->destscale = fscale));
}
#ifndef PHOBOS_BUILD
// vanilla compat really is annoying.......
// but this stuff is messed up on mobjscaled maps
// and we gotta respawn it locally to avoid desynchs...
if (mapobjectscale != FRACUNIT)
{
// hide the normal lazers!
mo->flags2 |= MF2_DONTDRAW;
newx = player->mo->x + P_ReturnThrustX(player->mo, newangle, 31 * player->mo->scale);
newy = player->mo->y + P_ReturnThrustY(player->mo, newangle, 31 * player->mo->scale);
// now spawn our local lazers
mo = P_SpawnMobj(newx, newy, newz, MT_DEZLASER);
if (!P_MobjWasRemovedCompat(mo))
{
if (player->mo->eflags & MFE_VERTICALFLIP)
mo->eflags |= MFE_VERTICALFLIP;
P_SetTarget(&mo->target, player->mo);
mo->angle = newangle+ANGLE_90;
mo->momz = (8 * player->mo->scale) * P_MobjFlip(player->mo);
P_SetScale(mo, (mo->destscale = player->mo->scale));
mo->islocal = true; // Keep this local!
}
}
#endif
}
}
}
@@ -2194,7 +2207,7 @@ static void K_GetKartBoostPower(player_t *player)
// Technically, all mobjs that think can cause desynchs if they are spawned conditionally, so best we can do
// is to hide them if you are in saltyhop jump
if (dust && player->mo->salty.jump)
if (dust && player->salty.jump)
dust->flags2 |= MF2_DONTDRAW;
if (leveltime % 6 == 0)
@@ -3223,10 +3236,8 @@ static void K_SpawnDriftSparks(player_t *player)
for (i = 0; i < 2; i++)
{
fixed_t driftExtraScale = 0;
angle_t thrustangle = (travelangle + ((i&1) ? -1 : 1)*ANGLE_135);
fixed_t smolscale = FixedMul(32*FRACUNIT, player->mo->scale);
const angle_t thrustangle = (travelangle + ((i&1) ? -1 : 1)*ANGLE_135);
const fixed_t smolscale = FixedMul(32*FRACUNIT, player->mo->scale);
newx = player->mo->x + P_ReturnThrustX(player->mo, thrustangle, smolscale);
newy = player->mo->y + P_ReturnThrustY(player->mo, thrustangle, smolscale);
@@ -3238,9 +3249,9 @@ static void K_SpawnDriftSparks(player_t *player)
spark->angle = travelangle-(ANGLE_45/5)*player->kartstuff[k_drift];
// scale increase while driftspark level gained timer is running
driftExtraScale = FixedDiv(player->driftsparkGrowTimer, DRIFTSPARKGROWTICS);
const fixed_t driftExtraScale = FixedDiv(player->driftsparkGrowTimer, DRIFTSPARKGROWTICS);
spark->destscale = FixedMul(player->mo->scale, FRACUNIT + FixedMul(driftExtraScale, cv_driftsparkpulse.value));
P_SetScale(spark, spark->destscale); // why not use what we calculated above?
P_SetScale(spark, spark->destscale);
spark->momx = player->mo->momx/2;
spark->momy = player->mo->momy/2;
@@ -3332,10 +3343,10 @@ static void K_StretchPlayerGravity(player_t *player)
mobj_t *pmo = player->mo;
fixed_t tempxscale = pmo->realxscale;
fixed_t tempyscale = pmo->realyscale;
const fixed_t tempxscale = pmo->realxscale;
const fixed_t tempyscale = pmo->realyscale;
stretchScaleFactor = FixedDiv(FRACUNIT*60, cv_gravstretch.value);
stretchScaleFactor = FixedDiv(mapobjectscale*60, cv_gravstretch.value);
stretchScaleFactor = min(stretchScaleFactor, MAXSTRETCHDIV);
if (pmo->slamsoundtimer)
@@ -3343,26 +3354,26 @@ static void K_StretchPlayerGravity(player_t *player)
if (!P_IsObjectOnGround(pmo))
{
fixed_t pzmom = abs(pmo->momz);
const fixed_t pzmom = abs(pmo->momz);
const fixed_t stretchDiv = FixedDiv(pzmom, stretchScaleFactor);
if (abs(pzmom/FRACUNIT) != 0)
if (abs(pzmom/mapobjectscale) != 0)
{
if (((tempxscale-(stretchDiv))) > (tempxscale/5))
if ((tempxscale - stretchDiv) > (tempxscale / 5))
{
pmo->spritexscale = (tempxscale - stretchDiv);
pmo->stretchslam = pzmom;
}
else
pmo->spritexscale = (tempxscale/5);
pmo->spritexscale = (tempxscale / 5);
pmo->spriteyscale = (tempyscale + ((stretchDiv*2)/3));
pmo->spriteyscale = (tempyscale + ((stretchDiv * 2) / 3));
}
}
else if (pmo->stretchslam > 0)
{
// Funni slam sound when landing
if (cv_slamsound.value && (pmo->eflags & MFE_JUSTHITFLOOR) && !pmo->slamsoundtimer && (pmo->stretchslam > 4*FRACUNIT))
if (cv_slamsound.value && (pmo->eflags & MFE_JUSTHITFLOOR) && !pmo->slamsoundtimer && (pmo->stretchslam > 4*mapobjectscale))
{
S_StartSound(pmo, sfx_s3k4c);
pmo->slamsoundtimer = TICRATE;
@@ -3370,9 +3381,9 @@ static void K_StretchPlayerGravity(player_t *player)
const fixed_t slamDiv = FixedDiv(pmo->stretchslam, stretchScaleFactor);
pmo->spritexscale = (tempxscale + (((slamDiv*2)/3)*2));
pmo->spritexscale = (tempxscale + (((slamDiv * 2) / 3 ) * 2));
pmo->spriteyscale = (tempyscale - slamDiv);
pmo->stretchslam -= (4*FRACUNIT);
pmo->stretchslam -= (4*mapobjectscale);
}
else
pmo->stretchslam = 0;
@@ -3387,16 +3398,16 @@ static void K_SaltySquish(player_t *player)
mobj_t *pmo = player->mo;
fixed_t tempxscale = pmo->realxscale;
fixed_t tempyscale = pmo->realyscale;
const fixed_t tempxscale = pmo->realxscale;
const fixed_t tempyscale = pmo->realyscale;
if (pmo->stretchslam > 0)
{
const fixed_t slamDiv = FixedDiv(pmo->stretchslam, FRACUNIT*60); // stretchScaleFactor = FixedDiv(FRACUNIT*60, FRACUNIT)
const fixed_t slamDiv = FixedDiv(pmo->stretchslam, mapobjectscale*60); // stretchScaleFactor = FixedDiv(mapobjectscale*60, FRACUNIT)
pmo->spritexscale = (tempxscale + (((slamDiv*2)/3)*2));
pmo->spritexscale = (tempxscale + (((slamDiv * 2) / 3) * 2));
pmo->spriteyscale = (tempyscale - slamDiv);
pmo->stretchslam -= (4*FRACUNIT);
pmo->stretchslam -= (4*mapobjectscale);
}
else
pmo->stretchslam = 0;
@@ -3404,88 +3415,92 @@ static void K_SaltySquish(player_t *player)
static void K_QuiteSaltyHop(player_t *player)
{
if (!cv_saltyhop.value)
return;
I_Assert(player != NULL);
I_Assert(!P_MobjWasRemoved(player->mo));
// what the fuck is this haya
mobj_t *pmo = player->mo;
salty_t *psalt = &pmo->salty;
salty_t *psalty = &player->salty;
if (!cv_saltyhop.value)
{
// reset before we leave
psalty->jump = psalty->ready = psalty->tapping = false;
psalty->momz = psalty->zoffset = 0;
return;
}
const boolean onground = P_IsObjectOnGround(pmo);
// ready?
if (!player->kartstuff[k_jmp])
{
psalt->ready = true;
psalt->tapping = false;
psalty->ready = true;
psalty->tapping = false;
}
else if (psalt->ready)
else if (psalty->ready)
{
psalt->ready = false;
psalt->tapping = true;
psalty->ready = false;
psalty->tapping = true;
}
else
{
psalt->tapping = false;
psalty->tapping = false;
}
// GO!
if (!psalt->init)
{
psalt->jump = false;
psalt->zoffset = 0;
psalt->momz = 0;
psalt->init = true;
}
else if (psalt->jump)
if (psalty->jump)
{
if (pmo->eflags & MFE_JUSTHITFLOOR)
{
psalt->zoffset = 0;
psalty->zoffset = 0;
}
else if (onground)
{
psalt->zoffset += psalt->momz;
psalt->momz -= (FRACUNIT*3/2);
psalty->zoffset += psalty->momz;
psalty->momz -= (FRACUNIT*3/2);
}
else
{
psalt->zoffset *= (49/50)*FRACUNIT;
psalt->momz = 0;
//psalty->zoffset *= (49/50)*FRACUNIT; // this just rounds down to 0 lol
psalty->zoffset = 0;
psalty->momz = 0;
}
if (psalt->zoffset <= 0)
if (psalty->zoffset <= 0)
{
if (cv_saltyhopsfx.value && !(pmo->eflags & MFE_JUSTHITFLOOR) && onground)
S_StartSound(pmo, sfx_s268);
psalt->jump = false;
psalt->zoffset = 0;
psalt->momz = 0;
psalty->jump = false;
psalty->zoffset = 0;
psalty->momz = 0;
// shlamma damma
if (cv_saltysquish.value)
pmo->stretchslam += 8*FRACUNIT;
pmo->stretchslam += 8*mapobjectscale;
}
else if (cv_saltysquish.value && psalt->zoffset >= 0)
else if (psalty->zoffset > 0)
{
// goofy ahh hack
pmo->spriteyscale += (FRACUNIT/8);
pmo->spritexscale -= (FRACUNIT/8);
if (cv_saltysquish.value)
{
// goofy ahh hack
pmo->spriteyscale += (FRACUNIT/8);
pmo->spritexscale -= (FRACUNIT/8);
}
}
pmo->spriteyoffset += FixedMul(psalt->zoffset, cv_saltyheight.value);
pmo->spriteyoffset += FixedMul(psalty->zoffset, cv_saltyheight.value);
if (cv_saltyhopsfx.value)
{
if (S_SoundPlaying(pmo, sfx_screec))
S_StopSoundByID(pmo, sfx_screec);
if (S_SoundPlaying(pmo, sfx_drift))
S_StopSoundByID(pmo, sfx_drift);
}
// Stop any and all drift sounds when hopping.
if (S_SoundPlaying(pmo, sfx_screec))
S_StopSoundByID(pmo, sfx_screec);
if (S_SoundPlaying(pmo, sfx_drift))
S_StopSoundByID(pmo, sfx_drift);
}
else if (psalt->tapping && onground && !player->kartstuff[k_spinouttimer] && !player->kartstuff[k_squishedtimer])
else if (psalty->tapping && onground && !player->kartstuff[k_spinouttimer] && !player->kartstuff[k_squishedtimer])
{
psalt->jump = true;
psalt->zoffset = 0;
psalt->momz = 6*FRACUNIT;
psalty->jump = true;
psalty->zoffset = 0;
psalty->momz = 6*FRACUNIT;
if (cv_saltyhopsfx.value)
S_StartSound(pmo, sfx_s25a);
}
@@ -3512,7 +3527,7 @@ boolean K_ShouldSlopeRoll(mobj_t *mobj)
return false;
// seeing a character rotate mid-hop looks really janky
if (!cv_saltyroll.value && mobj->player && mobj->player->mo->salty.jump)
if (!cv_saltyroll.value && mobj->player && mobj->player->salty.jump)
return false;
return K_CheckSlopeRollDist(mobj);
@@ -3724,7 +3739,7 @@ mobj_t *K_SpawnWipeoutTrail(mobj_t *mo, boolean translucent)
dust = P_SpawnMobj(rand_x, rand_y, mo->z, MT_WIPEOUTTRAIL);
P_SetTarget(&dust->target, mo);
dust->angle = R_PointToAngle2(0,0,mo->momx,mo->momy);
dust->angle = R_PointToAngle2(0, 0, mo->momx, mo->momy);
dust->destscale = mo->scale;
P_SetScale(dust, mo->scale);
K_FlipFromObject(dust, mo);
@@ -3750,6 +3765,11 @@ mobj_t *K_SpawnWipeoutTrail(mobj_t *mo, boolean translucent)
void K_DriftDustHandling(mobj_t *spawner)
{
angle_t anglediff;
#ifdef PHOBOS_BUILD
const fixed_t fscale = spawner->scale;
#else
static const fixed_t fscale = FRACUNIT; // should be spawner->scale but the below calls P_Random!
#endif
if (leveltime % 2 != 0 || !P_IsObjectOnGround(spawner))
return;
@@ -3766,7 +3786,7 @@ void K_DriftDustHandling(mobj_t *spawner)
{
angle_t playerangle = spawner->angle;
if (spawner->player->speed < 5<<FRACBITS)
if (spawner->player->speed < (5 * fscale))
return;
if (spawner->player->cmd.forwardmove < 0)
@@ -3777,7 +3797,7 @@ void K_DriftDustHandling(mobj_t *spawner)
}
else
{
if (P_AproxDistance(spawner->momx, spawner->momy) < 5<<FRACBITS)
if (P_AproxDistance(spawner->momx, spawner->momy) < (5 * fscale))
return;
anglediff = abs((signed)(spawner->angle - R_PointToAngle2(0, 0, spawner->momx, spawner->momy)));
@@ -3790,13 +3810,29 @@ void K_DriftDustHandling(mobj_t *spawner)
if (anglediff > ANG10*4) // Trying to turn further than 40 degrees
{
mobj_t *dust = NULL;
fixed_t spawnx = P_RandomRange(-spawnrange, spawnrange)<<FRACBITS;
fixed_t spawny = P_RandomRange(-spawnrange, spawnrange)<<FRACBITS;
INT32 speedrange = 2;
mobj_t *dust = P_SpawnMobj(spawner->x + spawnx, spawner->y + spawny, spawner->z, MT_DRIFTDUST);
dust->momx = FixedMul(spawner->momx + (P_RandomRange(-speedrange, speedrange)<<FRACBITS), 3*(spawner->scale)/4);
dust->momy = FixedMul(spawner->momy + (P_RandomRange(-speedrange, speedrange)<<FRACBITS), 3*(spawner->scale)/4);
dust->momz = P_MobjFlip(spawner) * (P_RandomRange(1, 4) * (spawner->scale));
dust = P_SpawnMobj(spawner->x + spawnx, spawner->y + spawny, spawner->z, MT_DRIFTDUST);
const INT32 momxrand = P_RandomRange(-speedrange, speedrange);
const INT32 momyrand = P_RandomRange(-speedrange, speedrange);
const INT32 momzrand = P_RandomRange(1, 4);
if (P_MobjWasRemovedCompat(dust))
return;
#ifdef PHOBOS_BUILD
dust->momx = FixedMul(spawner->momx + (momxrand * spawner->scale), 3*FRACUNIT/4);
dust->momy = FixedMul(spawner->momy + (momyrand * spawner->scale), 3*FRACUNIT/4);
#else
dust->momx = FixedMul(spawner->momx + (momxrand<<FRACBITS), 3*(spawner->scale)/4);
dust->momy = FixedMul(spawner->momy + (momyrand<<FRACBITS), 3*(spawner->scale)/4);
#endif
dust->momz = P_MobjFlip(spawner) * (momzrand * (spawner->scale));
P_SetScale(dust, spawner->scale/2);
dust->destscale = spawner->scale * 3;
dust->scalespeed = spawner->scale/12;
@@ -3805,6 +3841,33 @@ void K_DriftDustHandling(mobj_t *spawner)
S_StartSound(spawner, sfx_screec);
K_MatchGenericExtraFlags(dust, spawner);
#ifndef PHOBOS_BUILD
// vanilla compat really is annoying.......
// but this stuff is messed up on mobjscaled maps
// and we gotta respawn it locally to avoid desynchs...
if (mapobjectscale != FRACUNIT)
{
// hide the normal dust!
dust->flags2 |= MF2_DONTDRAW;
// now spawn our dust locally
dust = P_SpawnMobj(spawner->x + spawnx, spawner->y + spawny, spawner->z, MT_DRIFTDUST);
if (P_MobjWasRemovedCompat(dust))
return;
dust->momx = FixedMul(spawner->momx + (momxrand * spawner->scale), 3*FRACUNIT/4);
dust->momy = FixedMul(spawner->momy + (momyrand * spawner->scale), 3*FRACUNIT/4);
dust->momz = P_MobjFlip(spawner) * (momzrand * (spawner->scale));
P_SetScale(dust, spawner->scale/2);
dust->destscale = spawner->scale * 3;
dust->scalespeed = spawner->scale/12;
dust->islocal = true; // Keep this local!
K_MatchGenericExtraFlags(dust, spawner);
}
#endif
}
}
+6 -1
View File
@@ -182,14 +182,19 @@ void COM_Lua_f(void)
len = (argc+1)*256;
buf = malloc(len);
if (buf == NULL)
I_Error("Failed to allocate buffer for COM_Lua_f");
p = buf;
WRITEUINT8(p, argc);
for (i = 0; i < argc; i++)
WRITESTRINGN(p, COM_Argv(i), 255);
if (flags & 2)
if (flags & COM_SPLITSCREEN)
SendNetXCmdForPlayer(1, XD_LUACMD, buf, p-buf);
else
SendNetXCmd(XD_LUACMD, buf, p-buf);
free(buf);
return;
}
+11 -2
View File
@@ -13,6 +13,12 @@
#include <string.h>
#ifdef HAVE_THREADS
#define local_for_thread _Thread_local
#else
#define local_for_thread
#endif
#include "doomdef.h"
#include "command.h"
#include "m_argv.h"
@@ -31,8 +37,11 @@ char **myargv = NULL;
boolean myargmalloc = false;
/** \brief founded the parm
*
* thread_local because it can potentially be used from multiple threads (global variables aaaaaa)
* (myargc and myargv don't have to be thread_local because they are never modified after being set up)
*/
static INT32 found;
static local_for_thread INT32 found;
/** \brief The M_CheckParm function
@@ -91,7 +100,7 @@ INT32 M_CheckProtoParam(const char *check)
const char *M_GetProtoParam(void)
{
INT32 i;
static char *string;
char *string;
for (i = 1; i < myargc; i++)
{
+42 -20
View File
@@ -3984,6 +3984,14 @@ menudemo_t *demolist = NULL; // Replays that that have been checked to match wit
menudemo_t *demolist_all = NULL; // All replays
size_t demolist_all_size = 0;
boolean replaynamesloaded = false;
// Whenever we start a replay load thread, we increment this number and then thread will remember current value,
// and by the end it will compare it with current value, and if it is equal it means thread can store data it has loaded.
// If it's not equal, that means we started more than one thread (left and re-entered menu for example)
size_t replaythreadnum = 0;
// for replay dates
#include <locale.h>
const char *demodateformat = "%d.%m.%Y";
#ifdef HAVE_THREADS
I_mutex replayquerymutex;
@@ -4013,12 +4021,15 @@ static SINT8 replayScrollDelay = TICRATE, replayScrollDir = 1;
static void ReplayNamesLoadThread(void* userdata)
{
(void)userdata;
Lock_search_state();
size_t demolist_all_size_local = demolist_all_size;
menudemo_t *demolist_all_local = (menudemo_t*)malloc(sizeof(menudemo_t)*demolist_all_size_local);
memcpy(demolist_all_local, demolist_all, sizeof(menudemo_t)*demolist_all_size_local);
char *replaydirpath = (char*)userdata;
size_t localreplaythreadnum = replaythreadnum;
const char *localdemodateformat = demodateformat;
Unlock_search_state();
@@ -4026,19 +4037,13 @@ static void ReplayNamesLoadThread(void* userdata)
{
if (demolist_all_local[i].type != MD_SUBDIR)
{
G_LoadDemoTitle(&demolist_all_local[i]);
// this is fucking horrid, but i wanna be able to search for dates
/*if (demolist_all_local[i].date[0] != '\0')
{
snprintf(demolist_all_local[i].title, sizeof(demolist_all_local[i].title), "%s %s", demolist_all_local[i].title, demolist_all_local[i].date);
}*/
G_LoadDemoTitle(&demolist_all_local[i], localdemodateformat);
}
}
Lock_search_state();
if (fastcmp(menupath, replaydirpath) && demolist_all)
if (replaythreadnum == localreplaythreadnum && demolist_all)
{
memcpy(demolist_all, demolist_all_local, sizeof(menudemo_t)*demolist_all_size);
replaynamesloaded = true;
@@ -4047,22 +4052,32 @@ static void ReplayNamesLoadThread(void* userdata)
Unlock_search_state();
// Was allocated before thread start, we need to free it
free(replaydirpath);
free(demolist_all_local);
}
static void LoadReplayNames(void)
{
char *replaydirpath = strdup(menupath);
Lock_search_state();
replaythreadnum++;
replaynamesloaded = false;
if (cv_demodateformat.value == 2)
demodateformat = "%m.%d.%Y";
else if (cv_demodateformat.value == 1)
demodateformat = "%d.%m.%Y";
else
{
// get the date format here
// setlocale reads/writes global state
const char *locale = setlocale(LC_TIME, NULL);
// US ppl are special (:
demodateformat = (locale && strstr(locale, "en_US")) ? "%m.%d.%Y" : "%d.%m.%Y";
}
Unlock_search_state();
#ifdef HAVE_THREADS
I_spawn_thread("replay-names-load", ReplayNamesLoadThread, replaydirpath);
I_spawn_thread("replay-names-load", ReplayNamesLoadThread, NULL);
#else
ReplayNamesLoadThread(replaydirpath);
ReplayNamesLoadThread(NULL);
#endif
}
@@ -4101,8 +4116,12 @@ static void M_HutCheckReplays(size_t maxnum)
// Mark as done
replayqueryfound = replayquerycheck = sizedirmenu;
Lock_search_state();
memcpy(demolist, demolist_all, sizeof(menudemo_t) * sizedirmenu);
Unlock_search_state();
return;
}
@@ -4251,13 +4270,15 @@ static boolean M_HandleReplayHutQuery(INT32 choice)
char tmp[MAXREPLAYQUERY+1];
memcpy(tmp, replayqueryinput_buffer, MAXREPLAYQUERY+1);
Lock_search_state();
// Honestly not sure if locks for replaynamesloaded are necessary...
// Thread sanitizer does report race condition whenever replaynamesloaded is accessed without lock
// but really it is only ever set to false in main thread and only set to true in replay load thread,
// and both are done via locks. If replaynamesloaded is true, it is never gonna suddenly switch from true to false
// while we're in main thread, and if it would switch from false to true it is not really a big deal, we will just skip
// 1 frame where replay names were loaded
if (!replaynamesloaded)
{
Unlock_search_state();
return false;
}
Unlock_search_state();
if (M_TextInputHandle(&replayqueryinput, choice))
{
@@ -9929,6 +9950,7 @@ static void M_DrawLocalSkinMenu(void)
V_DrawFill(mx + 220 - (charw/2), my+54, charw, 84, 239);
#undef charw
// FIXME: is skins[displayskin.localnum] even correct?
UINT8 *colormap = R_GetLocalTranslationColormap(&skins[displayskin.localnum], (displayskin.localskin ? &localskins[displayskin.localnum] : NULL), cv_playercolor.value, GTC_MENUCACHE, displayskin.localskin);
V_DrawMappedPatch(mx, my+50, 0, (patch_t *)W_CachePatchName(displayskin.facewant, PU_PATCH), colormap);
@@ -9946,7 +9968,7 @@ static void M_DrawLocalSkinMenu(void)
my += 120;
#ifdef HWRENDER
md2_t *md2 = (displayskin.localskin ? &md2_localplayermodels[skintodisplay] : &md2_playermodels[skintodisplay]);
md2_t *md2 = (displayskin.localskin ? &md2_localplayermodels[displayskin.localnum] : &md2_playermodels[skintodisplay]);
// if we have 3d models enabled and a model exists
// try to show it instead of the sprite
+2 -2
View File
@@ -1004,7 +1004,7 @@ static menuitem_t OP_ExpOptionsMenu[] =
#ifdef HWRENDER
{IT_STRING | IT_CVAR, NULL, "Screen Textures", &cv_glscreentextures, 95},
#ifdef USE_FBO_OGL
{IT_STRING | IT_CVAR, NULL, "FBO Downsampling support", &cv_glframebuffer, 100},
{IT_STRING | IT_CVAR, NULL, "FBO support", &cv_glframebuffer, 100},
{IT_STRING | IT_CVAR, NULL, "Palette Depth", &cv_glpalettedepth, 110},
{IT_DISABLED, NULL, "", NULL, 120}, // dummy text
#else
@@ -1030,7 +1030,7 @@ static const char* OP_ExpTooltips[] =
#ifdef HWRENDER
"Disabling Screen Textures may result in a performance boost\nbut will break certain effects.\nScreen textures are required at resolutions lower than your desktop resolution!",
#ifdef USE_FBO_OGL
"Allows the game to downsample from a higher resolution\nthan your display in OpenGL renderer mode.\nRequires a GPU with atleast OpenGL 2.1 support.",
"Allows the game to downsample from a higher resolution\nthan your display in OpenGL renderer mode.\nThis can be set to automatically enable if the game resolution\nis higher than the current Display Resolution\nor enabled at all times.\nThis may improve performance in some cases.\nRequires a GPU with atleast OpenGL 2.1 support.",
#endif
"Change the bit depth of the Lookup Palette in Palette rendering mode\n 16 bits is like software looks ingame\nwhile 24 bits is how software looks in screenshots.",
#endif
+102 -60
View File
@@ -6280,16 +6280,39 @@ static void P_MobjSceneryThink(mobj_t *mobj)
case MT_SMOLDERING:
if (leveltime % 2 == 0)
{
mobj_t *smoke;
fixed_t x = P_RandomRange(-35, 35)*mobj->scale;
fixed_t y = P_RandomRange(-35, 35)*mobj->scale;
fixed_t z = P_RandomRange(0, 70)*mobj->scale;
mobj_t *smoke = P_SpawnMobj(mobj->x + x, mobj->y + y, mobj->z + z, MT_SMOKE);
smoke = P_SpawnMobj(mobj->x + x, mobj->y + y, mobj->z + z, MT_SMOKE);
P_SetMobjState(smoke, S_OPAQUESMOKE1);
K_MatchGenericExtraFlags(smoke, mobj);
smoke->scale = mobj->scale * 2;
smoke->destscale = mobj->scale * 6;
smoke->momz = P_RandomRange(4, 9)*FRACUNIT*P_MobjFlip(smoke);
const INT32 momrand = P_RandomRange(4, 9);
#ifdef PHOBOS_BUILD
smoke->momz = momrand*mobj->scale*P_MobjFlip(smoke);
#else
smoke->momz = momrand*FRACUNIT*P_MobjFlip(smoke);
// vanilla compat really is annoying.......
// but this stuff is messed up on mobjscaled maps
// so we gotta respawn it locally to avoid desynchs...
if (mapobjectscale != FRACUNIT)
{
// hide the smoke!
smoke->flags2 |= MF2_DONTDRAW;
smoke = P_SpawnMobj(mobj->x + x, mobj->y + y, mobj->z + z, MT_SMOKE);
P_SetMobjState(smoke, S_OPAQUESMOKE1);
K_MatchGenericExtraFlags(smoke, mobj);
smoke->scale = mobj->scale * 2;
smoke->destscale = mobj->scale * 6;
smoke->momz = momrand*mobj->scale*P_MobjFlip(smoke);
smoke->islocal = true; // Keep this local!
}
#endif
}
break;
case MT_BOOMPARTICLE:
@@ -9164,6 +9187,12 @@ static boolean P_MobjPushableThink(mobj_t *mobj)
static void P_FiringThink(mobj_t *mobj)
{
if (!mobj->target)
return;
if (mobj->health <= 0)
return;
if (mobj->state->action == (actionf_p1)A_Boss1Laser)
{
var1 = mobj->state->var1;
@@ -9226,7 +9255,12 @@ void P_MobjThinker(mobj_t *mobj)
mobj->flags2 &= ~MF2_PUSHED;
mobj->eflags &= ~(MFE_SPRUNG|MFE_JUSTBOUNCEDWALL);
#ifdef PHOBOS_BUILD
P_SetTarget(&tmfloorthing, NULL);
P_SetTarget(&tmhitthing, NULL);
#else
tmfloorthing = tmhitthing = NULL;
#endif
// do NOT trigger linedef executors for "local" mobjs
if (!mobj->islocal)
@@ -9242,8 +9276,13 @@ void P_MobjThinker(mobj_t *mobj)
}
if (mobj->scale != mobj->destscale)
{
P_MobjScaleThink(mobj); // Slowly scale up/down to reach your destscale.
if (P_MobjWasRemovedCompat(mobj))
return;
}
if (!mobj->player)
{
if (mobj->type == MT_GHOST && mobj->fuse > 0 // Not guaranteed to be MF_SCENERY or not MF_SCENERY!
@@ -9288,6 +9327,21 @@ void P_MobjThinker(mobj_t *mobj)
{
if (!P_MobjDeadThink(mobj))
return;
// Fading tile
if (mobj->type >= MT_BOUNCEPICKUP && mobj->type <= MT_GRENADEPICKUP)
{
INT32 value = mobj->info->damage/10;
value = mobj->fuse/value;
value = 10-value;
value--;
if (value <= 0)
value = 1;
mobj->frame &= ~FF_TRANSMASK;
mobj->frame |= value << FF_TRANSSHIFT;
}
}
else
{
@@ -9298,7 +9352,7 @@ void P_MobjThinker(mobj_t *mobj)
if (P_MobjWasRemoved(mobj))
return;
if (mobj->flags2 & MF2_FIRING && mobj->target && mobj->health > 0)
if (mobj->flags2 & MF2_FIRING)
P_FiringThink(mobj);
if (mobj->flags & MF_AMBIENT)
@@ -9365,23 +9419,27 @@ void P_MobjThinker(mobj_t *mobj)
P_ButteredSlope(mobj);
}
if (mobj->flags & (MF_ENEMY|MF_BOSS) && mobj->health &&
P_CheckDeathPitCollide(mobj)) // extra pit check in case these didn't have momz
if (mobj->health)
{
P_KillMobj(mobj, NULL, NULL);
return;
}
// Crush enemies!
if (mobj->ceilingz - mobj->floorz < mobj->height)
{
if (((mobj->flags & (MF_ENEMY|MF_BOSS) && mobj->flags & MF_SHOOTABLE) || mobj->type == MT_EGGSHIELD) &&
!(mobj->flags & MF_NOCLIPHEIGHT) &&
mobj->health > 0)
// extra pit check in case these didn't have momz
if ((mobj->flags & (MF_ENEMY|MF_BOSS)) &&
P_CheckDeathPitCollide(mobj))
{
P_KillMobj(mobj, NULL, NULL);
return;
}
// Crush enemies!
if ((mobj->ceilingz - mobj->floorz) < mobj->height)
{
if ((((mobj->flags & (MF_ENEMY|MF_BOSS)) && (mobj->flags & MF_SHOOTABLE)) || mobj->type == MT_EGGSHIELD) &&
!(mobj->flags & MF_NOCLIPHEIGHT) &&
mobj->health > 0)
{
P_KillMobj(mobj, NULL, NULL);
return;
}
}
}
if (P_MobjWasRemovedCompat(mobj))
@@ -9389,24 +9447,6 @@ void P_MobjThinker(mobj_t *mobj)
// Can end up here if a player dies.
P_CycleMobjState(mobj);
if (P_MobjWasRemoved(mobj))
return;
if ((mobj->health == 0) && // Fading tile
(mobj->type >= MT_BOUNCEPICKUP && mobj->type <= MT_GRENADEPICKUP))
{
INT32 value = mobj->info->damage/10;
value = mobj->fuse/value;
value = 10-value;
value--;
if (value <= 0)
value = 1;
mobj->frame &= ~FF_TRANSMASK;
mobj->frame |= value << FF_TRANSSHIFT;
}
}
// Quick, optimized function for the Rail Rings
@@ -9660,20 +9700,13 @@ mobj_t *P_SpawnMobj(fixed_t x, fixed_t y, fixed_t z, mobjtype_t type)
// All mobjs are created at 100% scale.
mobj->scale = FRACUNIT;
mobj->destscale = mobj->scale;
mobj->scalespeed = FRACUNIT/12;
if (mapobjectscale != FRACUNIT) //&& !(mobj->type == MT_BLACKEGGMAN)
{
mobj->destscale = mapobjectscale;
mobj->scalespeed = mapobjectscale/12;
}
mobj->destscale = mapobjectscale;
mobj->scalespeed = mapobjectscale/12;
// Sprite rendering
mobj->blendmode = AST_TRANSLUCENT;
mobj->realxscale = mobj->realyscale = mobj->scale;
mobj->spritexscale = mobj->realxscale;
mobj->spriteyscale = mobj->realyscale;
mobj->realxscale = mobj->realyscale =
mobj->spritexscale = mobj->spriteyscale = mobj->scale;
// set subsector and/or block links
P_SetThingPosition(mobj);
@@ -10115,20 +10148,13 @@ mobj_t *P_SpawnShadowMobj(mobj_t * caster)
// All mobjs are created at 100% scale.
mobj->scale = FRACUNIT;
mobj->destscale = mobj->scale;
mobj->scalespeed = FRACUNIT/12;
if (mapobjectscale != FRACUNIT) //&& !(mobj->type == MT_BLACKEGGMAN)
{
mobj->destscale = mapobjectscale;
mobj->scalespeed = mapobjectscale/12;
}
mobj->destscale = mapobjectscale;
mobj->scalespeed = mapobjectscale/12;
// Sprite rendering
mobj->blendmode = AST_TRANSLUCENT;
mobj->realxscale = mobj->realyscale = mobj->scale;
mobj->spritexscale = mobj->realxscale;
mobj->spriteyscale = mobj->realyscale;
mobj->realxscale = mobj->realyscale =
mobj->spritexscale = mobj->spriteyscale = mobj->scale;
// set subsector and/or block links
P_SetThingPosition(mobj);
@@ -10228,7 +10254,9 @@ static precipmobj_t *P_SpawnPrecipMobj(fixed_t x, fixed_t y, fixed_t z, mobjtype
P_CalculatePrecipFloor(mobj);
if (mobj->floorz != starting_floorz)
mobj->precipflags |= PCF_FOF;
{
; //mobj->precipflags |= PCF_FOF;
}
else
{
const INT32 special = GETSECSPECIAL(mobj->subsector->sector->special, 1);
@@ -10362,7 +10390,13 @@ void P_RemoveMobj(mobj_t *mobj)
// clear the reference from the mapthing
if (mobj->spawnpoint)
{
#ifdef PHOBOS_BUILD
P_SetTarget(&mobj->spawnpoint->mobj, NULL);
#else
mobj->spawnpoint->mobj = NULL;
#endif
}
R_RemoveMobjInterpolator(mobj);
@@ -10573,6 +10607,9 @@ void P_PrecipitationEffects(void)
P_SpawnLightningFlash(ss); // Spawn a quick flash thinker
}
if (sound_disabled)
return; // Sound off? D'aw, no fun.
const mobj_t *pmo = players[displayplayers[0]].mo;
// Local effects from here on out!
@@ -10580,9 +10617,6 @@ void P_PrecipitationEffects(void)
if (!playeringame[displayplayers[0]] || !pmo)
return;
if (sound_disabled)
return; // Sound off? D'aw, no fun.
const boolean sounds_rain = ((cv_drawdist_precip.value != 0) && rainsfx && (!leveltime || leveltime % 80 == 1));
if (!sounds_rain && !sounds_thunder)
@@ -10830,7 +10864,9 @@ void P_SpawnPlayer(INT32 playernum)
mobj_t *mobj;
if (p->playerstate == PST_REBORN)
{
G_PlayerReborn(playernum);
}
for (i = 0; i < MAXPLAYERS; i++)
{
@@ -10904,9 +10940,15 @@ void P_SpawnPlayer(INT32 playernum)
}
mobj = P_SpawnMobj(0, 0, 0, MT_PLAYER);
I_Assert(mobj != NULL);
#ifdef PHOBOS_BUILD
mobj->player = p;
P_SetTarget(&p->mo, mobj);
#else
(mobj->player = p)->mo = mobj;
//P_SetTarget(&p->mo, mobj);
#endif
mobj->angle = mobj->old_angle = 0;
+3 -17
View File
@@ -258,23 +258,12 @@ typedef enum
// PRECIPITATION flags ?! ?! ?!
//
typedef enum {
PCF_INVISIBLE = 1, // Don't draw.
PCF_INVISIBLE = 1, // Don't draw.
PCF_PIT = 1<<1, // Above pit.
PCF_FOF = 1<<2, // Above FOF.
PCF_MOVINGFOF = 1<<3, // Above MOVING FOF (this means we need to keep floorz up to date...)
PCF_SPLASH = 1<<4, // Splashed on the ground, return to the ceiling after the animation's over
PCF_THUNK = 1<<5, // Ran the thinker this tic.
PCF_SPLASH = 1<<2, // Splashed on the ground, return to the ceiling after the animation's over
PCF_THUNK = 1<<3, // Ran the thinker this tic.
} precipflag_t;
typedef struct salty_s
{
bool init;
bool ready;
bool tapping;
fixed_t zoffset;
fixed_t momz;
bool jump;
} salty_t;
// Map Object definition.
typedef struct mobj_s
@@ -412,9 +401,6 @@ typedef struct mobj_s
tic_t slamsoundtimer; // Funni slam sound when landing
// saltyhop! hardcode edition
salty_t salty;
// WARNING: New fields must be added separately to savegame and Lua.
boolean islocal; // BEWARE: islocal does not exist in vanilla, strictly to be used for locally loaded addons to not cause desynchs with the mobj linedef trigger check. DO NOT USE THIS IN ACTUAL ADDONS YOU INTEND TO USE ON YOUR SERVER
} mobj_t;
+36
View File
@@ -1109,6 +1109,10 @@ static void SaveMobjThinker(savebuffer_t *save, const thinker_t *th, const UINT8
if (mobj->type == MT_HOOPCENTER && mobj->threshold == 4242)
return;
// do not send over locally spawned mobjs
if (mobj->islocal)
return;
if (mobj->spawnpoint && mobj->info->doomednum != -1)
{
// spawnpoint is not modified but we must save it since it is an identifier
@@ -1134,9 +1138,17 @@ static void SaveMobjThinker(savebuffer_t *save, const thinker_t *th, const UINT8
if (mobj->momx != 0 || mobj->momy != 0 || mobj->momz != 0)
#endif
diff |= MD_MOM;
#ifdef PHOBOS_BUILD
if (mobj->radius != FixedMul(mapobjectscale, mobj->info->radius))
#else
if (mobj->radius != mobj->info->radius)
#endif
diff |= MD_RADIUS;
#ifdef PHOBOS_BUILD
if (mobj->height != FixedMul(mapobjectscale, mobj->info->height))
#else
if (mobj->height != mobj->info->height)
#endif
diff |= MD_HEIGHT;
if (mobj->flags != mobj->info->flags)
diff |= MD_FLAGS;
@@ -1179,11 +1191,19 @@ static void SaveMobjThinker(savebuffer_t *save, const thinker_t *th, const UINT8
diff |= MD_MOVEFACTOR;
if (mobj->fuse)
diff |= MD_FUSE;
#ifdef PHOBOS_BUILD
if (mobj->watertop != INT32_MAX)
#else
if (mobj->watertop)
#endif
diff |= MD_WATERTOP;
if (mobj->waterbottom)
diff |= MD_WATERBOTTOM;
#ifdef PHOBOS_BUILD
if (mobj->scale != mapobjectscale)
#else
if (mobj->scale != FRACUNIT)
#endif
diff |= MD_SCALE;
if (mobj->destscale != mobj->scale)
diff |= MD_DSCALE;
@@ -2090,11 +2110,19 @@ static void LoadMobjThinker(savebuffer_t *save, actionf_p1 thinker)
if (diff & MD_RADIUS)
mobj->radius = READFIXED(save->p);
else
#ifdef PHOBOS_BUILD
mobj->radius = FixedMul(mobj->info->radius, mapobjectscale);
#else
mobj->radius = mobj->info->radius;
#endif
if (diff & MD_HEIGHT)
mobj->height = READFIXED(save->p);
else
#ifdef PHOBOS_BUILD
mobj->height = FixedMul(mobj->info->height, mapobjectscale);
#else
mobj->height = mobj->info->height;
#endif
if (diff & MD_FLAGS)
mobj->flags = READUINT32(save->p);
else
@@ -2166,12 +2194,20 @@ static void LoadMobjThinker(savebuffer_t *save, actionf_p1 thinker)
mobj->fuse = READINT32(save->p);
if (diff & MD_WATERTOP)
mobj->watertop = READFIXED(save->p);
#ifdef PHOBOS_BUILD
else
mobj->watertop = INT32_MAX;
#endif
if (diff & MD_WATERBOTTOM)
mobj->waterbottom = READFIXED(save->p);
if (diff & MD_SCALE)
mobj->scale = READFIXED(save->p);
else
#ifdef PHOBOS_BUILD
mobj->scale = mapobjectscale;
#else
mobj->scale = FRACUNIT;
#endif
if (diff & MD_DSCALE)
mobj->destscale = READFIXED(save->p);
else
+18 -7
View File
@@ -570,13 +570,13 @@ static void P_LoadSegs(UINT8 *data)
if (seg->sidedef == &sides[seg->linedef->sidenum[0]])
{
seg->v1 = lines[ms->linedef].v1;
seg->v2 = lines[ms->linedef].v2;
seg->v1 = lines[rawlinedef].v1;
seg->v2 = lines[rawlinedef].v2;
}
else
{
seg->v1 = lines[ms->linedef].v2;
seg->v2 = lines[ms->linedef].v1;
seg->v1 = lines[rawlinedef].v2;
seg->v2 = lines[rawlinedef].v1;
}
}
else
@@ -584,7 +584,6 @@ static void P_LoadSegs(UINT8 *data)
seg->v1 = &vertexes[v1];
seg->v2 = &vertexes[v2];
}
#ifdef HWRENDER
if (rendermode == render_opengl)
{
@@ -597,7 +596,6 @@ static void P_LoadSegs(UINT8 *data)
//seg->fv2.z = FixedToFloat(seg->v2->z);
}
#endif
seg->length = P_SegLength(seg);
P_UpdateSegLightOffset(seg);
@@ -2096,6 +2094,13 @@ static void P_LoadMapBSP(const virtres_t* virt)
virtlump_t* virtsegs = vres_Find(virt, "SEGS");
virtlump_t* virtnodes = vres_Find(virt, "NODES");
if (!virtssectors)
I_Error("SSECTORS lump not found");
if (!virtsegs)
I_Error("SEGS lump not found");
if (!virtnodes)
I_Error("NODES lump not found");
numsubsectors = virtssectors->size / sizeof(mapsubsector_t);
numnodes = virtnodes->size / sizeof(mapnode_t);
numsegs = virtsegs->size / sizeof(mapseg_t);
@@ -3424,7 +3429,13 @@ UINT16 P_PartialAddWadFile(const char *wadfilename, boolean local)
{
// check if someone tries to load maps locally lol
// do this here so we can skip loading the file anyways
if (W_CheckAutoLoadContainsMap(wadfilename))
int retmap = W_CheckAutoLoadContainsMap(wadfilename);
if (retmap == -1)
{
CONS_Alert(CONS_WARNING, "addilelocal: file %s was not found or not valid.\n", wadfilename);
return UINT16_MAX;
}
if (retmap > 0)
{
CONS_Alert(CONS_WARNING, "addilelocal: locally added file %s contains map data, this WILL cause crashes and desynchs! not added.\n", wadfilename);
return UINT16_MAX;
+9 -3
View File
@@ -1962,13 +1962,19 @@ static void P_ProcessLineSpecial(line_t *line, mobj_t *mo, sector_t *callsec)
if (!dest)
return;
const angle_t ang = (line->flags & ML_NOCLIMB) ? mo->angle : dest->angle;
const boolean dontstopmove = (line->flags & ML_EFFECT4) == ML_EFFECT4;
if (bot)
P_Teleport(bot, dest->x, dest->y, dest->z, (line->flags & ML_NOCLIMB) ? mo->angle : dest->angle, (line->flags & ML_BLOCKMONSTERS) == 0, (line->flags & ML_EFFECT4) == ML_EFFECT4);
P_Teleport(bot, dest->x, dest->y, dest->z, ang, (line->flags & ML_BLOCKMONSTERS) == 0, dontstopmove);
if (line->flags & ML_BLOCKMONSTERS)
P_Teleport(mo, dest->x, dest->y, dest->z, (line->flags & ML_NOCLIMB) ? mo->angle : dest->angle, false, (line->flags & ML_EFFECT4) == ML_EFFECT4);
{
P_Teleport(mo, dest->x, dest->y, dest->z, ang, false, dontstopmove);
}
else
{
P_Teleport(mo, dest->x, dest->y, dest->z, (line->flags & ML_NOCLIMB) ? mo->angle : dest->angle, true, (line->flags & ML_EFFECT4) == ML_EFFECT4);
P_Teleport(mo, dest->x, dest->y, dest->z, ang, true, dontstopmove);
// Play the 'bowrwoosh!' sound
S_StartSound(dest, sfx_mixup);
}
+17 -11
View File
@@ -91,7 +91,7 @@ void P_InstaThrust(mobj_t *mo, angle_t angle, fixed_t move)
mo->momx = FixedMul(move, FINECOSINE(angle));
if (!twodmo(mo))
mo->momy = FixedMul(move,FINESINE(angle));
mo->momy = FixedMul(move, FINESINE(angle));
}
void P_InstaThrustEvenIn2D(mobj_t *mo, angle_t angle, fixed_t move)
@@ -4517,27 +4517,33 @@ static void DoABarrelRoll(player_t *player)
static void P_DoFunnyDance(player_t *player)
{
fixed_t bpm; // 140bpm ish
fixed_t work, ang, bounce; // hehe squishy
if (player->spectator || !player->mo || player->kartstuff[k_respawn] || player->mo->salty.jump) // this looks jank as hell during hop
I_Assert(player != NULL);
I_Assert(!P_MobjWasRemoved(player->mo));
if (player->spectator)
return;
player->squishdance.bounce = 0;
// this looks jank as hell during hop or respawn
if (player->kartstuff[k_respawn] || player->salty.jump)
return;
// bpm = FixedDiv((60*TICRATE)<<FRACBITS, FLOAT_TO_FIXED(mapmusic.bpm)); << maybe can get the tempo and beat detection lib to work for bpm autodetection
bpm = FixedDiv((60*TICRATE)<<FRACBITS, FLOAT_TO_FIXED((float)cv_squishdancespeed.value));
bpm = ((60*TICRATE) / (cv_squishdancespeed.value)) << FRACBITS;
player->squishdance.work = (player->squishdance.time << FRACBITS) % bpm;
work = (player->squishdance.time << FRACBITS) % bpm;
if (player->squishdance.time >= (FRACUNIT >> 1)) // prevent overflow jump - takes about 15 minutes
player->squishdance.time = (player->squishdance.work >> FRACBITS);
player->squishdance.time = (work >> FRACBITS);
player->squishdance.work = FixedDiv(player->squishdance.work*180, bpm);
work = FixedDiv(work*180, bpm);
player->squishdance.ang = ((FixedAngle(player->squishdance.work) >> ANGLETOFINESHIFT) & FINEMASK);
player->squishdance.bounce = ((FINESINE(player->squishdance.ang) - FRACUNIT/2) / 2);
ang = ((FixedAngle(work) >> ANGLETOFINESHIFT) & FINEMASK);
bounce = ((FINESINE(ang) - FRACUNIT/2) / 2);
player->mo->spritexscale -= player->squishdance.bounce;
player->mo->spriteyscale += player->squishdance.bounce;
player->mo->spritexscale -= bounce;
player->mo->spriteyscale += bounce;
player->squishdance.time++;
}
+3
View File
@@ -504,6 +504,9 @@ typedef struct subsector_s
void *splats; // floorsplat_t list
#endif
size_t validcount;
#ifdef HWRENDER
boolean hashorizon; // not really needed for software, this stuff works differently there
#endif
} subsector_t;
// Sector list node showing all sectors an object appears in.
+1 -1
View File
@@ -6,7 +6,7 @@
// Copyright (C) 1996 by id Software, Inc.
// Copyright (C) 1999 by Chi Hoang, Lee Killough, Jim Flynn, Rand Phares, Ty Halderman
// Copyright (C) 1999-2000 by Jess Haas, Nicolas Kalkhof, Colin Phipps, Florian Schulze
// Copyright (C) Copyright 2005, 2006 by Florian Schulze, Colin Phipps, Neil Stevens, Andrey Budko
// Copyright (C) 2005, 2006 by Florian Schulze, Colin Phipps, Neil Stevens, Andrey Budko
// Copyright (C) 2013 by James Haley, Stephen McGranahan, et al.
//
// This program is free software distributed under the
+6 -38
View File
@@ -61,7 +61,6 @@ fixed_t rw_distance = 0;
static INT32 rw_x, rw_stopx;
static angle_t rw_centerangle;
static fixed_t rw_offset;
static fixed_t rw_offset2; // for splats
static fixed_t rw_scale, rw_scalestep;
static fixed_t rw_midtexturemid, rw_toptexturemid, rw_bottomtexturemid;
static INT32 worldtop, worldbottom, worldhigh, worldlow;
@@ -264,12 +263,7 @@ static void R_RenderMaskedSegLoop(drawcolumndata_t* dc, drawseg_t *drawseg, INT3
else if (P_ApplyLightOffset(lightnum, frontsector))
lightnum += curline->lightOffset;
if (lightnum < 0)
walllights = scalelight[0];
else if (lightnum >= LIGHTLEVELS)
walllights = scalelight[LIGHTLEVELS - 1];
else
walllights = scalelight[lightnum];
walllights = R_GetWallLight(lightnum);
}
if (frontsector->heightsec != -1)
@@ -371,12 +365,7 @@ static void R_RenderMaskedSegLoop(drawcolumndata_t* dc, drawseg_t *drawseg, INT3
lightnum = rlight->lightnum;
if (lightnum < 0)
xwalllights = scalelight[0];
else if (lightnum >= LIGHTLEVELS)
xwalllights = scalelight[LIGHTLEVELS-1];
else
xwalllights = scalelight[lightnum];
xwalllights = R_GetWallLight(lightnum);
pindex = FixedMul(spryscale, LIGHTRESOLUTIONFIX)>>LIGHTSCALESHIFT;
@@ -824,12 +813,7 @@ void R_RenderThickSideRange(drawseg_t *drawseg, INT32 x1, INT32 x2, ffloor_t *pf
else if (P_ApplyLightOffset(lightnum, frontsector))
lightnum += curline->lightOffset;
if (lightnum < 0)
walllights = scalelight[0];
else if (lightnum >= LIGHTLEVELS)
walllights = scalelight[LIGHTLEVELS-1];
else
walllights = scalelight[lightnum];
walllights = R_GetWallLight(lightnum);
}
maskedtexturecol = drawseg->thicksidecol;
@@ -971,12 +955,7 @@ void R_RenderThickSideRange(drawseg_t *drawseg, INT32 x1, INT32 x2, ffloor_t *pf
lightnum = rlight->lightnum;
if (lightnum < 0)
xwalllights = scalelight[0];
else if (lightnum >= LIGHTLEVELS)
xwalllights = scalelight[LIGHTLEVELS-1];
else
xwalllights = scalelight[lightnum];
xwalllights = R_GetWallLight(lightnum);
pindex = FixedMul(spryscale, LIGHTRESOLUTIONFIX)>>LIGHTSCALESHIFT;
@@ -1467,12 +1446,7 @@ static void R_RenderSegLoop(drawcolumndata_t* dc)
else if (P_ApplyLightOffset(lightnum, curline->frontsector))
lightnum += curline->lightOffset;
if (lightnum < 0)
xwalllights = scalelight[0];
else if (lightnum >= LIGHTLEVELS)
xwalllights = scalelight[LIGHTLEVELS-1];
else
xwalllights = scalelight[lightnum];
xwalllights = R_GetWallLight(lightnum);
pindex = FixedMul(rw_scale, LIGHTRESOLUTIONFIX)>>LIGHTSCALESHIFT;
@@ -2551,7 +2525,6 @@ void R_StoreWallRange(INT32 start, INT32 stop)
rw_offset = -rw_offset;
/// don't use texture offset for splats
rw_offset2 = rw_offset + curline->offset;
rw_offset += sidedef->textureoffset + curline->offset;
rw_centerangle = ANGLE_90 + viewangle - rw_normalangle;
@@ -2564,12 +2537,7 @@ void R_StoreWallRange(INT32 start, INT32 stop)
if (P_ApplyLightOffset(lightnum, frontsector))
lightnum += curline->lightOffset;
if (lightnum < 0)
walllights = scalelight[0];
else if (lightnum >= LIGHTLEVELS)
walllights = scalelight[LIGHTLEVELS - 1];
else
walllights = scalelight[lightnum];
walllights = R_GetWallLight(lightnum);
}
// if a floor / ceiling plane is on the wrong side
+5
View File
@@ -22,6 +22,11 @@ extern "C" {
#pragma interface
#endif
FUNCINLINE static ATTRINLINE lighttable_t** R_GetWallLight(INT32 llevel)
{
return scalelight[CLAMP(llevel, 0, LIGHTLEVELS-1)];
}
void R_RenderMaskedSegRange(drawseg_t *ds, INT32 x1, INT32 x2);
void R_RenderThickSideRange(drawseg_t *ds, INT32 x1, INT32 x2, ffloor_t *pffloor);
void R_StoreWallRange(INT32 start, INT32 stop);
+5 -20
View File
@@ -1062,12 +1062,7 @@ static void R_SplitSprite(vissprite_t *sprite)
{
INT32 lightnum = R_GetSoftLightlevel(*sector->lightlist[i].lightlevel);
if (lightnum < 0)
spritelights = scalelight[0];
else if (lightnum >= LIGHTLEVELS)
spritelights = scalelight[LIGHTLEVELS-1];
else
spritelights = scalelight[lightnum];
spritelights = R_GetWallLight(lightnum);
newsprite->extra_colormap = sector->lightlist[i].extra_colormap;
@@ -1745,12 +1740,7 @@ static void R_ProjectSprite(mobj_t *thing)
}
}
if (lightnum < 0)
lights_array = scalelight[0];
else if (lightnum >= LIGHTLEVELS)
lights_array = scalelight[LIGHTLEVELS-1];
else
lights_array = scalelight[lightnum];
lights_array = R_GetWallLight(lightnum);
}
// store information in a vissprite
@@ -2087,16 +2077,11 @@ void R_AddSprites(sector_t *sec, INT32 lightlevel)
if (!sec->numlights)
{
if (sec->heightsec == -1) lightlevel = sec->lightlevel;
if (sec->heightsec == -1)
lightlevel = sec->lightlevel;
lightnum = R_GetSoftLightlevel(lightlevel);
if (lightnum < 0)
spritelights = scalelight[0];
else if (lightnum >= LIGHTLEVELS)
spritelights = scalelight[LIGHTLEVELS-1];
else
spritelights = scalelight[lightnum];
spritelights = R_GetWallLight(lightnum);
}
// Handle all things in sector.
+8 -3
View File
@@ -233,20 +233,25 @@ if(${SDL2_FOUND})
-DHAVE_THREADS
)
if(SRB2_CONFIG_LTO AND NOT SRB2_CONFIG_DEBUGMODE)
if(SRB2_CONFIG_LTO AND NOT SRB2_CONFIG_DEBUGMODE AND NOT SRB2_CONFIG_ASAN AND NOT SRB2_CONFIG_UBSAN AND NOT SRB2_CONFIG_TSAN)
set_property(TARGET SRB2SDL2 PROPERTY INTERPROCEDURAL_OPTIMIZATION TRUE)
endif()
if(SRB2_CONFIG_ASAN)
target_compile_options(SRB2SDL2 PRIVATE -fsanitize=address)
target_compile_options(SRB2SDL2 PRIVATE -O1 -fsanitize=address -fno-omit-frame-pointer -fno-common)
target_link_options(SRB2SDL2 PRIVATE -fsanitize=address)
endif()
if(SRB2_CONFIG_UBSAN)
target_compile_options(SRB2SDL2 PRIVATE -fsanitize=undefined)
target_compile_options(SRB2SDL2 PRIVATE -O1 -fsanitize=undefined -fno-omit-frame-pointer)
target_link_options(SRB2SDL2 PRIVATE -fsanitize=undefined)
endif()
if(SRB2_CONFIG_TSAN)
target_compile_options(SRB2SDL2 PRIVATE -O1 -fsanitize=thread -fno-omit-frame-pointer)
target_link_options(SRB2SDL2 PRIVATE -fsanitize=thread)
endif()
if(NOT SRB2_CONFIG_MUMBLE)
target_compile_options(SRB2SDL2 PRIVATE -DNOMUMBLE)
endif()
+34 -104
View File
@@ -97,11 +97,9 @@ static char vidModeName[33][32]; // allow 33 different modes
rendermode_t rendermode = render_none;
#ifdef HWRENDER
unsigned msaa = 0;
// Eee probably the way i organize it isn't best ><
// Just don't know where do i put declaration and "implementation"
boolean a2c = false;
unsigned msaa = 0;
#endif
static void KeyboardLayout_OnChange(void)
@@ -115,10 +113,6 @@ consvar_t cv_keyboardlayout = {"keyboardlayout", "Default US", CV_SAVE|CV_CALL,
static void Impl_SetVsync(void);
static INT32 desktopwidth = 0, desktopheight = 0;
static void I_CheckDesktopRes(void);
// synchronize page flipping with screen refresh
consvar_t cv_vidwait = {"vid_wait", "Off", CV_SAVE|CV_CALL|CV_NOINIT, CV_OnOff, Impl_SetVsync, 0, NULL, NULL, 0, 0, NULL};
static consvar_t cv_stretch = {"stretch", "Off", CV_SAVE|CV_NOSHOWHELP, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL};
@@ -197,10 +191,6 @@ static INT32 custom_height = 0;
static SDL_bool Impl_CreateWindow(SDL_bool fullscreen);
static void Impl_SetWindowIcon(void);
#ifdef USE_FBO_OGL
boolean downsample = false;
#endif
static INT32 Impl_SDL_Scancode_To_Keycode(SDL_Scancode code)
{
if (code >= SDL_SCANCODE_A && code <= SDL_SCANCODE_Z)
@@ -518,11 +508,11 @@ static void Impl_HandleWindowEvent(SDL_WindowEvent evt)
return;
}
if (windowmoved && rendermode == render_opengl)
if (windowmoved)
{
I_CheckDesktopRes();
#ifdef USE_FBO_OGL
I_DownSample();
if (rendermode == render_opengl)
I_CheckDownSampleState(false);
#endif
windowmoved = SDL_FALSE;
}
@@ -1229,9 +1219,7 @@ static void VID_Command_ModeList_f(void)
// List windowed modes
INT32 i = 0;
CONS_Printf("NOTE: Under SDL2, all modes are supported on all platforms.\n"
"Under opengl, fullscreen only supports native desktop resolution.\n"
"Under software, the mode is stretched up to desktop resolution.\n");
CONS_Printf("NOTE: Under SDL2, all modes are supported on all platforms.\n");
for (i = 0; i < MAXWINMODES; i++)
{
@@ -1257,78 +1245,41 @@ static void VID_Command_Mode_f (void)
setmodeneeded = modenum+1; // request vid mode change
}
// Get the desktop resolution from the current display the gamewindow resides on
static void I_CheckDesktopRes(void)
{
int currentDisplayIndex = -1;
SDL_DisplayMode curmode;
desktopwidth = 0;
desktopheight = 0;
currentDisplayIndex = SDL_GetWindowDisplayIndex(window);
// No valid index
if (currentDisplayIndex < 0)
{
return;
}
if (SDL_GetDesktopDisplayMode(currentDisplayIndex, &curmode) != 0)
{
return;
}
desktopwidth = curmode.w;
desktopheight = curmode.h;
}
// Check if the game resolution matches the desktop resolution
boolean I_CheckNativeRes(void)
{
return (vid.width == desktopwidth && vid.height == desktopheight);
}
#ifdef USE_FBO_OGL
static boolean vid_downsampling = false;
void RefreshOGLSDLSurface(void)
boolean I_IsDownsampling(void)
{
if (rendermode == render_opengl)
OglSdlSurface(vid.width, vid.height);
return vid_downsampling;
}
void I_DownSample(void)
void I_CheckDownSampleState(boolean forcerefresh)
{
boolean needrefresh = false;
if (!cv_glframebuffer.value || !supportFBO || (cv_glscreentextures.value == 0)) // no sense to do this crap if we cant benefit from it
// no fbo support so we dont care
if (!supportFBO)
{
downsample = false;
vid_downsampling = false;
return;
}
if (I_CheckNativeRes() && (downsample == true))
// no sense to do this crap if we cant benefit from it
boolean newdownsamplestate = false;
if (cv_glframebuffer.value && (cv_glscreentextures.value == 2))
{
downsample = false;
RefreshOGLSDLSurface();
return;
int sdlw, sdlh;
SDL_GetWindowSize(window, &sdlw, &sdlh);
if (vid.width > sdlw || vid.height > sdlh)
newdownsamplestate = true;
}
if ((vid.width > desktopwidth) || (vid.height > desktopheight)) //check if current resolution is higher than current display resolution
// state changed or fbo was toggled
if (vid_downsampling != newdownsamplestate || forcerefresh)
{
downsample = true;
needrefresh = true;
}
else if (downsample == true)
{
downsample = false;
needrefresh = true;
}
if (needrefresh)
{
RefreshOGLSDLSurface();
needrefresh = false;
//printf("downsample changed from %d to %d\n", vid_downsampling, newdownsamplestate);
// needs to be reset before refreshing the gl surface!
vid_downsampling = newdownsamplestate;
OglSdlSurface(vid.width, vid.height);
}
}
#endif
@@ -1360,9 +1311,10 @@ static void SDLSetMode(INT32 width, INT32 height, SDL_bool fullscreen)
// Reposition window only in windowed mode
SDL_SetWindowSize(window, width, height);
const int windowpos = SDL_GetWindowDisplayIndex(window);
SDL_SetWindowPosition(window,
SDL_WINDOWPOS_CENTERED_DISPLAY(SDL_GetWindowDisplayIndex(window)),
SDL_WINDOWPOS_CENTERED_DISPLAY(SDL_GetWindowDisplayIndex(window))
SDL_WINDOWPOS_CENTERED_DISPLAY(windowpos),
SDL_WINDOWPOS_CENTERED_DISPLAY(windowpos)
);
}
}
@@ -1382,9 +1334,8 @@ static void SDLSetMode(INT32 width, INT32 height, SDL_bool fullscreen)
#ifdef HWRENDER
if (rendermode == render_opengl)
{
I_CheckDesktopRes();
#ifdef USE_FBO_OGL
I_DownSample();
I_CheckDownSampleState(false);
#endif
OglSdlSurface(vid.width, vid.height);
}
@@ -1580,7 +1531,7 @@ void VID_PrepareModeList(void)
static UINT32 refresh_rate;
static UINT32 VID_GetRefreshRate(void)
{
int index = SDL_GetWindowDisplayIndex(window);
int index;
SDL_DisplayMode m;
if (SDL_WasInit(SDL_INIT_VIDEO) == 0)
@@ -1589,6 +1540,8 @@ static UINT32 VID_GetRefreshRate(void)
return 0;
}
index = SDL_GetWindowDisplayIndex(window);
if (SDL_GetDesktopDisplayMode(index, &m) != 0)
{
// Error has occurred.
@@ -1825,7 +1778,6 @@ void I_StartupGraphics(void)
rendermode = render_opengl;
msaa = 0; boolean msaa_set = false;
a2c = false; boolean a2c_set = false;
// MSAA antialiasing
if (M_CheckParm("-msaa") && M_IsNextParm())
@@ -1837,16 +1789,6 @@ void I_StartupGraphics(void)
}
}
if (M_CheckParm("-a2c"))
{
a2c = true;
a2c_set = true;
}
else if (M_CheckParm("-noa2c"))
{
a2c_set = true;
}
{
char line[16];
char * word;
@@ -1890,19 +1832,10 @@ void I_StartupGraphics(void)
}
else
{
CONS_Printf("Using last know MSAA value: %u\n", msaa);
CONS_Printf("Using last known MSAA value: %u\n", msaa);
}
}
}
if (!a2c_set)
{
if (fasticmp(word, "a2c"))
{
a2c = true;
CONS_Printf("Using a2c because it was specified to be used earlier\n");
}
}
}
fclose(file);
@@ -1937,9 +1870,6 @@ void I_StartupGraphics(void)
#ifdef HWRENDER
fprintf(file, "msaa %u\n", msaa);
if (a2c)
fputs("a2c\n", file);
#endif
fclose(file);
}
+7 -13
View File
@@ -65,7 +65,7 @@ PFNglGetString pglGetString;
#ifdef USE_FBO_OGL
boolean UseScreenFBO(void)
{
return (supportFBO && cv_glframebuffer.value && downsample);
return (supportFBO && cv_glframebuffer.value && (cv_glscreentextures.value == 2) && (cv_glframebuffer.value == 2 || I_IsDownsampling()));
}
#endif
@@ -203,9 +203,9 @@ boolean OglSdlSurface(INT32 w, INT32 h)
#ifdef USE_FBO_OGL
if (UseScreenFBO())
GL_Framebuffer_Enable();
GL_FBO_Enable();
else
GL_Framebuffer_Disable();
GL_FBO_Disable();
#endif
if (!first_init)
@@ -225,7 +225,6 @@ boolean OglSdlSurface(INT32 w, INT32 h)
void OglSdlFinishUpdate(SDL_Window *window)
{
int sdlw, sdlh;
#ifdef USE_FBO_OGL
const boolean usefbo = UseScreenFBO();
#endif
@@ -235,9 +234,7 @@ void OglSdlFinishUpdate(SDL_Window *window)
#ifdef USE_FBO_OGL
if (usefbo)
{
GL_Framebuffer_Unbind();
}
GL_FBO_BindMainFrameBuffer();
#endif
if (HWR_ShouldUsePaletteRendering())
@@ -255,9 +252,7 @@ void OglSdlFinishUpdate(SDL_Window *window)
#ifdef USE_FBO_OGL
if (usefbo)
{
GL_Framebuffer_Enable();
}
GL_FBO_Enable();
#endif
SDL_GL_SwapWindow(window);
@@ -266,11 +261,10 @@ void OglSdlFinishUpdate(SDL_Window *window)
// Sryder: We need to draw the final screen texture again into the other buffer in the original position so that
// effects that want to take the old screen can do so after this
// well we dont need it on native res it seems
#ifdef USE_FBO_OGL
if ((!I_CheckNativeRes() && !usefbo) || WipeInAction)
if (!usefbo && (realwidth != sdlw || realheight != sdlh)) // not needed if fbo is in use
#else
if (!I_CheckNativeRes() || WipeInAction)
if (realwidth != sdlw || realheight != sdlh) // this is not needed if the render size matches window size
#endif
HWR_DrawScreenFinalTexture(realwidth, realheight);
}
+4 -4
View File
@@ -1882,7 +1882,7 @@ void V_DrawVhsEffect(boolean rewind)
#ifdef HWRENDER
if (rendermode == render_opengl)
{
HWR_RenderVhsEffect(uby, dby, updistort, downdistort, barsize);
HWR_RenderVhsEffect(uby, dby, updistort, downdistort, barsize, rewind);
return;
}
#endif
@@ -3619,7 +3619,7 @@ void V_DoPostProcessor(INT32 view, INT32 param)
for (y = yoffset; y < yoffset+viewheight; y++)
{
sine = (FINESINE(disStart)*5)>>FRACBITS;
sine = (FINESINE(disStart) * 5) >> FRACBITS;
newpix = abs(sine);
if (sine < 0)
@@ -3659,8 +3659,8 @@ void V_DoPostProcessor(INT32 view, INT32 param)
tmpscr[y*vid.width + x] = srcscr[y*vid.width+newpix]; // *(transme + (srcscr[y*vid.width+x]<<8) + srcscr[y*vid.width+newpix]);
}*/
disStart += 22;//the offset into the displacement map, increment each game loop
disStart &= FINEMASK; //clip it to FINEMASK
disStart += 22; // the offset into the displacement map, increment each game loop
disStart &= FINEMASK; // clip it to FINEMASK
}
UINT8 *tmp = tmpscr;