Merge remote-tracking branch 'gzdoom_upstream/master' into lightmath

# Conflicts:
#	src/gl/renderer/gl_renderbuffers.cpp
#	src/gl/renderer/gl_renderbuffers.h
#	src/gl/renderer/gl_renderer.h
#	src/gl/scene/gl_scene.cpp
#	wadsrc/static/language.enu
#	wadsrc/static/menudef.z
This commit is contained in:
Magnus Norddahl 2016-09-09 09:31:30 +02:00
commit f6bede8374
75 changed files with 4532 additions and 1016 deletions

BIN
docs/licenses/xBRZ.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 59 KiB

View file

@ -115,49 +115,59 @@ if( WIN32 )
set( FMOD_LIB_PATH_SUFFIXES PATH_SUFFIXES lib )
set( NASM_NAMES nasmw nasm )
find_path( D3D_INCLUDE_DIR d3d9.h
PATHS ENV DXSDK_DIR
PATH_SUFFIXES Include )
if( NOT D3D_INCLUDE_DIR )
message( SEND_ERROR "Could not find DirectX 9 header files" )
else()
include_directories( ${D3D_INCLUDE_DIR} )
endif()
if( NOT MSVC )
find_path( D3D_INCLUDE_DIR d3d9.h
PATHS ENV DXSDK_DIR
PATH_SUFFIXES Include )
if( NOT D3D_INCLUDE_DIR )
message( SEND_ERROR "Could not find DirectX 9 header files" )
else()
include_directories( ${D3D_INCLUDE_DIR} )
endif()
find_path( XINPUT_INCLUDE_DIR xinput.h
PATHS ENV DXSDK_DIR
PATH_SUFFIXES Include )
if( NOT XINPUT_INCLUDE_DIR )
message( WARNING "Could not find xinput.h. XInput will be disabled." )
add_definitions( -DNO_XINPUT )
find_path( XINPUT_INCLUDE_DIR xinput.h
PATHS ENV DXSDK_DIR
PATH_SUFFIXES Include )
if( NOT XINPUT_INCLUDE_DIR )
message( WARNING "Could not find xinput.h. XInput will be disabled." )
add_definitions( -DNO_XINPUT )
else()
include_directories( ${XINPUT_INCLUDE_DIR} )
endif()
find_library( DX_dxguid_LIBRARY dxguid
PATHS ENV DXSDK_DIR
PATH_SUFFIXES Lib Lib/${XBITS} )
find_library( DX_dinput8_LIBRARY dinput8
PATHS ENV DXSDK_DIR
PATH_SUFFIXES Lib Lib/${XBITS} )
set( DX_LIBS_FOUND YES )
if( NOT DX_dxguid_LIBRARY )
set( DX_LIBS_FOUND NO )
endif()
if( NOT DX_dinput8_LIBRARY )
set( DX_LIBS_FOUND NO )
endif()
if( NOT DX_LIBS_FOUND )
message( FATAL_ERROR "Could not find DirectX 9 libraries" )
endif()
set( DX_LIBS
"${DX_dxguid_LIBRARY}"
"${DX_dinput8_LIBRARY}"
)
else()
include_directories( ${XINPUT_INCLUDE_DIR} )
set( DX_LIBS
dxguid
dinput8
)
endif()
find_library( DX_dxguid_LIBRARY dxguid
PATHS ENV DXSDK_DIR
PATH_SUFFIXES Lib Lib/${XBITS} )
find_library( DX_dinput8_LIBRARY dinput8
PATHS ENV DXSDK_DIR
PATH_SUFFIXES Lib Lib/${XBITS} )
set( DX_LIBS_FOUND YES )
if( NOT DX_dxguid_LIBRARY )
set( DX_LIBS_FOUND NO )
endif()
if( NOT DX_dinput8_LIBRARY )
set( DX_LIBS_FOUND NO )
endif()
if( NOT DX_LIBS_FOUND )
message( FATAL_ERROR "Could not find DirectX 9 libraries" )
endif()
set( ZDOOM_LIBS
set( ZDOOM_LIBS ${DX_LIBS}
wsock32
winmm
"${DX_dxguid_LIBRARY}"
"${DX_dinput8_LIBRARY}"
ole32
user32
gdi32
@ -660,6 +670,7 @@ set( PLAT_WIN32_SOURCES
win32/i_main.cpp
win32/i_movie.cpp
win32/i_system.cpp
win32/i_specialpaths.cpp
win32/st_start.cpp
win32/win32gliface.cpp
win32/win32video.cpp )
@ -679,8 +690,11 @@ set( PLAT_SDL_SOURCES
posix/sdl/sdlvideo.cpp
posix/sdl/sdlglvideo.cpp
posix/sdl/st_start.cpp )
set( PLAT_UNIX_SOURCES
posix/unix/i_specialpaths.cpp )
set( PLAT_OSX_SOURCES
posix/osx/iwadpicker_cocoa.mm
posix/osx/i_specialpaths.mm
posix/osx/zdoom.icns )
set( PLAT_COCOA_SOURCES
posix/cocoa/critsec.cpp
@ -697,7 +711,7 @@ set( PLAT_COCOA_SOURCES
if( WIN32 )
set( SYSTEM_SOURCES_DIR win32 )
set( SYSTEM_SOURCES ${PLAT_WIN32_SOURCES} )
set( OTHER_SYSTEM_SOURCES ${PLAT_POSIX_SOURCES} ${PLAT_SDL_SOURCES} ${PLAT_OSX_SOURCES} ${PLAT_COCOA_SOURCES} )
set( OTHER_SYSTEM_SOURCES ${PLAT_POSIX_SOURCES} ${PLAT_SDL_SOURCES} ${PLAT_OSX_SOURCES} ${PLAT_COCOA_SOURCES} ${PLAT_UNIX_SOURCES} )
if( ZD_CMAKE_COMPILER_IS_GNUCXX_COMPATIBLE )
# CMake is not set up to compile and link rc files with GCC. :(
@ -712,12 +726,12 @@ elseif( APPLE )
if( OSX_COCOA_BACKEND )
set( SYSTEM_SOURCES_DIR posix posix/cocoa )
set( SYSTEM_SOURCES ${PLAT_COCOA_SOURCES} )
set( OTHER_SYSTEM_SOURCES ${PLAT_WIN32_SOURCES} ${PLAT_SDL_SOURCES} )
set( OTHER_SYSTEM_SOURCES ${PLAT_WIN32_SOURCES} ${PLAT_SDL_SOURCES} ${PLAT_UNIX_SOURCES} )
else()
set( SYSTEM_SOURCES_DIR posix posix/sdl )
set( SYSTEM_SOURCES ${PLAT_SDL_SOURCES} )
set( PLAT_OSX_SOURCES ${PLAT_OSX_SOURCES} posix/sdl/i_system.mm )
set( OTHER_SYSTEM_SOURCES ${PLAT_WIN32_SOURCES} ${PLAT_COCOA_SOURCES} )
set( OTHER_SYSTEM_SOURCES ${PLAT_WIN32_SOURCES} ${PLAT_COCOA_SOURCES} ${PLAT_UNIX_SOURCES} )
endif()
set( SYSTEM_SOURCES ${SYSTEM_SOURCES} ${PLAT_POSIX_SOURCES} ${PLAT_OSX_SOURCES} "${FMOD_LIBRARY}" )
@ -727,7 +741,7 @@ elseif( APPLE )
set_source_files_properties( posix/osx/iwadpicker_cocoa.mm PROPERTIES COMPILE_FLAGS -fobjc-exceptions )
else()
set( SYSTEM_SOURCES_DIR posix posix/sdl )
set( SYSTEM_SOURCES ${PLAT_POSIX_SOURCES} ${PLAT_SDL_SOURCES} )
set( SYSTEM_SOURCES ${PLAT_POSIX_SOURCES} ${PLAT_SDL_SOURCES} ${PLAT_UNIX_SOURCES} )
set( OTHER_SYSTEM_SOURCES ${PLAT_WIN32_SOURCES} ${PLAT_OSX_SOURCES} ${PLAT_COCOA_SOURCES} )
endif()
@ -849,6 +863,7 @@ file( GLOB HEADER_FILES
gl/dynlights/*.h
gl/hqnx/*.h
gl/hqnx_asm/*.h
gl/xbr/*.h
gl/models/*.h
gl/renderer/*.h
gl/scene/*.h
@ -1072,6 +1087,8 @@ set( FASTMATH_SOURCES
gl/hqnx/hq2x.cpp
gl/hqnx/hq3x.cpp
gl/hqnx/hq4x.cpp
gl/xbr/xbrz.cpp
gl/xbr/xbrz_old.cpp
gl/textures/gl_hwtexture.cpp
gl/textures/gl_texture.cpp
gl/textures/gl_material.cpp
@ -1385,7 +1402,6 @@ add_executable( zdoom WIN32 MACOSX_BUNDLE
${FASTMATH_SOURCES}
${PCH_SOURCES}
x86.cpp
m_specialpaths.cpp
strnatcmp.c
zstring.cpp
math/asin.c
@ -1543,7 +1559,8 @@ source_group("OpenGL Renderer" REGULAR_EXPRESSION "^${CMAKE_CURRENT_SOURCE_DIR}/
source_group("OpenGL Renderer\\Data" REGULAR_EXPRESSION "^${CMAKE_CURRENT_SOURCE_DIR}/gl/data/.+")
source_group("OpenGL Renderer\\Dynamic Lights" REGULAR_EXPRESSION "^${CMAKE_CURRENT_SOURCE_DIR}/gl/dynlights/.+")
source_group("OpenGL Renderer\\HQ Resize" REGULAR_EXPRESSION "^${CMAKE_CURRENT_SOURCE_DIR}/gl/hqnx/.+")
source_group("OpenGL Renderer\\HQ Resize Assembly version" REGULAR_EXPRESSION "^${CMAKE_CURRENT_SOURCE_DIR}/gl/hqnx_asm/.+")
source_group("OpenGL Renderer\\HQ Resize MMX version" REGULAR_EXPRESSION "^${CMAKE_CURRENT_SOURCE_DIR}/gl/hqnx_asm/.+")
source_group("OpenGL Renderer\\XBRZ" REGULAR_EXPRESSION "^${CMAKE_CURRENT_SOURCE_DIR}/gl/hqnx_asm/.+")
source_group("OpenGL Renderer\\Models" REGULAR_EXPRESSION "^${CMAKE_CURRENT_SOURCE_DIR}/gl/models/.+")
source_group("OpenGL Renderer\\Renderer" REGULAR_EXPRESSION "^${CMAKE_CURRENT_SOURCE_DIR}/gl/renderer/.+")
source_group("OpenGL Renderer\\Scene" REGULAR_EXPRESSION "^${CMAKE_CURRENT_SOURCE_DIR}/gl/scene/.+")
@ -1562,6 +1579,7 @@ source_group("Resource Files" REGULAR_EXPRESSION "^${CMAKE_CURRENT_SOURCE_DIR}/r
source_group("POSIX Files" REGULAR_EXPRESSION "^${CMAKE_CURRENT_SOURCE_DIR}/posix/.+")
source_group("Cocoa Files" REGULAR_EXPRESSION "^${CMAKE_CURRENT_SOURCE_DIR}/posix/cocoa/.+")
source_group("OS X Files" REGULAR_EXPRESSION "^${CMAKE_CURRENT_SOURCE_DIR}/posix/osx/.+")
source_group("Unix Files" REGULAR_EXPRESSION "^${CMAKE_CURRENT_SOURCE_DIR}/posix/unix/.+")
source_group("SDL Files" REGULAR_EXPRESSION "^${CMAKE_CURRENT_SOURCE_DIR}/posix/sdl/.+")
source_group("SFMT" REGULAR_EXPRESSION "^${CMAKE_CURRENT_SOURCE_DIR}/sfmt/.+")
source_group("Shared Game" REGULAR_EXPRESSION "^${CMAKE_CURRENT_SOURCE_DIR}/g_shared/.+")

View file

@ -283,7 +283,7 @@ enum ActorFlag4
enum ActorFlag5
{
MF5_DONTDRAIN = 0x00000001, // cannot be drained health from.
/* FREE SLOT 0x00000002*/
MF5_GETOWNER = 0x00000002,
MF5_NODROPOFF = 0x00000004, // cannot drop off under any circumstances.
MF5_NOFORWARDFALL = 0x00000008, // Does not make any actor fall forward by being damaged by this
MF5_COUNTSECRET = 0x00000010, // From Doom 64: actor acts like a secret

View file

@ -159,12 +159,37 @@ static int HistSize;
CVAR (Float, con_notifytime, 3.f, CVAR_ARCHIVE)
CVAR (Bool, con_centernotify, false, CVAR_ARCHIVE)
CUSTOM_CVAR (Int, con_scaletext, 0, CVAR_ARCHIVE) // Scale notify text at high resolutions?
CUSTOM_CVAR (Int, con_scaletext, 1, CVAR_ARCHIVE) // Scale notify text at high resolutions?
{
if (self < 0) self = 0;
if (self > 3) self = 3;
}
CUSTOM_CVAR(Int, con_scale, 0, CVAR_ARCHIVE)
{
if (self < 0) self = 0;
}
int active_con_scale()
{
if (con_scale == 0)
return uiscale;
else
return con_scale;
}
int active_con_scaletext()
{
switch (con_scaletext)
{
default:
case 0: return 1;
case 1: return uiscale;
case 2: return 2;
case 3: return 4;
}
}
CUSTOM_CVAR(Float, con_alpha, 0.75f, CVAR_ARCHIVE)
{
if (self < 0.f) self = 0.f;
@ -493,13 +518,13 @@ void C_AddNotifyString (int printlevel, const char *source)
return;
}
switch (con_scaletext)
if (active_con_scaletext() == 0)
{
default:
case 0: width = DisplayWidth; break;
case 1: width = DisplayWidth / CleanXfac; break;
case 2: width = DisplayWidth / 2; break;
case 3: width = DisplayWidth / 4; break;
width = DisplayWidth / CleanXfac;
}
else
{
width = DisplayWidth / active_con_scaletext();
}
if (addtype == APPENDLINE && NotifyStrings[NUMNOTIFIES-1].PrintLevel == printlevel)
@ -721,7 +746,7 @@ static void C_DrawNotifyText ()
canskip = true;
lineadv = SmallFont->GetHeight ();
if (con_scaletext == 1)
if (active_con_scaletext() == 0)
{
lineadv *= CleanYfac;
}
@ -755,7 +780,7 @@ static void C_DrawNotifyText ()
else
color = PrintColors[NotifyStrings[i].PrintLevel];
if (con_scaletext == 1)
if (active_con_scaletext() == 0)
{
if (!center)
screen->DrawText (SmallFont, color, 0, line, NotifyStrings[i].Text,
@ -766,7 +791,7 @@ static void C_DrawNotifyText ()
line, NotifyStrings[i].Text, DTA_CleanNoMove, true,
DTA_AlphaF, alpha, TAG_DONE);
}
else if (con_scaletext == 0)
else if (active_con_scaletext() == 1)
{
if (!center)
screen->DrawText (SmallFont, color, 0, line, NotifyStrings[i].Text,
@ -777,37 +802,20 @@ static void C_DrawNotifyText ()
line, NotifyStrings[i].Text,
DTA_AlphaF, alpha, TAG_DONE);
}
else if (con_scaletext == 3)
{
if (!center)
screen->DrawText (SmallFont, color, 0, line, NotifyStrings[i].Text,
DTA_VirtualWidth, screen->GetWidth() / 4,
DTA_VirtualHeight, screen->GetHeight() / 4,
DTA_KeepRatio, true,
DTA_AlphaF, alpha, TAG_DONE);
else
screen->DrawText (SmallFont, color, (screen->GetWidth() / 4 -
SmallFont->StringWidth (NotifyStrings[i].Text))/4,
line, NotifyStrings[i].Text,
DTA_VirtualWidth, screen->GetWidth() / 4,
DTA_VirtualHeight, screen->GetHeight() / 4,
DTA_KeepRatio, true,
DTA_AlphaF, alpha, TAG_DONE);
}
else
{
if (!center)
screen->DrawText (SmallFont, color, 0, line, NotifyStrings[i].Text,
DTA_VirtualWidth, screen->GetWidth() / 2,
DTA_VirtualHeight, screen->GetHeight() / 2,
DTA_VirtualWidth, screen->GetWidth() / active_con_scaletext(),
DTA_VirtualHeight, screen->GetHeight() / active_con_scaletext(),
DTA_KeepRatio, true,
DTA_AlphaF, alpha, TAG_DONE);
else
screen->DrawText (SmallFont, color, (screen->GetWidth() / 2 -
SmallFont->StringWidth (NotifyStrings[i].Text))/2,
screen->DrawText (SmallFont, color, (screen->GetWidth() / active_con_scaletext() -
SmallFont->StringWidth (NotifyStrings[i].Text))/ active_con_scaletext(),
line, NotifyStrings[i].Text,
DTA_VirtualWidth, screen->GetWidth() / 2,
DTA_VirtualHeight, screen->GetHeight() / 2,
DTA_VirtualWidth, screen->GetWidth() / active_con_scaletext(),
DTA_VirtualHeight, screen->GetHeight() / active_con_scaletext(),
DTA_KeepRatio, true,
DTA_AlphaF, alpha, TAG_DONE);
}
@ -851,9 +859,13 @@ void C_DrawConsole (bool hw2d)
static int oldbottom = 0;
int lines, left, offset;
int textScale = active_con_scale();
if (textScale == 0)
textScale = CleanXfac;
left = LEFTMARGIN;
lines = (ConBottom-ConFont->GetHeight()*2)/ConFont->GetHeight();
if (-ConFont->GetHeight() + lines*ConFont->GetHeight() > ConBottom - ConFont->GetHeight()*7/2)
lines = (ConBottom/textScale-ConFont->GetHeight()*2)/ConFont->GetHeight();
if (-ConFont->GetHeight() + lines*ConFont->GetHeight() > ConBottom/textScale - ConFont->GetHeight()*7/2)
{
offset = -ConFont->GetHeight()/2;
lines--;
@ -899,16 +911,26 @@ void C_DrawConsole (bool hw2d)
if (ConBottom >= 12)
{
screen->DrawText (ConFont, CR_ORANGE, SCREENWIDTH - 8 -
ConFont->StringWidth (GetVersionString()),
ConBottom - ConFont->GetHeight() - 4,
GetVersionString(), TAG_DONE);
if (textScale == 1)
screen->DrawText (ConFont, CR_ORANGE, SCREENWIDTH - 8 -
ConFont->StringWidth (GetVersionString()),
ConBottom / textScale - ConFont->GetHeight() - 4,
GetVersionString(), TAG_DONE);
else
screen->DrawText(ConFont, CR_ORANGE, SCREENWIDTH / textScale - 8 -
ConFont->StringWidth(GetVersionString()),
ConBottom / textScale - ConFont->GetHeight() - 4,
GetVersionString(),
DTA_VirtualWidth, screen->GetWidth() / textScale,
DTA_VirtualHeight, screen->GetHeight() / textScale,
DTA_KeepRatio, true, TAG_DONE);
if (TickerMax)
{
char tickstr[256];
const int tickerY = ConBottom - ConFont->GetHeight() - 4;
const int tickerY = ConBottom / textScale - ConFont->GetHeight() - 4;
size_t i;
int tickend = ConCols - SCREENWIDTH / 90 - 6;
int tickend = ConCols / textScale - SCREENWIDTH / textScale / 90 - 6;
int tickbegin = 0;
if (TickerLabel)
@ -931,11 +953,23 @@ void C_DrawConsole (bool hw2d)
{
tickstr[tickend+3] = 0;
}
screen->DrawText (ConFont, CR_BROWN, LEFTMARGIN, tickerY, tickstr, TAG_DONE);
if (textScale == 1)
screen->DrawText (ConFont, CR_BROWN, LEFTMARGIN, tickerY, tickstr, TAG_DONE);
else
screen->DrawText (ConFont, CR_BROWN, LEFTMARGIN, tickerY, tickstr,
DTA_VirtualWidth, screen->GetWidth() / textScale,
DTA_VirtualHeight, screen->GetHeight() / textScale,
DTA_KeepRatio, true, TAG_DONE);
// Draw the marker
i = LEFTMARGIN+5+tickbegin*8 + Scale (TickerAt, (SDWORD)(tickend - tickbegin)*8, TickerMax);
screen->DrawChar (ConFont, CR_ORANGE, (int)i, tickerY, 0x13, TAG_DONE);
if (textScale == 1)
screen->DrawChar (ConFont, CR_ORANGE, (int)i, tickerY, 0x13, TAG_DONE);
else
screen->DrawChar(ConFont, CR_ORANGE, (int)i, tickerY, 0x13,
DTA_VirtualWidth, screen->GetWidth() / textScale,
DTA_VirtualHeight, screen->GetHeight() / textScale,
DTA_KeepRatio, true, TAG_DONE);
TickerVisible = true;
}
@ -971,18 +1005,28 @@ void C_DrawConsole (bool hw2d)
if (lines > 0)
{
// No more enqueuing because adding new text to the console won't touch the actual print data.
conbuffer->FormatText(ConFont, ConWidth);
conbuffer->FormatText(ConFont, ConWidth / textScale);
unsigned int consolelines = conbuffer->GetFormattedLineCount();
FBrokenLines **blines = conbuffer->GetLines();
FBrokenLines **printline = blines + consolelines - 1 - RowAdjust;
int bottomline = ConBottom - ConFont->GetHeight()*2 - 4;
int bottomline = ConBottom / textScale - ConFont->GetHeight()*2 - 4;
ConsoleDrawing = true;
for(FBrokenLines **p = printline; p >= blines && lines > 0; p--, lines--)
{
screen->DrawText(ConFont, CR_TAN, LEFTMARGIN, offset + lines * ConFont->GetHeight(), (*p)->Text, TAG_DONE);
if (textScale == 1)
{
screen->DrawText(ConFont, CR_TAN, LEFTMARGIN, offset + lines * ConFont->GetHeight(), (*p)->Text, TAG_DONE);
}
else
{
screen->DrawText(ConFont, CR_TAN, LEFTMARGIN, offset + lines * ConFont->GetHeight(), (*p)->Text,
DTA_VirtualWidth, screen->GetWidth() / textScale,
DTA_VirtualHeight, screen->GetHeight() / textScale,
DTA_KeepRatio, true, TAG_DONE);
}
}
ConsoleDrawing = false;
@ -997,21 +1041,52 @@ void C_DrawConsole (bool hw2d)
FString command((char *)&CmdLine[2+CmdLine[259]]);
int cursorpos = CmdLine[1] - CmdLine[259];
screen->DrawChar (ConFont, CR_ORANGE, left, bottomline, '\x1c', TAG_DONE);
screen->DrawText (ConFont, CR_ORANGE, left + ConFont->GetCharWidth(0x1c), bottomline,
command, TAG_DONE);
if (cursoron)
if (textScale == 1)
{
screen->DrawChar (ConFont, CR_YELLOW, left + ConFont->GetCharWidth(0x1c) + cursorpos * ConFont->GetCharWidth(0xb),
bottomline, '\xb', TAG_DONE);
screen->DrawChar(ConFont, CR_ORANGE, left, bottomline, '\x1c', TAG_DONE);
screen->DrawText(ConFont, CR_ORANGE, left + ConFont->GetCharWidth(0x1c), bottomline,
command, TAG_DONE);
if (cursoron)
{
screen->DrawChar(ConFont, CR_YELLOW, left + ConFont->GetCharWidth(0x1c) + cursorpos * ConFont->GetCharWidth(0xb),
bottomline, '\xb', TAG_DONE);
}
}
else
{
screen->DrawChar(ConFont, CR_ORANGE, left, bottomline, '\x1c',
DTA_VirtualWidth, screen->GetWidth() / textScale,
DTA_VirtualHeight, screen->GetHeight() / textScale,
DTA_KeepRatio, true, TAG_DONE);
screen->DrawText(ConFont, CR_ORANGE, left + ConFont->GetCharWidth(0x1c), bottomline,
command,
DTA_VirtualWidth, screen->GetWidth() / textScale,
DTA_VirtualHeight, screen->GetHeight() / textScale,
DTA_KeepRatio, true, TAG_DONE);
if (cursoron)
{
screen->DrawChar(ConFont, CR_YELLOW, left + ConFont->GetCharWidth(0x1c) + cursorpos * ConFont->GetCharWidth(0xb),
bottomline, '\xb',
DTA_VirtualWidth, screen->GetWidth() / textScale,
DTA_VirtualHeight, screen->GetHeight() / textScale,
DTA_KeepRatio, true, TAG_DONE);
}
}
}
if (RowAdjust && ConBottom >= ConFont->GetHeight()*7/2)
{
// Indicate that the view has been scrolled up (10)
// and if we can scroll no further (12)
screen->DrawChar (ConFont, CR_GREEN, 0, bottomline, RowAdjust == conbuffer->GetFormattedLineCount() ? 12 : 10, TAG_DONE);
if (textScale == 1)
screen->DrawChar (ConFont, CR_GREEN, 0, bottomline, RowAdjust == conbuffer->GetFormattedLineCount() ? 12 : 10, TAG_DONE);
else
screen->DrawChar(ConFont, CR_GREEN, 0, bottomline, RowAdjust == conbuffer->GetFormattedLineCount() ? 12 : 10,
DTA_VirtualWidth, screen->GetWidth() / textScale,
DTA_VirtualHeight, screen->GetHeight() / textScale,
DTA_KeepRatio, true, TAG_DONE);
}
}
}

View file

@ -46,6 +46,8 @@ EXTERN_CVAR (Bool, sb_cooperative_enable)
EXTERN_CVAR (Bool, sb_deathmatch_enable)
EXTERN_CVAR (Bool, sb_teamdeathmatch_enable)
int active_con_scaletext();
// Public data
void CT_Init ();
@ -224,7 +226,7 @@ void CT_Drawer (void)
int i, x, scalex, y, promptwidth;
y = (viewactive || gamestate != GS_LEVEL) ? -10 : -30;
if (con_scaletext == 1)
if (active_con_scaletext() == 0)
{
scalex = CleanXfac;
y *= CleanYfac;
@ -235,25 +237,17 @@ void CT_Drawer (void)
}
int screen_width, screen_height, st_y;
switch (con_scaletext)
if (active_con_scaletext() == 0)
{
default:
case 0:
case 1:
screen_width = SCREENWIDTH;
screen_height = SCREENHEIGHT;
st_y = ST_Y;
break;
case 2:
screen_width = SCREENWIDTH / 2;
screen_height = SCREENHEIGHT / 2;
st_y = ST_Y / 2;
break;
case 3:
screen_width = SCREENWIDTH / 4;
screen_height = SCREENHEIGHT / 4;
st_y = ST_Y / 4;
break;
}
else
{
screen_width = SCREENWIDTH / active_con_scaletext();
screen_height = SCREENHEIGHT / active_con_scaletext();
st_y = ST_Y / active_con_scaletext();
}
y += ((SCREENHEIGHT == viewheight && viewactive) || gamestate != GS_LEVEL) ? screen_height : st_y;
@ -280,10 +274,10 @@ void CT_Drawer (void)
// draw the prompt, text, and cursor
ChatQueue[len] = SmallFont->GetCursor();
ChatQueue[len+1] = '\0';
if (con_scaletext < 2)
if (active_con_scaletext() < 2)
{
screen->DrawText (SmallFont, CR_GREEN, 0, y, prompt, DTA_CleanNoMove, *con_scaletext, TAG_DONE);
screen->DrawText (SmallFont, CR_GREY, promptwidth, y, (char *)(ChatQueue + i), DTA_CleanNoMove, *con_scaletext, TAG_DONE);
screen->DrawText (SmallFont, CR_GREEN, 0, y, prompt, DTA_CleanNoMove, active_con_scaletext() == 0, TAG_DONE);
screen->DrawText (SmallFont, CR_GREY, promptwidth, y, (char *)(ChatQueue + i), DTA_CleanNoMove, active_con_scaletext() == 0, TAG_DONE);
}
else
{

View file

@ -166,8 +166,14 @@ void AFastProjectile::Effect()
if (trail != NULL)
{
AActor *act = Spawn (trail, PosAtZ(hitz), ALLOW_REPLACE);
if (act != NULL)
if (act != nullptr)
{
if ((flags5 & MF5_GETOWNER) && (target != nullptr))
act->target = target;
else
act->target = this;
act->Angles.Pitch = Angles.Pitch;
act->Angles.Yaw = Angles.Yaw;
}
}

View file

@ -161,7 +161,7 @@ double DEarthquake::GetModWave(double waveMultiplier) const
//
//==========================================================================
double DEarthquake::GetModIntensity(double intensity) const
double DEarthquake::GetModIntensity(double intensity, bool fake) const
{
assert(m_CountdownStart >= m_Countdown);
@ -195,7 +195,7 @@ double DEarthquake::GetModIntensity(double intensity) const
}
scalar = (scalar > divider) ? divider : scalar;
if (m_Flags & QF_FULLINTENSITY)
if (!fake && (m_Flags & QF_FULLINTENSITY))
{
scalar *= 2;
}
@ -273,64 +273,69 @@ int DEarthquake::StaticGetQuakeIntensities(AActor *victim, FQuakeJiggers &jigger
DEarthquake *quake;
int count = 0;
while ( (quake = iterator.Next()) != NULL)
while ( (quake = iterator.Next()) != nullptr)
{
if (quake->m_Spot != NULL)
if (quake->m_Spot != nullptr)
{
double dist = quake->m_Spot->Distance2D (victim, true);
const double dist = quake->m_Spot->Distance2D(victim, true);
if (dist < quake->m_TremorRadius)
{
const double falloff = quake->GetFalloff(dist);
const double rfalloff = (quake->m_RollIntensity != 0) ? falloff : 0.;
++count;
double x = quake->GetModIntensity(quake->m_Intensity.X);
double y = quake->GetModIntensity(quake->m_Intensity.Y);
double z = quake->GetModIntensity(quake->m_Intensity.Z);
double r = quake->GetModIntensity(quake->m_RollIntensity);
const double falloff = quake->GetFalloff(dist);
const double r = quake->GetModIntensity(quake->m_RollIntensity);
const double strength = quake->GetModIntensity(1.0, true);
DVector3 intensity;
intensity.X = quake->GetModIntensity(quake->m_Intensity.X);
intensity.Y = quake->GetModIntensity(quake->m_Intensity.Y);
intensity.Z = quake->GetModIntensity(quake->m_Intensity.Z);
if (!(quake->m_Flags & QF_WAVE))
{
jiggers.Falloff = MAX(falloff, jiggers.Falloff);
jiggers.RFalloff = MAX(rfalloff, jiggers.RFalloff);
jiggers.RollIntensity = MAX(r, jiggers.RollIntensity);
jiggers.RollIntensity = MAX(r, jiggers.RollIntensity) * jiggers.Falloff;
intensity *= jiggers.Falloff;
if (quake->m_Flags & QF_RELATIVE)
{
jiggers.RelIntensity.X = MAX(x, jiggers.RelIntensity.X);
jiggers.RelIntensity.Y = MAX(y, jiggers.RelIntensity.Y);
jiggers.RelIntensity.Z = MAX(z, jiggers.RelIntensity.Z);
jiggers.RelIntensity.X = MAX(intensity.X, jiggers.RelIntensity.X);
jiggers.RelIntensity.Y = MAX(intensity.Y, jiggers.RelIntensity.Y);
jiggers.RelIntensity.Z = MAX(intensity.Z, jiggers.RelIntensity.Z);
}
else
{
jiggers.Intensity.X = MAX(x, jiggers.Intensity.X);
jiggers.Intensity.Y = MAX(y, jiggers.Intensity.Y);
jiggers.Intensity.Z = MAX(z, jiggers.Intensity.Z);
jiggers.Intensity.X = MAX(intensity.X, jiggers.Intensity.X);
jiggers.Intensity.Y = MAX(intensity.Y, jiggers.Intensity.Y);
jiggers.Intensity.Z = MAX(intensity.Z, jiggers.Intensity.Z);
}
}
else
{
jiggers.WFalloff = MAX(falloff, jiggers.WFalloff);
jiggers.RWFalloff = MAX(rfalloff, jiggers.RWFalloff);
jiggers.RollWave = r * quake->GetModWave(quake->m_RollWave);
double mx = x * quake->GetModWave(quake->m_WaveSpeed.X);
double my = y * quake->GetModWave(quake->m_WaveSpeed.Y);
double mz = z * quake->GetModWave(quake->m_WaveSpeed.Z);
jiggers.Falloff = MAX(falloff, jiggers.Falloff);
jiggers.RollWave = r * quake->GetModWave(quake->m_RollWave) * jiggers.Falloff * strength;
intensity.X *= quake->GetModWave(quake->m_WaveSpeed.X);
intensity.Y *= quake->GetModWave(quake->m_WaveSpeed.Y);
intensity.Z *= quake->GetModWave(quake->m_WaveSpeed.Z);
intensity *= strength * jiggers.Falloff;
// [RH] This only gives effect to the last sine quake. I would
// prefer if some way was found to make multiples coexist
// peacefully, but just summing them together is undesirable
// because they could cancel each other out depending on their
// relative phases.
// [MC] Now does so. And they stack rather well. I'm a little
// surprised at how easy it was.
if (quake->m_Flags & QF_RELATIVE)
{
jiggers.RelOffset.X = mx;
jiggers.RelOffset.Y = my;
jiggers.RelOffset.Z = mz;
jiggers.RelOffset += intensity;
}
else
{
jiggers.Offset.X = mx;
jiggers.Offset.Y = my;
jiggers.Offset.Z = mz;
jiggers.Offset += intensity;
}
}
}

View file

@ -153,7 +153,7 @@ struct FQuakeJiggers
DVector3 RelIntensity;
DVector3 Offset;
DVector3 RelOffset;
double Falloff, WFalloff, RFalloff, RWFalloff;
double Falloff;
double RollIntensity, RollWave;
};
@ -180,8 +180,7 @@ public:
int m_Highpoint, m_MiniCount;
double m_RollIntensity, m_RollWave;
double GetModIntensity(double intensity) const;
double GetModIntensity(double intensity, bool fake = false) const;
double GetModWave(double waveMultiplier) const;
double GetFalloff(double dist) const;

View file

@ -41,7 +41,8 @@
#include "doomstat.h"
#include "farchive.h"
EXTERN_CVAR (Int, con_scaletext)
EXTERN_CVAR(Int, con_scaletext)
int active_con_scaletext();
IMPLEMENT_POINTY_CLASS (DHUDMessage)
DECLARE_POINTER(Next)
@ -260,13 +261,10 @@ void DHUDMessage::ResetText (const char *text)
}
else
{
switch (con_scaletext)
switch (active_con_scaletext())
{
default:
case 0: width = SCREENWIDTH; break;
case 1: width = SCREENWIDTH / CleanXfac; break;
case 2: width = SCREENWIDTH / 2; break;
case 3: width = SCREENWIDTH / 4; break;
case 0: width = SCREENWIDTH / CleanXfac; break;
default: width = SCREENWIDTH / active_con_scaletext(); break;
}
}
@ -332,7 +330,7 @@ void DHUDMessage::Draw (int bottom, int visibility)
int screen_width = SCREENWIDTH;
int screen_height = SCREENHEIGHT;
if (HUDWidth == 0 && con_scaletext==1)
if (HUDWidth == 0 && active_con_scaletext() == 0)
{
clean = true;
xscale = CleanXfac;
@ -341,17 +339,11 @@ void DHUDMessage::Draw (int bottom, int visibility)
else
{
xscale = yscale = 1;
if (HUDWidth==0 && con_scaletext==2)
if (HUDWidth == 0)
{
screen_width/=2;
screen_height/=2;
bottom/=2;
}
else if (HUDWidth==0 && con_scaletext==3)
{
screen_width/=4;
screen_height/=4;
bottom/=4;
screen_width /= active_con_scaletext();
screen_height /= active_con_scaletext();
bottom /= active_con_scaletext();
}
}
@ -453,7 +445,7 @@ void DHUDMessage::DoDraw (int linenum, int x, int y, bool clean, int hudheight)
{
if (hudheight == 0)
{
if (con_scaletext <= 1)
if (active_con_scaletext() <= 1)
{
screen->DrawText (Font, TextColor, x, y, Lines[linenum].Text,
DTA_CleanNoMove, clean,
@ -461,21 +453,11 @@ void DHUDMessage::DoDraw (int linenum, int x, int y, bool clean, int hudheight)
DTA_RenderStyle, Style,
TAG_DONE);
}
else if (con_scaletext == 3)
{
screen->DrawText (Font, TextColor, x, y, Lines[linenum].Text,
DTA_VirtualWidth, SCREENWIDTH/4,
DTA_VirtualHeight, SCREENHEIGHT/4,
DTA_AlphaF, Alpha,
DTA_RenderStyle, Style,
DTA_KeepRatio, true,
TAG_DONE);
}
else
{
screen->DrawText (Font, TextColor, x, y, Lines[linenum].Text,
DTA_VirtualWidth, SCREENWIDTH/2,
DTA_VirtualHeight, SCREENHEIGHT/2,
DTA_VirtualWidth, SCREENWIDTH / active_con_scaletext(),
DTA_VirtualHeight, SCREENHEIGHT / active_con_scaletext(),
DTA_AlphaF, Alpha,
DTA_RenderStyle, Style,
DTA_KeepRatio, true,
@ -566,7 +548,7 @@ void DHUDMessageFadeOut::DoDraw (int linenum, int x, int y, bool clean, int hudh
float trans = float(Alpha * -(Tics - FadeOutTics) / FadeOutTics);
if (hudheight == 0)
{
if (con_scaletext <= 1)
if (active_con_scaletext() <= 1)
{
screen->DrawText (Font, TextColor, x, y, Lines[linenum].Text,
DTA_CleanNoMove, clean,
@ -574,21 +556,11 @@ void DHUDMessageFadeOut::DoDraw (int linenum, int x, int y, bool clean, int hudh
DTA_RenderStyle, Style,
TAG_DONE);
}
else if (con_scaletext == 3)
{
screen->DrawText (Font, TextColor, x, y, Lines[linenum].Text,
DTA_VirtualWidth, SCREENWIDTH/4,
DTA_VirtualHeight, SCREENHEIGHT/4,
DTA_AlphaF, trans,
DTA_RenderStyle, Style,
DTA_KeepRatio, true,
TAG_DONE);
}
else
{
screen->DrawText (Font, TextColor, x, y, Lines[linenum].Text,
DTA_VirtualWidth, SCREENWIDTH/2,
DTA_VirtualHeight, SCREENHEIGHT/2,
DTA_VirtualWidth, SCREENWIDTH / active_con_scaletext(),
DTA_VirtualHeight, SCREENHEIGHT / active_con_scaletext(),
DTA_AlphaF, trans,
DTA_RenderStyle, Style,
DTA_KeepRatio, true,
@ -676,7 +648,7 @@ void DHUDMessageFadeInOut::DoDraw (int linenum, int x, int y, bool clean, int hu
float trans = float(Alpha * Tics / FadeInTics);
if (hudheight == 0)
{
if (con_scaletext <= 1)
if (active_con_scaletext() <= 1)
{
screen->DrawText (Font, TextColor, x, y, Lines[linenum].Text,
DTA_CleanNoMove, clean,
@ -684,21 +656,11 @@ void DHUDMessageFadeInOut::DoDraw (int linenum, int x, int y, bool clean, int hu
DTA_RenderStyle, Style,
TAG_DONE);
}
else if (con_scaletext == 3)
{
screen->DrawText (Font, TextColor, x, y, Lines[linenum].Text,
DTA_VirtualWidth, SCREENWIDTH/4,
DTA_VirtualHeight, SCREENHEIGHT/4,
DTA_AlphaF, trans,
DTA_RenderStyle, Style,
DTA_KeepRatio, true,
TAG_DONE);
}
else
{
screen->DrawText (Font, TextColor, x, y, Lines[linenum].Text,
DTA_VirtualWidth, SCREENWIDTH/2,
DTA_VirtualHeight, SCREENHEIGHT/2,
DTA_VirtualWidth, SCREENWIDTH / active_con_scaletext(),
DTA_VirtualHeight, SCREENHEIGHT / active_con_scaletext(),
DTA_AlphaF, trans,
DTA_RenderStyle, Style,
DTA_KeepRatio, true,
@ -864,7 +826,7 @@ void DHUDMessageTypeOnFadeOut::DoDraw (int linenum, int x, int y, bool clean, in
{
if (hudheight == 0)
{
if (con_scaletext <= 1)
if (active_con_scaletext() <= 1)
{
screen->DrawText (Font, TextColor, x, y, Lines[linenum].Text,
DTA_CleanNoMove, clean,
@ -873,22 +835,11 @@ void DHUDMessageTypeOnFadeOut::DoDraw (int linenum, int x, int y, bool clean, in
DTA_RenderStyle, Style,
TAG_DONE);
}
else if (con_scaletext == 3)
{
screen->DrawText (Font, TextColor, x, y, Lines[linenum].Text,
DTA_VirtualWidth, SCREENWIDTH/4,
DTA_VirtualHeight, SCREENHEIGHT/4,
DTA_KeepRatio, true,
DTA_TextLen, LineVisible,
DTA_AlphaF, Alpha,
DTA_RenderStyle, Style,
TAG_DONE);
}
else
{
screen->DrawText (Font, TextColor, x, y, Lines[linenum].Text,
DTA_VirtualWidth, SCREENWIDTH/2,
DTA_VirtualHeight, SCREENHEIGHT/2,
DTA_VirtualWidth, SCREENWIDTH / active_con_scaletext(),
DTA_VirtualHeight, SCREENHEIGHT / active_con_scaletext(),
DTA_KeepRatio, true,
DTA_TextLen, LineVisible,
DTA_AlphaF, Alpha,

View file

@ -1013,7 +1013,15 @@ public:
void ScreenSizeChanged()
{
Super::ScreenSizeChanged();
V_CalcCleanFacs(script->resW, script->resH, SCREENWIDTH, SCREENHEIGHT, &script->cleanX, &script->cleanY);
if (uiscale > 0)
{
script->cleanX = uiscale;
script->cleanY = uiscale;
}
else
{
V_CalcCleanFacs(script->resW, script->resH, SCREENWIDTH, SCREENHEIGHT, &script->cleanX, &script->cleanY);
}
}
void Draw (EHudState state)

View file

@ -3464,6 +3464,78 @@ class CommandIfWaterLevel : public SBarInfoNegatableFlowControl
////////////////////////////////////////////////////////////////////////////////
class CommandIfCVarInt : public SBarInfoNegatableFlowControl
{
public:
CommandIfCVarInt(SBarInfo *script) : SBarInfoNegatableFlowControl(script),
equalcomp(false)
{
}
void ParseNegatable(FScanner &sc, bool fullScreenOffsets)
{
if(!sc.CheckToken(TK_StringConst))
{
sc.MustGetToken(TK_Identifier);
}
cvarname = sc.String;
cvar = FindCVar(cvarname, nullptr);
if (cvar != nullptr)
{
ECVarType cvartype = cvar->GetRealType();
if (cvartype == CVAR_Bool || cvartype == CVAR_Int)
{
sc.MustGetToken(',');
sc.MustGetToken(TK_IntConst);
value = sc.Number;
if (sc.CheckToken(','))
{
sc.MustGetToken(TK_Identifier);
if(sc.Compare("equal"))
{
equalcomp = true;
}
}
}
else
{
sc.ScriptError("Type mismatch: console variable '%s' is not of type 'bool' or 'int'.", cvarname.GetChars());
}
}
else
{
sc.ScriptError("Unknown console variable '%s'.", cvarname.GetChars());
}
}
void Tick(const SBarInfoMainBlock *block, const DSBarInfo *statusBar, bool hudChanged)
{
SBarInfoNegatableFlowControl::Tick(block, statusBar, hudChanged);
bool result = false;
cvar = GetCVar(statusBar->CPlayer->mo, cvarname);
if (cvar != nullptr)
{
int cvarvalue = cvar->GetGenericRep(CVAR_Int).Int;
result = equalcomp ? cvarvalue == value : cvarvalue >= value;
}
SetTruth(result, block, statusBar);
}
protected:
FString cvarname;
FBaseCVar *cvar;
int value;
bool equalcomp;
};
////////////////////////////////////////////////////////////////////////////////
static const char *SBarInfoCommandNames[] =
{
"drawimage", "drawnumber", "drawswitchableimage",
@ -3474,7 +3546,7 @@ static const char *SBarInfoCommandNames[] =
"isselected", "usesammo", "usessecondaryammo",
"hasweaponpiece", "inventorybarnotvisible",
"weaponammo", "ininventory", "alpha", "ifhealth",
"ifinvulnerable", "ifwaterlevel",
"ifinvulnerable", "ifwaterlevel", "ifcvarint",
NULL
};
@ -3488,7 +3560,7 @@ enum SBarInfoCommands
SBARINFO_ISSELECTED, SBARINFO_USESAMMO, SBARINFO_USESSECONDARYAMMO,
SBARINFO_HASWEAPONPIECE, SBARINFO_INVENTORYBARNOTVISIBLE,
SBARINFO_WEAPONAMMO, SBARINFO_ININVENTORY, SBARINFO_ALPHA, SBARINFO_IFHEALTH,
SBARINFO_IFINVULNERABLE, SBARINFO_IFWATERLEVEL,
SBARINFO_IFINVULNERABLE, SBARINFO_IFWATERLEVEL, SBARINFO_IFCVARINT,
};
SBarInfoCommand *SBarInfoCommandFlowControl::NextCommand(FScanner &sc)
@ -3524,6 +3596,7 @@ SBarInfoCommand *SBarInfoCommandFlowControl::NextCommand(FScanner &sc)
case SBARINFO_IFHEALTH: return new CommandIfHealth(script);
case SBARINFO_IFINVULNERABLE: return new CommandIfInvulnerable(script);
case SBARINFO_IFWATERLEVEL: return new CommandIfWaterLevel(script);
case SBARINFO_IFCVARINT: return new CommandIfCVarInt(script);
}
sc.ScriptError("Unknown command '%s'.\n", sc.String);

View file

@ -66,7 +66,7 @@ EXTERN_CVAR (Int, screenblocks)
EXTERN_CVAR (Bool, am_showtime)
EXTERN_CVAR (Bool, am_showtotaltime)
CVAR(Int,hud_althudscale, 2, CVAR_ARCHIVE) // Scale the hud to 640x400?
CVAR(Int,hud_althudscale, 4, CVAR_ARCHIVE) // Scale the hud to 640x400?
CVAR(Bool,hud_althud, false, CVAR_ARCHIVE) // Enable/Disable the alternate HUD
// These are intentionally not the same as in the automap!
@ -118,7 +118,7 @@ static int hudwidth, hudheight; // current width/height for HUD display
static int statspace;
DVector2 AM_GetPosition();
int active_con_scaletext();
FTextureID GetHUDIcon(PClassInventory *cls)
{
@ -886,22 +886,15 @@ static void DrawCoordinates(player_t * CPlayer)
}
int vwidth, vheight;
switch (con_scaletext)
if (active_con_scaletext() == 0)
{
default:
case 0:
vwidth = SCREENWIDTH;
vheight = SCREENHEIGHT;
break;
case 1:
case 2:
vwidth = SCREENWIDTH/2;
vheight = SCREENHEIGHT/2;
break;
case 3:
vwidth = SCREENWIDTH/4;
vheight = SCREENHEIGHT/4;
break;
vwidth = SCREENWIDTH / 2;
vheight = SCREENHEIGHT / 2;
}
else
{
vwidth = SCREENWIDTH / active_con_scaletext();
vheight = SCREENHEIGHT / active_con_scaletext();
}
int xpos = vwidth - SmallFont->StringWidth("X: -00000")-6;
@ -1090,7 +1083,20 @@ void DrawHUD()
if (hud_althudscale && SCREENWIDTH>640)
{
hudwidth=SCREENWIDTH/2;
if (hud_althudscale == 3)
if (hud_althudscale == 4)
{
if (uiscale == 0)
{
hudwidth = CleanWidth;
hudheight = CleanHeight;
}
else
{
hudwidth = SCREENWIDTH / uiscale;
hudheight = SCREENHEIGHT / uiscale;
}
}
else if (hud_althudscale == 3)
{
hudwidth = SCREENWIDTH / 4;
hudheight = SCREENHEIGHT / 4;

View file

@ -74,6 +74,8 @@ EXTERN_CVAR (Bool, am_showtotaltime)
EXTERN_CVAR (Bool, noisedebug)
EXTERN_CVAR (Int, con_scaletext)
int active_con_scaletext();
DBaseStatusBar *StatusBar;
extern int setblocks;
@ -1240,17 +1242,17 @@ void DBaseStatusBar::Draw (EHudState state)
int xpos;
int y;
if (con_scaletext == 0)
if (active_con_scaletext() == 1)
{
vwidth = SCREENWIDTH;
vheight = SCREENHEIGHT;
xpos = vwidth - 80;
y = ::ST_Y - height;
}
else if (con_scaletext == 3)
else if (active_con_scaletext() > 1)
{
vwidth = SCREENWIDTH/4;
vheight = SCREENHEIGHT/4;
vwidth = SCREENWIDTH / active_con_scaletext();
vheight = SCREENHEIGHT / active_con_scaletext();
xpos = vwidth - SmallFont->StringWidth("X: -00000")-6;
y = ::ST_Y/4 - height;
}
@ -1264,9 +1266,9 @@ void DBaseStatusBar::Draw (EHudState state)
if (gameinfo.gametype == GAME_Strife)
{
if (con_scaletext == 0)
if (active_con_scaletext() == 1)
y -= height * 4;
else if (con_scaletext == 3)
else if (active_con_scaletext() > 3)
y -= height;
else
y -= height * 2;
@ -1400,27 +1402,15 @@ void DBaseStatusBar::DrawLog ()
if (CPlayer->LogText.IsNotEmpty())
{
// This uses the same scaling as regular HUD messages
switch (con_scaletext)
if (active_con_scaletext() == 0)
{
default:
hudwidth = SCREENWIDTH;
hudheight = SCREENHEIGHT;
break;
case 1:
hudwidth = SCREENWIDTH / CleanXfac;
hudheight = SCREENHEIGHT / CleanYfac;
break;
case 2:
hudwidth = SCREENWIDTH / 2;
hudheight = SCREENHEIGHT / 2;
break;
case 3:
hudwidth = SCREENWIDTH / 4;
hudheight = SCREENHEIGHT / 4;
break;
}
else
{
hudwidth = SCREENWIDTH / active_con_scaletext();
hudheight = SCREENHEIGHT / active_con_scaletext();
}
int linelen = hudwidth<640? Scale(hudwidth,9,10)-40 : 560;

View file

@ -552,7 +552,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_MaulerTorpedoWave)
// If the torpedo hit the ceiling, it should still spawn the wave
savedz = self->Z();
if (wavedef && self->ceilingz < wavedef->Top())
if (wavedef && self->ceilingz < self->Z() + wavedef->Height)
{
self->SetZ(self->ceilingz - wavedef->Height);
}

View file

@ -57,6 +57,8 @@
#include "gl/data/gl_vertexbuffer.h"
CVAR(Bool, gl_lights_additive, false, CVAR_ARCHIVE | CVAR_GLOBALCONFIG)
//==========================================================================
//
// Do some tinkering with the menus so that certain options only appear
@ -384,7 +386,7 @@ bool gl_SetupLight(int group, Plane & p, ADynamicLight * light, Vector & nearPt,
DVector3 lpos = light->PosRelative(group);
float dist = fabsf(p.DistToPoint(lpos.X, lpos.Z, lpos.Y));
float radius = (light->GetRadius() * gl_lights_size);
float radius = light->GetRadius();
if (radius <= 0.f) return false;
if (dist > radius) return false;
@ -415,9 +417,9 @@ bool gl_SetupLight(int group, Plane & p, ADynamicLight * light, Vector & nearPt,
float cs = 1.0f - (dist / radius);
if (additive) cs *= 0.2f; // otherwise the light gets too strong.
float r = light->GetRed() / 255.0f * cs * gl_lights_intensity;
float g = light->GetGreen() / 255.0f * cs * gl_lights_intensity;
float b = light->GetBlue() / 255.0f * cs * gl_lights_intensity;
float r = light->GetRed() / 255.0f * cs;
float g = light->GetGreen() / 255.0f * cs;
float b = light->GetBlue() / 255.0f * cs;
if (light->IsSubtractive())
{
@ -478,7 +480,7 @@ bool GLWall::PutWallCompat(int passflag)
if (sub->lighthead == nullptr) return false;
}
bool foggy = !gl_isBlack(Colormap.FadeColor) || (level.flags&LEVEL_HASFADETABLE) || gl_lights_additive;
bool foggy = gl_CheckFog(&Colormap, lightlevel) || (level.flags&LEVEL_HASFADETABLE) || gl_lights_additive;
bool masked = passflag == 2 && gltexture->isMasked();
int list = list_indices[masked][foggy];

View file

@ -10,6 +10,15 @@ struct secplane_t;
struct subsector_t;
struct sector_t;
enum
{
VATTR_VERTEX_BIT,
VATTR_TEXCOORD_BIT,
VATTR_COLOR_BIT,
VATTR_VERTEX2_BIT,
VATTR_NORMAL_BIT
};
class FVertexBuffer
{
@ -20,6 +29,7 @@ public:
FVertexBuffer(bool wantbuffer = true);
virtual ~FVertexBuffer();
virtual void BindVBO() = 0;
void EnableBufferArrays(int enable, int disable);
};
struct FFlatVertex

View file

@ -57,8 +57,6 @@
#include "gl/utility/gl_convert.h"
#include "gl/utility/gl_templates.h"
EXTERN_CVAR (Float, gl_lights_size);
EXTERN_CVAR (Bool, gl_lights_additive);
EXTERN_CVAR(Int, vid_renderer)
@ -379,7 +377,7 @@ void ADynamicLight::UpdateLocation()
{
intensity = m_currentRadius;
}
radius = intensity * 2.0f * gl_lights_size;
radius = intensity * 2.0f;
if (X() != oldx || Y() != oldy || radius != oldradius)
{

View file

@ -61,8 +61,6 @@
#include "gl/utility/gl_clock.h"
#include "gl/utility/gl_convert.h"
EXTERN_CVAR (Float, gl_lights_intensity);
EXTERN_CVAR (Float, gl_lights_size);
int ScriptDepth;
void gl_InitGlow(FScanner &sc);
void gl_ParseBrightmap(FScanner &sc, int);
@ -175,7 +173,7 @@ void FLightDefaults::ApplyProperties(ADynamicLight * light) const
light->Angles.Yaw.Degrees = m_Param;
light->SetOffset(m_Pos);
light->halo = m_halo;
for (int a = 0; a < 3; a++) light->args[a] = clamp<int>((int)(m_Args[a] * gl_lights_intensity), 0, 255);
for (int a = 0; a < 3; a++) light->args[a] = clamp<int>((int)(m_Args[a]), 0, 255);
light->m_Radius[0] = int(m_Args[LIGHT_INTENSITY]);
light->m_Radius[1] = int(m_Args[LIGHT_SECONDARY_INTENSITY]);
light->flags4 &= ~(MF4_ADDITIVE | MF4_SUBTRACTIVE | MF4_DONTLIGHTSELF);

View file

@ -184,7 +184,7 @@ struct FDynLightData
bool gl_GetLight(int group, Plane & p, ADynamicLight * light, bool checkside, bool forceadditive, FDynLightData &data);
bool gl_GetLight(int group, Plane & p, ADynamicLight * light, bool checkside, FDynLightData &data);
void gl_UploadLights(FDynLightData &data);

View file

@ -70,15 +70,8 @@ CUSTOM_CVAR (Bool, gl_lights, true, CVAR_ARCHIVE | CVAR_GLOBALCONFIG | CVAR_NOIN
CVAR (Bool, gl_attachedlights, true, CVAR_ARCHIVE | CVAR_GLOBALCONFIG);
CVAR (Bool, gl_lights_checkside, true, CVAR_ARCHIVE | CVAR_GLOBALCONFIG);
CVAR (Float, gl_lights_intensity, 1.0f, CVAR_ARCHIVE | CVAR_GLOBALCONFIG);
CVAR (Float, gl_lights_size, 1.0f, CVAR_ARCHIVE | CVAR_GLOBALCONFIG);
CVAR (Bool, gl_light_sprites, true, CVAR_ARCHIVE | CVAR_GLOBALCONFIG);
CVAR (Bool, gl_light_particles, true, CVAR_ARCHIVE | CVAR_GLOBALCONFIG);
CUSTOM_CVAR (Bool, gl_lights_additive, false, CVAR_ARCHIVE | CVAR_GLOBALCONFIG | CVAR_NOINITCALL)
{
gl_DeleteAllAttachedLights();
gl_RecreateAllAttachedLights();
}
CUSTOM_CVAR(Int, gl_light_math, 0, CVAR_ARCHIVE | CVAR_GLOBALCONFIG)
{
@ -90,14 +83,14 @@ CUSTOM_CVAR(Int, gl_light_math, 0, CVAR_ARCHIVE | CVAR_GLOBALCONFIG)
// Sets up the parameters to render one dynamic light onto one plane
//
//==========================================================================
bool gl_GetLight(int group, Plane & p, ADynamicLight * light, bool checkside, bool forceadditive, FDynLightData &ldata)
bool gl_GetLight(int group, Plane & p, ADynamicLight * light, bool checkside, FDynLightData &ldata)
{
int i = 0;
DVector3 pos = light->PosRelative(group);
float dist = fabsf(p.DistToPoint(pos.X, pos.Z, pos.Y));
float radius = (light->GetRadius() * gl_lights_size);
float radius = (light->GetRadius());
if (radius <= 0.f) return false;
if (dist > radius) return false;
@ -108,7 +101,7 @@ bool gl_GetLight(int group, Plane & p, ADynamicLight * light, bool checkside, bo
float cs;
if (gl_lights_additive || light->flags4&MF4_ADDITIVE || forceadditive)
if (light->IsAdditive())
{
cs = 0.2f;
i = 2;
@ -118,9 +111,9 @@ bool gl_GetLight(int group, Plane & p, ADynamicLight * light, bool checkside, bo
cs = 1.0f;
}
float r = light->GetRed() / 255.0f * cs * gl_lights_intensity;
float g = light->GetGreen() / 255.0f * cs * gl_lights_intensity;
float b = light->GetBlue() / 255.0f * cs * gl_lights_intensity;
float r = light->GetRed() / 255.0f * cs;
float g = light->GetGreen() / 255.0f * cs;
float b = light->GetBlue() / 255.0f * cs;
if (light->IsSubtractive())
{

View file

@ -378,7 +378,7 @@ void F2DDrawer::AddPixel(int x1, int y1, int palcolor, uint32 color)
//
//==========================================================================
void F2DDrawer::Flush()
void F2DDrawer::Draw()
{
F2DDrawer::EDrawType lasttype = DrawTypeTexture;
@ -490,10 +490,12 @@ void F2DDrawer::Flush()
}
i += dg->mLen;
}
mVertices.Clear();
mData.Clear();
gl_RenderState.SetVertexBuffer(GLRenderer->mVBO);
glset.lightmode = savedlightmode;
}
void F2DDrawer::Clear()
{
mVertices.Clear();
mData.Clear();
}

View file

@ -66,7 +66,8 @@ public:
void AddLine(int x1, int y1, int x2, int y2, int palcolor, uint32 color);
void AddPixel(int x1, int y1, int palcolor, uint32 color);
void Flush();
void Draw();
void Clear();
};

View file

@ -76,6 +76,7 @@
#include "gl/shaders/gl_lensshader.h"
#include "gl/shaders/gl_presentshader.h"
#include "gl/renderer/gl_2ddrawer.h"
#include "gl/stereo3d/gl_stereo3d.h"
//==========================================================================
//
@ -395,7 +396,7 @@ void FGLRenderer::BindTonemapPalette(int texunit)
{
for (int b = 0; b < 64; b++)
{
PalEntry color = GPalette.BaseColors[ColorMatcher.Pick((r << 2) | (r >> 1), (g << 2) | (g >> 1), (b << 2) | (b >> 1))];
PalEntry color = GPalette.BaseColors[(BYTE)PTM_BestColor((uint32 *)GPalette.BaseColors, (r << 2) | (r >> 4), (g << 2) | (g >> 4), (b << 2) | (b >> 4), 0, 256)];
int index = ((r * 64 + g) * 64 + b) * 4;
lut[index] = color.r;
lut[index + 1] = color.g;
@ -513,6 +514,41 @@ void FGLRenderer::LensDistortScene()
FGLDebug::PopGroup();
}
//-----------------------------------------------------------------------------
//
// Copies the rendered screen to its final destination
//
//-----------------------------------------------------------------------------
void FGLRenderer::Flush()
{
const s3d::Stereo3DMode& stereo3dMode = s3d::Stereo3DMode::getCurrentMode();
if (stereo3dMode.IsMono() || !FGLRenderBuffers::IsEnabled())
{
CopyToBackbuffer(nullptr, true);
}
else
{
// Render 2D to eye textures
for (int eye_ix = 0; eye_ix < stereo3dMode.eye_count(); ++eye_ix)
{
FGLDebug::PushGroup("Eye2D");
mBuffers->BindEyeFB(eye_ix);
glViewport(mScreenViewport.left, mScreenViewport.top, mScreenViewport.width, mScreenViewport.height);
glScissor(mScreenViewport.left, mScreenViewport.top, mScreenViewport.width, mScreenViewport.height);
m2DDrawer->Draw();
FGLDebug::PopGroup();
}
m2DDrawer->Clear();
FGLPostProcessState savedState;
FGLDebug::PushGroup("PresentEyes");
stereo3dMode.Present();
FGLDebug::PopGroup();
}
}
//-----------------------------------------------------------------------------
//
// Gamma correct while copying to frame buffer
@ -521,7 +557,9 @@ void FGLRenderer::LensDistortScene()
void FGLRenderer::CopyToBackbuffer(const GL_IRECT *bounds, bool applyGamma)
{
m2DDrawer->Flush(); // draw all pending 2D stuff before copying the buffer
m2DDrawer->Draw(); // draw all pending 2D stuff before copying the buffer
m2DDrawer->Clear();
FGLDebug::PushGroup("CopyToBackbuffer");
if (FGLRenderBuffers::IsEnabled())
{
@ -539,28 +577,8 @@ void FGLRenderer::CopyToBackbuffer(const GL_IRECT *bounds, bool applyGamma)
box = mOutputLetterbox;
}
// Present what was rendered:
glViewport(box.left, box.top, box.width, box.height);
mPresentShader->Bind();
mPresentShader->InputTexture.Set(0);
if (!applyGamma || framebuffer->IsHWGammaActive())
{
mPresentShader->InvGamma.Set(1.0f);
mPresentShader->Contrast.Set(1.0f);
mPresentShader->Brightness.Set(0.0f);
}
else
{
mPresentShader->InvGamma.Set(1.0f / clamp<float>(Gamma, 0.1f, 4.f));
mPresentShader->Contrast.Set(clamp<float>(vid_contrast, 0.1f, 3.f));
mPresentShader->Brightness.Set(clamp<float>(vid_brightness, -0.8f, 0.8f));
}
mPresentShader->Scale.Set(mScreenViewport.width / (float)mBuffers->GetWidth(), mScreenViewport.height / (float)mBuffers->GetHeight());
mBuffers->BindCurrentTexture(0);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
RenderScreenQuad();
DrawPresentTexture(box, applyGamma);
}
else if (!bounds)
{
@ -570,6 +588,32 @@ void FGLRenderer::CopyToBackbuffer(const GL_IRECT *bounds, bool applyGamma)
FGLDebug::PopGroup();
}
void FGLRenderer::DrawPresentTexture(const GL_IRECT &box, bool applyGamma)
{
glViewport(box.left, box.top, box.width, box.height);
glActiveTexture(GL_TEXTURE0);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
mPresentShader->Bind();
mPresentShader->InputTexture.Set(0);
if (!applyGamma || framebuffer->IsHWGammaActive())
{
mPresentShader->InvGamma.Set(1.0f);
mPresentShader->Contrast.Set(1.0f);
mPresentShader->Brightness.Set(0.0f);
}
else
{
mPresentShader->InvGamma.Set(1.0f / clamp<float>(Gamma, 0.1f, 4.f));
mPresentShader->Contrast.Set(clamp<float>(vid_contrast, 0.1f, 3.f));
mPresentShader->Brightness.Set(clamp<float>(vid_brightness, -0.8f, 0.8f));
}
mPresentShader->Scale.Set(mScreenViewport.width / (float)mBuffers->GetWidth(), mScreenViewport.height / (float)mBuffers->GetHeight());
RenderScreenQuad();
}
//-----------------------------------------------------------------------------
//
// Fills the black bars around the screen letterbox
@ -582,6 +626,8 @@ void FGLRenderer::ClearBorders()
int clientWidth = framebuffer->GetClientWidth();
int clientHeight = framebuffer->GetClientHeight();
if (clientWidth == 0 || clientHeight == 0)
return;
glViewport(0, 0, clientWidth, clientHeight);
glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
@ -608,3 +654,40 @@ void FGLRenderer::ClearBorders()
}
glDisable(GL_SCISSOR_TEST);
}
// [SP] Re-implemented BestColor for more precision rather than speed. This function is only ever called once until the game palette is changed.
int FGLRenderer::PTM_BestColor (const uint32 *pal_in, int r, int g, int b, int first, int num)
{
const PalEntry *pal = (const PalEntry *)pal_in;
static double powtable[256];
static bool firstTime = true;
double fbestdist, fdist;
int bestcolor;
if (firstTime)
{
firstTime = false;
for (int x = 0; x < 256; x++) powtable[x] = pow((double)x/255,1.2);
}
for (int color = first; color < num; color++)
{
double x = powtable[abs(r-pal[color].r)];
double y = powtable[abs(g-pal[color].g)];
double z = powtable[abs(b-pal[color].b)];
fdist = x + y + z;
if (color == first || fdist < fbestdist)
{
if (fdist == 0)
return color;
fbestdist = fdist;
bestcolor = color;
}
}
return bestcolor;
}

View file

@ -86,6 +86,7 @@ FGLRenderBuffers::~FGLRenderBuffers()
{
ClearScene();
ClearPipeline();
ClearEyeBuffers();
ClearBloom();
ClearAmbientOcclusion();
}
@ -128,6 +129,18 @@ void FGLRenderBuffers::ClearAmbientOcclusion()
DeleteTexture(AmbientRandomTexture);
}
void FGLRenderBuffers::ClearEyeBuffers()
{
for (auto handle : mEyeFBs)
DeleteFrameBuffer(handle);
for (auto handle : mEyeTextures)
DeleteTexture(handle);
mEyeTextures.Clear();
mEyeFBs.Clear();
}
void FGLRenderBuffers::DeleteTexture(GLuint &handle)
{
if (handle != 0)
@ -212,6 +225,7 @@ bool FGLRenderBuffers::Setup(int width, int height, int sceneWidth, int sceneHei
{
ClearScene();
ClearPipeline();
ClearEyeBuffers();
ClearBloom();
mWidth = 0;
mHeight = 0;
@ -255,6 +269,7 @@ void FGLRenderBuffers::CreateScene(int width, int height, int samples)
void FGLRenderBuffers::CreatePipeline(int width, int height)
{
ClearPipeline();
ClearEyeBuffers();
for (int i = 0; i < NumPipelineTextures; i++)
{
@ -336,6 +351,35 @@ void FGLRenderBuffers::CreateAmbientOcclusion(int width, int height)
AmbientRandomTexture = Create2DTexture("AmbientRandomTexture", GL_RGBA16_SNORM, 4, 4, randomValues);
}
//==========================================================================
//
// Creates eye buffers if needed
//
//==========================================================================
void FGLRenderBuffers::CreateEyeBuffers(int eye)
{
if (mEyeFBs.Size() > eye)
return;
GLint activeTex, textureBinding, frameBufferBinding;
glGetIntegerv(GL_ACTIVE_TEXTURE, &activeTex);
glActiveTexture(GL_TEXTURE0);
glGetIntegerv(GL_TEXTURE_BINDING_2D, &textureBinding);
glGetIntegerv(GL_FRAMEBUFFER_BINDING, &frameBufferBinding);
while (mEyeFBs.Size() <= eye)
{
GLuint texture = Create2DTexture("EyeTexture", GL_RGBA16F, mWidth, mHeight);
mEyeTextures.Push(texture);
mEyeFBs.Push(CreateFrameBuffer("EyeFB", texture));
}
glBindTexture(GL_TEXTURE_2D, textureBinding);
glActiveTexture(activeTex);
glBindFramebuffer(GL_FRAMEBUFFER, frameBufferBinding);
}
//==========================================================================
//
// Creates a 2D texture defaulting to linear filtering and clamp to edge
@ -544,6 +588,43 @@ void FGLRenderBuffers::BlitSceneToTexture()
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0);
}
//==========================================================================
//
// Eye textures and their frame buffers
//
//==========================================================================
void FGLRenderBuffers::BlitToEyeTexture(int eye)
{
CreateEyeBuffers(eye);
glBindFramebuffer(GL_READ_FRAMEBUFFER, mPipelineFB[mCurrentPipelineTexture]);
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, mEyeFBs[eye]);
glBlitFramebuffer(0, 0, mWidth, mHeight, 0, 0, mWidth, mHeight, GL_COLOR_BUFFER_BIT, GL_NEAREST);
if ((gl.flags & RFL_INVALIDATE_BUFFER) != 0)
{
GLenum attachments[2] = { GL_COLOR_ATTACHMENT0, GL_DEPTH_STENCIL_ATTACHMENT };
glInvalidateFramebuffer(GL_READ_FRAMEBUFFER, 2, attachments);
}
glBindFramebuffer(GL_READ_FRAMEBUFFER, 0);
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0);
}
void FGLRenderBuffers::BindEyeTexture(int eye, int texunit)
{
CreateEyeBuffers(eye);
glActiveTexture(GL_TEXTURE0 + texunit);
glBindTexture(GL_TEXTURE_2D, mEyeTextures[eye]);
}
void FGLRenderBuffers::BindEyeFB(int eye, bool readBuffer)
{
CreateEyeBuffers(eye);
glBindFramebuffer(readBuffer ? GL_READ_FRAMEBUFFER : GL_FRAMEBUFFER, mEyeFBs[eye]);
}
//==========================================================================
//
// Makes the scene frame buffer active (multisample, depth, stecil, etc.)

View file

@ -34,6 +34,10 @@ public:
void BindOutputFB();
void BlitToEyeTexture(int eye);
void BindEyeTexture(int eye, int texunit);
void BindEyeFB(int eye, bool readBuffer = false);
enum { NumBloomLevels = 4 };
FGLBloomTextureLevel BloomLevels[NumBloomLevels];
@ -57,12 +61,14 @@ public:
private:
void ClearScene();
void ClearPipeline();
void ClearEyeBuffers();
void ClearBloom();
void ClearAmbientOcclusion();
void CreateScene(int width, int height, int samples);
void CreatePipeline(int width, int height);
void CreateBloom(int width, int height);
void CreateAmbientOcclusion(int width, int height);
void CreateEyeBuffers(int eye);
GLuint Create2DTexture(const FString &name, GLuint format, int width, int height, const void *data = nullptr);
GLuint Create2DMultisampleTexture(const FString &name, GLuint format, int width, int height, int samples, bool fixedSampleLocations);
GLuint CreateRenderBuffer(const FString &name, GLuint format, int width, int height);
@ -97,6 +103,10 @@ private:
// Back buffer frame buffer
GLuint mOutputFB = 0;
// Eye buffers
TArray<GLuint> mEyeTextures;
TArray<GLuint> mEyeFBs;
static bool FailedCreate;
static bool BuffersActive;
};

View file

@ -244,6 +244,13 @@ void FGLRenderer::SetOutputViewport(GL_IRECT *bounds)
// Back buffer letterbox for the final output
int clientWidth = framebuffer->GetClientWidth();
int clientHeight = framebuffer->GetClientHeight();
if (clientWidth == 0 || clientHeight == 0)
{
// When window is minimized there may not be any client area.
// Pretend to the rest of the render code that we just have a very small window.
clientWidth = 160;
clientHeight = 120;
}
int screenWidth = framebuffer->GetWidth();
int screenHeight = framebuffer->GetHeight();
float scale = MIN(clientWidth / (float)screenWidth, clientHeight / (float)screenHeight);

View file

@ -183,7 +183,8 @@ public:
void ClearTonemapPalette();
void LensDistortScene();
void CopyToBackbuffer(const GL_IRECT *bounds, bool applyGamma);
void Flush() { CopyToBackbuffer(nullptr, true); }
void DrawPresentTexture(const GL_IRECT &box, bool applyGamma);
void Flush();
void SetProjection(float fov, float ratio, float fovratio);
void SetProjection(VSMatrix matrix); // raw matrix input from stereo 3d modes
@ -200,6 +201,8 @@ public:
double originx, double originy, double scalex, double scaley,
DAngle rotation, FDynamicColormap *colormap, int lightlevel);
int PTM_BestColor (const uint32 *pal_in, int r, int g, int b, int first, int num);
static float GetZNear() { return 5.f; }
static float GetZFar() { return 65536.f; }
};

View file

@ -154,7 +154,7 @@ void GLFlat::SetupSubsectorLights(int pass, subsector_t * sub, int *dli)
}
p.Set(plane.plane);
gl_GetLight(sub->sector->PortalGroup, p, light, false, false, lightdata);
gl_GetLight(sub->sector->PortalGroup, p, light, false, lightdata);
node = node->nextLight;
}
@ -419,15 +419,17 @@ void GLFlat::Draw(int pass, bool trans) // trans only has meaning for GLPASS_LIG
if (renderstyle==STYLE_Add) gl_RenderState.BlendFunc(GL_SRC_ALPHA, GL_ONE);
gl_SetColor(lightlevel, rel, Colormap, alpha);
gl_SetFog(lightlevel, rel, &Colormap, false);
gl_RenderState.AlphaFunc(GL_GEQUAL, gl_mask_threshold);
if (!gltexture)
{
gl_RenderState.AlphaFunc(GL_GEQUAL, 0.f);
gl_RenderState.EnableTexture(false);
DrawSubsectors(pass, false, true);
gl_RenderState.EnableTexture(true);
}
else
{
if (!gltexture->GetTransparent()) gl_RenderState.AlphaFunc(GL_GEQUAL, gl_mask_threshold);
else gl_RenderState.AlphaFunc(GL_GEQUAL, 0.f);
gl_RenderState.SetMaterial(gltexture, CLAMP_NONE, 0, -1, false);
gl_SetPlaneTextureRotation(&plane, gltexture);
DrawSubsectors(pass, !gl.legacyMode, true);
@ -477,6 +479,21 @@ inline void GLFlat::PutFlat(bool fog)
// translucent 3D floors go into the regular translucent list, translucent portals go into the translucent border list.
list = (renderflags&SSRF_RENDER3DPLANES) ? GLDL_TRANSLUCENT : GLDL_TRANSLUCENTBORDER;
}
else if (gltexture->GetTransparent())
{
if (stack)
{
list = GLDL_TRANSLUCENTBORDER;
}
else if ((renderflags&SSRF_RENDER3DPLANES) && !plane.plane.isSlope())
{
list = GLDL_TRANSLUCENT;
}
else
{
list = GLDL_PLAINFLATS;
}
}
else
{
bool masked = gltexture->isMasked() && ((renderflags&SSRF_RENDER3DPLANES) || stack);

View file

@ -56,6 +56,7 @@
#include "gl/renderer/gl_lightdata.h"
#include "gl/renderer/gl_renderer.h"
#include "gl/renderer/gl_renderstate.h"
#include "gl/renderer/gl_quaddrawer.h"
#include "gl/dynlights/gl_glow.h"
#include "gl/data/gl_data.h"
#include "gl/data/gl_vertexbuffer.h"
@ -128,8 +129,16 @@ void GLPortal::ClearScreen()
bool multi = !!glIsEnabled(GL_MULTISAMPLE);
gl_MatrixStack.Push(gl_RenderState.mViewMatrix);
gl_MatrixStack.Push(gl_RenderState.mProjectionMatrix);
screen->Begin2D(false);
screen->Dim(0, 1.f, 0, 0, SCREENWIDTH, SCREENHEIGHT);
gl_RenderState.mViewMatrix.loadIdentity();
gl_RenderState.mProjectionMatrix.ortho(0, SCREENWIDTH, SCREENHEIGHT, 0, -1.0f, 1.0f);
gl_RenderState.ApplyMatrices();
glDisable(GL_MULTISAMPLE);
glDisable(GL_DEPTH_TEST);
glDrawArrays(GL_TRIANGLE_STRIP, FFlatVertexBuffer::FULLSCREEN_INDEX, 4);
glEnable(GL_DEPTH_TEST);
gl_MatrixStack.Pop(gl_RenderState.mProjectionMatrix);
gl_MatrixStack.Pop(gl_RenderState.mViewMatrix);
@ -137,7 +146,6 @@ void GLPortal::ClearScreen()
if (multi) glEnable(GL_MULTISAMPLE);
}
//-----------------------------------------------------------------------------
//
// DrawPortalStencil

View file

@ -682,8 +682,6 @@ void FGLRenderer::EndDrawScene(sector_t * viewsector)
}
if (gl.legacyMode)
{
int cm = gl_RenderState.GetFixedColormap();
gl_RenderState.SetFixedColormap(cm);
gl_RenderState.DrawColormapOverlay();
}
@ -775,7 +773,7 @@ void FGLRenderer::SetFixedColormap (player_t *player)
sector_t * FGLRenderer::RenderViewpoint (AActor * camera, GL_IRECT * bounds, float fov, float ratio, float fovratio, bool mainview, bool toscreen)
{
sector_t * retval;
sector_t * lviewsector;
mSceneClearColor[0] = 0.0f;
mSceneClearColor[1] = 0.0f;
mSceneClearColor[2] = 0.0f;
@ -822,11 +820,11 @@ sector_t * FGLRenderer::RenderViewpoint (AActor * camera, GL_IRECT * bounds, flo
}
// 'viewsector' will not survive the rendering so it cannot be used anymore below.
retval = viewsector;
lviewsector = viewsector;
// Render (potentially) multiple views for stereo 3d
float viewShift[3];
const s3d::Stereo3DMode& stereo3dMode = s3d::Stereo3DMode::getCurrentMode();
const s3d::Stereo3DMode& stereo3dMode = mainview && toscreen? s3d::Stereo3DMode::getCurrentMode() : s3d::Stereo3DMode::getMonoMode();
stereo3dMode.SetUp();
for (int eye_ix = 0; eye_ix < stereo3dMode.eye_count(); ++eye_ix)
{
@ -852,20 +850,26 @@ sector_t * FGLRenderer::RenderViewpoint (AActor * camera, GL_IRECT * bounds, flo
clipper.SafeAddClipRangeRealAngles(ViewAngle.BAMs() + a1, ViewAngle.BAMs() - a1);
ProcessScene(toscreen);
if (mainview && toscreen) EndDrawScene(retval); // do not call this for camera textures.
if (mainview && toscreen) EndDrawScene(lviewsector); // do not call this for camera textures.
if (mainview && FGLRenderBuffers::IsEnabled())
{
PostProcessScene();
DrawBlend(viewsector); // This should be done after postprocessing, not before.
// This should be done after postprocessing, not before.
mBuffers->BindCurrentFB();
glViewport(mScreenViewport.left, mScreenViewport.top, mScreenViewport.width, mScreenViewport.height);
DrawBlend(lviewsector);
}
mDrawingScene2D = false;
if (!stereo3dMode.IsMono() && FGLRenderBuffers::IsEnabled())
mBuffers->BlitToEyeTexture(eye_ix);
eye->TearDown();
}
stereo3dMode.TearDown();
gl_frameCount++; // This counter must be increased right before the interpolations are restored.
interpolator.RestoreInterpolations ();
return retval;
return lviewsector;
}
//-----------------------------------------------------------------------------
@ -1313,29 +1317,16 @@ void FGLInterface::RenderTextureView (FCanvasTexture *tex, AActor *Viewpoint, in
gl_fixedcolormap=CM_DEFAULT;
gl_RenderState.SetFixedColormap(CM_DEFAULT);
bool usefb = gl_usefb || gltex->GetWidth() > screen->GetWidth() || gltex->GetHeight() > screen->GetHeight();
if (!usefb)
if (gl.legacyMode)
{
// In legacy mode, fail if the requested texture is too large.
if (gltex->GetWidth() > screen->GetWidth() || gltex->GetHeight() > screen->GetHeight()) return;
glFlush();
}
else
{
#if defined(_WIN32) && (defined(_MSC_VER) || defined(__INTEL_COMPILER))
__try
#endif
{
GLRenderer->StartOffscreen();
gltex->BindToFrameBuffer();
}
#if defined(_WIN32) && (defined(_MSC_VER) || defined(__INTEL_COMPILER))
__except(1)
{
usefb = false;
gl_usefb = false;
GLRenderer->EndOffscreen();
glFlush();
}
#endif
GLRenderer->StartOffscreen();
gltex->BindToFrameBuffer();
}
GL_IRECT bounds;
@ -1345,7 +1336,7 @@ void FGLInterface::RenderTextureView (FCanvasTexture *tex, AActor *Viewpoint, in
GLRenderer->RenderViewpoint(Viewpoint, &bounds, FOV, (float)width/height, (float)width/height, false, false);
if (!usefb)
if (gl.legacyMode)
{
glFlush();
gl_RenderState.SetMaterial(gltex, 0, 0, -1, false);

View file

@ -110,17 +110,155 @@ CVAR(Bool, gl_nolayer, false, 0)
static const float LARGE_VALUE = 1e19f;
//==========================================================================
//
//
//
//==========================================================================
void GLSprite::CalculateVertices(FVector3 *v)
{
// [BB] Billboard stuff
const bool drawWithXYBillboard = ((particle && gl_billboard_particles) || (!(actor && actor->renderflags & RF_FORCEYBILLBOARD)
//&& GLRenderer->mViewActor != NULL
&& (gl_billboard_mode == 1 || (actor && actor->renderflags & RF_FORCEXYBILLBOARD))));
const bool drawBillboardFacingCamera = gl_billboard_faces_camera;
// [Nash] has +ROLLSPRITE
const bool drawRollSpriteActor = (actor != nullptr && actor->renderflags & RF_ROLLSPRITE);
// [fgsfds] check sprite type mask
DWORD spritetype = (DWORD)-1;
if (actor != nullptr) spritetype = actor->renderflags & RF_SPRITETYPEMASK;
// [Nash] is a flat sprite
const bool isFlatSprite = (actor != nullptr) && (spritetype == RF_WALLSPRITE || spritetype == RF_FLATSPRITE);
const bool dontFlip = (actor != nullptr) && (actor->renderflags & RF_DONTFLIP);
const bool useOffsets = (actor != nullptr) && !(actor->renderflags & RF_ROLLCENTER);
// [Nash] check for special sprite drawing modes
if (drawWithXYBillboard || drawBillboardFacingCamera || drawRollSpriteActor || isFlatSprite)
{
// Compute center of sprite
float xcenter = (x1 + x2)*0.5;
float ycenter = (y1 + y2)*0.5;
float zcenter = (z1 + z2)*0.5;
float xx = -xcenter + x;
float zz = -zcenter + z;
float yy = -ycenter + y;
Matrix3x4 mat;
mat.MakeIdentity();
mat.Translate(xcenter, zcenter, ycenter); // move to sprite center
// Order of rotations matters. Perform yaw rotation (Y, face camera) before pitch (X, tilt up/down).
if (drawBillboardFacingCamera && !isFlatSprite)
{
// [CMB] Rotate relative to camera XY position, not just camera direction,
// which is nicer in VR
float xrel = xcenter - ViewPos.X;
float yrel = ycenter - ViewPos.Y;
float absAngleDeg = RAD2DEG(atan2(-yrel, xrel));
float counterRotationDeg = 270. - GLRenderer->mAngles.Yaw.Degrees; // counteracts existing sprite rotation
float relAngleDeg = counterRotationDeg + absAngleDeg;
mat.Rotate(0, 1, 0, relAngleDeg);
}
// [fgsfds] calculate yaw vectors
float yawvecX = 0, yawvecY = 0, rollDegrees = 0;
float angleRad = (270. - GLRenderer->mAngles.Yaw).Radians();
if (actor) rollDegrees = actor->Angles.Roll.Degrees;
if (isFlatSprite)
{
yawvecX = actor->Angles.Yaw.Cos();
yawvecY = actor->Angles.Yaw.Sin();
}
// [MC] This is the only thing that I changed in Nash's submission which
// was constantly applying roll to everything. That was wrong. Flat sprites
// with roll literally look like paper thing space ships trying to swerve.
// However, it does well with wall sprites.
// Also, renamed FLOORSPRITE to FLATSPRITE because that's technically incorrect.
// I plan on adding proper FLOORSPRITEs which can actually curve along sloped
// 3D floors later... if possible.
// Here we need some form of priority in order to work.
if (spritetype == RF_FLATSPRITE)
{
float pitchDegrees = -actor->Angles.Pitch.Degrees;
DVector3 apos = { x, y, z };
DVector3 diff = ViewPos - apos;
DAngle angto = diff.Angle();
angto = deltaangle(actor->Angles.Yaw, angto);
bool noFlipSprite = (!dontFlip || (fabs(angto) < 90.));
mat.Rotate(0, 1, 0, (noFlipSprite) ? 0 : 180);
mat.Rotate(-yawvecY, 0, yawvecX, (noFlipSprite) ? -pitchDegrees : pitchDegrees);
if (drawRollSpriteActor)
{
if (useOffsets) mat.Translate(xx, zz, yy);
mat.Rotate(yawvecX, 0, yawvecY, (noFlipSprite) ? -rollDegrees : rollDegrees);
if (useOffsets) mat.Translate(-xx, -zz, -yy);
}
}
// [fgsfds] Rotate the sprite about the sight vector (roll)
else if (spritetype == RF_WALLSPRITE)
{
mat.Rotate(0, 1, 0, 0);
if (drawRollSpriteActor)
{
if (useOffsets) mat.Translate(xx, zz, yy);
mat.Rotate(yawvecX, 0, yawvecY, rollDegrees);
if (useOffsets) mat.Translate(-xx, -zz, -yy);
}
}
else if (drawRollSpriteActor)
{
if (useOffsets) mat.Translate(xx, zz, yy);
if (drawWithXYBillboard)
{
mat.Rotate(-sin(angleRad), 0, cos(angleRad), -GLRenderer->mAngles.Pitch.Degrees);
}
mat.Rotate(cos(angleRad), 0, sin(angleRad), rollDegrees);
if (useOffsets) mat.Translate(-xx, -zz, -yy);
}
else if (drawWithXYBillboard)
{
// Rotate the sprite about the vector starting at the center of the sprite
// triangle strip and with direction orthogonal to where the player is looking
// in the x/y plane.
mat.Rotate(-sin(angleRad), 0, cos(angleRad), -GLRenderer->mAngles.Pitch.Degrees);
}
mat.Translate(-xcenter, -zcenter, -ycenter); // retreat from sprite center
v[0] = mat * FVector3(x1, z1, y1);
v[1] = mat * FVector3(x2, z1, y2);
v[2] = mat * FVector3(x1, z2, y1);
v[3] = mat * FVector3(x2, z2, y2);
}
else // traditional "Y" billboard mode
{
v[0] = FVector3(x1, z1, y1);
v[1] = FVector3(x2, z1, y2);
v[2] = FVector3(x1, z2, y1);
v[3] = FVector3(x2, z2, y2);
}
}
//==========================================================================
//
//
//
//==========================================================================
void GLSprite::Draw(int pass)
{
if (pass == GLPASS_DECALS || pass == GLPASS_LIGHTSONLY) return;
bool additivefog = false;
bool foglayer = false;
int rel = fullbright? 0 : getExtraLight();
@ -264,147 +402,17 @@ void GLSprite::Draw(int pass)
if (!modelframe)
{
// [BB] Billboard stuff
const bool drawWithXYBillboard = ((particle && gl_billboard_particles) || (!(actor && actor->renderflags & RF_FORCEYBILLBOARD)
//&& GLRenderer->mViewActor != NULL
&& (gl_billboard_mode == 1 || (actor && actor->renderflags & RF_FORCEXYBILLBOARD))));
const bool drawBillboardFacingCamera = gl_billboard_faces_camera;
// [Nash] has +ROLLSPRITE
const bool drawRollSpriteActor = (actor != nullptr && actor->renderflags & RF_ROLLSPRITE);
gl_RenderState.Apply();
FVector3 v1;
FVector3 v2;
FVector3 v3;
FVector3 v4;
FVector3 v[4];
CalculateVertices(v);
// [fgsfds] check sprite type mask
DWORD spritetype = (DWORD)-1;
if (actor != nullptr) spritetype = actor->renderflags & RF_SPRITETYPEMASK;
// [Nash] is a flat sprite
const bool isFlatSprite = (actor != nullptr) && (spritetype == RF_WALLSPRITE || spritetype == RF_FLATSPRITE);
const bool dontFlip = (actor != nullptr) && (actor->renderflags & RF_DONTFLIP);
const bool useOffsets = (actor != nullptr) && !(actor->renderflags & RF_ROLLCENTER);
// [Nash] check for special sprite drawing modes
if (drawWithXYBillboard || drawBillboardFacingCamera || drawRollSpriteActor || isFlatSprite)
{
// Compute center of sprite
float xcenter = (x1 + x2)*0.5;
float ycenter = (y1 + y2)*0.5;
float zcenter = (z1 + z2)*0.5;
float xx = -xcenter + x;
float zz = -zcenter + z;
float yy = -ycenter + y;
Matrix3x4 mat;
mat.MakeIdentity();
mat.Translate(xcenter, zcenter, ycenter); // move to sprite center
// Order of rotations matters. Perform yaw rotation (Y, face camera) before pitch (X, tilt up/down).
if (drawBillboardFacingCamera && !isFlatSprite)
{
// [CMB] Rotate relative to camera XY position, not just camera direction,
// which is nicer in VR
float xrel = xcenter - ViewPos.X;
float yrel = ycenter - ViewPos.Y;
float absAngleDeg = RAD2DEG(atan2(-yrel, xrel));
float counterRotationDeg = 270. - GLRenderer->mAngles.Yaw.Degrees; // counteracts existing sprite rotation
float relAngleDeg = counterRotationDeg + absAngleDeg;
mat.Rotate(0, 1, 0, relAngleDeg);
}
// [fgsfds] calculate yaw vectors
float yawvecX = 0, yawvecY = 0, rollDegrees = 0;
float angleRad = (270. - GLRenderer->mAngles.Yaw).Radians();
if (actor) rollDegrees = actor->Angles.Roll.Degrees;
if (isFlatSprite)
{
yawvecX = actor->Angles.Yaw.Cos();
yawvecY = actor->Angles.Yaw.Sin();
}
// [MC] This is the only thing that I changed in Nash's submission which
// was constantly applying roll to everything. That was wrong. Flat sprites
// with roll literally look like paper thing space ships trying to swerve.
// However, it does well with wall sprites.
// Also, renamed FLOORSPRITE to FLATSPRITE because that's technically incorrect.
// I plan on adding proper FLOORSPRITEs which can actually curve along sloped
// 3D floors later... if possible.
// Here we need some form of priority in order to work.
if (spritetype == RF_FLATSPRITE)
{
float pitchDegrees = -actor->Angles.Pitch.Degrees;
DVector3 apos = { x, y, z };
DVector3 diff = ViewPos - apos;
DAngle angto = diff.Angle();
angto = deltaangle(actor->Angles.Yaw, angto);
bool noFlipSprite = (!dontFlip || (fabs(angto) < 90.));
mat.Rotate(0, 1, 0, (noFlipSprite) ? 0 : 180);
mat.Rotate(-yawvecY, 0, yawvecX, (noFlipSprite) ? -pitchDegrees : pitchDegrees);
if (drawRollSpriteActor)
{
if (useOffsets) mat.Translate(xx, zz, yy);
mat.Rotate(yawvecX, 0, yawvecY, (noFlipSprite) ? -rollDegrees : rollDegrees);
if (useOffsets) mat.Translate(-xx, -zz, -yy);
}
}
// [fgsfds] Rotate the sprite about the sight vector (roll)
else if (spritetype == RF_WALLSPRITE)
{
mat.Rotate(0, 1, 0, 0);
if (drawRollSpriteActor)
{
if (useOffsets) mat.Translate(xx, zz, yy);
mat.Rotate(yawvecX, 0, yawvecY, rollDegrees);
if (useOffsets) mat.Translate(-xx, -zz, -yy);
}
}
else if (drawRollSpriteActor)
{
if (useOffsets) mat.Translate(xx, zz, yy);
if (drawWithXYBillboard)
{
mat.Rotate(-sin(angleRad), 0, cos(angleRad), -GLRenderer->mAngles.Pitch.Degrees);
}
mat.Rotate(cos(angleRad), 0, sin(angleRad), rollDegrees);
if (useOffsets) mat.Translate(-xx, -zz, -yy);
}
// apply the transform
else if (drawWithXYBillboard)
{
// Rotate the sprite about the vector starting at the center of the sprite
// triangle strip and with direction orthogonal to where the player is looking
// in the x/y plane.
mat.Rotate(-sin(angleRad), 0, cos(angleRad), -GLRenderer->mAngles.Pitch.Degrees);
}
mat.Translate(-xcenter, -zcenter, -ycenter); // retreat from sprite center
v1 = mat * FVector3(x1, z1, y1);
v2 = mat * FVector3(x2, z1, y2);
v3 = mat * FVector3(x1, z2, y1);
v4 = mat * FVector3(x2, z2, y2);
}
else // traditional "Y" billboard mode
{
v1 = FVector3(x1, z1, y1);
v2 = FVector3(x2, z1, y2);
v3 = FVector3(x1, z2, y1);
v4 = FVector3(x2, z2, y2);
}
FQuadDrawer qd;
qd.Set(0, v1[0], v1[1], v1[2], ul, vt);
qd.Set(1, v2[0], v2[1], v2[2], ur, vt);
qd.Set(2, v3[0], v3[1], v3[2], ul, vb);
qd.Set(3, v4[0], v4[1], v4[2], ur, vb);
qd.Set(0, v[0][0], v[0][1], v[0][2], ul, vt);
qd.Set(1, v[1][0], v[1][1], v[1][2], ur, vt);
qd.Set(2, v[2][0], v[2][1], v[2][2], ul, vb);
qd.Set(3, v[3][0], v[3][1], v[3][2], ur, vb);
qd.Render(GL_TRIANGLE_STRIP);
if (foglayer)
@ -703,7 +711,7 @@ void GLSprite::Process(AActor* thing, sector_t * sector, int thruportal)
x = thingpos.X;
z = thingpos.Z;
y = thingpos.Y;
if (spritetype == RF_FLATSPRITE) z -= thing->Floorclip;
if (spritetype != RF_FLATSPRITE) z -= thing->Floorclip;
// [RH] Make floatbobbing a renderer-only effect.
if (thing->flags2 & MF2_FLOATBOB)

View file

@ -96,7 +96,7 @@ void gl_SetDynSpriteLight(AActor *self, float x, float y, float z, subsector_t *
dist = FVector3(x - light->X(), y - light->Y(), z - light->Z()).LengthSquared();
}
radius = light->GetRadius() * gl_lights_size;
radius = light->GetRadius();
if (dist < radius * radius)
{
@ -106,9 +106,9 @@ void gl_SetDynSpriteLight(AActor *self, float x, float y, float z, subsector_t *
if (frac > 0)
{
lr = light->GetRed() / 255.0f * gl_lights_intensity;
lg = light->GetGreen() / 255.0f * gl_lights_intensity;
lb = light->GetBlue() / 255.0f * gl_lights_intensity;
lr = light->GetRed() / 255.0f;
lg = light->GetGreen() / 255.0f;
lb = light->GetBlue() / 255.0f;
if (light->IsSubtractive())
{
float bright = FVector3(lr, lg, lb).Length();

View file

@ -371,6 +371,7 @@ public:
void SplitSprite(sector_t * frontsector, bool translucent);
void SetLowerParam();
void PerformSpriteClipAdjustment(AActor *thing, const DVector2 &thingpos, float spriteheight);
void CalculateVertices(FVector3 *v);
public:

View file

@ -124,7 +124,7 @@ void GLWall::SetupLights()
float y = node->lightsource->Y();
float z = node->lightsource->Z();
float dist = fabsf(p.DistToPoint(x, z, y));
float radius = (node->lightsource->GetRadius() * gl_lights_size);
float radius = node->lightsource->GetRadius();
float scale = 1.0f / ((2.f * radius) - dist);
if (radius > 0.f && dist < radius)
@ -158,7 +158,7 @@ void GLWall::SetupLights()
}
if (outcnt[0]!=4 && outcnt[1]!=4 && outcnt[2]!=4 && outcnt[3]!=4)
{
gl_GetLight(seg->frontsector->PortalGroup, p, node->lightsource, true, false, lightdata);
gl_GetLight(seg->frontsector->PortalGroup, p, node->lightsource, true, lightdata);
}
}
}

View file

@ -12,7 +12,8 @@ enum
VATTR_VERTEX = 0,
VATTR_TEXCOORD = 1,
VATTR_COLOR = 2,
VATTR_VERTEX2 = 3
VATTR_VERTEX2 = 3,
VATTR_NORMAL = 4
};

View file

@ -34,6 +34,8 @@
*/
#include "gl_anaglyph.h"
#include "gl/renderer/gl_renderer.h"
#include "gl/renderer/gl_renderbuffers.h"
namespace s3d {
@ -44,6 +46,25 @@ MaskAnaglyph::MaskAnaglyph(const ColorMask& leftColorMask, double ipdMeters)
eye_ptrs.Push(&rightEye);
}
void MaskAnaglyph::Present() const
{
GLRenderer->mBuffers->BindOutputFB();
GLRenderer->ClearBorders();
gl_RenderState.SetColorMask(leftEye.GetColorMask().r, leftEye.GetColorMask().g, leftEye.GetColorMask().b, true);
gl_RenderState.ApplyColorMask();
GLRenderer->mBuffers->BindEyeTexture(0, 0);
GLRenderer->DrawPresentTexture(GLRenderer->mOutputLetterbox, true);
gl_RenderState.SetColorMask(rightEye.GetColorMask().r, rightEye.GetColorMask().g, rightEye.GetColorMask().b, true);
gl_RenderState.ApplyColorMask();
GLRenderer->mBuffers->BindEyeTexture(1, 0);
GLRenderer->DrawPresentTexture(GLRenderer->mOutputLetterbox, true);
gl_RenderState.ResetColorMask();
gl_RenderState.ApplyColorMask();
}
/* static */
const GreenMagenta& GreenMagenta::getInstance(float ipd)

View file

@ -61,14 +61,8 @@ class AnaglyphLeftPose : public LeftEyePose
{
public:
AnaglyphLeftPose(const ColorMask& colorMask, float ipd) : LeftEyePose(ipd), colorMask(colorMask) {}
virtual void SetUp() const {
gl_RenderState.SetColorMask(colorMask.r, colorMask.g, colorMask.b, true);
gl_RenderState.ApplyColorMask();
}
virtual void TearDown() const {
gl_RenderState.ResetColorMask();
gl_RenderState.ApplyColorMask();
}
ColorMask GetColorMask() const { return colorMask; }
private:
ColorMask colorMask;
};
@ -77,14 +71,8 @@ class AnaglyphRightPose : public RightEyePose
{
public:
AnaglyphRightPose(const ColorMask& colorMask, float ipd) : RightEyePose(ipd), colorMask(colorMask) {}
virtual void SetUp() const {
gl_RenderState.SetColorMask(colorMask.r, colorMask.g, colorMask.b, true);
gl_RenderState.ApplyColorMask();
}
virtual void TearDown() const {
gl_RenderState.ResetColorMask();
gl_RenderState.ApplyColorMask();
}
ColorMask GetColorMask() const { return colorMask; }
private:
ColorMask colorMask;
};
@ -93,6 +81,7 @@ class MaskAnaglyph : public Stereo3DMode
{
public:
MaskAnaglyph(const ColorMask& leftColorMask, double ipdMeters);
void Present() const override;
private:
AnaglyphLeftPose leftEye;
AnaglyphRightPose rightEye;

View file

@ -34,6 +34,8 @@
*/
#include "gl_quadstereo.h"
#include "gl/renderer/gl_renderer.h"
#include "gl/renderer/gl_renderbuffers.h"
namespace s3d {
@ -46,7 +48,7 @@ QuadStereo::QuadStereo(double ipdMeters)
GLboolean supportsStereo, supportsBuffered;
glGetBooleanv(GL_STEREO, &supportsStereo);
glGetBooleanv(GL_DOUBLEBUFFER, &supportsBuffered);
bool bQuadStereoSupported = supportsStereo && supportsBuffered;
bQuadStereoSupported = supportsStereo && supportsBuffered;
leftEye.bQuadStereoSupported = bQuadStereoSupported;
rightEye.bQuadStereoSupported = bQuadStereoSupported;
@ -57,6 +59,33 @@ QuadStereo::QuadStereo(double ipdMeters)
}
}
void QuadStereo::Present() const
{
if (bQuadStereoSupported)
{
GLRenderer->mBuffers->BindOutputFB();
glDrawBuffer(GL_BACK_LEFT);
GLRenderer->ClearBorders();
GLRenderer->mBuffers->BindEyeTexture(0, 0);
GLRenderer->DrawPresentTexture(GLRenderer->mOutputLetterbox, true);
glDrawBuffer(GL_BACK_RIGHT);
GLRenderer->ClearBorders();
GLRenderer->mBuffers->BindEyeTexture(1, 0);
GLRenderer->DrawPresentTexture(GLRenderer->mOutputLetterbox, true);
glDrawBuffer(GL_BACK);
}
else
{
GLRenderer->mBuffers->BindOutputFB();
GLRenderer->ClearBorders();
GLRenderer->mBuffers->BindEyeTexture(1, 0);
GLRenderer->DrawPresentTexture(GLRenderer->mOutputLetterbox, true);
}
}
/* static */
const QuadStereo& QuadStereo::getInstance(float ipd)
{

View file

@ -47,14 +47,6 @@ class QuadStereoLeftPose : public LeftEyePose
{
public:
QuadStereoLeftPose(float ipd) : LeftEyePose(ipd), bQuadStereoSupported(false) {}
virtual void SetUp() const {
if (bQuadStereoSupported)
glDrawBuffer(GL_BACK_LEFT);
}
virtual void TearDown() const {
if (bQuadStereoSupported)
glDrawBuffer(GL_BACK);
}
bool bQuadStereoSupported;
};
@ -62,14 +54,6 @@ class QuadStereoRightPose : public RightEyePose
{
public:
QuadStereoRightPose(float ipd) : RightEyePose(ipd), bQuadStereoSupported(false){}
virtual void SetUp() const {
if (bQuadStereoSupported)
glDrawBuffer(GL_BACK_RIGHT);
}
virtual void TearDown() const {
if (bQuadStereoSupported)
glDrawBuffer(GL_BACK);
}
bool bQuadStereoSupported;
};
@ -84,10 +68,12 @@ class QuadStereo : public Stereo3DMode
{
public:
QuadStereo(double ipdMeters);
void Present() const override;
static const QuadStereo& getInstance(float ipd);
private:
QuadStereoLeftPose leftEye;
QuadStereoRightPose rightEye;
bool bQuadStereoSupported;
};

View file

@ -74,6 +74,7 @@ class Stereo3DMode
public:
/* static methods for managing the selected stereoscopic view state */
static const Stereo3DMode& getCurrentMode();
static const Stereo3DMode& getMonoMode();
Stereo3DMode();
virtual ~Stereo3DMode();
@ -84,6 +85,9 @@ public:
virtual void SetUp() const {};
virtual void TearDown() const {};
virtual bool IsMono() const { return false; }
virtual void Present() const = 0;
protected:
TArray<const EyePose *> eye_ptrs;
@ -101,6 +105,9 @@ class MonoView : public Stereo3DMode
public:
static const MonoView& getInstance();
bool IsMono() const override { return true; }
void Present() const override { }
protected:
MonoView() { eye_ptrs.Push(&centralEye); }
EyePose centralEye;

View file

@ -105,5 +105,12 @@ const Stereo3DMode& Stereo3DMode::getCurrentMode()
return *currentStereo3DMode;
}
const Stereo3DMode& Stereo3DMode::getMonoMode()
{
setCurrentMode(MonoView::getInstance());
return *currentStereo3DMode;
}
} /* namespace s3d */

View file

@ -37,7 +37,10 @@
#include "vectors.h" // RAD2DEG
#include "doomtype.h" // M_PI
#include "gl/system/gl_cvars.h"
#include "gl/system/gl_system.h"
#include "gl/renderer/gl_renderstate.h"
#include "gl/renderer/gl_renderer.h"
#include "gl/renderer/gl_renderbuffers.h"
#include <cmath>
EXTERN_CVAR(Float, vr_screendist)
@ -89,6 +92,13 @@ const LeftEyeView& LeftEyeView::getInstance(float ipd)
return instance;
}
void LeftEyeView::Present() const
{
GLRenderer->mBuffers->BindOutputFB();
GLRenderer->ClearBorders();
GLRenderer->mBuffers->BindEyeTexture(0, 0);
GLRenderer->DrawPresentTexture(GLRenderer->mOutputLetterbox, true);
}
/* static */
const RightEyeView& RightEyeView::getInstance(float ipd)
@ -98,5 +108,13 @@ const RightEyeView& RightEyeView::getInstance(float ipd)
return instance;
}
void RightEyeView::Present() const
{
GLRenderer->mBuffers->BindOutputFB();
GLRenderer->ClearBorders();
GLRenderer->mBuffers->BindEyeTexture(0, 0);
GLRenderer->DrawPresentTexture(GLRenderer->mOutputLetterbox, true);
}
} /* namespace s3d */

View file

@ -83,6 +83,7 @@ public:
LeftEyeView(float ipd) : eye(ipd) { eye_ptrs.Push(&eye); }
float getIpd() const { return eye.getIpd(); }
void setIpd(float ipd) { eye.setIpd(ipd); }
void Present() const override;
protected:
LeftEyePose eye;
};
@ -96,6 +97,7 @@ public:
RightEyeView(float ipd) : eye(ipd) { eye_ptrs.Push(&eye); }
float getIpd() const { return eye.getIpd(); }
void setIpd(float ipd) { eye.setIpd(ipd); }
void Present() const override;
protected:
RightEyePose eye;
};

View file

@ -24,9 +24,6 @@ EXTERN_CVAR(Int, gl_weaponlight)
EXTERN_CVAR (Bool, gl_lights);
EXTERN_CVAR (Bool, gl_attachedlights);
EXTERN_CVAR (Bool, gl_lights_checkside);
EXTERN_CVAR (Float, gl_lights_intensity);
EXTERN_CVAR (Float, gl_lights_size);
EXTERN_CVAR (Bool, gl_lights_additive);
EXTERN_CVAR (Bool, gl_light_sprites);
EXTERN_CVAR (Bool, gl_light_particles);
EXTERN_CVAR (Int, gl_light_math);

View file

@ -189,7 +189,8 @@ bool OpenGLFrameBuffer::WipeStartScreen(int type)
void OpenGLFrameBuffer::WipeEndScreen()
{
GLRenderer->m2DDrawer->Flush();
GLRenderer->m2DDrawer->Draw();
GLRenderer->m2DDrawer->Clear();
const auto &viewport = GLRenderer->mScreenViewport;
wipeendscreen = new FHardwareTexture(viewport.width, viewport.height, true);

View file

@ -43,15 +43,21 @@
#ifdef HAVE_MMX
#include "gl/hqnx_asm/hqnx_asm.h"
#endif
#include "gl/xbr/xbrz.h"
#include "gl/xbr/xbrz_old.h"
CUSTOM_CVAR(Int, gl_texture_hqresize, 0, CVAR_ARCHIVE | CVAR_GLOBALCONFIG | CVAR_NOINITCALL)
{
#ifdef HAVE_MMX
if (self < 0 || self > 9)
#else
if (self < 0 || self > 6)
#endif
if (self < 0 || self > 16)
{
self = 0;
}
#ifndef HAVE_MMX
// This is to allow the menu option to work properly so that these filters can be skipped while cycling through them.
if (self == 7) self = 10;
if (self == 8) self = 10;
if (self == 9) self = 6;
#endif
GLRenderer->FlushTextures();
}
@ -242,6 +248,42 @@ static unsigned char *hqNxHelper( void (*hqNxFunction) ( unsigned*, unsigned*, i
}
static unsigned char *xbrzHelper( void (*xbrzFunction) ( size_t, const uint32_t*, uint32_t*, int, int, xbrz::ColorFormat, const xbrz::ScalerCfg&, int, int ),
const int N,
unsigned char *inputBuffer,
const int inWidth,
const int inHeight,
int &outWidth,
int &outHeight )
{
outWidth = N * inWidth;
outHeight = N *inHeight;
unsigned char * newBuffer = new unsigned char[outWidth*outHeight*4];
xbrzFunction(N, reinterpret_cast<uint32_t*>(inputBuffer), reinterpret_cast<uint32_t*>(newBuffer), inWidth, inHeight, xbrz::ARGB, xbrz::ScalerCfg(), 0, std::numeric_limits<int>::max());
delete[] inputBuffer;
return newBuffer;
}
static unsigned char *xbrzoldHelper( void (*xbrzFunction) ( size_t factor, const uint32_t* src, uint32_t* trg, int srcWidth, int srcHeight, const xbrz_old::ScalerCfg& cfg, int yFirst, int yLast ),
const int N,
unsigned char *inputBuffer,
const int inWidth,
const int inHeight,
int &outWidth,
int &outHeight )
{
outWidth = N * inWidth;
outHeight = N *inHeight;
unsigned char * newBuffer = new unsigned char[outWidth*outHeight*4];
xbrzFunction(N, reinterpret_cast<uint32_t*>(inputBuffer), reinterpret_cast<uint32_t*>(newBuffer), inWidth, inHeight, xbrz_old::ScalerCfg(), 0, std::numeric_limits<int>::max());
delete[] inputBuffer;
return newBuffer;
}
//===========================================================================
//
// [BB] Upsamples the texture in inputBuffer, frees inputBuffer and returns
@ -322,6 +364,16 @@ unsigned char *gl_CreateUpsampledTextureBuffer ( const FTexture *inputTexture, u
case 9:
return hqNxAsmHelper( &HQnX_asm::hq4x_32, 4, inputBuffer, inWidth, inHeight, outWidth, outHeight );
#endif
case 10:
case 11:
case 12:
return xbrzHelper(xbrz::scale, type - 8, inputBuffer, inWidth, inHeight, outWidth, outHeight );
case 13:
case 14:
case 15:
return xbrzoldHelper(xbrz_old::scale, type - 11, inputBuffer, inWidth, inHeight, outWidth, outHeight );
}
}
return inputBuffer;

View file

@ -64,18 +64,6 @@ extern int TexFormat[];
//===========================================================================
unsigned int FHardwareTexture::lastbound[FHardwareTexture::MAX_TEXTURES];
//===========================================================================
//
// STATIC - Gets the maximum size of hardware textures
//
//===========================================================================
int FHardwareTexture::GetTexDimension(int value)
{
if (value > gl.max_texturesize) return gl.max_texturesize;
return value;
}
//===========================================================================
//
// Quick'n dirty image rescaling.

View file

@ -10,6 +10,7 @@
#define DIRECT_PALETTE -2
#include "tarray.h"
#include "gl/system/gl_interface.h"
class FCanvasTexture;
class AActor;
@ -49,7 +50,11 @@ public:
static unsigned int lastbound[MAX_TEXTURES];
static int GetTexDimension(int value);
static int GetTexDimension(int value)
{
if (value > gl.max_texturesize) return gl.max_texturesize;
return value;
}
static void InitGlobalState() { for (int i = 0; i < MAX_TEXTURES; i++) lastbound[i] = 0; }

View file

@ -267,3 +267,5 @@ public:
};
#endif

1229
src/gl/xbr/xbrz.cpp Normal file

File diff suppressed because it is too large Load diff

102
src/gl/xbr/xbrz.h Normal file
View file

@ -0,0 +1,102 @@
// ****************************************************************************
// * This file is part of the HqMAME project. It is distributed under *
// * GNU General Public License: http://www.gnu.org/licenses/gpl-3.0 *
// * Copyright (C) Zenju (zenju AT gmx DOT de) - All Rights Reserved *
// * *
// * Additionally and as a special exception, the author gives permission *
// * to link the code of this program with the MAME library (or with modified *
// * versions of MAME that use the same license as MAME), and distribute *
// * linked combinations including the two. You must obey the GNU General *
// * Public License in all respects for all of the code used other than MAME. *
// * If you modify this file, you may extend this exception to your version *
// * of the file, but you are not obligated to do so. If you do not wish to *
// * do so, delete this exception statement from your version. *
// * *
// * An explicit permission was granted to use xBRZ in combination with ZDoom *
// * and derived projects as long as it is used for non-commercial purposes. *
// * *
// * Backported to C++98 by Alexey Lysiuk *
// ****************************************************************************
#ifndef XBRZ_HEADER_3847894708239054
#define XBRZ_HEADER_3847894708239054
#include <cstddef> //size_t
#include <stdint.h> //uint32_t
#include <limits>
#include "xbrz_config.h"
namespace xbrz
{
/*
-------------------------------------------------------------------------
| xBRZ: "Scale by rules" - high quality image upscaling filter by Zenju |
-------------------------------------------------------------------------
using a modified approach of xBR:
http://board.byuu.org/viewtopic.php?f=10&t=2248
- new rule set preserving small image features
- highly optimized for performance
- support alpha channel
- support multithreading
- support 64-bit architectures
- support processing image slices
- support scaling up to 6xBRZ
*/
enum ColorFormat //from high bits -> low bits, 8 bit per channel
{
RGB, //8 bit for each red, green, blue, upper 8 bits unused
ARGB, //including alpha channel, BGRA byte order on little-endian machines
};
/*
-> map source (srcWidth * srcHeight) to target (scale * width x scale * height) image, optionally processing a half-open slice of rows [yFirst, yLast) only
-> support for source/target pitch in bytes!
-> if your emulator changes only a few image slices during each cycle (e.g. DOSBox) then there's no need to run xBRZ on the complete image:
Just make sure you enlarge the source image slice by 2 rows on top and 2 on bottom (this is the additional range the xBRZ algorithm is using during analysis)
Caveat: If there are multiple changed slices, make sure they do not overlap after adding these additional rows in order to avoid a memory race condition
in the target image data if you are using multiple threads for processing each enlarged slice!
THREAD-SAFETY: - parts of the same image may be scaled by multiple threads as long as the [yFirst, yLast) ranges do not overlap!
- there is a minor inefficiency for the first row of a slice, so avoid processing single rows only; suggestion: process 8-16 rows at least
*/
#ifdef max
#undef max
#endif
void scale(size_t factor, //valid range: 2 - 6
const uint32_t* src, uint32_t* trg, int srcWidth, int srcHeight,
ColorFormat colFmt,
const ScalerCfg& cfg = ScalerCfg(),
int yFirst = 0, int yLast = std::numeric_limits<int>::max()); //slice of source image
void nearestNeighborScale(const uint32_t* src, int srcWidth, int srcHeight,
uint32_t* trg, int trgWidth, int trgHeight);
enum SliceType
{
NN_SCALE_SLICE_SOURCE,
NN_SCALE_SLICE_TARGET,
};
void nearestNeighborScale(const uint32_t* src, int srcWidth, int srcHeight, int srcPitch, //pitch in bytes!
uint32_t* trg, int trgWidth, int trgHeight, int trgPitch,
SliceType st, int yFirst, int yLast);
//parameter tuning
bool equalColorTest(uint32_t col1, uint32_t col2, ColorFormat colFmt, double luminanceWeight, double equalColorTolerance);
//########################### implementation ###########################
inline
void nearestNeighborScale(const uint32_t* src, int srcWidth, int srcHeight,
uint32_t* trg, int trgWidth, int trgHeight)
{
nearestNeighborScale(src, srcWidth, srcHeight, srcWidth * sizeof(uint32_t),
trg, trgWidth, trgHeight, trgWidth * sizeof(uint32_t),
NN_SCALE_SLICE_TARGET, 0, trgHeight);
}
}
#endif

45
src/gl/xbr/xbrz_config.h Normal file
View file

@ -0,0 +1,45 @@
// ****************************************************************************
// * This file is part of the HqMAME project. It is distributed under *
// * GNU General Public License: http://www.gnu.org/licenses/gpl-3.0 *
// * Copyright (C) Zenju (zenju AT gmx DOT de) - All Rights Reserved *
// * *
// * Additionally and as a special exception, the author gives permission *
// * to link the code of this program with the MAME library (or with modified *
// * versions of MAME that use the same license as MAME), and distribute *
// * linked combinations including the two. You must obey the GNU General *
// * Public License in all respects for all of the code used other than MAME. *
// * If you modify this file, you may extend this exception to your version *
// * of the file, but you are not obligated to do so. If you do not wish to *
// * do so, delete this exception statement from your version. *
// * *
// * An explicit permission was granted to use xBRZ in combination with ZDoom *
// * and derived projects as long as it is used for non-commercial purposes. *
// * *
// * Backported to C++98 by Alexey Lysiuk *
// ****************************************************************************
#ifndef XBRZ_CONFIG_HEADER_284578425345
#define XBRZ_CONFIG_HEADER_284578425345
//do NOT include any headers here! used by xBRZ_dll!!!
namespace xbrz
{
struct ScalerCfg
{
ScalerCfg() :
luminanceWeight(1),
equalColorTolerance(30),
dominantDirectionThreshold(3.6),
steepDirectionThreshold(2.2),
newTestAttribute(0) {}
double luminanceWeight;
double equalColorTolerance;
double dominantDirectionThreshold;
double steepDirectionThreshold;
double newTestAttribute; //unused; test new parameters
};
}
#endif

View file

@ -0,0 +1,45 @@
// ****************************************************************************
// * This file is part of the HqMAME project. It is distributed under *
// * GNU General Public License: http://www.gnu.org/licenses/gpl.html *
// * Copyright (C) Zenju (zenju AT gmx DOT de) - All Rights Reserved *
// * *
// * Additionally and as a special exception, the author gives permission *
// * to link the code of this program with the MAME library (or with modified *
// * versions of MAME that use the same license as MAME), and distribute *
// * linked combinations including the two. You must obey the GNU General *
// * Public License in all respects for all of the code used other than MAME. *
// * If you modify this file, you may extend this exception to your version *
// * of the file, but you are not obligated to do so. If you do not wish to *
// * do so, delete this exception statement from your version. *
// * *
// * An explicit permission was granted to use xBRZ in combination with ZDoom *
// * and derived projects as long as it is used for non-commercial purposes. *
// * *
// * Backported to C++98 by Alexey Lysiuk *
// ****************************************************************************
#ifndef __XBRZ_CONFIG_OLD_HEADER_INCLUDED__
#define __XBRZ_CONFIG_OLD_HEADER_INCLUDED__
//do NOT include any headers here! used by xBRZ_dll!!!
namespace xbrz_old
{
struct ScalerCfg
{
ScalerCfg() :
luminanceWeight_(1),
equalColorTolerance_(30),
dominantDirectionThreshold(3.6),
steepDirectionThreshold(2.2),
newTestAttribute_(0) {}
double luminanceWeight_;
double equalColorTolerance_;
double dominantDirectionThreshold;
double steepDirectionThreshold;
double newTestAttribute_; //unused; test new parameters
};
}
#endif

1365
src/gl/xbr/xbrz_old.cpp Normal file

File diff suppressed because it is too large Load diff

92
src/gl/xbr/xbrz_old.h Normal file
View file

@ -0,0 +1,92 @@
// ****************************************************************************
// * This file is part of the HqMAME project. It is distributed under *
// * GNU General Public License: http://www.gnu.org/licenses/gpl.html *
// * Copyright (C) Zenju (zenju AT gmx DOT de) - All Rights Reserved *
// * *
// * Additionally and as a special exception, the author gives permission *
// * to link the code of this program with the MAME library (or with modified *
// * versions of MAME that use the same license as MAME), and distribute *
// * linked combinations including the two. You must obey the GNU General *
// * Public License in all respects for all of the code used other than MAME. *
// * If you modify this file, you may extend this exception to your version *
// * of the file, but you are not obligated to do so. If you do not wish to *
// * do so, delete this exception statement from your version. *
// * *
// * An explicit permission was granted to use xBRZ in combination with ZDoom *
// * and derived projects as long as it is used for non-commercial purposes. *
// * *
// * Backported to C++98 by Alexey Lysiuk *
// ****************************************************************************
#ifndef __XBRZ_OLD_HEADER_INCLUDED__
#define __XBRZ_OLD_HEADER_INCLUDED__
#include <cstddef> //size_t
#include <stdint.h> //uint32_t
#include <limits>
#include "xbrz_config_old.h"
namespace xbrz_old
{
/*
-------------------------------------------------------------------------
| xBRZ: "Scale by rules" - high quality image upscaling filter by Zenju |
-------------------------------------------------------------------------
using a modified approach of xBR:
http://board.byuu.org/viewtopic.php?f=10&t=2248
- new rule set preserving small image features
- support multithreading
- support 64 bit architectures
- support processing image slices
*/
/*
-> map source (srcWidth * srcHeight) to target (scale * width x scale * height) image, optionally processing a half-open slice of rows [yFirst, yLast) only
-> color format: ARGB (BGRA byte order), alpha channel unused
-> support for source/target pitch in bytes!
-> if your emulator changes only a few image slices during each cycle (e.g. Dosbox) then there's no need to run xBRZ on the complete image:
Just make sure you enlarge the source image slice by 2 rows on top and 2 on bottom (this is the additional range the xBRZ algorithm is using during analysis)
Caveat: If there are multiple changed slices, make sure they do not overlap after adding these additional rows in order to avoid a memory race condition
if you are using multiple threads for processing each enlarged slice!
THREAD-SAFETY: - parts of the same image may be scaled by multiple threads as long as the [yFirst, yLast) ranges do not overlap!
- there is a minor inefficiency for the first row of a slice, so avoid processing single rows only
*/
void scale(size_t factor, //valid range: 2 - 5
const uint32_t* src, uint32_t* trg, int srcWidth, int srcHeight,
const ScalerCfg& cfg = ScalerCfg(),
int yFirst = 0, int yLast = std::numeric_limits<int>::max()); //slice of source image
void nearestNeighborScale(const uint32_t* src, int srcWidth, int srcHeight,
uint32_t* trg, int trgWidth, int trgHeight);
enum SliceType
{
NN_SCALE_SLICE_SOURCE,
NN_SCALE_SLICE_TARGET,
};
void nearestNeighborScale(const uint32_t* src, int srcWidth, int srcHeight, int srcPitch, //pitch in bytes!
uint32_t* trg, int trgWidth, int trgHeight, int trgPitch,
SliceType st, int yFirst, int yLast);
//parameter tuning
bool equalColor(uint32_t col1, uint32_t col2, double luminanceWeight, double equalColorTolerance);
//########################### implementation ###########################
inline
void nearestNeighborScale(const uint32_t* src, int srcWidth, int srcHeight,
uint32_t* trg, int trgWidth, int trgHeight)
{
nearestNeighborScale(src, srcWidth, srcHeight, srcWidth * sizeof(uint32_t),
trg, trgWidth, trgHeight, trgWidth * sizeof(uint32_t),
NN_SCALE_SLICE_TARGET, 0, trgHeight);
}
}
#endif

View file

@ -4450,6 +4450,8 @@ enum EACSFunctions
*/
ACSF_CheckClass = 200,
ACSF_DamageActor, // [arookas]
ACSF_SetActorFlag,
// ZDaemon
ACSF_GetTeamScore = 19620, // (int team)
@ -6035,6 +6037,43 @@ doplaysound: if (funcIndex == ACSF_PlayActorSound)
const char *clsname = FBehavior::StaticLookupString(args[0]);
return !!PClass::FindActor(clsname);
}
case ACSF_DamageActor: // [arookas] wrapper around P_DamageMobj
{
// (target, ptr_select1, inflictor, ptr_select2, amount, damagetype)
AActor* target = COPY_AAPTR(SingleActorFromTID(args[0], activator), args[1]);
AActor* inflictor = COPY_AAPTR(SingleActorFromTID(args[2], activator), args[3]);
FName damagetype(FBehavior::StaticLookupString(args[5]));
return P_DamageMobj(target, inflictor, inflictor, args[4], damagetype);
}
case ACSF_SetActorFlag:
{
int tid = args[0];
FString flagname = FBehavior::StaticLookupString(args[1]);
bool flagvalue = !!args[2];
int count = 0; // Return value; number of actors affected
if (tid == 0)
{
if (ModActorFlag(activator, flagname, flagvalue))
{
++count;
}
}
else
{
FActorIterator it(tid);
while ((actor = it.Next()) != nullptr)
{
// Don't log errors when affecting many actors because things might share a TID but not share the flag
if (ModActorFlag(actor, flagname, flagvalue, false))
{
++count;
}
}
}
return count;
}
default:
break;

View file

@ -459,23 +459,14 @@ CocoaWindow* CreateCocoaWindow(const NSUInteger styleMask)
return window;
}
} // unnamed namespace
// ---------------------------------------------------------------------------
CocoaVideo::CocoaVideo()
: m_window(CreateCocoaWindow(STYLE_MASK_WINDOWED))
, m_width(-1)
, m_height(-1)
, m_fullscreen(false)
, m_hiDPI(false)
enum OpenGLProfile
{
memset(&m_modeIterator, 0, sizeof m_modeIterator);
// Set attributes for OpenGL context
Core,
Legacy
};
NSOpenGLPixelFormat* CreatePixelFormat(const OpenGLProfile profile)
{
NSOpenGLPixelFormatAttribute attributes[16];
size_t i = 0;
@ -492,17 +483,59 @@ CocoaVideo::CocoaVideo()
attributes[i++] = NSOpenGLPFAAllowOfflineRenderers;
}
if (NSAppKitVersionNumber >= AppKit10_7)
if (NSAppKitVersionNumber >= AppKit10_7 && OpenGLProfile::Core == profile)
{
NSOpenGLPixelFormatAttribute profile = NSOpenGLProfileVersion3_2Core;
const char* const glversion = Args->CheckValue("-glversion");
if (nullptr != glversion)
{
const double version = strtod(glversion, nullptr) + 0.01;
if (version < 3.2)
{
profile = NSOpenGLProfileVersionLegacy;
}
}
attributes[i++] = NSOpenGLPFAOpenGLProfile;
attributes[i++] = NSOpenGLProfileVersion3_2Core;
attributes[i++] = profile;
}
attributes[i] = NSOpenGLPixelFormatAttribute(0);
// Create OpenGL context and view
return [[NSOpenGLPixelFormat alloc] initWithAttributes:attributes];
}
NSOpenGLPixelFormat *pixelFormat = [[NSOpenGLPixelFormat alloc] initWithAttributes:attributes];
} // unnamed namespace
// ---------------------------------------------------------------------------
CocoaVideo::CocoaVideo()
: m_window(CreateCocoaWindow(STYLE_MASK_WINDOWED))
, m_width(-1)
, m_height(-1)
, m_fullscreen(false)
, m_hiDPI(false)
{
memset(&m_modeIterator, 0, sizeof m_modeIterator);
// Create OpenGL pixel format
NSOpenGLPixelFormat* pixelFormat = CreatePixelFormat(OpenGLProfile::Core);
if (nil == pixelFormat)
{
pixelFormat = CreatePixelFormat(OpenGLProfile::Legacy);
if (nil == pixelFormat)
{
I_FatalError("Cannot OpenGL create pixel format, graphics hardware is not supported");
}
}
// Create OpenGL context and view
const NSRect contentRect = [m_window contentRectForFrameRect:[m_window frame]];
NSOpenGLView* glView = [[CocoaView alloc] initWithFrame:contentRect

View file

@ -0,0 +1,187 @@
/*
** i_specialpaths.mm
** Gets special system folders where data should be stored. (macOS version)
**
**---------------------------------------------------------------------------
** Copyright 2013-2016 Randy Heit
** Copyright 2016 Christoph Oelckers
** All rights reserved.
**
** Redistribution and use in source and binary forms, with or without
** modification, are permitted provided that the following conditions
** are met:
**
** 1. Redistributions of source code must retain the above copyright
** notice, this list of conditions and the following disclaimer.
** 2. Redistributions in binary form must reproduce the above copyright
** notice, this list of conditions and the following disclaimer in the
** documentation and/or other materials provided with the distribution.
** 3. The name of the author may not be used to endorse or promote products
** derived from this software without specific prior written permission.
**
** THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
** IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
** OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
** IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
** INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
** NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
** THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
**---------------------------------------------------------------------------
**
*/
#include <CoreServices/CoreServices.h>
#include "cmdlib.h"
#include "m_misc.h"
#include "version.h" // for GAMENAME
//===========================================================================
//
// M_GetCachePath macOS
//
// Returns the path for cache GL nodes.
//
//===========================================================================
FString M_GetCachePath(bool create)
{
FString path;
char pathstr[PATH_MAX];
FSRef folder;
if (noErr == FSFindFolder(kUserDomain, kApplicationSupportFolderType, create ? kCreateFolder : 0, &folder) &&
noErr == FSRefMakePath(&folder, (UInt8*)pathstr, PATH_MAX))
{
path = pathstr;
}
else
{
path = progdir;
}
path += "/zdoom/cache";
return path;
}
//===========================================================================
//
// M_GetAutoexecPath macOS
//
// Returns the expected location of autoexec.cfg.
//
//===========================================================================
FString M_GetAutoexecPath()
{
FString path;
char cpath[PATH_MAX];
FSRef folder;
if (noErr == FSFindFolder(kUserDomain, kDocumentsFolderType, kCreateFolder, &folder) &&
noErr == FSRefMakePath(&folder, (UInt8*)cpath, PATH_MAX))
{
path << cpath << "/" GAME_DIR "/autoexec.cfg";
}
return path;
}
//===========================================================================
//
// M_GetCajunPath macOS
//
// Returns the location of the Cajun Bot definitions.
//
//===========================================================================
FString M_GetCajunPath(const char *botfilename)
{
FString path;
// Just copies the Windows code. Should this be more Mac-specific?
path << progdir << "zcajun/" << botfilename;
if (!FileExists(path))
{
path = "";
}
return path;
}
//===========================================================================
//
// M_GetConfigPath macOS
//
// Returns the path to the config file. On Windows, this can vary for reading
// vs writing. i.e. If $PROGDIR/zdoom-<user>.ini does not exist, it will try
// to read from $PROGDIR/zdoom.ini, but it will never write to zdoom.ini.
//
//===========================================================================
FString M_GetConfigPath(bool for_reading)
{
char cpath[PATH_MAX];
FSRef folder;
if (noErr == FSFindFolder(kUserDomain, kPreferencesFolderType, kCreateFolder, &folder) &&
noErr == FSRefMakePath(&folder, (UInt8*)cpath, PATH_MAX))
{
FString path;
path << cpath << "/" GAMENAMELOWERCASE ".ini";
return path;
}
// Ungh.
return GAMENAMELOWERCASE ".ini";
}
//===========================================================================
//
// M_GetScreenshotsPath macOS
//
// Returns the path to the default screenshots directory.
//
//===========================================================================
FString M_GetScreenshotsPath()
{
FString path;
char cpath[PATH_MAX];
FSRef folder;
if (noErr == FSFindFolder(kUserDomain, kDocumentsFolderType, kCreateFolder, &folder) &&
noErr == FSRefMakePath(&folder, (UInt8*)cpath, PATH_MAX))
{
path << cpath << "/" GAME_DIR "/Screenshots/";
}
else
{
path = "~/";
}
return path;
}
//===========================================================================
//
// M_GetSavegamesPath macOS
//
// Returns the path to the default save games directory.
//
//===========================================================================
FString M_GetSavegamesPath()
{
FString path;
char cpath[PATH_MAX];
FSRef folder;
if (noErr == FSFindFolder(kUserDomain, kDocumentsFolderType, kCreateFolder, &folder) &&
noErr == FSRefMakePath(&folder, (UInt8*)cpath, PATH_MAX))
{
path << cpath << "/" GAME_DIR "/Savegames/";
}
return path;
}

View file

@ -0,0 +1,200 @@
/*
** i_specialpaths.cpp
** Gets special system folders where data should be stored. (Unix version)
**
**---------------------------------------------------------------------------
** Copyright 2013-2016 Randy Heit
** Copyright 2016 Christoph Oelckers
** All rights reserved.
**
** Redistribution and use in source and binary forms, with or without
** modification, are permitted provided that the following conditions
** are met:
**
** 1. Redistributions of source code must retain the above copyright
** notice, this list of conditions and the following disclaimer.
** 2. Redistributions in binary form must reproduce the above copyright
** notice, this list of conditions and the following disclaimer in the
** documentation and/or other materials provided with the distribution.
** 3. The name of the author may not be used to endorse or promote products
** derived from this software without specific prior written permission.
**
** THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
** IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
** OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
** IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
** INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
** NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
** THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
**---------------------------------------------------------------------------
**
*/
#include <sys/stat.h>
#include <sys/types.h>
#include "i_system.h"
#include "cmdlib.h"
#include "version.h" // for GAMENAME
FString GetUserFile (const char *file)
{
FString path;
struct stat info;
path = NicePath("~/" GAME_DIR "/");
if (stat (path, &info) == -1)
{
struct stat extrainfo;
// Sanity check for ~/.config
FString configPath = NicePath("~/.config/");
if (stat (configPath, &extrainfo) == -1)
{
if (mkdir (configPath, S_IRUSR | S_IWUSR | S_IXUSR) == -1)
{
I_FatalError ("Failed to create ~/.config directory:\n%s", strerror(errno));
}
}
else if (!S_ISDIR(extrainfo.st_mode))
{
I_FatalError ("~/.config must be a directory");
}
// This can be removed after a release or two
// Transfer the old zdoom directory to the new location
bool moved = false;
FString oldpath = NicePath("~/." GAMENAMELOWERCASE "/");
if (stat (oldpath, &extrainfo) != -1)
{
if (rename(oldpath, path) == -1)
{
I_Error ("Failed to move old " GAMENAMELOWERCASE " directory (%s) to new location (%s).",
oldpath.GetChars(), path.GetChars());
}
else
moved = true;
}
if (!moved && mkdir (path, S_IRUSR | S_IWUSR | S_IXUSR) == -1)
{
I_FatalError ("Failed to create %s directory:\n%s",
path.GetChars(), strerror (errno));
}
}
else
{
if (!S_ISDIR(info.st_mode))
{
I_FatalError ("%s must be a directory", path.GetChars());
}
}
path += file;
return path;
}
//===========================================================================
//
// M_GetCachePath Unix
//
// Returns the path for cache GL nodes.
//
//===========================================================================
FString M_GetCachePath(bool create)
{
// Don't use GAME_DIR and such so that ZDoom and its child ports can
// share the node cache.
FString path = NicePath("~/.config/zdoom/cache");
if (create)
{
CreatePath(path);
}
return path;
}
//===========================================================================
//
// M_GetAutoexecPath Unix
//
// Returns the expected location of autoexec.cfg.
//
//===========================================================================
FString M_GetAutoexecPath()
{
return GetUserFile("autoexec.cfg");
}
//===========================================================================
//
// M_GetCajunPath Unix
//
// Returns the location of the Cajun Bot definitions.
//
//===========================================================================
FString M_GetCajunPath(const char *botfilename)
{
FString path;
// Check first in ~/.config/zdoom/botfilename.
path = GetUserFile(botfilename);
if (!FileExists(path))
{
// Then check in SHARE_DIR/botfilename.
path = SHARE_DIR;
path << botfilename;
if (!FileExists(path))
{
path = "";
}
}
return path;
}
//===========================================================================
//
// M_GetConfigPath Unix
//
// Returns the path to the config file. On Windows, this can vary for reading
// vs writing. i.e. If $PROGDIR/zdoom-<user>.ini does not exist, it will try
// to read from $PROGDIR/zdoom.ini, but it will never write to zdoom.ini.
//
//===========================================================================
FString M_GetConfigPath(bool for_reading)
{
return GetUserFile(GAMENAMELOWERCASE ".ini");
}
//===========================================================================
//
// M_GetScreenshotsPath Unix
//
// Returns the path to the default screenshots directory.
//
//===========================================================================
FString M_GetScreenshotsPath()
{
return NicePath("~/" GAME_DIR "/screenshots/");
}
//===========================================================================
//
// M_GetSavegamesPath Unix
//
// Returns the path to the default save games directory.
//
//===========================================================================
FString M_GetSavegamesPath()
{
return NicePath("~/" GAME_DIR);
}

View file

@ -656,7 +656,7 @@ void R_AddInterpolationPoint(const DVector3a &vec)
//
//==========================================================================
static double QuakePower(double factor, double intensity, double offset, double falloff, double wfalloff)
static double QuakePower(double factor, double intensity, double offset)
{
double randumb;
if (intensity == 0)
@ -667,7 +667,7 @@ static double QuakePower(double factor, double intensity, double offset, double
{
randumb = pr_torchflicker.GenRand_Real2() * (intensity * 2) - intensity;
}
return factor * (wfalloff * offset + falloff * randumb);
return factor * (offset + randumb);
}
//==========================================================================
@ -797,36 +797,36 @@ void R_SetupFrame (AActor *actor)
if (jiggers.RollIntensity != 0 || jiggers.RollWave != 0)
{
ViewRoll += QuakePower(quakefactor, jiggers.RollIntensity, jiggers.RollWave, jiggers.RFalloff, jiggers.RWFalloff);
ViewRoll += QuakePower(quakefactor, jiggers.RollIntensity, jiggers.RollWave);
}
if (jiggers.RelIntensity.X != 0 || jiggers.RelOffset.X != 0)
{
an = camera->Angles.Yaw;
double power = QuakePower(quakefactor, jiggers.RelIntensity.X, jiggers.RelOffset.X, jiggers.Falloff, jiggers.WFalloff);
double power = QuakePower(quakefactor, jiggers.RelIntensity.X, jiggers.RelOffset.X);
ViewPos += an.ToVector(power);
}
if (jiggers.RelIntensity.Y != 0 || jiggers.RelOffset.Y != 0)
{
an = camera->Angles.Yaw + 90;
double power = QuakePower(quakefactor, jiggers.RelIntensity.Y, jiggers.RelOffset.Y, jiggers.Falloff, jiggers.WFalloff);
double power = QuakePower(quakefactor, jiggers.RelIntensity.Y, jiggers.RelOffset.Y);
ViewPos += an.ToVector(power);
}
// FIXME: Relative Z is not relative
if (jiggers.RelIntensity.Z != 0 || jiggers.RelOffset.Z != 0)
{
ViewPos.Z += QuakePower(quakefactor, jiggers.RelIntensity.Z, jiggers.RelOffset.Z, jiggers.Falloff, jiggers.WFalloff);
ViewPos.Z += QuakePower(quakefactor, jiggers.RelIntensity.Z, jiggers.RelOffset.Z);
}
if (jiggers.Intensity.X != 0 || jiggers.Offset.X != 0)
{
ViewPos.X += QuakePower(quakefactor, jiggers.Intensity.X, jiggers.Offset.X, jiggers.Falloff, jiggers.WFalloff);
ViewPos.X += QuakePower(quakefactor, jiggers.Intensity.X, jiggers.Offset.X);
}
if (jiggers.Intensity.Y != 0 || jiggers.Offset.Y != 0)
{
ViewPos.Y += QuakePower(quakefactor, jiggers.Intensity.Y, jiggers.Offset.Y, jiggers.Falloff, jiggers.WFalloff);
ViewPos.Y += QuakePower(quakefactor, jiggers.Intensity.Y, jiggers.Offset.Y);
}
if (jiggers.Intensity.Z != 0 || jiggers.Offset.Z != 0)
{
ViewPos.Z += QuakePower(quakefactor, jiggers.Intensity.Z, jiggers.Offset.Z, jiggers.Falloff, jiggers.WFalloff);
ViewPos.Z += QuakePower(quakefactor, jiggers.Intensity.Z, jiggers.Offset.Z);
}
}
}

View file

@ -380,7 +380,7 @@ struct bCopyAlpha
};
struct bOverlay
{
{
static __forceinline void OpC(BYTE &d, BYTE s, BYTE a, FCopyInfo *i) { d = (s*a + d*(255-a))/255; }
static __forceinline void OpA(BYTE &d, BYTE s, FCopyInfo *i) { d = MAX(s,d); }
static __forceinline bool ProcessAlpha0() { return false; }

View file

@ -628,8 +628,9 @@ int FMultiPatchTexture::CopyTrueColorPixels(FBitmap *bmp, int x, int y, int rota
{
ret = Parts[i].Texture->CopyTrueColorPixels(bmp, x+Parts[i].OriginX, y+Parts[i].OriginY, Parts[i].Rotate, &info);
}
if (ret > retv) retv = ret;
// treat -1 (i.e. unknown) as absolute. We have no idea if this may have overwritten previous info so a real check needs to be done.
if (ret == -1) retv = ret;
else if (retv != -1 && ret > retv) retv = ret;
}
// Restore previous clipping rectangle.
bmp->SetClipRect(saved_cr);

View file

@ -30,6 +30,7 @@ void HandleDeprecatedFlags(AActor *defaults, PClassActor *info, bool set, int in
bool CheckDeprecatedFlags(const AActor *actor, PClassActor *info, int index);
const char *GetFlagName(unsigned int flagnum, int flagoffset);
void ModActorFlag(AActor *actor, FFlagDef *fd, bool set);
bool ModActorFlag(AActor *actor, FString &flagname, bool set, bool printerror = true);
INTBOOL CheckActorFlag(const AActor *actor, FFlagDef *fd);
INTBOOL CheckActorFlag(const AActor *owner, const char *flagname, bool printerror = true);

View file

@ -76,6 +76,7 @@
#include "d_player.h"
#include "p_maputl.h"
#include "p_spec.h"
#include "templates.h"
#include "math/cmath.h"
AActor *SingleActorFromTID(int tid, AActor *defactor);
@ -1421,7 +1422,11 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_Explode)
damagetype = self->DamageType;
}
int count = P_RadiusAttack (self, self->target, damage, distance, damagetype, flags, fulldmgdistance);
int pflags = 0;
if (flags & XF_HURTSOURCE) pflags |= RADF_HURTSOURCE;
if (flags & XF_NOTMISSILE) pflags |= RADF_SOURCEISSPOT;
int count = P_RadiusAttack (self, self->target, damage, distance, damagetype, pflags, fulldmgdistance);
P_CheckSplash(self, distance);
if (alert && self->target != NULL && self->target->player != NULL)
{
@ -4501,7 +4506,9 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_JumpIfTargetInLOS)
else { target = viewport; viewport = self; }
}
if (fov > 0 && (fov < 360.))
fov = MIN<DAngle>(fov, 360.);
if (fov > 0)
{
DAngle an = absangle(viewport->AngleTo(target), viewport->Angles.Yaw);
@ -4678,90 +4685,7 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_ChangeFlag)
PARAM_STRING (flagname);
PARAM_BOOL (value);
const char *dot = strchr(flagname, '.');
FFlagDef *fd;
PClassActor *cls = self->GetClass();
if (dot != NULL)
{
FString part1(flagname.GetChars(), dot - flagname);
fd = FindFlag(cls, part1, dot + 1);
}
else
{
fd = FindFlag(cls, flagname, NULL);
}
if (fd != NULL)
{
bool kill_before, kill_after;
INTBOOL item_before, item_after;
INTBOOL secret_before, secret_after;
kill_before = self->CountsAsKill();
item_before = self->flags & MF_COUNTITEM;
secret_before = self->flags5 & MF5_COUNTSECRET;
if (fd->structoffset == -1)
{
HandleDeprecatedFlags(self, cls, value, fd->flagbit);
}
else
{
ActorFlags *flagp = (ActorFlags*) (((char*)self) + fd->structoffset);
// If these 2 flags get changed we need to update the blockmap and sector links.
bool linkchange = flagp == &self->flags && (fd->flagbit == MF_NOBLOCKMAP || fd->flagbit == MF_NOSECTOR);
if (linkchange) self->UnlinkFromWorld();
ModActorFlag(self, fd, value);
if (linkchange) self->LinkToWorld();
}
kill_after = self->CountsAsKill();
item_after = self->flags & MF_COUNTITEM;
secret_after = self->flags5 & MF5_COUNTSECRET;
// Was this monster previously worth a kill but no longer is?
// Or vice versa?
if (kill_before != kill_after)
{
if (kill_after)
{ // It counts as a kill now.
level.total_monsters++;
}
else
{ // It no longer counts as a kill.
level.total_monsters--;
}
}
// same for items
if (item_before != item_after)
{
if (item_after)
{ // It counts as an item now.
level.total_items++;
}
else
{ // It no longer counts as an item
level.total_items--;
}
}
// and secretd
if (secret_before != secret_after)
{
if (secret_after)
{ // It counts as an secret now.
level.total_secrets++;
}
else
{ // It no longer counts as an secret
level.total_secrets--;
}
}
}
else
{
Printf("Unknown flag '%s' in '%s'\n", flagname.GetChars(), cls->TypeName.GetChars());
}
ModActorFlag(self, flagname, value);
return 0;
}

View file

@ -182,6 +182,7 @@ static FFlagDef ActorFlagDefs[]=
DEFINE_FLAG(MF4, BOSSDEATH, AActor, flags4),
DEFINE_FLAG(MF5, DONTDRAIN, AActor, flags5),
DEFINE_FLAG(MF5, GETOWNER, AActor, flags5),
DEFINE_FLAG(MF5, NODROPOFF, AActor, flags5),
DEFINE_FLAG(MF5, NOFORWARDFALL, AActor, flags5),
DEFINE_FLAG(MF5, COUNTSECRET, AActor, flags5),

View file

@ -309,7 +309,8 @@ static FxExpression *ParseExpressionC (FScanner &sc, PClassActor *cls)
static FxExpression *ParseExpressionB (FScanner &sc, PClassActor *cls)
{
sc.GetToken();
switch(sc.TokenType)
int token = sc.TokenType;
switch(token)
{
case '~':
return new FxUnaryNotBitwise(ParseExpressionA (sc, cls));
@ -325,7 +326,7 @@ static FxExpression *ParseExpressionB (FScanner &sc, PClassActor *cls)
case TK_Incr:
case TK_Decr:
return new FxPreIncrDecr(ParseExpressionA(sc, cls), sc.TokenType);
return new FxPreIncrDecr(ParseExpressionA(sc, cls), token);
default:
sc.UnGet();

View file

@ -162,6 +162,71 @@ void ModActorFlag(AActor *actor, FFlagDef *fd, bool set)
#endif
}
//==========================================================================
//
// Finds a flag by name and sets or clears it
//
// Returns true if the flag was found for the actor; else returns false
//
//==========================================================================
bool ModActorFlag(AActor *actor, FString &flagname, bool set, bool printerror)
{
bool found = false;
if (actor != NULL)
{
const char *dot = strchr(flagname, '.');
FFlagDef *fd;
PClassActor *cls = actor->GetClass();
if (dot != NULL)
{
FString part1(flagname.GetChars(), dot - flagname);
fd = FindFlag(cls, part1, dot + 1);
}
else
{
fd = FindFlag(cls, flagname, NULL);
}
if (fd != NULL)
{
found = true;
if (actor->CountsAsKill() && actor->health > 0) --level.total_monsters;
if (actor->flags & MF_COUNTITEM) --level.total_items;
if (actor->flags5 & MF5_COUNTSECRET) --level.total_secrets;
if (fd->structoffset == -1)
{
HandleDeprecatedFlags(actor, cls, set, fd->flagbit);
}
else
{
ActorFlags *flagp = (ActorFlags*)(((char*)actor) + fd->structoffset);
// If these 2 flags get changed we need to update the blockmap and sector links.
bool linkchange = flagp == &actor->flags && (fd->flagbit == MF_NOBLOCKMAP || fd->flagbit == MF_NOSECTOR);
if (linkchange) actor->UnlinkFromWorld();
ModActorFlag(actor, fd, set);
if (linkchange) actor->LinkToWorld();
}
if (actor->CountsAsKill() && actor->health > 0) ++level.total_monsters;
if (actor->flags & MF_COUNTITEM) ++level.total_items;
if (actor->flags5 & MF5_COUNTSECRET) ++level.total_secrets;
}
else if (printerror)
{
DPrintf(DMSG_ERROR, "ACS/DECORATE: '%s' is not a flag in '%s'\n", flagname.GetChars(), cls->TypeName.GetChars());
}
}
return found;
}
//==========================================================================
//
// Returns whether an actor flag is true or not.

View file

@ -62,6 +62,14 @@
#include "colormatcher.h"
#include "r_data/colormaps.h"
CUSTOM_CVAR(Int, uiscale, 2, CVAR_ARCHIVE | CVAR_NOINITCALL)
{
if (StatusBar != NULL)
{
StatusBar->ScreenSizeChanged();
}
}
// [RH] Stretch values to make a 320x200 image best fit the screen
// without using fractional steppings
int CleanXfac, CleanYfac;
@ -75,7 +83,7 @@ int CleanXfac_1, CleanYfac_1, CleanWidth_1, CleanHeight_1;
// FillSimplePoly uses this
extern "C" short spanend[MAXHEIGHT];
CVAR (Bool, hud_scale, false, CVAR_ARCHIVE);
CVAR (Bool, hud_scale, true, CVAR_ARCHIVE);
// For routines that take RGB colors, cache the previous lookup in case there
// are several repetitions with the same color.

View file

@ -65,6 +65,7 @@
#include "menu/menu.h"
#include "r_data/voxels.h"
int active_con_scale();
FRenderer *Renderer;
@ -857,10 +858,20 @@ void DFrameBuffer::DrawRateStuff ()
int chars;
int rate_x;
int textScale = active_con_scale();
if (textScale == 0)
textScale = CleanXfac;
chars = mysnprintf (fpsbuff, countof(fpsbuff), "%2u ms (%3u fps)", howlong, LastCount);
rate_x = Width - ConFont->StringWidth(&fpsbuff[0]);
Clear (rate_x, 0, Width, ConFont->GetHeight(), GPalette.BlackIndex, 0);
DrawText (ConFont, CR_WHITE, rate_x, 0, (char *)&fpsbuff[0], TAG_DONE);
rate_x = Width / textScale - ConFont->StringWidth(&fpsbuff[0]);
Clear (rate_x * textScale, 0, Width, ConFont->GetHeight() * textScale, GPalette.BlackIndex, 0);
if (textScale == 1)
DrawText (ConFont, CR_WHITE, rate_x, 0, (char *)&fpsbuff[0], TAG_DONE);
else
DrawText (ConFont, CR_WHITE, rate_x, 0, (char *)&fpsbuff[0],
DTA_VirtualWidth, screen->GetWidth() / textScale,
DTA_VirtualHeight, screen->GetHeight() / textScale,
DTA_KeepRatio, true, TAG_DONE);
DWORD thisSec = ms/1000;
if (LastSec < thisSec)

View file

@ -522,4 +522,6 @@ inline bool Is54Aspect(int ratio) {
return ratio == 4;
}
EXTERN_CVAR(Int, uiscale);
#endif // __V_VIDEO_H__

View file

@ -1,27 +1,46 @@
#ifdef __APPLE__
#include <CoreServices/CoreServices.h>
#endif
/*
** i_specialpaths.cpp
** Gets special system folders where data should be stored. (Windows version)
**
**---------------------------------------------------------------------------
** Copyright 2013-2016 Randy Heit
** Copyright 2016 Christoph Oelckers
** All rights reserved.
**
** Redistribution and use in source and binary forms, with or without
** modification, are permitted provided that the following conditions
** are met:
**
** 1. Redistributions of source code must retain the above copyright
** notice, this list of conditions and the following disclaimer.
** 2. Redistributions in binary form must reproduce the above copyright
** notice, this list of conditions and the following disclaimer in the
** documentation and/or other materials provided with the distribution.
** 3. The name of the author may not be used to endorse or promote products
** derived from this software without specific prior written permission.
**
** THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
** IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
** OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
** IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
** INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
** NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
** THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
**---------------------------------------------------------------------------
**
*/
#ifdef _WIN32
#include <windows.h>
#include <lmcons.h>
#include <shlobj.h>
#define USE_WINDOWS_DWORD
#endif
#include "cmdlib.h"
#include "m_misc.h"
#if !defined(__APPLE__) && !defined(_WIN32)
#include <sys/stat.h>
#include <sys/types.h>
#include "i_system.h"
#endif
#include "version.h" // for GAMENAME
#if defined(_WIN32)
#include "i_system.h"
typedef HRESULT (WINAPI *GKFP)(REFKNOWNFOLDERID, DWORD, HANDLE, PWSTR *);
@ -323,314 +342,3 @@ FString M_GetSavegamesPath()
}
return path;
}
#elif defined(__APPLE__)
//===========================================================================
//
// M_GetCachePath Mac OS X
//
// Returns the path for cache GL nodes.
//
//===========================================================================
FString M_GetCachePath(bool create)
{
FString path;
char pathstr[PATH_MAX];
FSRef folder;
if (noErr == FSFindFolder(kUserDomain, kApplicationSupportFolderType, create ? kCreateFolder : 0, &folder) &&
noErr == FSRefMakePath(&folder, (UInt8*)pathstr, PATH_MAX))
{
path = pathstr;
}
else
{
path = progdir;
}
path += "/zdoom/cache";
return path;
}
//===========================================================================
//
// M_GetAutoexecPath Mac OS X
//
// Returns the expected location of autoexec.cfg.
//
//===========================================================================
FString M_GetAutoexecPath()
{
FString path;
char cpath[PATH_MAX];
FSRef folder;
if (noErr == FSFindFolder(kUserDomain, kDocumentsFolderType, kCreateFolder, &folder) &&
noErr == FSRefMakePath(&folder, (UInt8*)cpath, PATH_MAX))
{
path << cpath << "/" GAME_DIR "/autoexec.cfg";
}
return path;
}
//===========================================================================
//
// M_GetCajunPath Mac OS X
//
// Returns the location of the Cajun Bot definitions.
//
//===========================================================================
FString M_GetCajunPath(const char *botfilename)
{
FString path;
// Just copies the Windows code. Should this be more Mac-specific?
path << progdir << "zcajun/" << botfilename;
if (!FileExists(path))
{
path = "";
}
return path;
}
//===========================================================================
//
// M_GetConfigPath Mac OS X
//
// Returns the path to the config file. On Windows, this can vary for reading
// vs writing. i.e. If $PROGDIR/zdoom-<user>.ini does not exist, it will try
// to read from $PROGDIR/zdoom.ini, but it will never write to zdoom.ini.
//
//===========================================================================
FString M_GetConfigPath(bool for_reading)
{
char cpath[PATH_MAX];
FSRef folder;
if (noErr == FSFindFolder(kUserDomain, kPreferencesFolderType, kCreateFolder, &folder) &&
noErr == FSRefMakePath(&folder, (UInt8*)cpath, PATH_MAX))
{
FString path;
path << cpath << "/" GAMENAMELOWERCASE ".ini";
return path;
}
// Ungh.
return GAMENAMELOWERCASE ".ini";
}
//===========================================================================
//
// M_GetScreenshotsPath Mac OS X
//
// Returns the path to the default screenshots directory.
//
//===========================================================================
FString M_GetScreenshotsPath()
{
FString path;
char cpath[PATH_MAX];
FSRef folder;
if (noErr == FSFindFolder(kUserDomain, kDocumentsFolderType, kCreateFolder, &folder) &&
noErr == FSRefMakePath(&folder, (UInt8*)cpath, PATH_MAX))
{
path << cpath << "/" GAME_DIR "/Screenshots/";
}
else
{
path = "~/";
}
return path;
}
//===========================================================================
//
// M_GetSavegamesPath Mac OS X
//
// Returns the path to the default save games directory.
//
//===========================================================================
FString M_GetSavegamesPath()
{
FString path;
char cpath[PATH_MAX];
FSRef folder;
if (noErr == FSFindFolder(kUserDomain, kDocumentsFolderType, kCreateFolder, &folder) &&
noErr == FSRefMakePath(&folder, (UInt8*)cpath, PATH_MAX))
{
path << cpath << "/" GAME_DIR "/Savegames/";
}
return path;
}
#else // Linux, et al.
FString GetUserFile (const char *file)
{
FString path;
struct stat info;
path = NicePath("~/" GAME_DIR "/");
if (stat (path, &info) == -1)
{
struct stat extrainfo;
// Sanity check for ~/.config
FString configPath = NicePath("~/.config/");
if (stat (configPath, &extrainfo) == -1)
{
if (mkdir (configPath, S_IRUSR | S_IWUSR | S_IXUSR) == -1)
{
I_FatalError ("Failed to create ~/.config directory:\n%s", strerror(errno));
}
}
else if (!S_ISDIR(extrainfo.st_mode))
{
I_FatalError ("~/.config must be a directory");
}
// This can be removed after a release or two
// Transfer the old zdoom directory to the new location
bool moved = false;
FString oldpath = NicePath("~/." GAMENAMELOWERCASE "/");
if (stat (oldpath, &extrainfo) != -1)
{
if (rename(oldpath, path) == -1)
{
I_Error ("Failed to move old " GAMENAMELOWERCASE " directory (%s) to new location (%s).",
oldpath.GetChars(), path.GetChars());
}
else
moved = true;
}
if (!moved && mkdir (path, S_IRUSR | S_IWUSR | S_IXUSR) == -1)
{
I_FatalError ("Failed to create %s directory:\n%s",
path.GetChars(), strerror (errno));
}
}
else
{
if (!S_ISDIR(info.st_mode))
{
I_FatalError ("%s must be a directory", path.GetChars());
}
}
path += file;
return path;
}
//===========================================================================
//
// M_GetCachePath Unix
//
// Returns the path for cache GL nodes.
//
//===========================================================================
FString M_GetCachePath(bool create)
{
// Don't use GAME_DIR and such so that ZDoom and its child ports can
// share the node cache.
FString path = NicePath("~/.config/zdoom/cache");
if (create)
{
CreatePath(path);
}
return path;
}
//===========================================================================
//
// M_GetAutoexecPath Unix
//
// Returns the expected location of autoexec.cfg.
//
//===========================================================================
FString M_GetAutoexecPath()
{
return GetUserFile("autoexec.cfg");
}
//===========================================================================
//
// M_GetCajunPath Unix
//
// Returns the location of the Cajun Bot definitions.
//
//===========================================================================
FString M_GetCajunPath(const char *botfilename)
{
FString path;
// Check first in ~/.config/zdoom/botfilename.
path = GetUserFile(botfilename);
if (!FileExists(path))
{
// Then check in SHARE_DIR/botfilename.
path = SHARE_DIR;
path << botfilename;
if (!FileExists(path))
{
path = "";
}
}
return path;
}
//===========================================================================
//
// M_GetConfigPath Unix
//
// Returns the path to the config file. On Windows, this can vary for reading
// vs writing. i.e. If $PROGDIR/zdoom-<user>.ini does not exist, it will try
// to read from $PROGDIR/zdoom.ini, but it will never write to zdoom.ini.
//
//===========================================================================
FString M_GetConfigPath(bool for_reading)
{
return GetUserFile(GAMENAMELOWERCASE ".ini");
}
//===========================================================================
//
// M_GetScreenshotsPath Unix
//
// Returns the path to the default screenshots directory.
//
//===========================================================================
FString M_GetScreenshotsPath()
{
return NicePath("~/" GAME_DIR "/screenshots/");
}
//===========================================================================
//
// M_GetSavegamesPath Unix
//
// Returns the path to the default save games directory.
//
//===========================================================================
FString M_GetSavegamesPath()
{
return NicePath("~/" GAME_DIR);
}
#endif

View file

@ -1807,6 +1807,7 @@ DSPLYMNU_STILLBOB = "View bob amount while not moving";
HUDMNU_TITLE = "HUD Options";
HUDMNU_ALTHUD = "Alternative HUD";
HUDMNU_MESSAGE = "Message Options";
HUDMNU_UISCALE = "User interface scale";
HUDMNU_CROSSHAIR = "Default Crosshair";
HUDMNU_FORCECROSSHAIR = "Force default crosshair";
HUDMNU_GROWCROSSHAIR = "Grow crosshair when picking up items";
@ -1946,6 +1947,7 @@ MSGMNU_SHOWMESSAGES = "Show messages";
MSGMNU_SHOWOBITUARIES = "Show obituaries";
MSGMNU_SHOWSECRETS = "Show secret notifications";
MSGMNU_SCALETEXT = "Scale text in high res";
MSGMNU_SCALECONSOLE = "Scale console";
MSGMNU_MESSAGELEVEL = "Minimum message level";
MSGMNU_CENTERMESSAGES = "Center messages";
MSGMNU_MESSAGECOLORS = "Message Colors";
@ -2237,6 +2239,7 @@ OPTVAL_ANIMATED = "Animated";
OPTVAL_ROTATED = "Rotated";
OPTVAL_MAPDEFINEDCOLORSONLY = "Map defined colors only";
OPTVAL_DOUBLE = "Double";
OPTVAL_TRIPLE = "Triple";
OPTVAL_QUADRUPLE = "Quadruple";
OPTVAL_ITEMPICKUP = "Item Pickup";
OPTVAL_OBITUARIES = "Obituaries";
@ -2594,7 +2597,6 @@ GLTEXMNU_RESIZETEX = "Resize textures";
GLTEXMNU_RESIZESPR = "Resize sprites";
GLTEXMNU_RESIZEFNT = "Resize fonts";
GLTEXMNU_PRECACHETEX = "Precache GL textures";
GLTEXMNU_CAMTEXOFFSCR = "Camera textures offscreen";
GLTEXMNU_TRIMSPREDGE = "Trim sprite edges";
GLTEXMNU_SORTDRAWLIST = "Sort draw lists by texture";
@ -2605,9 +2607,6 @@ GLLIGHTMNU_LIGHTDEFS = "Enable light definitions";
GLLIGHTMNU_CLIPLIGHTS = "Clip lights";
GLLIGHTMNU_LIGHTSPRITES = "Lights affect sprites";
GLLIGHTMNU_LIGHTPARTICLES = "Lights affect particles";
GLLIGHTMNU_FORCEADDITIVE = "Force additive lighting";
GLLIGHTMNU_LIGHTINTENSITY = "Light intensity";
GLLIGHTMNU_LIGHTSIZE = "Light size";
GLLIGHTMNU_LIGHTMATH = "Light quality";
// OpenGL Preferences

View file

@ -768,6 +768,8 @@ OptionMenu "HUDOptions"
Submenu "$HUDMNU_ALTHUD", "AltHudOptions"
Submenu "$HUDMNU_MESSAGE", "MessageOptions"
StaticText " "
Slider "$HUDMNU_UISCALE", "uiscale", 0.0, 8.0, 1.0, 0
StaticText " "
Option "$HUDMNU_CROSSHAIR", "crosshair", "Crosshairs"
Option "$HUDMNU_FORCECROSSHAIR", "crosshairforce", "OnOff"
Option "$HUDMNU_GROWCROSSHAIR", "crosshairgrow", "OnOff"
@ -802,6 +804,7 @@ OptionValue "AMCoordinates"
OptionValue "AltHUDScale"
{
0, "$OPTVAL_OFF"
4, "$OPTVAL_ON"
1, "$OPTVAL_SCALETO640X400"
2, "$OPTVAL_PIXELDOUBLE"
3, "$OPTVAL_PIXELQUADRUPLE"
@ -1124,6 +1127,15 @@ OptionValue ScaleValues
3, "$OPTVAL_QUADRUPLE"
}
OptionValue ConsoleScaleValues
{
1, "$OPTVAL_OFF"
0, "$OPTVAL_ON"
2, "$OPTVAL_DOUBLE"
3, "$OPTVAL_TRIPLE"
4, "$OPTVAL_QUADRUPLE"
}
OptionValue MessageLevels
{
0.0, "$OPTVAL_ITEMPICKUP"
@ -1147,6 +1159,7 @@ OptionMenu MessageOptions
Option "$MSGMNU_SHOWOBITUARIES", "show_obituaries", "OnOff"
Option "$MSGMNU_SHOWSECRETS", "cl_showsecretmessage", "OnOff"
Option "$MSGMNU_SCALETEXT", "con_scaletext", "ScaleValues"
Option "$MSGMNU_SCALECONSOLE", "con_scale", "ConsoleScaleValues"
Option "$MSGMNU_MESSAGELEVEL", "msg", "MessageLevels"
Option "$MSGMNU_DEVELOPER", "developer", "DevMessageLevels"
Option "$MSGMNU_CENTERMESSAGES", "con_centernotify", "OnOff"

View file

@ -141,6 +141,12 @@ OptionValue "HqResizeModes"
7, "$OPTVAL_HQ2XMMX"
8, "$OPTVAL_HQ3XMMX"
9, "$OPTVAL_HQ4XMMX"
10, "xBRZ 2x"
11, "xBRZ 3x"
12, "xBRZ 4x"
13, "xBRZ_old 2x"
14, "xBRZ_old 3x"
15, "xBRZ_old 4x"
}
OptionValue "FogMode"
@ -186,7 +192,6 @@ OptionMenu "GLTextureGLOptions"
Option "$GLTEXMNU_RESIZESPR", gl_texture_hqresize_sprites, "OnOff"
Option "$GLTEXMNU_RESIZEFNT", gl_texture_hqresize_fonts, "OnOff"
Option "$GLTEXMNU_PRECACHETEX", gl_precache, "YesNo"
Option "$GLTEXMNU_CAMTEXOFFSCR", gl_usefb, "OnOff"
Option "$GLTEXMNU_TRIMSPREDGE", gl_trimsprites, "OnOff"
Option "$GLTEXMNU_SORTDRAWLIST", gl_sort_textures, "YesNo"
}
@ -199,10 +204,7 @@ OptionMenu "GLLightOptions"
Option "$GLLIGHTMNU_CLIPLIGHTS", gl_lights_checkside, "YesNo"
Option "$GLLIGHTMNU_LIGHTSPRITES", gl_light_sprites, "YesNo"
Option "$GLLIGHTMNU_LIGHTPARTICLES", gl_light_particles, "YesNo"
Option "$GLLIGHTMNU_FORCEADDITIVE", gl_lights_additive, "YesNo"
Option "$GLLIGHTMNU_LIGHTMATH", gl_light_math, "LightMathModes"
Slider "$GLLIGHTMNU_LIGHTINTENSITY", gl_lights_intensity, 0.0, 1.0, 0.1
Slider "$GLLIGHTMNU_LIGHTSIZE", gl_lights_size, 0.0, 2.0, 0.1
}
OptionMenu "GLPrefOptions"

View file

@ -69,15 +69,15 @@ uniform sampler2D PaletteLUT;
vec3 Tonemap(vec3 color)
{
ivec3 c = ivec3(clamp(color.rgb, vec3(0.0), vec3(1.0)) * 255.0 + 0.5);
int index = ((c.r >> 2) * 64 + (c.g >> 2)) * 64 + (c.b >> 2);
ivec3 c = ivec3(clamp(color.rgb, vec3(0.0), vec3(1.0)) * 63.0 + 0.5);
int index = (c.r * 64 + c.g) * 64 + c.b;
int tx = index % 512;
int ty = index / 512;
return texelFetch(PaletteLUT, ivec2(tx, ty), 0).rgb;
}
#else
#error "Tonemap mode define is missing"
#error Tonemap mode define is missing
#endif
void main()