Lazy GLSL loading, for faster load times.

Fixed some xim issues, for proper keyboard input under x11.
Cmake project can now work for cross compiling win32 targets.
Some other fun-but-pointless stuff.



git-svn-id: https://svn.code.sf.net/p/fteqw/code/trunk@5344 fc73d0e0-1445-4013-8a0c-d673dee63da5
master
Spoike 5 years ago
parent 79689474b6
commit 5b4756f3d9

@ -64,6 +64,16 @@ IF(NOT ZLIB_FOUND)
SET(ZLIB_LIBRARIES )
ENDIF()
FIND_PACKAGE(BZip2)
IF(BZIP2_FOUND)
SET(FTE_LIB_DEFINES ${FTE_LIB_DEFINES};AVAIL_BZLIB)
SET(FTE_LIBS ${FTE_LIBS} bz2)
SET(FTESV_LIBS ${FTESV_LIBS} bz2)
MESSAGE(STATUS "bzip2 library found. bz2-compressed pk3s will work for the price of extra bloat! yay!")
ELSE()
MESSAGE(WARNING "bzip2 library NOT available. bz2-compressed pk3s will not be available, as if anyone cares.")
ENDIF()
SET(OpenGL_GL_PREFERENCE LEGACY)
FIND_PACKAGE(OpenGL)
IF(OpenGL_FOUND)
@ -93,14 +103,13 @@ ELSE()
SET(FTE_LIB_DEFINES ${FTE_LIB_DEFINES};NO_FREETYPE)
ENDIF()
#FIND_PACKAGE(Vulkan)
#IF(Vulkan_FOUND)
# INCLUDE_DIRECTORIES( ${Vulkan_INCLUDE_DIRS} )
SET(FTE_DEFINES ${FTE_DEFINES};VKQUAKE)
#ELSE()
# SET(FTE_DEFINES ${FTE_DEFINES};VKQUAKE)
# MESSAGE(WARNING "System vulkan headers NOT available.")
#ENDIF()
FIND_PATH(VULKAN_INCLUDE_DIR vulkan/vulkan.h)
IF(VULKAN_INCLUDE_DIR)
INCLUDE_DIRECTORIES( ${VULKAN_INCLUDE_DIR} )
SET(FTE_DEFINES ${FTE_DEFINES};VKQUAKE) #no libs required, thankfully
ELSE()
MESSAGE(WARNING "Vulkan headers NOT available.")
ENDIF()
FIND_LIBRARY(VORBISFILE_LIBRARY NAMES vorbisfile)
IF(NOT VORBISFILE_LIBRARY)
@ -132,7 +141,7 @@ IF(${ANDROID})
# INCLUDE_DIRECTORIES( ${FREETYPE_INCLUDE_DIRS} )
SET(FTE_DEFINES ${FTE_DEFINES};ANDROID;VKQUAKE;DYNAMIC_LIBPNG;DYNAMIC_LIBJPEG;MULTITHREAD;stricmp=strcasecmp;strnicmp=strncasecmp)
SET(FTE_LIBS android log EGL ${ZLIB_LIBRARIES} m ${CMAKE_DL_LIBS})
SET(FTE_LIBS ${FTE_LIBS} android log EGL ${ZLIB_LIBRARIES} m ${CMAKE_DL_LIBS})
SET(FTE_ARCH_FILES
engine/client/sys_droid.c
engine/common/sys_linux_threads.c
@ -146,7 +155,7 @@ ELSEIF(${WIN32})
# engine/server/sv_sys_win.c
SET(FTE_LIBS ${ZLIB_LIBRARIES} ole32 gdi32 wsock32 winmm dxguid)
SET(FTE_LIBS ${FTE_LIBS} ${ZLIB_LIBRARIES} ole32 gdi32 wsock32 winmm dxguid)
SET(FTE_DEFINES ${FTE_DEFINES};D3D9QUAKE;D3D11QUAKE;DYNAMIC_LIBPNG;DYNAMIC_LIBJPEG)
SET(FTE_ARCH_FILES
engine/client/winquake.rc
@ -177,7 +186,7 @@ ELSEIF(${WIN32})
engine/d3d/vid_d3d8.c
)
SET(FTESV_LIBS ${ZLIB_LIBRARIES} wsock32 winmm)
SET(FTESV_LIBS ${FTESV_LIBS} ${ZLIB_LIBRARIES} wsock32 winmm)
SET(FTESV_ARCH_FILES
engine/client/winquake.rc
engine/common/sys_win_threads.c
@ -213,7 +222,7 @@ ELSEIF(${UNIX}) #linux(ish)
ENDIF()
SET(FTE_DEFINES ${FTE_DEFINES};DYNAMIC_LIBPNG;DYNAMIC_LIBJPEG;DYNAMIC_SDL;MULTITHREAD;stricmp=strcasecmp;strnicmp=strncasecmp)
SET(FTE_LIBS ${ZLIB_LIBRARIES} m ${CMAKE_DL_LIBS} pthread ${SDL2_LIBRARIES})
SET(FTE_LIBS ${FTE_LIBS} ${ZLIB_LIBRARIES} m ${CMAKE_DL_LIBS} pthread ${SDL2_LIBRARIES})
SET(FTE_ARCH_FILES
engine/client/sys_linux.c
engine/common/sys_linux_threads.c
@ -267,7 +276,7 @@ ELSEIF(${UNIX}) #linux(ish)
engine/common/net_ssl_gnutls.c
# engine/common/net_ssl_openssl.c
)
SET(FTESV_LIBS ${ZLIB_LIBRARIES} m ${CMAKE_DL_LIBS} pthread)
SET(FTESV_LIBS ${FTESV_LIBS} ${ZLIB_LIBRARIES} m ${CMAKE_DL_LIBS} pthread)
# SET(FTE_DEFINES ${FTE_DEFINES};HAVE_OPENSSL)
# SET(FTESV_DEFINES ${FTESV_DEFINES};HAVE_OPENSSL)
@ -286,7 +295,7 @@ ELSEIF(1) #SDL
#SDL2.0.7 supports vulkan, so lets use it.
SET(FTE_DEFINES ${FTE_DEFINES};FTE_SDL;DYNAMIC_LIBPNG;DYNAMIC_LIBJPEG;stricmp=strcasecmp;strnicmp=strncasecmp)
SET(FTE_LIBS ${ZLIB_LIBRARIES} m ${CMAKE_DL_LIBS} ${SDL2_LIBRARIES})
SET(FTE_LIBS ${FTE_LIBS} ${ZLIB_LIBRARIES} m ${CMAKE_DL_LIBS} ${SDL2_LIBRARIES})
SET(FTE_ARCH_FILES
engine/client/sys_sdl.c
engine/client/snd_al.c
@ -297,7 +306,7 @@ ELSEIF(1) #SDL
)
SET(FTESV_DEFINES FTE_SDL;stricmp=strcasecmp;strnicmp=strncasecmp)
SET(FTESV_LIBS ${ZLIB_LIBRARIES} m ${CMAKE_DL_LIBS} ${SDL2_LIBRARIES})
SET(FTESV_LIBS ${FTESV_LIBS} ${ZLIB_LIBRARIES} m ${CMAKE_DL_LIBS} ${SDL2_LIBRARIES})
IF(WIN32)
SET(FTE_LIBS ${FTE_LIBS} wsock32 gdi32 ole32)
@ -375,6 +384,7 @@ SET(FTE_COMMON_FILES
engine/common/fs_stdio.c
engine/common/fs_xz.c
engine/common/fs_zip.c
engine/common/fs_vpk.c
engine/common/gl_q2bsp.c
engine/common/huff.c
engine/common/log.c
@ -394,6 +404,11 @@ SET(FTE_COMMON_FILES
engine/common/sha1.c
engine/common/translate.c
engine/common/zone.c
engine/common/config_fteqw.h
engine/common/config_minimal.h
engine/common/config_nocompat.h
engine/common/config_wastes.h
#sigh
engine/client/pr_skelobj.c
@ -542,6 +557,31 @@ SET(FTE_CLIENT_FILES
engine/vk/vk_init.c
)
FILE(STRINGS "${FTE_BUILD_CONFIG}" BULLET_INTERNAL REGEX "^#define[\t ]+USE_INTERNAL_BULLET")
IF(BULLET_INTERNAL)
#Built-in bullet physics plugin...
FIND_PACKAGE(Bullet REQUIRED)
SET(FTE_COMMON_FILES ${FTE_COMMON_FILES} plugins/bullet/bulletplug.cpp)
INCLUDE_DIRECTORIES( ${BULLET_INCLUDE_DIRS} )
SET(FTE_LIBS ${FTE_LIBS} ${BULLET_LIBRARIES})
SET(FTESV_LIBS ${FTESV_LIBS} ${BULLET_LIBRARIES})
ELSE()
#Bullet Physics library plugin
FIND_PACKAGE(Bullet)
IF (BULLET_FOUND)
ADD_LIBRARY(bullet MODULE
plugins/qvm_api.c
plugins/plugin.c
plugins/bullet/bulletplug.cpp
)
TARGET_INCLUDE_DIRECTORIES(bullet PUBLIC ${BULLET_INCLUDE_DIRS})
SET_TARGET_PROPERTIES(bullet PROPERTIES COMPILE_DEFINITIONS "FTEPLUGIN")
SET_TARGET_PROPERTIES(bullet PROPERTIES PREFIX "fteplug_")
SET_TARGET_PROPERTIES(bullet PROPERTIES LINK_FLAGS "-Wl,--no-undefined")
TARGET_LINK_LIBRARIES(bullet m ${BULLET_LIBRARIES})
ENDIF()
ENDIF()
IF(ANDROID)
#android sucks. everything is a library. so we build the engine as a shared library and completely ignore dedicated servers+tools
ADD_LIBRARY(ftedroid MODULE
@ -581,6 +621,9 @@ ELSE()
engine/http/ftpserver.c
)
SET_TARGET_PROPERTIES(httpserver PROPERTIES COMPILE_DEFINITIONS "WEBSERVER;WEBSVONLY;${FTE_REVISON};stricmp=strcasecmp;strnicmp=strncasecmp")
IF(WIN32)
TARGET_LINK_LIBRARIES(httpserver ${ZLIB_LIBRARIES} ws2_32)
ENDIF()
ADD_EXECUTABLE(fteqcc
engine/qclib/qcctui.c
@ -626,31 +669,24 @@ ADD_LIBRARY(qi MODULE
)
SET_TARGET_PROPERTIES(qi PROPERTIES COMPILE_DEFINITIONS "FTEPLUGIN;${FTE_LIB_DEFINES}")
SET_TARGET_PROPERTIES(qi PROPERTIES PREFIX "fteplug_")
#Bullet Physics library plugin
#FIND_PACKAGE(Bullet)
IF (BULLET_FOUND)
ADD_LIBRARY(bullet MODULE
plugins/qvm_api.c
plugins/plugin.c
plugins/bullet/bulletplug.cpp
)
TARGET_INCLUDE_DIRECTORIES(bullet PUBLIC ${BULLET_INCLUDE_DIRS})
SET_TARGET_PROPERTIES(bullet PROPERTIES COMPILE_DEFINITIONS "FTEPLUGIN")
SET_TARGET_PROPERTIES(bullet PROPERTIES PREFIX "fteplug_")
ENDIF()
SET_TARGET_PROPERTIES(qi PROPERTIES LINK_FLAGS "-Wl,--no-undefined")
TARGET_LINK_LIBRARIES(qi m)
#ODE Physics library plugin
#FIND_PACKAGE(ode)
IF (ODE_FOUND)
FIND_PATH(LIBODE_INCLUDE_DIR ode/ode.h)
FIND_LIBRARY(LIBODE_LIBRARY ode)
IF (LIBODE_INCLUDE_DIR)
ADD_LIBRARY(ode MODULE
plugins/qvm_api.c
plugins/plugin.c
engine/common/com_phys_ode.c
engine/common/mathlib.c
)
TARGET_INCLUDE_DIRECTORIES(ode PUBLIC ${ODE_INCLUDE_DIRS})
SET_TARGET_PROPERTIES(ode PROPERTIES COMPILE_DEFINITIONS "FTEPLUGIN;ODE_STATIC")
SET_TARGET_PROPERTIES(ode PROPERTIES PREFIX "fteplug_")
SET_TARGET_PROPERTIES(ode PROPERTIES LINK_FLAGS "-Wl,--no-undefined")
TARGET_LINK_LIBRARIES(ode m ${LIBODE_LIBRARY})
ENDIF()
#EzQuake Hud port plugin
@ -664,6 +700,8 @@ ADD_LIBRARY(ezhud MODULE
)
SET_TARGET_PROPERTIES(ezhud PROPERTIES COMPILE_DEFINITIONS "FTEPLUGIN;${FTE_LIB_DEFINES}")
SET_TARGET_PROPERTIES(ezhud PROPERTIES PREFIX "fteplug_")
SET_TARGET_PROPERTIES(ezhud PROPERTIES LINK_FLAGS "-Wl,--no-undefined")
TARGET_LINK_LIBRARIES(ezhud m)
#IRC client plugin
ADD_LIBRARY(irc MODULE
@ -673,6 +711,8 @@ ADD_LIBRARY(irc MODULE
)
SET_TARGET_PROPERTIES(irc PROPERTIES COMPILE_DEFINITIONS "FTEPLUGIN;${FTE_LIB_DEFINES}")
SET_TARGET_PROPERTIES(irc PROPERTIES PREFIX "fteplug_")
SET_TARGET_PROPERTIES(irc PROPERTIES LINK_FLAGS "-Wl,--no-undefined")
TARGET_LINK_LIBRARIES(irc m)
#ffmpeg client plugin. no proper way to detect dependancies right now, so I've gotta try the manual way.
FIND_PATH(AVCODEC_INCLUDE_DIR libavcodec/avcodec.h)
@ -715,6 +755,11 @@ IF(NOT ANDROID)
)
SET_TARGET_PROPERTIES(xmpp PROPERTIES COMPILE_DEFINITIONS "FTEPLUGIN;${FTE_LIB_DEFINES}")
SET_TARGET_PROPERTIES(xmpp PROPERTIES PREFIX "fteplug_")
SET_TARGET_PROPERTIES(xmpp PROPERTIES LINK_FLAGS "-Wl,--no-undefined")
IF(${WIN32})
ELSE()
TARGET_LINK_LIBRARIES(xmpp m resolv)
ENDIF()
ENDIF()
#cef plugin

@ -0,0 +1,59 @@
#!/bin/sh
#this script is DANGEROUS
#be sure to have committed *BEFORE* running this script.
#Note: This script does not understand dead files (including botlib).
#expect '-Wmisleading-indentation' warnings (that were previously muted by nearby ifdefs).
#DO NOT COMMIT THE RESULTS TO FTE'S TRUNK
CONFIG=wastes
#must have trailing slashes
SRCDIR=./
NEWDIR=/tmp/fte-$CONFIG/
echo "WARNING: This script will lock-in a build config upon your C files."
echo "The resulting files will support only your choice of feature set, instead of having lots of unused code mixed in."
echo "THIS IS DESTRUCTIVE SO MUST ONLY BE USED FOR FORKS."
read -p "Press name the build config (or ctrl+c to abort)" CONFIG
if [ "$foo" == "" ]; then
echo "no config specified."
exit 1
fi
mkdir -p $NEWDIR
cat $SRCDIR/engine/common/config_$CONFIG.h | grep "#define" | sed "s/\/\/#define/#undef/g" > $NEWDIR/unifdefrules
cat $SRCDIR/engine/common/config_$CONFIG.h | grep "#undef" >> $NEWDIR/unifdefrules
if [ "$SRCDIR" != "$NEWDIR" ]; then
echo "Copying files to strip to $NEWDIR."
cp -r $SRCDIR* $NEWDIR
else
echo "WARNING: WRITING FILES IN PLACE MUST ONLY BE USED FOR FORKS."
read -p "Press y<enter> to confirm (or ctrl+c to abort)" foo
if [ "$foo" != "y" ]; then
exit 1
fi
fi
cd $NEWDIR
for FILENAME in engine/*/*.c; do
unifdef -f unifdefrules -m $FILENAME
done
#headers keep any defines that will be expanded in code.
cat $NEWDIR/unifdefrules | grep -v FULLENGINENAME | grep -v DISTRIBUTION | grep -v ENGINEWEBSITE | grep -v MAX_SPLITS | grep GAME_SHORTNAME > $NEWDIR/unifdefhrules
for FILENAME in engine/*/*.h; do
unifdef -f unifdefhrules -m $FILENAME
done
rm $NEWDIR/unifdefrules
echo "Files in $NEWDIR have now been stripped down."
echo "Some things may require hand-editing to remove warnings (or just compile with CFLAGS=-Wno-misleading-indentation)."
echo "You still need to set FTE_CONFIG too."
read -p "Press enter to test-compile" foo
cd $NEWDIR/engine && make sv-rel m-rel -j8 FTE_CONFIG=$CONFIG -k

@ -382,11 +382,13 @@ void CL_MakeActive(char *gamename)
//kill models left over from the last map.
Mod_Purge(MP_MAPCHANGED);
Image_Purge();
//and reload shaders now if needed (this was blocked earlier)
Shader_DoReload();
//and now free any textures that were not still needed.
Image_Purge();
SCR_EndLoadingPlaque();
CL_UpdateWindowTitle();
@ -5911,6 +5913,7 @@ double Host_Frame (double time)
{
RSpeedMark();
vid.ime_allow = false;
if (SCR_UpdateScreen())
fps_count++;
if (R2D_Flush)

@ -1638,9 +1638,9 @@ void SCR_SizeDown_f (void)
//============================================================================
void SCR_StringXY(char *str, float x, float y)
void SCR_StringXY(const char *str, float x, float y)
{
char *s2;
const char *s2;
int px, py;
unsigned int codepoint;
int error;
@ -3448,6 +3448,7 @@ void SCR_DeInit (void)
Cmd_RemoveCommand ("screenshot_mega");
Cmd_RemoveCommand ("screenshot_stereo");
Cmd_RemoveCommand ("screenshot_vr");
Cmd_RemoveCommand ("screenshot_360");
Cmd_RemoveCommand ("screenshot_cubemap");
Cmd_RemoveCommand ("envmap");
Cmd_RemoveCommand ("sizeup");

@ -1339,6 +1339,20 @@ DRAWING
==============================================================================
*/
qboolean COM_InsertIME(conchar_t *buffer, size_t buffersize, conchar_t **cursor, conchar_t **textend)
{
conchar_t *in = vid.ime_preview;
if (in && *in && *textend+vid.ime_previewlen < buffer+buffersize)
{
memmove(buffer + (*cursor-buffer) + vid.ime_previewlen, *cursor, ((*textend-*cursor)+1)*sizeof(conchar_t));
memcpy(buffer + (*cursor-buffer), in, vid.ime_previewlen*sizeof(conchar_t));
*cursor += vid.ime_caret;
*textend += vid.ime_previewlen;
return true;
}
return false;
}
/*
================
@ -1364,9 +1378,18 @@ int Con_DrawInput (console_t *con, qboolean focused, int left, int right, int y,
size_t textsize;
qboolean cursorframe;
unsigned int codeflags, codepoint;
int cursorpos;
qboolean hidecomplete;
int x;
if (focused)
{
vid.ime_allow = true;
vid.ime_position[0] = ((float)left/vid.pixelwidth)*vid.width;
vid.ime_position[1] = ((float)y/vid.pixelheight)*vid.height;
}
if (!con->linebuffered || con->linebuffered == Con_Navigate)
{
if (con->footerline)
@ -1383,6 +1406,8 @@ int Con_DrawInput (console_t *con, qboolean focused, int left, int right, int y,
text = key_lines[edit_line];
cursorpos = key_linepos;
//copy it to an alternate buffer and fill in text colouration escape codes.
//if it's recognised as a command, colour it yellow.
//if it's not a command, and the cursor is at the end of the line, leave it as is,
@ -1390,13 +1415,24 @@ int Con_DrawInput (console_t *con, qboolean focused, int left, int right, int y,
textstart = COM_ParseFunString(CON_WHITEMASK, con->prompt, maskedtext, sizeof(maskedtext) - sizeof(maskedtext[0]), PFS_FORCEUTF8);
textsize = (countof(maskedtext) - (textstart-maskedtext) - 1) * sizeof(maskedtext[0]);
i = text[key_linepos];
text[key_linepos] = 0;
i = text[cursorpos];
text[cursorpos] = 0;
cursor = COM_ParseFunString(CON_WHITEMASK, text, textstart, textsize, PFS_KEEPMARKUP | PFS_FORCEUTF8);
text[key_linepos] = i;
//okay, so that's where the cursor is. heal the input string and reparse (so we don't mess up escapes)
text[cursorpos] = i;
endmtext = COM_ParseFunString(CON_WHITEMASK, text, textstart, textsize, PFS_KEEPMARKUP | PFS_FORCEUTF8);
// endmtext = COM_ParseFunString(CON_WHITEMASK, text+key_linepos, cursor, ((char*)maskedtext)+sizeof(maskedtext) - (char*)(cursor+1), PFS_KEEPMARKUP | PFS_FORCEUTF8);
hidecomplete = COM_InsertIME(maskedtext, countof(maskedtext), &cursor, &endmtext);
/* if (cursorpos == strlen(text) && vid.ime_preview)
{
endmtext = COM_ParseFunString(COLOR_MAGENTA<<CON_FGSHIFT, vid.ime_preview, endmtext, (countof(maskedtext) - (endmtext-maskedtext) - 1) * sizeof(maskedtext[0]), PFS_KEEPMARKUP | PFS_FORCEUTF8);
cursor += strlen(vid.ime_preview);
cursorpos += strlen(vid.ime_preview);
text = va("%s%s", text, vid.ime_preview);
}
*/
if ((char*)endmtext == (char*)(maskedtext-2) + sizeof(maskedtext))
endmtext[-1] = CON_WHITEMASK | '+' | CON_NONCLEARBG;
endmtext[1] = 0;
@ -1432,7 +1468,7 @@ int Con_DrawInput (console_t *con, qboolean focused, int left, int right, int y,
i = 0;
x = left;
if (con->commandcompletion && con_showcompletion.ival && text[0] && !(text[0] == '/' && !text[1]))
if (!hidecomplete && con->commandcompletion && con_showcompletion.ival && text[0] && !(text[0] == '/' && !text[1]))
{
if (cl_chatmode.ival && (text[0] == '/' || (cl_chatmode.ival == 2 && Cmd_IsCommand(text))))
{ //color the first token yellow, it's a valid command
@ -1447,10 +1483,10 @@ int Con_DrawInput (console_t *con, qboolean focused, int left, int right, int y,
fname = Cmd_CompleteCommand(text+cmdstart, true, true, max(1, con_commandmatch), NULL);
if (fname && strlen(fname) < 256) //we can compleate it to:
{
for (p = min(strlen(fname), key_linepos-cmdstart); fname[p]>0; p++)
for (p = min(strlen(fname), cursorpos-cmdstart); fname[p]>0; p++)
textstart[p+cmdstart] = (unsigned int)fname[p] | (COLOR_GREEN<<CON_FGSHIFT);
if (p < key_linepos-cmdstart)
p = key_linepos-cmdstart;
if (p < cursorpos-cmdstart)
p = cursorpos-cmdstart;
p = min(p+cmdstart, sizeof(maskedtext)/sizeof(maskedtext[0]) - 3);
textstart[p] = 0;
textstart[p+1] = 0;
@ -1742,7 +1778,8 @@ void Con_DrawNotify (void)
conchar_t *ends[8];
conchar_t markup[MAXCMDLINE+64];
conchar_t *c, *end;
char *foo = va(chat_team?"say_team: %s":"say: %s", chat_buffer?(char*)chat_buffer:"");
char demoji[8192];
char *foo = va(chat_team?"say_team: %s":"say: %s", Key_Demoji(demoji, sizeof(demoji), chat_buffer?(char*)chat_buffer:""));
int lines, i, pos;
Font_BeginString(font_console, 0, 0, &x, &y);
y = con_numnotifylines.ival * Font_CharHeight();
@ -1767,7 +1804,7 @@ void Con_DrawNotify (void)
if (c == end)
end++;
lines = Font_LineBreaks(markup, end, Font_ScreenWidth(), 8, starts, ends);
lines = Font_LineBreaks(markup, end, Font_ScreenWidth(), countof(starts), starts, ends);
for (i = 0; i < lines; i++)
{
x = 0;
@ -1775,6 +1812,10 @@ void Con_DrawNotify (void)
y += Font_CharHeight();
}
Font_EndString(font_console);
vid.ime_allow = true;
vid.ime_position[0] = 0;
vid.ime_position[1] = y;
}
}
@ -2105,7 +2146,7 @@ static int Con_DrawConsoleLines(console_t *con, conline_t *l, int sx, int ex, in
}
}
*/
if (seley < selsy)
if (seley <= selsy)
{ //selection goes upwards
x = selsy;
selsy = seley;
@ -2745,7 +2786,7 @@ void Con_DrawConsole (int lines, qboolean noback)
char *mouseover;
if (!mouseconsole->mouseover || !mouseconsole->mouseover(mouseconsole, &tiptext, &shader))
{
mouseover = Con_CopyConsole(mouseconsole, false, true);
mouseover = Con_CopyConsole(mouseconsole, false, true, true);
if (mouseover)
{
char *end = strstr(mouseover, "^]");
@ -3131,7 +3172,7 @@ void Con_ExpandConsoleSelection(console_t *con)
con->selstartoffset = cur-(conchar_t*)(l+1);
}
char *Con_CopyConsole(console_t *con, qboolean nomarkup, qboolean onlyiflink)
char *Con_CopyConsole(console_t *con, qboolean nomarkup, qboolean onlyiflink, qboolean forceutf8)
{
conchar_t *cur;
conline_t *l;
@ -3229,7 +3270,7 @@ char *Con_CopyConsole(console_t *con, qboolean nomarkup, qboolean onlyiflink)
else
lend = (conchar_t*)(l+1) + l->length;
outlen = COM_DeFunString(cur, lend, result + outlen, maxlen - outlen, nomarkup, !!(con->parseflags & PFS_FORCEUTF8)) - result;
outlen = COM_DeFunString(cur, lend, result + outlen, maxlen - outlen, nomarkup, forceutf8||!!(con->parseflags & PFS_FORCEUTF8)) - result;
if (l == con->selendline)
break;

@ -146,7 +146,7 @@ static void Stats_OwnFrag(char *name)
void VARGS Stats_Message(char *msg, ...);
qboolean Stats_TrackerImageLoaded(char *in)
qboolean Stats_TrackerImageLoaded(const char *in)
{
int error;
if (in)

@ -4030,6 +4030,190 @@ static struct pendingtextureinfo *Image_ReadBLPFile(unsigned int flags, const ch
}
#endif
#ifdef IMAGEFMT_VTF
//many of these look like dupes, not really sure how they're meant to work. probably legacy.
typedef enum {
VMF_INVALID=-1,
// VMF_RGBA8=0,
// VMF_ABGR8=1,
VMF_RGB8=2,
VMF_BGR8=3,
// VMF_RGB565=4,
// VMF_I8=5,
// VMF_IA8=6,
// VMF_P8=7,
// VMF_A8=8,
// VMF_RGB8_BS=9,
// VMF_BGR8_BS=10,
// VMF_ARGB_BS=11,
VMF_BGRA8=12,
VMF_BC1=13,
VMF_BC2=14,
VMF_BC3=15,
VMF_BGRX8=16,
// VMF_BGR565=17,
// VMF_BGRX5551=18,
// VMF_BGRA4444=19,
VMF_BC1A=20,
// VMF_BGRA5551=21,
VMF_UV88=22,
// VMF_UVWQ8=23,
VMF_RGBA16F=24,
// VMF_RGBA16N=25,
// VMF_UVLX8=26,
VMF_MAX
} fmtfmt_t;
static uploadfmt_t ImageVTF_VtfToFTE(fmtfmt_t f)
{
switch(f)
{
case VMF_BC1:
return PTI_BC1_RGB;
case VMF_BC1A:
return PTI_BC1_RGBA;
case VMF_BC2:
return PTI_BC2_RGBA;
case VMF_BC3:
return PTI_BC3_RGBA;
case VMF_RGB8:
return PTI_RGB8;
case VMF_BGR8:
return PTI_BGR8;
case VMF_BGRA8:
return PTI_BGRA8;
case VMF_BGRX8:
return PTI_BGRX8;
case VMF_RGBA16F:
return PTI_RGBA16F;
case VMF_UV88:
return PTI_RG8;
case VMF_INVALID:
return PTI_INVALID;
default:
return PTI_INVALID;
}
}
static struct pendingtextureinfo *Image_ReadVTFFile(unsigned int flags, const char *fname, qbyte *filedata, size_t filesize)
{
//FIXME: cba with endian.
struct vtf_s
{
char magic[4];
unsigned int major,minor;
unsigned int headersize;
unsigned short width, height;
unsigned int flags;
unsigned short numframes, firstframe;
unsigned int pad1;
vec3_t reflectivity;
float pad2;
float bumpmapscale;
unsigned int imgformat;
unsigned char mipmapcount;
unsigned char lowresfmt_misaligned[4];
unsigned char lowreswidth;
unsigned char lowresheight;
//7.2
unsigned char depth_misaligned[2];
//7.3
unsigned char pad3[3];
unsigned int numresources;
} *vtf;
fmtfmt_t vmffmt, lrfmt;
unsigned int bw, bh, bb;
qbyte *end = filedata + filesize;
unsigned int face, faces, frame, frames, miplevel, miplevels, img;
unsigned int w, h;
size_t datasize;
unsigned int version;
struct pendingtextureinfo *mips;
vtf = (void*)filedata;
if (memcmp(vtf->magic, "VTF\0", 4))
return NULL;
version = (vtf->major<<16)|vtf->minor;
if (version >= 0x00070003)
return NULL; //we don't support the whole resources thing.
lrfmt = (vtf->lowresfmt_misaligned[0]<<0)|(vtf->lowresfmt_misaligned[1]<<16)|(vtf->lowresfmt_misaligned[2]<<16)|(vtf->lowresfmt_misaligned[3]<<24);
vmffmt = vtf->imgformat;
if (vtf->lowreswidth && vtf->lowresheight)
Image_BlockSizeForEncoding(ImageVTF_VtfToFTE(lrfmt), &bb, &bw, &bh);
else
bb=bw=bh=1;
datasize = ((vtf->lowreswidth+bw-1)/bw) * ((vtf->lowresheight+bh-1)/bh) * bb;
mips = Z_Malloc(sizeof(*mips));
mips->type = (vtf->flags & 0x4000)?PTI_CUBEMAP:PTI_2D;
mips->extrafree = filedata;
filedata += vtf->headersize; //skip the header
filedata += datasize; //and skip the low-res image too.
mips->encoding = ImageVTF_VtfToFTE(vmffmt);
Image_BlockSizeForEncoding(mips->encoding, &bb, &bw, &bh);
miplevels = vtf->mipmapcount;
frames = 1;//vtf->numframes;
faces = ((mips->type==PTI_CUBEMAP)?6:1); //no cubemaps yet.
mips->mipcount = miplevels * frames * faces;
while (mips->mipcount > countof(mips->mip))
{
if (miplevels > 1)
miplevels--;
else
frames--;
mips->mipcount = miplevels * frames * faces;
}
if (!mips->mipcount)
{
Z_Free(mips);
return NULL;
}
for (miplevel = vtf->mipmapcount; miplevel-- > 0;)
{ //smallest to largest, which is awkward.
w = vtf->width>>miplevel;
h = vtf->height>>miplevel;
if (!w)
w = 1;
if (!h)
h = 1;
datasize = ((w+bw-1)/bw) * ((h+bh-1)/bh) * bb;
for (frame = 0; frame < vtf->numframes; frame++)
{
for (face = 0; face < faces; face++)
{
if (miplevel < miplevels && face < faces)
{
img = face+miplevel*faces + frame*miplevels*faces;
if (img >= countof(mips->mip))
break; //erk?
if (filedata + datasize > end)
break; //no more data here...
mips->mip[img].width = w;
mips->mip[img].height = h;
mips->mip[img].depth = 1;
mips->mip[img].data = filedata;
mips->mip[img].datasize = datasize;
}
filedata += datasize;
}
}
}
return mips;
}
#endif
//if force_rgba8 then it guarentees rgba8 or rgbx8, otherwise can return l8, etc
qbyte *ReadRawImageFile(qbyte *buf, int len, int *width, int *height, uploadfmt_t *format, qboolean force_rgba8, const char *fname)
{
@ -6957,6 +7141,10 @@ static struct pendingtextureinfo *Image_LoadMipsFromMemory(int flags, const char
if (!mips && filedata[0] == 'B' && filedata[1] == 'L' && filedata[2] == 'P' && filedata[3] == '2')
mips = Image_ReadBLPFile(flags, fname, filedata, filesize);
#endif
#ifdef IMAGEFMT_VTF
if (!mips && filedata[0] == 'V' && filedata[1] == 'T' && filedata[2] == 'F' && filedata[3] == '\0')
mips = Image_ReadVTFFile(flags, fname, filedata, filesize);
#endif
//the above formats are assumed to have consumed filedata somehow (probably storing into mips->extradata)
if (mips)

@ -541,7 +541,7 @@ void CompleteCommand (qboolean force, int direction)
Key_UpdateCompletionDesc();
}
int Con_Navigate(console_t *con, char *line)
int Con_Navigate(console_t *con, const char *line)
{
if (con->backshader)
{
@ -558,7 +558,7 @@ int Con_Navigate(console_t *con, char *line)
}
//lines typed at the main console enter here
int Con_ExecuteLine(console_t *con, char *line)
int Con_ExecuteLine(console_t *con, const char *line)
{
qboolean waschat = false;
char *deutf8 = NULL;
@ -598,7 +598,7 @@ int Con_ExecuteLine(console_t *con, char *line)
Cbuf_AddText (line, RESTRICT_LOCAL);
else
{
char *exec = NULL;
const char *exec = NULL;
if (line[0] == '\\' || line[0] == '/')
exec = line+1; // skip the slash
else if (cl_chatmode.value == 2 && Cmd_IsCommand(line))
@ -1128,6 +1128,19 @@ void Key_ConsoleRelease(console_t *con, int key, unsigned int unicode)
{
if (con->selstartline)
{
if (con->userline)
{
if (con->flags & CONF_BACKSELECTION)
{
con->userline = con->selendline;
con->useroffset = con->selendoffset;
}
else
{
con->userline = con->selstartline;
con->useroffset = con->selstartoffset;
}
}
if (con->selstartline == con->selendline && con->selendoffset <= con->selstartoffset+1)
{
con->flags &= ~CONF_KEEPSELECTION;
@ -1135,7 +1148,7 @@ void Key_ConsoleRelease(console_t *con, int key, unsigned int unicode)
;
else
{
buffer = Con_CopyConsole(con, false, true);
buffer = Con_CopyConsole(con, false, true, false);
if (buffer)
{
Key_HandleConsoleLink(con, buffer);
@ -1146,21 +1159,8 @@ void Key_ConsoleRelease(console_t *con, int key, unsigned int unicode)
else
{
con->flags |= CONF_KEEPSELECTION;
if (con->userdata)
{
if (con->flags & CONF_BACKSELECTION)
{
con->userline = con->selendline;
con->useroffset = con->selendoffset;
}
else
{
con->userline = con->selstartline;
con->useroffset = con->selstartoffset;
}
}
buffer = Con_CopyConsole(con, true, false); //don't keep markup if we're copying to the clipboard
buffer = Con_CopyConsole(con, true, false, true); //don't keep markup if we're copying to the clipboard
if (buffer)
{
Sys_SaveClipboard(CBT_SELECTION, buffer);
@ -1175,7 +1175,7 @@ void Key_ConsoleRelease(console_t *con, int key, unsigned int unicode)
con->buttonsdown = CB_NONE;
if (abs(con->mousedown[0] - con->mousecursor[0]) < 5 && abs(con->mousedown[1] - con->mousecursor[1]) < 5)
{
buffer = Con_CopyConsole(con, false, false);
buffer = Con_CopyConsole(con, false, false, false);
Con_Footerf(con, false, "");
if (!buffer)
return;
@ -1208,7 +1208,7 @@ void Key_ConsoleRelease(console_t *con, int key, unsigned int unicode)
if (key == K_MOUSE2 && con->buttonsdown == CB_COPY)
{
con->buttonsdown = CB_NONE;
buffer = Con_CopyConsole(con, true, false); //don't keep markup if we're copying to the clipboard
buffer = Con_CopyConsole(con, true, false, true); //don't keep markup if we're copying to the clipboard
if (!buffer)
return;
Sys_SaveClipboard(CBT_CLIPBOARD, buffer);
@ -1236,6 +1236,111 @@ void Key_ConsoleRelease(console_t *con, int key, unsigned int unicode)
}
#endif
}
const char *Key_Demoji(char *buffer, size_t buffersize, const char *in)
{
static const struct
{
const char *pattern;
const char *repl;
} emoji[] =
{
//https://www.webpagefx.com/tools/emoji-cheat-sheet/
// {":)", "\xE2\x98\xBA"},
#ifdef QUAKEHUD
{":sg:", "\xEE\x84\x82"},
{":ssg:", "\xEE\x84\x83"},
{":ng:", "\xEE\x84\x84"},
{":sng:", "\xEE\x84\x85"},
{":gl:", "\xEE\x84\x86"},
{":rl:", "\xEE\x84\x87"},
{":lg:", "\xEE\x84\x88"},
{":sg2:", "\xEE\x84\x92"},
{":ssg2:", "\xEE\x84\x93"},
{":ng2:", "\xEE\x84\x94"},
{":sng2:", "\xEE\x84\x95"},
{":gl2:", "\xEE\x84\x96"},
{":rl2:", "\xEE\x84\x97"},
{":lg2:", "\xEE\x84\x98"},
{":shells:", "\xEE\x84\xA0"},
{":nails:", "\xEE\x84\xA1"},
{":rocket:", "\xEE\x84\xA2"},
{":cells:", "\xEE\x84\xA3"},
{":ga:", "\xEE\x84\xA4"},
{":ya:", "\xEE\x84\xA5"},
{":ra:", "\xEE\x84\xA6"},
{":key1:", "\xEE\x84\xB0"},
{":key2:", "\xEE\x84\xB1"},
{":ring:", "\xEE\x84\xB2"},
{":pent:", "\xEE\x84\xB3"},
{":suit:", "\xEE\x84\xB4"},
{":quad:", "\xEE\x84\xB5"},
{":sigil1:", "\xEE\x84\xB6"},
{":sigil2:", "\xEE\x84\xB7"},
{":sigil3:", "\xEE\x84\xB8"},
{":sigil4:", "\xEE\x84\xB9"},
{":face1:", "\xEE\x85\x80"},
{":face_p1:", "\xEE\x85\x81"},
{":face2:", "\xEE\x85\x82"},
{":face_p2:", "\xEE\x85\x83"},
{":face3:", "\xEE\x85\x84"},
{":face_p3:", "\xEE\x85\x85"},
{":face4:", "\xEE\x85\x86"},
{":face_p4:", "\xEE\x85\x87"},
{":face5:", "\xEE\x85\x88"},
{":face_p5:", "\xEE\x85\x89"},
{":face_invis:", "\xEE\x85\x8A"},
{":face_invul2:", "\xEE\x85\x8B"},
{":face_inv2:", "\xEE\x85\x8C"},
{":face_quad:", "\xEE\x85\x8D"},
#endif
};
char *estart = strchr(in, ':');
size_t i;
char *out = buffer, *outend = buffer+buffersize-1;
if (!estart)
return in;
for(; estart; )
{
if (out + (estart-in) >= outend)
break; //not enough space
memcpy(out, in, estart-in);
out += estart-in;
in = estart;
for (i = 0; i < countof(emoji); i++)
{
if (!strncmp(in, emoji[i].pattern, strlen(emoji[i].pattern)))
break; //its this one!
}
if (i < countof(emoji))
{
if (out + strlen(emoji[i].repl) >= outend)
{
in = ""; //no half-emoji
break;
}
in += strlen(emoji[i].pattern);
memcpy(out, emoji[i].repl, strlen(emoji[i].repl));
out += strlen(emoji[i].repl);
estart = strchr(in, ':');
}
else
{
estart = strchr(in+1, ':');
}
}
while (*in && out < outend)
*out++ = *in++;
*out = 0;
return buffer;
}
//if the referenced (trailing) chevron is doubled up, then it doesn't act as part of any markup and should be ignored for such things.
static qboolean utf_specialchevron(unsigned char *start, unsigned char *chev)
{
@ -1456,7 +1561,7 @@ qboolean Key_EntryLine(console_t *con, unsigned char **line, int lineoffset, int
{
if (con && (con->flags & CONF_KEEPSELECTION))
{ //copy selected text to the system clipboard
char *buffer = Con_CopyConsole(con, true, false);
char *buffer = Con_CopyConsole(con, true, false, true);
if (buffer)
{
Sys_SaveClipboard(CBT_CLIPBOARD, buffer);
@ -1666,7 +1771,7 @@ qboolean Key_Console (console_t *con, int key, unsigned int unicode)
Con_ExpandConsoleSelection(con);
con->flags |= CONF_KEEPSELECTION;
buffer = Con_CopyConsole(con, true, false); //don't keep markup if we're copying to the clipboard
buffer = Con_CopyConsole(con, true, false, true); //don't keep markup if we're copying to the clipboard
if (buffer)
{
Sys_SaveClipboard(CBT_SELECTION, buffer);
@ -1789,16 +1894,16 @@ qboolean Key_Console (console_t *con, int key, unsigned int unicode)
if (key == K_ENTER || key == K_KP_ENTER || key == K_GP_START)
{ // backslash text are commands, else chat
int oldl = edit_line;
char demoji[8192];
const char *txt = Key_Demoji(demoji, sizeof(demoji), key_lines[edit_line]);
#ifndef FTE_TARGET_WEB
if (keydown[K_LALT] || keydown[K_RALT])
Cbuf_AddText("\nvid_toggle\n", RESTRICT_LOCAL);
#endif
if ((con_commandmatch && !strchr(key_lines[edit_line], ' ')) || shift)
if ((con_commandmatch && !strchr(txt, ' ')) || shift)
{ //if that isn't actually a command, and we can actually complete it to something, then lets try to complete it.
char *txt = key_lines[edit_line];
if (*txt == '/')
txt++;
@ -1814,7 +1919,7 @@ qboolean Key_Console (console_t *con, int key, unsigned int unicode)
if (con->linebuffered)
{
if (con->linebuffered(con, key_lines[oldl]) != 2)
if (con->linebuffered(con, txt) != 2)
{
edit_line = (edit_line + 1) & (CON_EDIT_LINES_MASK);
history_line = edit_line;
@ -1946,8 +2051,11 @@ void Key_Message (int key, int unicode)
{
if (chat_buffer && chat_buffer[0])
{ //send it straight into the command.
char *line = chat_buffer;
const char *line = chat_buffer;
char deutf8[8192];
char demoji[8192];
line = Key_Demoji(demoji, sizeof(demoji), line);
if (com_parseutf8.ival <= 0)
{
unsigned int unicode;

@ -316,6 +316,8 @@ void Key_ConsoleRelease(console_t *con, int key, unsigned int unicode);
struct console_s;
qboolean Key_GetConsoleSelectionBox(struct console_s *con, int *sx, int *sy, int *ex, int *ey);
qboolean Key_MouseShouldBeFree(void);
const char *Key_Demoji(char *buffer, size_t buffersize, const char *in); //strips out :smile: stuff.
#endif
#endif

@ -385,7 +385,7 @@ void PM_ValidatePackage(package_t *p)
else
#endif
{
#ifdef AVAIL_ZLIB //assume zip/pk3/pk4/apk/etc
#ifdef PACKAGE_PK3 //assume zip/pk3/pk4/apk/etc
archive = FSZIP_LoadArchive(pf, NULL, n, n, NULL);
#else
archive = NULL;
@ -2011,6 +2011,7 @@ static void PM_Download_Got(struct dl_download *dl)
if (p->extract == EXTRACT_ZIP)
{
#ifdef PACKAGE_PK3
vfsfile_t *f = FS_OpenVFS(tempname, "rb", p->fsroot);
if (f)
{
@ -2038,7 +2039,9 @@ static void PM_Download_Got(struct dl_download *dl)
VFS_CLOSE(f);
}
PM_ValidatePackage(p);
#else
Con_Printf("zip format not supported in this build - %s (from %s)\n", p->name, dl->url);
#endif
FS_Remove (tempname, p->fsroot);
Z_Free(tempname);
PM_StartADownload();

@ -559,6 +559,10 @@ static void MenuDrawItems(int xpos, int ypos, menuoption_t *option, menu_t *menu
if (menu->selecteditem == option && (int)(realtime*4) & 1)
{
vid.ime_allow = true;
vid.ime_position[0] = x;
vid.ime_position[1] = y+8;
x += strlen(option->edit.text)*8;
Draw_FunString(x, y, "^Ue00b");
}

@ -101,6 +101,7 @@ static qboolean qacmStartup(void)
#endif
static char media_currenttrack[MAX_QPATH];
static cvar_t music_fade = CVAR("music_fade", "1");
//higher bits have priority (if they have something to play).
#define MEDIA_GAMEMUSIC (1u<<0) //cd music. also music command etc.
@ -295,7 +296,7 @@ static qboolean Media_Changed (unsigned int mediatype)
CDAudio_Stop();
}
#endif
media_fadeout = true;
media_fadeout = music_fade.ival;
media_fadeouttime = realtime;
return true;
}
@ -2450,9 +2451,10 @@ cin_t *Media_StartCin(char *name)
if (!name || !*name) //clear only.
return NULL;
#ifndef MINIMAL
if (!cin)
cin = Media_Static_TryLoad(name);
#endif
#ifdef Q2CLIENT
if (!cin)
cin = Media_Cin_TryLoad(name);
@ -5130,6 +5132,7 @@ void Media_Init(void)
Cmd_AddCommand ("menu_media", M_Menu_Media_f);
#endif
#endif
Cvar_Register(&music_fade, "Media player things");
#ifdef HAVE_SPEECHTOTEXT
Cmd_AddCommand("tts", TTS_Say_f);

@ -1394,6 +1394,7 @@ qboolean M_VideoApplyShadowLighting (union menuoption_s *op,struct menu_s *menu,
break;
}
#ifdef MINIMAL
(void)cvarv;
Cbuf_AddText(va("r_shadow_realtime_world %s;r_shadow_realtime_world_shadows %s\n", cvarsrw, cvarsrws), RESTRICT_LOCAL);
#else
Cbuf_AddText(va("r_vertexlight %s;r_shadow_realtime_world %s;r_shadow_realtime_world_shadows %s\n", cvarv, cvarsrw, cvarsrws), RESTRICT_LOCAL);

@ -485,11 +485,13 @@ int MP_GetServerCategory(int index);
#endif
#ifdef MENU_NATIVECODE
#ifdef HAVE_CLIENT
#include "api_menu.h"
extern menu_export_t *mn_entry;
void MN_Shutdown(void);
qboolean MN_Init(void);
#endif
#endif
#define MGT_BAD ~0
#define MGT_QUAKE1 0

@ -870,7 +870,7 @@ void QCBUILTIN PF_CL_drawrawstring (pubprogfuncs_t *prinst, struct globalvars_s
while(*text)
{
if (1)//VMUTF8)
c = unicode_decode(&error, text, (char**)&text, false);
c = unicode_decode(&error, text, &text, false);
else
{
//FIXME: which charset is this meant to be using?

@ -3689,7 +3689,8 @@ uploadfmt_t Surf_LightmapMode(model_t *model)
}
Con_DPrintf("%s: Using lightmap format %s\n", model->name, Image_FormatName(fmt));
if (!model->submodelof)
Con_DPrintf("%s: Using lightmap format %s\n", model->name, Image_FormatName(fmt));
return fmt;
}

@ -1232,7 +1232,7 @@ void Draw_TinyString (float x, float y, const qbyte *str)
while (*str)
{
codepoint = unicode_decode(&error, str, (char**)&str, true);
codepoint = unicode_decode(&error, str, (char const**)&str, true);
if (codepoint == '\n')
{
@ -2728,7 +2728,7 @@ static void Sbar_Voice(int y)
#endif
}
void SCR_StringXY(char *str, float x, float y);
void SCR_StringXY(const char *str, float x, float y);
void SCR_DrawClock(void);
void SCR_DrawGameClock(void);
static void Sbar_DrawUPS(playerview_t *pv)

@ -916,7 +916,7 @@ void S_Voip_Decode(unsigned int sender, unsigned int codec, unsigned int gen, un
if (decodesamps > 0)
{ //calculate levels of other people. eukara demanded this.
float level;
float level = 0;
float f;
for (len = 0; len < decodesamps; len++)
{

@ -1,6 +1,6 @@
#include "quakedef.h"
#ifdef HAVE_MIXER
#if defined(HAVE_MIXER) || defined(VOICECHAT)
#include "winquake.h"
#ifdef DYNAMIC_SDL
@ -87,8 +87,8 @@ static dllhandle_t *libsdl;
#else
#include <SDL.h>
#endif
#define SELFPAINT
#define SDRVNAME "SDL"
#endif
//SDL calls a callback each time it needs to repaint the 'hardware' buffers
//This results in extra latency due it needing to buffer that much data.
@ -133,7 +133,8 @@ static qboolean SSDL_InitAudio(void)
return true;
}
#ifdef HAVE_MIXER
#define SELFPAINT
static void SSDL_Shutdown(soundcardinfo_t *sc)
{
Con_DPrintf("Shutdown SDL sound\n");
@ -328,7 +329,6 @@ static qboolean QDECL SDL_InitCard(soundcardinfo_t *sc, const char *devicename)
return true;
}
#define SDRVNAME "SDL"
static qboolean QDECL SDL_Enumerate(void (QDECL *cb) (const char *drivername, const char *devicecode, const char *readablename))
{
#if SDL_MAJOR_VERSION >= 2
@ -355,6 +355,7 @@ sounddriver_t SDL_Output =
SDL_InitCard,
SDL_Enumerate
};
#endif
#if SDL_VERSION_ATLEAST(2,0,5) && defined(VOICECHAT)
//Requires SDL 2.0.5+ supposedly.
@ -403,20 +404,24 @@ static void *QDECL SDL_Capture_Init (int rate, const char *devname)
SDL_AudioSpec want, have;
sdlcapture_t c, *r;
memset(&want, 0, sizeof(want));
want.freq = rate;
want.format = AUDIO_S16SYS;
want.channels = 1;
want.samples = 256; //this seems to be chunk sizes rather than total buffer size, so lets keep it reasonably small for lower latencies
want.callback = NULL;
c.dev = SDL_OpenAudioDevice(devname, true, &want, &have, 0);
if (!c.dev) //failed?
return NULL;
r = Z_Malloc(sizeof(*r));
*r = c;
return r;
if (SSDL_InitAudio())
{
memset(&want, 0, sizeof(want));
want.freq = rate;
want.format = AUDIO_S16SYS;
want.channels = 1;
want.samples = 256; //this seems to be chunk sizes rather than total buffer size, so lets keep it reasonably small for lower latencies
want.callback = NULL;
c.dev = SDL_OpenAudioDevice(devname, true, &want, &have, 0);
if (c.dev)
{
r = Z_Malloc(sizeof(*r));
*r = c;
return r;
}
}
return NULL;
}
/*minbytes is a hint to not bother wasting time*/
@ -444,4 +449,4 @@ snd_capture_driver_t SDL_Capture =
SDL_Capture_Shutdown
};
#endif
#endif

@ -1928,7 +1928,7 @@ void Sys_Clipboard_PasteText(clipboardtype_t cbt, void (*callback)(void *cb, cha
CloseClipboard();
}
}
void Sys_SaveClipboard(clipboardtype_t cbt, char *text)
void Sys_SaveClipboard(clipboardtype_t cbt, const char *text)
{
HANDLE glob;
char *temp;

@ -97,7 +97,7 @@ conline_t *Con_Editor_FindLine(console_t *con, int line)
return NULL;
}
int Con_Editor_Evaluate(console_t *con, char *evalstring)
int Con_Editor_Evaluate(console_t *con, const char *evalstring)
{
char *eq, *term;
@ -304,7 +304,7 @@ static void Con_Editor_Save(console_t *con)
}
qboolean Con_Editor_MouseOver(struct console_s *con, char **out_tiptext, shader_t **out_shader)
{
char *mouseover = Con_CopyConsole(con, true, false);
char *mouseover = Con_CopyConsole(con, true, false, false);
if (mouseover)
{
@ -618,7 +618,7 @@ qboolean Con_Editor_Key(console_t *con, unsigned int unicode, int key)
}
if (ctrldown && (con->flags & CONF_KEEPSELECTION))
{
char *buffer = Con_CopyConsole(con, true, false); //don't keep markup if we're copying to the clipboard
char *buffer = Con_CopyConsole(con, true, false, true); //don't keep markup if we're copying to the clipboard
if (buffer)
{
Sys_SaveClipboard(CBT_CLIPBOARD, buffer);
@ -803,7 +803,7 @@ qboolean Con_Editor_Key(console_t *con, unsigned int unicode, int key)
}
if (ctrldown && key =='c' && (con->flags & CONF_KEEPSELECTION))
{
char *buffer = Con_CopyConsole(con, true, false); //don't keep markup if we're copying to the clipboard
char *buffer = Con_CopyConsole(con, true, false, true); //don't keep markup if we're copying to the clipboard
if (buffer)
{
Sys_SaveClipboard(CBT_CLIPBOARD, buffer);
@ -820,7 +820,7 @@ qboolean Con_Editor_Key(console_t *con, unsigned int unicode, int key)
c[l++] = CON_WHITEMASK | (unicode&0xffff);
if (con->flags & CONF_KEEPSELECTION)
Con_Editor_DeleteSelection(con);
if (Con_InsertConChars(con, con->userline, con->useroffset, c, l))
if (con->userline && Con_InsertConChars(con, con->userline, con->useroffset, c, l))
{
con->useroffset += l;
Con_Editor_LineChanged(con, con->userline);

@ -107,6 +107,12 @@ typedef struct
float dpi_x;
float dpi_y;
conchar_t *ime_preview; //pending IME preview text that has been entered but isn't committed yet. set by video code.
size_t ime_previewlen;
size_t ime_caret;
float ime_position[2]; //where to display any ime popups (virtual coords)
qboolean ime_allow; //enable the ime (ie: at the console or messagemode)
} viddef_t;
extern viddef_t vid; // global video state

@ -194,4 +194,5 @@ qboolean If_EvaluateBoolean(const char *text, int restriction);
extern cvar_t rcon_level;
void Cmd_AddTimer(float delay, void(*callback)(int iarg, void *data), int iarg, void *data, size_t datasize); //wrong place, gah
void Cmd_AddTimer(float delay, void(*callback)(int iarg, void *data), int iarg, void *data, size_t datasize); //wrong place, gah

@ -2259,7 +2259,7 @@ qboolean COM_RequireExtension(char *path, const char *extension, int maxlen)
//3 invalid unicode char
//4 invalid utf-16 lead/high surrogate
//5 invalid utf-16 tail/low surrogate
unsigned int utf8_decode(int *error, const void *in, char **out)
unsigned int utf8_decode(int *error, const void *in, char const**out)
{
//uc is the output unicode char
unsigned int uc = 0xfffdu; //replacement character
@ -2375,7 +2375,7 @@ unsigned int utf8_decode(int *error, const void *in, char **out)
uc = *str;
}
*out = (void*)(str + l);
*out = (const void*)(str + l);
if (!*error)
{
@ -2384,7 +2384,7 @@ unsigned int utf8_decode(int *error, const void *in, char **out)
{
#if 1
//cesu-8
char *lowend;
const char *lowend;
unsigned int lowsur = utf8_decode(error, str + l, &lowend);
if (*error == 4)
{
@ -2409,7 +2409,7 @@ unsigned int utf8_decode(int *error, const void *in, char **out)
return uc;
}
unsigned int unicode_decode(int *error, const void *in, char **out, qboolean markup)
unsigned int unicode_decode(int *error, const void *in, char const**out, qboolean markup)
{
unsigned int charcode;
if (markup && ((char*)in)[0] == '^' && ((char*)in)[1] == 'U' && ishexcode(((char*)in)[2]) && ishexcode(((char*)in)[3]) && ishexcode(((char*)in)[4]) && ishexcode(((char*)in)[5]))
@ -2636,7 +2636,7 @@ unsigned int unicode_charcount(const char *in, size_t buffersize, qboolean marku
int chars = 0;
for(chars = 0; in < end && *in; chars+=1)
{
unicode_decode(&error, in, (char**)&in, markup);
unicode_decode(&error, in, &in, markup);
if (in > end)
break; //exceeded buffer size uncleanly
@ -2655,7 +2655,7 @@ unsigned int unicode_byteofsfromcharofs(const char *str, unsigned int charofs, q
if (chars >= charofs)
return in - str;
unicode_decode(&error, in, (char**)&in, markup);
unicode_decode(&error, in, &in, markup);
}
return in - str;
}
@ -2667,7 +2667,7 @@ unsigned int unicode_charofsfrombyteofs(const char *str, unsigned int byteofs, q
int chars = 0;
for(chars = 0; str < end && *str; chars+=1)
{
unicode_decode(&error, str, (char**)&str, markup);
unicode_decode(&error, str, &str, markup);
if (str > end)
break; //exceeded buffer size uncleanly
@ -2722,7 +2722,7 @@ size_t unicode_strtoupper(const char *in, char *out, size_t outsize, qboolean ma
while(*in)
{
c = unicode_decode(&error, in, (char**)&in, markup);
c = unicode_decode(&error, in, &in, markup);
if (c >= 0xe020 && c <= 0xe07f) //quake-char-aware.
c = towupper(c & 0x7f) + (c & 0xff80);
else
@ -2746,7 +2746,7 @@ size_t unicode_strtolower(const char *in, char *out, size_t outsize, qboolean ma
while(*in)
{
c = unicode_decode(&error, in, (char**)&in, markup);
c = unicode_decode(&error, in, &in, markup);
if (c >= 0xe020 && c <= 0xe07f) //quake-char-aware.
c = towlower(c & 0x7f) + (c & 0xff80);
else
@ -3274,7 +3274,7 @@ conchar_t *COM_ParseFunString(conchar_t defaultflags, const char *str, conchar_t
if ((*str & 0x80) && utf8 > 0)
{ //check for utf-8
int decodeerror;
char *end;
const char *end;
uc = utf8_decode(&decodeerror, str, &end);
if (decodeerror && !(utf8 & 2))
{
@ -5882,7 +5882,7 @@ unsigned int COM_RemapMapChecksum(model_t *model, unsigned int checksum)
{
#ifndef NOLEGACY
static const struct {
char *name;
const char *name;
unsigned int gpl2;
unsigned int id11;
unsigned int id12;

@ -405,7 +405,7 @@ char *COM_DeFunString(conchar_t *str, conchar_t *stop, char *out, int outsize, q
#define PFS_CENTERED 16 //flag used by console prints (text should remain centered)
#define PFS_NONOTIFY 32 //flag used by console prints (text won't be visible other than by looking at the console)
conchar_t *COM_ParseFunString(conchar_t defaultflags, const char *str, conchar_t *out, int outsize, int keepmarkup); //ext is usually CON_WHITEMASK, returns its null terminator
unsigned int utf8_decode(int *error, const void *in, char **out);
unsigned int utf8_decode(int *error, const void *in, char const**out);
unsigned int utf8_encode(void *out, unsigned int unicode, int maxlen);
unsigned int iso88591_encode(char *out, unsigned int unicode, int maxlen, qboolean markup);
unsigned int qchar_encode(char *out, unsigned int unicode, int maxlen, qboolean markup);
@ -420,7 +420,7 @@ void COM_BiDi_Shutdown(void);
unsigned int unicode_byteofsfromcharofs(const char *str, unsigned int charofs, qboolean markup);
unsigned int unicode_charofsfrombyteofs(const char *str, unsigned int byteofs, qboolean markup);
unsigned int unicode_encode(char *out, unsigned int unicode, int maxlen, qboolean markup);
unsigned int unicode_decode(int *error, const void *in, char **out, qboolean markup);
unsigned int unicode_decode(int *error, const void *in, char const**out, qboolean markup);
size_t unicode_strtolower(const char *in, char *out, size_t outsize, qboolean markup);
size_t unicode_strtoupper(const char *in, char *out, size_t outsize, qboolean markup);
unsigned int unicode_charcount(const char *in, size_t buffersize, qboolean markup);

@ -51,13 +51,15 @@
#define IPLOG //track player's ip addresses (any decent server will hide ip addresses, so this probably isn't that useful, but nq players expect its)
//Filesystem formats
#define PACKAGE_PK3
#define PACKAGE_PK3 //aka zips. we support utf8,zip64,spans,weakcrypto,deflate,(bzip2),symlinks. we do not support strongcrypto nor any of the other compression schemes.
#define PACKAGE_Q1PAK //also q2
//#define PACKAGE_DOOMWAD //doom wad support (generates various file names, and adds support for doom's audio, sprites, etc)
//#define PACKAGE_VPK //hl2 packages
#define AVAIL_XZDEC //.xz decompression
#define AVAIL_GZDEC //.gz decompression
#define AVAIL_ZLIB //whether pk3s can be compressed or not.
#define AVAIL_DZIP //.dzip support for smaller demos (which are actually more like pak files and can store ANY type of file)
//#define AVAIL_BZLIB //whether pk3s can use bz2 compression
#define PACKAGE_DZIP //.dzip support for smaller demos (which are actually more like pak files and can store ANY type of file)
//Map formats
#define Q1BSPS //Quake1
@ -87,9 +89,10 @@
#define IMAGEFMT_KTX //Khronos TeXture. common on gles3 devices for etc2 compression
#define IMAGEFMT_PKM //file format generally written by etcpack or android's etc1tool. doesn't support mips.
#define IMAGEFMT_DDS //.dds files embed mipmaps and texture compression. faster to load.
#define IMAGEFMT_BLP //legacy crap
//#define IMAGEFMT_BLP //legacy crap
#define IMAGEFMT_BMP //windows bmp. yuck.
#define IMAGEFMT_PCX //paletted junk. required for qw player skins, q2 and a few old skyboxes.
//#define IMAGEFMT_VTF //hl2 image format
#define AVAIL_PNGLIB //.png image format support (read+screenshots)
#define AVAIL_JPEGLIB //.jpeg image format support (read+screenshots)
#define PACKAGE_TEXWAD //quake's image wad support

@ -71,6 +71,7 @@
#define PACKAGE_TEXWAD // HL content support, WAD3
#define PACKAGE_Q1PAK // HL content support, PAK
#undef PACKAGE_DOOMWAD
#undef PACKAGE_VPK //legacy crap
// Map formats
#define Q3BSPS // What we use exclusively
@ -113,6 +114,7 @@
#undef IMAGEFMT_KTX
#undef IMAGEFMT_PKM
#undef IMAGEFMT_BLP //legacy crap
#undef IMAGEFMT_VTF //legacy crap
#define IMAGEFMT_BMP //legacy crap
//#undef IMAGEFMT_PCX //legacy crap
#undef NETPREPARSE //allows for running both nq+qw on the same server (if not, protocol used must match gamecode).
@ -164,6 +166,7 @@
#undef HEADLESSQUAKE
#undef WAYLANDQUAKE
#undef AVAIL_FREETYPE // for truetype font rendering
#undef SERVER_DEMO_PLAYBACK //outdated crap
#ifdef COMPILE_OPTS
//things to configure qclib, which annoyingly doesn't include this file itself

@ -179,7 +179,7 @@ typedef struct console_s
int commandcompletion; //allows tab completion of quake console commands
//WARNING: note that links do NOT represent any sort of security. text can be inserted from anywhere. Its fine to use such things for context, but don't treat them as sescure.
int (*linebuffered) (struct console_s *con, char *line); //if present, called on enter, causes the standard console input to appear. return 2 to not save the line in history.
int (*linebuffered) (struct console_s *con, const char *line); //if present, called on enter, causes the standard console input to appear. return 2 to not save the line in history.
qboolean (*redirect) (struct console_s *con, unsigned int unicode, int key); //if present, called every character.
qboolean (*mouseover)(struct console_s *con, char **out_tiptext, struct shader_s **out_shader);
qboolean (*close) (struct console_s *con, qboolean force);
@ -232,7 +232,7 @@ struct font_s;
void Con_DrawOneConsole(console_t *con, qboolean focused, struct font_s *font, float fx, float fy, float fsx, float fsy, float lineagelimit);
void Con_DrawConsole (int lines, qboolean noback);
void Con_ExpandConsoleSelection(console_t *con);
char *Con_CopyConsole(console_t *con, qboolean nomarkup, qboolean onlyiflink);
char *Con_CopyConsole(console_t *con, qboolean nomarkup, qboolean onlyiflink, qboolean forceutf8);
void Con_Print (const char *txt);
void Con_CenterPrint(const char *txt);
void Con_PrintFlags(const char *text, unsigned int setflags, unsigned int clearflags);
@ -249,8 +249,8 @@ void Con_ClearNotify (void);
void Con_ToggleConsole_f (void);//note: allows csqc to intercept the toggleconsole
void Con_ToggleConsole_Force(void);
int Con_ExecuteLine(console_t *con, char *line); //takes normal console commands
int Con_Navigate(console_t *con, char *line); //special webbrowser hacks
int Con_ExecuteLine(console_t *con, const char *line); //takes normal console commands
int Con_Navigate(console_t *con, const char *line); //special webbrowser hacks
vfsfile_t *Con_POpen(char *conname);
void Con_CycleConsole (void);

@ -810,9 +810,11 @@ static int QDECL COM_Dir_List(const char *name, qofs_t size, time_t mtime, void
|| !Q_strcasecmp(link, "txt") || !Q_strcasecmp(link, "log")
|| !Q_strcasecmp(link, "ent") || !Q_strcasecmp(link, "rtlights")
|| !Q_strcasecmp(link, "glsl") || !Q_strcasecmp(link, "hlsl")
|| !Q_strcasecmp(link, "shader") || !Q_strcasecmp(link, "framegroups"))
|| !Q_strcasecmp(link, "shader") || !Q_strcasecmp(link, "framegroups")
|| !Q_strcasecmp(link, "vmt")
)
Q_snprintfz(link, sizeof(link), "\\tip\\Open in Text Editor\\edit\\%s", name);
else if (!Q_strcasecmp(link, "tga") || !Q_strcasecmp(link, "png") || !Q_strcasecmp(link, "jpg") || !Q_strcasecmp(link, "jpeg") || !Q_strcasecmp(link, "lmp") || !Q_strcasecmp(link, "pcx") || !Q_strcasecmp(link, "bmp") || !Q_strcasecmp(link, "dds") || !Q_strcasecmp(link, "ktx"))
else if (!Q_strcasecmp(link, "tga") || !Q_strcasecmp(link, "png") || !Q_strcasecmp(link, "jpg") || !Q_strcasecmp(link, "jpeg") || !Q_strcasecmp(link, "lmp") || !Q_strcasecmp(link, "pcx") || !Q_strcasecmp(link, "bmp") || !Q_strcasecmp(link, "dds") || !Q_strcasecmp(link, "ktx") || !Q_strcasecmp(link, "vtf"))
{
//FIXME: image replacements are getting in the way here.
Q_snprintfz(link, sizeof(link), "\\tiprawimg\\%s\\tip\\(note: image replacement rules are context-dependant, including base path, sub path, extension, or complete replacement via a shader)", name);
@ -6427,6 +6429,9 @@ void FS_RegisterDefaultFileSystems(void)
FS_RegisterFileSystemType(NULL, "zip", FSZIP_LoadArchive, false);
FS_RegisterFileSystemType(NULL, "exe", FSZIP_LoadArchive, false); //for self-extracting zips.
#endif
#ifdef PACKAGE_VPK
FS_RegisterFileSystemType(NULL, "vpk", FSVPK_LoadArchive, true);
#endif
#ifdef PACKAGE_DOOMWAD
FS_RegisterFileSystemType(NULL, "wad", FSDWD_LoadArchive, true);
#endif

@ -59,6 +59,7 @@ struct searchpathfuncs_s
//warning: the handle is known to be a string pointer to the dir name
extern searchpathfuncs_t *(QDECL VFSOS_OpenPath) (vfsfile_t *file, searchpathfuncs_t *parent, const char *filename, const char *desc, const char *prefix);
extern searchpathfuncs_t *(QDECL FSZIP_LoadArchive) (vfsfile_t *file, searchpathfuncs_t *parent, const char *filename, const char *desc, const char *prefix);
extern searchpathfuncs_t *(QDECL FSVPK_LoadArchive) (vfsfile_t *file, searchpathfuncs_t *parent, const char *filename, const char *desc, const char *prefix);
extern searchpathfuncs_t *(QDECL FSPAK_LoadArchive) (vfsfile_t *file, searchpathfuncs_t *parent, const char *filename, const char *desc, const char *prefix);
extern searchpathfuncs_t *(QDECL FSDWD_LoadArchive) (vfsfile_t *file, searchpathfuncs_t *parent, const char *filename, const char *desc, const char *prefix);
extern searchpathfuncs_t *(QDECL FSDZ_LoadArchive) (vfsfile_t *file, searchpathfuncs_t *parent, const char *filename, const char *desc, const char *prefix);

@ -0,0 +1,502 @@
#include "quakedef.h"
#include "fs.h"
#ifdef PACKAGE_VPK
//
// in memory
//
typedef struct
{
fsbucket_t bucket;
char name[MAX_QPATH];
const struct dvpkfile_s *file;
} mvpkfile_t;
typedef struct vpk_s
{
searchpathfuncs_t pub;
char descname[MAX_OSPATH];
qbyte *treedata; //raw file list
size_t treesize;
struct vpk_s **fragments;
size_t numfragments;
void *mutex;
vfsfile_t *handle;
unsigned int filepos; //the pos the subfiles left it at (to optimize calls to vfs_seek)
int references; //seeing as all vfiles from a pak file use the parent's vfsfile, we need to keep the parent open until all subfiles are closed.
size_t numfiles;
mvpkfile_t files[1]; //processed file list
} vpk_t;
//
// on disk
//
typedef struct dvpkfile_s
{ //chars because these are misaligned.
unsigned char crc[4];
unsigned char preloadsize[2];
unsigned char archiveindex[2];
unsigned char archiveoffset[4];
unsigned char archivesize[4];
unsigned char sentinal[2];//=0xffff;
} dvpkfile_t;
typedef struct
{
//v1
unsigned int magic;
unsigned int version;
unsigned int tablesize;
//v2
unsigned int filedatasize;
unsigned int archivemd5size;
unsigned int globalmd5size;
unsigned int signaturesize;
} dvpkheader_t;
static void QDECL FSVPK_GetPathDetails(searchpathfuncs_t *handle, char *out, size_t outlen)
{
vpk_t *pak = (void*)handle;
*out = 0;
if (pak->references != 1)
Q_snprintfz(out, outlen, "(%i)", pak->references-1);
}
static void QDECL FSVPK_ClosePath(searchpathfuncs_t *handle)
{
qboolean stillopen;
size_t i;
vpk_t *pak = (void*)handle;
if (!Sys_LockMutex(pak->mutex))
return; //ohnoes
stillopen = --pak->references > 0;
Sys_UnlockMutex(pak->mutex);
if (stillopen)
return; //not free yet
VFS_CLOSE (pak->handle);
Sys_DestroyMutex(pak->mutex);
for (i = 0; i < pak->numfragments; i++)
{
if (pak->fragments[i])
pak->fragments[i]->Close(pak->fragments[i]);
pak->fragments[i] = NULL;
}
Z_Free(pak->fragments);
Z_Free(pak->treedata);
Z_Free(pak);
}
static void QDECL FSVPK_BuildHash(searchpathfuncs_t *handle, int depth, void (QDECL *AddFileHash)(int depth, const char *fname, fsbucket_t *filehandle, void *pathhandle))
{
vpk_t *pak = (void*)handle;
int i;
for (i = 0; i < pak->numfiles; i++)
{
AddFileHash(depth, pak->files[i].name, &pak->files[i].bucket, &pak->files[i]);
}
}
static unsigned int QDECL FSVPK_FLocate(searchpathfuncs_t *handle, flocation_t *loc, const char *filename, void *hashedresult)
{
mvpkfile_t *pf = hashedresult;
int i;
vpk_t *pak = (void*)handle;
// look through all the pak file elements
if (pf)
{ //is this a pointer to a file in this pak?
if (pf < pak->files || pf > pak->files + pak->numfiles)
return FF_NOTFOUND; //was found in a different path
}
else
{
for (i=0 ; i<pak->numfiles ; i++) //look for the file
{
if (!Q_strcasecmp (pak->files[i].name, filename))
{
pf = &pak->files[i];
break;
}
}
}
if (pf)
{
if (loc)
{
loc->fhandle = pf;
*loc->rawname = 0;
loc->offset = (qofs_t)-1;
loc->len = ((pf->file->preloadsize[0]<<0)|(pf->file->preloadsize[1]<<8))
+((pf->file->archivesize[0]<<0)|(pf->file->archivesize[1]<<8)|(pf->file->archivesize[2]<<16)|(pf->file->archivesize[3]<<24));
}
return FF_FOUND;
}
return FF_NOTFOUND;
}
static int QDECL FSVPK_EnumerateFiles (searchpathfuncs_t *handle, const char *match, int (QDECL *func)(const char *, qofs_t, time_t mtime, void *, searchpathfuncs_t *spath), void *parm)
{
vpk_t *pak = (void*)handle;
int num;
mvpkfile_t *file;
qofs_t size;
for (num = 0; num<(int)pak->numfiles; num++)
{
if (wildcmp(match, pak->files[num].name))
{
file = &pak->files[num];
//FIXME: time 0? maybe use the pak's mtime?
size = ((file->file->preloadsize[0]<<0)|(file->file->preloadsize[1]<<8))
+((file->file->archivesize[0]<<0)|(file->file->archivesize[1]<<8)|(file->file->archivesize[2]<<16)|(file->file->archivesize[3]<<24));
if (!func(file->name, size, 0, parm, handle))
return false;
}
}
return true;
}
static int QDECL FSVPK_GeneratePureCRC(searchpathfuncs_t *handle, int seed, int crctype)
{
vpk_t *pak = (void*)handle;
return Com_BlockChecksum(pak->treedata, pak->treesize);
}
typedef struct {
vfsfile_t funcs;
vpk_t *parentpak;
const qbyte *preloaddata;
size_t preloadsize;
qofs_t startpos;
qofs_t length;
qofs_t currentpos;
} vfsvpk_t;
static int QDECL VFSVPK_ReadBytes (struct vfsfile_s *vfs, void *buffer, int bytestoread)
{
vfsvpk_t *vfsp = (void*)vfs;
int read;
if (bytestoread <= 0)
return 0;
if (vfsp->currentpos < vfsp->preloadsize)
{
read = bytestoread;
if (read > vfsp->preloadsize-vfsp->currentpos)
read = vfsp->preloadsize-vfsp->currentpos;
memcpy(buffer, vfsp->preloaddata, read);
vfsp->currentpos += read;
if (read == bytestoread)
return read; //we're done, no need to seek etc
bytestoread -= read;
}
if (vfsp->currentpos-vfsp->preloadsize + bytestoread > vfsp->length)
bytestoread = vfsp->length - (vfsp->currentpos-vfsp->preloadsize);
if (bytestoread <= 0)
{
return -1;
}
if (Sys_LockMutex(vfsp->parentpak->mutex))
{
if (vfsp->parentpak->filepos != vfsp->startpos+vfsp->currentpos-vfsp->preloadsize)
VFS_SEEK(vfsp->parentpak->handle, vfsp->startpos+vfsp->currentpos-vfsp->preloadsize);
read = VFS_READ(vfsp->parentpak->handle, buffer, bytestoread);
if (read > 0)
vfsp->currentpos += read;
vfsp->parentpak->filepos = vfsp->startpos+vfsp->currentpos-vfsp->preloadsize;
Sys_UnlockMutex(vfsp->parentpak->mutex);
}
else
read = 0;
return read;
}
static int QDECL VFSVPK_WriteBytes (struct vfsfile_s *vfs, const void *buffer, int bytestoread)
{ //not supported.
Sys_Error("Cannot write to vpk files\n");
return 0;
}
static qboolean QDECL VFSVPK_Seek (struct vfsfile_s *vfs, qofs_t pos)
{
vfsvpk_t *vfsp = (void*)vfs;
if (pos > vfsp->length)
return false;
vfsp->currentpos = pos + vfsp->startpos;
return true;
}
static qofs_t QDECL VFSVPK_Tell (struct vfsfile_s *vfs)
{
vfsvpk_t *vfsp = (void*)vfs;
return vfsp->currentpos - vfsp->startpos;
}
static qofs_t QDECL VFSVPK_GetLen (struct vfsfile_s *vfs)
{
vfsvpk_t *vfsp = (void*)vfs;
return vfsp->length;
}
static qboolean QDECL VFSVPK_Close(vfsfile_t *vfs)
{
vfsvpk_t *vfsp = (void*)vfs;
FSVPK_ClosePath(&vfsp->parentpak->pub); //tell the parent that we don't need it open any more (reference counts)
Z_Free(vfsp); //free ourselves.
return true;
}
static vfsfile_t *QDECL FSVPK_OpenVFS(searchpathfuncs_t *handle, flocation_t *loc, const char *mode)
{
vpk_t *pack = (void*)handle;
vfsvpk_t *vfs;
mvpkfile_t *f = loc->fhandle;
unsigned int frag;
if (strcmp(mode, "rb"))
return NULL; //urm, unable to write/append
frag = (f->file->archiveindex[0]<<0)|(f->file->archiveindex[1]<<8);
if (frag >= pack->numfragments || !pack->fragments[frag])
return NULL;
pack = pack->fragments[frag];
vfs = Z_Malloc(sizeof(vfsvpk_t));
vfs->parentpak = pack;
if (!Sys_LockMutex(pack->mutex))
{
Z_Free(vfs);
return NULL;
}
vfs->parentpak->references++;
Sys_UnlockMutex(pack->mutex);
vfs->preloaddata = (const qbyte*)f->file + sizeof(*f->file);
vfs->preloadsize = (f->file->preloadsize[0]<<0) | (f->file->preloadsize[1]<<8);
vfs->startpos = (f->file->archiveoffset[0]<<0)|(f->file->archiveoffset[1]<<8)|(f->file->archiveoffset[2]<<16)|(f->file->archiveoffset[3]<<24);
vfs->length = loc->len;
vfs->currentpos = 0;
#ifdef _DEBUG
{
mpackfile_t *pf = loc->fhandle;
Q_strncpyz(vfs->funcs.dbgname, pf->name, sizeof(vfs->funcs.dbgname));
}
#endif
vfs->funcs.Close = VFSVPK_Close;
vfs->funcs.GetLen = VFSVPK_GetLen;
vfs->funcs.ReadBytes = VFSVPK_ReadBytes;
vfs->funcs.Seek = VFSVPK_Seek;
vfs->funcs.Tell = VFSVPK_Tell;
vfs->funcs.WriteBytes = VFSVPK_WriteBytes; //not supported
return (vfsfile_t *)vfs;
}
static void QDECL FSVPK_ReadFile(searchpathfuncs_t *handle, flocation_t *loc, char *buffer)
{
vfsfile_t *f;
f = FSVPK_OpenVFS(handle, loc, "rb");
if (!f) //err...
return;
VFS_READ(f, buffer, loc->len);
VFS_CLOSE(f);
}
static unsigned int FSVPK_WalkTree(vpk_t *vpk, const char *start, const char *end)
{ //the weird arrangement of these files is presumably an indicator of how source handles its file types.
const char *ext, *path, *name;
const dvpkfile_t *file;
size_t preloadsize;
unsigned int files = 0;
while(start < end)
{ //extensions
ext = start;
if (!*ext)
{
start++;
break;
}
if (ext[0] == ' ' && !ext[1])
ext = "";
start += strlen(start)+1;
while(start < end)
{ //paths
path = start;
if (!*path)
{
start++;
break;
}
if (path[0] == ' ' && !path[1])
path = "";
start += strlen(start)+1;
while(start < end)
{ //names
name = start;
if (!*name)
{
start++;
break;
}
if (name[0] == ' ' && !name[1])
name = "";
start += strlen(start)+1;
file = (const dvpkfile_t*)start;
preloadsize = (file->preloadsize[0]<<0) | (file->preloadsize[1]<<8);
start += sizeof(*file)+preloadsize;
if (start > end)
return 0; //truncated...
if (file->sentinal[0] != 0xff || file->sentinal[1] != 0xff)
return 0; //sentinal failure
// Con_Printf("Found file %s%s%s%s%s\n", path, *path?"/":"", name, *ext?".":"", ext);
if (!vpk)
files++;
else if (files < vpk->numfiles)
{
unsigned int frag = (file->archiveindex[0]<<0)|(file->archiveindex[1]<<8);
Q_snprintfz(vpk->files[files].name, sizeof(vpk->files[files].name), "%s%s%s%s%s", path, *path?"/":"", name, *ext?".":"", ext);
COM_CleanUpPath(vpk->files[files].name); //just in case...
vpk->files[files].file = file;
if (vpk->numfragments < frag+1)
vpk->numfragments = frag+1;
files++;
}
}
}
}
return files;
}
/*
=================
COM_LoadPackFile
Takes an explicit (not game tree related) path to a pak file.
Loads the header and directory, adding the files at the beginning
of the list so they override previous pack files.
=================
*/
searchpathfuncs_t *QDECL FSVPK_LoadArchive (vfsfile_t *file, searchpathfuncs_t *parent, const char *filename, const char *desc, const char *prefix)
{
dvpkheader_t header;
int i;
int numpackfiles;
vpk_t *vpk, *f;
vfsfile_t *packhandle;
int read;
qbyte *tree;
unsigned int frag;
packhandle = file;
if (packhandle == NULL)
return NULL;
if (prefix && *prefix)
return NULL; //not supported at this time
read = VFS_READ(packhandle, &header, sizeof(header));
header.magic = LittleLong(header.magic);
header.version = LittleLong(header.version);
header.tablesize = LittleLong(header.tablesize);
header.filedatasize = LittleLong(header.filedatasize);
header.archivemd5size = LittleLong(header.archivemd5size);
header.globalmd5size = LittleLong(header.globalmd5size);
header.signaturesize = LittleLong(header.signaturesize);
if (read < 12 || header.magic != 0x55aa1234 || header.tablesize <= 0)
{ //this will include the non-dir files too.
// Con_Printf("%s is not a vpk\n", desc);
return NULL;
}
i = LittleLong(header.version);
if (i == 2)
;//VFS_SEEK(packhandle, 7*sizeof(int));
// else if (i == 1)
// VFS_SEEK(packhandle, 3*sizeof(int));
else
{
Con_Printf("vpk %s is version %x (unspported)\n", desc, i);
return NULL;
}
tree = BZ_Malloc(header.tablesize);
read = VFS_READ(packhandle, tree, header.tablesize);
numpackfiles = FSVPK_WalkTree(NULL, tree, tree+read);
vpk = (vpk_t*)Z_Malloc (sizeof (*vpk) + sizeof(*vpk->files)*(numpackfiles-1));
vpk->treedata = tree;
vpk->treesize = read;
vpk->numfiles = numpackfiles;
vpk->numfragments = 0;
vpk->numfiles = FSVPK_WalkTree(vpk, tree, tree+read);
strcpy (vpk->descname, desc);
vpk->handle = packhandle;
vpk->filepos = 0;
VFS_SEEK(packhandle, vpk->filepos);
vpk->references++;
vpk->mutex = Sys_CreateMutex();
Con_TPrintf ("Added vpkfile %s (%i files)\n", desc, numpackfiles);
vpk->pub.fsver = FSVER;
vpk->pub.GetPathDetails = FSVPK_GetPathDetails;
vpk->pub.ClosePath = FSVPK_ClosePath;
vpk->pub.BuildHash = FSVPK_BuildHash;
vpk->pub.FindFile = FSVPK_FLocate;
vpk->pub.ReadFile = FSVPK_ReadFile;
vpk->pub.EnumerateFiles = FSVPK_EnumerateFiles;
vpk->pub.GeneratePureCRC = FSVPK_GeneratePureCRC;
vpk->pub.OpenVFS = FSVPK_OpenVFS;
vpk->fragments = Z_Malloc(vpk->numfragments*sizeof(*vpk->fragments));
for(frag = 0; frag < vpk->numfragments; frag++)
{
flocation_t loc;
char fragname[MAX_OSPATH], *ext;
Q_strncpyz(fragname, filename, sizeof(fragname));
ext = strrchr(fragname, '.');
if (!ext)
ext = fragname + strlen(fragname);
if (ext-fragname>4 && !strncmp(ext-4, "_dir", 4))
ext-=4;
Q_snprintfz(ext, sizeof(fragname)-(ext-fragname), "_%03u.vpk", frag);
if (parent->FindFile(parent, &loc, fragname, NULL) != FF_FOUND)
continue;
packhandle = parent->OpenVFS(parent, &loc, "rb");
if (!packhandle)
continue;
vpk->fragments[frag] = f = (vpk_t*)Z_Malloc(sizeof(*f));
// Q_strncpyz(f->descname, splitname, sizeof(f->descname));
f->handle = packhandle;
// f->rawsize = VFS_GETLEN(f->raw);
f->references = 1;
f->mutex = Sys_CreateMutex();
f->pub.ClosePath = FSVPK_ClosePath;
}
return &vpk->pub;
}
#endif

@ -75,7 +75,7 @@ typedef struct plugin_s {
struct plugin_s *next;
} plugin_t;
int Plug_SubConsoleCommand(console_t *con, char *line);
int Plug_SubConsoleCommand(console_t *con, const char *line);
plugin_t *currentplug;
@ -1826,7 +1826,7 @@ qboolean Plug_ConsoleLink(char *text, char *info, const char *consolename)
return result;
}
int Plug_SubConsoleCommand(console_t *con, char *line)
int Plug_SubConsoleCommand(console_t *con, const char *line)
{
int ret;
char buffer[2048];

@ -2318,7 +2318,7 @@ static int PF_fwrite_internal (pubprogfuncs_t *prinst, int fnum, const char *msg
}
}
static int PF_fread_internal (pubprogfuncs_t *prinst, int fnum, char *msg, size_t len)
static int PF_fread_internal (pubprogfuncs_t *prinst, int fnum, char *buf, size_t len)
{
if (fnum < 0 || fnum >= MAX_QC_FILES)
{
@ -2347,7 +2347,7 @@ static int PF_fread_internal (pubprogfuncs_t *prinst, int fnum, char *msg, size_
if (pf_fopen_files[fnum].ofs + len > pf_fopen_files[fnum].len)
len = pf_fopen_files[fnum].len - pf_fopen_files[fnum].ofs;
memcpy(msg, pf_fopen_files[fnum].data + pf_fopen_files[fnum].ofs, len);
memcpy(buf, pf_fopen_files[fnum].data + pf_fopen_files[fnum].ofs, len);
pf_fopen_files[fnum].ofs+=len;
return len;
}
@ -2380,7 +2380,7 @@ void QCBUILTIN PF_fread (pubprogfuncs_t *prinst, struct globalvars_s *pr_globals
int fnum = G_FLOAT(OFS_PARM0) - FIRST_QC_FILE_INDEX;
int ptr = G_INT(OFS_PARM1);
int size = G_INT(OFS_PARM2);
if (ptr < 0 || size < 0 || ptr+size >= prinst->stringtablesize)
if (ptr <= 0 || size < 0 || (unsigned)ptr+(unsigned)size >= (unsigned)prinst->stringtablesize)
{
PR_BIError(prinst, "PF_fread: invalid ptr / size\n");
return;
@ -3391,7 +3391,7 @@ void QCBUILTIN PF_chr2str (pubprogfuncs_t *prinst, struct globalvars_s *pr_globa
void QCBUILTIN PF_str2chr (pubprogfuncs_t *prinst, struct globalvars_s *pr_globals)
{
int err;
char *next;
const char *next;
const char *instr = PR_GetStringOfs(prinst, OFS_PARM0);
int ofs = (prinst->callargc>1)?G_FLOAT(OFS_PARM1):0;
@ -6306,14 +6306,14 @@ void QCBUILTIN PF_physics_addforce(pubprogfuncs_t *prinst, struct globalvars_s *
{
wedict_t*e = G_WEDICT(prinst, OFS_PARM0);
float *force = G_VECTOR(OFS_PARM1);
float *relative_ofs = G_VECTOR(OFS_PARM2);
float *impactpos = G_VECTOR(OFS_PARM2); //world coord of impact.
world_t *world = prinst->parms->user;
rbecommandqueue_t cmd;
cmd.command = RBECMD_FORCE;
cmd.edict = e;
VectorCopy(force, cmd.v1);
VectorCopy(relative_ofs, cmd.v2);
VectorCopy(impactpos, cmd.v2);
if (world->rbe)
world->rbe->PushCommand(world, &cmd);

@ -80,7 +80,7 @@ typedef enum
CBT_CLIPBOARD //ctrl+c, ctrl+v
} clipboardtype_t;
void Sys_Clipboard_PasteText(clipboardtype_t clipboardtype, void (*callback)(void *cb, char *utf8), void *ctx); //calls the callback once the text is available (maybe instantly). utf8 arg may be NULL if the clipboard was unavailable.
void Sys_SaveClipboard(clipboardtype_t clipboardtype, char *text); //a stub would do nothing.
void Sys_SaveClipboard(clipboardtype_t clipboardtype, const char *text); //a stub would do nothing.
//stuff for dynamic dedicated console -> gfx and back.
void Sys_CloseTerminal (void);

@ -194,7 +194,7 @@ typedef struct
void (QDECL *RunFrame)(struct world_s *world, double frametime, double gravity);
void (QDECL *PushCommand)(struct world_s *world, rbecommandqueue_t *cmd);
// void (QDECL *ExpandBodyAABB)(struct world_s *world, rbebody_t *bodyptr, float *mins, float *maxs); //expands an aabb to include the size of the body.
// void (QDECL *Trace) ();
void (QDECL *Trace) (struct world_s *world, wedict_t *ed, vec3_t start, vec3_t end, trace_t *trace);
} rigidbodyengine_t;
#endif

@ -1908,7 +1908,7 @@ static void deformgen(const deformv_t *deformv, int cnt, vecV_t *src, vecV_t *ds
}
static void BE_ApplyUniforms(program_t *prog, int permu)
static void BE_ApplyUniforms(program_t *prog, struct programpermu_s *permu)
{
ID3D11Buffer *cbuf[3] =
{
@ -1917,20 +1917,20 @@ static void BE_ApplyUniforms(program_t *prog, int permu)
shaderstate.lcbuffer //light buffer that changes rarelyish
};
//FIXME: how many of these calls can we avoid?
ID3D11DeviceContext_IASetInputLayout(d3ddevctx, prog->permu[permu].h.hlsl.layouts[shaderstate.stream_rgbaf]);
ID3D11DeviceContext_VSSetShader(d3ddevctx, prog->permu[permu].h.hlsl.vert, NULL, 0);
ID3D11DeviceContext_HSSetShader(d3ddevctx, prog->permu[permu].h.hlsl.hull, NULL, 0);
ID3D11DeviceContext_DSSetShader(d3ddevctx, prog->permu[permu].h.hlsl.domain, NULL, 0);
ID3D11DeviceContext_GSSetShader(d3ddevctx, prog->permu[permu].h.hlsl.geom, NULL, 0);
ID3D11DeviceContext_PSSetShader(d3ddevctx, prog->permu[permu].h.hlsl.frag, NULL, 0);
ID3D11DeviceContext_IASetPrimitiveTopology(d3ddevctx, prog->permu[permu].h.hlsl.topology);
ID3D11DeviceContext_IASetInputLayout(d3ddevctx, permu->h.hlsl.layouts[shaderstate.stream_rgbaf]);
ID3D11DeviceContext_VSSetShader(d3ddevctx, permu->h.hlsl.vert, NULL, 0);
ID3D11DeviceContext_HSSetShader(d3ddevctx, permu->h.hlsl.hull, NULL, 0);
ID3D11DeviceContext_DSSetShader(d3ddevctx, permu->h.hlsl.domain, NULL, 0);
ID3D11DeviceContext_GSSetShader(d3ddevctx, permu->h.hlsl.geom, NULL, 0);
ID3D11DeviceContext_PSSetShader(d3ddevctx, permu->h.hlsl.frag, NULL, 0);
ID3D11DeviceContext_IASetPrimitiveTopology(d3ddevctx, permu->h.hlsl.topology);
ID3D11DeviceContext_VSSetConstantBuffers(d3ddevctx, 0, 3, cbuf);
if (prog->permu[permu].h.hlsl.hull)
if (permu->h.hlsl.hull)
ID3D11DeviceContext_HSSetConstantBuffers(d3ddevctx, 0, 3, cbuf);
if (prog->permu[permu].h.hlsl.domain)
if (permu->h.hlsl.domain)
ID3D11DeviceContext_DSSetConstantBuffers(d3ddevctx, 0, 3, cbuf);
if (prog->permu[permu].h.hlsl.geom)
if (permu->h.hlsl.geom)
ID3D11DeviceContext_GSSetConstantBuffers(d3ddevctx, 0, 3, cbuf);
ID3D11DeviceContext_PSSetConstantBuffers(d3ddevctx, 0, 3, cbuf);
}
@ -1940,18 +1940,29 @@ static void BE_RenderMeshProgram(program_t *p, shaderpass_t *pass, unsigned int
int passno;
int perm = 0;
if (TEXLOADED(shaderstate.curtexnums->bump) && p->permu[perm|PERMUTATION_BUMPMAP].h.loaded)
struct programpermu_s *pp;
if (TEXLOADED(shaderstate.curtexnums->bump))
perm |= PERMUTATION_BUMPMAP;
if (TEXLOADED(shaderstate.curtexnums->fullbright) && p->permu[perm|PERMUTATION_FULLBRIGHT].h.loaded)
if (TEXLOADED(shaderstate.curtexnums->fullbright))
perm |= PERMUTATION_FULLBRIGHT;
if (p->permu[perm|PERMUTATION_UPPERLOWER].h.loaded && (TEXLOADED(shaderstate.curtexnums->upperoverlay) || TEXLOADED(shaderstate.curtexnums->loweroverlay)))
if ((TEXLOADED(shaderstate.curtexnums->upperoverlay) || TEXLOADED(shaderstate.curtexnums->loweroverlay)))
perm |= PERMUTATION_UPPERLOWER;
if (r_refdef.globalfog.density && p->permu[perm|PERMUTATION_FOG].h.loaded)
if (r_refdef.globalfog.density)
perm |= PERMUTATION_FOG;
// if (r_glsl_offsetmapping.ival && TEXLOADED(shaderstate.curtexnums->bump) && p->handle[perm|PERMUTATION_OFFSET.hlsl.vert)
// if (r_glsl_offsetmapping.ival && TEXLOADED(shaderstate.curtexnums->bump))
// perm |= PERMUTATION_OFFSET;
BE_ApplyUniforms(p, perm);
perm &= p->supportedpermutations;
pp = p->permu[perm];
if (!pp)
{
pp = Shader_LoadPermutation(p, perm);
if (!pp)
pp = p->permu[perm=0];
}
BE_ApplyUniforms(p, pp);
D3D11BE_ApplyShaderBits(pass->shaderbits, &pass->becache);
@ -3622,7 +3633,7 @@ void D3D11BE_RenderShadowBuffer(unsigned int numverts, void *vbuf, unsigned int
ID3D11DeviceContext_IASetVertexBuffers(d3ddevctx, 0, 1, vbufs, vstrides, voffsets);
ID3D11DeviceContext_IASetIndexBuffer(d3ddevctx, ibuf, DXGI_FORMAT_INDEX_UINT, 0);
BE_ApplyUniforms(shaderstate.depthonly->prog, 0);
BE_ApplyUniforms(shaderstate.depthonly->prog, shaderstate.depthonly->prog->permu[0]);
ID3D11DeviceContext_DrawIndexed(d3ddevctx, numindicies, 0, 0);
}

@ -211,17 +211,21 @@ void D3D11Shader_DeleteProg(program_t *prog)
ID3D11PixelShader *frag;
ID3D11VertexShader *vert;
unsigned int permu, l;
struct programpermu_s *pp;
for (permu = 0; permu < countof(prog->permu); permu++)
{
vert = prog->permu[permu].h.hlsl.vert;
frag = prog->permu[permu].h.hlsl.frag;
pp = prog->permu[permu];
if (!pp)
continue;
vert = pp->h.hlsl.vert;
frag = pp->h.hlsl.frag;
if (vert)
ID3D11VertexShader_Release(vert);
if (frag)
ID3D11PixelShader_Release(frag);
for (l = 0; l < countof(prog->permu[permu].h.hlsl.layouts); l++)
for (l = 0; l < countof(pp->h.hlsl.layouts); l++)
{
layout = prog->permu[permu].h.hlsl.layouts[l];
layout = pp->h.hlsl.layouts[l];
if (layout)
ID3D11InputLayout_Release(layout);
}
@ -229,7 +233,7 @@ void D3D11Shader_DeleteProg(program_t *prog)
}
//create a program from two blobs.
static qboolean D3D11Shader_CreateShaders(program_t *prog, const char *name, int permu,
static qboolean D3D11Shader_CreateShaders(program_t *prog, const char *name, struct programpermu_s *permu,
void *vblob, size_t vsize,
void *hblob, size_t hsize,
void *dblob, size_t dsize,
@ -239,25 +243,25 @@ static qboolean D3D11Shader_CreateShaders(program_t *prog, const char *name, int
int l;
qboolean success = true;
if (FAILED(ID3D11Device_CreateVertexShader(pD3DDev11, vblob, vsize, NULL, (ID3D11VertexShader**)&prog->permu[permu].h.hlsl.vert)))
if (FAILED(ID3D11Device_CreateVertexShader(pD3DDev11, vblob, vsize, NULL, (ID3D11VertexShader**)&permu->h.hlsl.vert)))
success = false;
if (hblob || dblob)
{
prog->permu[permu].h.hlsl.topology = D3D11_PRIMITIVE_TOPOLOGY_3_CONTROL_POINT_PATCHLIST;
if (FAILED(ID3D11Device_CreateHullShader(pD3DDev11, hblob, hsize, NULL, (ID3D11HullShader**)&prog->permu[permu].h.hlsl.hull)))
permu->h.hlsl.topology = D3D11_PRIMITIVE_TOPOLOGY_3_CONTROL_POINT_PATCHLIST;
if (FAILED(ID3D11Device_CreateHullShader(pD3DDev11, hblob, hsize, NULL, (ID3D11HullShader**)&permu->h.hlsl.hull)))
success = false;
if (FAILED(ID3D11Device_CreateDomainShader(pD3DDev11, dblob, dsize, NULL, (ID3D11DomainShader**)&prog->permu[permu].h.hlsl.domain)))
if (FAILED(ID3D11Device_CreateDomainShader(pD3DDev11, dblob, dsize, NULL, (ID3D11DomainShader**)&permu->h.hlsl.domain)))
success = false;
}
else
prog->permu[permu].h.hlsl.topology = D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST;
permu->h.hlsl.topology = D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST;
if (gblob && FAILED(ID3D11Device_CreateGeometryShader(pD3DDev11, gblob, gsize, NULL, (ID3D11GeometryShader**)&prog->permu[permu].h.hlsl.geom)))
if (gblob && FAILED(ID3D11Device_CreateGeometryShader(pD3DDev11, gblob, gsize, NULL, (ID3D11GeometryShader**)&permu->h.hlsl.geom)))
success = false;
if (FAILED(ID3D11Device_CreatePixelShader(pD3DDev11, fblob, fsize, NULL, (ID3D11PixelShader**)&prog->permu[permu].h.hlsl.frag)))
if (FAILED(ID3D11Device_CreatePixelShader(pD3DDev11, fblob, fsize, NULL, (ID3D11PixelShader**)&permu->h.hlsl.frag)))
success = false;
for (l = 0; l < 2 && success; l++)
@ -347,7 +351,7 @@ static qboolean D3D11Shader_CreateShaders(program_t *prog, const char *name, int
decl[elements].InstanceDataStepRate = 0;
elements++;
*/
if (FAILED(ID3D11Device_CreateInputLayout(pD3DDev11, decl, elements, vblob, vsize, (ID3D11InputLayout**)&prog->permu[permu].h.hlsl.layouts[l])))
if (FAILED(ID3D11Device_CreateInputLayout(pD3DDev11, decl, elements, vblob, vsize, (ID3D11InputLayout**)&permu->h.hlsl.layouts[l])))
{
Con_Printf("HLSL Shader %s requires unsupported inputs\n", name);
success = false;
@ -356,7 +360,7 @@ static qboolean D3D11Shader_CreateShaders(program_t *prog, const char *name, int
return success;
}
static qboolean D3D11Shader_LoadBlob(program_t *prog, const char *name, unsigned int permu, vfsfile_t *blobfile)
static qboolean D3D11Shader_LoadBlob(program_t *prog, unsigned int permu, vfsfile_t *blobfile)
{
qboolean success;
char *vblob, *hblob, *dblob, *gblob, *fblob;
@ -398,7 +402,7 @@ static qboolean D3D11Shader_LoadBlob(program_t *prog, const char *name, unsigned
VFS_READ(blobfile, fblob, fsz);
success = D3D11Shader_CreateShaders(prog, name, permu, vblob, vsz, hblob, hsz, dblob, dsz, gblob, gsz, fblob, fsz);
success = D3D11Shader_CreateShaders(prog, prog->name, prog->permu[permu], vblob, vsz, hblob, hsz, dblob, dsz, gblob, gsz, fblob, fsz);
Z_Free(vblob);
Z_Free(hblob);
Z_Free(dblob);
@ -407,7 +411,7 @@ static qboolean D3D11Shader_LoadBlob(program_t *prog, const char *name, unsigned
return success;
}
qboolean D3D11Shader_CreateProgram (program_t *prog, const char *name, unsigned int permu, int ver, const char **precompilerconstants, const char *vert, const char *hull, const char *domain, const char *geom, const char *frag, qboolean silenterrors, vfsfile_t *blobfile)
qboolean D3D11Shader_CreateProgram (program_t *prog, struct programpermu_s *permu, int ver, const char **precompilerconstants, const char *vert, const char *hull, const char *domain, const char *geom, const char *frag, qboolean silenterrors, vfsfile_t *blobfile)
{
char *vsformat;
char *hsformat = NULL;
@ -452,12 +456,12 @@ qboolean D3D11Shader_CreateProgram (program_t *prog, const char *name, unsigned
fsformat = "ps_4_0_level_9_1";
}
prog->permu[permu].h.hlsl.vert = NULL;
prog->permu[permu].h.hlsl.frag = NULL;
prog->permu[permu].h.hlsl.hull = NULL;
prog->permu[permu].h.hlsl.domain = NULL;
prog->permu[permu].h.hlsl.geom = NULL;
memset(prog->permu[permu].h.hlsl.layouts, 0, sizeof(prog->permu[permu].h.hlsl.layouts));
permu->h.hlsl.vert = NULL;
permu->h.hlsl.frag = NULL;
permu->h.hlsl.hull = NULL;
permu->h.hlsl.domain = NULL;
permu->h.hlsl.geom = NULL;
memset(permu->h.hlsl.layouts, 0, sizeof(permu->h.hlsl.layouts));
if (pD3DCompile)
{
@ -517,12 +521,12 @@ qboolean D3D11Shader_CreateProgram (program_t *prog, const char *name, unsigned
success = true;
defines[0].Name = "VERTEX_SHADER";
if (FAILED(pD3DCompile(vert, strlen(vert), name, defines, &myd3dinclude, "main", vsformat, 0, 0, &vcode, &errors)))
if (FAILED(pD3DCompile(vert, strlen(vert), prog->name, defines, &myd3dinclude, "main", vsformat, 0, 0, &vcode, &errors)))
success = false;
if (errors && !silenterrors)
{
char *messages = ID3DBlob_GetBufferPointer(errors);
Con_Printf("vertex shader %s:\n%s", name, messages);
Con_Printf("vertex shader %s:\n%s", prog->name, messages);
ID3DBlob_Release(errors);
}
@ -533,12 +537,12 @@ qboolean D3D11Shader_CreateProgram (program_t *prog, const char *name, unsigned
else
{
defines[0].Name = "HULL_SHADER";
if (FAILED(pD3DCompile(hull, strlen(hull), name, defines, &myd3dinclude, "main", hsformat, 0, 0, &hcode, &errors)))
if (FAILED(pD3DCompile(hull, strlen(hull), prog->name, defines, &myd3dinclude, "main", hsformat, 0, 0, &hcode, &errors)))
success = false;
if (errors && !silenterrors)
{
char *messages = ID3DBlob_GetBufferPointer(errors);
Con_Printf("hull shader %s:\n%s", name, messages);
Con_Printf("hull shader %s:\n%s", prog->name, messages);
ID3DBlob_Release(errors);
}
}
@ -551,12 +555,12 @@ qboolean D3D11Shader_CreateProgram (program_t *prog, const char *name, unsigned
else
{
defines[0].Name = "DOMAIN_SHADER";
if (FAILED(pD3DCompile(domain, strlen(domain), name, defines, &myd3dinclude, "main", dsformat, 0, 0, &dcode, &errors)))
if (FAILED(pD3DCompile(domain, strlen(domain), prog->name, defines, &myd3dinclude, "main", dsformat, 0, 0, &dcode, &errors)))
success = false;
if (errors && !silenterrors)
{
char *messages = ID3DBlob_GetBufferPointer(errors);
Con_Printf("domain shader %s:\n%s", name, messages);
Con_Printf("domain shader %s:\n%s", prog->name, messages);
ID3DBlob_Release(errors);
}
}
@ -569,24 +573,24 @@ qboolean D3D11Shader_CreateProgram (program_t *prog, const char *name, unsigned
else
{
defines[0].Name = "GEOMETRY_SHADER";
if (FAILED(pD3DCompile(domain, strlen(domain), name, defines, &myd3dinclude, "main", gsformat, 0, 0, &gcode, &errors)))
if (FAILED(pD3DCompile(domain, strlen(domain), prog->name, defines, &myd3dinclude, "main", gsformat, 0, 0, &gcode, &errors)))
success = false;
if (errors && !silenterrors)
{
char *messages = ID3DBlob_GetBufferPointer(errors);
Con_Printf("geometry shader %s:\n%s", name, messages);
Con_Printf("geometry shader %s:\n%s", prog->name, messages);
ID3DBlob_Release(errors);
}
}
}
defines[0].Name = "FRAGMENT_SHADER";
if (FAILED(pD3DCompile(frag, strlen(frag), name, defines, &myd3dinclude, "main", fsformat, 0, 0, &fcode, &errors)))
if (FAILED(pD3DCompile(frag, strlen(frag), prog->name, defines, &myd3dinclude, "main", fsformat, 0, 0, &fcode, &errors)))
success = false;
if (errors && !silenterrors)
{
char *messages = ID3DBlob_GetBufferPointer(errors);
Con_Printf("fragment shader %s:\n%s", name, messages);
Con_Printf("fragment shader %s:\n%s", prog->name, messages);
ID3DBlob_Release(errors);
}
@ -597,7 +601,7 @@ qboolean D3D11Shader_CreateProgram (program_t *prog, const char *name, unsigned
}
if (success)
success = D3D11Shader_CreateShaders(prog, name, permu,
success = D3D11Shader_CreateShaders(prog, prog->name, permu,
ID3DBlob_GetBufferPointer(vcode), ID3DBlob_GetBufferSize(vcode),
hcode?ID3DBlob_GetBufferPointer(hcode):NULL, hcode?ID3DBlob_GetBufferSize(hcode):0,
dcode?ID3DBlob_GetBufferPointer(dcode):NULL, dcode?ID3DBlob_GetBufferSize(dcode):0,
@ -712,6 +716,7 @@ qboolean D3D11Shader_Init(unsigned int flevel)
{NULL,NULL}
};
//FIXME: wine's d3dcompiler dlls don't work properly right now, and winetricks installs ms' only up to 43 (which works, but we loaded 47 instead)
for (ver = 47; ver >= 33; ver--)
{
shaderlib = Sys_LoadLibrary(va("D3dcompiler_%i.dll", ver), (ver>=40)?funcsnew:funcsold);

@ -817,6 +817,9 @@ static void SelectPassTexture(unsigned int tu, shaderpass_t *pass)
{
int last;
extern texid_t missing_texture;
extern texid_t missing_texture_gloss;
extern texid_t missing_texture_normal;
extern texid_t r_blackimage;
switch(pass->texgen)
{
@ -828,25 +831,46 @@ static void SelectPassTexture(unsigned int tu, shaderpass_t *pass)
BindTexture(tu, missing_texture);
break;
case T_GEN_NORMALMAP:
BindTexture( tu, shaderstate.curtexnums->bump);
if (TEXLOADED(shaderstate.curtexnums->bump))
BindTexture(tu, shaderstate.curtexnums->bump);
else
BindTexture(tu, missing_texture_normal);
break;
case T_GEN_SPECULAR:
BindTexture(tu, shaderstate.curtexnums->specular);
if (TEXLOADED(shaderstate.curtexnums->specular))
BindTexture(tu, shaderstate.curtexnums->specular);
else
BindTexture(tu, missing_texture_gloss);
break;
case T_GEN_UPPEROVERLAY:
BindTexture(tu, shaderstate.curtexnums->upperoverlay);
if (TEXLOADED(shaderstate.curtexnums->upperoverlay))
BindTexture(tu, shaderstate.curtexnums->upperoverlay);
else
BindTexture(tu, r_blackimage);
break;
case T_GEN_LOWEROVERLAY:
BindTexture(tu, shaderstate.curtexnums->loweroverlay);
if (TEXLOADED(shaderstate.curtexnums->loweroverlay))
BindTexture(tu, shaderstate.curtexnums->loweroverlay);
else
BindTexture(tu, r_blackimage);
break;
case T_GEN_FULLBRIGHT:
BindTexture(tu, shaderstate.curtexnums->fullbright);
if (TEXLOADED(shaderstate.curtexnums->fullbright))
BindTexture(tu, shaderstate.curtexnums->fullbright);
else
BindTexture(tu, r_blackimage);
break;
case T_GEN_REFLECTCUBE:
BindTexture(tu, shaderstate.curtexnums->reflectcube);
if (TEXLOADED(shaderstate.curtexnums->reflectcube))
BindTexture(tu, shaderstate.curtexnums->reflectcube);
else
BindTexture(tu, r_whiteimage);
break;
case T_GEN_REFLECTMASK:
BindTexture(tu, shaderstate.curtexnums->reflectmask);
if (TEXLOADED(shaderstate.curtexnums->reflectmask))
BindTexture(tu, shaderstate.curtexnums->reflectmask);
else
BindTexture(tu, r_whiteimage);
break;
case T_GEN_ANIMMAP:
BindTexture(tu, pass->anim_frames[(int)(pass->anim_fps * shaderstate.curtime) % pass->anim_numframes]);
@ -1902,9 +1926,8 @@ static void R_FetchPlayerColour(unsigned int cv, vec3_t rgb)
*retblue = gammatable[*retblue];
}*/
}
static void BE_ApplyUniforms(program_t *prog, int permu)
static void BE_ApplyUniforms(program_t *prog, struct programpermu_s *perm)
{
struct programpermu_s *perm = &prog->permu[permu];
shaderprogparm_t *pp;
vec4_t param4;
int h;
@ -2082,23 +2105,21 @@ static unsigned int BE_DrawMeshChain_SetupProgram(program_t *p)
{
unsigned int vdec = 0;
unsigned int perm = 0;
struct programpermu_s *pp;
#ifdef SKELETALMODELS
if (shaderstate.batchvbo && shaderstate.batchvbo->numbones)
{
if (p->permu[perm|PERMUTATION_SKELETAL].h.loaded)
perm |= PERMUTATION_SKELETAL;
}
perm |= PERMUTATION_SKELETAL;
#endif
if (TEXLOADED(shaderstate.curtexnums->bump) && p->permu[perm|PERMUTATION_BUMPMAP].h.loaded)
if (TEXLOADED(shaderstate.curtexnums->bump))
perm |= PERMUTATION_BUMPMAP;
if (TEXLOADED(shaderstate.curtexnums->fullbright) && p->permu[perm|PERMUTATION_FULLBRIGHT].h.loaded)
if (TEXLOADED(shaderstate.curtexnums->fullbright))
perm |= PERMUTATION_FULLBRIGHT;
if (p->permu[perm|PERMUTATION_UPPERLOWER].h.loaded && (TEXLOADED(shaderstate.curtexnums->upperoverlay) || TEXLOADED(shaderstate.curtexnums->loweroverlay)))
if ((TEXLOADED(shaderstate.curtexnums->upperoverlay) || TEXLOADED(shaderstate.curtexnums->loweroverlay)))
perm |= PERMUTATION_UPPERLOWER;
if (r_refdef.globalfog.density && p->permu[perm|PERMUTATION_FOG].h.loaded)
if (r_refdef.globalfog.density)
perm |= PERMUTATION_FOG;
#ifdef NONSKELETALMODELS
if (p->permu[perm|PERMUTATION_FRAMEBLEND].h.loaded && shaderstate.batchvbo && shaderstate.batchvbo->coord2.d3d.buff)
if (shaderstate.batchvbo && shaderstate.batchvbo->coord2.d3d.buff)
{
perm |= PERMUTATION_FRAMEBLEND;
vdec |= D3D_VDEC_POS2;
@ -2107,13 +2128,24 @@ static unsigned int BE_DrawMeshChain_SetupProgram(program_t *p)
// if (p->permu[perm|PERMUTATION_DELUXE].h.loaded && TEXVALID(shaderstate.curtexnums->bump) && shaderstate.curbatch->lightmap[0] >= 0 && lightmap[shaderstate.curbatch->lightmap[0]]->hasdeluxe)
// perm |= PERMUTATION_DELUXE;
#if MAXRLIGHTMAPS > 1
if (shaderstate.curbatch && shaderstate.curbatch->lightmap[1] >= 0 && p->permu[perm|PERMUTATION_LIGHTSTYLES].h.loaded)
if (shaderstate.curbatch && shaderstate.curbatch->lightmap[1] >= 0)
perm |= PERMUTATION_LIGHTSTYLES;
#endif
vdec |= D3D_VDEC_COL4B;//BE_GenerateColourMods(vertcount, s->passes);
BE_ApplyUniforms(p, perm);
perm &= p->supportedpermutations;
pp = p->permu[perm];
if (!pp)
{
pp = p->permu[perm] = Shader_LoadPermutation(p, perm);
if (!pp)
pp = p->permu[perm=0];
}
if (perm & PERMUTATION_FRAMEBLEND)
vdec |= D3D_VDEC_POS2;
BE_ApplyUniforms(p, pp);
return vdec;
}
@ -2287,26 +2319,27 @@ static void BE_RenderMeshProgram(shader_t *s, unsigned int vertbase, unsigned in
int perm = 0;
program_t *p = s->prog;
struct programpermu_s *pp;
#ifdef SKELETALMODELS
if (shaderstate.batchvbo && shaderstate.batchvbo->numbones)
{
if (p->permu[perm|PERMUTATION_SKELETAL].h.loaded)
if (p->supportedpermutations & PERMUTATION_SKELETAL)
perm |= PERMUTATION_SKELETAL;
else
return;
}
#endif
if (TEXLOADED(shaderstate.curtexnums->bump) && p->permu[perm|PERMUTATION_BUMPMAP].h.loaded)
if (TEXLOADED(shaderstate.curtexnums->bump))
perm |= PERMUTATION_BUMPMAP;
if (TEXLOADED(shaderstate.curtexnums->fullbright) && p->permu[perm|PERMUTATION_FULLBRIGHT].h.loaded)
if (TEXLOADED(shaderstate.curtexnums->fullbright))
perm |= PERMUTATION_FULLBRIGHT;
if (p->permu[perm|PERMUTATION_UPPERLOWER].h.loaded && (TEXLOADED(shaderstate.curtexnums->upperoverlay) || TEXLOADED(shaderstate.curtexnums->loweroverlay)))
if ((TEXLOADED(shaderstate.curtexnums->upperoverlay) || TEXLOADED(shaderstate.curtexnums->loweroverlay)))
perm |= PERMUTATION_UPPERLOWER;
if (r_refdef.globalfog.density && p->permu[perm|PERMUTATION_FOG].h.loaded)
if (r_refdef.globalfog.density)
perm |= PERMUTATION_FOG;
#ifdef NONSKELETALMODELS
if (p->permu[perm|PERMUTATION_FRAMEBLEND].h.loaded && shaderstate.batchvbo && shaderstate.batchvbo->coord2.d3d.buff)
if (shaderstate.batchvbo && shaderstate.batchvbo->coord2.d3d.buff)
{
perm |= PERMUTATION_FRAMEBLEND;
vdec |= D3D_VDEC_POS2;
@ -2315,13 +2348,24 @@ static void BE_RenderMeshProgram(shader_t *s, unsigned int vertbase, unsigned in
// if (p->permu[perm|PERMUTATION_DELUXE].h.loaded && TEXVALID(shaderstate.curtexnums->bump) && shaderstate.curbatch->lightmap[0] >= 0 && lightmap[shaderstate.curbatch->lightmap[0]]->hasdeluxe)
// perm |= PERMUTATION_DELUXE;
#if MAXRLIGHTMAPS > 1
if (shaderstate.curbatch && shaderstate.curbatch->lightmap[1] >= 0 && p->permu[perm|PERMUTATION_LIGHTSTYLES].h.loaded)
if (shaderstate.curbatch && shaderstate.curbatch->lightmap[1] >= 0)
perm |= PERMUTATION_LIGHTSTYLES;
#endif
vdec |= D3D_VDEC_COL4B;//BE_GenerateColourMods(vertcount, s->passes);
BE_ApplyUniforms(p, perm);
perm &= p->supportedpermutations;
pp = p->permu[perm];
if (!pp)
{
pp = Shader_LoadPermutation(p, perm);
if (!pp)
pp = p->permu[perm=0];
}
if (perm & PERMUTATION_FRAMEBLEND)
vdec |= D3D_VDEC_POS2;
BE_ApplyUniforms(p, pp);
BE_ApplyShaderBits(s->passes->shaderbits);

@ -256,7 +256,7 @@ static struct myID3DXIncludeVtbl myID3DXIncludeVtbl_C =
};
static struct myID3DXInclude myID3DXIncludeVtbl_Instance = {&myID3DXIncludeVtbl_C};
static qboolean D3D9Shader_CreateProgram (program_t *prog, const char *sname, unsigned int permu, int ver, const char **precompilerconstants, const char *vert, const char *tcs, const char *tes, const char *geom, const char *frag, qboolean silent, vfsfile_t *blobfile)
static qboolean D3D9Shader_CreateProgram (program_t *prog, struct programpermu_s *permu, int ver, const char **precompilerconstants, const char *vert, const char *tcs, const char *tes, const char *geom, const char *frag, qboolean silent, vfsfile_t *blobfile)
{
D3DXMACRO defines[64];
@ -267,12 +267,12 @@ static qboolean D3D9Shader_CreateProgram (program_t *prog, const char *sname, un
if (geom || tcs || tes)
{
Con_Printf("geometry and tessellation shaders are not availale in d3d9 (%s)\n", sname);
Con_Printf("geometry and tessellation shaders are not availale in d3d9 (%s)\n", prog->name);
return false;
}
prog->permu[permu].h.hlsl.vert = NULL;
prog->permu[permu].h.hlsl.frag = NULL;
permu->h.hlsl.vert = NULL;
permu->h.hlsl.frag = NULL;
if (pD3DXCompileShader)
{
@ -325,32 +325,36 @@ static qboolean D3D9Shader_CreateProgram (program_t *prog, const char *sname, un
success = true;
defines[0].Name = "VERTEX_SHADER";
if (FAILED(pD3DXCompileShader(vert, strlen(vert), defines, &myID3DXIncludeVtbl_Instance, "main", "vs_2_0", 0, &code, &errors, (LPD3DXCONSTANTTABLE*)&prog->permu[permu].h.hlsl.ctabv)))
if (FAILED(pD3DXCompileShader(vert, strlen(vert), defines, &myID3DXIncludeVtbl_Instance, "main", "vs_2_0", 0, &code, &errors, (LPD3DXCONSTANTTABLE*)&permu->h.hlsl.ctabv)))
success = false;
else
{
IDirect3DDevice9_CreateVertexShader(pD3DDev9, code->lpVtbl->GetBufferPointer(code), (IDirect3DVertexShader9**)&prog->permu[permu].h.hlsl.vert);
IDirect3DDevice9_CreateVertexShader(pD3DDev9, code->lpVtbl->GetBufferPointer(code), (IDirect3DVertexShader9**)&permu->h.hlsl.vert);
code->lpVtbl->Release(code);
}
if (errors)
{
char *messages = errors->lpVtbl->GetBufferPointer(errors);
Con_Printf("Error compiling vertex shader %s:\n%s", sname, messages);
//int i;
// for (i = 0; i < consts; i++)
// Con_Printf("%s %i: %s==%s\n", prog->name, i, defines[i].Name, defines[i].Definition);
// Con_Printf("%s\n", vert);
Con_Printf("Error compiling vertex shader %s:\n%s", prog->name, messages);
errors->lpVtbl->Release(errors);
}
defines[0].Name = "FRAGMENT_SHADER";
if (FAILED(pD3DXCompileShader(frag, strlen(frag), defines, &myID3DXIncludeVtbl_Instance, "main", "ps_2_0", 0, &code, &errors, (LPD3DXCONSTANTTABLE*)&prog->permu[permu].h.hlsl.ctabf)))
if (FAILED(pD3DXCompileShader(frag, strlen(frag), defines, &myID3DXIncludeVtbl_Instance, "main", "ps_2_0", 0, &code, &errors, (LPD3DXCONSTANTTABLE*)&permu->h.hlsl.ctabf)))
success = false;
else
{
IDirect3DDevice9_CreatePixelShader(pD3DDev9, code->lpVtbl->GetBufferPointer(code), (IDirect3DPixelShader9**)&prog->permu[permu].h.hlsl.frag);
IDirect3DDevice9_CreatePixelShader(pD3DDev9, code->lpVtbl->GetBufferPointer(code), (IDirect3DPixelShader9**)&permu->h.hlsl.frag);
code->lpVtbl->Release(code);
}
if (errors)
{
char *messages = errors->lpVtbl->GetBufferPointer(errors);
Con_Printf("Error compiling pixel shader %s:\n%s", sname, messages);
Con_Printf("Error compiling pixel shader %s:\n%s", prog->name, messages);
errors->lpVtbl->Release(errors);
}
}
@ -389,134 +393,117 @@ static int D3D9Shader_FindUniform(union programhandle_u *h, int type, const char
return -1;
}
static void D3D9Shader_ProgAutoFields(program_t *prog, const char *progname, cvar_t **cvarrefs, char **cvarnames, int *cvartypes)
static void D3D9Shader_ProgAutoFields(program_t *prog, struct programpermu_s *pp, cvar_t **cvarrefs, char **cvarnames, int *cvartypes)
{
struct programpermu_s *pp;
unsigned int i, p;
unsigned int i;
int uniformloc;
char tmpbuffer[256];
#define ALTLIGHTMAPSAMP 13
#define ALTDELUXMAPSAMP 16
prog->nofixedcompat = true;
/* prog->nofixedcompat = true;
prog->defaulttextures = 0;
prog->numsamplers = 0;
for (p = 0; p < PERMUTATIONS; p++)
*/
int maxparms = 0;
pp->parm = NULL;
pp->numparms = 0;
IDirect3DDevice9_SetVertexShader(pD3DDev9, pp->h.hlsl.vert);
IDirect3DDevice9_SetPixelShader(pD3DDev9, pp->h.hlsl.frag);
for (i = 0; shader_unif_names[i].name; i++)
{
int maxparms = 0;
pp = &prog->permu[p];
pp->parm = NULL;
pp->numparms = 0;
if (!pp->h.loaded)
continue;
IDirect3DDevice9_SetVertexShader(pD3DDev9, pp->h.hlsl.vert);
IDirect3DDevice9_SetPixelShader(pD3DDev9, pp->h.hlsl.frag);
for (i = 0; shader_unif_names[i].name; i++)
uniformloc = D3D9Shader_FindUniform(&pp->h, 0, shader_unif_names[i].name);
if (uniformloc != -1)
{
uniformloc = D3D9Shader_FindUniform(&pp->h, 0, shader_unif_names[i].name);
if (uniformloc != -1)
if (pp->numparms == maxparms)
{
if (pp->numparms == maxparms)
{
maxparms = maxparms?maxparms*2:8;
pp->parm = BZ_Realloc(pp->parm, sizeof(*pp->parm) * maxparms);
}
pp->parm[pp->numparms].handle = uniformloc;
pp->parm[pp->numparms].type = shader_unif_names[i].ptype;
pp->numparms++;
maxparms = maxparms?maxparms*2:8;
pp->parm = BZ_Realloc(pp->parm, sizeof(*pp->parm) * maxparms);
}
pp->parm[pp->numparms].handle = uniformloc;
pp->parm[pp->numparms].type = shader_unif_names[i].ptype;
pp->numparms++;
}
}
for (i = 0; cvarnames[i]; i++)
{
if (!cvarrefs[i])
continue;
//just directly sets uniforms. can't cope with cvars dynamically changing.
cvarrefs[i]->flags |= CVAR_SHADERSYSTEM;
for (i = 0; cvarnames[i]; i++)
Q_snprintfz(tmpbuffer, sizeof(tmpbuffer), "cvar_%s", cvarnames[i]);
uniformloc = D3D9Shader_FindUniform(&pp->h, 1, tmpbuffer);
if (uniformloc != -1)
{
if (!cvarrefs[i])
continue;
//just directly sets uniforms. can't cope with cvars dynamically changing.
cvarrefs[i]->flags |= CVAR_SHADERSYSTEM;
Q_snprintfz(tmpbuffer, sizeof(tmpbuffer), "cvar_%s", cvarnames[i]);
uniformloc = D3D9Shader_FindUniform(&prog->permu[p].h, 1, tmpbuffer);
if (uniformloc != -1)
if (cvartypes[i] == SP_CVARI)
{
if (cvartypes[i] == SP_CVARI)
{
int v[4] = {cvarrefs[i]->ival, 0, 0, 0};
IDirect3DDevice9_SetVertexShaderConstantI(pD3DDev9, 0, v, 1);
}
else
IDirect3DDevice9_SetVertexShaderConstantF(pD3DDev9, 0, cvarrefs[i]->vec4, 1);
}
uniformloc = D3D9Shader_FindUniform(&prog->permu[p].h, 2, tmpbuffer);
if (uniformloc != -1)
{
if (cvartypes[i] == SP_CVARI)
{
int v[4] = {cvarrefs[i]->ival, 0, 0, 0};
IDirect3DDevice9_SetPixelShaderConstantI(pD3DDev9, 0, v, 1);
}
else
IDirect3DDevice9_SetPixelShaderConstantF(pD3DDev9, 0, cvarrefs[i]->vec4, 1);
int v[4] = {cvarrefs[i]->ival, 0, 0, 0};
IDirect3DDevice9_SetVertexShaderConstantI(pD3DDev9, 0, v, 1);
}
else
IDirect3DDevice9_SetVertexShaderConstantF(pD3DDev9, 0, cvarrefs[i]->vec4, 1);
}
/*set texture uniforms*/
for (i = 0; i < 8; i++)
uniformloc = D3D9Shader_FindUniform(&pp->h, 2, tmpbuffer);
if (uniformloc != -1)
{
Q_snprintfz(tmpbuffer, sizeof(tmpbuffer), "s_t%i", i);
uniformloc = D3D9Shader_FindUniform(&pp->h, 2, tmpbuffer);
if (uniformloc != -1)
if (cvartypes[i] == SP_CVARI)
{
int v[4] = {i};
IDirect3DDevice9_SetPixelShader(pD3DDev9, pp->h.hlsl.frag);
int v[4] = {cvarrefs[i]->ival, 0, 0, 0};
IDirect3DDevice9_SetPixelShaderConstantI(pD3DDev9, 0, v, 1);
if (prog->numsamplers < i+1)
prog->numsamplers = i+1;
}
else
IDirect3DDevice9_SetPixelShaderConstantF(pD3DDev9, 0, cvarrefs[i]->vec4, 1);
}
}
for (i = 0; sh_defaultsamplers[i].name; i++)
/*set texture uniforms*/
for (i = 0; i < prog->numsamplers; i++)
{
Q_snprintfz(tmpbuffer, sizeof(tmpbuffer), "s_t%i", i);
uniformloc = D3D9Shader_FindUniform(&pp->h, 2, tmpbuffer);
if (uniformloc != -1)
{
//figure out which ones are needed.
if (prog->defaulttextures & sh_defaultsamplers[i].defaulttexbits)
continue; //don't spam
uniformloc = D3D9Shader_FindUniform(&pp->h, 2, sh_defaultsamplers[i].name);
if (uniformloc != -1)
prog->defaulttextures |= sh_defaultsamplers[i].defaulttexbits;
int v[4] = {i};
IDirect3DDevice9_SetPixelShader(pD3DDev9, pp->h.hlsl.frag);
IDirect3DDevice9_SetPixelShaderConstantI(pD3DDev9, 0, v, 1);
// if (prog->numsamplers < i+1)
// prog->numsamplers = i+1;
}
}
//multiple lightmaps is kinda hacky. if any are set, all must be.
if (prog->defaulttextures & ((1u<<(ALTLIGHTMAPSAMP+0)) | (1u<<(ALTLIGHTMAPSAMP+1)) | (1u<<(ALTLIGHTMAPSAMP+2))))
prog->defaulttextures |=((1u<<(ALTLIGHTMAPSAMP+0)) | (1u<<(ALTLIGHTMAPSAMP+1)) | (1u<<(ALTLIGHTMAPSAMP+2)));
if (prog->defaulttextures & ((1u<<(ALTDELUXMAPSAMP+0)) | (1u<<(ALTDELUXMAPSAMP+1)) | (1u<<(ALTDELUXMAPSAMP+2))))
prog->defaulttextures |=((1u<<(ALTDELUXMAPSAMP+0)) | (1u<<(ALTDELUXMAPSAMP+1)) | (1u<<(ALTDELUXMAPSAMP+2)));
/* for (i = 0; sh_defaultsamplers[i].name; i++)
{
//figure out which ones are needed.
if (prog->defaulttextures & sh_defaultsamplers[i].defaulttexbits)
continue; //don't spam
uniformloc = D3D9Shader_FindUniform(&pp->h, 2, sh_defaultsamplers[i].name);
if (uniformloc != -1)
prog->defaulttextures |= sh_defaultsamplers[i].defaulttexbits;
}
*/
if (prog->defaulttextures)
{
unsigned int sampnum;
/*set default texture uniforms*/
for (p = 0; p < PERMUTATIONS; p++)
sampnum = prog->numsamplers;
for (i = 0; sh_defaultsamplers[i].name; i++)
{
if (!prog->permu[p].h.loaded)
continue;
sampnum = prog->numsamplers;
for (i = 0; sh_defaultsamplers[i].name; i++)
if (prog->defaulttextures & sh_defaultsamplers[i].defaulttexbits)
{
if (prog->defaulttextures & sh_defaultsamplers[i].defaulttexbits)
uniformloc = D3D9Shader_FindUniform(&pp->h, 2, sh_defaultsamplers[i].name);
if (uniformloc != -1)
{
uniformloc = D3D9Shader_FindUniform(&prog->permu[p].h, 2, sh_defaultsamplers[i].name);
if (uniformloc != -1)
{
int v[4] = {sampnum};
IDirect3DDevice9_SetPixelShader(pD3DDev9, prog->permu[p].h.hlsl.frag);
IDirect3DDevice9_SetPixelShaderConstantI(pD3DDev9, 0, v, 1);
}
sampnum++;
int v[4] = {sampnum};
IDirect3DDevice9_SetPixelShader(pD3DDev9, pp->h.hlsl.frag);
IDirect3DDevice9_SetPixelShaderConstantI(pD3DDev9, 0, v, 1);
}
sampnum++;
}
}
}
@ -527,34 +514,38 @@ static void D3D9Shader_ProgAutoFields(program_t *prog, const char *progname, cva
void D3D9Shader_DeleteProg(program_t *prog)
{
unsigned int permu;
struct programpermu_s *pp;
for (permu = 0; permu < countof(prog->permu); permu++)
{
if (prog->permu[permu].h.hlsl.vert)
pp = prog->permu[permu];
if (!pp)
continue;
if (pp->h.hlsl.vert)
{
IDirect3DVertexShader9 *vs = prog->permu[permu].h.hlsl.vert;
prog->permu[permu].h.hlsl.vert = NULL;
IDirect3DVertexShader9 *vs = pp->h.hlsl.vert;
pp->h.hlsl.vert = NULL;
IDirect3DVertexShader9_Release(vs);
}
if (prog->permu[permu].h.hlsl.frag)
if (pp->h.hlsl.frag)
{
IDirect3DPixelShader9 *fs = prog->permu[permu].h.hlsl.frag;
prog->permu[permu].h.hlsl.frag = NULL;
IDirect3DPixelShader9 *fs = pp->h.hlsl.frag;
pp->h.hlsl.frag = NULL;
IDirect3DPixelShader9_Release(fs);
}
if (prog->permu[permu].h.hlsl.ctabv)
if (pp->h.hlsl.ctabv)
{
LPD3DXCONSTANTTABLE vct = prog->permu[permu].h.hlsl.ctabv;
prog->permu[permu].h.hlsl.ctabv = NULL;
LPD3DXCONSTANTTABLE vct = pp->h.hlsl.ctabv;
pp->h.hlsl.ctabv = NULL;
IUnknown_Release(vct);
}
if (prog->permu[permu].h.hlsl.ctabf)
if (pp->h.hlsl.ctabf)
{
LPD3DXCONSTANTTABLE fct = prog->permu[permu].h.hlsl.ctabf;
prog->permu[permu].h.hlsl.ctabf = NULL;
LPD3DXCONSTANTTABLE fct = pp->h.hlsl.ctabf;
pp->h.hlsl.ctabf = NULL;
IUnknown_Release(fct);
}
prog->permu[permu].numparms = 0;
BZ_Free(prog->permu[permu].parm);
pp->numparms = 0;
BZ_Free(pp->parm);
}
}

@ -675,6 +675,7 @@ static void BE_ApplyAttributes(unsigned int bitstochange, unsigned int bitstoend
{
shaderstate.sha_attr &= ~(1u<<i);
qglDisableVertexAttribArray(i);
qglVertexAttrib4f(VATTR_COLOUR, 1, 1, 1, 1);
continue;
}
GL_SelectVBO(shaderstate.pendingcolourvbo);
@ -3317,7 +3318,7 @@ static void DrawPass(const shaderpass_t *pass)
}
#endif
static void BE_Program_Set_Attributes(const program_t *prog, unsigned int perm, qboolean entunchanged)
static void BE_Program_Set_Attributes(const program_t *prog, struct programpermu_s *perm, qboolean entunchanged)
{
vec4_t param4;
int r, g;//, b;
@ -3329,8 +3330,8 @@ static void BE_Program_Set_Attributes(const program_t *prog, unsigned int perm,
if (entunchanged)
return;
p = prog->permu[perm].parm;
for (i = prog->permu[perm].numparms; i > 0; i--, p++)
p = perm->parm;
for (i = perm->numparms; i > 0; i--, p++)
{
ph = p->handle;
switch(p->type)
@ -3472,7 +3473,7 @@ static void BE_Program_Set_Attributes(const program_t *prog, unsigned int perm,
case SP_E_VLSCALE:
#if MAXRLIGHTMAPS > 1
if (perm & PERMUTATION_LIGHTSTYLES)
if (perm->permutation & PERMUTATION_LIGHTSTYLES)
{
vec4_t colscale[MAXRLIGHTMAPS];
int j, s;
@ -3524,7 +3525,7 @@ static void BE_Program_Set_Attributes(const program_t *prog, unsigned int perm,
break;
case SP_E_LMSCALE:
#if MAXRLIGHTMAPS > 1
if (perm & PERMUTATION_LIGHTSTYLES)
if (perm->permutation & PERMUTATION_LIGHTSTYLES)
{
vec4_t colscale[MAXRLIGHTMAPS];
int j, s;
@ -3777,8 +3778,9 @@ static void BE_RenderMeshProgram(const shader_t *shader, const shaderpass_t *pas
int perm;
struct programpermu_s *permu;
perm = 0;
#if 0
if (shaderstate.sourcevbo->numbones)
perm |= PERMUTATION_SKELETAL;
#ifdef NONSKELETALMODELS
@ -3793,7 +3795,7 @@ static void BE_RenderMeshProgram(const shader_t *shader, const shaderpass_t *pas
perm |= PERMUTATION_UPPERLOWER;
if (r_refdef.globalfog.density)
perm |= PERMUTATION_FOG;
// if (p->permu[perm|PERMUTATION_DELUXE].handle.glsl.handle && TEXLOADED(shaderstate.curtexnums->bump) && shaderstate.curbatch->lightmap[0] >= 0 && lightmap[shaderstate.curbatch->lightmap[0]]->hasdeluxe)
// if (TEXLOADED(shaderstate.curtexnums->bump) && shaderstate.curbatch->lightmap[0] >= 0 && lightmap[shaderstate.curbatch->lightmap[0]]->hasdeluxe)
// perm |= PERMUTATION_DELUXE;
if ((TEXLOADED(shaderstate.curtexnums->reflectcube) || TEXLOADED(shaderstate.curtexnums->reflectmask)))
perm |= PERMUTATION_REFLECTCUBEMASK;
@ -3803,45 +3805,15 @@ static void BE_RenderMeshProgram(const shader_t *shader, const shaderpass_t *pas
#endif
perm &= p->supportedpermutations;
if (!p->permu[perm].h.loaded)
{
perm = 0;
if (!p->permu[perm].h.loaded)
return;
}
#else
if (shaderstate.sourcevbo->numbones)
permu = p->permu[perm];
if (!permu)
{
if (p->permu[perm|PERMUTATION_SKELETAL].h.loaded)
perm |= PERMUTATION_SKELETAL;
else
p->permu[perm] = permu = Shader_LoadPermutation(p, perm);
if (!permu)
return;
}
#ifdef NONSKELETALMODELS
if (p->permu[perm|PERMUTATION_FRAMEBLEND].h.loaded && shaderstate.sourcevbo->coord2.gl.addr)
perm |= PERMUTATION_FRAMEBLEND;
#endif
if (TEXLOADED(shaderstate.curtexnums->bump) && p->permu[perm|PERMUTATION_BUMPMAP].h.loaded)
perm |= PERMUTATION_BUMPMAP;
if (TEXLOADED(shaderstate.curtexnums->fullbright) && p->permu[perm|PERMUTATION_FULLBRIGHT].h.loaded)
perm |= PERMUTATION_FULLBRIGHT;
if ((TEXLOADED(shaderstate.curtexnums->loweroverlay) || TEXLOADED(shaderstate.curtexnums->upperoverlay)) && p->permu[perm|PERMUTATION_UPPERLOWER].h.loaded)
perm |= PERMUTATION_UPPERLOWER;
if (r_refdef.globalfog.density && p->permu[perm|PERMUTATION_FOG].h.loaded)
perm |= PERMUTATION_FOG;
// if (p->permu[perm|PERMUTATION_DELUXE].handle.glsl.handle && TEXLOADED(shaderstate.curtexnums->bump) && shaderstate.curbatch->lightmap[0] >= 0 && lightmap[shaderstate.curbatch->lightmap[0]]->hasdeluxe)
// perm |= PERMUTATION_DELUXE;
if ((TEXLOADED(shaderstate.curtexnums->reflectcube) || TEXLOADED(shaderstate.curtexnums->reflectmask)) && p->permu[perm|PERMUTATION_REFLECTCUBEMASK].h.loaded)
perm |= PERMUTATION_REFLECTCUBEMASK;
#if MAXRLIGHTMAPS > 1
if (shaderstate.curbatch->lightmap[1] >= 0 && p->permu[perm|PERMUTATION_LIGHTSTYLES].h.loaded)
perm |= PERMUTATION_LIGHTSTYLES;
#endif
#endif
GL_SelectProgram(p->permu[perm].h.glsl.handle);
GL_SelectProgram(permu->h.glsl.handle);
#ifndef FORCESTATE
if (shaderstate.lastuniform == shaderstate.currentprogram)
i = true;
@ -3851,7 +3823,7 @@ static void BE_RenderMeshProgram(const shader_t *shader, const shaderpass_t *pas
i = false;
shaderstate.lastuniform = shaderstate.currentprogram;
}
BE_Program_Set_Attributes(p, perm, i);
BE_Program_Set_Attributes(p, permu, i);
BE_SendPassBlendDepthMask(pass->shaderbits);
@ -3892,8 +3864,8 @@ static void BE_RenderMeshProgram(const shader_t *shader, const shaderpass_t *pas
GL_LazyBind(--shaderstate.lastpasstmus, 0, r_nulltex);
shaderstate.lastpasstmus = i; //in case it was already lower
}
BE_EnableShaderAttributes(p->permu[perm].attrmask, shaderstate.sourcevbo->vao);
BE_SubmitMeshChain(p->permu[perm].h.glsl.usetesselation);
BE_EnableShaderAttributes(permu->attrmask, shaderstate.sourcevbo->vao);
BE_SubmitMeshChain(permu->h.glsl.usetesselation);
}
qboolean GLBE_LightCullModel(vec3_t org, model_t *model)

@ -84,6 +84,7 @@ typedef unsigned int FT_Pixel_Mode; //for consistency even without freetype supp
#define FT_PIXEL_MODE_RGBA_SA (100) //RGBA, straight alpha. not in freetype.
#define FT_PIXEL_MODE_RGBA (101) //RGBA, premultiplied alpha. not in freetype.
#ifdef QUAKEHUD
static const char *imgs[] =
{
//0xe10X
@ -188,6 +189,7 @@ static const char *imgs[] =
"e16e",
"e16f"
};
#endif
#define FONT_MAXCHARS 0x110000 //as defined by UTF-16, and thus applied to all unicode because UTF-16 is the crappy limited one.
#define FONTBLOCKS ((FONT_MAXCHARS+FONTBLOCKSIZE-1)/FONTBLOCKSIZE)
@ -288,7 +290,8 @@ typedef struct font_s
//texture/screen pixel sizes.
unsigned char bmw;
unsigned char bmh;
//unsigned short pad;
unsigned short flags;
#define CHARF_FORCEWHITE (1u<<0) //coloured emoji should not be tinted.
//screen offsets.
short top;
@ -643,6 +646,7 @@ static struct charcache_s *Font_LoadGlyphData(font_t *f, CHARIDXTYPE charidx, FT
fontplanes.oldestchar = c;
fontplanes.newestchar = c;
c->nextchar = NULL;
c->flags = 0;
c->texplane = fontplanes.activeplane;
c->bmx = fontplanes.planerowx+pad;
@ -748,6 +752,8 @@ static struct charcache_s *Font_LoadGlyphData(font_t *f, CHARIDXTYPE charidx, FT
*(unsigned int *)&out[x*4] = BORDERCOLOUR;
out += PLANEWIDTH*4;
}
c->flags = CHARF_FORCEWHITE; //private glyph colours
}
else if ((unsigned int)pixelmode == FT_PIXEL_MODE_RGBA)
{ //bgra srgb font, already premultiplied
@ -774,6 +780,8 @@ static struct charcache_s *Font_LoadGlyphData(font_t *f, CHARIDXTYPE charidx, FT
*(unsigned int *)&out[x*4] = BORDERCOLOUR;
out += PLANEWIDTH*4;
}
c->flags = CHARF_FORCEWHITE; //private glyph colours
}
fontplanes.planechanged = true;
return c;
@ -976,6 +984,7 @@ static struct charcache_s *Font_TryLoadGlyph(font_t *f, CHARIDXTYPE charidx)
}
#endif
#ifdef QUAKEHUD
if (charidx >= 0xe100 && charidx <= 0xe1ff)
{
qpic_t *wadimg;
@ -1029,6 +1038,7 @@ static struct charcache_s *Font_TryLoadGlyph(font_t *f, CHARIDXTYPE charidx)
c = Font_LoadGlyphData(f, charidx, FT_PIXEL_MODE_RGBA_SA, img, nw, nh, 64*4);
if (c)
{
c->flags = CHARF_FORCEWHITE; //private glyph colours
c->left = 0;
c->top = f->charheight - nh;
c->advance = nw;
@ -1036,6 +1046,7 @@ static struct charcache_s *Font_TryLoadGlyph(font_t *f, CHARIDXTYPE charidx)
}
}
}
#endif
/*make tab invisible*/
if (charidx == '\t' || charidx == '\n')
{
@ -2866,10 +2877,20 @@ int Font_DrawChar(int px, int py, unsigned int charflags, unsigned int codepoint
font_coord[v+3][0] = sx;
font_coord[v+3][1] = sy+sh;
*(int*)font_forecoloura[v+0] = *(int*)font_forecolour;
*(int*)font_forecoloura[v+1] = *(int*)font_forecolour;
*(int*)font_forecoloura[v+2] = *(int*)font_forecolour;
*(int*)font_forecoloura[v+3] = *(int*)font_forecolour;
if (c->flags&CHARF_FORCEWHITE)
{
*(int*)font_forecoloura[v+0] =
*(int*)font_forecoloura[v+1] =
*(int*)font_forecoloura[v+2] =
*(int*)font_forecoloura[v+3] = 0xffffffff;
}
else
{
*(int*)font_forecoloura[v+0] =
*(int*)font_forecoloura[v+1] =
*(int*)font_forecoloura[v+2] =
*(int*)font_forecoloura[v+3] = *(int*)font_forecolour;
}
if (font_colourmask & CON_NONCLEARBG)
{

@ -5486,10 +5486,10 @@ void Terr_Brush_Draw(heightmap_t *hm, batch_t **batches, entity_t *e)
size_t numindicies = 0;
int w, h, lmnum;
float scale[2];
#ifdef RUNTIMELIGHTING
lightmapinfo_t *lm;
qboolean dorelight = true;
#ifdef RUNTIMELIGHTING
//FIXME: lightmaps
//if we're enabling lightmaps, make sure all surfaces have known sizes first.
//allocate lightmap space for all surfaces, and then rebuild all textures.

@ -269,7 +269,7 @@ qboolean QDECL Mod_LoadHLModel (model_t *mod, void *buffer, size_t fsize)
if (header->version != 10)
{
Con_Printf(CON_ERROR "Cannot load model %s - unknown version %i\n", mod->name, header->version);
Con_Printf(CON_ERROR "Cannot load halflife model %s - unknown version %i\n", mod->name, header->version);
return false;
}

@ -4950,7 +4950,7 @@ void ModBrush_LoadGLStuff(void *ctx, void *data, size_t a, size_t b)
mod->textures[a]->shader = R_RegisterShader_Lightmap(va("%s#BUMPMODELSPACE", mod->textures[a]->name));
R_BuildDefaultTexnums(NULL, mod->textures[a]->shader, IF_WORLDTEX);
mod->textures[a+mod->numtexinfo]->shader = R_RegisterShader_Vertex (mod->textures[a+mod->numtexinfo]->name);
mod->textures[a+mod->numtexinfo]->shader = R_RegisterShader_Vertex (va("%s#VERTEXLIT", mod->textures[a+mod->numtexinfo]->name));
R_BuildDefaultTexnums(NULL, mod->textures[a+mod->numtexinfo]->shader, IF_WORLDTEX);
}
}
@ -4961,7 +4961,7 @@ void ModBrush_LoadGLStuff(void *ctx, void *data, size_t a, size_t b)
mod->textures[a]->shader = R_RegisterShader_Lightmap(mod->textures[a]->name);
R_BuildDefaultTexnums(NULL, mod->textures[a]->shader, IF_WORLDTEX);
mod->textures[a+mod->numtexinfo]->shader = R_RegisterShader_Vertex (mod->textures[a+mod->numtexinfo]->name);
mod->textures[a+mod->numtexinfo]->shader = R_RegisterShader_Vertex (va("%s#VERTEXLIT", mod->textures[a+mod->numtexinfo]->name));
R_BuildDefaultTexnums(NULL, mod->textures[a+mod->numtexinfo]->shader, IF_WORLDTEX);
}
}

@ -32,7 +32,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#include <ctype.h>
extern texid_t missing_texture;
texid_t r_whiteimage;
texid_t r_whiteimage, r_blackimage;
qboolean shader_reload_needed;
static qboolean shader_rescan_needed;
static char **saveshaderbody;
@ -189,15 +189,15 @@ skipwhite:
return com_token;
}
static float Shader_FloatArgument(shader_t *shader, char *arg)
static float Com_FloatArgument(const char *shadername, char *arg, size_t arglen)
{
char *var;
int arglen = strlen(arg);
const char *var;
//grab an argument instead, otherwise 0
var = shader->name;
var = shadername;
while((var = strchr(var, '#')))
{
var++;
if (!strnicmp(var, arg, arglen))
{
if (var[arglen] == '=')
@ -209,6 +209,7 @@ static float Shader_FloatArgument(shader_t *shader, char *arg)
}
return 0; //not present.
}
#define Shader_FloatArgument(s,k) (Com_FloatArgument(s->name,k,strlen(k)))
@ -315,7 +316,7 @@ static qboolean Shader_EvaluateCondition(shader_t *shader, char **ptr)
token++;
if (*token == '#')
lhs = !!Shader_FloatArgument(shader, token);
lhs = !!Shader_FloatArgument(shader, token+1);
else if (!Q_stricmp(token, "lpp"))
lhs = r_lightprepass;
else if (!Q_stricmp(token, "lightmap"))
@ -495,7 +496,7 @@ static float Shader_ParseFloat(shader_t *shader, char **ptr, float defaultval)
{
if (token[1] == '#')
{
return Shader_FloatArgument(shader, token+1);
return Shader_FloatArgument(shader, token+2);
}
else
{
@ -1121,7 +1122,6 @@ static qboolean Shader_ParseProgramCvar(char *script, cvar_t **cvarrefs, char **
cvarnames[0] = Z_Malloc(script - namestart + 1);
memcpy(cvarnames[0], namestart, script - namestart);
cvarnames[0][script - namestart] = 0;
cvarnames[1] = NULL;
while (*script == ' ' || *script == '\t')
script++;
@ -1176,46 +1176,127 @@ const struct sh_defaultsamplers_s sh_defaultsamplers[] =
{NULL}
};
/*program text is already loaded, this function parses the 'header' of it to see which permutations it provides, and how many times we need to recompile it*/
static struct
{
char *name;
unsigned int bitmask;
} permutations[] =
{
{"BUMP", PERMUTATION_BUMPMAP},
{"FULLBRIGHT", PERMUTATION_FULLBRIGHT},
{"UPPERLOWER", PERMUTATION_UPPERLOWER},
{"REFLECTCUBEMASK", PERMUTATION_REFLECTCUBEMASK},
{"SKELETAL", PERMUTATION_SKELETAL},
{"FOG", PERMUTATION_FOG},
{"FRAMEBLEND", PERMUTATION_FRAMEBLEND},
{"LIGHTSTYLED", PERMUTATION_LIGHTSTYLES}
};
#define MAXMODIFIERS 64
void VARGS Q_strlcatfz (char *dest, size_t *offset, size_t size, const char *fmt, ...) LIKEPRINTF(4);
void VARGS Q_strlcatfz (char *dest, size_t *offset, size_t size, const char *fmt, ...)
{
va_list argptr;
dest += *offset;
size -= *offset;
va_start (argptr, fmt);
Q_vsnprintfz(dest, size, fmt, argptr);
va_end (argptr);
*offset += strlen(dest);
}
struct programpermu_s *Shader_LoadPermutation(program_t *prog, unsigned int p)
{
const char *permutationdefines[3];
struct programpermu_s *pp;
size_t n, pn = 0;
char defines[8192];
size_t offset;
extern cvar_t gl_specular, gl_specular_power;
if (~prog->supportedpermutations & p)
return NULL; //o.O
pp = Z_Malloc(sizeof(*pp));
pp->permutation = p;
*defines = 0;
offset = 0;
if (p & PERMUTATION_SKELETAL)
Q_strlcatfz(defines, &offset, sizeof(defines), "#define MAX_GPU_BONES %i\n", sh_config.max_gpu_bones);
if (gl_specular.value)
Q_strlcatfz(defines, &offset, sizeof(defines), "#define SPECULAR\n#define SPECULAR_BASE_MUL %f\n#define SPECULAR_BASE_POW %f\n", 1.0*gl_specular.value, max(1,gl_specular_power.value));
for (n = 0; n < countof(permutations); n++)
{
if (p & permutations[n].bitmask)
Q_strlcatfz(defines, &offset, sizeof(defines), "#define %s\n", permutations[n].name);
}
if (p & PERMUTATION_UPPERLOWER)
Q_strlcatfz(defines, &offset, sizeof(defines), "#define UPPER\n#define LOWER\n");
if (p & PERMUTATION_BUMPMAP)
{
if (r_glsl_offsetmapping.ival)
{
Q_strlcatfz(defines, &offset, sizeof(defines), "#define OFFSETMAPPING\n");
if (r_glsl_offsetmapping_reliefmapping.ival && (p & PERMUTATION_BUMPMAP))
Q_strlcatfz(defines, &offset, sizeof(defines), "#define RELIEFMAPPING\n");
}
if (r_deluxemapping) //fixme: should be per-model really
Q_strlcatfz(defines, &offset, sizeof(defines), "#define DELUXE\n");
}
permutationdefines[pn++] = defines;
permutationdefines[pn++] = prog->preshade;
permutationdefines[pn++] = NULL;
if (!sh_config.pCreateProgram(prog, pp, prog->shaderver, permutationdefines, prog->shadertext, prog->tess?prog->shadertext:NULL, prog->tess?prog->shadertext:NULL, prog->geom?prog->shadertext:NULL, prog->shadertext, prog->warned, NULL))
prog->warned = true;
//extra loop to validate the programs actually linked properly.
//delaying it like this gives certain threaded drivers a chance to compile them all while we're messing around with other junk
if (sh_config.pValidateProgram && !sh_config.pValidateProgram(prog, pp, prog->warned, NULL))
prog->warned = true;
if (sh_config.pProgAutoFields)
{
cvar_t *cvarrefs[64];
char *cvarnames[64+1];
int cvartypes[64];
unsigned char *cvardata = prog->cvardata;
size_t size = prog->cvardatasize, i;
for (i = 0; i < countof(cvartypes) && size; i++)
{
memcpy(&cvartypes[i], cvardata, sizeof(int));
cvarnames[i] = cvardata+sizeof(int);
size -= sizeof(int)+strlen(cvarnames[i])+1;
cvardata += sizeof(int)+strlen(cvarnames[i])+1;
cvarrefs[i] = Cvar_FindVar(cvarnames[i]);
}
cvarnames[i] = NULL; //no more
sh_config.pProgAutoFields(prog, pp, cvarrefs, cvarnames, cvartypes);
}
return pp;
}
static qboolean Shader_LoadPermutations(char *name, program_t *prog, char *script, int qrtype, int ver, char *blobfilename)
{
#if defined(GLQUAKE) || defined(D3DQUAKE)
static struct
{
char *name;
unsigned int bitmask;
} permutations[] =
{
{"#define BUMP\n", PERMUTATION_BUMPMAP},
{"#define FULLBRIGHT\n", PERMUTATION_FULLBRIGHT},
{"#define UPPERLOWER\n", PERMUTATION_UPPERLOWER},
{"#define REFLECTCUBEMASK\n", PERMUTATION_REFLECTCUBEMASK},
{"#define SKELETAL\n", PERMUTATION_SKELETAL},
{"#define FOG\n", PERMUTATION_FOG},
{"#define FRAMEBLEND\n", PERMUTATION_FRAMEBLEND},
{"#define LIGHTSTYLED\n", PERMUTATION_LIGHTSTYLES}
};
#define MAXMODIFIERS 64
const char *permutationdefines[countof(permutations) + MAXMODIFIERS + 1];
// const char *permutationdefines[countof(permutations) + MAXMODIFIERS + 1];
unsigned int nopermutation = PERMUTATIONS-1;
int nummodifiers = 0;
int p, n, pn;
// int nummodifiers = 0;
int p;
char *end;
vfsfile_t *blobfile;
unsigned int permuoffsets[PERMUTATIONS], initoffset=0;
unsigned int blobheaderoffset=0;
qboolean blobadded;
qboolean geom = false;
qboolean tess = false;
qboolean cantess = false;
char maxgpubones[128];
cvar_t *cvarrefs[64];
char *cvarnames[64];
int cvartypes[64];
int cvarcount = 0;
qboolean onefailed = false;
size_t cvarcount = 0, i;
extern cvar_t gl_specular, gl_specular_power;
qboolean cantess; //not forced.
char prescript[8192];
size_t offset = 0;
#endif
#ifdef VKQUAKE
@ -1237,8 +1318,15 @@ static qboolean Shader_LoadPermutations(char *name, program_t *prog, char *scrip
if (!sh_config.pCreateProgram && !sh_config.pLoadBlob)
return false;
cvarnames[cvarcount] = NULL;
if (prog->name)
return false; //o.O
*prescript = 0;
offset = 0;
memset(prog->permu, 0, sizeof(prog->permu));
prog->name = Z_StrDup(name);
prog->geom = false;
prog->tess = false;
prog->nofixedcompat = true;
prog->numsamplers = 0;
prog->defaulttextures = 0;
@ -1253,52 +1341,94 @@ static qboolean Shader_LoadPermutations(char *name, program_t *prog, char *scrip
}
else if (!strncmp(script, "!!geom", 6))
{
geom = true;
prog->geom = true;
script += 6;
}
else if (!strncmp(script, "!!tess", 6))
{
tess = true;
prog->tess = true;
script += 6;
}
else if (!strncmp(script, "!!samps", 7))
{
com_tokentype_t tt;
qboolean ignore = false;
script += 7;
while (*script != '\n' && *script != '\r')
for(;;)
{
size_t len;
int i;
char *start;
while (*script == ' ' || *script == '\t')
script++;
start = script;
while (*script != ' ' && *script != '\t' && *script != '\r' && *script != '\n')
script++;
char *type, *idx, *next;
char *token = com_token;
next = COM_ParseTokenOut(script, "", com_token, sizeof(com_token), &tt);
if (tt == TTP_LINEENDING || tt == TTP_EOF)
break;
script = next;
if (*token == '=' || *token == '!')
{
len = strlen(token);
if (*token == (Com_FloatArgument(name, token+1, len-1)?'!':'='))
ignore = true;
continue;
}
else if (ignore)
continue;
#ifndef NOLEGACY
if (script-start >= 8 && !strncmp(start, "deluxmap", 8))
else if (!strncmp(token, "deluxmap", 8))
{ //FIXME: remove this some time.
start = va("deluxemap%s",start+8);
len = strlen(start);
token = va("deluxemap%s",token+8);
}
else
#endif
len = script-start;
for (i = 0; sh_defaultsamplers[i].name; i++)
{
if (!strncmp(start, sh_defaultsamplers[i].name+2, len) && sh_defaultsamplers[i].name[2+len] == 0)
type = strchr(token, ':');
idx = strchr(token, '=');
if (type || idx)
{ //name:type=idx
if (type)
*type++ = 0;
else
type = "sampler2D";
if (idx)
{
prog->defaulttextures |= sh_defaultsamplers[i].defaulttexbits;
break;
*idx++ = 0;
i = atoi(idx);
}
else
i = prog->numsamplers;
if (prog->numsamplers < i+1)
prog->numsamplers = i+1;
//I really want to use layout(binding = %i) here, but its specific to the glsl version (which we don't really know yet)
Q_strlcatfz(prescript, &offset, sizeof(prescript), "#define s_%s s_t%u\nuniform %s s_%s;\n", token, i, type, token);
}
if (!sh_defaultsamplers[i].name)
else
{
i = atoi(start);
if (i)
prog->numsamplers = i;
else
Con_Printf("Unknown texture name in %s\n", name);
len = strlen(token);
for (i = 0; sh_defaultsamplers[i].name; i++)
{
if (!strcmp(token, sh_defaultsamplers[i].name+2))
{
prog->defaulttextures |= sh_defaultsamplers[i].defaulttexbits;
break;
}
}
if (!sh_defaultsamplers[i].name)
{ //this path is deprecated.
i = atoi(token);
if (i)
{
if (qrenderer == QR_OPENGL)
{
while (prog->numsamplers < i)
Q_strlcatfz(prescript, &offset, sizeof(prescript), "uniform sampler2D s_t%u;\n", prog->numsamplers++);
}
else if (prog->numsamplers < i)
prog->numsamplers = i;
}
else
Con_Printf("Unknown texture name in %s\n", name);
}
}
}
}
@ -1350,7 +1480,7 @@ static qboolean Shader_LoadPermutations(char *name, program_t *prog, char *scrip
end = script;
while ((*end >= 'A' && *end <= 'Z') || (*end >= 'a' && *end <= 'z') || (*end >= '0' && *end <= '9') || *end == '_')
end++;
if (nummodifiers < MAXMODIFIERS && end - script < 64)
if (end - script < 64)
{
cvar_t *var;
char namebuf[64];
@ -1375,20 +1505,20 @@ static qboolean Shader_LoadPermutations(char *name, program_t *prog, char *scrip
if (srgb)
{
if (type == '4')
permutationdefines[nummodifiers++] = Z_StrDup(va("#define %s %s(%g,%g,%g,%g)\n", namebuf, ((qrenderer == QR_OPENGL)?"vec4":"float4"), SRGBf(var->vec4[0]/div), SRGBf(var->vec4[1]/div), SRGBf(var->vec4[2]/div), var->vec4[3]/div));
Q_strlcatfz(prescript, &offset, sizeof(prescript), "#define %s %s(%g,%g,%g,%g)\n", namebuf, ((qrenderer == QR_OPENGL)?"vec4":"float4"), SRGBf(var->vec4[0]/div), SRGBf(var->vec4[1]/div), SRGBf(var->vec4[2]/div), var->vec4[3]/div);
else if (type == '3')
permutationdefines[nummodifiers++] = Z_StrDup(va("#define %s %s(%g,%g,%g)\n", namebuf, ((qrenderer == QR_OPENGL)?"vec3":"float3"), SRGBf(var->vec4[0]/div), SRGBf(var->vec4[1]/div), SRGBf(var->vec4[2]/div)));
Q_strlcatfz(prescript, &offset, sizeof(prescript), "#define %s %s(%g,%g,%g)\n", namebuf, ((qrenderer == QR_OPENGL)?"vec3":"float3"), SRGBf(var->vec4[0]/div), SRGBf(var->vec4[1]/div), SRGBf(var->vec4[2]/div));
else
permutationdefines[nummodifiers++] = Z_StrDup(va("#define %s %g\n", namebuf, SRGBf(var->value/div)));
Q_strlcatfz(prescript, &offset, sizeof(prescript), "#define %s %g\n", namebuf, SRGBf(var->value/div));
}
else
{
if (type == '4')
permutationdefines[nummodifiers++] = Z_StrDup(va("#define %s %s(%g,%g,%g,%g)\n", namebuf, ((qrenderer == QR_OPENGL)?"vec4":"float4"), var->vec4[0]/div, var->vec4[1]/div, var->vec4[2]/div, var->vec4[3]/div));
Q_strlcatfz(prescript, &offset, sizeof(prescript), "#define %s %s(%g,%g,%g,%g)\n", namebuf, ((qrenderer == QR_OPENGL)?"vec4":"float4"), var->vec4[0]/div, var->vec4[1]/div, var->vec4[2]/div, var->vec4[3]/div);
else if (type == '3')
permutationdefines[nummodifiers++] = Z_StrDup(va("#define %s %s(%g,%g,%g)\n", namebuf, ((qrenderer == QR_OPENGL)?"vec3":"float3"), var->vec4[0]/div, var->vec4[1]/div, var->vec4[2]/div));
Q_strlcatfz(prescript, &offset, sizeof(prescript), "#define %s %s(%g,%g,%g)\n", namebuf, ((qrenderer == QR_OPENGL)?"vec3":"float3"), var->vec4[0]/div, var->vec4[1]/div, var->vec4[2]/div);
else
permutationdefines[nummodifiers++] = Z_StrDup(va("#define %s %g\n", namebuf, var->value/div));
Q_strlcatfz(prescript, &offset, sizeof(prescript), "#define %s %g\n", namebuf, var->value/div);
}
}
}
@ -1396,17 +1526,17 @@ static qboolean Shader_LoadPermutations(char *name, program_t *prog, char *scrip
}
else if (!strncmp(script, "!!cvarf", 7))
{
if (cvarcount+1 != sizeof(cvarnames)/sizeof(cvarnames[0]))
if (cvarcount != sizeof(cvarnames)/sizeof(cvarnames[0]))
cvarcount += Shader_ParseProgramCvar(script+7, &cvarrefs[cvarcount], &cvarnames[cvarcount], &cvartypes[cvarcount], SP_CVARF);
}
else if (!strncmp(script, "!!cvari", 7))
{
if (cvarcount+1 != sizeof(cvarnames)/sizeof(cvarnames[0]))
if (cvarcount != sizeof(cvarnames)/sizeof(cvarnames[0]))
cvarcount += Shader_ParseProgramCvar(script+7, &cvarrefs[cvarcount], &cvarnames[cvarcount], &cvartypes[cvarcount], SP_CVARI);
}
else if (!strncmp(script, "!!cvarv", 7))
{
if (cvarcount+1 != sizeof(cvarnames)/sizeof(cvarnames[0]))
if (cvarcount != sizeof(cvarnames)/sizeof(cvarnames[0]))
cvarcount += Shader_ParseProgramCvar(script+7, &cvarrefs[cvarcount], &cvarnames[cvarcount], &cvartypes[cvarcount], SP_CVAR3F);
}
else if (!strncmp(script, "!!permu", 7))
@ -1419,7 +1549,7 @@ static qboolean Shader_LoadPermutations(char *name, program_t *prog, char *scrip
end++;
for (p = 0; p < countof(permutations); p++)
{
if (!strncmp(permutations[p].name+8, script, end - script) && permutations[p].name[8+end-script] == '\n')
if (!strncmp(permutations[p].name, script, end - script) && permutations[p].name[end-script] == '\0')
{
nopermutation &= ~permutations[p].bitmask;
break;
@ -1451,7 +1581,7 @@ static qboolean Shader_LoadPermutations(char *name, program_t *prog, char *scrip
minver = strtol(script, &script, 0);
while (*script == ' ' || *script == '\t')
script++;
maxver = strtol(script, NULL, 0);
maxver = strtol(script, NULL, 0);
if (!maxver)
maxver = minver;
@ -1481,284 +1611,86 @@ static qboolean Shader_LoadPermutations(char *name, program_t *prog, char *scrip
while (*script && *script != '\n')
script++;
};
prog->shadertext = Z_StrDup(script);
if (qrenderer == qrtype && ver < 150)
tess = cantess = false; //GL_ARB_tessellation_shader requires glsl 150(gl3.2) (or glessl 3.1). nvidia complains about layouts if you try anyway
if (sh_config.pLoadBlob && blobfilename && *blobfilename)
blobfile = FS_OpenVFS(blobfilename, "w+b", FS_GAMEONLY);
else
blobfile = NULL;
prog->tess = cantess = false; //GL_ARB_tessellation_shader requires glsl 150(gl3.2) (or glessl 3.1). nvidia complains about layouts if you try anyway
if (!r_fog_permutation.ival)
nopermutation |= PERMUTATION_BIT_FOG;
if (blobfile)
{
unsigned int magic;
unsigned int corrupt = false;
char ever[MAX_QPATH];
char *thisever = version_string();
corrupt |= VFS_READ(blobfile, &magic, sizeof(magic)) != sizeof(magic);
corrupt |= magic != *(unsigned int*)"FBLB";
corrupt |= VFS_READ(blobfile, &blobheaderoffset, sizeof(blobheaderoffset)) != sizeof(blobheaderoffset);
corrupt |= VFS_READ(blobfile, ever, sizeof(ever)) != sizeof(ever);
corrupt |= strcmp(ever, thisever);
//if the magic or header didn't read properly then the file is corrupt
if (corrupt)
{
//close and reopen it without the + flag, to replace it with a new file.
VFS_CLOSE(blobfile);
blobfile = FS_OpenVFS(blobfilename, "wb", FS_GAMEONLY);
if (blobfile)
{
blobheaderoffset = 0;
VFS_SEEK(blobfile, 0);
magic = *(unsigned int*)"FBLB"; //magic
VFS_WRITE(blobfile, &magic, sizeof(magic));
VFS_WRITE(blobfile, &blobheaderoffset, sizeof(blobheaderoffset));
memset(ever, 0, sizeof(ever)); //make sure we don't leak stuff.
Q_strncpyz(ever, thisever, sizeof(ever));
VFS_WRITE(blobfile, ever, sizeof(ever));
blobheaderoffset = 0;
}
}
}
blobadded = false;
if (!sh_config.max_gpu_bones)
{
Q_snprintfz(maxgpubones, sizeof(maxgpubones), "");
nopermutation |= PERMUTATION_SKELETAL;
}
else if (qrenderer == QR_OPENGL && sh_config.maxver < 120) //with old versions of glsl (including gles), mat3x4 is not supported, and we have to emulate it with 3*vec4. maybe we should just do that unconditionally, but whatever.
Q_snprintfz(maxgpubones, sizeof(maxgpubones), "#define MAX_GPU_BONES %i\n#define PACKEDBONES\n", sh_config.max_gpu_bones);
else
Q_snprintfz(maxgpubones, sizeof(maxgpubones), "#define MAX_GPU_BONES %i\n", sh_config.max_gpu_bones);
if (gl_specular.value)
{
if (nummodifiers < MAXMODIFIERS)
permutationdefines[nummodifiers++] = Z_StrDup(va("#define SPECULAR\n#define SPECULAR_BASE_MUL %f\n#define SPECULAR_BASE_POW %f\n", 1.0*gl_specular.value, max(1,gl_specular_power.value)));
}
//multiple lightmaps is kinda hacky. if any are set, all must be.
#define ALTLIGHTMAPSAMP 13
if (prog->defaulttextures & ((1u<<(ALTLIGHTMAPSAMP+0)) | (1u<<(ALTLIGHTMAPSAMP+1)) | (1u<<(ALTLIGHTMAPSAMP+2))))
prog->defaulttextures |=((1u<<(ALTLIGHTMAPSAMP+0)) | (1u<<(ALTLIGHTMAPSAMP+1)) | (1u<<(ALTLIGHTMAPSAMP+2)));
#define ALTDELUXMAPSAMP 16
if (prog->defaulttextures & ((1u<<(ALTDELUXMAPSAMP+0)) | (1u<<(ALTDELUXMAPSAMP+1)) | (1u<<(ALTDELUXMAPSAMP+2))))
prog->defaulttextures |=((1u<<(ALTDELUXMAPSAMP+0)) | (1u<<(ALTDELUXMAPSAMP+1)) | (1u<<(ALTDELUXMAPSAMP+2)));
for (end = strchr(name, '#'); end && *end; )
{
char *start = end+1, *d;
char *start = end+1;
end = strchr(start, '#');
if (!end)
end = start + strlen(start);
if (end-start == 7 && !Q_strncasecmp(start, "usemods", 7))
prog->nofixedcompat = false;
if (nummodifiers < MAXMODIFIERS)
{
if (end-start == 4 && !Q_strncasecmp(start, "tess", 4))
tess |= cantess;
permutationdefines[nummodifiers] = d = BZ_Malloc(10 + end - start);
memcpy(d, "#define ", 8);
memcpy(d+8, start, end - start);
memcpy(d+8+(end-start), "\n", 2);
start = strchr(d+8, '=');
if (start)
*start = ' ';
for (start = d+8; *start; start++)
*start = toupper(*start);
nummodifiers++;
permutationdefines[nummodifiers] = NULL;
}
}
if (blobfile)
{
unsigned int next;
unsigned int argsz;
char *args, *mp;
const char *mv;
int ml, mi;
unsigned int bloblink = 4;
if (end-start == 4 && !Q_strncasecmp(start, "tess", 4))
prog->tess |= cantess;
//walk through looking for an argset match
while (blobheaderoffset)
Q_strlcatfz(prescript, &offset, sizeof(prescript), "#define ");
while (offset < sizeof(prescript) && start < end)
{
VFS_SEEK(blobfile, blobheaderoffset);
VFS_READ(blobfile, &next, sizeof(next));
VFS_READ(blobfile, &argsz, sizeof(argsz));
args = Z_Malloc(argsz+1);
VFS_READ(blobfile, args, argsz);
args[argsz] = 0;
for (mi = 0, mp = args; mi < nummodifiers; mi++)
{
mv = permutationdefines[mi]+8;
ml = strlen(mv);
if (mp+ml > args+argsz)
break;
if (strncmp(mp, mv, ml))
break;
mp += ml;
}
//this one is a match.
if (mi == nummodifiers && mp == args+argsz)
if (*start == '=')
{
blobheaderoffset = VFS_TELL(blobfile);
VFS_READ(blobfile, permuoffsets, sizeof(permuoffsets));
start++;
prescript[offset++] = ' ';
break;
}
bloblink = blobheaderoffset;
blobheaderoffset = next;
}
//these arguments have never been seen before. add a new argset.
if (!blobheaderoffset)
{
unsigned int link = 0;
initoffset = VFS_GETLEN(blobfile);
VFS_SEEK(blobfile, initoffset);
VFS_WRITE(blobfile, &link, sizeof(link));
for (mi = 0, argsz = 0; mi < nummodifiers; mi++)
{
mv = permutationdefines[mi]+8;
ml = strlen(mv);
argsz += ml;
}
VFS_WRITE(blobfile, &argsz, sizeof(argsz));
for (mi = 0; mi < nummodifiers; mi++)
{
mv = permutationdefines[mi]+8;
ml = strlen(mv);
VFS_WRITE(blobfile, mv, ml);
}
//and the offsets come here
blobheaderoffset = VFS_TELL(blobfile);
memset(permuoffsets, 0, sizeof(permuoffsets));
VFS_WRITE(blobfile, permuoffsets, sizeof(permuoffsets));
//now rewrite the link to add us. the value in the file should always be set to 0.
VFS_SEEK(blobfile, bloblink);
VFS_WRITE(blobfile, &initoffset, sizeof(initoffset));
prescript[offset++] = toupper(*start++);
}
while (offset < sizeof(prescript) && start < end)
prescript[offset++] = toupper(*start++);
Q_strlcatfz(prescript, &offset, sizeof(prescript), "\n");
}
prog->tess = tess;
prog->supportedpermutations = ~nopermutation;
for (p = 0; p < PERMUTATIONS; p++)
{
qboolean isprimary;
memset(&prog->permu[p].h, 0, sizeof(prog->permu[p].h));
if (nopermutation & p)
{
continue;
}
pn = nummodifiers;
for (n = 0; n < countof(permutations); n++)
{
if (p & permutations[n].bitmask)
permutationdefines[pn++] = permutations[n].name;
}
isprimary = (pn-nummodifiers)==1;
if (p & PERMUTATION_UPPERLOWER)
permutationdefines[pn++] = "#define UPPER\n#define LOWER\n";
if (p & PERMUTATION_SKELETAL)
permutationdefines[pn++] = maxgpubones;
if (p & PERMUTATION_BUMPMAP)
{
if (r_glsl_offsetmapping.ival)
{
permutationdefines[pn++] = "#define OFFSETMAPPING\n";
if (r_glsl_offsetmapping_reliefmapping.ival && (p & PERMUTATION_BUMPMAP))
permutationdefines[pn++] = "#define RELIEFMAPPING\n";
}
if (r_deluxemapping) //fixme: should be per-model really
permutationdefines[pn++] = "#define DELUXE\n";
}
permutationdefines[pn++] = NULL;
if (blobfile && permuoffsets[p])
{
VFS_SEEK(blobfile, permuoffsets[p]);
if (sh_config.pLoadBlob(prog, name, p, blobfile))
continue; //blob was loaded from disk, yay.
//otherwise fall through.
}
if (blobfile && !sh_config.pValidateProgram)
{
initoffset = VFS_GETLEN(blobfile);
VFS_SEEK(blobfile, initoffset);
}
#define SILENTPERMUTATIONS (developer.ival?0:PERMUTATION_SKELETAL)
if (!sh_config.pCreateProgram(prog, name, p, ver, permutationdefines, script, tess?script:NULL, tess?script:NULL, geom?script:NULL, script, (p & SILENTPERMUTATIONS)?true:onefailed, sh_config.pValidateProgram?NULL:blobfile))
{
if (isprimary)
prog->supportedpermutations &= ~p;
if (!(p & SILENTPERMUTATIONS))
onefailed = true; //don't flag it if skeletal failed.
if (!p) //give up if permutation 0 failed. that one failing is fatal.
break;
}
if (!sh_config.pValidateProgram && blobfile && initoffset != VFS_GETLEN(blobfile))
{
permuoffsets[p] = initoffset;
blobadded = true;
}
}
while(nummodifiers)
Z_Free((char*)permutationdefines[--nummodifiers]);
prog->preshade = Z_StrDup(prescript);
prog->supportedpermutations = (~nopermutation) & (PERMUTATIONS-1);
//extra loop to validate the programs actually linked properly.
//delaying it like this gives certain threaded drivers a chance to compile them all while we're messing around with other junk
if (sh_config.pValidateProgram)
for (p = 0; p < PERMUTATIONS; p++)
if (cvarcount)
{
if (nopermutation & p)
continue;
if (blobfile)
*prescript = 0;
offset = 0;
for (i = 0; i < cvarcount && offset < sizeof(prescript); i++)
{
initoffset = VFS_GETLEN(blobfile);
VFS_SEEK(blobfile, initoffset);
}
if (!sh_config.pValidateProgram(prog, name, p, (p & PERMUTATION_SKELETAL)?true:onefailed, blobfile))
{
if (!(p & PERMUTATION_SKELETAL))
if (cvarrefs[i])
{
onefailed = true; //don't flag it if skeletal failed.
continue;
memcpy(prescript+offset, &cvartypes[i], sizeof(int));
offset+=4;
Q_strlcatfz(prescript, &offset, sizeof(prescript), "%s", cvarnames[i]);
offset++;
}
if (!p)
break;
}
if (blobfile && initoffset != VFS_GETLEN(blobfile))
{
permuoffsets[p] = initoffset;
blobadded = true;
}
prog->cvardata = Z_Malloc(offset);
prog->cvardatasize = offset;
memcpy(prog->cvardata, prescript, prog->cvardatasize);
}
if (sh_config.pProgAutoFields)
sh_config.pProgAutoFields(prog, name, cvarrefs, cvarnames, cvartypes);
while(cvarcount)
Z_Free((char*)cvarnames[--cvarcount]);
if (blobfile && blobadded)
{
VFS_SEEK(blobfile, blobheaderoffset);
VFS_WRITE(blobfile, permuoffsets, sizeof(permuoffsets));
}
if (blobfile)
VFS_CLOSE(blobfile);
if (p == PERMUTATIONS)
return true;
#endif
//ensure that permutation 0 works correctly as a fallback.
//FIXME: add debug mode to compile all.
prog->permu[0] = Shader_LoadPermutation(prog, 0);
return !!prog->permu[0];
#else
return false;
#endif
}
typedef struct sgeneric_s
{
program_t prog;
@ -1783,6 +1715,10 @@ void Shader_UnloadProg(program_t *prog)
if (sh_config.pDeleteProg)
sh_config.pDeleteProg(prog);
Z_Free(prog->name);
Z_Free(prog->preshade);
Z_Free(prog->shadertext);
Z_Free(prog);
}
static void Shader_FlushGenerics(void)
@ -1847,6 +1783,12 @@ static void Shader_LoadGeneric(sgeneric_t *g, int qrtype)
{
sh_config.pDeleteProg(&g->prog);
}
Z_Free(g->prog.name);
g->prog.name = NULL;
Z_Free(g->prog.preshade);
g->prog.preshade = NULL;
Z_Free(g->prog.shadertext);
g->prog.shadertext = NULL;
if (file)
{
@ -1879,17 +1821,6 @@ static void Shader_LoadGeneric(sgeneric_t *g, int qrtype)
}
}
const char *Shader_NameForGeneric(program_t *prog)
{
sgeneric_t *g;
for (g = sgenerics; g; g = g->next)
{
if (prog == &g->prog)
return g->name;
}
return "INLINE";
}
program_t *Shader_FindGeneric(char *name, int qrtype)
{
sgeneric_t *g;
@ -3743,6 +3674,8 @@ qboolean Shader_Init (void)
r_whiteimage = r_nulltex;
else
r_whiteimage = R_LoadTexture("$whiteimage", 4, 4, TF_RGBA32, wibuf, IF_NOMIPMAP|IF_NOPICMIP|IF_NEAREST|IF_NOGAMMA);
memset(wibuf, 0, sizeof(wibuf));
r_blackimage = R_LoadTexture("$blackimage", 4, 4, TF_RGBA32, wibuf, IF_NOMIPMAP|IF_NOPICMIP|IF_NEAREST|IF_NOGAMMA);
Shader_NeedReload(true);
Shader_DoReload();
@ -6029,7 +5962,7 @@ char *Shader_DefaultBSPWater(shader_t *s, const char *shortname, char *buffer, s
type = 3;
else
type = 0;
alpha = Shader_FloatArgument(s, "#ALPHA");
alpha = Shader_FloatArgument(s, "ALPHA");
if (alpha)
explicitalpha = true;
else
@ -6212,12 +6145,12 @@ void Shader_DefaultBSPQ2(const char *shortname, shader_t *s, const void *args)
"}\n"
);
}
else if (Shader_FloatArgument(s, "#WARP"))//!strncmp(shortname, "warp/", 5) || !strncmp(shortname, "warp33/", 7) || !strncmp(shortname, "warp66/", 7))
else if (Shader_FloatArgument(s, "WARP"))//!strncmp(shortname, "warp/", 5) || !strncmp(shortname, "warp33/", 7) || !strncmp(shortname, "warp66/", 7))
{
char tmpbuffer[2048];
Shader_DefaultScript(shortname, s, Shader_DefaultBSPWater(s, shortname, tmpbuffer, sizeof(tmpbuffer)));
}
else if (Shader_FloatArgument(s, "#ALPHA"))// !strncmp(shortname, "trans/", 6))
else if (Shader_FloatArgument(s, "ALPHA"))// !strncmp(shortname, "trans/", 6))
{
Shader_DefaultScript(shortname, s,
"{\n"
@ -6966,7 +6899,7 @@ static char *Shader_DecomposePass(char *o, shaderpass_t *p, qboolean simple)
if (p->prog)
{
sprintf(o, "program %s\n", Shader_NameForGeneric(p->prog));
sprintf(o, "program %s\n", p->prog->name);
o+=strlen(o);
}
@ -7198,7 +7131,7 @@ char *Shader_Decompose(shader_t *s)
if (s->prog)
{
sprintf(o, "program %s\n", Shader_NameForGeneric(s->prog));
sprintf(o, "program %s\n", s->prog->name);
o+=strlen(o);
p = s->passes;

@ -3713,7 +3713,7 @@ void Sh_CheckSettings(void)
#endif
#ifdef D3D9QUAKE
case QR_DIRECT3D9:
canshadowless = true;
// canshadowless = true;
//the code still has a lot of ifdefs, so will crash if you try it in a merged build.
//its not really usable in d3d-only builds either, so no great loss.
// canstencil = true;
@ -3739,7 +3739,7 @@ void Sh_CheckSettings(void)
{
//can't even do lighting
if (r_shadow_realtime_world.ival || r_shadow_realtime_dlight.ival)
Con_Printf("Missing rendering features: realtime lighting is not possible.\n");
Con_Printf("Missing rendering features: realtime %s lighting is not possible.\n", r_shadow_realtime_world.ival?"world":"dynamic");
r_shadow_realtime_world.ival = 0;
r_shadow_realtime_dlight.ival = 0;
}

@ -58,6 +58,7 @@ void (APIENTRY *qglBindFramebufferEXT)(GLenum target, GLuint id);
void (APIENTRY *qglDeleteRenderbuffersEXT)(GLsizei n, const GLuint* ids);
void (APIENTRY *qglFramebufferTexture2DEXT)(GLenum target, GLenum attachmentPoint, GLenum textureTarget, GLuint textureId, GLint level);
FTEPFNGLVERTEXATTRIBPOINTER qglVertexAttribPointer;
FTEPFNGLVERTEXATTRIB4FARBPROC qglVertexAttrib4f;
FTEPFNGLGETVERTEXATTRIBIV qglGetVertexAttribiv;
FTEPFNGLENABLEVERTEXATTRIBARRAY qglEnableVertexAttribArray;
FTEPFNGLDISABLEVERTEXATTRIBARRAY qglDisableVertexAttribArray;
@ -948,6 +949,7 @@ void GL_CheckExtensions (void *(*getglfunction) (char *name))
qglLinkProgramARB = NULL;
qglBindAttribLocationARB = NULL;
qglGetAttribLocationARB = NULL;
qglVertexAttrib4f = NULL;
qglVertexAttribPointer = NULL;
qglGetVertexAttribiv = NULL;
qglGetVertexAttribPointerv = NULL;
@ -1009,6 +1011,7 @@ void GL_CheckExtensions (void *(*getglfunction) (char *name))
qglUniform2fvARB = (void *)getglext("glUniform2fv");
qglUniform1iARB = (void *)getglext("glUniform1i");
qglUniform1fARB = (void *)getglext("glUniform1f");
qglVertexAttrib4f = (void *)getglext("glVertexAttrib4f");
qglVertexAttribPointer = (void *)getglext("glVertexAttribPointer");
qglGetVertexAttribiv = (void *)getglext("glGetVertexAttribiv");
qglGetVertexAttribPointerv = (void *)getglext("glGetVertexAttribPointerv");
@ -1037,6 +1040,7 @@ void GL_CheckExtensions (void *(*getglfunction) (char *name))
qglLinkProgramARB = (void *)getglext("glLinkProgramARB");
qglBindAttribLocationARB = (void *)getglext("glBindAttribLocationARB");
qglGetAttribLocationARB = (void *)getglext("glGetAttribLocationARB");
qglVertexAttrib4f = (void *)getglext("glVertexAttrib4fARB");
qglVertexAttribPointer = (void *)getglext("glVertexAttribPointerARB");
qglGetVertexAttribiv = (void *)getglext("glGetVertexAttribivARB");
qglGetVertexAttribPointerv = (void *)getglext("glGetVertexAttribPointervARB");
@ -1340,7 +1344,7 @@ static const char *glsl_hdrs[] =
"#define SPECMUL 1.0\n"
"#endif\n"
"#define FTE_SPECULAR_MULTIPLIER (SPECULAR_BASE_MUL*float(SPECMUL))\n"
#ifndef NOLEGACY
#if 0//ndef NOLEGACY
"uniform sampler2DShadow s_shadowmap;"
"uniform samplerCube s_projectionmap;"
"uniform sampler2D s_diffuse;"
@ -2118,19 +2122,8 @@ static GLhandleARB GLSlang_CreateShader (program_t *prog, const char *name, int
}
if (prog)
{ //for compat with vulkan, that injects samplers...
const char *numberedsamplernames[] =
{
"uniform sampler2D s_t0;\n",
"uniform sampler2D s_t1;\n",
"uniform sampler2D s_t2;\n",
"uniform sampler2D s_t3;\n",
"uniform sampler2D s_t4;\n",
"uniform sampler2D s_t5;\n",
"uniform sampler2D s_t6;\n",
"uniform sampler2D s_t7;\n",
};
#ifdef NOLEGACY
{ //for compat with our vulkan processor, which injects samplers in order to control layouts.
#if 1//def NOLEGACY
const char *defaultsamplernames[] =
{
"uniform sampler2DShadow s_shadowmap;\n",
@ -2160,8 +2153,6 @@ static GLhandleARB GLSlang_CreateShader (program_t *prog, const char *name, int
GLSlang_GenerateInternal(&glsl, defaultsamplernames[i]);
}
#endif
for (i = 0; i < prog->numsamplers && i < countof(numberedsamplernames); i++)
GLSlang_GenerateInternal(&glsl, numberedsamplernames[i]);
}
break;
case GL_GEOMETRY_SHADER_ARB:
@ -2210,6 +2201,9 @@ static GLhandleARB GLSlang_CreateShader (program_t *prog, const char *name, int
"#define varying out\n"
);
}
else if (ver < 120)
GLSlang_GenerateInternal(&glsl, "#define PACKEDBONES\n");
if (gl_config_nofixedfunc)
{
GLSlang_GenerateInternal(&glsl,
@ -2363,13 +2357,13 @@ static GLhandleARB GLSlang_FinishShader(GLhandleARB shader, const char *name, GL
typedesc = "???";
break;
}
Con_Printf("%s shader (%s) compilation error:\n----------\n%s----------\n", typedesc, name, str);
Con_Printf("%s shader (%s) compilation error:\n"CON_ERROR"%s"CON_DEFAULT"----------\n", typedesc, name, str);
//if there's no fixed function then failure to compile the default2d shader should be considered fatal. this should help avoid black screens on android.
if (gl_config_nofixedfunc && !strcmp(name, "default2d"))
Sys_Error("%s shader (%s) compilation error:\n----------\n%s----------\n", typedesc, name, str);
if (developer.ival)
if (developer.ival>1)
{ //could use echo console-link I guess (with embedded line numbers). shaders can get quite big though.
unsigned int line;
char *eol, *start;
@ -2582,11 +2576,13 @@ union programhandle_u GLSlang_CreateProgram(program_t *prog, const char *name, i
return ret;
}
qboolean GLSlang_ValidateProgramPermu(program_t *prog, const char *name, unsigned int permu, qboolean noerrors, vfsfile_t *blobfile)
qboolean GLSlang_ValidateProgramPermu(program_t *prog, struct programpermu_s *permu, qboolean noerrors, vfsfile_t *blobfile)
{
return GLSlang_ValidateProgram(&prog->permu[permu].h, name, noerrors, blobfile);
if (!permu)
return false;
return GLSlang_ValidateProgram(&permu->h, prog->name, noerrors, blobfile);
}
qboolean GLSlang_CreateProgramPermu(program_t *prog, const char *name, unsigned int permu, int ver, const char **precompilerconstants, const char *vert, const char *tcs, const char *tes, const char *geom, const char *frag, qboolean noerrors, vfsfile_t *blobfile)
qboolean GLSlang_CreateProgramPermu(program_t *prog, struct programpermu_s *permu, int ver, const char **precompilerconstants, const char *vert, const char *tcs, const char *tes, const char *geom, const char *frag, qboolean noerrors, vfsfile_t *blobfile)
{
if (!ver)
{
@ -2595,19 +2591,19 @@ qboolean GLSlang_CreateProgramPermu(program_t *prog, const char *name, unsigned
else
{
ver = 110;
if (sh_config.maxver>=120 && (permu & PERMUTATION_SKELETAL))
if (sh_config.maxver>=120 && (permu->permutation & PERMUTATION_SKELETAL))
ver = 120;
}
}
if ((permu & PERMUTATION_SKELETAL) && gl_config.maxattribs < 10)
if ((permu->permutation & PERMUTATION_SKELETAL) && gl_config.maxattribs < 10)
return false; //can happen in gles2
#if MAXRLIGHTMAPS > 1
if ((permu & PERMUTATION_LIGHTSTYLES) && gl_config.maxattribs < 16)
if ((permu->permutation & PERMUTATION_LIGHTSTYLES) && gl_config.maxattribs < 16)
return false; //can happen in gles2
#endif
prog->permu[permu].h = GLSlang_CreateProgram(prog, name, ver, precompilerconstants, vert, tcs, tes, geom, frag, noerrors, blobfile);
if (prog->permu[permu].h.glsl.handle)
permu->h = GLSlang_CreateProgram(prog, prog->name, ver, precompilerconstants, vert, tcs, tes, geom, frag, noerrors, blobfile);
if (permu->h.glsl.handle)
return true;
return false;
}
@ -2622,8 +2618,10 @@ GLint GLSlang_GetUniformLocation (int prog, char *name)
return i;
}
static qboolean GLSlang_LoadBlob(program_t *prog, const char *name, unsigned int permu, vfsfile_t *blobfile)
static qboolean GLSlang_LoadBlob(program_t *prog, unsigned int permu, vfsfile_t *blobfile)
{
return false;
/*
unsigned int fmt;
unsigned int length;
void *binary;
@ -2647,120 +2645,107 @@ static qboolean GLSlang_LoadBlob(program_t *prog, const char *name, unsigned int
memset(&prog->permu[permu].h, 0, sizeof(prog->permu[permu].h));
}
return !!success;
*/
}
static void GLSlang_DeleteProg(program_t *prog)
{
unsigned int permu;
struct programpermu_s *pp;
for (permu = 0; permu < countof(prog->permu); permu++)
{
if (prog->permu[permu].h.loaded)
pp = prog->permu[permu];
if (pp)
{
qglDeleteProgramObject_(prog->permu[permu].h.glsl.handle);
prog->permu[permu].h.glsl.handle = 0;
qglDeleteProgramObject_(pp->h.glsl.handle);
pp->h.glsl.handle = 0;
BZ_Free(prog->permu[permu].parm);
prog->permu[permu].parm = NULL;
prog->permu[permu].numparms = 0;
BZ_Free(pp->parm);
pp->parm = NULL;
pp->numparms = 0;
}
}
}
static void GLSlang_ProgAutoFields(program_t *prog, const char *progname, cvar_t **cvars, char **cvarnames, int *cvartypes)
static void GLSlang_ProgAutoFields(program_t *prog, struct programpermu_s *pp, cvar_t **cvars, char **cvarnames, int *cvartypes)
{
#define ALTLIGHTMAPSAMP 13
#define ALTDELUXMAPSAMP 16
unsigned int i, p;
unsigned int i;
int uniformloc;
char tmpname[128];
struct programpermu_s *pp;
int maxparms = 0;
//figure out visible attributes
for (p = 0; p < PERMUTATIONS; p++)
GLSlang_UseProgram(pp->h.glsl.handle);
for (i = 0; shader_attr_names[i].name; i++)
{
if (!prog->permu[p].h.loaded)
continue;
GLSlang_UseProgram(prog->permu[p].h.glsl.handle);
for (i = 0; shader_attr_names[i].name; i++)
uniformloc = qglGetAttribLocationARB(pp->h.glsl.handle, shader_attr_names[i].name);
if (uniformloc != -1)
{
uniformloc = qglGetAttribLocationARB(prog->permu[p].h.glsl.handle, shader_attr_names[i].name);
if (uniformloc != -1)
{
if (shader_attr_names[i].ptype != uniformloc)
Con_Printf("Bad attribute: %s\n", shader_attr_names[i].name);
else
prog->permu[p].attrmask |= 1u<<uniformloc;
}
if (shader_attr_names[i].ptype != uniformloc)
Con_Printf("Bad attribute: %s\n", shader_attr_names[i].name);
else
pp->attrmask |= 1u<<uniformloc;
}
}
prog->numsamplers = 0;
prog->defaulttextures = 0;
for (p = 0; p < PERMUTATIONS; p++)
{
int maxparms = 0;
pp = &prog->permu[p];
if (!pp->h.loaded)
continue;
pp->numparms = 0;
pp->parm = NULL;
pp->numparms = 0;
pp->parm = NULL;
GLSlang_UseProgram(prog->permu[p].h.glsl.handle); //we'll probably be setting samplers anyway.
for (i = 0; shader_unif_names[i].name; i++)
for (i = 0; shader_unif_names[i].name; i++)
{
uniformloc = qglGetUniformLocationARB(pp->h.glsl.handle, shader_unif_names[i].name);
if (uniformloc >= 0)
{
uniformloc = qglGetUniformLocationARB(pp->h.glsl.handle, shader_unif_names[i].name);
if (uniformloc >= 0)
if (pp->numparms >= maxparms)
{
if (pp->numparms >= maxparms)
{
maxparms = pp->numparms?pp->numparms * 2:8;
pp->parm = BZ_Realloc(pp->parm, sizeof(*pp->parm) * maxparms);
}
pp->parm[pp->numparms].type = shader_unif_names[i].ptype;
pp->parm[pp->numparms].handle = uniformloc;
pp->parm[pp->numparms].pval = NULL;
pp->numparms++;
maxparms = pp->numparms?pp->numparms * 2:8;
pp->parm = BZ_Realloc(pp->parm, sizeof(*pp->parm) * maxparms);
}
pp->parm[pp->numparms].type = shader_unif_names[i].ptype;
pp->parm[pp->numparms].handle = uniformloc;
pp->parm[pp->numparms].pval = NULL;
pp->numparms++;
}
}
/*set cvar uniforms*/
/*FIXME: enumerate cvars automatically instead*/
for (i = 0; cvarnames[i]; i++)
{
if (!cvars[i])
continue;
/*set cvar uniforms*/
/*FIXME: enumerate cvars automatically instead*/
for (i = 0; cvarnames[i]; i++)
{
if (!cvars[i])
continue;
Q_snprintfz(tmpname, sizeof(tmpname), "cvar_%s", cvarnames[i]);
uniformloc = qglGetUniformLocationARB(pp->h.glsl.handle, tmpname);
if (uniformloc >= 0)
Q_snprintfz(tmpname, sizeof(tmpname), "cvar_%s", cvarnames[i]);
uniformloc = qglGetUniformLocationARB(pp->h.glsl.handle, tmpname);
if (uniformloc >= 0)
{
if (pp->numparms >= maxparms)
{
if (pp->numparms >= maxparms)
{
maxparms = pp->numparms?pp->numparms * 2:8;
pp->parm = BZ_Realloc(pp->parm, sizeof(*pp->parm) * maxparms);
}
pp->parm[pp->numparms].type = cvartypes[i];
pp->parm[pp->numparms].pval = cvars[i];
pp->parm[pp->numparms].handle = uniformloc;
pp->numparms++;
maxparms = pp->numparms?pp->numparms * 2:8;
pp->parm = BZ_Realloc(pp->parm, sizeof(*pp->parm) * maxparms);
}
pp->parm[pp->numparms].type = cvartypes[i];
pp->parm[pp->numparms].pval = cvars[i];
pp->parm[pp->numparms].handle = uniformloc;
pp->numparms++;
}
}
//now scan/set texture uniforms
if (!(pp->attrmask & (1u<<VATTR_VERTEX1))) //a shader kinda has to use one of these...
pp->attrmask |= (1u<<VATTR_LEG_VERTEX);
for (i = 0; i < 8; i++)
//now scan/set texture uniforms
if (!(pp->attrmask & (1u<<VATTR_VERTEX1))) //a shader kinda has to use one of these...
pp->attrmask |= (1u<<VATTR_LEG_VERTEX);
for (i = 0; i < prog->numsamplers; i++)
{
Q_snprintfz(tmpname, sizeof(tmpname), "s_t%i", i);
uniformloc = qglGetUniformLocationARB(pp->h.glsl.handle, tmpname);
if (uniformloc != -1)
{
Q_snprintfz(tmpname, sizeof(tmpname), "s_t%i", i);
uniformloc = qglGetUniformLocationARB(pp->h.glsl.handle, tmpname);
if (uniformloc != -1)
{
qglUniform1iARB(uniformloc, i);
if (prog->numsamplers < i+1)
prog->numsamplers = i+1;
}
qglUniform1iARB(uniformloc, i);
// if (prog->numsamplers < i+1)
// prog->numsamplers = i+1;
}
}
if (developer.ival)
for (i = 0; sh_defaultsamplers[i].name; i++)
{
//figure out which ones are needed.
@ -2768,35 +2753,22 @@ static void GLSlang_ProgAutoFields(program_t *prog, const char *progname, cvar_t
continue; //don't spam
uniformloc = qglGetUniformLocationARB(pp->h.glsl.handle, sh_defaultsamplers[i].name);
if (uniformloc != -1)
prog->defaulttextures |= sh_defaultsamplers[i].defaulttexbits;
Con_Printf("glsl \"%s\" needs %s but doesn't declare so\n", prog->name, sh_defaultsamplers[i].name);
}
}
//multiple lightmaps is kinda hacky. if any are set, all must be.
if (prog->defaulttextures & ((1u<<(ALTLIGHTMAPSAMP+0)) | (1u<<(ALTLIGHTMAPSAMP+1)) | (1u<<(ALTLIGHTMAPSAMP+2))))
prog->defaulttextures |=((1u<<(ALTLIGHTMAPSAMP+0)) | (1u<<(ALTLIGHTMAPSAMP+1)) | (1u<<(ALTLIGHTMAPSAMP+2)));
if (prog->defaulttextures & ((1u<<(ALTDELUXMAPSAMP+0)) | (1u<<(ALTDELUXMAPSAMP+1)) | (1u<<(ALTDELUXMAPSAMP+2))))
prog->defaulttextures |=((1u<<(ALTDELUXMAPSAMP+0)) | (1u<<(ALTDELUXMAPSAMP+1)) | (1u<<(ALTDELUXMAPSAMP+2)));
if (prog->defaulttextures)
{
unsigned int sampnum;
unsigned int sampnum = prog->numsamplers;
/*set default texture uniforms now that we know the right sampler ids*/
for (p = 0; p < PERMUTATIONS; p++)
for (i = 0; sh_defaultsamplers[i].name; i++)
{
if (!prog->permu[p].h.glsl.handle)
continue;
sampnum = prog->numsamplers;
GLSlang_UseProgram(prog->permu[p].h.glsl.handle);
for (i = 0; sh_defaultsamplers[i].name; i++)
if (prog->defaulttextures & sh_defaultsamplers[i].defaulttexbits)
{
if (prog->defaulttextures & sh_defaultsamplers[i].defaulttexbits)
{
uniformloc = qglGetUniformLocationARB(prog->permu[p].h.glsl.handle, sh_defaultsamplers[i].name);
if (uniformloc != -1)
qglUniform1iARB(uniformloc, sampnum);
sampnum++;
}
uniformloc = qglGetUniformLocationARB(pp->h.glsl.handle, sh_defaultsamplers[i].name);
if (uniformloc != -1)
qglUniform1iARB(uniformloc, sampnum);
sampnum++;
}
}
}
@ -3019,6 +2991,7 @@ void GL_ForgetPointers(void)
qglLinkProgramARB = NULL;
qglBindAttribLocationARB = NULL;
qglGetAttribLocationARB = NULL;
qglVertexAttrib4f = NULL;
qglVertexAttribPointer = NULL;
qglGetVertexAttribiv = NULL;
qglGetVertexAttribPointerv = NULL;

@ -84,6 +84,7 @@ static qboolean XVK_SetupSurface_XCB(void);
#include <X11/keysym.h>
#include <X11/cursorfont.h>
#include <wchar.h>
static Display *vid_dpy = NULL;
static Cursor vid_nullcursor; //'cursor' to use when none should be shown
@ -210,15 +211,18 @@ static struct
XIC (*pXCreateIC)(XIM im, ...);
void (*pXSetICFocus)(XIC ic);
void (*pXUnsetICFocus)(XIC ic);
char * (*pXGetICValues)(XIC ic, ...);
char * (*pXGetICValues)(XIC ic, ...);
char * (*pXSetICValues)(XIC ic, ...);
Bool (*pXFilterEvent)(XEvent *event, Window w);
int (*pXutf8LookupString)(XIC ic, XKeyPressedEvent *event, char *buffer_return, int bytes_buffer, KeySym *keysym_return, Status *status_return);
int (*pXwcLookupString)(XIC ic, XKeyPressedEvent *event, wchar_t *buffer_return, int bytes_buffer, KeySym *keysym_return, Status *status_return);
void (*pXDestroyIC)(XIC ic);
Status (*pXCloseIM)(XIM im);
qboolean dounicode;
int ime_shown;
XIC unicodecontext;
XIM inputmethod;
XPoint ime_pos;
struct
{
@ -325,6 +329,7 @@ static qboolean x11_initlib(void)
x11.pXSetICFocus = Sys_GetAddressForName(x11.lib, "XSetICFocus");
x11.pXUnsetICFocus = Sys_GetAddressForName(x11.lib, "XUnsetICFocus");
x11.pXGetICValues = Sys_GetAddressForName(x11.lib, "XGetICValues");
x11.pXSetICValues = Sys_GetAddressForName(x11.lib, "XSetICValues");
x11.pXFilterEvent = Sys_GetAddressForName(x11.lib, "XFilterEvent");
x11.pXutf8LookupString = Sys_GetAddressForName(x11.lib, "Xutf8LookupString");
x11.pXwcLookupString = Sys_GetAddressForName(x11.lib, "XwcLookupString");
@ -1687,6 +1692,171 @@ static void X_ShutdownUnicode(void)
x11.inputmethod = NULL;
x11.dounicode = false;
}
static int XIMPreEditStartCallback(XIC ic, XPointer client_data, XPointer call_data)
{
Z_Free(vid.ime_preview); //just in case
vid.ime_preview = NULL;
vid.ime_previewlen = 0;
// Con_Printf("XIMPreEditStartCallback\n");
return -1; //length of string we can handle (negative for unlimited)
}
static void XIMPreEditDoneCallback(XIC ic, XPointer client_data, XPointer call_data)
{
// Con_Printf("XIMPreEditDoneCallback\n");
Z_Free(vid.ime_preview);
vid.ime_preview = NULL;
vid.ime_previewlen = 0;
}
static void XIMPreEditDrawCallback(XIM ic, XPointer client_data, XIMPreeditDrawCallbackStruct *d)
{
//if chg_length, wipe chg_length chars @chg_first.
//if text, insert at chg_first (with per-char feedback properties)
//if feedback (without text) then change text char flags
//caret should then be moved accordingly.
// Con_Printf("XIMPreEditDrawCallback %i %i %i %i %s\n", d->caret, d->chg_first, d->chg_length, d->text?d->text->encoding_is_wchar:0, d->text?d->text->string.multi_byte:"???");
conchar_t *part[3];
size_t clen[3], c;
conchar_t *n;
unsigned int wc;
unsigned int defaultfl = CON_WHITEMASK, fl;
if (d->chg_length || (d->text && d->text->length))
{
//so inputs are in terms of chars.
//our conchar_t struct is variable-sized (*sigh*), so we always use our longchar encoding.
//so we end up with two conchars per wchar.
part[0] = vid.ime_preview;
clen[0] = bound(0, d->chg_first, vid.ime_previewlen/2)*2;
part[1] = NULL;
clen[1] = 0;
part[2] = part[0]+clen[0] + bound(0, d->chg_length, vid.ime_previewlen/2)*2;
clen[2] = 0;
if (part[2])
while (part[2][clen[2]])
clen[2]+=1;
if (d->text && d->text->encoding_is_wchar && d->text->string.wide_char)
{
part[1] = alloca(d->text->length * 2*sizeof(wchar_t));
for (c = 0; c < d->text->length; c++)
{
wc = d->text->string.wide_char[c];
if (!wc)
break; //erk? nulls confuse things
part[1][c*2+0] = CON_LONGCHAR|(wc>>16);
part[1][c*2+1] = defaultfl|(wc&CON_CHARMASK);
}
clen[1] = c*2;
}
else if (d->text && !d->text->encoding_is_wchar && d->text->string.multi_byte)
{
const char *in = d->text->string.multi_byte;
int error;
part[1] = alloca(d->text->length * 2*sizeof(wchar_t));
//FIXME: d->text->length is meant to be chars, but fcitx always reports 1.
for (c = 0; c < d->text->length; c++)
{
//FIXME: This should use mbcstowcs, but that would require switching locales all the frikkin time, which isn't thread-safe.
wc = utf8_decode(&error, in, &in);
if (!wc)
break; //abort if there's a null...
part[1][c*2+0] = CON_LONGCHAR|(wc>>16);
part[1][c*2+1] = defaultfl|(wc&CON_CHARMASK);
}
clen[1] = c*2;
}
n = Z_Malloc((clen[0]+clen[1]+clen[2]+1)*sizeof(*n));
memcpy(n, part[0], clen[0]*sizeof(*n));
memcpy(n+clen[0], part[1], clen[1]*sizeof(*n));
memcpy(n+clen[0]+clen[1], part[2], clen[2]*sizeof(*n));
n[clen[0]+clen[1]+clen[2]] = 0;
Z_Free(vid.ime_preview);
vid.ime_preview = n;
vid.ime_previewlen = clen[0]+clen[1]+clen[2];
}
if (d->text && d->text->feedback && d->chg_first >= 0 && d->chg_first+d->text->length <= vid.ime_previewlen/2)
{
for (c = 0; c < d->text->length; c++)
{
fl = defaultfl;
if (d->text->feedback[c] & XIMPrimary)
fl = COLOR_RED<<CON_FGSHIFT;
if (d->text->feedback[c] & XIMSecondary)
fl = COLOR_GREEN<<CON_FGSHIFT;
if (d->text->feedback[c] & XIMTertiary)
fl = COLOR_BLUE<<CON_FGSHIFT;
if (d->text->feedback[c] & XIMUnderline)
fl = COLOR_MAGENTA<<CON_FGSHIFT;
if (d->text->feedback[c] & XIMReverse)
fl = ((fl&CON_FGMASK) << (CON_BGSHIFT-CON_FGSHIFT)) | ((fl&CON_BGMASK) >> (CON_BGSHIFT-CON_FGSHIFT));
if (d->text->feedback[c] & XIMHighlight)
fl |= CON_2NDCHARSETTEXT;
vid.ime_preview[(d->chg_first+c)*2+1] = ((vid.ime_preview[(d->chg_first+c)*2+1])&~CON_FLAGSMASK)|fl;
}
}
vid.ime_caret = bound(0, d->caret, vid.ime_previewlen/2)*2;
}
static void XIMPreEditCaretCallback(XIC ic, XPointer client_data, XIMPreeditCaretCallbackStruct *d)
{
// Con_Printf("XIMPreEditCaretCallback %i %i %i\n", d->direction, d->position, d->style);
}
static qboolean XIMSupportedStyle(XIMStyle preedit, XIMStyle status)
{
if (!( //preedit==XIMPreeditCallbacks|| //FIXME: this should actually work, but we still need an ime that actually supports it properly to be sure.
//preedit==XIMPreeditPosition||
//preedit==XIMPreeditArea|| //FIXME: assume the bottom half of the screen
preedit==XIMPreeditNothing||
preedit==XIMPreeditNone))
return false;
if (!( //status==XIMStatusCallbacks||
//status==XIMStatusArea||
status==XIMStatusNothing||
status==XIMStatusNone))
return false;
return true;
}
static XIMStyle XIMPreferredStyle(XIMStyle old, XIMStyle new)
{ //favour the more complicated (supported) preedit styles, *THEN* choose the preferred status style.
XIMStyle p1 = old&0x00ff;
XIMStyle p2 = new&0x00ff;
XIMStyle s1 = old&0xff00;
XIMStyle s2 = new&0xff00;
if (!XIMSupportedStyle(p2, s2))
return old;
if (!XIMSupportedStyle(p1, s1))
return new;
if (p1 != p2)
{ //choose based upon the preedit flags
if ((p1^p2)&XIMPreeditCallbacks) //FIXME: support this one properly some time.
return (p1&XIMPreeditCallbacks)?old:new;
if ((p1^p2)&XIMPreeditPosition)
return (p1&XIMPreeditPosition)?old:new;
if ((p1^p2)&XIMPreeditArea)
return (p1&XIMPreeditArea)?old:s2;
if ((p1^p2)&XIMPreeditNothing)
return (p1&XIMPreeditNothing)?old:new;
if ((p1^p2)&XIMPreeditNone)
return (p1&XIMPreeditNone)?old:new;
}
else
{ //preedit flags are equal, now pick the better
if ((s1^s2)&XIMStatusCallbacks)
return (s1&XIMStatusCallbacks)?old:new;
if ((s1^s2)&XIMStatusArea)
return (s1&XIMStatusArea)?old:new;
if ((s1^s2)&XIMStatusNothing)
return (s1&XIMStatusNothing)?old:new;
if ((s1^s2)&XIMStatusNone)
return (s1&XIMStatusNone)?old:new;
}
//difference not known. stick with the first
return old;
}
#include <locale.h>
static long X_InitUnicode(void)
{
@ -1694,12 +1864,13 @@ static long X_InitUnicode(void)
X_ShutdownUnicode();
//FIXME: enable by default if ubuntu's issue can ever be resolved.
if (X11_CheckFeature("xim", false))
if (X11_CheckFeature("xim", true))
{
if (x11.pXSetLocaleModifiers && x11.pXSupportsLocale && x11.pXOpenIM && x11.pXGetIMValues && x11.pXCreateIC && x11.pXSetICFocus && x11.pXUnsetICFocus && x11.pXGetICValues && x11.pXFilterEvent && (x11.pXutf8LookupString || x11.pXwcLookupString) && x11.pXDestroyIC && x11.pXCloseIM)
if (x11.pXSetLocaleModifiers && x11.pXSupportsLocale && x11.pXOpenIM && x11.pXGetIMValues && x11.pXCreateIC && x11.pXSetICFocus && x11.pXUnsetICFocus && x11.pXGetICValues && x11.pXSetICValues && x11.pXFilterEvent && (x11.pXutf8LookupString || x11.pXwcLookupString) && x11.pXDestroyIC && x11.pXCloseIM)
{
setlocale(LC_CTYPE, ""); //just in case.
setlocale(LC_ALL, ""); //just in case.
x11.pXSetLocaleModifiers("");
if (x11.pXSupportsLocale())
{
x11.inputmethod = x11.pXOpenIM(vid_dpy, NULL, XI_RESOURCENAME, XI_RESOURCECLASS);
@ -1710,48 +1881,49 @@ static long X_InitUnicode(void)
int i;
x11.pXGetIMValues(x11.inputmethod, XNQueryInputStyle, &sup, NULL);
for (i = 0; sup && i < sup->count_styles; i++)
{ //each style will have one of each bis set.
#define prestyles (XIMPreeditNothing|XIMPreeditNone)
#define statusstyles (XIMStatusNothing|XIMStatusNone)
#define supstyles (prestyles|statusstyles)
if ((sup->supported_styles[i] & supstyles) != sup->supported_styles[i])
continue;
if ((st & prestyles) != (sup->supported_styles[i] & prestyles))
{
if ((sup->supported_styles[i] & XIMPreeditNothing) && !(st & XIMPreeditNothing))
st = sup->supported_styles[i];
else if ((sup->supported_styles[i] & XIMPreeditNone) && !(st & (XIMPreeditNone|XIMPreeditNothing)))
st = sup->supported_styles[i];
}
else
{
if ((sup->supported_styles[i] & XIMStatusNothing) && !(st & XIMStatusNothing))
st = sup->supported_styles[i];
else if ((sup->supported_styles[i] & XIMStatusNone) && !(st & (XIMStatusNone|XIMStatusNothing)))
st = sup->supported_styles[i];
}
}
st = XIMPreferredStyle(st, sup->supported_styles[i]);
x11.pXFree(sup);
Con_DPrintf("Chosen XIM Input Style: %x\n", (unsigned)st);
// st=XIMPreeditCallbacks|XIMStatusArea;
// st=XIMPreeditCallbacks|XIMStatusNothing;
if (st != 0)
{
XIMCallback pe_cb_start={NULL,(XIMProc)XIMPreEditStartCallback};
XIMCallback pe_cb_done={NULL,(XIMProc)XIMPreEditDoneCallback};
XIMCallback pe_cb_draw={NULL,(XIMProc)XIMPreEditDrawCallback};
XIMCallback pe_cb_caret={NULL,(XIMProc)XIMPreEditCaretCallback};
void *preedit[] = {
//should probably add in fonts, but that's kinda messy if we don't know the language/charset very well
XNPreeditStartCallback, &pe_cb_start,
XNPreeditDoneCallback, &pe_cb_done,
XNPreeditDrawCallback, &pe_cb_draw,
XNPreeditCaretCallback, &pe_cb_caret,
XNSpotLocation, &x11.ime_pos,
NULL};
void *status[] = {
NULL};
x11.unicodecontext = x11.pXCreateIC(x11.inputmethod,
XNInputStyle, st,
XNClientWindow, vid_window,
XNFocusWindow, vid_window,
// XNFocusWindow, vid_window,
XNResourceName, XI_RESOURCENAME,
XNResourceClass, XI_RESOURCECLASS,
XNPreeditAttributes, preedit,
XNStatusAttributes, status,
NULL);
if (x11.unicodecontext)
{
// x11.pXSetICFocus(x11.unicodecontext);
x11.ime_shown = -1;
x11.dounicode = true;
x11.pXGetICValues(x11.unicodecontext, XNFilterEvents, &requiredevents, NULL);
requiredevents |= KeyPressMask;
}
}
}
}
setlocale(LC_CTYPE, "C");
setlocale(LC_ALL, "C");
}
}
@ -1772,13 +1944,14 @@ static void X_KeyEvent(XKeyEvent *ev, qboolean pressed, qboolean filtered)
keysym = x11.pXLookupKeysym(ev, 0);
if (pressed && !filtered)
{
if (x11.dounicode)
if (x11.dounicode && vid.ime_allow)
{
Status status = XLookupNone;
if (x11.pXutf8LookupString)
{
char buf1[4] = {0};
char *buf = buf1, *c;
char buf1[512] = {0};
char *buf = buf1;
const char *c;
int count = x11.pXutf8LookupString(x11.unicodecontext, (XKeyPressedEvent*)ev, buf1, sizeof(buf1), NULL, &status);
if (status == XBufferOverflow)
{
@ -1796,7 +1969,7 @@ static void X_KeyEvent(XKeyEvent *ev, qboolean pressed, qboolean filtered)
else
{
//is allowed some weird encodings...
wchar_t buf1[4] = {0};
wchar_t buf1[512] = {0};
wchar_t *buf = buf1;
int count = x11.pXwcLookupString(x11.unicodecontext, (XKeyPressedEvent*)ev, buf, sizeof(buf1), &shifted, &status);
if (status == XBufferOverflow)
@ -2073,8 +2246,14 @@ static void GetEvent(void)
x11.pXNextEvent(vid_dpy, &event);
if (x11.dounicode)
if (x11.pXFilterEvent(&event, vid_window))
{
if (x11.pXFilterEvent(&event, None))//vid_window))
{
if (vid.ime_allow)
return;
filtered = true;
}
}
switch (event.type)
{
@ -2324,8 +2503,8 @@ static void GetEvent(void)
modeswitchtime = Sys_Milliseconds() + 1500; /*fairly slow, to make sure*/
}
if (event.xfocus.window == vid_window && x11.unicodecontext)
x11.pXSetICFocus(x11.unicodecontext);
if (event.xfocus.window == vid_window)
x11.ime_shown = -1;
//we we're focusing onto the game window and we're currently fullscreen, hide the other one so alt-tab won't select that instead of a real alternate app.
// if ((fullscreenflags & FULLSCREEN_ACTIVE) && (fullscreenflags & FULLSCREEN_LEGACY) && event.xfocus.window == vid_window)
@ -2333,8 +2512,8 @@ static void GetEvent(void)
break;
case FocusOut:
//if we're already active, the decoy window shouldn't be focused anyway.
if (event.xfocus.window == vid_window && x11.unicodecontext)
x11.pXSetICFocus(x11.unicodecontext);
if (event.xfocus.window == vid_window)
x11.ime_shown = -1;
if ((fullscreenflags & FULLSCREEN_ACTIVE) && event.xfocus.window == vid_decoywindow)
{
@ -2571,7 +2750,7 @@ static void GetEvent(void)
else if (event.xselectionrequest.property != None && event.xselectionrequest.target == xa_l1string)
{ //STRING == latin1. convert as needed.
char *latin1 = alloca(strlen(cliptext)+1); //may shorten
char *in = cliptext;
const char *in = cliptext;
int c = 0;
int err;
while (*in && c < sizeof(latin1))
@ -2993,7 +3172,7 @@ static void X_StoreIcon(Window wnd)
data[0] = icon.width;
data[1] = icon.height;
for (i = 0; i < data[0]*data[1]; i++)
data[i+2] = ((unsigned int*)icon.pixel_data)[i];
data[i+2] = ((const unsigned int*)icon.pixel_data)[i];
x11.pXChangeProperty(vid_dpy, wnd, propname, proptype, 32, PropModeReplace, (void*)data, data[0]*data[1]+2);
}
@ -3840,6 +4019,28 @@ void Sys_SendKeyEvents(void)
}
if (vid_dpy && vid_window)
{
if (x11.unicodecontext)
{
qboolean want = vid.ime_allow && vid.activeapp;
XPoint pos;
if (want != x11.ime_shown)
{
x11.ime_shown = want;
if (x11.ime_shown)
x11.pXSetICFocus(x11.unicodecontext);
else
x11.pXUnsetICFocus(x11.unicodecontext);
}
pos.x = (vid.ime_position[0] * vid.pixelwidth)/vid.width;
pos.y = (vid.ime_position[1] * vid.pixelheight)/vid.height;
if (/*x11.ime_shown &&*/ (x11.ime_pos.x != pos.x || x11.ime_pos.y != pos.y))
{
void *attr[] = {XNSpotLocation, &x11.ime_pos, NULL};
x11.ime_pos = pos;
x11.pXSetICValues(x11.unicodecontext, XNPreeditAttributes, attr, NULL);
}
}
while (x11.pXPending(vid_dpy))
GetEvent();

@ -175,6 +175,7 @@ typedef void (APIENTRYP FTEPFNGLLINKPROGRAMARBPROC) (GLhandleARB programObj);
typedef void (APIENTRYP FTEPFNGLBINDATTRIBLOCATIONARBPROC) (GLhandleARB programObj, GLuint index, GLcharARB *name);
typedef GLint (APIENTRYP FTEPFNGLGETATTRIBLOCATIONARBPROC) (GLhandleARB programObj, const GLcharARB *name);
typedef void (APIENTRYP FTEPFNGLVERTEXATTRIBPOINTER) (GLuint index, GLint size, GLenum type, GLboolean normalized, GLsizei stride, const GLvoid *pointer);
typedef void (APIENTRYP FTEPFNGLVERTEXATTRIB4FARBPROC) (GLuint index, GLfloat x, GLfloat y, GLfloat z, GLfloat w);
typedef void (APIENTRYP FTEPFNGLENABLEVERTEXATTRIBARRAY) (GLuint index);
typedef void (APIENTRYP FTEPFNGLDISABLEVERTEXATTRIBARRAY) (GLuint index);
typedef GLint (APIENTRYP FTEPFNGLGETUNIFORMLOCATIONARBPROC) (GLhandleARB programObj, const GLcharARB *name);
@ -715,6 +716,7 @@ extern FTEPFNGLUNIFORM3FVARBPROC qglUniform3fvARB;
extern FTEPFNGLUNIFORM2FVARBPROC qglUniform2fvARB;
extern FTEPFNGLUNIFORM1IARBPROC qglUniform1iARB;
extern FTEPFNGLUNIFORM1FARBPROC qglUniform1fARB;
extern FTEPFNGLVERTEXATTRIB4FARBPROC qglVertexAttrib4f;
extern FTEPFNGLVERTEXATTRIBPOINTER qglVertexAttribPointer;
extern FTEPFNGLGETVERTEXATTRIBIV qglGetVertexAttribiv;
extern FTEPFNGLENABLEVERTEXATTRIBARRAY qglEnableVertexAttribArray;

@ -6,6 +6,7 @@ YOU SHOULD NOT EDIT THIS FILE BY HAND
#ifdef GLQUAKE
{QR_OPENGL, 110, "fixedemu",
"!!ver 100-450\n"
"!!samps sourcetex:0\n"
//this shader is present for support for gles/gl3core contexts
//it is single-texture-with-vertex-colours, and doesn't do anything special.
@ -29,7 +30,6 @@ YOU SHOULD NOT EDIT THIS FILE BY HAND
"}\n"
"#endif\n"
"#ifdef FRAGMENT_SHADER\n"
"uniform sampler2D s_t0;\n"
"varying vec2 tc;\n"
"#ifndef UC\n"
"varying vec4 vc;\n"
@ -40,7 +40,7 @@ YOU SHOULD NOT EDIT THIS FILE BY HAND
"float e_time;\n"
"void main ()\n"
"{\n"
"vec4 fc = texture2D(s_t0, tc) * vc;\n"
"vec4 fc = texture2D(s_sourcetex, tc) * vc;\n"
"#ifdef ALPHATEST\n"
"if (!(fc.a ALPHATEST))\n"
"discard;\n"
@ -358,7 +358,11 @@ YOU SHOULD NOT EDIT THIS FILE BY HAND
{QR_OPENGL, 110, "altwater",
"!!cvardf r_glsl_turbscale_reflect=1 //simpler scaler\n"
"!!cvardf r_glsl_turbscale_refract=1 //simpler scaler\n"
"!!samps 4 diffuse normalmap\n"
"!!samps diffuse normalmap\n"
"!!samps refract=0 //always present\n"
"!!samps =REFLECT reflect=1\n"
"!!samps =RIPPLEMAP ripplemap=2\n"
"!!samps =DEPTH refractdepth=3\n"
"#include \"sys/defs.h\"\n"
@ -446,11 +450,6 @@ YOU SHOULD NOT EDIT THIS FILE BY HAND
"#endif\n"
"#define s_refract s_t0\n"
"#define s_reflect s_t1\n"
"#define s_ripplemap s_t2\n"
"#define s_refractdepth s_t3\n"
"void main (void)\n"
"{\n"
"vec2 stc; //screen tex coords\n"
@ -1108,6 +1107,7 @@ YOU SHOULD NOT EDIT THIS FILE BY HAND
#endif
#ifdef GLQUAKE
{QR_OPENGL, 110, "bloom_blur",
"!!samps 1\n"
//apply gaussian filter
"varying vec2 tc;\n"
@ -1123,7 +1123,6 @@ YOU SHOULD NOT EDIT THIS FILE BY HAND
"#ifdef FRAGMENT_SHADER\n"
/*offset should be 1.2 pixels away from the center*/
"uniform vec3 e_glowmod;\n"
"uniform sampler2D s_t0;\n"
"void main ()\n"
"{\n"
"gl_FragColor =\n"
@ -1355,6 +1354,7 @@ YOU SHOULD NOT EDIT THIS FILE BY HAND
#ifdef GLQUAKE
{QR_OPENGL, 110, "bloom_filter",
"!!cvarv r_bloom_filter\n"
"!!samps 1\n"
//the bloom filter
//filter out any texels which are not to bloom
@ -1370,7 +1370,6 @@ YOU SHOULD NOT EDIT THIS FILE BY HAND
"#endif\n"
"#ifdef FRAGMENT_SHADER\n"
"uniform vec3 cvar_r_bloom_filter;\n"
"uniform sampler2D s_t0;\n"
"void main ()\n"
"{\n"
"gl_FragColor.rgb = (texture2D(s_t0, tc).rgb - cvar_r_bloom_filter)/(1.0-cvar_r_bloom_filter);\n"
@ -1611,6 +1610,7 @@ YOU SHOULD NOT EDIT THIS FILE BY HAND
{QR_OPENGL, 110, "bloom_final",
"!!cvarf r_bloom\n"
"!!cvarf r_bloom_retain=1.0\n"
"!!samps 4\n"
//add them together
//optionally apply tonemapping
@ -1625,10 +1625,6 @@ YOU SHOULD NOT EDIT THIS FILE BY HAND
"}\n"
"#endif\n"
"#ifdef FRAGMENT_SHADER\n"
"uniform sampler2D s_t0;\n"
"uniform sampler2D s_t1;\n"
"uniform sampler2D s_t2;\n"
"uniform sampler2D s_t3;\n"
"uniform float cvar_r_bloom;\n"
"uniform float cvar_r_bloom_retain;\n"
"void main ()\n"
@ -1872,6 +1868,7 @@ YOU SHOULD NOT EDIT THIS FILE BY HAND
#endif
#ifdef GLQUAKE
{QR_OPENGL, 110, "colourtint",
"!!samps 2\n"
//this glsl shader is useful for cubemapped post processing effects (see csaddon for an example)
"varying vec4 tf;\n"
"#ifdef VERTEX_SHADER\n"
@ -1881,8 +1878,6 @@ YOU SHOULD NOT EDIT THIS FILE BY HAND
"}\n"
"#endif\n"
"#ifdef FRAGMENT_SHADER\n"
"uniform sampler2D s_t0;\n"
"uniform sampler3D s_t1;\n"
"void main()\n"
"{\n"
"vec2 fc;\n"
@ -1918,6 +1913,7 @@ YOU SHOULD NOT EDIT THIS FILE BY HAND
"!!cvarf crep_decay\n"
"!!cvarf crep_density\n"
"!!cvarf crep_weight\n"
"!!samps 1\n"
//this is a post-processing shader, drawn in 2d
//there will be a render target containing sky surfaces drawn with crepuscular_sky, and everything else drawn with crepuscular_opaque (to mask out the sky)
@ -1939,7 +1935,6 @@ YOU SHOULD NOT EDIT THIS FILE BY HAND
"const float crep_weight = 0.2;\n"
"uniform vec3 l_lightcolour;\n"
"uniform vec3 l_lightscreen;\n"
"uniform sampler2D s_t0;\n"
"const int NUM_SAMPLES = 100;\n"
"void main()\n"
"{\n"
@ -1963,6 +1958,7 @@ YOU SHOULD NOT EDIT THIS FILE BY HAND
#endif
#ifdef GLQUAKE
{QR_OPENGL, 110, "crepuscular_sky",
"!!samps 2\n"
//pretty much a regular sky shader
//though in reality we should render a sun circle in the middle.
//still, its kinda cool to have scrolling clouds masking out parts of the sun.
@ -1979,8 +1975,6 @@ YOU SHOULD NOT EDIT THIS FILE BY HAND
"uniform float e_time;\n"
"uniform vec3 e_eyepos;\n"
"varying vec3 pos;\n"
"uniform sampler2D s_t0;\n"
"uniform sampler2D s_t1;\n"
"void main ()\n"
"{\n"
"vec2 tccoord;\n"
@ -2337,6 +2331,7 @@ YOU SHOULD NOT EDIT THIS FILE BY HAND
#ifdef GLQUAKE
{QR_OPENGL, 110, "default2d",
"!!ver 100-450\n"
"!!samps 1\n"
//this shader is present for support for gles/gl3core contexts
//it is single-texture-with-vertex-colours, and doesn't do anything special.
@ -2357,7 +2352,6 @@ YOU SHOULD NOT EDIT THIS FILE BY HAND
"}\n"
"#endif\n"
"#ifdef FRAGMENT_SHADER\n"
"uniform sampler2D s_t0;\n"
"void main ()\n"
"{\n"
"vec4 f = vc;\n"
@ -2642,6 +2636,7 @@ YOU SHOULD NOT EDIT THIS FILE BY HAND
#ifdef GLQUAKE
{QR_OPENGL, 110, "defaultadditivesprite",
"!!permu FOG\n"
"!!samps 1\n"
//meant to be used for additive stuff. presumably particles and sprites. though actually its only flashblend effects that use this at the time of writing.
//includes fog, apparently.
@ -2660,7 +2655,6 @@ YOU SHOULD NOT EDIT THIS FILE BY HAND
"}\n"
"#endif\n"
"#ifdef FRAGMENT_SHADER\n"
"uniform sampler2D s_t0;\n"
"varying vec2 tc;\n"
"varying vec4 vc;\n"
"uniform vec4 e_colourident;\n"
@ -2686,7 +2680,8 @@ YOU SHOULD NOT EDIT THIS FILE BY HAND
"!!cvarf gl_specular\n"
"!!cvardf gl_affinemodels=0\n"
"!!cvardf r_tessellation_level=5\n"
"!!samps diffuse normalmap specular fullbright upper lower paletted reflectmask reflectcube\n"
"!!samps !EIGHTBIT diffuse normalmap specular fullbright upper lower reflectmask reflectcube\n"
"!!samps =EIGHTBIT paletted 1\n"
"#include \"sys/defs.h\"\n"
@ -2883,7 +2878,6 @@ YOU SHOULD NOT EDIT THIS FILE BY HAND
"#ifdef EIGHTBIT\n"
"#define s_colourmap s_t0\n"
"uniform sampler2D s_colourmap;\n"
"#endif\n"
"affine varying vec2 tc;\n"
@ -3589,6 +3583,10 @@ YOU SHOULD NOT EDIT THIS FILE BY HAND
{QR_DIRECT3D9, 9, "defaultskin",
"!!permu FRAMEBLEND\n"
"!!permu UPPERLOWER\n"
//!!permu FULLBRIGHT
"!!samps diffuse upper lower\n"
// fullbright
"struct a2v\n"
"{\n"
"float3 pos: POSITION0;\n"
@ -3659,7 +3657,7 @@ YOU SHOULD NOT EDIT THIS FILE BY HAND
"col.rgb *= inp.light;\n"
"#ifdef FULLBRIGHT\n"
"float4 fb = tex2D(s_fullbright, inp.tc);\n"
"col.rgb = mix(col.rgb, fb.rgb, fb.a);\n"
"col.rgb = lerp(col.rgb, fb.rgb, fb.a);\n"
"#endif\n"
"return col * e_colourident;\n"
// return fog4(col * e_colourident);
@ -3753,6 +3751,7 @@ YOU SHOULD NOT EDIT THIS FILE BY HAND
#ifdef GLQUAKE
{QR_OPENGL, 110, "defaultsky",
"!!permu FOG\n"
"!!samps 2\n"
"#include \"sys/fog.h\"\n"
//regular sky shader for scrolling q1 skies
@ -3770,8 +3769,6 @@ YOU SHOULD NOT EDIT THIS FILE BY HAND
"uniform float e_time;\n"
"uniform vec3 e_eyepos;\n"
"varying vec3 pos;\n"
"uniform sampler2D s_t0;\n"
"uniform sampler2D s_t1;\n"
"void main ()\n"
"{\n"
"vec2 tccoord;\n"
@ -4094,6 +4091,8 @@ YOU SHOULD NOT EDIT THIS FILE BY HAND
#endif
#ifdef D3D9QUAKE
{QR_DIRECT3D9, 9, "defaultsky",
"!!samps 2\n"
"struct a2v\n"
"{\n"
"float4 pos: POSITION;\n"
@ -4108,11 +4107,11 @@ YOU SHOULD NOT EDIT THIS FILE BY HAND
"#ifdef VERTEX_SHADER\n"
"float4x4 m_modelviewprojection;\n"
"v2f main (a2v inp)\n"
"v2f main (in a2v inp)\n"
"{\n"
"v2f outp;\n"
"outp.pos = mul(m_modelviewprojection, inp.pos);\n"
"outp.vpos = inp.pos;\n"
"outp.vpos = inp.pos.xyz;\n"
"return outp;\n"
"}\n"
"#endif\n"
@ -4137,7 +4136,6 @@ YOU SHOULD NOT EDIT THIS FILE BY HAND
"tccoord = (dir.xy + e_time*0.0625);\n"
"float4 clouds = tex2D(s_fullbright, tccoord);\n"
"return float4((solid.rgb*(1.0-clouds.a)) + (clouds.a*clouds.rgb), 1);\n"
"}\n"
"#endif\n"
@ -4498,6 +4496,8 @@ YOU SHOULD NOT EDIT THIS FILE BY HAND
#endif
#ifdef D3D9QUAKE
{QR_DIRECT3D9, 9, "defaultskybox",
"!!samps reflectcube\n"
"struct a2v\n"
"{\n"
"float4 pos: POSITION;\n"
@ -4834,6 +4834,7 @@ YOU SHOULD NOT EDIT THIS FILE BY HAND
#ifdef GLQUAKE
{QR_OPENGL, 110, "defaultsprite",
"!!permu FOG\n"
"!!samps 1\n"
//used by both particles and sprites.
//note the fog blending mode is all that differs from defaultadditivesprite
@ -4851,7 +4852,6 @@ YOU SHOULD NOT EDIT THIS FILE BY HAND
"}\n"
"#endif\n"
"#ifdef FRAGMENT_SHADER\n"
"uniform sampler2D s_t0;\n"
"varying vec2 tc;\n"
"varying vec4 vc;\n"
"uniform vec4 e_colourident;\n"
@ -5204,7 +5204,11 @@ YOU SHOULD NOT EDIT THIS FILE BY HAND
"!!permu REFLECTCUBEMASK\n"
"!!cvarf r_glsl_offsetmapping_scale\n"
"!!cvardf r_tessellation_level=5\n"
"!!samps diffuse lightmap specular normalmap fullbright reflectmask reflectcube paletted lightmap1 lightmap2 lightmap3 deluxemap deluxemap1 deluxemap2 deluxemap3\n"
"!!samps !EIGHTBIT diffuse specular normalmap fullbright reflectmask reflectcube\n"
//diffuse gives us alpha, and prevents dlight from bugging out when there's no diffuse.
"!!samps =EIGHTBIT paletted 1 specular diffuse\n"
"!!samps lightmap deluxemap\n"
"!!samps =LIGHTSTYLED lightmap1 lightmap2 lightmap3 deluxemap deluxemap1 deluxemap2 deluxemap3\n"
"#include \"sys/defs.h\"\n"
@ -5419,10 +5423,7 @@ YOU SHOULD NOT EDIT THIS FILE BY HAND
"#ifdef FRAGMENT_SHADER\n"
//samplers
"#define s_colourmap s_t0\n"
"uniform sampler2D s_colourmap;\n"
"#ifdef OFFSETMAPPING\n"
"#include \"sys/offsetmapping.h\"\n"
@ -6958,6 +6959,8 @@ YOU SHOULD NOT EDIT THIS FILE BY HAND
#ifdef D3D9QUAKE
{QR_DIRECT3D9, 9, "defaultwarp",
"!!cvarf r_wateralpha\n"
"!!samps diffuse\n"
"struct a2v {\n"
"float4 pos: POSITION;\n"
"float2 tc: TEXCOORD0;\n"
@ -7054,6 +7057,7 @@ YOU SHOULD NOT EDIT THIS FILE BY HAND
#ifdef GLQUAKE
{QR_OPENGL, 110, "defaultgammacb",
"!!ver 100-450\n"
"!!samps 1\n"
//this shader is applies gamma/contrast/brightness to the source image, and dumps it out.
"varying vec2 tc;\n"
@ -7070,7 +7074,6 @@ YOU SHOULD NOT EDIT THIS FILE BY HAND
"}\n"
"#endif\n"
"#ifdef FRAGMENT_SHADER\n"
"uniform sampler2D s_t0;\n"
"void main ()\n"
"{\n"
"gl_FragColor = pow(texture2D(s_t0, tc) * vc.g, vec4(vc.r)) + vc.b;\n"
@ -7300,6 +7303,7 @@ YOU SHOULD NOT EDIT THIS FILE BY HAND
"!!cvard_srgb_b r_floorcolor\n"
"!!cvard_srgb_b r_wallcolor\n"
"!!permu FOG\n"
"!!samps lm:0\n"
//this is for the '286' preset walls, and just draws lightmaps coloured based upon surface normals.
@ -7322,11 +7326,10 @@ YOU SHOULD NOT EDIT THIS FILE BY HAND
"}\n"
"#endif\n"
"#ifdef FRAGMENT_SHADER\n"
"uniform sampler2D s_t0;\n"
"varying vec2 lm;\n"
"void main ()\n"
"{\n"
"gl_FragColor = fog4(col * texture2D(s_t0, lm));\n"
"gl_FragColor = fog4(col * texture2D(s_lm, lm));\n"
"}\n"
"#endif\n"
},
@ -7665,6 +7668,7 @@ YOU SHOULD NOT EDIT THIS FILE BY HAND
{QR_DIRECT3D9, 9, "drawflat_wall",
"!!cvard3 r_floorcolour\n"
"!!cvard3 r_wallcolour\n"
"!!samps 1\n"
//FIXME !!permu FOG
"struct a2v {\n"
@ -8146,6 +8150,7 @@ YOU SHOULD NOT EDIT THIS FILE BY HAND
#ifdef GLQUAKE
{QR_OPENGL, 110, "postproc_fisheye",
"!!cvarf ffov\n"
"!!samps screen:samplerCube=0\n"
//fisheye view rendering, for silly fovs that are still playable.
@ -8159,7 +8164,6 @@ YOU SHOULD NOT EDIT THIS FILE BY HAND
"}\n"
"#endif\n"
"#ifdef FRAGMENT_SHADER\n"
"uniform samplerCube s_t0;\n"
"varying vec2 texcoord;\n"
"uniform float cvar_ffov;\n"
"void main()\n"
@ -8173,7 +8177,7 @@ YOU SHOULD NOT EDIT THIS FILE BY HAND
"tc.x = sin(ang.x) * cos(ang.y); \n"
"tc.y = sin(ang.x) * sin(ang.y); \n"
"tc.z = cos(ang.x); \n"
"gl_FragColor = textureCube(s_t0, tc);\n"
"gl_FragColor = textureCube(s_screen, tc);\n"
"}\n"
"#endif\n"
},
@ -8423,6 +8427,7 @@ YOU SHOULD NOT EDIT THIS FILE BY HAND
#ifdef GLQUAKE
{QR_OPENGL, 110, "postproc_panorama",
"!!cvarf ffov\n"
"!!samps screen:samplerCube=0\n"
//panoramic view rendering, for promo map shots or whatever.
@ -8436,7 +8441,6 @@ YOU SHOULD NOT EDIT THIS FILE BY HAND
"}\n"
"#endif\n"
"#ifdef FRAGMENT_SHADER\n"
"uniform samplerCube s_t0;\n"
"varying vec2 texcoord;\n"
"uniform float cvar_ffov;\n"
"void main()\n"
@ -8447,7 +8451,7 @@ YOU SHOULD NOT EDIT THIS FILE BY HAND
"tc.x = sin(ang); \n"
"tc.y = -texcoord.y; \n"
"tc.z = cos(ang); \n"
"gl_FragColor = textureCube(s_t0, tc);\n"
"gl_FragColor = textureCube(s_screen, tc);\n"
"}\n"
"#endif\n"
},
@ -8678,6 +8682,7 @@ YOU SHOULD NOT EDIT THIS FILE BY HAND
#ifdef GLQUAKE
{QR_OPENGL, 110, "postproc_laea",
"!!cvarf ffov\n"
"!!samps screen:samplerCube=0\n"
//my attempt at lambert azimuthal equal-area view rendering, because you'll remember that name easily.
@ -8696,7 +8701,6 @@ YOU SHOULD NOT EDIT THIS FILE BY HAND
"}\n"
"#endif\n"
"#ifdef FRAGMENT_SHADER\n"
"uniform samplerCube s_t0;\n"
"varying vec2 texcoord;\n"
"void main()\n"
"{\n"
@ -8718,7 +8722,7 @@ YOU SHOULD NOT EDIT THIS FILE BY HAND
"tc.y *= -1.0;\n"
"tc.z *= -1.0;\n"
"gl_FragColor = textureCube(s_t0, tc);\n"
"gl_FragColor = textureCube(s_screen, tc);\n"
"}\n"
"}\n"
"#endif\n"
@ -8727,6 +8731,7 @@ YOU SHOULD NOT EDIT THIS FILE BY HAND
#ifdef GLQUAKE
{QR_OPENGL, 110, "postproc_stereographic",
"!!cvarf ffov\n"
"!!samps screen:samplerCube=0\n"
//stereographic view rendering, for high fovs that are still playable.
@ -8745,7 +8750,6 @@ YOU SHOULD NOT EDIT THIS FILE BY HAND
"}\n"
"#endif\n"
"#ifdef FRAGMENT_SHADER\n"
"uniform samplerCube s_t0;\n"
"varying vec2 texcoord;\n"
"void main()\n"
"{\n"
@ -8760,7 +8764,7 @@ YOU SHOULD NOT EDIT THIS FILE BY HAND
"tc.y = -2.0*d.y/div;\n"
"tc.z = -(-1.0 + d.x*d.x + d.y*d.y)/div;\n"
"gl_FragColor = textureCube(s_t0, tc);\n"
"gl_FragColor = textureCube(s_screen, tc);\n"
"}\n"
"#endif\n"
},
@ -9012,6 +9016,7 @@ YOU SHOULD NOT EDIT THIS FILE BY HAND
#ifdef GLQUAKE
{QR_OPENGL, 110, "postproc_equirectangular",
"!!cvarf ffov\n"
"!!samps screen:samplerCube=0\n"
//equirectangular view rendering, commonly used for sphere->2d map projections.
@ -9025,7 +9030,6 @@ YOU SHOULD NOT EDIT THIS FILE BY HAND
"}\n"
"#endif\n"
"#ifdef FRAGMENT_SHADER\n"
"uniform samplerCube s_t0;\n"
"varying vec2 texcoord;\n"
"uniform float cvar_ffov;\n"
@ -9039,7 +9043,7 @@ YOU SHOULD NOT EDIT THIS FILE BY HAND
"tc.z = cos(lng) * sin(lat); \n"
"tc.x = sin(lng) * sin(lat);\n"
"tc.y = cos(lat);\n"
"gl_FragColor = textureCube(s_t0, tc);\n"
"gl_FragColor = textureCube(s_screen, tc);\n"
"}\n"
"#endif\n"
},
@ -9047,7 +9051,7 @@ YOU SHOULD NOT EDIT THIS FILE BY HAND
#ifdef GLQUAKE
{QR_OPENGL, 110, "postproc_ascii",
"!!cvardf r_glsl_ascii_mono=0\n"
"!!samps 1\n"
"!!samps screen=0\n"
//derived from https://www.shadertoy.com/view/lssGDj
@ -9078,7 +9082,7 @@ YOU SHOULD NOT EDIT THIS FILE BY HAND
"void main(void)\n"
"{\n"
"vec2 uv = floor(texcoord.xy * e_sourcesize); //in pixels.\n"
"vec3 col = texture2D(s_t0, (floor(uv/8.0)*8.0+4.0)/e_sourcesize.xy).rgb; \n"
"vec3 col = texture2D(s_screen, (floor(uv/8.0)*8.0+4.0)/e_sourcesize.xy).rgb; \n"
"float gray = 0.3 * col.r + 0.59 * col.g + 0.11 * col.b;\n"
@ -9541,15 +9545,16 @@ YOU SHOULD NOT EDIT THIS FILE BY HAND
#ifdef GLQUAKE
{QR_OPENGL, 110, "underwaterwarp",
"!!cvarf r_waterwarp\n"
"!!samps screen=0 warp=1 edge=2\n"
//this is a post processing shader that is drawn fullscreen whenever the view is underwater.
//its generally expected to warp the view a little.
"#ifdef VERTEX_SHADER\n"
"attribute vec2 v_texcoord;\n"
"varying vec2 v_stc;\n"
"varying vec2 v_warp;\n"
"varying vec2 v_edge;\n"
"#ifdef VERTEX_SHADER\n"
"attribute vec2 v_texcoord;\n"
"uniform float e_time;\n"
"void main ()\n"
"{\n"
@ -9561,20 +9566,14 @@ YOU SHOULD NOT EDIT THIS FILE BY HAND
"}\n"
"#endif\n"
"#ifdef FRAGMENT_SHADER\n"
"varying vec2 v_stc;\n"
"varying vec2 v_warp;\n"
"varying vec2 v_edge;\n"
"uniform sampler2D s_t0;/*$currentrender*/\n"
"uniform sampler2D s_t1;/*warp image*/\n"
"uniform sampler2D s_t2;/*edge image*/\n"
"uniform vec4 e_rendertexturescale;\n"
"uniform float cvar_r_waterwarp;\n"
"void main ()\n"
"{\n"
"vec2 amp = (0.010 / 0.625) * cvar_r_waterwarp * texture2D(s_t2, v_edge).rg;\n"
"vec3 offset = (texture2D(s_t1, v_warp).rgb - 0.5) * 2.0;\n"
"vec2 amp = (0.010 / 0.625) * cvar_r_waterwarp * texture2D(s_edge, v_edge).rg;\n"
"vec3 offset = (texture2D(s_warp, v_warp).rgb - 0.5) * 2.0;\n"
"vec2 temp = v_stc + offset.xy * amp;\n"
"gl_FragColor = texture2D(s_t0, temp*e_rendertexturescale.st);\n"
"gl_FragColor = texture2D(s_screen, temp*e_rendertexturescale.st);\n"
"}\n"
"#endif\n"
},
@ -9582,11 +9581,11 @@ YOU SHOULD NOT EDIT THIS FILE BY HAND
#ifdef VKQUAKE
{QR_VULKAN, -1, "underwaterwarp",
"\xFF\x53\x50\x56\x01\x00\x00\x00\x00\x00\x00\x00\x03\x00\x00\x00\x00\x00\x00\x00\x2C\x00\x00\x00\x14\x00\x00\x00\x40\x00\x00\x00"
"\x34\x11\x00\x00\x74\x11\x00\x00\xF4\x0D\x00\x00\x01\x00\x66\x31\x72\x5F\x77\x61\x74\x65\x72\x77\x61\x72\x70\x00\x00\x00\x00\x00"
"\x03\x02\x23\x07\x00\x00\x01\x00\x06\x00\x08\x00\x69\x00\x00\x00\x00\x00\x00\x00\x11\x00\x02\x00\x01\x00\x00\x00\x0B\x00\x06\x00"
"\x20\x11\x00\x00\x60\x11\x00\x00\xF4\x0D\x00\x00\x01\x00\x66\x31\x72\x5F\x77\x61\x74\x65\x72\x77\x61\x72\x70\x00\x00\x00\x00\x00"
"\x03\x02\x23\x07\x00\x00\x01\x00\x06\x00\x08\x00\x68\x00\x00\x00\x00\x00\x00\x00\x11\x00\x02\x00\x01\x00\x00\x00\x0B\x00\x06\x00"
"\x01\x00\x00\x00\x47\x4C\x53\x4C\x2E\x73\x74\x64\x2E\x34\x35\x30\x00\x00\x00\x00\x0E\x00\x03\x00\x00\x00\x00\x00\x01\x00\x00\x00"
"\x0F\x00\x10\x00\x00\x00\x00\x00\x04\x00\x00\x00\x6D\x61\x69\x6E\x00\x00\x00\x00\x1C\x00\x00\x00\x3A\x00\x00\x00\x3F\x00\x00\x00"
"\x41\x00\x00\x00\x4A\x00\x00\x00\x5D\x00\x00\x00\x64\x00\x00\x00\x65\x00\x00\x00\x66\x00\x00\x00\x67\x00\x00\x00\x68\x00\x00\x00"
"\x41\x00\x00\x00\x49\x00\x00\x00\x5C\x00\x00\x00\x63\x00\x00\x00\x64\x00\x00\x00\x65\x00\x00\x00\x66\x00\x00\x00\x67\x00\x00\x00"
"\x03\x00\x03\x00\x02\x00\x00\x00\xC2\x01\x00\x00\x05\x00\x04\x00\x04\x00\x00\x00\x6D\x61\x69\x6E\x00\x00\x00\x00\x05\x00\x06\x00"
"\x09\x00\x00\x00\x66\x74\x65\x74\x72\x61\x6E\x73\x66\x6F\x72\x6D\x28\x00\x00\x00\x05\x00\x04\x00\x0C\x00\x00\x00\x70\x72\x6F\x6A"
"\x00\x00\x00\x00\x05\x00\x05\x00\x13\x00\x00\x00\x65\x6E\x74\x69\x74\x79\x62\x6C\x6F\x63\x6B\x00\x06\x00\x07\x00\x13\x00\x00\x00"
@ -9611,20 +9610,20 @@ YOU SHOULD NOT EDIT THIS FILE BY HAND
"\x38\x00\x00\x00\x67\x6C\x5F\x50\x65\x72\x56\x65\x72\x74\x65\x78\x00\x00\x00\x00\x06\x00\x06\x00\x38\x00\x00\x00\x00\x00\x00\x00"
"\x67\x6C\x5F\x50\x6F\x73\x69\x74\x69\x6F\x6E\x00\x05\x00\x03\x00\x3A\x00\x00\x00\x00\x00\x00\x00\x05\x00\x04\x00\x3F\x00\x00\x00"
"\x76\x5F\x73\x74\x63\x00\x00\x00\x05\x00\x05\x00\x41\x00\x00\x00\x76\x5F\x74\x65\x78\x63\x6F\x6F\x72\x64\x00\x00\x05\x00\x04\x00"
"\x4A\x00\x00\x00\x76\x5F\x77\x61\x72\x70\x00\x00\x05\x00\x04\x00\x5D\x00\x00\x00\x76\x5F\x65\x64\x67\x65\x00\x00\x05\x00\x07\x00"
"\x5F\x00\x00\x00\x63\x76\x61\x72\x5F\x72\x5F\x77\x61\x74\x65\x72\x77\x61\x72\x70\x00\x00\x00\x00\x05\x00\x05\x00\x60\x00\x00\x00"
"\x6C\x69\x67\x68\x74\x62\x6C\x6F\x63\x6B\x00\x00\x06\x00\x07\x00\x60\x00\x00\x00\x00\x00\x00\x00\x6C\x5F\x63\x75\x62\x65\x6D\x61"
"\x74\x72\x69\x78\x00\x00\x00\x00\x06\x00\x07\x00\x60\x00\x00\x00\x01\x00\x00\x00\x6C\x5F\x6C\x69\x67\x68\x74\x70\x6F\x73\x69\x74"
"\x69\x6F\x6E\x00\x06\x00\x05\x00\x60\x00\x00\x00\x02\x00\x00\x00\x6C\x70\x61\x64\x31\x00\x00\x00\x06\x00\x07\x00\x60\x00\x00\x00"
"\x03\x00\x00\x00\x6C\x5F\x6C\x69\x67\x68\x74\x63\x6F\x6C\x6F\x75\x72\x00\x00\x00\x06\x00\x05\x00\x60\x00\x00\x00\x04\x00\x00\x00"
"\x6C\x70\x61\x64\x32\x00\x00\x00\x06\x00\x08\x00\x60\x00\x00\x00\x05\x00\x00\x00\x6C\x5F\x6C\x69\x67\x68\x74\x63\x6F\x6C\x6F\x75"
"\x72\x73\x63\x61\x6C\x65\x00\x00\x06\x00\x07\x00\x60\x00\x00\x00\x06\x00\x00\x00\x6C\x5F\x6C\x69\x67\x68\x74\x72\x61\x64\x69\x75"
"\x73\x00\x00\x00\x06\x00\x07\x00\x60\x00\x00\x00\x07\x00\x00\x00\x6C\x5F\x73\x68\x61\x64\x6F\x77\x6D\x61\x70\x70\x72\x6F\x6A\x00"
"\x06\x00\x08\x00\x60\x00\x00\x00\x08\x00\x00\x00\x6C\x5F\x73\x68\x61\x64\x6F\x77\x6D\x61\x70\x73\x63\x61\x6C\x65\x00\x00\x00\x00"
"\x06\x00\x05\x00\x60\x00\x00\x00\x09\x00\x00\x00\x6C\x70\x61\x64\x33\x00\x00\x00\x05\x00\x03\x00\x62\x00\x00\x00\x00\x00\x00\x00"
"\x05\x00\x05\x00\x64\x00\x00\x00\x76\x5F\x63\x6F\x6C\x6F\x75\x72\x00\x00\x00\x00\x05\x00\x05\x00\x65\x00\x00\x00\x76\x5F\x6C\x6D"
"\x63\x6F\x6F\x72\x64\x00\x00\x00\x05\x00\x05\x00\x66\x00\x00\x00\x76\x5F\x6E\x6F\x72\x6D\x61\x6C\x00\x00\x00\x00\x05\x00\x05\x00"
"\x67\x00\x00\x00\x76\x5F\x73\x76\x65\x63\x74\x6F\x72\x00\x00\x00\x05\x00\x05\x00\x68\x00\x00\x00\x76\x5F\x74\x76\x65\x63\x74\x6F"
"\x49\x00\x00\x00\x76\x5F\x77\x61\x72\x70\x00\x00\x05\x00\x04\x00\x5C\x00\x00\x00\x76\x5F\x65\x64\x67\x65\x00\x00\x05\x00\x07\x00"
"\x5E\x00\x00\x00\x63\x76\x61\x72\x5F\x72\x5F\x77\x61\x74\x65\x72\x77\x61\x72\x70\x00\x00\x00\x00\x05\x00\x05\x00\x5F\x00\x00\x00"
"\x6C\x69\x67\x68\x74\x62\x6C\x6F\x63\x6B\x00\x00\x06\x00\x07\x00\x5F\x00\x00\x00\x00\x00\x00\x00\x6C\x5F\x63\x75\x62\x65\x6D\x61"
"\x74\x72\x69\x78\x00\x00\x00\x00\x06\x00\x07\x00\x5F\x00\x00\x00\x01\x00\x00\x00\x6C\x5F\x6C\x69\x67\x68\x74\x70\x6F\x73\x69\x74"
"\x69\x6F\x6E\x00\x06\x00\x05\x00\x5F\x00\x00\x00\x02\x00\x00\x00\x6C\x70\x61\x64\x31\x00\x00\x00\x06\x00\x07\x00\x5F\x00\x00\x00"
"\x03\x00\x00\x00\x6C\x5F\x6C\x69\x67\x68\x74\x63\x6F\x6C\x6F\x75\x72\x00\x00\x00\x06\x00\x05\x00\x5F\x00\x00\x00\x04\x00\x00\x00"
"\x6C\x70\x61\x64\x32\x00\x00\x00\x06\x00\x08\x00\x5F\x00\x00\x00\x05\x00\x00\x00\x6C\x5F\x6C\x69\x67\x68\x74\x63\x6F\x6C\x6F\x75"
"\x72\x73\x63\x61\x6C\x65\x00\x00\x06\x00\x07\x00\x5F\x00\x00\x00\x06\x00\x00\x00\x6C\x5F\x6C\x69\x67\x68\x74\x72\x61\x64\x69\x75"
"\x73\x00\x00\x00\x06\x00\x07\x00\x5F\x00\x00\x00\x07\x00\x00\x00\x6C\x5F\x73\x68\x61\x64\x6F\x77\x6D\x61\x70\x70\x72\x6F\x6A\x00"
"\x06\x00\x08\x00\x5F\x00\x00\x00\x08\x00\x00\x00\x6C\x5F\x73\x68\x61\x64\x6F\x77\x6D\x61\x70\x73\x63\x61\x6C\x65\x00\x00\x00\x00"
"\x06\x00\x05\x00\x5F\x00\x00\x00\x09\x00\x00\x00\x6C\x70\x61\x64\x33\x00\x00\x00\x05\x00\x03\x00\x61\x00\x00\x00\x00\x00\x00\x00"
"\x05\x00\x05\x00\x63\x00\x00\x00\x76\x5F\x63\x6F\x6C\x6F\x75\x72\x00\x00\x00\x00\x05\x00\x05\x00\x64\x00\x00\x00\x76\x5F\x6C\x6D"
"\x63\x6F\x6F\x72\x64\x00\x00\x00\x05\x00\x05\x00\x65\x00\x00\x00\x76\x5F\x6E\x6F\x72\x6D\x61\x6C\x00\x00\x00\x00\x05\x00\x05\x00"
"\x66\x00\x00\x00\x76\x5F\x73\x76\x65\x63\x74\x6F\x72\x00\x00\x00\x05\x00\x05\x00\x67\x00\x00\x00\x76\x5F\x74\x76\x65\x63\x74\x6F"
"\x72\x00\x00\x00\x47\x00\x04\x00\x11\x00\x00\x00\x06\x00\x00\x00\x10\x00\x00\x00\x48\x00\x04\x00\x13\x00\x00\x00\x00\x00\x00\x00"
"\x05\x00\x00\x00\x48\x00\x05\x00\x13\x00\x00\x00\x00\x00\x00\x00\x23\x00\x00\x00\x00\x00\x00\x00\x48\x00\x05\x00\x13\x00\x00\x00"
"\x00\x00\x00\x00\x07\x00\x00\x00\x10\x00\x00\x00\x48\x00\x04\x00\x13\x00\x00\x00\x01\x00\x00\x00\x05\x00\x00\x00\x48\x00\x05\x00"
@ -9647,19 +9646,19 @@ YOU SHOULD NOT EDIT THIS FILE BY HAND
"\x22\x00\x00\x00\x00\x00\x00\x00\x47\x00\x04\x00\x15\x00\x00\x00\x21\x00\x00\x00\x00\x00\x00\x00\x47\x00\x04\x00\x1C\x00\x00\x00"
"\x1E\x00\x00\x00\x00\x00\x00\x00\x48\x00\x05\x00\x38\x00\x00\x00\x00\x00\x00\x00\x0B\x00\x00\x00\x00\x00\x00\x00\x47\x00\x03\x00"
"\x38\x00\x00\x00\x02\x00\x00\x00\x47\x00\x04\x00\x3F\x00\x00\x00\x1E\x00\x00\x00\x00\x00\x00\x00\x47\x00\x04\x00\x41\x00\x00\x00"
"\x1E\x00\x00\x00\x01\x00\x00\x00\x47\x00\x04\x00\x4A\x00\x00\x00\x1E\x00\x00\x00\x01\x00\x00\x00\x47\x00\x04\x00\x5D\x00\x00\x00"
"\x1E\x00\x00\x00\x02\x00\x00\x00\x47\x00\x04\x00\x5F\x00\x00\x00\x01\x00\x00\x00\x00\x01\x00\x00\x48\x00\x04\x00\x60\x00\x00\x00"
"\x00\x00\x00\x00\x05\x00\x00\x00\x48\x00\x05\x00\x60\x00\x00\x00\x00\x00\x00\x00\x23\x00\x00\x00\x00\x00\x00\x00\x48\x00\x05\x00"
"\x60\x00\x00\x00\x00\x00\x00\x00\x07\x00\x00\x00\x10\x00\x00\x00\x48\x00\x05\x00\x60\x00\x00\x00\x01\x00\x00\x00\x23\x00\x00\x00"
"\x40\x00\x00\x00\x48\x00\x05\x00\x60\x00\x00\x00\x02\x00\x00\x00\x23\x00\x00\x00\x4C\x00\x00\x00\x48\x00\x05\x00\x60\x00\x00\x00"
"\x03\x00\x00\x00\x23\x00\x00\x00\x50\x00\x00\x00\x48\x00\x05\x00\x60\x00\x00\x00\x04\x00\x00\x00\x23\x00\x00\x00\x5C\x00\x00\x00"
"\x48\x00\x05\x00\x60\x00\x00\x00\x05\x00\x00\x00\x23\x00\x00\x00\x60\x00\x00\x00\x48\x00\x05\x00\x60\x00\x00\x00\x06\x00\x00\x00"
"\x23\x00\x00\x00\x6C\x00\x00\x00\x48\x00\x05\x00\x60\x00\x00\x00\x07\x00\x00\x00\x23\x00\x00\x00\x70\x00\x00\x00\x48\x00\x05\x00"
"\x60\x00\x00\x00\x08\x00\x00\x00\x23\x00\x00\x00\x80\x00\x00\x00\x48\x00\x05\x00\x60\x00\x00\x00\x09\x00\x00\x00\x23\x00\x00\x00"
"\x88\x00\x00\x00\x47\x00\x03\x00\x60\x00\x00\x00\x02\x00\x00\x00\x47\x00\x04\x00\x62\x00\x00\x00\x22\x00\x00\x00\x00\x00\x00\x00"
"\x47\x00\x04\x00\x62\x00\x00\x00\x21\x00\x00\x00\x01\x00\x00\x00\x47\x00\x04\x00\x64\x00\x00\x00\x1E\x00\x00\x00\x02\x00\x00\x00"
"\x47\x00\x04\x00\x65\x00\x00\x00\x1E\x00\x00\x00\x03\x00\x00\x00\x47\x00\x04\x00\x66\x00\x00\x00\x1E\x00\x00\x00\x04\x00\x00\x00"
"\x47\x00\x04\x00\x67\x00\x00\x00\x1E\x00\x00\x00\x05\x00\x00\x00\x47\x00\x04\x00\x68\x00\x00\x00\x1E\x00\x00\x00\x06\x00\x00\x00"
"\x1E\x00\x00\x00\x01\x00\x00\x00\x47\x00\x04\x00\x49\x00\x00\x00\x1E\x00\x00\x00\x01\x00\x00\x00\x47\x00\x04\x00\x5C\x00\x00\x00"
"\x1E\x00\x00\x00\x02\x00\x00\x00\x47\x00\x04\x00\x5E\x00\x00\x00\x01\x00\x00\x00\x00\x01\x00\x00\x48\x00\x04\x00\x5F\x00\x00\x00"
"\x00\x00\x00\x00\x05\x00\x00\x00\x48\x00\x05\x00\x5F\x00\x00\x00\x00\x00\x00\x00\x23\x00\x00\x00\x00\x00\x00\x00\x48\x00\x05\x00"
"\x5F\x00\x00\x00\x00\x00\x00\x00\x07\x00\x00\x00\x10\x00\x00\x00\x48\x00\x05\x00\x5F\x00\x00\x00\x01\x00\x00\x00\x23\x00\x00\x00"
"\x40\x00\x00\x00\x48\x00\x05\x00\x5F\x00\x00\x00\x02\x00\x00\x00\x23\x00\x00\x00\x4C\x00\x00\x00\x48\x00\x05\x00\x5F\x00\x00\x00"
"\x03\x00\x00\x00\x23\x00\x00\x00\x50\x00\x00\x00\x48\x00\x05\x00\x5F\x00\x00\x00\x04\x00\x00\x00\x23\x00\x00\x00\x5C\x00\x00\x00"
"\x48\x00\x05\x00\x5F\x00\x00\x00\x05\x00\x00\x00\x23\x00\x00\x00\x60\x00\x00\x00\x48\x00\x05\x00\x5F\x00\x00\x00\x06\x00\x00\x00"
"\x23\x00\x00\x00\x6C\x00\x00\x00\x48\x00\x05\x00\x5F\x00\x00\x00\x07\x00\x00\x00\x23\x00\x00\x00\x70\x00\x00\x00\x48\x00\x05\x00"
"\x5F\x00\x00\x00\x08\x00\x00\x00\x23\x00\x00\x00\x80\x00\x00\x00\x48\x00\x05\x00\x5F\x00\x00\x00\x09\x00\x00\x00\x23\x00\x00\x00"
"\x88\x00\x00\x00\x47\x00\x03\x00\x5F\x00\x00\x00\x02\x00\x00\x00\x47\x00\x04\x00\x61\x00\x00\x00\x22\x00\x00\x00\x00\x00\x00\x00"
"\x47\x00\x04\x00\x61\x00\x00\x00\x21\x00\x00\x00\x01\x00\x00\x00\x47\x00\x04\x00\x63\x00\x00\x00\x1E\x00\x00\x00\x02\x00\x00\x00"
"\x47\x00\x04\x00\x64\x00\x00\x00\x1E\x00\x00\x00\x03\x00\x00\x00\x47\x00\x04\x00\x65\x00\x00\x00\x1E\x00\x00\x00\x04\x00\x00\x00"
"\x47\x00\x04\x00\x66\x00\x00\x00\x1E\x00\x00\x00\x05\x00\x00\x00\x47\x00\x04\x00\x67\x00\x00\x00\x1E\x00\x00\x00\x06\x00\x00\x00"
"\x13\x00\x02\x00\x02\x00\x00\x00\x21\x00\x03\x00\x03\x00\x00\x00\x02\x00\x00\x00\x16\x00\x03\x00\x06\x00\x00\x00\x20\x00\x00\x00"
"\x17\x00\x04\x00\x07\x00\x00\x00\x06\x00\x00\x00\x04\x00\x00\x00\x21\x00\x03\x00\x08\x00\x00\x00\x07\x00\x00\x00\x20\x00\x04\x00"
"\x0B\x00\x00\x00\x07\x00\x00\x00\x07\x00\x00\x00\x18\x00\x04\x00\x0D\x00\x00\x00\x07\x00\x00\x00\x04\x00\x00\x00\x17\x00\x04\x00"
@ -9680,164 +9679,164 @@ YOU SHOULD NOT EDIT THIS FILE BY HAND
"\x3C\x00\x00\x00\x03\x00\x00\x00\x07\x00\x00\x00\x20\x00\x04\x00\x3E\x00\x00\x00\x03\x00\x00\x00\x12\x00\x00\x00\x3B\x00\x04\x00"
"\x3E\x00\x00\x00\x3F\x00\x00\x00\x03\x00\x00\x00\x20\x00\x04\x00\x40\x00\x00\x00\x01\x00\x00\x00\x12\x00\x00\x00\x3B\x00\x04\x00"
"\x40\x00\x00\x00\x41\x00\x00\x00\x01\x00\x00\x00\x2B\x00\x04\x00\x0F\x00\x00\x00\x42\x00\x00\x00\x00\x00\x00\x00\x20\x00\x04\x00"
"\x43\x00\x00\x00\x01\x00\x00\x00\x06\x00\x00\x00\x3B\x00\x04\x00\x3E\x00\x00\x00\x4A\x00\x00\x00\x03\x00\x00\x00\x2B\x00\x04\x00"
"\x16\x00\x00\x00\x4B\x00\x00\x00\x04\x00\x00\x00\x20\x00\x04\x00\x4C\x00\x00\x00\x02\x00\x00\x00\x06\x00\x00\x00\x2B\x00\x04\x00"
"\x06\x00\x00\x00\x4F\x00\x00\x00\x00\x00\x80\x3E\x20\x00\x04\x00\x54\x00\x00\x00\x03\x00\x00\x00\x06\x00\x00\x00\x3B\x00\x04\x00"
"\x3E\x00\x00\x00\x5D\x00\x00\x00\x03\x00\x00\x00\x32\x00\x04\x00\x06\x00\x00\x00\x5F\x00\x00\x00\x00\x00\x80\x43\x1E\x00\x0C\x00"
"\x60\x00\x00\x00\x0D\x00\x00\x00\x0E\x00\x00\x00\x06\x00\x00\x00\x0E\x00\x00\x00\x06\x00\x00\x00\x0E\x00\x00\x00\x06\x00\x00\x00"
"\x07\x00\x00\x00\x12\x00\x00\x00\x12\x00\x00\x00\x20\x00\x04\x00\x61\x00\x00\x00\x02\x00\x00\x00\x60\x00\x00\x00\x3B\x00\x04\x00"
"\x61\x00\x00\x00\x62\x00\x00\x00\x02\x00\x00\x00\x20\x00\x04\x00\x63\x00\x00\x00\x01\x00\x00\x00\x07\x00\x00\x00\x3B\x00\x04\x00"
"\x63\x00\x00\x00\x64\x00\x00\x00\x01\x00\x00\x00\x3B\x00\x04\x00\x40\x00\x00\x00\x65\x00\x00\x00\x01\x00\x00\x00\x3B\x00\x04\x00"
"\x1B\x00\x00\x00\x66\x00\x00\x00\x01\x00\x00\x00\x3B\x00\x04\x00\x1B\x00\x00\x00\x67\x00\x00\x00\x01\x00\x00\x00\x3B\x00\x04\x00"
"\x1B\x00\x00\x00\x68\x00\x00\x00\x01\x00\x00\x00\x36\x00\x05\x00\x02\x00\x00\x00\x04\x00\x00\x00\x00\x00\x00\x00\x03\x00\x00\x00"
"\x43\x00\x00\x00\x01\x00\x00\x00\x06\x00\x00\x00\x3B\x00\x04\x00\x3E\x00\x00\x00\x49\x00\x00\x00\x03\x00\x00\x00\x2B\x00\x04\x00"
"\x16\x00\x00\x00\x4A\x00\x00\x00\x04\x00\x00\x00\x20\x00\x04\x00\x4B\x00\x00\x00\x02\x00\x00\x00\x06\x00\x00\x00\x2B\x00\x04\x00"
"\x06\x00\x00\x00\x4E\x00\x00\x00\x00\x00\x80\x3E\x20\x00\x04\x00\x53\x00\x00\x00\x03\x00\x00\x00\x06\x00\x00\x00\x3B\x00\x04\x00"
"\x3E\x00\x00\x00\x5C\x00\x00\x00\x03\x00\x00\x00\x32\x00\x04\x00\x06\x00\x00\x00\x5E\x00\x00\x00\x00\x00\x80\x43\x1E\x00\x0C\x00"
"\x5F\x00\x00\x00\x0D\x00\x00\x00\x0E\x00\x00\x00\x06\x00\x00\x00\x0E\x00\x00\x00\x06\x00\x00\x00\x0E\x00\x00\x00\x06\x00\x00\x00"
"\x07\x00\x00\x00\x12\x00\x00\x00\x12\x00\x00\x00\x20\x00\x04\x00\x60\x00\x00\x00\x02\x00\x00\x00\x5F\x00\x00\x00\x3B\x00\x04\x00"
"\x60\x00\x00\x00\x61\x00\x00\x00\x02\x00\x00\x00\x20\x00\x04\x00\x62\x00\x00\x00\x01\x00\x00\x00\x07\x00\x00\x00\x3B\x00\x04\x00"
"\x62\x00\x00\x00\x63\x00\x00\x00\x01\x00\x00\x00\x3B\x00\x04\x00\x40\x00\x00\x00\x64\x00\x00\x00\x01\x00\x00\x00\x3B\x00\x04\x00"
"\x1B\x00\x00\x00\x65\x00\x00\x00\x01\x00\x00\x00\x3B\x00\x04\x00\x1B\x00\x00\x00\x66\x00\x00\x00\x01\x00\x00\x00\x3B\x00\x04\x00"
"\x1B\x00\x00\x00\x67\x00\x00\x00\x01\x00\x00\x00\x36\x00\x05\x00\x02\x00\x00\x00\x04\x00\x00\x00\x00\x00\x00\x00\x03\x00\x00\x00"
"\xF8\x00\x02\x00\x05\x00\x00\x00\x39\x00\x04\x00\x07\x00\x00\x00\x3B\x00\x00\x00\x09\x00\x00\x00\x41\x00\x05\x00\x3C\x00\x00\x00"
"\x3D\x00\x00\x00\x3A\x00\x00\x00\x17\x00\x00\x00\x3E\x00\x03\x00\x3D\x00\x00\x00\x3B\x00\x00\x00\x41\x00\x05\x00\x43\x00\x00\x00"
"\x44\x00\x00\x00\x41\x00\x00\x00\x42\x00\x00\x00\x3D\x00\x04\x00\x06\x00\x00\x00\x45\x00\x00\x00\x44\x00\x00\x00\x41\x00\x05\x00"
"\x43\x00\x00\x00\x46\x00\x00\x00\x41\x00\x00\x00\x25\x00\x00\x00\x3D\x00\x04\x00\x06\x00\x00\x00\x47\x00\x00\x00\x46\x00\x00\x00"
"\x83\x00\x05\x00\x06\x00\x00\x00\x48\x00\x00\x00\x1E\x00\x00\x00\x47\x00\x00\x00\x50\x00\x05\x00\x12\x00\x00\x00\x49\x00\x00\x00"
"\x45\x00\x00\x00\x48\x00\x00\x00\x3E\x00\x03\x00\x3F\x00\x00\x00\x49\x00\x00\x00\x41\x00\x05\x00\x4C\x00\x00\x00\x4D\x00\x00\x00"
"\x15\x00\x00\x00\x4B\x00\x00\x00\x3D\x00\x04\x00\x06\x00\x00\x00\x4E\x00\x00\x00\x4D\x00\x00\x00\x85\x00\x05\x00\x06\x00\x00\x00"
"\x50\x00\x00\x00\x4E\x00\x00\x00\x4F\x00\x00\x00\x41\x00\x05\x00\x43\x00\x00\x00\x51\x00\x00\x00\x41\x00\x00\x00\x42\x00\x00\x00"
"\x3D\x00\x04\x00\x06\x00\x00\x00\x52\x00\x00\x00\x51\x00\x00\x00\x81\x00\x05\x00\x06\x00\x00\x00\x53\x00\x00\x00\x50\x00\x00\x00"
"\x52\x00\x00\x00\x41\x00\x05\x00\x54\x00\x00\x00\x55\x00\x00\x00\x4A\x00\x00\x00\x42\x00\x00\x00\x3E\x00\x03\x00\x55\x00\x00\x00"
"\x53\x00\x00\x00\x41\x00\x05\x00\x4C\x00\x00\x00\x56\x00\x00\x00\x15\x00\x00\x00\x4B\x00\x00\x00\x3D\x00\x04\x00\x06\x00\x00\x00"
"\x57\x00\x00\x00\x56\x00\x00\x00\x85\x00\x05\x00\x06\x00\x00\x00\x58\x00\x00\x00\x57\x00\x00\x00\x4F\x00\x00\x00\x41\x00\x05\x00"
"\x43\x00\x00\x00\x59\x00\x00\x00\x41\x00\x00\x00\x25\x00\x00\x00\x3D\x00\x04\x00\x06\x00\x00\x00\x5A\x00\x00\x00\x59\x00\x00\x00"
"\x81\x00\x05\x00\x06\x00\x00\x00\x5B\x00\x00\x00\x58\x00\x00\x00\x5A\x00\x00\x00\x41\x00\x05\x00\x54\x00\x00\x00\x5C\x00\x00\x00"
"\x4A\x00\x00\x00\x25\x00\x00\x00\x3E\x00\x03\x00\x5C\x00\x00\x00\x5B\x00\x00\x00\x3D\x00\x04\x00\x12\x00\x00\x00\x5E\x00\x00\x00"
"\x41\x00\x00\x00\x3E\x00\x03\x00\x5D\x00\x00\x00\x5E\x00\x00\x00\xFD\x00\x01\x00\x38\x00\x01\x00\x36\x00\x05\x00\x07\x00\x00\x00"
"\x09\x00\x00\x00\x00\x00\x00\x00\x08\x00\x00\x00\xF8\x00\x02\x00\x0A\x00\x00\x00\x3B\x00\x04\x00\x0B\x00\x00\x00\x0C\x00\x00\x00"
"\x07\x00\x00\x00\x41\x00\x05\x00\x18\x00\x00\x00\x19\x00\x00\x00\x15\x00\x00\x00\x17\x00\x00\x00\x3D\x00\x04\x00\x0D\x00\x00\x00"
"\x1A\x00\x00\x00\x19\x00\x00\x00\x3D\x00\x04\x00\x0E\x00\x00\x00\x1D\x00\x00\x00\x1C\x00\x00\x00\x51\x00\x05\x00\x06\x00\x00\x00"
"\x1F\x00\x00\x00\x1D\x00\x00\x00\x00\x00\x00\x00\x51\x00\x05\x00\x06\x00\x00\x00\x20\x00\x00\x00\x1D\x00\x00\x00\x01\x00\x00\x00"
"\x51\x00\x05\x00\x06\x00\x00\x00\x21\x00\x00\x00\x1D\x00\x00\x00\x02\x00\x00\x00\x50\x00\x07\x00\x07\x00\x00\x00\x22\x00\x00\x00"
"\x1F\x00\x00\x00\x20\x00\x00\x00\x21\x00\x00\x00\x1E\x00\x00\x00\x91\x00\x05\x00\x07\x00\x00\x00\x23\x00\x00\x00\x1A\x00\x00\x00"
"\x22\x00\x00\x00\x3E\x00\x03\x00\x0C\x00\x00\x00\x23\x00\x00\x00\x41\x00\x05\x00\x26\x00\x00\x00\x27\x00\x00\x00\x0C\x00\x00\x00"
"\x25\x00\x00\x00\x3D\x00\x04\x00\x06\x00\x00\x00\x28\x00\x00\x00\x27\x00\x00\x00\x85\x00\x05\x00\x06\x00\x00\x00\x29\x00\x00\x00"
"\x28\x00\x00\x00\x24\x00\x00\x00\x41\x00\x05\x00\x26\x00\x00\x00\x2A\x00\x00\x00\x0C\x00\x00\x00\x25\x00\x00\x00\x3E\x00\x03\x00"
"\x2A\x00\x00\x00\x29\x00\x00\x00\x41\x00\x05\x00\x26\x00\x00\x00\x2C\x00\x00\x00\x0C\x00\x00\x00\x2B\x00\x00\x00\x3D\x00\x04\x00"
"\x06\x00\x00\x00\x2D\x00\x00\x00\x2C\x00\x00\x00\x41\x00\x05\x00\x26\x00\x00\x00\x2F\x00\x00\x00\x0C\x00\x00\x00\x2E\x00\x00\x00"
"\x3D\x00\x04\x00\x06\x00\x00\x00\x30\x00\x00\x00\x2F\x00\x00\x00\x81\x00\x05\x00\x06\x00\x00\x00\x31\x00\x00\x00\x2D\x00\x00\x00"
"\x30\x00\x00\x00\x88\x00\x05\x00\x06\x00\x00\x00\x33\x00\x00\x00\x31\x00\x00\x00\x32\x00\x00\x00\x41\x00\x05\x00\x26\x00\x00\x00"
"\x34\x00\x00\x00\x0C\x00\x00\x00\x2B\x00\x00\x00\x3E\x00\x03\x00\x34\x00\x00\x00\x33\x00\x00\x00\x3D\x00\x04\x00\x07\x00\x00\x00"
"\x35\x00\x00\x00\x0C\x00\x00\x00\xFE\x00\x02\x00\x35\x00\x00\x00\x38\x00\x01\x00\x03\x02\x23\x07\x00\x00\x01\x00\x06\x00\x08\x00"
"\x42\x00\x00\x00\x00\x00\x00\x00\x11\x00\x02\x00\x01\x00\x00\x00\x0B\x00\x06\x00\x01\x00\x00\x00\x47\x4C\x53\x4C\x2E\x73\x74\x64"
"\x2E\x34\x35\x30\x00\x00\x00\x00\x0E\x00\x03\x00\x00\x00\x00\x00\x01\x00\x00\x00\x0F\x00\x09\x00\x04\x00\x00\x00\x04\x00\x00\x00"
"\x6D\x61\x69\x6E\x00\x00\x00\x00\x13\x00\x00\x00\x1E\x00\x00\x00\x28\x00\x00\x00\x30\x00\x00\x00\x10\x00\x03\x00\x04\x00\x00\x00"
"\x07\x00\x00\x00\x03\x00\x03\x00\x02\x00\x00\x00\xC2\x01\x00\x00\x05\x00\x04\x00\x04\x00\x00\x00\x6D\x61\x69\x6E\x00\x00\x00\x00"
"\x05\x00\x03\x00\x09\x00\x00\x00\x61\x6D\x70\x00\x05\x00\x07\x00\x0B\x00\x00\x00\x63\x76\x61\x72\x5F\x72\x5F\x77\x61\x74\x65\x72"
"\x77\x61\x72\x70\x00\x00\x00\x00\x05\x00\x04\x00\x10\x00\x00\x00\x73\x5F\x74\x32\x00\x00\x00\x00\x05\x00\x04\x00\x13\x00\x00\x00"
"\x76\x5F\x65\x64\x67\x65\x00\x00\x05\x00\x04\x00\x1B\x00\x00\x00\x6F\x66\x66\x73\x65\x74\x00\x00\x05\x00\x04\x00\x1C\x00\x00\x00"
"\x73\x5F\x74\x31\x00\x00\x00\x00\x05\x00\x04\x00\x1E\x00\x00\x00\x76\x5F\x77\x61\x72\x70\x00\x00\x05\x00\x04\x00\x27\x00\x00\x00"
"\x74\x65\x6D\x70\x00\x00\x00\x00\x05\x00\x04\x00\x28\x00\x00\x00\x76\x5F\x73\x74\x63\x00\x00\x00\x05\x00\x05\x00\x30\x00\x00\x00"
"\x6F\x75\x74\x63\x6F\x6C\x6F\x75\x72\x00\x00\x00\x05\x00\x04\x00\x31\x00\x00\x00\x73\x5F\x74\x30\x00\x00\x00\x00\x05\x00\x05\x00"
"\x3C\x00\x00\x00\x65\x6E\x74\x69\x74\x79\x62\x6C\x6F\x63\x6B\x00\x06\x00\x07\x00\x3C\x00\x00\x00\x00\x00\x00\x00\x6D\x5F\x6D\x6F"
"\x64\x65\x6C\x76\x69\x65\x77\x70\x72\x6F\x6A\x00\x06\x00\x05\x00\x3C\x00\x00\x00\x01\x00\x00\x00\x6D\x5F\x6D\x6F\x64\x65\x6C\x00"
"\x06\x00\x06\x00\x3C\x00\x00\x00\x02\x00\x00\x00\x6D\x5F\x6D\x6F\x64\x65\x6C\x69\x6E\x76\x00\x00\x06\x00\x06\x00\x3C\x00\x00\x00"
"\x03\x00\x00\x00\x65\x5F\x65\x79\x65\x70\x6F\x73\x00\x00\x00\x00\x06\x00\x05\x00\x3C\x00\x00\x00\x04\x00\x00\x00\x65\x5F\x74\x69"
"\x6D\x65\x00\x00\x06\x00\x07\x00\x3C\x00\x00\x00\x05\x00\x00\x00\x65\x5F\x6C\x69\x67\x68\x74\x5F\x61\x6D\x62\x69\x65\x6E\x74\x00"
"\x06\x00\x05\x00\x3C\x00\x00\x00\x06\x00\x00\x00\x65\x70\x61\x64\x31\x00\x00\x00\x06\x00\x06\x00\x3C\x00\x00\x00\x07\x00\x00\x00"
"\x65\x5F\x6C\x69\x67\x68\x74\x5F\x64\x69\x72\x00\x06\x00\x05\x00\x3C\x00\x00\x00\x08\x00\x00\x00\x65\x70\x61\x64\x32\x00\x00\x00"
"\x06\x00\x06\x00\x3C\x00\x00\x00\x09\x00\x00\x00\x65\x5F\x6C\x69\x67\x68\x74\x5F\x6D\x75\x6C\x00\x06\x00\x05\x00\x3C\x00\x00\x00"
"\x0A\x00\x00\x00\x65\x70\x61\x64\x33\x00\x00\x00\x06\x00\x06\x00\x3C\x00\x00\x00\x0B\x00\x00\x00\x65\x5F\x6C\x6D\x73\x63\x61\x6C"
"\x65\x73\x00\x00\x06\x00\x07\x00\x3C\x00\x00\x00\x0C\x00\x00\x00\x65\x5F\x75\x70\x70\x65\x72\x63\x6F\x6C\x6F\x75\x72\x00\x00\x00"
"\x06\x00\x05\x00\x3C\x00\x00\x00\x0D\x00\x00\x00\x65\x70\x61\x64\x34\x00\x00\x00\x06\x00\x07\x00\x3C\x00\x00\x00\x0E\x00\x00\x00"
"\x65\x5F\x6C\x6F\x77\x65\x72\x63\x6F\x6C\x6F\x75\x72\x00\x00\x00\x06\x00\x05\x00\x3C\x00\x00\x00\x0F\x00\x00\x00\x65\x70\x61\x64"
"\x35\x00\x00\x00\x06\x00\x06\x00\x3C\x00\x00\x00\x10\x00\x00\x00\x65\x5F\x67\x6C\x6F\x77\x6D\x6F\x64\x00\x00\x00\x06\x00\x05\x00"
"\x3C\x00\x00\x00\x11\x00\x00\x00\x65\x70\x61\x64\x36\x00\x00\x00\x06\x00\x07\x00\x3C\x00\x00\x00\x12\x00\x00\x00\x65\x5F\x63\x6F"
"\x6C\x6F\x75\x72\x69\x64\x65\x6E\x74\x00\x00\x00\x06\x00\x07\x00\x3C\x00\x00\x00\x13\x00\x00\x00\x77\x5F\x66\x6F\x67\x63\x6F\x6C"
"\x6F\x75\x72\x73\x00\x00\x00\x00\x06\x00\x07\x00\x3C\x00\x00\x00\x14\x00\x00\x00\x77\x5F\x66\x6F\x67\x64\x65\x6E\x73\x69\x74\x79"
"\x00\x00\x00\x00\x06\x00\x07\x00\x3C\x00\x00\x00\x15\x00\x00\x00\x77\x5F\x66\x6F\x67\x64\x65\x70\x74\x68\x62\x69\x61\x73\x00\x00"
"\x06\x00\x05\x00\x3C\x00\x00\x00\x16\x00\x00\x00\x65\x70\x61\x64\x37\x00\x00\x00\x05\x00\x03\x00\x3E\x00\x00\x00\x00\x00\x00\x00"
"\x05\x00\x05\x00\x3F\x00\x00\x00\x6C\x69\x67\x68\x74\x62\x6C\x6F\x63\x6B\x00\x00\x06\x00\x07\x00\x3F\x00\x00\x00\x00\x00\x00\x00"
"\x6C\x5F\x63\x75\x62\x65\x6D\x61\x74\x72\x69\x78\x00\x00\x00\x00\x06\x00\x07\x00\x3F\x00\x00\x00\x01\x00\x00\x00\x6C\x5F\x6C\x69"
"\x67\x68\x74\x70\x6F\x73\x69\x74\x69\x6F\x6E\x00\x06\x00\x05\x00\x3F\x00\x00\x00\x02\x00\x00\x00\x6C\x70\x61\x64\x31\x00\x00\x00"
"\x06\x00\x07\x00\x3F\x00\x00\x00\x03\x00\x00\x00\x6C\x5F\x6C\x69\x67\x68\x74\x63\x6F\x6C\x6F\x75\x72\x00\x00\x00\x06\x00\x05\x00"
"\x3F\x00\x00\x00\x04\x00\x00\x00\x6C\x70\x61\x64\x32\x00\x00\x00\x06\x00\x08\x00\x3F\x00\x00\x00\x05\x00\x00\x00\x6C\x5F\x6C\x69"
"\x67\x68\x74\x63\x6F\x6C\x6F\x75\x72\x73\x63\x61\x6C\x65\x00\x00\x06\x00\x07\x00\x3F\x00\x00\x00\x06\x00\x00\x00\x6C\x5F\x6C\x69"
"\x67\x68\x74\x72\x61\x64\x69\x75\x73\x00\x00\x00\x06\x00\x07\x00\x3F\x00\x00\x00\x07\x00\x00\x00\x6C\x5F\x73\x68\x61\x64\x6F\x77"
"\x6D\x61\x70\x70\x72\x6F\x6A\x00\x06\x00\x08\x00\x3F\x00\x00\x00\x08\x00\x00\x00\x6C\x5F\x73\x68\x61\x64\x6F\x77\x6D\x61\x70\x73"
"\x63\x61\x6C\x65\x00\x00\x00\x00\x06\x00\x05\x00\x3F\x00\x00\x00\x09\x00\x00\x00\x6C\x70\x61\x64\x33\x00\x00\x00\x05\x00\x03\x00"
"\x41\x00\x00\x00\x00\x00\x00\x00\x47\x00\x04\x00\x0B\x00\x00\x00\x01\x00\x00\x00\x00\x01\x00\x00\x47\x00\x04\x00\x10\x00\x00\x00"
"\x22\x00\x00\x00\x00\x00\x00\x00\x47\x00\x04\x00\x10\x00\x00\x00\x21\x00\x00\x00\x04\x00\x00\x00\x47\x00\x04\x00\x13\x00\x00\x00"
"\x1E\x00\x00\x00\x02\x00\x00\x00\x47\x00\x04\x00\x1C\x00\x00\x00\x22\x00\x00\x00\x00\x00\x00\x00\x47\x00\x04\x00\x1C\x00\x00\x00"
"\x21\x00\x00\x00\x03\x00\x00\x00\x47\x00\x04\x00\x1E\x00\x00\x00\x1E\x00\x00\x00\x01\x00\x00\x00\x47\x00\x04\x00\x28\x00\x00\x00"
"\x1E\x00\x00\x00\x00\x00\x00\x00\x47\x00\x04\x00\x30\x00\x00\x00\x1E\x00\x00\x00\x00\x00\x00\x00\x47\x00\x04\x00\x31\x00\x00\x00"
"\x22\x00\x00\x00\x00\x00\x00\x00\x47\x00\x04\x00\x31\x00\x00\x00\x21\x00\x00\x00\x02\x00\x00\x00\x47\x00\x04\x00\x3B\x00\x00\x00"
"\x06\x00\x00\x00\x10\x00\x00\x00\x48\x00\x04\x00\x3C\x00\x00\x00\x00\x00\x00\x00\x05\x00\x00\x00\x48\x00\x05\x00\x3C\x00\x00\x00"
"\x00\x00\x00\x00\x23\x00\x00\x00\x00\x00\x00\x00\x48\x00\x05\x00\x3C\x00\x00\x00\x00\x00\x00\x00\x07\x00\x00\x00\x10\x00\x00\x00"
"\x48\x00\x04\x00\x3C\x00\x00\x00\x01\x00\x00\x00\x05\x00\x00\x00\x48\x00\x05\x00\x3C\x00\x00\x00\x01\x00\x00\x00\x23\x00\x00\x00"
"\x40\x00\x00\x00\x48\x00\x05\x00\x3C\x00\x00\x00\x01\x00\x00\x00\x07\x00\x00\x00\x10\x00\x00\x00\x48\x00\x04\x00\x3C\x00\x00\x00"
"\x02\x00\x00\x00\x05\x00\x00\x00\x48\x00\x05\x00\x3C\x00\x00\x00\x02\x00\x00\x00\x23\x00\x00\x00\x80\x00\x00\x00\x48\x00\x05\x00"
"\x3C\x00\x00\x00\x02\x00\x00\x00\x07\x00\x00\x00\x10\x00\x00\x00\x48\x00\x05\x00\x3C\x00\x00\x00\x03\x00\x00\x00\x23\x00\x00\x00"
"\xC0\x00\x00\x00\x48\x00\x05\x00\x3C\x00\x00\x00\x04\x00\x00\x00\x23\x00\x00\x00\xCC\x00\x00\x00\x48\x00\x05\x00\x3C\x00\x00\x00"
"\x05\x00\x00\x00\x23\x00\x00\x00\xD0\x00\x00\x00\x48\x00\x05\x00\x3C\x00\x00\x00\x06\x00\x00\x00\x23\x00\x00\x00\xDC\x00\x00\x00"
"\x48\x00\x05\x00\x3C\x00\x00\x00\x07\x00\x00\x00\x23\x00\x00\x00\xE0\x00\x00\x00\x48\x00\x05\x00\x3C\x00\x00\x00\x08\x00\x00\x00"
"\x23\x00\x00\x00\xEC\x00\x00\x00\x48\x00\x05\x00\x3C\x00\x00\x00\x09\x00\x00\x00\x23\x00\x00\x00\xF0\x00\x00\x00\x48\x00\x05\x00"
"\x3C\x00\x00\x00\x0A\x00\x00\x00\x23\x00\x00\x00\xFC\x00\x00\x00\x48\x00\x05\x00\x3C\x00\x00\x00\x0B\x00\x00\x00\x23\x00\x00\x00"
"\x00\x01\x00\x00\x48\x00\x05\x00\x3C\x00\x00\x00\x0C\x00\x00\x00\x23\x00\x00\x00\x40\x01\x00\x00\x48\x00\x05\x00\x3C\x00\x00\x00"
"\x0D\x00\x00\x00\x23\x00\x00\x00\x4C\x01\x00\x00\x48\x00\x05\x00\x3C\x00\x00\x00\x0E\x00\x00\x00\x23\x00\x00\x00\x50\x01\x00\x00"
"\x48\x00\x05\x00\x3C\x00\x00\x00\x0F\x00\x00\x00\x23\x00\x00\x00\x5C\x01\x00\x00\x48\x00\x05\x00\x3C\x00\x00\x00\x10\x00\x00\x00"
"\x23\x00\x00\x00\x60\x01\x00\x00\x48\x00\x05\x00\x3C\x00\x00\x00\x11\x00\x00\x00\x23\x00\x00\x00\x6C\x01\x00\x00\x48\x00\x05\x00"
"\x3C\x00\x00\x00\x12\x00\x00\x00\x23\x00\x00\x00\x70\x01\x00\x00\x48\x00\x05\x00\x3C\x00\x00\x00\x13\x00\x00\x00\x23\x00\x00\x00"
"\x80\x01\x00\x00\x48\x00\x05\x00\x3C\x00\x00\x00\x14\x00\x00\x00\x23\x00\x00\x00\x90\x01\x00\x00\x48\x00\x05\x00\x3C\x00\x00\x00"
"\x15\x00\x00\x00\x23\x00\x00\x00\x94\x01\x00\x00\x48\x00\x05\x00\x3C\x00\x00\x00\x16\x00\x00\x00\x23\x00\x00\x00\x98\x01\x00\x00"
"\x47\x00\x03\x00\x3C\x00\x00\x00\x02\x00\x00\x00\x47\x00\x04\x00\x3E\x00\x00\x00\x22\x00\x00\x00\x00\x00\x00\x00\x47\x00\x04\x00"
"\x3E\x00\x00\x00\x21\x00\x00\x00\x00\x00\x00\x00\x48\x00\x04\x00\x3F\x00\x00\x00\x00\x00\x00\x00\x05\x00\x00\x00\x48\x00\x05\x00"
"\x3F\x00\x00\x00\x00\x00\x00\x00\x23\x00\x00\x00\x00\x00\x00\x00\x48\x00\x05\x00\x3F\x00\x00\x00\x00\x00\x00\x00\x07\x00\x00\x00"
"\x10\x00\x00\x00\x48\x00\x05\x00\x3F\x00\x00\x00\x01\x00\x00\x00\x23\x00\x00\x00\x40\x00\x00\x00\x48\x00\x05\x00\x3F\x00\x00\x00"
"\x02\x00\x00\x00\x23\x00\x00\x00\x4C\x00\x00\x00\x48\x00\x05\x00\x3F\x00\x00\x00\x03\x00\x00\x00\x23\x00\x00\x00\x50\x00\x00\x00"
"\x48\x00\x05\x00\x3F\x00\x00\x00\x04\x00\x00\x00\x23\x00\x00\x00\x5C\x00\x00\x00\x48\x00\x05\x00\x3F\x00\x00\x00\x05\x00\x00\x00"
"\x23\x00\x00\x00\x60\x00\x00\x00\x48\x00\x05\x00\x3F\x00\x00\x00\x06\x00\x00\x00\x23\x00\x00\x00\x6C\x00\x00\x00\x48\x00\x05\x00"
"\x3F\x00\x00\x00\x07\x00\x00\x00\x23\x00\x00\x00\x70\x00\x00\x00\x48\x00\x05\x00\x3F\x00\x00\x00\x08\x00\x00\x00\x23\x00\x00\x00"
"\x80\x00\x00\x00\x48\x00\x05\x00\x3F\x00\x00\x00\x09\x00\x00\x00\x23\x00\x00\x00\x88\x00\x00\x00\x47\x00\x03\x00\x3F\x00\x00\x00"
"\x02\x00\x00\x00\x47\x00\x04\x00\x41\x00\x00\x00\x22\x00\x00\x00\x00\x00\x00\x00\x47\x00\x04\x00\x41\x00\x00\x00\x21\x00\x00\x00"
"\x01\x00\x00\x00\x13\x00\x02\x00\x02\x00\x00\x00\x21\x00\x03\x00\x03\x00\x00\x00\x02\x00\x00\x00\x16\x00\x03\x00\x06\x00\x00\x00"
"\x20\x00\x00\x00\x17\x00\x04\x00\x07\x00\x00\x00\x06\x00\x00\x00\x02\x00\x00\x00\x20\x00\x04\x00\x08\x00\x00\x00\x07\x00\x00\x00"
"\x07\x00\x00\x00\x2B\x00\x04\x00\x06\x00\x00\x00\x0A\x00\x00\x00\x6F\x12\x83\x3C\x32\x00\x04\x00\x06\x00\x00\x00\x0B\x00\x00\x00"
"\x00\x00\x80\x43\x19\x00\x09\x00\x0D\x00\x00\x00\x06\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
"\x01\x00\x00\x00\x00\x00\x00\x00\x1B\x00\x03\x00\x0E\x00\x00\x00\x0D\x00\x00\x00\x20\x00\x04\x00\x0F\x00\x00\x00\x00\x00\x00\x00"
"\x0E\x00\x00\x00\x3B\x00\x04\x00\x0F\x00\x00\x00\x10\x00\x00\x00\x00\x00\x00\x00\x20\x00\x04\x00\x12\x00\x00\x00\x01\x00\x00\x00"
"\x07\x00\x00\x00\x3B\x00\x04\x00\x12\x00\x00\x00\x13\x00\x00\x00\x01\x00\x00\x00\x17\x00\x04\x00\x15\x00\x00\x00\x06\x00\x00\x00"
"\x04\x00\x00\x00\x17\x00\x04\x00\x19\x00\x00\x00\x06\x00\x00\x00\x03\x00\x00\x00\x20\x00\x04\x00\x1A\x00\x00\x00\x07\x00\x00\x00"
"\x19\x00\x00\x00\x3B\x00\x04\x00\x0F\x00\x00\x00\x1C\x00\x00\x00\x00\x00\x00\x00\x3B\x00\x04\x00\x12\x00\x00\x00\x1E\x00\x00\x00"
"\x01\x00\x00\x00\x2B\x00\x04\x00\x06\x00\x00\x00\x22\x00\x00\x00\x00\x00\x00\x3F\x2B\x00\x04\x00\x06\x00\x00\x00\x25\x00\x00\x00"
"\x00\x00\x00\x40\x3B\x00\x04\x00\x12\x00\x00\x00\x28\x00\x00\x00\x01\x00\x00\x00\x20\x00\x04\x00\x2F\x00\x00\x00\x03\x00\x00\x00"
"\x15\x00\x00\x00\x3B\x00\x04\x00\x2F\x00\x00\x00\x30\x00\x00\x00\x03\x00\x00\x00\x3B\x00\x04\x00\x0F\x00\x00\x00\x31\x00\x00\x00"
"\x00\x00\x00\x00\x2B\x00\x04\x00\x06\x00\x00\x00\x34\x00\x00\x00\x00\x00\x80\x3F\x2C\x00\x05\x00\x07\x00\x00\x00\x35\x00\x00\x00"
"\x34\x00\x00\x00\x34\x00\x00\x00\x18\x00\x04\x00\x38\x00\x00\x00\x15\x00\x00\x00\x04\x00\x00\x00\x15\x00\x04\x00\x39\x00\x00\x00"
"\x20\x00\x00\x00\x00\x00\x00\x00\x2B\x00\x04\x00\x39\x00\x00\x00\x3A\x00\x00\x00\x04\x00\x00\x00\x1C\x00\x04\x00\x3B\x00\x00\x00"
"\x15\x00\x00\x00\x3A\x00\x00\x00\x1E\x00\x19\x00\x3C\x00\x00\x00\x38\x00\x00\x00\x38\x00\x00\x00\x38\x00\x00\x00\x19\x00\x00\x00"
"\x06\x00\x00\x00\x19\x00\x00\x00\x06\x00\x00\x00\x19\x00\x00\x00\x06\x00\x00\x00\x19\x00\x00\x00\x06\x00\x00\x00\x3B\x00\x00\x00"
"\x19\x00\x00\x00\x06\x00\x00\x00\x19\x00\x00\x00\x06\x00\x00\x00\x19\x00\x00\x00\x06\x00\x00\x00\x15\x00\x00\x00\x15\x00\x00\x00"
"\x06\x00\x00\x00\x06\x00\x00\x00\x07\x00\x00\x00\x20\x00\x04\x00\x3D\x00\x00\x00\x02\x00\x00\x00\x3C\x00\x00\x00\x3B\x00\x04\x00"
"\x3D\x00\x00\x00\x3E\x00\x00\x00\x02\x00\x00\x00\x1E\x00\x0C\x00\x3F\x00\x00\x00\x38\x00\x00\x00\x19\x00\x00\x00\x06\x00\x00\x00"
"\x19\x00\x00\x00\x06\x00\x00\x00\x19\x00\x00\x00\x06\x00\x00\x00\x15\x00\x00\x00\x07\x00\x00\x00\x07\x00\x00\x00\x20\x00\x04\x00"
"\x40\x00\x00\x00\x02\x00\x00\x00\x3F\x00\x00\x00\x3B\x00\x04\x00\x40\x00\x00\x00\x41\x00\x00\x00\x02\x00\x00\x00\x36\x00\x05\x00"
"\x02\x00\x00\x00\x04\x00\x00\x00\x00\x00\x00\x00\x03\x00\x00\x00\xF8\x00\x02\x00\x05\x00\x00\x00\x3B\x00\x04\x00\x08\x00\x00\x00"
"\x09\x00\x00\x00\x07\x00\x00\x00\x3B\x00\x04\x00\x1A\x00\x00\x00\x1B\x00\x00\x00\x07\x00\x00\x00\x3B\x00\x04\x00\x08\x00\x00\x00"
"\x27\x00\x00\x00\x07\x00\x00\x00\x85\x00\x05\x00\x06\x00\x00\x00\x0C\x00\x00\x00\x0A\x00\x00\x00\x0B\x00\x00\x00\x3D\x00\x04\x00"
"\x0E\x00\x00\x00\x11\x00\x00\x00\x10\x00\x00\x00\x3D\x00\x04\x00\x07\x00\x00\x00\x14\x00\x00\x00\x13\x00\x00\x00\x57\x00\x05\x00"
"\x15\x00\x00\x00\x16\x00\x00\x00\x11\x00\x00\x00\x14\x00\x00\x00\x4F\x00\x07\x00\x07\x00\x00\x00\x17\x00\x00\x00\x16\x00\x00\x00"
"\x16\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x8E\x00\x05\x00\x07\x00\x00\x00\x18\x00\x00\x00\x17\x00\x00\x00\x0C\x00\x00\x00"
"\x3E\x00\x03\x00\x09\x00\x00\x00\x18\x00\x00\x00\x3D\x00\x04\x00\x0E\x00\x00\x00\x1D\x00\x00\x00\x1C\x00\x00\x00\x3D\x00\x04\x00"
"\x07\x00\x00\x00\x1F\x00\x00\x00\x1E\x00\x00\x00\x57\x00\x05\x00\x15\x00\x00\x00\x20\x00\x00\x00\x1D\x00\x00\x00\x1F\x00\x00\x00"
"\x4F\x00\x08\x00\x19\x00\x00\x00\x21\x00\x00\x00\x20\x00\x00\x00\x20\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x02\x00\x00\x00"
"\x50\x00\x06\x00\x19\x00\x00\x00\x23\x00\x00\x00\x22\x00\x00\x00\x22\x00\x00\x00\x22\x00\x00\x00\x83\x00\x05\x00\x19\x00\x00\x00"
"\x24\x00\x00\x00\x21\x00\x00\x00\x23\x00\x00\x00\x8E\x00\x05\x00\x19\x00\x00\x00\x26\x00\x00\x00\x24\x00\x00\x00\x25\x00\x00\x00"
"\x3E\x00\x03\x00\x1B\x00\x00\x00\x26\x00\x00\x00\x3D\x00\x04\x00\x07\x00\x00\x00\x29\x00\x00\x00\x28\x00\x00\x00\x3D\x00\x04\x00"
"\x19\x00\x00\x00\x2A\x00\x00\x00\x1B\x00\x00\x00\x4F\x00\x07\x00\x07\x00\x00\x00\x2B\x00\x00\x00\x2A\x00\x00\x00\x2A\x00\x00\x00"
"\x00\x00\x00\x00\x01\x00\x00\x00\x3D\x00\x04\x00\x07\x00\x00\x00\x2C\x00\x00\x00\x09\x00\x00\x00\x85\x00\x05\x00\x07\x00\x00\x00"
"\x2D\x00\x00\x00\x2B\x00\x00\x00\x2C\x00\x00\x00\x81\x00\x05\x00\x07\x00\x00\x00\x2E\x00\x00\x00\x29\x00\x00\x00\x2D\x00\x00\x00"
"\x3E\x00\x03\x00\x27\x00\x00\x00\x2E\x00\x00\x00\x3D\x00\x04\x00\x0E\x00\x00\x00\x32\x00\x00\x00\x31\x00\x00\x00\x3D\x00\x04\x00"
"\x07\x00\x00\x00\x33\x00\x00\x00\x27\x00\x00\x00\x85\x00\x05\x00\x07\x00\x00\x00\x36\x00\x00\x00\x33\x00\x00\x00\x35\x00\x00\x00"
"\x57\x00\x05\x00\x15\x00\x00\x00\x37\x00\x00\x00\x32\x00\x00\x00\x36\x00\x00\x00\x3E\x00\x03\x00\x30\x00\x00\x00\x37\x00\x00\x00"
"\xFD\x00\x01\x00\x38\x00\x01\x00"},
"\x50\x00\x05\x00\x12\x00\x00\x00\x48\x00\x00\x00\x45\x00\x00\x00\x47\x00\x00\x00\x3E\x00\x03\x00\x3F\x00\x00\x00\x48\x00\x00\x00"
"\x41\x00\x05\x00\x4B\x00\x00\x00\x4C\x00\x00\x00\x15\x00\x00\x00\x4A\x00\x00\x00\x3D\x00\x04\x00\x06\x00\x00\x00\x4D\x00\x00\x00"
"\x4C\x00\x00\x00\x85\x00\x05\x00\x06\x00\x00\x00\x4F\x00\x00\x00\x4D\x00\x00\x00\x4E\x00\x00\x00\x41\x00\x05\x00\x43\x00\x00\x00"
"\x50\x00\x00\x00\x41\x00\x00\x00\x42\x00\x00\x00\x3D\x00\x04\x00\x06\x00\x00\x00\x51\x00\x00\x00\x50\x00\x00\x00\x81\x00\x05\x00"
"\x06\x00\x00\x00\x52\x00\x00\x00\x4F\x00\x00\x00\x51\x00\x00\x00\x41\x00\x05\x00\x53\x00\x00\x00\x54\x00\x00\x00\x49\x00\x00\x00"
"\x42\x00\x00\x00\x3E\x00\x03\x00\x54\x00\x00\x00\x52\x00\x00\x00\x41\x00\x05\x00\x4B\x00\x00\x00\x55\x00\x00\x00\x15\x00\x00\x00"
"\x4A\x00\x00\x00\x3D\x00\x04\x00\x06\x00\x00\x00\x56\x00\x00\x00\x55\x00\x00\x00\x85\x00\x05\x00\x06\x00\x00\x00\x57\x00\x00\x00"
"\x56\x00\x00\x00\x4E\x00\x00\x00\x41\x00\x05\x00\x43\x00\x00\x00\x58\x00\x00\x00\x41\x00\x00\x00\x25\x00\x00\x00\x3D\x00\x04\x00"
"\x06\x00\x00\x00\x59\x00\x00\x00\x58\x00\x00\x00\x81\x00\x05\x00\x06\x00\x00\x00\x5A\x00\x00\x00\x57\x00\x00\x00\x59\x00\x00\x00"
"\x41\x00\x05\x00\x53\x00\x00\x00\x5B\x00\x00\x00\x49\x00\x00\x00\x25\x00\x00\x00\x3E\x00\x03\x00\x5B\x00\x00\x00\x5A\x00\x00\x00"
"\x3D\x00\x04\x00\x12\x00\x00\x00\x5D\x00\x00\x00\x41\x00\x00\x00\x3E\x00\x03\x00\x5C\x00\x00\x00\x5D\x00\x00\x00\xFD\x00\x01\x00"
"\x38\x00\x01\x00\x36\x00\x05\x00\x07\x00\x00\x00\x09\x00\x00\x00\x00\x00\x00\x00\x08\x00\x00\x00\xF8\x00\x02\x00\x0A\x00\x00\x00"
"\x3B\x00\x04\x00\x0B\x00\x00\x00\x0C\x00\x00\x00\x07\x00\x00\x00\x41\x00\x05\x00\x18\x00\x00\x00\x19\x00\x00\x00\x15\x00\x00\x00"
"\x17\x00\x00\x00\x3D\x00\x04\x00\x0D\x00\x00\x00\x1A\x00\x00\x00\x19\x00\x00\x00\x3D\x00\x04\x00\x0E\x00\x00\x00\x1D\x00\x00\x00"
"\x1C\x00\x00\x00\x51\x00\x05\x00\x06\x00\x00\x00\x1F\x00\x00\x00\x1D\x00\x00\x00\x00\x00\x00\x00\x51\x00\x05\x00\x06\x00\x00\x00"
"\x20\x00\x00\x00\x1D\x00\x00\x00\x01\x00\x00\x00\x51\x00\x05\x00\x06\x00\x00\x00\x21\x00\x00\x00\x1D\x00\x00\x00\x02\x00\x00\x00"
"\x50\x00\x07\x00\x07\x00\x00\x00\x22\x00\x00\x00\x1F\x00\x00\x00\x20\x00\x00\x00\x21\x00\x00\x00\x1E\x00\x00\x00\x91\x00\x05\x00"
"\x07\x00\x00\x00\x23\x00\x00\x00\x1A\x00\x00\x00\x22\x00\x00\x00\x3E\x00\x03\x00\x0C\x00\x00\x00\x23\x00\x00\x00\x41\x00\x05\x00"
"\x26\x00\x00\x00\x27\x00\x00\x00\x0C\x00\x00\x00\x25\x00\x00\x00\x3D\x00\x04\x00\x06\x00\x00\x00\x28\x00\x00\x00\x27\x00\x00\x00"
"\x85\x00\x05\x00\x06\x00\x00\x00\x29\x00\x00\x00\x28\x00\x00\x00\x24\x00\x00\x00\x41\x00\x05\x00\x26\x00\x00\x00\x2A\x00\x00\x00"
"\x0C\x00\x00\x00\x25\x00\x00\x00\x3E\x00\x03\x00\x2A\x00\x00\x00\x29\x00\x00\x00\x41\x00\x05\x00\x26\x00\x00\x00\x2C\x00\x00\x00"
"\x0C\x00\x00\x00\x2B\x00\x00\x00\x3D\x00\x04\x00\x06\x00\x00\x00\x2D\x00\x00\x00\x2C\x00\x00\x00\x41\x00\x05\x00\x26\x00\x00\x00"
"\x2F\x00\x00\x00\x0C\x00\x00\x00\x2E\x00\x00\x00\x3D\x00\x04\x00\x06\x00\x00\x00\x30\x00\x00\x00\x2F\x00\x00\x00\x81\x00\x05\x00"
"\x06\x00\x00\x00\x31\x00\x00\x00\x2D\x00\x00\x00\x30\x00\x00\x00\x88\x00\x05\x00\x06\x00\x00\x00\x33\x00\x00\x00\x31\x00\x00\x00"
"\x32\x00\x00\x00\x41\x00\x05\x00\x26\x00\x00\x00\x34\x00\x00\x00\x0C\x00\x00\x00\x2B\x00\x00\x00\x3E\x00\x03\x00\x34\x00\x00\x00"
"\x33\x00\x00\x00\x3D\x00\x04\x00\x07\x00\x00\x00\x35\x00\x00\x00\x0C\x00\x00\x00\xFE\x00\x02\x00\x35\x00\x00\x00\x38\x00\x01\x00"
"\x03\x02\x23\x07\x00\x00\x01\x00\x06\x00\x08\x00\x42\x00\x00\x00\x00\x00\x00\x00\x11\x00\x02\x00\x01\x00\x00\x00\x0B\x00\x06\x00"
"\x01\x00\x00\x00\x47\x4C\x53\x4C\x2E\x73\x74\x64\x2E\x34\x35\x30\x00\x00\x00\x00\x0E\x00\x03\x00\x00\x00\x00\x00\x01\x00\x00\x00"
"\x0F\x00\x09\x00\x04\x00\x00\x00\x04\x00\x00\x00\x6D\x61\x69\x6E\x00\x00\x00\x00\x13\x00\x00\x00\x1E\x00\x00\x00\x28\x00\x00\x00"
"\x30\x00\x00\x00\x10\x00\x03\x00\x04\x00\x00\x00\x07\x00\x00\x00\x03\x00\x03\x00\x02\x00\x00\x00\xC2\x01\x00\x00\x05\x00\x04\x00"
"\x04\x00\x00\x00\x6D\x61\x69\x6E\x00\x00\x00\x00\x05\x00\x03\x00\x09\x00\x00\x00\x61\x6D\x70\x00\x05\x00\x07\x00\x0B\x00\x00\x00"
"\x63\x76\x61\x72\x5F\x72\x5F\x77\x61\x74\x65\x72\x77\x61\x72\x70\x00\x00\x00\x00\x05\x00\x04\x00\x10\x00\x00\x00\x73\x5F\x74\x32"
"\x00\x00\x00\x00\x05\x00\x04\x00\x13\x00\x00\x00\x76\x5F\x65\x64\x67\x65\x00\x00\x05\x00\x04\x00\x1B\x00\x00\x00\x6F\x66\x66\x73"
"\x65\x74\x00\x00\x05\x00\x04\x00\x1C\x00\x00\x00\x73\x5F\x74\x31\x00\x00\x00\x00\x05\x00\x04\x00\x1E\x00\x00\x00\x76\x5F\x77\x61"
"\x72\x70\x00\x00\x05\x00\x04\x00\x27\x00\x00\x00\x74\x65\x6D\x70\x00\x00\x00\x00\x05\x00\x04\x00\x28\x00\x00\x00\x76\x5F\x73\x74"
"\x63\x00\x00\x00\x05\x00\x05\x00\x30\x00\x00\x00\x6F\x75\x74\x63\x6F\x6C\x6F\x75\x72\x00\x00\x00\x05\x00\x04\x00\x31\x00\x00\x00"
"\x73\x5F\x74\x30\x00\x00\x00\x00\x05\x00\x05\x00\x3C\x00\x00\x00\x65\x6E\x74\x69\x74\x79\x62\x6C\x6F\x63\x6B\x00\x06\x00\x07\x00"
"\x3C\x00\x00\x00\x00\x00\x00\x00\x6D\x5F\x6D\x6F\x64\x65\x6C\x76\x69\x65\x77\x70\x72\x6F\x6A\x00\x06\x00\x05\x00\x3C\x00\x00\x00"
"\x01\x00\x00\x00\x6D\x5F\x6D\x6F\x64\x65\x6C\x00\x06\x00\x06\x00\x3C\x00\x00\x00\x02\x00\x00\x00\x6D\x5F\x6D\x6F\x64\x65\x6C\x69"
"\x6E\x76\x00\x00\x06\x00\x06\x00\x3C\x00\x00\x00\x03\x00\x00\x00\x65\x5F\x65\x79\x65\x70\x6F\x73\x00\x00\x00\x00\x06\x00\x05\x00"
"\x3C\x00\x00\x00\x04\x00\x00\x00\x65\x5F\x74\x69\x6D\x65\x00\x00\x06\x00\x07\x00\x3C\x00\x00\x00\x05\x00\x00\x00\x65\x5F\x6C\x69"
"\x67\x68\x74\x5F\x61\x6D\x62\x69\x65\x6E\x74\x00\x06\x00\x05\x00\x3C\x00\x00\x00\x06\x00\x00\x00\x65\x70\x61\x64\x31\x00\x00\x00"
"\x06\x00\x06\x00\x3C\x00\x00\x00\x07\x00\x00\x00\x65\x5F\x6C\x69\x67\x68\x74\x5F\x64\x69\x72\x00\x06\x00\x05\x00\x3C\x00\x00\x00"
"\x08\x00\x00\x00\x65\x70\x61\x64\x32\x00\x00\x00\x06\x00\x06\x00\x3C\x00\x00\x00\x09\x00\x00\x00\x65\x5F\x6C\x69\x67\x68\x74\x5F"
"\x6D\x75\x6C\x00\x06\x00\x05\x00\x3C\x00\x00\x00\x0A\x00\x00\x00\x65\x70\x61\x64\x33\x00\x00\x00\x06\x00\x06\x00\x3C\x00\x00\x00"
"\x0B\x00\x00\x00\x65\x5F\x6C\x6D\x73\x63\x61\x6C\x65\x73\x00\x00\x06\x00\x07\x00\x3C\x00\x00\x00\x0C\x00\x00\x00\x65\x5F\x75\x70"
"\x70\x65\x72\x63\x6F\x6C\x6F\x75\x72\x00\x00\x00\x06\x00\x05\x00\x3C\x00\x00\x00\x0D\x00\x00\x00\x65\x70\x61\x64\x34\x00\x00\x00"
"\x06\x00\x07\x00\x3C\x00\x00\x00\x0E\x00\x00\x00\x65\x5F\x6C\x6F\x77\x65\x72\x63\x6F\x6C\x6F\x75\x72\x00\x00\x00\x06\x00\x05\x00"
"\x3C\x00\x00\x00\x0F\x00\x00\x00\x65\x70\x61\x64\x35\x00\x00\x00\x06\x00\x06\x00\x3C\x00\x00\x00\x10\x00\x00\x00\x65\x5F\x67\x6C"
"\x6F\x77\x6D\x6F\x64\x00\x00\x00\x06\x00\x05\x00\x3C\x00\x00\x00\x11\x00\x00\x00\x65\x70\x61\x64\x36\x00\x00\x00\x06\x00\x07\x00"
"\x3C\x00\x00\x00\x12\x00\x00\x00\x65\x5F\x63\x6F\x6C\x6F\x75\x72\x69\x64\x65\x6E\x74\x00\x00\x00\x06\x00\x07\x00\x3C\x00\x00\x00"
"\x13\x00\x00\x00\x77\x5F\x66\x6F\x67\x63\x6F\x6C\x6F\x75\x72\x73\x00\x00\x00\x00\x06\x00\x07\x00\x3C\x00\x00\x00\x14\x00\x00\x00"
"\x77\x5F\x66\x6F\x67\x64\x65\x6E\x73\x69\x74\x79\x00\x00\x00\x00\x06\x00\x07\x00\x3C\x00\x00\x00\x15\x00\x00\x00\x77\x5F\x66\x6F"
"\x67\x64\x65\x70\x74\x68\x62\x69\x61\x73\x00\x00\x06\x00\x05\x00\x3C\x00\x00\x00\x16\x00\x00\x00\x65\x70\x61\x64\x37\x00\x00\x00"
"\x05\x00\x03\x00\x3E\x00\x00\x00\x00\x00\x00\x00\x05\x00\x05\x00\x3F\x00\x00\x00\x6C\x69\x67\x68\x74\x62\x6C\x6F\x63\x6B\x00\x00"
"\x06\x00\x07\x00\x3F\x00\x00\x00\x00\x00\x00\x00\x6C\x5F\x63\x75\x62\x65\x6D\x61\x74\x72\x69\x78\x00\x00\x00\x00\x06\x00\x07\x00"
"\x3F\x00\x00\x00\x01\x00\x00\x00\x6C\x5F\x6C\x69\x67\x68\x74\x70\x6F\x73\x69\x74\x69\x6F\x6E\x00\x06\x00\x05\x00\x3F\x00\x00\x00"
"\x02\x00\x00\x00\x6C\x70\x61\x64\x31\x00\x00\x00\x06\x00\x07\x00\x3F\x00\x00\x00\x03\x00\x00\x00\x6C\x5F\x6C\x69\x67\x68\x74\x63"
"\x6F\x6C\x6F\x75\x72\x00\x00\x00\x06\x00\x05\x00\x3F\x00\x00\x00\x04\x00\x00\x00\x6C\x70\x61\x64\x32\x00\x00\x00\x06\x00\x08\x00"
"\x3F\x00\x00\x00\x05\x00\x00\x00\x6C\x5F\x6C\x69\x67\x68\x74\x63\x6F\x6C\x6F\x75\x72\x73\x63\x61\x6C\x65\x00\x00\x06\x00\x07\x00"
"\x3F\x00\x00\x00\x06\x00\x00\x00\x6C\x5F\x6C\x69\x67\x68\x74\x72\x61\x64\x69\x75\x73\x00\x00\x00\x06\x00\x07\x00\x3F\x00\x00\x00"
"\x07\x00\x00\x00\x6C\x5F\x73\x68\x61\x64\x6F\x77\x6D\x61\x70\x70\x72\x6F\x6A\x00\x06\x00\x08\x00\x3F\x00\x00\x00\x08\x00\x00\x00"
"\x6C\x5F\x73\x68\x61\x64\x6F\x77\x6D\x61\x70\x73\x63\x61\x6C\x65\x00\x00\x00\x00\x06\x00\x05\x00\x3F\x00\x00\x00\x09\x00\x00\x00"
"\x6C\x70\x61\x64\x33\x00\x00\x00\x05\x00\x03\x00\x41\x00\x00\x00\x00\x00\x00\x00\x47\x00\x04\x00\x0B\x00\x00\x00\x01\x00\x00\x00"
"\x00\x01\x00\x00\x47\x00\x04\x00\x10\x00\x00\x00\x22\x00\x00\x00\x00\x00\x00\x00\x47\x00\x04\x00\x10\x00\x00\x00\x21\x00\x00\x00"
"\x04\x00\x00\x00\x47\x00\x04\x00\x13\x00\x00\x00\x1E\x00\x00\x00\x02\x00\x00\x00\x47\x00\x04\x00\x1C\x00\x00\x00\x22\x00\x00\x00"
"\x00\x00\x00\x00\x47\x00\x04\x00\x1C\x00\x00\x00\x21\x00\x00\x00\x03\x00\x00\x00\x47\x00\x04\x00\x1E\x00\x00\x00\x1E\x00\x00\x00"
"\x01\x00\x00\x00\x47\x00\x04\x00\x28\x00\x00\x00\x1E\x00\x00\x00\x00\x00\x00\x00\x47\x00\x04\x00\x30\x00\x00\x00\x1E\x00\x00\x00"
"\x00\x00\x00\x00\x47\x00\x04\x00\x31\x00\x00\x00\x22\x00\x00\x00\x00\x00\x00\x00\x47\x00\x04\x00\x31\x00\x00\x00\x21\x00\x00\x00"
"\x02\x00\x00\x00\x47\x00\x04\x00\x3B\x00\x00\x00\x06\x00\x00\x00\x10\x00\x00\x00\x48\x00\x04\x00\x3C\x00\x00\x00\x00\x00\x00\x00"
"\x05\x00\x00\x00\x48\x00\x05\x00\x3C\x00\x00\x00\x00\x00\x00\x00\x23\x00\x00\x00\x00\x00\x00\x00\x48\x00\x05\x00\x3C\x00\x00\x00"
"\x00\x00\x00\x00\x07\x00\x00\x00\x10\x00\x00\x00\x48\x00\x04\x00\x3C\x00\x00\x00\x01\x00\x00\x00\x05\x00\x00\x00\x48\x00\x05\x00"
"\x3C\x00\x00\x00\x01\x00\x00\x00\x23\x00\x00\x00\x40\x00\x00\x00\x48\x00\x05\x00\x3C\x00\x00\x00\x01\x00\x00\x00\x07\x00\x00\x00"
"\x10\x00\x00\x00\x48\x00\x04\x00\x3C\x00\x00\x00\x02\x00\x00\x00\x05\x00\x00\x00\x48\x00\x05\x00\x3C\x00\x00\x00\x02\x00\x00\x00"
"\x23\x00\x00\x00\x80\x00\x00\x00\x48\x00\x05\x00\x3C\x00\x00\x00\x02\x00\x00\x00\x07\x00\x00\x00\x10\x00\x00\x00\x48\x00\x05\x00"
"\x3C\x00\x00\x00\x03\x00\x00\x00\x23\x00\x00\x00\xC0\x00\x00\x00\x48\x00\x05\x00\x3C\x00\x00\x00\x04\x00\x00\x00\x23\x00\x00\x00"
"\xCC\x00\x00\x00\x48\x00\x05\x00\x3C\x00\x00\x00\x05\x00\x00\x00\x23\x00\x00\x00\xD0\x00\x00\x00\x48\x00\x05\x00\x3C\x00\x00\x00"
"\x06\x00\x00\x00\x23\x00\x00\x00\xDC\x00\x00\x00\x48\x00\x05\x00\x3C\x00\x00\x00\x07\x00\x00\x00\x23\x00\x00\x00\xE0\x00\x00\x00"
"\x48\x00\x05\x00\x3C\x00\x00\x00\x08\x00\x00\x00\x23\x00\x00\x00\xEC\x00\x00\x00\x48\x00\x05\x00\x3C\x00\x00\x00\x09\x00\x00\x00"
"\x23\x00\x00\x00\xF0\x00\x00\x00\x48\x00\x05\x00\x3C\x00\x00\x00\x0A\x00\x00\x00\x23\x00\x00\x00\xFC\x00\x00\x00\x48\x00\x05\x00"
"\x3C\x00\x00\x00\x0B\x00\x00\x00\x23\x00\x00\x00\x00\x01\x00\x00\x48\x00\x05\x00\x3C\x00\x00\x00\x0C\x00\x00\x00\x23\x00\x00\x00"
"\x40\x01\x00\x00\x48\x00\x05\x00\x3C\x00\x00\x00\x0D\x00\x00\x00\x23\x00\x00\x00\x4C\x01\x00\x00\x48\x00\x05\x00\x3C\x00\x00\x00"
"\x0E\x00\x00\x00\x23\x00\x00\x00\x50\x01\x00\x00\x48\x00\x05\x00\x3C\x00\x00\x00\x0F\x00\x00\x00\x23\x00\x00\x00\x5C\x01\x00\x00"
"\x48\x00\x05\x00\x3C\x00\x00\x00\x10\x00\x00\x00\x23\x00\x00\x00\x60\x01\x00\x00\x48\x00\x05\x00\x3C\x00\x00\x00\x11\x00\x00\x00"
"\x23\x00\x00\x00\x6C\x01\x00\x00\x48\x00\x05\x00\x3C\x00\x00\x00\x12\x00\x00\x00\x23\x00\x00\x00\x70\x01\x00\x00\x48\x00\x05\x00"
"\x3C\x00\x00\x00\x13\x00\x00\x00\x23\x00\x00\x00\x80\x01\x00\x00\x48\x00\x05\x00\x3C\x00\x00\x00\x14\x00\x00\x00\x23\x00\x00\x00"
"\x90\x01\x00\x00\x48\x00\x05\x00\x3C\x00\x00\x00\x15\x00\x00\x00\x23\x00\x00\x00\x94\x01\x00\x00\x48\x00\x05\x00\x3C\x00\x00\x00"
"\x16\x00\x00\x00\x23\x00\x00\x00\x98\x01\x00\x00\x47\x00\x03\x00\x3C\x00\x00\x00\x02\x00\x00\x00\x47\x00\x04\x00\x3E\x00\x00\x00"
"\x22\x00\x00\x00\x00\x00\x00\x00\x47\x00\x04\x00\x3E\x00\x00\x00\x21\x00\x00\x00\x00\x00\x00\x00\x48\x00\x04\x00\x3F\x00\x00\x00"
"\x00\x00\x00\x00\x05\x00\x00\x00\x48\x00\x05\x00\x3F\x00\x00\x00\x00\x00\x00\x00\x23\x00\x00\x00\x00\x00\x00\x00\x48\x00\x05\x00"
"\x3F\x00\x00\x00\x00\x00\x00\x00\x07\x00\x00\x00\x10\x00\x00\x00\x48\x00\x05\x00\x3F\x00\x00\x00\x01\x00\x00\x00\x23\x00\x00\x00"
"\x40\x00\x00\x00\x48\x00\x05\x00\x3F\x00\x00\x00\x02\x00\x00\x00\x23\x00\x00\x00\x4C\x00\x00\x00\x48\x00\x05\x00\x3F\x00\x00\x00"
"\x03\x00\x00\x00\x23\x00\x00\x00\x50\x00\x00\x00\x48\x00\x05\x00\x3F\x00\x00\x00\x04\x00\x00\x00\x23\x00\x00\x00\x5C\x00\x00\x00"
"\x48\x00\x05\x00\x3F\x00\x00\x00\x05\x00\x00\x00\x23\x00\x00\x00\x60\x00\x00\x00\x48\x00\x05\x00\x3F\x00\x00\x00\x06\x00\x00\x00"
"\x23\x00\x00\x00\x6C\x00\x00\x00\x48\x00\x05\x00\x3F\x00\x00\x00\x07\x00\x00\x00\x23\x00\x00\x00\x70\x00\x00\x00\x48\x00\x05\x00"
"\x3F\x00\x00\x00\x08\x00\x00\x00\x23\x00\x00\x00\x80\x00\x00\x00\x48\x00\x05\x00\x3F\x00\x00\x00\x09\x00\x00\x00\x23\x00\x00\x00"
"\x88\x00\x00\x00\x47\x00\x03\x00\x3F\x00\x00\x00\x02\x00\x00\x00\x47\x00\x04\x00\x41\x00\x00\x00\x22\x00\x00\x00\x00\x00\x00\x00"
"\x47\x00\x04\x00\x41\x00\x00\x00\x21\x00\x00\x00\x01\x00\x00\x00\x13\x00\x02\x00\x02\x00\x00\x00\x21\x00\x03\x00\x03\x00\x00\x00"
"\x02\x00\x00\x00\x16\x00\x03\x00\x06\x00\x00\x00\x20\x00\x00\x00\x17\x00\x04\x00\x07\x00\x00\x00\x06\x00\x00\x00\x02\x00\x00\x00"
"\x20\x00\x04\x00\x08\x00\x00\x00\x07\x00\x00\x00\x07\x00\x00\x00\x2B\x00\x04\x00\x06\x00\x00\x00\x0A\x00\x00\x00\x6F\x12\x83\x3C"
"\x32\x00\x04\x00\x06\x00\x00\x00\x0B\x00\x00\x00\x00\x00\x80\x43\x19\x00\x09\x00\x0D\x00\x00\x00\x06\x00\x00\x00\x01\x00\x00\x00"
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00\x1B\x00\x03\x00\x0E\x00\x00\x00\x0D\x00\x00\x00"
"\x20\x00\x04\x00\x0F\x00\x00\x00\x00\x00\x00\x00\x0E\x00\x00\x00\x3B\x00\x04\x00\x0F\x00\x00\x00\x10\x00\x00\x00\x00\x00\x00\x00"
"\x20\x00\x04\x00\x12\x00\x00\x00\x01\x00\x00\x00\x07\x00\x00\x00\x3B\x00\x04\x00\x12\x00\x00\x00\x13\x00\x00\x00\x01\x00\x00\x00"
"\x17\x00\x04\x00\x15\x00\x00\x00\x06\x00\x00\x00\x04\x00\x00\x00\x17\x00\x04\x00\x19\x00\x00\x00\x06\x00\x00\x00\x03\x00\x00\x00"
"\x20\x00\x04\x00\x1A\x00\x00\x00\x07\x00\x00\x00\x19\x00\x00\x00\x3B\x00\x04\x00\x0F\x00\x00\x00\x1C\x00\x00\x00\x00\x00\x00\x00"
"\x3B\x00\x04\x00\x12\x00\x00\x00\x1E\x00\x00\x00\x01\x00\x00\x00\x2B\x00\x04\x00\x06\x00\x00\x00\x22\x00\x00\x00\x00\x00\x00\x3F"
"\x2B\x00\x04\x00\x06\x00\x00\x00\x25\x00\x00\x00\x00\x00\x00\x40\x3B\x00\x04\x00\x12\x00\x00\x00\x28\x00\x00\x00\x01\x00\x00\x00"
"\x20\x00\x04\x00\x2F\x00\x00\x00\x03\x00\x00\x00\x15\x00\x00\x00\x3B\x00\x04\x00\x2F\x00\x00\x00\x30\x00\x00\x00\x03\x00\x00\x00"
"\x3B\x00\x04\x00\x0F\x00\x00\x00\x31\x00\x00\x00\x00\x00\x00\x00\x2B\x00\x04\x00\x06\x00\x00\x00\x34\x00\x00\x00\x00\x00\x80\x3F"
"\x2C\x00\x05\x00\x07\x00\x00\x00\x35\x00\x00\x00\x34\x00\x00\x00\x34\x00\x00\x00\x18\x00\x04\x00\x38\x00\x00\x00\x15\x00\x00\x00"
"\x04\x00\x00\x00\x15\x00\x04\x00\x39\x00\x00\x00\x20\x00\x00\x00\x00\x00\x00\x00\x2B\x00\x04\x00\x39\x00\x00\x00\x3A\x00\x00\x00"
"\x04\x00\x00\x00\x1C\x00\x04\x00\x3B\x00\x00\x00\x15\x00\x00\x00\x3A\x00\x00\x00\x1E\x00\x19\x00\x3C\x00\x00\x00\x38\x00\x00\x00"
"\x38\x00\x00\x00\x38\x00\x00\x00\x19\x00\x00\x00\x06\x00\x00\x00\x19\x00\x00\x00\x06\x00\x00\x00\x19\x00\x00\x00\x06\x00\x00\x00"
"\x19\x00\x00\x00\x06\x00\x00\x00\x3B\x00\x00\x00\x19\x00\x00\x00\x06\x00\x00\x00\x19\x00\x00\x00\x06\x00\x00\x00\x19\x00\x00\x00"
"\x06\x00\x00\x00\x15\x00\x00\x00\x15\x00\x00\x00\x06\x00\x00\x00\x06\x00\x00\x00\x07\x00\x00\x00\x20\x00\x04\x00\x3D\x00\x00\x00"
"\x02\x00\x00\x00\x3C\x00\x00\x00\x3B\x00\x04\x00\x3D\x00\x00\x00\x3E\x00\x00\x00\x02\x00\x00\x00\x1E\x00\x0C\x00\x3F\x00\x00\x00"
"\x38\x00\x00\x00\x19\x00\x00\x00\x06\x00\x00\x00\x19\x00\x00\x00\x06\x00\x00\x00\x19\x00\x00\x00\x06\x00\x00\x00\x15\x00\x00\x00"
"\x07\x00\x00\x00\x07\x00\x00\x00\x20\x00\x04\x00\x40\x00\x00\x00\x02\x00\x00\x00\x3F\x00\x00\x00\x3B\x00\x04\x00\x40\x00\x00\x00"
"\x41\x00\x00\x00\x02\x00\x00\x00\x36\x00\x05\x00\x02\x00\x00\x00\x04\x00\x00\x00\x00\x00\x00\x00\x03\x00\x00\x00\xF8\x00\x02\x00"
"\x05\x00\x00\x00\x3B\x00\x04\x00\x08\x00\x00\x00\x09\x00\x00\x00\x07\x00\x00\x00\x3B\x00\x04\x00\x1A\x00\x00\x00\x1B\x00\x00\x00"
"\x07\x00\x00\x00\x3B\x00\x04\x00\x08\x00\x00\x00\x27\x00\x00\x00\x07\x00\x00\x00\x85\x00\x05\x00\x06\x00\x00\x00\x0C\x00\x00\x00"
"\x0A\x00\x00\x00\x0B\x00\x00\x00\x3D\x00\x04\x00\x0E\x00\x00\x00\x11\x00\x00\x00\x10\x00\x00\x00\x3D\x00\x04\x00\x07\x00\x00\x00"
"\x14\x00\x00\x00\x13\x00\x00\x00\x57\x00\x05\x00\x15\x00\x00\x00\x16\x00\x00\x00\x11\x00\x00\x00\x14\x00\x00\x00\x4F\x00\x07\x00"
"\x07\x00\x00\x00\x17\x00\x00\x00\x16\x00\x00\x00\x16\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x8E\x00\x05\x00\x07\x00\x00\x00"
"\x18\x00\x00\x00\x17\x00\x00\x00\x0C\x00\x00\x00\x3E\x00\x03\x00\x09\x00\x00\x00\x18\x00\x00\x00\x3D\x00\x04\x00\x0E\x00\x00\x00"
"\x1D\x00\x00\x00\x1C\x00\x00\x00\x3D\x00\x04\x00\x07\x00\x00\x00\x1F\x00\x00\x00\x1E\x00\x00\x00\x57\x00\x05\x00\x15\x00\x00\x00"
"\x20\x00\x00\x00\x1D\x00\x00\x00\x1F\x00\x00\x00\x4F\x00\x08\x00\x19\x00\x00\x00\x21\x00\x00\x00\x20\x00\x00\x00\x20\x00\x00\x00"
"\x00\x00\x00\x00\x01\x00\x00\x00\x02\x00\x00\x00\x50\x00\x06\x00\x19\x00\x00\x00\x23\x00\x00\x00\x22\x00\x00\x00\x22\x00\x00\x00"
"\x22\x00\x00\x00\x83\x00\x05\x00\x19\x00\x00\x00\x24\x00\x00\x00\x21\x00\x00\x00\x23\x00\x00\x00\x8E\x00\x05\x00\x19\x00\x00\x00"
"\x26\x00\x00\x00\x24\x00\x00\x00\x25\x00\x00\x00\x3E\x00\x03\x00\x1B\x00\x00\x00\x26\x00\x00\x00\x3D\x00\x04\x00\x07\x00\x00\x00"
"\x29\x00\x00\x00\x28\x00\x00\x00\x3D\x00\x04\x00\x19\x00\x00\x00\x2A\x00\x00\x00\x1B\x00\x00\x00\x4F\x00\x07\x00\x07\x00\x00\x00"
"\x2B\x00\x00\x00\x2A\x00\x00\x00\x2A\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x3D\x00\x04\x00\x07\x00\x00\x00\x2C\x00\x00\x00"
"\x09\x00\x00\x00\x85\x00\x05\x00\x07\x00\x00\x00\x2D\x00\x00\x00\x2B\x00\x00\x00\x2C\x00\x00\x00\x81\x00\x05\x00\x07\x00\x00\x00"
"\x2E\x00\x00\x00\x29\x00\x00\x00\x2D\x00\x00\x00\x3E\x00\x03\x00\x27\x00\x00\x00\x2E\x00\x00\x00\x3D\x00\x04\x00\x0E\x00\x00\x00"
"\x32\x00\x00\x00\x31\x00\x00\x00\x3D\x00\x04\x00\x07\x00\x00\x00\x33\x00\x00\x00\x27\x00\x00\x00\x85\x00\x05\x00\x07\x00\x00\x00"
"\x36\x00\x00\x00\x33\x00\x00\x00\x35\x00\x00\x00\x57\x00\x05\x00\x15\x00\x00\x00\x37\x00\x00\x00\x32\x00\x00\x00\x36\x00\x00\x00"
"\x3E\x00\x03\x00\x30\x00\x00\x00\x37\x00\x00\x00\xFD\x00\x01\x00\x38\x00\x01\x00"},
#endif
#ifdef GLQUAKE
{QR_OPENGL, 110, "menutint",
"!!cvari r_menutint_inverse\n"
"!!cvard_srgb r_menutint\n"
"!!samps 1\n"
"#ifdef VERTEX_SHADER\n"
"attribute vec2 v_texcoord;\n"
@ -9853,7 +9852,6 @@ YOU SHOULD NOT EDIT THIS FILE BY HAND
"#ifdef FRAGMENT_SHADER\n"
"varying vec2 texcoord;\n"
"uniform sampler2D s_t0;\n"
"uniform int cvar_r_menutint_inverse;\n"
"const vec3 lumfactors = vec3(0.299, 0.587, 0.114);\n"
"const vec3 invertvec = vec3(1.0, 1.0, 1.0);\n"
@ -10176,6 +10174,13 @@ YOU SHOULD NOT EDIT THIS FILE BY HAND
#ifdef GLQUAKE
{QR_OPENGL, 110, "terrain",
"!!permu FOG\n"
//t0-t3 are the diffusemaps, t4 is the blend factors
"!!samps 5\n"
"!!samps =PCF 6\n"
"!!samps =CUBE 7\n"
//light levels
"#include \"sys/fog.h\"\n"
"varying vec2 tc;\n"
"varying vec2 lm;\n"
@ -10249,22 +10254,9 @@ YOU SHOULD NOT EDIT THIS FILE BY HAND
"#ifdef FRAGMENT_SHADER\n"
//four texture passes
"uniform sampler2D s_t0;\n"
"uniform sampler2D s_t1;\n"
"uniform sampler2D s_t2;\n"
"uniform sampler2D s_t3;\n"
//mix values
"uniform sampler2D s_t4;\n"
"#ifdef PCF\n"
"uniform sampler2DShadow s_t5;\n"
"#include \"sys/pcf.h\"\n"
"#endif\n"
"#ifdef CUBE\n"
"uniform samplerCube s_t6;\n"
"#endif\n"
//light levels
"uniform vec4 e_lmscale;\n"
@ -11828,7 +11820,7 @@ YOU SHOULD NOT EDIT THIS FILE BY HAND
"!!permu OFFSETMAPPING\n"
"!!permu SKELETAL\n"
"!!permu FOG\n"
"!!samps diffuse\n"
// texture units:
// s0=diffuse, s1=normal, s2=specular, s3=shadowmap

@ -479,61 +479,71 @@ typedef struct {
unsigned int handle;
} shaderprogparm_t;
struct programpermu_s
{
union programhandle_u
{
#ifdef GLQUAKE
struct
{
int handle;
qboolean usetesselation;
} glsl;
#endif
#ifdef D3DQUAKE
struct
{
void *vert;
void *frag;
#ifdef D3D9QUAKE
void *ctabf;
void *ctabv;
#endif
#ifdef D3D11QUAKE
int topology; //D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST
void *hull;
void *domain;
void *geom;
void *layouts[2];
#endif
} hlsl;
#endif
} h;
unsigned int permutation;
unsigned int attrmask;
unsigned int texmask; //'standard' textures that are in use
unsigned int numparms;
shaderprogparm_t *parm;
};
typedef struct programshared_s
{
char *name;
int refs;
qboolean nofixedcompat;
qboolean tess;
unsigned nofixedcompat:1;
unsigned tess:2;
unsigned geom:1;
unsigned warned:1; //one of the permutations of this shader has already been warned about. don't warn about all of them because that's potentially spammy.
unsigned short numsamplers; //shader system can strip any passes above this
unsigned int defaulttextures; //diffuse etc
unsigned int supportedpermutations;
#ifdef VKQUAKE
unsigned char *cvardata;
unsigned int cvardatasize;
#ifdef VKQUAKE
qVkShaderModule vert; //for slightly faster regeneration
qVkShaderModule frag;
qVkPipelineLayout layout; //all permutations share the same layout. I'm too lazy not to.
qVkDescriptorSetLayout desclayout;
struct pipeline_s *pipelines;
#endif
#if defined(GLQUAKE) || defined(D3DQUAKE)
struct programpermu_s
{
union programhandle_u
{
qintptr_t loaded; //generic code must be able to test this to see if its valid. if not 0, then its considered loaded
#ifdef GLQUAKE
struct
{
int handle;
qboolean usetesselation;
} glsl;
#endif
#ifdef D3DQUAKE
struct
{
void *vert;
void *frag;
#ifdef D3D9QUAKE
void *ctabf;
void *ctabv;
#endif
#ifdef D3D11QUAKE
int topology; //D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST
void *hull;
void *domain;
void *geom;
void *layouts[2];
#endif
} hlsl;
#endif
} h;
unsigned int attrmask;
unsigned int texmask; //'standard' textures that are in use
unsigned int numparms;
shaderprogparm_t *parm;
} permu[PERMUTATIONS];
#define DELAYEDSHADERCOMPILE
#ifdef DELAYEDSHADERCOMPILE
int shaderver; //glsl version
char *preshade; //general prefixed #defines
char *shadertext; //the glsl text
unsigned char failed[(PERMUTATIONS+7)/8]; //so we don't try recompiling endlessly
struct programpermu_s *permu[PERMUTATIONS]; //set once compiled.
#endif
} program_t;
@ -716,7 +726,7 @@ void Shader_RemapShader_f(void);
void Shader_ShowShader_f(void);
program_t *Shader_FindGeneric(char *name, int qrtype);
const char *Shader_NameForGeneric(program_t *prog);
struct programpermu_s *Shader_LoadPermutation(program_t *prog, unsigned int p);
void Shader_ReleaseGeneric(program_t *prog);
image_t *Mod_CubemapForOrigin(model_t *wmodel, vec3_t org);
@ -780,10 +790,10 @@ typedef struct
qboolean havecubemaps; //since gl1.3, so pretty much everyone will have this... should probably only be set if we also have seamless or clamp-to-edge.
void (*pDeleteProg) (program_t *prog);
qboolean (*pLoadBlob) (program_t *prog, const char *name, unsigned int permu, vfsfile_t *blobfile);
qboolean (*pCreateProgram) (program_t *prog, const char *name, unsigned int permu, int ver, const char **precompilerconstants, const char *vert, const char *tcs, const char *tes, const char *geom, const char *frag, qboolean noerrors, vfsfile_t *blobfile);
qboolean (*pValidateProgram)(program_t *prog, const char *name, unsigned int permu, qboolean noerrors, vfsfile_t *blobfile);
void (*pProgAutoFields) (program_t *prog, const char *name, cvar_t **cvars, char **cvarnames, int *cvartypes);
qboolean (*pLoadBlob) (program_t *prog, unsigned int permu, vfsfile_t *blobfile);
qboolean (*pCreateProgram) (program_t *prog, struct programpermu_s *permu, int ver, const char **precompilerconstants, const char *vert, const char *tcs, const char *tes, const char *geom, const char *frag, qboolean noerrors, vfsfile_t *blobfile);
qboolean (*pValidateProgram)(program_t *prog, struct programpermu_s *permu, qboolean noerrors, vfsfile_t *blobfile);
void (*pProgAutoFields) (program_t *prog, struct programpermu_s *permu, cvar_t **cvars, char **cvarnames, int *cvartypes);
} sh_config_t;
extern sh_config_t sh_config;
#endif

@ -4848,7 +4848,7 @@ static void QCC_VerifyArgs_setviewprop (const char *funcname, QCC_ref_t **arglis
{"VF_SIZE", 4, ev_vector},
{"VF_SIZE_X", 5, ev_float},
{"VF_SIZE_Y", 6, ev_float},
{"VF_VIEWPORT", 7, ev_vector},
{"VF_VIEWPORT", 7, ev_vector, ev_vector},
{"VF_FOV", 8, ev_vector},
{"VF_FOVX", 9, ev_float},
{"VF_FOVY", 10, ev_float},

@ -7231,7 +7231,7 @@ static void QCBUILTIN PF_logtext(pubprogfuncs_t *prinst, struct globalvars_s *pr
otext = text = PF_VarString(prinst, 2, pr_globals);
while (*text)
{
int cp = unicode_decode(&err, text, (char**)&text, false);
int cp = unicode_decode(&err, text, &text, false);
if ((cp >= 0xe000 && cp < 0xe100) || cp == '\r')
cp = readable2[cp&0xff]; //dequake it
out += utf8_encode(out, cp, sizeof(unitext)-1-(out-unitext));
@ -11162,7 +11162,7 @@ BuiltinList_t BuiltinList[] = { //nq qw h2 ebfs
// {"matchpattern", PF_Fixme, 0, 0, 0, 538, "float(string s, string pattern, float matchrule)"},
// {"undefined", PF_Fixme, 0, 0, 0, 539, ""},
{"physics_supported",PF_physics_supported,0, 0, 0, 0, D("float(optional float force)", "Queries whether rigid body physics is enabled or not. CSQC and SSQC may report different values. If the force argument is used then the engine will try to activate or release physics (returning the new state, which may fail if plugins or dlls are missing). Note that restarting the physics engine is likely to result in hitches when collision trees get generated. The state may change if a plugin is disabled mid-map.")},
{"physics_supported",PF_physics_supported,0, 0, 0, 0, D("float(optional float forcestate)", "Queries whether rigid body physics is enabled or not. CSQC and SSQC may report different values. If the force argument is specified then the engine will try to activate or release physics (returning the new state, which may fail if plugins or dlls are missing). Note that restarting the physics engine is likely to result in hitches when collision trees get generated. The state may change if a plugin is disabled mid-map.")},
#ifdef USERBE
{"physics_enable", PF_physics_enable, 0, 0, 0, 540, D("void(entity e, float physics_enabled)", "Enable or disable the physics attached to a MOVETYPE_PHYSICS entity. Entities which have been disabled in this way will stop taking so much cpu time.")},
{"physics_addforce",PF_physics_addforce,0, 0, 0, 541, D("void(entity e, vector force, vector relative_ofs)", "Apply some impulse directional force upon a MOVETYPE_PHYSICS entity.")},

@ -2724,6 +2724,10 @@ trace_t World_Move (world_t *w, vec3_t start, vec3_t mins, vec3_t maxs, vec3_t e
}
}
}
/*else if (w->rbe_hasphysicsents && passedict->rbe.body.body)
{
w->rbe->Trace(w, clip.passedict, clip.start, clip.end, &clip.trace);
}*/
else
{
#ifdef USEAREAGRID

@ -1,6 +1,10 @@
!!cvardf r_glsl_turbscale_reflect=1 //simpler scaler
!!cvardf r_glsl_turbscale_refract=1 //simpler scaler
!!samps 4 diffuse normalmap
!!samps diffuse normalmap
!!samps refract=0 //always present
!!samps =REFLECT reflect=1
!!samps =RIPPLEMAP ripplemap=2
!!samps =DEPTH refractdepth=3
#include "sys/defs.h"
@ -88,11 +92,6 @@ void main (void)
#endif
#define s_refract s_t0
#define s_reflect s_t1
#define s_ripplemap s_t2
#define s_refractdepth s_t3
void main (void)
{
vec2 stc; //screen tex coords

@ -1,3 +1,4 @@
!!samps 1
//apply gaussian filter
varying vec2 tc;
@ -13,7 +14,6 @@ void main ()
#ifdef FRAGMENT_SHADER
/*offset should be 1.2 pixels away from the center*/
uniform vec3 e_glowmod;
uniform sampler2D s_t0;
void main ()
{
gl_FragColor =
@ -21,4 +21,4 @@ void main ()
0.375 * texture2D(s_t0, tc) +
0.3125 * texture2D(s_t0, tc + e_glowmod.st);
}
#endif
#endif

@ -1,4 +1,5 @@
!!cvarv r_bloom_filter
!!samps 1
//the bloom filter
//filter out any texels which are not to bloom
@ -14,9 +15,8 @@ void main ()
#endif
#ifdef FRAGMENT_SHADER
uniform vec3 cvar_r_bloom_filter;
uniform sampler2D s_t0;
void main ()
{
gl_FragColor.rgb = (texture2D(s_t0, tc).rgb - cvar_r_bloom_filter)/(1.0-cvar_r_bloom_filter);
}
#endif
#endif

@ -1,5 +1,6 @@
!!cvarf r_bloom
!!cvarf r_bloom_retain=1.0
!!samps 4
//add them together
//optionally apply tonemapping
@ -14,10 +15,6 @@ void main ()
}
#endif
#ifdef FRAGMENT_SHADER
uniform sampler2D s_t0;
uniform sampler2D s_t1;
uniform sampler2D s_t2;
uniform sampler2D s_t3;
uniform float cvar_r_bloom;
uniform float cvar_r_bloom_retain;
void main ()

@ -1,3 +1,4 @@
!!samps 2
//this glsl shader is useful for cubemapped post processing effects (see csaddon for an example)
varying vec4 tf;
#ifdef VERTEX_SHADER
@ -7,8 +8,6 @@ void main ()
}
#endif
#ifdef FRAGMENT_SHADER
uniform sampler2D s_t0;
uniform sampler3D s_t1;
void main()
{
vec2 fc;

@ -1,6 +1,7 @@
!!cvarf crep_decay
!!cvarf crep_density
!!cvarf crep_weight
!!samps 1
//this is a post-processing shader, drawn in 2d
//there will be a render target containing sky surfaces drawn with crepuscular_sky, and everything else drawn with crepuscular_opaque (to mask out the sky)
@ -22,7 +23,6 @@ const float crep_density = 0.5;
const float crep_weight = 0.2;
uniform vec3 l_lightcolour;
uniform vec3 l_lightscreen;
uniform sampler2D s_t0;
const int NUM_SAMPLES = 100;
void main()
{

@ -1,3 +1,4 @@
!!samps 2
//pretty much a regular sky shader
//though in reality we should render a sun circle in the middle.
//still, its kinda cool to have scrolling clouds masking out parts of the sun.
@ -14,8 +15,6 @@ void main ()
uniform float e_time;
uniform vec3 e_eyepos;
varying vec3 pos;
uniform sampler2D s_t0;
uniform sampler2D s_t1;
void main ()
{
vec2 tccoord;

@ -1,4 +1,5 @@
!!ver 100-450
!!samps 1
//this shader is present for support for gles/gl3core contexts
//it is single-texture-with-vertex-colours, and doesn't do anything special.
@ -19,7 +20,6 @@ void main ()
}
#endif
#ifdef FRAGMENT_SHADER
uniform sampler2D s_t0;
void main ()
{
vec4 f = vc;

@ -1,4 +1,5 @@
!!permu FOG
!!samps 1
//meant to be used for additive stuff. presumably particles and sprites. though actually its only flashblend effects that use this at the time of writing.
//includes fog, apparently.
@ -17,7 +18,6 @@ void main ()
}
#endif
#ifdef FRAGMENT_SHADER
uniform sampler2D s_t0;
varying vec2 tc;
varying vec4 vc;
uniform vec4 e_colourident;

@ -1,4 +1,5 @@
!!ver 100-450
!!samps 1
//this shader is applies gamma/contrast/brightness to the source image, and dumps it out.
varying vec2 tc;
@ -15,7 +16,6 @@ void main ()
}
#endif
#ifdef FRAGMENT_SHADER
uniform sampler2D s_t0;
void main ()
{
gl_FragColor = pow(texture2D(s_t0, tc) * vc.g, vec4(vc.r)) + vc.b;

@ -11,7 +11,8 @@
!!cvarf gl_specular
!!cvardf gl_affinemodels=0
!!cvardf r_tessellation_level=5
!!samps diffuse normalmap specular fullbright upper lower paletted reflectmask reflectcube
!!samps !EIGHTBIT diffuse normalmap specular fullbright upper lower reflectmask reflectcube
!!samps =EIGHTBIT paletted 1
#include "sys/defs.h"
@ -208,7 +209,6 @@ uniform float cvar_gl_specular;
#ifdef EIGHTBIT
#define s_colourmap s_t0
uniform sampler2D s_colourmap;
#endif
affine varying vec2 tc;

@ -1,4 +1,5 @@
!!permu FOG
!!samps 2
#include "sys/fog.h"
//regular sky shader for scrolling q1 skies
@ -16,8 +17,6 @@ void main ()
uniform float e_time;
uniform vec3 e_eyepos;
varying vec3 pos;
uniform sampler2D s_t0;
uniform sampler2D s_t1;
void main ()
{
vec2 tccoord;

@ -1,4 +1,5 @@
!!permu FOG
!!samps 1
//used by both particles and sprites.
//note the fog blending mode is all that differs from defaultadditivesprite
@ -16,7 +17,6 @@ void main ()
}
#endif
#ifdef FRAGMENT_SHADER
uniform sampler2D s_t0;
varying vec2 tc;
varying vec4 vc;
uniform vec4 e_colourident;

@ -9,7 +9,11 @@
!!permu REFLECTCUBEMASK
!!cvarf r_glsl_offsetmapping_scale
!!cvardf r_tessellation_level=5
!!samps diffuse lightmap specular normalmap fullbright reflectmask reflectcube paletted lightmap1 lightmap2 lightmap3 deluxemap deluxemap1 deluxemap2 deluxemap3
!!samps !EIGHTBIT diffuse specular normalmap fullbright reflectmask reflectcube
//diffuse gives us alpha, and prevents dlight from bugging out when there's no diffuse.
!!samps =EIGHTBIT paletted 1 specular diffuse
!!samps lightmap deluxemap
!!samps =LIGHTSTYLED lightmap1 lightmap2 lightmap3 deluxemap deluxemap1 deluxemap2 deluxemap3
#include "sys/defs.h"
@ -224,10 +228,7 @@ void main()
#ifdef FRAGMENT_SHADER
//samplers
#define s_colourmap s_t0
uniform sampler2D s_colourmap;
#ifdef OFFSETMAPPING
#include "sys/offsetmapping.h"

@ -1,6 +1,7 @@
!!cvard_srgb_b r_floorcolor
!!cvard_srgb_b r_wallcolor
!!permu FOG
!!samps lm:0
//this is for the '286' preset walls, and just draws lightmaps coloured based upon surface normals.
@ -23,10 +24,9 @@ void main ()
}
#endif
#ifdef FRAGMENT_SHADER
uniform sampler2D s_t0;
varying vec2 lm;
void main ()
{
gl_FragColor = fog4(col * texture2D(s_t0, lm));
gl_FragColor = fog4(col * texture2D(s_lm, lm));
}
#endif

@ -1,4 +1,5 @@
!!ver 100-450
!!samps sourcetex:0
//this shader is present for support for gles/gl3core contexts
//it is single-texture-with-vertex-colours, and doesn't do anything special.
@ -22,7 +23,6 @@ void main ()
}
#endif
#ifdef FRAGMENT_SHADER
uniform sampler2D s_t0;
varying vec2 tc;
#ifndef UC
varying vec4 vc;
@ -33,7 +33,7 @@ uniform vec4 s_colour;
float e_time;
void main ()
{
vec4 fc = texture2D(s_t0, tc) * vc;
vec4 fc = texture2D(s_sourcetex, tc) * vc;
#ifdef ALPHATEST
if (!(fc.a ALPHATEST))
discard;

@ -1,5 +1,6 @@
!!cvari r_menutint_inverse
!!cvard_srgb r_menutint
!!samps 1
#ifdef VERTEX_SHADER
attribute vec2 v_texcoord;
@ -15,7 +16,6 @@
#ifdef FRAGMENT_SHADER
varying vec2 texcoord;
uniform sampler2D s_t0;
uniform int cvar_r_menutint_inverse;
const vec3 lumfactors = vec3(0.299, 0.587, 0.114);
const vec3 invertvec = vec3(1.0, 1.0, 1.0);
@ -28,4 +28,4 @@
texcolor = (cvar_r_menutint_inverse > 0) ? (invertvec - texcolor) : texcolor;
gl_FragColor = vec4(texcolor, 1.0);
}
#endif
#endif

@ -1,5 +1,5 @@
!!cvardf r_glsl_ascii_mono=0
!!samps 1
!!samps screen=0
//derived from https://www.shadertoy.com/view/lssGDj
@ -30,7 +30,7 @@ float character(float n, vec2 p)
void main(void)
{
vec2 uv = floor(texcoord.xy * e_sourcesize); //in pixels.
vec3 col = texture2D(s_t0, (floor(uv/8.0)*8.0+4.0)/e_sourcesize.xy).rgb;
vec3 col = texture2D(s_screen, (floor(uv/8.0)*8.0+4.0)/e_sourcesize.xy).rgb;
float gray = 0.3 * col.r + 0.59 * col.g + 0.11 * col.b;
@ -56,4 +56,4 @@ void main(void)
col = col*character(n, p); //note that this is kinda cheating.
gl_FragColor = vec4(col, 1.0);
}
#endif
#endif

@ -1,4 +1,5 @@
!!cvarf ffov
!!samps screen:samplerCube=0
//equirectangular view rendering, commonly used for sphere->2d map projections.
@ -12,7 +13,6 @@ void main()
}
#endif
#ifdef FRAGMENT_SHADER
uniform samplerCube s_t0;
varying vec2 texcoord;
uniform float cvar_ffov;
@ -26,6 +26,6 @@ void main()
tc.z = cos(lng) * sin(lat);
tc.x = sin(lng) * sin(lat);
tc.y = cos(lat);
gl_FragColor = textureCube(s_t0, tc);
gl_FragColor = textureCube(s_screen, tc);
}
#endif

@ -1,4 +1,5 @@
!!cvarf ffov
!!samps screen:samplerCube=0
//fisheye view rendering, for silly fovs that are still playable.
@ -12,7 +13,6 @@ void main()
}
#endif
#ifdef FRAGMENT_SHADER
uniform samplerCube s_t0;
varying vec2 texcoord;
uniform float cvar_ffov;
void main()
@ -26,6 +26,6 @@ void main()
tc.x = sin(ang.x) * cos(ang.y);
tc.y = sin(ang.x) * sin(ang.y);
tc.z = cos(ang.x);
gl_FragColor = textureCube(s_t0, tc);
gl_FragColor = textureCube(s_screen, tc);
}
#endif

@ -1,4 +1,5 @@
!!cvarf ffov
!!samps screen:samplerCube=0
//my attempt at lambert azimuthal equal-area view rendering, because you'll remember that name easily.
@ -17,7 +18,6 @@ void main()
}
#endif
#ifdef FRAGMENT_SHADER
uniform samplerCube s_t0;
varying vec2 texcoord;
void main()
{
@ -39,7 +39,7 @@ void main()
tc.y *= -1.0;
tc.z *= -1.0;
gl_FragColor = textureCube(s_t0, tc);
gl_FragColor = textureCube(s_screen, tc);
}
}
#endif

@ -1,4 +1,5 @@
!!cvarf ffov
!!samps screen:samplerCube=0
//panoramic view rendering, for promo map shots or whatever.
@ -12,7 +13,6 @@ void main()
}
#endif
#ifdef FRAGMENT_SHADER
uniform samplerCube s_t0;
varying vec2 texcoord;
uniform float cvar_ffov;
void main()
@ -23,6 +23,6 @@ void main()
tc.x = sin(ang);
tc.y = -texcoord.y;
tc.z = cos(ang);
gl_FragColor = textureCube(s_t0, tc);
gl_FragColor = textureCube(s_screen, tc);
}
#endif

@ -1,4 +1,5 @@
!!cvarf ffov
!!samps screen:samplerCube=0
//stereographic view rendering, for high fovs that are still playable.
@ -17,7 +18,6 @@ void main()
}
#endif
#ifdef FRAGMENT_SHADER
uniform samplerCube s_t0;
varying vec2 texcoord;
void main()
{
@ -32,6 +32,6 @@ void main()
tc.y = -2.0*d.y/div;
tc.z = -(-1.0 + d.x*d.x + d.y*d.y)/div;
gl_FragColor = textureCube(s_t0, tc);
gl_FragColor = textureCube(s_screen, tc);
}
#endif

@ -1,4 +1,11 @@
!!permu FOG
//t0-t3 are the diffusemaps, t4 is the blend factors
!!samps 5
!!samps =PCF 6
!!samps =CUBE 7
//light levels
#include "sys/fog.h"
varying vec2 tc;
varying vec2 lm;
@ -72,22 +79,9 @@ void main (void)
#ifdef FRAGMENT_SHADER
//four texture passes
uniform sampler2D s_t0;
uniform sampler2D s_t1;
uniform sampler2D s_t2;
uniform sampler2D s_t3;
//mix values
uniform sampler2D s_t4;
#ifdef PCF
uniform sampler2DShadow s_t5;
#include "sys/pcf.h"
#endif
#ifdef CUBE
uniform samplerCube s_t6;
#endif
//light levels
uniform vec4 e_lmscale;
@ -151,4 +145,4 @@ void main (void)
gl_FragColor = fog4(r);
#endif
}
#endif
#endif

@ -1,13 +1,14 @@
!!cvarf r_waterwarp
!!samps screen=0 warp=1 edge=2
//this is a post processing shader that is drawn fullscreen whenever the view is underwater.
//its generally expected to warp the view a little.
#ifdef VERTEX_SHADER
attribute vec2 v_texcoord;
varying vec2 v_stc;
varying vec2 v_warp;
varying vec2 v_edge;
#ifdef VERTEX_SHADER
attribute vec2 v_texcoord;
uniform float e_time;
void main ()
{
@ -19,19 +20,13 @@ void main ()
}
#endif
#ifdef FRAGMENT_SHADER
varying vec2 v_stc;
varying vec2 v_warp;
varying vec2 v_edge;
uniform sampler2D s_t0;/*$currentrender*/
uniform sampler2D s_t1;/*warp image*/
uniform sampler2D s_t2;/*edge image*/
uniform vec4 e_rendertexturescale;
uniform float cvar_r_waterwarp;
void main ()
{
vec2 amp = (0.010 / 0.625) * cvar_r_waterwarp * texture2D(s_t2, v_edge).rg;
vec3 offset = (texture2D(s_t1, v_warp).rgb - 0.5) * 2.0;
vec2 amp = (0.010 / 0.625) * cvar_r_waterwarp * texture2D(s_edge, v_edge).rg;
vec3 offset = (texture2D(s_warp, v_warp).rgb - 0.5) * 2.0;
vec2 temp = v_stc + offset.xy * amp;
gl_FragColor = texture2D(s_t0, temp*e_rendertexturescale.st);
gl_FragColor = texture2D(s_screen, temp*e_rendertexturescale.st);
}
#endif

@ -1,5 +1,9 @@
!!permu FRAMEBLEND
!!permu UPPERLOWER
//!!permu FULLBRIGHT
!!samps diffuse upper lower
// fullbright
struct a2v
{
float3 pos: POSITION0;
@ -70,7 +74,7 @@ sampler s_fullbright; /*fullbright*/
col.rgb *= inp.light;
#ifdef FULLBRIGHT
float4 fb = tex2D(s_fullbright, inp.tc);
col.rgb = mix(col.rgb, fb.rgb, fb.a);
col.rgb = lerp(col.rgb, fb.rgb, fb.a);
#endif
return col * e_colourident;
// return fog4(col * e_colourident);

@ -1,3 +1,5 @@
!!samps 2
struct a2v
{
float4 pos: POSITION;
@ -12,11 +14,11 @@
#ifdef VERTEX_SHADER
float4x4 m_modelviewprojection;
v2f main (a2v inp)
v2f main (in a2v inp)
{
v2f outp;
outp.pos = mul(m_modelviewprojection, inp.pos);
outp.vpos = inp.pos;
outp.vpos = inp.pos.xyz;
return outp;
}
#endif
@ -41,7 +43,6 @@
tccoord = (dir.xy + e_time*0.0625);
float4 clouds = tex2D(s_fullbright, tccoord);
return float4((solid.rgb*(1.0-clouds.a)) + (clouds.a*clouds.rgb), 1);
}
#endif
#endif

@ -1,3 +1,5 @@
!!samps reflectcube
struct a2v
{
float4 pos: POSITION;
@ -30,4 +32,4 @@
tc.y = -tc.y;
return texCUBE(s_reflectcube, tc);
}
#endif
#endif

@ -1,4 +1,6 @@
!!cvarf r_wateralpha
!!samps diffuse
struct a2v {
float4 pos: POSITION;
float2 tc: TEXCOORD0;

@ -1,5 +1,6 @@
!!cvard3 r_floorcolour
!!cvard3 r_wallcolour
!!samps 1
//FIXME !!permu FOG
struct a2v {

@ -3,7 +3,7 @@
!!permu OFFSETMAPPING
!!permu SKELETAL
!!permu FOG
!!samps diffuse
// texture units:
// s0=diffuse, s1=normal, s2=specular, s3=shadowmap
@ -62,4 +62,4 @@
#endif
return float4(diff * col, 1);
}
#endif
#endif

@ -14,7 +14,7 @@ layout(location=2) varying vec2 v_edge;
void main ()
{
gl_Position = ftetransform();
v_stc = vec2(v_texcoord.x, 1.0-v_texcoord.y);
v_stc = vec2(v_texcoord.x, /*1.0-*/v_texcoord.y);
v_warp.s = e_time * 0.25 + v_texcoord.s;
v_warp.t = e_time * 0.25 + v_texcoord.t;
v_edge = v_texcoord.xy;

@ -1028,9 +1028,9 @@ VkShaderModule VK_CreateGLSLModule(program_t *prog, const char *name, int ver, c
return mod;
}
qboolean VK_LoadGLSL(program_t *prog, const char *name, unsigned int permu, int ver, const char **precompilerconstants, const char *vert, const char *tcs, const char *tes, const char *geom, const char *frag, qboolean noerrors, vfsfile_t *blobfile)
qboolean VK_LoadGLSL(program_t *prog, struct programpermu_s *permu, int ver, const char **precompilerconstants, const char *vert, const char *tcs, const char *tes, const char *geom, const char *frag, qboolean noerrors, vfsfile_t *blobfile)
{
if (permu) //FIXME...
if (permu->permutation) //FIXME...
return false;
prog->nofixedcompat = false;
@ -1038,10 +1038,10 @@ qboolean VK_LoadGLSL(program_t *prog, const char *name, unsigned int permu, int
prog->cvardata = NULL;
prog->cvardatasize = 0;
prog->pipelines = NULL;
prog->vert = VK_CreateGLSLModule(prog, name, ver, precompilerconstants, vert, false);
prog->frag = VK_CreateGLSLModule(prog, name, ver, precompilerconstants, frag, true);
prog->vert = VK_CreateGLSLModule(prog, prog->name, ver, precompilerconstants, vert, false);
prog->frag = VK_CreateGLSLModule(prog, prog->name, ver, precompilerconstants, frag, true);
VK_FinishProg(prog, name);
VK_FinishProg(prog, prog->name);
return true;
}

@ -2346,6 +2346,8 @@ static qboolean VK_R_RenderScene_Cubemap(struct vk_rendertarg *fb)
if (R2D_Flush)
Con_Printf("no flush\n");
VKBE_RT_End(&rtc->face[i]);
}
r_refdef.vrect = vrect;

@ -434,7 +434,8 @@ void VK_R_BloomShutdown(void);
qboolean R_CanBloom(void);
struct programshared_s;
qboolean VK_LoadGLSL(struct programshared_s *prog, const char *name, unsigned int permu, int ver, const char **precompilerconstants, const char *vert, const char *tcs, const char *tes, const char *geom, const char *frag, qboolean noerrors, vfsfile_t *blobfile);
struct programpermu_s;
qboolean VK_LoadGLSL(struct programshared_s *prog, struct programpermu_s *permu, int ver, const char **precompilerconstants, const char *vert, const char *tcs, const char *tes, const char *geom, const char *frag, qboolean noerrors, vfsfile_t *blobfile);
VkCommandBuffer VK_AllocFrameCBuf(void);
void VK_Submit_Work(VkCommandBuffer cmdbuf, VkSemaphore semwait, VkPipelineStageFlags semwaitstagemask, VkSemaphore semsignal, VkFence fencesignal, struct vkframe *presentframe, struct vk_fencework *fencedwork);

@ -924,6 +924,7 @@ public:
VectorNegate(axis[1], axis[1]);
VectorAvg(edict->rbe.mins, edict->rbe.maxs, offset);
VectorMA(edict->v->origin, offset[0]*1, axis[0], org);
org[3] = 0;//for sse.
VectorMA(org, offset[1]*1, axis[1], org);
VectorMA(org, offset[2]*1, axis[2], org);
@ -1705,8 +1706,11 @@ static void World_Bullet_RunCmd(world_t *world, rbecommandqueue_t *cmd)
case RBECMD_FORCE:
if (body)
{
btVector3 relativepos;
const btVector3 &center = body->getCenterOfMassPosition();
VectorSubtract(cmd->v2, center, relativepos);
body->setActivationState(1);
body->applyForce(btVector3(cmd->v1[0], cmd->v1[1], cmd->v1[2]), btVector3(cmd->v2[0], cmd->v2[1], cmd->v2[2]));
body->applyImpulse(btVector3(cmd->v1[0], cmd->v1[1], cmd->v1[2]), relativepos);
}
break;
case RBECMD_TORQUE:
@ -1736,26 +1740,48 @@ static void QDECL World_Bullet_PushCommand(world_t *world, rbecommandqueue_t *va
ctx->cmdqueuetail = ctx->cmdqueuehead = cmd;
}
/*
static void QDECL World_Bullet_TraceEntity(world_t *world, vec3_t start, vec3_t end, wedict_t *ed)
static void QDECL World_Bullet_TraceEntity(world_t *world, wedict_t *ed, vec3_t start, vec3_t end, trace_t *trace)
{
struct bulletcontext_s *ctx = (struct bulletcontext_s*)world->rbe;
btCollisionShape *shape = (btCollisionShape*)ed->rbe.body.geom;
//btCollisionAlgorithm
class myConvexResultCallback : public btCollisionWorld::ConvexResultCallback
{
public:
void *m_impactent;
btVector3 m_impactpos;
btVector3 m_impactnorm;
virtual btScalar addSingleResult(btCollisionWorld::LocalConvexResult& convexResult,bool normalInWorldSpace)
{
if (m_closestHitFraction > convexResult.m_hitFraction)
{
m_closestHitFraction = convexResult.m_hitFraction;
m_impactpos = convexResult.m_hitPointLocal;
m_impactnorm = convexResult.m_hitNormalLocal;
m_impactent = convexResult.m_hitCollisionObject->getUserPointer();
}
return 0;
}
} result;
result.m_impactent = NULL;
result.m_closestHitFraction = trace->fraction;
btTransform from(btMatrix3x3(1, 0, 0, 0, 1, 0, 0, 0, 1), btVector3(start[0], start[1], start[2]));
btTransform to(btMatrix3x3(1, 0, 0, 0, 1, 0, 0, 0, 1), btVector3(end[0], end[1], end[2]));
ctx->dworld->convexSweepTest((btConvexShape*)shape, from, to, result, 1);
if (result.m_impactent)
{
memset(trace, 0, sizeof(*trace));
trace->fraction = trace->truefraction = result.m_closestHitFraction;
VectorInterpolate(start, result.m_closestHitFraction, end, trace->endpos);
// VectorCopy(result.m_impactpos, trace->endpos);
VectorCopy(result.m_impactnorm, trace->plane.normal);
trace->ent = result.m_impactent;
trace->startsolid = qfalse; //FIXME: we don't really know
}
}
*/
static void QDECL World_Bullet_Start(world_t *world)
{
@ -1782,6 +1808,7 @@ static void QDECL World_Bullet_Start(world_t *world)
ctx->funcs.RagDestroyJoint = World_Bullet_RagDestroyJoint;
ctx->funcs.RunFrame = World_Bullet_Frame;
ctx->funcs.PushCommand = World_Bullet_PushCommand;
ctx->funcs.Trace = World_Bullet_TraceEntity;
world->rbe = &ctx->funcs;

Loading…
Cancel
Save