Compare commits
29
Commits
lugstuff
...
shadercrap
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
59a4627911 | ||
|
|
ecab383078 | ||
|
|
ee4c060cc8 | ||
|
|
ebd5b86e87 | ||
|
|
9321036049 | ||
|
|
12f43ae504 | ||
|
|
cfc94c0f9e | ||
|
|
3385df4c7e | ||
|
|
561f871e61 | ||
|
|
bffafa0540 | ||
|
|
473619ab66 | ||
|
|
d75638cbfc | ||
|
|
f09b591989 | ||
|
|
79d75aa08d | ||
|
|
486560d79e | ||
|
|
953b0c8f94 | ||
|
|
5639e872f1 | ||
|
|
80da0fc538 | ||
|
|
014126b57d | ||
|
|
d7b150a04f | ||
|
|
5751f9b29b | ||
|
|
1a29bd1e63 | ||
|
|
e54b6a780d | ||
|
|
c1a0b97c54 | ||
|
|
b8aaf63b20 | ||
|
|
d43b60ad83 | ||
|
|
cb5d3ab4e1 | ||
|
|
eba1cfb94d | ||
|
|
f5030e6a3c |
No files matched your search
@@ -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
@@ -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
|
||||
|
||||
@@ -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]);
|
||||
|
||||
@@ -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)
|
||||
|
||||
+27
-58
@@ -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
@@ -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
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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
@@ -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
|
||||
|
||||
+2
-23
@@ -614,16 +614,8 @@ 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;
|
||||
INT32 k;
|
||||
|
||||
@@ -635,9 +627,6 @@ static void HWR_PrecacheLevelFlats(void)
|
||||
}
|
||||
#endif
|
||||
|
||||
flatcheck_init(&flatpresent);
|
||||
flatcheck_reserve(&flatpresent, numlevelflats);
|
||||
|
||||
// special case for encore
|
||||
#if 0
|
||||
#ifdef GLENCORE
|
||||
@@ -689,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 ?
|
||||
{
|
||||
@@ -701,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)
|
||||
|
||||
@@ -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
|
||||
};
|
||||
|
||||
|
||||
@@ -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);
|
||||
|
||||
+394
-91
@@ -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;
|
||||
}
|
||||
@@ -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 && !FOFsector && cv_glhorizonlines.value)
|
||||
if (subsector && subsector->hashorizon && cv_glhorizonlines.value)
|
||||
{
|
||||
// Horizon lines
|
||||
FOutVector horizonpts[6];
|
||||
@@ -806,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)
|
||||
{
|
||||
@@ -1239,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
|
||||
@@ -1385,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;
|
||||
|
||||
@@ -1396,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
|
||||
@@ -1406,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)
|
||||
@@ -1424,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
|
||||
@@ -1436,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)
|
||||
{
|
||||
@@ -1449,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);
|
||||
}
|
||||
@@ -1460,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))
|
||||
{
|
||||
@@ -1532,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))
|
||||
{
|
||||
@@ -2936,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
|
||||
{
|
||||
@@ -2957,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(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);
|
||||
}
|
||||
@@ -4167,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));
|
||||
|
||||
@@ -4181,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
|
||||
@@ -5704,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)
|
||||
{
|
||||
@@ -5714,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);
|
||||
@@ -5875,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();
|
||||
}
|
||||
@@ -5963,7 +6250,7 @@ void HWR_Shutdown(void)
|
||||
GL_FlushScreenTextures();
|
||||
HWR_ClearAllTextures();
|
||||
#ifdef USE_FBO_OGL
|
||||
GL_Framebuffer_Disable();
|
||||
GL_FBO_Disable();
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -6064,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)
|
||||
|
||||
@@ -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[];
|
||||
|
||||
@@ -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
@@ -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
@@ -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)
|
||||
|
||||
@@ -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
@@ -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
-2
@@ -14,8 +14,7 @@
|
||||
#include <string.h>
|
||||
|
||||
#ifdef HAVE_THREADS
|
||||
#include <threads.h>
|
||||
#define local_for_thread thread_local
|
||||
#define local_for_thread _Thread_local
|
||||
#else
|
||||
#define local_for_thread
|
||||
#endif
|
||||
|
||||
+18
-7
@@ -3989,6 +3989,10 @@ boolean replaynamesloaded = false;
|
||||
// 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;
|
||||
|
||||
@@ -4025,6 +4029,7 @@ static void ReplayNamesLoadThread(void* userdata)
|
||||
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);
|
||||
size_t localreplaythreadnum = replaythreadnum;
|
||||
const char *localdemodateformat = demodateformat;
|
||||
|
||||
Unlock_search_state();
|
||||
|
||||
@@ -4032,13 +4037,7 @@ 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);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4061,6 +4060,18 @@ static void LoadReplayNames(void)
|
||||
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
|
||||
|
||||
+2
-2
@@ -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
|
||||
|
||||
+11
-6
@@ -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);
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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
@@ -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
@@ -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
@@ -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;
|
||||
|
||||
Reference in new issue
Block a user